Skip to content

Commit

Permalink
Merge pull request #1 from redromnon/testing
Browse files Browse the repository at this point in the history
[Tech|UI] Display operation execution + Refactor
  • Loading branch information
redromnon authored Dec 17, 2022
2 parents b0ea102 + 66b5b60 commit 369d90e
Show file tree
Hide file tree
Showing 3 changed files with 123 additions and 162 deletions.
26 changes: 14 additions & 12 deletions src/libutilities.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,32 +37,34 @@ def backup(self, folder, password):
#Enable encryption if password is given
if password is None:

self.process = subprocess.Popen(["idevicebackup2", "backup", folder], stdout=subprocess.PIPE)

self.process = subprocess.Popen(["idevicebackup2", "backup", folder], stdout=subprocess.PIPE, bufsize=1, universal_newlines=True)

return self.process

else:

print("Checking encryption...")
self.encrypt_process = subprocess.Popen(["idevicebackup2", "encryption", "on", password, folder])
self.process = subprocess.Popen(["idevicebackup2", "backup", folder], stdout=subprocess.PIPE)
self.encrypt_process.wait()

while(self.process.poll() == None):
pass
self.process = subprocess.Popen(["idevicebackup2", "backup", folder], stdout=subprocess.PIPE, bufsize=1, universal_newlines=True)

return self.process

def restore(self, folder, password):

if password is None:

self.process = subprocess.Popen(["idevicebackup2", "restore", folder], stdout=subprocess.PIPE)

else:
self.process = subprocess.Popen(["idevicebackup2", "restore", folder], stdout=subprocess.PIPE, bufsize=1, universal_newlines=True)

print("Restoring encrypted backup...")
self.process = subprocess.Popen(["idevicebackup2", "restore", "--password", password, folder], stdout=subprocess.PIPE)
return self.process

else:

while(self.process.poll() == None):
pass
print("Restoring encrypted backup...")
self.process = subprocess.Popen(["idevicebackup2", "restore", "--password", password, folder], stdout=subprocess.PIPE, bufsize=1, universal_newlines=True)

return self.process

def cancel(self):

Expand Down
161 changes: 11 additions & 150 deletions src/ui/app.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import flet as ft
from libutilities import scan, Action
from libutilities import scan
from ui.about import About
from ui.encrypt import Encrypt
from ui.operations import Operation

class App(ft.UserControl):

Expand All @@ -13,46 +14,9 @@ def build(self):

#Import encryption password container row
self.pwd_encrypt = Encrypt()

#Action (operations - backup, restore and cancel) obj to used later
self.action = Action()


#Action (pop-up) dialogs
self.backup_dialog = ft.AlertDialog(
title=ft.Text("Backing Up Device", text_align="center"),
content=ft.Column(
[ft.Text("This will take some time"), ft.ProgressRing()],
height=50, horizontal_alignment="center"
),
actions=[ft.TextButton("Cancel", on_click=self.cancel_op)],
content_padding=40, modal=True
)

self.restore_dialog = ft.AlertDialog(
title=ft.Text("Restoring Device", text_align="center"),
content=ft.Column(
[ft.Text("This will take some time"), ft.ProgressRing()],
height=50, horizontal_alignment="center"
),
actions=[ft.TextButton("Cancel", on_click=self.cancel_op)],
content_padding=40, modal=True
)

#Check if operation is cancelled
self.cancel_pressed = None

self.lib_output = ft.TextField(max_lines=6, height=200, filled=True, read_only=True)
self.result_dialog = ft.AlertDialog(
content=ft.Column(
[
ft.Text("Scroll down to view the output", text_align="center", size=16, style="bodySmall"),
self.lib_output,
ft.Text("Click anywhere outside the dialog to close", text_align="center", size=16, style="bodySmall")
],
height=220, width=400, horizontal_alignment="center"
), content_padding=40
)
#Process dialog for Action
self.operation_dialog = Operation()


#Snackbar (bottom) dialog
Expand All @@ -62,16 +26,6 @@ def build(self):


#Banner dialog
self.backup_cancel_banner = ft.Banner(
content=ft.Text("Backup cancelled"),
actions=[ft.TextButton("Ok", on_click=self.close_banner)]
)

self.restore_cancel_banner = ft.Banner(
content=ft.Text("Backup cancelled"),
actions=[ft.TextButton("Ok", on_click=self.close_banner)]
)

self.lib_not_installed_banner = ft.Banner(
content=ft.Text("Looks like libimobiledevice or libimobiledevice-utils is not installed"),
actions=[ft.TextButton("Ok", on_click=self.close_banner)]
Expand All @@ -83,7 +37,7 @@ def build(self):

self.display_folderpath = ft.TextField(
hint_text="Select folder icon", width=400, read_only=True, border="none",
filled=True, max_lines=3
filled=True, max_lines=3, color="#a6a6a6"
)

self.select_folder_icon = ft.IconButton(
Expand Down Expand Up @@ -119,13 +73,12 @@ def build(self):
self.main_container = ft.Stack(
[
#Alerts and dialogs go here
self.backup_cancel_banner, self.backup_dialog, self.restore_dialog, self.lib_not_installed_banner,
self.no_device_dialog, self.no_folder_selected_dlg, self.restore_cancel_banner, self.result_dialog,
self.lib_not_installed_banner, self.operation_dialog,
self.no_device_dialog, self.no_folder_selected_dlg,

#Others
ft.Column(
[self.folder_container, self.pwd_encrypt, self.options_container,
self.about_button],
[self.folder_container, self.pwd_encrypt, self.options_container, self.about_button],
spacing=30, horizontal_alignment="center"
)
]
Expand All @@ -147,11 +100,7 @@ def folder_dialog_result(self, e: ft.FilePickerResultEvent):
#Close action finished banner
def close_banner(self, e):

if(self.backup_cancel_banner.open):
self.backup_cancel_banner.open = False
elif(self.restore_cancel_banner.open):
self.restore_cancel_banner.open = False
elif(self.lib_not_installed_banner.open):
if(self.lib_not_installed_banner.open):
self.lib_not_installed_banner.open = False

self.update()
Expand All @@ -175,40 +124,10 @@ def do_backup(self, e):
if lib_installed and status:
print("Device found!")

#Set this to off
self.cancel_pressed = False

#Display backup alert progress dialog
self.backup_dialog.open = True
self.update()

#Run backup operation
print("Backup running...")
pwd = self.pwd_encrypt.get_pwd()#Check if password is given
self.action.backup(self.display_folderpath.value, pwd)

#Store output text
self.poutput = self.action.process.communicate()
self.lib_output.value = self.poutput[0].decode()

#Successfully executed with return code as 0
if self.action.process.poll() == 0:
self.backup_dialog.open = False

self.result_dialog.title = ft.Text("Backup Successful", text_align="center")
self.result_dialog.open = True

print("Backup successfully finished")

self.update()
else:
if not self.cancel_pressed:
self.backup_dialog.open = False

self.result_dialog.title = ft.Text("Backup Unsuccessful", text_align="center")
self.result_dialog.open = True

print("Something went wrong")
self.operation_dialog.backup(self.display_folderpath.value, pwd)

elif lib_installed and not status:
self.no_device_dialog.open = True
Expand Down Expand Up @@ -237,42 +156,11 @@ def do_restore(self, e):
if lib_installed and status:
print("Device found!")

#Set this to off
self.cancel_pressed = False

#Display backup alert progress dialog
self.restore_dialog.open = True
self.update()

#Run restore operation
print("Restore running...")
pwd = self.pwd_encrypt.get_pwd()#Check if password is given
self.action.restore(self.display_folderpath.value, pwd)

#Store output text
self.poutput = self.action.process.communicate()
self.lib_output.value = self.poutput[0].decode()

#Successfully executed with return code as 0
if self.action.process.poll() == 0:
self.restore_dialog.open = False

self.result_dialog.title = ft.Text("Restore Successful", text_align="center")
self.result_dialog.open = True

print("Restore successfully finished")
self.operation_dialog.restore(self.display_folderpath.value, pwd)

self.update()
else:
if not self.cancel_pressed:
self.restore_dialog.open = False

self.result_dialog.title = ft.Text("Restore Unsuccessful", text_align="center")
self.result_dialog.open = True

print("Something went wrong")

self.update()
elif lib_installed and not status:
self.no_device_dialog.open = True
self.update()
Expand All @@ -282,30 +170,3 @@ def do_restore(self, e):

self.update()


def cancel_op(self, e):

self.action.cancel()

#close alert dialogs
if(self.backup_dialog.open):

self.backup_dialog.open = False

self.backup_cancel_banner.open = True

print("Backup cancelled")

elif(self.restore_dialog.open):

self.restore_dialog.open = False

self.restore_cancel_banner.open = True

print("Restore cancelled")

#Set this to True
self.cancel_pressed = True

self.update()

98 changes: 98 additions & 0 deletions src/ui/operations.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import flet as ft
from libutilities import Action

class Operation(ft.UserControl):

def build(self):

self.action = Action()

self.lib_output = ft.TextField(value="", filled=True, read_only=True, multiline=True, text_size=13, color=ft.colors.AMBER)

self.close_button = ft.TextButton("Close", disabled=True, on_click=self.close_dialog)
self.cancel_button = ft.TextButton("Cancel", disabled=False, on_click=self.cancel_op)

self.loading = ft.ProgressBar()

self.result_dialog = ft.AlertDialog(
content=ft.Column(
[
self.loading,
ft.Column(
[self.lib_output],
horizontal_alignment="center", expand=True, auto_scroll=True, scroll="auto",
width=400
),
], width=400
),
content_padding=30, modal=True,
actions=[self.close_button, self.cancel_button]
)

return self.result_dialog

def backup(self, folder, pwd):

self.result_dialog.open = True
self.result_dialog.title = ft.Text("Backing Up", text_align="center")
self.lib_output.value = "...\n"
self.update()

process = self.action.backup(folder, pwd)

for line in process.stdout:
print(line, end="")
self.lib_output.value += line
self.update()

process.wait()

self.close_button.disabled = False
self.cancel_button.disabled = True
self.loading.value = 0.0
self.update()


def restore(self, folder, pwd):

self.result_dialog.open = True
self.result_dialog.title = ft.Text("Restoring", text_align="center")
self.lib_output.value = "...\n"
self.update()

process = self.action.restore(folder, pwd)

for line in process.stdout:
print(line, end="")
self.lib_output.value += line
self.update()

process.wait()

self.close_button.disabled = False
self.cancel_button.disabled = True
self.loading.value = 0.0
self.update()


def close_dialog(self, e):

#Reset properties to default
self.lib_output.value = ""
self.close_button.disabled = True
self.cancel_button.disabled = False
self.loading.value = None
self.result_dialog.open = False
self.update()


def cancel_op(self, e):

self.lib_output.value += "\n--CANCELLED BY USER--"
self.loading.value = 0.0
self.update()

self.action.cancel()



0 comments on commit 369d90e

Please sign in to comment.