예제 #1
0
class ProgressBar(QWidget):
    def __init__(self, parent=None) -> None:
        super().__init__(parent)
        self.setAttribute(QtCore.Qt.WA_DeleteOnClose)
        self.pbar = QProgressBar()
        self.description_label = QLabel()
        self.eta_label = QLabel()

        layout = QHBoxLayout()
        layout.addWidget(self.description_label)
        layout.addWidget(self.pbar)
        layout.addWidget(self.eta_label)
        self.setLayout(layout)

    def setRange(self, min, max):
        self.pbar.setRange(min, max)

    def _set_value(self, value):
        self.pbar.setValue(value)
        QApplication.processEvents()

    def _get_value(self):
        return self.pbar.value()

    def _set_description(self, desc):
        self.description_label.setText(desc)
        QApplication.processEvents()

    def _set_eta(self, eta):
        self.eta_label.setText(eta)
예제 #2
0
class QtLabeledProgressBar(QWidget):
    """QProgressBar with QLabels for description and ETA."""
    def __init__(self,
                 parent: Optional[QWidget] = None,
                 prog: progress = None) -> None:
        super().__init__(parent)
        self.setAttribute(QtCore.Qt.WA_DeleteOnClose)

        self.progress = prog

        self.qt_progress_bar = QProgressBar()
        self.description_label = QLabel()
        self.eta_label = QLabel()
        base_layout = QVBoxLayout()

        pbar_layout = QHBoxLayout()
        pbar_layout.addWidget(self.description_label)
        pbar_layout.addWidget(self.qt_progress_bar)
        pbar_layout.addWidget(self.eta_label)
        base_layout.addLayout(pbar_layout)

        line = QFrame(self)
        line.setObjectName("QtCustomTitleBarLine")
        line.setFixedHeight(1)
        base_layout.addWidget(line)

        self.setLayout(base_layout)

    def setRange(self, min, max):
        self.qt_progress_bar.setRange(min, max)

    def setValue(self, value):
        self.qt_progress_bar.setValue(value)
        QApplication.processEvents()

    def setDescription(self, value):
        if not value.endswith(': '):
            value = f'{value}: '
        self.description_label.setText(value)
        QApplication.processEvents()

    def _set_value(self, event):
        self.setValue(event.value)

    def _get_value(self):
        return self.qt_progress_bar.value()

    def _set_description(self, event):
        self.setDescription(event.value)

    def _make_indeterminate(self, event):
        self.setRange(0, 0)

    def _set_eta(self, event):
        self.eta_label.setText(event.value)

    def _set_total(self, event):
        self.setRange(0, event.value)
예제 #3
0
    def __init__(self):
        """Create our windgets.
        """
        super().__init__()
        layout = QVBoxLayout()

        # For our "uptime" timer.
        self.start_time = time.time()

        # Label for our progress bar.
        bar_label = QLabel("Draw Time:")
        layout.addWidget(bar_label)

        # Progress bar is not used for "progress", it's just a bar graph to show
        # the "draw time", the duration of the "UpdateRequest" event.
        bar = QProgressBar()
        bar.setRange(0, 100)
        bar.setValue(50)
        bar.setFormat("%vms")
        layout.addWidget(bar)
        self.bar = bar

        # We let the user set the "slow event" threshold.
        self.thresh_ms = self.THRESH_DEFAULT
        self.thresh_combo = QComboBox()
        self.thresh_combo.addItems(self.THRESH_OPTIONS)
        self.thresh_combo.activated[str].connect(self._change_thresh)
        self.thresh_combo.setCurrentText(str(self.thresh_ms))

        combo_layout = QHBoxLayout()
        combo_layout.addWidget(QLabel("Show Events Slower Than:"))
        combo_layout.addWidget(self.thresh_combo)
        combo_layout.addWidget(QLabel("milliseconds"))
        combo_layout.addItem(
            QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
        )
        layout.addLayout(combo_layout)

        # We log slow events to this window.
        self.log = TextLog()
        layout.addWidget(self.log)

        # Uptime label. To indicate if the widget is getting updated.
        label = QLabel('')
        layout.addWidget(label)
        self.timer_label = label

        self.setLayout(layout)

        # Update us with a timer.
        self.timer = QTimer(self)
        self.timer.timeout.connect(self.update)
        self.timer.setInterval(self.UPDATE_MS)
        self.timer.start()
예제 #4
0
class FileProgressBar(QWidget):
    """Simple progress bar with a label"""
    MAX_LABEL_LENGTH = 60

    def __init__(self, parent, *args, **kwargs):
        QWidget.__init__(self, parent)
        self.pap = parent
        self.status_text = QLabel(self)
        self.bar = QProgressBar(self)
        self.bar.setRange(0, 0)
        layout = QVBoxLayout()
        layout.addWidget(self.status_text)
        layout.addWidget(self.bar)
        self.setLayout(layout)

    def __truncate(self, text):
        ellipsis = '...'
        part_len = (self.MAX_LABEL_LENGTH - len(ellipsis)) / 2.0
        left_text = text[:int(math.ceil(part_len))]
        right_text = text[-int(math.floor(part_len)):]
        return left_text + ellipsis + right_text

    @Slot(str, int)
    def set_label_file(self, file, size):
        text = self.__truncate(file)
        status_str = 'Downloading file list: {0} ({1})'.format(
            text, humanize.naturalsize(size))
        self.status_text.setText(status_str)

    def set_bounds(self, a, b):
        self.bar.setRange(a, b)

    def reset_files(self):
        self.status_text.setText("  Downloading file(s)...")
        self.bar.show()

    def reset_status(self):
        self.status_text.setText("  Download Complete!")
        self.bar.hide()

    @Slot(str, int, int, int)
    def update_progress(self, file, num_chunks, bytes_recv, total_bytes):
        text = "  Downloading {0} - {1}/{2} (Chunk {3})"
        self.status_text.setText(
            text.format(file, humanize.naturalsize(bytes_recv),
                        humanize.naturalsize(total_bytes), num_chunks))
        self.bar.setValue(bytes_recv)
예제 #5
0
class WaitingDialog(QDialog):
    def __init__(self, thread: QThread, text="", parent=None, exception_hook=None):
        super().__init__(parent)
        label = QLabel(text)
        self.exception_hook = exception_hook
        self.progress = QProgressBar()
        self.progress.setRange(0, 0)
        self.cancel_btn = QPushButton("Cancel")
        self.cancel_btn.setDisabled(True)
        self._error_caught = False
        layout = QHBoxLayout()
        layout.addWidget(label)
        layout.addWidget(self.progress)
        layout.addWidget(self.cancel_btn)
        self.cancel_btn.clicked.connect(self.close)
        thread.finished.connect(self.accept_if_no_reject)
        self.thread_to_wait = thread
        self.setLayout(layout)
        self.setResult(QDialog.Accepted)
        if isinstance(thread, ProgressTread):
            thread.range_changed.connect(self.progress.setRange)
            thread.step_changed.connect(self.progress.setValue)
            thread.error_signal.connect(self.error_catch)

    def error_catch(self, error):
        # print(self.thread() == QApplication.instance().thread(), error, isinstance(error, Exception))
        self._error_caught = True
        self.reject()
        if self.exception_hook:
            self.exception_hook(error)
        else:
            raise error

    def accept_if_no_reject(self):
        if self._error_caught:
            self.reject()
        else:
            self.accept()

    def exec(self):
        self.exec_()

    def exec_(self):
        self.thread_to_wait.start()
        return super().exec_()
예제 #6
0
class ProgressBar(QWidget):
    """QProgressBar with QLabels for description and ETA."""

    def __init__(self, parent=None) -> None:
        super().__init__(parent)
        self.setAttribute(QtCore.Qt.WA_DeleteOnClose)
        self.pbar = QProgressBar()
        self.description_label = QLabel()
        self.eta_label = QLabel()
        base_layout = QVBoxLayout()

        pbar_layout = QHBoxLayout()
        pbar_layout.addWidget(self.description_label)
        pbar_layout.addWidget(self.pbar)
        pbar_layout.addWidget(self.eta_label)
        base_layout.addLayout(pbar_layout)

        line = QFrame(self)
        line.setObjectName("QtCustomTitleBarLine")
        line.setFixedHeight(1)
        base_layout.addWidget(line)

        self.setLayout(base_layout)

    def setRange(self, min, max):
        self.pbar.setRange(min, max)

    def _set_value(self, value):
        self.pbar.setValue(value)
        QApplication.processEvents()

    def _get_value(self):
        return self.pbar.value()

    def _set_description(self, desc):
        self.description_label.setText(desc)
        QApplication.processEvents()

    def _set_eta(self, eta):
        self.eta_label.setText(eta)
예제 #7
0
class ProgressView(QWidget):
    def __init__(self, parent=None) -> None:
        super(ProgressView, self).__init__(parent)

        self._progress_tree_view = QTreeView(self)
        self._progress_tree_view.setHeaderHidden(True)
        self._progress_tree_view.setItemsExpandable(False)
        self._progress_tree_view.setItemDelegate(ProgressDelegate(self))
        self._progress_tree_view.setRootIsDecorated(False)
        self._progress_tree_view.setFixedHeight(30)
        self._progress_tree_view.setVerticalScrollBarPolicy(
            Qt.ScrollBarAlwaysOff)

        self._progress_bar = QProgressBar(self)
        self._progress_bar.setRange(0, 0)
        self._progress_bar.setFixedHeight(30)
        self._progress_bar.setVisible(False)

        layout = QVBoxLayout(self)
        layout.setContentsMargins(0, 0, 0, 0)
        layout.addWidget(self._progress_tree_view)
        layout.addWidget(self._progress_bar)

        self.setLayout(layout)

        self.setFixedHeight(30)

    def setModel(self, model) -> None:
        self._progress_tree_view.setModel(model)

    @Slot(bool)
    def setIndeterminate(self, b: bool) -> None:
        if b:
            self._progress_bar.setVisible(True)
            self._progress_tree_view.setVisible(False)
        else:
            self._progress_bar.setVisible(False)
            self._progress_tree_view.setVisible(True)
예제 #8
0
class RunDialog(QDialog):
    simulation_done = Signal(bool, str)
    simulation_termination_request = Signal()

    def __init__(self,
                 config_file,
                 run_model,
                 simulation_arguments,
                 parent=None):
        QDialog.__init__(self, parent)
        self.setWindowFlags(Qt.Window)
        self.setWindowFlags(self.windowFlags()
                            & ~Qt.WindowContextHelpButtonHint)
        self.setModal(True)
        self.setWindowModality(Qt.WindowModal)
        self.setWindowTitle("Simulations - {}".format(config_file))

        self._snapshot_model = SnapshotModel(self)
        self._run_model = run_model

        self._isDetailedDialog = False
        self._minimum_width = 1200

        ert = None
        if isinstance(run_model, BaseRunModel):
            ert = run_model.ert()

        self._simulations_argments = simulation_arguments

        self._ticker = QTimer(self)
        self._ticker.timeout.connect(self._on_ticker)

        progress_proxy_model = ProgressProxyModel(self._snapshot_model,
                                                  parent=self)

        self._total_progress_label = QLabel(_TOTAL_PROGRESS_TEMPLATE.format(0),
                                            self)

        self._total_progress_bar = QProgressBar(self)
        self._total_progress_bar.setRange(0, 100)
        self._total_progress_bar.setTextVisible(False)

        self._iteration_progress_label = QLabel(self)

        self._progress_view = ProgressView(self)
        self._progress_view.setModel(progress_proxy_model)
        self._progress_view.setIndeterminate(True)

        legend_view = LegendView(self)
        legend_view.setModel(progress_proxy_model)

        self._tab_widget = QTabWidget(self)
        self._snapshot_model.rowsInserted.connect(self.on_new_iteration)

        self._job_label = QLabel(self)

        self._job_model = JobListProxyModel(self, 0, 0, 0, 0)
        self._job_model.setSourceModel(self._snapshot_model)

        self._job_view = QTableView(self)
        self._job_view.clicked.connect(self._job_clicked)
        self._open_files = {}
        self._job_view.setModel(self._job_model)

        self.running_time = QLabel("")

        self.plot_tool = PlotTool(config_file)
        self.plot_tool.setParent(self)
        self.plot_button = QPushButton(self.plot_tool.getName())
        self.plot_button.clicked.connect(self.plot_tool.trigger)
        self.plot_button.setEnabled(ert is not None)

        self.kill_button = QPushButton("Kill Simulations")
        self.done_button = QPushButton("Done")
        self.done_button.setHidden(True)
        self.restart_button = QPushButton("Restart")
        self.restart_button.setHidden(True)
        self.show_details_button = QPushButton("Show Details")
        self.show_details_button.setCheckable(True)

        size = 20
        spin_movie = resourceMovie("ide/loading.gif")
        spin_movie.setSpeed(60)
        spin_movie.setScaledSize(QSize(size, size))
        spin_movie.start()

        self.processing_animation = QLabel()
        self.processing_animation.setMaximumSize(QSize(size, size))
        self.processing_animation.setMinimumSize(QSize(size, size))
        self.processing_animation.setMovie(spin_movie)

        button_layout = QHBoxLayout()
        button_layout.addWidget(self.processing_animation)
        button_layout.addWidget(self.running_time)
        button_layout.addStretch()
        button_layout.addWidget(self.show_details_button)
        button_layout.addWidget(self.plot_button)
        button_layout.addWidget(self.kill_button)
        button_layout.addWidget(self.done_button)
        button_layout.addWidget(self.restart_button)

        button_widget_container = QWidget()
        button_widget_container.setLayout(button_layout)

        layout = QVBoxLayout()
        layout.addWidget(self._total_progress_label)
        layout.addWidget(self._total_progress_bar)
        layout.addWidget(self._iteration_progress_label)
        layout.addWidget(self._progress_view)
        layout.addWidget(legend_view)
        layout.addWidget(self._tab_widget)
        layout.addWidget(self._job_label)
        layout.addWidget(self._job_view)
        layout.addWidget(button_widget_container)

        self.setLayout(layout)

        self.kill_button.clicked.connect(self.killJobs)
        self.done_button.clicked.connect(self.accept)
        self.restart_button.clicked.connect(self.restart_failed_realizations)
        self.show_details_button.clicked.connect(self.toggle_detailed_progress)
        self.simulation_done.connect(self._on_simulation_done)

        self.setMinimumWidth(self._minimum_width)
        self._setSimpleDialog()

    def _setSimpleDialog(self) -> None:
        self._isDetailedDialog = False
        self._tab_widget.setVisible(False)
        self._job_label.setVisible(False)
        self._job_view.setVisible(False)
        self.show_details_button.setText("Show Details")

    def _setDetailedDialog(self) -> None:
        self._isDetailedDialog = True
        self._tab_widget.setVisible(True)
        self._job_label.setVisible(True)
        self._job_view.setVisible(True)
        self.show_details_button.setText("Hide Details")

    @Slot(QModelIndex, int, int)
    def on_new_iteration(self, parent: QModelIndex, start: int,
                         end: int) -> None:
        if not parent.isValid():
            iter = start
            self._iteration_progress_label.setText(
                f"Progress for iteration {iter}")

            widget = RealizationWidget(iter)
            widget.setSnapshotModel(self._snapshot_model)
            widget.currentChanged.connect(self._select_real)

            self._tab_widget.addTab(widget,
                                    f"Realizations for iteration {iter}")

    @Slot(QModelIndex)
    def _job_clicked(self, index):
        if not index.isValid():
            return
        selected_file = index.data(FileRole)

        if selected_file and selected_file not in self._open_files:
            job_name = index.siblingAtColumn(0).data()
            viewer = FileDialog(
                selected_file,
                job_name,
                index.row(),
                index.model().get_real(),
                index.model().get_iter(),
                self,
            )
            self._open_files[selected_file] = viewer
            viewer.finished.connect(
                lambda _, f=selected_file: self._open_files.pop(f))

        elif selected_file in self._open_files:
            self._open_files[selected_file].raise_()

    @Slot(QModelIndex)
    def _select_real(self, index):
        step = 0
        stage = 0
        real = index.row()
        iter_ = index.model().get_iter()
        self._job_model.set_step(iter_, real, stage, step)
        self._job_label.setText(
            f"Realization id {index.data(RealIens)} in iteration {iter_}")

        self._job_view.horizontalHeader().setSectionResizeMode(
            QHeaderView.Stretch)

        # Clear the selection in the other tabs
        for i in range(0, self._tab_widget.count()):
            if i != self._tab_widget.currentIndex():
                self._tab_widget.widget(i).clearSelection()

    def reject(self):
        return

    def closeEvent(self, QCloseEvent):
        if self._run_model.isFinished():
            self.simulation_done.emit(self._run_model.hasRunFailed(),
                                      self._run_model.getFailMessage())
        else:
            # Kill jobs if dialog is closed
            if self.killJobs() != QMessageBox.Yes:
                QCloseEvent.ignore()

    def startSimulation(self):
        self._run_model.reset()
        self._snapshot_model.reset()
        self._tab_widget.clear()

        def run():
            asyncio.set_event_loop(asyncio.new_event_loop())
            self._run_model.startSimulations(self._simulations_argments)

        simulation_thread = Thread(name="ert_gui_simulation_thread")
        simulation_thread.setDaemon(True)
        simulation_thread.run = run
        simulation_thread.start()

        self._ticker.start(1000)

        tracker = create_tracker(
            self._run_model,
            num_realizations=self._simulations_argments["active_realizations"].
            count(),
            ee_config=self._simulations_argments.get("ee_config", None),
        )

        worker = TrackerWorker(tracker)
        worker_thread = QThread()
        worker.done.connect(worker_thread.quit)
        worker.consumed_event.connect(self._on_tracker_event)
        worker.moveToThread(worker_thread)
        self.simulation_done.connect(worker.stop)
        self._worker = worker
        self._worker_thread = worker_thread
        worker_thread.started.connect(worker.consume_and_emit)
        self._worker_thread.start()

    def killJobs(self):

        msg = "Are you sure you want to kill the currently running simulations?"
        if self._run_model.getQueueStatus().get(
                JobStatusType.JOB_QUEUE_UNKNOWN, 0) > 0:
            msg += "\n\nKilling a simulation with unknown status will not kill the realizations already submitted!"
        kill_job = QMessageBox.question(self, "Kill simulations?", msg,
                                        QMessageBox.Yes | QMessageBox.No)

        if kill_job == QMessageBox.Yes:
            # Normally this slot would be invoked by the signal/slot system,
            # but the worker is busy tracking the evaluation.
            self._worker.request_termination()
            self.reject()
        return kill_job

    @Slot(bool, str)
    def _on_simulation_done(self, failed, failed_msg):
        self.processing_animation.hide()
        self.kill_button.setHidden(True)
        self.done_button.setHidden(False)
        self.restart_button.setVisible(self.has_failed_realizations())
        self.restart_button.setEnabled(self._run_model.support_restart)
        self._total_progress_bar.setValue(100)
        self._total_progress_label.setText(
            _TOTAL_PROGRESS_TEMPLATE.format(100))

        if failed:
            QMessageBox.critical(
                self,
                "Simulations failed!",
                f"The simulation failed with the following error:\n\n{failed_msg}",
            )

    @Slot()
    def _on_ticker(self):
        runtime = self._run_model.get_runtime()
        self.running_time.setText(format_running_time(runtime))

    @Slot(object)
    def _on_tracker_event(self, event):
        if isinstance(event, EndEvent):
            self.simulation_done.emit(event.failed, event.failed_msg)
            self._worker.stop()
            self._ticker.stop()

        elif isinstance(event, FullSnapshotEvent):
            if event.snapshot is not None:
                self._snapshot_model._add_snapshot(event.snapshot,
                                                   event.iteration)
            self._progress_view.setIndeterminate(event.indeterminate)
            progress = int(event.progress * 100)
            self._total_progress_bar.setValue(progress)
            self._total_progress_label.setText(
                _TOTAL_PROGRESS_TEMPLATE.format(progress))

        elif isinstance(event, SnapshotUpdateEvent):
            if event.partial_snapshot is not None:
                self._snapshot_model._add_partial_snapshot(
                    event.partial_snapshot, event.iteration)
            self._progress_view.setIndeterminate(event.indeterminate)
            progress = int(event.progress * 100)
            self._total_progress_bar.setValue(progress)
            self._total_progress_label.setText(
                _TOTAL_PROGRESS_TEMPLATE.format(progress))

    def has_failed_realizations(self):
        completed = self._run_model.completed_realizations_mask
        initial = self._run_model.initial_realizations_mask
        for (index, successful) in enumerate(completed):
            if initial[index] and not successful:
                return True
        return False

    def count_successful_realizations(self):
        """
        Counts the realizations completed in the prevoius ensemble run
        :return:
        """
        completed = self._run_model.completed_realizations_mask
        return completed.count(True)

    def create_mask_from_failed_realizations(self):
        """
        Creates a BoolVector mask representing the failed realizations
        :return: Type BoolVector
        """
        completed = self._run_model.completed_realizations_mask
        initial = self._run_model.initial_realizations_mask
        inverted_mask = BoolVector(default_value=False)
        for (index, successful) in enumerate(completed):
            inverted_mask[index] = initial[index] and not successful
        return inverted_mask

    def restart_failed_realizations(self):

        msg = QMessageBox(self)
        msg.setIcon(QMessageBox.Information)
        msg.setText(
            "Note that workflows will only be executed on the restarted realizations and that this might have unexpected consequences."
        )
        msg.setWindowTitle("Restart Failed Realizations")
        msg.setStandardButtons(QMessageBox.Ok | QMessageBox.Cancel)
        result = msg.exec_()

        if result == QMessageBox.Ok:
            self.restart_button.setVisible(False)
            self.kill_button.setVisible(True)
            self.done_button.setVisible(False)
            active_realizations = self.create_mask_from_failed_realizations()
            self._simulations_argments[
                "active_realizations"] = active_realizations
            self._simulations_argments[
                "prev_successful_realizations"] = self._simulations_argments.get(
                    "prev_successful_realizations", 0)
            self._simulations_argments[
                "prev_successful_realizations"] += self.count_successful_realizations(
                )
            self.startSimulation()

    @Slot()
    def toggle_detailed_progress(self):
        if self._isDetailedDialog:
            self._setSimpleDialog()
        else:
            self._setDetailedDialog()

        self.adjustSize()
예제 #9
0
class KiteInstallation(QWidget):
    """Kite progress installation widget."""
    def __init__(self, parent):
        super(KiteInstallation, self).__init__(parent)

        # Left side
        action_layout = QVBoxLayout()
        progress_layout = QHBoxLayout()
        self._progress_widget = QWidget(self)
        self._progress_widget.setFixedHeight(50)
        self._progress_filter = HoverEventFilter()
        self._progress_bar = QProgressBar(self)
        self._progress_bar.setFixedWidth(180)
        self._progress_widget.installEventFilter(self._progress_filter)
        self.cancel_button = QPushButton()
        self.cancel_button.setIcon(ima.icon('DialogCloseButton'))
        self.cancel_button.hide()
        progress_layout.addWidget(self._progress_bar, alignment=Qt.AlignLeft)
        progress_layout.addWidget(self.cancel_button)
        self._progress_widget.setLayout(progress_layout)

        self._progress_label = QLabel(_('Downloading'))
        install_info = QLabel(
            _("Kite comes with a native app called the Copilot <br>"
              "which provides you with real time <br>"
              "documentation as you code.<br><br>"
              "When Kite is done installing, the Copilot will <br>"
              "launch automatically and guide you throught the <br>"
              "rest of the setup process."))

        button_layout = QHBoxLayout()
        self.ok_button = QPushButton(_('OK'))
        button_layout.addStretch()
        button_layout.addWidget(self.ok_button)
        button_layout.addStretch()

        action_layout.addStretch()
        action_layout.addWidget(self._progress_label)
        action_layout.addWidget(self._progress_widget)
        action_layout.addWidget(install_info)
        action_layout.addSpacing(10)
        action_layout.addLayout(button_layout)
        action_layout.addStretch()

        # Right side
        copilot_image_source = get_image_path('kite_copilot.png')

        copilot_image = QPixmap(copilot_image_source)
        copilot_label = QLabel()
        screen = QApplication.primaryScreen()
        device_pixel_ratio = screen.devicePixelRatio()
        if device_pixel_ratio > 1:
            copilot_image.setDevicePixelRatio(device_pixel_ratio)
            copilot_label.setPixmap(copilot_image)
        else:
            image_height = int(copilot_image.height() * 0.4)
            image_width = int(copilot_image.width() * 0.4)
            copilot_label.setPixmap(
                copilot_image.scaled(image_width, image_height,
                                     Qt.KeepAspectRatio,
                                     Qt.SmoothTransformation))

        # Layout
        general_layout = QHBoxLayout()
        general_layout.addLayout(action_layout)
        general_layout.addWidget(copilot_label)

        self.setLayout(general_layout)

        # Signals
        self._progress_filter.sig_hover_enter.connect(
            lambda: self.cancel_button.show())
        self._progress_filter.sig_hover_leave.connect(
            lambda: self.cancel_button.hide())

    def update_installation_status(self, status):
        """Update installation status (downloading, installing, finished)."""
        self._progress_label.setText(status)
        if status == INSTALLING:
            self._progress_bar.setRange(0, 0)

    def update_installation_progress(self, current_value, total):
        """Update installation progress bar."""
        self._progress_bar.setMaximum(total)
        self._progress_bar.setValue(current_value)
예제 #10
0
class AbortWindow(QDialog):
    """
    Displays busy message and provides abort button.
    The class serves SmoothCube, WorkerThread and SelectSmoothing.
    """
    def __init__(self, parent=None):
        """
        init abort or notification ui.
        Displays while smoothing freezes the application.
        Allows abort button to be added if needed.
        """
        super(AbortWindow, self).__init__(parent)
        self.setModal(False)
        self.setWindowFlags(self.windowFlags() | Qt.Tool)

        self.parent = parent

        self.label_a_1 = QLabel("Executing smoothing algorithm.")
        self.label_a_2 = QLabel("This may take several minutes.")

        self.abort_button = QPushButton("Abort")
        self.abort_button.clicked.connect(self.abort)

        self.pb = QProgressBar(self)
        self.pb_counter = 0

        self.abort_flag = False

        # vbl is short for Vertical Box Layout
        vbl = QVBoxLayout()
        vbl.addWidget(self.label_a_1)
        vbl.addWidget(self.label_a_2)
        vbl.addWidget(self.pb)
        vbl.addWidget(self.abort_button)

        self.setLayout(vbl)

        self.show()

    def init_pb(self, start, end):
        """
        Init the progress bar
        :param start: Start Value
        :param end: End Value
        """
        self.pb.setRange(start, end)
        self.pb_counter = start

    def update_pb(self):
        """
        This function is called in the worker thread to
        update the progress bar and checks if the
        local class variable abort_flag is active.

        If the abort button is clicked, the main thread
        will set abort_flag to True. The next time the
        worker thread calls this function, a custom
        exception is raised terminating the calculation.
        The exception is handled by the WorkerThread class.
        :raises: AbortException: terminating smoothing calculation
        """
        if self.abort_flag:
            raise AbortException("Abort Calculation")
        self.pb_counter += 1
        self.pb.setValue(self.pb_counter)
        QApplication.processEvents()

    def abort(self):
        """Abort calculation"""
        self.abort_flag = True
        self.parent.clean_up()

    def smoothing_done(self, component_id=None):
        """Notify user success"""
        self.hide()
        if component_id is None:
            message = "The result has been added as a" \
                      " new component of the input Data." \
                      " The new component can be accessed" \
                      " in the viewer drop-downs."
        else:
            message = "The result has been added as" \
                      " \"{0}\" and can be selected" \
                      " in the viewer drop-down menu.".format(component_id)

        info = QMessageBox.information(self, "Success", message)
        self.clean_up()

    def print_error(self, exception):
        """Print error message"""

        if "signal only works in main thread" in str(exception):
            message = "Smoothing Failed!\n\n" + "Please update your SpectralCube package"
        else:
            message = "Smoothing Failed!\n\n" + str(exception)

        info = QMessageBox.critical(self, "Error", message)
        self.clean_up()

    def clean_up(self):
        self.parent.clean_up()

    def keyPressEvent(self, e):
        if e.key() == Qt.Key_Escape:
            self.abort()
예제 #11
0
class MainWindow(QMainWindow):
    def __init__(self, title):
        super().__init__()
        self.setWindowTitle(title)
        self.lib_path = ""
        self.final_title = ""
        analysis_icon = QIcon(os.path.join(icons_dir, "icon.png"))
        stack_icon = QIcon(os.path.join(icons_dir, "icon_stack.png"))
        self.analysis_button = QToolButton(self)
        self.analysis_button.setToolButtonStyle(Qt.ToolButtonTextUnderIcon)
        self.analysis_button.setIcon(analysis_icon)
        # TODO use more general solution for text wrapping
        self.analysis_button.setText(ANALYSIS_NAME.replace(" ", "\n"))
        self.analysis_button.setIconSize(QSize(100, 100))
        self.mask_button = QToolButton(self)
        self.mask_button.setToolButtonStyle(Qt.ToolButtonTextUnderIcon)
        self.mask_button.setIcon(stack_icon)
        self.mask_button.setText(MASK_NAME.replace(" ", "\n"))
        self.mask_button.setIconSize(QSize(100, 100))
        self.analysis_button.clicked.connect(self.launch_analysis)
        self.mask_button.clicked.connect(self.launch_mask)
        self.progress = QProgressBar()
        self.progress.setHidden(True)
        layout = QGridLayout()
        layout.addWidget(self.progress, 0, 0, 1, 2)
        layout.addWidget(self.analysis_button, 1, 1)
        layout.addWidget(self.mask_button, 1, 0)
        widget = QWidget()
        widget.setLayout(layout)
        self.setCentralWidget(widget)
        self.setWindowIcon(analysis_icon)
        self.prepare = None
        self.wind = None
        self._update_theme()

    def _update_theme(self):
        napari_settings = napari_get_settings(state_store.save_folder)
        with warnings.catch_warnings():
            warnings.simplefilter("ignore", FutureWarning)
            theme = get_theme(napari_settings.appearance.theme)
        # TODO understand qss overwrite mechanism
        self.setStyleSheet(napari_template(get_stylesheet(), **theme))

    def _launch_begin(self):
        self.progress.setVisible(True)
        self.progress.setRange(0, 0)
        self.analysis_button.setDisabled(True)
        self.mask_button.setDisabled(True)
        import_config()

    def launch_analysis(self):
        self._launch_begin()
        self._launch_analysis()
        self.prepare.start()

    def _launch_analysis(self):
        self.lib_path = "PartSeg._roi_analysis.main_window"
        self.final_title = f"{APP_NAME} {ANALYSIS_NAME}"
        self.prepare = Prepare(self.lib_path)
        self.prepare.finished.connect(self.launch)

    def launch_mask(self):
        self._launch_begin()
        self._launch_mask()
        self.prepare.start()

    def _launch_mask(self):
        self.lib_path = "PartSeg._roi_mask.main_window"
        self.final_title = f"{APP_NAME} {MASK_NAME}"
        self.prepare = Prepare(self.lib_path)
        self.prepare.finished.connect(self.launch)

    def window_shown(self):
        self.close()

    def launch(self):
        if self.prepare.result is None:
            self.close()
            return
        if self.prepare.errors:
            errors_message = QMessageBox()
            errors_message.setText("There are errors during start")
            errors_message.setInformativeText(
                "During load saved state some of data could not be load properly\n"
                "The files has prepared backup copies in  state directory (Help > State directory)"
            )
            errors_message.setStandardButtons(QMessageBox.Ok)
            text = "\n".join("File: " + x[0] + "\n" + str(x[1])
                             for x in self.prepare.errors)

            errors_message.setDetailedText(text)
            errors_message.exec_()
        wind = self.prepare.result(title=self.final_title,
                                   signal_fun=self.window_shown)
        wind.show()
        self.wind = wind
예제 #12
0
class DialogChannels(DialogBase):
    """Dialog to add delete and select active conda package channels."""

    sig_channels_updated = Signal(object, object)  # added, removed
    sig_setup_ready = Signal()
    sig_check_ready = Signal()
    WIDTH = 550

    def __init__(self, parent=None):
        """Dialog to add delete and select active conda pacakge channels ."""
        super(DialogChannels, self).__init__(parent)
        self._parent = parent
        self._conda_url = 'https://conda.anaconda.org'
        self.api = AnacondaAPI()
        self.initial_sources = None
        self.config_sources = None
        self.style_sheet = None
        self._setup_ready = False
        self._conda_url_setup_ready = False

        # Widgets
        self.list = ListWidgetChannels(parent=self, api=self.api)
        self.label_info = LabelBase(
            'Manage channels you want Navigator to include.')
        self.label_status = LabelBase('Collecting sources...')
        self.progress_bar = QProgressBar(self)
        self.button_add = ButtonNormal('Add...')
        self.button_cancel = ButtonNormal('Cancel')
        self.button_ok = ButtonPrimary('Update channels')

        # Widget setup
        self.frame_title_bar.setVisible(False)
        self.list.setFrameStyle(QFrame.NoFrame)
        self.list.setFrameShape(QFrame.NoFrame)
        self.setWindowFlags(self.windowFlags() | Qt.Popup)
        self.setWindowOpacity(0.96)
        self.setMinimumHeight(300)
        self.setMinimumWidth(self.WIDTH)
        self.setModal(True)

        # Layout
        layout_button = QHBoxLayout()
        layout_button.addWidget(self.label_info)
        layout_button.addStretch()
        layout_button.addWidget(self.button_add)

        layout_ok = QHBoxLayout()
        layout_ok.addWidget(self.label_status)
        layout_ok.addWidget(SpacerHorizontal())
        layout_ok.addWidget(self.progress_bar)
        layout_ok.addWidget(SpacerHorizontal())
        layout_ok.addStretch()
        layout_ok.addWidget(self.button_cancel)
        layout_ok.addWidget(SpacerHorizontal())
        layout_ok.addWidget(self.button_ok)

        layout = QVBoxLayout()
        layout.addLayout(layout_button)
        layout.addWidget(SpacerVertical())
        layout.addWidget(self.list)
        layout.addWidget(SpacerVertical())
        layout.addWidget(SpacerVertical())
        layout.addLayout(layout_ok)
        self.setLayout(layout)

        # Signals
        self.button_add.clicked.connect(self.add_channel)
        self.button_ok.clicked.connect(self.update_channels)
        self.button_cancel.clicked.connect(self.reject)
        self.list.sig_status_updated.connect(self.update_status)
        self.list.sig_channel_added.connect(
            lambda v=None: self.set_tab_order())
        self.list.sig_channel_added.connect(
            lambda v=None: self.button_ok.setFocus())
        self.list.sig_channel_removed.connect(
            lambda v=None: self.set_tab_order())
        self.list.sig_channel_removed.connect(
            lambda v=None: self.button_ok.setFocus())
        self.list.sig_channel_checked.connect(self.sig_check_ready)
        self.list.sig_channel_status.connect(self.refresh)

        self.button_add.setDisabled(True)
        self.button_ok.setDisabled(True)
        self.button_cancel.setDisabled(True)
        self.update_status(action='Collecting sources...',
                           value=0,
                           max_value=0)

    @staticmethod
    def _group_sources_and_channels(sources):
        """
        Flatten sources and channels dictionary to list of tuples.

        [(source, channel), (source, channel)...]
        """
        grouped = []
        for source, channels in sources.items():
            for channel in channels:
                grouped.append((source, channel))
        return grouped

    def keyPressEvent(self, event):
        """Override Qt method."""
        key = event.key()
        if key in [Qt.Key_Escape]:
            if self.list.is_editing:
                self.refresh()
                self.list.is_editing = False
            else:
                self.reject()

    # --- Public API
    # -------------------------------------------------------------------------
    def update_style_sheet(self, style_sheet=None):
        """Update custom css style sheets."""
        if style_sheet is None:
            self.style_sheet = load_style_sheet()
        else:
            self.style_sheet = style_sheet

        self.setStyleSheet(self.style_sheet)
        self.setMinimumWidth(SASS_VARIABLES.WIDGET_CHANNEL_DIALOG_WIDTH)

        try:
            self.list.update_style_sheet(style_sheet)
        except Exception:
            pass

    def update_api(self, worker, api_info, error):
        """Update api info."""
        self._conda_url = api_info.get('conda_url',
                                       'https://conda.anaconda.org')
        self._conda_url_setup_ready = True

        if self._setup_ready:
            self.sig_setup_ready.emit()

    def setup(self, worker, conda_config_data, error):
        """Setup the channels widget."""
        self.config_sources = conda_config_data.get('config_sources')
        self.button_add.setDisabled(False)

        for source, data in self.config_sources.items():
            channels = data.get('channels', [])
            for channel in channels:
                item = ListWidgetItemChannel(channel=channel, location=source)
                item.set_editable(False)
                self.list.addItem(item)

        self.set_tab_order()
        self.button_add.setFocus()
        self.button_ok.setDefault(True)
        self.button_cancel.setEnabled(True)

        self.initial_sources = self.list.sources.copy()
        self.update_status()
        self._setup_ready = True

        if self._conda_url_setup_ready:
            self.sig_setup_ready.emit()

    def set_tab_order(self):
        """Fix the tab ordering in the list."""
        if self.list._items:
            self.setTabOrder(self.button_add,
                             self.list._items[0].button_remove)
            self.setTabOrder(self.list._items[-1].button_remove,
                             self.button_cancel)

        self.setTabOrder(self.button_cancel, self.button_ok)
        self.refresh()

    def add_channel(self):
        """Add new conda channel."""
        user_rc_path = self.api._conda_api.user_rc_path
        item = ListWidgetItemChannel(channel='', location=user_rc_path)
        self.list.addItem(item)
        self.refresh(False)

    def update_channels(self):
        """Update channels list and status."""
        sources = self.list.sources

        original = self._group_sources_and_channels(self.initial_sources)
        updated = self._group_sources_and_channels(sources)

        if sorted(original) != sorted(updated):
            self.sig_channels_updated.emit(*self.sources)
            self.accept()
        else:
            self.reject()

    def refresh(self, channel_status=True):
        """Update enable/disable status based on item count."""
        self.button_add.setEnabled(channel_status and bool(self.list.count))
        self.button_ok.setEnabled(channel_status)
        self.button_cancel.setEnabled(True)

        if self.list.count() == 0:
            self.button_add.setEnabled(True)
            self.button_ok.setEnabled(False)

    def update_status(self, action='', message='', value=None, max_value=None):
        """Update the status and progress bar of the widget."""
        visible = bool(action)
        self.label_status.setText(action)
        self.label_status.setVisible(visible)
        if value is not None and max_value is not None:
            self.progress_bar.setVisible(True)
            self.progress_bar.setRange(0, max_value)
            self.progress_bar.setValue(value)
        else:
            self.progress_bar.setVisible(False)

    @property
    def sources(self):
        """Return sources to add and remove from config."""
        original = self._group_sources_and_channels(self.initial_sources)
        updated = self._group_sources_and_channels(self.list.sources)

        original = set(original)
        updated = set(updated)

        add = updated - original
        remove = original - updated

        return add, remove
예제 #13
0
class MainDialog(DialogBase):
    """Main dialog for the anaconda navgator updater."""
    # Signals
    sig_application_updated = Signal()
    sig_ready = Signal()

    # Class variables
    PACKAGE = 'anaconda-navigator'
    WIDTH = 450
    HEIGHT = 200

    def __init__(self, latest_version=None, prefix=None):
        """Main dialog for the anaconda navgator updater."""
        super(MainDialog, self).__init__()

        # Variables
        self.api = CondaAPI()
        self.prefix = prefix or os.environ.get('CONDA_PREFIX',
                                               self.api.ROOT_PREFIX)
        self.info = {}
        self.first_run = True
        self.setup_ready = False
        self.busy = False
        self.up_to_date = False
        self.error = False
        self.success = False
        self.status = ''
        self.current_version = None
        self.latest_version = latest_version
        self.style_sheet = load_style_sheet()
        self.timer = QTimer()
        self.timer_2 = QTimer()
        self._windows_appusermodelid = None

        # Widgets
        self.message_box = None  # For testing
        self.label_icon = QSvgWidget()
        self.label_message = LabelBase(
            "There's a new version of Anaconda Navigator available. "
            "We strongly recommend you to update.")

        self.label_status = LabelBase('')
        self.progress_bar = QProgressBar()
        self.button_cancel = ButtonNormal('Dismiss')
        self.button_update = ButtonPrimary('Update now')
        self.button_launch = ButtonPrimary('Launch Navigator')

        # Widgets setup
        if WIN:
            self._windows_appusermodelid = set_windows_appusermodelid()

        self.setMinimumSize(self.WIDTH, self.HEIGHT)
        self.label_message.setAlignment(Qt.AlignLeft | Qt.AlignTop)
        self.label_message.setWordWrap(True)
        self.label_status.setWordWrap(True)
        self.button_update.setAutoDefault(True)
        self.button_launch.setAutoDefault(True)
        self.button_cancel.setFocusPolicy(Qt.NoFocus)
        self.timer.setInterval(1000)
        self.timer_2.setInterval(5000)
        self.progress_bar.setTextVisible(False)
        self.progress_bar.setStyleSheet(self.style_sheet)
        self.label_icon.load(images.ANACONDA_LOGO)
        self.label_icon.setMaximumSize(QSize(64, 64))
        self.label_icon.setMinimumSize(QSize(64, 64))
        self.setWindowTitle('Anaconda Navigator Updater')
        self.progress_bar.setMaximumWidth(self.WIDTH / 3)
        self.setMinimumWidth(self.WIDTH)
        self.setMaximumWidth(self.WIDTH)
        self.setMinimumHeight(self.HEIGHT)

        # Layouts
        layout_status = QHBoxLayout()
        layout_status.addWidget(self.label_status)
        layout_status.addWidget(SpacerHorizontal())
        layout_status.addWidget(self.progress_bar)

        layout_text = QVBoxLayout()
        layout_text.addWidget(self.label_message)
        layout_text.addStretch()
        layout_text.addWidget(SpacerVertical())
        layout_text.addLayout(layout_status)

        layout_icon = QVBoxLayout()
        layout_icon.addWidget(self.label_icon)
        layout_icon.addStretch()

        layout_top = QHBoxLayout()
        layout_top.addLayout(layout_icon)
        layout_top.addWidget(SpacerHorizontal())
        layout_top.addLayout(layout_text)

        layout_buttons = QHBoxLayout()
        layout_buttons.addStretch()
        layout_buttons.addWidget(self.button_cancel)
        layout_buttons.addWidget(SpacerHorizontal())
        layout_buttons.addWidget(self.button_update)
        layout_buttons.addWidget(self.button_launch)

        layout = QVBoxLayout()
        layout.addLayout(layout_top)
        layout.addWidget(SpacerVertical())
        layout.addWidget(SpacerVertical())
        layout.addStretch()
        layout.addLayout(layout_buttons)

        self.setLayout(layout)

        # Signals
        self.button_update.clicked.connect(self.install_update)
        self.button_cancel.clicked.connect(self.reject)
        self.button_launch.clicked.connect(self.launch)
        self.timer.timeout.connect(self.refresh)
        self.timer_2.timeout.connect(self.check_conditions)

        # Setup
        self.timer.start()
        self.timer_2.start()
        self.check_conditions()
        self.refresh()

    def check_conditions(self):
        """Check every 5 seconds installed packages in case codna was used."""
        packages = self.api.linked(prefix=self.prefix)
        package = [p for p in packages if self.PACKAGE in p]
        if package:
            n, v, b = self.api.split_canonical_name(package[0])
            self.current_version = v
        else:
            self.current_version = None

        if self.latest_version is None:
            worker_search = self.api.search(self.PACKAGE,
                                            platform=self.api.get_platform())
            worker_search.sig_finished.connect(self._search_callback)
        else:
            worker = self.api.info()
            worker.sig_finished.connect(self.setup)
            self.check_versions()

    def check_versions(self):
        """Check if navigator is up to date."""
        if self.latest_version and self.current_version:
            from distutils.version import LooseVersion
            cur_ver = LooseVersion(self.current_version)
            lat_ver = LooseVersion(self.latest_version)
            self.up_to_date = cur_ver >= lat_ver
        else:
            self.up_to_date = False

    def _search_callback(self, worker, output, error):
        """Setup the widget."""
        if isinstance(output, dict):
            packages = output.get(self.PACKAGE, [])
            versions = [package.get('version') for package in packages]
            unique_versions = []
            for version in versions:
                if version not in unique_versions:
                    unique_versions.append(version)
            if unique_versions:
                self.latest_version = unique_versions[-1]

        self.check_versions()
        worker = self.api.info()
        worker.sig_finished.connect(self.setup)

        self.refresh()

    def setup(self, worker, info, error):
        """Setup the widget."""
        self.info = info
        self.setup_ready = True
        self.sig_ready.emit()
        self.refresh()

        if self.button_update.isVisible():
            self.button_update.setFocus()

        if self.button_launch.isVisible():
            self.button_launch.setFocus()

    def update_style_sheet(self):
        """Update custom CSS style sheet."""
        self.style_sheet = load_style_sheet()
        self.setStyleSheet(self.style_sheet)

    def refresh(self):
        """Refresh enabled/disabled status of widgets."""
        current_version = 'Not installed'
        if self.current_version:
            current_version = self.current_version

        latest_version = '-'
        if self.latest_version:
            latest_version = self.latest_version

        main_message = (
            "Current version:    &nbsp;&nbsp;&nbsp;&nbsp;<i>{0}</i><br>"
            "Available version: &nbsp;&nbsp;<b>{1}</b><br>").format(
                current_version, latest_version)

        message = self.status
        running = self.check_running()
        self.button_launch.setVisible(False)

        if not self.setup_ready:
            self.button_update.setDisabled(True)
            self.progress_bar.setVisible(True)
            message = 'Updating index...'
            self.update_status(message)
        elif self.busy:
            self.button_update.setDisabled(True)
            self.progress_bar.setVisible(True)
        else:
            self.progress_bar.setVisible(False)

            if running:
                message = 'Please close Anaconda Navigator before updating.'
                self.button_update.setDisabled(running)
            elif not running:
                self.button_update.setDisabled(False)
                if self.success and self.current_version:
                    message = 'Anaconda Navigator was updated successfully.'
                    self.button_update.setVisible(False)
                    self.button_launch.setVisible(True)
                elif self.up_to_date:
                    message = 'Anaconda Navigator is already up to date.'
                    self.button_update.setVisible(False)
                    self.button_launch.setVisible(True)
                elif not self.error:
                    self.button_update.setVisible(True)
                    if self.current_version:
                        message = ('An update for Anaconda Navigator is now '
                                   'available.')
                        self.button_update.setText('Update now')
                    else:
                        message = (
                            'Anaconda Navigator is available for install.')
                        self.button_update.setText('Install now')

            if self.error:
                self.button_update.setDisabled(False)
                message = 'Cannot update Anaconda Navigator, <b>{0}</b>'
                message = message.format(self.error)

        self.label_status.setText(message)
        self.label_message.setText(main_message)

    def update_status(self, status='', value=-1, max_val=-1):
        """Update progress bar and message status."""
        if status:
            self.status = status
            self.label_status.setText(status)
            if value < 0 and max_val < 0:
                self.progress_bar.setRange(0, 0)
            else:
                self.progress_bar.setMinimum(0)
                self.progress_bar.setMaximum(max_val)
                self.progress_bar.setValue(value)

    def check_running(self):
        """Check if Anaconda Navigator is running."""
        # Create file lock
        lock = filelock.FileLock(NAVIGATOR_LOCKFILE)
        try:
            running = False
            with lock.acquire(timeout=0.01):
                pass
        except filelock.Timeout:
            running = True
        return running

    # --- Conda actions and helpers
    # -------------------------------------------------------------------------
    def partial_output_ready(self, worker, output, error):
        """Handle conda partial output ready."""
        self.busy = True
        # print(type(output))
        # print(output)

        # Get errors and data from ouput if it exists
        fetch = None
        if output and isinstance(output, dict):
            fetch = output.get('fetch')
            max_val = output.get('maxval', -1)
            value = output.get('progress', -1)

        if fetch:
            status = 'Fetching <b>{0}</b>...'.format(fetch)
            self.update_status(status=status, max_val=max_val, value=value)

    def output_ready(self, worker, output, error):
        """Handle conda output ready."""
        self.check_conditions()

        # Get errors and data from ouput if it exists
        error_text = output.get('error', '')
        exception_type = output.get('exception_type', '')
        exception_name = output.get('exception_name', '')
        success = output.get('success')
        actions = output.get('actions', {})
        # op_order = output.get('op_order', [])
        # action_check_fetch = actions.get('CHECK_FETCH', [])
        # action_rm_fetch = actions.get('RM_FETCHED', [])
        # action_fetch = actions.get('FETCH', [])
        # action_check_extract = actions.get('CHECK_EXTRACT', [])
        # action_rm_extract = actions.get('RM_EXTRACTED', [])
        # action_extract = actions.get('EXTRACT', [])
        # action_unlink = actions.get('UNLINK', [])
        action_link = actions.get('LINK', [])
        # action_symlink_conda = actions.get('SYMLINK_CONDA', [])

        self.busy = False

        # Get errors from json output
        if error_text or exception_type or exception_name or not success:
            self.error = exception_name
            self.success = False
            self.up_to_date = False
        elif success and action_link:
            self.sig_application_updated.emit()
            self.error = None
            self.success = True
            self.up_to_date = False
        elif success:
            self.success = False
            self.error = None
            self.up_to_date = True

        worker.lock.release()
        self.refresh()

    def install_update(self):
        """Install the specified version or latest version of navigator."""
        self.busy = True
        self.refresh()
        # conda_prefix = self.info.et('conda_prefix')
        # root_prefix = self.info.et('root_prefix')
        navigator_prefixes = [
            # os.path.join(self.api.ROOT_PREFIX, 'envs', '_navigator_'),
            # os.path.join(self.api.ROOT_PREFIX, 'envs', '_conda_'),
            self.prefix,
        ]
        for prefix in navigator_prefixes:
            if self.api.environment_exists(prefix=prefix):
                break

        if self.latest_version:
            pkgs = ['{0}=={1}'.format(self.PACKAGE, self.latest_version)]
        else:
            pkgs = [self.PACKAGE.format(self.latest_version)]

        # Lock Navigator
        lock = filelock.FileLock(NAVIGATOR_LOCKFILE)
        lock.acquire()
        worker = self.api.install(prefix=prefix, pkgs=pkgs)
        worker.lock = lock
        worker.sig_partial.connect(self.partial_output_ready)
        worker.sig_finished.connect(self.output_ready)
        self.refresh()

        if self.prefix == self.api.ROOT_PREFIX:
            name = 'root'
        else:
            name = os.path.basename(self.prefix)

        self.button_launch.setFocus()
        if self.current_version:
            msg = 'Updating package on <b>{0}</b>...'.format(name)
        else:
            msg = 'Installing package on <b>{0}</b>...'.format(name)
        self.update_status(msg)

    def launch(self):
        """Launch Anaconda Navigator."""
        leave_path_alone = True
        root_prefix = self.api.ROOT_PREFIX
        prefix = self.prefix
        command = ['anaconda-navigator']

        # Use the app bundle on OSX
        if MAC:
            command = ['open', os.path.join(prefix, 'Anaconda-Navigator.app')]

        launch_cmd(
            prefix,
            command,
            leave_path_alone,
            package_name='anaconda-navigator-app',
            root_prefix=root_prefix,
        )
        self.close()

    # --- Qt Overrides
    # -------------------------------------------------------------------------
    def reject(self):
        """Override Qt method."""
        if self.busy:
            msg_box = MessageBoxQuestion(title='Quit Navigator Updater?',
                                         text='Anaconda Navigator is being '
                                         'updated. <br><br>'
                                         'Are you sure you want to quit?')

            if msg_box.exec_():
                super(MainDialog, self).reject()
        else:
            super(MainDialog, self).reject()
예제 #14
0
class WidgetGallery(QWidget):
    def __init__(self, parent=None):
        super(WidgetGallery, self).__init__(parent)

        self.originalPalette = QApplication.palette()

        styleComboBox = QComboBox()
        styleComboBox.addItems(QStyleFactory.keys())

        styleLabel = QLabel("&Style:")
        styleLabel.setBuddy(styleComboBox)

        self.useStylePaletteCheckBox = QCheckBox(
            "&Use style's standard palette")
        self.useStylePaletteCheckBox.setChecked(True)

        disableWidgetsCheckBox = QCheckBox("&Disable widgets")

        self.createTopLeftGroupBox()
        self.createTopRightGroupBox()
        self.createBottomLeftTabWidget()
        self.createBottomRightGroupBox()
        self.createProgressBar()

        styleComboBox.activated[str].connect(self.changeStyle)
        self.useStylePaletteCheckBox.toggled.connect(self.changePalette)
        disableWidgetsCheckBox.toggled.connect(
            self.topLeftGroupBox.setDisabled)
        disableWidgetsCheckBox.toggled.connect(
            self.topRightGroupBox.setDisabled)
        disableWidgetsCheckBox.toggled.connect(
            self.bottomLeftTabWidget.setDisabled)
        disableWidgetsCheckBox.toggled.connect(
            self.bottomRightGroupBox.setDisabled)

        topLayout = QHBoxLayout()
        topLayout.addWidget(styleLabel)
        topLayout.addWidget(styleComboBox)
        topLayout.addStretch(1)
        topLayout.addWidget(self.useStylePaletteCheckBox)
        topLayout.addWidget(disableWidgetsCheckBox)

        mainLayout = QGridLayout()
        mainLayout.addLayout(topLayout, 0, 0, 1, 2)
        mainLayout.addWidget(self.topLeftGroupBox, 1, 0)
        mainLayout.addWidget(self.topRightGroupBox, 1, 1)
        mainLayout.addWidget(self.bottomLeftTabWidget, 2, 0)
        mainLayout.addWidget(self.bottomRightGroupBox, 2, 1)
        mainLayout.addWidget(self.progressBar, 3, 0, 1, 2)
        mainLayout.setRowStretch(1, 1)
        mainLayout.setRowStretch(2, 1)
        mainLayout.setColumnStretch(0, 1)
        mainLayout.setColumnStretch(1, 1)
        self.setLayout(mainLayout)

        self.changeStyle('Windows')

        self.val = 0

    def changeStyle(self, styleName):
        QApplication.setStyle(QStyleFactory.create(styleName))
        self.changePalette()

    def changePalette(self):
        if (self.useStylePaletteCheckBox.isChecked()):
            QApplication.setPalette(QApplication.style().standardPalette())
        else:
            QApplication.setPalette(self.originalPalette)

    def advanceProgressBar(self):
        self.progressBar.setMaximum(100)
        self.val += 1
        self.progressBar.setValue(self.val)

    def createTopLeftGroupBox(self):
        self.topLeftGroupBox = QGroupBox("Group 1")

        radioButton1 = QRadioButton("Radio button 1")
        radioButton2 = QRadioButton("Radio button 2")
        radioButton3 = QRadioButton("Radio button 3")
        radioButton1.setChecked(True)

        checkBox = QCheckBox("Tri-state check box")
        checkBox.setTristate(True)
        checkBox.setCheckState(Qt.PartiallyChecked)

        layout = QVBoxLayout()
        layout.addWidget(radioButton1)
        layout.addWidget(radioButton2)
        layout.addWidget(radioButton3)
        layout.addWidget(checkBox)
        layout.addStretch(1)
        self.topLeftGroupBox.setLayout(layout)

    def createTopRightGroupBox(self):
        self.topRightGroupBox = QGroupBox("Group 2")

        defaultPushButton = QPushButton("Default Push Button")
        defaultPushButton.setDefault(True)

        togglePushButton = QPushButton("Toggle Push Button")
        togglePushButton.setCheckable(True)
        togglePushButton.setChecked(True)

        flatPushButton = QPushButton("Flat Push Button")
        flatPushButton.setFlat(True)

        layout = QVBoxLayout()
        layout.addWidget(defaultPushButton)
        layout.addWidget(togglePushButton)
        layout.addWidget(flatPushButton)
        layout.addStretch(1)
        self.topRightGroupBox.setLayout(layout)

    def createBottomLeftTabWidget(self):
        self.bottomLeftTabWidget = QTabWidget()
        self.bottomLeftTabWidget.setSizePolicy(QSizePolicy.Preferred,
                                               QSizePolicy.Ignored)

        tab1 = QWidget()
        tableWidget = QTableWidget(10, 10)

        tab1hbox = QHBoxLayout()
        tab1hbox.setContentsMargins(5, 5, 5, 5)
        tab1hbox.addWidget(tableWidget)
        tab1.setLayout(tab1hbox)

        tab2 = QWidget()
        textEdit = QTextEdit()

        textEdit.setPlainText("Twinkle, twinkle, little star,\n"
                              "How I wonder what you are.\n"
                              "Up above the world so high,\n"
                              "Like a diamond in the sky.\n"
                              "Twinkle, twinkle, little star,\n"
                              "How I wonder what you are!\n")

        tab2hbox = QHBoxLayout()
        tab2hbox.setContentsMargins(5, 5, 5, 5)
        tab2hbox.addWidget(textEdit)
        tab2.setLayout(tab2hbox)

        self.bottomLeftTabWidget.addTab(tab1, "&Table")
        self.bottomLeftTabWidget.addTab(tab2, "Text &Edit")

    def createBottomRightGroupBox(self):
        self.bottomRightGroupBox = QGroupBox("Group 3")
        self.bottomRightGroupBox.setCheckable(True)
        self.bottomRightGroupBox.setChecked(True)

        lineEdit = QLineEdit('s3cRe7')
        lineEdit.setEchoMode(QLineEdit.Password)

        spinBox = QSpinBox(self.bottomRightGroupBox)
        spinBox.setValue(50)

        dateTimeEdit = QDateTimeEdit(self.bottomRightGroupBox)
        dateTimeEdit.setDateTime(QDateTime.currentDateTime())

        slider = QSlider(Qt.Horizontal, self.bottomRightGroupBox)
        slider.setValue(40)

        scrollBar = QScrollBar(Qt.Horizontal, self.bottomRightGroupBox)
        scrollBar.setValue(60)

        dial = QDial(self.bottomRightGroupBox)
        dial.setValue(30)
        dial.setNotchesVisible(True)

        layout = QGridLayout()
        layout.addWidget(lineEdit, 0, 0, 1, 2)
        layout.addWidget(spinBox, 1, 0, 1, 2)
        layout.addWidget(dateTimeEdit, 2, 0, 1, 2)
        layout.addWidget(slider, 3, 0)
        layout.addWidget(scrollBar, 4, 0)
        layout.addWidget(dial, 3, 1, 2, 1)
        layout.setRowStretch(5, 1)
        self.bottomRightGroupBox.setLayout(layout)

    def createProgressBar(self):
        self.progressBar = QProgressBar()
        self.progressBar.setRange(0, 10000)
        self.progressBar.setValue(0)

        timer = QTimer(self)
        timer.timeout.connect(self.advanceProgressBar)
        timer.start(1000)
class BatchProcessingView(View):
    btn_run_batch: QPushButton
    progress_bar: QProgressBar
    field_channel: QLineEdit
    field_workflow_config: FileInput
    field_input_dir: FileInput
    field_output_dir: FileInput

    def __init__(self, controller: IBatchProcessingController):
        super().__init__(template_class=MainTemplate)

        if controller is None:
            raise ValueError("controller")
        self._controller = controller
        self.setObjectName("batchProcessingView")

    def load(self, model=None):
        self._setup_ui()

    def _setup_ui(self):
        """
        Set up the UI for the BatchProcessingView
        """
        layout = QVBoxLayout()
        self.setLayout(layout)

        # Workflow config
        self.field_workflow_config = FileInput(
            mode=FileInputMode.FILE, filter="Json file (*.json)", placeholder_text="Load a JSON workflow file..."
        )
        self.field_workflow_config.file_selected.connect(self._form_field_changed)
        row1 = FormRow("1.  Load workflow:", self.field_workflow_config)

        # Channel index
        self.field_channel = QLineEdit("0")
        self.field_channel.setValidator(QIntValidator(bottom=0))
        self.field_channel.textChanged.connect(self._form_field_changed)
        row2 = FormRow("2.  Structure channel index:", self.field_channel)

        # Input dir
        self.field_input_dir = FileInput(mode=FileInputMode.DIRECTORY, placeholder_text="Select a directory...")
        self.field_input_dir.file_selected.connect(self._form_field_changed)
        row3 = FormRow("3.  Input directory:", self.field_input_dir)

        # Output dir
        self.field_output_dir = FileInput(mode=FileInputMode.DIRECTORY, placeholder_text="Select a directory...")
        self.field_output_dir.file_selected.connect(self._form_field_changed)
        row4 = FormRow("4.  Output directory:", self.field_output_dir)

        # Help
        label = QLabel()
        label.setText("Supported file formats: .tif, .tiff, .czi, .ome.tif, .ome.tiff")

        form = QWidget()
        form.setLayout(Form([row1, row2, row3, row4]))
        layout.addWidget(form)
        layout.addWidget(label)

        # Submit
        self.btn_run_batch = QPushButton("Run Batch")
        self.btn_run_batch.clicked.connect(self._btn_run_batch_clicked)
        self.update_button(enabled=False)
        layout.addWidget(self.btn_run_batch)

        # Progress bar
        self.progress_bar = QProgressBar()
        self.progress_bar.setRange(0, 100)
        self.progress_bar.setValue(0)
        self.progress_bar.setTextVisible(True)
        self.progress_bar.setVisible(False)
        layout.addWidget(self.progress_bar)

    def update_button(self, enabled: bool):
        """
        Update state of process button
        Inputs:
            enabled: True to enable the button, false to disable it
        """
        self.btn_run_batch.setEnabled(enabled)

    def set_run_batch_in_progress(self):
        """
        Update page to reflect that a batch run is in progress
        """
        # TODO make a CancelButton widget to avoid repeating this connect / disconnect pattern
        self.btn_run_batch.setText("Cancel")
        self.btn_run_batch.clicked.disconnect()
        self.btn_run_batch.clicked.connect(self._btn_run_batch_cancel_clicked)
        self.progress_bar.setVisible(True)

    def reset_run_batch(self):
        """
        Reset page state to reflect that there is no batch run in progress
        """
        self.progress_bar.setValue(0)
        self.btn_run_batch.setText("Run Batch")
        self.btn_run_batch.clicked.disconnect()
        self.btn_run_batch.clicked.connect(self._btn_run_batch_clicked)
        self.progress_bar.setVisible(False)

    def set_progress(self, progress: int):
        """
        Update progress bar

        Inputs:
            progress (int): numerical value to set the progress bar to
        """
        self.progress_bar.setValue(progress)

    #####################################################################
    # Event handlers
    #####################################################################
    def _btn_run_batch_clicked(self):
        self._controller.run_batch()

    def _btn_run_batch_cancel_clicked(self):
        self.btn_run_batch.setText("Canceling...")
        self._controller.cancel_run_batch()

    def _form_field_changed(self, value):
        workflow_config = self.field_workflow_config.selected_file
        channel_index = int(self.field_channel.text()) if self.field_channel.text() else None
        input_dir = self.field_input_dir.selected_file
        output_dir = self.field_output_dir.selected_file

        self._controller.update_batch_parameters(workflow_config, channel_index, input_dir, output_dir)
예제 #16
0
class AlgorithmOptions(QWidget):
    def __init__(self, settings: StackSettings, image_view: StackImageView):
        super().__init__()
        self.settings = settings
        self.view_name = image_view.name
        self.show_result = QEnumComboBox(
            enum_class=LabelEnum)  # QCheckBox("Show result")
        self._set_show_label_from_settings()
        self.opacity = QDoubleSpinBox()
        self.opacity.setRange(0, 1)
        self.opacity.setSingleStep(0.1)
        self._set_opacity_from_settings()
        self.only_borders = QCheckBox("Only borders")
        self._set_border_mode_from_settings()
        self.borders_thick = QSpinBox()
        self.borders_thick.setRange(1, 25)
        self.borders_thick.setSingleStep(1)
        self._set_border_thick_from_settings()
        self.execute_in_background_btn = QPushButton("Execute in background")
        self.execute_in_background_btn.setToolTip(
            "Run calculation in background. Put result in multiple files panel"
        )
        self.execute_btn = QPushButton("Execute")
        self.execute_btn.setStyleSheet("QPushButton{font-weight: bold;}")
        self.execute_all_btn = QPushButton("Execute all")
        self.execute_all_btn.setToolTip(
            "Execute in batch mode segmentation with current parameter. File list need to be specified in image tab."
        )
        self.execute_all_btn.setDisabled(True)
        self.save_parameters_btn = QPushButton("Save parameters")
        self.block_execute_all_btn = False
        self.algorithm_choose_widget = AlgorithmChoose(settings,
                                                       mask_algorithm_dict)
        self.algorithm_choose_widget.result.connect(self.execution_result_set)
        self.algorithm_choose_widget.finished.connect(self.execution_finished)
        self.algorithm_choose_widget.progress_signal.connect(
            self.progress_info)

        # self.stack_layout = QStackedLayout()
        self.keep_chosen_components_chk = QCheckBox("Save selected components")
        self.keep_chosen_components_chk.setToolTip(
            "Save chosen components when loading segmentation form file\n or from multiple file widget."
        )
        self.keep_chosen_components_chk.stateChanged.connect(
            self.set_keep_chosen_components)
        self.keep_chosen_components_chk.setChecked(
            settings.keep_chosen_components)
        self.show_parameters = QPushButton("Show parameters")
        self.show_parameters.setToolTip(
            "Show parameters of segmentation for each components")
        self.show_parameters_widget = SegmentationInfoDialog(
            self.settings, self.algorithm_choose_widget.change_algorithm)
        self.show_parameters.clicked.connect(self.show_parameters_widget.show)
        self.choose_components = ChosenComponents()
        self.choose_components.check_change_signal.connect(
            image_view.refresh_selected)
        self.choose_components.mouse_leave.connect(image_view.component_unmark)
        self.choose_components.mouse_enter.connect(image_view.component_mark)
        # WARNING works only with one channels algorithms
        # SynchronizeValues.add_synchronization("channels_chose", widgets_list)
        self.chosen_list = []
        self.progress_bar2 = QProgressBar()
        self.progress_bar2.setHidden(True)
        self.progress_bar = QProgressBar()
        self.progress_bar.setHidden(True)
        self.progress_info_lab = QLabel()
        self.progress_info_lab.setHidden(True)
        self.file_list = []
        self.batch_process = BatchProceed()
        self.batch_process.progress_signal.connect(self.progress_info)
        self.batch_process.error_signal.connect(self.execution_all_error)
        self.batch_process.execution_done.connect(self.execution_all_done)
        self.batch_process.range_signal.connect(self.progress_bar.setRange)
        self.is_batch_process = False

        self.setContentsMargins(0, 0, 0, 0)
        main_layout = QVBoxLayout()
        # main_layout.setSpacing(0)
        opt_layout = QHBoxLayout()
        opt_layout.setContentsMargins(0, 0, 0, 0)
        opt_layout.addWidget(self.show_result)
        opt_layout.addWidget(right_label("Opacity:"))
        opt_layout.addWidget(self.opacity)
        main_layout.addLayout(opt_layout)
        opt_layout2 = QHBoxLayout()
        opt_layout2.setContentsMargins(0, 0, 0, 0)
        opt_layout2.addWidget(self.only_borders)
        opt_layout2.addWidget(right_label("Border thick:"))
        opt_layout2.addWidget(self.borders_thick)
        main_layout.addLayout(opt_layout2)
        btn_layout = QGridLayout()
        btn_layout.setContentsMargins(0, 0, 0, 0)
        btn_layout.addWidget(self.execute_btn, 0, 0)
        btn_layout.addWidget(self.execute_in_background_btn, 0, 1)
        btn_layout.addWidget(self.execute_all_btn, 1, 0)
        btn_layout.addWidget(self.save_parameters_btn, 1, 1)
        main_layout.addLayout(btn_layout)
        main_layout.addWidget(self.progress_bar2)
        main_layout.addWidget(self.progress_bar)
        main_layout.addWidget(self.progress_info_lab)
        main_layout.addWidget(self.algorithm_choose_widget, 1)
        # main_layout.addWidget(self.algorithm_choose)
        # main_layout.addLayout(self.stack_layout, 1)
        main_layout.addWidget(self.choose_components)
        down_layout = QHBoxLayout()
        down_layout.addWidget(self.keep_chosen_components_chk)
        down_layout.addWidget(self.show_parameters)
        main_layout.addLayout(down_layout)
        main_layout.addStretch()
        main_layout.setContentsMargins(0, 0, 0, 0)
        # main_layout.setSpacing(0)
        self.setLayout(main_layout)

        # noinspection PyUnresolvedReferences
        self.execute_in_background_btn.clicked.connect(
            self.execute_in_background)
        self.execute_btn.clicked.connect(self.execute_action)
        self.execute_all_btn.clicked.connect(self.execute_all_action)
        self.save_parameters_btn.clicked.connect(self.save_parameters)
        # noinspection PyUnresolvedReferences
        self.opacity.valueChanged.connect(self._set_opacity)
        # noinspection PyUnresolvedReferences
        self.show_result.currentEnumChanged.connect(self._set_show_label)
        self.only_borders.stateChanged.connect(self._set_border_mode)
        # noinspection PyUnresolvedReferences
        self.borders_thick.valueChanged.connect(self._set_border_thick)
        image_view.component_clicked.connect(
            self.choose_components.other_component_choose)
        settings.chosen_components_widget = self.choose_components
        settings.components_change_list.connect(
            self.choose_components.new_choose)
        settings.image_changed.connect(
            self.choose_components.remove_components)
        settings.connect_to_profile(
            f"{self.view_name}.image_state.only_border",
            self._set_border_mode_from_settings)
        settings.connect_to_profile(
            f"{self.view_name}.image_state.border_thick",
            self._set_border_thick_from_settings)
        settings.connect_to_profile(f"{self.view_name}.image_state.opacity",
                                    self._set_opacity_from_settings)
        settings.connect_to_profile(f"{self.view_name}.image_state.show_label",
                                    self._set_show_label_from_settings)

    def _set_border_mode(self, value: bool):
        self.settings.set_in_profile(
            f"{self.view_name}.image_state.only_border", value)

    def _set_border_thick(self, value: int):
        self.settings.set_in_profile(
            f"{self.view_name}.image_state.border_thick", value)

    def _set_opacity(self, value: float):
        self.settings.set_in_profile(f"{self.view_name}.image_state.opacity",
                                     value)

    def _set_show_label(self, value: LabelEnum):
        self.settings.set_in_profile(
            f"{self.view_name}.image_state.show_label", value)

    def _set_border_mode_from_settings(self):
        self.only_borders.setChecked(
            self.settings.get_from_profile(
                f"{self.view_name}.image_state.only_border", True))

    def _set_border_thick_from_settings(self):
        self.borders_thick.setValue(
            self.settings.get_from_profile(
                f"{self.view_name}.image_state.border_thick", 1))

    def _set_opacity_from_settings(self):
        self.opacity.setValue(
            self.settings.get_from_profile(
                f"{self.view_name}.image_state.opacity", 1.0))

    def _set_show_label_from_settings(self):
        self.show_result.setCurrentEnum(
            self.settings.get_from_profile(
                f"{self.view_name}.image_state.show_label",
                LabelEnum.Show_results))

    @Slot(int)
    def set_keep_chosen_components(self, val):
        self.settings.set_keep_chosen_components(val)

    def save_parameters(self):
        dial = PSaveDialog(io_functions.save_parameters_dict,
                           system_widget=False,
                           settings=self.settings,
                           path=IO_SAVE_DIRECTORY)
        if not dial.exec_():
            return
        res = dial.get_result()
        res.save_class.save(res.save_destination,
                            self.algorithm_choose_widget.current_parameters())

    def file_list_change(self, val):
        self.file_list = val
        if len(self.file_list) > 0 and not self.block_execute_all_btn:
            self.execute_all_btn.setEnabled(True)
        else:
            self.execute_all_btn.setDisabled(True)

    def get_chosen_components(self):
        return sorted(self.choose_components.get_chosen())

    @property
    def segmentation(self):
        return self.settings.roi

    @segmentation.setter
    def segmentation(self, val):
        self.settings.roi = val

    def _image_changed(self):
        self.settings.roi = None
        self.choose_components.set_chose([], [])

    def _execute_in_background_init(self):
        if self.batch_process.isRunning():
            return
        self.progress_bar2.setVisible(True)
        self.progress_bar2.setRange(0, self.batch_process.queue.qsize())
        self.progress_bar2.setValue(self.batch_process.index)
        self.progress_bar.setVisible(True)
        self.progress_bar.setValue(0)
        self.execute_btn.setDisabled(True)
        self.batch_process.start()

    def execute_in_background(self):
        # TODO check if components are properly passed
        widget = self.algorithm_choose_widget.current_widget()
        segmentation_profile = widget.get_segmentation_profile()
        task = BatchTask(self.settings.get_project_info(),
                         segmentation_profile, None)
        self.batch_process.add_task(task)
        self.progress_bar2.setRange(0, self.progress_bar2.maximum() + 1)
        self._execute_in_background_init()

    def execute_all_action(self):
        dial = PSaveDialog(
            SaveROI,
            settings=self.settings,
            system_widget=False,
            path="io.save_batch",
            file_mode=PSaveDialog.Directory,
        )
        if not dial.exec_():
            return
        folder_path = str(dial.selectedFiles()[0])

        widget = self.algorithm_choose_widget.current_widget()

        save_parameters = dial.values
        segmentation_profile = widget.get_segmentation_profile()
        for file_path in self.file_list:
            task = BatchTask(file_path, segmentation_profile,
                             (folder_path, save_parameters))
            self.batch_process.add_task(task)
        self.progress_bar2.setRange(
            0,
            self.progress_bar2.maximum() + len(self.file_list))
        self._execute_in_background_init()

    def execution_all_error(self, text):
        QMessageBox.warning(self, "Proceed error", text)

    def execution_all_done(self):
        if not self.batch_process.queue.empty():
            self._execute_in_background_init()
            return
        self.execute_btn.setEnabled(True)
        self.block_execute_all_btn = False
        if len(self.file_list) > 0:
            self.execute_all_btn.setEnabled(True)
        self.progress_bar.setHidden(True)
        self.progress_bar2.setHidden(True)
        self.progress_info_lab.setHidden(True)

    def execute_action(self):
        self.execute_btn.setDisabled(True)
        self.execute_all_btn.setDisabled(True)
        self.block_execute_all_btn = True
        self.is_batch_process = False
        self.progress_bar.setRange(0, 0)
        self.choose_components.setDisabled(True)
        chosen = sorted(self.choose_components.get_chosen())
        blank = get_mask(self.settings.roi, self.settings.mask, chosen)
        if blank is not None:
            # Problem with handling time data in algorithms
            # TODO Fix This
            blank = blank[0]
        self.progress_bar.setHidden(False)
        widget: AlgorithmSettingsWidget = self.algorithm_choose_widget.current_widget(
        )
        widget.set_mask(blank)
        self.progress_bar.setRange(0, widget.algorithm.get_steps_num())
        widget.execute()
        self.chosen_list = chosen

    def progress_info(self, text, num, file_name="", file_num=0):
        self.progress_info_lab.setVisible(True)
        if file_name != "":
            self.progress_info_lab.setText(file_name + "\n" + text)
        else:
            self.progress_info_lab.setText(text)
        self.progress_bar.setValue(num)
        self.progress_bar2.setValue(file_num)

    def execution_finished(self):
        self.execute_btn.setEnabled(True)
        self.block_execute_all_btn = False
        if len(self.file_list) > 0:
            self.execute_all_btn.setEnabled(True)
        self.progress_bar.setHidden(True)
        self.progress_info_lab.setHidden(True)
        self.choose_components.setDisabled(False)

    def execution_result_set(self, result):
        self.settings.set_segmentation_result(result)

    def showEvent(self, _):
        widget = self.algorithm_choose_widget.current_widget()
        widget.image_changed(self.settings.image)
예제 #17
0
class EmailReport(QWidget):
    emailSentSignal = Signal()
    
    def __init__(self, info='', report='', toemail=None, fromemail=None, password=None, server=None, port=25, 
                        subject='Report', parent=None):
        super().__init__(parent=parent)

        self._info = str(info)  # infomation reported
        self._report  = str(report)  # report
        self._toemail = str(toemail)
        self._subject = str(subject)

        mainLayout = QVBoxLayout(self)
        mainLayout.setContentsMargins(0, 0, 0, 0)
        mainLayout.setSpacing(0)

        self.setStyleSheet("background-color: white;")

        # information
        self.infoText = QLabel(self._info)
        self.infoText.setWordWrap(True)
        self.infoText.setAlignment(Qt.AlignLeft | Qt.AlignTop)
        self.infoText.setFont(QFont('Mcorsoft YaHei', 11, 50))
        self.infoText.setStyleSheet("color:rgb(130,130,130); padding:10px;")
        self.infoText.setFrameStyle(QFrame.Box|QFrame.Raised)

        # report
        self.reportText = QLabel(self._report)
        self.reportText.setWordWrap(True)
        self.reportText.setAlignment(Qt.AlignLeft | Qt.AlignTop)
        self.reportText.setFont(QFont('Mcorsoft YaHei', 11, 50))
        self.reportText.setStyleSheet("color:rgb(130,130,130); padding:10px;")
        self.reportText.setFrameStyle(QFrame.Box|QFrame.Raised)
        self.reportText.hide()

        # 邮件地址
        self.emailWidget = Email(email=fromemail, password=password, server=server, port=port, parent=self)

        # 邮件发送按钮
        buttonLayout = QHBoxLayout()
        buttonLayout.setContentsMargins(10, 10, 10, 10)
        buttonLayout.setSpacing(0)
        buttonLayout.setAlignment(Qt.AlignHCenter)

        emailSendButton = QPushButton()
        emailSendButton.setText("发送邮件")
        # 绑定点击事件处理函数
        emailSendButton.clicked.connect(self.sendEmail)
        emailSendButton.setStyleSheet(
            "QPushButton{font:63 11pt 微软雅黑;border:0px; border-radius:3px; color:#FFFFFF; background-color:#2278C6}"
            "QPushButton:hover{font:63 11pt 微软雅黑;border:0px; border-radius:3px;background-color:#1891FF;}"
        )

        buttonLayout.addWidget(emailSendButton)

        # 进度条
        self.progressBar = QProgressBar(self)
        self.progressBar.setRange(0, 10)
        self.progressBar.setTextVisible(False)
        self.progressBar.setMaximumHeight(5)

        # 将控件放入布局中
        mainLayout.addWidget(self.infoText)
        mainLayout.addWidget(self.reportText)
        mainLayout.addWidget(self.emailWidget)
        mainLayout.addLayout(buttonLayout)
        mainLayout.addWidget(self.progressBar)

    def sendEmail(self):
        successFlag = True

        subject = self.subject()
        report = self.report()
        toemail = self.toemail()
        server = self.server()
        port = self.port()
        fromemail = self.fromemail()
        password = self.password()
        self.progressBar.setValue(2)

        if successFlag:
            try:
                message = MIMEText(report, 'plain', 'utf-8')
                message['From'] = Header(formataddr(('Reporter', fromemail)), 'utf-8')   # 发送者
                message['To'] =  Header(formataddr(('Handler', toemail)), 'utf-8')    # 接收者
                message['Subject'] = Header(subject, 'utf-8')
                self.progressBar.setValue(4)
            except:
                showQuickMessage(title='error', text='请输入合法的邮箱', icon=QMessageBox.Critical, parent=self)
                successFlag = False

        if successFlag:
            try:
                with smtplib.SMTP() as smtpObj:
                    smtpObj.connect(server, port)
                    smtpObj.login(fromemail, password)
                    self.progressBar.setValue(6)
                    smtpObj.sendmail(fromemail, [toemail], message.as_string())
                    self.progressBar.setValue(10)
                showQuickMessage(title='info', text="邮件发送完成", icon=QMessageBox.Information, parent=self)
            except:
                showQuickMessage(title='error', 
                    text=textwrap.dedent("""
                            邮件发送失败,请检查
                            1)网络是否连接。
                            2)邮箱账号密码是否输入正确
                            3)邮箱是否与服务器对应"""),
                    icon=QMessageBox.Critical,
                    parent=self)
                successFlag = False

        if successFlag:
            self.emailSentSignal.emit()
        
        self.progressBar.reset()

    def subject(self):
        return self._subject

    def setSubject(self, subject):
        self._subject = str(subject)

    def info(self):
        return self._info

    def setInfo(self, info):
        self._info = str(info)
        self.infoText.setText(self._info)
    
    def report(self):
        return self._report
    
    def setReport(self, report):
        self._report = str(report)
        self.reportText.setText(self._report)

    def setReportVisible(self, visible=True):
        if visible:
            self.reportText.show()
        else:
            self.reportText.hide()

    def showReport(self):
        self.setReportVisible(True)
    
    def hideReport(self):
        self.setReportVisible(False)
    
    def server(self):
        return self.emailWidget.server()
    
    def setServer(self, server):
        self.emailWidget.setServer(server)

    def port(self):
        return self.emailWidget.port()
    
    def setPort(self, port):
        self.emailWidget.setPort(port)

    def fromemail(self):
        return self.emailWidget.email()

    def setFromemail(self, email):
        self.emailWidget.setEmail(email)
    
    def toemail(self):
        return self._toemail
    
    def setToemail(self, email):
        self._toemail = email
    
    def password(self):
        return self.emailWidget.password()
    
    def setPassword(self, password):
        self.emailWidget.setPassword(password)
예제 #18
0
class RunDialog(QDialog):
    simulation_done = Signal(bool, str)
    simulation_termination_request = Signal()

    def __init__(self, config_file, run_model, parent=None):
        QDialog.__init__(self, parent)
        self.setWindowFlags(Qt.Window)
        self.setWindowFlags(self.windowFlags()
                            & ~Qt.WindowContextHelpButtonHint)
        self.setModal(True)
        self.setWindowModality(Qt.WindowModal)
        self.setWindowTitle(f"Simulations - {config_file}")

        self._snapshot_model = SnapshotModel(self)
        self._run_model = run_model

        self._isDetailedDialog = False
        self._minimum_width = 1200

        ert = None
        if isinstance(run_model, BaseRunModel):
            ert = run_model.ert()

        self._ticker = QTimer(self)
        self._ticker.timeout.connect(self._on_ticker)

        progress_proxy_model = ProgressProxyModel(self._snapshot_model,
                                                  parent=self)

        self._total_progress_label = QLabel(
            _TOTAL_PROGRESS_TEMPLATE.format(
                total_progress=0, phase_name=run_model.getPhaseName()),
            self,
        )

        self._total_progress_bar = QProgressBar(self)
        self._total_progress_bar.setRange(0, 100)
        self._total_progress_bar.setTextVisible(False)

        self._iteration_progress_label = QLabel(self)

        self._progress_view = ProgressView(self)
        self._progress_view.setModel(progress_proxy_model)
        self._progress_view.setIndeterminate(True)

        legend_view = LegendView(self)
        legend_view.setModel(progress_proxy_model)

        self._tab_widget = QTabWidget(self)
        self._tab_widget.currentChanged.connect(self._current_tab_changed)
        self._snapshot_model.rowsInserted.connect(self.on_new_iteration)

        self._job_label = QLabel(self)

        self._job_model = JobListProxyModel(self, 0, 0, 0, 0)
        self._job_model.setSourceModel(self._snapshot_model)

        self._job_view = QTableView(self)
        self._job_view.setVerticalScrollMode(QAbstractItemView.ScrollPerItem)
        self._job_view.setSelectionBehavior(QAbstractItemView.SelectRows)
        self._job_view.setSelectionMode(QAbstractItemView.SingleSelection)
        self._job_view.clicked.connect(self._job_clicked)
        self._open_files = {}
        self._job_view.setModel(self._job_model)

        self.running_time = QLabel("")

        self.plot_tool = PlotTool(ert, config_file)
        self.plot_tool.setParent(self)
        self.plot_button = QPushButton(self.plot_tool.getName())
        self.plot_button.clicked.connect(self.plot_tool.trigger)
        self.plot_button.setEnabled(ert is not None)

        self.kill_button = QPushButton("Kill simulations")
        self.done_button = QPushButton("Done")
        self.done_button.setHidden(True)
        self.restart_button = QPushButton("Restart")
        self.restart_button.setHidden(True)
        self.show_details_button = QPushButton("Show details")
        self.show_details_button.setCheckable(True)

        size = 20
        spin_movie = resourceMovie("loading.gif")
        spin_movie.setSpeed(60)
        spin_movie.setScaledSize(QSize(size, size))
        spin_movie.start()

        self.processing_animation = QLabel()
        self.processing_animation.setMaximumSize(QSize(size, size))
        self.processing_animation.setMinimumSize(QSize(size, size))
        self.processing_animation.setMovie(spin_movie)

        button_layout = QHBoxLayout()
        button_layout.addWidget(self.processing_animation)
        button_layout.addWidget(self.running_time)
        button_layout.addStretch()
        button_layout.addWidget(self.show_details_button)
        button_layout.addWidget(self.plot_button)
        button_layout.addWidget(self.kill_button)
        button_layout.addWidget(self.done_button)
        button_layout.addWidget(self.restart_button)

        button_widget_container = QWidget()
        button_widget_container.setLayout(button_layout)

        layout = QVBoxLayout()
        layout.addWidget(self._total_progress_label)
        layout.addWidget(self._total_progress_bar)
        layout.addWidget(self._iteration_progress_label)
        layout.addWidget(self._progress_view)
        layout.addWidget(legend_view)
        layout.addWidget(self._tab_widget)
        layout.addWidget(self._job_label)
        layout.addWidget(self._job_view)
        layout.addWidget(button_widget_container)

        self.setLayout(layout)

        self.kill_button.clicked.connect(self.killJobs)
        self.done_button.clicked.connect(self.accept)
        self.restart_button.clicked.connect(self.restart_failed_realizations)
        self.show_details_button.clicked.connect(self.toggle_detailed_progress)
        self.simulation_done.connect(self._on_simulation_done)

        self.setMinimumWidth(self._minimum_width)
        self._setSimpleDialog()

    def _current_tab_changed(self, index: int):
        # Clear the selection in the other tabs
        for i in range(0, self._tab_widget.count()):
            if i != index:
                self._tab_widget.widget(i).clearSelection()

    def _setSimpleDialog(self) -> None:
        self._isDetailedDialog = False
        self._tab_widget.setVisible(False)
        self._job_label.setVisible(False)
        self._job_view.setVisible(False)
        self.show_details_button.setText("Show details")

    def _setDetailedDialog(self) -> None:
        self._isDetailedDialog = True
        self._tab_widget.setVisible(True)
        self._job_label.setVisible(True)
        self._job_view.setVisible(True)
        self.show_details_button.setText("Hide details")

    @Slot(QModelIndex, int, int)
    def on_new_iteration(self, parent: QModelIndex, start: int,
                         end: int) -> None:
        if not parent.isValid():
            index = self._snapshot_model.index(start, 0, parent)
            iter_row = start
            self._iteration_progress_label.setText(
                f"Progress for iteration {index.internalPointer().id}")

            widget = RealizationWidget(iter_row)
            widget.setSnapshotModel(self._snapshot_model)
            widget.currentChanged.connect(self._select_real)

            self._tab_widget.addTab(
                widget,
                f"Realizations for iteration {index.internalPointer().id}")

    @Slot(QModelIndex)
    def _job_clicked(self, index):
        if not index.isValid():
            return
        selected_file = index.data(FileRole)

        if selected_file and selected_file not in self._open_files:
            job_name = index.siblingAtColumn(0).data()
            viewer = FileDialog(
                selected_file,
                job_name,
                index.row(),
                index.model().get_real(),
                index.model().get_iter(),
                self,
            )
            self._open_files[selected_file] = viewer

            def remove_file():
                """
                We have sometimes seen this fail because the selected file is not
                in open file, without being able to reproduce the exception.
                """
                try:
                    self._open_files.pop(selected_file)
                except KeyError:
                    logger = logging.getLogger(__name__)
                    logger.exception(
                        f"Failed to pop: {selected_file} from {self._open_files}"
                    )

            viewer.finished.connect(remove_file)

        elif selected_file in self._open_files:
            self._open_files[selected_file].raise_()

    @Slot(QModelIndex)
    def _select_real(self, index):
        step = 0
        stage = 0
        real = index.row()
        iter_ = index.model().get_iter()
        self._job_model.set_step(iter_, real, stage, step)
        self._job_label.setText(
            f"Realization id {index.data(RealIens)} in iteration {iter_}")

        self._job_view.horizontalHeader().setSectionResizeMode(
            QHeaderView.Stretch)

    def reject(self):
        return

    def closeEvent(self, QCloseEvent):
        if self._run_model.isFinished():
            self.simulation_done.emit(self._run_model.hasRunFailed(),
                                      self._run_model.getFailMessage())
        else:
            # Kill jobs if dialog is closed
            if self.killJobs() != QMessageBox.Yes:
                QCloseEvent.ignore()

    def startSimulation(self):
        self._run_model.reset()
        self._snapshot_model.reset()
        self._tab_widget.clear()

        evaluator_server_config = EvaluatorServerConfig()

        def run():
            asyncio.set_event_loop(asyncio.new_event_loop())
            self._run_model.startSimulations(
                evaluator_server_config=evaluator_server_config, )

        simulation_thread = Thread(name="ert_gui_simulation_thread")
        simulation_thread.setDaemon(True)
        simulation_thread.run = run
        simulation_thread.start()

        self._ticker.start(1000)

        tracker = EvaluatorTracker(
            self._run_model,
            ee_con_info=evaluator_server_config.get_connection_info(),
        )

        worker = TrackerWorker(tracker)
        worker_thread = QThread()
        worker.done.connect(worker_thread.quit)
        worker.consumed_event.connect(self._on_tracker_event)
        worker.moveToThread(worker_thread)
        self.simulation_done.connect(worker.stop)
        self._worker = worker
        self._worker_thread = worker_thread
        worker_thread.started.connect(worker.consume_and_emit)
        self._worker_thread.start()

    def killJobs(self):

        msg = "Are you sure you want to kill the currently running simulations?"
        kill_job = QMessageBox.question(self, "Kill simulations?", msg,
                                        QMessageBox.Yes | QMessageBox.No)

        if kill_job == QMessageBox.Yes:
            # Normally this slot would be invoked by the signal/slot system,
            # but the worker is busy tracking the evaluation.
            self._worker.request_termination()
            self.reject()
        return kill_job

    @Slot(bool, str)
    def _on_simulation_done(self, failed, failed_msg):
        self.processing_animation.hide()
        self.kill_button.setHidden(True)
        self.done_button.setHidden(False)
        self.restart_button.setVisible(
            self._run_model.has_failed_realizations())
        self.restart_button.setEnabled(self._run_model.support_restart)
        self._total_progress_bar.setValue(100)
        self._total_progress_label.setText(
            _TOTAL_PROGRESS_TEMPLATE.format(
                total_progress=100, phase_name=self._run_model.getPhaseName()))

        if failed:
            msg = QMessageBox()
            msg.setIcon(QMessageBox.Critical)
            msg.setText("Simulations failed!".center(100))
            msg.setDetailedText(failed_msg)
            msg.exec_()

    @Slot()
    def _on_ticker(self):
        runtime = self._run_model.get_runtime()
        self.running_time.setText(format_running_time(runtime))

    @Slot(object)
    def _on_tracker_event(self, event):
        if isinstance(event, EndEvent):
            self.simulation_done.emit(event.failed, event.failed_msg)
            self._worker.stop()
            self._ticker.stop()

        elif isinstance(event, FullSnapshotEvent):
            if event.snapshot is not None:
                self._snapshot_model._add_snapshot(event.snapshot,
                                                   event.iteration)
            self._progress_view.setIndeterminate(event.indeterminate)
            progress = int(event.progress * 100)
            self._total_progress_bar.setValue(progress)
            self._total_progress_label.setText(
                _TOTAL_PROGRESS_TEMPLATE.format(total_progress=progress,
                                                phase_name=event.phase_name))

        elif isinstance(event, SnapshotUpdateEvent):
            if event.partial_snapshot is not None:
                self._snapshot_model._add_partial_snapshot(
                    event.partial_snapshot, event.iteration)
            self._progress_view.setIndeterminate(event.indeterminate)
            progress = int(event.progress * 100)
            self._total_progress_bar.setValue(progress)
            self._total_progress_label.setText(
                _TOTAL_PROGRESS_TEMPLATE.format(total_progress=progress,
                                                phase_name=event.phase_name))

    def restart_failed_realizations(self):

        msg = QMessageBox(self)
        msg.setIcon(QMessageBox.Information)
        msg.setText(
            "Note that workflows will only be executed on the restarted "
            "realizations and that this might have unexpected consequences.")
        msg.setWindowTitle("Restart failed realizations")
        msg.setStandardButtons(QMessageBox.Ok | QMessageBox.Cancel)
        result = msg.exec_()

        if result == QMessageBox.Ok:
            self.restart_button.setVisible(False)
            self.kill_button.setVisible(True)
            self.done_button.setVisible(False)
            self._run_model.restart()
            self.startSimulation()

    @Slot()
    def toggle_detailed_progress(self):
        if self._isDetailedDialog:
            self._setSimpleDialog()
        else:
            self._setDetailedDialog()

        self.adjustSize()
예제 #19
0
class AbortWindow(QDialog):
    """
    Displays busy message and provides abort button.
    The class serves SmoothCube, WorkerThread and SelectSmoothing.
    """

    def __init__(self, parent=None):
        """
        init abort or notification ui.
        Displays while smoothing freezes the application.
        Allows abort button to be added if needed.
        """
        super(AbortWindow, self).__init__(parent)
        self.setModal(False)
        self.setWindowFlags(self.windowFlags() | Qt.WindowStaysOnTopHint)

        self.parent = parent

        self.label_a_1 = QLabel("Executing smoothing algorithm.")
        self.label_a_2 = QLabel("This may take several minutes.")

        self.abort_button = QPushButton("Abort")
        self.abort_button.clicked.connect(self.abort)

        self.pb = QProgressBar(self)
        self.pb_counter = 0

        self.abort_flag = False

        self.info_box = None

        # vbl is short for Vertical Box Layout
        vbl = QVBoxLayout()
        vbl.addWidget(self.label_a_1)
        vbl.addWidget(self.label_a_2)
        vbl.addWidget(self.pb)
        vbl.addWidget(self.abort_button)

        self.setLayout(vbl)

        self.show()

    def init_pb(self, start, end):
        """
        Init the progress bar
        :param start: Start Value
        :param end: End Value
        """
        self.pb.setRange(start, end)
        self.pb_counter = start

    def update_pb(self):
        """
        This function is called in the worker thread to
        update the progress bar and checks if the
        local class variable abort_flag is active.

        If the abort button is clicked, the main thread
        will set abort_flag to True. The next time the
        worker thread calls this function, a custom
        exception is raised terminating the calculation.
        The exception is handled by the WorkerThread class.
        :raises: AbortException: terminating smoothing calculation
        """
        if self.abort_flag:
            raise AbortException("Abort Calculation")
        self.pb_counter += 1
        self.pb.setValue(self.pb_counter)
        QApplication.processEvents()

    def abort(self):
        """Abort calculation"""
        self.abort_flag = True
        self.parent.clean_up()

    def show_error_message(self, message, title, parent=None):
        self.info_box = QMessageBox(parent=parent)
        self.info_box.setIcon(QMessageBox.Information)
        self.info_box.setText(message)
        self.info_box.setWindowTitle(title)
        self.info_box.setStandardButtons(QMessageBox.Ok)
        self.info_box.show()

    def smoothing_done(self, component_id=None):
        """Notify user success"""
        self.hide()
        if component_id is None:
            message = "The result has been added as a" \
                      " new component of the input Data." \
                      " The new component can be accessed" \
                      " in the viewer drop-downs."
        else:
            message = "The result has been added as" \
                      " \"{0}\" and can be selected" \
                      " in the viewer drop-down menu.".format(component_id)

        self.show_error_message(message, "Success", self)
        self.clean_up()

    def print_error(self, exception):
        """Print error message"""

        if "signal only works in main thread" in str(exception):
            message = "Smoothing Failed!\n\n" + "Please update your SpectralCube package"
        else:
            message = "Smoothing Failed!\n\n" + str(exception)

        self.show_error_message(message, "Error", self)
        self.clean_up()

    def clean_up(self):
        self.parent.clean_up()

    def keyPressEvent(self, e):
        if e.key() == Qt.Key_Escape:
            self.abort()
예제 #20
0
class MainWindow(QMainWindow):
    def __init__(self, title):
        super().__init__()
        self.setWindowTitle(title)
        self.lib_path = ""
        self.final_title = ""
        analysis_icon = QIcon(os.path.join(icons_dir, "icon.png"))
        stack_icon = QIcon(os.path.join(icons_dir, "icon_stack.png"))
        self.analysis_button = QToolButton(self)
        self.analysis_button.setToolButtonStyle(Qt.ToolButtonTextUnderIcon)
        self.analysis_button.setIcon(analysis_icon)
        # TODO use more general solution for text wrapping
        self.analysis_button.setText(SEGMENTATION_NAME.replace(" ", "\n"))
        self.analysis_button.setIconSize(QSize(100, 100))
        self.mask_button = QToolButton(self)
        self.mask_button.setToolButtonStyle(Qt.ToolButtonTextUnderIcon)
        self.mask_button.setIcon(stack_icon)
        self.mask_button.setText(MASK_NAME.replace(" ", "\n"))
        self.mask_button.setIconSize(QSize(100, 100))
        self.analysis_button.clicked.connect(self.launch_analysis)
        self.mask_button.clicked.connect(self.launch_mask)
        self.progress = QProgressBar()
        self.progress.setHidden(True)
        layout = QGridLayout()
        layout.addWidget(self.progress, 0, 0, 1, 2)
        layout.addWidget(self.analysis_button, 1, 1)
        layout.addWidget(self.mask_button, 1, 0)
        widget = QWidget()
        widget.setLayout(layout)
        self.setCentralWidget(widget)
        self.setWindowIcon(analysis_icon)
        self.prepare = None
        self.wind = None

    def _launch_begin(self):
        self.progress.setVisible(True)
        self.progress.setRange(0, 0)
        self.analysis_button.setDisabled(True)
        self.mask_button.setDisabled(True)
        import_config()

    def launch_analysis(self):
        self._launch_begin()
        self.lib_path = "PartSeg.segmentation_analysis.main_window"
        self.final_title = "PartSeg Segmentation Analysis"
        self.prepare = Prepare(self.lib_path)
        self.prepare.finished.connect(self.launch)
        self.prepare.start()

    def launch_mask(self):
        self._launch_begin()
        self.lib_path = "PartSeg.segmentation_mask.main_window"
        self.final_title = "PartSeg Mask Segmentation"
        self.prepare = Prepare(self.lib_path)
        self.prepare.finished.connect(self.launch)
        self.prepare.start()

    def window_shown(self):
        self.close()

    def launch(self):
        if self.prepare.result is None:
            self.close()
            return
        if self.prepare.errors:
            errors_message = QMessageBox()
            errors_message.setText("There are errors during start")
            errors_message.setInformativeText(
                "During load saved state some of data could not be load properly\n"
                "The files has prepared backup copies in  state directory (Help > State directory)"
            )
            errors_message.setStandardButtons(QMessageBox.Ok)
            text = "\n".join(["File: " + x[0] + "\n" + str(x[1]) for x in self.prepare.errors])
            errors_message.setDetailedText(text)
            errors_message.exec()
        wind = self.prepare.result(title=self.final_title, signal_fun=self.window_shown)
        wind.show()
        self.wind = wind
예제 #21
0
class AbortWindow(QDialog):
    """
    Displays busy message and provides abort button.
    The class serves SmoothCube, WorkerThread and SelectSmoothing.
    """
    def __init__(self, parent=None):
        """
        init abort or notification ui.
        Displays while smoothing freezes the application.
        Allows abort button to be added if needed.
        """
        super(AbortWindow, self).__init__(parent)
        self.setModal(False)
        self.setWindowFlags(self.windowFlags() | Qt.Tool)

        self.parent = parent

        self.label_a_1 = QLabel("Executing smoothing algorithm.")
        self.label_a_2 = QLabel("This may take several minutes.")

        self.abort_button = QPushButton("Abort")
        self.abort_button.clicked.connect(self.abort)

        self.pb = QProgressBar(self)
        self.pb_counter = 0

        self.abort_function = None

        # vbl is short for Vertical Box Layout
        vbl = QVBoxLayout()
        vbl.addWidget(self.label_a_1)
        vbl.addWidget(self.label_a_2)
        vbl.addWidget(self.pb)
        vbl.addWidget(self.abort_button)

        self.setLayout(vbl)

        self.show()

    def init_pb(self, start, end):
        """
        Init the progress bar
        :param start: Start Value
        :param end: End Value
        """
        self.pb.setRange(start, end)
        self.pb_counter = start

    def update_pb(self):
        """Update progress bar"""
        self.pb_counter += 1
        self.pb.setValue(self.pb_counter)
        QApplication.processEvents()

    def abort(self):
        """Abort calculation"""
        if self.abort_function is not None:
            self.abort_function()
        self.parent.clean_up()

    def smoothing_done(self, component_id=None):
        """Notify user success"""
        self.hide()
        if component_id is None:
            message = "The result has been added as a" \
                      " new component of the input Data." \
                      " The new component can be accessed" \
                      " in the viewer drop-downs."
        else:
            message = "The result has been added as" \
                      " \"{0}\" and can be selected" \
                      " in the viewer drop-down menu.".format(component_id)

        info = QMessageBox.information(self, "Success", message)
        self.clean_up()

    def print_error(self, exception):
        """Print error message"""
        message = "Smoothing Failed!\n\n" + str(exception)
        info = QMessageBox.critical(self, "Error", message)
        self.clean_up()

    def clean_up(self):
        self.parent.clean_up()