Added support for closing projects. Fixed some bugs with editing existing links.
This commit is contained in:
@@ -115,7 +115,7 @@ class EntitiesDB:
|
||||
self.mainWindow.updateEntityNodeLabelsOnCanvases(entity['uid'], entity[list(entity)[1]])
|
||||
self.dbLock.release()
|
||||
if not fromServer:
|
||||
self.mainWindow.sendLocalDatabaseUpdateToServer(entity, True)
|
||||
self.mainWindow.sendLocalDatabaseUpdateToServer(entity, 1)
|
||||
self.mainWindow.populateEntitiesWidget(returnValue, add=True)
|
||||
|
||||
if updateTimeline:
|
||||
@@ -149,7 +149,7 @@ class EntitiesDB:
|
||||
# Update canvases if the node already exists.
|
||||
self.mainWindow.updateEntityNodeLabelsOnCanvases(entity['uid'], entity[list(entity)[1]])
|
||||
if not fromServer:
|
||||
self.mainWindow.sendLocalDatabaseUpdateToServer(entity, True)
|
||||
self.mainWindow.sendLocalDatabaseUpdateToServer(entity, 1)
|
||||
self.mainWindow.populateEntitiesWidget(entity, add=True)
|
||||
|
||||
self.dbLock.release()
|
||||
@@ -157,10 +157,11 @@ class EntitiesDB:
|
||||
|
||||
return returnValue
|
||||
|
||||
def addLink(self, linkJson: dict, fromServer=False):
|
||||
def addLink(self, linkJson: dict, fromServer: bool = False, overwrite: bool = False):
|
||||
"""
|
||||
Add a link between two entities in the database.
|
||||
|
||||
:param overwrite:
|
||||
:param linkJson:
|
||||
:param fromServer:
|
||||
:return:
|
||||
@@ -180,8 +181,14 @@ class EntitiesDB:
|
||||
newRes = link.get('Resolution')
|
||||
newNotes = link.get('Notes')
|
||||
if newRes and newRes != exists['Resolution']:
|
||||
link['Resolution'] = exists['Resolution'] + ' | ' + newRes
|
||||
if newNotes and newNotes != exists['Notes']:
|
||||
if overwrite:
|
||||
link['Resolution'] = newRes
|
||||
else:
|
||||
link['Resolution'] = exists['Resolution'] + ' | ' + newRes
|
||||
if newNotes and newNotes != exists['Notes'] and newNotes != 'None':
|
||||
if overwrite:
|
||||
link['Notes'] = str(newNotes)
|
||||
else:
|
||||
link['Notes'] = exists['Notes'] + '\n\n' + str(newNotes)
|
||||
exists.update(link)
|
||||
link.update(exists)
|
||||
@@ -194,7 +201,10 @@ class EntitiesDB:
|
||||
|
||||
self.dbLock.release()
|
||||
if not fromServer:
|
||||
self.mainWindow.sendLocalDatabaseUpdateToServer(link, True)
|
||||
if overwrite:
|
||||
self.mainWindow.sendLocalDatabaseUpdateToServer(link, 3)
|
||||
else:
|
||||
self.mainWindow.sendLocalDatabaseUpdateToServer(link, 1)
|
||||
return link
|
||||
|
||||
def getEntity(self, uid: str):
|
||||
@@ -291,7 +301,7 @@ class EntitiesDB:
|
||||
if ent is not None:
|
||||
self.mainWindow.handleGroupNodeUpdateAfterEntityDeletion(uid) # Blocking - locks the db.
|
||||
if not fromServer:
|
||||
self.mainWindow.sendLocalDatabaseUpdateToServer(ent, False)
|
||||
self.mainWindow.sendLocalDatabaseUpdateToServer(ent, 2)
|
||||
if updateTimeLine:
|
||||
self.updateTimeline(ent, False)
|
||||
|
||||
@@ -305,7 +315,7 @@ class EntitiesDB:
|
||||
self.database.remove_edge(uid[0], uid[1])
|
||||
self.dbLock.release()
|
||||
if not fromServer:
|
||||
self.mainWindow.sendLocalDatabaseUpdateToServer({"uid": uid}, False)
|
||||
self.mainWindow.sendLocalDatabaseUpdateToServer({"uid": uid}, 2)
|
||||
|
||||
def doesEntityExist(self, primaryAttr: str):
|
||||
"""
|
||||
|
||||
@@ -55,7 +55,7 @@ class CommunicationsHandler(QtCore.QObject):
|
||||
close_project_signal = QtCore.Signal()
|
||||
open_project_canvas_signal = QtCore.Signal(str)
|
||||
close_project_canvas_signal = QtCore.Signal(str)
|
||||
receive_project_database_update = QtCore.Signal(dict, bool)
|
||||
receive_project_database_update = QtCore.Signal(dict, int)
|
||||
receive_project_canvas_update_node = QtCore.Signal(str, str)
|
||||
receive_project_canvas_update_link = QtCore.Signal(str, tuple)
|
||||
receive_sync_database = QtCore.Signal(dict, dict)
|
||||
@@ -88,7 +88,7 @@ class CommunicationsHandler(QtCore.QObject):
|
||||
self.receive_project_canvases_list_signal.connect(self.mainWindow.receiveProjectCanvasesListListener)
|
||||
self.open_project_signal.connect(self.mainWindow.openServerProjectListener)
|
||||
self.open_project_canvas_signal.connect(self.mainWindow.openServerCanvasListener)
|
||||
self.close_project_signal.connect(self.mainWindow.closeCurrentServerProject)
|
||||
self.close_project_signal.connect(self.mainWindow.closeServerProjectListener)
|
||||
self.close_project_canvas_signal.connect(self.mainWindow.closeServerCanvasListener)
|
||||
self.receive_project_database_update.connect(self.mainWindow.receiveServerDatabaseUpdate)
|
||||
self.receive_project_canvas_update_node.connect(self.mainWindow.receiveServerCanvasUpdate)
|
||||
@@ -150,17 +150,19 @@ class CommunicationsHandler(QtCore.QObject):
|
||||
|
||||
self.mainWindow.MESSAGEHANDLER.warning("Server did not reply in the expected manner to "
|
||||
"password authentication.", popUp=True)
|
||||
except ConnectionRefusedError:
|
||||
self.mainWindow.MESSAGEHANDLER.error("Did not connect: Server not running.", popUp=True, exc_info=False)
|
||||
except Exception as exception:
|
||||
self.mainWindow.MESSAGEHANDLER.error("Did not connect: " + str(exception))
|
||||
|
||||
try:
|
||||
if self.sock is not None:
|
||||
self.sock.shutdown(socket.SHUT_RDWR)
|
||||
self.sock.close()
|
||||
self.sock = None
|
||||
except OSError:
|
||||
# This would typically occur if the socket is already closed.
|
||||
self.mainWindow.MESSAGEHANDLER.info('Tried to close socket that was already closed.')
|
||||
# This would typically occur if the socket is already shut down.
|
||||
self.mainWindow.MESSAGEHANDLER.debug('Tried to shutdown socket that was already shut down.')
|
||||
self.sock.close()
|
||||
self.sock = None
|
||||
|
||||
return False
|
||||
|
||||
@@ -447,14 +449,14 @@ class CommunicationsHandler(QtCore.QObject):
|
||||
# to a particular canvas.
|
||||
# Being verbose is better than prematurely optimizing for a few kbps of
|
||||
# network traffic.
|
||||
def receiveDatabaseUpdateEvent(self, entity_json: dict, add: bool):
|
||||
def receiveDatabaseUpdateEvent(self, entity_json: dict, add: int):
|
||||
try:
|
||||
entity_json['Icon'] = QtCore.QByteArray(b64decode(entity_json['Icon']))
|
||||
except KeyError:
|
||||
pass
|
||||
self.receive_project_database_update.emit(entity_json, add)
|
||||
|
||||
def sendDatabaseUpdateEvent(self, project_name: str, entity_json: dict, add: bool):
|
||||
def sendDatabaseUpdateEvent(self, project_name: str, entity_json: dict, add: int):
|
||||
try:
|
||||
entity_json['Icon'] = entity_json['Icon'].toBase64().data()
|
||||
except KeyError:
|
||||
|
||||
@@ -481,14 +481,16 @@ class TabbedPane(QtWidgets.QTabWidget):
|
||||
scene.rearrangeGraph()
|
||||
# self.mainWindow.syncCanvasByName(canvas)
|
||||
|
||||
def serverLinkAddHelper(self, linkJson: dict) -> None:
|
||||
def serverLinkAddHelper(self, linkJson: dict, overwrite: bool = False) -> None:
|
||||
"""
|
||||
Assumes that the 'uid' field is a tuple.
|
||||
|
||||
:param overwrite:
|
||||
:param linkJson:
|
||||
:return:
|
||||
"""
|
||||
linkUID = linkJson['uid']
|
||||
lJson = self.entityDB.addLink(linkJson, fromServer=True)
|
||||
lJson = self.entityDB.addLink(linkJson, fromServer=True, overwrite=overwrite)
|
||||
for canvas in self.canvasTabs:
|
||||
if self.canvasTabs[canvas].scene().sceneGraph.nodes.get(linkUID[0]) is not None:
|
||||
if self.canvasTabs[canvas].scene().sceneGraph.nodes.get(linkUID[1]) is None:
|
||||
@@ -1543,7 +1545,7 @@ class CanvasScene(QtWidgets.QGraphicsScene):
|
||||
pEditor = PropertiesEditor(self, linkJSON)
|
||||
if pEditor.exec_():
|
||||
# Adding link with the same UID just overwrites properties.
|
||||
self.parent().entityDB.addLink(pEditor.objectJson)
|
||||
self.parent().entityDB.addLink(pEditor.objectJson, overwrite=True)
|
||||
self.parent().messageHandler.info('Edited link: ' + str(pEditor.objectJson['uid']) + ' | ' +
|
||||
pEditor.objectJson['Resolution'])
|
||||
|
||||
|
||||
@@ -227,6 +227,11 @@ class MenuBar(QtWidgets.QMenuBar):
|
||||
triggered=self.serverOpenOrCreateProject)
|
||||
serverMenu.addAction(createOrOpenProjectAction)
|
||||
|
||||
closeCurrentProjectAction = QtGui.QAction("Close Current Project", self,
|
||||
statusTip="Close the Server project that is currently open.",
|
||||
triggered=self.serverCloseProject)
|
||||
serverMenu.addAction(closeCurrentProjectAction)
|
||||
|
||||
deleteProjectAction = QtGui.QAction("Delete Current Project", self,
|
||||
statusTip="Delete the Server project that is currently opened.",
|
||||
triggered=self.serverDeleteProject)
|
||||
@@ -686,6 +691,9 @@ class MenuBar(QtWidgets.QMenuBar):
|
||||
self.parent().MESSAGEHANDLER.warning('Not Connected to Server!', popUp=True)
|
||||
self.parent().setStatus('Must connect to a server before opening a project.')
|
||||
|
||||
def serverCloseProject(self) -> None:
|
||||
self.parent().closeCurrentServerProject()
|
||||
|
||||
def serverDeleteProject(self) -> None:
|
||||
if self.parent().FCOM.isConnected():
|
||||
current_project = self.parent().SETTINGS.value("Project/Server/Project")
|
||||
|
||||
46
LinkScope.py
46
LinkScope.py
@@ -1108,6 +1108,8 @@ class MainWindow(QtWidgets.QMainWindow):
|
||||
self.RESOLUTIONMANAGER.removeServerResolutions()
|
||||
self.dockbarOne.resolutionsPalette.loadAllResolutions()
|
||||
self.closeServerProjectListener()
|
||||
with self.serverProjectsLock:
|
||||
self.serverProjects = []
|
||||
self.setStatus("Disconnected from server.")
|
||||
self.dockbarThree.serverStatus.updateStatus("Not connected to a server")
|
||||
|
||||
@@ -1139,6 +1141,7 @@ class MainWindow(QtWidgets.QMainWindow):
|
||||
with self.serverProjectsLock:
|
||||
try:
|
||||
self.serverProjects.remove(deleted_project)
|
||||
self.closeServerProjectListener()
|
||||
except ValueError:
|
||||
# If the client doesn't know about the deleted project, nothing to do.
|
||||
pass
|
||||
@@ -1154,23 +1157,29 @@ class MainWindow(QtWidgets.QMainWindow):
|
||||
self.MESSAGEHANDLER.info("Opened Server Project: " + project_name, popUp=True)
|
||||
|
||||
def closeCurrentServerProject(self) -> None:
|
||||
current_project = self.SETTINGS.value("Project/Server/Project")
|
||||
if current_project != "":
|
||||
self.FCOM.closeProject(current_project)
|
||||
if self.FCOM.isConnected():
|
||||
current_project = self.SETTINGS.value("Project/Server/Project")
|
||||
if current_project != "":
|
||||
self.FCOM.closeProject(current_project)
|
||||
else:
|
||||
self.MESSAGEHANDLER.warning('No Server Project to close.', popUp=True)
|
||||
else:
|
||||
self.MESSAGEHANDLER.warning('Not connected to a Server.', popUp=True)
|
||||
|
||||
def closeServerProjectListener(self) -> None:
|
||||
project_name = self.SETTINGS.value("Project/Server/Project")
|
||||
server = self.SETTINGS.value("Project/Server")
|
||||
self.SETTINGS.setValue("Project/Server/Project", "")
|
||||
self.FCOM.receiveFileAbortAll(project_name)
|
||||
self.FCOM.sendFileAbortAll(project_name)
|
||||
self.unSyncCanvasByName()
|
||||
self.setStatus("Closed Server project: " + project_name)
|
||||
self.dockbarThree.serverStatus.updateStatus("Connected to server: " +
|
||||
self.SETTINGS.value("Project/Server"))
|
||||
if server is not None:
|
||||
statusMessage = "Closed Server project: " + str(project_name)
|
||||
self.MESSAGEHANDLER.info(statusMessage)
|
||||
self.setStatus(statusMessage)
|
||||
self.dockbarThree.serverStatus.updateStatus("Connected to server: " + server)
|
||||
|
||||
self.dockbarOne.documentsList.updateFileListFromServer(None)
|
||||
with self.serverProjectsLock:
|
||||
self.serverProjects = []
|
||||
with self.syncedCanvasesLock:
|
||||
self.syncedCanvases = []
|
||||
|
||||
@@ -1233,8 +1242,14 @@ class MainWindow(QtWidgets.QMainWindow):
|
||||
if project_name != '':
|
||||
self.FCOM.closeCanvas(project_name, canvasName)
|
||||
if canvasName is not None:
|
||||
self.setStatus('Stopped syncing Canvas: ' + canvasName)
|
||||
self.MESSAGEHANDLER.info('Stopped syncing Canvas: ' + canvasName)
|
||||
statusMessage = 'Stopped syncing Canvas: ' + canvasName
|
||||
self.setStatus(statusMessage)
|
||||
self.MESSAGEHANDLER.info(statusMessage)
|
||||
else:
|
||||
statusMessage = 'Stopped syncing all Canvases.'
|
||||
self.setStatus(statusMessage)
|
||||
self.MESSAGEHANDLER.info(statusMessage)
|
||||
|
||||
|
||||
def receiveSyncCanvasListener(self, canvas_name: str, canvas_nodes: dict, canvas_edges: dict) -> None:
|
||||
if canvas_name in self.centralWidget().tabbedPane.canvasTabs:
|
||||
@@ -1279,7 +1294,7 @@ class MainWindow(QtWidgets.QMainWindow):
|
||||
self.MESSAGEHANDLER.debug('Received update to canvas: ' + canvas_name + ' for entity / link: ' +
|
||||
str(entity_or_link_uid))
|
||||
|
||||
def sendLocalDatabaseUpdateToServer(self, entityJson: dict, add: bool) -> None:
|
||||
def sendLocalDatabaseUpdateToServer(self, entityJson: dict, add: int) -> None:
|
||||
"""
|
||||
Called by the database when a local item event occurs.
|
||||
If connected to a server, the event is propagated to all other connected clients.
|
||||
@@ -1292,11 +1307,11 @@ class MainWindow(QtWidgets.QMainWindow):
|
||||
self.MESSAGEHANDLER.debug('Sent database update to server: ' + str(entityJson) + ' - Operation: ' +
|
||||
str(add))
|
||||
|
||||
def receiveServerDatabaseUpdate(self, entityJson, add) -> None:
|
||||
def receiveServerDatabaseUpdate(self, entityJson: dict, add: int) -> None:
|
||||
# Check that the JSON received is not empty.
|
||||
if entityJson:
|
||||
uid = entityJson['uid']
|
||||
if add:
|
||||
if add == 1:
|
||||
# Add item
|
||||
if isinstance(uid, str):
|
||||
# Add Entity
|
||||
@@ -1304,7 +1319,7 @@ class MainWindow(QtWidgets.QMainWindow):
|
||||
else:
|
||||
# Add Link
|
||||
self.centralWidget().tabbedPane.serverLinkAddHelper(entityJson)
|
||||
else:
|
||||
elif add == 2:
|
||||
# Remove item
|
||||
if isinstance(uid, str):
|
||||
# Remove Entity
|
||||
@@ -1314,6 +1329,9 @@ class MainWindow(QtWidgets.QMainWindow):
|
||||
# Remove Link
|
||||
self.centralWidget().tabbedPane.linkRemoveAllHelper(uid)
|
||||
self.LENTDB.removeLink(uid, fromServer=True)
|
||||
elif add == 3:
|
||||
# Overwrite existing link
|
||||
self.centralWidget().tabbedPane.serverLinkAddHelper(entityJson, overwrite=True)
|
||||
|
||||
self.MESSAGEHANDLER.debug('Received database update from server: ' + str(entityJson) + ' - Operation: ' +
|
||||
str(add))
|
||||
|
||||
Reference in New Issue
Block a user