mirror of
https://github.com/CopterExpress/clever-show.git
synced 2026-05-26 07:07:58 +00:00
Added dialog for existing configs and server config dialog, improved config.py
This commit is contained in:
@@ -158,14 +158,14 @@ class ConfigModelItem:
|
||||
if self.spec_default is not None and self.data(1) == self.spec_default \
|
||||
and self.data(0) == self.default_values[0] and self.type != 'section':
|
||||
self.set_state('default')
|
||||
print('def', self.data(1), self.data(0), self.spec_default)
|
||||
# print('def', self.data(1), self.data(0), self.spec_default)
|
||||
|
||||
child_states = [child.state for child in self.childItems]
|
||||
if any(state in child_states for state in ['edited', 'added', 'deleted']):
|
||||
self.state = 'edited'
|
||||
if len(set(child_states)) == 1: # if all states equal
|
||||
self.set_state(child_states[0], set_children=False)
|
||||
print(child_states)
|
||||
# print(child_states)
|
||||
|
||||
if self.parentItem is not None:
|
||||
self.parentItem.check_state()
|
||||
@@ -285,7 +285,7 @@ class ConfigModel(QtCore.QAbstractItemModel):
|
||||
|
||||
childItem = index.internalPointer()
|
||||
if not isinstance(childItem, ConfigModelItem):
|
||||
print(childItem, index.column()), # index.row(), index.parent().internalPointer())
|
||||
# print(childItem, index.column()), # index.row(), index.parent().internalPointer())
|
||||
return QtCore.QModelIndex()
|
||||
parentItem = childItem.parent()
|
||||
|
||||
@@ -744,10 +744,15 @@ class ConfigDialog(QtWidgets.QDialog):
|
||||
super(ConfigDialog, self).__init__(parent)
|
||||
self.ui = config_editor.Ui_config_dialog()
|
||||
self.model = ConfigModel(widget=self)
|
||||
self._filename = None
|
||||
self.unsaved = False
|
||||
self.setupUi()
|
||||
self.copter_editor_signal.connect(self._call_copter_dialog)
|
||||
|
||||
@property
|
||||
def filename(self):
|
||||
return self._filename or 'Untitled.ini'
|
||||
|
||||
def setupModel(self, data, pure_dict=False, convert_types=False):
|
||||
if pure_dict:
|
||||
self.model.dict_setup(data, convert_types=convert_types)
|
||||
@@ -774,10 +779,12 @@ class ConfigDialog(QtWidgets.QDialog):
|
||||
|
||||
# self.ui.delete_button.pressed.connect(self.remove_selected)
|
||||
|
||||
def update_title(self):
|
||||
self.setWindowTitle(f"Config editor - {self.filename}" + "*"*self.unsaved)
|
||||
|
||||
def unsaved_call(self):
|
||||
name = self.windowTitle()+'*'
|
||||
self.setWindowTitle(name)
|
||||
self.unsaved = True
|
||||
self.update_title()
|
||||
self.model.dataChanged.disconnect(self.unsaved_call)
|
||||
|
||||
def closeEvent(self, event):
|
||||
@@ -803,13 +810,14 @@ class ConfigDialog(QtWidgets.QDialog):
|
||||
return reply == QMessageBox.Yes
|
||||
|
||||
def save_as(self):
|
||||
cfg = config.ConfigManager()
|
||||
cfg.load_from_dict(self.model.to_config_dict())
|
||||
save_path = QFileDialog.getSaveFileName(self, "Save as configuration file",
|
||||
directory=self.filename,
|
||||
filter="Config files (*.ini)")[0]
|
||||
if not save_path:
|
||||
return
|
||||
|
||||
cfg = config.ConfigManager()
|
||||
cfg.load_from_dict(self.model.to_config_dict())
|
||||
cfg.config.filename = save_path
|
||||
cfg.write()
|
||||
|
||||
@@ -841,21 +849,36 @@ class ConfigDialog(QtWidgets.QDialog):
|
||||
|
||||
@pyqtSlot(object, object)
|
||||
def _call_copter_dialog(self, client, value):
|
||||
logging.info("Opening dialog")
|
||||
logging.info("Opening copter config dialog")
|
||||
config_dict, spec_dict = value["config"], value["configspec"]
|
||||
cfg = config.ConfigManager()
|
||||
cfg.load_from_dict(config_dict, spec_dict)
|
||||
|
||||
self.setupModel(cfg.full_dict(include_defaults=True))
|
||||
if not self.validation_loop(cfg, spec_dict):
|
||||
return False
|
||||
def save_callback():
|
||||
edited_dict = cfg.full_dict(include_defaults=False)
|
||||
client.send_message("config", {"config": edited_dict, "mode": "rewrite"})
|
||||
|
||||
edited_dict = self.model.to_config_dict()
|
||||
client.send_message("config", {"config": edited_dict, "mode": "rewrite"})
|
||||
|
||||
if self.ui.do_restart.isChecked():
|
||||
def restart_callback():
|
||||
client.send_message("service_restart", {"name": "clever-show"})
|
||||
|
||||
if not self.call_config_dialog(cfg, save_callback, restart_callback, f"{client.copter_id}"):
|
||||
return False
|
||||
return True
|
||||
|
||||
def call_config_dialog(self, cfg: config.ConfigManager, on_save=None, on_restart=None, name="Untitled.ini"):
|
||||
self.setupModel(cfg.full_dict(include_defaults=True), convert_types=(not cfg.validated))
|
||||
self.ui.do_restart.setEnabled(on_restart is not None)
|
||||
self._filename = name
|
||||
self.update_title()
|
||||
|
||||
if not self.validation_loop(cfg, cfg.config.configspec):
|
||||
return False
|
||||
|
||||
if on_save is not None:
|
||||
on_save()
|
||||
|
||||
if on_restart is not None and self.ui.do_restart.isChecked():
|
||||
on_restart()
|
||||
return True
|
||||
|
||||
def call_standalone_dialog(self):
|
||||
@@ -872,26 +895,26 @@ class ConfigDialog(QtWidgets.QDialog):
|
||||
"Config cannot be opened or validated: {}".format(error))
|
||||
return False
|
||||
|
||||
self.setupModel(cfg.full_dict(include_defaults=True), convert_types=(not cfg.validated))
|
||||
self.ui.do_restart.setDisabled(True)
|
||||
def save_callback():
|
||||
if cfg.config.filename is None:
|
||||
save_path = QFileDialog.getSaveFileName(self, "Save configuration file",
|
||||
directory=self.filename,
|
||||
filter="Config files (*.ini)")[0]
|
||||
if not save_path:
|
||||
return False
|
||||
else:
|
||||
save_path = cfg.config.filename
|
||||
|
||||
filename = cfg.config.filename
|
||||
validation_path = path if cfg.config.filename is None else cfg.config.filename
|
||||
validation_path = validation_path if cfg.validated else None
|
||||
cfg.config.filename = save_path
|
||||
cfg.write()
|
||||
|
||||
if not self.validation_loop(cfg, validation_path):
|
||||
if cfg.config.filename is not None:
|
||||
name = os.path.split(cfg.config.filename)[1]
|
||||
else: # when editing only configspec-based file
|
||||
name = os.path.split(path)[1]
|
||||
|
||||
if not self.call_config_dialog(cfg, on_save=save_callback, name=name):
|
||||
return False
|
||||
|
||||
if filename is None:
|
||||
save_path = QFileDialog.getSaveFileName(self, "Save configuration file",
|
||||
filter="Config files (*.ini)")[0]
|
||||
if not save_path:
|
||||
return False
|
||||
else:
|
||||
save_path = filename
|
||||
|
||||
cfg.config.filename = save_path
|
||||
cfg.write()
|
||||
return True
|
||||
|
||||
|
||||
|
||||
@@ -41,6 +41,7 @@ def b_partial(func, *args, **kwargs): # call argument blocker partial
|
||||
|
||||
|
||||
def restart(): # move to core
|
||||
# ANY prints will break restarting or opening new windows after restart
|
||||
os.execl(sys.executable, os.path.abspath(__file__), *sys.argv)
|
||||
|
||||
|
||||
@@ -135,6 +136,10 @@ class MainWindow(QtWidgets.QMainWindow):
|
||||
self.ui.action_play_music.triggered.connect(self.play_music)
|
||||
self.ui.action_stop_music.triggered.connect(self.stop_music)
|
||||
|
||||
self.ui.action_edit_any_config.triggered.connect(ConfigDialog.call_standalone_dialog)
|
||||
self.ui.action_edit_server_config.triggered.connect(self.edit_server_config)
|
||||
|
||||
|
||||
self.ui.action_restart_server.triggered.connect(restart)
|
||||
self.ui.action_update_server_git.triggered.connect(update_server)
|
||||
|
||||
@@ -589,6 +594,15 @@ class MainWindow(QtWidgets.QMainWindow):
|
||||
def configure_columns(self):
|
||||
HeaderEditDialog(self.ui.copter_table, self.server.config).exec()
|
||||
|
||||
@pyqtSlot()
|
||||
def edit_server_config(self):
|
||||
config = self.server.config
|
||||
|
||||
def save_callback():
|
||||
config.write()
|
||||
|
||||
ConfigDialog().call_config_dialog(config, save_callback, restart, name="Server config")
|
||||
|
||||
def register_callbacks(self):
|
||||
@messaging.message_callback("telemetry")
|
||||
def get_telem_data(client, value, **kwargs):
|
||||
|
||||
38
config.py
38
config.py
@@ -48,7 +48,6 @@ class ValidationError(ValueError):
|
||||
class ConfigManager:
|
||||
def __init__(self, config=None):
|
||||
self.config = ConfigObj() if config is None else config
|
||||
self.validated = False
|
||||
|
||||
self._name_dict = {}
|
||||
|
||||
@@ -75,13 +74,16 @@ class ConfigManager:
|
||||
def write(self):
|
||||
self.config.write()
|
||||
|
||||
@property
|
||||
def validated(self):
|
||||
return self.config.configspec is not None
|
||||
|
||||
def set_config(self, config):
|
||||
self.config = config
|
||||
self._name_dict = self.flatten_keys(config)
|
||||
self.validated = False
|
||||
|
||||
def validate_config(self, config=None, copy_defaults=False):
|
||||
config = config or self.config
|
||||
config = self.config if config is None else config
|
||||
vdt = Validator()
|
||||
|
||||
test = config.validate(vdt, copy=copy_defaults, preserve_errors=True)
|
||||
@@ -89,7 +91,6 @@ class ConfigManager:
|
||||
raise ValidationError('Some config values are wrong', config, test)
|
||||
|
||||
self.set_config(config)
|
||||
self.validated = True
|
||||
|
||||
@classmethod
|
||||
def _full_dict(cls, item, include_defaults=False):
|
||||
@@ -263,21 +264,27 @@ class ConfigManager:
|
||||
final_comment = d.pop('final_comment', [''])
|
||||
|
||||
kwargs = {'infile': self._extract_values(d), 'indent_type': ''}
|
||||
filename = None
|
||||
if isinstance(configspec, dict):
|
||||
kwargs.update({'configspec': configspec})
|
||||
elif isinstance(configspec, str):
|
||||
spec_path = self._get_spec_path(configspec) # check for /spec, then for config
|
||||
if not self._config_exists(spec_path):
|
||||
spec_path = configspec
|
||||
if self._config_exists(spec_path):
|
||||
spec_path = self._get_spec_path(configspec)
|
||||
if self._config_exists(spec_path): # when 'configspec' points to configuration file and configspec exists
|
||||
kwargs.update({'configspec': spec_path})
|
||||
filename = configspec
|
||||
elif self._config_exists(configspec): # when 'configspec' points to configspec file
|
||||
kwargs.update({'configspec': configspec})
|
||||
if parent_dir(configspec) == 'spec':
|
||||
filename = self._get_config_path(configspec)
|
||||
else:
|
||||
raise ValueError("Configspec does not exist")
|
||||
|
||||
config = ConfigObj(**kwargs)
|
||||
config.filename = configspec if isinstance(configspec, str) else None
|
||||
config.filename = filename
|
||||
config.initial_comment = initial_comment
|
||||
config.final_comment = final_comment
|
||||
|
||||
if configspec is not None:
|
||||
if config.configspec is not None:
|
||||
self.validate_config(config)
|
||||
else:
|
||||
self.set_config(config)
|
||||
@@ -318,13 +325,14 @@ if __name__ == '__main__':
|
||||
import pprint
|
||||
#pprint.pprint(cfg.full_dict)
|
||||
cfg2 = ConfigManager()
|
||||
cfg2.load_from_dict({"PRIVATE": {"offset": [1, 2, 3]}}, configspec='Drone/config/spec/configspec_client.ini')
|
||||
#cfg2.load_from_dict({"PRIVATE": {"id": 123132}})
|
||||
#cfg2.load_from_dict({"PRIVATE": {"offset": [1, 2, 3]}}, configspec='Drone/config/spec/configspec_client.ini')
|
||||
cfg2.load_from_dict({"PRIVATE": {"id": "heh"}})
|
||||
#pprint.pprint(cfg2.full_dict)
|
||||
cfg.merge(cfg2)
|
||||
#cfg.merge(cfg2)
|
||||
#pprint.pprint(cfg.full_dict)
|
||||
print(cfg.full_dict(include_defaults=True))
|
||||
print(dict(cfg.config.configspec))
|
||||
print(cfg2.full_dict(include_defaults=True))
|
||||
#print(dict(cfg2.config.configspec))
|
||||
print(cfg2.config.PRIVATE)
|
||||
#print(dict(ConfigManager(cfg.config.configspec).config))
|
||||
|
||||
# #print(cfg.full_dict)
|
||||
|
||||
Reference in New Issue
Block a user