mirror of
https://github.com/onionshare/onionshare.git
synced 2025-01-24 13:41:14 -05:00
beginning to refactor onionshare_gui to work with multiple files (#66)
This commit is contained in:
parent
3f59fe7af0
commit
78f6c31061
@ -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
|
||||
|
@ -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
10
onionshare_gui/common.py
Normal 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()
|
BIN
onionshare_gui/drop_files.png
Normal file
BIN
onionshare_gui/drop_files.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.0 KiB |
145
onionshare_gui/file_selection.py
Normal file
145
onionshare_gui/file_selection.py
Normal 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()
|
||||
|
@ -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_())
|
||||
|
@ -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,
|
||||
|
@ -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"
|
||||
|
Loading…
Reference in New Issue
Block a user