Example #1
0
def killProcesses(pids):
    """Kill the processes in the pids list."""
    warning = """..

Killing processes
-----------------
I will now try to kill the following processes::

    %s

You can choose the signal to be sent to the processes:

- KILL (9)
- TERM (15)

We advice you to first try the TERM(15) signal, and only if that
does not seem to work, use the KILL(9) signal.
""" % pids
    actions = ['Cancel the operation','KILL(9)','TERM(15)']

    answer = draw.ask(warning,actions)

    if answer == 'TERM(15)':
        print "KILLING WITH SIGNAL 15"
        utils.killProcesses(pids,15)
    elif answer == 'KILL(9)':
        print "KILLING WITH SIGNAL 9"
        utils.killProcesses(pids,9)
Example #2
0
def closeProject(save=None,clear=None):
    """Close the current project, saving it or not.

    Parameters:

    - `save`: None, True or False. Determines whether the project should be
      saved prior to closing it. If None, it will be asked from the user.
      Note that this parameter is only used for named Projects. Temporary
      Projects are never saved implicitely.
    - `clear`: None, True or False.
    """
    if pf.PF.filename is not None:
        if save is None:
            save = draw.ack("Save the current project before closing it?")
        pf.message("Closing project %s (save=%s)" % (pf.PF.filename,save))
        if save:
            saveProject()
            if pf.PF:
                listProject()
                if clear is None:
                    clear = draw.ask("What shall I do with the existing globals?",["Delete","Keep"]) == "Delete"

    if clear:
        pf.PF.clear()

    pf.PF.filename = None
    pf.GUI.setcurproj('None')
    updateSettings({
        'curproj':pf.PF.filename,
        },save=True)
Example #3
0
def closeProject(save=None, clear=None):
    """Close the current project, saving it or not.

    Parameters:

    - `save`: None, True or False. Determines whether the project should be
      saved prior to closing it. If None, it will be asked from the user.
      Note that this parameter is only used for named Projects. Temporary
      Projects are never saved implicitely.
    - `clear`: None, True or False.
    """
    if pf.PF.filename is not None:
        if save is None:
            save = draw.ack("Save the current project before closing it?")
        pf.message("Closing project %s (save=%s)" % (pf.PF.filename, save))
        if save:
            saveProject()
            if pf.PF:
                listProject()
                if clear is None:
                    clear = draw.ask(
                        "What shall I do with the existing globals?",
                        ["Delete", "Keep"]) == "Delete"

    if clear:
        pf.PF.clear()

    pf.PF.filename = None
    pf.GUI.setcurproj('None')
    updateSettings({
        'curproj': pf.PF.filename,
    }, save=True)
def askCloseProject():
    if the_project is not None:
        choices = ['Exit without saving','SaveAs and Exit','Save and Exit']
        res = draw.ask("You have an unsaved open project: %s\nWhat do you want me to do?"%the_project.filename,choices,default=2)
        res = choices.index(res)
        if res == 1:
            saveAsProject()
        elif res == 2:
            saveProject()
def openProject(exist=True):
    """Open a file selection dialog and let the user select a project.

    The default only accepts existing project files.
    Use createProject() to accept new file names.
    """
    global the_project,the_project_saved
    if the_project is None:
        cur = GD.cfg.get('workdir','.')
    else:
        if draw.ask("Another project is still open. Shall I close it first?",
                    ['Close','Cancel']) == 'Cancel':
            return
        cur = the_project.filename
    typ = [ 'pyFormex projects (*.pyf)', 'All files (*)' ]
    fn = widgets.FileSelection(cur,typ,exist=exist).getFilename()
    if fn:
        if not fn.endswith('.pyf'):
            fn += '.pyf'
        if not exist and os.path.exists(fn):
            res = draw.ask("The project file '%s' already exists\nShall I delete the contents or add to it?" % fn,['Delete','Add','Cancel'])
            if res == 'Cancel':
                return
            if res == 'Add':
                exist = True
        if GD.PF:
            GD.message("Exportd symbols: %s" % GD.PF.keys())
            res = draw.ask("pyFormex already contains exported symbols.\nShall I add them to your project?",['Delete','Add','Cancel'])
            if res == 'Cancel':
                return
            if res == 'Delete':
                GD.PF = {}
        GD.message("Opening project %s" % fn)
        the_project = project.Project(fn,create=not exist)
        the_project_saved = False
        if GD.PF:
            the_project.update(GD.PF)
        GD.PF = the_project
        GD.gui.setcurproj(fn)
        GD.cfg['workdir'] = os.path.dirname(fn)
        GD .message("Project contents: %s" % the_project.keys())
Example #6
0
def killProcesses(pids):
    """Kill the processes in the pids list."""
    warning = """..

Killing processes
-----------------
I will now try to kill the following processes::

    %s

You can choose the signal to be sent to the processes:

- KILL (9)
- TERM (15)

We advice you to first try the TERM(15) signal, and only if that
does not seem to work, use the KILL(9) signal.
""" % pids
    actions = ['Cancel the operation','KILL(9)','TERM(15)']
    answer = draw.ask(warning,actions)
    if answer == 'TERM(15)':
        utils.killProcesses(pids,15)
    elif answer == 'KILL(9)':
        utils.killProcesses(pids,9)
def createProject(create=True,compression=0,addGlobals=None):
    """Open a file selection dialog and let the user select a project.

    The default will let the user create new project files as well as open
    existing ones.
    Use create=False or the convenience function openProject to only accept
    existing project files.

    If a compression level (1..9) is given, the contents will be compressed,
    resulting in much smaller project files at the cost of  

    Only one pyFormex project can be open at any time. The open project
    owns all the global data created and exported by any script.
    If addGlobals is None, the user is asked whether the current globals
    should be added to the project. Set True or False to force or reject
    the adding without asking.
    """
    global the_project

    # ask filename from user
    if the_project is None:
        cur = GD.cfg.get('workdir','.')
    else:
        options = ['Cancel','Close without saving','Save and Close']
        ans = draw.ask("Another project is still open. Shall I close it first?",
                    options)
        if ans == 'Cancel':
            return
        if ans == options[2]:
            the_project.save()
        cur = the_project.filename
    typ = [ 'pyFormex projects (*.pyf)', 'All files (*)' ]
    res = widgets.ProjectSelection(cur,typ,exist=not create).getResult()
    if res is None:
        # user canceled
        return

    fn = res.fn
    if not fn.endswith('.pyf'):
        fn += '.pyf'
    legacy = res.leg
    compression = res.cpr
    print fn,legacy,compression

    if create and os.path.exists(fn):
        res = draw.ask("The project file '%s' already exists\nShall I delete the contents or add to it?" % fn,['Delete','Add','Cancel'])
        if res == 'Cancel':
            return
        if res == 'Add':
            create = False
    GD.message("Opening project %s" % fn)
    
    if GD.PF:
        GD.message("Exported symbols: %s" % GD.PF.keys())
        if addGlobals is None:
            res = draw.ask("pyFormex already contains exported symbols.\nShall I delete them or add them to your project?",['Delete','Add','Cancel'])
            if res == 'Cancel':
                # ESCAPE FROM CREATING THE PROJECT
                return

            addGlobals = res == 'Add'

    # OK, we have all data, now create/open the project
        
    GD.cfg['workdir'] = os.path.dirname(fn)
    GD.GUI.setBusy()
    try:
        sig = GD.Version[:GD.Version.rfind('-')]
        the_project = project.Project(fn,create=create,signature=sig,compression=compression,legacy=legacy)
        if GD.PF and addGlobals:
            the_project.update(GD.PF)
        GD.PF = the_project
        GD.GUI.setcurproj(fn)
        GD.message("Project contents: %s" % the_project.keys())
        if hasattr(the_project,'autofile') and draw.ack("The project has an autofile attribute: %s\nShall I execute this script?" % the_project.autofile):
            processArgs([the_project.autofile])
    finally:
        GD.GUI.setBusy(False)
Example #8
0
def startGUI(args):
    """Create the QT4 application and GUI.

    A (possibly empty) list of command line options should be provided.
    QT4 wil remove the recognized QT4 and X11 options.
    """
    # This seems to be the only way to make sure the numeric conversion is
    # always correct
    #
    QtCore.QLocale.setDefault(QtCore.QLocale.c())
    #
    #pf.options.debug = -1
    pf.debug("Arguments passed to the QApplication: %s" % args)
    pf.app = QtGui.QApplication(args)
    
    #
    pf.debug("Arguments left after constructing the QApplication: %s" % args)
    pf.debug("Arguments left after constructing the QApplication: %s" % pf.app.arguments().join('\n'))
    #pf.options.debug = 0
    # As far as I have been testing this, the args passed to the Qt application are
    # NOT acknowledged and neither are they removed!!


    pf.app.setOrganizationName("pyformex.org")
    pf.app.setOrganizationDomain("pyformex.org")
    pf.app.setApplicationName("pyFormex")
    pf.app.setApplicationVersion(pf.__version__)
    ## pf.settings = QtCore.QSettings("pyformex.org", "pyFormex")
    ## pf.settings.setValue("testje","testvalue")
    
    #QtCore.QObject.connect(pf.app,QtCore.SIGNAL("lastWindowClosed()"),pf.app,QtCore.SLOT("quit()"))
    QtCore.QObject.connect(pf.app,QtCore.SIGNAL("lastWindowClosed()"),quitGUI)
    #QtCore.QObject.connect(pf.app,QtCore.SIGNAL("aboutToQuit()"),quitGUI)

    # Check if we have DRI
    viewport.setOpenGLFormat()
    dri = viewport.opengl_format.directRendering()


    # Check for existing pyFormex processes
    windowname,running = findOldProcesses()

    while len(running) > 0:
        if len(running) >= 16:
            print("Too many open pyFormex windows --- bailing out")
            return -1

        pids = [ i[2] for i in running if i[2] is not None ]
        warning = """..

pyFormex is already running on this screen
------------------------------------------
A main pyFormex window already exists on your screen. 

If you really intended to start another instance of pyFormex, you
can just continue now.

The window might however be a leftover from a previously crashed pyFormex
session, in which case you might not even see the window anymore, nor be able
to shut down that running process. In that case, you would better bail out now
and try to fix the problem by killing the related process(es).

If you think you have already killed those processes, you may check it by
rerunning the tests.
"""
        actions = ['Really Continue','Rerun the tests','Bail out and fix the problem']
        if pids:
            warning += """

I have identified the process(es) by their PID as::

%s

If you trust me enough, you can also have me kill this processes for you.
""" % pids
            actions[2:2] = ['Kill the running processes']
            
        if dri:
            answer = draw.ask(warning,actions)
        else:
            warning += """
I have detected that the Direct Rendering Infrastructure
is not activated on your system. Continuing with a second
instance of pyFormex may crash your XWindow system.
You should seriously consider to bail out now!!!
"""
            answer = draw.warning(warning,actions)


        if answer == 'Really Continue':
            break # OK, Go ahead

        elif answer == 'Rerun the tests':
            windowname,running = findOldProcesses() # try again
        
        elif answer == 'Kill the running processes':
            killProcesses(pids)
            windowname,running = findOldProcesses() # try again
            
        else:
            return -1 # I'm out of here!

        
    # Load the splash image
    splash = None
    if os.path.exists(pf.cfg['gui/splash']):
        pf.debug('Loading splash %s' % pf.cfg['gui/splash'])
        splashimage = QtGui.QPixmap(pf.cfg['gui/splash'])
        splash = QtGui.QSplashScreen(splashimage)
        splash.setWindowFlags(QtCore.Qt.WindowStaysOnTopHint)
        splash.setFont(QtGui.QFont("Helvetica",24))
        splash.showMessage(pf.Version,QtCore.Qt.AlignHCenter,QtCore.Qt.red)
        splash.show()

    # create GUI, show it, run it

    pf.GUI = GUI(windowname,
                 pf.cfg.get('gui/size',(800,600)),
                 pf.cfg.get('gui/pos',(0,0)),
                 pf.cfg.get('gui/bdsize',(800,600)),
                 )

    # set the appearance
    pf.GUI.setAppearence()


    # setup the message board
    pf.board = pf.GUI.board
    pf.board.write("""%s  (C) Benedict Verhegghe

pyFormex comes with ABSOLUTELY NO WARRANTY. This is free software, and you are welcome to redistribute it under the conditions of the GNU General Public License, version 3 or later. See Help->License or the file COPYING for details.
""" % pf.Version)
    
    # Set interaction functions
    
    def show_warning(message,category,filename,lineno,file=None,line=None):
        """Replace the default warnings.showwarning

        We display the warnings using our interactive warning widget.
        This feature can be turned off by setting
        cfg['warnings/popup'] = False
        """
        full_message = warnings.formatwarning(message,category,filename,lineno,line)
        ## from widgets import simpleInputItem as I
        ## res = draw.askItems([
        ##     I('message',message,itemtype='label',text='warning'),
        ##     I('filter',False,text='Suppress this message in future sessions'),
        ##     ],actions=[('OK',)],legacy=False)
        #print res
        pf.message(full_message)
        res,check = draw.showMessage(full_message,level='warning',check="Do not show this warning anymore in future sessions")
        if check[0]:
            oldfilters = pf.prefcfg['warnings/filters']
            newfilters = oldfilters + [(str(message),)]
            pf.prefcfg.update({'filters':newfilters},name='warnings')


##     def format_warning(message,category,filename,lineno,line=None):
##         """Replace the default warnings.formatwarning

##         We display the warnings using our interactive warning widget.
##         This feature can be turned off by setting
##         cfg['nice_warnings'] = False
##         """
##         import messages
##         message = messages.getMessage(message)
##         message = """..

## pyFormex Warning
## ================
## %s

## `Called from:` %s `line:` %s
## """ % (message,filename,lineno)
##         if line:
##             message += "%s\n" % line
##         return message


##     if pf.cfg['warnings/nice']:
##         warnings.formatwarning = format_warning

    if pf.cfg['warnings/popup']:
        warnings.showwarning = show_warning
    
    
    pf.message = draw.message
    pf.warning = draw.warning

    # setup the canvas
    pf.GUI.viewports.changeLayout(1)
    pf.GUI.viewports.setCurrent(0)
    pf.canvas = pf.GUI.viewports.current
    draw.reset()

    # setup the status bar
    pf.GUI.addInputBox()
    pf.GUI.toggleInputBox(False)
    pf.GUI.addCoordsTracker()
    pf.GUI.toggleCoordsTracker(pf.cfg.get('gui/coordsbox',False))
    pf.debug("Using window name %s" % pf.GUI.windowTitle())
    
    # Create additional menus (put them in a list to save)
    
    # History Menu
    pf.GUI.history = scriptMenu.ScriptMenu('History',files=pf.cfg['gui/history'],max=pf.cfg['gui/history_max'])

    if pf.cfg.get('gui/history_in_main_menu',False):
        before = pf.GUI.menu.item('help')
        pf.GUI.menu.insertMenu(before,pf.GUI.history)
    else:
        filemenu = pf.GUI.menu.item('file')
        before = filemenu.item('---1')
        filemenu.insertMenu(before,pf.GUI.history)
    

    # Scripts menu
    pf.GUI.scriptmenu = scriptMenu.createScriptMenu(pf.GUI.menu,before='help')

    # Create databases
    createDatabases()
 
    # PLugin menus
    import plugins
    ## filemenu = pf.GUI.menu.item('file')
    ## pf.gui.saveobj = plugins.create_plugin_menus(filemenu,before='options')
    ## # Load configured plugins, ignore if not found
    plugins.loadConfiguredPlugins()
    #for p in pf.cfg['gui/plugins']:
    #    plugins.load(p)

    pf.GUI.setBusy(False)
    pf.GUI.addStatusBarButtons()

    # remove the splash window
    if splash is not None:
        splash.finish(pf.GUI)

    pf.GUI.setBusy(False)

    if os.path.isdir(pf.cfg['workdir']):
        # Make the workdir the current dir
        os.chdir(pf.cfg['workdir'])
        pf.debug("Setting workdir to %s" % pf.cfg['workdir'])
    else:
        # Save the current dir as workdir
        prefMenu.updateSettings({'workdir':os.getcwd(),'Save changes':True})

    pf.GUI.show()
    pf.GUI.update()
    pf.app_started = True
    pf.GUI.processEvents()
    return 0
Example #9
0
def runApp(args):
    """Create and run the qt application."""
    GD.app = QtGui.QApplication(args)
    QtCore.QObject.connect(GD.app,QtCore.SIGNAL("lastWindowClosed()"),GD.app,QtCore.SLOT("quit()"))
    QtCore.QObject.connect(GD.app,QtCore.SIGNAL("aboutToQuit()"),quit)
        
     # Set some globals
    GD.image_formats_qt = map(str,QtGui.QImageWriter.supportedImageFormats())
    GD.image_formats_qtr = map(str,QtGui.QImageReader.supportedImageFormats())
    if GD.cfg.get('imagesfromeps',False):
        GD.image_formats_qt = []
    if GD.options.debug:
        print "Qt image types for saving: ",GD.image_formats_qt
        print "Qt image types for input: ",GD.image_formats_qtr
        print "gl2ps image types:",GD.image_formats_gl2ps
        print "image types converted from EPS:",GD.image_formats_fromeps
        
    # Load the splash image
    splash = None
    if os.path.exists(GD.cfg['gui/splash']):
        GD.debug('Loading splash %s' % GD.cfg['gui/splash'])
        splashimage = QtGui.QPixmap(GD.cfg['gui/splash'])
        splash = QtGui.QSplashScreen(splashimage)
        splash.setWindowFlags(QtCore.Qt.WindowStaysOnTopHint)
        splash.setFont(QtGui.QFont("Helvetica",24))
        splash.showMessage(GD.Version,QtCore.Qt.AlignHCenter,QtCore.Qt.red)
        splash.show()
        
    # create GUI, show it, run it
    viewport.setOpenGLFormat()
    dri = viewport.opengl_format.directRendering()
    windowname = GD.Version
    count = 0
    while windowExists(windowname):
        if count > 255:
            print "Can not open the main window --- bailing out"
            return 1
        count += 1
        windowname = '%s (%s)' % (GD.Version,count)

    if count > 0:
        warning = """
Another instance of pyFormex is already running
on this screen. This may be a leftover from a
previously crashed program. In that case you should
bail out now and first kill the crashed program.

On the other hand, if you really want to run another
pyFormex in parallel, you can just continue now.
"""
        actions = ['Really Continue','Bail out and fix the problem']
        if dri:
            answer = draw.ask(warning,actions)
        if not dri:
            warning += """
I have detected that the Direct Rendering Infrastructure
is not activated on your system. Continuing with a second
instance of pyFormex may crash you XWindow system.
You should seriously consider to bail out now!!!
"""
            answer = draw.warning(warning,actions)
        if answer != 'Really Continue':
            return 1

    GD.gui = GUI(windowname,
                 GD.cfg.get('gui/size',(800,600)),
                 GD.cfg.get('gui/pos',(0,0)),
                 GD.cfg.get('gui/bdsize',(800,600))
                 )

    # set the appearence
    GD.gui.setStyle(GD.cfg.get('gui/style','Plastique'))
    font = GD.cfg.get('gui/font',None)
    if font:
        GD.gui.setFont(font)
    else:
        fontfamily = GD.cfg.get('gui/fontfamily',None)
        if fontfamily:
            GD.gui.setFontFamily(fontfamily)
        fontsize =  GD.cfg.get('gui/fontsize',None)
        if fontsize:
            GD.gui.setFontSize(fontsize)
    GD.gui.viewports.changeLayout(1)
    GD.gui.viewports.setCurrent(0)
    GD.board = GD.gui.board
    GD.board.write("""%s  (C) B. Verhegghe

pyFormex comes with ABSOLUTELY NO WARRANTY. This is free software,
and you are welcome to redistribute it under certain conditions.
See Help->License or the file COPYING for details.
""" % GD.Version)
    GD.gui.show()
    GD.debug("Using window name %s" % GD.gui.windowTitle())
    
    # Create additional menus (put them in a list to save)
    
    # History Menu
    history = GD.cfg.get('history',None)
    if type(history) == list:
        GD.gui.history = scriptsMenu.ScriptsMenu('History',files=history,max=20)

    if GD.cfg.get('gui/history_in_main_menu',False):
        before = GD.gui.menu.item('help').menuAction()
        GD.gui.menu.insertMenu(before,GD.gui.history)
    else:
        filemenu = GD.gui.menu.item('file')
        before = filemenu.item('---1')
        filemenu.insertMenu(before,GD.gui.history)


    # Create a menu with pyFormex examples
    # and insert it before the help menu
    menus = []
    scriptdirs = GD.cfg['scriptdirs']
    knownscriptdirs = { 'examples': GD.cfg['examplesdir'] }

    if GD.cfg.get('gui/separate_script_dirs',False):
        # This will create separate menus for all scriptdirs
        pass
    else:
        # The default is to collect all scriptdirs in a single main menu
        if len(scriptdirs) > 1:
            scriptsmenu = widgets.Menu('Scripts',GD.gui.menu)
            before = GD.gui.menu.item('help').menuAction()
            GD.gui.menu.insertMenu(before,scriptsmenu)
            before = None
        else:
            scriptsmenu = GD.gui.menu
            before = scriptsmenu.itemAction('help')

        for title,dirname in scriptdirs:
            GD.debug("Loading script dir %s" % dirname)
            if not dirname:
                dirname = knownscriptdirs[title.lower()]
            if os.path.exists(dirname):
                m = scriptsMenu.ScriptsMenu(title,dirname,autoplay=True)
                scriptsmenu.insert_menu(m,before)
                menus.append(m)   # Needed to keep m linked to a name,
                                  # else the menu is destroyed!

    # Set interaction functions
    GD.message = draw.message
    GD.warning = draw.warning
    draw.reset()
    # Load plugins, ignore if not found
    import plugins
    for p in GD.cfg.get('gui/plugins',[]):
        try:
            m = getattr(plugins,p)
            if hasattr(m,'show_menu'):
                m.show_menu()
        except:
            GD.debug('ERROR while loading plugin %s' % p)
    GD.gui.setBusy(False)
    GD.gui.update()

    # remove the splash window
    if splash is not None:
        splash.finish(GD.gui)


    # Add the autorun script to the remaining args
    if GD.gui.easter_egg:
        draw.playScript(utils.mergeme(*GD.gui.easter_egg))
    ar = GD.cfg.get('autorun','')
    if ar:
        if type(ar) == str:
            ar = [ar]
        args = ar + args

    # remaining args are interpreted as scripts
    for arg in args:
        if os.path.exists(arg):
            draw.play(arg)

    GD.gui.setBusy(False)
    GD.gui.update()
    if os.path.isdir(GD.cfg['workdir']):
        # Make the workdir the current dir
        os.chdir(GD.cfg['workdir'])
    else:
        # Save the current dir as workdir
        GD.cfg['workdir'] = os.getcwd()
    GD.app_started = True
    GD.app.exec_()

    # Cleanup
    draw.drawrelease()
    GD.gui.setBusy(False)

    # store the history and main window size/pos
    GD.cfg['history'] = GD.gui.history.files

    # Sometimes, a negative value is stored, making restart partially obscured
    x,y = Pos(GD.gui)
    if x < 0:
        x = 0
    if y < 0:
        y = 0
    GD.cfg.update({'size':Size(GD.gui),
                   'pos':(x,y),
                   'bdsize':Size(GD.gui.board),
                   },name='gui')
    return 0
Example #10
0
def runApp(args):
    """Create and run the qt application."""
    #
    # FIX FOR A BUG IN NUMPY (It's always sane anyway)
    #
    import locale
    GD.debug("LC_NUMERIC = %s" %  locale.setlocale(locale.LC_NUMERIC))
    #
    GD.app = QtGui.QApplication(args)
    #
    GD.debug("LC_NUMERIC = %s" %  locale.setlocale(locale.LC_NUMERIC))
    locale.setlocale(locale.LC_NUMERIC, 'C')
    GD.debug("LC_NUMERIC = %s" %  locale.setlocale(locale.LC_NUMERIC))
    #
    #
    #
    
    QtCore.QObject.connect(GD.app,QtCore.SIGNAL("lastWindowClosed()"),GD.app,QtCore.SLOT("quit()"))
    QtCore.QObject.connect(GD.app,QtCore.SIGNAL("aboutToQuit()"),quit)
        
       
    # Load the splash image
    splash = None
    if os.path.exists(GD.cfg['gui/splash']):
        GD.debug('Loading splash %s' % GD.cfg['gui/splash'])
        splashimage = QtGui.QPixmap(GD.cfg['gui/splash'])
        splash = QtGui.QSplashScreen(splashimage)
        splash.setWindowFlags(QtCore.Qt.WindowStaysOnTopHint)
        splash.setFont(QtGui.QFont("Helvetica",24))
        splash.showMessage(GD.Version,QtCore.Qt.AlignHCenter,QtCore.Qt.red)
        splash.show()
        
    # create GUI, show it, run it
    viewport.setOpenGLFormat()
    dri = viewport.opengl_format.directRendering()
    windowname = GD.Version
    count = 0
    while windowExists(windowname):
        if count > 255:
            print "Can not open the main window --- bailing out"
            return 1
        count += 1
        windowname = '%s (%s)' % (GD.Version,count)

    if count > 0:
        warning = """
Another instance of pyFormex is already running
on this screen. This may be a leftover from a
previously crashed program. In that case you should
bail out now and first kill the crashed program.

On the other hand, if you really want to run another
pyFormex in parallel, you can just continue now.
"""
        actions = ['Really Continue','Bail out and fix the problem']
        if dri:
            answer = draw.ask(warning,actions)
        if not dri:
            warning += """
I have detected that the Direct Rendering Infrastructure
is not activated on your system. Continuing with a second
instance of pyFormex may crash you XWindow system.
You should seriously consider to bail out now!!!
"""
            answer = draw.warning(warning,actions)
        if answer != 'Really Continue':
            return 1

    GD.gui = GUI(windowname,
                 GD.cfg.get('gui/size',(800,600)),
                 GD.cfg.get('gui/pos',(0,0)),
                 GD.cfg.get('gui/bdsize',(800,600))
                 )

    # set the appearence
    GD.gui.setStyle(GD.cfg.get('gui/style','Plastique'))
    font = GD.cfg.get('gui/font',None)
    if font:
        GD.gui.setFont(font)
    else:
        fontfamily = GD.cfg.get('gui/fontfamily',None)
        if fontfamily:
            GD.gui.setFontFamily(fontfamily)
        fontsize =  GD.cfg.get('gui/fontsize',None)
        if fontsize:
            GD.gui.setFontSize(fontsize)
    GD.gui.viewports.changeLayout(1)
    GD.gui.viewports.setCurrent(0)
    GD.board = GD.gui.board
    GD.board.write("""%s  (C) Benedict Verhegghe

pyFormex comes with ABSOLUTELY NO WARRANTY. This is free software,
and you are welcome to redistribute it under the conditions of the
GNU General Public License, version 3 or later.
See Help->License or the file COPYING for details.
""" % GD.Version)
    GD.gui.show()
    GD.debug("Using window name %s" % GD.gui.windowTitle())
    
    # Create additional menus (put them in a list to save)
    
    # History Menu
    history = GD.cfg.get('history',None)
    if type(history) == list:
        GD.gui.history = scriptsMenu.ScriptsMenu('History',files=history,max=20)

    if GD.cfg.get('gui/history_in_main_menu',False):
        before = GD.gui.menu.item('help').menuAction()
        GD.gui.menu.insertMenu(before,GD.gui.history)
    else:
        filemenu = GD.gui.menu.item('file')
        before = filemenu.item('---1')
        filemenu.insertMenu(before,GD.gui.history)


    # Script menu
    scriptmenu = createScriptMenu()


    # Set interaction functions
    GD.message = draw.message
    GD.warning = draw.warning
    draw.reset()
    # Load plugins, ignore if not found
    import plugins
    for p in GD.cfg.get('gui/plugins',[]):
        try:
            m = getattr(plugins,p)
            if hasattr(m,'show_menu'):
                m.show_menu()
        except:
            GD.debug('ERROR while loading plugin %s' % p)
    GD.gui.setBusy(False)
    GD.gui.update()
    GD.gui.addStatusBarButtons()

    # remove the splash window
    if splash is not None:
        splash.finish(GD.gui)

    GD.gui.setBusy(False)
    GD.gui.update()
    
    if os.path.isdir(GD.cfg['workdir']):
        # Make the workdir the current dir
        os.chdir(GD.cfg['workdir'])
    else:
        # Save the current dir as workdir
        GD.cfg['workdir'] = os.getcwd()
    GD.app_started = True

    if GD.gui.easter_egg:
        draw.playScript(utils.mergeme(*GD.gui.easter_egg))

    # remaining args are interpreted as scripts and their parameters
    script.runApp(args)
    
    # Go into interactive mode
    GD.debug("Start main loop")
    GD.app.exec_()
    GD.debug("Exit main loop")

    return 0
Example #11
0
def createProject(create=True,compression=0,addGlobals=None,makeDefault=True):
    """Open a file selection dialog and let the user select a project.

    The default will let the user create new project files as well as open
    existing ones.
    Use create=False or the convenience function openProject to only accept
    existing project files.

    If a compression level (1..9) is given, the contents will be compressed,
    resulting in much smaller project files at the cost of  

    Only one pyFormex project can be open at any time. The open project
    owns all the global data created and exported by any script.

    If makeDefault is True, an already open project will be closed and
    the opened project becomes the current project.
    If makeDefault is False, the project data are imported into GD.PF
    and the current project does not change. This means that if a project was
    open, the imported data will be added to it.
    
    If addGlobals is None, the user is asked whether the current globals
    should be added to the project. Set True or False to force or reject
    the adding without asking.
    """
    global the_project

    # ask filename from user
    if the_project is None:
        cur = GD.cfg.get('workdir','.')
    else:
        if makeDefault:
            options = ['Cancel','Close without saving','Save and Close']
            ans = draw.ask("Another project is still open. Shall I close it first?",
                        options)
            if ans == 'Cancel':
                return
            if ans == options[2]:
                the_project.save()
        cur = the_project.filename
    typ = utils.fileDescription(['pyf','all'])
    res = widgets.ProjectSelection(cur,typ,exist=not create).getResult()
    if res is None:
        # user canceled
        return

    fn = res.fn
    if not fn.endswith('.pyf'):
        fn += '.pyf'
    legacy = res.leg
    ignoresig = res.sig
    compression = res.cpr
    #print(fn,legacy,compression)

    if create and os.path.exists(fn):
        res = draw.ask("The project file '%s' already exists\nShall I delete the contents or add to it?" % fn,['Delete','Add','Cancel'])
        if res == 'Cancel':
            return
        if res == 'Add':
            create = False
    GD.message("Opening project %s" % fn)
    
    if GD.PF:
        GD.message("Exported symbols: %s" % GD.PF.keys())
        if addGlobals is None:
            res = draw.ask("pyFormex already contains exported symbols.\nShall I delete them or add them to your project?",['Delete','Add','Cancel'])
            if res == 'Cancel':
                # ESCAPE FROM CREATING THE PROJECT
                return

            addGlobals = res == 'Add'

    # OK, we have all data, now create/open the project
        
    updateSettings({'workdir':os.path.dirname(fn)},save=True)
    sig = GD.Version[:GD.Version.rfind('-')]
    if ignoresig:
        sig = ''

    proj = _open_project(fn,create,sig,compression,legacy)
        
    GD.message("Project contents: %s" % proj.keys())
    
    if hasattr(proj,'_autoscript_'):
        _ignore = "Ignore it!"
        _show = "Show it"
        _edit = "Load it in the editor"
        _exec = "Execute it"
        res = draw.ask("There is an autoscript stored inside the project.\nIf you received this project file from an untrusted source, you should probably not execute it.",[_ignore,_show,_edit,_exec])
        if res == _show:
            res = draw.showText(proj._autoscript_)#,actions=[_ignore,_edit,_show])
            return
        if res == _exec:
            draw.playScript(proj._autoscript_)
        elif res == _edit:
            fn = "_autoscript_.py"
            draw.checkWorkdir()
            f = file(fn,'w')
            f.write(proj._autoscript_)
            f.close()
            openScript(fn)
            editScript(fn)

    if hasattr(proj,'autofile') and draw.ack("The project has an autofile attribute: %s\nShall I execute this script?" % proj.autofile):
        processArgs([proj.autofile])

    if makeDefault:
        the_project = proj
        if GD.PF and addGlobals:
            the_project.update(GD.PF)
        GD.PF = the_project
        GD.GUI.setcurproj(fn)

    else:
        # Just import the data into current project
        GD.PF.update(proj)

    GD.message("Exported symbols: %s" % GD.PF.keys())
Example #12
0
def startGUI(args):
    """Create the QT4 application and GUI.

    A (possibly empty) list of command line options should be provided.
    QT4 wil remove the recognized QT4 and X11 options.
    """
    # This seems to be the only way to make sure the numeric conversion is
    # always correct
    #
    QtCore.QLocale.setDefault(QtCore.QLocale.c())
    #
    #pf.options.debug = -1
    pf.debug("Arguments passed to the QApplication: %s" % args,pf.DEBUG.INFO)
    pf.app = Application(args)
    #
    pf.debug("Arguments left after constructing the QApplication: %s" % args,pf.DEBUG.INFO)
    pf.debug("Arguments left after constructing the QApplication: %s" % '\n'.join(pf.app.arguments()),pf.DEBUG.INFO)
    #pf.options.debug = 0
    # As far as I have been testing this, the args passed to the Qt application are
    # NOT acknowledged and neither are they removed!!


    pf.debug("Setting application attributes",pf.DEBUG.INFO)
    pf.app.setOrganizationName("pyformex.org")
    pf.app.setOrganizationDomain("pyformex.org")
    pf.app.setApplicationName("pyFormex")
    pf.app.setApplicationVersion(pf.__version__)
    ## pf.settings = QtCore.QSettings("pyformex.org", "pyFormex")
    ## pf.settings.setValue("testje","testvalue")

    # Quit application if last window closed
    pf.app.lastWindowClosed.connect(pf.app.quit)

    # Check if we have DRI
    pf.debug("Setting OpenGL format",pf.DEBUG.OPENGL)
    dri = hasDRI()

    # Check for existing pyFormex processes
    pf.debug("Checking for running pyFormex",pf.DEBUG.INFO)
    if pf.X11:
        windowname,running = findOldProcesses()
    else:
        windowname,running = "UNKOWN",[]
    pf.debug("%s,%s" % (windowname,running),pf.DEBUG.INFO)


    while len(running) > 0:
        if len(running) >= 16:
            print("Too many open pyFormex windows --- bailing out")
            return -1

        pids = [ i[2] for i in running if i[2] is not None ]
        warning = """..

pyFormex is already running on this screen
------------------------------------------
A main pyFormex window already exists on your screen.

If you really intended to start another instance of pyFormex, you
can just continue now.

The window might however be a leftover from a previously crashed pyFormex
session, in which case you might not even see the window anymore, nor be able
to shut down that running process. In that case, you would better bail out now
and try to fix the problem by killing the related process(es).

If you think you have already killed those processes, you may check it by
rerunning the tests.
"""
        actions = ['Really Continue','Rerun the tests','Bail out and fix the problem']
        if pids:
            warning += """

I have identified the process(es) by their PID as::

%s

If you trust me enough, you can also have me kill this processes for you.
""" % pids
            actions[2:2] = ['Kill the running processes']

        if dri:
            answer = draw.ask(warning,actions)
        else:
            warning += """
I have detected that the Direct Rendering Infrastructure
is not activated on your system. Continuing with a second
instance of pyFormex may crash your XWindow system.
You should seriously consider to bail out now!!!
"""
            answer = draw.warning(warning,actions)


        if answer == 'Really Continue':
            break # OK, Go ahead

        elif answer == 'Rerun the tests':
            windowname,running = findOldProcesses() # try again

        elif answer == 'Kill the running processes':
            killProcesses(pids)
            windowname,running = findOldProcesses() # try again

        else:
            return -1 # I'm out of here!


    # Load the splash image
    pf.debug("Loading the splash image",pf.DEBUG.GUI)
    splash = None
    if os.path.exists(pf.cfg['gui/splash']):
        pf.debug('Loading splash %s' % pf.cfg['gui/splash'],pf.DEBUG.GUI)
        splashimage = QtGui.QPixmap(pf.cfg['gui/splash'])
        splash = QtGui.QSplashScreen(splashimage)
        splash.setWindowFlags(QtCore.Qt.WindowStaysOnTopHint|QtCore.Qt.SplashScreen)
        splash.setFont(QtGui.QFont("Helvetica",20))
        splash.showMessage(pf.Version,QtCore.Qt.AlignHCenter|QtCore.Qt.AlignTop,QtCore.Qt.red)
        splash.show()

    # create GUI, show it, run it

    pf.debug("Creating the GUI",pf.DEBUG.GUI)
    desktop = pf.app.desktop()
    pf.maxsize = Size(desktop.availableGeometry())
    size = pf.cfg.get('gui/size',(800,600))
    pos = pf.cfg.get('gui/pos',(0,0))
    bdsize = pf.cfg.get('gui/bdsize',(800,600))
    size = MinSize(size,pf.maxsize)

    # Create the GUI
    pf.GUI = Gui(windowname,
                 pf.cfg.get('gui/size',(800,600)),
                 pf.cfg.get('gui/pos',(0,0)),
                 pf.cfg.get('gui/bdsize',(800,600)),
                 )


    # set the appearance
    pf.debug("Setting Appearence",pf.DEBUG.GUI)
    pf.GUI.setAppearence()


    # setup the message board
    pf.board = pf.GUI.board
    pf.board.write("""%s   (C) Benedict Verhegghe

pyFormex comes with ABSOLUTELY NO WARRANTY. This is free software, and you are welcome to redistribute it under the conditions of the GNU General Public License, version 3 or later. See Help->License or the file COPYING for details.
""" % pf.fullVersion())

    # Set interaction functions


    def show_warning(message,category,filename,lineno,file=None,line=None):
        """Replace the default warnings.showwarning

        We display the warnings using our interactive warning widget.
        This feature can be turned off by setting
        cfg['warnings/popup'] = False
        """
        full_message = warnings.formatwarning(message,category,filename,lineno,line)
        pf.message(full_message)
        res,check = draw.showMessage(full_message,level='warning',check="Do not show this warning anymore in future sessions")
        if check[0]:
            utils.filterWarning(str(message))
            utils.saveWarningFilter(str(message))

    if pf.cfg['warnings/popup']:
        warnings.showwarning = show_warning


    pf.message = draw.message
    pf.warning = draw.warning
    pf.error = draw.error


    # setup the canvas
    pf.debug("Setting the canvas",pf.DEBUG.GUI)
    pf.GUI.processEvents()
    pf.GUI.viewports.changeLayout(1)
    pf.GUI.viewports.setCurrent(0)
    #pf.canvas = pf.GUI.viewports.current
    pf.canvas.setRenderMode(pf.cfg['draw/rendermode'])

    #
    # PYSIDE: raises (intercepted) exception on startup
    #
    draw.reset()

    # setup the status bar
    pf.debug("Setup status bar",pf.DEBUG.GUI)
    pf.GUI.addInputBox()
    pf.GUI.toggleInputBox(False)
    pf.GUI.addCoordsTracker()
    pf.GUI.toggleCoordsTracker(pf.cfg.get('gui/coordsbox',False))
    pf.debug("Using window name %s" % pf.GUI.windowTitle(),pf.DEBUG.GUI)

    # Script menu
    pf.GUI.scriptmenu = appMenu.createAppMenu(mode='script',parent=pf.GUI.menu,before='help')

    # App menu
    pf.GUI.appmenu = appMenu.createAppMenu(parent=pf.GUI.menu,before='help')


    # BV: removed, because they are in the script/app menus,
    # and the file menu is alredy very loaded

    ## # Link History Menus also in the File menu
    ## parent = pf.GUI.menu.item('file')
    ## before = parent.item('---1')
    ## if pf.GUI.apphistory:
    ##     parent.insert_menu(pf.GUI.apphistory,before)

    ## if pf.GUI.scripthistory:
    ##     parent.insert_menu(pf.GUI.scripthistory,before)

    # Create databases
    createDatabases()

    # Plugin menus
    import plugins
    filemenu = pf.GUI.menu.item('file')
    pf.gui.plugin_menu = plugins.create_plugin_menu(filemenu,before='---1')
    # Load configured plugins, ignore if not found
    plugins.loadConfiguredPlugins()

    # show current application/file
    appname = pf.cfg['curfile']
    pf.GUI.setcurfile(appname)

    # Last minute menu modifications can go here

    # cleanup
    pf.GUI.setBusy(False)         # HERE
    pf.GUI.addStatusBarButtons()

    if splash is not None:
        # remove the splash window
        splash.finish(pf.GUI)

    pf.GUI.setBusy(False)        # OR HERE

    pf.debug("Showing the GUI",pf.DEBUG.GUI)
    pf.GUI.show()

    # redirect standard output to board
    # TODO: this should disappear when we have buffered stdout
    # and moved this up into GUI init
    pf.GUI.board.redirect(pf.cfg['gui/redirect'])


    pf.GUI.update()

    if pf.cfg['gui/fortune']:
        sta,out = utils.runCommand(pf.cfg['fortune'])
        if sta == 0:
            draw.showInfo(out)

    #pf.app.setQuitOnLastWindowClosed(False)
    pf.app_started = True
    pf.GUI.processEvents()

    # load last project
    #
    #  TODO
    if pf.cfg['openlastproj']:
        fn = pf.cfg['curproj']
        if fn:
            try:
                proj = fileMenu.readProjectFile(fn)
                fileMenu.setProject(proj)
            except:
                # Avoid crashes from a faulty project file
                # TODO: should we push this up to fileMenu.readProjectFile ?
                #
                pf.message("Could not load the current project %s" % fn)
    #
    return 0
Example #13
0
def map_editor():
    from constants import FPS, MAP_WIDTH, MAP_HEIGHT, PALLETE_OFFSET_X, PALLETE_OFFSET_Y, TILE_WIDTH, TILE_HEIGHT, \
        TILE_PALLETE_SPACING, TILE_PALLETE_ROWS, TILE_PALLETE_COLUMNS, MINIMAP_POSITION_OFFSET_X, MINIMAP_POSITION_OFFSET_Y, MINIMAP_TILE_SIZE
    from copy import deepcopy
    import os.path
    current_tile = False  # placeholder value until a tile is selected for the first time
    mapchange = True
    location_x = 0  # initial player starting xpos
    location_y = 0  # initial player starting ypos

    fpsclock = pygame.time.Clock()  # initialize the clock
    levelmap = init_new_map()  # create a new map
    oldlevelmap = deepcopy(levelmap)
    displaysurface = init_graphics()  # start pygame and build the window
    mousebuttons = pygame.mouse.get_pressed()  # get initial mouse values
    mousex, mousey = pygame.mouse.get_pos()
    bitmaps = load_tiles()  # load the tileset
    palleterects = draw_pallete(bitmaps, displaysurface)  # draw the pallet and return the button rectangles
    palleterect = pygame.Rect(PALLETE_OFFSET_X, PALLETE_OFFSET_Y,
                              (TILE_WIDTH + TILE_PALLETE_SPACING) * TILE_PALLETE_COLUMNS,
                              (TILE_HEIGHT + TILE_PALLETE_SPACING) * TILE_PALLETE_ROWS)
    # Start Main Loop
    while True:

        if mapchange:
            mapsurf = draw_main_map(levelmap, bitmaps)  # draw the main map surface
            minimapsurf = draw_mini_map(levelmap)
            mapchange = False
        displayrect = blit_map_to_main_map_surface(displaysurface, mapsurf, location_x,
                                         location_y, mousex, mousey)  # update the map portion of the screen
        minimaprect = update_mini_map_display_surface(displaysurface, minimapsurf, location_x, location_y)
        for event in pygame.event.get():
            if event.type == QUIT:
                pygame.quit()
                sys.exit()
            if event.type == KEYUP:
                if event.key == K_a:
                    location_x -= 1
                    if location_x < 0:
                        location_x = 0
                elif event.key == K_d:
                    location_x += 1
                    if location_x > MAP_WIDTH:
                        location_x = MAP_WIDTH
                elif event.key == K_w:
                    location_y -= 1
                    if location_y < 0:
                        location_y = 0
                elif event.key == K_s:
                    location_y += 1
                    if location_y > MAP_HEIGHT:
                        location_y = MAP_HEIGHT
                elif event.key == K_F1:
                    filename = ask(displaysurface, 'Save Filename')
                    if filename:
                        json.dump(levelmap, open(filename, 'w'))
                elif event.key == K_F2:
                    filename = ask(displaysurface, 'Load Filename')
                    if filename:
                        if os.path.isfile(filename):
                            levelmap = json.load(open(filename))
                            mapchange = True
                elif event.key == K_F3:
                    levelmap = gen_random_map()
                    mapchange = True
                elif event.key == K_ESCAPE:
                    levelmap = deepcopy(oldlevelmap)
                    mapchange = True
            if event.type == MOUSEBUTTONDOWN:
                mouse_down_x, mouse_down_y = event.pos  # store the mouse position during the click
                if displayrect.collidepoint(mouse_down_x, mouse_down_y):  # If in the map display
                    oldlevelmap = deepcopy(levelmap)  # save a copy of the level for UNDO
                if minimaprect.collidepoint(mouse_down_x, mouse_down_y):
                    location_x = (mouse_down_x - MINIMAP_POSITION_OFFSET_X) // MINIMAP_TILE_SIZE
                    location_y = (mouse_down_y - MINIMAP_POSITION_OFFSET_Y) // MINIMAP_TILE_SIZE
            if event.type == MOUSEBUTTONUP:
                if mousebuttons[0] == 1:
                    if palleterect.collidepoint(mouse_down_x, mouse_down_y):
                        old_tile = current_tile
                        current_tile = get_pallete_selection(palleterects, mouse_down_x, mouse_down_y)
                        if not current_tile:
                            current_tile = old_tile
                    if displayrect.collidepoint(mouse_down_x, mouse_down_y):
                        set_map_tile(levelmap, current_tile, mouse_down_x, mouse_down_y, location_x, location_y)
                        mapchange = True

            if event.type == MOUSEMOTION:
                mousex, mousey = event.pos
                if mousebuttons[0] == 1:
                    if displayrect.collidepoint(mouse_down_x, mouse_down_y):
                        set_map_tile(levelmap, current_tile, mousex, mousey, location_x, location_y)
                        mapchange = True
        mousebuttons = pygame.mouse.get_pressed()  # store which mouse buttons were pressed
        fpsclock.tick(FPS)
Example #14
0
def setProject(proj):
    """Make the specified project the current project.

    proj is an open project.
    If a filename, the project file is opened.

    .. note: The remainder is obsolete

    The user is asked for a Project file name and the access modalities.
    Depending on the results of the dialog:

    - either an new project is create or an old is opened,
    - the old data may be discarded, added to the current pyFormex globals,
      or replace them
    - the opened Project may become the current Project, or its data are
      just imported in the current Project.


    The default will let the user create new project files as well as open
    existing ones.
    Use create=False or the convenience function openProject to only accept
    existing project files.

    If a compression level (1..9) is given, the contents will be compressed,
    resulting in much smaller project files at the cost of

    Only one pyFormex project can be open at any time. The open project
    owns all the global data created and exported by any script.

    If makeDefault is True, an already open project will be closed and
    the opened project becomes the current project.
    If makeDefault is False, the project data are imported into pf.PF
    and the current project does not change. This means that if a project was
    open, the imported data will be added to it.

    If addGlobals is None, the user is asked whether the current globals
    should be added to the project. Set True or False to force or reject
    the adding without asking.
    """
    pf.message("Setting current project to %s" % proj.filename)
    pf.message("Project contents: %s" % utils.sortedKeys(proj))
    keep = {}
    if pf.PF:
        pf.message("Current pyFormex globals: %s" % utils.sortedKeys(pf.PF))
        _delete = "Delete"
        _add = "Keep non existing"
        _overwrite = "Keep all (overwrite project)"
        res = draw.ask("What shall I do with the current pyFormex globals?",[_delete,_add,_overwrite])
        if res == _add:
            keep = utils.removeDict(pf.PF,proj)
        elif res == _overwrite:
            keep = pf.PF
    pf.PF = proj
    if keep:
        pf.PF.update(keep)
    if pf.PF.filename:
        updateSettings({
            'curproj':pf.PF.filename,
            'workdir':os.path.dirname(pf.PF.filename),
            },save=True)
    pf.GUI.setcurproj(pf.PF.filename)

    if hasattr(proj,'_autoscript_'):
        _ignore = "Ignore it!"
        _show = "Show it"
        _edit = "Load it in the editor"
        _exec = "Execute it"
        res = draw.ask("There is an autoscript stored inside the project.\nIf you received this project file from an untrusted source, you should probably not execute it.",[_ignore,_show,_edit,_exec])
        if res == _show:
            res = draw.showText(proj._autoscript_)#,actions=[_ignore,_edit,_show])
            return
        if res == _exec:
            draw.playScript(proj._autoscript_)
        elif res == _edit:
            fn = "_autoscript_.py"
            draw.checkWorkdir()
            f = open(fn,'w')
            f.write(proj._autoscript_)
            f.close()
            openScript(fn)
            editApp(fn)

    if hasattr(proj,'autofile') and draw.ack("The project has an autofile attribute: %s\nShall I execute this script?" % proj.autofile):
        draw.processArgs([proj.autofile])

    listProject()
Example #15
0
def setProject(proj):
    """Make the specified project the current project.

    proj is an open project.
    If a filename, the project file is opened.

    .. note: The remainder is obsolete

    The user is asked for a Project file name and the access modalities.
    Depending on the results of the dialog:

    - either an new project is create or an old is opened,
    - the old data may be discarded, added to the current pyFormex globals,
      or replace them
    - the opened Project may become the current Project, or its data are
      just imported in the current Project.


    The default will let the user create new project files as well as open
    existing ones.
    Use create=False or the convenience function openProject to only accept
    existing project files.

    If a compression level (1..9) is given, the contents will be compressed,
    resulting in much smaller project files at the cost of

    Only one pyFormex project can be open at any time. The open project
    owns all the global data created and exported by any script.

    If makeDefault is True, an already open project will be closed and
    the opened project becomes the current project.
    If makeDefault is False, the project data are imported into pf.PF
    and the current project does not change. This means that if a project was
    open, the imported data will be added to it.

    If addGlobals is None, the user is asked whether the current globals
    should be added to the project. Set True or False to force or reject
    the adding without asking.
    """
    pf.message("Setting current project to %s" % proj.filename)
    pf.message("Project contents: %s" % utils.sortedKeys(proj))
    keep = {}
    if pf.PF:
        pf.message("Current pyFormex globals: %s" % utils.sortedKeys(pf.PF))
        _delete = "Delete"
        _add = "Keep non existing"
        _overwrite = "Keep all (overwrite project)"
        res = draw.ask("What shall I do with the current pyFormex globals?",
                       [_delete, _add, _overwrite])
        if res == _add:
            keep = utils.removeDict(pf.PF, proj)
        elif res == _overwrite:
            keep = pf.PF
    pf.PF = proj
    if keep:
        pf.PF.update(keep)
    if pf.PF.filename:
        updateSettings(
            {
                'curproj': pf.PF.filename,
                'workdir': os.path.dirname(pf.PF.filename),
            },
            save=True)
    pf.GUI.setcurproj(pf.PF.filename)

    if hasattr(proj, '_autoscript_'):
        _ignore = "Ignore it!"
        _show = "Show it"
        _edit = "Load it in the editor"
        _exec = "Execute it"
        res = draw.ask(
            "There is an autoscript stored inside the project.\nIf you received this project file from an untrusted source, you should probably not execute it.",
            [_ignore, _show, _edit, _exec])
        if res == _show:
            res = draw.showText(
                proj._autoscript_)  #,actions=[_ignore,_edit,_show])
            return
        if res == _exec:
            draw.playScript(proj._autoscript_)
        elif res == _edit:
            fn = "_autoscript_.py"
            draw.checkWorkdir()
            f = open(fn, 'w')
            f.write(proj._autoscript_)
            f.close()
            openScript(fn)
            editApp(fn)

    if hasattr(proj, 'autofile') and draw.ack(
            "The project has an autofile attribute: %s\nShall I execute this script?"
            % proj.autofile):
        draw.processArgs([proj.autofile])

    listProject()
Example #16
0
def main_loop(player, displaysurface, bitmaps):
    from constants import FPS, MINIMAP_POSITION_OFFSET_X, \
        MINIMAP_POSITION_OFFSET_Y, MINIMAP_TILE_SIZE
    from draw import draw_main_map, draw_mini_map, update_mini_map_display_surface, draw_mobs, \
        ask, update_main_display_surface, init_main_map_surface, init_mini_map_surface, init_player_info_surface, \
        draw_player_info_box, update_player_info_box
    from player import move_player
    from utils import update_explored_portion_of_map_based_on_vision, make_all_explored
    import os.path
    import json
    import sys

    mapchangeall = True  # redraw the entire explored map surface the first time
    mapchange = True
    fpsclock = pygame.time.Clock()  # initialize the clock
    mousebuttons = pygame.mouse.get_pressed()  # get initial mouse values
    mousex, mousey = pygame.mouse.get_pos()
    mapsurf = init_main_map_surface()
    minimapsurf = init_mini_map_surface()
    playinfosurf = init_player_info_surface()
    # Start Main Loop
    while True:

        player = update_explored_portion_of_map_based_on_vision(player)

        if mapchangeall:
            mapsurf = draw_main_map(player, bitmaps, mapsurf, True)  # redraw the entire explored main map surface
            minimapsurf = draw_mini_map(player, minimapsurf, True)
            mapchangeall = False
        if mapchange:
            mapsurf = draw_main_map(player, bitmaps, mapsurf, False)  # draw the main map surface in view of the player
            minimapsurf = draw_mini_map(player, minimapsurf, False)
            mapchange = False

        mobsurf = draw_mobs(player, bitmaps)
        displayrect = update_main_display_surface(displaysurface, mapsurf, mobsurf, mousex, mousey, player['locationx'],
                                                  player['locationy'])
        minimaprect = update_mini_map_display_surface(displaysurface, minimapsurf, player['locationx'],
                                                      player['locationy'])
        playinfosurf = draw_player_info_box(player, playinfosurf)
        playinforect = update_player_info_box(displaysurface, playinfosurf)

        for event in pygame.event.get():
            if event.type == QUIT:
                pygame.quit()
                sys.exit()
            if event.type == KEYUP:
                if event.key == K_UP:
                    player = move_player(player, 'N')
                    mapchange = True
                elif event.key == K_DOWN:
                    player = move_player(player, 'S')
                    mapchange = True
                elif event.key == K_LEFT:
                    player = move_player(player, 'W')
                    mapchange = True
                elif event.key == K_RIGHT:
                    player = move_player(player, 'E')
                    mapchange = True
                elif event.key == K_F1:
                    filename = ask(displaysurface, 'Save Filename')
                    if filename:
                        json.dump(player, open(filename, 'w'))
                elif event.key == K_F2:
                    filename = ask(displaysurface, 'Load Filename')
                    if filename:
                        if os.path.isfile(filename):
                            player = json.load(open(filename))
                            mapchangeall = True
                elif event.key == K_F12:
                    player = make_all_explored(player)
                    mapchangeall = True
            if event.type == MOUSEBUTTONDOWN:
                mouse_down_x, mouse_down_y = event.pos  # store the mouse position during the click
                if displayrect.collidepoint(mouse_down_x, mouse_down_y):  # If in the map display
                    None
                if minimaprect.collidepoint(mouse_down_x, mouse_down_y):
                    player['locationx'] = (mouse_down_x - MINIMAP_POSITION_OFFSET_X) // MINIMAP_TILE_SIZE
                    player['locationy'] = (mouse_down_y - MINIMAP_POSITION_OFFSET_Y) // MINIMAP_TILE_SIZE
            if event.type == MOUSEBUTTONUP:
                if mousebuttons[0] == 1:
                    None
            if event.type == MOUSEMOTION:
                mousex, mousey = event.pos
                if mousebuttons[0] == 1:
                    if displayrect.collidepoint(mouse_down_x, mouse_down_y):
                        None
        mousebuttons = pygame.mouse.get_pressed()  # store which mouse buttons were pressed
        fpsclock.tick(FPS)