class SetPolicyWidget(QWidget):

    Sg_view_changed = Signal()

    def __init__(self, model: SettingsModel, parent=None):
        super(SetPolicyWidget, self).__init__(parent)

        self._model = model

        self.setAccessibleName("InfoBox")

        self.titolo = QLabel("Politica di gestione conflitti")
        self.titolo.setAccessibleName('Title2')

        self.sottotitolo = QLabel("Cambia come vengono gestiti conflitti")
        self.sottotitolo.setAccessibleName('Sottotitolo')

        self.spaceLabel = QLabel(" ")

        self.client = QRadioButton(
            "Client: le modifiche in locale sovrascrivono quelle presenti nel server"
        )
        self.manual = QRadioButton(
            "Manuale: verranno salvati entrambi i file, sarà l'utente a decidere cosa mantenere"
        )
        self.Sl_model_changed()

        layout = QVBoxLayout()
        layout.addWidget(self.titolo)
        layout.addWidget(self.sottotitolo)
        layout.addWidget(self.spaceLabel)
        sub_layout = QVBoxLayout()
        sub_layout.addWidget(self.client)
        sub_layout.addWidget(self.manual)

        layout.addLayout(sub_layout)
        self.setLayout(layout)

        self.client.clicked.connect(self.Sl_client_checked)
        self.manual.clicked.connect(self.Sl_manual_checked)

    @Slot()
    def Sl_client_checked(self):
        if self.client.isChecked():
            self.Sg_view_changed.emit()

    @Slot()
    def Sl_manual_checked(self):
        if self.manual.isChecked():
            self.Sg_view_changed.emit()

    @Slot()
    def Sl_model_changed(self):
        if self._model.get_policy() == Policy.Manual:
            self.client.setChecked(False)
            self.manual.setChecked(True)
        else:
            self.client.setChecked(True)
            self.manual.setChecked(False)
示例#2
0
class SetPathWidget(QWidget):
    Sg_view_changed = Signal(str)

    def __init__(self, model: SettingsModel, parent=None):
        super(SetPathWidget, self).__init__(parent)

        self._model = model

        self.setAccessibleName("InfoBox")

        self.debug = False
        self.titolo = QLabel()
        self.titolo.setText("Cartella sincronizzata")
        self.titolo.setAccessibleName("Title2")

        self.sottotitolo = QLabel()
        self.sottotitolo.setAccessibleName('Sottotitolo')
        self.sottotitolo.setText("Cambia il path della cartella sincronizzata")

        self.spaceLabel = QLabel(" ")

        self.path = QLabel()
        self.path.setText(self._model.get_path())

        self.change_path_button = QPushButton("Cambia")
        self.change_path_button.setMaximumWidth(150)

        layout = QVBoxLayout()
        layout.addWidget(self.titolo)
        layout.addWidget(self.sottotitolo)
        layout.addWidget(self.spaceLabel)
        sub_layout = QHBoxLayout()
        sub_layout.addWidget(self.path)
        sub_layout.addWidget(self.change_path_button)

        layout.addLayout(sub_layout)
        self.setLayout(layout)

        self.change_path_button.clicked.connect(self.Sl_show_file_dialog)

    @Slot()
    def Sl_model_changed(self):
        self.path.setText(self._model.get_path())

    @Slot()
    def Sl_show_file_dialog(self):
        dialog = QFileDialog()
        dialog.setFileMode(QFileDialog.Directory)
        dialog.setViewMode(QFileDialog.Detail)
        dialog.setOption(QFileDialog.ShowDirsOnly)
        dialog.setOption(QFileDialog.DontResolveSymlinks)

        if dialog.exec():
            # Serve per fare in modo che il test abbia una stringa da usare
            sync_path = ["test"] if self.debug else dialog.selectedFiles()
            if len(sync_path) == 1:
                self.Sg_view_changed.emit(sync_path[0])
class SetSyncTimeWidget(QWidget):
    Sg_view_changed = Signal()

    def __init__(self, model: SettingsModel, parent=None):
        super(SetSyncTimeWidget, self).__init__(parent)

        self._time_list = ["5s", "10s", "15s", "15m", "30m", "45m"]
        self._time_in_sec = []
        for curr_time in self._time_list:
            time_int = int(re.search(r'\d+', curr_time).group())
            if 'm' in curr_time:
                time_int = time_int * 60
            if 'h' in curr_time:
                time_int = time_int * 3600
            self._time_in_sec.append(time_int)

        self._model = model
        self.setAccessibleName('InfoBox')
        self._titolo = QLabel()
        self._titolo.setText("Finestra Temporale")
        self._titolo.setAccessibleName('Title2')

        self.sottotitolo = QLabel()
        self.sottotitolo.setAccessibleName('Sottotitolo')
        self.sottotitolo.setText("Seleziona finestra temporale per la sincronizzazione")

        self.spaceLabel = QLabel(" ")

        self.time_box = QComboBox()
        self.time_box.wheelEvent = lambda event: None
        self.time_box.addItems(self._time_list)
        self.Sl_model_changed()

        layout = QVBoxLayout()
        layout.addWidget(self._titolo)
        layout.addWidget(self.sottotitolo)
        layout.addWidget(self.spaceLabel)
        layout.addWidget(self.time_box)

        self.setLayout(layout)

        # connect signal
        self.time_box.currentIndexChanged.connect(self.Sl_time_checked)

    @Slot()
    def Sl_time_checked(self):
        self.Sg_view_changed.emit()

    @Slot()
    def Sl_model_changed(self):
        time = self._model.get_sync_time()
        i: int = 0
        for el in self._time_in_sec:
            if time == el:
                self.time_box.setCurrentIndex(i)
            i += 1
示例#4
0
class SyncWidget(QWidget):

    Sg_view_changed = Signal()

    def __init__(self, model: SyncModel, parent=None):
        super(SyncWidget, self).__init__(parent)

        self._model = model

        self.watch_label = QLabel(self)
        self.watch_label.setAlignment(Qt.AlignCenter)
        self.watch_label.setText("SYNC")
        self.watch_label.setAccessibleName("Title")

        self.running_label = QLabel(self)
        self.running_label.setAlignment(Qt.AlignCenter)
        self.running_label.setText("Disattivata")
        self.running_label.setAccessibleName("Subtitle")

        self.sync_button = QPushButton(self)
        self.sync_button.setIcon(QIcon(resource_path('icons/reload.png')))
        self.sync_button.setIconSize(QSize(50, 50))
        self.sync_button.setCheckable(True)
        self.sync_button.setAccessibleName('HighlightButton')

        self.menu_label = QLabel(self)
        self.menu_label.setAlignment(Qt.AlignCenter)
        self.menu_label.setText("• • •")

        # create layout
        self.layout = QVBoxLayout()
        self.layout.setAlignment(Qt.AlignCenter)
        self.layout.addWidget(self.watch_label)
        self.layout.addWidget(self.running_label)
        self.layout.addWidget(self.sync_button)
        self.layout.addWidget(self.menu_label)
        self.setLayout(self.layout)

        self.sync_button.clicked.connect(self.Sl_button_clicked)
        self.Sl_model_changed()

    @Slot()
    def Sl_button_clicked(self):
        self.Sg_view_changed.emit()

    @Slot()
    def Sl_model_changed(self):
        self.sync_button.setChecked(self._model.get_state())
        if self._model.get_state():
            self.running_label.setText("Attivata")
        else:
            self.running_label.setText("Disattivata")
class SetProfileView(QWidget):

    Sg_profile_logout = Signal()

    def __init__(self, model: NetworkModel, parent=None):
        super(SetProfileView, self).__init__(parent)
        self._model = model

        self.setAccessibleName("InfoBox")

        # Titolo
        self._titolo = QLabel('Profilo')
        self._titolo.setAccessibleName('Title2')

        self.username = QLabel()

        sub_layout_user = QHBoxLayout()
        sub_layout_user.addWidget(QLabel('Account:'))
        sub_layout_user.addWidget(self.username)
        sub_layout_user.addStretch()

        self.spaceLabel = QLabel(" ")

        # Pulsante logout
        self.logout_button = QPushButton('Logout')
        self.logout_button.setMaximumWidth(150)
        self.logout_button.clicked.connect(self.Sl_logout)

        self.buttonLayout = QHBoxLayout()
        self.buttonLayout.addWidget(self.spaceLabel)
        self.buttonLayout.addWidget(self.logout_button)
        self.buttonLayout.addWidget(self.spaceLabel)

        # Layout
        layout = QVBoxLayout()
        layout.addWidget(self._titolo)
        layout.addWidget(self.spaceLabel)
        layout.addLayout(sub_layout_user)
        layout.addLayout(self.buttonLayout)

        self.setLayout(layout)
        self.Sl_model_changed()

    @Slot()
    def Sl_model_changed(self):
        if self._model.is_logged:
            self.username.setText(self._model.get_username())

    @Slot()
    def Sl_logout(self):
        self.Sg_profile_logout.emit()
class RemoteFileView(QWidget):
    Sg_update_files_with_new_id = Signal(str)
    Sg_add_sync_file = Signal(str)
    Sg_remove_sync_file = Signal(str)
    Sg_file_status_changed = Signal()

    def __init__(self, model: MainModel, parent=None):
        super(RemoteFileView, self).__init__(parent)

        self.env_settings = QSettings()
        self._model: RemoteFileModel = model.remote_file_model
        self.settings_model: SettingsModel = model.settings_model

        self.title = QLabel("File remoti", self)
        self.title.setAlignment(Qt.AlignLeft)
        self.title.setAccessibleName("Title")

        self.refresh_button = QPushButton("Refresh", self)
        self.refresh_button.clicked.connect(self.Sl_refresh_button_clicked)
        # scroll area
        self.scrollArea = QScrollArea()
        self.scrollArea.setAccessibleName("FileScroll")
        self.scrollArea.setWidgetResizable(True)
        self.scrollArea.horizontalScrollBar().setEnabled(False)

        # contenitore per file
        self.fileWindow = QWidget(self)
        self.fileLayout = FlowLayout()
        self.fileLayout.setContentsMargins(0, 0, 0, 0)

        self.fileWindow.setParent(self.scrollArea)
        self.fileWindow.setLayout(self.fileLayout)

        self.scrollArea.setWidget(self.fileWindow)

        header_layout = QHBoxLayout()
        header_layout.addWidget(self.title)
        header_layout.addWidget(self.refresh_button)

        layout = QVBoxLayout()
        layout.addLayout(header_layout)
        layout.addWidget(self.scrollArea)
        self.setLayout(layout)

        self.Sl_model_changed()

    @Slot()
    def Sl_model_changed(self) -> None:
        data = self._model.get_data()
        # Pulisco la vista
        for i in reversed(range(self.fileLayout.count())):
            self.fileLayout.itemAt(i).widget().setParent(None)
        # Se model.get_data ha avuto eccezioni di rete restituisce None
        if data is not None:
            list_of_files, list_of_dirs = data
            # Aggiungo le cartelle
            for i in list_of_dirs:
                self.fileLayout.addWidget(RemoteDirectoryWidget(i, self))
            # Aggiungo i file
            for i in list_of_files:
                self.fileLayout.addWidget(
                    RemoteFileWidget(i, self.settings_model))
                self.fileLayout._item_list[-1].wid.Sg_add_sync_file.connect(
                    self.Sl_add_sync_file)
                self.fileLayout._item_list[-1].wid.Sg_remove_sync_file.connect(
                    self.Sl_remove_sync_file)
                self.Sg_file_status_changed.connect(
                    self.fileLayout._item_list[-1].wid.
                    Sl_on_file_status_changed)

    @Slot(str)
    def Sl_update_files_with_new_id(self, id: str) -> None:
        self.Sg_update_files_with_new_id.emit(id)

    @Slot()
    def Sl_refresh_button_clicked(self):
        self._model.folder_queue = ["LOCAL_ROOT"]
        self.Sl_model_changed()

    @Slot()
    def Sl_add_sync_file(self, id: str) -> None:
        self.Sg_add_sync_file.emit(id)

    @Slot()
    def Sl_remove_sync_file(self, id: str) -> None:
        self.Sg_remove_sync_file.emit(id)

    @Slot()
    def Sl_file_status_changed(self) -> None:
        self.Sg_file_status_changed.emit()
示例#7
0
class LoginScreen(QDialog):

    Sg_login_success = Signal()
    Sg_login_failure = Signal()

    def __init__(self, model: NetworkModel, parent=None):
        super(LoginScreen, self).__init__(parent)

        # gestione modello
        self.model = model

        # inizializzazione layout
        self.layout = QVBoxLayout()

        # label e field
        self.login_title = QLabel(self)
        self.login_title.setText("Effettua l'accesso")
        self.login_title.setAccessibleName('LoginTitle')

        self.login_label = QLabel(self)
        self.login_label.setText('Username')
        self.login_label.setAccessibleName('LoginLabel')

        self.user_field = QLineEdit(self)

        self.psw_label = QLabel(self)
        self.psw_label.setText('Password')
        self.psw_label.setAccessibleName('LoginLabel')

        self.psw_field = QLineEdit(self)
        self.psw_field.setEchoMode(QLineEdit.Password)

        self.user_field.setText(self.model.get_username())

        # pulsante invio form
        self.login_button = QPushButton(self)
        self.login_button.setText('Login')

        # gestione layout
        self.layout.setAlignment(Qt.AlignCenter)
        self.layout.addWidget(self.login_title)
        self.layout.addWidget(self.login_label)
        self.layout.addWidget(self.user_field)
        self.layout.addWidget(self.psw_label)
        self.layout.addWidget(self.psw_field)
        self.layout.addWidget(self.login_button)

        self.setLayout(self.layout)
        setQss("style.qss", self)

    @Slot()
    def Sl_model_changed(self):
        is_logged = self.model.is_logged()
        if is_logged:
            self.Sg_login_success.emit()

    def get_user(self) -> str:
        return self.user_field.text()

    def get_psw(self) -> str:
        return self.psw_field.text()

    @Slot()
    def Sl_login_fail(self):
        self.Sg_login_failure.emit()
示例#8
0
class FileView(QWidget):
    Sg_update_files_with_new_path = Signal(str)

    def __init__(self, model: FileModel, parent=None):
        super(FileView, self).__init__(parent)

        self.env_settings = QSettings()
        self._model = model

        self.title = QLabel("File locali", self)
        self.title.setAlignment(Qt.AlignLeft)
        self.title.setAccessibleName("Title")

        # scroll area
        self.scrollArea = QScrollArea()
        self.scrollArea.setAccessibleName("FileScroll")
        self.scrollArea.setWidgetResizable(True)
        self.scrollArea.horizontalScrollBar().setEnabled(False)

        # contenitore per file
        self.fileWindow = QWidget(self)
        self.fileLayout = FlowLayout()
        self.fileLayout.setContentsMargins(0, 0, 0, 0)

        self.show_path_button = QPushButton("Apri file manager", self)
        self.force_sync_button = QPushButton("Sincronizza ora", self)

        self.fileWindow.setParent(self.scrollArea)
        self.fileWindow.setLayout(self.fileLayout)

        self.scrollArea.setWidget(self.fileWindow)

        header_layout = QHBoxLayout()
        header_layout.addWidget(self.title)
        header_layout.addWidget(self.force_sync_button)
        header_layout.addWidget(self.show_path_button)

        layout = QVBoxLayout()
        layout.addLayout(header_layout)
        layout.addWidget(self.scrollArea)
        self.setLayout(layout)

        self.Sl_model_changed()

    @Slot()
    def Sl_show_path_button_clicked(self) -> None:
        path = QUrl.fromUserInput(self.env_settings.value("sync_path"))
        QDesktopServices.openUrl(path)

    @Slot()
    def Sl_model_changed(self) -> None:
        list_of_files, list_of_dirs = self._model.get_data()

        for i in reversed(range(self.fileLayout.count())):
            self.fileLayout.itemAt(i).widget().setParent(None)
        for i in list_of_dirs:
            self.fileLayout.addWidget(LocalDirectoryWidget(i, self))
        for i in list_of_files:
            self.fileLayout.addWidget(LocalFileWidget(i))

    @Slot(str)
    def Sl_update_files_with_new_path(self, path: str) -> None:
        self.Sg_update_files_with_new_path.emit(path)

    def toggle_files_update(self, file_path: str, is_sync: bool) -> None:
        for widget in self.fileLayout._item_list:
            if type(widget.wid) == LocalFileWidget:
                if os.path.samefile(widget.wid.path, file_path):
                    widget.wid.show_synced(is_sync)
示例#9
0
class SetQuotaDiskWidget(QWidget):
    Sg_view_changed = Signal()

    def __init__(self, model: SettingsModel, parent=None):
        super(SetQuotaDiskWidget, self).__init__(parent)

        self._model = model

        self.setAccessibleName("InfoBox")

        self.title = QLabel()
        self.title.setText("Spazio di archiviazione")
        self.title.setAccessibleName("Title2")

        self.sottotitolo = QLabel()
        self.sottotitolo.setAccessibleName('Sottotitolo')
        self.sottotitolo.setText(
            "Cambia lo spazio di archiviazione destinato alla cartella sincronizzata"
        )

        # Barra riempimento disco
        self.progress_label = QLabel()
        self.progress_label.setText("Spazio occupato:")

        self.disk_progress = QProgressBar()
        self.disk_progress.setFormat("")

        self.disk_quota = QLabel()

        # Modifica spazio dedicato
        self.spaceLabel = QLabel(" ")

        self.dedicated_space = QLineEdit()
        self.dedicated_space.setValidator(QDoubleValidator())

        self.sizes_box = QComboBox()
        self.sizes_box.wheelEvent = lambda event: None
        _path_size = bitmath.parse_string(model.convert_size(model.get_size()))
        _disk_free = bitmath.parse_string(
            model.convert_size(model.get_free_disk()))

        self.populate_size_box(_path_size, _disk_free)

        self.change_quota_button = QPushButton("Cambia quota disco")
        self.change_quota_button.setMaximumWidth(150)

        self.change_quota_button.clicked.connect(
            self.Sl_dedicated_space_changed)
        self.dedicated_space.returnPressed.connect(
            self.Sl_dedicated_space_changed)

        self.buttonLayout = QHBoxLayout()
        self.buttonLayout.addWidget(self.spaceLabel)
        self.buttonLayout.addWidget(self.change_quota_button)
        self.buttonLayout.addWidget(self.spaceLabel)

        set_space_layout = QHBoxLayout()
        set_space_layout.addWidget(self.dedicated_space)
        set_space_layout.addWidget(self.sizes_box)

        quota_layout = QHBoxLayout()
        quota_layout.setAlignment(Qt.AlignLeft)
        quota_layout.addWidget(self.progress_label)
        quota_layout.addWidget(self.disk_quota)

        # layout
        disk_layout = QVBoxLayout()
        disk_layout.setAlignment(Qt.AlignLeft)
        disk_layout.addWidget(self.title)
        disk_layout.addWidget(self.sottotitolo)
        disk_layout.addWidget(self.spaceLabel)
        disk_layout.addLayout(quota_layout)
        disk_layout.addWidget(self.disk_progress)
        disk_layout.addWidget(self.spaceLabel)
        disk_layout.addLayout(set_space_layout)
        disk_layout.addLayout(self.buttonLayout)

        self.setLayout(disk_layout)
        self.Sl_model_changed()

    @Slot()
    def Sl_dedicated_space_changed(self):
        self.Sg_view_changed.emit()

    @Slot()
    def Sl_model_changed(self):
        """
        Slot collegato ai segnali del model, aggiorna la vista con i nuovi valori
        :return: None
        """

        # Prendo quota disco con unità e il peso della cartella senza unità (Byte default)
        new_max_quota = self._model.get_quota_disco()
        _folder_size = self._model.get_size()

        # Converto ad oggetto bitmath il peso della cartella e la quota disco
        folder_size_parsed = bitmath.parse_string(
            self._model.convert_size(_folder_size))
        quota_disco_parsed = bitmath.parse_string(new_max_quota)

        # Imposto la textbox che mi dice quanto peso ho occupato su quello disponibile
        self.disk_quota.setText(
            f"{folder_size_parsed} su {new_max_quota} in uso")

        free_disk_parsed = bitmath.parse_string(
            self._model.convert_size(self._model.get_free_disk()))

        # Imposto la textbox che richiede input
        if not self.dedicated_space.hasFocus():
            self.dedicated_space.setText(str(quota_disco_parsed.value))
            # Creo i nuovi valori della combobox
            if not self.sizes_box.hasFocus():
                self.populate_size_box(folder_size_parsed, free_disk_parsed)
                # Imposto l'item in focus della combobox
                self.sizes_box.setCurrentText(quota_disco_parsed.unit)

        # Prendo dimensione corrente della sync folder e della quota disco
        # e metto in proporzione con quotadisco:100=syncfolder:x
        _progress_bar_max_value = 100
        _tmp = folder_size_parsed.to_Byte().value * _progress_bar_max_value
        _progress_bar_current_percentage = _tmp / quota_disco_parsed.to_Byte(
        ).value

        # Inserisco nuovi valori nella progress bar
        self.disk_progress.setRange(0, _progress_bar_max_value)
        self.disk_progress.setValue(_progress_bar_current_percentage)

        # Se la cartella occupa più spazio di quanto voluto allora la porto a quanto occupa
        if quota_disco_parsed < folder_size_parsed and not self.dedicated_space.hasFocus(
        ):
            self.dedicated_space.setText(str(folder_size_parsed.value))
            self.sizes_box.setCurrentText(folder_size_parsed.unit)
            self.Sg_view_changed.emit()

    def populate_size_box(
        self,
        _min: str,
        _max: str,
    ) -> None:
        """
        This method populates the size box with only the available units
        ex hdd has only <1gb so gb will not be used, the current folder is
        heavier than 1mb so kb will not be used.
        :param _min: minimum value with unit ex 10 KiB or just 'KiB'
        :param _max: maximum value with unit ex 10 KiB or just 'KiB'
        :return: None
        """
        _sizes = "Byte", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"
        # Converto in ogni caso a string, in caso in cui venga passato un oggetto
        # tipo bitmath

        _min = str(_min)
        _max = str(_max)

        # Rimuovo eventuali numeri e caratteri extra, tengo solo l'unità di misura
        _min = ''.join(i for i in _min if not i.isdigit() and i != '.')
        _max = ''.join(i for i in _max if not i.isdigit() and i != '.')

        # Rimuovo possibili spazi ad inizio e fine stringa
        _min = _min.strip()
        _max = _max.strip()

        # Rimuovo dal vettore di possibili unità di misura tutte le unità sotto il lower bound
        lower_bound = _sizes[_sizes.index(_min):]
        # Rimuovo dal vettore di possibili unità di misura tutte le unità sopra l'upper bound
        upper_bound = lower_bound[:lower_bound.index(_max) + 1]

        # Pulisco il vecchio combo box
        self.sizes_box.clear()

        # Inserisco nuovi valori
        self.sizes_box.addItems(upper_bound)