def __init__(self, parent=None):
        """Initialize the class.

        Parameters
        ----------
        parent : QWidget
            The parent widget of this one.
        """
        QtWidgets.QMainWindow.__init__(self, parent)
        self.save_directory = None
        self.file_menu_offset = -3
        self.extra_props_dir = None

        self.create_file_menu()
        self.create_reset_menu()
        self.create_create_menu()
        self.create_help_menu()

        self.tab_widget = QtWidgets.QTabWidget()
        self.main_controller = MainController()
        self.create_tabs()

        self.setCentralWidget(self.tab_widget)

        settings = QtCore.QSettings()
        self.recent_directories = settings.value("RecentDirectories")
        setting_save_dir = str(settings.value("LastDirectory"))
        if setting_save_dir != "":
            self.save_directory = setting_save_dir
        self.update_file_menu()
Beispiel #2
0
    def __init__(self, parent=None):
        """Initialize the class.

        Parameters
        ----------
        parent : QWidget
            The parent widget of this one.
        """
        QtWidgets.QMainWindow.__init__(self, parent)
        self.save_directory = None

        self.create_file_menu()
        self.create_reset_menu()
        self.create_create_menu()
        self.create_help_menu()

        self.tab_widget = QtWidgets.QTabWidget()
        self.main_controller = MainController()
        self.create_tabs()

        self.setCentralWidget(self.tab_widget)

        settings = QtCore.QSettings()
        self.recent_directories = settings.value("RecentDirectories")
        setting_save_dir = str(settings.value("LastDirectory"))
        if setting_save_dir != "":
            self.save_directory = setting_save_dir
        self.update_file_menu()
class OpsimConfig(QtWidgets.QMainWindow):
    """Top-level UI.
    """
    RECENT_DIRECTORIES_TO_LIST = 9
    STATUS_BAR_TIMEOUT = 3000

    def __init__(self, parent=None):
        """Initialize the class.

        Parameters
        ----------
        parent : QWidget
            The parent widget of this one.
        """
        QtWidgets.QMainWindow.__init__(self, parent)
        self.save_directory = None
        self.file_menu_offset = -3
        self.extra_props_dir = None

        self.create_file_menu()
        self.create_reset_menu()
        self.create_create_menu()
        self.create_help_menu()

        self.tab_widget = QtWidgets.QTabWidget()
        self.main_controller = MainController()
        self.create_tabs()

        self.setCentralWidget(self.tab_widget)

        settings = QtCore.QSettings()
        self.recent_directories = settings.value("RecentDirectories")
        setting_save_dir = str(settings.value("LastDirectory"))
        if setting_save_dir != "":
            self.save_directory = setting_save_dir
        self.update_file_menu()

    def create_file_menu(self):
        """Create the file menu for the UI.
        """
        file_set_save_dir = self.create_action("Save Directory", self.set_save_directory, "Ctrl+D",
                                               "folder_open.svg",
                                               "Set the directory where the configurations will be saved.")
        file_clear_recent = self.create_action("Clear Recent List", self.clear_recent_list, "Ctrl+Alt+C",
                                               "clear.svg", "Clear the list of recent directories.")
        file_apply_overrides = self.create_action("Apply Overrides", self.apply_overrides, "Ctrl+Alt+O",
                                                  "bottom.svg",
                                                  "Apply override files to current configuration.")
        file_save_configs = self.create_action("&Save Configuration", self.save_configurations,
                                               QtGui.QKeySequence.Save,
                                               "filesave.svg", "Save the configuration to files.")
        file_quit_action = self.create_action("&Quit", self.close, "Ctrl+Q", "exit.svg",
                                              "Close the application.")

        self.file_menu = self.menuBar().addMenu("&File")
        self.file_menu_actions = (file_set_save_dir, file_clear_recent, None,
                                  file_apply_overrides, file_save_configs,
                                  file_quit_action)
        self.file_menu.aboutToShow.connect(self.update_file_menu)

    def create_reset_menu(self):
        """Create the reset menu for the UI.
        """
        reset_all_defaults = self.create_action("All Defaults", self.reset_tabs, "Ctrl+R", "undo.svg",
                                                "Reset all values to defaults.")
        reset_active_tab_defaults = self.create_action("Active Tab Defaults", self.reset_active_tab, "Ctrl+T",
                                                       "undo_tab.svg",
                                                       "Reset all values in the active tab.")
        reset_active_field_default = self.create_action("Active Field Default", self.reset_active_field,
                                                        "Ctrl+Alt+F", "undo_field.svg",
                                                        "Reset value of the active field.")
        reset_overrides = self.create_action("Overrides", self.reset_overrides, "Ctrl+Alt+Shift+O",
                                             "undo_override.svg",
                                             "Reset overrides including new proposals.")

        reset_menu = self.menuBar().addMenu("Reset")
        self.add_actions(reset_menu, (reset_all_defaults, reset_active_tab_defaults,
                                      reset_active_field_default, reset_overrides))

    def create_create_menu(self):
        """ Create the create menu for the UI.
        """
        diff_report = self.create_action("Diff Report", self.diff_report, "Ctrl+Alt+R", "snavigator.svg",
                                         "Generate a difference report.")
        proposal_wizard = self.create_action("Proposal Creation", self.proposal_creation, "Ctrl+Alt+P",
                                             "document_new.svg",
                                             "Create a new proposal.")

        create_menu = self.menuBar().addMenu("Create")
        self.add_actions(create_menu, (diff_report, proposal_wizard))

    def create_help_menu(self):
        """Create the help menu for the UI.
        """
        help_about = self.create_action("&About", self.about, None, None,
                                        "About the OpSim Configuration UI program.")

        help_menu = self.menuBar().addMenu("&Help")
        self.add_actions(help_menu, (help_about,))

    def create_action(self, text, slot=None, shortcut=None, icon=None, tip=None, checkable=False,
                      signal_name="triggered"):
        """Create menu actions.

        Parameters
        ----------
        text : str
            A label for the action.
        slot : QtCore.pyqtSlot, optional
            A callback function for the action.
        shortcut : str, optional
            A keyboard shortcut for the action.
        icon : str, optional
            An icon path for the action.
        tip : str, optional
            A tooltip string for the action.
        checkable : bool, optional
            Is the action checkable?
        signal_name : str, optional
            The signal associated with the action. Default: triggered
        """
        action = QtWidgets.QAction(text, self)
        if icon is not None:
            action.setIcon(QtGui.QIcon(QtGui.QPixmap(":/{}".format(icon))))
            action.setIconVisibleInMenu(True)
        if shortcut is not None:
            action.setShortcut(shortcut)
        if tip is not None:
            action.setToolTip(tip)
            action.setStatusTip(tip)
        if slot is not None:
            signal = getattr(action, signal_name)
            signal.connect(slot)
        if checkable:
            action.setCheckable(True)
        return action

    def add_actions(self, target, actions):
        """Add menu actions.

        Prameters
        ---------
        target : QMenuItem
            The menu item to add the action to.
        actions : list(QAction)
            THe set of actions to apply.
        """
        for action in actions:
            if action is None:
                target.addSeparator()
            else:
                target.addAction(action)

    def clear_recent_list(self):
        """Clear out the list of recent directories.
        """
        self.recent_directories = []
        self.update_file_menu()

    def create_tabs(self):
        """Create all the configuration tabs.
        """
        tab_dict = self.main_controller.get_tabs()
        for key, tab in tab_dict.items():
            self.tab_widget.addTab(tab, title(key))

    def apply_overrides(self):
        """Apply override configuration files to current configuration.
        """
        old_save_directory = self.save_directory
        if old_save_directory == 'None':
            open_dir = os.path.expanduser("~/")
        else:
            open_dir = os.path.dirname(old_save_directory)
        override_dir = QtWidgets.QFileDialog.getExistingDirectory(self, "Override Directory",
                                                                  open_dir)
        if override_dir == "":
            return

        config_files = []
        for item in os.listdir(override_dir):
            ifile = os.path.join(override_dir, item)
            if os.path.isfile(ifile):
                config_files.append(ifile)

        extra_props = None
        alt_prop_dir = os.path.join(override_dir, NEW_PROPS_DIR)
        if os.path.exists(alt_prop_dir):
            extra_props = alt_prop_dir
            sys.path.insert(0, extra_props)
            self.extra_props_dir = extra_props

        if len(config_files) or extra_props is not None:
            self.main_controller.apply_overrides(config_files, extra_props)

    @QtCore.pyqtSlot()
    def save_configurations(self):
        """Save the current differences to configuration files.
        """
        message = "Finished saving configuration"
        if self.save_directory is None:
            self.save_directory = os.curdir
            message += " in current working directory."
        else:
            message += "."
        for i in range(self.tab_widget.count()):
            tab = self.tab_widget.widget(i)
            tab.save(expand_path(str(self.save_directory)))
        self.statusBar().showMessage(message, self.STATUS_BAR_TIMEOUT)
        if self.save_directory == os.curdir:
            self.save_directory = None

    def reset_tabs(self):
        """Reset all fields in all tabs.
        """
        for i in range(self.tab_widget.count()):
            tab = self.tab_widget.widget(i)
            tab.reset_all()
        self.statusBar().showMessage("Reset complete.", self.STATUS_BAR_TIMEOUT)

    def reset_active_tab(self):
        """Reser all fields in the active tab.
        """
        tab = self.tab_widget.widget(self.tab_widget.currentIndex())
        tab.reset_active_tab()
        self.statusBar().showMessage("Reset complete.", self.STATUS_BAR_TIMEOUT)

    def reset_active_field(self):
        """Reset the active field in the current tab.
        """
        tab = self.tab_widget.widget(self.tab_widget.currentIndex())
        tab.reset_active_field()
        self.statusBar().showMessage("Reset complete.", self.STATUS_BAR_TIMEOUT)

    def reset_overrides(self):
        """Reset all values from overrides including new proposals.
        """
        for i in range(self.tab_widget.count()):
            tab = self.tab_widget.widget(i)
            tab.reset_all()

        if self.extra_props_dir is not None:
            sys.path.remove(self.extra_props_dir)
            self.main_controller.remove_extra_proposals()
            self.extra_props_dir = None
        self.statusBar().showMessage("Reset complete.", self.STATUS_BAR_TIMEOUT)

    def closeEvent(self, event):
        """Handle close events.

        This function mainly saves out the current settings before the program
        is shutdown.

        Parameters
        ----------
        event : QEvent
            The event to process.
        """
        if self.ok_to_continue():
            settings = QtCore.QSettings()
            save_directory = QtCore.QVariant(self.save_directory) \
                if self.save_directory is not None else QtCore.QVariant()
            settings.setValue("LastDirectory", save_directory)
            recent_directories = QtCore.QVariant(self.recent_directories) \
                if self.recent_directories else QtCore.QVariant()
            settings.setValue("RecentDirectories", recent_directories)
        else:
            event.ignore()

    def update_file_menu(self):
        """Add a new saved directory into the File menu list.
        """
        self.file_menu.clear()
        self.add_actions(self.file_menu, self.file_menu_actions[:self.file_menu_offset])
        current = self.save_directory if self.save_directory is not None else None

        recent_directories = []
        if current is not None:
            self.file_menu.addAction(QtWidgets.QAction("Current:", self))
            self.file_menu.addAction(QtWidgets.QAction(str(current), self))
        self.file_menu.addSeparator()

        if self.recent_directories is not None:
            for rdir in self.recent_directories:
                if rdir != current and QtCore.QDir.exists(QtCore.QDir(rdir)):
                    recent_directories.append(rdir)
            if len(recent_directories) != 0:
                self.file_menu.addSeparator()
                self.file_menu.addAction(QtWidgets.QAction("Recent:", self))
                for i, rdir in enumerate(recent_directories):
                    action = QtWidgets.QAction("&{} {}".format(i + 1, rdir), self)
                    action.setData(QtCore.QVariant(rdir))
                    action.triggered.connect(self.set_internal_save_directory)
                    self.file_menu.addAction(action)
        else:
            self.recent_directories = []
        self.file_menu.addSeparator()
        self.add_actions(self.file_menu, self.file_menu_actions[self.file_menu_offset:])

    def ok_to_continue(self):
        """Placeholder function until events can be processed correctly.
        """
        return True

    def set_internal_save_directory(self):
        action = self.sender()
        if isinstance(action, QtWidgets.QAction):
            old_save_directory = self.save_directory
            self.save_directory = action.data()
            if self.save_directory in self.recent_directories:
                try:
                    self.recent_directories.remove(self.save_directory)
                except ValueError:
                    pass
            self.recent_directories.insert(0, old_save_directory)
            self.update_file_menu()

    def set_save_directory(self):
        """Add a save directory to the internals of the program.
        """
        old_save_directory = self.save_directory
        if old_save_directory == 'None':
            open_dir = os.path.expanduser("~/")
        else:
            open_dir = os.path.dirname(old_save_directory)
        self.save_directory = QtWidgets.QFileDialog.getExistingDirectory(self, "Set Save Directory",
                                                                         open_dir)

        if self.save_directory == "":
            self.save_directory = old_save_directory
            return

        if old_save_directory is None:
            return

        if old_save_directory not in self.recent_directories:
            self.recent_directories.insert(0, old_save_directory)
            while len(self.recent_directories) > self.RECENT_DIRECTORIES_TO_LIST:
                self.recent_directories.pop()
        self.update_file_menu()

    def get_diff_dict(self):
        """Get the dictionary of current differences.

        Returns
        -------
        dict
        """
        return self.main_controller.get_diff()

    def diff_report(self):
        """Show the current difference report.
        """
        dlg = ReportDialog()
        dlg.make_report(self.get_diff_dict())
        dlg.exec_()

    def proposal_creation(self):
        """Show the proposal creation wizard.
        """
        wizard = ProposalCreationWizard()
        wizard.set_save_directory(self.save_directory)
        wizard.resize(600, 500)
        wizard.exec_()
        self.statusBar().showMessage("Proposal saved.", self.STATUS_BAR_TIMEOUT)

    def about(self):
        """Show information about the program.
        """
        about = QtWidgets.QMessageBox()
        about.setIconPixmap(QtGui.QPixmap(":/socs_logo.png"))
        about.setWindowTitle("About OpSim4 Configuration UI")
        about.setStandardButtons(QtWidgets.QMessageBox.Ok)
        about.setInformativeText("""
                                 <b>Operations Simulator Configuration UI</b>
                                 <p>Version {}</p>
                                 <p>SOCS Version: {}</p>
                                 <p>This application is used to create override files and new
                                 proposals to modify the running of the Operations Simulator
                                 from the baseline configuration.
                                 <br><br>
                                 Copyright 2016-2017 LSST Simulations
                                 """.format(version, socs_version))

        about.exec_()
Beispiel #4
0
class OpsimConfig(QtWidgets.QMainWindow):
    """Top-level UI.
    """
    RECENT_DIRECTORIES_TO_LIST = 9
    STATUS_BAR_TIMEOUT = 3000

    def __init__(self, parent=None):
        """Initialize the class.

        Parameters
        ----------
        parent : QWidget
            The parent widget of this one.
        """
        QtWidgets.QMainWindow.__init__(self, parent)
        self.save_directory = None

        self.create_file_menu()
        self.create_reset_menu()
        self.create_create_menu()
        self.create_help_menu()

        self.tab_widget = QtWidgets.QTabWidget()
        self.main_controller = MainController()
        self.create_tabs()

        self.setCentralWidget(self.tab_widget)

        settings = QtCore.QSettings()
        self.recent_directories = settings.value("RecentDirectories")
        setting_save_dir = str(settings.value("LastDirectory"))
        if setting_save_dir != "":
            self.save_directory = setting_save_dir
        self.update_file_menu()

    def create_file_menu(self):
        """Create the file menu for the UI.
        """
        file_set_save_dir = self.create_action("Save Directory", self.set_save_directory, "Ctrl+D",
                                               "folder_open.svg",
                                               "Set the directory where the configurations will be saved.")
        file_clear_recent = self.create_action("Clear Recent List", self.clear_recent_list, "Ctrl+Alt+C",
                                               "clear.svg", "Clear the list of recent directories.")

        file_save_configs = self.create_action("&Save Configuration", self.save_configurations,
                                               QtGui.QKeySequence.Save,
                                               "filesave.svg", "Save the configuration to files.")
        file_quit_action = self.create_action("&Quit", self.close, "Ctrl+Q", "exit.svg",
                                              "Close the application.")

        self.file_menu = self.menuBar().addMenu("&File")
        self.file_menu_actions = (file_set_save_dir, file_clear_recent, None,
                                  file_save_configs, file_quit_action)
        self.file_menu.aboutToShow.connect(self.update_file_menu)

    def create_reset_menu(self):
        """Create the reset menu for the UI.
        """
        reset_all_defaults = self.create_action("All Defaults", self.reset_tabs, "Ctrl+R", "undo.svg",
                                                "Reset all values to defaults.")
        reset_active_tab_defaults = self.create_action("Active Tab Defaults", self.reset_active_tab, "Ctrl+T",
                                                       "undo_tab.svg",
                                                       "Reset all values in the active tab.")
        reset_active_field_default = self.create_action("Active Field Default", self.reset_active_field,
                                                        "Ctrl+Alt+F", "undo_field.svg",
                                                        "Reset value of the active field.")

        reset_menu = self.menuBar().addMenu("Reset")
        self.add_actions(reset_menu, (reset_all_defaults, reset_active_tab_defaults,
                                      reset_active_field_default))

    def create_create_menu(self):
        """ Create the create menu for the UI.
        """
        diff_report = self.create_action("Diff Report", self.diff_report, "Ctrl+Alt+R", "snavigator.svg",
                                         "Generate a difference report.")
        proposal_wizard = self.create_action("Proposal Creation", self.proposal_creation, "Ctrl+Alt+P",
                                             "document_new.svg",
                                             "Create a new proposal.")

        create_menu = self.menuBar().addMenu("Create")
        self.add_actions(create_menu, (diff_report, proposal_wizard))

    def create_help_menu(self):
        """Create the help menu for the UI.
        """
        help_about = self.create_action("&About", self.about, None, None,
                                        "About the OpSim Configuration UI program.")

        help_menu = self.menuBar().addMenu("&Help")
        self.add_actions(help_menu, (help_about,))

    def create_action(self, text, slot=None, shortcut=None, icon=None, tip=None, checkable=False,
                      signal_name="triggered"):
        """Create menu actions.

        Parameters
        ----------
        text : str
            A label for the action.
        slot : QtCore.pyqtSlot, optional
            A callback function for the action.
        shortcut : str, optional
            A keyboard shortcut for the action.
        icon : str, optional
            An icon path for the action.
        tip : str, optional
            A tooltip string for the action.
        checkable : bool, optional
            Is the action checkable?
        signal_name : str, optional
            The signal associated with the action. Default: triggered
        """
        action = QtWidgets.QAction(text, self)
        if icon is not None:
            action.setIcon(QtGui.QIcon(QtGui.QPixmap(":/{}".format(icon))))
            action.setIconVisibleInMenu(True)
        if shortcut is not None:
            action.setShortcut(shortcut)
        if tip is not None:
            action.setToolTip(tip)
            action.setStatusTip(tip)
        if slot is not None:
            signal = getattr(action, signal_name)
            signal.connect(slot)
        if checkable:
            action.setCheckable(True)
        return action

    def add_actions(self, target, actions):
        """Add menu actions.

        Prameters
        ---------
        target : QMenuItem
            The menu item to add the action to.
        actions : list(QAction)
            THe set of actions to apply.
        """
        for action in actions:
            if action is None:
                target.addSeparator()
            else:
                target.addAction(action)

    def clear_recent_list(self):
        """Clear out the list of recent directories.
        """
        self.recent_directories = []
        self.update_file_menu()

    def create_tabs(self):
        """Create all the configuration tabs.
        """
        tab_dict = self.main_controller.get_tabs()
        for key, tab in tab_dict.items():
            self.tab_widget.addTab(tab, title(key))

    @QtCore.pyqtSlot()
    def save_configurations(self):
        """Save the current differences to configuration files.
        """
        message = "Finished saving configuration"
        if self.save_directory is None:
            self.save_directory = os.curdir
            message += " in current working directory."
        else:
            message += "."
        for i in range(self.tab_widget.count()):
            tab = self.tab_widget.widget(i)
            tab.save(expand_path(str(self.save_directory)))
        self.statusBar().showMessage(message, self.STATUS_BAR_TIMEOUT)
        if self.save_directory == os.curdir:
            self.save_directory = None

    def reset_tabs(self):
        """Reset all fields in all tabs.
        """
        for i in range(self.tab_widget.count()):
            tab = self.tab_widget.widget(i)
            tab.reset_all()
        self.statusBar().showMessage("Reset complete.", self.STATUS_BAR_TIMEOUT)

    def reset_active_tab(self):
        """Reser all fields in the active tab.
        """
        tab = self.tab_widget.widget(self.tab_widget.currentIndex())
        tab.reset_active_tab()
        self.statusBar().showMessage("Reset complete.", self.STATUS_BAR_TIMEOUT)

    def reset_active_field(self):
        """Reset the active field in the current tab.
        """
        tab = self.tab_widget.widget(self.tab_widget.currentIndex())
        tab.reset_active_field()
        self.statusBar().showMessage("Reset complete.", self.STATUS_BAR_TIMEOUT)

    def closeEvent(self, event):
        """Handle close events.

        This function mainly saves out the current settings before the program
        is shutdown.

        Parameters
        ----------
        event : QEvent
            The event to process.
        """
        if self.ok_to_continue():
            settings = QtCore.QSettings()
            save_directory = QtCore.QVariant(self.save_directory) \
                if self.save_directory is not None else QtCore.QVariant()
            settings.setValue("LastDirectory", save_directory)
            recent_directories = QtCore.QVariant(self.recent_directories) \
                if self.recent_directories else QtCore.QVariant()
            settings.setValue("RecentDirectories", recent_directories)
        else:
            event.ignore()

    def update_file_menu(self):
        """Add a new saved directory into the File menu list.
        """
        self.file_menu.clear()
        self.add_actions(self.file_menu, self.file_menu_actions[:-2])
        current = self.save_directory if self.save_directory is not None else None

        recent_directories = []
        if current is not None:
            self.file_menu.addAction(QtWidgets.QAction("Current:", self))
            self.file_menu.addAction(QtWidgets.QAction(str(current), self))
        self.file_menu.addSeparator()

        if self.recent_directories is not None:
            for rdir in self.recent_directories:
                if rdir != current and QtCore.QDir.exists(QtCore.QDir(rdir)):
                    recent_directories.append(rdir)
            if len(recent_directories) != 0:
                self.file_menu.addSeparator()
                self.file_menu.addAction(QtWidgets.QAction("Recent:", self))
                for i, rdir in enumerate(recent_directories):
                    action = QtWidgets.QAction("&{} {}".format(i + 1, rdir), self)
                    action.setData(QtCore.QVariant(rdir))
                    action.triggered.connect(self.set_internal_save_directory)
                    self.file_menu.addAction(action)
        else:
            self.recent_directories = []
        self.file_menu.addSeparator()
        self.add_actions(self.file_menu, self.file_menu_actions[-2:])

    def ok_to_continue(self):
        """Placeholder function until events can be processed correctly.
        """
        return True

    def set_internal_save_directory(self):
        action = self.sender()
        if isinstance(action, QtWidgets.QAction):
            old_save_directory = self.save_directory
            self.save_directory = action.data()
            if self.save_directory in self.recent_directories:
                try:
                    self.recent_directories.remove(self.save_directory)
                except ValueError:
                    pass
            self.recent_directories.insert(0, old_save_directory)
            self.update_file_menu()

    def set_save_directory(self):
        """Add a save directory to the internals of the program.
        """
        old_save_directory = self.save_directory
        self.save_directory = QtWidgets.QFileDialog.getExistingDirectory(self, "Set Save Directory",
                                                                         os.path.expanduser("~/"))

        if self.save_directory == "":
            self.save_directory = old_save_directory
            return

        if old_save_directory is None:
            return

        if old_save_directory not in self.recent_directories:
            self.recent_directories.insert(0, old_save_directory)
            while len(self.recent_directories) > self.RECENT_DIRECTORIES_TO_LIST:
                self.recent_directories.pop()
        self.update_file_menu()

    def get_diff_dict(self):
        """Get the dictionary of current differences.

        Returns
        -------
        dict
        """
        return self.main_controller.get_diff()

    def diff_report(self):
        """Show the current difference report.
        """
        dlg = ReportDialog()
        dlg.make_report(self.get_diff_dict())
        dlg.exec_()

    def proposal_creation(self):
        """Show the proposal creation wizard.
        """
        wizard = ProposalCreationWizard()
        wizard.set_save_directory(self.save_directory)
        wizard.resize(600, 500)
        wizard.exec_()
        self.statusBar().showMessage("Proposal saved.", self.STATUS_BAR_TIMEOUT)

    def about(self):
        """Show information about the program.
        """
        about = QtWidgets.QMessageBox()
        about.setIconPixmap(QtGui.QPixmap(":/socs_logo.png"))
        about.setWindowTitle("About OpSim4 Configuration UI")
        about.setStandardButtons(QtWidgets.QMessageBox.Ok)
        about.setInformativeText("""
                                 <b>Operations Simulator Configuration UI</b>
                                 <p>Version {}</p>
                                 <p>This application is used to create override files and new
                                 proposals to modify the running of the Operations Simulator
                                 from the baseline configuration.
                                 <br><br>
                                 Copyright 2016 LSST Simulations
                                 """.format(version))
        about.exec_()