Example #1
0
    def __init__(self):
        # Init mounts
        self._mount_mgr = MountManager(None)
        self._mount_mgr.mount()

        QtGui.QMainWindow.__init__(self)
        Ui_MainWindow.__init__(self)
        self.setupUi(self)
        self._interface = VirtualPluginInterface()
        self._current_plugin = None
        self._current_plugin_instance = None
        self.lbl_restart_pipeline.hide()
        self._set_settings_visible(False)
        self._update_queue = set()

        connect(self.lst_plugins, QtCore.SIGNAL("itemSelectionChanged()"), self.on_plugin_selected)
        connect(self.lst_plugins, QtCore.SIGNAL("itemChanged(QListWidgetItem*)"), self.on_plugin_state_changed)
        connect(self.btn_reset_plugin_settings, QtCore.SIGNAL("clicked()"), self.on_reset_plugin_settings)

        self._load_plugin_list()

        # Adjust column widths
        self.table_plugin_settings.setColumnWidth(0, 110)
        self.table_plugin_settings.setColumnWidth(1, 80)
        self.table_plugin_settings.setColumnWidth(2, 120)

        update_thread = Thread(target=self.update_thread, args=())
        update_thread.start()
Example #2
0
    def __init__(self):

        # Init mounts
        self._mount_mgr = MountManager(None)
        self._mount_mgr.mount()

        QtGui.QMainWindow.__init__(self)
        self.setupUi()
        self._tree_widgets = []
        self._cmd_queue = set()

        # Construct a new virtual interface since we don't run in the pipeline
        self._interface = VirtualPluginInterface()
        self._interface.set_base_dir("../../")
        self._interface.load_plugin_config()
        self._interface.load_plugins()

        # Construct a new daytime manager with that interface
        self._daytime = DayTimeInterface(self._interface)
        self._daytime.set_base_dir("../../")
        self._daytime.load()

        self._update_settings_list()

        self._selected_setting_handle = None
        self._selected_setting = None
        self._selected_plugin = None
        self._current_time = 0.5
        self._on_time_changed(self.time_slider.value())
        self.set_settings_visible(False)

        self._bg_thread = Thread(target=self.updateThread)
        self._bg_thread.start()
Example #3
0
class PluginConfigurator(QtGui.QMainWindow, Ui_MainWindow):

    """ Interface to change the plugin settings """

    def __init__(self):
        # Init mounts
        self._mount_mgr = MountManager(None)
        self._mount_mgr.mount()

        QtGui.QMainWindow.__init__(self)
        Ui_MainWindow.__init__(self)
        self.setupUi(self)
        self._interface = VirtualPluginInterface()
        self._current_plugin = None
        self._current_plugin_instance = None
        self.lbl_restart_pipeline.hide()
        self._set_settings_visible(False)
        self._update_queue = set()

        connect(self.lst_plugins, QtCore.SIGNAL("itemSelectionChanged()"), self.on_plugin_selected)
        connect(self.lst_plugins, QtCore.SIGNAL("itemChanged(QListWidgetItem*)"), self.on_plugin_state_changed)
        connect(self.btn_reset_plugin_settings, QtCore.SIGNAL("clicked()"), self.on_reset_plugin_settings)

        self._load_plugin_list()

        # Adjust column widths
        self.table_plugin_settings.setColumnWidth(0, 110)
        self.table_plugin_settings.setColumnWidth(1, 80)
        self.table_plugin_settings.setColumnWidth(2, 120)

        update_thread = Thread(target=self.update_thread, args=())
        update_thread.start()

    def closeEvent(self, event):
        event.accept()
        import os
        os._exit(1)

    def on_reset_plugin_settings(self):
        """ Gets called when the user wants to reset settings of a plugin """

        # Ask the user if he's really sure about it
        msg = "Are you sure you want to reset the settings of '" + self._current_plugin_instance.get_name() + "'?\n"
        msg+= "This does not reset the Time of Day settings of this plugin.\n\n"
        msg+= "!! This cannot be undone !! They will be lost forever (a long time!)."
        reply = QtGui.QMessageBox.question(self, "Warning", 
                         msg, QtGui.QMessageBox.Yes, QtGui.QMessageBox.No)
        if reply == QtGui.QMessageBox.Yes:
            
            QtGui.QMessageBox.information(self, "Success", "Settings have been reset! You may have to restart the pipeline.")
            self._interface.reset_plugin_settings(self._current_plugin)

            # Save config
            self._interface.write_configuration()

            # Always show the restart hint, even if its not always required
            self._show_restart_hint()

            # Re-render everything
            self._load_plugin_list()

    def on_plugin_state_changed(self, item):
        plugin_id = item._plugin_id
        state = item.checkState() == QtCore.Qt.Checked
        self._interface.set_plugin_state(plugin_id, state)
        self._rewrite_plugin_config()
        self._show_restart_hint()

    def on_plugin_selected(self):
        """ Gets called when a plugin got selected in the plugin list """
        selected_item = self.lst_plugins.selectedItems()
        if not selected_item:
            self._current_plugin = None
            self._current_plugin_instance = None
            self._set_settings_visible(False)
            return
        assert(len(selected_item) == 1)
        selected_item = selected_item[0]
        self._current_plugin = selected_item._plugin_id
        self._current_plugin_instance = self._interface.get_plugin_handle(self._current_plugin)
        assert(self._current_plugin_instance is not None)
        self._render_current_plugin()
        self._set_settings_visible(True)

    def update_thread(self):
        while True:
            if len(self._update_queue) > 0:
                item = self._update_queue.pop()
                UDPListenerService.ping_thread(UDPListenerService.CONFIG_PORT, item)
            time.sleep(0.3)


    def _rewrite_plugin_config(self):
        """ Rewrites the plugin configuration """
        self._interface.write_configuration()

    def _render_current_plugin(self):
        """ Displays the currently selected plugin """        
        self.lbl_plugin_name.setText(self._current_plugin_instance.get_name())

        version_str = "Version " + self._current_plugin_instance.get_config().get_version()
        version_str += " by " + self._current_plugin_instance.get_config().get_author()

        self.lbl_plugin_version.setText(version_str)
        self.lbl_plugin_desc.setText(self._current_plugin_instance.get_config().get_description())

        self._render_current_settings()

    def _show_restart_hint(self):
        """ Shows a hint to restart the pipeline """
        self.lbl_restart_pipeline.show()

    def _render_current_settings(self):
        """ Renders the current plugin settings """
        settings = self._current_plugin_instance.get_config().get_settings()

        # remove all rows
        while self.table_plugin_settings.rowCount() > 0:
            self.table_plugin_settings.removeRow(0)

        label_font = QtGui.QFont()
        label_font.setPointSize(10)
        label_font.setFamily("Segoe UI")

        desc_font = QtGui.QFont()
        desc_font.setPointSize(8)
        desc_font.setFamily("Segoe UI")

        for index, (name, handle) in enumerate(iteritems(settings)):

            # Dont show hidden settings
            if not handle.evaluate_display_conditions(settings):
                continue

            row_index = self.table_plugin_settings.rowCount()

            # Increase row count
            self.table_plugin_settings.insertRow(self.table_plugin_settings.rowCount())

            label = QtGui.QLabel()
            label.setText(handle.label)
            label.setWordWrap(True)
            label.setFont(label_font)

            if handle.is_dynamic():
                # label.setBackground(QtGui.QColor(200, 255, 200, 255))
                label.setStyleSheet("background: rgba(162, 204, 128, 255);")
            else:
                label.setStyleSheet("background: rgba(230, 230, 230, 255);")

            label.setMargin(10)

            self.table_plugin_settings.setCellWidget(row_index, 0, label)

            item_default = QtGui.QTableWidgetItem()
            item_default.setText(str(handle.default))
            item_default.setTextAlignment(QtCore.Qt.AlignCenter)
            self.table_plugin_settings.setItem(row_index, 1, item_default)

            setting_widget = self._get_widget_for_setting(name, handle)
            self.table_plugin_settings.setCellWidget(row_index, 2, setting_widget)

            label_desc = QtGui.QLabel()
            label_desc.setText(handle.description)
            label_desc.setWordWrap(True)
            label_desc.setFont(desc_font)            
            label_desc.setStyleSheet("color: #555;padding: 5px;")

            self.table_plugin_settings.setCellWidget(row_index, 3, label_desc)

    def _do_update_setting(self, setting_id, value):

        # Check whether the setting is a runtime setting 
        setting_handle = self._current_plugin_instance.get_config().get_setting_handle(setting_id)

        # Skip the setting in case the value is equal
        if setting_handle.value == value:
            # print("Skipping setting")
            return
            
        # Otherwise set the new value
        setting_handle.set_value(value)

        self._interface.update_setting(self._current_plugin, setting_id, value)
        self._interface.write_configuration()

        if not setting_handle.is_dynamic():
            self._show_restart_hint()
        else:
            # In case the setting is dynamic, notice the pipeline about it:
            # print("Sending reload packet ...")
            self._update_queue.add(self._current_plugin + "." + setting_id)

        # Update GUI, but only in case of enum and bool values, since they can trigger
        # display conditions:
        if setting_handle.type == "ENUM" or setting_handle.type == "BOOL":
            self._render_current_settings()

    def _on_setting_bool_changed(self, setting_id, value):
        self._do_update_setting(setting_id, value == QtCore.Qt.Checked)

    def _on_setting_scalar_changed(self, setting_id, value):
        self._do_update_setting(setting_id, value)

    def _on_setting_enum_changed(self, setting_id, value):
        self._do_update_setting(setting_id, value)

    def _on_setting_slider_changed(self, setting_id, bound_objs, value):
        value /= 100000.0 # was stored packed
        self._do_update_setting(setting_id, value)

        for obj in bound_objs:
            obj.setValue(value)

    def _on_setting_spinbox_changed(self, setting_id, bound_objs, value):
        self._do_update_setting(setting_id, value)
        # Assume objects are sliders, so we need to rescale the value
        for obj in bound_objs:
            obj.setValue(value * 100000.0)

    def _get_widget_for_setting(self, setting_id, setting):
        """ Returns an appropriate widget to control the given setting """

        widget = QtGui.QWidget()
        layout = QtGui.QVBoxLayout()
        layout.setAlignment(QtCore.Qt.AlignCenter)
        widget.setLayout(layout)

        if setting.type == "BOOL":
            box = QtGui.QCheckBox()
            box.setChecked(QtCore.Qt.Checked if setting.value else QtCore.Qt.Unchecked)
            connect(box, QtCore.SIGNAL("stateChanged(int)"), 
                partial(self._on_setting_bool_changed, setting_id))
            layout.addWidget(box)

        elif setting.type == "FLOAT" or setting.type == "INT":

            if setting.type == "FLOAT":
                box = QtGui.QDoubleSpinBox()
                
                if setting.max_value - setting.min_value <= 2.0:
                    box.setDecimals(4)
            else:
                box = QtGui.QSpinBox()
            box.setMinimum(setting.min_value)
            box.setMaximum(setting.max_value)
            box.setValue(setting.value)

            box.setSingleStep( abs(setting.max_value - setting.min_value) / 100.0 )
            box.setAlignment(QtCore.Qt.AlignCenter)

            slider = QtGui.QSlider()
            slider.setOrientation(QtCore.Qt.Horizontal)
            slider.setMinimum(setting.min_value * 100000.0)
            slider.setMaximum(setting.max_value * 100000.0)
            slider.setValue(setting.value * 100000.0) 

            layout.addWidget(box)
            layout.addWidget(slider)

            connect(slider, QtCore.SIGNAL("valueChanged(int)"), 
                partial(self._on_setting_slider_changed, setting_id, [box]))

            value_type = "int" if setting.type == "INT" else "double"

            connect(box, QtCore.SIGNAL("valueChanged(" + value_type + ")"), 
                partial(self._on_setting_spinbox_changed, setting_id, [slider]))

        elif setting.type == "ENUM":
            box = QtGui.QComboBox()
            for value in setting.values:
                box.addItem(value)
            connect(box, QtCore.SIGNAL("currentIndexChanged(QString)"), 
                partial(self._on_setting_enum_changed, setting_id))
            box.setCurrentIndex(setting.values.index(setting.value))

            layout.addWidget(box)

        elif setting.type == "IMAGE":

            label = QtGui.QLabel()
            label.setText(setting.value)

            button = QtGui.QPushButton()
            button.setText("Choose File ...")
            connect(button, QtCore.SIGNAL("clicked()"), partial(self._choose_image, setting))

            layout.addWidget(label)
            layout.addWidget(button)

        return widget

    def _choose_image(self, setting_handle):
        """ Shows a file chooser to show an image from """

        filename = QtGui.QFileDialog.getOpenFileName(self, "Open Image", "", "Image Files (*.png)")
        print("Filename =", filename)

    def _set_settings_visible(self, flag):
        """ Sets whether the settings panel is visible or not """
        if flag:
            self.lbl_select_plugin.hide()
            self.frame_details.show()
        else:
            self.lbl_select_plugin.show()
            self.frame_details.hide()

    def _load_plugin_list(self):
        """ Reloads the whole plugin list """
        print("Loading plugin list")

        # Reset selection
        self._current_plugin = None
        self._current_plugin_instance = None

        self._set_settings_visible(False)

        # Plugins are all plugins in the plugins directory
        self._interface.unload_plugins()
        self._interface.load_plugins()
        plugins = self._interface.get_plugin_instances()

        self.lst_plugins.clear()

        for plugin in plugins:
            item = QtGui.QListWidgetItem()
            item.setText(" " + plugin.get_name())

            if self._interface.is_plugin_enabled(plugin.get_id()):
                item.setCheckState(QtCore.Qt.Checked)
            else:
                item.setCheckState(QtCore.Qt.Unchecked)

            item._plugin_id = plugin.get_id()
            self.lst_plugins.addItem(item)
Example #4
0
class DayTimeEditor(QtGui.QMainWindow, Ui_MainWindow):

    """ This is the main editor class which handles the user interface """

    def __init__(self):

        # Init mounts
        self._mount_mgr = MountManager(None)
        self._mount_mgr.mount()

        QtGui.QMainWindow.__init__(self)
        self.setupUi()
        self._tree_widgets = []
        self._cmd_queue = set()

        # Construct a new virtual interface since we don't run in the pipeline
        self._interface = VirtualPluginInterface()
        self._interface.set_base_dir("../../")
        self._interface.load_plugin_config()
        self._interface.load_plugins()

        # Construct a new daytime manager with that interface
        self._daytime = DayTimeInterface(self._interface)
        self._daytime.set_base_dir("../../")
        self._daytime.load()

        self._update_settings_list()

        self._selected_setting_handle = None
        self._selected_setting = None
        self._selected_plugin = None
        self._current_time = 0.5
        self._on_time_changed(self.time_slider.value())
        self.set_settings_visible(False)

        self._bg_thread = Thread(target=self.updateThread)
        self._bg_thread.start()

    def set_settings_visible(self, visibility):
        if not visibility:
            self.frame_current_setting.hide()
            self.lbl_select_setting.show()
        else:
            self.frame_current_setting.show()
            self.lbl_select_setting.hide()

    def closeEvent(self, event):
        event.accept()
        import os
        os._exit(1)

    def updateThread(self):
        """ Seperate update thread """

        while True:
            if self._cmd_queue:
                cmd = self._cmd_queue.pop()
                if cmd == "settime":
                    # TODO: Send time change over network
                    local_time = self._current_time
                    UDPListenerService.do_ping(UDPListenerService.DAYTIME_PORT, "settime " + str(local_time))

                elif cmd == "write_settings":

                    # Write settings
                    self._daytime.write_configuration()
                    UDPListenerService.do_ping(UDPListenerService.DAYTIME_PORT, "loadconf")

                else:
                    print("Unkown cmd:", cmd)

            time.sleep(0.2)

    def setupUi(self):
        """ Setups the UI Components """
        Ui_MainWindow.setupUi(self, self)
        self.settings_tree.setColumnWidth(0, 160)
        self.settings_tree.expandAll()

        self.edit_widget = CurveWidget(self)
        self.edit_widget.set_change_handler(self._on_curve_edited)
        self.prefab_edit_widget.addWidget(self.edit_widget)

        connect(self.time_slider, QtCore.SIGNAL("valueChanged(int)"), self._on_time_changed)
        connect(self.settings_tree, QtCore.SIGNAL("itemSelectionChanged()"), self._on_setting_selected)

    def _update_tree_widgets(self):
        """ Updates the tree widgets """
        for setting_handle, widget in self._tree_widgets:
            value = setting_handle.get_value(self._current_time)

            formatted = setting_handle.format(value)
            widget.setText(1, formatted)

            if setting_handle.type == "COLOR":
                widget.setBackground(1, QtGui.QBrush(QtGui.QColor(*value)))

    def _on_curve_edited(self):
        """ Called when the curve got edited in the curve widget """
        self._cmd_queue.add("write_settings")
        self._update_tree_widgets()

    def _on_setting_selected(self):
        """ Called when a setting got selected in the settings tree """
        selected = self.settings_tree.selectedItems()
        if len(selected) != 1:
            self._selected_setting = None
            self._selected_plugin = None
            self._selected_setting_handle = None
            self.edit_widget.set_curves([])
            self.set_settings_visible(False)
        else:
            selected = selected[0]

            self._selected_plugin = selected._plugin_id
            self._selected_setting = selected._setting_id
            self._selected_setting_handle = selected._setting_handle

            self.lbl_current_setting.setText(self._selected_setting_handle.label)
            self.lbl_setting_desc.setText(self._selected_setting_handle.description)

            self.edit_widget.set_curves(self._selected_setting_handle.curves)
            self.edit_widget.set_unit_processor(self._selected_setting_handle.format_nonlinear)
            self.set_settings_visible(True)
            self._update_tree_widgets()

    def _on_time_changed(self, val):
        """ Handler when the time slider got moved """
        hour = val / (60 * 60 * 60)
        minute = (val / (60 * 60)) % 60
        ftime = float(val) / (24 * 60 * 60 * 60)

        self.time_label.setText(str(hour).zfill(2) + ":" + str(minute).zfill(2))
        self.edit_widget.set_current_time(ftime)
        self._current_time = ftime
        self._update_tree_widgets()

        self._cmd_queue.add("settime")

    def _update_settings_list(self):
        """ Updates the list of visible settings """

        self.settings_tree.clear()
        self._tree_widgets = []

        for plugin in self._interface.get_plugin_instances():

            if not self._interface.is_plugin_enabled(plugin.get_id()):
                continue

            daytime_settings = plugin.get_config().get_daytime_settings()

            if not daytime_settings:
                # Skip plugins with empty settings
                continue

            plugin_head = QtGui.QTreeWidgetItem(self.settings_tree)
            plugin_head.setText(0, plugin.get_name())
            plugin_head.setFlags(QtCore.Qt.ItemIsEnabled)

            # Display all settings
            for setting, setting_handle in iteritems(daytime_settings):
                setting_item = QtGui.QTreeWidgetItem(plugin_head)
                setting_item.setText(0, setting_handle.label)
                setting_item.setFlags(QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable)
                setting_item._setting_id = setting
                setting_item._setting_handle = setting_handle
                setting_item._plugin_id = plugin.get_id()
                setting_item.setToolTip(0, setting_handle.description)
                setting_item.setToolTip(1, setting_handle.description)
                self._tree_widgets.append((setting_handle, setting_item))

        self.settings_tree.expandAll()