Added ability to save and load widths of columns to config

This commit is contained in:
Artem30801
2020-02-15 00:41:43 +03:00
parent 1eeb820969
commit fe38e82573
5 changed files with 87 additions and 47 deletions

View File

@@ -12,21 +12,21 @@ config_version = float(default='0.0')
[[PRESETS]]
current = string(default="DEFAULT")
[[[DEFAULT]]]
copter_id = boolean(default=True)
git_version = boolean(default=True)
animation_id = boolean(default=True)
battery = boolean(default=True)
fcu_status = boolean(default=True)
calibration_status = boolean(default=True)
mode = boolean(default=True)
selfcheck = boolean(default=True)
current_position = boolean(default=True)
start_position = boolean(default=True)
last_task = boolean(default=True)
time_delta = boolean(default=True)
config_version = boolean(default=True)
copter_id = preset_param(default=list(True, 150))
git_version = preset_param(default=list(True, 100))
config_version = preset_param(default=list(True, 100))
animation_id = preset_param(default=list(True, 100))
battery = preset_param(default=list(True, 100))
fcu_status = preset_param(default=list(True, 100))
calibration_status = preset_param(default=list(True, 100))
mode = preset_param(default=list(True, 100))
selfcheck = preset_param(default=list(True, 100))
current_position = preset_param(default=list(True, 100))
start_position = preset_param(default=list(True, 100))
last_task = preset_param(default=list(True, 100))
time_delta = preset_param(default=list(True, 100))
[[[__many__]]]
__many__ = boolean
__many__ = preset_param
[CHECKS]
battery_min = float(default=50.0, min=0, max=100)

View File

@@ -16,7 +16,7 @@ def save_preset(config, current, header_dict):
presets = config.table_presets
for key in presets[HeaderEditWidget.default]:
if key not in presets[current] and not header_dict[key]:
if key not in presets[current] and not header_dict[key][0]:
header_dict.pop(key)
presets[current] = header_dict
@@ -33,7 +33,8 @@ class HeaderViewFilter(QObject):
if event.type() == QEvent.Enter:
# logicalIndex = self.header.logicalIndexAt(event.pos())
self.parent().cellHover.emit(QModelIndex())
else:
return False
return True
@@ -147,20 +148,36 @@ class CopterTableWidget(QTableView):
if index_to != index_from:
self.horizontalHeader().moveSection(index_from, index_to)
def load_columns(self, item_dict: dict=None):
def load_columns(self, item_dict: dict = None):
presets = self.config.table_presets
if item_dict is None:
item_dict = presets[self.config.table_presets_current]
item_dict.update({key: False for key in presets[HeaderEditWidget.default] if key not in item_dict})
item_dict.update({key: (False, presets[HeaderEditWidget.default][key][1])
for key in presets[HeaderEditWidget.default] if key not in item_dict})
self.set_column_order(list(item_dict.keys()))
for name, show in item_dict.items(): # for index, name in enumerate(self.columns):
self.setColumnHidden(self.columns.index(name), not show) # self.setColumnHidden(index, not item_dict.get(name, False))
self.set_column_order(item_dict.keys())
# self.set_column_widths({key: val[1] for key, val in item_dict.items()})
for name, value in item_dict.items(): # for index, name in enumerate(self.columns):
index = self.columns.index(name)
show, width = value
self.setColumnHidden(index, not show) # self.setColumnHidden(index, not item_dict.get(name, False))
self.setColumnWidth(index, width)
def _get_column_item(self, column):
index = self.columns.index(column)
presets = self.config.table_presets
show = not self.isColumnHidden(index)
# columnWidth is 0 when hidden, trying to get previous width from config or default
width = self.columnWidth(index) or \
presets[self.config.table_presets_current].get(column, 0)[1] or \
presets[HeaderEditWidget.default][column][1]
return show, width
@property
def item_dict(self):
return {column: not self.isColumnHidden(self.columns.index(column)) for column in self.current_columns}
return {column: self._get_column_item(column) for column in self.current_columns}
def save_columns(self):
current = self.config.table_presets_current
@@ -180,8 +197,7 @@ class CopterTableWidget(QTableView):
@pyqtSlot(QtCore.QModelIndex)
def on_double_click(self, index):
col = index.column()
if col == 7:
if self.model.is_column(index, "selfcheck"):
data = self.proxy_model.data(index, role=table.ModelDataRole)
if data and data != "OK":
self._show_info("Selfcheck info", data)
@@ -254,7 +270,8 @@ class CopterTableWidget(QTableView):
class HeaderListWidget(QListWidget):
ColumnKeyRole = 998
ColumnKeyRole = Qt.UserRole + 1000
ColumnWidthRole = Qt.UserRole + 1001
dropped = QtCore.pyqtSignal(bool)
@@ -268,18 +285,21 @@ class HeaderListWidget(QListWidget):
def populate_items(self, item_dict: dict):
self.clear()
for name, visible in item_dict.items():
for name, value in item_dict.items():
visible, width = value
flags = Qt.ItemIsUserCheckable | Qt.ItemIsSelectable | Qt.ItemIsDragEnabled | Qt.ItemIsEnabled
state = Qt.Checked if visible else Qt.Unchecked
item = QListWidgetItem(table.CopterDataModel.columns_dict.get(name, "").strip() or name, self)
item.setFlags(flags)
item.setCheckState(state)
item.setData(HeaderListWidget.ColumnKeyRole, name)
item.setData(self.ColumnKeyRole, name)
item.setData(self.ColumnWidthRole, width)
@property
def item_dict(self):
return {self.item(i).data(HeaderListWidget.ColumnKeyRole): bool(self.item(i).checkState())
return {self.item(i).data(self.ColumnKeyRole):
(bool(self.item(i).checkState()), self.item(i).data(self.ColumnWidthRole))
for i in range(self.count())}
def dropEvent(self, event: QtGui.QDropEvent):
@@ -307,8 +327,7 @@ class ActiveHeaderListWidget(HeaderListWidget):
key = item.data(HeaderListWidget.ColumnKeyRole)
if key is None:
return
self.source_widget.setColumnHidden(self.columns.index(key),
not bool(item.checkState()))
self.source_widget.setColumnHidden(self.columns.index(key), not bool(item.checkState()))
def dropEvent(self, event: QtGui.QDropEvent):
super().dropEvent(event)
@@ -332,7 +351,7 @@ class HeaderEditWidget(QtWidgets.QWidget):
self.preset_widget = QtWidgets.QComboBox()
self.header_widget = ActiveHeaderListWidget(self.source) \
if self.menu_mode else HeaderListWidget()
#self.header_widget.itemChanged.connect(partial(self.saved_signal.emit, False))
# self.header_widget.itemChanged.connect(partial(self.saved_signal.emit, False))
self.header_widget.model().dataChanged.connect(partial(self.saved_signal.emit, False))
self.header_widget.dropped.connect(partial(self.saved_signal.emit, False))
@@ -404,13 +423,17 @@ class HeaderEditWidget(QtWidgets.QWidget):
self.previous = index
presets = self.config.table_presets
items = {key: value for key, value in presets[index].items()}
items.update({key: False for key in presets[self.default] if key not in items})
item_dict = {key: value for key, value in presets[index].items()}
item_dict.update({key: (False, presets[self.default][key][1])
for key in presets[self.default] if key not in item_dict})
if self.menu_mode:
self.source.set_column_order(list(items.keys()))
self.source.set_column_order(list(item_dict.keys())) # hidden\shown is hold by header widget's itemChanged
for name, value in item_dict.items():
self.source.setColumnWidth(self.source.columns.index(name), value[1])
self.config.table_presets_current = index
self.header_widget.populate_items(items)
self.header_widget.populate_items(item_dict)
self.saved_signal.emit(True)
def add_preset(self):
@@ -438,7 +461,7 @@ class HeaderEditWidget(QtWidgets.QWidget):
return
reply = QMessageBox.question(None, "Action can't be undone", "Remove anyway?",
QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
if reply != QMessageBox.Yes:
return
@@ -486,7 +509,7 @@ class HeaderEditDialog(QtWidgets.QDialog):
unsaved = not saved
self.unsaved = unsaved
self.setWindowTitle(f"Column preset editor - {self.widget.preset_widget.currentText()}"
+ "*"*unsaved)
+ "*" * unsaved)
def closeEvent(self, event):
if not self.unsaved:
@@ -506,8 +529,11 @@ class HeaderEditDialog(QtWidgets.QDialog):
if __name__ == '__main__':
import sys
def except_hook(cls, exception, traceback):
sys.__excepthook__(cls, exception, traceback)
sys.excepthook = except_hook # for debugging (exceptions traceback)
app = QtWidgets.QApplication(sys.argv)
@@ -518,12 +544,14 @@ if __name__ == '__main__':
# model.add_client(copter_table_models.StatedCopterData())
import config
c = config.ConfigManager()
c.load_config_and_spec("config\server.ini")
#print(c.config)
#print(c._name_dict)
# print(c.config)
# print(c._name_dict)
w1 = CopterTableWidget(model, c)
w = HeaderEditWidget(w1, c)
print(w1.item_dict)
# print(*w1.current_columns, sep='\n')
w.show()
# w.show()
app.exec()

View File

@@ -354,8 +354,6 @@ class CopterDataModel(QtCore.QAbstractTableModel):
def __init__(self, checks=ModelChecks, formatter=ModelFormatter, data_model=StatedCopterData, parent=None):
super(CopterDataModel, self).__init__(parent)
# self.headers = (' copter ID ', ' version ', ' animation ID ', ' battery ', ' fcu_status ', ' sensors ',
# ' mode ', ' checks ', ' current x y z yaw frame_id ', ' start x y z ', ' task ', 'dt')
self.headers = list(self.columns_dict.values())
self.data_contents = []

View File

@@ -3,7 +3,7 @@ import copy
import collections
from configobj import ConfigObj, Section, flatten_errors
from validate import Validator
from validate import Validator, is_tuple, is_boolean, is_integer
def modify_filename(path, pattern): # TODO move to core
@@ -23,6 +23,11 @@ def parent_dir(path):
return os.path.basename(os.path.normpath(path))
def is_preset_param(value):
parsed = is_tuple(value, min=2, max=2)
return is_boolean(parsed[0]), is_integer(parsed[1], min=0)
class ValidationError(ValueError):
def __init__(self, message, config, errors):
super(ValidationError, self).__init__(message)
@@ -84,7 +89,7 @@ class ConfigManager:
def validate_config(self, config=None, copy_defaults=False):
config = self.config if config is None else config
vdt = Validator()
vdt = Validator({"preset_param": is_preset_param})
test = config.validate(vdt, copy=copy_defaults, preserve_errors=True)
if test != True: # Important syntax, do no change
@@ -306,9 +311,13 @@ class ConfigManager:
if __name__ == '__main__':
cfg = ConfigManager()
cfg.load_from_file('Server/config/server.ini')
cfg.load_from_file('Drone/config/client.ini')
# cfg.load_from_file('Server/config/server.ini')
#cfg.load_from_file('Drone/config/spec/configspec_client.ini')
print(dict(cfg.full_dict(include_defaults=True)))
cfg.config.pop("PRIVATE", None)
print(cfg.config)
# cfg.load_config_and_spec('Drone/config/client.ini')
# #print(cfg.config.comments)

View File

@@ -1,8 +1,13 @@
import config
from Server.copter_table_models import CopterDataModel
cfg_server = config.ConfigObj('SERVER/config/spec/configspec_server.ini')
default = {key: 'boolean(default=True)' for key in CopterDataModel.columns}
cfg_server = config.ConfigObj('SERVER/config/spec/configspec_server.ini', list_values=False)
widths = {"copter_id": 150}
default_width = 100
default = {key: f"preset_param(default=list(True, {widths.get(key, default_width)}))"
for key in CopterDataModel.columns}
cfg_server['TABLE']['PRESETS']['DEFAULT'] = default
cfg_server.write()