Skip to content
Draft
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
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@


TODO
* Progress bar
* More compression options
* Drag and drop support
* ~~Progress bar~~
* ~~More compression options~~
* ~~Drag and drop support~~

7Zip DOC - file:///usr/share/doc/p7zip/DOC/MANUAL/cmdline/switches/method.htm
33 changes: 31 additions & 2 deletions main.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import multiprocessing
import urllib.parse

import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
from gi.repository import Gdk, GLib, Gtk

from zipcontroller import ZipController

Expand Down Expand Up @@ -46,11 +47,24 @@ def __init__(self):
self.button_threads.set_value(multiprocessing.cpu_count())
box1.add(self.button_threads)

label_level = Gtk.Label("Level")
box1.add(label_level)

self.button_level = Gtk.SpinButton()
self.button_level.set_numeric(True)
self.button_level.set_range(0, 9)
self.button_level.set_increments(1, 1)
self.button_level.set_value(5)
box1.add(self.button_level)

self.store = Gtk.ListStore(str)
tree = Gtk.TreeView(self.store)
renderer = Gtk.CellRendererText()
column = Gtk.TreeViewColumn("Arquivos", renderer, text=0)
tree.append_column(column)
tree.drag_dest_set(Gtk.DestDefaults.ALL, [], Gdk.DragAction.COPY)
tree.drag_dest_add_uri_targets()
tree.connect("drag-data-received", self.on_drag_data_received)
box0.pack_start(tree, True, True, 0)

box_bottom_buttons = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=10)
Expand All @@ -64,6 +78,10 @@ def __init__(self):
button_clear.connect("clicked", self.clean)
box_bottom_buttons.add(button_clear)

self.progress_bar = Gtk.ProgressBar()
self.progress_bar.set_show_text(True)
box0.add(self.progress_bar)

def clean(self, widget):
self.file_list.clear()
self.store.clear()
Expand Down Expand Up @@ -127,7 +145,18 @@ def compress(self, widget):
output = self.entry_name.get_text()
if len(self.file_list) > 0 and output != '':
multithread = self.button_threads.get_value_as_int()
ZipController().compress(self.file_list, output, multithread)
level = self.button_level.get_value_as_int()
self.progress_bar.set_fraction(0)
ZipController().compress(self.file_list, output, multithread, level,
progress_callback=lambda f: GLib.idle_add(self.progress_bar.set_fraction, f))

def on_drag_data_received(self, widget, drag_context, x, y, data, info, time):
for uri in data.get_uris():
path = urllib.parse.urlparse(uri).path
path = urllib.parse.unquote(path)
if path not in self.file_list:
self.file_list.append(path)
self.store.append([path])

if __name__ == '__main__':
app_window = Py7zip()
Expand Down
34 changes: 27 additions & 7 deletions zipcontroller.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,39 @@
import re
import subprocess
import threading
from typing import List
from typing import Callable, List, Optional

class ZipController:
def compress(self, file_list: List[str], output: str, threads: int, level: int = 5):
def compress(self, file_list: List[str], output: str, threads: int, level: int = 5,
progress_callback: Optional[Callable[[float], None]] = None):
call = ["7za", "a", "-r", "-t7z", "-m0=lzma2", f"-mx={level}", f"-mmt={threads}", output]

for file in file_list:
call.append(file)

self.start_thread(call)
self.start_thread(call, progress_callback)

def do_subprocess(self, call):
subprocess.check_call(call)
def do_subprocess(self, call, progress_callback=None):
process = subprocess.Popen(call, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
buf = b''
while True:
chunk = process.stdout.read(4096)
if not chunk:
break
for byte in chunk:
c = bytes([byte])
if c in (b'\r', b'\n'):
if progress_callback and buf:
match = re.search(rb'(\d+)%', buf)
if match:
progress_callback(int(match.group(1)) / 100.0)
buf = b''
else:
buf += c
process.wait()
if process.returncode != 0:
raise subprocess.CalledProcessError(process.returncode, call)

def start_thread(self, call):
t = threading.Thread(target=self.do_subprocess, kwargs={'call': call})
def start_thread(self, call, progress_callback=None):
t = threading.Thread(target=self.do_subprocess, kwargs={'call': call, 'progress_callback': progress_callback})
t.start()