def __init__(self,parent=None,path=None): QtGui.QMainWindow.__init__(self) self.parent = parent self.filename = path self.image = QtGui.QLabel() self.image.setBackgroundRole(QtGui.QPalette.Base) self.image.setSizePolicy(QtGui.QSizePolicy.Ignored,QtGui.QSizePolicy.Ignored) #self.image.setScaledContents(True) self.scroll = QtGui.QScrollArea() self.scroll.setBackgroundRole(QtGui.QPalette.Dark) self.scroll.setWidget(self.image) self.scroll.setWidgetResizable(True) self.setCentralWidget(self.scroll) self.createActions() self.createMenus() self.setWindowTitle(tr(caption)) self.resize(500,400) self.setSizePolicy(QtGui.QSizePolicy.Minimum,QtGui.QSizePolicy.Minimum) if path: self.openfile(path)
def createMenus(self): self.fileMenu = QtGui.QMenu(tr("&File"),self) self.fileMenu.addAction(self.openAct) self.fileMenu.addAction(self.printAct) self.fileMenu.addSeparator() self.viewMenu = QtGui.QMenu(tr("&View"),self) self.viewMenu.addAction(self.zoomInAct) self.viewMenu.addAction(self.zoomOutAct) self.viewMenu.addAction(self.normalSizeAct) self.viewMenu.addSeparator() self.viewMenu.addAction(self.fitToImageAct) self.viewMenu.addAction(self.fitToWindowAct) self.helpMenu = QtGui.QMenu(tr("&Help"),self) self.helpMenu.addAction(self.aboutAct) self.menuBar().addMenu(self.fileMenu) self.menuBar().addMenu(self.viewMenu) self.menuBar().addMenu(self.helpMenu) if isinstance(self.parent,QtGui.QApplication): self.fileMenu.addAction(self.exitAct) self.helpMenu.addAction(self.aboutQtAct) elif isinstance(self.parent,QtGui.QDialog): self.fileMenu.addAction(self.acceptAct) self.fileMenu.addAction(self.rejectAct)
def print_(self): if not self.image.pixmap(): return self.printer = QtGui.QPrinter() dialog = QtGui.QPrintDialog(self.printer,self) if dialog.exec_(): painter = QtGui.QPainter(self.printer) rect = painter.viewport() size = self.image.pixmap().size() size.scale(rect.size(),QtCore.Qt.KeepAspectRatio) painter.setViewport(rect.x(),rect.y(),size.width(),size.height()) painter.setWindow(self.image.pixmap().rect()) painter.drawPixmap(0,0,self.image.pixmap())
def openfile(self,filename=None): if filename is None: filename = self.filename if filename is None: filename = QtCore.QDir.currentPath() filename = QtGui.QFileDialog.getOpenFileName(self,tr("Open File"),filename) if not filename: return image = QtGui.QImage(filename) if image.isNull(): QtGui.QMessageBox.information(self,tr(caption),tr("Cannot load %1.").arg(filename)) return #print("Size %sx%s" % (image.width(),image.height())) self.filename = str(filename) self.image.setPixmap(QtGui.QPixmap.fromImage(image)) self.scaleFactor = 1.0 self.printAct.setEnabled(True) self.fitToWindowAct.setEnabled(True) self.updateActions() ## if not self.fitToWindowAct.isChecked(): self.image.adjustSize() self.normalSize()
def GLcolor(color): """Convert a color to an OpenGL RGB color. The output is a tuple of three RGB float values ranging from 0.0 to 1.0. The input can be any of the following: - a QColor - a string specifying the Xwindow name of the color - a hex string '#RGB' with 1 to 4 hexadecimal digits per color - a tuple or list of 3 integer values in the range 0..255 - a tuple or list of 3 float values in the range 0.0..1.0 Any other input may give unpredictable results. Examples: >>> GLcolor('indianred') (0.803921568627451, 0.3607843137254902, 0.3607843137254902) >>> print(GLcolor('#ff0000')) (1.0, 0.0, 0.0) >>> GLcolor(red) (1.0, 0.0, 0.0) >>> GLcolor([200,200,255]) (0.7843137254901961, 0.7843137254901961, 1.0) >>> GLcolor([1.,1.,1.]) (1.0, 1.0, 1.0) """ col = color # as of Qt4.5, QtGui.Qcolor no longer raises an error if given # erroneous input. Therefore, we check it ourselves # str or QtCore.Globalcolor: convert to QColor if (type(col) is str or isinstance(col, QtCore.Qt.GlobalColor)): try: col = QtGui.QColor(col) except: pass # QColor: convert to (r,g,b) tuple (0..255) if isinstance(col, QtGui.QColor): col = (col.red(), col.green(), col.blue()) # Convert to a list and check length try: col = tuple(col) if len(col) == 3: if isInt(col[0]): # convert int values to float col = [c / 255. for c in col] col = map(float, col) # SUCCESS ! return tuple(col) except: pass # No success: raise an error raise ValueError, "GLcolor: unexpected input of type %s: %s" % ( type(color), color)
def fontHeight(font=None, size=None): """Return the height in pixels of the given font. This can be used to determine the canvas coordinates where the text is to be drawn. """ font = getFont(font, size) fh = font.pixelSize() if fh < 0: fh = QtGui.QFontInfo(font).pixelSize() return fh
def main(): import sys global app app = QtGui.QApplication(sys.argv) if len(sys.argv) > 1: path = sys.argv[1] else: path = None viewer = ImageViewer(app,path) viewer.show() sys.exit(app.exec_())
def setFont(self,font): """Set the main application font. font is either a QFont or a string resulting from the QFont.toString() method """ if not isinstance(font,QtGui.QFont): f = QtGui.QFont() f.fromString(font) font = f pf.app.setFont(font) self.update()
def getFont(font=None, size=None): """Get the best fonts matching font name and size If nothing is specified, returns the default GUI font. """ if font is None: font = pyformex.GUI.font() else: font = QtGui.QFont(font) if size is not None: font.setPointSize(size) return font
def __init__(self,parent=None): """Construct the Message Board widget.""" QtGui.QTextEdit.__init__(self,parent) self.setReadOnly(True) self.setAcceptRichText(False) self.setFrameStyle(QtGui.QFrame.StyledPanel | QtGui.QFrame.Sunken) self.setMinimumSize(24,24) self.setSizePolicy(QtGui.QSizePolicy.MinimumExpanding,QtGui.QSizePolicy.MinimumExpanding) self.cursor = self.textCursor() #self.buffer = '' font = QtGui.QFont("DejaVu Sans Mono") #font.setStyle(QtGui.QFont.StyleNormal) self.setFont(font) self.stdout = self.stderr = None # redirected streams
def setcurfile(self,appname): """Set the current application or script. appname is either an application module name or a script file. """ is_app = not utils.is_script(appname) if is_app: # application label = 'App:' name = appname import apps app = apps.load(appname) if app is None: self.canPlay = False try: self.canEdit = os.path.exists(apps.findAppSource(appname)) except: self.canEdit = False else: self.canPlay = hasattr(app,'run') self.canEdit = os.path.exists(apps.findAppSource(app)) else: # script file label = 'Script:' name = os.path.basename(appname) self.canPlay = self.canEdit = utils.is_pyFormex(appname) or appname.endswith('.pye') pf.prefcfg['curfile'] = appname #self.curfile.label.setText(label) self.curfile.setText(label,0) self.curfile.setText(name,1) self.enableButtons(self.actions,['Play','Info'],self.canPlay) self.enableButtons(self.actions,['Edit'],self.canEdit) self.enableButtons(self.actions,['ReRun'],is_app and(self.canEdit or self.canPlay)) self.enableButtons(self.actions,['Step','Continue'],False) icon = 'ok' if self.canPlay else 'notok' self.curfile.setIcon(QtGui.QIcon(QtGui.QPixmap(os.path.join(pf.cfg['icondir'],icon)+pf.cfg['gui/icontype'])),1)
def add(self, name, icon=None, text=None): """Add a new name to the actions list and create a matching DAction. If the actions list has an associated menu or toolbar, a matching button will be inserted in each of these. If an icon is specified, it will be used on the menu and toolbar. The icon is either a filename or a QIcon object. If text is specified, it is displayed instead of the action's name. """ if type(icon) == str: if os.path.exists(icon): icon = QtGui.QIcon(QtGui.QPixmap(icon)) else: raise RuntimeError, 'Icons not installed properly' if text is None: text = name a = DAction(text, icon, name) if self.function: a.signal.connect(self.function) self.actions.append([name, a]) if self.menu: self.menu.addAction(a) if self.toolbar: self.toolbar.addAction(a)
def write(self,s,color=None): """Write a string to the message board. If a color is specified, the text is shown in the specified color, but the default board color remains unchanged. """ if color: savecolor = self.textColor() self.setTextColor(QtGui.QColor(color)) else: savecolor = None # A single blank character seems to be generated by a print # instruction containing a comma: skip it if s == ' ': return #self.buffer += '[%s:%s]' % (len(s),s) s = s.rstrip('\n') if len(s) > 0: self.append(s) self.cursor.movePosition(QtGui.QTextCursor.End) self.setTextCursor(self.cursor) if savecolor: self.setTextColor(savecolor)
def updateToolBar(self,shortname,fullname=None): """Add a toolbar or change its position. This function adds a toolbar to the GUI main window at the position specified in the configuration. If the toolbar already exists, it is moved from its previous location to the requested position. If the toolbar does not exist, it is created with the given fullname, or the shortname by default. The full name is the name as displayed to the user. The short name is the name as used in the config settings. The config setting for the toolbar determines its placement: - None: the toolbar is not created - 'left', 'right', 'top' or 'bottom': a separate toolbar is created - 'default': the default top toolbar is used and a separator is added. """ area = pf.cfg['gui/%s' % shortname] try: toolbar = getattr(self,shortname) except: toolbar = None if area: area = self.toolbar_area.get(area,4) # default is top # Add/reposition the toolbar if toolbar is None: if fullname is None: fullname = shortname toolbar = QtGui.QToolBar(fullname,self) self.addToolBar(area,toolbar) else: if toolbar is not None: self.removeToolBar(toolbar) toolbar = None return toolbar
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
def insertItems(self, items, before=None, debug=False): """Insert a list of items in the menu. Parameters: - `items`: a list of menuitem tuples. Each item is a tuple of two or three elements: (text, action, options): - `text`: the text that will be displayed in the menu item. It is stored in a normalized way: all lower case and with '&' removed. - `action`: can be any of the following: - a Python function or instance method : it will be called when the item is selected, - a string with the name of a function/method, - a list of Menu Items: a popup Menu will be created that will appear when the item is selected, - an existing Menu, - None : this will create a separator item with no action. - `options`: optional dictionary with following honoured fields: - `icon`: the name of an icon to be displayed with the item text. This name should be that of one of the icons in the pyFormex icondir. - `shortcut`: is an optional key combination to select the item. - `tooltip`: a text that is displayed as popup help. - `before`: if specified, should be the text *or* the action of one of the items in the Menu (not the items list!): the new list of items will be inserted before the specified item. """ if debug: print("Inserting %s items in menu %s" % (len(items), self.title())) before = self.action(before) for item in items: txt, val = item[:2] if debug: print("INSERTING %s: %s" % (txt, val)) if len(item) > 2: options = item[2] else: options = {} if val is None: a = self.insert_sep(before) self.separators[txt] = a elif isinstance(val, list): a = Menu(txt, parent=self, before=before) a.insertItems(val) elif isinstance(val, BaseMenu): #print("INSERTING MENU %s"%txt) self.insert_menu(val, before=before) else: if type(val) == str: val = eval(val) if 'data' in options: # DActions should be saved to keep them alive !!! if debug: print("INSERTING DAction %s" % txt) a = DAction(txt, data=options['data']) a.signal.connect(val) self.insert_action(a, before) # We need to store the DActions, or else they are # destroyed. QActions are stroed by Qt self._actions_.append(a) else: if debug: print("INSERTING QAction %s" % txt) if before is not None: raise RuntimeError, "I can not insert a QAction menu item before an existing one." a = self.create_insert_action(txt, val, before) for k, v in options.items(): if k == 'icon': a.setIcon(QtGui.QIcon(QtGui.QPixmap( utils.findIcon(v)))) elif k == 'shortcut': a.setShortcut(v) elif k == 'tooltip': a.setToolTip(v) elif k == 'checkable': a.setCheckable(v) elif k == 'checked': a.setCheckable(True) a.setChecked(v) elif k == 'disabled': a.setDisabled(True)
def windowId(): """Return the X windowid of the main pyFormex window.""" info = QtGui.QX11Info() print(info) print("%x" % info.appRootWindow())
def getStyles(self): return map(str,QtGui.QStyleFactory().keys())
def createActions(self): self.openAct = QtGui.QAction(tr("&Open..."),self) self.openAct.setShortcut(tr("Ctrl+O")) self.openAct.triggered.connect(self.openfile) self.printAct = QtGui.QAction(tr("&Print..."),self) self.printAct.setShortcut(tr("Ctrl+P")) self.printAct.setEnabled(False) self.printAct.triggered.connect(self.print_) self.zoomInAct = QtGui.QAction(tr("Zoom &In (25%)"),self) self.zoomInAct.setShortcut(tr("Ctrl++")) self.zoomInAct.setEnabled(False) self.zoomInAct.triggered.connect(self.zoomIn) self.zoomOutAct = QtGui.QAction(tr("Zoom &Out (25%)"),self) self.zoomOutAct.setShortcut(tr("Ctrl+-")) self.zoomOutAct.setEnabled(False) self.zoomOutAct.triggered.connect(self.zoomOut) self.normalSizeAct = QtGui.QAction(tr("&Normal Size"),self) self.normalSizeAct.setShortcut(tr("Ctrl+S")) self.normalSizeAct.setEnabled(False) self.normalSizeAct.triggered.connect(self.normalSize) self.fitToImageAct = QtGui.QAction(tr("Fit &Window to Image"),self) self.fitToImageAct.setShortcut(tr("Ctrl+W")) self.fitToImageAct.setEnabled(False) #self.fitToImageAct.setCheckable(True) self.fitToImageAct.triggered.connect(self.fitToImage) self.fitToWindowAct = QtGui.QAction(tr("&Fit Image to Window"),self) self.fitToWindowAct.setShortcut(tr("Ctrl+F")) self.fitToWindowAct.setEnabled(False) self.fitToWindowAct.setCheckable(True) self.fitToWindowAct.triggered.connect(self.fitToWindow) self.aboutAct = QtGui.QAction(tr("&About"),self) self.aboutAct.triggered.connect(self.about) if isinstance(self.parent,QtGui.QApplication): self.exitAct = QtGui.QAction(tr("E&xit"),self) self.exitAct.setShortcut(tr("Ctrl+Q")) self.exitAct.triggered.connect(self.close) self.aboutQtAct = QtGui.QAction(tr("About &Qt"),self) self.aboutQtAct.triggered.connect(self.parent.aboutQt) elif isinstance(self.parent,QtGui.QDialog): self.acceptAct = QtGui.QAction(tr("&Accept"),self) self.acceptAct.setShortcut(tr("Ctrl+A")) self.acceptAct.triggered.connect(self.parent.accept) self.rejectAct = QtGui.QAction(tr("&Reject"),self) self.rejectAct.setShortcut(tr("Ctrl+Q")) self.rejectAct.triggered.connect(self.parent.reject)
def setStyle(self,style): """Set the main application style.""" style = QtGui.QStyleFactory().create(style) pf.app.setStyle(style) self.update()
def __init__(self,windowname,size=(800,600),pos=(0,0),bdsize=(0,0)): """Constructs the GUI. The GUI has a central canvas for drawing, a menubar and a toolbar on top, and a statusbar at the bottom. """ pf.debug('Creating Main Window',pf.DEBUG.GUI) self.on_exit = [] QtGui.QMainWindow.__init__(self) self.fullscreen = False self.setWindowTitle(windowname) # add widgets to the main window # The status bar pf.debug('Creating Status Bar',pf.DEBUG.GUI) self.statusbar = self.statusBar() #self.statusbar.setSizePolicy(QtGui.QSizePolicy.Minimum,QtGui.QSizePolicy.Minimum) #self.statusbar.setFixedHeight(32) #self.statusbar.setContentsMargins(0,0,0,0) #widgets.addEffect(self.statusbar,color=(255,0,0)) self.curproj = widgets.ButtonBox('Project:',[('None',fileMenu.openExistingProject)]) self.curfile = widgets.ButtonBox('',[('Script:',toggleAppScript),('None',fileMenu.openScript)]) self.curdir = widgets.ButtonBox('Cwd:',[('None',draw.askDirname)]) self.canPlay = False self.canEdit = False # The menu bar pf.debug('Creating Menu Bar',pf.DEBUG.GUI) self.menu = menu.MenuBar('TopMenu') self.setMenuBar(self.menu) # The toolbar pf.debug('Creating ToolBar',pf.DEBUG.GUI) self.toolbar = self.addToolBar('Top ToolBar') self.editor = None # Create a box for the central widget self.box = QtGui.QWidget() self.setCentralWidget(self.box) self.boxlayout = QtGui.QVBoxLayout() self.boxlayout.setContentsMargins(*pf.cfg['gui/boxmargins']) self.box.setLayout(self.boxlayout) #self.box.setFrameStyle(qt.QFrame.Sunken | qt.QFrame.Panel) #self.box.setLineWidth(2) # Create a splitter self.splitter = QtGui.QSplitter() self.boxlayout.addWidget(self.splitter) self.splitter.setOrientation(QtCore.Qt.Vertical) self.splitter.show() # self.central is the central widget of the main window # self.viewports is its layout, containing multiple viewports pf.debug('Creating Central Widget',pf.DEBUG.GUI) self.central = QtGui.QWidget() self.central.autoFillBackground() #self.central.setFrameStyle(QtGui.QFrame.StyledPanel | QtGui.QFrame.Sunken) self.central.setSizePolicy(QtGui.QSizePolicy.MinimumExpanding,QtGui.QSizePolicy.MinimumExpanding) self.central.resize(*pf.cfg['gui/size']) self.viewports = viewport.MultiCanvas(parent=self.central) self.centralgrid = QtGui.QGridLayout() self.centralgrid.addLayout(self.viewports,0,0) self.central.setLayout(self.centralgrid) # Create the message board self.board = Board() #self.board.setPlainText(pf.Version+' started') # Put everything together self.splitter.addWidget(self.central) self.splitter.addWidget(self.board) #self.splitter.setSizes([(800,200),(800,600)]) self.box.setLayout(self.boxlayout) # Create the top menu pf.debug('Creating Menus',pf.DEBUG.GUI) menudata = menu.createMenuData() self.menu.insertItems(menudata) # ... and the toolbar self.actions = toolbar.addActionButtons(self.toolbar) # timeout button toolbar.addTimeoutButton(self.toolbar) self.menu.show() # Define Toolbars pf.debug('Creating Toolbars',pf.DEBUG.GUI) self.camerabar = self.updateToolBar('camerabar','Camera ToolBar') self.modebar = self.updateToolBar('modebar','RenderMode ToolBar') self.viewbar = self.updateToolBar('viewbar','Views ToolBar') self.toolbars = [self.camerabar, self.modebar, self.viewbar] ############### CAMERA menu and toolbar ############# if self.camerabar: toolbar.addCameraButtons(self.camerabar) toolbar.addPerspectiveButton(self.camerabar) ############### RENDERMODE menu and toolbar ############# modes = [ 'wireframe', 'smooth', 'smoothwire', 'flat', 'flatwire' ] if pf.cfg['gui/modemenu']: mmenu = QtGui.QMenu('Render Mode') else: mmenu = None #menutext = '&' + name.capitalize() self.modebtns = menu.ActionList( modes,guifunc.renderMode,menu=mmenu,toolbar=self.modebar) # Add the toggle type buttons if self.modebar: toolbar.addTransparencyButton(self.modebar) if self.modebar and pf.cfg['gui/lightbutton']: toolbar.addLightButton(self.modebar) if self.modebar and pf.cfg['gui/normalsbutton']: toolbar.addNormalsButton(self.modebar) if self.modebar and pf.cfg['gui/shrinkbutton']: toolbar.addShrinkButton(self.modebar) if mmenu: # insert the mode menu in the viewport menu pmenu = self.menu.item('viewport') pmenu.insertMenu(pmenu.item('background color'),mmenu) ############### VIEWS menu ################ if pf.cfg['gui/viewmenu']: if pf.cfg['gui/viewmenu'] == 'main': parent = self.menu before = 'help' else: parent = self.menu.item('camera') before = parent.item('---') self.viewsMenu = menu.Menu('&Views',parent=parent,before=before) else: self.viewsMenu = None defviews = pf.cfg['gui/defviews'] views = [ v[0] for v in defviews ] viewicons = [ v[1] for v in defviews ] self.viewbtns = menu.ActionList( views,self.setView, menu=self.viewsMenu, toolbar=self.viewbar, icons = viewicons ) ## TESTING SAVE CURRENT VIEW ## self.saved_views = {} self.saved_views_name = utils.NameSequence('View') if self.viewsMenu: name = self.saved_views_name.next() self.menu.item('camera').addAction('Save View',self.saveView) # Restore previous pos/size pf.debug('Restore size/pos',pf.DEBUG.GUI) self.resize(*size) self.move(*pos) self.board.resize(*bdsize) pf.debug('Set Curdir',pf.DEBUG.GUI) self.setcurdir() # redirect standard/error output if option set # # TODO: we should redirect it to a buffer and # wait until GUI shown, then show in board # else show on stdout/err #self.board.redirect(pf.cfg['gui/redirect']) if pf.options.debuglevel: s = sizeReport(self,'DEBUG: Main:') + \ sizeReport(self.central,'DEBUG: Canvas:') + \ sizeReport(self.board,'DEBUG: Board:') pf.debug(s,pf.DEBUG.GUI) # Drawing lock self.drawwait = pf.cfg['draw/wait'] self.drawlock = drawlock.DrawLock() # Materials and Lights database self.materials = canvas.createMaterials() ## for m in self.materials: ## print self.materials[m] # Modeless child dialogs self.doc_dialog = None pf.debug('Done initializing GUI',pf.DEBUG.GUI) # Set up signal/slot connections self.signals = signals.Signals() self.signals.FULLSCREEN.connect(self.fullScreen) # Set up hot keys: hitting the key will emit the corresponding signal self.hotkey = { QtCore.Qt.Key_F2: self.signals.SAVE, QtCore.Qt.Key_F5: self.signals.FULLSCREEN, }