From ac1702c648a12825614f8a6e9677c1b9f0bd3c2b Mon Sep 17 00:00:00 2001 From: Artem30801 Date: Thu, 23 Jan 2020 23:14:37 +0300 Subject: [PATCH] Added new config column + drag support --- Drone/copter_client.py | 9 +++- Server/config/spec/configspec_server.ini | 1 + Server/config_editor_models.py | 2 +- Server/copter_table.py | 4 +- Server/copter_table_models.py | 52 ++++++++++++++++++++---- Server/server_qt.py | 3 +- 6 files changed, 60 insertions(+), 11 deletions(-) diff --git a/Drone/copter_client.py b/Drone/copter_client.py index 85c6fe2..597e6c1 100644 --- a/Drone/copter_client.py +++ b/Drone/copter_client.py @@ -645,6 +645,7 @@ def _play_animation(*args, **kwargs): ) +# noinspection PyAttributeOutsideInit class Telemetry: params_default_dict = { "git_version": None, @@ -652,13 +653,14 @@ class Telemetry: "battery": None, "armed": False, "fcu_status": None, - "cal_status": None, + "calibration_status": None, "mode": None, "selfcheck": None, "current_position": None, "start_position": None, "task": None, "time": None, + "config_version": None, } def __init__(self): @@ -690,6 +692,10 @@ class Telemetry: def get_git_version(cls): return subprocess.check_output("git log --pretty=format:'%h' -n 1", shell=True) + @classmethod + def get_config_version(cls): + return "{} V{}".format(client.active_client.config.config_name, client.active_client.config.config_version) + @classmethod def get_start_position(cls): x_start, y_start = animation.get_start_xy(os.path.abspath("animation.csv"), @@ -764,6 +770,7 @@ class Telemetry: def update_telemetry_slow(self): self.animation_id = animation.get_id() self.git_version = self.get_git_version() + self.config_version = self.get_config_varsion() try: self.cal_status = get_calibration_status() self.fcu_status = get_sys_status() diff --git a/Server/config/spec/configspec_server.ini b/Server/config/spec/configspec_server.ini index 905a6be..b0efd85 100644 --- a/Server/config/spec/configspec_server.ini +++ b/Server/config/spec/configspec_server.ini @@ -24,6 +24,7 @@ remove_disconnected = boolean(default=False) start_position = boolean(default=True) last_task = boolean(default=True) time_delta = boolean(default=True) + config_version = boolean(default=True) [[[__many__]]] __many__ = boolean diff --git a/Server/config_editor_models.py b/Server/config_editor_models.py index cf5dec2..898db7b 100644 --- a/Server/config_editor_models.py +++ b/Server/config_editor_models.py @@ -372,7 +372,7 @@ class ConfigModel(QtCore.QAbstractItemModel): return QtCore.Qt.CopyAction | QtCore.Qt.MoveAction def mimeTypes(self): - return ['app/configitem', 'text/xml'] + return ['app/configitem'] def mimeData(self, indexes): mimedata = QtCore.QMimeData() diff --git a/Server/copter_table.py b/Server/copter_table.py index b9b3a15..725c12b 100644 --- a/Server/copter_table.py +++ b/Server/copter_table.py @@ -49,8 +49,10 @@ class CopterTableWidget(QTableView): self.setSortingEnabled(True) self.setSizeAdjustPolicy(QtWidgets.QAbstractScrollArea.AdjustToContents) self.resizeColumnsToContents() - self.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows) + self.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectItems) + self.setSelectionMode(QtWidgets.QAbstractItemView.SingleSelection) self.doubleClicked.connect(self.on_double_click) + self.setDragEnabled(True) def moved(self, logical_index, old_index, new_index): name = self.current_columns.pop(old_index) diff --git a/Server/copter_table_models.py b/Server/copter_table_models.py index b992aaf..d414760 100644 --- a/Server/copter_table_models.py +++ b/Server/copter_table_models.py @@ -1,12 +1,14 @@ import re import sys +import os import time import math import indexed +from contextlib import suppress from PyQt5 import QtCore, QtGui, QtWidgets -from PyQt5.QtCore import Qt as Qt - +from PyQt5.QtCore import Qt as Qt, QUrl, QDir +from PyQt5.QtWidgets import QApplication ModelDataRole = 998 ModelStateRole = 999 @@ -116,15 +118,18 @@ columns_names = {'copter_id': 'copter ID', 'current_position': 'current x y z yaw frame_id', 'start_position': ' start x y z ', 'last_task': 'last task', - 'time_delta': 'dt' + 'time_delta': 'dt', + 'config_version': 'configuration', } +columns = list(columns_names.keys()) class CopterData: class_basic_attrs = indexed.IndexedOrderedDict([('copter_id', None), ('git_ver', None), ('animation_id', None), - ('battery', None), ('fcu_status', None), ('cal_status', None), + ('battery', None), ('fcu_status', None), ('calibration_status', None), ('mode', None), ('selfcheck', None), ('current_position', None), - ('start_position', None), ('last_task', None), ('time_delta', None), ('client', None)]) + ('start_position', None), ('last_task', None), ('time_delta', None), + ("config_version", None), ('client', None)]) def __init__(self, **kwargs): self.attrs_dict = self.class_basic_attrs.copy() @@ -299,7 +304,11 @@ def place_time_delta(value): @ModelFormatter.col_format(11, ModelFormatter.VIEW_FORMATTER) def view_time_delta(value): - return "{:.3f}".format(value) + return "{:.3f}".format(value) + + +def is_column(index, column_name): + return index.column() == columns.index(column_name) class CopterDataModel(QtCore.QAbstractTableModel): @@ -470,7 +479,7 @@ class CopterDataModel(QtCore.QAbstractTableModel): self.update_model(index, role) return True - def select_all(self): # probably NOT thread-safe! + def select_all(self): # probably NOT thread-safe! TODO remake self.first_col_is_checked = not self.first_col_is_checked for row_num, copter in enumerate(self.data_contents): copter.states.checked = int(self.first_col_is_checked)*2 @@ -480,8 +489,37 @@ class CopterDataModel(QtCore.QAbstractTableModel): roles = Qt.ItemIsSelectable | Qt.ItemIsEnabled if index.column() == 0: roles |= Qt.ItemIsUserCheckable | Qt.ItemIsEditable + if is_column(index, "config_version"): + roles |= Qt.ItemIsDragEnabled # | Qt.ItemIsDropEnabled + return roles + def supportedDropActions(self): + return QtCore.Qt.CopyAction + + def mimeTypes(self): + return ['text/plain'] + + def mimeData(self, indexes): + index = indexes[0] + if is_column(index, "config_version"): + return self._config_mime(index) + + return None + + def _config_mime(self, index): + mimedata = QtCore.QMimeData() + path = os.path.join(QDir.tempPath(), "config_{}.ini".format( + self.data_contents[index.row()].copter_id)) + + with suppress(OSError): # remove if file exists + os.remove(path) + + self.data_contents[index.row()].client.get_file("config/client.ini", path,) + mimedata.setUrls([QUrl.fromLocalFile(path)]) + + return mimedata + @QtCore.pyqtSlot(int, int, QtCore.QVariant, QtCore.QVariant) def update_item(self, row, col, value, role=Qt.EditRole): self.setData(self.index(row, col), value, role) diff --git a/Server/server_qt.py b/Server/server_qt.py index 242cd71..8a39c84 100644 --- a/Server/server_qt.py +++ b/Server/server_qt.py @@ -238,13 +238,14 @@ class MainWindow(QtWidgets.QMainWindow): "animation_id": 2, "battery": 3, "fcu_status": 4, - "cal_status": 5, + "calibration_status": 5, "mode": 6, "selfcheck": 7, "current_position": 8, "start_position": 9, "task": 10, "time": 11, + "config_version": 12, } for key, value in telems.items():