コード例 #1
0
ファイル: Dialogs.py プロジェクト: radjkarl/QELAclient
 def getExistingDirectory(self, **kwargs):
     kwargs = self._processOpenKwargs(kwargs)
     fname = QtWidgets.QFileDialog.getExistingDirectory(**kwargs)
     if fname:
         p = PathStr(fname)
         self.opts['open'] = p.dirname()
         return p
コード例 #2
0
ファイル: Dialogs.py プロジェクト: radjkarl/QELAclient
 def getSaveFileName(self, *args, **kwargs):
     """
     analogue to QtWidgets.QFileDialog.getSaveFileNameAndFilter
     but returns the filename + chosen file ending even if not typed in gui
     """
     if 'directory' not in kwargs:
         if self.opts['save']:
             if self.opts['save']:
                 kwargs['directory'] = self.opts['save']
     fname = QtWidgets.QFileDialog.getSaveFileName(**kwargs)
     if fname:
         if type(fname) == tuple:
             # only happened since qt5
             # getSaveFileName returns (path, ftype)
             if not fname[0]:
                 return
             p = PathStr(fname[0])
             if not p.filetype():
                 ftyp = self._extractFtype(fname[1])
                 p = p.setFiletype(ftyp)
         else:
             p = PathStr(fname)
         self.opts['save'] = p.dirname()
         if self.opts['open'] is None:
             self.opts['open'] = self.opts['save']
         return p
コード例 #3
0
ファイル: Dialogs.py プロジェクト: radjkarl/fancyWidgets
 def getSaveFileName(self, *args, **kwargs):
     """
     analogue to QtWidgets.QFileDialog.getSaveFileNameAndFilter
     but returns the filename + chosen file ending even if not typed in gui
     """
     if 'directory' not in kwargs:
         if self.opts['save']:
             if self.opts['save']:
                 kwargs['directory'] = self.opts['save']
     fname = QtWidgets.QFileDialog.getSaveFileName(**kwargs)
     if fname:
         if type(fname) == tuple:
             #only happened since qt5
             #getSaveFileName returns (path, ftype)
             if not fname[0]:
                 return
             p = PathStr(fname[0])
             if not p.filetype():
                 ftyp = self._extractFtype(fname[1]) 
                 p = p.setFiletype(ftyp)
         else:
             p = PathStr(fname)
         self.opts['save'] = p.dirname()
         if self.opts['open'] is None:
             self.opts['open'] = self.opts['save']
         return p
コード例 #4
0
ファイル: Dialogs.py プロジェクト: radjkarl/fancyWidgets
 def getExistingDirectory(self, **kwargs):
     kwargs = self._processOpenKwargs(kwargs)
     fname = QtWidgets.QFileDialog.getExistingDirectory(**kwargs)
     if fname:
         p = PathStr(fname)
         self.opts['open'] = p.dirname()
         return p
コード例 #5
0
ファイル: Dialogs.py プロジェクト: radjkarl/QELAclient
 def getOpenFileName(self, **kwargs):
     kwargs = self._processOpenKwargs(kwargs)
     fname = QtWidgets.QFileDialog.getOpenFileName(**kwargs)
     if isinstance(fname, tuple):
         fname = fname[0]
     if fname:
         p = PathStr(fname)
         self.opts['open'] = p.dirname()
         return p
コード例 #6
0
ファイル: Dialogs.py プロジェクト: radjkarl/fancyWidgets
 def getOpenFileName(self, **kwargs):
     kwargs = self._processOpenKwargs(kwargs)
     fname = QtWidgets.QFileDialog.getOpenFileName(**kwargs)
     if isinstance(fname, tuple):
         fname = fname[0]
     if fname:
         p = PathStr(fname)
         self.opts['open'] = p.dirname()
         return p
コード例 #7
0
ファイル: equalizeImage.py プロジェクト: Jayme-T/imgProcessor
def equalizeImage(img, save_path=None, name_additive='_eqHist'):
    '''
    Equalize the histogram (contrast) of an image
    works with RGB/multi-channel images
    and flat-arrays
    
    @param img  - image_path or np.array
    @param save_path if given output images will be saved there
    @param name_additive if given this additive will be appended to output images 

    @return output images if input images are numpy.arrays and no save_path is given
    @return None elsewise 
    '''

    if isinstance(img, basestring):
        img = PathStr(img)
        if not img.exists():
            raise Exception("image path doesn't exist")
        img_name = img.basename().replace('.','%s.' %name_additive)
        if save_path is None:
            save_path = img.dirname()
        img = cv2.imread(img)

    
    if img.dtype != np.dtype('uint8'):
        #openCV cannot work with float arrays or uint > 8bit
        eqFn = _equalizeHistogram
    else:
        eqFn = cv2.equalizeHist
    if len(img.shape) == 3:#multi channel img like rgb
        for i in range(img.shape[2]):
            img[:, :, i] = eqFn(img[:, :, i]) 
    else: # grey scale image 
        img = eqFn(img)
    if save_path:
        img_name = PathStr(save_path).join(img_name)
        cv2.imwrite(img_name, img)
    return img
コード例 #8
0
def equalizeImage(img, save_path=None, name_additive='_eqHist'):
    '''
    Equalize the histogram (contrast) of an image
    works with RGB/multi-channel images
    and flat-arrays

    @param img  - image_path or np.array
    @param save_path if given output images will be saved there
    @param name_additive if given this additive will be appended to output images

    @return output images if input images are numpy.arrays and no save_path is given
    @return None elsewise
    '''

    if isinstance(img, string_types):
        img = PathStr(img)
        if not img.exists():
            raise Exception("image path doesn't exist")
        img_name = img.basename().replace('.', '%s.' % name_additive)
        if save_path is None:
            save_path = img.dirname()
        img = cv2.imread(img)

    if img.dtype != np.dtype('uint8'):
        # openCV cannot work with float arrays or uint > 8bit
        eqFn = _equalizeHistogram
    else:
        eqFn = cv2.equalizeHist
    if len(img.shape) == 3:  # multi channel img like rgb
        for i in range(img.shape[2]):
            img[:, :, i] = eqFn(img[:, :, i])
    else:  # grey scale image
        img = eqFn(img)
    if save_path:
        img_name = PathStr(save_path).join(img_name)
        cv2.imwrite(img_name, img)
    return img
コード例 #9
0
class Launcher(QtWidgets.QMainWindow):
    """
    A graphical starter for *.pyz files created by the save-method from
    appbase.MainWindow

    NEEDS AN OVERHAUL ... after that's done it will be able to:

    * show all *.pyz-files in a filetree
    * show the session specific ...

        * icon
        * description
        * author etc.
    * start, remove, rename, modify a session
    * modify, start a certain state of a session
    """

    def __init__(self,
                 title='PYZ-Launcher',
                 icon=None,
                 start_script=None,
                 left_header=None,
                 right_header=None,
                 file_type='pyz'
                 ):
        self.dialogs = Dialogs()

        _path = PathStr.getcwd()
        _default_text_color = '#3c3c3c'

        if icon is None:
            icon = os.path.join(_path, 'media', 'launcher_logo.svg')
        if start_script is None:
            start_script = os.path.join(_path, 'test_session.py')
        if left_header is None:
            _description = "<a href=%s style='color: %s'>%s</a>" % (
                appbase.__url__, _default_text_color, appbase.__description__)

            left_header = """<b>%s</b><br>
                version&nbsp;&nbsp;
                <a href=%s style='color: %s'>%s</a><br>
                autor&nbsp;&nbsp;&nbsp;&nbsp;
                    <a href=mailto:%s style='color: %s'>%s</a> """ % (  # text-decoration:underline
                _description,
                os.path.join(_path, 'media', 'recent_changes.txt'),
                _default_text_color,
                appbase.__version__,
                appbase.__email__,
                _default_text_color,
                appbase.__author__
            )
        if right_header is None:
            # if no header is given, list all pdfs in folder media as link
            d = _path
            right_header = ''
            for f in os.listdir(os.path.join(d, 'media')):
                if f.endswith('.pdf'):
                    _guidePath = os.path.join(d, 'media', f)
                    right_header += "<a href=%s style='color: %s'>%s</a><br>" % (
                        _guidePath, _default_text_color, f[:-4])
            right_header = right_header[:-4]

        QtWidgets.QMainWindow.__init__(self)

        self._start_script = start_script
        self.setWindowTitle(title)
        self.setWindowIcon(QtGui.QIcon(icon))
        self.resize(900, 500)
        # BASE STRUTURE
        area = QtWidgets.QWidget()
        self.setCentralWidget(area)
        layout = QtWidgets.QVBoxLayout()
        area.setLayout(layout)
        #header = QtWidgets.QHBoxLayout()
        # layout.addLayout(header)
        # grab the default text color of a qlabel to color all links from blue to it:
        # LEFT TEXT
        info = QtWidgets.QLabel(left_header)
        info.setOpenExternalLinks(True)
        # LOGO
        header = QtWidgets.QWidget()
        header.setFixedHeight(70)
        headerlayout = QtWidgets.QHBoxLayout()
        header.setLayout(headerlayout)
        logo = QtSvg.QSvgWidget(icon)
        logo.setFixedWidth(50)
        logo.setFixedHeight(50)
        headerlayout.addWidget(logo)
        headerlayout.addWidget(info)
        layout.addWidget(header)
        # RIGHT_HEADER
        userGuide = QtWidgets.QLabel(right_header)
        userGuide.setOpenExternalLinks(True)
        userGuide.setAlignment(QtCore.Qt.AlignTop | QtCore.Qt.AlignRight)
        headerlayout.addWidget(userGuide)
        # ROOT-PATH OF THE SESSIONS
        rootLayout = QtWidgets.QHBoxLayout()
        rootFrame = QtWidgets.QFrame()
        rootFrame.setFrameStyle(
            QtWidgets.QFrame.StyledPanel | QtWidgets.QFrame.Plain)
        rootFrame.setFixedHeight(45)
        rootFrame.setLineWidth(0)
        rootFrame.setLayout(rootLayout)
        layout.addWidget(rootFrame)
        self.rootDir = QtWidgets.QLabel()
        self.rootDir.setAutoFillBackground(True)
        self.rootDir.setStyleSheet("QLabel { background-color: white; }")

        # FILE-BROWSER
        self.treeView = _TreeView()

        self.fileSystemModel = _FileSystemModel(self.treeView, file_type)
        self.fileSystemModel.setNameFilters(['*.%s' % file_type])
        self.fileSystemModel.setNameFilterDisables(False)
        self.treeView.setModel(self.fileSystemModel)

        treelayout = QtWidgets.QHBoxLayout()
        splitter = QtWidgets.QSplitter(QtCore.Qt.Orientation(1))

        self.fileInfo = _PyzInfo(splitter, self.fileSystemModel, self.treeView)
        self.treeView.clicked.connect(self.fileInfo.update)

        splitter.addWidget(self.treeView)
        splitter.addWidget(self.fileInfo)
        treelayout.addWidget(splitter)

        layout.addLayout(treelayout)

        # get last root-path
        self._path = PathStr('')
        if CONFIG_FILE:
            try:
                self._path = PathStr(
                    open(
                        CONFIG_FILE,
                        'r').read().decode('unicode-escape'))
            except IOError:
                pass  # file not existant
        if not self._path or not self._path.exists():
            msgBox = QtWidgets.QMessageBox()
            msgBox.setText("Please choose your projectDirectory.")
            msgBox.exec_()
            self._changeRootDir()
        self.treeView.setPath(self._path)
        abspath = os.path.abspath(self._path)
        self.rootDir.setText(abspath)
        rootLayout.addWidget(self.rootDir)
        # GO UPWARDS ROOT-PATH BUTTON
        btnUpRootDir = QtWidgets.QPushButton('up')
        btnUpRootDir.clicked.connect(self._goUpRootDir)
        rootLayout.addWidget(btnUpRootDir)
        # DEFINE CURRENT DIR AS ROOT-PATH
        btnDefineRootDir = QtWidgets.QPushButton('set')
        btnDefineRootDir.clicked.connect(self._defineRootDir)
        rootLayout.addWidget(btnDefineRootDir)
        # SELECT ROOT-PATH BUTTON
        buttonRootDir = QtWidgets.QPushButton('select')
        buttonRootDir.clicked.connect(self._changeRootDir)
        rootLayout.addWidget(buttonRootDir)
        # NEW-BUTTON
        if self._start_script:
            newButton = QtWidgets.QPushButton('NEW')
            newButton.clicked.connect(self._openNew)
            layout.addWidget(newButton)

    @staticmethod
    def rootDir():
        try:
            return PathStr(
                open(CONFIG_FILE, 'r').read().decode('unicode-escape'))
        except IOError:  # create starter
            return PathStr.home()

    def _goUpRootDir(self):
        self._setRootDir(self._path.dirname())

    def _defineRootDir(self):
        i = self.treeView.selectedIndexes()
        # if not self.treeView.isIndexHidden(i):
        if i:
            if self.fileSystemModel.isDir(i[0]):
                self._setRootDir(PathStr(self.fileSystemModel.filePath(i[0])))

    def _changeRootDir(self):
        path = self.dialogs.getExistingDirectory()
        if path:
            self._setRootDir(path)

    def _setRootDir(self, path):
        self._path = path
        self.rootDir.setText(self._path)
        root = self.fileSystemModel.setRootPath(self._path)
        self.treeView.setRootIndex(root)
        # save last path to file
        if CONFIG_FILE:
            open(CONFIG_FILE, 'w').write(self._path.encode('unicode-escape'))

    def _openNew(self):
        p = spawn.find_executable("python")
        os.spawnl(os.P_NOWAIT, p, 'python', '%s' % self._start_script)
コード例 #10
0
class Session(QtCore.QObject):
    """Session management to be accessible in QtWidgets.QApplication.instance().session

    * extract the opened (as pyz-zipped) session in a temp folder
    * create 2nd temp-folder for sessions to be saved
    * send a close signal to all child structures when exit
    * write a log file with all output
    * enable icons in menus of gnome-sessions [linux only]
    * gives option of debug mode
    """

    #     sigPathChanged = QtCore.Signal(object) #path
    sigSave = QtCore.Signal(object)  # state dict
    sigRestore = QtCore.Signal(object)  # state dict

    def __init__(self, args, **kwargs):
        """
        Args:
            first_start_dialog (Optional[bool]):
                Show a different dialog for the first start.
            name (Optional[str]): The applications name.
            type (Optional[str]): The file type to be used for saving sessions.
            icon (Optional[str]): Path to the application icon.
        """

        QtCore.QObject.__init__(self)

        # SESSION CONSTANTS:
        self.NAME = kwargs.get('name', __main__.__name__)
        self.FTYPE = kwargs.get('ftype', 'pyz')
        self.ICON = kwargs.get('icon', None)
        # hidden app-preferences folder:
        self.dir = PathStr.home().mkdir('.%s' % self.NAME)
        self.APP_CONFIG_FILE = self.dir.join('config.txt')
        self._tmp_dir_session = None

        # session specific options:
        self.opts = _Opts({
            'maxSessions':         3,
            'enableGuiIcons':      True,
            'writeToShell':        True,
            'createLog':           False,
            'debugMode':           False,
            'autosave':            False,
            'autosaveIntervalMin': 15,
            'server':              False,
        }, self)
        # global options - same for all new and restored sessions:
        self.app_opts = {'showCloseDialog': True, 'recent sessions': []}

        if not self.APP_CONFIG_FILE.exists():
            # allow different first start dialog:
            dialog = kwargs.get('first_start_dialog', FirstStart)
            f = dialog(self)
            f.exec_()
            if not f.result():
                sys.exit()

            # create the config file
            with open(self.APP_CONFIG_FILE, 'w') as f:
                pass
        else:
            with open(self.APP_CONFIG_FILE, 'r') as f:
                r = f.read()
                if r:
                    self.app_opts.update(eval(r))

        self._icons_enabled = False
        self.log_file = None
        dirname = self.app_opts['recent sessions']
        if dirname:
            dirname = PathStr(dirname[-1]).dirname()
        self.dialogs = Dialogs(dirname)
        self.saveThread = _SaveThread()

        self._createdAutosaveFile = None
        self.tmp_dir_save_session = None
        # a work-dir for temp. storage:
#         self.tmp_dir_work = PathStr(tempfile.mkdtemp('%s_work' % self.NAME))

        pathName = self._inspectArguments(args)
        self.setSessionPath(pathName)
        if self.opts['createLog']:
            self._setupLogFile()
        # create connectable stdout and stderr signal:
        self.streamOut = StreamSignal('out')
        self.streamErr = StreamSignal('err')
        self._enableGuiIcons()
        # Auto-save timer:
        self.timerAutosave = QtCore.QTimer()
        self.timerAutosave.timeout.connect(self._autoSave)
        self.opts.activate()
        # first thing to do after start:
        QtCore.QTimer.singleShot(0, self.restoreCurrentState)

    def setSessionPath(self, path, statename=None):
        if path:  # and path.endswith('.%s' %self.FTYPE):
            # this script was opened out from a zip-container (named as
            # '*.pyz')
            self.path = PathStr(path)

            self.dir = self.path.dirname().abspath()
            # extract the zip temporally
            ZipFile(self.path, 'r').extractall(path=self.tmp_dir_session)
            self.n_sessions = len(self.stateNames())
            # SET STATE
            snames = self.stateNames()
            if statename is None:
                # last one
                self.current_session = snames[-1]
            elif statename in snames:
                self.current_session = statename
            else:
                raise Exception(
                        "state '%s' not in saved states %s" %
                        (statename, snames))
        else:
            self.path = None
            self.n_sessions = 0
            self.current_session = None

    def writeLog(self, write=True):
        if not self.log_file:
            return
        so = self.streamOut.message
        se = self.streamErr.message
        w = self.log_file.write
        if write:
            try:
                # ensure only connected once
                so.disconnect(w)
                se.disconnect(w)
            except TypeError:
                pass
            so.connect(w)
            se.connect(w)
        else:
            try:
                so.disconnect(w)
                se.disconnect(w)
            except TypeError:
                pass

    def _enableGuiIcons(self):
        # enable icons in all QMenuBars only for this program if generally
        # disabled
        if self.opts['enableGuiIcons']:
            if os.name == 'posix':  # linux
                this_env = str(os.environ.get('DESKTOP_SESSION'))
                relevant_env = (
                    'gnome',
                    'gnome-shell',
                    'ubuntustudio',
                    'xubuntu')
                if this_env in relevant_env:
                    if 'false' in os.popen(
                            # if the menu-icons on the gnome-desktop are disabled
                            'gconftool-2 --get /desktop/gnome/interface/menus_have_icons').read():
                        print('enable menu-icons')
                        os.system(
                                'gconftool-2 --type Boolean --set /desktop/gnome/interface/menus_have_icons True')
                        self._icons_enabled = True

    def _setupLogFile(self):
        lfile = self.tmp_dir_session.join('log.txt')
        if lfile.exists():
            self.log_file = open(lfile, 'a')
        else:
            self.log_file = open(lfile, 'w')
        self.log_file.write('''

####################################
New run at %s
####################################

''' % strftime("%d.%m.%Y|%H:%M:%S", gmtime()))

    def checkMaxSessions(self, nMax=None):
        """
        check whether max. number of saved sessions is reached
        if: remove the oldest session
        """
        if nMax is None:
            nMax = self.opts['maxSessions']
        l = self.stateNames()
        if len(l) > nMax:
            for f in l[:len(l) - nMax]:
                self.tmp_dir_session.remove(str(f))

    def stateNames(self):
        """Returns:
             list: the names of all saved sessions
        """
        if self.current_session:
            s = self.tmp_dir_session
            l = s.listdir()
            l = [x for x in l if s.join(x).isdir()]
            naturalSorting(l)
        else:
            l=[]
        # bring autosave to first position:
        if 'autoSave' in l:
            l.remove('autoSave')
            l.insert(0, 'autoSave')
        return l

    def restorePreviousState(self):
        s = self.stateNames()
        if s:
            i = s.index(self.current_session)
            if i > 1:
                self.current_session = s[i - 1]
                self.restoreCurrentState()

    def restoreNextState(self):
        s = self.stateNames()
        if s:
            i = s.index(self.current_session)
            if i < len(s) - 1:
                self.current_session = s[i + 1]
                self.restoreCurrentState()

    def restoreStateName(self, name):
        """restore the state of given [name]"""
        self.current_session = name
        self.restoreCurrentState()

    def renameState(self, oldStateName, newStateName):
        s = self.tmp_dir_session.join(oldStateName)
        s.rename(newStateName)
        if self.current_session == oldStateName:
            self.current_session = newStateName
        print("==> State [%s] renamed to  [%s]" % (oldStateName, newStateName))

    def _recusiveReplacePlaceholderWithArray(self, state, arrays):
        def recursive(state):
            for key, val in list(state.items()):
                if isinstance(val, dict):
                    recursive(val)
                elif isinstance(val, str) and val.startswith('arr_'):
                    state[key] = arrays[val]

        recursive(state)

    def restoreCurrentState(self):
        if self.current_session:
            orig = self.tmp_dir_save_session
            path = self.tmp_dir_save_session = self.tmp_dir_session.join(
                    self.current_session)
            with open(path.join('state.pickle'), "rb") as f:
                state = pickle.load(f)
            p = path.join('arrays.npz')
            if p.exists():
                arrays = np.load(path.join('arrays.npz'))
                self._recusiveReplacePlaceholderWithArray(state, arrays)

            self.dialogs.restoreState(state['dialogs'])
            self.opts.update(state['session'])
            self.sigRestore.emit(state)
            self.tmp_dir_save_session = orig

            print(
                    "==> State [%s] restored from '%s'" %
                    (self.current_session, self.path))

    def addSession(self):
        self.current_session = self.n_sessions
        self.n_sessions += 1
        self.tmp_dir_save_session = self.tmp_dir_session.join(
                str(self.n_sessions)).mkdir()
        self.checkMaxSessions()

    def quit(self):
        print('exiting...')
        # RESET ICONS
        if self._icons_enabled:
            print('disable menu-icons')
            os.system(  # restore the standard-setting for seeing icons in the menus
                    'gconftool-2 --type Boolean --set /desktop/gnome/interface/menus_have_icons False')

        # WAIT FOR PROMT IF IN DEBUG MODE
        if self.opts['debugMode']:
            input("Press any key to end the session...")
        # REMOVE TEMP FOLDERS
        try:
            self.tmp_dir_session.remove()
#             self.tmp_dir_work.remove()
        except OSError:
            pass  # in case the folders are used by another process

        with open(self.APP_CONFIG_FILE, 'w') as f:
            f.write(str(self.app_opts))
        # CLOSE LOG FILE
        if self.log_file:
            self.writeLog(False)
            self.log_file.close()

    def _inspectArguments(self, args):
        """inspect the command-line-args and give them to appBase"""
        if args:
            self.exec_path = PathStr(args[0])
        else:
            self.exec_path = None

        session_name = None
        args = args[1:]

        openSession = False
        for arg in args:
            if arg in ('-h', '--help'):
                self._showHelp()
            elif arg in ('-d', '--debug'):
                print('RUNNGING IN DEBUG-MODE')
                self.opts['debugMode'] = True
            elif arg in ('-l', '--log'):
                print('CREATE LOG')
                self.opts['createLog'] = True
            elif arg in ('-s', '--server'):
                self.opts['server'] = True
            elif arg in ('-o', '--open'):
                openSession = True
            elif openSession:
                session_name = arg
            else:
                print("Argument '%s' not known." % arg)
                return self._showHelp()
        return session_name

    def _showHelp(self):
        sys.exit('''
    %s-sessions can started with the following arguments:
        [-h or --help] - show the help-page
        [-d or --debug] - run in debugging-mode
        [-l or --log] - create log file
        [-n or --new] - start a new session, don'l load saved properties
        [-exec [cmd]] - execute python code from this script/executable
        ''' % self.__class__.__name__)

    def save(self):
        """save the current session
        override, if session was saved earlier"""
        if self.path:
            self._saveState(self.path)
        else:
            self.saveAs()

    def saveAs(self, filename=None):
        if filename is None:
            # ask for filename:
            filename = self.dialogs.getSaveFileName(filter="*.%s" % self.FTYPE)
        if filename:
            self.path = filename
            self._saveState(self.path)
            if self._createdAutosaveFile:
                self._createdAutosaveFile.remove()
                print(
                        "removed automatically created '%s'" %
                        self._createdAutosaveFile)
                self._createdAutosaveFile = None

    def replace(self, path):
        """
        replace current session with one given by file path
        """
        self.setSessionPath(path)
        self.restoreCurrentState()

    def open(self):
        """open a session to define in a dialog in an extra window"""
        filename = self.dialogs.getOpenFileName(filter="*.%s" % self.FTYPE)
        if filename:
            self.new(filename)

    def new(self, filename=None):
        """start a session an independent process"""
        path = (self.exec_path,)
        if self.exec_path.filetype() in ('py', 'pyw', 'pyz', self.FTYPE):
            # get the absolute path to the python-executable
            p = find_executable("python")
            path = (p, 'python') + path
        else:
            # if run in frozen env (.exe):
            # first arg if execpath of the next session:
            path += (self.exec_path,)
        if filename:
            path += ('-o', filename)
        os.spawnl(os.P_NOWAIT, *path)

    def registerMainWindow(self, win):
        win.setWindowIcon(QtGui.QIcon(self.ICON))

        self._mainWindow = win
        win.show = self._showMainWindow
        win.hide = self._hideMainWindow
        if self.opts['server']:
            server_ = Server(win)
            win.hide()
        else:
            win.show()

    @property
    def tmp_dir_session(self):
        #only create folder if needed
        if self._tmp_dir_session is None:
            # make temp-dir
            # the directory where the content of the *pyz-file will be copied:
            self._tmp_dir_session = PathStr(
                tempfile.mkdtemp(
                        '%s_session' %
                        self.NAME))
        return self._tmp_dir_session
    
    def _showMainWindow(self):
        try:
            # restore autosave
            del self._autosave
        except AttributeError:
            pass
        self._mainWindow.__class__.show(self._mainWindow)

    def _hideMainWindow(self):
        # disable autosave on hidden window
        self._autosave = self.opts['autosave']
        self.opts['autosave'] = False
        self._mainWindow.__class__.hide(self._mainWindow)

    def _saveState(self, path):
        """save current state and add a new state"""
        self.addSession()  # next session
        self._save(str(self.n_sessions), path)

    def _autoSave(self):
        """save state into 'autosave' """
        a = 'autoSave'
        path = self.path
        if not path:
            path = self.dir.join('%s.%s' % (a, self.FTYPE))
            self._createdAutosaveFile = path
        self.tmp_dir_save_session = self.tmp_dir_session.join(a).mkdir()
        self._save(a, path)

    def blockingSave(self, path):
        """
        saved session to file - returns after finish
        only called by interactiveTutorial-save at the moment
        """
        self.tmp_dir_save_session = self.tmp_dir_session.join('block').mkdir()
        state = {'session': dict(self.opts),
                 'dialogs': self.dialogs.saveState()}
        self.saveThread.prepare('0', path, self.tmp_dir_session, state)
        self.sigSave.emit(self)
        self.saveThread.run()

    def _save(self, stateName, path):
        """save into 'stateName' to pyz-path"""
        print('saving...')

        state = {'session': dict(self.opts),
                 'dialogs': self.dialogs.saveState()}

        self.sigSave.emit(state)
        self.saveThread.prepare(stateName, path, self.tmp_dir_session, state)
        self.saveThread.start()

        self.current_session = stateName

        r = self.app_opts['recent sessions']
        try:
            # is this session already exists: remove it
            r.pop(r.index(path))
        except ValueError:
            pass
        # add this session at the beginning
        r.insert(0, path)