From 80d6c657d5bd7ef5e45cdf312934a314a384190f Mon Sep 17 00:00:00 2001 From: Kamil Sopko Date: Fri, 25 Mar 2016 13:56:18 +0100 Subject: [PATCH] merge changes from master merge dockable shell --- FlatCAMApp.py | 61 ++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 48 insertions(+), 13 deletions(-) diff --git a/FlatCAMApp.py b/FlatCAMApp.py index 0ed5b896..d17bbbcf 100644 --- a/FlatCAMApp.py +++ b/FlatCAMApp.py @@ -10,6 +10,7 @@ import os import Tkinter from PyQt4 import QtCore import time # Just used for debugging. Double check before removing. +from xml.dom.minidom import parseString as parse_xml_string from contextlib import contextmanager ######################################## @@ -26,7 +27,6 @@ from FlatCAMDraw import FlatCAMDraw from FlatCAMProcess import * from MeasurementTool import Measurement from DblSidedTool import DblSidedTool -from xml.dom.minidom import parseString as parse_xml_string import tclCommands ######################################## @@ -105,6 +105,8 @@ class App(QtCore.QObject): # and is ready to be used. new_object_available = QtCore.pyqtSignal(object) + message = QtCore.pyqtSignal(str, str, str) + # Emmited when shell command is finished(one command only) shell_command_finished = QtCore.pyqtSignal(object) @@ -112,8 +114,6 @@ class App(QtCore.QObject): # in the worker task. thread_exception = QtCore.pyqtSignal(object) - message = QtCore.pyqtSignal(str, str, str) - def __init__(self, user_defaults=True, post_gui=None): """ Starts the application. @@ -479,7 +479,7 @@ class App(QtCore.QObject): self.ui.menuviewdisableall.triggered.connect(self.disable_plots) self.ui.menuviewdisableother.triggered.connect(lambda: self.disable_plots(except_current=True)) self.ui.menuviewenable.triggered.connect(self.enable_all_plots) - self.ui.menutoolshell.triggered.connect(lambda: self.shell.show()) + self.ui.menutoolshell.triggered.connect(self.on_toggle_shell) self.ui.menuhelp_about.triggered.connect(self.on_about) self.ui.menuhelp_home.triggered.connect(lambda: webbrowser.open(self.app_url)) self.ui.menuhelp_manual.triggered.connect(lambda: webbrowser.open(self.manual_url)) @@ -493,7 +493,7 @@ class App(QtCore.QObject): self.ui.editgeo_btn.triggered.connect(self.edit_geometry) self.ui.updategeo_btn.triggered.connect(self.editor2geometry) self.ui.delete_btn.triggered.connect(self.on_delete) - self.ui.shell_btn.triggered.connect(lambda: self.shell.show()) + self.ui.shell_btn.triggered.connect(self.on_toggle_shell) # Object list self.collection.view.activated.connect(self.on_row_activated) # Options @@ -528,14 +528,24 @@ class App(QtCore.QObject): self.shell = FCShell(self) self.shell.setWindowIcon(self.ui.app_icon) self.shell.setWindowTitle("FlatCAM Shell") - if self.defaults["shell_at_startup"]: - self.shell.show() self.shell.resize(*self.defaults["shell_shape"]) self.shell.append_output("FlatCAM %s\n(c) 2014-2015 Juan Pablo Caram\n\n" % self.version) self.shell.append_output("Type help to get started.\n\n") self.init_tcl() + self.ui.shell_dock = QtGui.QDockWidget("FlatCAM TCL Shell") + self.ui.shell_dock.setWidget(self.shell) + self.ui.shell_dock.setAllowedAreas(QtCore.Qt.AllDockWidgetAreas) + self.ui.shell_dock.setFeatures(QtGui.QDockWidget.DockWidgetMovable | + QtGui.QDockWidget.DockWidgetFloatable | QtGui.QDockWidget.DockWidgetClosable) + self.ui.addDockWidget(QtCore.Qt.BottomDockWidgetArea, self.ui.shell_dock) + + if self.defaults["shell_at_startup"]: + self.ui.shell_dock.show() + else: + self.ui.shell_dock.hide() + if self.cmd_line_shellfile: try: with open(self.cmd_line_shellfile, "r") as myfile: @@ -1064,6 +1074,16 @@ class App(QtCore.QObject): if not silent: self.inform.emit("Defaults saved.") + def on_toggle_shell(self): + """ + toggle shell if is visible close it if closed open it + :return: + """ + if self.ui.shell_dock.isVisible(): + self.ui.shell_dock.hide() + else: + self.ui.shell_dock.show() + def on_edit_join(self): """ Callback for Edit->Join. Joins the selected geometry objects into @@ -2201,13 +2221,22 @@ class App(QtCore.QObject): return a, kwa - @contextmanager def wait_signal(signal, timeout=10000): - """Block loop until signal emitted, or timeout (ms) elapses.""" + """ + Block loop until signal emitted, timeout (ms) elapses + or unhandled exception happens in a thread. + + :param signal: Signal to wait for. + """ loop = QtCore.QEventLoop() + + # Normal termination signal.connect(loop.quit) + # Termination by exception in thread + self.thread_exception.connect(loop.quit) + status = {'timed_out': False} def report_quit(): @@ -2216,17 +2245,23 @@ class App(QtCore.QObject): yield + # Temporarily change how exceptions are managed. oeh = sys.excepthook ex = [] - def exceptHook(type_, value, traceback): - ex.append(value) - oeh(type_, value, traceback) - sys.excepthook = exceptHook + def except_hook(type_, value, traceback_): + ex.append(value) + oeh(type_, value, traceback_) + sys.excepthook = except_hook + + # Terminate on timeout if timeout is not None: QtCore.QTimer.singleShot(timeout, report_quit) + #### Block #### loop.exec_() + + # Restore exception management sys.excepthook = oeh if ex: self.raiseTclError(str(ex[0]))