def update_folder_icon(self, folder_name, folder_path, overlay_file=None): items = self.findItems(folder_name) if items: folder_icon = QFileIconProvider().icon(QFileInfo(folder_path)) folder_pixmap = folder_icon.pixmap(256, 256) if overlay_file: pixmap = CompositePixmap(folder_pixmap, resource(overlay_file)) else: pixmap = CompositePixmap(folder_pixmap) items[0].setIcon(QIcon(pixmap))
def dragFile(widget, filename, icon=None, dropactions=Qt.CopyAction): """Starts dragging the given local file from the widget.""" if icon is None or icon.isNull(): icon = QFileIconProvider().icon(QFileInfo(filename)) drag = QDrag(widget) data = QMimeData() data.setUrls([QUrl.fromLocalFile(filename)]) drag.setMimeData(data) drag.setPixmap(icon.pixmap(32)) drag.exec_(dropactions)
def get_external_file_icon(): if gui_constants._REFRESH_EXTERNAL_VIEWER: if os.path.exists(gui_constants.GALLERY_EXT_ICO_PATH): os.remove(gui_constants.GALLERY_EXT_ICO_PATH) info = QFileInfo(gui_constants.EXTERNAL_VIEWER_PATH) icon = QFileIconProvider().icon(info) pixmap = icon.pixmap(QSize(32, 32)) pixmap.save(gui_constants.GALLERY_EXT_ICO_PATH, quality=100) gui_constants._REFRESH_EXTERNAL_VIEWER = False return QIcon(gui_constants.GALLERY_EXT_ICO_PATH)
def refresh_default_icon(): if os.path.exists(gui_constants.GALLERY_DEF_ICO_PATH): os.remove(gui_constants.GALLERY_DEF_ICO_PATH) def get_file(n): gallery = gallerydb.GalleryDB.get_gallery_by_id(n) if not gallery: return False file = "" if gallery.path.endswith(tuple(ARCHIVE_FILES)): zip = ArchiveFile(gallery.path) for name in zip.namelist(): if name.endswith(tuple(IMG_FILES)): folder = os.path.join( gui_constants.temp_dir, '{}{}'.format(name, n)) zip.extract(name, folder) file = os.path.join( folder, name) break; else: for name in os.listdir(gallery.chapters[0]): if name.endswith(tuple(IMG_FILES)): file = os.path.join( gallery.chapters[0], name) break; return file # TODO: fix this! (When there are no ids below 300? (because they go deleted)) for x in range(1, 300): try: file = get_file(x) break except FileNotFoundError: continue except CreateZipFail: continue if not file: return None icon = QFileIconProvider().icon(QFileInfo(file)) pixmap = icon.pixmap(QSize(32, 32)) pixmap.save(gui_constants.GALLERY_DEF_ICO_PATH, quality=100) return True
def __init__(self, gateways): super(InviteReceiver, self).__init__() self.gateways = gateways self.wormhole = None self.setup_runner = None self.joined_folders = [] self.use_tor = False self.setMinimumSize(500, 300) self.mail_closed_icon = QLabel() self.mail_closed_icon.setPixmap( QPixmap(resource('mail-envelope-closed.png')).scaled(128, 128)) self.mail_closed_icon.setAlignment(Qt.AlignCenter) self.mail_open_icon = QLabel() self.mail_open_icon.setPixmap( QPixmap(resource('mail-envelope-open.png')).scaled(128, 128)) self.mail_open_icon.setAlignment(Qt.AlignCenter) self.folder_icon = QLabel() icon = QFileIconProvider().icon(QFileInfo(config_dir)) self.folder_icon.setPixmap(icon.pixmap(128, 128)) self.folder_icon.setAlignment(Qt.AlignCenter) self.invite_code_widget = InviteCodeWidget(self) self.label = self.invite_code_widget.label self.tor_checkbox = self.invite_code_widget.checkbox self.tor_checkbox.stateChanged.connect(self.on_checkbox_state_changed) self.lineedit = self.invite_code_widget.lineedit self.lineedit.error.connect(self.show_error) self.lineedit.go.connect(self.go) self.tor_label = QLabel() self.tor_label.setToolTip( "This connection is being routed through the Tor network.") self.tor_label.setPixmap( QPixmap(resource('tor-onion.png')).scaled(32, 32)) self.progressbar = QProgressBar(self) self.progressbar.setValue(0) self.progressbar.setMaximum(6) # XXX self.progressbar.setTextVisible(False) self.message_label = QLabel() self.message_label.setStyleSheet("color: grey") self.message_label.setAlignment(Qt.AlignCenter) self.error_label = QLabel() self.error_label.setStyleSheet("color: red") self.error_label.setAlignment(Qt.AlignCenter) self.close_button = QPushButton("Close") self.close_button.clicked.connect(self.close) layout = QGridLayout(self) layout.addItem(QSpacerItem(0, 0, 0, QSizePolicy.Expanding), 0, 0) layout.addItem(QSpacerItem(0, 0, QSizePolicy.Expanding, 0), 1, 1) layout.addItem(QSpacerItem(0, 0, QSizePolicy.Expanding, 0), 1, 2) layout.addWidget(self.mail_closed_icon, 1, 2, 1, 3) layout.addWidget(self.mail_open_icon, 1, 2, 1, 3) layout.addWidget(self.folder_icon, 1, 2, 1, 3) layout.addItem(QSpacerItem(0, 0, QSizePolicy.Expanding, 0), 1, 4) layout.addItem(QSpacerItem(0, 0, QSizePolicy.Expanding, 0), 1, 5) layout.addWidget(self.label, 2, 3, 1, 1) layout.addWidget(self.tor_label, 3, 1, 1, 1, Qt.AlignRight | Qt.AlignVCenter) layout.addWidget(self.lineedit, 3, 2, 1, 3) layout.addWidget(self.progressbar, 3, 2, 1, 3) layout.addWidget(self.tor_checkbox, 4, 2, 1, 3, Qt.AlignCenter) layout.addWidget(self.message_label, 5, 1, 1, 5) layout.addWidget(self.error_label, 5, 2, 1, 3) layout.addWidget(self.close_button, 6, 3) layout.addItem(QSpacerItem(0, 0, 0, QSizePolicy.Expanding), 7, 1) self.reset()
def __init__(self, gateway, gui, folder_names=None): # noqa: max-complexity=11 XXX super(ShareWidget, self).__init__() self.gateway = gateway self.gui = gui self.folder_names = folder_names self.folder_names_humanized = humanized_list(folder_names, 'folders') self.settings = {} self.wormhole = None self.pending_invites = [] self.use_tor = self.gateway.use_tor # XXX Temporary(?) workaround for font-scaling inconsistencies observed # during user-testing (wherein fonts on Windows on one laptop were # rendering especially large for some reason but were fine elsewhere) if sys.platform == 'win32': self.setMinimumSize(600, 400) else: self.setMinimumSize(500, 300) header_icon = QLabel(self) if self.folder_names: icon = QFileIconProvider().icon( QFileInfo( self.gateway.get_magic_folder_directory( self.folder_names[0]))) else: icon = QIcon(os.path.join(gateway.nodedir, 'icon')) if not icon.availableSizes(): icon = QIcon(resource('tahoe-lafs.png')) header_icon.setPixmap(icon.pixmap(50, 50)) header_text = QLabel(self) if self.folder_names: header_text.setText(self.folder_names_humanized) else: header_text.setText(self.gateway.name) font = QFont() if sys.platform == 'darwin': font.setPointSize(22) else: font.setPointSize(18) header_text.setFont(font) header_text.setAlignment(Qt.AlignCenter) header_layout = QGridLayout() header_layout.addItem(QSpacerItem(0, 0, QSizePolicy.Expanding, 0), 1, 1) header_layout.addWidget(header_icon, 1, 2) header_layout.addWidget(header_text, 1, 3) header_layout.addItem(QSpacerItem(0, 0, QSizePolicy.Expanding, 0), 1, 4) self.subtext_label = QLabel(self) font = QFont() if sys.platform == 'darwin': font.setPointSize(13) else: font.setPointSize(10) self.subtext_label.setFont(font) self.subtext_label.setStyleSheet("color: grey") self.subtext_label.setWordWrap(True) self.subtext_label.setAlignment(Qt.AlignCenter) self.noise_label = QLabel() font = QFont() if sys.platform == 'darwin': font.setPointSize(20) else: font.setPointSize(16) font.setFamily("Courier") font.setStyleHint(QFont.Monospace) self.noise_label.setFont(font) self.noise_label.setStyleSheet("color: grey") self.noise_timer = QTimer() self.noise_timer.timeout.connect( lambda: self.noise_label.setText(b58encode(os.urandom(16)))) self.noise_timer.start(75) self.code_label = QLabel() font = QFont() if sys.platform == 'darwin': font.setPointSize(22) else: font.setPointSize(18) self.code_label.setFont(font) self.code_label.setTextInteractionFlags(Qt.TextSelectableByMouse) self.code_label.hide() self.box_title = QLabel(self) self.box_title.setAlignment(Qt.AlignCenter) font = QFont() if sys.platform == 'darwin': font.setPointSize(20) else: font.setPointSize(16) self.box_title.setFont(font) self.box = QGroupBox() self.box.setAlignment(Qt.AlignCenter) self.box.setStyleSheet('QGroupBox {font-size: 16px}') self.copy_button = QToolButton() self.copy_button.setIcon(QIcon(resource('copy.png'))) self.copy_button.setToolTip("Copy to clipboard") self.copy_button.setStyleSheet('border: 0px; padding: 0px;') self.copy_button.hide() box_layout = QGridLayout(self.box) box_layout.addItem(QSpacerItem(0, 0, QSizePolicy.Expanding, 0), 1, 1) box_layout.addWidget(self.noise_label, 1, 2) box_layout.addWidget(self.code_label, 1, 3) box_layout.addWidget(self.copy_button, 1, 4) box_layout.addItem(QSpacerItem(0, 0, QSizePolicy.Expanding, 0), 1, 5) self.close_button = QPushButton("Close and cancel invite") self.close_button.setAutoDefault(False) self.checkmark = QLabel() self.checkmark.setPixmap( QPixmap(resource('green_checkmark.png')).scaled(32, 32)) self.checkmark.setAlignment(Qt.AlignCenter) self.checkmark.hide() self.tor_label = QLabel() self.tor_label.setToolTip( "This connection is being routed through the Tor network.") self.tor_label.setPixmap( QPixmap(resource('tor-onion.png')).scaled(32, 32)) self.tor_label.hide() self.progress_bar = QProgressBar() self.progress_bar.setMaximum(2) self.progress_bar.setTextVisible(False) self.progress_bar.hide() layout = QGridLayout(self) layout.addItem(QSpacerItem(0, 0, 0, QSizePolicy.Expanding), 0, 0) layout.addItem(QSpacerItem(0, 0, QSizePolicy.Expanding, 0), 1, 1) layout.addItem(QSpacerItem(0, 0, QSizePolicy.Expanding, 0), 1, 2) layout.addItem(QSpacerItem(0, 0, QSizePolicy.Expanding, 0), 1, 3) layout.addItem(QSpacerItem(0, 0, QSizePolicy.Expanding, 0), 1, 4) layout.addItem(QSpacerItem(0, 0, QSizePolicy.Expanding, 0), 1, 5) layout.addLayout(header_layout, 1, 3) layout.addItem(QSpacerItem(0, 0, 0, QSizePolicy.Expanding), 2, 1) layout.addWidget(self.box_title, 3, 2, 1, 3) layout.addWidget(self.checkmark, 3, 3) layout.addWidget(self.tor_label, 4, 1, 1, 1, Qt.AlignRight | Qt.AlignVCenter) layout.addWidget(self.box, 4, 2, 1, 3) layout.addWidget(self.progress_bar, 4, 2, 1, 3) layout.addWidget(self.subtext_label, 5, 2, 1, 3) layout.addItem(QSpacerItem(0, 0, 0, QSizePolicy.Expanding), 6, 1) layout.addWidget(self.close_button, 7, 3) layout.addItem(QSpacerItem(0, 0, 0, QSizePolicy.Expanding), 8, 1) self.copy_button.clicked.connect(self.on_copy_button_clicked) self.close_button.clicked.connect(self.close) self.set_box_title("Generating invite code...") if self.use_tor: self.tor_label.show() self.progress_bar.setStyleSheet( 'QProgressBar::chunk {{ background-color: {}; }}'.format( TOR_PURPLE)) self.go() # XXX
class Model(QStandardItemModel): def __init__(self, view): super(Model, self).__init__(0, 4) self.view = view self.gui = self.view.gui self.gateway = self.view.gateway self.monitor = Monitor(self.gateway) self.status_dict = {} self.grid_status = '' self.available_space = 0 self.setHeaderData(0, Qt.Horizontal, "Name") self.setHeaderData(1, Qt.Horizontal, "Status") self.setHeaderData(2, Qt.Horizontal, "Last modified") self.setHeaderData(3, Qt.Horizontal, "Size") #self.setHeaderData(4, Qt.Horizontal, "Action") self.icon_blank = QIcon() self.icon_up_to_date = QIcon(resource('checkmark.png')) self.icon_user = QIcon(resource('user.png')) self.icon_folder = QFileIconProvider().icon(QFileInfo(config_dir)) composite_pixmap = CompositePixmap(self.icon_folder.pixmap(256, 256), overlay=None, grayout=True) self.icon_folder_gray = QIcon(composite_pixmap) self.monitor.connected.connect(self.on_connected) self.monitor.disconnected.connect(self.on_disconnected) self.monitor.nodes_updated.connect(self.on_nodes_updated) self.monitor.space_updated.connect(self.on_space_updated) self.monitor.data_updated.connect(self.set_data) self.monitor.status_updated.connect(self.set_status) self.monitor.mtime_updated.connect(self.set_mtime) self.monitor.size_updated.connect(self.set_size) #self.monitor.member_added.connect(self.add_member) # XXX self.monitor.first_sync_started.connect(self.on_first_sync) self.monitor.sync_started.connect(self.on_sync_started) self.monitor.sync_finished.connect(self.on_sync_finished) self.monitor.files_updated.connect(self.on_updated_files) self.monitor.check_finished.connect(self.update_natural_times) self.monitor.remote_folder_added.connect(self.add_remote_folder) def on_space_updated(self, size): self.available_space = size @pyqtSlot(int, int) def on_nodes_updated(self, num_connected, num_happy): if num_connected < num_happy: self.grid_status = "Connecting ({}/{} nodes)...".format( num_connected, num_happy) elif num_connected >= num_happy: obj = ('node' if num_connected == 1 else 'nodes') self.grid_status = "Connected to {} {}; {} available".format( num_connected, obj, naturalsize(self.available_space)) self.gui.main_window.set_current_grid_status() # TODO: Use pyqtSignal? @pyqtSlot(str) def on_connected(self, grid_name): if get_preference('notifications', 'connection') != 'false': self.gui.show_message(grid_name, "Connected to {}".format(grid_name)) @pyqtSlot(str) def on_disconnected(self, grid_name): if get_preference('notifications', 'connection') != 'false': self.gui.show_message(grid_name, "Disconnected from {}".format(grid_name)) @pyqtSlot(str, list) def on_updated_files(self, folder_name, files_list): if get_preference('notifications', 'folder') != 'false': self.gui.show_message(folder_name + " updated and encrypted", "Updated " + humanized_list(files_list)) def data(self, index, role): value = super(Model, self).data(index, role) if role == Qt.SizeHintRole: return QSize(0, 30) return value def add_folder(self, path, name_data=None, status_data=0): basename = os.path.basename(os.path.normpath(path)) if self.findItems(basename): logging.warning("Tried to add a folder (%s) that already exists", basename) return composite_pixmap = CompositePixmap(self.icon_folder.pixmap(256, 256)) name = QStandardItem(QIcon(composite_pixmap), basename) name.setData(name_data, Qt.UserRole) name.setToolTip(path) status = QStandardItem() mtime = QStandardItem() size = QStandardItem() self.appendRow([name, status, mtime, size]) self.view.hide_drop_label() self.set_status(basename, status_data) @pyqtSlot(str, str) def add_member(self, folder, member): items = self.findItems(folder) if items: items[0].appendRow([QStandardItem(self.icon_user, member)]) def populate(self): for magic_folder in list(self.gateway.load_magic_folders().values()): self.add_folder(magic_folder['directory']) self.monitor.start() def update_folder_icon(self, folder_name, folder_path, overlay_file=None): items = self.findItems(folder_name) if items: folder_icon = QFileIconProvider().icon(QFileInfo(folder_path)) folder_pixmap = folder_icon.pixmap(256, 256) if overlay_file: pixmap = CompositePixmap(folder_pixmap, resource(overlay_file)) else: pixmap = CompositePixmap(folder_pixmap) items[0].setIcon(QIcon(pixmap)) @pyqtSlot(str, object) def set_data(self, folder_name, data): items = self.findItems(folder_name) if items: items[0].setData(data, Qt.UserRole) @pyqtSlot(str, int) def set_status(self, name, status): items = self.findItems(name) if not items: return item = self.item(items[0].row(), 1) if not status: item.setIcon(self.icon_blank) item.setText("Initializing...") elif status == 1: item.setIcon(self.icon_blank) item.setText("Syncing") elif status == 2: item.setIcon(self.icon_up_to_date) item.setText("Up to date") item.setData(status, Qt.UserRole) self.status_dict[name] = status def fade_row(self, folder_name, overlay_file=None): folder_item = self.findItems(folder_name)[0] if overlay_file: folder_pixmap = self.icon_folder_gray.pixmap(256, 256) pixmap = CompositePixmap(folder_pixmap, resource(overlay_file)) folder_item.setIcon(QIcon(pixmap)) else: folder_item.setIcon(self.icon_folder_gray) row = folder_item.row() for i in range(4): item = self.item(row, i) font = item.font() font.setItalic(True) item.setFont(font) item.setForeground(QColor('gray')) def unfade_row(self, folder_name): default_foreground = QStandardItem().foreground() folder_item = self.findItems(folder_name)[0] row = folder_item.row() for i in range(4): item = self.item(row, i) font = item.font() font.setItalic(False) item.setFont(font) item.setForeground(default_foreground) @pyqtSlot(str) def on_first_sync(self, folder_name): self.unfade_row(folder_name) self.update_folder_icon( folder_name, self.gateway.get_magic_folder_directory(folder_name)) @pyqtSlot(str) def on_sync_started(self, folder_name): self.gui.core.operations.append((self.gateway, folder_name)) self.gui.systray.update() @pyqtSlot(str) def on_sync_finished(self, folder_name): self.gui.core.operations.remove((self.gateway, folder_name)) self.update_folder_icon( folder_name, self.gateway.get_magic_folder_directory(folder_name), 'lock-closed-green.svg') @pyqtSlot(str, int) def set_mtime(self, name, mtime): item = self.item(self.findItems(name)[0].row(), 2) item.setData(mtime, Qt.UserRole) item.setText( naturaltime(datetime.now() - datetime.fromtimestamp(mtime))) item.setToolTip("Last modified: {}".format(time.ctime(mtime))) @pyqtSlot(str, int) def set_size(self, name, size): item = self.item(self.findItems(name)[0].row(), 3) item.setText(naturalsize(size)) item.setData(size, Qt.UserRole) @pyqtSlot() def update_natural_times(self): for i in range(self.rowCount()): item = self.item(i, 2) data = item.data(Qt.UserRole) if data: item.setText( naturaltime(datetime.now() - datetime.fromtimestamp(data))) @pyqtSlot(str, dict, str) def add_remote_folder(self, folder_name, caps, overlay_file=None): self.add_folder(folder_name, caps, 3) self.fade_row(folder_name, overlay_file)
def __init__(self, gui): super(MainWindow, self).__init__() self.gui = gui self.gateways = [] self.crypter = None self.crypter_thread = None self.export_data = None self.export_dest = None self.setWindowTitle(APP_NAME) self.setMinimumSize(QSize(500, 300)) self.shortcut_new = QShortcut(QKeySequence.New, self) self.shortcut_new.activated.connect(self.gui.show_setup_form) self.shortcut_open = QShortcut(QKeySequence.Open, self) self.shortcut_open.activated.connect(self.select_folder) self.shortcut_close = QShortcut(QKeySequence.Close, self) self.shortcut_close.activated.connect(self.close) self.shortcut_quit = QShortcut(QKeySequence.Quit, self) self.shortcut_quit.activated.connect(self.confirm_quit) self.combo_box = ComboBox() self.combo_box.activated[int].connect(self.on_grid_selected) self.central_widget = CentralWidget(self.gui) self.setCentralWidget(self.central_widget) invite_action = QAction(QIcon(resource('invite.png')), 'Enter an Invite Code...', self) invite_action.setStatusTip('Enter an Invite Code...') invite_action.triggered.connect(self.open_invite_receiver) folder_icon_default = QFileIconProvider().icon(QFileInfo(config_dir)) folder_icon_composite = CompositePixmap( folder_icon_default.pixmap(256, 256), resource('green-plus.png')) folder_icon = QIcon(folder_icon_composite) folder_action = QAction(folder_icon, "Add folder...", self) folder_action.setStatusTip("Add folder...") folder_from_local_action = QAction(QIcon(resource('laptop.png')), "From local computer...", self) folder_from_local_action.setStatusTip("Add folder from local computer") folder_from_local_action.setToolTip("Add folder from local computer") #self.from_local_action.setShortcut(QKeySequence.Open) folder_from_local_action.triggered.connect(self.select_folder) folder_from_invite_action = QAction(QIcon(resource('invite.png')), "From Invite Code...", self) folder_from_invite_action.setStatusTip("Add folder from Invite Code") folder_from_invite_action.setToolTip("Add folder from Invite Code") folder_from_invite_action.triggered.connect(self.open_invite_receiver) folder_menu = QMenu(self) folder_menu.addAction(folder_from_local_action) folder_menu.addAction(folder_from_invite_action) folder_button = QToolButton(self) folder_button.setDefaultAction(folder_action) folder_button.setMenu(folder_menu) folder_button.setPopupMode(2) folder_button.setStyleSheet( 'QToolButton::menu-indicator { image: none }') pair_action = QAction(QIcon(resource('laptop.png')), 'Connect another device...', self) pair_action.setStatusTip('Connect another device...') pair_action.triggered.connect(self.open_pair_widget) export_action = QAction(QIcon(resource('export.png')), 'Export Recovery Key', self) export_action.setStatusTip('Export Recovery Key...') export_action.setShortcut(QKeySequence.Save) export_action.triggered.connect(self.export_recovery_key) preferences_action = QAction(QIcon(resource('preferences.png')), 'Preferences', self) preferences_action.setStatusTip('Preferences') preferences_action.setShortcut(QKeySequence.Preferences) preferences_action.triggered.connect(self.toggle_preferences_widget) spacer_left = QWidget() spacer_left.setSizePolicy(QSizePolicy.Expanding, 0) spacer_right = QWidget() spacer_right.setSizePolicy(QSizePolicy.Expanding, 0) self.toolbar = self.addToolBar('') #self.toolbar.setToolButtonStyle(Qt.ToolButtonTextUnderIcon) #self.toolbar.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) self.toolbar.setIconSize(QSize(24, 24)) self.toolbar.setMovable(False) self.toolbar.addWidget(folder_button) #self.toolbar.addAction(invite_action) self.toolbar.addAction(pair_action) self.toolbar.addWidget(spacer_left) self.toolbar.addWidget(self.combo_box) self.toolbar.addWidget(spacer_right) self.toolbar.addAction(export_action) self.toolbar.addAction(preferences_action) self.status_bar = self.statusBar() self.status_bar_label = QLabel('Initializing...') self.status_bar.addPermanentWidget(self.status_bar_label) self.preferences_widget = PreferencesWidget() self.preferences_widget.accepted.connect(self.show_selected_grid_view) self.active_pair_widgets = [] self.active_invite_receivers = []
class Model(QStandardItemModel): def __init__(self, view): super(Model, self).__init__(0, 5) self.view = view self.gui = self.view.gui self.gateway = self.view.gateway self.monitor = self.gateway.monitor self.status_dict = {} self.members_dict = {} self.grid_status = '' self.available_space = 0 self.setHeaderData(0, Qt.Horizontal, "Name") self.setHeaderData(1, Qt.Horizontal, "Status") self.setHeaderData(2, Qt.Horizontal, "Last modified") self.setHeaderData(3, Qt.Horizontal, "Size") self.setHeaderData(4, Qt.Horizontal, "") self.icon_blank = QIcon() self.icon_up_to_date = QIcon(resource('checkmark.png')) self.icon_user = QIcon(resource('user.png')) self.icon_folder = QFileIconProvider().icon(QFileInfo(config_dir)) composite_pixmap = CompositePixmap(self.icon_folder.pixmap(256, 256), overlay=None, grayout=True) self.icon_folder_gray = QIcon(composite_pixmap) self.icon_cloud = QIcon(resource('cloud-icon.png')) self.icon_action = QIcon(resource('dots-horizontal-triple.png')) self.monitor.connected.connect(self.on_connected) self.monitor.disconnected.connect(self.on_disconnected) self.monitor.nodes_updated.connect(self.on_nodes_updated) self.monitor.space_updated.connect(self.on_space_updated) self.monitor.status_updated.connect(self.set_status) self.monitor.mtime_updated.connect(self.set_mtime) self.monitor.size_updated.connect(self.set_size) self.monitor.members_updated.connect(self.on_members_updated) self.monitor.sync_started.connect(self.on_sync_started) self.monitor.sync_finished.connect(self.on_sync_finished) self.monitor.files_updated.connect(self.on_updated_files) self.monitor.check_finished.connect(self.update_natural_times) self.monitor.remote_folder_added.connect(self.add_remote_folder) self.monitor.transfer_progress_updated.connect( self.set_transfer_progress) def on_space_updated(self, size): self.available_space = size @pyqtSlot(int, int) def on_nodes_updated(self, num_connected, num_happy): if num_connected < num_happy: self.grid_status = "Connecting ({}/{} nodes){}".format( num_connected, num_happy, (" via Tor..." if self.gateway.use_tor else "...")) elif num_connected >= num_happy: self.grid_status = "Connected to {} {}{} {} available".format( num_connected, 'storage ' + ('node' if num_connected == 1 else 'nodes'), (" via Tor;" if self.gateway.use_tor else ";"), naturalsize(self.available_space)) self.gui.main_window.set_current_grid_status() # TODO: Use pyqtSignal? @pyqtSlot() def on_connected(self): if get_preference('notifications', 'connection') != 'false': self.gui.show_message(self.gateway.name, "Connected to {}".format(self.gateway.name)) @pyqtSlot() def on_disconnected(self): if get_preference('notifications', 'connection') != 'false': self.gui.show_message( self.gateway.name, "Disconnected from {}".format(self.gateway.name)) @pyqtSlot(str, list, str, str) def on_updated_files(self, folder_name, files_list, action, author): if get_preference('notifications', 'folder') != 'false': self.gui.show_message( folder_name + " folder updated", "{} {}".format( author + " " + action if author else action.capitalize(), humanized_list(files_list))) def data(self, index, role): value = super(Model, self).data(index, role) if role == Qt.SizeHintRole: return QSize(0, 30) return value def add_folder(self, path, status_data=0): basename = os.path.basename(os.path.normpath(path)) if self.findItems(basename): logging.warning("Tried to add a folder (%s) that already exists", basename) return composite_pixmap = CompositePixmap(self.icon_folder.pixmap(256, 256)) name = QStandardItem(QIcon(composite_pixmap), basename) name.setToolTip(path) status = QStandardItem() mtime = QStandardItem() size = QStandardItem() action = QStandardItem() self.appendRow([name, status, mtime, size, action]) action_bar = QToolBar() action_bar.setIconSize(QSize(16, 16)) if sys.platform == 'darwin': # See: https://bugreports.qt.io/browse/QTBUG-12717 action_bar.setStyleSheet( 'background-color: white; border: 0px white') action_bar_action = QAction(self.icon_action, "Action...", self) action_bar_action.setStatusTip("Action...") action_bar_action.triggered.connect(self.view.on_right_click) action_bar.addAction(action_bar_action) self.view.setIndexWidget(action.index(), action_bar) self.view.hide_drop_label() self.set_status(basename, status_data) def remove_folder(self, folder_name): items = self.findItems(folder_name) if items: self.removeRow(items[0].row()) def populate(self): for magic_folder in list(self.gateway.load_magic_folders().values()): self.add_folder(magic_folder['directory']) def update_folder_icon(self, folder_name, folder_path, overlay_file=None): items = self.findItems(folder_name) if items: if folder_path: folder_icon = QFileIconProvider().icon(QFileInfo(folder_path)) else: folder_icon = self.icon_folder_gray folder_pixmap = folder_icon.pixmap(256, 256) if overlay_file: pixmap = CompositePixmap(folder_pixmap, resource(overlay_file)) else: pixmap = CompositePixmap(folder_pixmap) items[0].setIcon(QIcon(pixmap)) def set_status_private(self, folder_name): self.update_folder_icon( folder_name, self.gateway.get_magic_folder_directory(folder_name)) items = self.findItems(folder_name) if items: items[0].setToolTip( "{}\n\nThis folder is private; only you can view and\nmodify " "its contents.".format( self.gateway.get_magic_folder_directory(folder_name) or folder_name + " (Stored remotely)")) def set_status_shared(self, folder_name): self.update_folder_icon( folder_name, self.gateway.get_magic_folder_directory(folder_name), 'laptop.png') items = self.findItems(folder_name) if items: items[0].setToolTip( "{}\n\nAt least one other device can view and modify\n" "this folder's contents.".format( self.gateway.get_magic_folder_directory(folder_name) or folder_name + " (Stored remotely)")) def update_overlay(self, folder_name): members = self.members_dict.get(folder_name) if members and len(members) > 1: self.set_status_shared(folder_name) else: self.set_status_private(folder_name) @pyqtSlot(str, list) def on_members_updated(self, folder, members): self.members_dict[folder] = members self.update_overlay(folder) @pyqtSlot(str, int) def set_status(self, name, status): items = self.findItems(name) if not items: return item = self.item(items[0].row(), 1) if not status: item.setIcon(self.icon_blank) item.setText("Loading...") elif status == 1: item.setIcon(self.icon_blank) item.setText("Syncing") item.setToolTip( "This folder is syncing. New files are being uploaded or " "downloaded.") elif status == 2: item.setIcon(self.icon_up_to_date) item.setText("Up to date") item.setToolTip( 'This folder is up to date. The contents of this folder on\n' 'your computer matches the contents of the folder on the\n' '"{}" grid.'.format(self.gateway.name)) self.update_overlay(name) self.unfade_row(name) elif status == 3: item.setIcon(self.icon_cloud) item.setText("Stored remotely") item.setToolTip( 'This folder is stored remotely on the "{}" grid.\n' 'Right-click and select "Download" to sync it with your ' 'local computer.'.format(self.gateway.name)) elif status == 99: item.setIcon(self.icon_blank) item.setText("Scanning") item.setToolTip("This folder is being scanned for changes.") item.setData(status, Qt.UserRole) self.status_dict[name] = status @pyqtSlot(str, object, object) def set_transfer_progress(self, folder_name, transferred, total): items = self.findItems(folder_name) if not items: return percent_done = int(transferred / total * 100) if not percent_done: # Magic-folder's periodic "full scan" (which occurs every 10 # minutes) temporarily adds *all* known files to the queue # exposed by the "status" API for a very brief period (seemingly # for only a second or two). Because of this -- and since we rely # on the magic-folder "status" API to tell us information about # current and pending transfers to calculate total progress -- # existing "syncing" operations will briefly display a progress # of "0%" during this time (since the number of bytes to be # transferred briefly becomes equal to the total size of the # entire folder -- even though those transfers do not occur and # vanish from the queue as soon as the the "full scan" is # completed). To compensate for this strange (and rare) event -- # and because it's probably jarring to the end-user to see # progress dip down to "0%" for a brief moment before returning to # normal -- we ignore any updates to "0" here (on the assumption # that it's better to have a couple of seconds of no progress # updates than a progress update which is wrong or misleading). return item = self.item(items[0].row(), 1) item.setText("Syncing ({}%)".format(percent_done)) def fade_row(self, folder_name, overlay_file=None): folder_item = self.findItems(folder_name)[0] if overlay_file: folder_pixmap = self.icon_folder_gray.pixmap(256, 256) pixmap = CompositePixmap(folder_pixmap, resource(overlay_file)) folder_item.setIcon(QIcon(pixmap)) else: folder_item.setIcon(self.icon_folder_gray) row = folder_item.row() for i in range(4): item = self.item(row, i) font = item.font() font.setItalic(True) item.setFont(font) item.setForeground(QColor('gray')) def unfade_row(self, folder_name): default_foreground = QStandardItem().foreground() folder_item = self.findItems(folder_name)[0] row = folder_item.row() for i in range(4): item = self.item(row, i) font = item.font() font.setItalic(False) item.setFont(font) item.setForeground(default_foreground) @pyqtSlot(str) def on_sync_started(self, folder_name): self.gui.core.operations.append((self.gateway, folder_name)) self.gui.systray.update() @pyqtSlot(str) def on_sync_finished(self, folder_name): try: self.gui.core.operations.remove((self.gateway, folder_name)) except ValueError: pass @pyqtSlot(str, int) def set_mtime(self, name, mtime): if not mtime: return items = self.findItems(name) if items: item = self.item(items[0].row(), 2) item.setData(mtime, Qt.UserRole) item.setText( naturaltime(datetime.now() - datetime.fromtimestamp(mtime))) item.setToolTip("Last modified: {}".format(time.ctime(mtime))) @pyqtSlot(str, object) def set_size(self, name, size): items = self.findItems(name) if items: item = self.item(items[0].row(), 3) item.setText(naturalsize(size)) item.setData(size, Qt.UserRole) @pyqtSlot() def update_natural_times(self): for i in range(self.rowCount()): item = self.item(i, 2) data = item.data(Qt.UserRole) if data: item.setText( naturaltime(datetime.now() - datetime.fromtimestamp(data))) @pyqtSlot(str, str) def add_remote_folder(self, folder_name, overlay_file=None): self.add_folder(folder_name, 3) self.fade_row(folder_name, overlay_file)
def __init__(self, gui): # noqa: max-complexity super().__init__() self.gui = gui self.gateways = [] self.welcome_dialog = None self.recovery_key_exporter = None self.setWindowTitle(APP_NAME) self.setMinimumSize(QSize(600, 400)) self.setUnifiedTitleAndToolBarOnMac(True) self.setContextMenuPolicy(Qt.NoContextMenu) if sys.platform == "darwin": # To disable the broken/buggy "full screen" mode on macOS. # See https://github.com/gridsync/gridsync/issues/241 self.setWindowFlags(Qt.Dialog) grid_invites_enabled = True invites_enabled = True multiple_grids_enabled = True features_settings = settings.get("features") if features_settings: grid_invites = features_settings.get("grid_invites") if grid_invites and grid_invites.lower() == "false": grid_invites_enabled = False invites = features_settings.get("invites") if invites and invites.lower() == "false": invites_enabled = False multiple_grids = features_settings.get("multiple_grids") if multiple_grids and multiple_grids.lower() == "false": multiple_grids_enabled = False if multiple_grids_enabled: self.shortcut_new = QShortcut(QKeySequence.New, self) self.shortcut_new.activated.connect(self.show_welcome_dialog) self.shortcut_open = QShortcut(QKeySequence.Open, self) self.shortcut_open.activated.connect(self.select_folder) self.shortcut_preferences = QShortcut(QKeySequence.Preferences, self) self.shortcut_preferences.activated.connect( self.gui.show_preferences_window) self.shortcut_close = QShortcut(QKeySequence.Close, self) self.shortcut_close.activated.connect(self.close) self.shortcut_quit = QShortcut(QKeySequence.Quit, self) self.shortcut_quit.activated.connect(self.confirm_quit) self.central_widget = CentralWidget(self.gui) self.setCentralWidget(self.central_widget) font = Font(8) folder_icon_default = QFileIconProvider().icon(QFileInfo(config_dir)) folder_icon_composite = CompositePixmap( folder_icon_default.pixmap(256, 256), resource("green-plus.png")) folder_icon = QIcon(folder_icon_composite) folder_action = QAction(folder_icon, "Add Folder", self) folder_action.setToolTip("Add a Folder...") folder_action.setFont(font) folder_action.triggered.connect(self.select_folder) if grid_invites_enabled: invites_action = QAction(QIcon(resource("invite.png")), "Invites", self) invites_action.setToolTip("Enter or Create an Invite Code") invites_action.setFont(font) enter_invite_action = QAction(QIcon(), "Enter Invite Code...", self) enter_invite_action.setToolTip("Enter an Invite Code...") enter_invite_action.triggered.connect(self.open_invite_receiver) create_invite_action = QAction(QIcon(), "Create Invite Code...", self) create_invite_action.setToolTip("Create on Invite Code...") create_invite_action.triggered.connect( self.open_invite_sender_dialog) invites_menu = QMenu(self) invites_menu.addAction(enter_invite_action) invites_menu.addAction(create_invite_action) invites_button = QToolButton(self) invites_button.setDefaultAction(invites_action) invites_button.setMenu(invites_menu) invites_button.setPopupMode(2) invites_button.setStyleSheet( "QToolButton::menu-indicator { image: none }") invites_button.setToolButtonStyle(Qt.ToolButtonTextUnderIcon) elif invites_enabled: invite_action = QAction(QIcon(resource("invite.png")), "Enter Code", self) invite_action.setToolTip("Enter an Invite Code...") invite_action.setFont(font) invite_action.triggered.connect(self.open_invite_receiver) spacer_left = QWidget() spacer_left.setSizePolicy(QSizePolicy.Expanding, 0) self.combo_box = ComboBox() self.combo_box.currentIndexChanged.connect(self.on_grid_selected) if not multiple_grids_enabled: self.combo_box.hide() spacer_right = QWidget() spacer_right.setSizePolicy(QSizePolicy.Expanding, 0) history_action = QAction(QIcon(resource("time.png")), "History", self) history_action.setToolTip("Show/Hide History") history_action.setFont(font) history_action.triggered.connect(self.on_history_button_clicked) self.history_button = QToolButton(self) self.history_button.setDefaultAction(history_action) self.history_button.setCheckable(True) self.history_button.setToolButtonStyle(Qt.ToolButtonTextUnderIcon) recovery_action = QAction(QIcon(resource("key.png")), "Recovery", self) recovery_action.setToolTip("Import or Export a Recovery Key") recovery_action.setFont(font) import_action = QAction(QIcon(), "Import Recovery Key...", self) import_action.setToolTip("Import Recovery Key...") import_action.triggered.connect(self.import_recovery_key) export_action = QAction(QIcon(), "Export Recovery Key...", self) export_action.setToolTip("Export Recovery Key...") export_action.setShortcut(QKeySequence.Save) export_action.triggered.connect(self.export_recovery_key) recovery_menu = QMenu(self) recovery_menu.addAction(import_action) recovery_menu.addAction(export_action) recovery_button = QToolButton(self) recovery_button.setDefaultAction(recovery_action) recovery_button.setMenu(recovery_menu) recovery_button.setPopupMode(2) recovery_button.setStyleSheet( "QToolButton::menu-indicator { image: none }") recovery_button.setToolButtonStyle(Qt.ToolButtonTextUnderIcon) self.toolbar = self.addToolBar("") p = self.palette() dimmer_grey = BlendedColor(p.windowText().color(), p.window().color(), 0.7).name() if sys.platform != "darwin": self.toolbar.setStyleSheet(""" QToolBar {{ border: 0px }} QToolButton {{ color: {} }} """.format(dimmer_grey)) else: self.toolbar.setStyleSheet( "QToolButton {{ color: {} }}".format(dimmer_grey)) self.toolbar.setToolButtonStyle(Qt.ToolButtonTextUnderIcon) self.toolbar.setIconSize(QSize(24, 24)) self.toolbar.setMovable(False) self.toolbar.addAction(folder_action) if grid_invites_enabled: self.toolbar.addWidget(invites_button) elif invites_enabled: self.toolbar.addAction(invite_action) self.toolbar.addWidget(spacer_left) self.toolbar.addWidget(self.combo_box) self.toolbar.addWidget(spacer_right) self.toolbar.addWidget(self.history_button) self.toolbar.addWidget(recovery_button) if sys.platform != "win32": # Text is getting clipped on Windows 10 for action in self.toolbar.actions(): widget = self.toolbar.widgetForAction(action) if isinstance(widget, QToolButton): widget.setMaximumWidth(68) self.active_invite_sender_dialogs = [] self.active_invite_receiver_dialogs = [] self.pending_news_message = ()
def __init__(self, gateway, gui, folder_names=None): super(InviteSenderDialog, self).__init__() self.gateway = gateway self.gui = gui self.folder_names = folder_names self.folder_names_humanized = humanized_list(folder_names, 'folders') self.settings = {} self.pending_invites = [] self.use_tor = self.gateway.use_tor self.setMinimumSize(500, 300) header_icon = QLabel(self) if self.folder_names: icon = QFileIconProvider().icon( QFileInfo( self.gateway.get_magic_folder_directory( self.folder_names[0]))) else: icon = QIcon(os.path.join(gateway.nodedir, 'icon')) if not icon.availableSizes(): icon = QIcon(resource('tahoe-lafs.png')) header_icon.setPixmap(icon.pixmap(50, 50)) header_text = QLabel(self) if self.folder_names: header_text.setText(self.folder_names_humanized) else: header_text.setText(self.gateway.name) header_text.setFont(Font(18)) header_text.setAlignment(Qt.AlignCenter) header_layout = QGridLayout() header_layout.addItem(QSpacerItem(0, 0, QSizePolicy.Expanding, 0), 1, 1) header_layout.addWidget(header_icon, 1, 2) header_layout.addWidget(header_text, 1, 3) header_layout.addItem(QSpacerItem(0, 0, QSizePolicy.Expanding, 0), 1, 4) self.subtext_label = QLabel(self) self.subtext_label.setFont(Font(10)) self.subtext_label.setStyleSheet("color: grey") self.subtext_label.setWordWrap(True) self.subtext_label.setAlignment(Qt.AlignCenter) self.noise_label = QLabel() font = Font(16) font.setFamily("Courier") font.setStyleHint(QFont.Monospace) self.noise_label.setFont(font) self.noise_label.setStyleSheet("color: grey") self.noise_timer = QTimer() self.noise_timer.timeout.connect( lambda: self.noise_label.setText(b58encode(os.urandom(16)))) self.noise_timer.start(75) self.code_label = QLabel() self.code_label.setFont(Font(18)) self.code_label.setTextInteractionFlags(Qt.TextSelectableByMouse) self.code_label.hide() self.box_title = QLabel(self) self.box_title.setAlignment(Qt.AlignCenter) self.box_title.setFont(Font(16)) self.box = QGroupBox() self.box.setAlignment(Qt.AlignCenter) self.box.setStyleSheet('QGroupBox {font-size: 16px}') self.copy_button = QToolButton() self.copy_button.setIcon(QIcon(resource('copy.png'))) self.copy_button.setToolTip("Copy to clipboard") self.copy_button.setStyleSheet('border: 0px; padding: 0px;') self.copy_button.hide() box_layout = QGridLayout(self.box) box_layout.addItem(QSpacerItem(0, 0, QSizePolicy.Expanding, 0), 1, 1) box_layout.addWidget(self.noise_label, 1, 2) box_layout.addWidget(self.code_label, 1, 3) box_layout.addWidget(self.copy_button, 1, 4) box_layout.addItem(QSpacerItem(0, 0, QSizePolicy.Expanding, 0), 1, 5) self.close_button = QPushButton("Close and cancel invite") self.close_button.setAutoDefault(False) self.checkmark = QLabel() self.checkmark.setPixmap(Pixmap('green_checkmark.png', 32)) self.checkmark.setAlignment(Qt.AlignCenter) self.checkmark.hide() self.tor_label = QLabel() self.tor_label.setToolTip( "This connection is being routed through the Tor network.") self.tor_label.setPixmap(Pixmap('tor-onion.png', 24)) self.tor_label.hide() self.progress_bar = QProgressBar() self.progress_bar.setMaximum(2) self.progress_bar.setTextVisible(False) self.progress_bar.hide() layout = QGridLayout(self) layout.addItem(QSpacerItem(0, 0, 0, QSizePolicy.Expanding), 0, 0) layout.addItem(QSpacerItem(0, 0, QSizePolicy.Expanding, 0), 1, 1) layout.addItem(QSpacerItem(0, 0, QSizePolicy.Expanding, 0), 1, 2) layout.addItem(QSpacerItem(0, 0, QSizePolicy.Expanding, 0), 1, 3) layout.addItem(QSpacerItem(0, 0, QSizePolicy.Expanding, 0), 1, 4) layout.addItem(QSpacerItem(0, 0, QSizePolicy.Expanding, 0), 1, 5) layout.addLayout(header_layout, 1, 3) layout.addItem(QSpacerItem(0, 0, 0, QSizePolicy.Expanding), 2, 1) layout.addWidget(self.box_title, 3, 2, 1, 3) layout.addWidget(self.checkmark, 3, 3) layout.addWidget(self.tor_label, 4, 1, 1, 1, Qt.AlignRight | Qt.AlignVCenter) layout.addWidget(self.box, 4, 2, 1, 3) layout.addWidget(self.progress_bar, 4, 2, 1, 3) layout.addWidget(self.subtext_label, 5, 2, 1, 3) layout.addItem(QSpacerItem(0, 0, 0, QSizePolicy.Expanding), 6, 1) layout.addWidget(self.close_button, 7, 3) layout.addItem(QSpacerItem(0, 0, 0, QSizePolicy.Expanding), 8, 1) self.copy_button.clicked.connect(self.on_copy_button_clicked) self.close_button.clicked.connect(self.close) self.set_box_title("Generating invite code...") self.subtext_label.setText("Creating folder invite(s)...\n\n") if self.use_tor: self.tor_label.show() self.progress_bar.setStyleSheet( 'QProgressBar::chunk {{ background-color: {}; }}'.format( TOR_PURPLE)) self.go() # XXX
def __init__(self, gui): super(MainWindow, self).__init__() self.gui = gui self.gateways = [] self.welcome_dialog = None self.recovery_key_exporter = None self.setWindowTitle(APP_NAME) self.setMinimumSize(QSize(600, 400)) self.setUnifiedTitleAndToolBarOnMac(True) self.shortcut_new = QShortcut(QKeySequence.New, self) self.shortcut_new.activated.connect(self.show_welcome_dialog) self.shortcut_open = QShortcut(QKeySequence.Open, self) self.shortcut_open.activated.connect(self.select_folder) self.shortcut_close = QShortcut(QKeySequence.Close, self) self.shortcut_close.activated.connect(self.close) self.shortcut_quit = QShortcut(QKeySequence.Quit, self) self.shortcut_quit.activated.connect(self.confirm_quit) self.central_widget = CentralWidget(self.gui) self.setCentralWidget(self.central_widget) font = QFont() if sys.platform == 'darwin': font.setPointSize(11) else: font.setPointSize(8) folder_icon_default = QFileIconProvider().icon(QFileInfo(config_dir)) folder_icon_composite = CompositePixmap( folder_icon_default.pixmap(256, 256), resource('green-plus.png')) folder_icon = QIcon(folder_icon_composite) folder_action = QAction(folder_icon, "Add folder", self) folder_action.setToolTip("Add a folder...") folder_action.setFont(font) folder_action.triggered.connect(self.select_folder) invite_action = QAction( QIcon(resource('invite.png')), "Enter Code", self) invite_action.setToolTip("Enter an Invite Code...") invite_action.setFont(font) invite_action.triggered.connect(self.open_invite_receiver) history_action = QAction( QIcon(resource('time.png')), 'History', self) history_action.setToolTip("View history") history_action.setFont(font) history_action.triggered.connect(self.on_history_button_clicked) self.history_button = QToolButton(self) self.history_button.setDefaultAction(history_action) self.history_button.setCheckable(True) self.history_button.setToolButtonStyle(Qt.ToolButtonTextUnderIcon) spacer_left = QWidget() spacer_left.setSizePolicy(QSizePolicy.Expanding, 0) self.combo_box = ComboBox() self.combo_box.currentIndexChanged.connect(self.on_grid_selected) spacer_right = QWidget() spacer_right.setSizePolicy(QSizePolicy.Expanding, 0) share_action = QAction(QIcon(resource('share.png')), "Share", self) share_action.setToolTip("Share...") share_action.setFont(font) share_action.triggered.connect(self.open_invite_sender_dialog) recovery_action = QAction( QIcon(resource('key.png')), "Recovery", self) recovery_action.setToolTip("Import/Export Recovery Key...") recovery_action.setFont(font) import_action = QAction(QIcon(), "Import Recovery Key...", self) import_action.setToolTip("Import Recovery Key...") import_action.triggered.connect(self.import_recovery_key) export_action = QAction(QIcon(), "Export Recovery Key...", self) export_action.setToolTip("Export Recovery Key...") export_action.setShortcut(QKeySequence.Save) export_action.triggered.connect(self.export_recovery_key) recovery_menu = QMenu(self) recovery_menu.addAction(import_action) recovery_menu.addAction(export_action) recovery_button = QToolButton(self) recovery_button.setDefaultAction(recovery_action) recovery_button.setMenu(recovery_menu) recovery_button.setPopupMode(2) recovery_button.setStyleSheet( 'QToolButton::menu-indicator { image: none }') recovery_button.setToolButtonStyle(Qt.ToolButtonTextUnderIcon) preferences_action = QAction( QIcon(resource('preferences.png')), "Preferences", self) preferences_action.setStatusTip("Preferences") preferences_action.setToolTip("Preferences") preferences_action.setFont(font) preferences_action.setShortcut(QKeySequence.Preferences) preferences_action.triggered.connect(self.gui.show_preferences_window) self.toolbar = self.addToolBar('') if sys.platform != 'darwin': self.toolbar.setStyleSheet(""" QToolBar { border: 0px } QToolButton { color: rgb(50, 50, 50) } """) else: self.toolbar.setStyleSheet( "QToolButton { color: rgb(50, 50, 50) }") self.toolbar.setToolButtonStyle(Qt.ToolButtonTextUnderIcon) self.toolbar.setIconSize(QSize(24, 24)) self.toolbar.setMovable(False) self.toolbar.addAction(folder_action) self.toolbar.addAction(invite_action) self.toolbar.addWidget(self.history_button) self.toolbar.addWidget(spacer_left) self.toolbar.addWidget(self.combo_box) self.toolbar.addWidget(spacer_right) self.toolbar.addAction(share_action) self.toolbar.addWidget(recovery_button) self.toolbar.addAction(preferences_action) if sys.platform != 'win32': # Text is getting clipped on Windows 10 for action in self.toolbar.actions(): widget = self.toolbar.widgetForAction(action) if isinstance(widget, QToolButton): widget.setMaximumWidth(68) self.active_invite_sender_dialogs = [] self.active_invite_receiver_dialogs = []
def __init__(self, gateways): super(InviteReceiverDialog, self).__init__() self.gateways = gateways self.invite_receiver = None self.joined_folders = [] self.setMinimumSize(500, 300) self.mail_closed_icon = QLabel() self.mail_closed_icon.setAlignment(Qt.AlignCenter) self.mail_closed_icon.setPixmap( Pixmap("mail-envelope-closed.png", 128) ) self.mail_open_icon = QLabel() self.mail_open_icon.setAlignment(Qt.AlignCenter) self.mail_open_icon.setPixmap(Pixmap("mail-envelope-open.png", 128)) self.folder_icon = QLabel() icon = QFileIconProvider().icon(QFileInfo(config_dir)) self.folder_icon.setPixmap(icon.pixmap(128, 128)) self.folder_icon.setAlignment(Qt.AlignCenter) self.invite_code_widget = InviteCodeWidget(self) self.invite_code_widget.lineedit.go.connect(self.go) # XXX self.tor_label = QLabel() self.tor_label.setToolTip( "This connection is being routed through the Tor network." ) self.tor_label.setPixmap(Pixmap("tor-onion.png", 24)) self.checkmark = QLabel() self.checkmark.setAlignment(Qt.AlignCenter) self.checkmark.setPixmap(Pixmap("green_checkmark.png", 32)) self.progressbar = QProgressBar(self) self.progressbar.setValue(0) self.progressbar.setMaximum(6) # XXX self.progressbar.setTextVisible(False) self.message_label = QLabel(" ") self.message_label.setStyleSheet("color: grey") self.message_label.setAlignment(Qt.AlignCenter) self.error_label = QLabel() self.error_label.setStyleSheet("color: red") self.error_label.setAlignment(Qt.AlignCenter) self.close_button = QPushButton("Close") self.close_button.clicked.connect(self.close) layout = QGridLayout(self) layout.addItem(QSpacerItem(0, 0, 0, QSizePolicy.Expanding), 0, 0) layout.addItem(QSpacerItem(0, 0, QSizePolicy.Expanding, 0), 1, 1) layout.addItem(QSpacerItem(0, 0, QSizePolicy.Expanding, 0), 1, 2) layout.addItem(QSpacerItem(0, 0, QSizePolicy.Expanding, 0), 1, 3) layout.addWidget(self.mail_closed_icon, 1, 2, 1, 3) layout.addWidget(self.mail_open_icon, 1, 2, 1, 3) layout.addWidget(self.folder_icon, 1, 2, 1, 3) layout.addItem(QSpacerItem(0, 0, QSizePolicy.Expanding, 0), 1, 4) layout.addItem(QSpacerItem(0, 0, QSizePolicy.Expanding, 0), 1, 5) layout.addWidget(self.invite_code_widget, 2, 2, 1, 3) layout.addWidget(self.checkmark, 2, 3, 1, 1) layout.addWidget( self.tor_label, 3, 1, 1, 1, Qt.AlignRight | Qt.AlignVCenter ) layout.addWidget(self.progressbar, 3, 2, 1, 3) layout.addWidget(self.message_label, 5, 1, 1, 5) layout.addWidget(self.error_label, 5, 2, 1, 3) layout.addWidget(self.close_button, 6, 3) layout.addItem(QSpacerItem(0, 0, 0, QSizePolicy.Expanding), 7, 1) self.reset()
def fileAlreadyExists(parent, path1, path2, paths2, date1, date2, size1, size2, qicon1=None, qicon2=None): # Dialog dia = QtWidgets.QDialog() dia.setFixedSize(400, 550) dia.setWindowTitle("File Already Exists") # GUI gui = FileAlreadyExists(dia) # QSignal : response management response = None def __rename(): nonlocal response nonlocal gui nonlocal warnings_msg nonlocal path2 response = "/".join( path2.split("/")[:-1] + [gui.QLineEdit_rename.text()]) if response in paths2: msg_renameItAgain = "Warning: the name you suggested also exists" if msg_renameItAgain in warnings_msg: pass else: warnings_msg.append(msg_renameItAgain) gui.QLabel_warnings.setText("\n".join(warnings_msg)) if response == path2: msg_renameItAgain = "Warning: the name you suggested is the same" if msg_renameItAgain in warnings_msg: pass else: warnings_msg.append(msg_renameItAgain) gui.QLabel_warnings.setText("\n".join(warnings_msg)) if response != path2 and response not in paths2: response = None dia.done(0) def __overwr(): nonlocal response response = path2 dia.done(0) def __cancel(): nonlocal response response = None dia.done(0) gui.QPushButton_rename.clicked.connect(__rename) gui.QPushButton_overwr.clicked.connect(__overwr) gui.QPushButton_cancel.clicked.connect(__cancel) # Icons if qicon1 is None: qicon1 = QFileIconProvider().icon( QFileInfo("/home/d/Desktop/chocolate.txt")) if qicon2 is None: qicon2 = QFileIconProvider().icon( QFileInfo("/home/d/Desktop/chocolate.txt")) side_square_size = int(dia.size().width() / 2) - 40 gui.QLabel_icon1.resize(side_square_size, side_square_size) gui.QLabel_icon1.setPixmap( qicon1.pixmap(side_square_size, side_square_size)) gui.QLabel_icon2.resize(side_square_size, side_square_size) gui.QLabel_icon2.setPixmap( qicon2.pixmap(side_square_size, side_square_size)) # Clip paths gui.QLabel_path1.setText( QtGui.QFontMetrics(gui.QLabel_path1.font()).elidedText( path1, QtCore.Qt.ElideMiddle, int(dia.size().width() / 2) - 20)) gui.QLabel_path2.setText( QtGui.QFontMetrics(gui.QLabel_path2.font()).elidedText( path2, QtCore.Qt.ElideMiddle, int(dia.size().width() / 2) - 20)) # Dates gui.QLabel_date1.setText("Date:\n" + date1) gui.QLabel_date2.setText("Date:\n" + date2) # Sizes gui.QLabel_size1.setText("Size: " + humanfriendly.format_size(size1)) gui.QLabel_size2.setText("Size: " + humanfriendly.format_size(size2)) # Warnings warnings_msg = [] if size2 > size1: warnings_msg.append("Warning: size destination is bigger") if date2 > date1: warnings_msg.append("Warning: date destination is more recent") gui.QLabel_warnings.setText("\n".join(warnings_msg)) # Suggest name selection = path1.split("/")[-1] gui.QLineEdit_rename.setText(selection) gui.QLineEdit_rename.setSelection(0, len(selection)) # ONLY WHEN THE MESSAGE BOX IS THE ONLY THING - TODO TODO TODO if not dia.exec_(): return response
def __init__(self, gateway, gui, folder_names=None): # pylint:disable=too-many-statements super(ShareWidget, self).__init__() self.gateway = gateway self.gui = gui self.folder_names = folder_names self.folder_names_humanized = humanized_list(folder_names, 'folders') self.settings = {} self.wormhole = None self.pending_invites = [] self.setMinimumSize(500, 300) header_icon = QLabel(self) if self.folder_names: icon = QFileIconProvider().icon( QFileInfo( self.gateway.get_magic_folder_directory( self.folder_names[0]))) else: icon = QIcon(os.path.join(gateway.nodedir, 'icon')) if not icon.availableSizes(): icon = QIcon(resource('tahoe-lafs.png')) header_icon.setPixmap(icon.pixmap(50, 50)) header_text = QLabel(self) if self.folder_names: header_text.setText(self.folder_names_humanized) else: header_text.setText(self.gateway.name) font = QFont() font.setPointSize(18) header_text.setFont(font) header_text.setAlignment(Qt.AlignCenter) header_layout = QGridLayout() header_layout.addItem(QSpacerItem(0, 0, QSizePolicy.Expanding, 0), 1, 1) header_layout.addWidget(header_icon, 1, 2) header_layout.addWidget(header_text, 1, 3) header_layout.addItem(QSpacerItem(0, 0, QSizePolicy.Expanding, 0), 1, 4) self.subtext_label = QLabel(self) font = QFont() font.setPointSize(10) self.subtext_label.setFont(font) self.subtext_label.setStyleSheet("color: grey") self.subtext_label.setWordWrap(True) self.subtext_label.setAlignment(Qt.AlignCenter) self.noise_label = QLabel() font = QFont() font.setPointSize(16) font.setFamily("Courier") font.setStyleHint(QFont.Monospace) self.noise_label.setFont(font) self.noise_label.setStyleSheet("color: grey") self.noise_timer = QTimer() self.noise_timer.timeout.connect( lambda: self.noise_label.setText(b58encode(os.urandom(16)))) self.noise_timer.start(75) self.code_label = QLabel() font = QFont() font.setPointSize(18) self.code_label.setFont(font) self.code_label.setTextInteractionFlags(Qt.TextSelectableByMouse) self.code_label.hide() self.box_title = QLabel(self) self.box_title.setAlignment(Qt.AlignCenter) font = QFont() font.setPointSize(16) self.box_title.setFont(font) self.box = QGroupBox() self.box.setAlignment(Qt.AlignCenter) self.box.setStyleSheet('QGroupBox {font-size: 16px}') self.copy_button = QToolButton() self.copy_button.setIcon(QIcon(resource('copy.png'))) self.copy_button.setToolTip("Copy to clipboard") self.copy_button.setStyleSheet('border: 0px; padding: 0px;') self.copy_button.hide() box_layout = QGridLayout(self.box) box_layout.addItem(QSpacerItem(0, 0, QSizePolicy.Expanding, 0), 1, 1) box_layout.addWidget(self.noise_label, 1, 2) box_layout.addWidget(self.code_label, 1, 3) box_layout.addWidget(self.copy_button, 1, 4) box_layout.addItem(QSpacerItem(0, 0, QSizePolicy.Expanding, 0), 1, 5) self.close_button = QPushButton("Close and cancel invite") self.close_button.setAutoDefault(False) self.checkmark = QLabel() self.checkmark.setPixmap( QPixmap(resource('green_checkmark.png')).scaled(32, 32)) self.checkmark.setAlignment(Qt.AlignCenter) self.checkmark.hide() self.progress_bar = QProgressBar() self.progress_bar.setMaximum(2) self.progress_bar.setTextVisible(False) self.progress_bar.hide() layout = QGridLayout(self) layout.addItem(QSpacerItem(0, 0, 0, QSizePolicy.Expanding), 0, 0) layout.addItem(QSpacerItem(0, 0, QSizePolicy.Expanding, 0), 1, 1) layout.addItem(QSpacerItem(0, 0, QSizePolicy.Expanding, 0), 1, 2) layout.addItem(QSpacerItem(0, 0, QSizePolicy.Expanding, 0), 1, 3) layout.addItem(QSpacerItem(0, 0, QSizePolicy.Expanding, 0), 1, 4) layout.addItem(QSpacerItem(0, 0, QSizePolicy.Expanding, 0), 1, 5) layout.addLayout(header_layout, 1, 3) layout.addItem(QSpacerItem(0, 0, 0, QSizePolicy.Expanding), 2, 1) layout.addWidget(self.box_title, 3, 2, 1, 3) layout.addWidget(self.checkmark, 3, 3) layout.addWidget(self.box, 4, 2, 1, 3) layout.addWidget(self.progress_bar, 4, 2, 1, 3) layout.addWidget(self.subtext_label, 5, 2, 1, 3) layout.addItem(QSpacerItem(0, 0, 0, QSizePolicy.Expanding), 6, 1) layout.addWidget(self.close_button, 7, 3) layout.addItem(QSpacerItem(0, 0, 0, QSizePolicy.Expanding), 8, 1) self.copy_button.clicked.connect(self.on_copy_button_clicked) self.close_button.clicked.connect(self.close) self.set_box_title("Generating invite code...") self.go() # XXX