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() self._plugin_mgr = PluginManager(None) self._plugin_mgr.load() QtGui.QMainWindow.__init__(self) self.setupUi() self._tree_widgets = [] self._cmd_queue = set() 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): # noqa event.accept() import os os._exit(1) def updateThread(self): # noqa """ Seperate update thread """ while True: if self._cmd_queue: cmd = self._cmd_queue.pop() if cmd == "settime": NetworkCommunication.send_async( NetworkCommunication.DAYTIME_PORT, "settime " + str(self._current_time)) continue elif cmd == "write_settings": self._plugin_mgr.save_daytime_overrides("/$$rpconfig/daytime.yaml") NetworkCommunication.send_async( NetworkCommunication.DAYTIME_PORT, "loadconf") else: print("Unkown cmd:", cmd) time.sleep(0.1) def setupUi(self): # noqa """ 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) connect(self.btn_insert_point, QtCore.SIGNAL("clicked()"), self._insert_point) connect(self.btn_reset, QtCore.SIGNAL("clicked()"), self._reset_settings) def _reset_settings(self): """ Resets the current plugins settings """ # QtGui.QMessageBox.warning(self, "Houston, we have a problem!", # "This functionality is not yet implemented! Blame tobspr if you need it.\n\n" # "On a more serious note, you can still hand-edit config/daytime.yaml.", # QtGui.QMessageBox.Ok, QtGui.QMessageBox.Ok) # Ask the user if he's really sure about it msg = "Are you sure you want to reset the control points of '" +\ self._selected_setting_handle.label + "'?\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", "Control points have been reset!") default = self._selected_setting_handle.default self._selected_setting_handle.curves[0].set_single_value(default) self._update_settings_list() self._cmd_queue.add("write_settings") def _insert_point(self): """ Asks the user to insert a new point """ dialog = PointDialog(self) if dialog.exec_(): time, val = dialog.get_value() minutes = (time.hour() * 60 + time.minute()) / (24 * 60) if (val < self._selected_setting_handle.minvalue or val > self._selected_setting_handle.maxvalue): QtGui.QMessageBox.information( self, "Invalid Value", "Value is out of setting range!", QtGui.QMessageBox.Ok) return val_linear = self._selected_setting_handle.get_linear_value(val) self._selected_setting_handle.curves[0].append_cv(minutes, val_linear) self._cmd_queue.add("write_settings") def _update_tree_widgets(self): """ Updates the tree widgets """ for setting_handle, widget in self._tree_widgets: value = setting_handle.get_scaled_value_at(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) if self._selected_setting_handle.type == "color": self.edit_widget.set_unit_processor(lambda x: str(int(x * 255))) self.btn_insert_point.hide() else: self.edit_widget.set_unit_processor( lambda x: self._selected_setting_handle.format( self._selected_setting_handle.get_scaled_value(x))) self.btn_insert_point.show() 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.time_float_label.setText("{:1.4f}".format(ftime)) 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_id, plugin in iteritems(self._plugin_mgr.instances): daytime_settings = self._plugin_mgr.day_settings[plugin_id] if not daytime_settings: # Skip plugins with empty settings continue plugin_head = QtGui.QTreeWidgetItem(self.settings_tree) plugin_head.setText(0, plugin.name) plugin_head.setFlags(QtCore.Qt.ItemIsEnabled) font = QtGui.QFont() font.setBold(True) if not self._plugin_mgr.is_plugin_enabled(plugin_id): plugin_head.setText(0, plugin.name) plugin_head.setFont(0, font) # 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.setTextColor(0, QtGui.QColor(150, 150, 150)) 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_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()
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() self._plugin_mgr = PluginManager(None) self._plugin_mgr.requires_daytime_settings = False QtGui.QMainWindow.__init__(self) Ui_MainWindow.__init__(self) self.setupUi(self) self._current_plugin = None self._current_plugin_instance = None self.lbl_restart_pipeline.hide() self._set_settings_visible(False) self._update_queue = list() 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): # noqa 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 '" msg += self._current_plugin_instance.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._plugin_mgr.reset_plugin_settings(self._current_plugin) # Save config self._plugin_mgr.save_overrides("/$$rpconfig/plugins.yaml") # 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): """ Handler when a plugin got activated/deactivated """ plugin_id = item._plugin_id state = item.checkState() == QtCore.Qt.Checked self._plugin_mgr.set_plugin_enabled(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._plugin_mgr.instances[self._current_plugin] assert(self._current_plugin_instance is not None) self._render_current_plugin() self._set_settings_visible(True) def update_thread(self): """ Internal update thread """ while True: if len(self._update_queue) > 0: item = self._update_queue.pop(-1) NetworkCommunication.send_async(NetworkCommunication.CONFIG_PORT, item) if item.startswith("setval "): setting_id = item.split()[1] for entry in list(self._update_queue): if entry.split()[1] == setting_id: self._update_queue.remove(entry) time.sleep(0.2) def _rewrite_plugin_config(self): """ Rewrites the plugin configuration """ self._plugin_mgr.save_overrides("/$$rpconfig/plugins.yaml") def _render_current_plugin(self): """ Displays the currently selected plugin """ self.lbl_plugin_name.setText(self._current_plugin_instance.name) version_str = "Version " + self._current_plugin_instance.version version_str += " by " + self._current_plugin_instance.author self.lbl_plugin_version.setText(version_str) self.lbl_plugin_desc.setText(self._current_plugin_instance.description) if "(!)" in version_str: self.lbl_plugin_version.setStyleSheet( "background: rgb(200, 50, 50); padding: 5px; color: #eee;" "padding-left: 3px; border-radius: 3px;") else: self.lbl_plugin_version.setStyleSheet("color: #4f8027;") 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._plugin_mgr.settings[self._current_plugin] # 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)): if not handle.should_be_visible(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.shader_runtime or handle.runtime: # 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): """ Updates a setting of the current plugin """ # Check whether the setting is a runtime setting setting_handle = self._plugin_mgr.get_setting_handle( self._current_plugin, setting_id) # Skip the setting in case the value is equal if setting_handle.value == value: return # Otherwise set the new value setting_handle.set_value(value) self._rewrite_plugin_config() if not setting_handle.runtime and not setting_handle.shader_runtime: self._show_restart_hint() else: # In case the setting is dynamic, notice the pipeline about it: # print("Sending reload packet ...") self._update_queue.append("setval {}.{} {}".format( self._current_plugin, setting_id, value)) # 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, setting_type, bound_objs, value): if setting_type == "float": value /= 100000.0 self._do_update_setting(setting_id, value) for obj in bound_objs: obj.setValue(value) def _on_setting_spinbox_changed(self, setting_id, setting_type, 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 if setting_type == "float" else value) def _choose_path(self, setting_id, setting_handle, bound_objs): """ Shows a file chooser to show an path from """ this_dir = os.path.dirname(os.path.realpath(__file__)) plugin_dir = os.path.join(this_dir, "../../rpplugins/" + self._current_plugin, "resources") plugin_dir = os.path.abspath(plugin_dir) search_dir = os.path.join(plugin_dir, setting_handle.base_path) print("Plugin dir =", plugin_dir) print("Search dir =", search_dir) current_file = setting_handle.value.replace("\\", "/").split("/")[-1] print("Current file =", current_file) file_dlg = QtGui.QFileDialog(self, "Choose File ..", search_dir, setting_handle.file_type) file_dlg.selectFile(current_file) # file_dlg.setViewMode(QtGui.QFileDialog.Detail) if file_dlg.exec_(): filename = file_dlg.selectedFiles() filename = filename[-1] print("QT selected files returned:", filename) filename = os.path.relpath(str(filename), plugin_dir) filename = filename.replace("\\", "/") print("Relative path is", filename) self._do_update_setting(setting_id, filename) display_file = filename.split("/")[-1] for obj in bound_objs: obj.setText(display_file) 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.maxval - setting.minval <= 2.0: box.setDecimals(4) else: box = QtGui.QSpinBox() box.setMinimum(setting.minval) box.setMaximum(setting.maxval) box.setValue(setting.value) box.setAlignment(QtCore.Qt.AlignCenter) slider = QtGui.QSlider() slider.setOrientation(QtCore.Qt.Horizontal) if setting.type == "float": box.setSingleStep(abs(setting.maxval - setting.minval) / 100.0) slider.setMinimum(setting.minval * 100000.0) slider.setMaximum(setting.maxval * 100000.0) slider.setValue(setting.value * 100000.0) elif setting.type == "int": box.setSingleStep(max(1, (setting.maxval - setting.minval) / 32)) slider.setMinimum(setting.minval) slider.setMaximum(setting.maxval) slider.setValue(setting.value) layout.addWidget(box) layout.addWidget(slider) connect(slider, QtCore.SIGNAL("valueChanged(int)"), partial(self._on_setting_slider_changed, setting_id, setting.type, [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, setting.type, [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 == "path": label = QtGui.QLabel() display_file = setting.value.replace("\\", "/").split("/")[-1] desc_font = QtGui.QFont() desc_font.setPointSize(7) desc_font.setFamily("Segoe UI") label.setText(display_file) label.setFont(desc_font) button = QtGui.QPushButton() button.setText("Choose File ...") connect(button, QtCore.SIGNAL("clicked()"), partial( self._choose_path, setting_id, setting, (label,))) layout.addWidget(label) layout.addWidget(button) else: print("ERROR: Unkown setting type:", setting.type) return widget 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._plugin_mgr.unload() self._plugin_mgr.load() self.lst_plugins.clear() plugins = sorted(iteritems(self._plugin_mgr.instances), key=lambda plg: plg[1].name) for plugin_id, instance in plugins: item = QtGui.QListWidgetItem() item.setText(" " + instance.name) if self._plugin_mgr.is_plugin_enabled(plugin_id): item.setCheckState(QtCore.Qt.Checked) else: item.setCheckState(QtCore.Qt.Unchecked) item._plugin_id = plugin_id self.lst_plugins.addItem(item)
# Extract data print("Extracting data ..") lines = data.replace("\r", "").split("\n")[1:] # Load render pipeline api print("Loading plugin api ..") sys.path.insert(0, "../../") from rpcore.pluginbase.manager import PluginManager from rpcore.mount_manager import MountManager mount_mgr = MountManager(None) mount_mgr.mount() plugin_mgr = PluginManager(None) plugin_mgr.load() convert_to_linear = plugin_mgr.day_settings["scattering"]["sun_intensity"].get_linear_value hour, minutes = 0, 0 data_points_azimuth = [] data_points_altitude = [] data_points_intensity = [] for line in lines: if not line: break date, time, azim_angle, declination, ascension, elevation = line.split(",") float_azim = (float(azim_angle) + 180) / 360
class PluginConfigurator(QMainWindow, Ui_MainWindow): """ Interface to change the plugin settings """ def __init__(self): # Init mounts self._mount_mgr = MountManager(None) self._mount_mgr.mount() self._plugin_mgr = PluginManager(None) self._plugin_mgr.requires_daytime_settings = False QMainWindow.__init__(self) Ui_MainWindow.__init__(self) self.setupUi(self) self._current_plugin = None self._current_plugin_instance = None self.lbl_restart_pipeline.hide() self._set_settings_visible(False) self._update_queue = list() qt_connect(self.lst_plugins, "itemSelectionChanged()", self.on_plugin_selected) qt_connect(self.lst_plugins, "itemChanged(QListWidgetItem*)", self.on_plugin_state_changed) qt_connect(self.btn_reset_plugin_settings, "clicked()", self.on_reset_plugin_settings) self._load_plugin_list() # Adjust column widths self.table_plugin_settings.setColumnWidth(0, 140) self.table_plugin_settings.setColumnWidth(1, 105) self.table_plugin_settings.setColumnWidth(2, 160) update_thread = Thread(target=self.update_thread, args=()) update_thread.start() def closeEvent(self, event): # noqa 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 '" msg += self._current_plugin_instance.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 = QMessageBox.question(self, "Warning", msg, QMessageBox.Yes, QMessageBox.No) if reply == QMessageBox.Yes: QMessageBox.information( self, "Success", "Settings have been reset! You may have to restart the pipeline." ) self._plugin_mgr.reset_plugin_settings(self._current_plugin) # Save config self._plugin_mgr.save_overrides("/$$rp/config/plugins.yaml") # 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): """ Handler when a plugin got activated/deactivated """ plugin_id = item._plugin_id state = item.checkState() == Qt.Checked self._plugin_mgr.set_plugin_enabled(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._plugin_mgr.instances[ self._current_plugin] assert (self._current_plugin_instance is not None) self._render_current_plugin() self._set_settings_visible(True) def update_thread(self): """ Internal update thread """ while True: if len(self._update_queue) > 0: item = self._update_queue.pop(-1) NetworkCommunication.send_async( NetworkCommunication.CONFIG_PORT, item) if item.startswith("setval "): setting_id = item.split()[1] for entry in list(self._update_queue): if entry.split()[1] == setting_id: self._update_queue.remove(entry) time.sleep(0.2) def _rewrite_plugin_config(self): """ Rewrites the plugin configuration """ self._plugin_mgr.save_overrides("/$$rp/config/plugins.yaml") def _render_current_plugin(self): """ Displays the currently selected plugin """ self.lbl_plugin_name.setText( self._current_plugin_instance.name.upper() + " <span style='color: #999; margin-left: 5px;'>[" + self._current_plugin_instance.plugin_id + "]</span>") version_str = "Version " + self._current_plugin_instance.version version_str += " by " + self._current_plugin_instance.author self.lbl_plugin_version.setText(version_str) self.lbl_plugin_desc.setText(self._current_plugin_instance.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._plugin_mgr.settings[self._current_plugin] # remove all rows while self.table_plugin_settings.rowCount() > 0: self.table_plugin_settings.removeRow(0) label_font = QFont() label_font.setPointSize(10) label_font.setFamily("Roboto") desc_font = QFont() desc_font.setPointSize(8) desc_font.setFamily("Roboto") for index, (name, handle) in enumerate(iteritems(settings)): if not handle.should_be_visible(settings): continue row_index = self.table_plugin_settings.rowCount() # Increase row count self.table_plugin_settings.insertRow( self.table_plugin_settings.rowCount()) label = QLabel() label.setText(handle.label) label.setWordWrap(True) label.setFont(label_font) if not (handle.shader_runtime or handle.runtime): label.setStyleSheet("color: #999;") if handle.display_conditions: label.setStyleSheet(label.styleSheet() + "padding-left: 10px;") label.setMargin(10) self.table_plugin_settings.setCellWidget(row_index, 0, label) item_default = QTableWidgetItem() item_default.setText(str(handle.default)) item_default.setTextAlignment(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 = 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): """ Updates a setting of the current plugin """ # Check whether the setting is a runtime setting setting_handle = self._plugin_mgr.get_setting_handle( self._current_plugin, setting_id) # Skip the setting in case the value is equal if setting_handle.value == value: return # Otherwise set the new value setting_handle.set_value(value) self._rewrite_plugin_config() if not setting_handle.runtime and not setting_handle.shader_runtime: self._show_restart_hint() else: # In case the setting is dynamic, notice the pipeline about it: # print("Sending reload packet ...") self._update_queue.append("setval {}.{} {}".format( self._current_plugin, setting_id, value)) # 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 == 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_power_of_two_changed(self, setting_id, value): self._do_update_setting(setting_id, value) def _on_setting_slider_changed(self, setting_id, setting_type, bound_objs, value): if setting_type == "float": value /= 100000.0 self._do_update_setting(setting_id, value) for obj in bound_objs: obj.setValue(value) def _on_setting_spinbox_changed(self, setting_id, setting_type, 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 if setting_type == "float" else value) def _choose_path(self, setting_id, setting_handle, bound_objs): """ Shows a file chooser to show an path from """ this_dir = os.path.dirname(os.path.realpath(__file__)) plugin_dir = os.path.join(this_dir, "../../rpplugins/" + self._current_plugin, "resources") plugin_dir = os.path.abspath(plugin_dir) search_dir = os.path.join(plugin_dir, setting_handle.base_path) print("Plugin dir =", plugin_dir) print("Search dir =", search_dir) current_file = setting_handle.value.replace("\\", "/").split("/")[-1] print("Current file =", current_file) file_dlg = QFileDialog(self, "Choose File ..", search_dir, setting_handle.file_type) file_dlg.selectFile(current_file) # file_dlg.setViewMode(QFileDialog.Detail) if file_dlg.exec_(): filename = file_dlg.selectedFiles() filename = filename[-1] print("QT selected files returned:", filename) filename = os.path.relpath(str(filename), plugin_dir) filename = filename.replace("\\", "/") print("Relative path is", filename) self._do_update_setting(setting_id, filename) display_file = filename.split("/")[-1] for obj in bound_objs: obj.setText(display_file) def _get_widget_for_setting(self, setting_id, setting): """ Returns an appropriate widget to control the given setting """ widget = QWidget() layout = QHBoxLayout() layout.setAlignment(Qt.AlignCenter) widget.setLayout(layout) if setting.type == "bool": box = QCheckBox() box.setChecked(Qt.Checked if setting.value else Qt.Unchecked) qt_connect(box, "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 = QDoubleSpinBox() if setting.maxval - setting.minval <= 2.0: box.setDecimals(4) else: box = QSpinBox() box.setMinimum(setting.minval) box.setMaximum(setting.maxval) box.setValue(setting.value) box.setAlignment(Qt.AlignCenter) slider = QSlider() slider.setOrientation(Qt.Horizontal) if setting.type == "float": box.setSingleStep(abs(setting.maxval - setting.minval) / 100.0) slider.setMinimum(setting.minval * 100000.0) slider.setMaximum(setting.maxval * 100000.0) slider.setValue(setting.value * 100000.0) elif setting.type == "int": box.setSingleStep( max(1, (setting.maxval - setting.minval) / 32)) slider.setMinimum(setting.minval) slider.setMaximum(setting.maxval) slider.setValue(setting.value) layout.addWidget(box) layout.addWidget(slider) qt_connect( slider, "valueChanged(int)", partial(self._on_setting_slider_changed, setting_id, setting.type, [box])) value_type = "int" if setting.type == "int" else "double" qt_connect( box, "valueChanged(" + value_type + ")", partial(self._on_setting_spinbox_changed, setting_id, setting.type, [slider])) elif setting.type == "enum": box = QComboBox() for value in setting.values: box.addItem(value) qt_connect(box, "currentIndexChanged(QString)", partial(self._on_setting_enum_changed, setting_id)) box.setCurrentIndex(setting.values.index(setting.value)) box.setMinimumWidth(145) layout.addWidget(box) elif setting.type == "power_of_two": box = QComboBox() resolutions = [ str(2**i) for i in range(1, 32) if 2**i >= setting.minval and 2**i <= setting.maxval ] for value in resolutions: box.addItem(value) qt_connect( box, "currentIndexChanged(QString)", partial(self._on_setting_power_of_two_changed, setting_id)) box.setCurrentIndex(resolutions.index(str(setting.value))) box.setMinimumWidth(145) layout.addWidget(box) elif setting.type == "sample_sequence": box = QComboBox() for value in setting.sequences: box.addItem(value) qt_connect(box, "currentIndexChanged(QString)", partial(self._on_setting_enum_changed, setting_id)) box.setCurrentIndex(setting.sequences.index(str(setting.value))) box.setMinimumWidth(145) layout.addWidget(box) elif setting.type == "path": label = QLabel() display_file = setting.value.replace("\\", "/").split("/")[-1] desc_font = QFont() desc_font.setPointSize(7) desc_font.setFamily("Roboto") label.setText(display_file) label.setFont(desc_font) button = QPushButton() button.setText("Choose File ...") qt_connect( button, "clicked()", partial(self._choose_path, setting_id, setting, (label, ))) layout.addWidget(label) layout.addWidget(button) else: print("ERROR: Unkown setting type:", setting.type) return widget def _set_settings_visible(self, flag): """ Sets whether the settings panel is visible or not """ if flag: self.frame_details.show() else: 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._plugin_mgr.unload() self._plugin_mgr.load() self.lst_plugins.clear() plugins = sorted(iteritems(self._plugin_mgr.instances), key=lambda plg: plg[1].name) item_font = QFont() item_font.setBold(False) item_font.setPointSize(10) for plugin_id, instance in plugins: item = QListWidgetItem() item.setText(" " + instance.name) item.setFont(item_font) if self._plugin_mgr.is_plugin_enabled(plugin_id): item.setCheckState(Qt.Checked) else: item.setCheckState(Qt.Unchecked) item._plugin_id = plugin_id self.lst_plugins.addItem(item) self.lst_plugins.setCurrentRow(0)
class DayTimeEditor(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() self._plugin_mgr = PluginManager(None) self._plugin_mgr.load() QMainWindow.__init__(self) self.setupUi() self._tree_widgets = [] self._cmd_queue = set() self._selected_setting_handle = None self._selected_setting = None self._selected_plugin = None self._current_time = 0.5 self._update_settings_list() self._on_time_changed(self.time_slider.value()) 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() else: self.frame_current_setting.show() def closeEvent(self, event): # noqa event.accept() import os os._exit(1) def updateThread(self): # noqa """ Seperate update thread """ while True: if self._cmd_queue: cmd = self._cmd_queue.pop() if cmd == "settime": NetworkCommunication.send_async( NetworkCommunication.DAYTIME_PORT, "settime " + str(self._current_time)) continue elif cmd == "write_settings": self._plugin_mgr.save_daytime_overrides("/$$rp/config/daytime.yaml") NetworkCommunication.send_async( NetworkCommunication.DAYTIME_PORT, "loadconf") else: print("Unkown cmd:", cmd) time.sleep(0.1) def setupUi(self): # noqa """ 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) qt_connect(self.time_slider, "valueChanged(int)", self._on_time_changed) qt_connect(self.settings_tree, "itemSelectionChanged()", self._on_setting_selected) qt_connect(self.btn_insert_point, "clicked()", self._insert_point) qt_connect(self.btn_reset, "clicked()", self._reset_settings) def _reset_settings(self): """ Resets the current plugins settings """ # QMessageBox.warning(self, "Houston, we have a problem!", # "This functionality is not yet implemented! Blame tobspr if you need it.\n\n" # "On a more serious note, you can still hand-edit config/daytime.yaml.", # QMessageBox.Ok, QMessageBox.Ok) # Ask the user if he's really sure about it msg = "Are you sure you want to reset the control points of '" +\ self._selected_setting_handle.label + "'?\n" msg += "!! This cannot be undone !! They will be lost forever (a long time!)." reply = QMessageBox.question( self, "Warning", msg, QMessageBox.Yes, QMessageBox.No) if reply == QMessageBox.Yes: QMessageBox.information(self, "Success", "Control points have been reset!") default = self._selected_setting_handle.default if type(default) not in (tuple, list): default = [default] for i, val, in enumerate(default): self._selected_setting_handle.curves[i].set_single_value(val) self._update_settings_list() self._cmd_queue.add("write_settings") def _insert_point(self): """ Asks the user to insert a new point """ dialog = PointDialog(self) if dialog.exec_(): time, val = dialog.get_value() minutes = (time.hour() * 60 + time.minute()) / (24 * 60) if (val < self._selected_setting_handle.minvalue or val > self._selected_setting_handle.maxvalue): QMessageBox.information( self, "Invalid Value", "Value is out of setting range!", QMessageBox.Ok) return val_linear = self._selected_setting_handle.get_linear_value(val) self._selected_setting_handle.curves[0].append_cv(minutes, val_linear) self._cmd_queue.add("write_settings") def _update_tree_widgets(self): """ Updates the tree widgets """ for setting_handle, widget in self._tree_widgets: value = setting_handle.get_scaled_value_at(self._current_time) formatted = setting_handle.format(value) widget.setText(1, formatted) if setting_handle.type == "color": widget.setBackground(1, QBrush(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) if self._selected_setting_handle.type == "color": self.edit_widget.set_unit_processor(lambda x: str(int(x * 255))) self.btn_insert_point.hide() else: self.edit_widget.set_unit_processor( lambda x: self._selected_setting_handle.format( self._selected_setting_handle.get_scaled_value(x))) self.btn_insert_point.show() 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.time_float_label.setText("{:1.4f}".format(ftime)) 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 = [] first_item = None for plugin_id, plugin in iteritems(self._plugin_mgr.instances): daytime_settings = self._plugin_mgr.day_settings[plugin_id] if not daytime_settings: # Skip plugins with empty settings continue plugin_head = QTreeWidgetItem(self.settings_tree) plugin_head.setText(0, plugin.name) plugin_head.setFlags(Qt.ItemIsEnabled) font = QFont() font.setBold(True) if not self._plugin_mgr.is_plugin_enabled(plugin_id): plugin_head.setText(0, plugin.name) plugin_head.setFont(0, font) # Display all settings for setting, setting_handle in iteritems(daytime_settings): setting_item = QTreeWidgetItem(plugin_head) setting_item.setText(0, setting_handle.label) if PYQT_VERSION == 4: setting_item.setTextColor(0, QColor(150, 150, 150)) else: setting_item.setForeground(0, QColor(150, 150, 150)) setting_item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable) setting_item._setting_id = setting setting_item._setting_handle = setting_handle setting_item._plugin_id = plugin_id setting_item.setToolTip(0, setting_handle.description) setting_item.setToolTip(1, setting_handle.description) self._tree_widgets.append((setting_handle, setting_item)) if not first_item: first_item = setting_item self.settings_tree.expandAll() if first_item: self.settings_tree.setCurrentItem(first_item)
# Extract data print("Extracting data ..") lines = data.replace("\r", "").split("\n")[1:] # Load render pipeline api print("Loading plugin api ..") sys.path.insert(0, "../../") from rpcore.pluginbase.manager import PluginManager from rpcore.mount_manager import MountManager mount_mgr = MountManager(None) mount_mgr.mount() plugin_mgr = PluginManager(None) plugin_mgr.load() convert_to_linear = plugin_mgr.day_settings["scattering"][ "sun_intensity"].get_linear_value hour, minutes = 0, 0 data_points_azimuth = [] data_points_altitude = [] data_points_intensity = [] for line in lines: if not line: break date, time, azim_angle, declination, ascension, elevation = line.split( ",")