[Pkg-anonymity-tools] [onionshare] 34/140: beginning to refactor onionshare_gui to work with multiple files (#66)
Ulrike Uhlig
u-guest at moszumanska.debian.org
Mon Sep 29 20:33:45 UTC 2014
This is an automated email from the git hooks/post-receive script.
u-guest pushed a commit to branch master
in repository onionshare.
commit 78f6c310617e1ee936918484977d6766141e6e8f
Author: Micah Lee <micah at micahflee.com>
Date: Wed Aug 27 14:21:08 2014 -0700
beginning to refactor onionshare_gui to work with multiple files (#66)
---
MANIFEST.in | 1 +
onionshare/strings.json | 8 ++-
onionshare_gui/common.py | 10 +++
onionshare_gui/drop_files.png | Bin 0 -> 2035 bytes
onionshare_gui/file_selection.py | 145 +++++++++++++++++++++++++++++++++++++++
onionshare_gui/onionshare_gui.py | 87 ++++++++++++-----------
setup/onionshare-osx.spec | 1 +
setup/onionshare.nsi | 2 +
8 files changed, 214 insertions(+), 40 deletions(-)
diff --git a/MANIFEST.in b/MANIFEST.in
index 8af755d..d054d40 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -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
diff --git a/onionshare/strings.json b/onionshare/strings.json
index 312e86b..8207fc4 100644
--- a/onionshare/strings.json
+++ b/onionshare/strings.json
@@ -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}.",
diff --git a/onionshare_gui/common.py b/onionshare_gui/common.py
new file mode 100644
index 0000000..4394a26
--- /dev/null
+++ b/onionshare_gui/common.py
@@ -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()
diff --git a/onionshare_gui/drop_files.png b/onionshare_gui/drop_files.png
new file mode 100644
index 0000000..1e2ea7d
Binary files /dev/null and b/onionshare_gui/drop_files.png differ
diff --git a/onionshare_gui/file_selection.py b/onionshare_gui/file_selection.py
new file mode 100644
index 0000000..ea8e882
--- /dev/null
+++ b/onionshare_gui/file_selection.py
@@ -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()
+
diff --git a/onionshare_gui/onionshare_gui.py b/onionshare_gui/onionshare_gui.py
index 35780c5..84d0262 100644
--- a/onionshare_gui/onionshare_gui.py
+++ b/onionshare_gui/onionshare_gui.py
@@ -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:
- app = onionshare.OnionShare(debug, local_only, stay_open)
+ 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_())
diff --git a/setup/onionshare-osx.spec b/setup/onionshare-osx.spec
index d0ee763..8ba11b7 100644
--- a/setup/onionshare-osx.spec
+++ b/setup/onionshare-osx.spec
@@ -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,
diff --git a/setup/onionshare.nsi b/setup/onionshare.nsi
index 842ac80..ceab6a4 100644
--- a/setup/onionshare.nsi
+++ b/setup/onionshare.nsi
@@ -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"
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/collab-maint/onionshare.git
More information about the Pkg-anonymity-tools
mailing list