Example #1
0
        def _setup_timers(self, duration):
            close_timer = QtCore.QTimer(self)
            anim_timer = QtCore.QTimer(self)
            close_timer.setSingleShot(True)
            close_timer.timeout.connect(self.close)
            close_timer.timeout.connect(self.closed.emit)
            anim_timer.timeout.connect(self._on_fade_out)
            close_timer.setInterval((duration or self.DEFAULT_DURATION) * 1000)
            anim_timer.setInterval((duration or self.DEFAULT_DURATION) * 1000 -
                                   300)

            close_timer.start()
            anim_timer.start()

            self._pos_anim = QtCore.QPropertyAnimation(self)
            self._pos_anim.setTargetObject(self)
            self._pos_anim.setEasingCurve(QtCore.QEasingCurve.OutCubic)
            self._pos_anim.setDuration(300)
            self._pos_anim.setPropertyName(b'pos')

            self._opacity_anim = QtCore.QPropertyAnimation(self)
            self._opacity_anim = QtCore.QPropertyAnimation()
            self._opacity_anim.setTargetObject(self)
            self._opacity_anim.setDuration(300)
            self._opacity_anim.setEasingCurve(QtCore.QEasingCurve.OutCubic)
            self._opacity_anim.setPropertyName(b'windowOpacity')
            self._opacity_anim.setStartValue(0.0)
            self._opacity_anim.setEndValue(1.0)
Example #2
0
    def _fill_data(self):
        is_greater_version = self._is_greater_version()

        if is_greater_version:
            icon_pixmap = (resource.pixmap('success')
                           or QtGui.QPixmap()).scaled(
                               QtCore.QSize(30, 30),
                               QtCore.Qt.KeepAspectRatio,
                               transformMode=QtCore.Qt.SmoothTransformation)
            self._version_message_label.setText(
                'Artella {} Plugin is updated!'.format(dcc.nice_name()))
        else:
            icon_pixmap = (resource.pixmap('info') or QtGui.QPixmap()).scaled(
                QtCore.QSize(30, 30),
                QtCore.Qt.KeepAspectRatio,
                transformMode=QtCore.Qt.SmoothTransformation)
            self._version_icon.setPixmap(icon_pixmap)
            self._version_message_label.setText(
                'New Artella {} Plugin is available!'.format(dcc.nice_name()))

        self._version_icon.setPixmap(icon_pixmap)
        self._go_to_download_web_btn.setVisible(not is_greater_version)
        latest_version = self._latest_release_info.get('version', 'Undefined')
        self._current_version_label.setText(
            str(self._current_version or 'Undefined'))
        self._latest_version_label.setText(latest_version)
Example #3
0
        def __init__(self, parent=None, **kwargs):
            super(ProgressCricle, self).__init__(parent)

            self._infinite = False
            self._timer = QtCore.QTimer(self)
            self._timer.timeout.connect(self._on_increase_value)

            self._main_layout = QtWidgets.QHBoxLayout()
            self._default_label = QtWidgets.QLabel()
            self._default_label.setAlignment(QtCore.Qt.AlignCenter)
            self._main_layout.addWidget(self._default_label)
            self.setLayout(self._main_layout)
            self._color = QtGui.QColor(221, 235, 230)
            self._width = kwargs.get('width', 140)

            self.setTextDirection(self.Direction.BottomToTop)

            self._start_angle = 90 * 16
            self._max_delta_angle = 360 * 16
            self._height_factor = 1.0
            self._width_factor = 1.0

            self.setFixedSize(
                QtCore.QSize(self._width * self._width_factor,
                             self._width * self._height_factor))
Example #4
0
        def __init__(self, parent=None, **kwargs):
            if not parent:
                from artella import dcc
                parent = dcc.get_main_window()

            self._use_artella_header = kwargs.pop('use_artella_header', True)

            super(BaseDialog, self).__init__(parent, **kwargs)

            self._pos_anim = QtCore.QPropertyAnimation(self)
            self._pos_anim.setTargetObject(self)
            self._pos_anim.setEasingCurve(QtCore.QEasingCurve.OutCubic)
            self._pos_anim.setDuration(300)
            self._pos_anim.setPropertyName(b'pos')

            self._opacity_anim = QtCore.QPropertyAnimation()
            self._opacity_anim.setTargetObject(self)
            self._opacity_anim.setEasingCurve(QtCore.QEasingCurve.OutCubic)
            self._opacity_anim.setDuration(300)
            self._opacity_anim.setPropertyName(b'windowOpacity')
            self._opacity_anim.setStartValue(0.0)
            self._opacity_anim.setEndValue(1.0)

            self.setup_ui()
            theme.theme().apply(self)

            self._fade_in()
Example #5
0
            class MainThreadAsyncInvoker(QtCore.QObject):
                """
                Class that implements a mechanism to execute a function with arbitrary arguments in main
                thread asynchronously
                for DCCs that support Qt
                """

                __signal = QtCore.Signal(object)

                def __init__(self):
                    super(MainThreadAsyncInvoker, self).__init__()

                    self.__signal.connect(self.__execute_in_main_thread)

                def invoke(self, fn, *args, **kwargs):
                    """
                     Invoke the given function with the given arguments and keyword arguments in the main thread

                     :param function fn: function to execute in main thread
                     :param tuple args: args for the function
                     :param dict kwargs: Named arguments for the function
                     :return: Returns the result returned by the function
                     :rtype: object
                     """

                    self._signal.emit(lambda: fn(*args, **kwargs))

                def __execute_in_main_thread(self, fn):
                    """
                    Internal function that executes the function
                    """

                    fn()
Example #6
0
def string_is_hex(color_str):
    """
    Returns whether or not given string is a valid hexadecimal color
    :param color_str: str
    :return: bool
    """

    if color_str.startswith('#'):
        color_str = color_str[1:]
    hex_regex1 = QtCore.QRegExp('^[0-9A-F]{3}$', QtCore.Qt.CaseInsensitive)
    hex_regex2 = QtCore.QRegExp('^[0-9A-F]{6}$', QtCore.Qt.CaseInsensitive)
    hex_regex3 = QtCore.QRegExp('^[0-9A-F]{8}$', QtCore.Qt.CaseInsensitive)
    if hex_regex1.exactMatch(color_str) or hex_regex2.exactMatch(color_str) or hex_regex3.exactMatch(color_str):
        return True

    return False
Example #7
0
        def _calculate_position(self, parent=None):
            """
            Internal function that calculates a proper position for the snack bar relative to its parent
            """

            parent = parent or self.parent()
            parent_geo = parent.geometry()
            pos = parent_geo.topLeft(
            ) if parent.parent() is None else parent.mapToGlobal(
                parent_geo.topLeft())
            offset = 0
            for child in parent.children():
                if isinstance(child, SnackBarMessage) and child.isVisible():
                    offset = max(
                        offset,
                        child.y() + 10 + child.geometry().height() / 2)
            base_pos = pos.y() + SnackBarMessage.DEFAULT_TOP
            target_x = pos.x(
            ) + parent_geo.width() / 2 - self.size().width() / 2
            target_y = (offset + 50) if offset else base_pos
            self._pos_anim.setStartValue(QtCore.QPoint(target_x,
                                                       target_y - 40))
            self._pos_anim.setEndValue(QtCore.QPoint(target_x, target_y))
Example #8
0
    def setup_ui(self):
        super(SplashDialog, self).setup_ui()

        self.setWindowFlags(QtCore.Qt.Window | QtCore.Qt.FramelessWindowHint
                            | QtCore.Qt.WA_DeleteOnClose)
        self.setAttribute(QtCore.Qt.WA_TranslucentBackground)

        splash_pixmap = resource.pixmap('artella_splash')
        splash = SplashScreen(splash_pixmap)
        splash.setMask(splash_pixmap.mask())
        self._splash_layout = QtWidgets.QVBoxLayout()
        self._splash_layout.setAlignment(QtCore.Qt.AlignBottom)
        splash.setLayout(self._splash_layout)
        self.main_layout.addWidget(splash)

        size_width = splash_pixmap.size().width() + 20
        size_height = splash_pixmap.size().height() + 20
        self.setFixedSize(QtCore.QSize(size_width, size_height))

        shadow_effect = QtWidgets.QGraphicsDropShadowEffect(self)
        shadow_effect.setBlurRadius(qtutils.dpi_scale(15))
        shadow_effect.setColor(QtGui.QColor(0, 0, 0, 150))
        shadow_effect.setOffset(qtutils.dpi_scale(0))
        self.setGraphicsEffect(shadow_effect)
Example #9
0
    class BaseDialog(QtWidgets.QDialog, object):

        closed = QtCore.Signal()

        def __init__(self, parent=None, **kwargs):
            if not parent:
                from artella import dcc
                parent = dcc.get_main_window()

            self._use_artella_header = kwargs.pop('use_artella_header', True)

            super(BaseDialog, self).__init__(parent, **kwargs)

            self._pos_anim = QtCore.QPropertyAnimation(self)
            self._pos_anim.setTargetObject(self)
            self._pos_anim.setEasingCurve(QtCore.QEasingCurve.OutCubic)
            self._pos_anim.setDuration(300)
            self._pos_anim.setPropertyName(b'pos')

            self._opacity_anim = QtCore.QPropertyAnimation()
            self._opacity_anim.setTargetObject(self)
            self._opacity_anim.setEasingCurve(QtCore.QEasingCurve.OutCubic)
            self._opacity_anim.setDuration(300)
            self._opacity_anim.setPropertyName(b'windowOpacity')
            self._opacity_anim.setStartValue(0.0)
            self._opacity_anim.setEndValue(1.0)

            self.setup_ui()
            theme.theme().apply(self)

            self._fade_in()

        def get_main_layout(self):
            main_layout = QtWidgets.QVBoxLayout()
            main_layout.setContentsMargins(0, 0, 0, 0)
            main_layout.setSpacing(0)

            return main_layout

        def setup_ui(self):
            self.main_layout = self.get_main_layout()
            self.setLayout(self.main_layout)

            if self._use_artella_header:
                artella_frame = QtWidgets.QFrame()
                artella_frame.setObjectName('artellaFrame')
                artella_frame_layout = QtWidgets.QHBoxLayout()
                artella_frame.setLayout(artella_frame_layout)

                artella_header = QtWidgets.QLabel()
                artella_header_pixmap = resource.pixmap('artella_header')
                artella_header.setPixmap(artella_header_pixmap)
                artella_frame_layout.addStretch()
                artella_frame_layout.addWidget(artella_header)
                artella_frame_layout.addStretch()

                self.main_layout.addWidget(artella_frame)

        def fade_close(self):
            self._fade_out()

        # =================================================================================================================
        # INTERNAL
        # =================================================================================================================

        def _fade_out(self):
            self._opacity_anim.finished.connect(self.close)
            self._pos_anim.setDirection(QtCore.QAbstractAnimation.Backward)
            self._pos_anim.start()
            self._opacity_anim.setDirection(QtCore.QAbstractAnimation.Backward)
            self._opacity_anim.start()

        def _fade_in(self):
            self._pos_anim.start()
            self._opacity_anim.start()
Example #10
0
        def __init__(self,
                     id,
                     name,
                     package,
                     version,
                     author,
                     email,
                     summary,
                     latest_version,
                     upload_date,
                     size,
                     url,
                     icon_pixmap=None,
                     parent=None):
            super(PluginVersionWidget, self).__init__(parent)

            self._id = id
            self._name = name
            self._package = package
            self._version = version
            self._author = author
            self._email = email
            self._summary = summary
            self._latest_version = latest_version
            self._upload_date = upload_date
            self._size = size
            self._url = url

            icon_pixmap = (icon_pixmap or resource.pixmap('artella')
                           or QtGui.QPixmap()).scaled(
                               QtCore.QSize(30, 30),
                               QtCore.Qt.KeepAspectRatio,
                               transformMode=QtCore.Qt.SmoothTransformation)

            self.setFrameShape(QtWidgets.QFrame.StyledPanel)
            self.setFrameShadow(QtWidgets.QFrame.Raised)
            self.setMinimumHeight(130)

            main_layout = QtWidgets.QHBoxLayout()
            main_layout.setContentsMargins(2, 2, 2, 2)
            main_layout.setSpacing(2)
            self.setLayout(main_layout)

            main_info_layout = QtWidgets.QVBoxLayout()
            main_info_layout.setContentsMargins(2, 2, 2, 2)
            main_info_layout.setSpacing(2)

            top_layout = QtWidgets.QHBoxLayout()
            top_layout.setContentsMargins(2, 2, 2, 2)
            top_layout.setSpacing(5)
            self._icon_label = QtWidgets.QLabel()
            self._icon_label.setPixmap(icon_pixmap)
            self._icon_label.setAlignment(QtCore.Qt.AlignTop)

            self._plugin_name_label = QtWidgets.QLabel(name)
            self._plugin_version_label = QtWidgets.QLabel(
                '({})'.format(version))

            plugin_name_info_layout = QtWidgets.QVBoxLayout()
            plugin_name_info_layout.setContentsMargins(2, 2, 2, 2)
            plugin_name_info_layout.setSpacing(5)
            plugin_name_layout = QtWidgets.QHBoxLayout()
            plugin_name_layout.setContentsMargins(2, 2, 2, 2)
            plugin_name_layout.setSpacing(2)
            plugin_info_layout = QtWidgets.QHBoxLayout()
            plugin_info_layout.setContentsMargins(2, 2, 2, 2)
            plugin_info_layout.setSpacing(5)
            plugin_name_layout.addWidget(self._plugin_name_label)
            plugin_name_layout.addWidget(self._plugin_version_label)
            plugin_name_layout.addStretch()
            plugin_name_info_layout.addLayout(plugin_name_layout)
            plugin_name_info_layout.addLayout(plugin_info_layout)
            plugin_name_info_layout.addStretch()
            self._plugin_date_label = QtWidgets.QLabel(upload_date)
            self._plugin_size_label = QtWidgets.QLabel(size)
            separator_widget = QtWidgets.QWidget()
            separator_layout = QtWidgets.QVBoxLayout()
            separator_layout.setAlignment(QtCore.Qt.AlignLeft)
            separator_layout.setContentsMargins(0, 0, 0, 0)
            separator_layout.setSpacing(0)
            separator_widget.setLayout(separator_layout)
            separator_frame = QtWidgets.QFrame()
            separator_frame.setMaximumHeight(15)
            separator_frame.setFrameShape(QtWidgets.QFrame.VLine)
            separator_frame.setFrameShadow(QtWidgets.QFrame.Sunken)
            separator_layout.addWidget(separator_frame)
            plugin_info_layout.addWidget(self._plugin_date_label)
            plugin_info_layout.addWidget(separator_widget)
            plugin_info_layout.addWidget(self._plugin_size_label)
            plugin_info_layout.addStretch()

            top_layout.addWidget(self._icon_label)
            top_layout.addLayout(plugin_name_info_layout)

            bottom_layout = QtWidgets.QHBoxLayout()
            bottom_layout.setContentsMargins(2, 2, 2, 2)
            bottom_layout.setSpacing(5)
            self._summary_text = QtWidgets.QPlainTextEdit(summary)
            self._summary_text.setReadOnly(True)
            self._summary_text.setMinimumHeight(60)
            self._summary_text.setFocusPolicy(QtCore.Qt.NoFocus)
            bottom_layout.addWidget(self._summary_text)

            download_layout = QtWidgets.QVBoxLayout()
            download_layout.setContentsMargins(2, 2, 2, 2)
            download_layout.setSpacing(2)
            self._progress = splash.ProgressCricle(width=80)
            self._progress_text = QtWidgets.QLabel('Wait please ...')
            self._ok_label = QtWidgets.QLabel()
            self._ok_label.setPixmap(resource.pixmap('success'))
            self._update_button = QtWidgets.QPushButton()
            self._progress.setVisible(False)
            self._progress_text.setVisible(False)
            self._ok_label.setVisible(False)
            progress_layout = QtWidgets.QHBoxLayout()
            progress_layout.addStretch()
            progress_layout.addWidget(self._progress)
            progress_layout.addStretch()
            progress_text_layout = QtWidgets.QHBoxLayout()
            progress_text_layout.addStretch()
            progress_text_layout.addWidget(self._progress_text)
            progress_text_layout.addStretch()
            ok_layout = QtWidgets.QHBoxLayout()
            ok_layout.addStretch()
            ok_layout.addWidget(self._ok_label)
            ok_layout.addStretch()
            download_layout.addStretch()
            download_layout.addLayout(progress_layout)
            download_layout.addLayout(progress_text_layout)
            download_layout.addLayout(ok_layout)
            download_layout.addWidget(self._update_button)
            download_layout.addStretch()

            main_info_layout.addLayout(top_layout)
            main_info_layout.addStretch()
            main_info_layout.addLayout(bottom_layout)
            main_info_layout.addStretch()

            main_info_layout.addStretch()
            main_layout.addLayout(main_info_layout)
            separator_widget = QtWidgets.QWidget()
            separator_layout = QtWidgets.QVBoxLayout()
            separator_layout.setAlignment(QtCore.Qt.AlignLeft)
            separator_layout.setContentsMargins(0, 0, 0, 0)
            separator_layout.setSpacing(0)
            separator_widget.setLayout(separator_layout)
            separator_frame = QtWidgets.QFrame()
            separator_frame.setFrameShape(QtWidgets.QFrame.VLine)
            separator_frame.setFrameShadow(QtWidgets.QFrame.Sunken)
            separator_layout.addWidget(separator_frame)
            main_layout.addWidget(separator_widget)
            main_layout.addLayout(download_layout)
            main_info_layout.addStretch()

            self._update_plugin_thread = QtCore.QThread(self)
            self._update_plugin_worker = utils.UpdatePluginWorker()
            self._update_plugin_worker.moveToThread(self._update_plugin_thread)
            self._update_plugin_worker.updateStart.connect(
                self._on_start_update)
            self._update_plugin_worker.updateFinish.connect(
                self._on_finish_update)
            self._update_plugin_thread.start()

            self._timer = QtCore.QTimer(self)

            self.updatePlugin.connect(self._update_plugin_worker.run)
            self._update_button.clicked.connect(self._on_update)
            self._timer.timeout.connect(self._on_advance_progress)

            self.refresh()
Example #11
0
    class PluginVersionWidget(QtWidgets.QFrame, object):
        updatePlugin = QtCore.Signal()
        updated = QtCore.Signal()

        def __init__(self,
                     id,
                     name,
                     package,
                     version,
                     author,
                     email,
                     summary,
                     latest_version,
                     upload_date,
                     size,
                     url,
                     icon_pixmap=None,
                     parent=None):
            super(PluginVersionWidget, self).__init__(parent)

            self._id = id
            self._name = name
            self._package = package
            self._version = version
            self._author = author
            self._email = email
            self._summary = summary
            self._latest_version = latest_version
            self._upload_date = upload_date
            self._size = size
            self._url = url

            icon_pixmap = (icon_pixmap or resource.pixmap('artella')
                           or QtGui.QPixmap()).scaled(
                               QtCore.QSize(30, 30),
                               QtCore.Qt.KeepAspectRatio,
                               transformMode=QtCore.Qt.SmoothTransformation)

            self.setFrameShape(QtWidgets.QFrame.StyledPanel)
            self.setFrameShadow(QtWidgets.QFrame.Raised)
            self.setMinimumHeight(130)

            main_layout = QtWidgets.QHBoxLayout()
            main_layout.setContentsMargins(2, 2, 2, 2)
            main_layout.setSpacing(2)
            self.setLayout(main_layout)

            main_info_layout = QtWidgets.QVBoxLayout()
            main_info_layout.setContentsMargins(2, 2, 2, 2)
            main_info_layout.setSpacing(2)

            top_layout = QtWidgets.QHBoxLayout()
            top_layout.setContentsMargins(2, 2, 2, 2)
            top_layout.setSpacing(5)
            self._icon_label = QtWidgets.QLabel()
            self._icon_label.setPixmap(icon_pixmap)
            self._icon_label.setAlignment(QtCore.Qt.AlignTop)

            self._plugin_name_label = QtWidgets.QLabel(name)
            self._plugin_version_label = QtWidgets.QLabel(
                '({})'.format(version))

            plugin_name_info_layout = QtWidgets.QVBoxLayout()
            plugin_name_info_layout.setContentsMargins(2, 2, 2, 2)
            plugin_name_info_layout.setSpacing(5)
            plugin_name_layout = QtWidgets.QHBoxLayout()
            plugin_name_layout.setContentsMargins(2, 2, 2, 2)
            plugin_name_layout.setSpacing(2)
            plugin_info_layout = QtWidgets.QHBoxLayout()
            plugin_info_layout.setContentsMargins(2, 2, 2, 2)
            plugin_info_layout.setSpacing(5)
            plugin_name_layout.addWidget(self._plugin_name_label)
            plugin_name_layout.addWidget(self._plugin_version_label)
            plugin_name_layout.addStretch()
            plugin_name_info_layout.addLayout(plugin_name_layout)
            plugin_name_info_layout.addLayout(plugin_info_layout)
            plugin_name_info_layout.addStretch()
            self._plugin_date_label = QtWidgets.QLabel(upload_date)
            self._plugin_size_label = QtWidgets.QLabel(size)
            separator_widget = QtWidgets.QWidget()
            separator_layout = QtWidgets.QVBoxLayout()
            separator_layout.setAlignment(QtCore.Qt.AlignLeft)
            separator_layout.setContentsMargins(0, 0, 0, 0)
            separator_layout.setSpacing(0)
            separator_widget.setLayout(separator_layout)
            separator_frame = QtWidgets.QFrame()
            separator_frame.setMaximumHeight(15)
            separator_frame.setFrameShape(QtWidgets.QFrame.VLine)
            separator_frame.setFrameShadow(QtWidgets.QFrame.Sunken)
            separator_layout.addWidget(separator_frame)
            plugin_info_layout.addWidget(self._plugin_date_label)
            plugin_info_layout.addWidget(separator_widget)
            plugin_info_layout.addWidget(self._plugin_size_label)
            plugin_info_layout.addStretch()

            top_layout.addWidget(self._icon_label)
            top_layout.addLayout(plugin_name_info_layout)

            bottom_layout = QtWidgets.QHBoxLayout()
            bottom_layout.setContentsMargins(2, 2, 2, 2)
            bottom_layout.setSpacing(5)
            self._summary_text = QtWidgets.QPlainTextEdit(summary)
            self._summary_text.setReadOnly(True)
            self._summary_text.setMinimumHeight(60)
            self._summary_text.setFocusPolicy(QtCore.Qt.NoFocus)
            bottom_layout.addWidget(self._summary_text)

            download_layout = QtWidgets.QVBoxLayout()
            download_layout.setContentsMargins(2, 2, 2, 2)
            download_layout.setSpacing(2)
            self._progress = splash.ProgressCricle(width=80)
            self._progress_text = QtWidgets.QLabel('Wait please ...')
            self._ok_label = QtWidgets.QLabel()
            self._ok_label.setPixmap(resource.pixmap('success'))
            self._update_button = QtWidgets.QPushButton()
            self._progress.setVisible(False)
            self._progress_text.setVisible(False)
            self._ok_label.setVisible(False)
            progress_layout = QtWidgets.QHBoxLayout()
            progress_layout.addStretch()
            progress_layout.addWidget(self._progress)
            progress_layout.addStretch()
            progress_text_layout = QtWidgets.QHBoxLayout()
            progress_text_layout.addStretch()
            progress_text_layout.addWidget(self._progress_text)
            progress_text_layout.addStretch()
            ok_layout = QtWidgets.QHBoxLayout()
            ok_layout.addStretch()
            ok_layout.addWidget(self._ok_label)
            ok_layout.addStretch()
            download_layout.addStretch()
            download_layout.addLayout(progress_layout)
            download_layout.addLayout(progress_text_layout)
            download_layout.addLayout(ok_layout)
            download_layout.addWidget(self._update_button)
            download_layout.addStretch()

            main_info_layout.addLayout(top_layout)
            main_info_layout.addStretch()
            main_info_layout.addLayout(bottom_layout)
            main_info_layout.addStretch()

            main_info_layout.addStretch()
            main_layout.addLayout(main_info_layout)
            separator_widget = QtWidgets.QWidget()
            separator_layout = QtWidgets.QVBoxLayout()
            separator_layout.setAlignment(QtCore.Qt.AlignLeft)
            separator_layout.setContentsMargins(0, 0, 0, 0)
            separator_layout.setSpacing(0)
            separator_widget.setLayout(separator_layout)
            separator_frame = QtWidgets.QFrame()
            separator_frame.setFrameShape(QtWidgets.QFrame.VLine)
            separator_frame.setFrameShadow(QtWidgets.QFrame.Sunken)
            separator_layout.addWidget(separator_frame)
            main_layout.addWidget(separator_widget)
            main_layout.addLayout(download_layout)
            main_info_layout.addStretch()

            self._update_plugin_thread = QtCore.QThread(self)
            self._update_plugin_worker = utils.UpdatePluginWorker()
            self._update_plugin_worker.moveToThread(self._update_plugin_thread)
            self._update_plugin_worker.updateStart.connect(
                self._on_start_update)
            self._update_plugin_worker.updateFinish.connect(
                self._on_finish_update)
            self._update_plugin_thread.start()

            self._timer = QtCore.QTimer(self)

            self.updatePlugin.connect(self._update_plugin_worker.run)
            self._update_button.clicked.connect(self._on_update)
            self._timer.timeout.connect(self._on_advance_progress)

            self.refresh()

        def refresh(self):
            if self._latest_version == self._version:
                self._update_button.setText('Updated')
                self._update_button.setEnabled(False)
            else:
                self._update_button.setText('Update ({})'.format(
                    self._latest_version))

        def _on_update(self):

            install_path = r'D:\dev\artella\test_download'

            plugin_path = self._id.replace('-', '.')
            try:
                mod = importlib.import_module(plugin_path)
            except Exception:
                mod = None
            if mod:
                install_path = os.path.dirname(mod.__path__[0])

            print(install_path)

            # self._update_plugin_worker.set_id(self._id)
            # self._update_plugin_worker.set_package(self._package)
            # self._update_plugin_worker.set_latest_version(self._latest_version)
            # self._update_plugin_worker.set_url(self._url)
            # self._update_plugin_worker.set_install_path(install_path)
            #
            # self.updatePlugin.emit()

        def _on_finish_update(self, error_msg):
            valid = not bool(error_msg)
            self._progress.setVisible(False)
            self._progress_text.setVisible(False)
            self._update_button.setVisible(not valid)
            self._ok_label.setVisible(valid)
            self.updated.emit()

        def _on_start_update(self):
            self._progress.setVisible(True)
            self._progress_text.setVisible(True)
            self._update_button.setVisible(False)
            self._ok_label.setVisible(False)
            self._timer.start(5)

        def _on_advance_progress(self):
            self._progress.setValue(self._progress.value() + 1)
Example #12
0
 def _set_artella_size(self):
     self.setFixedSize(QtCore.QSize(self._artella_size, self._artella_size))
     self._set_artella_image()
Example #13
0
    class ArtellaLabel(QtWidgets.QLabel, object):
        def __init__(self, text='', parent=None):
            super(ArtellaLabel, self).__init__(text, parent)

            self._actual_text = text
            self._artella_type = ''
            self._artella_underline = False
            self._artella_mark = False
            self._artella_delete = False
            self._artella_strong = False
            self._artella_code = False
            self._artella_level = 0
            self._elide_mode = QtCore.Qt.ElideNone
            self.setProperty('artella_text', text)

            self.setTextInteractionFlags(QtCore.Qt.TextBrowserInteraction
                                         | QtCore.Qt.LinksAccessibleByMouse)
            self.setSizePolicy(QtWidgets.QSizePolicy.Preferred,
                               QtWidgets.QSizePolicy.Minimum)

        def get_artella_level(self):
            return self._artella_level

        def set_artella_level(self, value):
            self._artella_level = value
            self.style().polish(self)

        def set_artella_underline(self, value):
            self._artella_underline = value
            self.style().polish(self)

        def get_artella_underline(self):
            return self._artella_underline

        def set_artella_delete(self, value):
            self._artella_delete = value
            self.style().polish(self)

        def get_artella_delete(self):
            return self._artella_delete

        def set_artella_strong(self, value):
            self._artella_strong = value
            self.style().polish(self)

        def get_artella_strong(self):
            return self._artella_strong

        def set_artella_mark(self, value):
            self._artella_mark = value
            self.style().polish(self)

        def get_artella_mark(self):
            return self._artella_mark

        def set_artella_code(self, value):
            self._artella_code = value
            self.style().polish(self)

        def get_artella_code(self):
            return self._artella_code

        def get_elide_mode(self):
            return self._elide_mode

        def set_elide_mode(self, value):
            self._elide_mode = value
            self._update_elided_text()

        def get_artella_type(self):
            return self._artella_type

        def set_artella_type(self, value):
            self._artella_type = value
            self.style().polish(self)

        artella_level = QtCore.Property(int, get_artella_level,
                                        set_artella_level)
        artella_type = QtCore.Property(str, get_artella_type, set_artella_type)
        artella_underline = QtCore.Property(bool, get_artella_underline,
                                            set_artella_underline)
        artella_delete = QtCore.Property(bool, get_artella_delete,
                                         set_artella_delete)
        artella_strong = QtCore.Property(bool, get_artella_strong,
                                         set_artella_strong)
        artella_mark = QtCore.Property(bool, get_artella_mark,
                                       set_artella_mark)
        artella_code = QtCore.Property(bool, get_artella_code,
                                       set_artella_code)
        artella_elide_mod = QtCore.Property(QtCore.Qt.TextElideMode,
                                            get_artella_code, set_artella_code)

        def minimumSizeHint(self):
            return QtCore.QSize(1, self.fontMetrics().height())

        def text(self):
            return self._actual_text

        def setText(self, text):
            self._actual_text = text
            self._update_elided_text()
            self.setToolTip(text)

        def _update_elided_text(self):
            _font_metrics = self.fontMetrics()
            _elided_text = _font_metrics.elidedText(self._actual_text,
                                                    self._elide_mode,
                                                    self.width() - 2 * 2)
            super(ArtellaLabel, self).setText(_elided_text)

        def resizeEvent(self, event):
            self._update_elided_text()

        def h1(self):
            self.set_artella_level(ArtellaLabelTypes.H1)
            return self

        def h2(self):
            self.set_artella_level(ArtellaLabelTypes.H2)
            return self

        def h3(self):
            self.set_artella_level(ArtellaLabelTypes.H3)
            return self

        def h4(self):
            self.set_artella_level(ArtellaLabelTypes.H4)
            return self

        def secondary(self):
            self.set_artella_type(ArtellaLabelTypes.SECONDARY)
            return self

        def warning(self):
            self.set_artella_type(ArtellaLabelTypes.WARNING)
            return self

        def danger(self):
            self.set_artella_type(ArtellaLabel.DangerType)
            return self

        def strong(self):
            """Set QLabel with strong style."""
            self.set_artella_strong(True)
            return self

        def mark(self):
            self.set_artella_mark(True)
            return self

        def code(self):
            self.set_artella_code(True)
            return self

        def delete(self):
            self.set_artella_delete(True)
            return self

        def underline(self):
            self.set_artella_underline(True)
            return self
Example #14
0
 def set_artella_size(self, value):
     self._artella_size = value
     self.style().polish(self)
     if self.toolButtonStyle() == QtCore.Qt.ToolButtonIconOnly:
         self.setFixedSize(
             QtCore.QSize(self._artella_size, self._artella_size))
Example #15
0
    class ArtellaToolButton(QtWidgets.QToolButton):
        def __init__(self, parent=None):
            super(ArtellaToolButton, self).__init__(parent=parent)

            self._artella_image = None
            self._artella_size = theme.theme().default_size

            self.setAutoExclusive(False)
            self.setAutoRaise(True)
            self.setSizePolicy(QtWidgets.QSizePolicy.Minimum,
                               QtWidgets.QSizePolicy.Minimum)

            self._polish_icon()
            self.toggled.connect(self._polish_icon)

        def enterEvent(self, event):
            if self._artella_image:
                self.setIcon(
                    resource.icon(self._artella_image,
                                  color=theme.theme().main_color))
            return super(ArtellaToolButton, self).enterEvent(event)

        def leaveEvent(self, event):
            self._polish_icon()
            return super(ArtellaToolButton, self).leaveEvent(event)

        def get_artella_size(self):
            return self._artella_size

        def set_artella_size(self, value):
            self._artella_size = value
            self.style().polish(self)
            if self.toolButtonStyle() == QtCore.Qt.ToolButtonIconOnly:
                self.setFixedSize(
                    QtCore.QSize(self._artella_size, self._artella_size))

        def get_artella_image(self):
            return self._artella_image

        def set_artella_image(self, path):
            self._artella_image = path
            self._polish_icon()

        artella_size = QtCore.Property(int, get_artella_size, set_artella_size)

        def huge(self):
            self.set_artella_size(theme.theme().huge)
            return self

        def large(self):
            self.set_artella_size(theme.theme().large)
            return self

        def medium(self):
            self.set_artella_size(theme.theme().medium)
            return self

        def small(self):
            self.set_artella_size(theme.theme().small)
            return self

        def tiny(self):
            self.set_artella_size(theme.theme().tiny)
            return self

        def image(self, path):
            self.set_artella_image(path)
            return self

        def icon_only(self):
            self.setToolButtonStyle(QtCore.Qt.ToolButtonIconOnly)
            self.setFixedSize(
                QtCore.QSize(self._artella_size, self._artella_size))
            return self

        def text_only(self):
            self.setToolButtonStyle(QtCore.Qt.ToolButtonTextOnly)
            return self

        def text_beside_icon(self):
            self.setToolButtonStyle(QtCore.Qt.ToolButtonTextBesideIcon)
            return self

        def text_under_icon(self):
            self.setToolButtonStyle(QtCore.Qt.ToolButtonTextUnderIcon)
            return self

        def _polish_icon(self, *args, **kwargs):
            if self._artella_image:
                if self.isCheckable() and self.isChecked():
                    self.setIcon(
                        resource.icon(self._artella_image,
                                      color=theme.theme().main_color))
                else:
                    self.setIcon(resource.icon(self._artella_image))
Example #16
0
    class SnackBarMessage(QtWidgets.QWidget, object):

        closed = QtCore.Signal()

        DEFAULT_DURATION = 6
        DEFAULT_TOP = 180

        def __init__(self,
                     text='',
                     title='',
                     duration=None,
                     artella_type=None,
                     closable=False,
                     parent=None):

            if parent is None:
                parent = dcc.get_main_window()
            current_type = artella_type or SnackBarTypes.ARTELLA

            super(SnackBarMessage, self).__init__(parent)

            self.setWindowFlags(QtCore.Qt.FramelessWindowHint
                                | QtCore.Qt.Dialog
                                | QtCore.Qt.WA_DeleteOnClose)
            self.setAttribute(QtCore.Qt.WA_StyledBackground)
            self.setAttribute(QtCore.Qt.WA_TranslucentBackground)

            main_layout = QtWidgets.QVBoxLayout()
            main_layout.setContentsMargins(2, 2, 2, 2)
            main_layout.setSpacing(2)
            self.setLayout(main_layout)

            main_frame = QtWidgets.QFrame()
            main_frame.setObjectName('mainFrame')
            frame_layout = QtWidgets.QVBoxLayout()
            frame_layout.setContentsMargins(5, 5, 5, 5)
            frame_layout.setSpacing(5)

            main_frame.setLayout(frame_layout)
            main_layout.addWidget(main_frame)

            info_layout = QtWidgets.QHBoxLayout()

            artella_label_layout = QtWidgets.QHBoxLayout()
            artella_label = image.ArtellaImage.small()
            artella_label.set_artella_image(resource.pixmap('artella_white'))
            self._close_btn = button.ArtellaToolButton(
                parent=self).image('close').tiny().icon_only()
            self._close_btn.setVisible(closable or False)
            self._close_btn.clicked.connect(self.close)
            if closable:
                artella_label_layout.addSpacing(20)
            artella_label_layout.addStretch()
            artella_label_layout.addWidget(artella_label)
            artella_label_layout.addStretch()
            artella_label_layout.addWidget(self._close_btn)
            title_layout = QtWidgets.QHBoxLayout()
            self._title_label = label.ArtellaLabel(parent=self).strong()
            self._title_label.setText(title)
            self._title_label.setVisible(bool(text))
            title_layout.addStretch()
            title_layout.addWidget(self._title_label)
            title_layout.addStretch()

            self._icon_label = image.ArtellaImage.small()
            self._icon_label.set_artella_image(
                resource.pixmap('{}'.format(current_type),
                                color=vars(theme.theme()).get(current_type +
                                                              '_color')))

            self._content_label = label.ArtellaLabel(parent=self)
            self._content_label.setText(text)
            info_layout.addStretch()
            info_layout.addWidget(self._icon_label)
            info_layout.addWidget(self._content_label)
            info_layout.addStretch()

            frame_layout.addLayout(artella_label_layout)
            frame_layout.addWidget(divider.ArtellaDivider())
            frame_layout.addLayout(title_layout)
            frame_layout.addLayout(info_layout)

            self._setup_timers(duration)

            self._on_fade_in()

        @property
        def text(self):
            return self._text

        @text.setter
        def text(self, text):
            self._text = str(text)
            self._label.setText(self._text)
            self.setVisible(bool(self._text))

        @classmethod
        def artella(cls,
                    text,
                    title='',
                    parent=None,
                    duration=None,
                    closable=None):
            inst = cls(text,
                       title=title,
                       artella_type=SnackBarTypes.ARTELLA,
                       duration=duration,
                       closable=closable,
                       parent=parent)
            theme.theme().apply(inst)
            inst.show()

            return inst

        @classmethod
        def info(cls,
                 text,
                 title='',
                 parent=None,
                 duration=None,
                 closable=None):
            inst = cls(text,
                       title=title,
                       artella_type=SnackBarTypes.INFO,
                       duration=duration,
                       closable=closable,
                       parent=parent)
            theme.theme().apply(inst)
            inst.show()

            return inst

        @classmethod
        def success(cls,
                    text,
                    title='',
                    parent=None,
                    duration=None,
                    closable=None):
            inst = cls(text,
                       title=title,
                       artella_type=SnackBarTypes.SUCCESS,
                       duration=duration,
                       closable=closable,
                       parent=parent)
            theme.theme().apply(inst)
            inst.show()

            return inst

        @classmethod
        def warning(cls,
                    text,
                    title='',
                    parent=None,
                    duration=None,
                    closable=None):
            inst = cls(text,
                       title=title,
                       artella_type=SnackBarTypes.WARNING,
                       duration=duration,
                       closable=closable,
                       parent=parent)
            theme.theme().apply(inst)
            inst.show()

            return inst

        @classmethod
        def error(cls,
                  text,
                  title='',
                  parent=None,
                  duration=None,
                  closable=None):
            inst = cls(text,
                       title=title,
                       artella_type=SnackBarTypes.ERROR,
                       duration=duration,
                       closable=closable,
                       parent=parent)
            theme.theme().apply(inst)
            inst.show()

            return inst

        def _setup_timers(self, duration):
            close_timer = QtCore.QTimer(self)
            anim_timer = QtCore.QTimer(self)
            close_timer.setSingleShot(True)
            close_timer.timeout.connect(self.close)
            close_timer.timeout.connect(self.closed.emit)
            anim_timer.timeout.connect(self._on_fade_out)
            close_timer.setInterval((duration or self.DEFAULT_DURATION) * 1000)
            anim_timer.setInterval((duration or self.DEFAULT_DURATION) * 1000 -
                                   300)

            close_timer.start()
            anim_timer.start()

            self._pos_anim = QtCore.QPropertyAnimation(self)
            self._pos_anim.setTargetObject(self)
            self._pos_anim.setEasingCurve(QtCore.QEasingCurve.OutCubic)
            self._pos_anim.setDuration(300)
            self._pos_anim.setPropertyName(b'pos')

            self._opacity_anim = QtCore.QPropertyAnimation(self)
            self._opacity_anim = QtCore.QPropertyAnimation()
            self._opacity_anim.setTargetObject(self)
            self._opacity_anim.setDuration(300)
            self._opacity_anim.setEasingCurve(QtCore.QEasingCurve.OutCubic)
            self._opacity_anim.setPropertyName(b'windowOpacity')
            self._opacity_anim.setStartValue(0.0)
            self._opacity_anim.setEndValue(1.0)

        def resizeEvent(self, event):
            self.updateGeometry()
            self._calculate_position()
            super(SnackBarMessage, self).resizeEvent(event)

        def _calculate_position(self, parent=None):
            """
            Internal function that calculates a proper position for the snack bar relative to its parent
            """

            parent = parent or self.parent()
            parent_geo = parent.geometry()
            pos = parent_geo.topLeft(
            ) if parent.parent() is None else parent.mapToGlobal(
                parent_geo.topLeft())
            offset = 0
            for child in parent.children():
                if isinstance(child, SnackBarMessage) and child.isVisible():
                    offset = max(
                        offset,
                        child.y() + 10 + child.geometry().height() / 2)
            base_pos = pos.y() + SnackBarMessage.DEFAULT_TOP
            target_x = pos.x(
            ) + parent_geo.width() / 2 - self.size().width() / 2
            target_y = (offset + 50) if offset else base_pos
            self._pos_anim.setStartValue(QtCore.QPoint(target_x,
                                                       target_y - 40))
            self._pos_anim.setEndValue(QtCore.QPoint(target_x, target_y))

        def _on_fade_out(self):
            """
            Internal callback function that fades out snack bar widget
            """

            try:
                self._pos_anim.setDirection(QtCore.QAbstractAnimation.Backward)
                self._pos_anim.start()
                self._opacity_anim.setDirection(
                    QtCore.QAbstractAnimation.Backward)
                self._opacity_anim.start()
            except Exception:
                pass

        def _on_fade_in(self):
            """
            Internal callback function that fades in snack bar widget
            """

            try:
                self._pos_anim.start()
                self._opacity_anim.start()
            except Exception:
                pass
Example #17
0
 def minimumSizeHint(self):
     return QtCore.QSize(1, self.fontMetrics().height())
Example #18
0
 def icon_only(self):
     self.setToolButtonStyle(QtCore.Qt.ToolButtonIconOnly)
     self.setFixedSize(
         QtCore.QSize(self._artella_size, self._artella_size))
     return self
Example #19
0
    class UpdatePluginWorker(QtCore.QObject, object):

        updateStart = QtCore.Signal()
        updateFinish = QtCore.Signal(str)

        def __init__(self):
            super(UpdatePluginWorker, self).__init__()

            self.id = None
            self._package = None
            self._latest_version = None
            self._url = None
            self._install_path = None
            self._max_retries = 10

        def set_id(self, id):
            self._id = id

        def set_package(self, package):
            self._package = package

        def set_latest_version(self, latest_version):
            self._latest_version = latest_version

        def set_url(self, url):
            self._url = url

        def set_install_path(self, install_path):
            self._install_path = install_path

        def set_max_retries(self, value):
            self._max_retries = value

        def run(self):
            self.updateStart.emit()

            if not self._url or not self._url.endswith('.tar.gz'):
                error_msg = 'Plugin Package URL does not contains a .tar.gaz file ({} | {} | {}'.format(
                    self._id, self._latest_version, self._url)
                self.updateFinish.emit(error_msg)
                return

            # TODO: We should download to a temporal folder and once everything is extracted we should move the info to
            # TODO: its proper place

            base_file_name = '{}_{}'.format(self._id, self._latest_version)
            file_name = '{}.tar.gz'.format(base_file_name)
            file_path = os.path.join(self._install_path, file_name)

            try:
                valid = download_and_extract_package_from_pypi(
                    self._url, file_path, self._install_path, max_retries=self._max_retries)
                if not valid:
                    error_msg = 'Impossible to download and extract plugin from PyPI server ({} | {} | {})'.format(
                        self._id, self._latest_version, self._url)
                    self.updateFinish.emit(error_msg)
                    return
            except Exception as exc:
                error_msg = 'Error while downloading new plugin version from PyPI server ({} | {} | {} | {})'.format(
                        self._id, self._latest_version, self._url, exc)
                self.updateFinish.emit(error_msg)
                return False

            plugin_folder = None
            for root, dirs, files in os.walk(self._install_path):
                for plugin_dir in dirs:
                    if plugin_dir == self._package or plugin_dir == self._package.lower():
                        plugin_folder = os.path.join(root, plugin_dir)
                        break

            if not plugin_folder or not os.path.isdir(plugin_folder):
                error_msg = 'No Plugin folder found ({}) in the extracted Plugin data ({} | {})'.format(
                    self._package, self._id, self._latest_version)
                self.updateFinish.emit(error_msg)
                return

            self.updateFinish.emit('')
Example #20
0
    class ArtellaImage(QtWidgets.QLabel, object):
        def __init__(self, parent=None):
            super(ArtellaImage, self).__init__(parent)

            self._default_pixmap = resource.pixmap('artella')
            self._pixmap = self._default_pixmap
            self._artella_size = 0
            self.set_artella_size(theme.theme().default_size)

        def set_artella_size(self, value):
            self._artella_size = value
            self._set_artella_size()

        def _set_artella_size(self):
            self.setFixedSize(QtCore.QSize(self._artella_size, self._artella_size))
            self._set_artella_image()

        def _set_artella_image(self):
            self.setPixmap(self._pixmap.scaledToWidth(self.height(), QtCore.Qt.SmoothTransformation))

        def set_artella_image(self, value):
            """
            Set avatar image.
            :param value: QPixmap or None.
            :return: None
            """
            if value is None:
                self._pixmap = self._default_pixmap
            elif isinstance(value, QtGui.QPixmap):
                self._pixmap = value
            else:
                raise TypeError("Input argument 'value' should be QPixmap or None, but get {}".format(type(value)))
            self._set_artella_image()

        def get_artella_image(self):
            return self._pixmap

        def get_artella_size(self):
            return self._artella_size

        artella_image = QtCore.Property(QtGui.QPixmap, get_artella_image, set_artella_image)
        artella_size = QtCore.Property(int, get_artella_size, set_artella_size)

        @classmethod
        def tiny(cls, image=None):
            inst = cls()
            inst.set_artella_size(theme.theme().tiny)
            inst.set_artella_image(image)
            return inst

        @classmethod
        def small(cls, image=None):
            inst = cls()
            inst.set_artella_size(theme.theme().small)
            inst.set_artella_image(image)
            return inst

        @classmethod
        def medium(cls, image=None):
            inst = cls()
            inst.set_artella_size(theme.theme().medium)
            inst.set_artella_image(image)
            return inst

        @classmethod
        def large(cls, image=None):
            inst = cls()
            inst.set_artella_size(theme.theme().large)
            inst.set_artella_image(image)
            return inst

        @classmethod
        def huge(cls, image=None):
            inst = cls()
            inst.set_artella_size(theme.theme().huge)
            inst.set_artella_image(image)
            return inst