Ejemplo n.º 1
0
 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))
Ejemplo n.º 2
0
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)
Ejemplo n.º 3
0
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)
Ejemplo n.º 4
0
	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)
Ejemplo n.º 5
0
	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
Ejemplo n.º 6
0
    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()
Ejemplo n.º 7
0
    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
Ejemplo n.º 8
0
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)
Ejemplo n.º 9
0
    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 = []
Ejemplo n.º 10
0
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)
Ejemplo n.º 11
0
    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 = ()
Ejemplo n.º 12
0
    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
Ejemplo n.º 13
0
    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 = []
Ejemplo n.º 14
0
    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()
Ejemplo n.º 15
0
    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
Ejemplo n.º 16
0
    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