Skip to content

Commit

Permalink
Develop (#61)
Browse files Browse the repository at this point in the history
* default syncFolderPath: home

* Filecounter (#57)

* show filecount

* Bugfix: RefreshButton disappear

* Fix: SettingsUI refresh button dissappears

* changed to server2client sync

* server->client sync (#58)

* add syncMode (#60)

* prep for new version

Co-authored-by: LH <[email protected]>
Co-authored-by: Lorenz H <[email protected]>
  • Loading branch information
3 people authored Jan 23, 2023
1 parent d65f4ab commit c2c48cf
Show file tree
Hide file tree
Showing 7 changed files with 69 additions and 28 deletions.
4 changes: 3 additions & 1 deletion services/localappmanager.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,15 @@ def createDefaultSettingsJson():
return

defaultServerURL = ""
defaultSyncFolderPath = "./test/client/"
defaultSyncFolderPath = str(Path.home()) + "/ThunderklaudSyncFolder"
# "./test/client/"

settings = {}

settings["serverUrl"] = defaultServerURL
settings["syncFolderPath"] = defaultSyncFolderPath
settings["notToSyncFolders"] = []
settings["syncMode"] = "Server > Client"

settings = json.dumps(settings)

Expand Down
40 changes: 23 additions & 17 deletions services/permanent_sync_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,14 @@
from config import Config
from utils.file import uniqueDirectoryPath, uniqueFilePath, remoteFileOrDirectoryExists, removeBaseURL
from utils.request import getRequestURL, getRequestHeaders
from services.sync_handlers.filesynchandler import FileSyncHandler
from services.thundersynchandler import ThunderSyncHandler


class PermanentSyncHandler:

# global variable to set the observers state (0 = offline, 1 = running, 2 = syncing)
STATUS = 1
SYNCED_PATHS = []

def __init__(self):
self.syncDirectoryPath = LocalAppManager.getSetting(
Expand All @@ -30,13 +31,12 @@ def run(self):
def start(self):
print("[INFO] Starting permanent syncronisation...")

# self.runStartup()

try:
while PermanentSyncHandler.STATUS != 0:
time.sleep(5)
time.sleep(10) # every 10 seconds

if PermanentSyncHandler.STATUS == 1:
# mutex to prevent sync errors with watchdog
if PermanentSyncHandler.STATUS == 1 and ThunderSyncHandler.STATUS == 1:
self.runStartup() # Fallback for sync
except:
print("PermanentSyncHandler error")
Expand Down Expand Up @@ -78,6 +78,7 @@ def getTimestamp(self):

def runStartup(self):
PermanentSyncHandler.STATUS = 2
SYNCED_PATHS = []
print("[INFO] Sync local folder '" +
self.syncDirectoryPath + "' with remote server...")

Expand Down Expand Up @@ -143,6 +144,8 @@ def __downloadRemoteContentRecursive(self, parent_id=None, path="", directoriesN
# only create folder if folder should be synced
if not directoryID in directoriesNotToSync:
if not os.path.isdir(directoryPath):
if not directoryPath in PermanentSyncHandler.SYNCED_PATHS:
PermanentSyncHandler.SYNCED_PATHS.append(directoryPath)
os.makedirs(directoryPath)

childPath = uniqueDirectoryPath(path + "/" + directoryName)
Expand Down Expand Up @@ -173,22 +176,25 @@ def __handleFile(self, file, path):
fileResult["name"] = fileName
fileResult["path"] = uniqueFilePath(path + "/" + fileName)

if not fileResult["path"] in PermanentSyncHandler.SYNCED_PATHS:
PermanentSyncHandler.SYNCED_PATHS.append(fileResult["path"])

# if local file does not exists => download
if not os.path.isfile(filePath):
PermanentSyncHandler.__downloadFile(fileID, filePath)
# if not os.path.isfile(filePath):
PermanentSyncHandler.__downloadFile(fileID, filePath)

else: # check dates for newer file
# else: # check dates for newer file

# compare modified dates
remoteModifiedDate = float(
file["creation_date"]["$date"]["$numberLong"]) / 1000 # * 1000 to get timestamp in seconds
localModifiedDate = float(os.path.getmtime(filePath))
# compare modified dates
# remoteModifiedDate = float(
# file["creation_date"]["$date"]["$numberLong"]) / 1000 # * 1000 to get timestamp in seconds
# localModifiedDate = float(os.path.getmtime(filePath))

# if remote modified date is newer => download file, else upload file
if remoteModifiedDate > localModifiedDate:
PermanentSyncHandler.__downloadFile(fileID, filePath)
else:
FileSyncHandler.createFile(filePath)
# if remote modified date is newer => download file, else upload file
# if remoteModifiedDate > localModifiedDate:
# PermanentSyncHandler.__downloadFile(fileID, filePath)
# else:
# FileSyncHandler.createFile(filePath)

return fileResult

Expand Down
3 changes: 1 addition & 2 deletions services/server_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ def __getDirectoryRecursive(parentId=None, recPath="", multidimensionalArray=Tru
return []
jsonResponse = response.json()
dirs = jsonResponse["dirs"]
files = jsonResponse["files"]

# loop the result
for dir in dirs:
Expand All @@ -62,7 +61,7 @@ def __getDirectoryRecursive(parentId=None, recPath="", multidimensionalArray=Tru
directory["id"] = directoryID
directory["name"] = directoryName
directory["path"] = childPath
directory["childCount"] = len(files)
directory["childCount"] = dir["child_file_count"]

# set directory to sync/not to sync
directory["syncDir"] = not directoryID in directoriesNotToSync
Expand Down
9 changes: 9 additions & 0 deletions services/sync_handlers/filesynchandler.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ def createFile(src):
@staticmethod
def __renameFile(src, dest):
from services.thundersynchandler import ThunderSyncHandler
from services.permanent_sync_handler import PermanentSyncHandler

ThunderSyncHandler.STATUS = 2
print("[INFO] Rename file " + src + " to " + dest)
Expand Down Expand Up @@ -114,11 +115,19 @@ def deleteFile(src_path):
@staticmethod
def __modifyFile(src_path):
from services.thundersynchandler import ThunderSyncHandler
from services.permanent_sync_handler import PermanentSyncHandler

ThunderSyncHandler.STATUS = 2
src_path = src_path.replace("\\", "/")
print("[INFO] Modify file (delete and create): " + src_path)

toCheckSrcPath = removeBaseURL(src_path, True)
if toCheckSrcPath in PermanentSyncHandler.SYNCED_PATHS:
PermanentSyncHandler.SYNCED_PATHS.remove(toCheckSrcPath)
print("[INFO] Done, no action. Change came from PermanentSyncHandler.")
ThunderSyncHandler.STATUS = 1
return

# delete old file
FileSyncHandler.deleteFile(src_path)

Expand Down
5 changes: 5 additions & 0 deletions services/thundersynchandler.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@ class SyncHandlerHelper(FileSystemEventHandler):
@staticmethod
def on_any_event(event):

# mutex to prevent sync errors with PermanentSyncHandler
from services.permanent_sync_handler import PermanentSyncHandler
while PermanentSyncHandler.STATUS == 2:
time.sleep(3)

# delete files and directories
if event.event_type == "deleted":
SyncHandlerHelper.__deleteFileOrDirectory(event)
Expand Down
3 changes: 2 additions & 1 deletion ui/settings_interval_handler.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import threading
import time
from services.thundersynchandler import ThunderSyncHandler
from services.permanent_sync_handler import PermanentSyncHandler


class SettingsIntervalHandler:
Expand All @@ -22,7 +23,7 @@ def start(self):
status = "offline"
if ThunderSyncHandler.STATUS == 1:
status = "waiting for changes..."
if ThunderSyncHandler.STATUS == 2:
if ThunderSyncHandler.STATUS == 2 or PermanentSyncHandler.STATUS == 2:
status = "syncing..."

self.statusBadge.setText("Status: " + status)
Expand Down
33 changes: 26 additions & 7 deletions ui/settingsui.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,23 +105,22 @@ def createSyncDirectoriesArea(self):
self.contentLayout.addWidget(syncDirectoriesBox)

def addSyncDirectories(self):
self.refresh_button.setText("Loading...")

# remove all directories checkboxes
count = self.syncDirectoriesLayout.count()
for i in range(1, count):
item = self.syncDirectoriesLayout.itemAt(1).widget()

for i in range(2, count):
item = self.syncDirectoriesLayout.itemAt(2).widget()
item.setParent(None)

syncDirectories = ServerSettings.getSyncDirectories()
self.addSyncDirectoryRecursive(syncDirectories)
self.refresh_button.setText("↻")

def addSyncDirectoryRecursive(self, directory, level=0):
perLevelPadding = 7

for dir in directory:
checkboxLabel = dir["name"]
checkboxLabel = dir["name"] + \
" (Files: " + str(dir["childCount"]) + ")"

checkbox = QtWidgets.QCheckBox(checkboxLabel, self)
checkbox.setObjectName(dir["id"])
Expand All @@ -139,14 +138,15 @@ def createSettingsArea(self):
self.createLocalSyncPathInput()
settingsBox.setLayout(self.settingsBoxLayout)
self.contentLayout.addWidget(settingsBox)
self.createChangeMode()

def createAboutArea(self):
aboutBox = QtWidgets.QGroupBox("About")
self.aboutBoxLayout = QtWidgets.QVBoxLayout()

aboutLine1 = QtWidgets.QLabel("Thunderklaud Desktop-Client")
self.aboutBoxLayout.addWidget(aboutLine1)
aboutLine2 = QtWidgets.QLabel("Version 1.1.5")
aboutLine2 = QtWidgets.QLabel("Version 1.2.0")
self.aboutBoxLayout.addWidget(aboutLine2)

aboutLine3 = QtWidgets.QLabel(
Expand All @@ -172,6 +172,24 @@ def createLocalSyncPathInput(self):

self.settingsBoxLayout.addLayout(rowLayout)

def createChangeMode(self):
rowLayout = QtWidgets.QHBoxLayout()

syncMode = QtWidgets.QLabel("Sync Mode")

self.comboBox = QtWidgets.QComboBox(self)
self.comboBox.addItem("Server > Client")
self.comboBox.addItem("Client > Server")
self.comboBox.addItem("Bidirectional")
self.comboBox.setCurrentText(LocalAppManager.getSetting("syncMode"))

rowLayout.addWidget(syncMode)
rowLayout.addWidget(self.comboBox)
self.settingsBoxLayout.addLayout(rowLayout)

def getSyncMode(self):
return self.comboBox.currentText()

def getLocalSyncPathInput(self):
return self.localSyncPathInput.text()

Expand All @@ -187,6 +205,7 @@ def clickedSave(self):

settings["syncFolderPath"] = self.getLocalSyncPathInput()
settings["notToSyncFolders"] = self.getFoldersNotToSync()
settings["syncMode"] = self.getSyncMode()

LocalAppManager.saveSettings(settings)

Expand Down

0 comments on commit c2c48cf

Please sign in to comment.