コード例 #1
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])
コード例 #2
0
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()
コード例 #3
0
class UITransferROIWindow:
    def setup_ui(self, transfer_roi_window_instance,
                 signal_roi_transferred_to_fixed_container,
                 signal_roi_transferred_to_moving_container):
        self.patient_dict_container = PatientDictContainer()
        self.moving_dict_container = MovingDictContainer()
        self.fixed_image_initial_rois = self.patient_dict_container.get("rois")
        self.moving_image_initial_rois = self.moving_dict_container.get("rois")
        self.transfer_roi_window_instance = transfer_roi_window_instance
        self.signal_roi_transferred_to_fixed_container = \
            signal_roi_transferred_to_fixed_container
        self.signal_roi_transferred_to_moving_container = \
            signal_roi_transferred_to_moving_container
        self.fixed_to_moving_rois = {}
        self.moving_to_fixed_rois = {}
        self.add_suffix = True
        self.progress_window = ProgressWindow(
            self, QtCore.Qt.WindowTitleHint | QtCore.Qt.WindowCloseButtonHint)
        self.progress_window.setFixedSize(250, 100)
        self.progress_window.signal_loaded \
            .connect(self.onTransferRoiFinished)
        self.progress_window.signal_error.connect(self.onTransferRoiError)

        self.init_layout()

    def retranslate_ui(self, transfer_roi_window_instance):
        _translate = QtCore.QCoreApplication.translate
        transfer_roi_window_instance.setWindowTitle(
            _translate("TransferRoiWindowInstance",
                       "OnkoDICOM - Transfer Region of Interest"))
        self.add_suffix_checkbox.setText(
            _translate("AddSuffixCheckBox", "Add Suffix"))
        self.patient_A_label.setText(
            _translate("PatientAROILabel", "First Image Set ROIs"))
        self.patient_B_label.setText(
            _translate("PatientBROILabel", "Second Image Set ROIs"))
        self.transfer_all_rois_to_patient_B_button.setText(
            _translate("ROITransferToBButton", "All"))
        self.transfer_all_rois_to_patient_A_button.setText(
            _translate("ROITransferToAButton", "All"))
        self.save_button.setText(_translate("SaveButton", "Save"))
        self.reset_button.setText(_translate("ResetButton", "Reset"))

    def init_layout(self):
        """
        Initialize the layout for the Transfer ROI Window.
        """
        if platform.system() == 'Darwin':
            self.stylesheet_path = "res/stylesheet.qss"
        else:
            self.stylesheet_path = "res/stylesheet-win-linux.qss"
        stylesheet = open(resource_path(self.stylesheet_path)).read()
        window_icon = QIcon()
        window_icon.addPixmap(QPixmap(resource_path("res/images/icon.ico")),
                              QIcon.Normal, QIcon.Off)
        self.transfer_roi_window_instance.setObjectName(
            "TransferRoiWindowInstance")
        self.transfer_roi_window_instance.setWindowIcon(window_icon)

        # Creating a grid layout to hold all elements
        self.transfer_roi_window_grid_layout = QGridLayout()
        self.transfer_roi_window_grid_layout.setColumnStretch(0, 1)
        self.transfer_roi_window_grid_layout.setColumnStretch(1, 1)
        self.transfer_roi_window_grid_layout.setColumnStretch(2, 1)

        self.init_patient_labels()
        self.init_transfer_arrow_buttons()
        self.init_patient_A_initial_roi_list()
        self.init_patient_B_rois_to_A_layout()
        self.init_patient_A_rois_to_B_layout()
        self.init_patient_B_initial_roi_list()
        self.init_add_suffix_checkbox()
        self.init_save_and_reset_button_layout()

        # Create a new central widget to hold the grid layout
        self.transfer_roi_window_instance_central_widget = QWidget()
        self.transfer_roi_window_instance_central_widget.setLayout(
            self.transfer_roi_window_grid_layout)
        self.retranslate_ui(self.transfer_roi_window_instance)
        self.transfer_roi_window_instance.setStyleSheet(stylesheet)
        self.transfer_roi_window_instance.setCentralWidget(
            self.transfer_roi_window_instance_central_widget)
        QtCore.QMetaObject.connectSlotsByName(
            self.transfer_roi_window_instance)

    def init_transfer_arrow_buttons(self):
        """
        Initialize the layout for arrow buttons

        """
        self.transfer_all_rois_to_patient_B_button = QPushButton()
        self.transfer_all_rois_to_patient_B_button.setObjectName(
            "ROITransferToBButton")

        transfer_all_rois_to_patient_B_icon = QtGui.QIcon()
        transfer_all_rois_to_patient_B_icon.addPixmap(
            QtGui.QPixmap(
                resource_path('res/images/btn-icons/forward_slide_icon.png')),
            QtGui.QIcon.Normal, QtGui.QIcon.On)
        self.transfer_all_rois_to_patient_B_button \
            .setIcon(transfer_all_rois_to_patient_B_icon)
        self.transfer_all_rois_to_patient_B_button.clicked.connect(
            self.transfer_all_rois_to_patient_B_button_clicked)
        self.transfer_roi_window_grid_layout.addWidget(
            self.transfer_all_rois_to_patient_B_button, 1, 1)

        self.transfer_all_rois_to_patient_A_button = QPushButton()
        self.transfer_all_rois_to_patient_A_button.setObjectName(
            "ROITransferToAButton")
        self.transfer_all_rois_to_patient_A_button.setMaximumWidth(100)
        transfer_all_rois_to_patient_A_icon = QtGui.QIcon()
        transfer_all_rois_to_patient_A_icon.addPixmap(
            QtGui.QPixmap(
                resource_path('res/images/btn-icons/backward_slide_icon.png')),
            QtGui.QIcon.Normal, QtGui.QIcon.On)
        self.transfer_all_rois_to_patient_A_button \
            .setIcon(transfer_all_rois_to_patient_A_icon)
        self.transfer_all_rois_to_patient_A_button.clicked.connect(
            self.transfer_all_rois_to_patient_A_button_clicked)
        self.transfer_roi_window_grid_layout.addWidget(
            self.transfer_all_rois_to_patient_A_button, 2, 1)

    def transfer_all_rois_to_patient_B_button_clicked(self):
        """
        This function is triggered when the right arrow button is clicked.
        """
        self.fixed_to_moving_rois.clear()
        self.patient_A_rois_to_B_list_widget.clear()

        for i in range(0, len(self.fixed_image_initial_rois)):
            self.patient_A_initial_roi_double_clicked(
                self.patient_A_initial_rois_list_widget.item(i))

    def transfer_all_rois_to_patient_A_button_clicked(self):
        """
        This function is triggered when the left arrow button is clicked.
        """
        self.moving_to_fixed_rois.clear()
        self.patient_B_rois_to_A_list_widget.clear()

        for i in range(0, len(self.moving_image_initial_rois)):
            self.patient_B_initial_roi_double_clicked(
                self.patient_B_initial_rois_list_widget.item(i))

    def init_add_suffix_checkbox(self):
        """
        Initialize the layout for add suffix checkbox
        """
        self.add_suffix_checkbox = QCheckBox()
        self.add_suffix_checkbox.setObjectName("AddSuffixCheckBox")
        self.add_suffix_checkbox.setChecked(self.add_suffix)
        self.add_suffix_checkbox.clicked.connect(
            self.add_suffix_checkbox_clicked)
        self.transfer_roi_window_grid_layout.addWidget(
            self.add_suffix_checkbox, 3, 0)

    def init_patient_labels(self):
        """
        Initialize the layout for two patient labels
        """
        self.patient_A_label = QLabel()
        self.patient_A_label.setObjectName("PatientAROILabel")
        self.patient_A_label.setMinimumHeight(50)
        self.patient_A_label.setAlignment(Qt.AlignCenter)
        self.patient_A_label.setStyleSheet(
            "QLabel { background-color : green; color : white; "
            "font-size: 15pt; font-weight: bold;}")

        self.patient_B_label = QLabel()
        self.patient_B_label.setObjectName("PatientBROILabel")
        self.patient_B_label.setMinimumHeight(50)
        self.patient_B_label.setAlignment(Qt.AlignCenter)
        self.patient_B_label.setStyleSheet(
            "QLabel { background-color : red; color : white; "
            "font-size: 15pt; font-weight: bold;}")

        self.transfer_roi_window_grid_layout.addWidget(self.patient_A_label, 0,
                                                       0)
        self.transfer_roi_window_grid_layout.addWidget(self.patient_B_label, 0,
                                                       2)

    def init_save_and_reset_button_layout(self):
        """
        Initialize the layout for save and reset buttons
        """
        self.reset_and_save_buttons_layout = QHBoxLayout()
        self.reset_button = QPushButton()
        self.reset_button.setObjectName("ResetButton")
        self.reset_button.clicked.connect(self.reset_clicked)
        self.save_button = QPushButton()
        self.save_button.setObjectName("SaveButton")
        self.save_button.setDisabled(True)
        self.save_button.clicked.connect(self.transfer_roi_clicked)

        self.reset_and_save_buttons_layout.setAlignment(Qt.AlignRight)
        self.reset_and_save_buttons_layout.addWidget(self.reset_button)
        self.reset_and_save_buttons_layout.addWidget(self.save_button)

        # Create a widget to hold Reset and Save buttons
        self.reset_and_save_button_central_widget = QWidget()
        self.reset_and_save_button_central_widget.setLayout(
            self.reset_and_save_buttons_layout)

        self.transfer_roi_window_grid_layout.addWidget(
            self.reset_and_save_button_central_widget, 3, 2)

    def add_suffix_checkbox_clicked(self):
        """
        This function is triggered when the add suffix checkbox is clicked
        """
        self.add_suffix = self.add_suffix_checkbox.isChecked()

    def init_patient_B_rois_to_A_layout(self):
        """
        Initialize the layout for transfer rois from B to A container
        """
        # Create scrolling area widget to contain the content.
        self.patient_B_rois_to_A_list_widget = QListWidget(self)
        self.transfer_roi_window_grid_layout \
            .addWidget(self.patient_B_rois_to_A_list_widget, 2, 0)
        self.patient_B_rois_to_A_list_widget.itemDoubleClicked.connect(
            self.patient_B_to_A_rois_double_clicked)

    def init_patient_A_rois_to_B_layout(self):
        """
        Initialize the layout for transfer rois from A to B container
        """
        self.patient_A_rois_to_B_list_widget = QListWidget(self)
        self.transfer_roi_window_grid_layout \
            .addWidget(self.patient_A_rois_to_B_list_widget, 1, 2)
        self.patient_A_rois_to_B_list_widget.itemDoubleClicked.connect(
            self.patient_A_to_B_rois_double_clicked)

    def init_patient_A_initial_roi_list(self):
        """
        Initialize the layout for patient A's roi list
        """
        self.patient_A_initial_rois_list_widget = QListWidget(self)
        self.patient_A_initial_rois_list_widget.itemDoubleClicked.connect(
            self.patient_A_initial_roi_double_clicked)
        for idx in self.fixed_image_initial_rois:
            roi_label = QListWidgetItem(
                self.fixed_image_initial_rois[idx]['name'])
            roi_label.setForeground(Qt.darkGreen)
            roi_label.setData(Qt.UserRole, self.fixed_image_initial_rois[idx])
            self.patient_A_initial_rois_list_widget.addItem(roi_label)
        self.transfer_roi_window_grid_layout.addWidget(
            self.patient_A_initial_rois_list_widget, 1, 0)

    def init_patient_B_initial_roi_list(self):
        """
        Initialize the layout for patient B's roi list
        """
        self.patient_B_initial_rois_list_widget = QListWidget(self)
        self.patient_B_initial_rois_list_widget.itemDoubleClicked.connect(
            self.patient_B_initial_roi_double_clicked)
        for idx in self.moving_image_initial_rois:
            roi_label = QListWidgetItem(
                self.moving_image_initial_rois[idx]['name'])
            roi_label.setForeground(Qt.red)
            roi_label.setData(Qt.UserRole, self.moving_image_initial_rois[idx])

            self.patient_B_initial_rois_list_widget.addItem(roi_label)
        self.transfer_roi_window_grid_layout.addWidget(
            self.patient_B_initial_rois_list_widget, 2, 2)

    def patient_A_to_B_rois_double_clicked(self, item):
        """
        This function is triggered when a roi in "A to B" list is
        double-clicked.
        """
        roi_to_remove = item.data(Qt.UserRole)
        to_delete_value = roi_to_remove['name']
        self.fixed_to_moving_rois.pop(to_delete_value)
        self.patient_A_rois_to_B_list_widget.clear()
        for key, value in self.fixed_to_moving_rois.items():
            roi_label = QListWidgetItem(value)
            roi_label.setForeground(Qt.red)
            roi_label.setData(Qt.UserRole, {'name': key})
            self.patient_A_rois_to_B_list_widget.addItem(roi_label)
        if self.transfer_list_is_empty():
            self.save_button.setDisabled(True)

    def patient_B_to_A_rois_double_clicked(self, item):
        """
        This function is triggered when a roi in "B to A" list is
        double-clicked.
        """
        roi_to_remove = item.data(Qt.UserRole)
        to_delete_value = roi_to_remove['name']
        self.moving_to_fixed_rois.pop(to_delete_value)
        self.patient_B_rois_to_A_list_widget.clear()
        for key, value in self.moving_to_fixed_rois.items():
            roi_label = QListWidgetItem(value)
            roi_label.setForeground(Qt.red)
            roi_label.setData(Qt.UserRole, {'name': key})
            self.patient_B_rois_to_A_list_widget.addItem(roi_label)
        if self.transfer_list_is_empty():
            self.save_button.setDisabled(True)

    def patient_A_initial_roi_double_clicked(self, item):
        """
        This function is triggered when a roi in patient A's roi list is
        double-clicked.
        """
        roi_to_add = item.data(Qt.UserRole)
        transferred_roi_name = roi_to_add['name']

        # If the clicked roi is already transferred, return
        if transferred_roi_name in self.fixed_to_moving_rois.keys():
            QMessageBox.about(self, "Transfer Failed",
                              "Chosen ROI has already been transferred!")
            return
        # Create a set to store all current roi names in target patient
        # including both initial rois name and added roi names so far
        patient_B_initial_roi_name_list = set()

        for item in self.fixed_to_moving_rois.values():
            patient_B_initial_roi_name_list.add(item)
        for idx in self.moving_image_initial_rois:
            patient_B_initial_roi_name_list.add(
                self.moving_image_initial_rois[idx]['name'])

        # Check if clicked roi name has duplicate
        # in patient B's initial roi names list
        if transferred_roi_name in patient_B_initial_roi_name_list:
            if self.add_suffix:
                transferred_roi_name = generate_non_duplicated_name(
                    transferred_roi_name, patient_B_initial_roi_name_list)
            else:
                QMessageBox.about(
                    self, "Transfer Failed", "Duplicated ROI name. "
                    "Please consider adding suffix.")
                return

        # Add clicked roi to transferred list
        self.fixed_to_moving_rois[roi_to_add['name']] = transferred_roi_name
        roi_label = QListWidgetItem(transferred_roi_name)
        roi_label.setForeground(Qt.red)
        roi_label.setData(Qt.UserRole, roi_to_add)
        self.patient_A_rois_to_B_list_widget.addItem(roi_label)
        self.save_button.setDisabled(False)

    def patient_B_initial_roi_double_clicked(self, item):
        """
        This function is triggered when a roi in patient B's roi list is
        double-clicked.
        """
        roi_to_add = item.data(Qt.UserRole)
        transferred_roi_name = roi_to_add['name']

        # If the clicked roi is already transferred, return
        if transferred_roi_name in self.moving_to_fixed_rois.keys():
            QMessageBox.about(self, "Transfer Failed",
                              "Chosen ROI has already been transferred!")
            return

        # Create a set to store all current roi names in target patient
        # including both initial rois name and added roi names so far
        patient_A_current_roi_name_list = set()

        for item in self.moving_to_fixed_rois.values():
            patient_A_current_roi_name_list.add(item)

        for idx in self.fixed_image_initial_rois:
            patient_A_current_roi_name_list.add(
                self.fixed_image_initial_rois[idx]['name'])

        # Check if clicked roi name has duplicate in
        # target patient's roi names list
        if transferred_roi_name in patient_A_current_roi_name_list:
            # if add suffix is ticked, iteratively try adding suffix
            # from _A to _Z, stop when no duplicate found
            if self.add_suffix:
                transferred_roi_name = generate_non_duplicated_name(
                    transferred_roi_name, patient_A_current_roi_name_list)
            else:
                QMessageBox.about(
                    self, "Transfer Failed", "Duplicated ROI name. "
                    "Please consider adding suffix.")
                return

        # Add clicked roi to transferred list
        self.moving_to_fixed_rois[roi_to_add['name']] = transferred_roi_name
        roi_label = QListWidgetItem(transferred_roi_name)
        roi_label.setForeground(Qt.red)
        roi_label.setData(Qt.UserRole, roi_to_add)
        self.patient_B_rois_to_A_list_widget.addItem(roi_label)
        self.save_button.setDisabled(False)

    def reset_clicked(self):
        """
        This function is triggered when reset button is clicked.
        """
        self.fixed_to_moving_rois.clear()
        self.moving_to_fixed_rois.clear()
        self.patient_A_rois_to_B_list_widget.clear()
        self.patient_B_rois_to_A_list_widget.clear()
        self.save_button.setDisabled(True)

    def transfer_list_is_empty(self):
        """
        This function is to check if the transfer list is empty
        """
        return len(self.fixed_to_moving_rois) == 0 \
               and len(self.moving_to_fixed_rois) == 0

    def save_clicked(self, interrupt_flag, progress_callback):
        """
        This function is triggered when the save button is clicked. It contains
        all steps in the ROI transferring process.

        :param interrupt_flag: interrupt flag to stop process
        :param progress_callback: signal that receives the current
                                  progress of the loading.
        """
        progress_callback.emit(("Converting images to sitk", 0))

        # check if interrupt flag is set
        if not check_interrupt_flag(interrupt_flag):
            return False

        rtss = self.patient_dict_container.get("dataset_rtss")

        # get sitk for the fixed image
        dicom_image = read_dicom_image_to_sitk(
            self.patient_dict_container.filepaths)

        if not check_interrupt_flag(interrupt_flag):
            return False

        # get array of roi indexes from sitk images
        rois_images_fixed = transform_point_set_from_dicom_struct(
            dicom_image,
            rtss,
            self.fixed_to_moving_rois.keys(),
            spacing_override=None,
            interrupt_flag=interrupt_flag)

        moving_rtss = self.moving_dict_container.get("dataset_rtss")

        if not check_interrupt_flag(interrupt_flag):
            return False

        # get sitk for the moving image
        moving_dicom_image = read_dicom_image_to_sitk(
            self.moving_dict_container.filepaths)

        if not check_interrupt_flag(interrupt_flag):
            return False

        # get array of roi indexes from sitk images
        progress_callback \
            .emit(("Retrieving ROIs from \nboth image sets", 20))

        # check if interrupt flag is set
        if not check_interrupt_flag(interrupt_flag):
            return False

        if moving_rtss:
            rois_images_moving = transform_point_set_from_dicom_struct(
                moving_dicom_image,
                moving_rtss,
                self.moving_to_fixed_rois.keys(),
                spacing_override=None,
                interrupt_flag=interrupt_flag)
        else:
            rois_images_moving = ([], [])

        if not check_interrupt_flag(interrupt_flag):
            return False

        tfm = self.moving_dict_container.get("tfm")

        progress_callback.emit(
            ("Transfering ROIs from moving \nto fixed image set", 40))

        # check if interrupt flag is set
        if not check_interrupt_flag(interrupt_flag):
            return False

        # transform roi from moving_dict to fixed_dict
        self.transfer_rois(self.moving_to_fixed_rois, tfm, dicom_image,
                           rois_images_moving, self.patient_dict_container)

        progress_callback.emit(
            ("Transfering ROIs from fixed \nto moving image set", 60))

        if not check_interrupt_flag(interrupt_flag):
            return False

        # transform roi from moving_dict to fixed_dict
        self.transfer_rois(self.fixed_to_moving_rois, tfm.GetInverse(),
                           moving_dicom_image, rois_images_fixed,
                           self.moving_dict_container)

        progress_callback.emit(("Saving ROIs to RTSS", 80))

        # check if interrupt flag is set
        if not check_interrupt_flag(interrupt_flag):
            return False
        progress_callback.emit(("Reloading window", 90))
        return True

    def transfer_roi_clicked(self):
        """
        telling progress window to start ROI transfer
        """
        self.progress_window.start(self.save_clicked)

    def onTransferRoiError(self, exception):
        """
        This function is triggered when there is an error in the
        ROI transferring process.

        :param exception: exception thrown
        """
        QMessageBox.about(self.progress_window, "Unable to transfer ROIs",
                          "Please check your image set and ROI data.")
        self.progress_window.close()

    def onTransferRoiFinished(self, result):
        """
        This function is triggered when ROI transferring process is finished.
        """
        # emit changed dataset to structure_modified function and
        # auto_save_roi function
        if result[0] is True:
            if len(self.fixed_to_moving_rois) > 0:
                self.signal_roi_transferred_to_moving_container.emit(
                    (self.moving_dict_container.get("dataset_rtss"), {
                        "transfer": None
                    }))
            if len(self.moving_to_fixed_rois) > 0:
                self.signal_roi_transferred_to_fixed_container.emit(
                    (self.patient_dict_container.get("dataset_rtss"), {
                        "transfer": None
                    }))
            self.progress_window.close()
            QMessageBox.about(self.transfer_roi_window_instance, "Saved",
                              "ROIs are successfully transferred!")
        else:
            QMessageBox.about(self.transfer_roi_window_instance, "Cancelled",
                              "ROIs Transfer is cancelled.")
        self.closeWindow()

    def transfer_rois(self, transfer_dict, tfm, reference_image,
                      original_roi_list, patient_dict_container):
        """
        Converting (transferring) ROIs from one image set to another and save
        the transferred rois to rtss.
        :param transfer_dict: dictionary of rois to be transfer.
        key is original roi names, value is the name after transferred.
        :param original_roi_list: tuple of sitk rois from the base image.
        :param tfm: the tfm that contains information for transferring rois
        :param reference_image: the reference (base) image
        :param patient_dict_container: container of the transfer image set.

        """
        for roi_name, new_roi_name in transfer_dict.items():
            for index, name in enumerate(original_roi_list[1]):
                if name == roi_name:
                    sitk_image = original_roi_list[0][index]
                    new_contour = apply_linear_transform(
                        input_image=sitk_image,
                        transform=tfm,
                        reference_image=reference_image,
                        is_structure=True)
                    contour = sitk.GetArrayViewFromImage(new_contour)
                    contours = np.transpose(contour.nonzero())
                    self.save_roi_to_patient_dict_container(
                        contours, new_roi_name, patient_dict_container)

    def save_roi_to_patient_dict_container(self, contours, roi_name,
                                           patient_dict_container):
        """
        Save the transferred ROI to the corresponding rtss.

        :param contours: np array of coordinates of the ROI to be saved.
        :param roi_name: name of the ROI to be saved
        :param patient_dict_container: container of the transfer image set.

        """
        pixels_coords_dict = {}
        slice_ids_dict = get_dict_slice_to_uid(patient_dict_container)
        total_slices = len(slice_ids_dict)
        for contour in contours:
            curr_slice_id = total_slices - contour[0]
            if curr_slice_id >= total_slices:
                curr_slice_id = 0
            if curr_slice_id not in pixels_coords_dict:
                pixels_coords_dict[curr_slice_id] = [
                    tuple([contour[2], contour[1]])
                ]
            else:
                pixels_coords_dict[curr_slice_id].append(
                    tuple([contour[2], contour[1]]))

        rois_to_save = {}
        for key in pixels_coords_dict.keys():
            coords = pixels_coords_dict[key]
            polygon_list = ROI.calculate_concave_hull_of_points(coords)
            if len(polygon_list) > 0:
                rois_to_save[key] = {
                    'ds': patient_dict_container.dataset[key],
                    'coords': polygon_list
                }
        roi_list = ROI.convert_hull_list_to_contours_data(
            rois_to_save, patient_dict_container)

        if len(roi_list) > 0:
            print("Saving ", roi_name)
            if isinstance(patient_dict_container, MovingDictContainer):
                new_rtss = ROI.create_roi(
                    patient_dict_container.get("dataset_rtss"),
                    roi_name,
                    roi_list,
                    rtss_owner="MOVING")
                self.moving_dict_container.set("dataset_rtss", new_rtss)
                self.moving_dict_container.set("rtss_modified", True)
            else:
                new_rtss = ROI.create_roi(
                    patient_dict_container.get("dataset_rtss"), roi_name,
                    roi_list)
                self.patient_dict_container.set("dataset_rtss", new_rtss)
                self.patient_dict_container.set("rtss_modified", True)

    def closeWindow(self):
        """
        function to close transfer roi window
        """
        self.close()
コード例 #4
0
class ArrayRequirementEditor:
    def __init__(self, parent: QWidget, parent_layout: QVBoxLayout,
                 line_layout: QHBoxLayout, resource_database: ResourceDatabase,
                 requirement: RequirementArrayBase):
        self._editors = []
        self.resource_database = resource_database
        self._array_type = type(requirement)

        # the parent is added to a layout which is added to parent_layout, so we
        index = parent_layout.indexOf(line_layout) + 1

        self.group_box = QGroupBox(parent)
        self.group_box.setStyleSheet("QGroupBox { margin-top: 2px; }")
        parent_layout.insertWidget(index, self.group_box)
        self.item_layout = QVBoxLayout(self.group_box)
        self.item_layout.setContentsMargins(8, 2, 2, 6)
        self.item_layout.setAlignment(Qt.AlignTop)

        self.new_item_button = QPushButton(self.group_box)
        self.new_item_button.setMaximumWidth(75)
        self.new_item_button.setText("New Row")
        self.new_item_button.clicked.connect(self.new_item)

        self.comment_text_box = QLineEdit(parent)
        self.comment_text_box.setText(requirement.comment or "")
        self.comment_text_box.setPlaceholderText("Comment")
        line_layout.addWidget(self.comment_text_box)

        for item in requirement.items:
            self._create_item(item)

        self.item_layout.addWidget(self.new_item_button)

    def _create_item(self, item: Requirement):
        def on_remove():
            self._editors.remove(nested_editor)
            nested_editor.deleteLater()

        nested_editor = RequirementEditor(self.group_box,
                                          self.item_layout,
                                          self.resource_database,
                                          on_remove=on_remove)
        nested_editor.create_specialized_editor(item)
        self._editors.append(nested_editor)

    def new_item(self):
        self._create_item(
            _create_default_resource_requirement(self.resource_database))

        self.item_layout.removeWidget(self.new_item_button)
        self.item_layout.addWidget(self.new_item_button)

    def deleteLater(self):
        self.group_box.deleteLater()
        self.comment_text_box.deleteLater()
        for editor in self._editors:
            editor.deleteLater()
        self.new_item_button.deleteLater()

    @property
    def current_requirement(self) -> RequirementArrayBase:
        comment = self.comment_text_box.text().strip()
        if comment == "":
            comment = None

        return self._array_type(
            [editor.current_requirement for editor in self._editors],
            comment=comment,
        )
コード例 #5
0
class ItemRow:
    def __init__(self, parent: QWidget, parent_layout: QVBoxLayout,
                 resource_database: ResourceDatabase,
                 item: ResourceRequirement, rows: List["ItemRow"]):
        self.parent = parent
        self.resource_database = resource_database
        self._rows = rows
        rows.append(self)

        self.layout = QHBoxLayout()
        self.layout.setObjectName(f"Box layout for {item.resource.long_name}")
        parent_layout.addLayout(self.layout)

        self.resource_type_combo = _create_resource_type_combo(
            item.resource.resource_type, parent)
        self.resource_type_combo.setMinimumWidth(75)
        self.resource_type_combo.setMaximumWidth(75)

        self.resource_name_combo = _create_resource_name_combo(
            self.resource_database, item.resource.resource_type, item.resource,
            self.parent)

        self.negate_combo = QComboBox(parent)
        self.negate_combo.addItem("≥", False)
        self.negate_combo.addItem("<", True)
        self.negate_combo.setCurrentIndex(int(item.negate))
        self.negate_combo.setMinimumWidth(40)
        self.negate_combo.setMaximumWidth(40)

        self.amount_edit = QLineEdit(parent)
        self.amount_edit.setValidator(QIntValidator(1, 10000))
        self.amount_edit.setText(str(item.amount))
        self.amount_edit.setMinimumWidth(45)
        self.amount_edit.setMaximumWidth(45)

        self.remove_button = QPushButton(parent)
        self.remove_button.setText("X")
        self.remove_button.setMaximumWidth(20)

        self.layout.addWidget(self.resource_type_combo)
        self.layout.addWidget(self.resource_name_combo)
        self.layout.addWidget(self.negate_combo)
        self.layout.addWidget(self.amount_edit)
        self.layout.addWidget(self.remove_button)

        self.resource_type_combo.currentIndexChanged.connect(self._update_type)
        self.remove_button.clicked.connect(self._delete_row)

    def _update_type(self):
        old_combo = self.resource_name_combo
        self.resource_name_combo = _create_resource_name_combo(
            self.resource_database, self.resource_type_combo.currentData(),
            None, self.parent)

        self.layout.replaceWidget(old_combo, self.resource_name_combo)
        old_combo.deleteLater()

    def _delete_row(self):
        self.resource_type_combo.deleteLater()
        self.resource_name_combo.deleteLater()
        self.negate_combo.deleteLater()
        self.amount_edit.deleteLater()
        self.remove_button.deleteLater()
        self.layout.deleteLater()
        self._rows.remove(self)

    @property
    def current_individual(self) -> ResourceRequirement:
        return ResourceRequirement(self.resource_name_combo.currentData(),
                                   int(self.amount_edit.text()),
                                   self.negate_combo.currentData())
コード例 #6
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)