Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
142 changes: 124 additions & 18 deletions CloudComputing.qml
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,17 @@ Rectangle {
border.width: 1
radius: 4

ColumnLayout {
RowLayout {
id: contentLayout
anchors.fill: parent
anchors.margins: 10
spacing: 10
spacing: 20

// Left Column - Configuration/Upload
ColumnLayout {
Layout.fillWidth: true
Layout.preferredWidth: parent.width * 0.5
spacing: 10

Label {
text: "Target IP"
Expand Down Expand Up @@ -351,27 +357,127 @@ Rectangle {
}
}
}
} // End of Left Column

FileDialog {
id: configFileDialog
title: "Select Configuration File"
onAccepted: {
if (saveConfigButton.down) {
saveConfig(
hostInput.text,
usernameInput.text,
privateKeyDirInput.text,
targetDirInput.text,
ignoreHostKeyCheckbox.checked,
sourceDirInput.text,
fileUrl.toLocalFile()
);
} else {
loadConfig(fileUrl.toLocalFile());
// Right Column - Open Data and Console Log
ColumnLayout {
Layout.fillWidth: true
Layout.preferredWidth: parent.width * 0.5
spacing: 20

// Open Data Button
Rectangle {
Layout.alignment: Qt.AlignHCenter
Layout.preferredHeight: 120
Layout.preferredWidth: 120
color: "#2C3E50"
radius: 60
border.color: "#CCCCCC"
border.width: 2

Button {
id: openDataButton
objectName: "openDataButton"
anchors.fill: parent
text: "Open Data"
font.bold: true
font.pixelSize: 16
onClicked: console.log("Open Data clicked")

contentItem: Text {
text: parent.text
color: "white"
font.bold: true
font.pixelSize: 16
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}

background: Rectangle {
id: openDataButtonBackground
color: "#2C3E50"
radius: 60
}
}
}

// Console Log Section
Label {
text: "Console Log"
color: "white"
font.bold: true
font.pixelSize: 14
}

ScrollView {
Layout.fillWidth: true
Layout.fillHeight: true
Layout.preferredMinHeight: 300
clip: true

Rectangle {
width: parent.width
height: consoleLogArea.implicitHeight + 10
color: "#FFFFFF"
border.color: "#CCCCCC"
border.width: 1
radius: 4

TextArea {
id: consoleLogArea
objectName: "consoleLogArea"
anchors.fill: parent
anchors.margins: 5
text: ""
color: "#000000"
font.family: "monospace"
font.pixelSize: 12
readOnly: true
wrapMode: TextArea.Wrap
placeholderText: "Console output will appear here..."
}
}
}

// Hidden processed directory input for backend
TextField {
id: processedDirInput
objectName: "processedDirInput"
visible: false
text: ""
}
} // End of Right Column
} // End of RowLayout

// File Dialogs (outside the layout)
FileDialog {
id: processedDirFileDialog
title: "Select Processed Directory"
onAccepted: {
processedDirInput.text = fileUrl.toLocalFile();
}
}

FileDialog {
id: configFileDialog
title: "Select Configuration File"
onAccepted: {
if (saveConfigButton.down) {
saveConfig(
hostInput.text,
usernameInput.text,
privateKeyDirInput.text,
targetDirInput.text,
ignoreHostKeyCheckbox.checked,
sourceDirInput.text,
fileUrl.toLocalFile()
);
} else {
loadConfig(fileUrl.toLocalFile());
}
}
}
}
}
}
}
117 changes: 116 additions & 1 deletion cloud_api.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
from PySide6.QtWidgets import QFileDialog, QMessageBox
from PySide6.QtCore import QObject, Slot
from PySide6.QtCore import QObject, Slot, QProcess, QTimer
import configparser
import os
import sys
from pathlib import Path
from sftp import fileTransfer

class CloudAPI(QObject):
Expand All @@ -9,6 +12,8 @@ def __init__(self):
self.config = configparser.ConfigParser()
self.config.optionxform = str
self.root_object = None
self.opendata_process = None
self.opendata_timer = None

def set_root_object(self, root_object):
self.root_object = root_object
Expand All @@ -27,6 +32,9 @@ def connect_buttons(self):
self.root_object.findChild(QObject, "sourceDirButton").clicked.connect(self.browse_source_dir)
self.root_object.findChild(QObject, "targetDirButton").clicked.connect(self.browse_target_dir)

# Open Data button
self.root_object.findChild(QObject, "openDataButton").clicked.connect(self.browse_processed_dir)

print("Cloud API buttons connected successfully")
except Exception as e:
print(f"Error connecting cloud API buttons: {e}")
Expand Down Expand Up @@ -140,4 +148,111 @@ def upload(self):
except Exception as e:
QMessageBox.critical(None, "Upload failed", "Please ensure that your inputs are correct and that the server is running\n\nERROR:\n" + str(e))

# Start of change : Added Open Data functionality
@Slot()
def browse_processed_dir(self):
file_dialog = QFileDialog()
file_dialog.setFileMode(QFileDialog.FileMode.Directory)
file_dialog.setViewMode(QFileDialog.ViewMode.List)
if file_dialog.exec():
file_paths = file_dialog.selectedFiles()
if file_paths:
processed_dir = file_paths[0]
self.root_object.findChild(QObject, "processedDirInput").setProperty("text", processed_dir)

# Change button color to yellow when directory is selected
self.root_object.findChild(QObject, "openDataButtonBackground").setProperty("color", "#F39C12")

# Check if directory contains 'processed' in name and start automatically
if "processed" in os.path.basename(processed_dir).lower():
self.append_console_log(f"Selected directory: {processed_dir}")
self.append_console_log("Starting Open Data publishing process...")
# Automatically start the opendata process
self.start_opendata()
else:
self.append_console_log("Warning: Please select a directory named 'processed'")

@Slot()
def start_opendata(self):
processed_dir = self.root_object.findChild(QObject, "processedDirInput").property("text")

if not processed_dir or "processed" not in os.path.basename(processed_dir).lower():
QMessageBox.critical(None, "Error", "Please select a valid 'processed' directory first.")
return

# Check if opendata.py exists
opendata_script = Path(__file__).parent / "file-opendata" / "opendata.py"
if not opendata_script.exists():
QMessageBox.critical(None, "Error", f"Open Data script not found at: {opendata_script}")
return

# Button color indicates processing state
self.root_object.findChild(QObject, "openDataButtonBackground").setProperty("color", "#E67E22")
# Clear console and start logging
self.root_object.findChild(QObject, "consoleLogArea").setProperty("text", "")
self.append_console_log("Starting Open Data publishing process...")
self.append_console_log(f"Script: {opendata_script}")
self.append_console_log(f"Working directory: {processed_dir}")

# Setup process
self.opendata_process = QProcess()
self.opendata_process.readyReadStandardOutput.connect(self.read_opendata_output)
self.opendata_process.readyReadStandardError.connect(self.read_opendata_error)
self.opendata_process.finished.connect(self.opendata_finished)

# Set working directory to the parent of processed directory
working_dir = Path(processed_dir).parent

# Run the opendata script
try:
self.opendata_process.setWorkingDirectory(str(working_dir))
self.opendata_process.start(sys.executable, [str(opendata_script)])
self.append_console_log("Process started successfully...")
except Exception as e:
QMessageBox.critical(None, "Error", f"Failed to start Open Data process: {str(e)}")
self.root_object.findChild(QObject, "openDataButtonBackground").setProperty("color", "#F39C12")

@Slot()
def read_opendata_output(self):
if self.opendata_process:
data = self.opendata_process.readAllStandardOutput()
output = data.data().decode('utf-8', errors='ignore')
self.append_console_log(output.strip())

@Slot()
def read_opendata_error(self):
if self.opendata_process:
data = self.opendata_process.readAllStandardError()
error_output = data.data().decode('utf-8', errors='ignore')
self.append_console_log(f"ERROR: {error_output.strip()}")

@Slot()
def opendata_finished(self, exit_code, exit_status):
if exit_code == 0:
self.append_console_log("\n✅ Open Data publishing completed successfully!")
QMessageBox.information(None, "Success", "Open Data publishing completed successfully!")
else:
self.append_console_log(f"\n❌ Open Data publishing failed with exit code: {exit_code}")
QMessageBox.critical(None, "Error", f"Open Data publishing failed with exit code: {exit_code}")

# Reset button color to indicate completion
self.root_object.findChild(QObject, "openDataButtonBackground").setProperty("color", "#F39C12")
self.opendata_process = None


def append_console_log(self, message):
console_area = self.root_object.findChild(QObject, "consoleLogArea")
if console_area:
current_text = console_area.property("text")
if current_text == "Console output will appear here...":
new_text = message
else:
new_text = current_text + "\n" + message
console_area.setProperty("text", new_text)

# Auto-scroll to bottom
console_area.setProperty("cursorPosition", len(new_text))

# End of change : Added Open Data functionality

# End of change : Added Cloud Computing (Transfer Data) functionality
Loading