def save(self, w, tv): tb = tv.get_buffer() start = tb.get_start_iter() end = tb.get_end_iter() txt = tb.get_text(start, end) dialog = gtk.FileChooserDialog( title='Save As', action=gtk.FILE_CHOOSER_ACTION_SAVE, buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_SAVE, gtk.RESPONSE_OK)) filter = gtk.FileFilter() filter.set_name("any") filter.add_pattern("*") dialog.add_filter(filter) response = dialog.run() if response != gtk.RESPONSE_OK: dialog.destroy() return False fname = dialog.get_filename() dialog.destroy() try: f = open(fname, 'wb') except IOError, x: warning_dialog(str(x), self.window).warn()
def unregister_popup( self, w, reg, is_group=False ): window = gtk.MessageDialog( parent=self.window, flags=0, type=gtk.MESSAGE_QUESTION, buttons=gtk.BUTTONS_NONE, message_format="Unregistering Suite " + reg + """ \nDelete suite definition directory too? (DANGEROUS!)""") window.add_button( gtk.STOCK_YES, gtk.RESPONSE_YES ) window.add_button( gtk.STOCK_NO, gtk.RESPONSE_NO ) window.add_button( gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL ) response = window.run() window.destroy() if is_group: reg = '^' + reg + '\..*$' else: reg = '^' + reg + '$' if response == gtk.RESPONSE_YES: command = "cylc unregister -f -d " + reg elif response == gtk.RESPONSE_NO: command = "cylc unregister " + reg else: command = None if command: res, out = run_get_stdout( command ) if not res: warning_dialog( '\n'.join(out), self.window ).warn()
def filter( self, w, excl_e, incl_e, fbox ): filters = {} filters["excl"] = excl_e.get_text() filters["incl"] = incl_e.get_text() for filt_name, filt in filters.items(): if not filt: filters[filt_name] = None continue try: re.compile( filt ) except re.error as exc: warning_dialog( 'Bad filter regex: %s: error: %s' % (filt, exc)).warn() filters[filt_name] = None self.t.filter_include = filters["incl"] self.t.filter_exclude = filters["excl"] fstates = [] for b in fbox.get_children(): if not b.get_active(): # sub '_' from button label keyboard mnemonics fstates.append( re.sub('_', '', b.get_label())) if len(fstates) > 0: self.t.state_filter = fstates else: self.t.state_filter = None self.t.action_required = True
def copy_popup( self, w, reg, is_group=False ): window = EntryDialog( parent=self.window, flags=0, type=gtk.MESSAGE_QUESTION, buttons=gtk.BUTTONS_OK_CANCEL, message_format="Copy Suite " + reg + """To NAME,TOP_DIRECTORY""") out = window.run() window.destroy() if out: try: name, topdir = re.split(' *, *', out ) except Exception, e: warning_dialog( str(e), self.window ).warn() else: print name, topdir topdir = os.path.expanduser( os.path.expandvars( topdir )) print name, topdir command = "cylc cp " + reg + ' ' + name + ' ' + topdir print command res, out = run_get_stdout( command ) if not res: warning_dialog( '\n'.join(out), self.window ).warn() elif out: info_dialog( '\n'.join(out), self.window ).inform()
def unregister_popup(self, w, reg, is_group=False): window = gtk.MessageDialog(parent=self.window, flags=0, type=gtk.MESSAGE_QUESTION, buttons=gtk.BUTTONS_NONE, message_format="Unregistering Suite " + reg + """ \nDelete suite definition directory too? (DANGEROUS!)""") window.add_button(gtk.STOCK_YES, gtk.RESPONSE_YES) window.add_button(gtk.STOCK_NO, gtk.RESPONSE_NO) window.add_button(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL) response = window.run() window.destroy() if is_group: reg = '^' + reg + '\..*$' else: reg = '^' + reg + '$' if response == gtk.RESPONSE_YES: command = "cylc unregister -f -d " + reg elif response == gtk.RESPONSE_NO: command = "cylc unregister " + reg else: command = None if command: res, out = run_get_stdout(command) if not res: warning_dialog('\n'.join(out), self.window).warn()
def filter(self, w, excl_e, incl_e, fbox): filters = {} filters["excl"] = excl_e.get_text() filters["incl"] = incl_e.get_text() for filt_name, filt in filters.items(): if not filt: filters[filt_name] = None continue try: re.compile(filt) except re.error as exc: warning_dialog('Bad filter regex: %s: error: %s' % (filt, exc)).warn() filters[filt_name] = None self.t.filter_include = filters["incl"] self.t.filter_exclude = filters["excl"] fstates = [] for b in fbox.get_children(): if not b.get_active(): # sub '_' from button label keyboard mnemonics fstates.append(re.sub('_', '', b.get_label())) if len(fstates) > 0: self.t.state_filter = fstates else: self.t.state_filter = None self.t.action_required = True
def copy_popup(self, w, reg, is_group=False): window = EntryDialog(parent=self.window, flags=0, type=gtk.MESSAGE_QUESTION, buttons=gtk.BUTTONS_OK_CANCEL, message_format="Copy Suite " + reg + """To NAME,TOP_DIRECTORY""") out = window.run() window.destroy() if out: try: name, topdir = re.split(' *, *', out) except Exception, e: warning_dialog(str(e), self.window).warn() else: print name, topdir topdir = os.path.expanduser(os.path.expandvars(topdir)) print name, topdir command = "cylc cp " + reg + ' ' + name + ' ' + topdir print command res, out = run_get_stdout(command) if not res: warning_dialog('\n'.join(out), self.window).warn() elif out: info_dialog('\n'.join(out), self.window).inform()
def on_find_clicked(self, tv, e): needle = e.get_text() if not needle: return self.t.freeze = True self.freeze_button.set_active(True) self.freeze_button.set_label('Reconnect') if not self.search_warning_done: warning_dialog( "Find Next disconnects the live feed; click Reconnect when you're done" ).warn() self.search_warning_done = True tb = tv.get_buffer() if needle == self.find_current: s = self.find_current_iter else: s, e = tb.get_bounds() tb.remove_all_tags(s, e) s = tb.get_end_iter() tv.scroll_to_iter(s, 0) try: f, l = s.backward_search(needle, gtk.TEXT_SEARCH_TEXT_ONLY) except: warning_dialog('"' + needle + '"' + " not found").warn() else: tag = tb.create_tag(None, background="#70FFA9") tb.apply_tag(tag, f, l) self.find_current_iter = f self.find_current = needle tv.scroll_to_iter(f, 0)
def filter( self, w, excl_e, incl_e, fbox ): excl = excl_e.get_text() incl = incl_e.get_text() if excl == '': excl = None if incl == '': incl == None for filt in excl, incl: if not filt: continue try: re.compile( filt ) except: warning_dialog( "Bad Expression: " + filt ).warn() self.t.filter_include = incl self.t.filter_exclude = excl fstates = [] for b in fbox.get_children(): if not b.get_active(): # sub '_' from button label keyboard mnemonics fstates.append( re.sub('_', '', b.get_label())) if len(fstates) > 0: self.t.state_filter = fstates else: self.t.state_filter = None self.t.action_required = True
def save(self, w, tv): tb = tv.get_buffer() start = tb.get_start_iter() end = tb.get_end_iter() txt = tb.get_text(start, end) dialog = gtk.FileChooserDialog( title="Save As", action=gtk.FILE_CHOOSER_ACTION_SAVE, buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_SAVE, gtk.RESPONSE_OK), ) filter = gtk.FileFilter() filter.set_name("any") filter.add_pattern("*") dialog.add_filter(filter) response = dialog.run() if response != gtk.RESPONSE_OK: dialog.destroy() return False fname = dialog.get_filename() dialog.destroy() try: f = open(fname, "wb") except IOError, x: warning_dialog(str(x), self.window).warn()
def on_find_clicked(self, e): tv = self.textview tb = tv.get_buffer() needle = e.get_text() if not needle: s, e = tb.get_bounds() tb.remove_tag(self.ftag, s, e) return self.stdout_updater.freeze = True self.freeze_button.set_active(True) self.freeze_button.set_label("_Reconnect") if not self.search_warning_done: warning_dialog("Find Next disconnects the live feed. Click Reconnect when you're done.", self.window).warn() self.search_warning_done = True if needle == self.find_current: s = self.find_current_iter else: s, e = tb.get_bounds() tb.remove_tag(self.ftag, s, e) s = tb.get_end_iter() tv.scroll_to_iter(s, 0) try: f, l = s.backward_search(needle, gtk.TEXT_SEARCH_VISIBLE_ONLY) except: warning_dialog('"' + needle + '"' + " not found", self.window).warn() else: tb.apply_tag(self.ftag, f, l) self.find_current_iter = f self.find_current = needle tv.scroll_to_iter(f, 0)
def on_find_clicked( self, tv, e ): needle = e.get_text () if not needle: return self.t.freeze = True self.freeze_button.set_active(True) self.freeze_button.set_label('Reconnect') if not self.search_warning_done: warning_dialog( "Find Next disconnects the live feed; click Reconnect when you're done" ).warn() self.search_warning_done = True tb = tv.get_buffer () if needle == self.find_current: s = self.find_current_iter else: s,e = tb.get_bounds() tb.remove_all_tags( s,e ) s = tb.get_end_iter() tv.scroll_to_iter( s, 0 ) try: f, l = s.backward_search (needle, gtk.TEXT_SEARCH_TEXT_ONLY) except: warning_dialog( '"' + needle + '"' + " not found" ).warn() else: tag = tb.create_tag( None, background="#70FFA9" ) tb.apply_tag( tag, f, l ) self.find_current_iter = f self.find_current = needle tv.scroll_to_iter( f, 0 )
def graph_suite_popup( reg, cmd_help, defstartc, defstopc, graph_opts, gcapture_windows, tmpdir, parent_window=None): """Popup a dialog to allow a user to configure their suite graphing.""" try: import xdot except Exception, x: warning_dialog( str(x) + "\nGraphing disabled.", parent_window ).warn() return False
def graph_suite_popup( reg, cmd_help, defstartc, defstopc, graph_opts, gcapture_windows, tmpdir, template_opts, parent_window=None ): """Popup a dialog to allow a user to configure their suite graphing.""" try: import xdot except Exception, x: warning_dialog( str(x) + "\nGraphing disabled.", parent_window ).warn() return False
def check_filter_entry(self, e): ftext = self.filter_entry.get_text() try: re.compile(ftext) except re.error as exc: warning_dialog("Bad filter regex: '%s': error: %s" % (ftext, exc)).warn() self.tfilt = "" else: self.tfilt = ftext self.tmodelfilter.refilter()
def check_filter_entry( self, e ): ftext = self.filter_entry.get_text() try: re.compile(ftext) except re.error as exc: warning_dialog( 'Bad filter regex: %s: error: %s' % (ftext, exc)).warn() self.t.filter = "" else: self.t.filter = ftext self.t.action_required = True
def check_filter_entry(self, e): ftext = self.filter_entry.get_text() try: re.compile(ftext) except re.error as exc: warning_dialog('Bad filter regex: %s: error: %s' % (ftext, exc)).warn() self.t.filter = "" else: self.t.filter = ftext self.t.action_required = True
def filter(self, filtr_e ): if filtr_e == "": # reset self.start_updater() return filtr = filtr_e.get_text() try: re.compile( filtr ) except: warning_dialog( "Bad Regular Expression: " + filtr, self.window ).warn() filtr_e.set_text("") self.start_updater() return self.start_updater( filtr )
def visible_cb(self, model, iter): # visibility result determined by state matching active check # buttons: set visible if model value NOT in filter_states; # and matching name against current name filter setting. # (state result: sres; name result: nres) ctime = model.get_value(iter, 0) name = model.get_value(iter, 1) if name is None or ctime is None: return True name = re.sub(r'<.*?>', '', name) if ctime == name: # Cycle-time line (not state etc.) return True # Task or family. state = model.get_value(iter, 2) if state is not None: state = re.sub(r'<.*?>', '', state) sres = state not in self.tfilter_states try: if not self.tfilt: nres = True elif self.tfilt in name: # tfilt is any substring of name nres = True elif re.search(self.tfilt, name): # full regex match nres = True else: nres = False except: warning_dialog('Bad filter regex? ' + self.tfilt).warn() nres = False if model.iter_has_child(iter): # Family. path = model.get_path(iter) sub_st = self.ttree_paths.get(path, {}).get('states', []) sres = sres or any([t not in self.tfilter_states for t in sub_st]) if self.tfilt: sub_nm = self.ttree_paths.get(path, {}).get('names', []) nres = nres or any([self.tfilt in n for n in sub_nm]) return sres and nres
def visible_cb(self, model, iter ): # visibility result determined by state matching active check # buttons: set visible if model value NOT in filter_states; # and matching name against current name filter setting. # (state result: sres; name result: nres) ctime = model.get_value(iter, 0 ) name = model.get_value(iter, 1) if name is None or ctime is None: return True name = re.sub( r'<.*?>', '', name ) if ctime == name: # Cycle-time line (not state etc.) return True # Task or family. state = model.get_value(iter, 2 ) if state is not None: state = re.sub( r'<.*?>', '', state ) sres = state not in self.tfilter_states try: if not self.tfilt: nres = True elif self.tfilt in name: # tfilt is any substring of name nres = True elif re.search( self.tfilt, name ): # full regex match nres = True else: nres = False except: warning_dialog( 'Bad filter regex? ' + self.tfilt ).warn() nres = False if model.iter_has_child( iter ): # Family. path = model.get_path( iter ) sub_st = self.ttree_paths.get( path, {} ).get( 'states', [] ) sres = sres or any([t not in self.tfilter_states for t in sub_st]) if self.tfilt: sub_nm = self.ttree_paths.get( path, {} ).get( 'names', [] ) nres = nres or any([self.tfilt in n for n in sub_nm]) return sres and nres
def reregister_popup(self, w, reg, is_group=False): window = EntryDialog(parent=self.window, flags=0, type=gtk.MESSAGE_QUESTION, buttons=gtk.BUTTONS_OK_CANCEL, message_format="Reregister Suite " + reg + " As") rereg = window.run() window.destroy() if rereg: command = "cylc reregister " + reg + ' ' + rereg res, out = run_get_stdout(command) if not res: warning_dialog('\n'.join(out), self.window).warn()
def reregister_popup( self, w, reg, is_group=False ): window = EntryDialog( parent=self.window, flags=0, type=gtk.MESSAGE_QUESTION, buttons=gtk.BUTTONS_OK_CANCEL, message_format="Reregister Suite " + reg + " As") rereg = window.run() window.destroy() if rereg: command = "cylc reregister " + reg + ' ' + rereg res, out = run_get_stdout( command ) if not res: warning_dialog( '\n'.join(out), self.window ).warn()
def alias_popup( self, w, reg ): window = EntryDialog( parent=self.window, flags=0, type=gtk.MESSAGE_QUESTION, buttons=gtk.BUTTONS_OK_CANCEL, message_format="Alias Suite Name " + reg ) alias = window.run() window.destroy() if alias: command = "cylc alias " + reg + ' ' + alias res, out = run_get_stdout( command ) if not res: warning_dialog( '\n'.join(out), self.window ).warn()
def compare_popup(self, w, reg): window = EntryDialog(parent=self.window, flags=0, type=gtk.MESSAGE_QUESTION, buttons=gtk.BUTTONS_OK_CANCEL, message_format="Compare Suite " + reg + " With") compare = window.run() window.destroy() if compare: command = "cylc diff " + reg + ' ' + compare res, out = run_get_stdout(command) if not res: warning_dialog('\n'.join(out), self.window).warn() else: # TODO: need a bigger scrollable window here! info_dialog('\n'.join(out), self.window).inform()
def compare_popup( self, w, reg ): window = EntryDialog( parent=self.window, flags=0, type=gtk.MESSAGE_QUESTION, buttons=gtk.BUTTONS_OK_CANCEL, message_format="Compare Suite " + reg + " With") compare = window.run() window.destroy() if compare: command = "cylc diff " + reg + ' ' + compare res, out = run_get_stdout( command ) if not res: warning_dialog( '\n'.join(out), self.window ).warn() else: # TODO: need a bigger scrollable window here! info_dialog( '\n'.join(out), self.window ).inform()
def rotate_log(self, bt, go_older): if go_older: self.level += 1 else: self.level -= 1 if self.level < 0: warning_dialog( """ At newest rotation; reloading in case the suite has been restarted.""", self.window, ).warn() self.level = 0 # but update view in case user started suite after gui if self.current_log() not in os.listdir(self.dir): if go_older: warning_dialog("Older log not available", self.window).warn() self.level -= 1 return else: warning_dialog("Newer log not available", self.window).warn() self.level += 1 return else: self.file = self.current_log() self.update_view()
def graph_suite( reg, is_warm, ofile, start, stop, graph_opts, gcapture_windows, tmpdir, window=None ): """Launch the cylc graph command with some options.""" options = graph_opts if ofile != '': options += ' -o ' + ofile if True: if start != '': try: ct(start) except CycleTimeError,x: warning_dialog( str(x), window ).warn() return False if stop != '': if start == '': warning_dialog( "You cannot override Final Cycle without " + "overriding Initial Cycle.").warn() return False try: ct(stop) except CycleTimeError,x: warning_dialog( str(x), window ).warn() return False
def on_find_clicked(self, e): tv = self.textview tb = tv.get_buffer() needle = e.get_text() if not needle: s, e = tb.get_bounds() tb.remove_tag(self.ftag, s, e) return self.stdout_updater.freeze = True self.freeze_button.set_active(True) self.freeze_button.set_label('_Reconnect') if not self.search_warning_done: warning_dialog(("Find Next disconnects the live feed." + " Click Reconnect when you're done."), self.window).warn() self.search_warning_done = True if needle == self.find_current: s = self.find_current_iter else: s, e = tb.get_bounds() tb.remove_tag(self.ftag, s, e) s = tb.get_end_iter() tv.scroll_to_iter(s, 0) try: start, end = s.backward_search(needle, gtk.TEXT_SEARCH_VISIBLE_ONLY) except TypeError: # Search pattern not found. warning_dialog('"' + needle + '"' + " not found", self.window).warn() else: tb.apply_tag(self.ftag, start, end) self.find_current_iter = start self.find_current = needle tv.scroll_to_iter(start, 0)
def on_find_clicked(self, tv, e): needle = e.get_text() if not needle: return tb = tv.get_buffer() if needle == self.find_current: s = self.find_current_iter else: s, e = tb.get_bounds() tb.remove_all_tags(s, e) s = tb.get_start_iter() tv.scroll_to_iter(s, 0) try: f, l = s.forward_search(needle, gtk.TEXT_SEARCH_TEXT_ONLY) except: warning_dialog('"' + needle + '"' + " not found").warn() else: tag = tb.create_tag(None, background="#70FFA9") tb.apply_tag(tag, f, l) self.find_current_iter = l self.find_current = needle tv.scroll_to_iter(f, 0)
def on_find_clicked( self, tv, e ): needle = e.get_text () if not needle: return tb = tv.get_buffer () if needle == self.find_current: s = self.find_current_iter else: s,e = tb.get_bounds() tb.remove_all_tags( s,e ) s = tb.get_start_iter() tv.scroll_to_iter( s, 0 ) try: f, l = s.forward_search (needle, gtk.TEXT_SEARCH_TEXT_ONLY) except: warning_dialog( '"' + needle + '"' + " not found" ).warn() else: tag = tb.create_tag( None, background="#70FFA9" ) tb.apply_tag( tag, f, l ) self.find_current_iter = l self.find_current = needle tv.scroll_to_iter( f, 0 )
def update_gui( self, line ): try: line.decode('utf-8') except UnicodeDecodeError as exc: if self.has_warned_corrupt: return False self.has_warned_corrupt = True dialog = warning_dialog("Problem reading file:\n %s: %s" % (type(exc).__name__, exc)) gobject.idle_add(dialog.warn) return False if self.critical_re and re.search( self.critical_re, line ): self.logbuffer.insert_with_tags( self.logbuffer.get_end_iter(), line, self.critical_tag ) elif self.warning_re and re.search( self.warning_re, line ): self.logbuffer.insert_with_tags( self.logbuffer.get_end_iter(), line, self.warning_tag ) elif self.tag: self.logbuffer.insert_with_tags( self.logbuffer.get_end_iter(), line, self.tag ) else: self.logbuffer.insert( self.logbuffer.get_end_iter(), line ) self.logview.scroll_to_iter( self.logbuffer.get_end_iter(), 0 ) return False
def graph_suite( reg, start, stop, graph_opts, gcapture_windows, tmpdir, template_opts, window=None ): """Launch the cylc graph command with some options.""" options = graph_opts if True: if start != '': try: ct(start) except CycleTimeError,x: warning_dialog( str(x), window ).warn() return False if stop != '': if start == '': warning_dialog( "You cannot override Final Cycle without " + "overriding Initial Cycle.").warn() return False try: ct(stop) except CycleTimeError,x: warning_dialog( str(x), window ).warn() return False
def rotate_log(self, bt, go_older): if go_older: self.level += 1 else: self.level -= 1 if self.level < 0: warning_dialog( """ At newest rotation; reloading in case the suite has been restarted.""", self.window).warn() self.level = 0 # but update view in case user started suite after gui if self.current_log() not in os.listdir(self.dir): if go_older: warning_dialog("Older log not available", self.window).warn() self.level -= 1 return else: warning_dialog("Newer log not available", self.window).warn() self.level += 1 return else: self.file = self.current_log() self.update_view()
gobject.idle_add( self.update_gui, out ) if self.proc != None: # See comment below self.proc.poll() else: # Live feed (pythonic 'tail -f') for local job submission. #if not os.path.exists( self.logfile ): # #gobject.idle_add( self.warn, "File not found: " + self.logfile ) # print "File not found: " + self.logfile # #print "Disconnecting from tailer thread" # return try: gen = tail.tail( open( self.logfile )) except Exception as x: # e.g. file not found dialog = warning_dialog( type(x).__name__ + ": " + str(x) ) gobject.idle_add(dialog.warn) return while not self.quit: if not self.freeze: line = gen.next() if line: gobject.idle_add( self.update_gui, line ) if self.proc != None: # poll the subprocess; this reaps its exit code and thus # prevents the pid of the finished process staying in # the OS process table (a "defunct process") until the # parent process exits. self.proc.poll() # The following doesn't work, not sure why, perhaps because
if self.stop_summary is None: self.stop_summary = dump.get_stop_state_summary( self.cfg.suite, self.cfg.owner, self.cfg.host) self._flag_new_update() return False else: try: daemon_version = self.sinfo.get('get cylc version') except KeyError: daemon_version = "??? (pre 6.1.2?)" if daemon_version != CYLC_VERSION: warning_dialog( "Warning: cylc version mismatch!\n\n" + "Suite running with %r.\n" % daemon_version + "gcylc at %r.\n" % CYLC_VERSION, self.info_bar.get_toplevel() ).warn() self.stop_summary = None self.err_log_lines = [] self.err_log_size = 0 self.status = "connected" self.connected = True self.poll_schd.stop() self._flag_new_update() return True def connection_lost( self ): self._summary_update_time = None self.state_summary = {} self.full_state_summary = {}