Skip to content

Commit

Permalink
Store_Data_in_textfile (#1867)
Browse files Browse the repository at this point in the history
* Store_Data_in_textfile

* test_gsoc_updated

* restoration_feature_added

* Store_data_in_DB

* fixed_few_bugs

* Routed through mscolab server

* removed_comments

* fixed_flake8_removed_unnecessary_code
  • Loading branch information
sratslla authored Sep 28, 2023
1 parent ee2962f commit 706bcd2
Show file tree
Hide file tree
Showing 7 changed files with 302 additions and 89 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/testing_gsoc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ jobs:
&& mamba list
- name: Run tests
if: ${{ success() && inputs.xdist == 'no' }}
if: ${{ success() }}
timeout-minutes: 25
run: |
cd $GITHUB_WORKSPACE \
Expand All @@ -78,7 +78,7 @@ jobs:
- name: Run tests in parallel
if: ${{ success() && inputs.xdist == 'yes' }}
if: ${{ success() }}
timeout-minutes: 25
run: |
cd $GITHUB_WORKSPACE \
Expand All @@ -92,7 +92,7 @@ jobs:
; done)
- name: Collect coverage
if: ${{ success() && inputs.event_name == 'push' && inputs.branch_name == 'develop' && inputs.xdist == 'no'}}
if: ${{ success() }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
Expand Down
13 changes: 12 additions & 1 deletion mslib/mscolab/file_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
import logging
import git
from sqlalchemy.exc import IntegrityError
from mslib.mscolab.models import db, Operation, Permission, User, Change, Message
from mslib.mscolab.models import db, Operation, OperationLayout, Permission, User, Change, Message
from mslib.mscolab.conf import mscolab_settings


Expand Down Expand Up @@ -108,6 +108,17 @@ def list_operations(self, user):
})
return operations

def store_operation_layout_data(self, operation_name, json_data):
db.create_all()
OperationLayout.add_or_update(operation_name, json_data)
return True

def load_operation_layout_data(self, operation_name):
operation_layout = OperationLayout.query.filter_by(operation_id=operation_name).first()
if operation_layout:
return operation_layout.json_data
return "None"

def is_member(self, u_id, op_id):
"""
op_id: operation id
Expand Down
22 changes: 22 additions & 0 deletions mslib/mscolab/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,28 @@ def verify_auth_token(token):
return user


class OperationLayout(db.Model):

__tablename__ = 'Operation_layout'
id = db.Column(db.Integer, primary_key=True)
operation_id = db.Column(db.String, unique=True)
json_data = db.Column(db.JSON)

def __init__(self, operation_id, json_data):
self.operation_id = operation_id
self.json_data = json_data

@classmethod
def add_or_update(cls, operation_id, json_data):
existing_record = OperationLayout.query.filter_by(operation_id=operation_id).first()
if existing_record:
existing_record.json_data = json_data
else:
new_record = OperationLayout(operation_id=operation_id, json_data=json_data)
db.session.add(new_record)
db.session.commit()


class Permission(db.Model):

__tablename__ = 'permissions'
Expand Down
18 changes: 18 additions & 0 deletions mslib/mscolab/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,24 @@ def get_operation_by_id():
return json.dumps({"content": result})


@APP.route('/store_operation_layout', methods=["POST"])
def store_operation_layout():
operation_name = request.form['operation_name']
layout_data = request.form['layout_data']

fm.store_operation_layout_data(operation_name, layout_data)
return jsonify({"success": True}), 200


@APP.route('/load_operation_layout', methods=["GET"])
def load_operation_layout():
operation_name = request.args.get('operation_name')
layout_data = fm.load_operation_layout_data(operation_name)
if layout_data:
return layout_data
return layout_data


@APP.route('/get_all_changes', methods=['GET'])
@verify_user
def get_all_changes():
Expand Down
145 changes: 143 additions & 2 deletions mslib/msui/msui_mainwindow.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,11 @@
import logging
import os
import re
import requests
import sys
import fs
import json
import asyncio

from mslib import __version__
from mslib.msui.qt5 import ui_mainwindow as ui
Expand Down Expand Up @@ -468,6 +471,142 @@ def __init__(self, mscolab_data_dir=None, *args):
self.actionUpdater.triggered.connect(self.updater.show)
self.openOperationsGb.hide()

self.last_changed_item = None
self.StoreLayout.clicked.connect(self.store_operation_data)
self.RestoreLayout.clicked.connect(self.restore_operation_data)
self.allowed_widget_names = ["TopViewWindow", "SideViewWindow", "TableViewWindow", "LinearWindow"]
self.listOperationsMSC.itemActivated.connect(self.operation_changed)

def operation_changed(self):
selected_items = self.listOperationsMSC.selectedItems()

if not selected_items:
return

selected_item = selected_items[0]
operation_name = selected_item.text()
loaded_data = requests.get(f"{self.mscolab.mscolab_server_url}/load_operation_layout",
params={"operation_name": operation_name})
if loaded_data.text == "None":
return

if loaded_data is not None:
result = QtWidgets.QMessageBox.question(
self, "Saved Layout Detected", "Would you like to restore it?",
QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No, QtWidgets.QMessageBox.Yes)

if result == QtWidgets.QMessageBox.Yes:
self.restore_operation_data()

def store_operation_data(self):
operation_name = self.listOperationsMSC.currentItem()
if self.listOperationsMSC.currentItem() is None:
message_box = QtWidgets.QMessageBox()
message_box.setWindowTitle("Select Operation")
message_box.setText("Select a operation to save layout")
message_box.setStandardButtons(QtWidgets.QMessageBox.Ok)
message_box.exec_()
return
self.widget_info = {}
top_level_widgets = QtWidgets.QApplication.topLevelWidgets()
for widget in top_level_widgets:
if widget.objectName() in self.allowed_widget_names:
positions = []
if isinstance(widget, QtWidgets.QMainWindow):
geometry = widget.geometry().getRect()
screen_index = QtWidgets.QApplication.desktop().screenNumber(widget)
is_minimized = widget.isMinimized()
positions.append(geometry)
positions.append(screen_index)
positions.append(is_minimized)
child_info = {}
for child in widget.findChildren(QtWidgets.QWidget):
if isinstance(child, QtWidgets.QComboBox):
child_info[child.objectName()] = {"items": [child.itemText(i) for i in range(child.count())],
"current_index": child.currentIndex()}
elif isinstance(child, QtWidgets.QCheckBox):
child_info[child.objectName()] = {"checked": child.isChecked()}

itemlist = [widget.objectName(), child_info, positions]
self.widget_info[widget.windowTitle()] = itemlist

json_data = json.dumps(self.widget_info, indent=4)

data = {"operation_name": operation_name.text(), "layout_data": json_data}

response = requests.post(f"{self.mscolab.mscolab_server_url}/store_operation_layout",
data=data, timeout=(2, 10))

if response.status_code == 200:
message_box = QtWidgets.QMessageBox()
message_box.setWindowTitle("Select Operation")
message_box.setText("Dictionary has been successfully stored in the mscolab server")
message_box.setStandardButtons(QtWidgets.QMessageBox.Ok)
message_box.exec_()

async def delayed_process(self, widget_name, saved_data, loaded_data):
await asyncio.sleep(1)

for widget_name, saved_data in loaded_data.items():
if saved_data[0] in self.allowed_widget_names and len(saved_data) == 3:
positions = saved_data[2]
top_level_widgets = QtWidgets.QApplication.topLevelWidgets()

for widget in top_level_widgets:
if widget.windowTitle() == widget_name:
current_position = widget.geometry().getRect()
if current_position != positions[0]:
widget.setGeometry(*positions[0])

def restore_operation_data(self):
if self.listOperationsMSC.currentItem() is None:
message_box = QtWidgets.QMessageBox()
message_box.setWindowTitle("Select Operation")
message_box.setText("Select an operation to restore layout")
message_box.setStandardButtons(QtWidgets.QMessageBox.Ok)
message_box.exec_()
return

operation_name = self.listOperationsMSC.currentItem().text()
loaded_data = requests.get(f"{self.mscolab.mscolab_server_url}/load_operation_layout",
params={"operation_name": operation_name})
if loaded_data.text == "None":
message_box = QtWidgets.QMessageBox()
message_box.setWindowTitle("Layout not found")
message_box.setText("No Stored Layout Found")
message_box.setStandardButtons(QtWidgets.QMessageBox.Ok)
message_box.exec_()
return
layout_data = json.loads(loaded_data.text)

top_level_widgets = QtWidgets.QApplication.topLevelWidgets()

for widget_name, saved_data in layout_data.items():
if saved_data[0] in self.allowed_widget_names:
if saved_data[0] not in [w.objectName() for w in top_level_widgets]:
if saved_data[0] == "TopViewWindow":
new_widget = self.create_view_handler("topview")
new_widget.setWindowTitle(widget_name)
elif saved_data[0] == "SideViewWindow":
new_widget = self.create_view_handler("sideview")
new_widget.setWindowTitle(widget_name)
elif saved_data[0] == "TableViewWindow":
new_widget = self.create_view_handler("tableview")
new_widget.setWindowTitle(widget_name)
elif saved_data[0] == "LinearWindow":
new_widget = self.create_view_handler("linearview")
new_widget.setWindowTitle(widget_name)

asyncio.run(self.delayed_process(widget_name, saved_data, layout_data))

# Currently if a extra widget is open we dont close it.
# In future if we want to close it we can use below code.
# for widget in top_level_widgets:
# widget_name = widget.objectName()
# if widget_name in self.allowed_widget_names:
# if widget_name not in loaded_data:
# print(f"Extra widget found: '{widget_name}'")

def bring_main_window_to_front(self):
self.show()
self.raise_()
Expand Down Expand Up @@ -822,10 +961,11 @@ def close_selected_flight_track(self):

def create_view_handler(self, _type):
if self.local_active:
self.create_view(_type, self.active_flight_track)
temp = self.create_view(_type, self.active_flight_track)
else:
self.mscolab.waypoints_model.name = self.mscolab.active_operation_name
self.create_view(_type, self.mscolab.waypoints_model)
temp = self.create_view(_type, self.mscolab.waypoints_model)
return temp

def create_view(self, _type, model):
"""Method called when the user selects a new view to be opened. Creates
Expand Down Expand Up @@ -881,6 +1021,7 @@ def create_view(self, _type, model):
except AttributeError:
view_window.enable_navbar_action_buttons()
self.viewsChanged.emit()
return view_window

def get_active_views(self):
active_view_windows = []
Expand Down
Loading

0 comments on commit 706bcd2

Please sign in to comment.