from schrodinger.ui.qt.appframework2 import af2
# Super = af2.App # Use for non-job panels
Super = af2.JobApp  # Use for job panels
[docs]class AppTemplate(Super):
[docs]    def __init__(self, **kwargs):
        # Set options for JobApp or App and call the base class __init__.
        # The base __init__ will call setPanelOptions, setup, setDefaults, and
        # layOut, in that order.
        Super.__init__(self, **kwargs) 
        # Anything that gets placed here will be executed after layOut().
[docs]    def setPanelOptions(self):
        # Define instance variables that specify the creation of the panel. Call
        # the super class first.
        Super.setPanelOptions(self)
        self.maestro_dockable = True
        self.title = 'My Application Panel'
        self.allowed_run_modes = (af2.baseapp.MODE_MAESTRO,
                                  af2.baseapp.MODE_STANDALONE)
        # Or a single value, such as:
        self.allowed_run_modes = af2.baseapp.MODE_STANDALONE
        self.input_selector_options = {}  # Formerly called input frame (_if)
        # self.ui = template_ui.Ui_Form() # A UiForm instance
        # Job App Options:
        self.program_name = 'Program'
        self.default_jobname = 'jobname' 
[docs]    def getConfigDialog(self):
        # Define this method to get a config dialog. Only works in JobApp, not
        # App.
        return af2.ConfigDialog(self,
                                incorporation=True,
                                default_disp=af2.DISP_APPEND,
                                cpus=True,
                                host=True) 
[docs]    def setup(self):
        # This is the place to initialize variables, create widgets, connect
        # signals, slots, validators, etc. Generally call the super class setup
        # first and then proceed with our own setup
        Super.setup(self) 
[docs]    def setDefaults(self):
        # Any default values that need to be set should be done in this method.
        Super.setDefaults(self) 
[docs]    def layOut(self):
        # Add widgets to the panel layouts
        Super.layOut(self) 
[docs]    def defineCustomSettings(self):
        # Define any custom settings for saving and restoring panel state. See
        # af2.App documentation for details.
        # Real example for optoelectronics_gui.py. self.propbuttons in that
        # panel is just a list of check boxes, one for each optional property,
        # where button.propflag is a string label for that property.
        custom = [(button.propflag, button) for button in self.propbuttons]
        # Custom setter/getter
        custom.append(("Table", self.data_table, self.setData, self.getData))
        # Custom, human-readable label
        custom.append(("Temperature", self.bfactor_spinbox))
        return custom 
    #=========================================================================
    # Button methods
    #=========================================================================
    # Use decorators to indicate which methods are start, write, read, etc.
    # By default, the start method will double as a write method. For more
    # information, see the doc for the start decorator in the appmethods
    # module
[docs]    @af2.appmethods.start()
    def startJob(self):
        # Any method (but only one) can be defined as a start method. This will
        # automatically be hooked up to the start button in the bottom bar, and
        # can have any name.
        # Passing a string argument to start() decorator will cause the Run
        # button to have that name. Passing a <tooltip> argument will add a
        # custom tooltip to the run button.
        print('This is my start method') 
[docs]    @af2.appmethods.reset()
    def resetPanel(self):
        # This method will be called when the "Reset" action is selected, and
        # can have any name. Simply defining a no-op method with the reset()
        # decorator is enough to have the "Reset" action to show up - by
        # default it will call the setDefaults() method. Passing a string
        # argument to the reset() decorator will cause the reset action menu
        # item to have that given name.
        pass 
[docs]    @af2.appmethods.close()
    def closePanel(self):
        # This method will be called when the panel is closed. It can have
        # any name.
        print('Closing panel') 
    # Decorators may also be used to indicate Maestro callback methods
[docs]    @af2.maestro_callback.project_changed
    def onProjectChanged(self, proj):
        print('The project was just updated but not closed') 
[docs]    @af2.maestro_callback.project_close
    def onProjectClosed(self):
        print('The project was just closed') 
[docs]    @af2.maestro_callback.workspace_changed
    def onWorkspaceChanged(self, what_changed):
        print('The workspace was just changed') 
[docs]    @af2.maestro_callback.workspace_changed_active_project
    def onWorkspaceChangedWithActiveProj(self, what_changed, proj):
        print('The workspace was just changed, but not due to project closure') 
    #=========================================================================
    # Validation methods
    #=========================================================================
    # Decorators are also used to indicate that a method should be run at
    # whenever the panel is validated.
    @af2.validator()
    def validatePanel(self):
        # A validation should either return a True/False value or a tuple
        # consisting of (True/False, message string). True with a message is
        # interpreted as a warning. Note that forgetting to return something
        # will return None, which will evaluate to False and fail validation.
        # Multiple validation methods can be defined, and they can have any
        # name.
        print('Running a validation method')
        return True 
panel = AppTemplate.panel
if __name__ == "__main__":
    panel()
#===============================================================================
# Encoding settings in job names
#===============================================================================
[docs]class SettingsInJobNamesTemplate(af2.JobApp):
    """
    This class includes panel settings in its job name
    """
[docs]    def setPanelOptions(self):
        super(SettingsInJobNamesTemplate, self).setPanelOptions()
        self.title = "Settings in Job Names Template Panel"
        # Include interpolation characters in the default jobname
        self.default_jobname = "jobname_%s_%i_%s"
        # Either old-style or new-style interpolation may be used
        # self.default_jobname = "jobname_{}_{}_{}"
        # Named interpolation can also be used.  For this, jobnameData should
        # return a dictionary instead of a tuple
        # self.default_jobname = "jobname_%(setting1)s_%(setting2)s_%(setting3)s"
        # self.default_jobname = "jobname_{setting1}_{setting2}_{setting3}"
        self.ui = my_ui_module.Ui_Form()  # noqa 
[docs]    def setup(self):
        """
        In setup, make sure that `self.jobnameDataChanged` is called every time
        the jobname needs to be updated
        """
        super(SettingsInJobNamesTemplate, self).setup()
        self.ui.setting1_combo.currentIndexChanged.connect(
            self.jobnameDataChanged)
        self.ui.setting2_sb.valueChanged.connect(self.jobnameDataChanged)
        self.ui.setting3_le.textChanged.connect(self.jobnameDataChanged) 
[docs]    def jobnameData(self):
        """
        Reimplement `jobnameData` to return the data to be interpolated into
        the job name
        """
        setting1 = self.ui.setting1_combo.currentText()
        setting2 = self.ui.setting2_sb.value()
        setting3 = self.ui.setting3_le.text()
        # santizeJobnameText() converts spaces to underscores and removes all
        # other characters that are disallowed in job names
        setting3 = self.sanitizeJobnameText(setting3)
        return (setting1, setting2, setting3)
        # If using named interpolation, return a dictionary here instead of a
        # tuple
        return locals()