beginning to refactor onionshare_gui to work with multiple files (#66)

This commit is contained in:
Micah Lee 2014-08-27 14:21:08 -07:00
parent 3f59fe7af0
commit 78f6c31061
8 changed files with 214 additions and 40 deletions

View File

@ -6,5 +6,6 @@ include onionshare/index.html
include onionshare/404.html
include onionshare/strings.json
include onionshare_gui/logo.png
include onionshare_gui/drop_files.png
include setup/onionshare.desktop
include setup/onionshare80.xpm

View File

@ -26,7 +26,13 @@
"help_local_only": "Do not attempt to use tor: for development only",
"help_stay_open": "Keep hidden service running after download has finished",
"help_debug": "Log errors to disk",
"help_filename": "List of files or folders to share"
"help_filename": "List of files or folders to share",
"gui_drag_and_drop": "Drag and drop\nfiles here",
"gui_add_files": "Add Files",
"gui_add_folder": "Add Folder",
"gui_delete": "Delete",
"gui_choose_files": "Choose files",
"gui_choose_folder": "Choose folder"
}, "no": {
"calculating_sha1": "Kalkulerer SHA1 sjekksum.",
"connecting_ctrlport": "Kobler til Tors kontroll-port for å sette opp en gjemt tjeneste på port {0}.",

10
onionshare_gui/common.py Normal file
View File

@ -0,0 +1,10 @@
import os, inspect, platform
def get_onionshare_gui_dir():
if platform.system() == 'Darwin':
onionshare_gui_dir = os.path.dirname(__file__)
else:
onionshare_gui_dir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
return onionshare_gui_dir
onionshare_gui_dir = get_onionshare_gui_dir()

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@ -0,0 +1,145 @@
import os
from PyQt4 import QtCore, QtGui
import common
from onionshare import strings, helpers
class FileList(QtGui.QListWidget):
files_dropped = QtCore.pyqtSignal()
def __init__(self, parent=None):
super(FileList, self).__init__(parent)
self.setAcceptDrops(True)
self.setIconSize(QtCore.QSize(32, 32))
# drag and drop label
self.drop_label = QtGui.QLabel(QtCore.QString(strings._('gui_drag_and_drop')), parent=self)
self.drop_label.setAlignment(QtCore.Qt.AlignCenter)
self.drop_label.setStyleSheet('background: url({0}/drop_files.png) no-repeat center center; color: #999999;'.format(common.onionshare_gui_dir))
self.drop_label.hide()
self.filenames = []
self.update()
def update(self):
# file list should have a background image if empty
if len(self.filenames) == 0:
self.drop_label.show()
else:
self.drop_label.hide()
def resizeEvent(self, event):
self.drop_label.setGeometry(0, 0, self.width(), self.height())
def dragEnterEvent(self, event):
if event.mimeData().hasUrls:
event.accept()
else:
event.ignore()
def dragMoveEvent(self, event):
if event.mimeData().hasUrls:
event.setDropAction(QtCore.Qt.CopyAction)
event.accept()
else:
event.ignore()
def dropEvent(self, event):
if event.mimeData().hasUrls:
event.setDropAction(QtCore.Qt.CopyAction)
event.accept()
for url in event.mimeData().urls():
filename = str(url.toLocalFile())
self.add_file(filename)
else:
event.ignore()
self.files_dropped.emit()
def add_file(self, filename):
if filename not in self.filenames:
self.filenames.append(filename)
basename = os.path.basename(filename)
fileinfo = QtCore.QFileInfo(filename)
ip = QtGui.QFileIconProvider()
icon = ip.icon(fileinfo)
if os.path.isfile(filename):
size = self.human_readable_filesize(fileinfo.size())
else:
size = self.human_readable_filesize(helpers.dir_size(filename))
item = QtGui.QListWidgetItem('{0} ({1})'.format(basename, size))
item.setToolTip(QtCore.QString(size))
item.setIcon(icon)
self.addItem(item)
def human_readable_filesize(self, b):
thresh = 1024.0
if b < thresh:
return '{0} B'.format(b)
units = ['KiB','MiB','GiB','TiB','PiB','EiB','ZiB','YiB']
u = 0
b /= thresh
while b >= thresh:
b /= thresh
u += 1
return '{0} {1}'.format(round(b, 1), units[u])
class FileSelection(QtGui.QVBoxLayout):
def __init__(self):
super(FileSelection, self).__init__()
# file list
self.file_list = FileList()
self.file_list.currentItemChanged.connect(self.update)
self.file_list.files_dropped.connect(self.update)
# buttons
self.add_files_button = QtGui.QPushButton(strings._('gui_add_files'))
self.add_files_button.clicked.connect(self.add_files)
self.add_dir_button = QtGui.QPushButton(strings._('gui_add_folder'))
self.add_dir_button.clicked.connect(self.add_dir)
self.delete_button = QtGui.QPushButton(strings._('gui_delete'))
self.delete_button.clicked.connect(self.delete_file)
button_layout = QtGui.QHBoxLayout()
button_layout.addWidget(self.add_files_button)
button_layout.addWidget(self.add_dir_button)
button_layout.addWidget(self.delete_button)
# add the widgets
self.addWidget(self.file_list)
self.addLayout(button_layout)
self.update()
def update(self):
# delete button should be disabled if item isn't selected
current_item = self.file_list.currentItem()
if not current_item:
self.delete_button.setEnabled(False)
else:
self.delete_button.setEnabled(True)
# update the file list
self.file_list.update()
def add_files(self):
filenames = QtGui.QFileDialog.getOpenFileNames(caption=strings._('gui_choose_files'), options=QtGui.QFileDialog.ReadOnly)
if filenames:
for filename in filenames:
self.file_list.add_file(str(filename))
self.update()
def add_dir(self):
filename = QtGui.QFileDialog.getExistingDirectory(caption=strings._('gui_choose_folder'), options=QtGui.QFileDialog.ReadOnly)
if filename:
self.file_list.add_file(str(filename))
self.update()
def delete_file(self):
current_row = self.file_list.currentRow()
self.file_list.filenames.pop(current_row)
self.file_list.takeItem(current_row)
self.update()

View File

@ -2,20 +2,17 @@ from __future__ import division
import os, sys, subprocess, inspect, platform, argparse, threading, time, math, inspect, platform
from PyQt4 import QtCore, QtGui
def get_onionshare_gui_dir():
if platform.system() == 'Darwin':
onionshare_gui_dir = os.path.dirname(__file__)
else:
onionshare_gui_dir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
return onionshare_gui_dir
import common
try:
import onionshare
except ImportError:
sys.path.append(os.path.abspath(__file__+"/.."))
sys.path.append(os.path.abspath(common.onionshare_gui_dir+"/.."))
import onionshare
from onionshare import strings, helpers, web
from file_selection import FileSelection
class Application(QtGui.QApplication):
def __init__(self):
platform = helpers.get_platform()
@ -24,10 +21,28 @@ class Application(QtGui.QApplication):
QtGui.QApplication.__init__(self, sys.argv)
class OnionShareGui(QtGui.QWidget):
def __init__(self, app, filename, basename):
def __init__(self, app, filenames=None):
super(OnionShareGui, self).__init__()
self.app = app
self.filenames = filenames
self.setWindowTitle('OnionShare')
self.setWindowIcon(window_icon)
def start_send(self):
# file selection
file_selection = FileSelection()
if self.filenames:
for filename in self.filenames:
file_selection.file_list.add_file(filename)
# main layout
self.layout = QtGui.QVBoxLayout()
self.layout.addLayout(file_selection)
self.setLayout(self.layout)
self.show()
"""
# initialize ui
self.init_ui(filename, basename)
# check for requests every 1000ms
@ -64,7 +79,7 @@ class OnionShareGui(QtGui.QWidget):
# logo
self.logoLabel = QtGui.QLabel(self.widget)
self.logo = QtGui.QPixmap("{0}/static/logo.png".format(get_onionshare_gui_dir()))
self.logo = QtGui.QPixmap("{0}/static/logo.png".format(common.onionshare_gui_dir))
self.logoLabel.setPixmap(self.logo)
self.header.addWidget(self.logoLabel)
@ -268,6 +283,7 @@ class OnionShareGui(QtGui.QWidget):
else:
web.set_stay_open(True)
return
"""
def alert(msg, icon=QtGui.QMessageBox.NoIcon):
dialog = QtGui.QMessageBox()
@ -277,24 +293,6 @@ def alert(msg, icon=QtGui.QMessageBox.NoIcon):
dialog.setIcon(icon)
dialog.exec_()
def select_file(filename=None):
# get filename, either from argument or file chooser dialog
if not filename:
filename = QtGui.QFileDialog.getOpenFileName(caption=strings._('choose_file'), options=QtGui.QFileDialog.ReadOnly)
if not filename:
return False, False
filename = str(unicode(filename).encode("utf-8"))
# validate filename
if not os.path.isfile(filename):
alert(strings._("not_a_file").format(filename), QtGui.QMessageBox.Warning)
return False, False
filename = os.path.abspath(filename)
basename = os.path.basename(filename)
return filename, basename
def main():
strings.load_strings()
@ -307,23 +305,37 @@ def main():
parser.add_argument('--local-only', action='store_true', dest='local_only', help=strings._("help_local_only"))
parser.add_argument('--stay-open', action='store_true', dest='stay_open', help=strings._("help_stay_open"))
parser.add_argument('--debug', action='store_true', dest='debug', help=strings._("help_debug"))
parser.add_argument('filename', nargs='?', help=strings._("help_filename"))
parser.add_argument('--filenames', metavar='filenames', nargs='+', help=strings._('help_filename'))
args = parser.parse_args()
filename = args.filename
filenames = args.filenames
if filenames:
for i in range(len(filenames)):
filenames[i] = os.path.abspath(filenames[i])
local_only = bool(args.local_only)
stay_open = bool(args.stay_open)
debug = bool(args.debug)
web.set_stay_open(stay_open)
# validation
if filenames:
valid = True
for filename in filenames:
if not os.path.exists(filename):
alert(strings._("not_a_file").format(filename))
valid = False
if not valid:
sys.exit()
# create the onionshare icon
global window_icon
window_icon = QtGui.QIcon("{0}/static/logo.png".format(get_onionshare_gui_dir()))
window_icon = QtGui.QIcon("{0}/static/logo.png".format(common.onionshare_gui_dir))
# start the onionshare app
try:
web.set_stay_open(stay_open)
app = onionshare.OnionShare(debug, local_only, stay_open)
"""try:
app.start_hidden_service(gui=True)
except onionshare.NoTor as e:
alert(e.args[0], QtGui.QMessageBox.Warning)
@ -331,11 +343,7 @@ def main():
except onionshare.TailsError as e:
alert(e.args[0], QtGui.QMessageBox.Warning)
sys.exit()
# select file to share
filename, basename = select_file(filename)
if not filename:
return
"""
# clean up when app quits
def shutdown():
@ -343,7 +351,8 @@ def main():
qtapp.connect(qtapp, QtCore.SIGNAL("aboutToQuit()"), shutdown)
# launch the gui
gui = OnionShareGui(app, filename, basename)
gui = OnionShareGui(app, filenames)
gui.start_send()
# all done
sys.exit(qtapp.exec_())

View File

@ -9,6 +9,7 @@ a.datas += [
('onionshare/index.html', 'onionshare/index.html', 'DATA'),
('onionshare/404.html', 'onionshare/404.html', 'DATA'),
('onionshare_gui/logo.png', 'onionshare_gui/logo.png', 'DATA'),
('onionshare_gui/drop_files.png', 'onionshare_gui/drop_files.png', 'DATA'),
]
pyz = PYZ(a.pure)
exe = EXE(pyz,

View File

@ -59,6 +59,7 @@ Section "install"
File "${BINPATH}\onionshare_gui\__init__.py"
File "${BINPATH}\onionshare_gui\__init__.pyc"
File "${BINPATH}\onionshare_gui\logo.png"
File "${BINPATH}\onionshare_gui\drop_files.png"
# dependencies
SetOutPath $INSTDIR
@ -162,6 +163,7 @@ Section "uninstall"
Delete "$INSTDIR\onionshare_gui\__init__.py"
Delete "$INSTDIR\onionshare_gui\__init__.pyc"
Delete "$INSTDIR\onionshare_gui\logo.png"
Delete "$INSTDIR\onionshare_gui\drop_files.png"
Delete "$INSTDIR\onionshare_gui\onionshare_gui.py"
Delete "$INSTDIR\onionshare_gui\onionshare_gui.pyc"
Delete "$INSTDIR\qt4_plugins\accessible\qtaccessiblewidgets4.dll"