コード例 #1
0
ファイル: drawing.py プロジェクト: tynanford/pydm
    def filename(self, new_file):
        """
        The filename of the image to be displayed.

        This file can be either relative to the ``.ui`` file or absolute. If
        the path does not exist, a shape of ``.null_color`` will be displayed
        instead.

        Parameters
        -------
        new_file : str
            The filename to be used
        """
        # Expand user (~ or ~user) and environment variables.
        pixmap = None
        self._file = new_file
        abs_path = os.path.expanduser(os.path.expandvars(self._file))
        # Find the absolute path relative to UI
        if not os.path.isabs(abs_path):
            try:
                # Based on the QApplication
                if is_pydm_app():
                    abs_path = QApplication.instance().get_path(abs_path)
                # Based on the QtDesigner
                elif is_qt_designer():  # pragma: no cover
                    p = self.get_designer_window()
                    if p is not None:
                        ui_dir = p.absoluteDir().absolutePath()
                        abs_path = os.path.join(ui_dir, abs_path)
            except Exception:
                logger.exception("Unable to find full filepath for %s",
                                 self._file)
        # Check that the path exists
        if os.path.isfile(abs_path):
            if self._movie is not None:
                self._movie.stop()
                self._movie.deleteLater()
                self._movie = None
            if not abs_path.endswith(".gif"):
                pixmap = QPixmap(abs_path)
            else:
                self._movie = QMovie(abs_path, parent=self)
                self._movie.setCacheMode(QMovie.CacheAll)
                self._movie.frameChanged.connect(self.movie_frame_changed)
                if self._movie.frameCount() > 1:
                    self._movie.finished.connect(self.movie_finished)
                self._movie.start()

        # Return a blank image if we don't have a valid path
        else:
            # Warn the user loudly if their file does not exist, but avoid
            # doing this in Designer as this spams the user as they are typing
            if not is_qt_designer():  # pragma: no cover
                logger.error("Image file  %r does not exist", abs_path)
            pixmap = QPixmap(self.sizeHint())
            pixmap.fill(self.null_color)
        # Update the display
        if pixmap is not None:
            self._pixmap = pixmap
            self.update()
コード例 #2
0
ファイル: qt_activity_dialog.py プロジェクト: sbinnee/napari
    def __init__(self, parent=None) -> None:
        super().__init__(parent=parent)
        self.setLayout(QHBoxLayout())

        self._activityBtn = QToolButton()
        self._activityBtn.setObjectName("QtActivityButton")
        self._activityBtn.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)
        self._activityBtn.setArrowType(Qt.UpArrow)
        self._activityBtn.setIconSize(QSize(11, 11))
        self._activityBtn.setText(trans._('activity'))
        self._activityBtn.setCheckable(True)

        self._inProgressIndicator = QLabel(trans._("in progress..."), self)
        sp = self._inProgressIndicator.sizePolicy()
        sp.setRetainSizeWhenHidden(True)
        self._inProgressIndicator.setSizePolicy(sp)
        load_gif = str(Path(napari.resources.__file__).parent / "loading.gif")
        mov = QMovie(load_gif)
        mov.setScaledSize(QSize(18, 18))
        self._inProgressIndicator.setMovie(mov)
        self._inProgressIndicator.hide()

        self.layout().addWidget(self._inProgressIndicator)
        self.layout().addWidget(self._activityBtn)
        self.layout().setContentsMargins(0, 0, 0, 0)
コード例 #3
0
ファイル: id_control.py プロジェクト: lnls-sirius/hla
    def _setupUi(self):
        cw = QWidget()
        self.setCentralWidget(cw)

        label = QLabel('<h3>ID Control Window</h3>',
                       self, alignment=Qt.AlignCenter)
        label.setStyleSheet('QLabel{min-height: 3em; max-height: 3em;}')

        self.label_mov1 = QLabel(self)
        self.label_mov1.setVisible(False)
        self.label_mov1.setStyleSheet(
            'QLabel{min-height: 3em; max-height: 3em;}')
        self.label_mov2 = QLabel(self)
        self.label_mov2.setVisible(False)
        self.label_mov2.setStyleSheet(
            'QLabel{min-height: 3em; max-height: 3em;}')
        self.movie_mov = QMovie(_os.path.join(
            _os.path.abspath(_os.path.dirname(__file__)), 'hula.gif'))
        self.movie_mov.setScaledSize(QSize(50, 50))
        self.label_mov1.setMovie(self.movie_mov)
        self.label_mov2.setMovie(self.movie_mov)

        self._gbox_apu = QGroupBox('APU', self)
        self._gbox_apu.setLayout(self._setupAPULayout())

        lay = QGridLayout(cw)
        lay.addWidget(self.label_mov1, 0, 0)
        lay.addWidget(label, 0, 1)
        lay.addWidget(self.label_mov2, 0, 2)
        lay.addWidget(self._gbox_apu, 1, 0, 1, 3)
        lay.setColumnStretch(0, 1)
        lay.setColumnStretch(1, 15)
        lay.setColumnStretch(2, 1)
コード例 #4
0
    def __init__(self, name=None, prefix=None):
        super(ListItemEnvironment, self).__init__()

        self._selected = False
        self._name = name
        self._prefix = prefix

        # Widgets
        self.button_options = ButtonEnvironmentOptions()
        self.button_name = ButtonEnvironmentName(name)
        self.label_icon = LabelEnvironmentIcon()
        self.movie = QMovie(SPINNER_GREEN_16_PATH)
        self.widget = WidgetEnvironment()
        self.widget.setFocusPolicy(Qt.NoFocus)
        self.widget.button_name = self.button_name
        self.widget.button_options = self.button_options

        # Widget setup
        self.label_icon.setMovie(self.movie)
        self.button_name.setDefault(True)

        # Layouts
        layout = QHBoxLayout()
        layout.addWidget(self.label_icon)
        layout.addWidget(self.button_name)
        layout.addWidget(self.button_options)
        layout.addStretch()

        self.widget.setLayout(layout)
        self.widget.setStyleSheet(load_style_sheet())
        self.setSizeHint(self.widget.sizeHint())
コード例 #5
0
ファイル: loading.py プロジェクト: PaddlePaddle/PaddleSeg
 def __init__(self):
     super().__init__()
     self.setWindowFlags(QtCore.Qt.FramelessWindowHint)
     layout = QHBoxLayout(self)
     self.label = QLabel()
     layout.addWidget(self.label)
     self.setLayout(layout)
     self.movie = QMovie(osp.join(pjpath, "resource", "loading.gif"))
     self.label.setMovie(self.movie)
     self.movie.start()
コード例 #6
0
ファイル: splash.py プロジェクト: ihumphrey/Xi-cam.gui
    def __init__(self,
                 log_path: str,
                 initial_length: int,
                 f: int = Qt.WindowStaysOnTopHint | Qt.SplashScreen):
        """
        A QSplashScreen customized to display an animated gif. The splash triggers launch when clicked.

        After minsplashtime, this splash waits until the animation finishes before triggering the launch.

        Parameters
        ----------
        log_path    :   str
            Path to the Xi-CAM log file to reflect
        initial_length: int
            Length in bytes to seek forward before reading
        f           :   int
            Extra flags (see base class)
        """

        # Get logo movie from relative path
        self.movie = QMovie(str(static.path("images/animated_logo.gif")))

        # Setup drawing
        self.movie.frameChanged.connect(self.paintFrame)
        self.movie.jumpToFrame(1)
        self.pixmap = QPixmap(self.movie.frameRect().size())
        super(XicamSplashScreen, self).__init__(self.pixmap, f)
        self.setMask(self.pixmap.mask())
        self.movie.finished.connect(self.restartmovie)
        self.showMessage('Starting Xi-CAM...')

        self._launching = False
        self._launchready = False
        self.timer = QTimer(self)

        self.log_file = open(log_path, 'r')
        self.log_file.seek(initial_length)

        # Start splashing
        self.setAttribute(Qt.WA_DeleteOnClose)
        self.show()
        self.raise_()
        self.activateWindow()
        QApplication.instance().setActiveWindow(self)

        # Setup timed triggers for launching the QMainWindow
        self.timer.singleShot(self.minsplashtime, self.launchwindow)
コード例 #7
0
 def set_loading(self, value):
     # self.button_options.setDisabled(value)
     if value:
         self.label_icon.setMovie(self.movie)
         self.movie.start()
     else:
         self.label_icon.setMovie(QMovie())
         self.button_options.setFocus()
コード例 #8
0
    def __init__(self, parent):
        super(KiteWelcome, self).__init__(parent)
        self.setFixedHeight(350)

        # Left side
        install_info = QLabel(
            _("<big><b>Level up your completions with "
              "Kite</b></big><br><br>"
              "Kite is a native app that runs locally "
              "on your computer <br>and uses machine learning "
              "to provide advanced <br>completions.<br><br>"
              "&#10003; Specialized support for Python "
              "data analysis packages<br><br>"
              "&#10003; 1.5x more completions "
              "than the builtin engine<br><br>"
              "&#10003; Completions ranked by code context <br><br>"
              "&#10003; Full line code completions<br><br>"
              "&#10003; 100% local - no internet "
              "connection required<br><br>"
              "&#10003; 100% free to use<br><br>"
              "<a href=\"https://kite.com/spyder-integration\">"
              "Go to Kite website</a>"))
        install_info.setOpenExternalLinks(True)

        # Right side
        action_layout = QVBoxLayout()
        install_gif_source = get_image_path('kite.gif')

        install_gif = QMovie(install_gif_source)
        install_gif_label = QLabel()
        install_gif.start()
        install_image = install_gif.currentPixmap()
        image_height = install_image.height() * 0.8
        image_width = install_image.width() * 0.8
        install_gif.setScaledSize(QSize(image_width, image_height))
        install_gif_label.setMovie(install_gif)

        button_layout = QHBoxLayout()
        install_button = QPushButton(_('Install Kite'))
        dismiss_button = QPushButton(_('Dismiss'))
        button_layout.addStretch()
        button_layout.addWidget(install_button)
        button_layout.addWidget(dismiss_button)
        button_layout.addStretch()

        action_layout.addWidget(install_gif_label)
        action_layout.addStretch()
        action_layout.addLayout(button_layout)

        # Layout
        general_layout = QHBoxLayout()
        general_layout.addWidget(install_info)
        general_layout.addLayout(action_layout)
        self.setLayout(general_layout)

        # Signals
        install_button.clicked.connect(self.sig_install_button_clicked)
        dismiss_button.clicked.connect(self.sig_dismiss_button_clicked)
コード例 #9
0
    def __init__(self,
                 mainwindow: Callable[[], QMainWindow] = None,
                 f: int = Qt.WindowStaysOnTopHint | Qt.SplashScreen):
        """
        A QSplashScreen customized to display an animated gif. The splash triggers launch when clicked.

        After minsplashtime, this splash waits until the animation finishes before triggering the launch.

        Parameters
        ----------
        mainwindow  :   class
            Subclass of QMainWindow to display after splashing
        f           :   int
            Extra flags (see base class)
        """

        # Get logo movie from relative path
        self.movie = QMovie(str(static.path("images/animated_logo.gif")))

        # Setup drawing
        self.movie.frameChanged.connect(self.paintFrame)
        self.movie.jumpToFrame(1)
        self.pixmap = QPixmap(self.movie.frameRect().size())
        super(XicamSplashScreen, self).__init__(self.pixmap, f)
        self.setMask(self.pixmap.mask())
        self.movie.finished.connect(self.restartmovie)

        self._launching = False
        self._launchready = False
        self.timer = QTimer(self)
        self.mainwindow = mainwindow

        # Start splashing
        self.setAttribute(Qt.WA_DeleteOnClose)
        self.show()
        self.raise_()
        self.activateWindow()
        QApplication.instance().setActiveWindow(self)
        if "--nosplash" in sys.argv:
            self.execlaunch()
        else:
            # Setup timed triggers for launching the QMainWindow
            self.timer.singleShot(self.minsplashtime, self.launchwindow)
コード例 #10
0
 def set_loading(self, value):
     """Set loading status of widget."""
     # self.button_options.setDisabled(value)
     #        if value:
     #            self.label_icon.setMovie(self.movie)
     #            self.movie.start()
     #        else:
     #            self.label_icon.setMovie(QMovie())
     #            self.button_options.setFocus()
     self.label_icon.setMovie(QMovie())
     self.button_options.setFocus()
コード例 #11
0
ファイル: utils.py プロジェクト: slactjohnson/typhos
    def __init__(self, *args, **kwargs):

        super().__init__(*args, **kwargs)
        self._icon_size = QSize(32, 32)
        if TyphosLoading.loading_gif is None:
            loading_path = os.path.join(ui_dir, 'loading.gif')
            TyphosLoading.loading_gif = QMovie(loading_path)
        self._animation = TyphosLoading.loading_gif
        self._animation.setScaledSize(self._icon_size)
        self.setMovie(self._animation)
        self._animation.start()
        if self.LOADING_TIMEOUT_MS > 0:
            QtCore.QTimer.singleShot(self.LOADING_TIMEOUT_MS,
                                     self._handle_timeout)
コード例 #12
0
    def __init__(self, timeout_message, *, parent=None, **kwargs):
        self.timeout_message = timeout_message
        super().__init__(parent=parent, **kwargs)
        self._icon_size = QSize(32, 32)
        if TyphosLoading.loading_gif is None:
            loading_path = os.path.join(ui_dir, 'loading.gif')
            TyphosLoading.loading_gif = QMovie(loading_path)
        self._animation = TyphosLoading.loading_gif
        self._animation.setScaledSize(self._icon_size)
        self.setMovie(self._animation)
        self._animation.start()
        if self.LOADING_TIMEOUT_MS > 0:
            QtCore.QTimer.singleShot(self.LOADING_TIMEOUT_MS,
                                     self._handle_timeout)

        self.setContextMenuPolicy(QtCore.Qt.DefaultContextMenu)
コード例 #13
0
ファイル: apps.py プロジェクト: fisher2017/Anaconda
    def __init__(self,
                 name=None,
                 description=None,
                 command=None,
                 pixmap=None,
                 version=None,
                 versions=None,
                 path=None,
                 dev_tool=True,
                 prefix=None,
                 is_conda_app=False,
                 packages_widget=None):
        super(ListItemApplication, self).__init__()

        self.api = AnacondaAPI()
        self.command = command
        self.dev_tool = dev_tool
        self.installed = False
        self.is_conda_app = is_conda_app
        self.name = name
        self.path = path
        self.pixmap = pixmap if pixmap else QPixmap(ANACONDA_ICON_64_PATH)
        self.prefix = prefix
        self.timeout = 10000  # In miliseconds
        self.version = version
        self.versions = versions
        self.packages_widget = packages_widget

        # Widgets
        self.button_install = ButtonApplicationInstall("Install")
        self.button_launch = ButtonApplicationLaunch("Launch")
        self.button_options = ButtonApplicationOptions()
        self.label_icon = LabelApplicationIcon()
        self.label_name = LabelApplicationName(name)
        self.label_description = LabelApplicationDescription(description)
        #        self.label_update = LabelApplicationUpdate()
        self.button_version = ButtonApplicationVersion(to_text_string(version))
        self.label_spinner = LabelApplicationSpinner()
        #        self.label_version = LabelApplicationVersion(to_text_string(version))
        self.menu_options = QMenu('Application options')
        self.menu_versions = QMenu('Install specific version')
        self.movie_spinner = QMovie(SPINNER_WHITE_16_PATH)
        self.timer = QTimer()
        self.widget = WidgetApplication()

        # Widget setup
        self.button_version.setFocusPolicy(Qt.NoFocus)
        self.label_name.setToolTip(description)
        self.label_description.setAlignment(Qt.AlignCenter)
        self.movie_spinner.start()
        self.timer.setInterval(self.timeout)
        self.timer.setSingleShot(True)
        self.label_icon.setToolTip(description)
        self.label_icon.setPixmap(
            self.pixmap.scaled(self.ICON_SIZE, self.ICON_SIZE,
                               Qt.KeepAspectRatio, Qt.SmoothTransformation))
        self.label_icon.setAlignment(Qt.AlignCenter)
        self.label_name.setAlignment(Qt.AlignCenter)
        self.label_name.setWordWrap(True)
        self.label_description.setWordWrap(True)
        self.label_description.setAlignment(Qt.AlignTop | Qt.AlignHCenter)
        self.label_spinner.setVisible(False)
        self.label_spinner.setMinimumWidth(16)
        self.label_spinner.setMinimumHeight(16)

        # Layouts
        layout = QVBoxLayout()
        layout.addWidget(self.button_options, 0, Qt.AlignRight)
        layout.addWidget(self.label_icon, 0, Qt.AlignCenter)
        layout.addWidget(self.label_name, 0, Qt.AlignCenter)
        layout.addWidget(self.label_description, 0, Qt.AlignCenter)

        #        hlayout = QHBoxLayout()
        #        hlayout.addWidget(self.label_update)
        #        hlayout.addWidget(self.label_version)
        #        layout.addLayout(hlayout)
        #        layout.addWidget(self.label_version, 0, Qt.AlignCenter)
        layout.addWidget(self.button_version, 0, Qt.AlignCenter)
        layout.addWidget(self.label_spinner, 0, Qt.AlignCenter)
        layout.addWidget(self.button_launch, 0, Qt.AlignCenter)
        layout.addWidget(self.button_install, 0, Qt.AlignCenter)

        self.widget.setLayout(layout)
        self.widget.setStyleSheet(load_style_sheet())
        self.setSizeHint(self.widget.sizeHint())

        # Signals
        self.button_install.clicked.connect(self.install_application)
        self.button_launch.clicked.connect(self.launch_application)
        self.button_options.clicked.connect(self.actions_menu_requested)
        self.timer.timeout.connect(self._application_launched)

        # Setup
        self.update_status()
コード例 #14
0
    def setup_ui(self):
        self.resize(1080, 640)
        vlay_1 = QVBoxLayout(self)
        self.h_splitter = QSplitter(self)
        vlay_1.addWidget(self.h_splitter)
        self.h_splitter.setOrientation(Qt.Horizontal)
        self.v_splitter = QSplitter(self.h_splitter)
        self.v_splitter.setOrientation(Qt.Vertical)
        self.v_splitter.setMinimumWidth(500)

        installed = QWidget(self.v_splitter)
        lay = QVBoxLayout(installed)
        lay.setContentsMargins(0, 2, 0, 2)
        self.installed_label = QLabel(trans._("Installed Plugins"))
        self.packages_filter = QLineEdit()
        self.packages_filter.setPlaceholderText(trans._("filter..."))
        self.packages_filter.setMaximumWidth(350)
        self.packages_filter.setClearButtonEnabled(True)
        mid_layout = QVBoxLayout()
        mid_layout.addWidget(self.packages_filter)
        mid_layout.addWidget(self.installed_label)
        lay.addLayout(mid_layout)

        self.installed_list = QPluginList(installed, self.installer)
        self.packages_filter.textChanged.connect(self.installed_list.filter)
        lay.addWidget(self.installed_list)

        uninstalled = QWidget(self.v_splitter)
        lay = QVBoxLayout(uninstalled)
        lay.setContentsMargins(0, 2, 0, 2)
        self.avail_label = QLabel(trans._("Available Plugins"))
        mid_layout = QHBoxLayout()
        mid_layout.addWidget(self.avail_label)
        mid_layout.addStretch()
        lay.addLayout(mid_layout)
        self.available_list = QPluginList(uninstalled, self.installer)
        self.packages_filter.textChanged.connect(self.available_list.filter)
        lay.addWidget(self.available_list)

        self.stdout_text = QTextEdit(self.v_splitter)
        self.stdout_text.setReadOnly(True)
        self.stdout_text.setObjectName("pip_install_status")
        self.stdout_text.hide()

        buttonBox = QHBoxLayout()
        self.working_indicator = QLabel(trans._("loading ..."), self)
        sp = self.working_indicator.sizePolicy()
        sp.setRetainSizeWhenHidden(True)
        self.working_indicator.setSizePolicy(sp)
        self.process_error_indicator = QLabel(self)
        self.process_error_indicator.setObjectName("error_label")
        self.process_error_indicator.hide()
        load_gif = str(Path(napari.resources.__file__).parent / "loading.gif")
        mov = QMovie(load_gif)
        mov.setScaledSize(QSize(18, 18))
        self.working_indicator.setMovie(mov)
        mov.start()

        visibility_direct_entry = not running_as_constructor_app()
        self.direct_entry_edit = QLineEdit(self)
        self.direct_entry_edit.installEventFilter(self)
        self.direct_entry_edit.setPlaceholderText(
            trans._('install by name/url, or drop file...'))
        self.direct_entry_edit.setVisible(visibility_direct_entry)
        self.direct_entry_btn = QPushButton(trans._("Install"), self)
        self.direct_entry_btn.setVisible(visibility_direct_entry)
        self.direct_entry_btn.clicked.connect(self._install_packages)

        self.show_status_btn = QPushButton(trans._("Show Status"), self)
        self.show_status_btn.setFixedWidth(100)

        self.cancel_all_btn = QPushButton(trans._("cancel all actions"), self)
        self.cancel_all_btn.setObjectName("remove_button")
        self.cancel_all_btn.setVisible(False)
        self.cancel_all_btn.clicked.connect(lambda: self.installer.cancel())

        self.close_btn = QPushButton(trans._("Close"), self)
        self.close_btn.clicked.connect(self.accept)
        self.close_btn.setObjectName("close_button")
        buttonBox.addWidget(self.show_status_btn)
        buttonBox.addWidget(self.working_indicator)
        buttonBox.addWidget(self.direct_entry_edit)
        buttonBox.addWidget(self.direct_entry_btn)
        if not visibility_direct_entry:
            buttonBox.addStretch()
        buttonBox.addWidget(self.process_error_indicator)
        buttonBox.addSpacing(20)
        buttonBox.addWidget(self.cancel_all_btn)
        buttonBox.addSpacing(20)
        buttonBox.addWidget(self.close_btn)
        buttonBox.setContentsMargins(0, 0, 4, 0)
        vlay_1.addLayout(buttonBox)

        self.show_status_btn.setCheckable(True)
        self.show_status_btn.setChecked(False)
        self.show_status_btn.toggled.connect(self._toggle_status)

        self.v_splitter.setStretchFactor(1, 2)
        self.h_splitter.setStretchFactor(0, 2)

        self.packages_filter.setFocus()
コード例 #15
0
class ListItemApplication(ListWidgetItemBase):
    """Item with custom widget for the applications list."""

    ICON_SIZE = 64

    def __init__(
        self,
        name=None,
        description=None,
        command=None,
        versions=None,
        image_path=None,
        prefix=None,
        needs_license=False,
    ):
        """Item with custom widget for the applications list."""
        super(ListItemApplication, self).__init__()

        self.api = AnacondaAPI()
        self.prefix = prefix
        self.name = name
        self.url = ''
        self.expired = False
        self.needs_license = needs_license
        self.description = description
        self.command = command
        self.versions = versions
        self.image_path = image_path if image_path else ANACONDA_ICON_256_PATH
        self.style_sheet = None
        self.timeout = 2000

        # Widgets
        self.button_install = ButtonApplicationInstall("Install")  # or Try!
        self.button_launch = ButtonApplicationLaunch("Launch")
        self.button_options = ButtonApplicationOptions()
        self.label_license = LabelApplicationLicense('')
        self.button_license = ButtonApplicationLicense('')
        self.label_icon = LabelApplicationIcon()
        self.label_name = LabelApplicationName(self.name)
        self.label_description = LabelApplicationDescription(self.description)
        self.button_version = ButtonApplicationVersion(
            to_text_string(self.version))
        self.label_spinner = LabelApplicationSpinner()
        self.menu_options = QMenu('Application options')
        self.menu_versions = QMenu('Install specific version')
        self.movie_spinner = QMovie(SPINNER_WHITE_16_PATH)
        self.pixmap = QPixmap(self.image_path)
        self.timer = QTimer()
        self.widget = WidgetApplication()

        # Widget setup
        self.button_version.setFocusPolicy(Qt.NoFocus)
        self.button_version.setEnabled(True)
        self.label_description.setAlignment(Qt.AlignCenter)
        self.movie_spinner.start()
        self.timer.setInterval(self.timeout)
        self.timer.setSingleShot(True)
        self.label_icon.setPixmap(self.pixmap)
        self.label_icon.setScaledContents(True)  # important on High DPI!
        self.label_icon.setMaximumWidth(self.ICON_SIZE)
        self.label_icon.setMaximumHeight(self.ICON_SIZE)
        self.label_icon.setAlignment(Qt.AlignCenter)
        self.label_name.setAlignment(Qt.AlignCenter)
        self.label_name.setWordWrap(True)
        self.label_description.setWordWrap(True)
        self.label_description.setAlignment(Qt.AlignTop | Qt.AlignHCenter)
        self.label_spinner.setVisible(False)

        # Layouts
        layout_spinner = QHBoxLayout()
        layout_spinner.addWidget(self.button_version, 0, Qt.AlignCenter)
        layout_spinner.addWidget(self.label_spinner, 0, Qt.AlignCenter)

        layout_license = QHBoxLayout()
        layout_license.addStretch()
        layout_license.addWidget(self.label_license, 0, Qt.AlignCenter)
        layout_license.addWidget(self.button_license, 0, Qt.AlignCenter)
        layout_license.addStretch()

        layout_main = QVBoxLayout()
        layout_main.addWidget(self.button_options, 0, Qt.AlignRight)
        layout_main.addWidget(self.label_icon, 0, Qt.AlignCenter)
        layout_main.addWidget(self.label_name, 0, Qt.AlignCenter)
        layout_main.addLayout(layout_spinner)
        layout_main.addLayout(layout_license)
        layout_main.addWidget(self.label_description, 0, Qt.AlignCenter)
        layout_main.addWidget(self.button_launch, 0, Qt.AlignCenter)
        layout_main.addWidget(self.button_install, 0, Qt.AlignCenter)

        self.widget.setLayout(layout_main)
        self.widget.setStyleSheet(load_style_sheet())
        self.setSizeHint(self.widget_size())
        # This might help with visual quirks on the home screen
        self.widget.setMinimumSize(self.widget_size())

        # Signals
        self.button_install.clicked.connect(self.install_application)
        self.button_launch.clicked.connect(self.launch_application)
        self.button_options.clicked.connect(self.actions_menu_requested)
        self.button_license.clicked.connect(self.launch_url)
        self.timer.timeout.connect(self._application_launched)

        # Setup
        self.update_status()

    # --- Callbacks
    # -------------------------------------------------------------------------
    def _application_launched(self):
        self.button_launch.setDisabled(False)
        update_pointer()

    # --- Helpers
    # -------------------------------------------------------------------------
    def update_style_sheet(self, style_sheet=None):
        """Update custom CSS stylesheet."""
        if style_sheet:
            self.style_sheet = style_sheet
        else:
            self.style_sheet = load_style_sheet()

        self.menu_options.setStyleSheet(self.style_sheet)
        self.menu_versions.setStyleSheet(self.style_sheet)

    def ordered_widgets(self):
        """Return a list of the ordered widgets."""
        return [
            self.button_license, self.button_install, self.button_launch,
            self.button_options
        ]

    @staticmethod
    def widget_size():
        """Return the size defined in the SASS file."""
        return QSize(SASS_VARIABLES.WIDGET_APPLICATION_TOTAL_WIDTH,
                     SASS_VARIABLES.WIDGET_APPLICATION_TOTAL_HEIGHT)

    def launch_url(self):
        """Launch signal for url click."""
        self.widget.sig_url_clicked.emit(self.url)

    def actions_menu_requested(self):
        """Create and display menu for the currently selected application."""
        self.menu_options.clear()
        self.menu_versions.clear()

        # Add versions menu
        versions = self.versions if self.versions else []
        version_actions = []
        for version in reversed(versions):
            action = create_action(self.widget,
                                   version,
                                   triggered=lambda value, version=version:
                                   self.install_application(version=version))

            action.setCheckable(True)
            if self.version == version and self.installed:
                action.setChecked(True)
                action.setDisabled(True)

            version_actions.append(action)

        install_action = create_action(
            self.widget,
            'Install application',
            triggered=lambda: self.install_application())
        install_action.setEnabled(not self.installed)

        update_action = create_action(
            self.widget,
            'Update application',
            triggered=lambda: self.update_application())

        if versions and versions[-1] == self.version:
            update_action.setDisabled(True)
        else:
            update_action.setDisabled(False)

        remove_action = create_action(
            self.widget,
            'Remove application',
            triggered=lambda: self.remove_application())
        remove_action.setEnabled(self.installed)

        actions = [
            install_action, update_action, remove_action, None,
            self.menu_versions
        ]
        add_actions(self.menu_options, actions)
        add_actions(self.menu_versions, version_actions)
        offset = QPoint(self.button_options.width(), 0)
        position = self.button_options.mapToGlobal(QPoint(0, 0))
        self.menu_versions.setEnabled(len(versions) > 1)
        self.menu_options.move(position + offset)
        self.menu_options.exec_()

    def update_status(self):
        """Update status."""
        # License check
        license_label_text = ''
        license_url_text = ''
        self.url = ''
        self.expired = False
        button_label = 'Install'

        if self.needs_license:
            # TODO: Fix this method to use the api
            license_info = self.api.get_package_license(self.name)
            license_days = self.api.get_days_left(license_info)
            end_date = license_info.get('end_date', '')
            self.expired = license_days == 0
            plural = 's' if license_days != 1 else ''
            is_trial = license_info.get('type', '').lower() == 'trial'

            if self.installed and license_info:
                if is_trial and not self.expired:
                    license_label_text = ('Trial, {days} day{plural} '
                                          'remaining'.format(days=license_days,
                                                             plural=plural))
                    self.url = ''
                elif is_trial and self.expired:
                    license_label_text = 'Trial expired, '
                    license_url_text = 'contact us'
                    self.url = 'mailto:[email protected]'
                elif not is_trial and not self.expired:
                    license_label_text = 'License expires {}'.format(end_date)
                    self.url = ''
                elif not is_trial and self.expired:
                    license_url_text = 'Renew license'
                    self.url = 'mailto:[email protected]'
            elif self.installed and not bool(license_info):
                # Installed but no license found!
                license_url_text = 'No license found'
                self.url = 'mailto:[email protected]'
            else:
                if not self.expired:
                    button_label = 'Install'
                else:
                    button_label = 'Try'

        self.button_license.setText(license_url_text)
        self.button_license.setVisible(bool(self.url))
        self.label_license.setText(license_label_text)
        self.label_license.setVisible(bool(license_label_text))

        # Version and version updates
        if (self.versions and self.version != self.versions[-1]
                and self.installed):
            # The property is used with CSS to display updatable packages.
            self.button_version.setProperty('pressed', True)
            self.button_version.setToolTip('Version {0} available'.format(
                self.versions[-1]))
        else:
            self.button_version.setProperty('pressed', False)

        if not self.needs_license:
            self.button_install.setText(button_label)
            self.button_install.setVisible(not self.installed)
            self.button_launch.setVisible(self.installed)
        else:
            self.button_install.setText('Try' if self.expired else 'Install')
            self.button_launch.setVisible(not self.expired)
            self.button_install.setVisible(self.expired)

        self.button_launch.setEnabled(True)

    def update_versions(self, version=None, versions=None):
        """Update button visibility depending on update availability."""
        logger.debug(str((self.name, self.dev_tool, self.installed)))

        if self.installed and version:
            self.button_options.setVisible(True)
            self.button_version.setText(version)
            self.button_version.setVisible(True)
        elif not self.installed and versions:
            self.button_install.setEnabled(True)
            self.button_version.setText(versions[-1])
            self.button_version.setVisible(True)

        self.versions = versions
        self.version = version
        self.update_status()

    def set_loading(self, value):
        """Set loading status."""
        self.button_install.setDisabled(value)
        self.button_options.setDisabled(value)
        self.button_launch.setDisabled(value)
        self.button_license.setDisabled(value)

        if value:
            self.label_spinner.setMovie(self.movie_spinner)
        else:
            self.label_spinner.setMovie(None)
            if self.version is None and self.versions is not None:
                version = self.versions[-1]
            else:
                version = self.version
            self.button_version.setText(version)
            self.button_launch.setDisabled(self.expired)

        self.label_spinner.setVisible(value)
        self.button_version.setVisible(not value)

    # --- Helpers using api
    # -------------------------------------------------------------------------
    @property
    def installed(self):
        """Return the installed status of the package."""
        version = None
        if self.prefix:
            version = self.api.conda_package_version(prefix=self.prefix,
                                                     pkg=self.name,
                                                     build=False)
        return bool(version)

    @property
    def version(self):
        """Return the current installed version or the highest version."""
        version = None
        if self.prefix:
            version = self.api.conda_package_version(prefix=self.prefix,
                                                     pkg=self.name,
                                                     build=False)
        if not version:
            version = self.versions[-1]

        return version

    # --- Application actions
    # ------------------------------------------------------------------------
    def install_application(self, value=None, version=None, install=True):
        """
        Update the application on the defined prefix environment.

        This is used for both normal install and specific version install.
        """
        if not version:
            version = self.versions[-1]

        action = C.APPLICATION_INSTALL if install else C.APPLICATION_UPDATE
        self.widget.sig_conda_action_requested.emit(
            action,
            self.name,
            version,
            C.TAB_HOME,
        )
        self.set_loading(True)

    def remove_application(self):
        """Remove the application from the defined prefix environment."""
        self.widget.sig_conda_action_requested.emit(
            C.APPLICATION_REMOVE,
            self.name,
            None,
            C.TAB_HOME,
        )
        self.set_loading(True)

    def update_application(self):
        """Update the application on the defined prefix environment."""
        self.install_application(version=self.versions[-1], install=False)

    def launch_application(self):
        """Launch application installed in prefix environment."""
        leave_path_alone = False
        if self.command is not None:
            # Applications on Windows often live in 'bin' folders. By using
            # ${PREFIX} command we indicate that we do not want launch() to
            # mess with the path and will instead use selectors in recipes.
            if '${PREFIX}' in self.command:
                command = self.command.replace("${PREFIX}", self.prefix)
                leave_path_alone = True
            elif self.prefix:
                command = os.sep.join([self.prefix, 'bin', self.command])
            else:
                command = self.command

            self.button_launch.setDisabled(True)
            self.timer.setInterval(self.timeout)
            self.timer.start()
            update_pointer(Qt.BusyCursor)
            self.widget.sig_launch_action_requested.emit(
                self.name,
                command,
                leave_path_alone,
                self.prefix,
                C.TAB_HOME,
            )
コード例 #16
0
    def setup_ui(self):
        self.resize(1080, 640)
        vlay_1 = QVBoxLayout(self)
        self.h_splitter = QSplitter(self)
        vlay_1.addWidget(self.h_splitter)
        self.h_splitter.setOrientation(Qt.Horizontal)
        self.v_splitter = QSplitter(self.h_splitter)
        self.v_splitter.setOrientation(Qt.Vertical)
        self.v_splitter.setMinimumWidth(500)
        self.plugin_sorter = QtPluginSorter(parent=self.h_splitter)
        self.plugin_sorter.layout().setContentsMargins(2, 0, 0, 0)
        self.plugin_sorter.hide()

        installed = QWidget(self.v_splitter)
        lay = QVBoxLayout(installed)
        lay.setContentsMargins(0, 2, 0, 2)
        lay.addWidget(QLabel(trans._("Installed Plugins")))
        self.installed_list = QPluginList(installed, self.installer)
        lay.addWidget(self.installed_list)

        uninstalled = QWidget(self.v_splitter)
        lay = QVBoxLayout(uninstalled)
        lay.setContentsMargins(0, 2, 0, 2)
        self.avail_label = QLabel(trans._("Available Plugins"))
        lay.addWidget(self.avail_label)
        self.available_list = QPluginList(uninstalled, self.installer)
        lay.addWidget(self.available_list)

        self.stdout_text = QTextEdit(self.v_splitter)
        self.stdout_text.setReadOnly(True)
        self.stdout_text.setObjectName("pip_install_status")
        self.stdout_text.hide()

        buttonBox = QHBoxLayout()
        self.working_indicator = QLabel(trans._("loading ..."), self)
        sp = self.working_indicator.sizePolicy()
        sp.setRetainSizeWhenHidden(True)
        self.working_indicator.setSizePolicy(sp)
        self.process_error_indicator = QLabel(self)
        self.process_error_indicator.setObjectName("error_label")
        self.process_error_indicator.hide()
        load_gif = str(Path(napari.resources.__file__).parent / "loading.gif")
        mov = QMovie(load_gif)
        mov.setScaledSize(QSize(18, 18))
        self.working_indicator.setMovie(mov)
        mov.start()

        self.direct_entry_edit = QLineEdit(self)
        self.direct_entry_edit.installEventFilter(self)
        self.direct_entry_edit.setPlaceholderText(
            trans._('install by name/url, or drop file...'))
        self.direct_entry_btn = QPushButton(trans._("Install"), self)
        self.direct_entry_btn.clicked.connect(self._install_packages)

        self.show_status_btn = QPushButton(trans._("Show Status"), self)
        self.show_status_btn.setFixedWidth(100)
        self.show_sorter_btn = QPushButton(trans._("<< Show Sorter"), self)
        self.close_btn = QPushButton(trans._("Close"), self)
        self.close_btn.clicked.connect(self.reject)
        buttonBox.addWidget(self.show_status_btn)
        buttonBox.addWidget(self.working_indicator)
        buttonBox.addWidget(self.direct_entry_edit)
        buttonBox.addWidget(self.direct_entry_btn)
        buttonBox.addWidget(self.process_error_indicator)
        buttonBox.addSpacing(60)
        buttonBox.addWidget(self.show_sorter_btn)
        buttonBox.addWidget(self.close_btn)
        buttonBox.setContentsMargins(0, 0, 4, 0)
        vlay_1.addLayout(buttonBox)

        self.show_status_btn.setCheckable(True)
        self.show_status_btn.setChecked(False)
        self.show_status_btn.toggled.connect(self._toggle_status)

        self.show_sorter_btn.setCheckable(True)
        self.show_sorter_btn.setChecked(False)
        self.show_sorter_btn.toggled.connect(self._toggle_sorter)

        self.v_splitter.setStretchFactor(1, 2)
        self.h_splitter.setStretchFactor(0, 2)
コード例 #17
0
class ListItemEnvironment(QListWidgetItem):
    """
    Widget to build an item for the environments list.
    """
    def __init__(self, name=None, prefix=None):
        super(ListItemEnvironment, self).__init__()

        self._selected = False
        self._name = name
        self._prefix = prefix

        # Widgets
        self.button_options = ButtonEnvironmentOptions()
        self.button_name = ButtonEnvironmentName(name)
        self.label_icon = LabelEnvironmentIcon()
        self.movie = QMovie(SPINNER_GREEN_16_PATH)
        self.widget = WidgetEnvironment()
        self.widget.setFocusPolicy(Qt.NoFocus)
        self.widget.button_name = self.button_name
        self.widget.button_options = self.button_options

        # Widget setup
        self.label_icon.setMovie(self.movie)
        self.button_name.setDefault(True)

        # Layouts
        layout = QHBoxLayout()
        layout.addWidget(self.label_icon)
        layout.addWidget(self.button_name)
        layout.addWidget(self.button_options)
        layout.addStretch()

        self.widget.setLayout(layout)
        self.widget.setStyleSheet(load_style_sheet())
        self.setSizeHint(self.widget.sizeHint())

    def text(self):
        return self._name

    def prefix(self):
        return self._prefix

    def set_hovered(self, value):
        self.widget.setProperty('_hovered', value)
        self.button_name.set_hovered(value)

    def set_loading(self, value):
        # self.button_options.setDisabled(value)
        if value:
            self.label_icon.setMovie(self.movie)
            self.movie.start()
        else:
            self.label_icon.setMovie(QMovie())
            self.button_options.setFocus()

    def set_selected(self, value):
        self._selected = value
        try:
            self.widget.setProperty('_selected', value)
            self.button_name.set_selected(value)
        except RuntimeError:
            pass

        self.button_name.setDisabled(value)

        if value:
            self.label_icon.setMovie(None)
            self.button_name.setFocusPolicy(Qt.NoFocus)
            self.button_options.setVisible(True)
            self.button_options.setFocus()
        else:
            self.label_icon.setMovie(None)
            self.button_name.setFocusPolicy(Qt.TabFocus)
            self.button_options.setVisible(False)
コード例 #18
0
    def __init__(
        self,
        name=None,
        description=None,
        command=None,
        versions=None,
        image_path=None,
        prefix=None,
        needs_license=False,
    ):
        """Item with custom widget for the applications list."""
        super(ListItemApplication, self).__init__()

        self.api = AnacondaAPI()
        self.prefix = prefix
        self.name = name
        self.url = ''
        self.expired = False
        self.needs_license = needs_license
        self.description = description
        self.command = command
        self.versions = versions
        self.image_path = image_path if image_path else ANACONDA_ICON_256_PATH
        self.style_sheet = None
        self.timeout = 2000

        # Widgets
        self.button_install = ButtonApplicationInstall("Install")  # or Try!
        self.button_launch = ButtonApplicationLaunch("Launch")
        self.button_options = ButtonApplicationOptions()
        self.label_license = LabelApplicationLicense('')
        self.button_license = ButtonApplicationLicense('')
        self.label_icon = LabelApplicationIcon()
        self.label_name = LabelApplicationName(self.name)
        self.label_description = LabelApplicationDescription(self.description)
        self.button_version = ButtonApplicationVersion(
            to_text_string(self.version))
        self.label_spinner = LabelApplicationSpinner()
        self.menu_options = QMenu('Application options')
        self.menu_versions = QMenu('Install specific version')
        self.movie_spinner = QMovie(SPINNER_WHITE_16_PATH)
        self.pixmap = QPixmap(self.image_path)
        self.timer = QTimer()
        self.widget = WidgetApplication()

        # Widget setup
        self.button_version.setFocusPolicy(Qt.NoFocus)
        self.button_version.setEnabled(True)
        self.label_description.setAlignment(Qt.AlignCenter)
        self.movie_spinner.start()
        self.timer.setInterval(self.timeout)
        self.timer.setSingleShot(True)
        self.label_icon.setPixmap(self.pixmap)
        self.label_icon.setScaledContents(True)  # important on High DPI!
        self.label_icon.setMaximumWidth(self.ICON_SIZE)
        self.label_icon.setMaximumHeight(self.ICON_SIZE)
        self.label_icon.setAlignment(Qt.AlignCenter)
        self.label_name.setAlignment(Qt.AlignCenter)
        self.label_name.setWordWrap(True)
        self.label_description.setWordWrap(True)
        self.label_description.setAlignment(Qt.AlignTop | Qt.AlignHCenter)
        self.label_spinner.setVisible(False)

        # Layouts
        layout_spinner = QHBoxLayout()
        layout_spinner.addWidget(self.button_version, 0, Qt.AlignCenter)
        layout_spinner.addWidget(self.label_spinner, 0, Qt.AlignCenter)

        layout_license = QHBoxLayout()
        layout_license.addStretch()
        layout_license.addWidget(self.label_license, 0, Qt.AlignCenter)
        layout_license.addWidget(self.button_license, 0, Qt.AlignCenter)
        layout_license.addStretch()

        layout_main = QVBoxLayout()
        layout_main.addWidget(self.button_options, 0, Qt.AlignRight)
        layout_main.addWidget(self.label_icon, 0, Qt.AlignCenter)
        layout_main.addWidget(self.label_name, 0, Qt.AlignCenter)
        layout_main.addLayout(layout_spinner)
        layout_main.addLayout(layout_license)
        layout_main.addWidget(self.label_description, 0, Qt.AlignCenter)
        layout_main.addWidget(self.button_launch, 0, Qt.AlignCenter)
        layout_main.addWidget(self.button_install, 0, Qt.AlignCenter)

        self.widget.setLayout(layout_main)
        self.widget.setStyleSheet(load_style_sheet())
        self.setSizeHint(self.widget_size())
        # This might help with visual quirks on the home screen
        self.widget.setMinimumSize(self.widget_size())

        # Signals
        self.button_install.clicked.connect(self.install_application)
        self.button_launch.clicked.connect(self.launch_application)
        self.button_options.clicked.connect(self.actions_menu_requested)
        self.button_license.clicked.connect(self.launch_url)
        self.timer.timeout.connect(self._application_launched)

        # Setup
        self.update_status()
コード例 #19
0
ファイル: drawing.py プロジェクト: tynanford/pydm
class PyDMDrawingImage(PyDMDrawing):
    """
    Renders an image given by the ``filename`` property.
    This class inherits from PyDMDrawing.

    Parameters
    ----------
    parent : QWidget
        The parent widget for the Label
    init_channel : str, optional
        The channel to be used by the widget.

    Attributes
    ----------
    null_color : Qt.Color
        QColor to fill the image if the filename is not found.
    """
    null_color = Qt.gray

    def __init__(self, parent=None, init_channel=None, filename=""):
        super(PyDMDrawingImage, self).__init__(parent, init_channel)
        hint = super(PyDMDrawingImage, self).sizeHint()
        self._pixmap = QPixmap(hint)
        self._pixmap.fill(self.null_color)
        self._aspect_ratio_mode = Qt.KeepAspectRatio
        self._movie = None
        # Make sure we don't set a non-existant file
        if filename:
            self.filename = filename
        # But we always have an internal value to reference
        else:
            self._file = filename
        if is_qt_designer():  # pragma: no cover
            designer_window = self.get_designer_window()
            if designer_window is not None:
                designer_window.fileNameChanged.connect(
                    self.designer_form_saved)

    def get_designer_window(self):  # pragma: no cover
        # Internal function to find the designer window that owns this widget.
        p = self.parent()
        while p is not None:
            if isinstance(p, QDesignerFormWindowInterface):
                return p
            p = p.parent()
        return None

    @Slot(str)
    def designer_form_saved(self, filename):  # pragma: no cover
        self.filename = self._file

    @Property(str)
    def filename(self):
        """
        The filename of the image to be displayed.
        This can be an absolute or relative path to the display file.

        Returns
        -------
        str
            The filename configured.
        """
        return self._file

    @filename.setter
    def filename(self, new_file):
        """
        The filename of the image to be displayed.

        This file can be either relative to the ``.ui`` file or absolute. If
        the path does not exist, a shape of ``.null_color`` will be displayed
        instead.

        Parameters
        -------
        new_file : str
            The filename to be used
        """
        # Expand user (~ or ~user) and environment variables.
        pixmap = None
        self._file = new_file
        abs_path = os.path.expanduser(os.path.expandvars(self._file))
        # Find the absolute path relative to UI
        if not os.path.isabs(abs_path):
            try:
                # Based on the QApplication
                if is_pydm_app():
                    abs_path = QApplication.instance().get_path(abs_path)
                # Based on the QtDesigner
                elif is_qt_designer():  # pragma: no cover
                    p = self.get_designer_window()
                    if p is not None:
                        ui_dir = p.absoluteDir().absolutePath()
                        abs_path = os.path.join(ui_dir, abs_path)
            except Exception:
                logger.exception("Unable to find full filepath for %s",
                                 self._file)
        # Check that the path exists
        if os.path.isfile(abs_path):
            if self._movie is not None:
                self._movie.stop()
                self._movie.deleteLater()
                self._movie = None
            if not abs_path.endswith(".gif"):
                pixmap = QPixmap(abs_path)
            else:
                self._movie = QMovie(abs_path, parent=self)
                self._movie.setCacheMode(QMovie.CacheAll)
                self._movie.frameChanged.connect(self.movie_frame_changed)
                if self._movie.frameCount() > 1:
                    self._movie.finished.connect(self.movie_finished)
                self._movie.start()

        # Return a blank image if we don't have a valid path
        else:
            # Warn the user loudly if their file does not exist, but avoid
            # doing this in Designer as this spams the user as they are typing
            if not is_qt_designer():  # pragma: no cover
                logger.error("Image file  %r does not exist", abs_path)
            pixmap = QPixmap(self.sizeHint())
            pixmap.fill(self.null_color)
        # Update the display
        if pixmap is not None:
            self._pixmap = pixmap
            self.update()

    def sizeHint(self):
        if self._pixmap.size().isEmpty():
            return super(PyDMDrawingImage, self).sizeHint()
        return self._pixmap.size()

    @Property(Qt.AspectRatioMode)
    def aspectRatioMode(self):
        """
        PyQT Property for aspect ratio mode to be used when rendering
        the image

        Returns
        -------
        int
            Index at Qt.AspectRatioMode enum
        """
        return self._aspect_ratio_mode

    @aspectRatioMode.setter
    def aspectRatioMode(self, new_mode):
        """
        PyQT Property for aspect ratio mode to be used when rendering
        the image

        Parameters
        ----------
        new_mode : int
            Index at Qt.AspectRatioMode enum
        """
        if new_mode != self._aspect_ratio_mode:
            self._aspect_ratio_mode = new_mode
            self.update()

    def draw_item(self, painter):
        """
        Draws the image after setting up the canvas with a call to
        ```PyDMDrawing.draw_item```.
        """
        super(PyDMDrawingImage, self).draw_item(painter)
        x, y, w, h = self.get_bounds(maxsize=True, force_no_pen=True)
        if not isinstance(self._pixmap, QMovie):
            _scaled = self._pixmap.scaled(w, h, self._aspect_ratio_mode,
                                          Qt.SmoothTransformation)
            # Make sure the image is centered if smaller than the widget itself
            if w > _scaled.width():
                logger.debug("Centering image horizontally ...")
                x += (w - _scaled.width()) / 2
            if h > _scaled.height():
                logger.debug("Centering image vertically ...")
                y += (h - _scaled.height()) / 2
            painter.drawPixmap(x, y, _scaled)

    def movie_frame_changed(self, frame_no):
        """
        Callback executed when a new frame is available at the QMovie.

        Parameters
        ----------
        frame_no : int
            The new frame index

        Returns
        -------
        None

        """
        if self._movie is None:
            return
        curr_pixmap = self._movie.currentPixmap()
        self._pixmap = curr_pixmap
        self.update()

    def movie_finished(self):
        """
        Callback executed when the movie is finished.

        Returns
        -------
        None
        """
        if self._movie is None:
            return

        self._movie.start()
コード例 #20
0
ファイル: id_control.py プロジェクト: lnls-sirius/hla
class IDControl(SiriusMainWindow):
    """ID Control Window."""

    def __init__(self, parent=None, prefix=_vaca_prefix):
        super().__init__(parent)
        self._prefix = prefix
        self.setObjectName('IDApp')
        self.setWindowTitle('ID Controls')
        self.setWindowIcon(get_id_icon())
        self._setupUi()
        self._create_actions()

    def _setupUi(self):
        cw = QWidget()
        self.setCentralWidget(cw)

        label = QLabel('<h3>ID Control Window</h3>',
                       self, alignment=Qt.AlignCenter)
        label.setStyleSheet('QLabel{min-height: 3em; max-height: 3em;}')

        self.label_mov1 = QLabel(self)
        self.label_mov1.setVisible(False)
        self.label_mov1.setStyleSheet(
            'QLabel{min-height: 3em; max-height: 3em;}')
        self.label_mov2 = QLabel(self)
        self.label_mov2.setVisible(False)
        self.label_mov2.setStyleSheet(
            'QLabel{min-height: 3em; max-height: 3em;}')
        self.movie_mov = QMovie(_os.path.join(
            _os.path.abspath(_os.path.dirname(__file__)), 'hula.gif'))
        self.movie_mov.setScaledSize(QSize(50, 50))
        self.label_mov1.setMovie(self.movie_mov)
        self.label_mov2.setMovie(self.movie_mov)

        self._gbox_apu = QGroupBox('APU', self)
        self._gbox_apu.setLayout(self._setupAPULayout())

        lay = QGridLayout(cw)
        lay.addWidget(self.label_mov1, 0, 0)
        lay.addWidget(label, 0, 1)
        lay.addWidget(self.label_mov2, 0, 2)
        lay.addWidget(self._gbox_apu, 1, 0, 1, 3)
        lay.setColumnStretch(0, 1)
        lay.setColumnStretch(1, 15)
        lay.setColumnStretch(2, 1)

    def _setupAPULayout(self):
        lay = QVBoxLayout()
        lay.setAlignment(Qt.AlignTop)

        self._apu_header = APUSummaryHeader(self)
        lay.addWidget(self._apu_header)

        self._apu_widgets = list()
        self._channels_mov = list()
        idlist = ['SI-06SB:ID-APU22', 'SI-07SP:ID-APU22',
                  'SI-08SB:ID-APU22', 'SI-09SA:ID-APU22',
                  'SI-11SP:ID-APU58']
        for idname in idlist:
            apu_wid = APUSummaryWidget(self, self._prefix, idname)
            lay.addWidget(apu_wid)
            self._apu_widgets.append(apu_wid)
            ch_mov = SiriusConnectionSignal(_PVName(idname).substitute(
                prefix=self._prefix, propty='Moving-Mon'))
            ch_mov.new_value_signal[float].connect(self._handle_moving_vis)
            self._channels_mov.append(ch_mov)

        return lay

    def _create_actions(self):
        self.blctrl_enbl_act = QAction("Enable Beamline Control", self)
        self.blctrl_enbl_act.triggered.connect(
            lambda: self._set_beamline_control(True))
        self.blctrl_dsbl_act = QAction("Disable Beamline Control", self)
        self.blctrl_dsbl_act.triggered.connect(
            lambda: self._set_beamline_control(False))

    @Slot(bool)
    def _set_beamline_control(self, state):
        """Execute enable/disable beamline control actions."""
        for widget in self._apu_widgets:
            try:
                if state:
                    widget.enable_beamline_control()
                else:
                    widget.disable_beamline_control()
            except TypeError:
                pass

    def contextMenuEvent(self, event):
        """Show a custom context menu."""
        point = event.pos()
        menu = QMenu("Actions", self)
        menu.addAction(self.blctrl_enbl_act)
        menu.addAction(self.blctrl_dsbl_act)
        menu.addSeparator()
        action = menu.addAction('Show Connections...')
        action.triggered.connect(self.show_connections)
        menu.popup(self.mapToGlobal(point))

    def show_connections(self, checked):
        """Show connections."""
        _ = checked
        c = ConnectionInspector(self)
        c.show()

    def _handle_moving_vis(self, value):
        """Handle visualization of moving state label."""
        show = any([
            ch.connected and ch.value != 0
            for ch in self._channels_mov])
        self.label_mov1.setVisible(show)
        self.label_mov2.setVisible(show)
        if show:
            self.movie_mov.start()
        else:
            self.movie_mov.stop()
コード例 #21
0
def resourceMovie(name):
    """@rtype: QMovie"""
    movie = QMovie(resource_filename("ert_gui", "resources/gui/img/" + name))
    movie.start()
    return movie
コード例 #22
0
class ListItemEnv(ListWidgetItemBase):
    """Widget to build an item for the environments list."""
    def __init__(self, name=None, prefix=None):
        """Widget to build an item for the environments list."""
        super(ListItemEnv, self).__init__()

        self._selected = False
        self._name = name
        self._prefix = prefix

        # Widgets
        self.button_options = ButtonEnvironmentOptions()
        self.button_name = ButtonEnvironmentName(name)
        self.label_icon = LabelEnvironmentIcon()
        self.movie = QMovie(SPINNER_GREEN_16_PATH)
        self.widget = WidgetEnvironment()
        self.widget.button_name = self.button_name
        self.widget.button_options = self.button_options

        # Widget setup
        self.button_name.setDefault(True)
        self.label_icon.setMovie(self.movie)
        self.widget.setFocusPolicy(Qt.NoFocus)
        self.button_name.setFocusPolicy(Qt.StrongFocus)
        self.button_options.setFocusPolicy(Qt.StrongFocus)
        self.button_name.setToolTip(prefix if prefix else '')

        # Layouts
        layout = QHBoxLayout()
        layout.addWidget(self.label_icon)
        layout.addWidget(self.button_name)
        layout.addWidget(self.button_options)
        layout.addStretch()

        self.widget.setLayout(layout)
        self.widget.setStyleSheet(load_style_sheet())
        self.setSizeHint(self.widget.sizeHint())

    def ordered_widgets(self):
        """Return a list of the ordered widgets."""
        return [self.button_name, self.button_options]

    @property
    def name(self):
        """Resturn the environment name."""
        return self._name

    @property
    def prefix(self):
        """Return the environment prefix."""
        return self._prefix

    def set_hovered(self, value):
        """Set widget as hovered."""
        self.widget.setProperty('hovered', value)
        self.button_name.set_hovered(value)

    def set_loading(self, value):
        """Set loading status of widget."""
        # self.button_options.setDisabled(value)
        if value:
            self.label_icon.setMovie(self.movie)
            self.movie.start()
        else:
            self.label_icon.setMovie(QMovie())
            self.button_options.setFocus()

    def set_selected(self, value):
        """Set widget as selected."""
        self._selected = value
        try:
            self.widget.setProperty('pressed', value)
            self.button_name.set_selected(value)
        except RuntimeError:
            pass

        self.button_name.setDisabled(value)

        if value:
            self.label_icon.setMovie(None)
            self.button_options.setVisible(True)
        else:
            self.label_icon.setMovie(None)
            self.button_options.setVisible(False)

    @staticmethod
    def widget_size():
        """Return the size defined in the SASS file."""
        return QSize(SASS_VARIABLES.WIDGET_ENVIRONMENT_TOTAL_WIDTH,
                     SASS_VARIABLES.WIDGET_ENVIRONMENT_TOTAL_HEIGHT)
コード例 #23
0
ファイル: splash.py プロジェクト: magicknight/Xi-cam.gui
class XicamSplashScreen(QSplashScreen):
    minsplashtime = 3000

    def __init__(self, mainwindow: Callable[[], QMainWindow] = None,
                 f: int = Qt.WindowStaysOnTopHint | Qt.SplashScreen):
        """
        A QSplashScreen customized to display an animated gif. The splash triggers launch when clicked.

        After minsplashtime, this splash waits until the animation finishes before triggering the launch.

        Parameters
        ----------
        mainwindow  :   class
            Subclass of QMainWindow to display after splashing
        f           :   int
            Extra flags (see base class)
        """

        # Get logo movie from relative path
        self.movie = QMovie(str(static.path("images/animated_logo.gif")))

        # Setup drawing
        self.movie.frameChanged.connect(self.paintFrame)
        self.movie.jumpToFrame(1)
        self.pixmap = QPixmap(self.movie.frameRect().size())
        super(XicamSplashScreen, self).__init__(self.pixmap, f)
        self.setMask(self.pixmap.mask())
        self.movie.finished.connect(self.restartmovie)

        self._launching = False
        self._launchready = False
        self.timer = QTimer(self)
        self.mainwindow = mainwindow

        if args.nosplash:
            self.execlaunch()
        else:
            # Start splashing
            self.setAttribute(Qt.WA_DeleteOnClose)
            self.show()
            self.raise_()
            self.activateWindow()
            QApplication.instance().setActiveWindow(self)
            # Setup timed triggers for launching the QMainWindow
            self.timer.singleShot(self.minsplashtime, self.launchwindow)

    def showMessage(self, message: str, color=Qt.white):
        # TODO: Make this work.
        super(XicamSplashScreen, self).showMessage(message, color)

    def mousePressEvent(self, *args, **kwargs):
        # TODO: Apparently this doesn't work?
        self.timer.stop()
        self.execlaunch()

    def show(self):
        """
        Start the animation when shown
        """
        super(XicamSplashScreen, self).show()
        self.movie.start()

    def paintFrame(self):
        """
        Paint the current frame
        """
        self.pixmap = self.movie.currentPixmap()
        self.setMask(self.pixmap.mask())
        self.setPixmap(self.pixmap)
        self.movie.setSpeed(self.movie.speed() + 20)

    def sizeHint(self):
        return self.movie.scaledSize()

    def restartmovie(self):
        """
        Once the animation reaches the end, check if its time to launch, otherwise restart animation
        """
        if self._launchready:
            self.execlaunch()
            return
        self.movie.start()

    def launchwindow(self):
        """
        Save state, defer launch until animation finishes
        """
        self._launchready = True

    def execlaunch(self):
        """
        Launch the mainwindow
        """
        if not self._launching:
            self._launching = True

            app = QApplication.instance()

            from xicam.gui.windows.mainwindow import XicamMainWindow
            self.mainwindow = XicamMainWindow()
            self.timer.stop()

            # Show the QMainWindow
            self.mainwindow.show()
            self.mainwindow.raise_()
            self.mainwindow.activateWindow()
            app.setActiveWindow(self.mainwindow)

            # Stop splashing
            self.hide()
            self.movie.stop()
            self.finish(self.mainwindow)
コード例 #24
0
class XicamSplashScreen(QSplashScreen):
    minsplashtime = 5000

    def __init__(self, log_path: str, initial_length: int, f: int = Qt.WindowStaysOnTopHint | Qt.SplashScreen):
        """
        A QSplashScreen customized to display an animated gif. The splash triggers launch when clicked.

        After minsplashtime, this splash waits until the animation finishes before triggering the launch.

        Parameters
        ----------
        log_path    :   str
            Path to the Xi-CAM log file to reflect
        initial_length: int
            Length in bytes to seek forward before reading
        f           :   int
            Extra flags (see base class)
        """

        # Get logo movie from relative path
        self.movie = QMovie(str(static.path("images/animated_logo.gif")))

        # Setup drawing
        self.movie.frameChanged.connect(self.paintFrame)
        self.movie.jumpToFrame(1)
        self.pixmap = QPixmap(self.movie.frameRect().size())
        super(XicamSplashScreen, self).__init__(self.pixmap, f)
        self.setMask(self.pixmap.mask())
        self.movie.finished.connect(self.restartmovie)
        self.showMessage("Starting Xi-CAM...")

        self._launching = False
        self._launchready = False
        self.timer = QTimer(self)

        self.log_file = open(log_path, "r")
        self.log_file.seek(initial_length)

        # Start splashing
        self.setAttribute(Qt.WA_DeleteOnClose)
        self.show()
        self.raise_()
        self.activateWindow()
        QApplication.instance().setActiveWindow(self)

        # Setup timed triggers for launching the QMainWindow
        self.timer.singleShot(self.minsplashtime, self.launchwindow)

    def showMessage(self, message: str, color=Qt.darkGray):
        # attempt to parse out everyting besides the message
        try:
            message=message.split(" - ")[-1]
        except Exception:
            pass
        else:
            super(XicamSplashScreen, self).showMessage(elide(message), color=color, alignment=Qt.AlignBottom)

    def mousePressEvent(self, *args, **kwargs):
        # TODO: Apparently this doesn't work?
        self.timer.stop()
        self.execlaunch()

    def show(self):
        """
        Start the animation when shown
        """
        super(XicamSplashScreen, self).show()
        self.movie.start()

    def paintFrame(self):
        """
        Paint the current frame
        """
        self.pixmap = self.movie.currentPixmap()
        self.setMask(self.pixmap.mask())
        self.setPixmap(self.pixmap)
        self.movie.setSpeed(self.movie.speed() + 20)

        line = self.log_file.readline().strip()
        if line:
            self.showMessage(elide(line.split(">")[-1]))

    def sizeHint(self):
        return self.movie.scaledSize()

    def restartmovie(self):
        """
        Once the animation reaches the end, check if its time to launch, otherwise restart animation
        """
        if self._launchready:
            self.execlaunch()
            return
        self.movie.start()

    def launchwindow(self):
        """
        Save state, defer launch until animation finishes
        """
        self._launchready = True

    def execlaunch(self):
        """
        Launch the mainwindow
        """
        if not self._launching:
            self._launching = True

            self.timer.stop()

            # Stop splashing
            self.hide()
            self.movie.stop()
            self.close()
            QApplication.instance().quit()
コード例 #25
0
ファイル: apps.py プロジェクト: fisher2017/Anaconda
class ListItemApplication(QListWidgetItem):
    """
    Item with custom widget for the applications list.
    """
    ICON_SIZE = 48

    def __init__(self,
                 name=None,
                 description=None,
                 command=None,
                 pixmap=None,
                 version=None,
                 versions=None,
                 path=None,
                 dev_tool=True,
                 prefix=None,
                 is_conda_app=False,
                 packages_widget=None):
        super(ListItemApplication, self).__init__()

        self.api = AnacondaAPI()
        self.command = command
        self.dev_tool = dev_tool
        self.installed = False
        self.is_conda_app = is_conda_app
        self.name = name
        self.path = path
        self.pixmap = pixmap if pixmap else QPixmap(ANACONDA_ICON_64_PATH)
        self.prefix = prefix
        self.timeout = 10000  # In miliseconds
        self.version = version
        self.versions = versions
        self.packages_widget = packages_widget

        # Widgets
        self.button_install = ButtonApplicationInstall("Install")
        self.button_launch = ButtonApplicationLaunch("Launch")
        self.button_options = ButtonApplicationOptions()
        self.label_icon = LabelApplicationIcon()
        self.label_name = LabelApplicationName(name)
        self.label_description = LabelApplicationDescription(description)
        #        self.label_update = LabelApplicationUpdate()
        self.button_version = ButtonApplicationVersion(to_text_string(version))
        self.label_spinner = LabelApplicationSpinner()
        #        self.label_version = LabelApplicationVersion(to_text_string(version))
        self.menu_options = QMenu('Application options')
        self.menu_versions = QMenu('Install specific version')
        self.movie_spinner = QMovie(SPINNER_WHITE_16_PATH)
        self.timer = QTimer()
        self.widget = WidgetApplication()

        # Widget setup
        self.button_version.setFocusPolicy(Qt.NoFocus)
        self.label_name.setToolTip(description)
        self.label_description.setAlignment(Qt.AlignCenter)
        self.movie_spinner.start()
        self.timer.setInterval(self.timeout)
        self.timer.setSingleShot(True)
        self.label_icon.setToolTip(description)
        self.label_icon.setPixmap(
            self.pixmap.scaled(self.ICON_SIZE, self.ICON_SIZE,
                               Qt.KeepAspectRatio, Qt.SmoothTransformation))
        self.label_icon.setAlignment(Qt.AlignCenter)
        self.label_name.setAlignment(Qt.AlignCenter)
        self.label_name.setWordWrap(True)
        self.label_description.setWordWrap(True)
        self.label_description.setAlignment(Qt.AlignTop | Qt.AlignHCenter)
        self.label_spinner.setVisible(False)
        self.label_spinner.setMinimumWidth(16)
        self.label_spinner.setMinimumHeight(16)

        # Layouts
        layout = QVBoxLayout()
        layout.addWidget(self.button_options, 0, Qt.AlignRight)
        layout.addWidget(self.label_icon, 0, Qt.AlignCenter)
        layout.addWidget(self.label_name, 0, Qt.AlignCenter)
        layout.addWidget(self.label_description, 0, Qt.AlignCenter)

        #        hlayout = QHBoxLayout()
        #        hlayout.addWidget(self.label_update)
        #        hlayout.addWidget(self.label_version)
        #        layout.addLayout(hlayout)
        #        layout.addWidget(self.label_version, 0, Qt.AlignCenter)
        layout.addWidget(self.button_version, 0, Qt.AlignCenter)
        layout.addWidget(self.label_spinner, 0, Qt.AlignCenter)
        layout.addWidget(self.button_launch, 0, Qt.AlignCenter)
        layout.addWidget(self.button_install, 0, Qt.AlignCenter)

        self.widget.setLayout(layout)
        self.widget.setStyleSheet(load_style_sheet())
        self.setSizeHint(self.widget.sizeHint())

        # Signals
        self.button_install.clicked.connect(self.install_application)
        self.button_launch.clicked.connect(self.launch_application)
        self.button_options.clicked.connect(self.actions_menu_requested)
        self.timer.timeout.connect(self._application_launched)

        # Setup
        self.update_status()

    # --- Callbacks
    # -------------------------------------------------------------------------
    def _application_launched(self):
        """
        """
        self.button_launch.setDisabled(False)
        update_pointer()

    def _application_installed(self, worker, output, error):
        """
        """
        self.handle_action_finished(worker, output, error)

    def _application_updated(self, worker, output, error):
        """
        """
        self.handle_action_finished(worker, output, error)

    def _application_removed(self, worker, output, error):
        """
        """
        self.handle_action_finished(worker, output, error)

    # --- Helpers
    # -------------------------------------------------------------------------
    def _partial_output_ready(self, worker, output, error):
        """
        """
        message = None
        progress = (0, 0)

        if isinstance(output, dict):
            progress = (output.get('progress',
                                   None), output.get('maxval', None))
            name = output.get('name', None)
            fetch = output.get('fetch', None)

            if fetch:
                message = "Downloading <b>{0}</b>...".format(fetch)

            if name:
                self._current_action_name = name
                message = "Linking <b>{0}</b>...".format(name)

        logger.debug(message)
        self.widget.sig_status_updated.emit(message)

    def update_style_sheet(self, style_sheet=None):
        if style_sheet is None:
            style_sheet = load_style_sheet()
        self.menu_options.setStyleSheet(style_sheet)
        self.menu_versions.setStyleSheet(style_sheet)

    def actions_menu_requested(self):
        """
        Create and display options menu for the currently selected application.
        """
        self.menu_options.clear()
        self.menu_versions.clear()

        # Add versions menu
        versions = self.versions if self.versions else []
        version_actions = []
        for version in reversed(versions):
            action = create_action(self.widget,
                                   version,
                                   triggered=lambda value, version=version:
                                   self.install_application(version=version))

            action.setCheckable(True)
            if self.version == version:
                action.setChecked(True)
                action.setDisabled(True)

            version_actions.append(action)

        update_action = create_action(
            self.widget,
            'Update application',
            triggered=lambda: self.update_application())

        if versions and versions[-1] == self.version:
            update_action.setDisabled(True)
        else:
            update_action.setDisabled(False)

        remove_action = create_action(
            self.widget,
            'Remove application',
            triggered=lambda: self.remove_application())
        remove_action.setEnabled(self.installed)

        actions = [update_action, remove_action, None, self.menu_versions]
        add_actions(self.menu_options, actions)
        add_actions(self.menu_versions, version_actions)
        offset = QPoint(self.button_options.width(), 0)
        position = self.button_options.mapToGlobal(QPoint(0, 0))
        self.menu_versions.setEnabled(bool(versions))
        self.menu_options.move(position + offset)
        self.menu_options.exec_()

    def update_status(self):
        if self.prefix:
            self.version = self.api.conda_package_version(self.prefix,
                                                          pkg=self.name)
        self.installed = bool(self.version)
        if (self.versions and self.version != self.versions[-1]
                and self.installed):
            self.button_version.setIcon(QIcon(CONDA_MANAGER_UPGRADE_ARROW))
            self.button_version.setStyleSheet(
                "ButtonApplicationVersion {color: #0071a0;}")
            self.button_version.setToolTip('Version {0} available'.format(
                self.versions[-1]))
        else:
            self.button_version.setIcon(QIcon())
            self.button_version.setStyleSheet(
                "ButtonApplicationVersion {color: black;}")

        self.button_install.setVisible(not self.installed)
        self.button_launch.setVisible(self.installed)

    def set_loading(self, value):
        self.button_launch.setDisabled(value)
        self.button_install.setDisabled(value)
        self.button_options.setDisabled(value)

        if value:
            self.label_spinner.setMovie(self.movie_spinner)
        else:
            self.label_spinner.setMovie(None)
            if self.version is None:
                version = self.versions[-1]
            else:
                version = self.version
            self.button_version.setText(version)

        self.label_spinner.setVisible(value)
        self.button_version.setVisible(not value)

    def handle_action_finished(self, worker, output, error):
        if not isinstance(output, dict):
            output = {}
        success = output.get('success', True)

        if error or not success:
            # Error might be harmless if no decoding was possible...
            # Success deserves some sort of messagebox
            logger.error(error)
        self.widget.sig_application_updated.emit(self.name, self.version)

        self.update_status()
        self.set_loading(False)

    def update_versions(self, version=None, versions=None):
        """
        Update button visibility depending on update availability.
        """
        update = versions[-1] != version
        logger.debug(str((self.name, self.dev_tool, self.installed)))

        if self.installed and version:
            self.button_options.setVisible(True)
            self.button_version.setText(version)
            self.button_version.setVisible(True)
        elif not self.installed and versions:
            self.button_install.setEnabled(True)
            self.button_version.setText(versions[-1])
            self.button_version.setVisible(True)

        self.versions = versions
        self.version = version
        self.update_status()

    # --- Public API
    # ------------------------------------------------------------------------
    def install_application(self, value=None, version=None):
        """
        Update the application on the defined prefix environment.

        This is used for both normal install and specific version install.
        """
        if version:
            self.version = version
        else:
            self.version = self.versions[-1]
            version = self.versions[-1]

        pkg = '{0}={1}'.format(self.name, version)
        pkgs = [pkg]
        logger.debug(str((pkg, self.dev_tool)))

        # Check if environment exists and then create or install
        #        is_installed = self.api.conda_package_version(prefix=self.prefix,
        #                                                      pkg=self.name)
        #        pkgs = [pkg] + self.BASIC_PACKAGES
        #        if is_installed:
        #            worker = self.api.conda_install(prefix=self.prefix, pkgs=pkgs)
        #        else:
        #            worker = self.api.conda_create(prefix=self.prefix, pkgs=pkgs)

        worker = self.api.conda_install(prefix=self.prefix, pkgs=pkgs)
        worker.sig_finished.connect(self._application_installed)
        worker.sig_partial.connect(self._partial_output_ready)
        self.set_loading(True)
        self.widget.sig_status_updated.emit('Installing application '
                                            '<b>{0}</b>'.format(self.name))

    def launch_application(self):
        """
        Launch application installed in prefix environment.
        """
        if self.command is not None:
            if self.command.startswith('open'):
                command = self.command.replace("${PREFIX}", self.prefix)
            elif self.prefix:
                command = os.sep.join([self.prefix, 'bin', self.command])
            else:
                command = self.command

            self.button_launch.setDisabled(True)
            self.timer.setInterval(self.timeout)
            self.timer.start()
            update_pointer(Qt.BusyCursor)
            launch(self.path, command)

    def remove_application(self):
        """
        Remove the application from the defined prefix environment.
        """
        pkg = self.name
        pkgs = [pkg]
        logger.debug(str((self.name, self.dev_tool)))
        worker = self.api.conda_remove(prefix=self.prefix, pkgs=pkgs)
        worker.sig_finished.connect(self._application_removed)
        worker.sig_partial.connect(self._partial_output_ready)
        self.set_loading(True)
        self.widget.sig_status_updated.emit('Removing application '
                                            '<b>{0}</b>'.format(self.name))

    def update_application(self):
        """
        Update the application on the defined prefix environment.
        """
        logger.debug(str((self.name, self.dev_tool, self.installed)))
        self.install_application(version=self.versions[-1])
        self.widget.sig_status_updated.emit('Updating application '
                                            '<b>{0}</b>'.format(self.name))