Esempio n. 1
0
class SimSetup(QDialog, Ui_SimSetupDialog): # before 050325 this class was called runSim
    """
    The "Run Dynamics" dialog class for setting up and launching a simulator run.
    """
    def __init__(self, win, part, previous_movie = None, suffix = ""):
        """
        use previous_movie (if passed) for default values,
        otherwise use the same ones last ok'd by user
        (whether or not that sim got aborted), or default values if that never happened in this session;
        on success or failure, make a new Movie and store it as self.movie
        """
        QDialog.__init__(self, win) # win is parent.
        self.setupUi(self)

        self.setWindowIcon(geticon('ui/border/RunDynamics.png'))

        self.whatsthis_btn.setIcon(
            geticon('ui/actions/Properties Manager/WhatsThis.png'))
        self.whatsthis_btn.setIconSize(QSize(22, 22))
        self.whatsthis_btn.setToolTip('Enter "What\'s This?" help mode')

        self.connect(self.whatsthis_btn,
                     SIGNAL("clicked()"),
                     QWhatsThis.enterWhatsThisMode)

        self.watch_motion_buttongroup = QButtonGroup()
        self.watch_motion_buttongroup.setExclusive(True)
        for obj in self.watch_motion_groupbox.children():
            if isinstance(obj, QAbstractButton):
                self.watch_motion_buttongroup.addButton(obj)
        self.connect(self.run_sim_btn,SIGNAL("clicked()"),self.createMoviePressed)
        self.connect(self.cancel_btn,SIGNAL("clicked()"),self.close)
        qt4todo('self.connect(self.watch_motion_groupbox,SIGNAL("toggled(bool)"),self.setEnabled) ???')
        self.watch_motion_groupbox.setEnabled(True)
        ## self.part = part
            # not yet needed, though in future we might display info
            # about this Part in the dialog, to avoid confusion
            # if it's not the main Part.
        connect_checkbox_with_boolean_pref(self.potential_energy_checkbox,
                                           Potential_energy_tracefile_prefs_key)

        connect_checkbox_with_boolean_pref(
            self.electrostaticsForDnaDuringDynamics_checkBox,
            electrostaticsForDnaDuringDynamics_prefs_key)

        self.assy = part.assy # used only for assy.filename
        self.suffix = suffix
        self.previous_movie = previous_movie or _stickyParams or Movie(self.assy) # used only for its parameter settings
            # note: as of bruce 060601 fixing bug 1840, previous_movie is no longer ever passed by caller.
        self.movie = Movie(self.assy) # public attr used by client code after we return; always a Movie even on failure.
            # (we need it here since no extra method runs on failure, tho that could probably be fixed)
            # bruce 050325 changes:
            # We make a new Movie here (but only when we return with success).
            # But we use default param settings from prior movie.
            # Caller should pass info about default filename (including uniqueness
            #  when on selection or in clipboard item) -- i.e. the suffix.
            # We should set the params and filename using a Movie method, or warn it we did so,
            # or do them in its init... not yet cleaned up. ###@@@
            # self.movie is now a public attribute.
            #bruce 050329 comment: couldn't we set .movie to None, until we learn we succeeded? ###e ###@@@
        self.setup()
        self.watch_motion_groupbox.setWhatsThis(
            """<b>Watch motion in real time</b>
            <p>
            Enables real time graphical updates during simulation runs.
            """)
        self.update_number_spinbox.setWhatsThis(
            """<b>Update every <i>n units.</u></b>
            <p>
            Specify how often to update the model during the simulation.
            This allows the user to monitor simulation results while the
            simulation is running.
            </p>""")
        self.update_units_combobox.setWhatsThis(
            """<b>Update every <i>n units.</u></b>
            <p>
            Specify how often to update the model during the simulation.
            This allows the user to monitor simulation results while the
            simulation is running.
            </p>""")
        self.update_every_rbtn.setWhatsThis(
            """<b>Update every <i>n units.</u></b>
            <p>
            Specify how often to update the model during the simulation.
            This allows the user to monitor simulation results while the
            simulation is running.</p>""")
        self.update_asap_rbtn.setWhatsThis(
            """<b>Update as fast as possible</b>
            <p>
            Update every 2 seconds, or faster (up to 20x/sec) if it doesn't
            slow down the simulation by more than 20%.
            </p>""")
        self.temperatureSpinBox.setWhatsThis(
            """<b>Temperature</b>
            <p>
            The temperature of the simulation in Kelvin
            (300 K = room temperature)</p>""")
        self.totalFramesSpinBox.setWhatsThis(
            """<b>Total frames</b>
            <p>
            The total number of (movie) frames to create for the simulation run.
            </p>""")
        self.stepsPerFrameDoubleSpinBox.setWhatsThis(
            """<b>Steps per frame</b>
            <p>
            The time duration between frames in femtoseconds.
            </p>""")
        self.setWhatsThis(
            """<b>Run Dynamics</b>
            <p>
            The is the main dialog for configuring and launching a
            Molecular Dynamics simulation run. Specify the simulation parameters
            and click <b>Run Simulation</b> to launch.</p>
            <p>
            <img source=\"ui/actions/Simulation/PlayMovie.png\"><br>
            The <b>Play Movie</b> command can be used to play back the
            simulation.
            </p>""")

        if not debug_pref("GROMACS: Enable for Run Dynamics", Choice_boolean_False,
                          prefs_key=True):
            # Hide the Simulation engine groupbox altogether.
            self.md_engine_groupbox.setHidden(True)

        self.exec_()

    def setup(self):
        self.movie.cancelled = True # We will assume the user will cancel
        #bruce 050324: fixed KnownBug item 27 by making these call setValue, not assign to it:
        # If the sim parameters change, they need to be updated in all places marked "SIMPARAMS"
        # Movie.__init__ (movie.py), toward the end
        # SimSetup.setup (SimSetup.py)
        # FakeMovie.__init (runSim.py)
        self.totalFramesSpinBox.setValue( self.previous_movie.totalFramesRequested )
        self.temperatureSpinBox.setValue( self.previous_movie.temp )
        self.stepsPerFrameDoubleSpinBox.setValue( self.previous_movie.stepsper / 10.0 )
#        self.timestepSB.setValue( self.previous_movie.timestep ) # Not supported in Alpha
        # new checkboxes for Alpha7, circa 060108
        #self.create_movie_file_checkbox.setChecked( self.previous_movie.create_movie_file )
            # whether to store movie file (see NFR/bug 1286). [bruce & mark 060108]
            # create_movie_file_checkbox removed for A7 (bug 1729). mark 060321

        ##e the following really belongs in the realtime_update_controller,
        # and the update_cond is not the best thing to set this from;
        # but we can leave it here, then let the realtime_update_controller override it if it knows how. [now it does]
        self.watch_motion_groupbox.setChecked( self.previous_movie.watch_motion ) # whether to move atoms in realtime

        try:
            #bruce 060705 use new common code, if it works
            from widgets.widget_controllers import realtime_update_controller
            self.ruc = realtime_update_controller(
                ( self.watch_motion_buttongroup, self.update_number_spinbox, self.update_units_combobox ),
                self.watch_motion_groupbox
                # no prefs key for checkbox
            )
            self.ruc.set_widgets_from_update_data( self.previous_movie._update_data ) # includes checkbox
        except:
            print_compact_traceback( "bug; reverting to older code in simsetep setup: ")
            if self.previous_movie._update_data:
                update_number, update_units, update_as_fast_as_possible_data, watchjunk = self.previous_movie._update_data
                self.watch_motion_groupbox.setChecked(watchjunk) ###060705
                self.watch_motion_groupbox.setButton( update_as_fast_as_possible_data)
                self.update_number_spinbox.setValue( update_number)
                self.update_units_combobox.setCurrentText( update_units)
                    #k let's hope this changes the current choice, not the popup menu item text for the current choice!
        return

    def createMoviePressed(self):
        """
        Creates a DPB (movie) file of the current part.
        [Actually only saves the params and filename which should be used
         by the client code (in writemovie?) to create that file.]
        The part does not have to be saved as an MMP file first, as it used to.
        """
        ###@@@ bruce 050324 comment: Not sure if/when user can rename the file.
        QDialog.accept(self)

        if self.simulation_engine_combobox.currentIndex() == 1:
            # GROMACS was selected as the simulation engine.
            #
            # NOTE: This code is just for demo and prototyping purposes - the
            # real approach will be architected and utilize plugins.
            #
            # Brian Helfrich 2007-04-06
            #
            from simulation.GROMACS.GROMACS import GROMACS
            gmx = GROMACS(self.assy.part)
            gmx.run("md")

        else:
            # NanoDynamics-1 was selected as the simulation engine
            #
            errorcode, partdir = self.assy.find_or_make_part_files_directory()

            self.movie.cancelled = False # This is the only way caller can tell we succeeded.
            self.movie.totalFramesRequested = self.totalFramesSpinBox.value()
            self.movie.temp = self.temperatureSpinBox.value()
            self.movie.stepsper = self.stepsPerFrameDoubleSpinBox.value() * 10.0
            self.movie.print_energy = self.potential_energy_checkbox.isChecked()
    #        self.movie.timestep = self.timestepSB.value() # Not supported in Alpha
            #self.movie.create_movie_file = self.create_movie_file_checkbox.isChecked()
                # removed for A7 (bug 1729). mark 060321
            self.movie.create_movie_file = True

            # compute update_data and update_cond, using new or old code
            try:
                # try new common code for this, bruce 060705
                ruc = self.ruc
                update_cond = ruc.get_update_cond_from_widgets()
                assert update_cond or (update_cond is False) ###@@@ remove when works, and all the others like this
                # note, if those widgets are connected to env.prefs, that's not handled here or in ruc;
                # I'm not sure if they are. Ideally we'd tell ruc the prefs_keys and have it handle that too,
                # perhaps making it a long-lived object (though that might not be necessary).
                update_data = ruc.get_update_data_from_widgets() # redundant, but we can remove it when ruc handles prefs
            except:
                print_compact_traceback("bug using realtime_update_controller in SimSetup, will use older code instead: ")
                    # this older code can be removed after A8 if we don't see that message
                #bruce 060530 use new watch_motion rate parameters
                self.movie.watch_motion = self.watch_motion_groupbox.isChecked() # [deprecated for setattr as of 060705]
                if env.debug():
                    print "debug fyi: sim setup watch_motion = %r" % (self.movie.watch_motion,)
                # This code works, but I'll try to replace it with calls to common code (above). [bruce 060705]
                # first grab them from the UI
                update_as_fast_as_possible_data = self.watch_motion_groupbox.selectedId() # 0 means yes, 1 means no (for now)
                    # ( or -1 means neither, but that's prevented by how the button group is set up, at least when it's enabled)
                update_as_fast_as_possible = (update_as_fast_as_possible_data != 1)
                update_number = self.update_number_spinbox.value() # 1, 2, etc (or perhaps 0??)
                update_units = str(self.update_units_combobox.currentText()) # 'frames', 'seconds', 'minutes', 'hours'
                # for sake of propogating them to the next sim run:
                update_data = update_number, update_units, update_as_fast_as_possible_data, self.movie.watch_motion
    ##                if env.debug():
    ##                    print "stored _update_data %r into movie %r" % (self.movie._update_data, self.movie)
    ##                    print "debug: self.watch_motion_groupbox.selectedId() = %r" % (update_as_fast_as_possible_data,)
    ##                    print "debug: self.update_number_spinbox.value() is %r" % self.update_number_spinbox.value() # e.g. 1
    ##                    print "debug: combox text is %r" % str(self.update_units_combobox.currentText()) # e.g. 'frames'
                # Now figure out what these user settings mean our realtime updating algorithm should be,
                # as a function to be used for deciding whether to update the 3D view when each new frame is received,
                # which takes as arguments the time since the last update finished (simtime), the time that update took (pytime),
                # and the number of frames since then (nframes, 1 or more), and returns a boolean for whether to draw this new frame.
                # Notes:
                # - The Qt progress update will be done independently of this, at most once per second (in runSim.py).
                # - The last frame we expect to receive will always be drawn. (This func may be called anyway in case it wants
                #   to do something else with the info like store it somewhere, or it may not (check runSim.py for details #k),
                #   but its return value will be ignored if it's called for the last frame.)
                # The details of these functions (and the UI feeding them) might be revised.

                # This code for setting update_cond is duplicated (inexactly) in Minimize_CommandRun.doMinimize()
                if update_as_fast_as_possible:
                    # This radiobutton might be misnamed; it really means "use the old code,
                    # i.e. not worse than 20% slowdown, with threshholds".
                    # It's also ambiguous -- does "fast" mean "fast progress"
                    # or "often" (which are opposites)? It sort of means "often".
                    update_cond = ( lambda simtime, pytime, nframes:
                                    simtime >= max(0.05, min(pytime * 4, 2.0)) )
                elif update_units == 'frames':
                    update_cond = ( lambda simtime, pytime, nframes, _nframes = update_number:  nframes >= _nframes )
                elif update_units == 'seconds':
                    update_cond = ( lambda simtime, pytime, nframes, _timelimit = update_number:  simtime + pytime >= _timelimit )
                elif update_units == 'minutes':
                    update_cond = ( lambda simtime, pytime, nframes, _timelimit = update_number * 60:  simtime + pytime >= _timelimit )
                elif update_units == 'hours':
                    update_cond = ( lambda simtime, pytime, nframes, _timelimit = update_number * 3600:  simtime + pytime >= _timelimit )
                else:
                    print "don't know how to set update_cond from (%r, %r)" % (update_number, update_units)
                    update_cond = None
                # revision in this old code, 060705:
                if not self.movie.watch_motion:
                    update_cond = False
                del self.movie.watch_motion # let getattr do it
            # now do this, however we got update_data and update_cond:
            self.movie._update_data = update_data # for propogating them to the next sim run
            self.movie.update_cond = update_cond # used this time
            # end of 060705 changes

            suffix = self.suffix
            tStamp = timeStamp()
            if self.assy.filename and not errorcode: # filename could be an MMP or PDB file.
                import shutil
                dir, fil = os.path.split(self.assy.filename)
                fil, ext = os.path.splitext(fil)
                self.movie.filename = os.path.join(partdir, fil + '.' + tStamp + suffix + '.dpb')
                self.movie.origfile = os.path.join(partdir, fil + '.' + tStamp + '.orig' + ext)
                shutil.copy(self.assy.filename, self.movie.origfile)
            else:
                self.movie.filename = os.path.join(self.assy.w.tmpFilePath, "Untitled.%s%s.dpb" % (tStamp, suffix))
                # Untitled parts usually do not have a filename
            #bruce 060601 fix bug 1840, also make params sticky across opening of new files
            global _stickyParams
            _stickyParams = FakeMovie(self.movie) # these will be used as default params next time, whether or not this gets aborted
            return

    pass # end of class SimSetup
Esempio n. 2
0
    def __init__(self, win, part, previous_movie = None, suffix = ""):
        """
        use previous_movie (if passed) for default values,
        otherwise use the same ones last ok'd by user
        (whether or not that sim got aborted), or default values if that never happened in this session;
        on success or failure, make a new Movie and store it as self.movie
        """
        QDialog.__init__(self, win) # win is parent.
        self.setupUi(self)

        self.setWindowIcon(geticon('ui/border/RunDynamics.png'))

        self.whatsthis_btn.setIcon(
            geticon('ui/actions/Properties Manager/WhatsThis.png'))
        self.whatsthis_btn.setIconSize(QSize(22, 22))
        self.whatsthis_btn.setToolTip('Enter "What\'s This?" help mode')

        self.connect(self.whatsthis_btn,
                     SIGNAL("clicked()"),
                     QWhatsThis.enterWhatsThisMode)

        self.watch_motion_buttongroup = QButtonGroup()
        self.watch_motion_buttongroup.setExclusive(True)
        for obj in self.watch_motion_groupbox.children():
            if isinstance(obj, QAbstractButton):
                self.watch_motion_buttongroup.addButton(obj)
        self.connect(self.run_sim_btn,SIGNAL("clicked()"),self.createMoviePressed)
        self.connect(self.cancel_btn,SIGNAL("clicked()"),self.close)
        qt4todo('self.connect(self.watch_motion_groupbox,SIGNAL("toggled(bool)"),self.setEnabled) ???')
        self.watch_motion_groupbox.setEnabled(True)
        ## self.part = part
            # not yet needed, though in future we might display info
            # about this Part in the dialog, to avoid confusion
            # if it's not the main Part.
        connect_checkbox_with_boolean_pref(self.potential_energy_checkbox,
                                           Potential_energy_tracefile_prefs_key)

        connect_checkbox_with_boolean_pref(
            self.electrostaticsForDnaDuringDynamics_checkBox,
            electrostaticsForDnaDuringDynamics_prefs_key)

        self.assy = part.assy # used only for assy.filename
        self.suffix = suffix
        self.previous_movie = previous_movie or _stickyParams or Movie(self.assy) # used only for its parameter settings
            # note: as of bruce 060601 fixing bug 1840, previous_movie is no longer ever passed by caller.
        self.movie = Movie(self.assy) # public attr used by client code after we return; always a Movie even on failure.
            # (we need it here since no extra method runs on failure, tho that could probably be fixed)
            # bruce 050325 changes:
            # We make a new Movie here (but only when we return with success).
            # But we use default param settings from prior movie.
            # Caller should pass info about default filename (including uniqueness
            #  when on selection or in clipboard item) -- i.e. the suffix.
            # We should set the params and filename using a Movie method, or warn it we did so,
            # or do them in its init... not yet cleaned up. ###@@@
            # self.movie is now a public attribute.
            #bruce 050329 comment: couldn't we set .movie to None, until we learn we succeeded? ###e ###@@@
        self.setup()
        self.watch_motion_groupbox.setWhatsThis(
            """<b>Watch motion in real time</b>
            <p>
            Enables real time graphical updates during simulation runs.
            """)
        self.update_number_spinbox.setWhatsThis(
            """<b>Update every <i>n units.</u></b>
            <p>
            Specify how often to update the model during the simulation.
            This allows the user to monitor simulation results while the
            simulation is running.
            </p>""")
        self.update_units_combobox.setWhatsThis(
            """<b>Update every <i>n units.</u></b>
            <p>
            Specify how often to update the model during the simulation.
            This allows the user to monitor simulation results while the
            simulation is running.
            </p>""")
        self.update_every_rbtn.setWhatsThis(
            """<b>Update every <i>n units.</u></b>
            <p>
            Specify how often to update the model during the simulation.
            This allows the user to monitor simulation results while the
            simulation is running.</p>""")
        self.update_asap_rbtn.setWhatsThis(
            """<b>Update as fast as possible</b>
            <p>
            Update every 2 seconds, or faster (up to 20x/sec) if it doesn't
            slow down the simulation by more than 20%.
            </p>""")
        self.temperatureSpinBox.setWhatsThis(
            """<b>Temperature</b>
            <p>
            The temperature of the simulation in Kelvin
            (300 K = room temperature)</p>""")
        self.totalFramesSpinBox.setWhatsThis(
            """<b>Total frames</b>
            <p>
            The total number of (movie) frames to create for the simulation run.
            </p>""")
        self.stepsPerFrameDoubleSpinBox.setWhatsThis(
            """<b>Steps per frame</b>
            <p>
            The time duration between frames in femtoseconds.
            </p>""")
        self.setWhatsThis(
            """<b>Run Dynamics</b>
            <p>
            The is the main dialog for configuring and launching a
            Molecular Dynamics simulation run. Specify the simulation parameters
            and click <b>Run Simulation</b> to launch.</p>
            <p>
            <img source=\"ui/actions/Simulation/PlayMovie.png\"><br>
            The <b>Play Movie</b> command can be used to play back the
            simulation.
            </p>""")

        if not debug_pref("GROMACS: Enable for Run Dynamics", Choice_boolean_False,
                          prefs_key=True):
            # Hide the Simulation engine groupbox altogether.
            self.md_engine_groupbox.setHidden(True)

        self.exec_()
class PM_ToolButtonGrid( PM_WidgetGrid ):
    """
    The PM_ToolButtonGrid widget provides a grid of tool buttons that function
    as an I{exclusive button group}.
    
    @see: B{PM_ElementChooser} for an example of how this is used.
    
    @todo: Fix button size issue (e.g. all buttons are sized 32 x 32).
    """
    
    buttonList       = []
    defaultCheckedId = -1    # -1 means no checked Id
    setAsDefault     = True
    
    
    def __init__(self, 
                 parentWidget, 
                 title        = '', 
                 buttonList   = [],
                 alignment    = None, 
                 label        = '',
                 labelColumn = 0,
                 spanWidth   = True,
                 checkedId    = -1, 
                 setAsDefault = False,   
                 isAutoRaise  = False,
                 isCheckable  = True
                 ):
        """
        Appends a PM_ToolButtonGrid widget to the bottom of I{parentWidget}, 
        the Property Manager Group box.
        
        @param parentWidget: The parent group box containing this widget.
        @type  parentWidget: PM_GroupBox
        
        @param title: The group box title.
        @type  title: str
        
        @param buttonList: A list of I{button info lists}. There is one button
                           info list for each button in the grid. The button
                           info list contains the following items:
                           1. Button Type - in this case its 'ToolButton'(str),
                           2. Button Id (int), 
                           3. Button text (str),
                           4. Button icon path (str),
                           5. Button tool tip (str),
                           6. Column (int), 
                           7. Row (int).
        @type  buttonList: list
        
        @param alignment:  The alignment of the toolbutton row in the parent 
                           groupbox. Based on its value,spacer items is added 
                           to the grid layout of the parent groupbox. 
        @type  alignment:  str
        
        @param label:      The label for the toolbutton row. If present, it is 
                           added to the same grid layout as the rest of the 
                           toolbuttons, in column number E{0}.
        @type  label:      str
        
        @param labelColumn: The column in the parentWidget's grid layout to which
                            this widget's label will be added. The labelColum
                            can only be E{0} or E{1}
        @type  labelColumn: int
        
        @param spanWidth: If True, the widget and its label will span the width
                      of the group box. Its label will appear directly above
                      the widget (unless the label is empty) and is left justified.
        @type  spanWidth: bool (default False)
                
        @param checkedId:  Checked button id in the button group. Default value
                           is -1 that implies no button is checked. 
        @type  checkedId:  int
        
        @param setAsDefault: If True, sets the I{checkedId} specified by the
                            user as the  default checked
        @type  setAsDefault: boolean
        """
                
        self.buttonGroup = QButtonGroup()
        self.buttonGroup.setExclusive(True)
        
        self.isAutoRaise = isAutoRaise    
        self.isCheckable = isCheckable
        self.buttonsById   = {}
        self.buttonsByText = {}
        
        if setAsDefault:
            self.setDefaultCheckedId(checkedId)
        
                    
        PM_WidgetGrid.__init__(self, 
                               parentWidget , 
                               title, 
                               buttonList, 
                               alignment,
                               label,
                               labelColumn,
                               spanWidth
                              ) 
        
            
    def _createWidgetUsingParameters(self, widgetParams):
        """
        Returns a tool button created using the parameters specified by the user
        
        @param widgetParams: A list of label parameters. This is a modified
                             using the original list returned 
                             by L{self.getWidgetInfoList}. The modified list
                             doesn't contain the row and column information.
        @type  widgetParams: list
        @see:  L{PM_WidgetGrid._createWidgetUsingParameters} (overrided in this
               method)
        @see:  L{PM_WidgetGrid.loadWidgets} which calls this method. 
        
        """               
        buttonFont = self.getButtonFont() 
        buttonParams = list(widgetParams) 
        
        button = self._createToolButton(buttonParams)
        
        buttonId = buttonParams[1]     
        
        if self.defaultCheckedId == buttonId:
            button.setChecked(True)
        button.setFont(buttonFont)
        button.setAutoRaise(self.isAutoRaise)
        button.setCheckable(self.isCheckable)
        self.buttonGroup.addButton(button, buttonId)
        
        self.buttonsById[buttonId]    = button
        self.buttonsByText[str(button.text())] = button     
        
        return button
                   
        
    def getButtonFont(self):
        """
        Returns the font for the tool buttons in the grid.
        
        @return: Button font.
        @rtype:  U{B{QFont}<http://doc.trolltech.com/4/qfont.html>}
        """
        # Font for tool buttons.
        buttonFont = QFont(self.font())
        buttonFont.setFamily(BUTTON_FONT)
        buttonFont.setPointSize(BUTTON_FONT_POINT_SIZE)
        buttonFont.setBold(BUTTON_FONT_BOLD)
        return buttonFont              

    def restoreDefault(self):
        """
        Restores the default checkedId.
        """
        if self.setAsDefault:
            for buttonInfo in self.buttonList:
                buttonId = buttonInfo[0]
                if buttonId == self.defaultCheckedId:
                    button = self.getButtonById(buttonId)
                    button.setChecked(True)
        return
    
    def setDefaultCheckedId(self, checkedId):
        """
        Sets the default checked id (button) to I{checkedId}. The current checked
        button is unchanged.
                      
        @param checkedId: The new default id for the tool button group.
        @type  checkedId: int
        """
        self.setAsDefault = True
        self.defaultCheckedId = checkedId
        
    def checkedButton(self):
        """
        Returns the tool button group's checked button, or E{0} if no button is
        checked.
        @return: Checked tool button or E{0}
        @rtype:  instance of QToolButton  or int
        """
        return self.buttonGroup.checkedButton()
        
    def checkedId(self):
        """
        Returns the id of the checkedButton(), or -1 if no button is checked.
        
        @return: The checked button Id
        @rtype:  int
        """
        return self.buttonGroup.checkedId()
    
    def getButtonByText(self, text):
        """
        Returns the button with its current text set to I{text}.
        
        @return: The button, or B{None} if no button was found.
        @rtype:  U{B{QToolButton}<http://doc.trolltech.com/4/qtoolbutton.html>}
        
        @note: If multiple buttons have the same text, only the last one is returned.
        """
        if self.buttonsByText.has_key(text):
            return self.buttonsByText[text]
        else:
            return None
        
    def getButtonById(self, buttonId):
        """
        Returns the button with the button id of I{buttonId}.
        
        return: The button, or B{None} if no button was found.
        rtype:  U{B{QToolButton}<http://doc.trolltech.com/4/qtoolbutton.html>}
        """
        if self.buttonsById.has_key(buttonId):
            return self.buttonsById[buttonId]
        else:
            return None
    
    def setButtonSize(self, width = 32, height = 32):
        """
        """
        for btn in self.buttonGroup.buttons():
            btn.setFixedSize(QSize(width, height))
 def __init__(self, 
              parentWidget, 
              title        = '', 
              buttonList   = [],
              alignment    = None, 
              label        = '',
              labelColumn = 0,
              spanWidth   = True,
              checkedId    = -1, 
              setAsDefault = False,   
              isAutoRaise  = False,
              isCheckable  = True
              ):
     """
     Appends a PM_ToolButtonGrid widget to the bottom of I{parentWidget}, 
     the Property Manager Group box.
     
     @param parentWidget: The parent group box containing this widget.
     @type  parentWidget: PM_GroupBox
     
     @param title: The group box title.
     @type  title: str
     
     @param buttonList: A list of I{button info lists}. There is one button
                        info list for each button in the grid. The button
                        info list contains the following items:
                        1. Button Type - in this case its 'ToolButton'(str),
                        2. Button Id (int), 
                        3. Button text (str),
                        4. Button icon path (str),
                        5. Button tool tip (str),
                        6. Column (int), 
                        7. Row (int).
     @type  buttonList: list
     
     @param alignment:  The alignment of the toolbutton row in the parent 
                        groupbox. Based on its value,spacer items is added 
                        to the grid layout of the parent groupbox. 
     @type  alignment:  str
     
     @param label:      The label for the toolbutton row. If present, it is 
                        added to the same grid layout as the rest of the 
                        toolbuttons, in column number E{0}.
     @type  label:      str
     
     @param labelColumn: The column in the parentWidget's grid layout to which
                         this widget's label will be added. The labelColum
                         can only be E{0} or E{1}
     @type  labelColumn: int
     
     @param spanWidth: If True, the widget and its label will span the width
                   of the group box. Its label will appear directly above
                   the widget (unless the label is empty) and is left justified.
     @type  spanWidth: bool (default False)
             
     @param checkedId:  Checked button id in the button group. Default value
                        is -1 that implies no button is checked. 
     @type  checkedId:  int
     
     @param setAsDefault: If True, sets the I{checkedId} specified by the
                         user as the  default checked
     @type  setAsDefault: boolean
     """
             
     self.buttonGroup = QButtonGroup()
     self.buttonGroup.setExclusive(True)
     
     self.isAutoRaise = isAutoRaise    
     self.isCheckable = isCheckable
     self.buttonsById   = {}
     self.buttonsByText = {}
     
     if setAsDefault:
         self.setDefaultCheckedId(checkedId)
     
                 
     PM_WidgetGrid.__init__(self, 
                            parentWidget , 
                            title, 
                            buttonList, 
                            alignment,
                            label,
                            labelColumn,
                            spanWidth
                           ) 
Esempio n. 5
0
class PM_RadioButtonList( PM_GroupBox ):
    """
    The PM_RadioButtonList widget provides a list of radio buttons that function
    as an I{exclusive button group}.
    """
    
    buttonList       = []
    defaultCheckedId = -1    # -1 means no checked Id
    setAsDefault     = True
    labelWidget      = None
    
    def __init__(self, 
                 parentWidget, 
                 title        = '', 
                 label = '',
                 labelColumn = 0,
                 buttonList   = [],
                 checkedId    = -1,
                 setAsDefault = False, 
                 spanWidth   = True, 
                 borders = True
                 ):
        """
        Appends a PM_RadioButtonList widget to the bottom of I{parentWidget}, 
        the Property Manager dialog or group box.
        
        @param parentWidget: The parent group box containing this widget.
        @type  parentWidget: PM_GroupBox or PM_Dialog
        
        @param title: The group box title.
        @type  title: str
        
        @param label:      The label for the coordinate spinbox.
        @type  label:      str
        
        @param labelColumn: The column in the parentWidget's grid layout to 
                            which this widget's label will be added. 
                            The labelColum can only be E{0} or E{1}
        @type  labelColumn: int
                
        
        @param buttonList: A list of I{button info lists}. There is one button
                           info list for each radio button in the list. The 
                           button info list contains the following three items:
                           1). Button Id (int), 
                           2). Button text (str),
                           3). Button tool tip (str).
        @type  buttonList: list
        
        @param spanWidth: If True, the widget and its label will span the width
                         of the group box. Its label will appear directly above
                         the widget (unless the label is empty) and is left 
                         justified.
        @type  spanWidth: bool (default False)
        
        
        @param borders: If true (default), this widget will have borders displayed. 
                        otherwise the won't be any outside borders around the 
                        set of radio buttons this class provides
        @type borders: boolean
        """
        
        # Intializing label, labelColumn etc is needed before doing 
        # PM_GroupBox.__init__. This is done so that 
        # self.parentWidget.addPmWidget(self) done at the end of __init__
        # works properly. 
        # 'self.parentWidget.addPmWidget(self)' is done to avoid a bug where a 
        # groupbox is always appended as the 'last widget' when its 
        # parentWidget is also a groupbox. This is due to other PM widgets 
        #(e.g. PM_PushButton)add themselves to their parent widget in their 
        #__init__ using self.parentWidget.addPmWidget(self). So doing the
        #same thing here. More general fix is needed in PM_GroupBox code
        # --Ninad 2007-11-14 (comment copied from PM_coordinateSpinBoxes)
        self.label = label
        self.labelColumn = labelColumn
        self.spanWidth = spanWidth
        
        if label: # Create this widget's QLabel.
            self.labelWidget = QLabel()
            self.labelWidget.setText(label)
            
        
        PM_GroupBox.__init__(self, parentWidget, title)
        
        # These are needed to properly maintain the height of the grid if 
        # all buttons in a row are hidden via hide().
        self.vBoxLayout.setMargin(0)
        self.vBoxLayout.setSpacing(0)
        
        self.buttonGroup = QButtonGroup()
        self.buttonGroup.setExclusive(True)
        
        self.parentWidget = parentWidget
        self.buttonList   = buttonList
        
        if setAsDefault:
            self.setDefaultCheckedId(checkedId)
        
        self.buttonsById   = {}
        self.buttonsByText = {}
            
        # Create radio button list from button info.
        for buttonInfo in buttonList:
            buttonId       = buttonInfo[0]
            buttonText     = buttonInfo[1]
            buttonToolTip  = buttonInfo[2]
            
            button = QRadioButton(self)
            
            button.setText(buttonText)
            button.setToolTip(buttonToolTip) # Not working.
            button.setCheckable(True)
            if checkedId == buttonId:
                button.setChecked(True)
            self.buttonGroup.addButton(button, buttonId)
            self.vBoxLayout.addWidget(button)
            
            self.buttonsById[buttonId]    = button
            self.buttonsByText[buttonText] = button
            
        if isinstance(self.parentWidget, PM_GroupBox):
            self.parentWidget.addPmWidget(self)
        else:   
            #@@ Should self be added to self.parentWidget's widgetList?
            #don't know. Retaining old code -- Ninad 2008-06-23
            self._widgetList.append(self)            
            self._rowCount += 1
        
        if not borders:
            #reset the style sheet so that there are no borders around the 
            #radio button set this class provides. 
            self.setStyleSheet(self._getAlternateStyleSheet())
        
    def restoreDefault(self):
        """
        Restores the default checkedId.
        """
        if self.setAsDefault:
            for buttonInfo in self.buttonList:
                buttonId = buttonInfo[0]
                if buttonId == self.defaultCheckedId:
                    button = self.getButtonById(buttonId)
                    button.setChecked(True)
        return
    
    def setDefaultCheckedId(self, checkedId):
        """
        Sets the default checked id (button) to I{checkedId}. The current checked
        button is unchanged.
                      
        @param checkedId: The new default id for the tool button group.
        @type  checkedId: int
        """
        self.setAsDefault = True
        self.defaultCheckedId = checkedId
        
    def checkedButton(self):
        """
        Returns the tool button group's checked button, or 0 if no buttons are
        checked.
        """
        return self.buttonGroup.checkedButton()
        
    def checkedId(self):
        """
        Returns the id of the checkedButton(), or -1 if no button is checked.
        """
        return self.buttonGroup.checkedId()
    
    def getButtonByText(self, text):
        """
        Returns the button with its current text set to I{text}.
        """
        if self.buttonsByText.has_key(text):
            return self.buttonsByText[text]
        else:
            return None
        
    def getButtonById(self, buttonId):
        """
        Returns the button with the button id of I{buttonId}.
        """
        if self.buttonsById.has_key(buttonId):
            return self.buttonsById[buttonId]
        else:
            return None
              
        
    def _getAlternateStyleSheet(self):
        """
        Return the style sheet for the groupbox. This sets the following 
        properties only:
         - border style
         - border width
         - border color
         - border radius (on corners)
        @see: L{PM_GroupBox._getStyleSheet} (overrided here)
        """
        
        styleSheet = "QGroupBox {border-style:hidden;\
        border-width: 0px;\
        border-color: "";\
        border-radius: 0px;\
        min-width: 10em; }" 
   
        return styleSheet
            
# End of PM_RadioButtonList ############################
Esempio n. 6
0
class Ui_CommandToolbar( QWidget ):
    """ 
    This provides most of the User Interface for the command toolbar 
    called in CommandToolbar class.
    """
    def __init__(self, win):
        """
        Constructor for class Ui_CommandToolbar.
        
        @param win: Mainwindow object
        @type  win: L{MWsemantics}
        """
        QWidget.__init__(self)
        
        self.win = win
    
    def setupUi(self):
        """
        Setup the UI for the command toolbar.
        """
        #ninad 070123 : It's important to set the Vertical size policy of the 
        # cmd toolbar widget. otherwise the flyout QToolbar messes up the 
        #layout (makes the command toolbar twice as big) 
        #I have set the vertical policy as fixed. Works fine. There are some 
        # MainWindow resizing problems for but those are not due to this 
        #size policy AFAIK        
        self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
                
        layout_cmdtoolbar = QHBoxLayout(self)
        layout_cmdtoolbar.setMargin(2)
        layout_cmdtoolbar.setSpacing(2)
        
        #See comment at the top for details about this flag
        if DEFINE_CONTROL_AREA_AS_A_QWIDGET:
            self.cmdToolbarControlArea = QWidget(self)    
        else:
            self.cmdToolbarControlArea = QToolBar_WikiHelp(self)
            
        self.cmdToolbarControlArea.setAutoFillBackground(True)
                
        self.ctrlAreaPalette = self.getCmdMgrCtrlAreaPalette()  
        self.cmdToolbarControlArea.setPalette(self.ctrlAreaPalette)
                
        self.cmdToolbarControlArea.setMinimumHeight(62)
        self.cmdToolbarControlArea.setMinimumWidth(380)
        self.cmdToolbarControlArea.setSizePolicy(QSizePolicy.Fixed, 
                                                 QSizePolicy.Fixed)  
        
        #See comment at the top for details about this flag
        if DEFINE_CONTROL_AREA_AS_A_QWIDGET:
            layout_controlArea = QHBoxLayout(self.cmdToolbarControlArea)
            layout_controlArea.setMargin(0)
            layout_controlArea.setSpacing(0)
        
        self.cmdButtonGroup = QButtonGroup()    
        btn_index = 0
        
        for name in ('Build', 'Insert', 'Tools', 'Move', 'Simulation'):
            btn = QToolButton(self.cmdToolbarControlArea)           
            btn.setObjectName(name)
            btn.setMinimumWidth(75)
            btn.setMaximumWidth(75)
            btn.setMinimumHeight(62)
            btn.setAutoRaise(True)
            btn.setCheckable(True)
            btn.setAutoExclusive(True)
            iconpath = "ui/actions/Command Toolbar/ControlArea/" + name + ".png"
            btn.setIcon(geticon(iconpath))
            btn.setIconSize(QSize(22, 22))
            btn.setText(name)
            btn.setToolButtonStyle(Qt.ToolButtonTextUnderIcon)
            btn.setPalette(self.ctrlAreaPalette)
            self.cmdButtonGroup.addButton(btn, btn_index)
            btn_index += 1        
            #See comment at the top for details about this flag
            if DEFINE_CONTROL_AREA_AS_A_QWIDGET:
                layout_controlArea.addWidget(btn)
            else:
                self.cmdToolbarControlArea.layout().addWidget(btn)                
                #following has issues. so not adding widget directly to the 
                #toolbar. (instead adding it in its layout)-- ninad 070124
                ##self.cmdToolbarControlArea.addWidget(btn)      
        
        layout_cmdtoolbar.addWidget(self.cmdToolbarControlArea) 
        
        #Flyout Toolbar in the command toolbar  
        self.flyoutToolBar = FlyoutToolBar(self)
        
        layout_cmdtoolbar.addWidget(self.flyoutToolBar)   
        
        #ninad 070116: Define a spacer item. It will have the exact geometry 
        # as that of the flyout toolbar. it is added to the command toolbar 
        # layout only when the Flyout Toolbar is hidden. It is required
        # to keep the 'Control Area' widget fixed in its place (otherwise, 
        #after hiding the flyout toolbar, the layout adjusts the position of 
        #remaining widget items) 
        
        self.spacerItem = QSpacerItem(0, 
                                      0, 
                                      QtGui.QSizePolicy.Expanding, 
                                      QtGui.QSizePolicy.Minimum)
        self.spacerItem.setGeometry = self.flyoutToolBar.geometry()
        
        for btn in self.cmdButtonGroup.buttons():
            if str(btn.objectName()) == 'Build':
                btn.setMenu(self.win.buildStructuresMenu)
                btn.setPopupMode(QToolButton.MenuButtonPopup)
                btn.setToolTip("Build Commands")
                whatsThisTextForCommandToolbarBuildButton(btn)
            if str(btn.objectName()) == 'Insert':
                btn.setMenu(self.win.insertMenu)
                btn.setPopupMode(QToolButton.MenuButtonPopup)
                btn.setToolTip("Insert Commands")
                whatsThisTextForCommandToolbarInsertButton(btn)
            if str(btn.objectName()) == 'Tools':
                #fyi: cmd stands for 'command toolbar' - ninad070406
                self.win.cmdToolsMenu = QtGui.QMenu(self.win)
                self.win.cmdToolsMenu.addAction(self.win.toolsExtrudeAction) 
                self.win.cmdToolsMenu.addAction(self.win.toolsFuseChunksAction)
                self.win.cmdToolsMenu.addSeparator()
                self.win.cmdToolsMenu.addAction(self.win.modifyMergeAction)
                self.win.cmdToolsMenu.addAction(self.win.modifyMirrorAction)
                self.win.cmdToolsMenu.addAction(self.win.modifyInvertAction)
                self.win.cmdToolsMenu.addAction(self.win.modifyStretchAction)
                btn.setMenu(self.win.cmdToolsMenu)
                btn.setPopupMode(QToolButton.MenuButtonPopup)
                btn.setToolTip("Tools")
                whatsThisTextForCommandToolbarToolsButton(btn)
            if str(btn.objectName()) == 'Move':
                self.win.moveMenu = QtGui.QMenu(self.win)
                self.win.moveMenu.addAction(self.win.toolsMoveMoleculeAction)
                self.win.moveMenu.addAction(self.win.rotateComponentsAction)
                self.win.moveMenu.addSeparator()
                self.win.moveMenu.addAction(
                    self.win.modifyAlignCommonAxisAction)
                ##self.win.moveMenu.addAction(\
                ##    self.win.modifyCenterCommonAxisAction)
                btn.setMenu(self.win.moveMenu)
                btn.setPopupMode(QToolButton.MenuButtonPopup)
                btn.setToolTip("Move Commands")
                whatsThisTextForCommandToolbarMoveButton(btn)
            if str(btn.objectName()) == 'Dimension':
                btn.setMenu(self.win.dimensionsMenu)
                btn.setPopupMode(QToolButton.MenuButtonPopup)
                btn.setToolTip("Dimensioning Commands")
            if str(btn.objectName()) == 'Simulation':
                btn.setMenu(self.win.simulationMenu)
                btn.setPopupMode(QToolButton.MenuButtonPopup)
                btn.setToolTip("Simulation Commands")
                whatsThisTextForCommandToolbarSimulationButton(btn)
            
            # Convert all "img" tags in the button's "What's This" text 
            # into abs paths (from their original rel paths).
            # Partially fixes bug 2943. --mark 2008-12-07
            # [bruce 081209 revised this -- removed mac = False]
            fix_QAction_whatsthis(btn)
        return
    
    def truncateText(self, text, length = 12, truncateSymbol = '...'):
        """
        Truncates the tooltip text with the given truncation symbol
        (three dots) in the case 
        """
            
        #ninad 070201 This is a temporary fix. Ideally it should show the whole
        #text in the  toolbutton. But there are some layout / size policy 
        #problems because of which the toolbar height increases after you print
        #tooltip text on two or more lines. (undesirable effect) 
            
        if not text:
            print "no text to truncate. Returning"
            return 
        
        truncatedLength  = length - len(truncateSymbol)
        
        if len(text) > length:
            return text[:truncatedLength] + truncateSymbol
        else:
            return text
        
                
                        
    def wrapToolButtonText(self, text):
        """
        Add a newline character at the end of each word in the toolbutton text
        """
        #ninad 070126 QToolButton lacks this method. This is not really a 
        #'word wrap' but OK for now. 
        
        #@@@ ninad 070126. Not calling this method as it is creating an annoying
        #resizing problem in the Command toolbar layout. Possible solution is 
        #to add a spacer item in a vbox layout to the command toolbar layout
        
        stringlist = text.split(" ", QString.SkipEmptyParts)
        text2 = QString()
        if len(stringlist) > 1:
            for l in stringlist:
                text2.append(l)
                text2.append("\n")
            return text2
                
        return None
    
    ##==================================================================##
    #color palettes (UI stuff) for different command toolbar areas
   
    def getCmdMgrCtrlAreaPalette(self): 
        """ Return a palette for Command Manager control area 
        (Palette for Tool Buttons in command toolbar control area)
        """
        #See comment at the top for details about this flag
        if DEFINE_CONTROL_AREA_AS_A_QWIDGET:
            return getPalette(None,
                              QPalette.Window,
                              cmdTbarCntrlAreaBtnColor
                              )
        else:
            return getPalette(None,
                              QPalette.Button,
                              cmdTbarCntrlAreaBtnColor
                              )
            
    
    def getCmdMgrSubCtrlAreaPalette(self):
        """ Return a palette for Command Manager sub control area 
        (Palette for Tool Buttons in command toolbar sub control area)
        """
        #Define the color role. Make sure to apply color to QPalette.Button 
        #instead of QPalette.Window as it is a QToolBar. - ninad 20070619
        
        return getPalette(None,
                          QPalette.Button,
                          cmdTbarSubCntrlAreaBtnColor
                          )
    
    def getCmdMgrCommandAreaPalette(self):
        """ Return a palette for Command Manager 'Commands area'(flyout toolbar)
        (Palette for Tool Buttons in command toolbar command area)
        """
        return self.flyoutToolBar.getPalette()
class PM_RadioButtonList(PM_GroupBox):
    """
    The PM_RadioButtonList widget provides a list of radio buttons that function
    as an I{exclusive button group}.
    """

    buttonList = []
    defaultCheckedId = -1  # -1 means no checked Id
    setAsDefault = True
    labelWidget = None

    def __init__(self,
                 parentWidget,
                 title='',
                 label='',
                 labelColumn=0,
                 buttonList=[],
                 checkedId=-1,
                 setAsDefault=False,
                 spanWidth=True,
                 borders=True):
        """
        Appends a PM_RadioButtonList widget to the bottom of I{parentWidget}, 
        the Property Manager dialog or group box.
        
        @param parentWidget: The parent group box containing this widget.
        @type  parentWidget: PM_GroupBox or PM_Dialog
        
        @param title: The group box title.
        @type  title: str
        
        @param label:      The label for the coordinate spinbox.
        @type  label:      str
        
        @param labelColumn: The column in the parentWidget's grid layout to 
                            which this widget's label will be added. 
                            The labelColum can only be E{0} or E{1}
        @type  labelColumn: int
                
        
        @param buttonList: A list of I{button info lists}. There is one button
                           info list for each radio button in the list. The 
                           button info list contains the following three items:
                           1). Button Id (int), 
                           2). Button text (str),
                           3). Button tool tip (str).
        @type  buttonList: list
        
        @param spanWidth: If True, the widget and its label will span the width
                         of the group box. Its label will appear directly above
                         the widget (unless the label is empty) and is left 
                         justified.
        @type  spanWidth: bool (default False)
        
        
        @param borders: If true (default), this widget will have borders displayed. 
                        otherwise the won't be any outside borders around the 
                        set of radio buttons this class provides
        @type borders: boolean
        """

        # Intializing label, labelColumn etc is needed before doing
        # PM_GroupBox.__init__. This is done so that
        # self.parentWidget.addPmWidget(self) done at the end of __init__
        # works properly.
        # 'self.parentWidget.addPmWidget(self)' is done to avoid a bug where a
        # groupbox is always appended as the 'last widget' when its
        # parentWidget is also a groupbox. This is due to other PM widgets
        #(e.g. PM_PushButton)add themselves to their parent widget in their
        #__init__ using self.parentWidget.addPmWidget(self). So doing the
        #same thing here. More general fix is needed in PM_GroupBox code
        # --Ninad 2007-11-14 (comment copied from PM_coordinateSpinBoxes)
        self.label = label
        self.labelColumn = labelColumn
        self.spanWidth = spanWidth

        if label:  # Create this widget's QLabel.
            self.labelWidget = QLabel()
            self.labelWidget.setText(label)

        PM_GroupBox.__init__(self, parentWidget, title)

        # These are needed to properly maintain the height of the grid if
        # all buttons in a row are hidden via hide().
        self.vBoxLayout.setMargin(0)
        self.vBoxLayout.setSpacing(0)

        self.buttonGroup = QButtonGroup()
        self.buttonGroup.setExclusive(True)

        self.parentWidget = parentWidget
        self.buttonList = buttonList

        if setAsDefault:
            self.setDefaultCheckedId(checkedId)

        self.buttonsById = {}
        self.buttonsByText = {}

        # Create radio button list from button info.
        for buttonInfo in buttonList:
            buttonId = buttonInfo[0]
            buttonText = buttonInfo[1]
            buttonToolTip = buttonInfo[2]

            button = QRadioButton(self)

            button.setText(buttonText)
            button.setToolTip(buttonToolTip)  # Not working.
            button.setCheckable(True)
            if checkedId == buttonId:
                button.setChecked(True)
            self.buttonGroup.addButton(button, buttonId)
            self.vBoxLayout.addWidget(button)

            self.buttonsById[buttonId] = button
            self.buttonsByText[buttonText] = button

        if isinstance(self.parentWidget, PM_GroupBox):
            self.parentWidget.addPmWidget(self)
        else:
            #@@ Should self be added to self.parentWidget's widgetList?
            #don't know. Retaining old code -- Ninad 2008-06-23
            self._widgetList.append(self)
            self._rowCount += 1

        if not borders:
            #reset the style sheet so that there are no borders around the
            #radio button set this class provides.
            self.setStyleSheet(self._getAlternateStyleSheet())

    def restoreDefault(self):
        """
        Restores the default checkedId.
        """
        if self.setAsDefault:
            for buttonInfo in self.buttonList:
                buttonId = buttonInfo[0]
                if buttonId == self.defaultCheckedId:
                    button = self.getButtonById(buttonId)
                    button.setChecked(True)
        return

    def setDefaultCheckedId(self, checkedId):
        """
        Sets the default checked id (button) to I{checkedId}. The current checked
        button is unchanged.
                      
        @param checkedId: The new default id for the tool button group.
        @type  checkedId: int
        """
        self.setAsDefault = True
        self.defaultCheckedId = checkedId

    def checkedButton(self):
        """
        Returns the tool button group's checked button, or 0 if no buttons are
        checked.
        """
        return self.buttonGroup.checkedButton()

    def checkedId(self):
        """
        Returns the id of the checkedButton(), or -1 if no button is checked.
        """
        return self.buttonGroup.checkedId()

    def getButtonByText(self, text):
        """
        Returns the button with its current text set to I{text}.
        """
        if self.buttonsByText.has_key(text):
            return self.buttonsByText[text]
        else:
            return None

    def getButtonById(self, buttonId):
        """
        Returns the button with the button id of I{buttonId}.
        """
        if self.buttonsById.has_key(buttonId):
            return self.buttonsById[buttonId]
        else:
            return None

    def _getAlternateStyleSheet(self):
        """
        Return the style sheet for the groupbox. This sets the following 
        properties only:
         - border style
         - border width
         - border color
         - border radius (on corners)
        @see: L{PM_GroupBox._getStyleSheet} (overrided here)
        """

        styleSheet = "QGroupBox {border-style:hidden;\
        border-width: 0px;\
        border-color: " ";\
        border-radius: 0px;\
        min-width: 10em; }"

        return styleSheet


# End of PM_RadioButtonList ############################
Esempio n. 8
0
class MinimizeEnergyProp(QDialog, Ui_MinimizeEnergyPropDialog):

    cmdname = greenmsg("Minimize Energy: ") # WARNING: self.cmdname might be used by one of the superclasses
    plain_cmdname = "Minimize Energy"
    #@sponsor_keyword = None

    def __init__(self, win):
        QDialog.__init__(self, win)  # win is parent.
        self.setupUi(self)
        self.watch_motion_buttongroup = QButtonGroup()
        self.watch_motion_buttongroup.setExclusive(True)
        for obj in self.watch_motion_groupbox.children():
            if isinstance(obj, QAbstractButton):
                self.watch_motion_buttongroup.addButton(obj)

        #fix some icon problems
        self.setWindowIcon(
            geticon('ui/border/MinimizeEnergy.png'))

        self.connect(self.cancel_btn,
                     SIGNAL("clicked()"),
                     self.cancel_btn_clicked)
        self.connect(self.ok_btn,
                     SIGNAL("clicked()"),
                     self.ok_btn_clicked)
        self.connect(self.restore_btn,
                     SIGNAL("clicked()"),
                     self.restore_defaults_btn_clicked)

        self.whatsthis_btn.setIcon(
            geticon('ui/actions/Properties Manager/WhatsThis.png'))
        self.whatsthis_btn.setIconSize(QSize(22, 22))
        self.whatsthis_btn.setToolTip('Enter "What\'s This?" help mode')

        self.connect(self.whatsthis_btn,
                     SIGNAL("clicked()"),
                     QWhatsThis.enterWhatsThisMode)

        connect_checkbox_with_boolean_pref(
            self.electrostaticsForDnaDuringMinimize_checkBox,
            electrostaticsForDnaDuringMinimize_prefs_key)

        connect_checkbox_with_boolean_pref(
            self.enableNeighborSearching_check_box,
            neighborSearchingInGromacs_prefs_key)

        self.connect(self.minimize_engine_combobox, SIGNAL("activated(int)"), self.update_minimize_engine)

        self.minimize_engine_combobox.setCurrentIndex(
            env.prefs[Minimize_minimizationEngine_prefs_key])

        self.connect(self.endRmsDoubleSpinBox, SIGNAL("valueChanged(double)"), self.changeEndRms)
        self.connect(self.endMaxDoubleSpinBox, SIGNAL("valueChanged(double)"), self.changeEndMax)
        self.connect(self.cutoverRmsDoubleSpinBox, SIGNAL("valueChanged(double)"), self.changeCutoverRms)
        self.connect(self.cutoverMaxDoubleSpinBox, SIGNAL("valueChanged(double)"), self.changeCutoverMax)

        self.endRmsDoubleSpinBox.setSpecialValueText("Automatic")
        self.endMaxDoubleSpinBox.setSpecialValueText("Automatic")
        self.cutoverRmsDoubleSpinBox.setSpecialValueText("Automatic")
        self.cutoverMaxDoubleSpinBox.setSpecialValueText("Automatic")

        self.win = win
        self.previousParams = None
        self.setup_ruc()
        self.seltype = 'All'
        self.minimize_selection_enabled = True #bruce 080513

        # Assign "What's This" text for all widgets.
        from commands.MinimizeEnergy.WhatsThisText_for_MinimizeEnergyDialog import whatsThis_MinimizeEnergyDialog
        whatsThis_MinimizeEnergyDialog(self)

        self.update_widgets() # to make sure self attrs are set
        return

    def setup_ruc(self):
        """
        #doc
        """
        #bruce 060705 use new common code, if it works
        from widgets.widget_controllers import realtime_update_controller
        self.ruc = realtime_update_controller(
            #( self.update_btngrp, self.update_number_spinbox, self.update_units_combobox ),
            ( self.watch_motion_buttongroup, self.update_number_spinbox, self.update_units_combobox ),
            self.watch_motion_groupbox,
            Minimize_watchRealtimeMinimization_prefs_key
        )
        ## can't do this yet: self.ruc.set_widgets_from_update_data( self.previous_movie._update_data ) # includes checkbox
        # for A8, only the checkbox will be persistent; the others will be sticky only because the dialog is not remade at runtime
        return

    def setup(self):
        """
        Setup and show the Minimize Energy dialog.
        """
        # Get widget parameters, update widgets, save previous parameters (for Restore Defaults) and show dialog.

        # set up default & enabled choices for Minimize Selection vs. Min All
        # (details revised to fix nfr bug 2848, item 1, bruce 080513;
        #  prior code used selection nonempty to determine default seltype)
        selection = self.win.assy.selection_from_glpane()
            # a compact rep of the currently selected subset of the Part's stuff
        if selection.nonempty():
            ## self.seltype = 'Sel'
            self.seltype = 'All'
            self.minimize_selection_enabled = True
        else:
            self.seltype = 'All'
            self.minimize_selection_enabled = False
        self.update_widgets() # only the convergence criteria, for A8, plus All/Sel command from self.seltype
        self.previousParams = self.gather_parameters() # only used in case Cancel wants to restore them; only conv crit for A8
        self.exec_() # Show dialog as a modal dialog.
        return

    def gather_parameters(self): ###e should perhaps include update_data from ruc (not sure it's good) -- but no time for A8
        """
        Returns a tuple with the current parameter values from the widgets. Also sets those in env.prefs.
        Doesn't do anything about self.seltype, since that is a choice of command, not a parameter for a command.
        """
        return tuple([env.prefs[key] for key in (endRMS_prefs_key, endMax_prefs_key, cutoverRMS_prefs_key, cutoverMax_prefs_key)])

    def update_widgets(self, update_seltype = True):
        """
        Update the widgets using the current env.prefs values and self attrs.
        """
        if update_seltype:
            if self.seltype == 'All':
                self.minimize_all_rbtn.setChecked(1)
            else:
                # note: this case might no longer ever happen after today's
                # change, but I'm not sure. Doesn't matter. [bruce 080513]
                self.minimize_sel_rbtn.setChecked(1)
            self.minimize_sel_rbtn.setEnabled( self.minimize_selection_enabled)
            pass

        # Convergence Criteria groupbox
        # WARNING: some of the following code is mostly duplicated by Preferences code
        self.endrms = get_pref_or_optval(endRMS_prefs_key, -1.0, 0.0)
        self.endRmsDoubleSpinBox.setValue(self.endrms)

        self.endmax = get_pref_or_optval(endMax_prefs_key, -1.0, 0.0)
        self.endMaxDoubleSpinBox.setValue(self.endmax)

        self.cutoverrms = get_pref_or_optval(cutoverRMS_prefs_key, -1.0, 0.0)
        self.cutoverRmsDoubleSpinBox.setValue(self.cutoverrms)

        self.cutovermax = get_pref_or_optval(cutoverMax_prefs_key, -1.0, 0.0)
        self.cutoverMaxDoubleSpinBox.setValue(self.cutovermax)

        self.update_minimize_engine()

        ###e also watch in realtime prefs for this -- no, thats in another method for now
        return

    def ok_btn_clicked(self):
        """
        Slot for OK button
        """
        QDialog.accept(self)
        if env.debug():
            print "ok"
        self.gather_parameters()
        ### kluge: has side effect on env.prefs
        # (should we pass these as arg to Minimize_CommandRun rather than thru env.prefs??)
        if debug_flags.atom_debug:
            print "debug: reloading runSim & sim_commandruns on each use, for development"
            import simulation.runSim as runSim
            reload_once_per_event(runSim)
                # bug: only works some of the times runSim.py is modified,
                # don't know why; might be that sim_commandruns.py
                # also needs to be modified, but touching them both
                # doesn't seem to work consistently either.
                # [bruce 080520]
            import simulation.sim_commandruns as sim_commandruns
            reload_once_per_event(sim_commandruns)
        from simulation.sim_commandruns import Minimize_CommandRun
        # do this in gather?
        if self.minimize_all_rbtn.isChecked():
            self.seltype = 'All'
            seltype_name = "All"
        else:
            self.seltype = 'Sel'
            seltype_name = "Selection"
        self.win.assy.current_command_info(cmdname = self.plain_cmdname + " (%s)" % seltype_name) # cmdname for Undo

        update_cond = self.ruc.get_update_cond_from_widgets()
        engine = self.minimize_engine_combobox.currentIndex()
        env.prefs[Minimize_minimizationEngine_prefs_key] = engine
        cmdrun = Minimize_CommandRun( self.win, self.seltype, type = 'Minimize', update_cond = update_cond, engine = engine)
        cmdrun.run()
        return

    def cancel_btn_clicked(self):
        """
        Slot for Cancel button
        """
        if env.debug():
            print "cancel"
        # restore values we grabbed on entry.
        for key,val in zip((endRMS_prefs_key, endMax_prefs_key, cutoverRMS_prefs_key, cutoverMax_prefs_key), self.previousParams):
            env.prefs[key] = val
        self.update_widgets(update_seltype = False) #k might not matter since we're about to hide it, but can't hurt
        QDialog.reject(self)
        return

    def restore_defaults_btn_clicked(self):
        """
        Slot for Restore Defaults button
        """
        # restore factory defaults # for A8, only for conv crit, not for watch motion settings
        self.minimize_engine_combobox.setCurrentIndex(0) # ND1
        env.prefs.restore_defaults([endRMS_prefs_key, endMax_prefs_key, cutoverRMS_prefs_key, cutoverMax_prefs_key])
        self.update_widgets(update_seltype = False)
        return
    # Dialog slots

    def update_minimize_engine(self, ignoredIndex = 0):
        """
        Slot for the Minimize Engine comobox.
        """

        engineIndex = self.minimize_engine_combobox.currentIndex()

        if engineIndex == 0: # NanoDynamics-1

            # Minimize options widgets.
            self.electrostaticsForDnaDuringMinimize_checkBox.setEnabled(False)
            self.enableNeighborSearching_check_box.setEnabled(False)

            # Watch minimize in real time widgets.
            self.watch_motion_groupbox.setEnabled(True)

            # Converence criteria widgets
            self.endMaxDoubleSpinBox.setEnabled(True)
            self.cutoverRmsDoubleSpinBox.setEnabled(True)
            self.cutoverMaxDoubleSpinBox.setEnabled(True)
        else: # GROMACS

            # Minimize options widgets.
            self.electrostaticsForDnaDuringMinimize_checkBox.setEnabled(True)
            self.enableNeighborSearching_check_box.setEnabled(True)

            # Watch minimize in real time widgets.
            self.watch_motion_groupbox.setEnabled(False)

            # Converence criteria widgets
            self.endMaxDoubleSpinBox.setEnabled(False)
            self.cutoverRmsDoubleSpinBox.setEnabled(False)
            self.cutoverMaxDoubleSpinBox.setEnabled(False)
        return

    def changeEndRms(self, endRms):
        """
        Slot for EndRMS.
        """
        if endRms:
            env.prefs[endRMS_prefs_key] = endRms
        else:
            env.prefs[endRMS_prefs_key] = -1.0
        return

    def changeEndMax(self, endMax):
        """
        Slot for EndMax.
        """
        if endMax:
            env.prefs[endMax_prefs_key] = endMax
        else:
            env.prefs[endMax_prefs_key] = -1.0
        return

    def changeCutoverRms(self, cutoverRms):
        """
        Slot for CutoverRMS.
        """
        if cutoverRms:
            env.prefs[cutoverRMS_prefs_key] = cutoverRms
        else:
            env.prefs[cutoverRMS_prefs_key] = -1.0
        return

    def changeCutoverMax(self, cutoverMax):
        """
        Slot for CutoverMax.
        """
        if cutoverMax:
            env.prefs[cutoverMax_prefs_key] = cutoverMax
        else:
            env.prefs[cutoverMax_prefs_key] = -1.0
        return

    pass # end of class MinimizeEnergyProp
Esempio n. 9
0
class GamessProp(QDialog, Ui_GamessPropDialog):
    """
    The Gamess Jig Properties dialog used for:
    - running a GAMESS energy calculation on a structure (group of atoms).
    - running a GAMESS optimization on a structure.
    - setting and saving the GAMESS parameters used for an energy calculation or optimization.
    """
    def __init__(self):
        QDialog.__init__(self)
        self.setModal(True)
        self.setupUi(self)

        self.ecm_btngrp = QButtonGroup()
        self.ecm_btngrp.setExclusive(True)
        objId = 0
        for obj in self.ecm_grpbox.children():
            if isinstance(obj, QAbstractButton):
                self.ecm_btngrp.addButton(obj)
                self.ecm_btngrp.setId(obj, objId)
                objId +=1

        self.scftyp_btngrp = QButtonGroup()
        self.scftyp_btngrp.setExclusive(True)
        objId = 0
        for obj in self.scftyp_grpbox.children():
            if isinstance(obj, QAbstractButton):
                self.scftyp_btngrp.addButton(obj)
                self.scftyp_btngrp.setId(obj, objId)
                objId +=1

        self.connect(self.cancel_btn,SIGNAL("clicked()"),self.reject)
        self.connect(self.ecm_btngrp,SIGNAL("buttonPressed(int)"),self.set_ecmethod)
        self.connect(self.multi_combox,SIGNAL("activated(int)"),self.set_multiplicity)
        self.connect(self.run_job_btn,SIGNAL("clicked()"),self.run_job)
        self.connect(self.save_btn,SIGNAL("clicked()"),self.accept)
        self.connect(self.runtyp_combox,SIGNAL("activated(int)"),self.calculate_changed)
        self.connect(self.choose_color_btn,SIGNAL("clicked()"),self.change_jig_color)
        self.connect(self.whats_this_btn,SIGNAL("clicked()"),self.whats_this)
        ##self.connect(self.new_btn,SIGNAL("clicked()"),self.addServer)
        ##self.connect(self.exit_btn,SIGNAL("clicked()"),self.close)
        ##self.connect(self.server_listview,SIGNAL("currentChanged(QListViewItem*)"),self.changeServer)
        ##self.connect(self.engine_combox,SIGNAL("activated(const QString&)"),self.engineChanged)
        ##self.connect(self.del_btn,SIGNAL("clicked()"),self.deleteServer)
        self.sManager = ServerManager()
        self.servers = self.sManager.getServers()
        self.server = self.servers[0]

        self.name_linedit.setWhatsThis("""Name of the GAMESS jig.""")
        self.runtyp_combox.setWhatsThis("""Type of calculation, where "Energy" calculates the Energy Minima,and "Optimization" calculates the "Equilibrium Geometry".""")
        self.comment_linedit.setWhatsThis("""Description, also placed in the comment line of the $DATA section of the INP file.""")
        self.choose_color_btn.setWhatsThis("""Change the GAMESS jig color.""")
        self.rhf_radiobtn.setWhatsThis("""Restricted Hartree-Fock.  All electrons are paired and each spatial orbital is doubly occupied.  Cannot be used with multiplicities greater than 1.""")
        self.uhf_radiobtn.setWhatsThis("""Unrestricted Hartree-Fock.  All electrons are unpaired and spatial (spin) orbitals are uniquely defined for each electron.  More time consuming, but more accurate, than ROHF.  """)
        self.rohf_radiobtn.setWhatsThis("""Restricted Open-shell Hartree-Fock.  Spin-paired electrons are assigned to doubly-occupied spatial orbitals, while electrons with unpaired spins are provided unique spatial orbitals.""")
        self.icharg_spinbox.setWhatsThis("""The total charge of the structure to be treated quantum mechanically (ICHARG).""")
        self.multi_combox.setWhatsThis("""N + 1, where N is the number of unpaired electrons (MULT).""")
        self.memory_spinbox.setWhatsThis("""System memory reserved for calculation""")
        self.dirscf_checkbox.setWhatsThis("""Check this box to run the calculation in RAM and avoid hard disk usage for integral storage.""")
        self.gbasis_combox.setWhatsThis("""Select from among the standard Gaussian-type basis sets and semi-empirical parameters in GAMESS.""")
        self.checkBox10_3_2.setWhatsThis("""Reads the $HESS group from the output file of a previous GAMESS calculation.  Only valid for identical molecules.""")
        self.checkBox10_2_2_2.setWhatsThis("""Reads the $VEC group from the output of a previous GAMESS calculation. Requires that both the molecule and basis set be identical.  Useful for restarted calculations and starting orbitals for electron correlation methods.""")
        self.none_radiobtn.setWhatsThis("""Select this button to neglect electron correlation in the calculation.""")
        self.dft_radiobtn.setWhatsThis("""Select this button to perform a density functional theory calculation.""")
        self.mp2_radiobtn.setWhatsThis("""Select this button to perform a Second-Order Moeller Plesset calculation.""")
        self.dfttyp_combox.setWhatsThis("""Select an available density functional in GAMESS.""")
        self.gridsize_combox.setWhatsThis("""Select the grid spacing for the DFT calculation.""")
        self.core_electrons_checkbox.setWhatsThis("""Check this box to include both the valence and core electrons in the MP2 calculation.""")
        self.density_conv_combox.setWhatsThis("""Selects the accuracy of the electron density convergence for the calculation (CONV).""")
        self.rmsd_combox.setWhatsThis("""Gradient convergence tolerance (OPTTOL), in Hartree/Bohr. Convergence of a geometry search requires the largest component of the gradient to be less than this value, and the root mean square gradient less than 1/3 of OPTTOL.  (default=0.0001)""")
        self.iterations_spinbox.setWhatsThis("""Maximum number of SCF iteration cycles (MAXIT).""")
        self.edit_input_file_cbox.setWhatsThis("""Opens the INP file generated by NanoEngineer-1 in a text editor.""")
        self.whats_this_btn.setWhatsThis("""What's This Help Utility""")
        self.run_job_btn.setWhatsThis("""Save GAMESS parameters, generates the INP file and launches the GAMESS job.""")
        self.save_btn.setWhatsThis("""Save GAMESS parameters and generates the INP file.  It does not launch the GAMESS job.""")
        self.cancel_btn.setWhatsThis("""Cancels changes and closes dialog.""")

    def showDialog(self, job):
        """
        Display the GAMESS Jig Properties dialog
        """
        self.gamessJig =  job.gamessJig
        self.job = job
        self.pset = self.gamessJig.pset
        self.win = self.gamessJig.assy.w
        self.glpane = self.gamessJig.assy.o

        if self._setup(): return
        self.exec_()


    ######Private or helper methods###############################
    def _setup(self):
        """
        Setup widgets to initial (default or defined) values. Return True on error.
        """
        #To fix bug 684
        #if gamess.is_disabled():
        #    self.run_job_btn.setEnabled(False)
        #else:
        #    self.run_job_btn.setEnabled(True)

        self.jig_attrs = self.gamessJig.copyable_attrs_dict() # Save the jig's attributes in case of Cancel.

        # Jig color
        self.original_normcolor = self.gamessJig.normcolor
        self.jig_QColor = RGBf_to_QColor(self.gamessJig.normcolor) # Used as default color by Color Chooser
        self.jig_color_pixmap = get_widget_with_color_palette(
                self.jig_color_pixmap, self.jig_QColor)

        # Init the top widgets (name, runtyp drop box, comment)
        self.name_linedit.setText(self.gamessJig.name)
        self.runtyp_combox.setCurrentIndex(self.pset.ui.runtyp) # RUNTYP
        self.calculate_changed(self.pset.ui.runtyp)
        self.comment_linedit.setText(self.pset.ui.comment)

        # Electronic Structure Properties section.
        btn = self.scftyp_btngrp.button(self.pset.ui.scftyp)# RHF, UHF, or ROHF
        btn.setChecked(True)
        self.icharg_spinbox.setValue(self.pset.ui.icharg) # Charge
        self.multi_combox.setCurrentIndex(self.pset.ui.mult) # Multiplicity
        # Disable RHF if multiplicity is not the first item.
        if self.pset.ui.mult == 0:
            self.rhf_radiobtn.setEnabled(1) # Enable RHF
        else:
            self.rhf_radiobtn.setEnabled(0) # Disable RHF

        # System Memory and Usage
        self.dirscf_checkbox.setChecked(self.pset.ui.dirscf) # DIRSCF
        self.memory_spinbox.setValue(self.pset.ui.memory) # Memory

        # Electron Correlation Method and Basis Set
        ecm = self.pset.ui.ecm
        btn = self.ecm_btngrp.button(self.pset.ui.ecm)# None, DFT or MP2
        btn.setChecked(True)
        self.set_ecmethod(self.pset.ui.ecm) # None, DFT or MP2
        self.gbasis_combox.setCurrentIndex(self.pset.ui.gbasis) # Basis set

        # Load the combo box with all the valid DFT functions.
        self._load_dfttyp_combox()
        self.dfttyp_combox.setCurrentIndex(self.pset.ui.dfttyp) # DFT Functional
        self.gridsize_combox.setCurrentIndex(self.pset.ui.gridsize) # Grid Size
        self.core_electrons_checkbox.setChecked(self.pset.ui.ncore) # Include core electrons

        # Convergence Criteria
        self.density_conv_combox.setCurrentIndex(self.pset.ui.conv) # Density Convergence
        self.rmsd_combox.setCurrentIndex(self.pset.ui.rmsdconv) # RMSD Convergence
        self.iterations_spinbox.setValue(self.pset.ui.iterations) # Iterations

# These have been removed per discussions with Damian.
# Mark 050628
#        self.extrap_checkbox.setChecked(self.pset.ui.extrap) # EXTRAP
#        self.damp_checkbox.setChecked(self.pset.ui.damp) # DAMP
#        self.diis_checkbox.setChecked(self.pset.ui.diis) # DIIS
#        self.shift_checkbox.setChecked(self.pset.ui.shift) # SHIFT
#        self.soscf_checkbox.setChecked(self.pset.ui.soscf) # SOSCF
#        self.rstrct_checkbox.setChecked(self.pset.ui.rstrct) # RSTRCT

        # Load the server combo box
        #self._reloadServerList() # Not used in A6.  Mark.

        # If there is an error, return 1. NIY.
        return 0

    def _reloadServerList(self):
        """
        Load the server combo box
        """
        self.server_combox.clear()
        for s in self.servers:
            self.server_combox.insertItem(100, s.hostname + "-" + s.engine)
            # 100 makes sure item is appended to list. [mark 2007-05-04]
        if self.server not in self.servers:
            self.server = self.servers[0]
        indx = self.servers.index(self.server)
        self.server_combox.setCurrentIndex(indx)

    def _load_dfttyp_combox(self):
        """
        Load list of DFT function in a combobox widget
        """
        self.dfttyp_combox.clear() # Clear all combo box items
        if self.server.engine == 'GAMESS':
            for f in gms_dfttyp_items:
                self.dfttyp_combox.insertItem(100, f)
                # 100 makes sure item is appended to list. [mark 2007-05-04]
        elif self.server.engine == 'PC GAMESS':
            for f in pcgms_dfttyp_items:
                self.dfttyp_combox.insertItem(100, f)
                # 100 makes sure item is appended to list. [mark 2007-05-04]
        else:
            print "load_dfttyp_combox: Unknown GAMESS Version.  Loading GAMES DFT functionals."
            for f in gms_dfttyp_items:
                self.dfttyp_combox.insertItem(100, f)
                # 100 makes sure item is appended to list. [mark 2007-05-04]

    def _update_gbasis_list(self, val):
        """
        Add/remove AM1 and PM3 to/from the gbasis list.
        """
        citem = self.gbasis_combox.currentIndex()
        if val == DFT or val == MP2:
            if self.gbasis_combox.count() == 18:
                self.gbasis_combox.removeItem(0)
                self.gbasis_combox.removeItem(0)
                self.gbasis_combox.setCurrentIndex(max(0, citem-2))
        else:
            if self.gbasis_combox.count() != 18:
                self.gbasis_combox.insertItem(0,"PM3") # 0 prepends item to list.
                self.gbasis_combox.insertItem(0,"AM1")
                self.gbasis_combox.setCurrentIndex(citem+2)

    def _save_ui_settings(self):
        """
        Save the UI settings in the Gamess jig pset.
        There is one setting for each pset.
        """
        self.pset.ui.comment = str(self.comment_linedit.text()) # Description
        self.pset.ui.runtyp = self.runtyp_combox.currentIndex() # RUNTYP = Energy or Optimize

        # Electronic Structure Props and Basis Set section.
        self.pset.ui.scftyp = self.scftyp_btngrp.checkedId() # SCFTYP = RHF, UHF, or ROHF
        self.pset.ui.icharg = self.icharg_spinbox.value() # Charge
        self.pset.ui.mult = self.multi_combox.currentIndex() # Multiplicity

        # System Memory and Usage
        self.pset.ui.memory = self.memory_spinbox.value() # Memory
        self.pset.ui.dirscf = self.dirscf_checkbox.isChecked() # DIRSCF

        # Electron Correlation Method
        self.pset.ui.ecm = self.ecm_btngrp.checkedId() # None, DFT or MP2
        #self.pset.ui.inttyp = self.ecm_btngrp.selectedId() # INTTYP
        self.pset.ui.gbasis = self.gbasis_combox.currentIndex() # Basis Set
        self.pset.ui.gbasisname = str(self.gbasis_combox.currentText())
        self.pset.ui.dfttyp = self.dfttyp_combox.currentIndex() # DFT Functional Type
        self.pset.ui.gridsize = self.gridsize_combox.currentIndex() # Grid Size
        self.pset.ui.ncore = self.core_electrons_checkbox.isChecked() # Include core electrons

        # Convergence Criteria
        self.pset.ui.conv = self.density_conv_combox.currentIndex() # Density Convergence
        self.pset.ui.rmsdconv = self.rmsd_combox.currentIndex() # RMSD Convergence
        self.pset.ui.iterations = self.iterations_spinbox.value() # Iterations

#        self.pset.ui.extrap = self.extrap_checkbox.isChecked() # EXTRAP
#        self.pset.ui.damp = self.damp_checkbox.isChecked() # DAMP
#        self.pset.ui.diis = self.diis_checkbox.isChecked() # DIIS
#        self.pset.ui.shift = self.shift_checkbox.isChecked() # SHIFT
#        self.pset.ui.soscf = self.soscf_checkbox.isChecked() # SOSCF
#        self.pset.ui.rstrct = self.rstrct_checkbox.isChecked() # RSTRCT

    def _save_job_parms(self):
        calculate = ['Energy', 'Optimization']
        self.job.Calculation = calculate[self.pset.ui.runtyp]
        self.job.Description = self.pset.ui.comment
        self.job.server =  self.server
        ##Copy some  attributes from the server object to job description
        self.job.Server_id = self.server.server_id
        self.job.Engine = self.server.engine

    ######End of private or helper methods.########################

    ###### Unused methods ###############

    def openServerManager(self):
        """
        Pop up ServerManagerDialog to edit the properties of the servers.
        """
        self.sManager.showDialog(self.server)
        self.servers = self.sManager.getServers()
        self._reloadServerList()

    def serverChanged(self, si):
        """
        User has changed server, so update the DFT comboBox. Currently not used.
        """
        self.server = self.servers[si]
        self._load_dfttyp_combox()

    ###### End of unused methods ###############

    ##########Slot methods for some GUI controls################

    def calculate_changed(self, val):
        """
        """
        if val == 0: # Energy
            self.rmsd_lbl.setEnabled(0)
            self.rmsd_combox.setEnabled(0)
            self.iterations_lbl.setEnabled(0)
            self.iterations_spinbox.setEnabled(0)
#            self.extrap_checkbox.setEnabled(0)
#            self.rstrct_checkbox.setEnabled(0)
#            self.damp_checkbox.setEnabled(0)
#            self.diis_checkbox.setEnabled(0)
#            self.shift_checkbox.setEnabled(0)
#            self.soscf_checkbox.setEnabled(0)
        else: # Optimization
            self.rmsd_lbl.setEnabled(1)
            self.rmsd_combox.setEnabled(1)
            self.iterations_lbl.setEnabled(1)
            self.iterations_spinbox.setEnabled(1)
#            self.extrap_checkbox.setEnabled(1)
#            self.rstrct_checkbox.setEnabled(1)
#            self.damp_checkbox.setEnabled(1)
#            self.diis_checkbox.setEnabled(1)
#            self.shift_checkbox.setEnabled(1)
#            self.soscf_checkbox.setEnabled(1)

    def set_multiplicity(self, val):
        """
        Enable/disable widgets when user changes Multiplicity.
        """
        if val != 0:
            qt4todo("if scftyp[self.scftyp_btngrp.selectedId()] != 'RHF':")
            #if scftyp[self.scftyp_btngrp.selectedId()] != 'RHF':
            #    self.rhf_radiobtn.setEnabled(0)
            #    return

            ret = QMessageBox.warning( self, "Multiplicity Conflict",
                "If Multiplicity is greater than 1, then <b>UHF</b> or <b>ROHF</b> must be selected.\n"
                "Select Cancel to keep <b>RHF</b>.",
                "&UHF", "&ROHF", "Cancel",
                0, 2 )

            if ret == 0: # UHF
                self.uhf_radiobtn.toggle()
                self.rhf_radiobtn.setEnabled(0)

            elif ret == 1: # ROHF
                self.rohf_radiobtn.toggle()
                self.rhf_radiobtn.setEnabled(0)

            elif ret == 2: # Cancel
                self.multi_combox.setCurrentIndex(0)

        elif val == 0:
            self.rhf_radiobtn.setEnabled(1)

    def set_ecmethod(self, val):
        """
        Enable/disable widgets when user changes Electron Correlation Method.
        """
        #print "set_ecmethod = ", val
        if val == DFT:
            self.dfttyp_label.setEnabled(1)
            self.dfttyp_combox.setEnabled(1)
            self.gridsize_label.setEnabled(1)
            self.gridsize_combox.setEnabled(1)
            self.core_electrons_checkbox.setChecked(0)
            self.core_electrons_checkbox.setEnabled(0)

        elif val == MP2:
            self.core_electrons_checkbox.setEnabled(1)
            self.dfttyp_label.setEnabled(0)
            self.dfttyp_combox.setEnabled(0)
            self.gridsize_label.setEnabled(0)
            self.gridsize_combox.setEnabled(0)

        else: # None = Hartree-Fock
            self.dfttyp_label.setEnabled(0)
            self.dfttyp_combox.setEnabled(0)
            self.gridsize_label.setEnabled(0)
            self.gridsize_combox.setEnabled(0)
            self.core_electrons_checkbox.setChecked(0)
            self.core_electrons_checkbox.setEnabled(0)

        # AM1 and PM3 are not options for DFT or MP2.
        # We have to remove or add them from the combo box.
        self._update_gbasis_list(val)

    def open_tmp_inputfile(self):
        """
        Writes a temporary GAMESS inputfile of the current Gamess jig and opens the
        file in an editor.
        """
        # Make tmp_inputfile filename (i.e. ~/Nanorex/temp/jigname_parms_info.inp)
        from platform_dependent.PlatformDependent import find_or_make_Nanorex_subdir
        tmpdir = find_or_make_Nanorex_subdir('temp')
        basename = self.gamessJig.name + "-" + self.gamessJig.gms_parms_info('_')
        tmp_inputfile = os.path.join(tmpdir, "%s.inp" % basename)

        # Write INP file (in ~/Nanorex/temp subdirectory)
        from analysis.GAMESS.files_gms import writegms_inpfile
        writegms_inpfile(tmp_inputfile, self.gamessJig)

        from platform_dependent.PlatformDependent import open_file_in_editor
        open_file_in_editor(tmp_inputfile)

    def run_job(self):
        """
        Slot method for the 'Save and Run' button
        """
        self.accept()

        # Run GAMESS job.  Return value r:
        # 0 = success
        # 1 = job cancelled
        # 2 = job failed.
        r = self.job.launch()

        if r == 1: # Job was cancelled
            env.history.message( redmsg( "GAMESS job cancelled."))
            return

        if r == 2: # Job failed.
            env.history.message( redmsg( "GAMESS job failed. Maybe you didn't set the right Gamess executable file. Make sure you can run the same job manually."))
            return

        # Job success.
        fn = self.gamessJig.outputfile

        # Print energy or move atoms
        if self.pset.ui.runtyp == 0: #Energy
            self.gamessJig.print_energy()
        else:  # Optimize
            try:
                r = self.gamessJig.move_optimized_atoms()
                # r = insertgms(self.gamessJig.assy, fn)
            except:
                print_compact_traceback( "GamessProp.run_job(): error reading GAMESS OUT file [%s]: " % fn )
                env.history.message( redmsg( "Internal error while inserting GAMESS geometry: " + fn) )
            else:
                if r:
                    env.history.message(redmsg( "Atoms not adjusted."))
                else:
                    self.gamessJig.assy.changed() # The file and the part are not the same.
                    self.gamessJig.print_energy() # Print the final energy from the optimize OUT file, too.
                    env.history.message( "Atoms adjusted.")

    def change_jig_color(self):
        """
        Slot method to change the jig's color.
        """
        color = QColorDialog.getColor(self.jig_QColor, self)

        if color.isValid():
            self.jig_QColor = color
            self.jig_color_pixmap = get_widget_with_color_palette(
                self.jig_color_pixmap, self.jig_QColor)

            self.gamessJig.color = self.gamessJig.normcolor = QColor_to_RGBf(color)
            self.glpane.gl_update()

    def accept(self):
        """
        The slot method for the 'Save' button.
        """
        QDialog.accept(self)
        self.gamessJig.try_rename(self.name_linedit.text())
        self._save_ui_settings()
        self.gamessJig.update_gamess_parms() # Update all the GAMESS parameters.
        self._save_job_parms()
        if self.edit_input_file_cbox.isChecked():
            self.open_tmp_inputfile()

    def reject(self):
        """
        The slot method for the 'Cancel' button.
        """
        QDialog.reject(self)
        self.gamessJig.attr_update(self.jig_attrs) # Restore attributes of the jig.
        # self.gamessJig.color = self.gamessJig.normcolor = self.original_normcolor
        self.gamessJig.cancelled = True
        self.glpane.gl_update()

    def whats_this(self):
        from PyQt4.Qt import QWhatsThis, QDialog
        QWhatsThis.enterWhatsThisMode()
Esempio n. 10
0
    def __init__(self):
        QDialog.__init__(self)
        self.setModal(True)
        self.setupUi(self)

        self.ecm_btngrp = QButtonGroup()
        self.ecm_btngrp.setExclusive(True)
        objId = 0
        for obj in self.ecm_grpbox.children():
            if isinstance(obj, QAbstractButton):
                self.ecm_btngrp.addButton(obj)
                self.ecm_btngrp.setId(obj, objId)
                objId +=1

        self.scftyp_btngrp = QButtonGroup()
        self.scftyp_btngrp.setExclusive(True)
        objId = 0
        for obj in self.scftyp_grpbox.children():
            if isinstance(obj, QAbstractButton):
                self.scftyp_btngrp.addButton(obj)
                self.scftyp_btngrp.setId(obj, objId)
                objId +=1

        self.connect(self.cancel_btn,SIGNAL("clicked()"),self.reject)
        self.connect(self.ecm_btngrp,SIGNAL("buttonPressed(int)"),self.set_ecmethod)
        self.connect(self.multi_combox,SIGNAL("activated(int)"),self.set_multiplicity)
        self.connect(self.run_job_btn,SIGNAL("clicked()"),self.run_job)
        self.connect(self.save_btn,SIGNAL("clicked()"),self.accept)
        self.connect(self.runtyp_combox,SIGNAL("activated(int)"),self.calculate_changed)
        self.connect(self.choose_color_btn,SIGNAL("clicked()"),self.change_jig_color)
        self.connect(self.whats_this_btn,SIGNAL("clicked()"),self.whats_this)
        ##self.connect(self.new_btn,SIGNAL("clicked()"),self.addServer)
        ##self.connect(self.exit_btn,SIGNAL("clicked()"),self.close)
        ##self.connect(self.server_listview,SIGNAL("currentChanged(QListViewItem*)"),self.changeServer)
        ##self.connect(self.engine_combox,SIGNAL("activated(const QString&)"),self.engineChanged)
        ##self.connect(self.del_btn,SIGNAL("clicked()"),self.deleteServer)
        self.sManager = ServerManager()
        self.servers = self.sManager.getServers()
        self.server = self.servers[0]

        self.name_linedit.setWhatsThis("""Name of the GAMESS jig.""")
        self.runtyp_combox.setWhatsThis("""Type of calculation, where "Energy" calculates the Energy Minima,and "Optimization" calculates the "Equilibrium Geometry".""")
        self.comment_linedit.setWhatsThis("""Description, also placed in the comment line of the $DATA section of the INP file.""")
        self.choose_color_btn.setWhatsThis("""Change the GAMESS jig color.""")
        self.rhf_radiobtn.setWhatsThis("""Restricted Hartree-Fock.  All electrons are paired and each spatial orbital is doubly occupied.  Cannot be used with multiplicities greater than 1.""")
        self.uhf_radiobtn.setWhatsThis("""Unrestricted Hartree-Fock.  All electrons are unpaired and spatial (spin) orbitals are uniquely defined for each electron.  More time consuming, but more accurate, than ROHF.  """)
        self.rohf_radiobtn.setWhatsThis("""Restricted Open-shell Hartree-Fock.  Spin-paired electrons are assigned to doubly-occupied spatial orbitals, while electrons with unpaired spins are provided unique spatial orbitals.""")
        self.icharg_spinbox.setWhatsThis("""The total charge of the structure to be treated quantum mechanically (ICHARG).""")
        self.multi_combox.setWhatsThis("""N + 1, where N is the number of unpaired electrons (MULT).""")
        self.memory_spinbox.setWhatsThis("""System memory reserved for calculation""")
        self.dirscf_checkbox.setWhatsThis("""Check this box to run the calculation in RAM and avoid hard disk usage for integral storage.""")
        self.gbasis_combox.setWhatsThis("""Select from among the standard Gaussian-type basis sets and semi-empirical parameters in GAMESS.""")
        self.checkBox10_3_2.setWhatsThis("""Reads the $HESS group from the output file of a previous GAMESS calculation.  Only valid for identical molecules.""")
        self.checkBox10_2_2_2.setWhatsThis("""Reads the $VEC group from the output of a previous GAMESS calculation. Requires that both the molecule and basis set be identical.  Useful for restarted calculations and starting orbitals for electron correlation methods.""")
        self.none_radiobtn.setWhatsThis("""Select this button to neglect electron correlation in the calculation.""")
        self.dft_radiobtn.setWhatsThis("""Select this button to perform a density functional theory calculation.""")
        self.mp2_radiobtn.setWhatsThis("""Select this button to perform a Second-Order Moeller Plesset calculation.""")
        self.dfttyp_combox.setWhatsThis("""Select an available density functional in GAMESS.""")
        self.gridsize_combox.setWhatsThis("""Select the grid spacing for the DFT calculation.""")
        self.core_electrons_checkbox.setWhatsThis("""Check this box to include both the valence and core electrons in the MP2 calculation.""")
        self.density_conv_combox.setWhatsThis("""Selects the accuracy of the electron density convergence for the calculation (CONV).""")
        self.rmsd_combox.setWhatsThis("""Gradient convergence tolerance (OPTTOL), in Hartree/Bohr. Convergence of a geometry search requires the largest component of the gradient to be less than this value, and the root mean square gradient less than 1/3 of OPTTOL.  (default=0.0001)""")
        self.iterations_spinbox.setWhatsThis("""Maximum number of SCF iteration cycles (MAXIT).""")
        self.edit_input_file_cbox.setWhatsThis("""Opens the INP file generated by NanoEngineer-1 in a text editor.""")
        self.whats_this_btn.setWhatsThis("""What's This Help Utility""")
        self.run_job_btn.setWhatsThis("""Save GAMESS parameters, generates the INP file and launches the GAMESS job.""")
        self.save_btn.setWhatsThis("""Save GAMESS parameters and generates the INP file.  It does not launch the GAMESS job.""")
        self.cancel_btn.setWhatsThis("""Cancels changes and closes dialog.""")
Esempio n. 11
0
    def __init__(self):
        QDialog.__init__(self)
        self.setModal(True)
        self.setupUi(self)

        self.ecm_btngrp = QButtonGroup()
        self.ecm_btngrp.setExclusive(True)
        objId = 0
        for obj in self.ecm_grpbox.children():
            if isinstance(obj, QAbstractButton):
                self.ecm_btngrp.addButton(obj)
                self.ecm_btngrp.setId(obj, objId)
                objId += 1

        self.scftyp_btngrp = QButtonGroup()
        self.scftyp_btngrp.setExclusive(True)
        objId = 0
        for obj in self.scftyp_grpbox.children():
            if isinstance(obj, QAbstractButton):
                self.scftyp_btngrp.addButton(obj)
                self.scftyp_btngrp.setId(obj, objId)
                objId += 1

        self.connect(self.cancel_btn, SIGNAL("clicked()"), self.reject)
        self.connect(self.ecm_btngrp, SIGNAL("buttonPressed(int)"),
                     self.set_ecmethod)
        self.connect(self.multi_combox, SIGNAL("activated(int)"),
                     self.set_multiplicity)
        self.connect(self.run_job_btn, SIGNAL("clicked()"), self.run_job)
        self.connect(self.save_btn, SIGNAL("clicked()"), self.accept)
        self.connect(self.runtyp_combox, SIGNAL("activated(int)"),
                     self.calculate_changed)
        self.connect(self.choose_color_btn, SIGNAL("clicked()"),
                     self.change_jig_color)
        self.connect(self.whats_this_btn, SIGNAL("clicked()"), self.whats_this)
        ##self.connect(self.new_btn,SIGNAL("clicked()"),self.addServer)
        ##self.connect(self.exit_btn,SIGNAL("clicked()"),self.close)
        ##self.connect(self.server_listview,SIGNAL("currentChanged(QListViewItem*)"),self.changeServer)
        ##self.connect(self.engine_combox,SIGNAL("activated(const QString&)"),self.engineChanged)
        ##self.connect(self.del_btn,SIGNAL("clicked()"),self.deleteServer)
        self.sManager = ServerManager()
        self.servers = self.sManager.getServers()
        self.server = self.servers[0]

        self.name_linedit.setWhatsThis("""Name of the GAMESS jig.""")
        self.runtyp_combox.setWhatsThis(
            """Type of calculation, where "Energy" calculates the Energy Minima,and "Optimization" calculates the "Equilibrium Geometry"."""
        )
        self.comment_linedit.setWhatsThis(
            """Description, also placed in the comment line of the $DATA section of the INP file."""
        )
        self.choose_color_btn.setWhatsThis("""Change the GAMESS jig color.""")
        self.rhf_radiobtn.setWhatsThis(
            """Restricted Hartree-Fock.  All electrons are paired and each spatial orbital is doubly occupied.  Cannot be used with multiplicities greater than 1."""
        )
        self.uhf_radiobtn.setWhatsThis(
            """Unrestricted Hartree-Fock.  All electrons are unpaired and spatial (spin) orbitals are uniquely defined for each electron.  More time consuming, but more accurate, than ROHF.  """
        )
        self.rohf_radiobtn.setWhatsThis(
            """Restricted Open-shell Hartree-Fock.  Spin-paired electrons are assigned to doubly-occupied spatial orbitals, while electrons with unpaired spins are provided unique spatial orbitals."""
        )
        self.icharg_spinbox.setWhatsThis(
            """The total charge of the structure to be treated quantum mechanically (ICHARG)."""
        )
        self.multi_combox.setWhatsThis(
            """N + 1, where N is the number of unpaired electrons (MULT).""")
        self.memory_spinbox.setWhatsThis(
            """System memory reserved for calculation""")
        self.dirscf_checkbox.setWhatsThis(
            """Check this box to run the calculation in RAM and avoid hard disk usage for integral storage."""
        )
        self.gbasis_combox.setWhatsThis(
            """Select from among the standard Gaussian-type basis sets and semi-empirical parameters in GAMESS."""
        )
        self.checkBox10_3_2.setWhatsThis(
            """Reads the $HESS group from the output file of a previous GAMESS calculation.  Only valid for identical molecules."""
        )
        self.checkBox10_2_2_2.setWhatsThis(
            """Reads the $VEC group from the output of a previous GAMESS calculation. Requires that both the molecule and basis set be identical.  Useful for restarted calculations and starting orbitals for electron correlation methods."""
        )
        self.none_radiobtn.setWhatsThis(
            """Select this button to neglect electron correlation in the calculation."""
        )
        self.dft_radiobtn.setWhatsThis(
            """Select this button to perform a density functional theory calculation."""
        )
        self.mp2_radiobtn.setWhatsThis(
            """Select this button to perform a Second-Order Moeller Plesset calculation."""
        )
        self.dfttyp_combox.setWhatsThis(
            """Select an available density functional in GAMESS.""")
        self.gridsize_combox.setWhatsThis(
            """Select the grid spacing for the DFT calculation.""")
        self.core_electrons_checkbox.setWhatsThis(
            """Check this box to include both the valence and core electrons in the MP2 calculation."""
        )
        self.density_conv_combox.setWhatsThis(
            """Selects the accuracy of the electron density convergence for the calculation (CONV)."""
        )
        self.rmsd_combox.setWhatsThis(
            """Gradient convergence tolerance (OPTTOL), in Hartree/Bohr. Convergence of a geometry search requires the largest component of the gradient to be less than this value, and the root mean square gradient less than 1/3 of OPTTOL.  (default=0.0001)"""
        )
        self.iterations_spinbox.setWhatsThis(
            """Maximum number of SCF iteration cycles (MAXIT).""")
        self.edit_input_file_cbox.setWhatsThis(
            """Opens the INP file generated by NanoEngineer-1 in a text editor."""
        )
        self.whats_this_btn.setWhatsThis("""What's This Help Utility""")
        self.run_job_btn.setWhatsThis(
            """Save GAMESS parameters, generates the INP file and launches the GAMESS job."""
        )
        self.save_btn.setWhatsThis(
            """Save GAMESS parameters and generates the INP file.  It does not launch the GAMESS job."""
        )
        self.cancel_btn.setWhatsThis("""Cancels changes and closes dialog.""")
Esempio n. 12
0
class GamessProp(QDialog, Ui_GamessPropDialog):
    """
    The Gamess Jig Properties dialog used for:
    - running a GAMESS energy calculation on a structure (group of atoms).
    - running a GAMESS optimization on a structure.
    - setting and saving the GAMESS parameters used for an energy calculation or optimization.
    """
    def __init__(self):
        QDialog.__init__(self)
        self.setModal(True)
        self.setupUi(self)

        self.ecm_btngrp = QButtonGroup()
        self.ecm_btngrp.setExclusive(True)
        objId = 0
        for obj in self.ecm_grpbox.children():
            if isinstance(obj, QAbstractButton):
                self.ecm_btngrp.addButton(obj)
                self.ecm_btngrp.setId(obj, objId)
                objId += 1

        self.scftyp_btngrp = QButtonGroup()
        self.scftyp_btngrp.setExclusive(True)
        objId = 0
        for obj in self.scftyp_grpbox.children():
            if isinstance(obj, QAbstractButton):
                self.scftyp_btngrp.addButton(obj)
                self.scftyp_btngrp.setId(obj, objId)
                objId += 1

        self.connect(self.cancel_btn, SIGNAL("clicked()"), self.reject)
        self.connect(self.ecm_btngrp, SIGNAL("buttonPressed(int)"),
                     self.set_ecmethod)
        self.connect(self.multi_combox, SIGNAL("activated(int)"),
                     self.set_multiplicity)
        self.connect(self.run_job_btn, SIGNAL("clicked()"), self.run_job)
        self.connect(self.save_btn, SIGNAL("clicked()"), self.accept)
        self.connect(self.runtyp_combox, SIGNAL("activated(int)"),
                     self.calculate_changed)
        self.connect(self.choose_color_btn, SIGNAL("clicked()"),
                     self.change_jig_color)
        self.connect(self.whats_this_btn, SIGNAL("clicked()"), self.whats_this)
        ##self.connect(self.new_btn,SIGNAL("clicked()"),self.addServer)
        ##self.connect(self.exit_btn,SIGNAL("clicked()"),self.close)
        ##self.connect(self.server_listview,SIGNAL("currentChanged(QListViewItem*)"),self.changeServer)
        ##self.connect(self.engine_combox,SIGNAL("activated(const QString&)"),self.engineChanged)
        ##self.connect(self.del_btn,SIGNAL("clicked()"),self.deleteServer)
        self.sManager = ServerManager()
        self.servers = self.sManager.getServers()
        self.server = self.servers[0]

        self.name_linedit.setWhatsThis("""Name of the GAMESS jig.""")
        self.runtyp_combox.setWhatsThis(
            """Type of calculation, where "Energy" calculates the Energy Minima,and "Optimization" calculates the "Equilibrium Geometry"."""
        )
        self.comment_linedit.setWhatsThis(
            """Description, also placed in the comment line of the $DATA section of the INP file."""
        )
        self.choose_color_btn.setWhatsThis("""Change the GAMESS jig color.""")
        self.rhf_radiobtn.setWhatsThis(
            """Restricted Hartree-Fock.  All electrons are paired and each spatial orbital is doubly occupied.  Cannot be used with multiplicities greater than 1."""
        )
        self.uhf_radiobtn.setWhatsThis(
            """Unrestricted Hartree-Fock.  All electrons are unpaired and spatial (spin) orbitals are uniquely defined for each electron.  More time consuming, but more accurate, than ROHF.  """
        )
        self.rohf_radiobtn.setWhatsThis(
            """Restricted Open-shell Hartree-Fock.  Spin-paired electrons are assigned to doubly-occupied spatial orbitals, while electrons with unpaired spins are provided unique spatial orbitals."""
        )
        self.icharg_spinbox.setWhatsThis(
            """The total charge of the structure to be treated quantum mechanically (ICHARG)."""
        )
        self.multi_combox.setWhatsThis(
            """N + 1, where N is the number of unpaired electrons (MULT).""")
        self.memory_spinbox.setWhatsThis(
            """System memory reserved for calculation""")
        self.dirscf_checkbox.setWhatsThis(
            """Check this box to run the calculation in RAM and avoid hard disk usage for integral storage."""
        )
        self.gbasis_combox.setWhatsThis(
            """Select from among the standard Gaussian-type basis sets and semi-empirical parameters in GAMESS."""
        )
        self.checkBox10_3_2.setWhatsThis(
            """Reads the $HESS group from the output file of a previous GAMESS calculation.  Only valid for identical molecules."""
        )
        self.checkBox10_2_2_2.setWhatsThis(
            """Reads the $VEC group from the output of a previous GAMESS calculation. Requires that both the molecule and basis set be identical.  Useful for restarted calculations and starting orbitals for electron correlation methods."""
        )
        self.none_radiobtn.setWhatsThis(
            """Select this button to neglect electron correlation in the calculation."""
        )
        self.dft_radiobtn.setWhatsThis(
            """Select this button to perform a density functional theory calculation."""
        )
        self.mp2_radiobtn.setWhatsThis(
            """Select this button to perform a Second-Order Moeller Plesset calculation."""
        )
        self.dfttyp_combox.setWhatsThis(
            """Select an available density functional in GAMESS.""")
        self.gridsize_combox.setWhatsThis(
            """Select the grid spacing for the DFT calculation.""")
        self.core_electrons_checkbox.setWhatsThis(
            """Check this box to include both the valence and core electrons in the MP2 calculation."""
        )
        self.density_conv_combox.setWhatsThis(
            """Selects the accuracy of the electron density convergence for the calculation (CONV)."""
        )
        self.rmsd_combox.setWhatsThis(
            """Gradient convergence tolerance (OPTTOL), in Hartree/Bohr. Convergence of a geometry search requires the largest component of the gradient to be less than this value, and the root mean square gradient less than 1/3 of OPTTOL.  (default=0.0001)"""
        )
        self.iterations_spinbox.setWhatsThis(
            """Maximum number of SCF iteration cycles (MAXIT).""")
        self.edit_input_file_cbox.setWhatsThis(
            """Opens the INP file generated by NanoEngineer-1 in a text editor."""
        )
        self.whats_this_btn.setWhatsThis("""What's This Help Utility""")
        self.run_job_btn.setWhatsThis(
            """Save GAMESS parameters, generates the INP file and launches the GAMESS job."""
        )
        self.save_btn.setWhatsThis(
            """Save GAMESS parameters and generates the INP file.  It does not launch the GAMESS job."""
        )
        self.cancel_btn.setWhatsThis("""Cancels changes and closes dialog.""")

    def showDialog(self, job):
        """
        Display the GAMESS Jig Properties dialog
        """
        self.gamessJig = job.gamessJig
        self.job = job
        self.pset = self.gamessJig.pset
        self.win = self.gamessJig.assy.w
        self.glpane = self.gamessJig.assy.o

        if self._setup(): return
        self.exec_()

    ######Private or helper methods###############################
    def _setup(self):
        """ 
        Setup widgets to initial (default or defined) values. Return True on error.
        """
        #To fix bug 684
        #if gamess.is_disabled():
        #    self.run_job_btn.setEnabled(False)
        #else:
        #    self.run_job_btn.setEnabled(True)

        self.jig_attrs = self.gamessJig.copyable_attrs_dict(
        )  # Save the jig's attributes in case of Cancel.

        # Jig color
        self.original_normcolor = self.gamessJig.normcolor
        self.jig_QColor = RGBf_to_QColor(
            self.gamessJig.normcolor)  # Used as default color by Color Chooser
        self.jig_color_pixmap = get_widget_with_color_palette(
            self.jig_color_pixmap, self.jig_QColor)

        # Init the top widgets (name, runtyp drop box, comment)
        self.name_linedit.setText(self.gamessJig.name)
        self.runtyp_combox.setCurrentIndex(self.pset.ui.runtyp)  # RUNTYP
        self.calculate_changed(self.pset.ui.runtyp)
        self.comment_linedit.setText(self.pset.ui.comment)

        # Electronic Structure Properties section.
        btn = self.scftyp_btngrp.button(
            self.pset.ui.scftyp)  # RHF, UHF, or ROHF
        btn.setChecked(True)
        self.icharg_spinbox.setValue(self.pset.ui.icharg)  # Charge
        self.multi_combox.setCurrentIndex(self.pset.ui.mult)  # Multiplicity
        # Disable RHF if multiplicity is not the first item.
        if self.pset.ui.mult == 0:
            self.rhf_radiobtn.setEnabled(1)  # Enable RHF
        else:
            self.rhf_radiobtn.setEnabled(0)  # Disable RHF

        # System Memory and Usage
        self.dirscf_checkbox.setChecked(self.pset.ui.dirscf)  # DIRSCF
        self.memory_spinbox.setValue(self.pset.ui.memory)  # Memory

        # Electron Correlation Method and Basis Set
        ecm = self.pset.ui.ecm
        btn = self.ecm_btngrp.button(self.pset.ui.ecm)  # None, DFT or MP2
        btn.setChecked(True)
        self.set_ecmethod(self.pset.ui.ecm)  # None, DFT or MP2
        self.gbasis_combox.setCurrentIndex(self.pset.ui.gbasis)  # Basis set

        # Load the combo box with all the valid DFT functions.
        self._load_dfttyp_combox()
        self.dfttyp_combox.setCurrentIndex(
            self.pset.ui.dfttyp)  # DFT Functional
        self.gridsize_combox.setCurrentIndex(
            self.pset.ui.gridsize)  # Grid Size
        self.core_electrons_checkbox.setChecked(
            self.pset.ui.ncore)  # Include core electrons

        # Convergence Criteria
        self.density_conv_combox.setCurrentIndex(
            self.pset.ui.conv)  # Density Convergence
        self.rmsd_combox.setCurrentIndex(
            self.pset.ui.rmsdconv)  # RMSD Convergence
        self.iterations_spinbox.setValue(self.pset.ui.iterations)  # Iterations

        # These have been removed per discussions with Damian.
        # Mark 050628
        #        self.extrap_checkbox.setChecked(self.pset.ui.extrap) # EXTRAP
        #        self.damp_checkbox.setChecked(self.pset.ui.damp) # DAMP
        #        self.diis_checkbox.setChecked(self.pset.ui.diis) # DIIS
        #        self.shift_checkbox.setChecked(self.pset.ui.shift) # SHIFT
        #        self.soscf_checkbox.setChecked(self.pset.ui.soscf) # SOSCF
        #        self.rstrct_checkbox.setChecked(self.pset.ui.rstrct) # RSTRCT

        # Load the server combo box
        #self._reloadServerList() # Not used in A6.  Mark.

        # If there is an error, return 1. NIY.
        return 0

    def _reloadServerList(self):
        """ 
        Load the server combo box
        """
        self.server_combox.clear()
        for s in self.servers:
            self.server_combox.insertItem(100, s.hostname + "-" + s.engine)
            # 100 makes sure item is appended to list. [mark 2007-05-04]
        if self.server not in self.servers:
            self.server = self.servers[0]
        indx = self.servers.index(self.server)
        self.server_combox.setCurrentIndex(indx)

    def _load_dfttyp_combox(self):
        """
        Load list of DFT function in a combobox widget
        """
        self.dfttyp_combox.clear()  # Clear all combo box items
        if self.server.engine == 'GAMESS':
            for f in gms_dfttyp_items:
                self.dfttyp_combox.insertItem(100, f)
                # 100 makes sure item is appended to list. [mark 2007-05-04]
        elif self.server.engine == 'PC GAMESS':
            for f in pcgms_dfttyp_items:
                self.dfttyp_combox.insertItem(100, f)
                # 100 makes sure item is appended to list. [mark 2007-05-04]
        else:
            print "load_dfttyp_combox: Unknown GAMESS Version.  Loading GAMES DFT functionals."
            for f in gms_dfttyp_items:
                self.dfttyp_combox.insertItem(100, f)
                # 100 makes sure item is appended to list. [mark 2007-05-04]

    def _update_gbasis_list(self, val):
        """
        Add/remove AM1 and PM3 to/from the gbasis list. 
        """
        citem = self.gbasis_combox.currentIndex()
        if val == DFT or val == MP2:
            if self.gbasis_combox.count() == 18:
                self.gbasis_combox.removeItem(0)
                self.gbasis_combox.removeItem(0)
                self.gbasis_combox.setCurrentIndex(max(0, citem - 2))
        else:
            if self.gbasis_combox.count() != 18:
                self.gbasis_combox.insertItem(
                    0, "PM3")  # 0 prepends item to list.
                self.gbasis_combox.insertItem(0, "AM1")
                self.gbasis_combox.setCurrentIndex(citem + 2)

    def _save_ui_settings(self):
        """
        Save the UI settings in the Gamess jig pset.  
        There is one setting for each pset.
        """
        self.pset.ui.comment = str(self.comment_linedit.text())  # Description
        self.pset.ui.runtyp = self.runtyp_combox.currentIndex(
        )  # RUNTYP = Energy or Optimize

        # Electronic Structure Props and Basis Set section.
        self.pset.ui.scftyp = self.scftyp_btngrp.checkedId(
        )  # SCFTYP = RHF, UHF, or ROHF
        self.pset.ui.icharg = self.icharg_spinbox.value()  # Charge
        self.pset.ui.mult = self.multi_combox.currentIndex()  # Multiplicity

        # System Memory and Usage
        self.pset.ui.memory = self.memory_spinbox.value()  # Memory
        self.pset.ui.dirscf = self.dirscf_checkbox.isChecked()  # DIRSCF

        # Electron Correlation Method
        self.pset.ui.ecm = self.ecm_btngrp.checkedId()  # None, DFT or MP2
        #self.pset.ui.inttyp = self.ecm_btngrp.selectedId() # INTTYP
        self.pset.ui.gbasis = self.gbasis_combox.currentIndex()  # Basis Set
        self.pset.ui.gbasisname = str(self.gbasis_combox.currentText())
        self.pset.ui.dfttyp = self.dfttyp_combox.currentIndex(
        )  # DFT Functional Type
        self.pset.ui.gridsize = self.gridsize_combox.currentIndex(
        )  # Grid Size
        self.pset.ui.ncore = self.core_electrons_checkbox.isChecked(
        )  # Include core electrons

        # Convergence Criteria
        self.pset.ui.conv = self.density_conv_combox.currentIndex(
        )  # Density Convergence
        self.pset.ui.rmsdconv = self.rmsd_combox.currentIndex(
        )  # RMSD Convergence
        self.pset.ui.iterations = self.iterations_spinbox.value()  # Iterations

#        self.pset.ui.extrap = self.extrap_checkbox.isChecked() # EXTRAP
#        self.pset.ui.damp = self.damp_checkbox.isChecked() # DAMP
#        self.pset.ui.diis = self.diis_checkbox.isChecked() # DIIS
#        self.pset.ui.shift = self.shift_checkbox.isChecked() # SHIFT
#        self.pset.ui.soscf = self.soscf_checkbox.isChecked() # SOSCF
#        self.pset.ui.rstrct = self.rstrct_checkbox.isChecked() # RSTRCT

    def _save_job_parms(self):
        calculate = ['Energy', 'Optimization']
        self.job.Calculation = calculate[self.pset.ui.runtyp]
        self.job.Description = self.pset.ui.comment
        self.job.server = self.server
        ##Copy some  attributes from the server object to job description
        self.job.Server_id = self.server.server_id
        self.job.Engine = self.server.engine

    ######End of private or helper methods.########################

    ###### Unused methods ###############

    def openServerManager(self):
        """
        Pop up ServerManagerDialog to edit the properties of the servers.
        """
        self.sManager.showDialog(self.server)
        self.servers = self.sManager.getServers()
        self._reloadServerList()

    def serverChanged(self, si):
        """
        User has changed server, so update the DFT comboBox. Currently not used.
        """
        self.server = self.servers[si]
        self._load_dfttyp_combox()

    ###### End of unused methods ###############

    ##########Slot methods for some GUI controls################

    def calculate_changed(self, val):
        """
        """
        if val == 0:  # Energy
            self.rmsd_lbl.setEnabled(0)
            self.rmsd_combox.setEnabled(0)
            self.iterations_lbl.setEnabled(0)
            self.iterations_spinbox.setEnabled(0)
#            self.extrap_checkbox.setEnabled(0)
#            self.rstrct_checkbox.setEnabled(0)
#            self.damp_checkbox.setEnabled(0)
#            self.diis_checkbox.setEnabled(0)
#            self.shift_checkbox.setEnabled(0)
#            self.soscf_checkbox.setEnabled(0)
        else:  # Optimization
            self.rmsd_lbl.setEnabled(1)
            self.rmsd_combox.setEnabled(1)
            self.iterations_lbl.setEnabled(1)
            self.iterations_spinbox.setEnabled(1)
#            self.extrap_checkbox.setEnabled(1)
#            self.rstrct_checkbox.setEnabled(1)
#            self.damp_checkbox.setEnabled(1)
#            self.diis_checkbox.setEnabled(1)
#            self.shift_checkbox.setEnabled(1)
#            self.soscf_checkbox.setEnabled(1)

    def set_multiplicity(self, val):
        """
        Enable/disable widgets when user changes Multiplicity.
        """
        if val != 0:
            qt4todo("if scftyp[self.scftyp_btngrp.selectedId()] != 'RHF':")
            #if scftyp[self.scftyp_btngrp.selectedId()] != 'RHF':
            #    self.rhf_radiobtn.setEnabled(0)
            #    return

            ret = QMessageBox.warning(
                self, "Multiplicity Conflict",
                "If Multiplicity is greater than 1, then <b>UHF</b> or <b>ROHF</b> must be selected.\n"
                "Select Cancel to keep <b>RHF</b>.", "&UHF", "&ROHF", "Cancel",
                0, 2)

            if ret == 0:  # UHF
                self.uhf_radiobtn.toggle()
                self.rhf_radiobtn.setEnabled(0)

            elif ret == 1:  # ROHF
                self.rohf_radiobtn.toggle()
                self.rhf_radiobtn.setEnabled(0)

            elif ret == 2:  # Cancel
                self.multi_combox.setCurrentIndex(0)

        elif val == 0:
            self.rhf_radiobtn.setEnabled(1)

    def set_ecmethod(self, val):
        """
        Enable/disable widgets when user changes Electron Correlation Method.
        """
        #print "set_ecmethod = ", val
        if val == DFT:
            self.dfttyp_label.setEnabled(1)
            self.dfttyp_combox.setEnabled(1)
            self.gridsize_label.setEnabled(1)
            self.gridsize_combox.setEnabled(1)
            self.core_electrons_checkbox.setChecked(0)
            self.core_electrons_checkbox.setEnabled(0)

        elif val == MP2:
            self.core_electrons_checkbox.setEnabled(1)
            self.dfttyp_label.setEnabled(0)
            self.dfttyp_combox.setEnabled(0)
            self.gridsize_label.setEnabled(0)
            self.gridsize_combox.setEnabled(0)

        else:  # None = Hartree-Fock
            self.dfttyp_label.setEnabled(0)
            self.dfttyp_combox.setEnabled(0)
            self.gridsize_label.setEnabled(0)
            self.gridsize_combox.setEnabled(0)
            self.core_electrons_checkbox.setChecked(0)
            self.core_electrons_checkbox.setEnabled(0)

        # AM1 and PM3 are not options for DFT or MP2.
        # We have to remove or add them from the combo box.
        self._update_gbasis_list(val)

    def open_tmp_inputfile(self):
        """
        Writes a temporary GAMESS inputfile of the current Gamess jig and opens the
        file in an editor.
        """
        # Make tmp_inputfile filename (i.e. ~/Nanorex/temp/jigname_parms_info.inp)
        from platform_dependent.PlatformDependent import find_or_make_Nanorex_subdir
        tmpdir = find_or_make_Nanorex_subdir('temp')
        basename = self.gamessJig.name + "-" + self.gamessJig.gms_parms_info(
            '_')
        tmp_inputfile = os.path.join(tmpdir, "%s.inp" % basename)

        # Write INP file (in ~/Nanorex/temp subdirectory)
        from analysis.GAMESS.files_gms import writegms_inpfile
        writegms_inpfile(tmp_inputfile, self.gamessJig)

        from platform_dependent.PlatformDependent import open_file_in_editor
        open_file_in_editor(tmp_inputfile)

    def run_job(self):
        """
        Slot method for the 'Save and Run' button 
        """
        self.accept()

        # Run GAMESS job.  Return value r:
        # 0 = success
        # 1 = job cancelled
        # 2 = job failed.
        r = self.job.launch()

        if r == 1:  # Job was cancelled
            env.history.message(redmsg("GAMESS job cancelled."))
            return

        if r == 2:  # Job failed.
            env.history.message(
                redmsg(
                    "GAMESS job failed. Maybe you didn't set the right Gamess executable file. Make sure you can run the same job manually."
                ))
            return

        # Job success.
        fn = self.gamessJig.outputfile

        # Print energy or move atoms
        if self.pset.ui.runtyp == 0:  #Energy
            self.gamessJig.print_energy()
        else:  # Optimize
            try:
                r = self.gamessJig.move_optimized_atoms()
                # r = insertgms(self.gamessJig.assy, fn)
            except:
                print_compact_traceback(
                    "GamessProp.run_job(): error reading GAMESS OUT file [%s]: "
                    % fn)
                env.history.message(
                    redmsg("Internal error while inserting GAMESS geometry: " +
                           fn))
            else:
                if r:
                    env.history.message(redmsg("Atoms not adjusted."))
                else:
                    self.gamessJig.assy.changed(
                    )  # The file and the part are not the same.
                    self.gamessJig.print_energy(
                    )  # Print the final energy from the optimize OUT file, too.
                    env.history.message("Atoms adjusted.")

    def change_jig_color(self):
        """
        Slot method to change the jig's color.
        """
        color = QColorDialog.getColor(self.jig_QColor, self)

        if color.isValid():
            self.jig_QColor = color
            self.jig_color_pixmap = get_widget_with_color_palette(
                self.jig_color_pixmap, self.jig_QColor)

            self.gamessJig.color = self.gamessJig.normcolor = QColor_to_RGBf(
                color)
            self.glpane.gl_update()

    def accept(self):
        """
        The slot method for the 'Save' button.
        """
        QDialog.accept(self)
        self.gamessJig.try_rename(self.name_linedit.text())
        self._save_ui_settings()
        self.gamessJig.update_gamess_parms(
        )  # Update all the GAMESS parameters.
        self._save_job_parms()
        if self.edit_input_file_cbox.isChecked():
            self.open_tmp_inputfile()

    def reject(self):
        """
        The slot method for the 'Cancel' button.
        """
        QDialog.reject(self)
        self.gamessJig.attr_update(
            self.jig_attrs)  # Restore attributes of the jig.
        # self.gamessJig.color = self.gamessJig.normcolor = self.original_normcolor
        self.gamessJig.cancelled = True
        self.glpane.gl_update()

    def whats_this(self):
        from PyQt4.Qt import QWhatsThis, QDialog
        QWhatsThis.enterWhatsThisMode()
Esempio n. 13
0
 def __init__(self, 
              parentWidget, 
              title        = '', 
              label = '',
              labelColumn = 0,
              buttonList   = [],
              checkedId    = -1,
              setAsDefault = False, 
              spanWidth   = True, 
              borders = True
              ):
     """
     Appends a PM_RadioButtonList widget to the bottom of I{parentWidget}, 
     the Property Manager dialog or group box.
     
     @param parentWidget: The parent group box containing this widget.
     @type  parentWidget: PM_GroupBox or PM_Dialog
     
     @param title: The group box title.
     @type  title: str
     
     @param label:      The label for the coordinate spinbox.
     @type  label:      str
     
     @param labelColumn: The column in the parentWidget's grid layout to 
                         which this widget's label will be added. 
                         The labelColum can only be E{0} or E{1}
     @type  labelColumn: int
             
     
     @param buttonList: A list of I{button info lists}. There is one button
                        info list for each radio button in the list. The 
                        button info list contains the following three items:
                        1). Button Id (int), 
                        2). Button text (str),
                        3). Button tool tip (str).
     @type  buttonList: list
     
     @param spanWidth: If True, the widget and its label will span the width
                      of the group box. Its label will appear directly above
                      the widget (unless the label is empty) and is left 
                      justified.
     @type  spanWidth: bool (default False)
     
     
     @param borders: If true (default), this widget will have borders displayed. 
                     otherwise the won't be any outside borders around the 
                     set of radio buttons this class provides
     @type borders: boolean
     """
     
     # Intializing label, labelColumn etc is needed before doing 
     # PM_GroupBox.__init__. This is done so that 
     # self.parentWidget.addPmWidget(self) done at the end of __init__
     # works properly. 
     # 'self.parentWidget.addPmWidget(self)' is done to avoid a bug where a 
     # groupbox is always appended as the 'last widget' when its 
     # parentWidget is also a groupbox. This is due to other PM widgets 
     #(e.g. PM_PushButton)add themselves to their parent widget in their 
     #__init__ using self.parentWidget.addPmWidget(self). So doing the
     #same thing here. More general fix is needed in PM_GroupBox code
     # --Ninad 2007-11-14 (comment copied from PM_coordinateSpinBoxes)
     self.label = label
     self.labelColumn = labelColumn
     self.spanWidth = spanWidth
     
     if label: # Create this widget's QLabel.
         self.labelWidget = QLabel()
         self.labelWidget.setText(label)
         
     
     PM_GroupBox.__init__(self, parentWidget, title)
     
     # These are needed to properly maintain the height of the grid if 
     # all buttons in a row are hidden via hide().
     self.vBoxLayout.setMargin(0)
     self.vBoxLayout.setSpacing(0)
     
     self.buttonGroup = QButtonGroup()
     self.buttonGroup.setExclusive(True)
     
     self.parentWidget = parentWidget
     self.buttonList   = buttonList
     
     if setAsDefault:
         self.setDefaultCheckedId(checkedId)
     
     self.buttonsById   = {}
     self.buttonsByText = {}
         
     # Create radio button list from button info.
     for buttonInfo in buttonList:
         buttonId       = buttonInfo[0]
         buttonText     = buttonInfo[1]
         buttonToolTip  = buttonInfo[2]
         
         button = QRadioButton(self)
         
         button.setText(buttonText)
         button.setToolTip(buttonToolTip) # Not working.
         button.setCheckable(True)
         if checkedId == buttonId:
             button.setChecked(True)
         self.buttonGroup.addButton(button, buttonId)
         self.vBoxLayout.addWidget(button)
         
         self.buttonsById[buttonId]    = button
         self.buttonsByText[buttonText] = button
         
     if isinstance(self.parentWidget, PM_GroupBox):
         self.parentWidget.addPmWidget(self)
     else:   
         #@@ Should self be added to self.parentWidget's widgetList?
         #don't know. Retaining old code -- Ninad 2008-06-23
         self._widgetList.append(self)            
         self._rowCount += 1
     
     if not borders:
         #reset the style sheet so that there are no borders around the 
         #radio button set this class provides. 
         self.setStyleSheet(self._getAlternateStyleSheet())
class PM_ToolButtonGrid(PM_WidgetGrid):
    """
    The PM_ToolButtonGrid widget provides a grid of tool buttons that function
    as an I{exclusive button group}.
    
    @see: B{PM_ElementChooser} for an example of how this is used.
    
    @todo: Fix button size issue (e.g. all buttons are sized 32 x 32).
    """

    buttonList = []
    defaultCheckedId = -1  # -1 means no checked Id
    setAsDefault = True

    def __init__(self,
                 parentWidget,
                 title='',
                 buttonList=[],
                 alignment=None,
                 label='',
                 labelColumn=0,
                 spanWidth=True,
                 checkedId=-1,
                 setAsDefault=False,
                 isAutoRaise=False,
                 isCheckable=True):
        """
        Appends a PM_ToolButtonGrid widget to the bottom of I{parentWidget}, 
        the Property Manager Group box.
        
        @param parentWidget: The parent group box containing this widget.
        @type  parentWidget: PM_GroupBox
        
        @param title: The group box title.
        @type  title: str
        
        @param buttonList: A list of I{button info lists}. There is one button
                           info list for each button in the grid. The button
                           info list contains the following items:
                           1. Button Type - in this case its 'ToolButton'(str),
                           2. Button Id (int), 
                           3. Button text (str),
                           4. Button icon path (str),
                           5. Button tool tip (str),
                           6. Column (int), 
                           7. Row (int).
        @type  buttonList: list
        
        @param alignment:  The alignment of the toolbutton row in the parent 
                           groupbox. Based on its value,spacer items is added 
                           to the grid layout of the parent groupbox. 
        @type  alignment:  str
        
        @param label:      The label for the toolbutton row. If present, it is 
                           added to the same grid layout as the rest of the 
                           toolbuttons, in column number E{0}.
        @type  label:      str
        
        @param labelColumn: The column in the parentWidget's grid layout to which
                            this widget's label will be added. The labelColum
                            can only be E{0} or E{1}
        @type  labelColumn: int
        
        @param spanWidth: If True, the widget and its label will span the width
                      of the group box. Its label will appear directly above
                      the widget (unless the label is empty) and is left justified.
        @type  spanWidth: bool (default False)
                
        @param checkedId:  Checked button id in the button group. Default value
                           is -1 that implies no button is checked. 
        @type  checkedId:  int
        
        @param setAsDefault: If True, sets the I{checkedId} specified by the
                            user as the  default checked
        @type  setAsDefault: boolean
        """

        self.buttonGroup = QButtonGroup()
        self.buttonGroup.setExclusive(True)

        self.isAutoRaise = isAutoRaise
        self.isCheckable = isCheckable
        self.buttonsById = {}
        self.buttonsByText = {}

        if setAsDefault:
            self.setDefaultCheckedId(checkedId)

        PM_WidgetGrid.__init__(self, parentWidget, title, buttonList,
                               alignment, label, labelColumn, spanWidth)

    def _createWidgetUsingParameters(self, widgetParams):
        """
        Returns a tool button created using the parameters specified by the user
        
        @param widgetParams: A list of label parameters. This is a modified
                             using the original list returned 
                             by L{self.getWidgetInfoList}. The modified list
                             doesn't contain the row and column information.
        @type  widgetParams: list
        @see:  L{PM_WidgetGrid._createWidgetUsingParameters} (overrided in this
               method)
        @see:  L{PM_WidgetGrid.loadWidgets} which calls this method. 
        
        """
        buttonFont = self.getButtonFont()
        buttonParams = list(widgetParams)

        button = self._createToolButton(buttonParams)

        buttonId = buttonParams[1]

        if self.defaultCheckedId == buttonId:
            button.setChecked(True)
        button.setFont(buttonFont)
        button.setAutoRaise(self.isAutoRaise)
        button.setCheckable(self.isCheckable)
        self.buttonGroup.addButton(button, buttonId)

        self.buttonsById[buttonId] = button
        self.buttonsByText[str(button.text())] = button

        return button

    def getButtonFont(self):
        """
        Returns the font for the tool buttons in the grid.
        
        @return: Button font.
        @rtype:  U{B{QFont}<http://doc.trolltech.com/4/qfont.html>}
        """
        # Font for tool buttons.
        buttonFont = QFont(self.font())
        buttonFont.setFamily(BUTTON_FONT)
        buttonFont.setPointSize(BUTTON_FONT_POINT_SIZE)
        buttonFont.setBold(BUTTON_FONT_BOLD)
        return buttonFont

    def restoreDefault(self):
        """
        Restores the default checkedId.
        """
        if self.setAsDefault:
            for buttonInfo in self.buttonList:
                buttonId = buttonInfo[0]
                if buttonId == self.defaultCheckedId:
                    button = self.getButtonById(buttonId)
                    button.setChecked(True)
        return

    def setDefaultCheckedId(self, checkedId):
        """
        Sets the default checked id (button) to I{checkedId}. The current checked
        button is unchanged.
                      
        @param checkedId: The new default id for the tool button group.
        @type  checkedId: int
        """
        self.setAsDefault = True
        self.defaultCheckedId = checkedId

    def checkedButton(self):
        """
        Returns the tool button group's checked button, or E{0} if no button is
        checked.
        @return: Checked tool button or E{0}
        @rtype:  instance of QToolButton  or int
        """
        return self.buttonGroup.checkedButton()

    def checkedId(self):
        """
        Returns the id of the checkedButton(), or -1 if no button is checked.
        
        @return: The checked button Id
        @rtype:  int
        """
        return self.buttonGroup.checkedId()

    def getButtonByText(self, text):
        """
        Returns the button with its current text set to I{text}.
        
        @return: The button, or B{None} if no button was found.
        @rtype:  U{B{QToolButton}<http://doc.trolltech.com/4/qtoolbutton.html>}
        
        @note: If multiple buttons have the same text, only the last one is returned.
        """
        if self.buttonsByText.has_key(text):
            return self.buttonsByText[text]
        else:
            return None

    def getButtonById(self, buttonId):
        """
        Returns the button with the button id of I{buttonId}.
        
        return: The button, or B{None} if no button was found.
        rtype:  U{B{QToolButton}<http://doc.trolltech.com/4/qtoolbutton.html>}
        """
        if self.buttonsById.has_key(buttonId):
            return self.buttonsById[buttonId]
        else:
            return None

    def setButtonSize(self, width=32, height=32):
        """
        """
        for btn in self.buttonGroup.buttons():
            btn.setFixedSize(QSize(width, height))
    def __init__(self,
                 parentWidget,
                 title='',
                 label='',
                 labelColumn=0,
                 buttonList=[],
                 checkedId=-1,
                 setAsDefault=False,
                 spanWidth=True,
                 borders=True):
        """
        Appends a PM_RadioButtonList widget to the bottom of I{parentWidget}, 
        the Property Manager dialog or group box.
        
        @param parentWidget: The parent group box containing this widget.
        @type  parentWidget: PM_GroupBox or PM_Dialog
        
        @param title: The group box title.
        @type  title: str
        
        @param label:      The label for the coordinate spinbox.
        @type  label:      str
        
        @param labelColumn: The column in the parentWidget's grid layout to 
                            which this widget's label will be added. 
                            The labelColum can only be E{0} or E{1}
        @type  labelColumn: int
                
        
        @param buttonList: A list of I{button info lists}. There is one button
                           info list for each radio button in the list. The 
                           button info list contains the following three items:
                           1). Button Id (int), 
                           2). Button text (str),
                           3). Button tool tip (str).
        @type  buttonList: list
        
        @param spanWidth: If True, the widget and its label will span the width
                         of the group box. Its label will appear directly above
                         the widget (unless the label is empty) and is left 
                         justified.
        @type  spanWidth: bool (default False)
        
        
        @param borders: If true (default), this widget will have borders displayed. 
                        otherwise the won't be any outside borders around the 
                        set of radio buttons this class provides
        @type borders: boolean
        """

        # Intializing label, labelColumn etc is needed before doing
        # PM_GroupBox.__init__. This is done so that
        # self.parentWidget.addPmWidget(self) done at the end of __init__
        # works properly.
        # 'self.parentWidget.addPmWidget(self)' is done to avoid a bug where a
        # groupbox is always appended as the 'last widget' when its
        # parentWidget is also a groupbox. This is due to other PM widgets
        #(e.g. PM_PushButton)add themselves to their parent widget in their
        #__init__ using self.parentWidget.addPmWidget(self). So doing the
        #same thing here. More general fix is needed in PM_GroupBox code
        # --Ninad 2007-11-14 (comment copied from PM_coordinateSpinBoxes)
        self.label = label
        self.labelColumn = labelColumn
        self.spanWidth = spanWidth

        if label:  # Create this widget's QLabel.
            self.labelWidget = QLabel()
            self.labelWidget.setText(label)

        PM_GroupBox.__init__(self, parentWidget, title)

        # These are needed to properly maintain the height of the grid if
        # all buttons in a row are hidden via hide().
        self.vBoxLayout.setMargin(0)
        self.vBoxLayout.setSpacing(0)

        self.buttonGroup = QButtonGroup()
        self.buttonGroup.setExclusive(True)

        self.parentWidget = parentWidget
        self.buttonList = buttonList

        if setAsDefault:
            self.setDefaultCheckedId(checkedId)

        self.buttonsById = {}
        self.buttonsByText = {}

        # Create radio button list from button info.
        for buttonInfo in buttonList:
            buttonId = buttonInfo[0]
            buttonText = buttonInfo[1]
            buttonToolTip = buttonInfo[2]

            button = QRadioButton(self)

            button.setText(buttonText)
            button.setToolTip(buttonToolTip)  # Not working.
            button.setCheckable(True)
            if checkedId == buttonId:
                button.setChecked(True)
            self.buttonGroup.addButton(button, buttonId)
            self.vBoxLayout.addWidget(button)

            self.buttonsById[buttonId] = button
            self.buttonsByText[buttonText] = button

        if isinstance(self.parentWidget, PM_GroupBox):
            self.parentWidget.addPmWidget(self)
        else:
            #@@ Should self be added to self.parentWidget's widgetList?
            #don't know. Retaining old code -- Ninad 2008-06-23
            self._widgetList.append(self)
            self._rowCount += 1

        if not borders:
            #reset the style sheet so that there are no borders around the
            #radio button set this class provides.
            self.setStyleSheet(self._getAlternateStyleSheet())
    def __init__(self,
                 parentWidget,
                 title='',
                 buttonList=[],
                 alignment=None,
                 label='',
                 labelColumn=0,
                 spanWidth=True,
                 checkedId=-1,
                 setAsDefault=False,
                 isAutoRaise=False,
                 isCheckable=True):
        """
        Appends a PM_ToolButtonGrid widget to the bottom of I{parentWidget}, 
        the Property Manager Group box.
        
        @param parentWidget: The parent group box containing this widget.
        @type  parentWidget: PM_GroupBox
        
        @param title: The group box title.
        @type  title: str
        
        @param buttonList: A list of I{button info lists}. There is one button
                           info list for each button in the grid. The button
                           info list contains the following items:
                           1. Button Type - in this case its 'ToolButton'(str),
                           2. Button Id (int), 
                           3. Button text (str),
                           4. Button icon path (str),
                           5. Button tool tip (str),
                           6. Column (int), 
                           7. Row (int).
        @type  buttonList: list
        
        @param alignment:  The alignment of the toolbutton row in the parent 
                           groupbox. Based on its value,spacer items is added 
                           to the grid layout of the parent groupbox. 
        @type  alignment:  str
        
        @param label:      The label for the toolbutton row. If present, it is 
                           added to the same grid layout as the rest of the 
                           toolbuttons, in column number E{0}.
        @type  label:      str
        
        @param labelColumn: The column in the parentWidget's grid layout to which
                            this widget's label will be added. The labelColum
                            can only be E{0} or E{1}
        @type  labelColumn: int
        
        @param spanWidth: If True, the widget and its label will span the width
                      of the group box. Its label will appear directly above
                      the widget (unless the label is empty) and is left justified.
        @type  spanWidth: bool (default False)
                
        @param checkedId:  Checked button id in the button group. Default value
                           is -1 that implies no button is checked. 
        @type  checkedId:  int
        
        @param setAsDefault: If True, sets the I{checkedId} specified by the
                            user as the  default checked
        @type  setAsDefault: boolean
        """

        self.buttonGroup = QButtonGroup()
        self.buttonGroup.setExclusive(True)

        self.isAutoRaise = isAutoRaise
        self.isCheckable = isCheckable
        self.buttonsById = {}
        self.buttonsByText = {}

        if setAsDefault:
            self.setDefaultCheckedId(checkedId)

        PM_WidgetGrid.__init__(self, parentWidget, title, buttonList,
                               alignment, label, labelColumn, spanWidth)
Esempio n. 17
0
 def setupUi(self):
     """
     Setup the UI for the command toolbar.
     """
     #ninad 070123 : It's important to set the Vertical size policy of the 
     # cmd toolbar widget. otherwise the flyout QToolbar messes up the 
     #layout (makes the command toolbar twice as big) 
     #I have set the vertical policy as fixed. Works fine. There are some 
     # MainWindow resizing problems for but those are not due to this 
     #size policy AFAIK        
     self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
             
     layout_cmdtoolbar = QHBoxLayout(self)
     layout_cmdtoolbar.setMargin(2)
     layout_cmdtoolbar.setSpacing(2)
     
     #See comment at the top for details about this flag
     if DEFINE_CONTROL_AREA_AS_A_QWIDGET:
         self.cmdToolbarControlArea = QWidget(self)    
     else:
         self.cmdToolbarControlArea = QToolBar_WikiHelp(self)
         
     self.cmdToolbarControlArea.setAutoFillBackground(True)
             
     self.ctrlAreaPalette = self.getCmdMgrCtrlAreaPalette()  
     self.cmdToolbarControlArea.setPalette(self.ctrlAreaPalette)
             
     self.cmdToolbarControlArea.setMinimumHeight(62)
     self.cmdToolbarControlArea.setMinimumWidth(380)
     self.cmdToolbarControlArea.setSizePolicy(QSizePolicy.Fixed, 
                                              QSizePolicy.Fixed)  
     
     #See comment at the top for details about this flag
     if DEFINE_CONTROL_AREA_AS_A_QWIDGET:
         layout_controlArea = QHBoxLayout(self.cmdToolbarControlArea)
         layout_controlArea.setMargin(0)
         layout_controlArea.setSpacing(0)
     
     self.cmdButtonGroup = QButtonGroup()    
     btn_index = 0
     
     for name in ('Build', 'Insert', 'Tools', 'Move', 'Simulation'):
         btn = QToolButton(self.cmdToolbarControlArea)           
         btn.setObjectName(name)
         btn.setMinimumWidth(75)
         btn.setMaximumWidth(75)
         btn.setMinimumHeight(62)
         btn.setAutoRaise(True)
         btn.setCheckable(True)
         btn.setAutoExclusive(True)
         iconpath = "ui/actions/Command Toolbar/ControlArea/" + name + ".png"
         btn.setIcon(geticon(iconpath))
         btn.setIconSize(QSize(22, 22))
         btn.setText(name)
         btn.setToolButtonStyle(Qt.ToolButtonTextUnderIcon)
         btn.setPalette(self.ctrlAreaPalette)
         self.cmdButtonGroup.addButton(btn, btn_index)
         btn_index += 1        
         #See comment at the top for details about this flag
         if DEFINE_CONTROL_AREA_AS_A_QWIDGET:
             layout_controlArea.addWidget(btn)
         else:
             self.cmdToolbarControlArea.layout().addWidget(btn)                
             #following has issues. so not adding widget directly to the 
             #toolbar. (instead adding it in its layout)-- ninad 070124
             ##self.cmdToolbarControlArea.addWidget(btn)      
     
     layout_cmdtoolbar.addWidget(self.cmdToolbarControlArea) 
     
     #Flyout Toolbar in the command toolbar  
     self.flyoutToolBar = FlyoutToolBar(self)
     
     layout_cmdtoolbar.addWidget(self.flyoutToolBar)   
     
     #ninad 070116: Define a spacer item. It will have the exact geometry 
     # as that of the flyout toolbar. it is added to the command toolbar 
     # layout only when the Flyout Toolbar is hidden. It is required
     # to keep the 'Control Area' widget fixed in its place (otherwise, 
     #after hiding the flyout toolbar, the layout adjusts the position of 
     #remaining widget items) 
     
     self.spacerItem = QSpacerItem(0, 
                                   0, 
                                   QtGui.QSizePolicy.Expanding, 
                                   QtGui.QSizePolicy.Minimum)
     self.spacerItem.setGeometry = self.flyoutToolBar.geometry()
     
     for btn in self.cmdButtonGroup.buttons():
         if str(btn.objectName()) == 'Build':
             btn.setMenu(self.win.buildStructuresMenu)
             btn.setPopupMode(QToolButton.MenuButtonPopup)
             btn.setToolTip("Build Commands")
             whatsThisTextForCommandToolbarBuildButton(btn)
         if str(btn.objectName()) == 'Insert':
             btn.setMenu(self.win.insertMenu)
             btn.setPopupMode(QToolButton.MenuButtonPopup)
             btn.setToolTip("Insert Commands")
             whatsThisTextForCommandToolbarInsertButton(btn)
         if str(btn.objectName()) == 'Tools':
             #fyi: cmd stands for 'command toolbar' - ninad070406
             self.win.cmdToolsMenu = QtGui.QMenu(self.win)
             self.win.cmdToolsMenu.addAction(self.win.toolsExtrudeAction) 
             self.win.cmdToolsMenu.addAction(self.win.toolsFuseChunksAction)
             self.win.cmdToolsMenu.addSeparator()
             self.win.cmdToolsMenu.addAction(self.win.modifyMergeAction)
             self.win.cmdToolsMenu.addAction(self.win.modifyMirrorAction)
             self.win.cmdToolsMenu.addAction(self.win.modifyInvertAction)
             self.win.cmdToolsMenu.addAction(self.win.modifyStretchAction)
             btn.setMenu(self.win.cmdToolsMenu)
             btn.setPopupMode(QToolButton.MenuButtonPopup)
             btn.setToolTip("Tools")
             whatsThisTextForCommandToolbarToolsButton(btn)
         if str(btn.objectName()) == 'Move':
             self.win.moveMenu = QtGui.QMenu(self.win)
             self.win.moveMenu.addAction(self.win.toolsMoveMoleculeAction)
             self.win.moveMenu.addAction(self.win.rotateComponentsAction)
             self.win.moveMenu.addSeparator()
             self.win.moveMenu.addAction(
                 self.win.modifyAlignCommonAxisAction)
             ##self.win.moveMenu.addAction(\
             ##    self.win.modifyCenterCommonAxisAction)
             btn.setMenu(self.win.moveMenu)
             btn.setPopupMode(QToolButton.MenuButtonPopup)
             btn.setToolTip("Move Commands")
             whatsThisTextForCommandToolbarMoveButton(btn)
         if str(btn.objectName()) == 'Dimension':
             btn.setMenu(self.win.dimensionsMenu)
             btn.setPopupMode(QToolButton.MenuButtonPopup)
             btn.setToolTip("Dimensioning Commands")
         if str(btn.objectName()) == 'Simulation':
             btn.setMenu(self.win.simulationMenu)
             btn.setPopupMode(QToolButton.MenuButtonPopup)
             btn.setToolTip("Simulation Commands")
             whatsThisTextForCommandToolbarSimulationButton(btn)
         
         # Convert all "img" tags in the button's "What's This" text 
         # into abs paths (from their original rel paths).
         # Partially fixes bug 2943. --mark 2008-12-07
         # [bruce 081209 revised this -- removed mac = False]
         fix_QAction_whatsthis(btn)
     return
Esempio n. 18
0
    def __init__(self, win):
        QDialog.__init__(self, win)  # win is parent.
        self.setupUi(self)
        self.watch_motion_buttongroup = QButtonGroup()
        self.watch_motion_buttongroup.setExclusive(True)
        for obj in self.watch_motion_groupbox.children():
            if isinstance(obj, QAbstractButton):
                self.watch_motion_buttongroup.addButton(obj)

        #fix some icon problems
        self.setWindowIcon(
            geticon('ui/border/MinimizeEnergy.png'))

        self.connect(self.cancel_btn,
                     SIGNAL("clicked()"),
                     self.cancel_btn_clicked)
        self.connect(self.ok_btn,
                     SIGNAL("clicked()"),
                     self.ok_btn_clicked)
        self.connect(self.restore_btn,
                     SIGNAL("clicked()"),
                     self.restore_defaults_btn_clicked)

        self.whatsthis_btn.setIcon(
            geticon('ui/actions/Properties Manager/WhatsThis.png'))
        self.whatsthis_btn.setIconSize(QSize(22, 22))
        self.whatsthis_btn.setToolTip('Enter "What\'s This?" help mode')

        self.connect(self.whatsthis_btn,
                     SIGNAL("clicked()"),
                     QWhatsThis.enterWhatsThisMode)

        connect_checkbox_with_boolean_pref(
            self.electrostaticsForDnaDuringMinimize_checkBox,
            electrostaticsForDnaDuringMinimize_prefs_key)

        connect_checkbox_with_boolean_pref(
            self.enableNeighborSearching_check_box,
            neighborSearchingInGromacs_prefs_key)

        self.connect(self.minimize_engine_combobox, SIGNAL("activated(int)"), self.update_minimize_engine)

        self.minimize_engine_combobox.setCurrentIndex(
            env.prefs[Minimize_minimizationEngine_prefs_key])

        self.connect(self.endRmsDoubleSpinBox, SIGNAL("valueChanged(double)"), self.changeEndRms)
        self.connect(self.endMaxDoubleSpinBox, SIGNAL("valueChanged(double)"), self.changeEndMax)
        self.connect(self.cutoverRmsDoubleSpinBox, SIGNAL("valueChanged(double)"), self.changeCutoverRms)
        self.connect(self.cutoverMaxDoubleSpinBox, SIGNAL("valueChanged(double)"), self.changeCutoverMax)

        self.endRmsDoubleSpinBox.setSpecialValueText("Automatic")
        self.endMaxDoubleSpinBox.setSpecialValueText("Automatic")
        self.cutoverRmsDoubleSpinBox.setSpecialValueText("Automatic")
        self.cutoverMaxDoubleSpinBox.setSpecialValueText("Automatic")

        self.win = win
        self.previousParams = None
        self.setup_ruc()
        self.seltype = 'All'
        self.minimize_selection_enabled = True #bruce 080513

        # Assign "What's This" text for all widgets.
        from commands.MinimizeEnergy.WhatsThisText_for_MinimizeEnergyDialog import whatsThis_MinimizeEnergyDialog
        whatsThis_MinimizeEnergyDialog(self)

        self.update_widgets() # to make sure self attrs are set
        return
Esempio n. 19
0
        def __init__(self, dirname, purrlogs, parent=None, create=None, message=None):
            QWizardPage.__init__(self, parent)
            self.dirname = dirname
            self.purrlogs = purrlogs or []
            bg = QButtonGroup(self)
            lo = QVBoxLayout()
            self.setLayout(lo)
            # set page titles
            self.setTitle("Starting PURR")
            message and self.setSubTitle(message)
            if not purrlogs:
                self.rbs_log = []
            else:
                # add options for existing purrlogs
                self.rbs_log = [QRadioButton("Load %s" % Kittens.utils.collapseuser(log)) for log in purrlogs]
                for rb in self.rbs_log:
                    lo.addWidget(rb)
                    bg.addButton(rb)
                    QObject.connect(rb, SIGNAL("toggled(bool)"), self.checkCompleteness)
                self.rbs_log[0].setChecked(True)
            # add option to load another purrlog
            lo1 = QHBoxLayout()
            self.rb_other = QRadioButton("Load purrlog from:")
            lo1.addWidget(self.rb_other)
            bg.addButton(self.rb_other)
            self.wother = QLineEdit()
            self.wother.setReadOnly(True)
            lo1.addWidget(self.wother, 1)
            pb = QPushButton(pixmaps.folder_open.icon(), "")
            QObject.connect(pb, SIGNAL("clicked()"), self._select_other_dialog)
            QObject.connect(self.rb_other, SIGNAL("toggled(bool)"), pb.setEnabled)
            QObject.connect(self.rb_other, SIGNAL("toggled(bool)"), self.wother.setEnabled)
            QObject.connect(self.rb_other, SIGNAL("toggled(bool)"), self.checkCompleteness)
            pb.setEnabled(False)
            self.wother.setEnabled(False)
            lo1.addWidget(pb)
            lo.addLayout(lo1)
            self.load_path = None

            # add option to create new purrlog
            lo1 = QHBoxLayout()
            self.rb_create = QRadioButton("Create new purrlog:")
            lo1.addWidget(self.rb_create)
            bg.addButton(self.rb_create)
            self.wcreate = QLineEdit()
            lo1.addWidget(self.wcreate, 1)
            pb = QPushButton(pixmaps.folder_open.icon(), "")
            QObject.connect(pb, SIGNAL("clicked()"), self._select_create_dialog)
            QObject.connect(self.rb_create, SIGNAL("toggled(bool)"), pb.setEnabled)
            QObject.connect(self.rb_create, SIGNAL("toggled(bool)"), self.wcreate.setEnabled)
            QObject.connect(self.rb_create, SIGNAL("toggled(bool)"), self.checkCompleteness)
            QObject.connect(self.wcreate, SIGNAL("editingFinished()"), self._validate_create_filename)
            pb.setEnabled(False)
            self.wcreate.setEnabled(False)
            # this holds the last validated name
            self._validated_create_path = None
            self._validated_result = False
            # generate default name for a new purrlog
            self.create_path = os.path.join(dirname, "purrlog")
            num = 0
            while os.path.exists(self.create_path):
                self.create_path = os.path.join(dirname, "purrlog.%d" % num)
                num += 1
            # This will be not None as long as a valid name is entered
            self.create_path = Kittens.utils.collapseuser(os.path.normpath(self.create_path))
            if create:
                self.wcreate.setText(create or Kittens.utils.collapseuser(create))
                # this will emit checkCompleteness(), causing a _validate_create_filename() call, causing the content of the wcreate widget
                # to be validated and copied to create_path if valid, or reset from create_path if invalid
                self.rb_create.setChecked(True)
            else:
                self.wcreate.setText(self.create_path)

            lo1.addWidget(pb)
            lo.addLayout(lo1)

            # make create option default, if no purrlogs
            if not purrlogs:
                self.rb_create.setChecked(True)