def show_menu(self): last_menu = self._top_menu while True: entries = last_menu.entries for i, entry in enumerate(entries): g.pr(i, ')', entry.display()) g.pr(len(last_menu.entries), ')', '[Prev]') which = get_input('Which menu entry? > ') which = which.strip() if not which: continue try: n = int(which) except ValueError: # Look for accelerator character. ch = which[0].lower() for n, z in enumerate(entries): if hasattr(z, 'underline') and ch == z.label[z.underline].lower(): break else: continue if n == len(entries): return if n < 0 or n > len(entries) - 1: continue menu = entries[n] if isinstance(menu, textMenuEntry): menu.callback() return if isinstance(menu, textMenuCascade): last_menu = menu.menu else: pass
def init(self): '''Set our ivars from settings.''' c = self.c assert(c) table = ( (self.definingwords, "forth-defwords"), (self.brackets, "forth-delimiter-pairs"), (self.keywords, "forth-words"), (self.stringwords, "forth-string-word-pairs"), (self.boldwords, "forth-bold-words"), (self.bolditalicwords, "forth-bold-italic-words"), (self.italicwords, "forth-italic-words"), ) # Add entries from @data nodes (if they exist) to the corresponding lists. for(ivarList, setting) in table: extras = [] aList = c.config.getData(setting) if aList: for s in aList: s = s.strip() if s and s[0] != '\\': # g.trace(setting,s) extras.append(s) if extras: if self.verbose: if not g.app.unitTesting and not g.app.batchMode: g.pr("Found extra forth: %s" % " ".join(extras)) ivarList.extend(extras) # Create brackets1/2 and stringwords1/2 lists. table2 = ( ("brackets", "@data forth-delimiter-pairs"), ("stringwords", "@data forth-string-word-pairs"), ) for(ivar, setting) in table2: self.splitList(ivar, setting)
def dump(self, title): g.pr(title) # g.pr('self.i',self.i) for i, line in enumerate(self.lines): marker = g.choose(i==self.i,'**',' ') g.pr("%s %3s:%s" % (marker, i, repr(line)),)
def dump(self, title): g.pr(title) # g.pr('self.i',self.i) for i, line in enumerate(self.lines): marker = '**' if i==self.i else ' ' g.pr("%s %3s:%s" % (marker, i, repr(line)),)
def dump(self, title): '''Dump lines for debugging.''' g.pr(title) for i, line in enumerate(self.lines): marker = ' ' g.pr("%s %3s:%s" % (marker, i, repr(line)),newline=False)
def trace_lines(self, lines1, lines2, parent): '''Show both s1 and s2.''' print('===== s1: %s' % parent.h) for i, s in enumerate(lines1): g.pr('%3s %r' % (i+1, s)) print('===== s2') for i, s in enumerate(lines2): g.pr('%3s %r' % (i+1, s))
def simulateDialog (self,key,defaultVal=None): val = self.theDict.get(key,defaultVal) if self.trace: g.pr(key, val) return val
def plugin_signon(self, module_name, verbose=False): """Print the plugin signon.""" # This is called from as the result of the imports # in self.loadOnePlugin m = self.signonModule if verbose: g.es("", "...%s.py v%s: %s" % (m.__name__, m.__version__, g.plugin_date(m))) g.pr(m.__name__, m.__version__) self.signonModule = None # Prevent double signons.
def newPutNl (self): g.pr("newPutNl") if g.app.quitting > 0: return t = self.logCtrl if t: t.insert("end","\n\n") t.see("end") ### t.update_idletasks() else: g.pr('')
def cancel(lb=lb): try: i = int(lb.curselection()[0]) x = sc.queue[i] sc.cancel(x) lb.delete(i,i) except: g.pr("BOOM!")
def enable_body(body): global insertOnTime,insertOffTime if body.cget("state") == "disabled": try: g.es("enable") g.pr(insertOffTime,insertOnTime) body.configure(state="normal") body.configure(insertontime=insertOnTime,insertofftime=insertOffTime) except: g.es_exception()
def get_and_use_key_press(self): global TEST_SETTINGS trace = False if (TEST_SETTINGS['TEST_INPUT'] is None) and (TEST_SETTINGS['INPUT_GENERATOR'] is None): curses.raw() curses.cbreak() curses.meta(1) self.parent.curses_pad.keypad(1) if self.parent.keypress_timeout: curses.halfdelay(self.parent.keypress_timeout) ch = self._get_ch() if ch == -1: return self.try_while_waiting() else: self.parent.curses_pad.timeout(-1) ch = self._get_ch() # handle escape-prefixed rubbish. if ch == curses.ascii.ESC: #self.parent.curses_pad.timeout(1) self.parent.curses_pad.nodelay(1) ch2 = self.parent.curses_pad.getch() if ch2 != -1: ch = curses.ascii.alt(ch2) self.parent.curses_pad.timeout(-1) # back to blocking mode #curses.flushinp() elif (TEST_SETTINGS['INPUT_GENERATOR']): self._last_get_ch_was_unicode = True try: ch = next(TEST_SETTINGS['INPUT_GENERATOR']) except StopIteration: if TEST_SETTINGS['CONTINUE_AFTER_TEST_INPUT']: TEST_SETTINGS['INPUT_GENERATOR'] = None return else: raise ExhaustedTestInput else: self._last_get_ch_was_unicode = True try: ch = TEST_SETTINGS['TEST_INPUT'].pop(0) TEST_SETTINGS['TEST_INPUT_LOG'].append(ch) except IndexError: if TEST_SETTINGS['CONTINUE_AFTER_TEST_INPUT']: TEST_SETTINGS['TEST_INPUT'] = None return else: raise ExhaustedTestInput # if trace: g.trace('Widget', self.__class__.__name__, ch, chr(ch)) if trace: g.pr('Widget', self.__class__.__name__, 'get_and_use_key_press', ch, chr(ch)) self.handle_input(ch) if self.check_value_change: self.when_check_value_changed() if self.check_cursor_move: self.when_check_cursor_moved() self.try_adjust_widgets()
def unloadOnePlugin(self, moduleOrFileName, verbose=False): moduleName = self.regularizeName(moduleOrFileName) if self.isLoaded(moduleName): if verbose: g.pr('unloading', moduleName) del self.loadedModules[moduleName] for tag in self.handlers: bunches = self.handlers.get(tag) bunches = [bunch for bunch in bunches if bunch.moduleName != moduleName] self.handlers[tag] = bunches
def applyConfiguration(config): sections = config.sections() sections.sort() for section in sections: options = config.options(section) options.sort() for option in options: g.pr(section, option, config.get(section, option))
def newPut (self,s,color="black"): g.pr("newPut",s,newline=False) if g.app.quitting > 0: return s = s.upper() t = self.logCtrl if t: t.insert("end",s) t.see("end") ### t.update_idletasks() else: g.pr(s,newline=False)
def disable_body(body): global insertOnTime,insertOffTime if body.cget("state") == "normal": try: g.es("disable") insertOnTime = body.cget("insertontime") insertOffTime = body.cget("insertofftime") g.pr(insertOffTime,insertOnTime) body.configure(state="disabled") except Exception: g.es_exception()
def show(self, s): # g.pr(s) if self.outputFile: # self.outputFile is opened in 'wb' mode. s = g.toEncodedString(s + '\n') self.outputFile.write(s) elif self.c: g.es(s) else: g.pr(s) g.pr('')
def dump_args(self): '''Dump the argument lines.''' x = self table = ( (x.old_sent_lines,'old private lines'), (x.a,'old public lines'), (x.b,'new public lines'), ) for lines,title in table: x.dump_lines(lines,title) g.pr()
def skipInterface(self, s, i): """Skip from the opening delim to *past* the matching closing delim. If no matching is found i is set to len(s)""" trace = False start = i delim2 = "end." level = 0 start = i startIndent = self.startSigIndent if trace: g.trace("***", "startIndent", startIndent, g.callers()) while i < len(s): progress = i if g.is_nl(s, i): backslashNewline = i > 0 and g.match(s, i - 1, "\\\n") i = g.skip_nl(s, i) if not backslashNewline and not g.is_nl(s, i): j, indent = g.skip_leading_ws_with_indent(s, i, self.tab_width) line = g.get_line(s, j) if trace: g.trace("indent", indent, line) if indent < startIndent and line.strip(): # An non-empty underindented line. # Issue an error unless it contains just the closing bracket. if level == 1 and g.match(s, j, delim2): pass else: if j not in self.errorLines: # No error yet given. self.errorLines.append(j) self.underindentedLine(line) elif s[i] in (" ", "\t"): i += 1 # speed up the scan. elif self.startsComment(s, i): i = self.skipComment(s, i) elif self.startsString(s, i): i = self.skipString(s, i) elif g.match(s, i, delim2): i += len(delim2) if trace: g.trace("returns\n", repr(s[start:i])) return i else: i += 1 assert progress < i self.error("no interface") if 1: g.pr("** no interface **") i, j = g.getLine(s, start) g.trace(i, s[i:j]) else: if trace: g.trace("** no interface") return start
def text_run(self): frame_idx = 0 while not self.killed: # Frames can come and go. if frame_idx > len(self.frames) - 1: frame_idx = 0 f = self.frames[frame_idx] g.pr(f.getTitle()) s = get_input('Do what? (menu,key,body,frames,tree,quit) > ') try: self.doChoice(f, s) except Exception: g.es_exception()
def draw_tree_helper(self, p, indent): for p in p.self_and_siblings(): if p.hasChildren(): box = '+' if p.isExpanded() else '-' else: box = ' ' icons = '%s%s%s%s' % ( 'b' if p.b else ' ', 'm' if p.isMarked() else ' ', '@' if p.isCloned() else ' ', '*' if p.isDirty() else ' ') g.pr(" " * indent * 2, icons, box, p.h) if p.isExpanded() and p.hasChildren(): self.draw_tree_helper(p.firstChild(), indent + 1)
def init(): '''Return True if the plugin has loaded successfully.''' ok = not g.app.unitTesting # Not for unit testing. if ok: def forceLeoToQuit(tag,keywords): if not g.app.initing: g.pr("forceLeoToQuit",tag) g.app.forceShutdown() # Force a shutdown at any other time, even "idle" time. # Exception: do not call g.app.forceShutdown in a "start2" hook. g.pr(__doc__) g.registerHandler("idle",forceLeoToQuit) g.plugin_signon(__name__) return ok
def registerOneHandler(self, tag, fn): """Register one handler""" try: moduleName = self.loadingModuleNameStack[-1] except IndexError: moduleName = '<no module>' if 0: if g.app.unitTesting: g.pr('') g.pr('%6s %15s %25s %s' % (g.app.unitTesting, moduleName, tag, fn.__name__)) items = self.handlers.get(tag, []) if fn not in items: bunch = g.Bunch(fn=fn, moduleName=moduleName, tag='handler') items.append(bunch) self.handlers[tag] = items
def runTest (self,define_g = True): x = self.shadowController p = self.p.copy() results = x.propagate_changed_lines( self.new_public_lines,self.old_private_lines,self.marker,p=p) if not self.lax and results != self.expected_private_lines: # g.pr('%s\nAtShadowTestCase.runTest:failure\n%s' % ('*' * 40,p.h)) g.pr(p.h) for aList,tag in ( (results,'results'), (self.expected_private_lines,'expected_private_lines') ): g.pr('%s...' % tag) for i, line in enumerate(aList): g.pr('%3s %s' % (i,repr(line))) g.pr('-' * 40) assert results == self.expected_private_lines assert self.ok return self.ok
def draw_tree_helper(self, p, indent): for p in p.self_and_siblings(): if p.hasChildren(): box = "+" if p.isExpanded() else "-" else: box = " " icons = "%s%s%s%s" % ( "b" if p.b else " ", "m" if p.isMarked() else " ", "@" if p.isCloned() else " ", "*" if p.isDirty() else " ", ) g.pr(" " * indent * 2, icons, box, p.h) if p.isExpanded() and p.hasChildren(): self.draw_tree_helper(p.firstChild(), indent + 1)
def searchRecent(self, *args, **kw): """Do a search on a recently used item""" # Find the item. name = self.option_value.get() for item_name, mode in self.search_list: if item_name == name: # Ok, so set mode and text and then do the search self.option_value.set(mode) self.search.delete(0, "end") self.search.insert(0, name) self.doSearch() break else: g.pr(name, self.search_list ) g.es("Recent search item not found! Looks like a bug ...", color="red")
def registerOneExclusiveHandler(self, tag, fn): """Register one exclusive handler""" try: moduleName = self.loadingModuleNameStack[-1] except IndexError: moduleName = '<no module>' if 0: if g.app.unitTesting: g.pr('') g.pr('%6s %15s %25s %s' % (g.app.unitTesting, moduleName, tag, fn.__name__)) if g.app.unitTesting: return if tag in self.handlers: g.es("*** Two exclusive handlers for", "'%s'" % (tag)) else: bunch = g.Bunch(fn=fn, moduleName=moduleName, tag='handler') self.handlers = [bunch]
def printChaptersTree(self, tag=''): cc = self; c = cc.c chaptersNode = cc.findChaptersNode() inTree = False for p in c.rootPosition().self_and_siblings(): for p2 in p.self_and_subtree(): if p2 == chaptersNode: inTree = True; break if inTree: break g.trace('-' * 40) full = True if chaptersNode and full: g.pr('@chapters tree...', '(in main tree: %s)' % inTree) for p in chaptersNode.self_and_subtree(): g.pr('.' * p.level(), p.v)
def init (): if not import_ok: return False # This plugin depends on the properties of the gui's event loop. # It may work for other gui's, but this is not guaranteed. if g.app.gui and g.app.gui.guiName() == 'qt' and not g.app.useIpython: g.pr('ipython.py plugin disabled ("leo --ipython" enables it)') return False # Call onCreate after the commander and the key handler exist. g.registerHandler('after-create-leo-frame',onCreate) g.plugin_signon(__name__) return True
def onCreate (tag, keys): c = keys.get('c') if c and c.frame.log: g.pr('overriding c.executeScript') # Inject ivars. log = c.frame.log c.script_io_to_body_oldexec = c.executeScript c.script_io_to_body_oldput = log.put c.script_io_to_body_oldputnl = log.putnl # Override c.executeScript. g.funcToMethod(newExecuteScript,c.__class__,'executeScript') c.k.overrideCommand('execute-script',c.executeScript)
def runTest(self, define_g=True): """AtShadowTestCase.runTest.""" x = self.shadowController x.trace = self.trace p = self.p.copy() results = x.propagate_changed_lines( self.new_public_lines, self.old_private_lines, self.marker, p=p) if results != self.expected_private_lines: g.pr(p.h) for aList, tag in ( (results, 'results'), (self.expected_private_lines, 'expected_private_lines') ): g.pr(f"{tag}...") for i, line in enumerate(aList): g.pr('%3s %s' % (i, repr(line))) g.pr('-' * 40) assert results == self.expected_private_lines assert self.ok return self.ok
def print_tags(tag, old_i, old_j, new_i, new_j, message): sep1 = '=' * 10 ; sep2 = '-' * 20 g.pr('\n',sep1,message,sep1,p and p.h) g.pr('\n%s: old[%s:%s] new[%s:%s]' % (tag,old_i,old_j,new_i,new_j)) g.pr('\n',sep2) table = ( (old_private_lines_rdr,'old private lines'), (old_public_lines_rdr,'old public lines'), (new_public_lines_rdr,'new public lines'), (new_private_lines_wtr,'new private lines'), ) for f,tag in table: f.dump(tag) g.pr(sep2)
def dump_d(self, d, tag): '''Print dictionary d. Similar to g.printDict.''' if d: indent = '' n = 6 for key in sorted(d): if g.isString(key): n = max(n, len(key)) g.pr('%s...{' % (tag) if tag else '{') for key in sorted(d): val = d.get(key) if key == 'body': val = 'len(body) = %s' % (len(val)) else: val = repr(val).strip() # g.pr("%s%*s: %s" % (indent,n,key,repr(d.get(key)).strip())) g.pr("%s%*s: %s" % (indent, n, key, val)) g.pr('}') else: g.pr('%s...{}' % (tag) if tag else '{}')
def dumpCompareNodes(self, fileName1, fileName2, inserted, deleted, changed): for d, kind in ( (inserted, 'inserted (only in %s)' % (fileName1)), (deleted, 'deleted (only in %s)' % (fileName2)), (changed, 'changed'), ): g.pr('\n', kind) for key in d: p = d.get(key) if g.isPython3: g.pr('%-32s %s' % (key, p.h)) else: g.pr('%-32s %s' % (key, g.toEncodedString(p.h, 'ascii')))
def doOpenWithSettings(aList): '''Create an open-with table from a list of dictionaries.''' table = [] for z in aList: command = z.get('command') name = z.get('name') shortcut = z.get('shortcut') try: data = eval(command) if 0: g.pr(name, shortcut) for i in range(len(data)): g.pr(i, repr(data[i])) g.pr('') entry = name, shortcut, data table.append(entry) except SyntaxError: g.pr(g.es_exception()) return None return table
def dump_pyzo_menus(self): ''' Add pyzo's menus to Leo's 'Pyzo' menu. To do: Suppress translations. ''' main_window = g.app.gui.hidden_main_window menuBar = main_window.menuBar() #@+<< menu dumps >> #@+node:ekr.20190426075514.1: *4* << menu dumps >> # pylint: disable=no-member # pyzo.icons *does* exist. if 0: g.trace('menuBar.children()...') for child in menuBar.children(): g.pr(child) # pyzo.core.menu.FileMenu, etc. if 0: g.trace('menuBar.actions()...') for action in menuBar.actions(): g.pr(action) if 0: g.trace('pyzo.icons...') for key, icon in pyzo.icons.items(): g.pr('%30s %0x' % (key, id(icon))) # # Show icons that exist in pyzo.icons. if 0: g.printObj(pyzo.icons, tag='pyzo.icons') if 0: values = list(pyzo.icons.values()) # g.printObj(values, tag='pyzo.icons.values()') g.pr('Action icons in pyzo.icons...') for key, menu in menuBar._menumap.items(): # Keys are menu names, values are menus. for action in menu.actions(): if action.icon() in values: g.pr('FOUND icon: id=%s', id(action.icon())) # # Dump all menus. if 0: for key, menu in menuBar._menumap.items(): # Keys are menu names, values are menus. g.pr('MENU: %s' % key) for action in menu.actions(): g.pr('action: %015x icon: %015x text: %s' % (id(action), id(action.icon()), action.text())) g.pr('')
def load_pyzo(self): ''' Go through pyzo's *entire* startup logic with monkey-patches to integrate pyzo with Leo. Called by the the top-level init() function in pyzo_support.py. ''' sys.argv = [] # Avoid trying to load extra files. # # Part 1. Do *extra* early imports before calling pyzo.start. # These are needed so we can monkey-patch main.MainWindow. g.pr('\nload_pyzo: EARLY imports...') # # For MainWindow.__init__. from pyzo.core import commandline, main, splash # This imports... # pyzo.core.main.py # pyzo.core.icons.py # pyzo.core.splash.py # # For MainWindow._populate. from pyzo.codeeditor.misc import callLater # This imports... # pyzo.codeeditor # pyzo.codeeditor.parsers # pyzo/codeeditor/base.py # pyzo.codeeditor.highlighter.py g.pr('load_pyzo: AFTER early imports') # # Part 2: Add aliases for MainWindow. __init__. loadAppIcons = main.loadAppIcons loadIcons = main.loadIcons loadFonts = main.loadFonts SplashWidget = splash.SplashWidget # # Part 3: Define the monkey-patched functions. #@+others #@+node:ekr.20190421025254.1: *4* patched: MainWindow.__init__ def __init__(self, parent=None, locale=None): ''' A monkey-patched version of MainWindow.__init__.py. Copyright (C) 2013-2018, the Pyzo development team. ''' if g: g.pr('\nBEGIN PATCHED MainWindow.__init__') super().__init__(parent) # self.setObjectName('MainWindow') # EKR. self._closeflag = 0 # Used during closing/restarting # Init window title and application icon # Set title to something nice. On Ubuntu 12.10 this text is what # is being shown at the fancy title bar (since it's not properly # updated) self.setMainTitle() loadAppIcons() self.setWindowIcon(pyzo.icon) # Restore window geometry before drawing for the first time, # such that the window is in the right place self.resize(800, 600) # default size self.restoreGeometry() # Show splash screen (we need to set our color too) w = SplashWidget(self, distro='no distro') self.setCentralWidget(w) self.setStyleSheet("QMainWindow { background-color: #268bd2;}") # Show empty window and disable updates for a while self.show() self.paintNow() self.setUpdatesEnabled(False) # Determine timeout for showing splash screen splash_timeout = time.time() + 1.0 # Set locale of main widget, so that qt strings are translated # in the right way if locale: self.setLocale(locale) # Store myself pyzo.main = self # Init dockwidget settings self.setTabPosition(QtCore.Qt.AllDockWidgetAreas, QtWidgets.QTabWidget.South) self.setDockOptions(QtWidgets.QMainWindow.AllowNestedDocks | QtWidgets.QMainWindow.AllowTabbedDocks #| QtWidgets.QMainWindow.AnimatedDocks ) # Set window atrributes self.setAttribute(QtCore.Qt.WA_AlwaysShowToolTips, True) # Load icons and fonts loadIcons() loadFonts() # Set qt style and test success self.setQtStyle(None) # None means init! # Hold the splash screen if needed while time.time() < splash_timeout: QtWidgets.qApp.flush() QtWidgets.qApp.processEvents() time.sleep(0.05) # Populate the window (imports more code) self._populate() # Revert to normal background, and enable updates self.setStyleSheet('') self.setUpdatesEnabled(True) # Restore window state, force updating, and restore again self.restoreState() self.paintNow() self.restoreState() # Present user with wizard if he/she is new. if False: # pyzo.config.state.newUser: from pyzo.util.pyzowizard import PyzoWizard w = PyzoWizard(self) w.show( ) # Use show() instead of exec_() so the user can interact with pyzo # Create new shell config if there is None if not pyzo.config.shellConfigs2: from pyzo.core.kernelbroker import KernelInfo pyzo.config.shellConfigs2.append(KernelInfo()) # EKR:patch Set background. if True: bg = getattr(pyzo.config.settings, 'dark_background', '#657b83') # Default: solarized base00 try: self.setStyleSheet("background: %s" % bg) except Exception: if g: g.pr('oops: PATCHED MainWindow.__init__') # Focus on editor e = pyzo.editors.getCurrentEditor() if e is not None: e.setFocus() # Handle any actions commandline.handle_cmd_args() if g: g.pr('END PATCHED MainWindow.__init__') # To force drawing ourselves #@+node:ekr.20190421034940.1: *4* patched: MainWindow._populate def _populate(self): ''' A monkey-patched version of MainWindow._populate. Copyright (C) 2013-2018, the Pyzo development team ''' if g: g.pr('\nBEGIN PATCHED MainWindow._populate') # Delayed imports from pyzo.core.editorTabs import EditorTabs from pyzo.core.shellStack import ShellStackWidget from pyzo.core import codeparser from pyzo.core.history import CommandHistory from pyzo.tools import ToolManager # Instantiate tool manager pyzo.toolManager = ToolManager() # Check to install conda now ... #from pyzo.util.bootstrapconda import check_for_conda_env #check_for_conda_env() # Instantiate and start source-code parser if pyzo.parser is None: pyzo.parser = codeparser.Parser() pyzo.parser.start() # Create editor stack and make the central widget pyzo.editors = EditorTabs(self) self.setCentralWidget(pyzo.editors) # EKR: QMainWindow.setCentralWidget # Create floater for shell self._shellDock = dock = QtWidgets.QDockWidget(self) if pyzo.config.settings.allowFloatingShell: dock.setFeatures(dock.DockWidgetMovable | dock.DockWidgetFloatable) else: dock.setFeatures(dock.DockWidgetMovable) dock.setObjectName('shells') dock.setWindowTitle('Shells') self.addDockWidget(QtCore.Qt.RightDockWidgetArea, dock) # Create shell stack pyzo.shells = ShellStackWidget(self) dock.setWidget(pyzo.shells) # Initialize command history pyzo.command_history = CommandHistory('command_history.py') # Create the default shell when returning to the event queue callLater(pyzo.shells.addShell) # Create statusbar if pyzo.config.view.showStatusbar: pyzo.status = self.statusBar() else: pyzo.status = None self.setStatusBar(None) # Create menu from pyzo.core import menu pyzo.keyMapper = menu.KeyMapper() menu.buildMenus(self.menuBar()) # Add the context menu to the editor pyzo.editors.addContextMenu() pyzo.shells.addContextMenu() # Load tools if pyzo.config.state.newUser and not pyzo.config.state.loadedTools: pyzo.toolManager.loadTool('pyzosourcestructure') pyzo.toolManager.loadTool('pyzofilebrowser', 'pyzosourcestructure') elif pyzo.config.state.loadedTools: for toolId in pyzo.config.state.loadedTools: pyzo.toolManager.loadTool(toolId) if g: g.pr('END PATCHED MainWindow._populate\n') #@+node:ekr.20190418204559.1: *4* patched: MainWindow.closeEvent def closeEvent(self, event): ''' A monkey-patched version of MainWindow.closeEvent. Copyright (C) 2013-2018, the Pyzo development team ''' # pylint: disable=no-member, not-an-iterable # Pylint gets confused by monkey-patches. if g: g.pr('PATCHED MainWindow.closeEvent') # Are we restaring? # restarting = time.time() - self._closeflag < 1.0 # Save settings pyzo.saveConfig() pyzo.command_history.save() # Stop command server commandline.stop_our_server() # Proceed with closing... result = pyzo.editors.closeAll() if 0: # Force the close. if not result: self._closeflag = False event.ignore() return self._closeflag = True # Proceed with closing shells pyzo.localKernelManager.terminateAll() for shell in pyzo.shells: shell._context.close() # Close tools for toolname in pyzo.toolManager.getLoadedTools(): tool = pyzo.toolManager.getTool(toolname) tool.close() # Stop all threads (this should really only be daemon threads) import threading for thread in threading.enumerate(): if hasattr(thread, 'stop'): try: thread.stop(0.1) except Exception: pass # Proceed as normal QtWidgets.QMainWindow.closeEvent(self, event) # Don't exit Leo! # if sys.version_info >= (3,3,0): # and not restarting: # if hasattr(os, '_exit'): # os._exit(0) #@-others # # Part 4: Early patches: *before* calling pyzo.start() g.funcToMethod(__init__, main.MainWindow) g.funcToMethod(_populate, main.MainWindow) # # Part 5: Do pyzo's official startup: # - Does all pyzo imports # - Instantiates all pyzo objects. pyzo.start() # # Part 6: Late patches: *after* calling pyzo.start() # Late patches are safe because all pyzo imports have been done. g.funcToMethod(closeEvent, main.MainWindow) # # Part 7: Late inits. # Each PyzoController instance inits menus, etc. if 0: self.dump_pyzo_objects() if 0: self.reparent_dock()
def createEditor(parent, filename=None): """ Tries to load the file given by the filename and if succesful, creates an editor instance to put it in, which is returned. If filename is None, an new/unsaved/temp file is created. """ if g.pyzo_trace: g.pr('createEditor: %r' % filename) if filename is None: # Increase counter global newFileCounter newFileCounter += 1 # Create editor editor = PyzoEditor(parent) editor.document().setModified(True) # Set name editor._name = "<tmp {}>".format(newFileCounter) elif g.pyzo_outline_tab and g.pyzo and g.pyzo_patch and filename.endswith( '.leo'): from leo.core.pyzo_shims import OutlineEditorShim #@+<< createEditor patch >> #@+node:ekr.20190408085219.2: *3* << createEditor patch >> # check and normalize if not os.path.isfile(filename): raise IOError("File does not exist '%s'." % filename) # # load file (as bytes) with open(filename, 'rb') as f: bb = f.read() f.close() # convert to text, be gentle with files not encoded with utf-8 encoding = determineEncoding(bb) text = bb.decode(encoding, 'replace') # process line endings lineEndings = determineLineEnding(text) # if we got here safely ... # create editor and set text ### editor = PyzoEditor(parent) editor = OutlineEditorShim(filename, parent) editor.setPlainText(text) # g.trace('len(text)', len(text)) editor.lineEndings = lineEndings editor.encoding = encoding editor.document().setModified(False) # store name and filename # Now done in OutlineEditorShim. # editor._filename = filename # editor._name = os.path.split(filename)[1] # process indentation ### # indentWidth = determineIndentation(text) # if indentWidth == -1: #Tabs # editor.setIndentWidth(pyzo.config.settings.defaultIndentWidth) # editor.setIndentUsingSpaces(False) # elif indentWidth: # editor.setIndentWidth(indentWidth) # editor.setIndentUsingSpaces(True) if editor._filename: editor._modifyTime = os.path.getmtime(editor._filename) # Set parser if 0: if editor._filename: ### ext = os.path.splitext(editor._filename)[1] ext = '.py' parser = Manager.suggestParser(ext, text) editor.setParser(parser) else: # todo: rename style -> parser editor.setParser(pyzo.config.settings.defaultStyle) #@-<< createEditor patch >> return editor else: # check and normalize if not os.path.isfile(filename): raise IOError("File does not exist '%s'." % filename) # load file (as bytes) with open(filename, 'rb') as f: bb = f.read() f.close() # convert to text, be gentle with files not encoded with utf-8 encoding = determineEncoding(bb) text = bb.decode(encoding, 'replace') # process line endings lineEndings = determineLineEnding(text) # if we got here safely ... # create editor and set text editor = PyzoEditor(parent) # showlinenumbers=False) editor.setPlainText(text) editor.lineEndings = lineEndings editor.encoding = encoding editor.document().setModified(False) # store name and filename editor._filename = filename editor._name = os.path.split(filename)[1] # process indentation indentWidth = determineIndentation(text) if indentWidth == -1: #Tabs editor.setIndentWidth(pyzo.config.settings.defaultIndentWidth) editor.setIndentUsingSpaces(False) elif indentWidth: editor.setIndentWidth(indentWidth) editor.setIndentUsingSpaces(True) if editor._filename: editor._modifyTime = os.path.getmtime(editor._filename) # Set parser if editor._filename: ext = os.path.splitext(editor._filename)[1] parser = Manager.suggestParser(ext, text) editor.setParser(parser) else: # todo: rename style -> parser editor.setParser(pyzo.config.settings.defaultStyle) # return return editor
def putnl(self, tabName='log'): g.pr('')
def text_show(self): w = self.bodyCtrl g.pr('--- body ---') g.pr('ins', w.ins, 'sel', w.sel) g.pr(w.s)
def closeEvent(self, event): """ Override close event handler. """ import pyzo.core.commandline as commandline g.pr('\nMainWindowShim.closeEvent 1') t1 = time.process_time() # Are we restaring? ### restarting = time.time() - self._closeflag < 1.0 # Save settings pyzo.saveConfig() pyzo.command_history.save() # Stop command server commandline.stop_our_server() # Proceed with closing... result = pyzo.editors.closeAll() if not result: self._closeflag = False event.ignore() return else: self._closeflag = True t2 = time.process_time() # Proceed with closing shells pyzo.localKernelManager.terminateAll() # pylint: disable=no-member for shell in pyzo.shells: shell._context.close() t3 = time.process_time() # Close tools for toolname in pyzo.toolManager.getLoadedTools(): tool = pyzo.toolManager.getTool(toolname) tool.close() t4 = time.process_time() # Stop all threads (this should really only be daemon threads) import threading for thread in threading.enumerate(): if hasattr(thread, 'stop'): try: thread.stop(0.1) except Exception: pass t5 = time.process_time() if 1: # EKR g.pr('\nMainWindowShim.closeEvent 2') g.pr('stage 1: %5.2f' % (t2 - t1)) g.pr('stage 2: shells: %5.2f' % (t3 - t2)) g.pr('stage 3: tools: %5.2f' % (t4 - t3)) g.pr('stage 4: threads: %5.2f' % (t5 - t4)) # Proceed as normal QtWidgets.QMainWindow.closeEvent(self, event) # Harder exit to prevent segfault. Not really a solution, # but it does the job until Pyside gets fixed. if sys.version_info >= (3, 3, 0): # and not restarting: if hasattr(os, '_exit'): os._exit(0)
def oops(self): g.pr("BaseEditCommandsClass oops:", g.callers(), "must be overridden in subclass")
def dump_lines(self, lines, title): """Dump the given lines.""" print(f"\n{title}...\n") for i, line in enumerate(lines): g.pr(f"{i:4} {line!r}")
def oops(self): # It is not usually an error to call methods of this class. # However, this message is useful when writing gui plugins. if 1: g.pr("LeoGui oops", g.callers(4), "should be overridden in subclass")
def simulateDialog(self, key, defaultVal=None): val = self.theDict.get(key, defaultVal) if self.trace: g.pr(key, val) return val
#@@tabwidth -4 #@+<< imports >> #@+node:ekr.20050101090207.1: ** << imports >> import leo.core.leoGlobals as g Tk = g.importExtension('Tkinter', pluginName=__name__, verbose=True) try: import ImageTk except ImportError: # ImageTk has moved to PIL on some systems. try: from PIL import ImageTk except ImportError: g.pr('image.py: can not import ImageTk') ImageTk = None #@-<< imports >> #@+<< version history >> #@+node:ekr.20060619092335: ** << version history >> #@@nocolor #@+at # # 1.3 EKR: Attempt to use ImageTk if it exists. # Does not work on my machine, but that may be an installation problem. # # 1.4 EKR: Import ImageTk from PIL if the first import fails. #@-<< version history >> __version__ = "1.4" # Set version for the plugin handler.
def __init__(self): config_base.__init__(self) g.pr('\n===== ConfigShim: new_config: %s\n' % new_config) self.setObjectName('ConfigShim')
def dump_lines(self, lines, title): """Dump the given lines.""" print('\n%s...\n' % title) for i, line in enumerate(lines): g.pr('%4s %s' % (i, repr(line)))
def trace_tags(tag, keywords): global tagCount brief = True tagCount += 1 # Always count the hook. # List of hooks to suppress. if tag in ( 'bodykey1', 'bodykey2', 'dragging1', 'dragging2', 'headkey1', 'headkey2', 'idle', 'after-redraw-outline', 'redraw-entire-outline', 'draw-outline-text-box', 'draw-outline-icon', 'draw-outline-node', 'draw-outline-box', 'draw-sub-outline', ): return # Almost all tags have both c and v keys in the keywords dict. if tag not in ('start1', 'end1', 'open1', 'open2', 'idle'): c = keywords.get('c') v = keywords.get('v') if not c: g.pr(tagCount, tag, 'c = None') if not v: if tag not in ('select1', 'select2', 'select3', 'unselect1', 'unselect2'): g.pr(tagCount, tag, 'v = None') # Hook-specific traces... if tag in ('command1', 'command2'): g.pr(tagCount, tag, keywords.get('label')) elif tag in ('open1', 'open2'): g.pr(tagCount, tag, keywords.get('fileName')) elif brief: g.pr(tagCount, tag) else: # Verbose keys = list(keywords.items()) keys.sort() for key, value in keys: g.pr(tagCount, tag, key, value) g.pr('')
def _populate(self): ''' This method is based on pyzo code Copyright (C) 2013-2018 by Almar Klein. ''' trace = False and g.pyzo_trace_imports # Delayed imports, exactly as in MainWindow._populate. if trace: g.pr('\n===== MainWindowShim._populate\n') from pyzo.core.editorTabs import EditorTabs from pyzo.core.shellStack import ShellStackWidget from pyzo.core import codeparser from pyzo.core.history import CommandHistory from pyzo.tools import ToolManager if trace: g.pr('\n===== MainWindowShim._populate: end of delayed imports\n') g.pr('initial_draw:', self.initial_draw) g.pr(' use_menu:', self.use_menu) g.pr(' use_shell:', self.use_shell) # # Instantiate tool manager pyzo.toolManager = ToolManager() # # Instantiate and start source-code parser if pyzo.parser is None: pyzo.parser = codeparser.Parser() pyzo.parser.start() # # Create editor stack and make the central widget pyzo.editors = EditorTabs(self) self.setCentralWidget(pyzo.editors) # # Create floater for shell self._shellDock = dock = QtWidgets.QDockWidget(self) if pyzo.config.settings.allowFloatingShell: dock.setFeatures(dock.DockWidgetMovable | dock.DockWidgetFloatable) else: dock.setFeatures(dock.DockWidgetMovable) dock.setObjectName('shells') dock.setWindowTitle('Shells') self.addDockWidget(QtCore.Qt.RightDockWidgetArea, dock) # # Create shell stack if self.use_shell: # Disabling the shell works. pyzo.shells = ShellStackWidget(self) dock.setWidget(pyzo.shells) pyzo.shells.menu = g.TracingNullObject(tag='pyzo.shells.menu') # To suppress menu events. else: pyzo.shells = g.TracingNullObject(tag='pyzo.shells') # # Initialize command history pyzo.command_history = CommandHistory('command_history.py') # # Create the default shell when returning to the event queue if self.use_shell: pyzo.core.main.callLater(pyzo.shells.addShell) # # Create statusbar if pyzo.config.view.showStatusbar: pyzo.status = self.statusBar() else: pyzo.status = None self.setStatusBar(None) # # Create the menu. if self.use_menu: from pyzo.core import menu pyzo.keyMapper = menu.KeyMapper() assert not isinstance(pyzo.keyMapper, (g.TracingNullObject, g.NullObject)) # This should not be a Shim. menu.buildMenus(self.menuBar()) pyzo.editors.addContextMenu() pyzo.shells.addContextMenu() else: # Shim: pyzo.shells = g.TracingNullObject(tag='pyzo.shells') pyzo.keyMapper = g.TracingNullObject(tag='pyzo.keyMapper') from pyzo.core.shellStack import ShellStackWidget def null_menu_callback(*args, **kwargs): pass # g.trace(args, kwargs) # Apparently, doing nothing prevents the Shell from warming up. # For now, use_shell sets use_menu. assert not self.use_shell g.funcToMethod(null_menu_callback, ShellStackWidget, name='onShellStateChange') g.funcToMethod(null_menu_callback, ShellStackWidget, name='onShellDebugStateChange') # # Load tools if pyzo.config.state.newUser and not pyzo.config.state.loadedTools: pyzo.toolManager.loadTool('pyzosourcestructure') pyzo.toolManager.loadTool('pyzofilebrowser', 'pyzosourcestructure') elif pyzo.config.state.loadedTools: for toolId in pyzo.config.state.loadedTools: pyzo.toolManager.loadTool(toolId)
def __init__(self, c, title=None): g.pr("myLeoFrame ctor", title) super().__init__(c, gui=None)
def _addAction(self, *args, **kwargs): g.pr('MenuBarShim._addAction', args, kwargs)
def oops(self): g.pr("textGui oops", g.callers(), "should be implemented")
def __init__(self, title=None): g.pr("myLeoFrame ctor", title) leoFrame.LeoFrame.__init__(self, title)
def put(self, s, color=None, tabName='Log', from_redirect=False): g.pr(s, newline=False)
def _populate(self): ''' A monkey-patched version of MainWindow._populate. Copyright (C) 2013-2018, the Pyzo development team ''' if g: g.pr('\nBEGIN PATCHED MainWindow._populate') # Delayed imports from pyzo.core.editorTabs import EditorTabs from pyzo.core.shellStack import ShellStackWidget from pyzo.core import codeparser from pyzo.core.history import CommandHistory from pyzo.tools import ToolManager # Instantiate tool manager pyzo.toolManager = ToolManager() # Check to install conda now ... #from pyzo.util.bootstrapconda import check_for_conda_env #check_for_conda_env() # Instantiate and start source-code parser if pyzo.parser is None: pyzo.parser = codeparser.Parser() pyzo.parser.start() # Create editor stack and make the central widget pyzo.editors = EditorTabs(self) self.setCentralWidget(pyzo.editors) # EKR: QMainWindow.setCentralWidget # Create floater for shell self._shellDock = dock = QtWidgets.QDockWidget(self) if pyzo.config.settings.allowFloatingShell: dock.setFeatures(dock.DockWidgetMovable | dock.DockWidgetFloatable) else: dock.setFeatures(dock.DockWidgetMovable) dock.setObjectName('shells') dock.setWindowTitle('Shells') self.addDockWidget(QtCore.Qt.RightDockWidgetArea, dock) # Create shell stack pyzo.shells = ShellStackWidget(self) dock.setWidget(pyzo.shells) # Initialize command history pyzo.command_history = CommandHistory('command_history.py') # Create the default shell when returning to the event queue callLater(pyzo.shells.addShell) # Create statusbar if pyzo.config.view.showStatusbar: pyzo.status = self.statusBar() else: pyzo.status = None self.setStatusBar(None) # Create menu from pyzo.core import menu pyzo.keyMapper = menu.KeyMapper() menu.buildMenus(self.menuBar()) # Add the context menu to the editor pyzo.editors.addContextMenu() pyzo.shells.addContextMenu() # Load tools if pyzo.config.state.newUser and not pyzo.config.state.loadedTools: pyzo.toolManager.loadTool('pyzosourcestructure') pyzo.toolManager.loadTool('pyzofilebrowser', 'pyzosourcestructure') elif pyzo.config.state.loadedTools: for toolId in pyzo.config.state.loadedTools: pyzo.toolManager.loadTool(toolId) if g: g.pr('END PATCHED MainWindow._populate\n')
def text_draw_tree(self): # g.trace(g.callers()) g.pr('--- tree ---') self.draw_tree_helper(self.c.rootPosition(), indent=0)
def __init__(self, parent=None, locale=None): ''' A monkey-patched version of MainWindow.__init__.py. Copyright (C) 2013-2018, the Pyzo development team. ''' if g: g.pr('\nBEGIN PATCHED MainWindow.__init__') super().__init__(parent) # self.setObjectName('MainWindow') # EKR. self._closeflag = 0 # Used during closing/restarting # Init window title and application icon # Set title to something nice. On Ubuntu 12.10 this text is what # is being shown at the fancy title bar (since it's not properly # updated) self.setMainTitle() loadAppIcons() self.setWindowIcon(pyzo.icon) # Restore window geometry before drawing for the first time, # such that the window is in the right place self.resize(800, 600) # default size self.restoreGeometry() # Show splash screen (we need to set our color too) w = SplashWidget(self, distro='no distro') self.setCentralWidget(w) self.setStyleSheet("QMainWindow { background-color: #268bd2;}") # Show empty window and disable updates for a while self.show() self.paintNow() self.setUpdatesEnabled(False) # Determine timeout for showing splash screen splash_timeout = time.time() + 1.0 # Set locale of main widget, so that qt strings are translated # in the right way if locale: self.setLocale(locale) # Store myself pyzo.main = self # Init dockwidget settings self.setTabPosition(QtCore.Qt.AllDockWidgetAreas, QtWidgets.QTabWidget.South) self.setDockOptions(QtWidgets.QMainWindow.AllowNestedDocks | QtWidgets.QMainWindow.AllowTabbedDocks #| QtWidgets.QMainWindow.AnimatedDocks ) # Set window atrributes self.setAttribute(QtCore.Qt.WA_AlwaysShowToolTips, True) # Load icons and fonts loadIcons() loadFonts() # Set qt style and test success self.setQtStyle(None) # None means init! # Hold the splash screen if needed while time.time() < splash_timeout: QtWidgets.qApp.flush() QtWidgets.qApp.processEvents() time.sleep(0.05) # Populate the window (imports more code) self._populate() # Revert to normal background, and enable updates self.setStyleSheet('') self.setUpdatesEnabled(True) # Restore window state, force updating, and restore again self.restoreState() self.paintNow() self.restoreState() # Present user with wizard if he/she is new. if False: # pyzo.config.state.newUser: from pyzo.util.pyzowizard import PyzoWizard w = PyzoWizard(self) w.show( ) # Use show() instead of exec_() so the user can interact with pyzo # Create new shell config if there is None if not pyzo.config.shellConfigs2: from pyzo.core.kernelbroker import KernelInfo pyzo.config.shellConfigs2.append(KernelInfo()) # EKR:patch Set background. if True: bg = getattr(pyzo.config.settings, 'dark_background', '#657b83') # Default: solarized base00 try: self.setStyleSheet("background: %s" % bg) except Exception: if g: g.pr('oops: PATCHED MainWindow.__init__') # Focus on editor e = pyzo.editors.getCurrentEditor() if e is not None: e.setFocus() # Handle any actions commandline.handle_cmd_args() if g: g.pr('END PATCHED MainWindow.__init__')
def __init__(self, parent=None, locale=None): ''' Important: do *all* inits here. Do *not* call MainWindow.__init__. This allows us complete control over all aspects of the startup process. This method is based on pyzo code Copyright (C) 2013-2018 by Almar Klein. ''' # # pylint: disable=non-parent-init-called, super-init-not-called QtWidgets.QMainWindow.__init__(self, parent) # # Do **not** call MainWindow.__init__: it calls _populate! # self.setObjectName('MainWindowShim') self.monkey_patch_leo() pyzo.loadConfig() # To be replaced by LeoPyzoConfig.loadConfig. self._closeflag = 0 # Used during closing/restarting # # Init window title and application icon # Set title to something nice. On Ubuntu 12.10 this text is what # is being shown at the fancy title bar (since it's not properly # updated) self.setWindowTitle('Leo Main Window') pyzo.core.main.loadAppIcons() g.app.gui.attachLeoIcon(self) # # Restore window geometry before drawing for the first time. self.resize(800, 600) # default size self.restoreGeometry() # # This just slows down the initial draw. # self.setCentralWidget(SplashShim(parent)) # # These do nothing, even when use_shell is True. # self.setStyleSheet("QMainWindow { background-color: #268bd2;}") # self.setStyleSheet("QMainWindow { background-color: red;}") # # Show empty window and disable updates for a while if self.initial_draw: self.show() self.paintNow() self.setUpdatesEnabled(False) # # Set locale of main widget, for translate. if locale: self.setLocale(locale) # # Store myself pyzo.main = self # # Init dockwidget settings self.setTabPosition(QtCore.Qt.AllDockWidgetAreas, QtWidgets.QTabWidget.South) self.setDockOptions(QtWidgets.QMainWindow.AllowNestedDocks | QtWidgets.QMainWindow.AllowTabbedDocks #| QtWidgets.QMainWindow.AnimatedDocks ) # # Set window atrributes self.setAttribute(QtCore.Qt.WA_AlwaysShowToolTips, True) # # Load pyzo icons and fonts. pyzo.core.main.loadIcons() pyzo.core.main.loadFonts() # # Set qt style and test success self.setQtStyle(None) # None means init! # # Populate the window (imports more code) self._populate() # # Revert to normal background, and enable updates self.setStyleSheet('') # Required. self.setUpdatesEnabled(True) # # Restore window state, force updating, and restore again self.restoreState() if not self.initial_draw: self.show() self.paintNow() self.restoreState() # # Create new shell config if there is None if not pyzo.config.shellConfigs2: from pyzo.core.kernelbroker import KernelInfo pyzo.config.shellConfigs2.append(KernelInfo()) # # EKR: Set background. if getattr(pyzo.config.settings, 'dark_theme', None): bg = getattr(pyzo.config.settings, 'dark_background', '#657b83') # Default: solarized base00 try: self.setStyleSheet("background: %s" % bg) except Exception: g.pr('oops: MainWindow.__init__') # # Put the focus on editor e = pyzo.editors.getCurrentEditor() if e is not None: e.setFocus() # # Handle any actions pyzo.core.commandline.handle_cmd_args()
class MainWindowShim(pyzo.core.main.MainWindow): #@+<< MainWindowShim switches >> #@+node:ekr.20190402104228.1: *3* << MainWindowShim switches >> initial_draw = False # True: do an initial draw. Works either way. use_shell = False # There is no great flash when use_shell is True. use_menu = False # # The shell never warms up if there are no menus. # So for now just force use_menu to True. if use_shell and not use_menu: g.pr('\nMainWindowShim: use_shell sets use_menu = True\n') use_menu = True #@-<< MainWindowShim switches >> #@+others #@+node:ekr.20190317084647.2: *3* MainWindowShim.__init__ def __init__(self, parent=None, locale=None): ''' Important: do *all* inits here. Do *not* call MainWindow.__init__. This allows us complete control over all aspects of the startup process. This method is based on pyzo code Copyright (C) 2013-2018 by Almar Klein. ''' # # pylint: disable=non-parent-init-called, super-init-not-called QtWidgets.QMainWindow.__init__(self, parent) # # Do **not** call MainWindow.__init__: it calls _populate! # self.setObjectName('MainWindowShim') self.monkey_patch_leo() pyzo.loadConfig() # To be replaced by LeoPyzoConfig.loadConfig. self._closeflag = 0 # Used during closing/restarting # # Init window title and application icon # Set title to something nice. On Ubuntu 12.10 this text is what # is being shown at the fancy title bar (since it's not properly # updated) self.setWindowTitle('Leo Main Window') pyzo.core.main.loadAppIcons() g.app.gui.attachLeoIcon(self) # # Restore window geometry before drawing for the first time. self.resize(800, 600) # default size self.restoreGeometry() # # This just slows down the initial draw. # self.setCentralWidget(SplashShim(parent)) # # These do nothing, even when use_shell is True. # self.setStyleSheet("QMainWindow { background-color: #268bd2;}") # self.setStyleSheet("QMainWindow { background-color: red;}") # # Show empty window and disable updates for a while if self.initial_draw: self.show() self.paintNow() self.setUpdatesEnabled(False) # # Set locale of main widget, for translate. if locale: self.setLocale(locale) # # Store myself pyzo.main = self # # Init dockwidget settings self.setTabPosition(QtCore.Qt.AllDockWidgetAreas, QtWidgets.QTabWidget.South) self.setDockOptions(QtWidgets.QMainWindow.AllowNestedDocks | QtWidgets.QMainWindow.AllowTabbedDocks #| QtWidgets.QMainWindow.AnimatedDocks ) # # Set window atrributes self.setAttribute(QtCore.Qt.WA_AlwaysShowToolTips, True) # # Load pyzo icons and fonts. pyzo.core.main.loadIcons() pyzo.core.main.loadFonts() # # Set qt style and test success self.setQtStyle(None) # None means init! # # Populate the window (imports more code) self._populate() # # Revert to normal background, and enable updates self.setStyleSheet('') # Required. self.setUpdatesEnabled(True) # # Restore window state, force updating, and restore again self.restoreState() if not self.initial_draw: self.show() self.paintNow() self.restoreState() # # Create new shell config if there is None if not pyzo.config.shellConfigs2: from pyzo.core.kernelbroker import KernelInfo pyzo.config.shellConfigs2.append(KernelInfo()) # # EKR: Set background. if getattr(pyzo.config.settings, 'dark_theme', None): bg = getattr(pyzo.config.settings, 'dark_background', '#657b83') # Default: solarized base00 try: self.setStyleSheet("background: %s" % bg) except Exception: g.pr('oops: MainWindow.__init__') # # Put the focus on editor e = pyzo.editors.getCurrentEditor() if e is not None: e.setFocus() # # Handle any actions pyzo.core.commandline.handle_cmd_args() #@+node:ekr.20190317084647.3: *3* MainWindowShim._populate (5 shims) def _populate(self): ''' This method is based on pyzo code Copyright (C) 2013-2018 by Almar Klein. ''' trace = False and g.pyzo_trace_imports # Delayed imports, exactly as in MainWindow._populate. if trace: g.pr('\n===== MainWindowShim._populate\n') from pyzo.core.editorTabs import EditorTabs from pyzo.core.shellStack import ShellStackWidget from pyzo.core import codeparser from pyzo.core.history import CommandHistory from pyzo.tools import ToolManager if trace: g.pr('\n===== MainWindowShim._populate: end of delayed imports\n') g.pr('initial_draw:', self.initial_draw) g.pr(' use_menu:', self.use_menu) g.pr(' use_shell:', self.use_shell) # # Instantiate tool manager pyzo.toolManager = ToolManager() # # Instantiate and start source-code parser if pyzo.parser is None: pyzo.parser = codeparser.Parser() pyzo.parser.start() # # Create editor stack and make the central widget pyzo.editors = EditorTabs(self) self.setCentralWidget(pyzo.editors) # # Create floater for shell self._shellDock = dock = QtWidgets.QDockWidget(self) if pyzo.config.settings.allowFloatingShell: dock.setFeatures(dock.DockWidgetMovable | dock.DockWidgetFloatable) else: dock.setFeatures(dock.DockWidgetMovable) dock.setObjectName('shells') dock.setWindowTitle('Shells') self.addDockWidget(QtCore.Qt.RightDockWidgetArea, dock) # # Create shell stack if self.use_shell: # Disabling the shell works. pyzo.shells = ShellStackWidget(self) dock.setWidget(pyzo.shells) pyzo.shells.menu = g.TracingNullObject(tag='pyzo.shells.menu') # To suppress menu events. else: pyzo.shells = g.TracingNullObject(tag='pyzo.shells') # # Initialize command history pyzo.command_history = CommandHistory('command_history.py') # # Create the default shell when returning to the event queue if self.use_shell: pyzo.core.main.callLater(pyzo.shells.addShell) # # Create statusbar if pyzo.config.view.showStatusbar: pyzo.status = self.statusBar() else: pyzo.status = None self.setStatusBar(None) # # Create the menu. if self.use_menu: from pyzo.core import menu pyzo.keyMapper = menu.KeyMapper() assert not isinstance(pyzo.keyMapper, (g.TracingNullObject, g.NullObject)) # This should not be a Shim. menu.buildMenus(self.menuBar()) pyzo.editors.addContextMenu() pyzo.shells.addContextMenu() else: # Shim: pyzo.shells = g.TracingNullObject(tag='pyzo.shells') pyzo.keyMapper = g.TracingNullObject(tag='pyzo.keyMapper') from pyzo.core.shellStack import ShellStackWidget def null_menu_callback(*args, **kwargs): pass # g.trace(args, kwargs) # Apparently, doing nothing prevents the Shell from warming up. # For now, use_shell sets use_menu. assert not self.use_shell g.funcToMethod(null_menu_callback, ShellStackWidget, name='onShellStateChange') g.funcToMethod(null_menu_callback, ShellStackWidget, name='onShellDebugStateChange') # # Load tools if pyzo.config.state.newUser and not pyzo.config.state.loadedTools: pyzo.toolManager.loadTool('pyzosourcestructure') pyzo.toolManager.loadTool('pyzofilebrowser', 'pyzosourcestructure') elif pyzo.config.state.loadedTools: for toolId in pyzo.config.state.loadedTools: pyzo.toolManager.loadTool(toolId) #@+node:ekr.20190317084647.5: *3* MainWindowShim.closeEvent (traces) def closeEvent(self, event): """ Override close event handler. """ import pyzo.core.commandline as commandline g.pr('\nMainWindowShim.closeEvent 1') t1 = time.process_time() # Are we restaring? ### restarting = time.time() - self._closeflag < 1.0 # Save settings pyzo.saveConfig() pyzo.command_history.save() # Stop command server commandline.stop_our_server() # Proceed with closing... result = pyzo.editors.closeAll() if not result: self._closeflag = False event.ignore() return else: self._closeflag = True t2 = time.process_time() # Proceed with closing shells pyzo.localKernelManager.terminateAll() # pylint: disable=no-member for shell in pyzo.shells: shell._context.close() t3 = time.process_time() # Close tools for toolname in pyzo.toolManager.getLoadedTools(): tool = pyzo.toolManager.getTool(toolname) tool.close() t4 = time.process_time() # Stop all threads (this should really only be daemon threads) import threading for thread in threading.enumerate(): if hasattr(thread, 'stop'): try: thread.stop(0.1) except Exception: pass t5 = time.process_time() if 1: # EKR g.pr('\nMainWindowShim.closeEvent 2') g.pr('stage 1: %5.2f' % (t2 - t1)) g.pr('stage 2: shells: %5.2f' % (t3 - t2)) g.pr('stage 3: tools: %5.2f' % (t4 - t3)) g.pr('stage 4: threads: %5.2f' % (t5 - t4)) # Proceed as normal QtWidgets.QMainWindow.closeEvent(self, event) # Harder exit to prevent segfault. Not really a solution, # but it does the job until Pyside gets fixed. if sys.version_info >= (3, 3, 0): # and not restarting: if hasattr(os, '_exit'): os._exit(0) #@+node:ekr.20190402101635.1: *3* MainWindowShim.monkey_patch_leo def monkey_patch_leo(self): global old_loadFile # # Use a Leonine pyzo.config. if 0: # Works, but uses light theme. pyzo.config = ConfigShim() # # Ignore .leo files. if 0: # Probably will never be needed: it's fine to load .leo files for now. from pyzo.core.editorTabs import EditorTabs old_loadFile = EditorTabs.loadFile g.funcToMethod(loadFile, EditorTabs) # # Patch pyzo.core.editor.createEditor function if 1: import pyzo.core.editor pyzo.core.editor.createEditor = createEditor #@+node:ekr.20190331173436.1: *3* MainWindowShim.setMainTitle def setMainTitle(self, path=None): """ Set the title of the main window, by giving a file path. """ self.setWindowTitle('Leo Main Window') ### From MainWindow # if not path: # # Plain title # title = "Interactive Editor for Python" # else: # # Title with a filename # name = os.path.basename(path) # if os.path.isfile(path): # pass # elif name == path: # path = translate("main", 'unsaved') # else: # pass # We hope the given path is informative # # Set title # tmp = { 'fileName':name, 'filename':name, 'name':name, # 'fullPath':path, 'fullpath':path, 'path':path } # title = pyzo.config.advanced.titleText.format(**tmp) # # Set # self.setWindowTitle(title) #@+node:ekr.20190317084647.4: *3* MainWindowShim.setStyleSheet (override) firstStyleSheet = True def setStyleSheet(self, style, *args, **kwargs): # print('MainWindowShim.setStyleSheet', style, args, kwargs) # A hack: Ignore the first call. if self.firstStyleSheet: self.firstStyleSheet = False return QtWidgets.QMainWindow.setStyleSheet(self, style)