コード例 #1
0
ファイル: MMKit.py プロジェクト: alaindomissy/nanoengineer
    def _setNewView(self, viewClassName):
        # Put the GL widget inside the frame
        if not self.flayout:
            self.flayout = QVBoxLayout(self.elementFrame)
            self.flayout.setMargin(1)
            self.flayout.setSpacing(1)
        else:
            if self.elemGLPane:
                self.flayout.removeChild(self.elemGLPane)
                self.elemGLPane = None

        if viewClassName == 'ChunkView':
            # We never come here! How odd.
            self.elemGLPane = ChunkView(self.elementFrame, "chunk glPane", self.w.glpane)
        elif viewClassName == 'MMKitView':
            self.elemGLPane = MMKitView(self.elementFrame, "MMKitView glPane", self.w.glpane)

        self.flayout.addWidget(self.elemGLPane,1)


        #ninad 070326. Note that self.DirView inherits QTreeView.
        #It has got nothing to do with the experimental class DirView in file Dirview.py
        self.dirView = self.DirView(self, self.libraryPage)
        self.dirView.setSortingEnabled(False) #bruce 070521 changed True to False -- fixes "reverse order" bug on my Mac
        ##self.dirView.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOn)

        libraryPageLayout = QVBoxLayout(self.libraryPage)
        libraryPageLayout.setMargin(pmMMKitPageMargin) # Was 4. Mark 2007-05-30
        libraryPageLayout.setSpacing(2)
        libraryPageLayout.addWidget(self.dirView)


        filePath = os.path.dirname(os.path.abspath(sys.argv[0]))
        libDir = os.path.normpath(filePath + '/../partlib')

        self.libPathKey = '/nanorex/nE-1/libraryPath'
        libDir = env.prefs.get(self.libPathKey, libDir)

        if os.path.isdir(libDir):
            self.rootDir = libDir
            self.dirView.setRootPath(libDir)
        else:
            self.rootDir = None
            from history.HistoryWidget import redmsg
            env.history.message(redmsg("The part library directory: %s doesn't exist." %libDir))
コード例 #2
0
    def _loadPreviewGroupBox(self):
        """
        Load the L{self.elementViewer} widget inside this preview groupbox.  
        @attention: The L{self.elementViewer} widget is added to 
                    L{self.previewGroupBox.gridLayout} in L{Thumbview.__init__}. 
                    Based on  tests, it takes longer cpu time to complete this 
                    operation (adding QGLWidget to a gridlayout. By doing this
                    inside L{Thumbview.__init__}, a time gain of ~ 0.1 sec 
                    was noticed on Windows XP. 
        """

        self.elementViewer = MMKitView(self, "MMKitView glPane", self.glpane)
        self.elementViewer.setMinimumSize(QSize(150, 150))

        self.gridLayout.setMargin(0)
        self.gridLayout.setSpacing(0)
        #Append to the widget list. This is important for expand - collapse
        #functions (of the groupbox) to work properly.
        self._widgetList.append(self.elementViewer)
コード例 #3
0
 def _loadPreviewGroupBox(self):
     """
     Load the L{self.elementViewer} widget inside this preview groupbox.  
     @attention: The L{self.elementViewer} widget is added to 
                 L{self.previewGroupBox.gridLayout} in L{Thumbview.__init__}. 
                 Based on  tests, it takes longer cpu time to complete this 
                 operation (adding QGLWidget to a gridlayout. By doing this
                 inside L{Thumbview.__init__}, a time gain of ~ 0.1 sec 
                 was noticed on Windows XP. 
     """
           
     self.elementViewer = MMKitView(
                     self, 
                     "MMKitView glPane", 
                     self.glpane)
     self.elementViewer.setMinimumSize(QSize(150, 150))
     
     self.gridLayout.setMargin(0)
     self.gridLayout.setSpacing(0) 
     #Append to the widget list. This is important for expand - collapse 
     #functions (of the groupbox) to work properly. 
     self._widgetList.append(self.elementViewer)                   
コード例 #4
0
class PM_PreviewGroupBox(PM_GroupBox):
    """
    The PM_PreviewGroupBox widget provides a preview pane for previewing 
    elements , clipboard items , library parts etc. from the element chooser
    or list provided in the property manager. (The object being previewed can 
    then be deposited into the 3D workspace.)
    """
    elementViewer = None
    def __init__(self, 
                 parentWidget,
                 glpane = None,
                 title = 'Preview'
                 ):
        """
        Appends a PM_PreviewGroupBox widget to I{parentWidget},a L{PM_Dialog}
                
        @param parentWidget: The parent dialog (Property manager) containing 
                             this  widget.
        @type  parentWidget: L{PM_Dialog}
        
        @param glpane: GLPane object used in construction of the 
                       L{self.elementViewer}
        @type  glpane: L{GLPane} or None
        
        @param title: The title (button) text.
        @type  title: str      
        
        """
        PM_GroupBox.__init__(self, parentWidget, title)
        
        self.glpane = glpane 
        self.parentWidget = parentWidget        
        self._loadPreviewGroupBox()
       
    def _loadPreviewGroupBox(self):
        """
        Load the L{self.elementViewer} widget inside this preview groupbox.  
        @attention: The L{self.elementViewer} widget is added to 
                    L{self.previewGroupBox.gridLayout} in L{Thumbview.__init__}. 
                    Based on  tests, it takes longer cpu time to complete this 
                    operation (adding QGLWidget to a gridlayout. By doing this
                    inside L{Thumbview.__init__}, a time gain of ~ 0.1 sec 
                    was noticed on Windows XP. 
        """
              
        self.elementViewer = MMKitView(
                        self, 
                        "MMKitView glPane", 
                        self.glpane)
        self.elementViewer.setMinimumSize(QSize(150, 150))
        
        self.gridLayout.setMargin(0)
        self.gridLayout.setSpacing(0) 
        #Append to the widget list. This is important for expand - collapse 
        #functions (of the groupbox) to work properly. 
        self._widgetList.append(self.elementViewer)                   
        ##self.previewGroupBox.gridLayout.addWidget(self.elementViewer, 
        ##                                          0, 0, 1, 1)
    
       
    def expand(self):
        """
        Expand this group box i.e. show all its contents and change the look 
        and feel of the groupbox button. It also sets the gridlayout margin and
        spacing to 0. (necessary to get rid of the extra space inside the 
        groupbox.)       
        
        @see: L{PM_GroupBox.expand}
        """
        PM_GroupBox.expand(self)
        self.gridLayout.setMargin(0)
        self.gridLayout.setSpacing(0)
コード例 #5
0
class PM_PreviewGroupBox(PM_GroupBox):
    """
    The PM_PreviewGroupBox widget provides a preview pane for previewing 
    elements , clipboard items , library parts etc. from the element chooser
    or list provided in the property manager. (The object being previewed can 
    then be deposited into the 3D workspace.)
    """
    elementViewer = None

    def __init__(self, parentWidget, glpane=None, title='Preview'):
        """
        Appends a PM_PreviewGroupBox widget to I{parentWidget},a L{PM_Dialog}
                
        @param parentWidget: The parent dialog (Property manager) containing 
                             this  widget.
        @type  parentWidget: L{PM_Dialog}
        
        @param glpane: GLPane object used in construction of the 
                       L{self.elementViewer}
        @type  glpane: L{GLPane} or None
        
        @param title: The title (button) text.
        @type  title: str      
        
        """
        PM_GroupBox.__init__(self, parentWidget, title)

        self.glpane = glpane
        self.parentWidget = parentWidget
        self._loadPreviewGroupBox()

    def _loadPreviewGroupBox(self):
        """
        Load the L{self.elementViewer} widget inside this preview groupbox.  
        @attention: The L{self.elementViewer} widget is added to 
                    L{self.previewGroupBox.gridLayout} in L{Thumbview.__init__}. 
                    Based on  tests, it takes longer cpu time to complete this 
                    operation (adding QGLWidget to a gridlayout. By doing this
                    inside L{Thumbview.__init__}, a time gain of ~ 0.1 sec 
                    was noticed on Windows XP. 
        """

        self.elementViewer = MMKitView(self, "MMKitView glPane", self.glpane)
        self.elementViewer.setMinimumSize(QSize(150, 150))

        self.gridLayout.setMargin(0)
        self.gridLayout.setSpacing(0)
        #Append to the widget list. This is important for expand - collapse
        #functions (of the groupbox) to work properly.
        self._widgetList.append(self.elementViewer)
        ##self.previewGroupBox.gridLayout.addWidget(self.elementViewer,
        ##                                          0, 0, 1, 1)

    def expand(self):
        """
        Expand this group box i.e. show all its contents and change the look 
        and feel of the groupbox button. It also sets the gridlayout margin and
        spacing to 0. (necessary to get rid of the extra space inside the 
        groupbox.)       
        
        @see: L{PM_GroupBox.expand}
        """
        PM_GroupBox.expand(self)
        self.gridLayout.setMargin(0)
        self.gridLayout.setSpacing(0)
コード例 #6
0
ファイル: MMKit.py プロジェクト: alaindomissy/nanoengineer
class MMKit(QDialog,
            Ui_MMKitDialog,
            PropertyManagerMixin,
            SponsorableMixin):
    """
    THIS CLASS HAS BEEN DEPRECATED.
    SEE NEW IMPLEMETATION IN--
    Ui_BuildAtomsPropertyManager.py,
    BuildAtomsPropertyManager.py,
    Ui_PartLibPropertyManager.py,
    PartLibPropertyManager.py,
    Ui_PastePropertyManager.py
    PastePropertyManager.py

    Provide the MMKit PM for Build Atoms mode.
    """
    # <title> - the title that appears in the property manager header.
    title = "Build Atoms"
    # <iconPath> - full path to PNG file that appears in the header.
    iconPath = "ui/actions/Tools/Build Structures/Build Atoms.png"

    bond_id2name =['sp3', 'sp2', 'sp', 'sp2(graphitic)']
    sponsor_keyword = 'Build'

    def __init__(self, parentMode, win):
        QDialog.__init__(self, win, Qt.Dialog)# Qt.WStyle_Customize | Qt.WStyle_Tool | Qt.WStyle_Title | Qt.WStyle_NoBorder)

        self.w = win
        self.o = self.w.glpane

        #@NOTE: As of 20070717, MMKit supports only depositMode as its parent
        #(and perhaps subclasses of depositMode ..but such a class that also
        #uses MMKit is NIY so it is unconfirmed)  -- ninad
        self.parentMode = parentMode

        self.setupUi(self)

        # setupUi() did not add the icon or title. We do that here.
        pmSetPropMgrIcon( self, self.iconPath )
        pmSetPropMgrTitle( self, self.title )

        #self.connect(self.hybrid_btngrp,SIGNAL("buttonClicked(int)"),self.set_hybrid_type)

        self.pw = None # pw = partwindow

        self.connect(self.mmkit_tab,
                     SIGNAL("currentChanged(int)"),
                     self.tabCurrentChanged)

        self.connect(self.chunkListBox,
                     SIGNAL("currentItemChanged(QListWidgetItem*,QListWidgetItem*)"),
                     self.chunkChanged)
        self.connect(self.browseButton,
                     SIGNAL("clicked(bool)"),
                     self.browseDirectories)
        self.connect(self.defaultPartLibButton,
                     SIGNAL("clicked(bool)"),
                     self.useDefaultPartLibDirectory)

        #self.connect(self.elementButtonGroup,SIGNAL("buttonClicked(int)"),self.setElementInfo)

        self.connect(self.thumbView_groupBoxButton, SIGNAL("clicked()"),
                     self.toggle_thumbView_groupBox)
        self.connect(self.bondTool_groupBoxButton , SIGNAL("clicked()"),
                     self.toggle_bondTool_groupBox)
        self.connect(self.MMKitGrpBox_TitleButton, SIGNAL("clicked()"),
                     self.toggle_MMKit_groupBox)
        self.connect(self.filterCB, SIGNAL("stateChanged(int)"),
                     self.toggle_selectionFilter_groupBox)
        self.connect(self.advancedOptions_groupBoxButton, SIGNAL("clicked()"),
                     self.toggle_advancedOptions_groupBox)

        # Make the elements act like a big exclusive radio button.
        self.theElements = QtGui.QButtonGroup()
        self.theElements.setExclusive(True)
        self.theElements.addButton(self.toolButton1, 1)
        self.theElements.addButton(self.toolButton2, 2)
        self.theElements.addButton(self.toolButton6, 6)
        self.theElements.addButton(self.toolButton7, 7)
        self.theElements.addButton(self.toolButton8, 8)
        self.theElements.addButton(self.toolButton10, 10)
        self.theElements.addButton(self.toolButton9, 9)
        self.theElements.addButton(self.toolButton13,13)
        self.theElements.addButton(self.toolButton17,17)
        self.theElements.addButton(self.toolButton5, 5)
        self.theElements.addButton(self.toolButton10_2, 18)
        self.theElements.addButton(self.toolButton15, 15)
        self.theElements.addButton(self.toolButton16, 16)
        self.theElements.addButton(self.toolButton14, 14)
        self.theElements.addButton(self.toolButton33, 33)
        self.theElements.addButton(self.toolButton34, 34)
        self.theElements.addButton(self.toolButton35, 35)
        self.theElements.addButton(self.toolButton32, 32)
        self.theElements.addButton(self.toolButton36, 36)
        self.connect(self.theElements, SIGNAL("buttonPressed(int)"), self.update_dialog)

        self.theHybridizations = QtGui.QButtonGroup()
        self.theHybridizations.setExclusive(True)
        self.theHybridizations.addButton(self.sp3_btn, 0)
        self.theHybridizations.addButton(self.sp2_btn, 1)
        self.theHybridizations.addButton(self.sp_btn, 2)
        self.theHybridizations.addButton(self.graphitic_btn, 3)
        self.connect(self.theHybridizations, SIGNAL("buttonClicked(int)"), self.update_hybrid_btngrp)

        self.connect(self.filterCB,
                        SIGNAL("toggled(bool)"),self.set_selection_filter)


        self.elemTable = PeriodicTable
        self.displayMode = diTUBES
        self.elm = None

        self.newModel = None  ## used to save the selected lib part

        self.flayout = None

        # It looks like we now have correct fixes for bugs 1659 and bug 1824. If so, it would be safe to simply
        # hardware self.icon_tabs to True and simplify code accordingly. But we're not 100% certain, so by leaving
        # it as a debug pref, we can help any users who see those bugs come up again.
        # wware 060420
        #
        # Update, bruce 070328: the False value of this debug_pref is known to fail in the Qt4 version (on Mac anyway),
        # due to AttributeError exceptions for setMargin and setTabLabel,
        # so I'm changing the prefs key for it in order to let Qt3 and Qt4 have independent debug_pref settings,
        # adding a warning in the menu text, and adding a try/except to help in debugging this if anyone ever wants to.
        # (If the bugs Will mentioned go away entirely, we can abandon support for the False value instead of fixing it,
        #  as Will suggested.)
        from utilities.debug_prefs import debug_pref, Choice_boolean_True
        self.icon_tabs = debug_pref("use icons in MMKit tabs? (only True works in Qt4)", Choice_boolean_True,
                                    prefs_key = "A7/mmkit tab icons/Qt4")
            #e Changes to this only take effect in the next session.
            # Ideally we'd add a history message about that, when this is changed.
            # (It's not yet easy to do that in a supported way in debug_pref.) [bruce 060313]

        if not self.icon_tabs:
            # This code is known to fail in Qt4 Mac version, as explained above. [bruce 061222 and 070328]
            try:
                self.mmkit_tab.setMargin ( 0 )
            except:
                print_compact_traceback("ignoring this Qt4-specific exception: ") #bruce 061222
                pass
            self.mmkit_tab.setTabLabel (self.atomsPage, 'Atoms')
            self.mmkit_tab.setTabLabel (self.clipboardPage, 'Clipbd')
            self.mmkit_tab.setTabLabel (self.libraryPage, 'Lib')
        else:
            # Add icons to MMKit's tabs. mark 060223.
            atoms_ic = imagename_to_icon("actions/Properties Manager/MMKit.png")
            self.mmkit_tab.setTabIcon(self.mmkit_tab.indexOf(self.atomsPage), QIcon(atoms_ic))

            self.update_clipboard_page_icon() # Loads proper icon for clibpoard tab. Mark 2007-06-01

            library_ic = imagename_to_icon("actions/Properties Manager/library.png")
            self.mmkit_tab.setTabIcon(self.mmkit_tab.indexOf(self.libraryPage), QIcon(library_ic))

        # Tab tooltips. mark 060326
        self.mmkit_tab.setTabToolTip(self.mmkit_tab.indexOf(self.atomsPage), 'Atoms')
        self.mmkit_tab.setTabToolTip(self.mmkit_tab.indexOf(self.clipboardPage), 'Clipboard')
        self.mmkit_tab.setTabToolTip(self.mmkit_tab.indexOf(self.libraryPage), 'Part Library')

        self._setNewView('MMKitView')

        # Set current element in element button group.


        self.theElements.button(self.w.Element).setChecked(True)

        #self.connect(self., SIGNAL("), )

        self.connect(self.w.hybridComboBox, SIGNAL("activated(int)"), self.hybridChangedOutside)

        self.connect(self.w.hybridComboBox, SIGNAL("activated(const QString&)"), self.change2AtomsPage)
        self.connect(self.w.elemChangeComboBox, SIGNAL("activated(const QString&)"), self.change2AtomsPage)
        self.connect(self.w.pasteComboBox, SIGNAL("activated(const QString&)"), self.change2ClipboardPage)

        #self.connect(self.w.depositAtomDashboard.pasteBtn, SIGNAL("pressed()"), self.change2ClipboardPage)
        self.connect(self.w.depositAtomDashboard.pasteBtn, SIGNAL("stateChanged(int)"), self.pasteBtnStateChanged)
        self.connect(self.w.depositAtomDashboard.depositBtn, SIGNAL("stateChanged(int)"), self.depositBtnStateChanged)

        self.connect(self.dirView, SIGNAL("selectionChanged(QItemSelection *, QItemSelection *)"), self.partChanged)

        self.add_whats_this_text()

        return # from __init__

    # ==

    #bruce 060412 added everything related to __needs_update_xxx, to fix bugs 1726, 1629 and mitigate bug 1677;
    # for more info see the comments where update_clipboard_items is called (in depositMode.py).

    __needs_update_clipboard_items = False
        # (there could be other flags like this for other kinds of updates we might need)


    def show_propMgr(self):
        """
        Show the Build Property Manager.
        """
        #@NOTE: The build property manager files are still refered as MMKit and
        #MMKitDialog. This will change in the near future. -- ninad 20070717

        self.update_dialog(self.parentMode.w.Element)
        self.parentMode.set_selection_filter(False) # disable selection filter
        self.openPropertyManager(self)

        #Following is an old comment, was originally in depositMode.init_gui:
        #Do these before connecting signals or we'll get history msgs.
        #Part of fix for bug 1620. mark 060322
        self.highlightingCB.setChecked(self.parentMode.hover_highlighting_enabled)
        self.waterCB.setChecked(self.parentMode.water_enabled)


    def update_dialog(self, elemNum):
        """Called when the current element has been changed.
           Update non user interactive controls display for current selected
           element: element label info and element graphics info """

        elm = self.elemTable.getElement(elemNum)

        currentIndex = self.mmkit_tab.currentIndex()
        atomPageIndex = self.mmkit_tab.indexOf(self.atomsPage)

        ##if elm == self.elm and self.currentPageOpen(AtomsPage): return
        if elm == self.elm and (currentIndex == atomPageIndex) : return

        ## The following statements are redundant in some situations.
        self.theElements.button(elemNum).setChecked(True)
        self.w.Element = elemNum

        self.color = self.elemTable.getElemColor(elemNum)
        self.elm = self.elemTable.getElement(elemNum)

        self.update_hybrid_btngrp()

        self.elemGLPane.resetView()
        self.elemGLPane.refreshDisplay(self.elm, self.displayMode)

        #update the selection filter
        self.update_selection_filter_list()

        # Fix for bug 353, to allow the dialog to be updated with the correct page.  For example,
        # when the user selects Paste from the Edit toolbar/menu, the MMKit should show
        # the Clipboard page and not the Atoms page. Mark 050808
        if self.w.depositState == 'Clipboard':
            self.change2ClipboardPage()
        else:
            self.change2AtomsPage()
        self.tabCurrentChanged()

        self.updateBuildAtomsMessage() # Mark 2007-06-01

    def updateBuildAtomsMessage(self):
        """Updates the message box with an informative message based on the current page
        and current selected atom type.
        """
        msg = ""

        if self.MMKit_groupBox.isVisible():
            pageIndex = self.mmkit_tab.currentIndex()
            page = None

            if pageIndex is 0: # atomsPage
                msg = "Double click in empty space to insert a single " + self.elm.name + " atom. "
                if not self.elm.symbol in noblegases:
                    msg += "Click on an atom's <i>red bondpoint</i> to attach a " + self.elm.name + " atom to it."

            elif pageIndex is 1: # clipboardPage
                pastableItems = self.w.assy.shelf.get_pastable_chunks()
                if pastableItems:
                    msg = "Double click in empty space to insert a copy of the selected clipboard item. \
                    Click on a <i>red bondpoint</i> to attach a copy of the selected clipboard item."
                else:
                    msg = "There are no items on the clipboard."

            elif pageIndex is 2: # libraryPage
                msg = "Double click in empty space to insert a copy of the selected part in the library."

        else: # Bonds Tool is selected (MMKit groupbox is hidden).
            if self.parentMode.cutBondsAction.isChecked():
                msg = "<b> Cut Bonds </b> tool is active. \
                Click on bonds in order to delete them."
                self.MessageGroupBox.insertHtmlMessage(msg)
                return

            if not hasattr(self, 'bondclick_v6'): # Mark 2007-06-01
                return
            if self.bondclick_v6:
                name = btype_from_v6(self.bondclick_v6)
                msg = "Click bonds or bondpoints to make them %s bonds." % name # name is 'single' etc

        # Post message.
        self.MessageGroupBox.insertHtmlMessage(msg)

    #== Atom Selection Filter helper methods

    def set_selection_filter(self, enabled):
        """Slot for Atom Selection Filter checkbox. Prints history message when selection filter is
        enabled/disabled and updates the cursor.
        """

        if enabled != self.w.selection_filter_enabled:
            if enabled:
                env.history.message("Atom Selection Filter enabled.")
            else:
                env.history.message("Atom Selection Filter disabled.")

        self.w.selection_filter_enabled = enabled

        #print "update_selection_filter_list(): self.w.filtered_elements=", self.w.filtered_elements

        ##self.update_selection_filter_list_widget()
        self.update_selection_filter_list()
        self.filterlistLE.setEnabled(enabled)
        self.filterCB.setChecked(enabled)
        self.o.graphicsMode.update_cursor()

    def update_selection_filter_list(self):
        """Adds/removes the element selected in the MMKit to/from Atom Selection Filter
        based on what modifier key is pressed (if any).
        """
        eltnum = self.w.Element

        if self.o.modkeys is None:
            self.w.filtered_elements = []
            self.w.filtered_elements.append(PeriodicTable.getElement(eltnum))
        if self.o.modkeys == 'Shift':
            if not PeriodicTable.getElement(eltnum) in self.w.filtered_elements[:]:
                self.w.filtered_elements.append(PeriodicTable.getElement(eltnum))
        elif self.o.modkeys == 'Control':
            if PeriodicTable.getElement(eltnum) in self.w.filtered_elements[:]:
                self.w.filtered_elements.remove(PeriodicTable.getElement(eltnum))

        self.update_selection_filter_list_widget()

    def update_selection_filter_list_widget(self):
        """Updates the list of elements displayed in the Atom Selection Filter List.
        """
        filtered_syms=''
        for e in self.w.filtered_elements[:]:
            if filtered_syms: filtered_syms += ", "
            filtered_syms += e.symbol
        #self.w.depositAtomDashboard.filterlistLE.setText(filtered_syms)
        self.filterlistLE.setText(filtered_syms)

    def toggle_bondTool_groupBox(self):
        self.toggle_groupbox(self.bondTool_groupBoxButton, self.bondToolWidget)

    def toggle_thumbView_groupBox(self):
        self.toggle_groupbox(self.thumbView_groupBoxButton, self.elementFrame)

    def toggle_MMKit_groupBox(self):
        self.toggle_groupbox(self.MMKitGrpBox_TitleButton, self.mmkit_tab, self.transmuteBtn, self.transmuteCB)

    def toggle_selectionFilter_groupBox(self, state):
        """ Toggles the groupbox item display depending on checked state of the selection filter checkbox """

        #Current state is 'off' or(Qt.Unchecked)

        if state is 0:
            styleSheet = self.getGroupBoxCheckBoxStyleSheet(bool_expand = False)
            self.filterCB.setStyleSheet(styleSheet)

            palette = self.getGroupBoxCheckBoxPalette()
            self.filterCB.setPalette(palette)

            #hide the following widgets when checkbox is unchecked --
            self.selectionFilter_label.hide()
            self.filterlistLE.hide()
        else:
            styleSheet = self.getGroupBoxCheckBoxStyleSheet(bool_expand = True)
            self.filterCB.setStyleSheet(styleSheet)

            palette = self.getGroupBoxCheckBoxPalette()
            self.filterCB.setPalette(palette)

            #hide the following widgets when checkbox is unchecked --
            self.selectionFilter_label.show()
            self.filterlistLE.show()


    def toggle_advancedOptions_groupBox(self):
        self.toggle_groupbox(self.advancedOptions_groupBoxButton, self.autobondCB, self.waterCB, self.highlightingCB)

    #bruce 070615 removed 'def toggle_groupbox', since our mixin superclass PropertyManagerMixin
    # provides an identical-enough version.

    def tabCurrentChanged(self):
        pageIndex = self.mmkit_tab.currentIndex()
        page = None
        if pageIndex is 0: page = self.atomsPage
        elif pageIndex is 1: page = self.clipboardPage
        elif pageIndex is 2: page = self.libraryPage
        self.setup_current_page(page)

    def update_clipboard_items(self):
        self.__needs_update_clipboard_items = True
        self.update() # this makes sure self.event will get called; it might be better to test the flag only in self.repaint, not sure
        return

    def event(self, event): #bruce 060412 debug code, but also checks all self.__needs_update_xxx flags (an essential bugfix)
        if debug_mmkit_events:
            print "debug: MMKit.event got %r, type %r" % (event, event.type())
                # Qt doc for QEvent lists 'enum type' codes; the subclass is also printed by %r

        if self.__needs_update_clipboard_items:
            self.__really_update_clipboard_items()
            self.__needs_update_clipboard_items = False

        res = QDialog.event(self, event)
        if debug_mmkit_events:
            if res is not None:
                print "debug: MMKit.event returns %r" % (res,) # usually True, sometimes False
        # if we return None we get TypeError: invalid result type from MMKit.event()
        return res

    # ==

    def pasteBtnStateChanged(self, state):
        """Slot method. Called when the state of the Paste button of deposit dashboard has been changed. """
        if state == QButton.On:
            self.change2ClipboardPage()


    def depositBtnStateChanged(self, state):
        """Slot method. Called when the state of the Deposit button of deposit dashboard has been changed. """
        if state == QButton.On:
           self.change2AtomsPage()


    def hybridChangedOutside(self, newId):
        """Slot method. Called when user changes element hybridization from the dashboard.
         This method achieves the same effect as user clicked one of the hybridization buttons."""
        self.theElements.button(newId).setChecked(True)
        self.set_hybrid_type(newId)
        self.w.Element = newId

        ## fix bug 868
        self.w.depositAtomDashboard.depositBtn.setChecked(True)


    def change2AtomsPage(self):
        """Slot method called when user changes element/hybrid combobox or
        presses Deposit button from Build mode dashboard.
        """
        if self.mmkit_tab.currentIndex() != AtomsPage:
            self.mmkit_tab.setCurrentIndex(AtomsPage) # Generates signal

    def change2ClipboardPage(self):
        """Slot method called when user changes pastable item combobox or
        presses the Paste button from the Build mode dashboard. """
        if self.mmkit_tab.currentIndex() != ClipboardPage:
            self.mmkit_tab.setCurrentIndex(ClipboardPage) # Generates signal??


    def setElementInfo(self,value):
        """Slot method called when an element button is pressed in the element ButtonGroup.
        """
        self.w.setElement(value)


    def update_hybrid_btngrp(self, buttonIndex = 0):
        """Update the buttons of the current element\'s hybridization types into hybrid_btngrp;
        select the specified one if provided"""
        elem = PeriodicTable.getElement(self.w.Element) # self.w.Element is atomic number

        atypes = elem.atomtypes

        if elem.name == 'Carbon':
            self.setup_C_hybrid_buttons()
        elif elem.name == 'Nitrogen':
            self.setup_N_hybrid_buttons()
        elif elem.name == 'Oxygen':
            self.setup_O_hybrid_buttons()
        elif elem.name == 'Sulfur':
            self.setup_S_hybrid_buttons()
        else:
            self.hide_hybrid_btngrp()
            self.elemGLPane.changeHybridType(None)
            return

        #if len(atypes) > 1:
        # Prequisite: w.hybridComboBox has been updated at this moment.
        b_name = self.bond_id2name[buttonIndex]
        self.elemGLPane.changeHybridType(b_name)
        self.elemGLPane.refreshDisplay(self.elm, self.displayMode)
        self.theHybridizations.button(buttonIndex).setChecked(True)
        self.set_hybrid_type(buttonIndex)
        # Added Atomic Hybrids label. Mark 2007-05-30
        self.atomic_hybrids_label.setText("Atomic Hybrids for " + elem.name + " :")
        self.show_hybrid_btngrp()

    def show_hybrid_btngrp(self): # Mark 2007-06-20
        """Show the hybrid button group and label above it.
        This is a companion method to hide_hybrid_btngrp().
        It includes workarounds for Qt layout issues that crop up
        when hiding/showing the hybrid button groupbox using Qt's
        hide() and show() methods. See bug 2407 for more information.
        """
        if 1:
            self.hybrid_btngrp.show()
        else:
            self.hybrid_btngrp.show()
            self.atomic_hybrids_label.show()

    def hide_hybrid_btngrp(self): # Mark 2007-06-20
        """Hide the hybrid button group and label above it.
        This is a companion method to show_hybrid_btngrp().
        It includes workarounds for Qt layout issues that crop up
        when hiding/showing the hybrid button groupbox using Qt's
        hide() and show() methods. See bug 2407 for more information.
        """
        if 1:
            # This way of hiding confuses the layout manager, so I had
            # do create special spacers and set sizepolicies just to make
            # this work.
            self.hybrid_btngrp.hide()
            # I had to do this instead of use hide() since hide()
            # confuses the layout manager in special situations, like
            # that described in bug 2407. Mark 2007-06-20
            self.atomic_hybrids_label.setText(" ")
        else:
            # Alternate way of hiding. Hide all contents and the QButtonGroupbox
            # border, but there is no way to hide the border.
            self.sp3_btn.hide()
            self.sp2_btn.hide()
            self.sp_btn.hide()
            self.graphitic_btn.hide()
            self.atomic_hybrids_label.hide()

    def setup_C_hybrid_buttons(self):
        """Displays the Carbon hybrid buttons.
        """
        self.theElements.button(self.w.Element).setChecked(True)
        self.sp3_btn.setIcon(imagename_to_icon('modeltree/C_sp3.png'))
        self.sp3_btn.show()
        self.sp2_btn.setIcon(imagename_to_icon('modeltree/C_sp2.png'))
        self.sp2_btn.show()
        self.sp_btn.setIcon(imagename_to_icon('modeltree/C_sp.png'))
        self.sp_btn.show()
        self.graphitic_btn.hide()

    def setup_N_hybrid_buttons(self):
        """Displays the Nitrogen hybrid buttons.
        """
        self.sp3_btn.setIcon(imagename_to_icon('modeltree/N_sp3.png'))
        self.sp3_btn.show()
        self.sp2_btn.setIcon(imagename_to_icon('modeltree/N_sp2.png'))
        self.sp2_btn.show()
        self.sp_btn.setIcon(imagename_to_icon('modeltree/N_sp.png'))
        self.sp_btn.show()
        self.graphitic_btn.setIcon(imagename_to_icon('modeltree/N_graphitic.png'))
        self.graphitic_btn.show()


    def setup_O_hybrid_buttons(self):
        """Displays the Oxygen hybrid buttons.
        """
        self.sp3_btn.setIcon(imagename_to_icon('modeltree/O_sp3.png'))
        self.sp3_btn.show()
        self.sp2_btn.setIcon(imagename_to_icon('modeltree/O_sp2.png'))
        self.sp2_btn.show()
        self.sp_btn.hide()
        self.graphitic_btn.hide()


    def setup_S_hybrid_buttons(self):
        """Displays the Sulfur hybrid buttons.
        """
        self.sp3_btn.setIcon(imagename_to_icon('modeltree/O_sp3.png')) # S and O are the same.
        self.sp3_btn.show()
        self.sp2_btn.setIcon(imagename_to_icon('modeltree/O_sp2.png'))
        self.sp2_btn.show()
        self.sp_btn.hide()
        self.graphitic_btn.hide()


    def set_hybrid_type(self, type_id):
        """Slot method. Called when any of the hybrid type buttons was clicked. """
        self.w.hybridComboBox.setCurrentIndex( type_id )

        b_name = self.bond_id2name[type_id]

        #This condition fixs bug 866, also saves time since no need to draw without MMKIt shown
        if self.isVisible():
            self.elemGLPane.changeHybridType(b_name)
            self.elemGLPane.refreshDisplay(self.elm, self.displayMode)


    def setup_current_page(self, page):
        """Slot method that is called whenever a user clicks on the
        'Atoms', 'Clipboard' or 'Library' tab to change to that page.
        """

        #print "setup_current_page: page=", page

        if page == self.atomsPage:  # Atoms page
            self.w.depositState = 'Atoms'
            self.w.update_depositState_buttons()
            self.elemGLPane.resetView()
            self.elemGLPane.refreshDisplay(self.elm, self.displayMode)
            self.browseButton.hide()
            self.defaultPartLibButton.hide()
            self.atomsPageSpacer.changeSize(0,5,
                QtGui.QSizePolicy.Expanding,
                QtGui.QSizePolicy.Minimum)

        elif page == self.clipboardPage: # Clipboard page
            self.w.depositState = 'Clipboard'
            self.w.update_depositState_buttons()
            self.elemGLPane.setDisplay(self.displayMode)
            self._clipboardPageView()
            self.browseButton.hide()
            self.defaultPartLibButton.hide()
            self.atomsPageSpacer.changeSize(0,5,
                QtGui.QSizePolicy.Expanding,
                QtGui.QSizePolicy.Minimum)

        elif page == self.libraryPage: # Library page
            if self.rootDir:
                self.elemGLPane.setDisplay(self.displayMode)
                self._libPageView()
            self.browseButton.show()
            self.defaultPartLibButton.show()
            self.atomsPageSpacer.changeSize(0,5,
                QtGui.QSizePolicy.Minimum,
                QtGui.QSizePolicy.Minimum)

            #Turn off both paste and deposit buttons, so when in library page and user choose 'set hotspot and copy'
            #it will change to paste page, also, when no chunk selected, a history message shows instead of depositing an atom.
            self.w.depositState = 'Library'
            self.w.update_depositState_buttons()
        else:
            print 'Error: MMKit page unknown: ', page

        self.elemGLPane.setFocus()
        self.updateBuildAtomsMessage()

    def chunkChanged(self, item, previous):
        """Slot method. Called when user changed the selected chunk. """

        itemId = self.chunkListBox.row(item)

        if itemId != -1:

            newChunk = self.pastableItems[itemId]

            #self.w.pasteComboBox.setCurrentIndex(itemId)
            #buildModeObj = self.w.commandSequencer._commandTable['DEPOSIT']
            #assert buildModeObj
            #buildModeObj.setPaste()

            ##Compared to the above way, I think this way is better. Modules are more uncoupled.
            self.w.pasteComboBox.setCurrentIndex(itemId) # Fixes bug 1754. mark 060325

            self.elemGLPane.updateModel(newChunk)


    def __really_update_clipboard_items(self): #bruce 060412 renamed this from update_clipboard_items to __really_update_clipboard_items
        """Updates the items in the clipboard\'s listview, if the clipboard is currently shown. """
        if self.currentPageOpen(ClipboardPage): #bruce 060313 added this condition to fix bugs 1631, 1669, and MMKit part of 1627
            self._clipboardPageView() # includes self.update_clipboard_page_icon()
        else:
            self.update_clipboard_page_icon() # do this part of it, even if page not shown
        return

    def partChanged(self, item):
        """Slot method, called when user changed the partlib brower tree"""
        if isinstance(item, self.FileItem):
           self._libPageView(True)
        else:
           self.newModel = None
           self.elemGLPane.updateModel(self.newModel)


    def getPastablePart(self):
        """Public method. Retrieve pastable part and hotspot if current tab page is in libary, otherwise, return None. """
        if self.currentPageOpen(LibraryPage):
            return self.newModel, self.elemGLPane.hotspotAtom
        return None, None

    def currentPageOpen(self, page_id):
        """Returns True if <page_id> is the current page open in the tab widget, where:
            0 = Atoms page
            1 = Clipboard page
            2 = Library page
        """
        pageIndex = self.mmkit_tab.currentIndex()

        if page_id == pageIndex:
            return True
        else:
            return False

    def _libPageView(self, isFile = False):
        item = self.dirView.selectedItem()
        if not isFile and not isinstance(item, self.FileItem):
            self.newModel = None
            self.elemGLPane.updateModel(self.newModel)
            return

        mmpfile = str(item.getFileObj())
        if os.path.isfile(mmpfile):
            #self.newModel = Assembly(self.w, "Assembly 1")
            self.newModel = Assembly(self.w, os.path.normpath(mmpfile)) #ninad060924 to fix bug 1164
            self.newModel.o = self.elemGLPane ## Make it looks "Assembly" used by glpane.
            readmmp(self.newModel, mmpfile)

# What we did in Qt 3:
##         #self.newModel = Assembly(self.w, "Assembly 1")
##         self.newModel = Assembly(self.w, os.path.normpath(mmpfile)) #ninad060924 to fix bug 1164

##         self.newModel.o = self.elemGLPane ## Make it looks "Assembly" used by glpane.
##         readmmp(self.newModel, mmpfile)

##         # The following is absolute nonsense, and is part of what's breaking the fix of bug 2028,
##         # so it needs to be revised, to give this assy a standard structure.
##         # We'll have to find some other way to draw the hotspot singlet
##         # (e.g. a reasonable, straightforward way). So we did -- MMKitView.always_draw_hotspot is True.
##         # [bruce 060627]

## ##        # Move all stuff under assembly.tree into assy.shelf. This is needed to draw hotspot singlet
## ##        def addChild(child):
## ##            self.newModel.shelf.addchild(child)
## ##
## ##        # Remove existing clipboard items from the libary part before adopting childern from 'tree'.
## ##        self.newModel.shelf.members = []
## ##        self.newModel.tree.apply2all(addChild)
## ##
## ##        self.newModel.shelf.prior_part = None
## ##        self.newModel.part = Part(self.newModel, self.newModel.shelf)

##         if 1: #bruce 060627

            self.newModel.update_parts() #k not sure if needed after readmmp)
            self.newModel.checkparts()
            if self.newModel.shelf.members:
                if debug_flags.atom_debug:
                    print "debug warning: library part %r contains clipboard items" % mmpfile
                    # we'll see if this is common
                    # happens for e.g. nanokids/nanoKid-C39H42O2.mmp
                for m in self.newModel.shelf.members[:]:
                    m.kill() #k guess about a correct way to handle them
                self.newModel.update_parts() #k probably not needed
                self.newModel.checkparts() #k probably not needed
        else:
            self.newModel = None

        self.elemGLPane.updateModel(self.newModel)


    def _clipboardPageView(self):
        """Updates the clipboard page. """
        if not self.currentPageOpen(ClipboardPage):
            # (old code permitted this to be false below in 'if len(list):',
            #  but failed to check for it in the 'else' clause,
            #  thus causing bug 1627 [I think], now fixed in our caller)
            print "bug: _clipboardPageView called when not self.currentPageOpen(ClipboardPage)" #bruce 060313
            return

        self.pastableItems = self.w.assy.shelf.get_pastable_chunks()
        self.chunkListBox.clear()
        for item in self.pastableItems:
            self.chunkListBox.addItem(item.name)

        newModel = None
        if len(self.pastableItems):
            i = self.w.pasteComboBox.currentIndex()
            if i < 0:
                i = self.w.pasteComboBox.count() - 1
            # Make sure the clipboard page is open before calling selSelected(), because
            # setSelected() causes the clipboard page to be displayed when we don't want it to
            # be displayed (i.e. pressing Control+C to copy something to the clipboard).
            self.chunkListBox.setCurrentItem(self.chunkListBox.item(i))
            # bruce 060313 question: why don't we now have to pass the selected chunk to
            # self.elemGLPane.updateModel? ###@@@
            newModel = self.pastableItems[i]
        self.elemGLPane.updateModel(newModel)
        self.update_clipboard_page_icon()


    def update_clipboard_page_icon(self):
        """Updates the Clipboard page (tab) icon with a full or empty clipboard icon
        based on whether there is anything on the clipboard (pasteables).
        """
        if not self.icon_tabs:
            # Work around for bug 1659. mark 060310 [revised by bruce 060313]
            return

        if self.w.assy.shelf.get_pastable_chunks():
            clipboard_ic = imagename_to_icon("actions/Properties Manager/clipboard-full.png")
        else:
            clipboard_ic = imagename_to_icon("actions/Properties Manager/clipboard-empty.png")

        self.mmkit_tab.setTabIcon(self.mmkit_tab.indexOf(self.clipboardPage), QIcon(clipboard_ic))

    class DirView(QTreeView):
        def __init__(self, mmkit, parent):
            QTreeView.__init__(self, parent)

            self.setEnabled(True)
            self.model = QtGui.QDirModel(['*.mmp', '*.MMP'], # name filters
                                         QDir.AllEntries|QDir.AllDirs|QDir.NoDotAndDotDot, # filters
                                         QDir.Name # sort order
                                         )
                # explanation of filters (from Qt 4.2 doc for QDirModel):
                # - QDir.AllEntries = list files, dirs, drives, symlinks.
                # - QDir.AllDirs = include dirs regardless of other filters [guess: needed to ignore the name filters for dirs]
                # - QDir.NoDotAndDotDot = don't include '.' and '..' dirs
                #
                # about dirnames of "CVS":
                # The docs don't mention any way to filter the dirnames using a callback,
                # or any choices besides "filter them same as filenames" or "don't filter them".
                # So there is no documented way to filter out the "CVS" subdirectories like we did in Qt3
                # (short of subclassing this and overriding some methods,
                #  but the docs don't make it obvious how to do that correctly).
                # Fortunately, autoBuild.py removes them from the partlib copy in built releases.
                #
                # Other QDirModel methods we might want to use:
                # QDirModel.refresh, to update its state from the filesystem (but see the docs --
                #  they imply we might have to pass the model's root pathname to that method,
                #  even if it hasn't changed, but they're not entirely clear on that).
                #
                # [bruce 070502 comments]

            self.path = None
            self.mmkit = mmkit
            self.setModel(self.model)
            self.setWindowTitle(self.tr("Dir View"))

            self.setItemsExpandable(True)
            self.setAlternatingRowColors(True)
            self.setColumnWidth(0, 200)
            for i in range(2,4):
                self.setColumnWidth(i, 4)

            self.show()

        #Ninad 070326 reimplementing mouseReleaseEvent and resizeEvent
        #for DirView Class (which is a subclass of QTreeView)
        #The old code reimplemented 'event' class which handles *all* events.
        #There was a bad bug which didn't send an event when the widget is resized
        # and then the seletcion is changed. In NE1Qt3 this wasn't a problem because
        #it only had one column. Now that we have multiple columns
        #(which are needed to show the horizontal scrollbar.
        # While using Library page only resize event or mouse release events
        #by the user should update the thumbview.
        #The Qt documentation also suggests reimplementing subevents instead of the main
        #event handler method (event())
        def mouseReleaseEvent(self, evt):
            """ Reimplementation of mouseReleaseEvent method of QTreeView"""
            if self.selectedItem() is not None:
                    self.mmkit._libPageView()
            return QTreeView.mouseReleaseEvent(self, evt)

        def resizeEvent(self, evt):
            """ Reimplementation of resizeEvent method of QTreeView"""
            if self.selectedItem() is not None:
                    self.mmkit._libPageView()
            return QTreeView.resizeEvent(self, evt)


        #Following method (event() ) is not reimplemented anymore. Instead, the subevent handlers are
        #reimplemented (see above)  -- ninad 070326
        """
        def event(self, evt):
            if evt.type() == evt.Timer:
                # This is the event we get when the library selection changes, so if there has
                # been a library selection, update the library page's GLPane. But this can also
                # happen without a selection; in that case don't erase the atom page's display.
                if self.selectedItem() is not None:
                    self.mmkit._libPageView()
            return QTreeView.event(self, evt)"""

        def setRootPath(self, path):
            self.path = path
            self.setRootIndex(self.model.index(path))

        def selectedItem(self):
            indexes = self.selectedIndexes()
            if not indexes:
                return None
            index = indexes[0]
            if not index.isValid():
                return None

            return self.FileItem(str(self.model.filePath(index)))

    class FileItem:
        def __init__(self, path):
            self.path = path
            dummy, self.filename = os.path.split(path)
        def name(self):
            return self.filename
        def getFileObj(self):
            return self.path
    DirView.FileItem = FileItem

    def _setNewView(self, viewClassName):
        # Put the GL widget inside the frame
        if not self.flayout:
            self.flayout = QVBoxLayout(self.elementFrame)
            self.flayout.setMargin(1)
            self.flayout.setSpacing(1)
        else:
            if self.elemGLPane:
                self.flayout.removeChild(self.elemGLPane)
                self.elemGLPane = None

        if viewClassName == 'ChunkView':
            # We never come here! How odd.
            self.elemGLPane = ChunkView(self.elementFrame, "chunk glPane", self.w.glpane)
        elif viewClassName == 'MMKitView':
            self.elemGLPane = MMKitView(self.elementFrame, "MMKitView glPane", self.w.glpane)

        self.flayout.addWidget(self.elemGLPane,1)


        #ninad 070326. Note that self.DirView inherits QTreeView.
        #It has got nothing to do with the experimental class DirView in file Dirview.py
        self.dirView = self.DirView(self, self.libraryPage)
        self.dirView.setSortingEnabled(False) #bruce 070521 changed True to False -- fixes "reverse order" bug on my Mac
        ##self.dirView.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOn)

        libraryPageLayout = QVBoxLayout(self.libraryPage)
        libraryPageLayout.setMargin(pmMMKitPageMargin) # Was 4. Mark 2007-05-30
        libraryPageLayout.setSpacing(2)
        libraryPageLayout.addWidget(self.dirView)


        filePath = os.path.dirname(os.path.abspath(sys.argv[0]))
        libDir = os.path.normpath(filePath + '/../partlib')

        self.libPathKey = '/nanorex/nE-1/libraryPath'
        libDir = env.prefs.get(self.libPathKey, libDir)

        if os.path.isdir(libDir):
            self.rootDir = libDir
            self.dirView.setRootPath(libDir)
        else:
            self.rootDir = None
            from history.HistoryWidget import redmsg
            env.history.message(redmsg("The part library directory: %s doesn't exist." %libDir))

    def browseDirectories(self):
       """Slot method for the browse button of library page. """
       # Determine what directory to open.
       if self.w.assy.filename:
           odir = os.path.dirname(self.w.assy.filename)
       else:
           from utilities.prefs_constants import workingDirectory_prefs_key
           odir = env.prefs[workingDirectory_prefs_key]

       fdir = QFileDialog.getExistingDirectory(self, "Choose library directory", odir)
       libDir = str(fdir)
       if libDir and os.path.isdir(libDir):
           env.prefs[self.libPathKey] = libDir
           self.dirView.setRootPath(libDir)
           #Refresh GL-thumbView display
           self.newModel = None
           self.elemGLPane.updateModel(self.newModel)

    def useDefaultPartLibDirectory(self):
        """ Slot method that to reset the part lib directory path to default"""
        from history.HistoryWidget import redmsg

        #ninad070503 : A future enhancement would be a preference to have
        # a user defined 'default dir path' for the
        #part lib location.

        # set libDir to the standard partlib path
        filePath = os.path.dirname(os.path.abspath(sys.argv[0]))
        libDir = os.path.normpath(filePath + '/../partlib')

        if libDir and os.path.isdir(libDir):
            if self.dirView.path == libDir:
                msg1 = "Current directory path for the partlib is the default path."
                msg2 = " Current path not changed"
                env.history.message(redmsg(msg1 + msg2))
                return
            env.prefs[self.libPathKey] = libDir
            self.dirView.setRootPath(libDir)
            #Refresh GL-thumbView display
            self.newModel = None
            self.elemGLPane.updateModel(self.newModel)
        else:
            msg1 = "The default patlib directory %s doesn't exist."%libDir
            msg2 = "Current path not changed"
            env.history.message(redmsg(msg1 + msg2))


    def closeEvent(self, e):
        """This event handler receives all MMKit close events.  In other words,
        when this dialog's close() slot gets called, this gets called with event 'e'.
        """
        self.hide()

        # If the 'Library' page is open, change it to 'Atoms'.  Mark 051212.
        if self.currentPageOpen(LibraryPage):
            self.setup_current_page(self.atomsPage)


#bruce 070615 commented out the following since I think it's obsolete:
# (evidence: no other mentions of 'polish' or 'move_to_best_location' in our code,
#  and MMKit is no longer a movable dialog)
##    num_polish = 0
##
##    def polish(self):
##        """This slot is called after a widget has been fully created and before it is shown the very first time.
##        Polishing is useful for final initialization which depends on having an instantiated widget.
##        This is something a constructor cannot guarantee since the initialization of the subclasses might not be finished.
##        After this function, the widget has a proper font and palette and QApplication.polish() has been called.
##        Remember to call QDialog's implementation when reimplementing this function.
##        """
##        QDialog.polish(self) # call QDialog's polish() implementation
##        self.num_polish += 1
##        #&print "num_polish =", self.num_polish
##        if self.num_polish < 2:
##            # polish() is called twice; not sure why.
##            # Call move_to_best_location() only after the second polish signal since
##            # get_location() can only get self.frameGeometry() after that.
##            return
##        self.move_to_best_location(True)


    def show(self):
        """MMKit\'s show slot.
        """
        #QDialog.show(self)
        #&print "MMKit.move: setting mainwindow to active window"
        #Show it in Property Manager Tab ninad061207
        if not self.pw or self:
            self.pw = self.w.activePartWindow()       #@@@ ninad061206
            self.pw.updatePropertyManagerTab(self)
            self.setSponsor()

        else:
            if not self.pw:
                self.pw = self.w.activePartWindow()
            self.pw.updatePropertyManagerTab(self)


        self.w.activateWindow() # Fixes bug 1503.  mark 060216.
            # Required to give the keyboard input focus back to self (MainWindow).

    def add_whats_this_text(self):
        """What's This text for some of the widgets in the Build > Atoms Property Manager.
        Many are still missing.
        """

        self.elementFrame.setWhatsThis("""<b>Preview Window</b>
        <p>This displays the active object. It can be inserted by double
        clicking in the 3D graphics area.</p>
        <p>Left click on a red bondpoint to make it a green <i>hotspot</i>
        (clipboard and library parts only). The hotspot indicates which
        bondpoint should be used to bond the current object when selecting
        a bondpoint in the model.</p>
        <p><u>Mouse Commands Supported</u><br>
        Left - Select hotspot (clipboard and library parts only)<br>
        Middle - Rotate view<br> \
        Wheel - Zoom in/out \
        </p>""")

        self.MMKit_groupBox.setWhatsThis("""<b>Molecular Modeling Kit</b>
        <p>A tabular widget for selecting atom types or other structures to insert
        into the model.</p>
        <p><b>Atoms Tab</b> - A select group of atom types options from the periodic
        table of elements.</p>
        <p><b>Clipboard Tab</b> - the list of objects copied on the clipboard (using
        the Copy command).</p>
        <p><b>Library Tab</b> - Accesses the NE1 Part Library. There are hundreds of
        structures to choose from.</p>""")

        self.transmuteBtn.setWhatsThis("""<b>Transmute Atoms</b>
        <p>When clicked, transmutes selected atoms to the current type displayed
        in the Preview window.</p>""")

        self.transmuteCB.setWhatsThis("""<b>Force to keep bonds</b>
        <p>When checked, all bonds remain in place when atoms are transmuted,
        even if this will result in unrealistic (chemical) bonds.</p>""")

        self.selectionFilter_groupBox.setWhatsThis("""<b>Atoms Selection Filter</b>
        <p>When activated, only atoms listed can be selected.</p>""")

        self.advancedOptions_groupBox.setWhatsThis("""<b>Advanced Options</b>
        <p><b>Autobond</b> - when checked, the atom being inserted or attached to another
        atom will autobond to other bondpoints of other candidate atoms automatically.</p>
        <p><b>Highlighting</b> - Turns on/off hover highlighting.</p>
        <p><b>Water</b>- Adds a tranparent plane normal to the screen through 0,0,0. Anything
        behind the water plane can not be selected.</p>""")

        self.transmuteAtomsAction.setWhatsThis("""<b>Transmute Atoms</b>
        <p>When clicked, transmutes selected atoms to the current type displayed
        in the Preview window.</p>""")

    pass # end of class MMKit