Skip to content

Commit

Permalink
moar wip?
Browse files Browse the repository at this point in the history
  • Loading branch information
heartsucker committed May 21, 2019
1 parent 6c28cbf commit 4d87371
Show file tree
Hide file tree
Showing 6 changed files with 97 additions and 87 deletions.
7 changes: 4 additions & 3 deletions securedrop_client/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
import sys
import socket
from argparse import ArgumentParser
from sqlalchemy.orm import sessionmaker
from sqlalchemy.orm import sessionmaker, scoped_session
from PyQt5.QtWidgets import QApplication, QMessageBox
from PyQt5.QtCore import Qt, QTimer
from logging.handlers import TimedRotatingFileHandler
Expand Down Expand Up @@ -187,13 +187,14 @@ def start_app(args, qt_args) -> None:

engine = make_engine(args.sdc_home)
session_maker = sessionmaker(bind=engine)
scoped_session_maker = scoped_session(session_maker)

gui = Window(session_maker())
gui = Window(scoped_session_maker)

app.setWindowIcon(load_icon(gui.icon))
app.setStyleSheet(load_css('sdclient.css'))

controller = Controller("http://localhost:8081/", gui, session_maker,
controller = Controller("http://localhost:8081/", gui, scoped_session_maker,
args.sdc_home, not args.no_proxy)
controller.setup()

Expand Down
7 changes: 4 additions & 3 deletions securedrop_client/gui/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,12 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
import logging

from gettext import gettext as _
from typing import Dict, List, Optional # noqa: F401

from PyQt5.QtWidgets import QMainWindow, QWidget, QHBoxLayout, QVBoxLayout, QDesktopWidget, \
QApplication
from sqlalchemy.orm import scoped_session

from securedrop_client import __version__
from securedrop_client.db import Source
Expand All @@ -43,7 +44,7 @@ class Window(QMainWindow):

icon = 'icon.png'

def __init__(self, session):
def __init__(self, session_maker: scoped_session) -> None:
"""
Create the default start state. The window contains a root widget into
which is placed:
Expand All @@ -68,7 +69,7 @@ def __init__(self, session):
layout.setSpacing(0)
self.main_pane.setLayout(layout)
self.left_pane = LeftPane()
self.main_view = MainView(session, self.main_pane)
self.main_view = MainView(session_maker, self.main_pane)
layout.addWidget(self.left_pane, 1)
layout.addWidget(self.main_view, 8)

Expand Down
33 changes: 18 additions & 15 deletions securedrop_client/gui/widgets.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
from PyQt5.QtWidgets import QListWidget, QLabel, QWidget, QListWidgetItem, QHBoxLayout, \
QPushButton, QVBoxLayout, QLineEdit, QScrollArea, QDialog, QAction, QMenu, QMessageBox, \
QToolButton, QSizePolicy, QTextEdit, QStatusBar, QGraphicsDropShadowEffect
from sqlalchemy.orm.session import Session
from sqlalchemy.orm import scoped_session

from securedrop_client.db import Source, Message, File, Reply
from securedrop_client.storage import source_exists
Expand Down Expand Up @@ -588,9 +588,9 @@ class MainView(QWidget):
}
'''

def __init__(self, session: Session, parent: QObject):
def __init__(self, session_maker: scoped_session, parent: QObject):
super().__init__(parent)
self.session = session
self.session_maker = session_maker

self.setStyleSheet(self.CSS)

Expand Down Expand Up @@ -634,7 +634,7 @@ def on_source_changed(self):

if source:
conversation_wrapper = SourceConversationWrapper(
self.session,
self.session_maker,
source,
self.controller,
)
Expand Down Expand Up @@ -1282,7 +1282,7 @@ class FileWidget(QWidget):

def __init__(
self,
session: Session,
session_maker: scoped_session,
file_uuid: str,
controller: Controller,
file_ready_signal: pyqtBoundSignal,
Expand All @@ -1296,10 +1296,11 @@ def __init__(
accept files from sources to journalists.
"""
super().__init__()
self.session = session
self.session_maker = session_maker
self.controller = controller
self.file_uuid = file_uuid
self.align = align
self.file_is_downloaded = False # default to `False`, value updated in `update()`

self.layout = QHBoxLayout()
self.update()
Expand All @@ -1311,9 +1312,11 @@ def update(self):
icon = QLabel()
icon.setPixmap(load_image('file.png'))

file_ = self.session.query(File).filter_by(uuid=self.file_uuid).one()
session = self.session_maker()
file_ = session.query(File).filter_by(uuid=self.file_uuid).one()
self.file_is_downloaded = file_.is_downloaded

if file_.is_downloaded:
if self.file_is_downloaded:
description = QLabel("Open")
else:
human_filesize = humanize_filesize(file_.size)
Expand Down Expand Up @@ -1349,10 +1352,10 @@ def mouseReleaseEvent(self, e):
"""
if self.file_is_downloaded:
# Open the already downloaded file.
self.controller.on_file_open(self.submission_uuid)
self.controller.on_file_open(self.file_uuid)
else:
# Download the file.
self.controller.on_submission_download(self.submission_uuid)
self.controller.on_submission_download(File, self.file_uuid)


class ConversationView(QWidget):
Expand All @@ -1366,12 +1369,12 @@ class ConversationView(QWidget):

def __init__(
self,
session: Session,
session_maker: scoped_session,
source_db_object: Source,
controller: Controller,
):
super().__init__()
self.session = session
self.session_maker = session_maker
self.source = source_db_object
self.controller = controller

Expand Down Expand Up @@ -1423,7 +1426,7 @@ def add_file(self, source_db_object, submission_db_object):
"""
self.conversation_layout.addWidget(
FileWidget(
self.session,
self.session_maker,
submission_db_object.uuid,
self.controller,
self.controller.file_ready,
Expand Down Expand Up @@ -1498,7 +1501,7 @@ class SourceConversationWrapper(QWidget):

def __init__(
self,
session: Session,
session_maker: scoped_session,
source: Source,
controller: Controller,
) -> None:
Expand All @@ -1508,7 +1511,7 @@ def __init__(
self.setLayout(layout)

self.conversation_title_bar = SourceProfileShortWidget(source, controller)
self.conversation_view = ConversationView(session, source, controller)
self.conversation_view = ConversationView(session_maker, source, controller)
self.reply_box = ReplyBoxWidget(source, controller)

layout.addWidget(self.conversation_title_bar, 1)
Expand Down
38 changes: 17 additions & 21 deletions securedrop_client/logic.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
from PyQt5.QtCore import QObject, QThread, pyqtSignal, QTimer, QProcess, Qt
from sdclientapi import RequestTimeoutError
from sqlalchemy.orm.session import sessionmaker
from typing import Dict, Tuple, Union, Any # noqa: F401
from typing import Dict, Tuple, Union, Any, Type # noqa: F401

from securedrop_client import storage
from securedrop_client import db
Expand Down Expand Up @@ -146,31 +146,31 @@ def __init__(self, hostname: str, gui, session_maker: sessionmaker,
# Reference to the API for secure drop proxy.
self.api = None # type: sdclientapi.API

# Reference to the SqlAlchemy `sessionmaker` and `session`
self.session_maker = session_maker
self.session = session_maker()

# Queue that handles running API job
self.api_job_queue = ApiJobQueue(self.api)
self.api_job_queue = ApiJobQueue(self.api, self.session_maker)

# Contains active threads calling the API.
self.api_threads = {} # type: Dict[str, Dict]

# Reference to the SqlAlchemy `sessionmaker` and `session`
self.session_maker = session_maker
self.session = session_maker()
self.gpg = GpgHelper(home, proxy)

# thread responsible for fetching messages
self.message_thread = None
self.message_sync = MessageSync(self.api, self.home, self.proxy)
self.message_sync = MessageSync(self.api, self.gpg, self.session_maker)

# thread responsible for fetching replies
self.reply_thread = None
self.reply_sync = ReplySync(self.api, self.home, self.proxy)
self.reply_sync = ReplySync(self.api, self.gpg, self.session_maker)

self.sync_flag = os.path.join(home, 'sync_flag')

# File data.
self.data_dir = os.path.join(self.home, 'data')

self.gpg = GpgHelper(home, proxy)

@property
def is_authenticated(self) -> bool:
return self.__is_authenticated
Expand Down Expand Up @@ -540,36 +540,32 @@ def on_reply_download(self, source_db_object: db.Source, reply: db.Reply) -> Non

def on_submission_download(
self,
source_db_object: db.Source,
submission: Union[db.File, db.Message],
submission_type: Union[Type[db.File], Type[db.Message]],
submission_uuid: str,
) -> None:
"""
Download the file associated with the Submission (which may be a File or Message).
"""
if not self.api: # Then we should tell the user they need to login.
self.on_action_requiring_login()
return

job = DownloadSubmissionJob(
type(submission),
submission.uuid,
submission_type,
submission_uuid,
self.data_dir,
self.gpg,
self.session_maker,
)
job.success_signal.connect(self.on_file_download_success, type=Qt.QueuedConnection)
job.failure_signal.connect(self.on_file_download_failure, type=Qt.QueuedConnection)

self.api_job_queue.enqueue(job)
self.set_status(_('Downloading {}'.format(submission.filename)))
self.set_status(_('Downloading file'))

def on_file_download_success(self, result: Any):
def on_file_download_success(self, result: Any) -> None:
"""
Called when a file has downloaded.
"""
print(type(result), result)
self.file_ready.emit(result)

def on_file_download_failure(self, exception: Exception):
def on_file_download_failure(self, exception: Exception) -> None:
"""
Called when a file fails to download.
"""
Expand Down
Loading

0 comments on commit 4d87371

Please sign in to comment.