dropship/dropship.py

166 lines
5.3 KiB
Python
Raw Normal View History

2020-07-22 16:55:56 +02:00
"""Magic-Wormhole bundled up inside a PyGtk GUI."""
2020-07-22 17:26:59 +02:00
import logging
import os
2020-09-20 23:34:32 +02:00
from signal import SIGINT
2020-09-15 12:38:38 +02:00
from subprocess import PIPE
2020-07-22 16:55:56 +02:00
2020-07-21 14:48:34 +02:00
import gi
2020-09-15 12:38:38 +02:00
import trio
2020-09-20 23:34:32 +02:00
import trio_gtk
2020-07-21 14:48:34 +02:00
gi.require_version("Gtk", "3.0")
2020-07-22 16:03:55 +02:00
gi.require_version("Gdk", "3.0")
from gi.repository import Gdk
from gi.repository import GLib
from gi.repository import Gtk
from ui_templates import pendingTransmissions
2020-07-22 16:03:55 +02:00
2020-07-22 17:26:59 +02:00
logging.basicConfig(level=os.environ.get("LOGLEVEL", "INFO"))
log = logging.getLogger("dropship")
2020-07-22 16:55:56 +02:00
class DropShip:
"""Drag it, drop it, ship it."""
2020-07-21 14:48:34 +02:00
2020-09-15 12:38:38 +02:00
def __init__(self, nursery):
2020-07-23 12:24:50 +02:00
"""Object initialisation."""
2020-07-22 16:55:56 +02:00
self.GLADE_FILE = "dropship.glade"
self.CSS_FILE = "dropship.css"
2020-07-23 12:40:50 +02:00
self.DOWNLOAD_DIR = os.path.expanduser("~")
self.clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD)
2020-09-15 12:38:38 +02:00
self.nursery = nursery
2020-07-23 14:44:14 +02:00
2020-07-22 16:55:56 +02:00
self.init_glade()
self.init_css()
self.init_ui_elements()
self.init_window()
2020-07-22 16:55:56 +02:00
def init_glade(self):
"""Initialise the GUI from Glade file."""
self.builder = Gtk.Builder()
2020-07-22 16:55:56 +02:00
self.builder.add_from_file(self.GLADE_FILE)
2020-07-21 14:48:34 +02:00
self.builder.connect_signals(self)
2020-07-22 16:55:56 +02:00
def init_css(self):
"""Initialise CSS injection."""
self.screen = Gdk.Screen.get_default()
self.provider = Gtk.CssProvider()
self.provider.load_from_path(self.CSS_FILE)
Gtk.StyleContext.add_provider_for_screen(
self.screen, self.provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION
2020-07-22 16:03:55 +02:00
)
def init_window(self):
"""Initialise the Main GUI window."""
self.main_window_id = "mainWindow"
self.window = self.builder.get_object(self.main_window_id)
self.window.connect("delete-event", Gtk.main_quit)
self.window.show()
2020-07-21 14:48:34 +02:00
def init_ui_elements(self):
"""Initialize the UI elements."""
# Send UI
# Drag & Drop Box
self.files_to_send = ""
self.enforce_target = Gtk.TargetEntry.new(
"text/uri-list", Gtk.TargetFlags(4), 129
2020-07-27 13:41:58 +02:00
)
2020-07-27 13:41:58 +02:00
self.drop_box = self.builder.get_object("dropBox")
self.drop_box.drag_dest_set(
Gtk.DestDefaults.ALL, [self.enforce_target], Gdk.DragAction.COPY
2020-07-22 16:03:55 +02:00
)
self.drop_box.connect("drag-data-received", self.on_drop)
2020-07-27 13:41:58 +02:00
self.drop_label = self.builder.get_object("dropLabel")
self.drop_spinner = self.builder.get_object("dropSpinner")
2020-07-21 17:37:09 +02:00
# File chooser
2020-07-27 13:41:58 +02:00
self.file_chooser = self.builder.get_object("filePicker")
self.file_chooser.add_buttons(
"Cancel", Gtk.ResponseType.CANCEL, "Add", Gtk.ResponseType.OK
)
2020-07-24 17:18:42 +02:00
# Receive UI
# Code entry box
2020-07-27 13:41:58 +02:00
self.recv_box = self.builder.get_object("receiveBoxCodeEntry")
2020-07-23 13:06:56 +02:00
self.recv_box.connect("activate", self.on_recv)
2020-10-07 18:13:46 +02:00
# Pending Transmissions UI
self.pending_box = self.builder.get_object("pendingBox")
self.transfer_code = ''
2020-07-22 16:55:56 +02:00
def on_drop(self, widget, drag_context, x, y, data, info, time):
2020-07-23 13:06:56 +02:00
"""Handler for file dropping."""
files = data.get_uris()
2020-07-22 16:03:55 +02:00
self.files_to_send = files
2020-07-22 19:00:00 +02:00
if len(files) == 1:
2020-07-27 14:22:48 +02:00
fpath = files[0].replace("file://", "")
# TODO Luke can u make a callback that spawns pendingTransmissions after we got a code?
2020-09-15 12:38:38 +02:00
self.nursery.start_soon(self.wormhole_send, fpath)
2020-10-07 18:13:46 +02:00
# TODO Roel/Luke, move this somewhere logical in its own function?
status = pendingTransmissions(self, fpath.split('/')[-1], self.transfer_code)
self.pending_box.add(status)
2020-08-05 09:55:37 +02:00
else:
log.info("Multiple file sending coming soon ™")
2020-09-15 12:38:38 +02:00
def on_recv(self, entry):
"""Handler for receiving transfers."""
self.nursery.start_soon(self.wormhole_recv, entry.get_text())
2020-07-27 13:41:58 +02:00
def add_files(self, widget, event):
"""Handler for adding files with system interface"""
response = self.file_chooser.run()
if response == Gtk.ResponseType.OK:
2020-07-27 15:08:07 +02:00
fpath = self.file_chooser.get_filenames()[0]
2020-09-15 12:38:38 +02:00
self.nursery.start_soon(self.wormhole_send, fpath)
self.file_chooser.hide()
2020-09-15 12:38:38 +02:00
async def wormhole_send(self, fpath):
2020-07-27 14:14:55 +02:00
"""Run `wormhole send` on a local file path."""
command = ["wormhole", "send", fpath]
2020-09-15 12:38:38 +02:00
process = await trio.open_process(command, stderr=PIPE)
self.drop_label.set_visible(False)
self.drop_label.set_vexpand(False)
self.drop_spinner.set_vexpand(True)
self.drop_spinner.set_visible(True)
self.drop_spinner.start()
2020-07-23 14:44:14 +02:00
2020-09-15 12:38:38 +02:00
output = await process.stderr.receive_some()
code = output.decode().split()[-1]
self.transfer_code = code
2020-09-15 12:38:38 +02:00
self.drop_label.set_text(code)
2020-08-05 09:46:12 +02:00
self.drop_label.set_visible(True)
self.drop_label.set_selectable(True)
2020-09-15 12:38:38 +02:00
self.drop_spinner.stop()
2020-08-05 09:46:12 +02:00
self.drop_spinner.set_vexpand(False)
self.drop_spinner.set_visible(False)
2020-07-22 19:25:53 +02:00
2020-09-15 12:38:38 +02:00
await process.wait()
2020-07-23 14:44:14 +02:00
2020-09-15 12:38:38 +02:00
async def wormhole_recv(self, code):
2020-07-23 12:40:50 +02:00
"""Run `wormhole receive` with a pending transfer code."""
2020-07-27 14:14:55 +02:00
command = ["wormhole", "receive", "--accept-file", code]
2020-09-15 12:38:38 +02:00
await trio.run_process(command, stderr=PIPE)
2020-07-22 16:55:56 +02:00
2020-09-21 00:07:43 +02:00
async def main():
2020-09-20 23:34:32 +02:00
"""Trio main entrypoint."""
2020-09-21 00:07:43 +02:00
async with trio.open_nursery() as nursery:
DropShip(nursery)
await trio.sleep_forever()
2020-09-15 12:38:38 +02:00
2020-09-20 23:34:32 +02:00
trio_gtk.run(main)