Exemple #1
0
class FormWidget(QFrame, object):

    accepted = Signal(object)
    stateChanged = Signal()
    validated = Signal()

    def __init__(self, *args, **kwargs):
        super(FormWidget, self).__init__(*args, **kwargs)

        self._schema = dict()
        self._widgets = list()
        self._validator = None

        main_layout = layouts.VerticalLayout(spacing=0, margins=(0, 0, 0, 0))
        self.setLayout(main_layout)

        self._fields_frame = QFrame(self)
        self._fields_frame.setObjectName('fieldsFrame')
        options_layout = layouts.VerticalLayout(spacing=0,
                                                margins=(0, 0, 0, 0))
        self._fields_frame.setLayout(options_layout)

        self._title_widget = buttons.BaseButton(parent=self)
        self._title_widget.setCheckable(True)
        self._title_widget.setObjectName('titleWidget')
        self._title_widget.toggled.connect(self._on_title_clicked)
        self._title_widget.hide()

        main_layout.addWidget(self._title_widget)
        main_layout.addWidget(self._fields_frame)

    # =================================================================================================================
    # OVERRIDES
    # =================================================================================================================

    def closeEvent(self, event):
        self.save_persistent_values()
        super(FormWidget, self).closeEvent(event)

    # =================================================================================================================
    # BASE
    # =================================================================================================================

    def title_widget(self):
        """
        Returns the title widget
        :return: QWidget
        """

        return self._title_widget

    def set_title(self, title):
        """
        Sets the title text
        :param title: str
        """

        self.title_widget().setText(title)

    def is_expanded(self):
        """
        Returns whether the item is expanded or not
        :return: bool
        """

        return self._title_widget.isChecked()

    def set_expanded(self, flag):
        """
        Expands the options if True, otherwise collapses the options
        :param flag: bool
        """

        with qt_contexts.block_signals(self._title_widget):
            self._title_widget.setChecked(flag)
            self._fields_frame.setVisible(flag)

    def set_title_visible(self, flag):
        """
        Sets whether the title widget is visible or not
        :param flag: bool
        """

        self.title_widget().setVisible(flag)

    def widget(self, name):
        """
        Returns the widget for the given widget name
        :param name: str
        :return: FieldWidget
        """

        for widget in self._widgets:
            if widget.data().get('name') == name:
                return widget

    def value(self, name):
        """
        Returns the value for the given widget name
        :param name: str
        :return: object
        """

        widget = self.widget(name)
        return widget.value()

    def set_value(self, name, value):
        """
        Sets the value for the given field name
        :param name: str
        :param value: variant
        """

        widget = self.widget(name)
        widget.set_value(value)

    def values(self):
        """
        Returns all the field values indexed by the field name
        :return: dict
        """

        values = dict()
        for widget in self._widgets:
            name = widget.data().get('name')
            if name:
                values[name] = widget.value()

        return values

    def set_values(self, values):
        """
        Sets the field values for the current form
        :param values: dict
        """

        state = list()
        for name in values:
            state.append({'name': name, 'value': values[name]})

        self._set_state(state)

    def default_values(self):
        """
        Returns all teh default field values indexed by the field name
        :return: dict
        """

        values = dict()
        for widget in self._widgets:
            name = widget.data().get('name')
            if name:
                values[name] = widget.default()

        return values

    def set_data(self, name, data):
        """
        Sets the data for the given field name
        :param name: str
        :param data: dict
        """

        widget = self.widget(name)
        if not widget:
            return
        widget.set_data(data)

    def fields(self):
        """
        Returns fields data for the form
        :return: list(dict)
        """

        options = list()
        for widget in self._widgets:
            options.append(widget.data())

        return options

    def field_widgets(self):
        """
        Returns all field widgets
        :return: list(FieleWidget)
        """

        return self._widgets

    def state(self):
        """
        Returns the current state
        :return: dict
        """

        fields = list()
        for widget in self._widgets:
            fields.append(widget.state())

        state = {'fields': fields, 'expanded': self.is_expanded()}

        return state

    def set_state(self, state):
        """
        Sets the current state
        :param state: dict
        """

        expanded = state.get('expanded')
        if expanded is not None:
            self.set_expanded(expanded)

        fields = state.get('fields')
        if fields is not None:
            self._set_state(fields)

        self.validate()

    def schema(self):
        """
        Returns form's schema
        :return: dict
        """

        return self._schema

    def set_schema(self, schema, layout=None, errors_visible=False):
        """
        Sets the schema for the widget
        :param schema: list(dict)
        :param layout: str
        :param errors_visible: str
        """

        self._schema = self._sort_schema(schema)
        for field in schema:
            cls = formfields.FIELD_WIDGET_REGISTRY.get(
                field.get('type', 'label'))
            if not cls:
                LOGGER.warning('Cannot find widget for {}'.format(field))
                continue
            if layout and not field.get('layout'):
                field['layout'] = layout

            error_visible = field.get('errorVisible')
            field[
                'errorVisible'] = error_visible if error_visible is not None else errors_visible

            widget = cls(data=field,
                         parent=self._fields_frame,
                         form_widget=self)
            data = widget.default_data()
            data.update(field)

            widget.set_data(data)

            value = field.get('value')
            default = field.get('default')
            if value is None and default is not None:
                widget.set_value(default)

            self._widgets.append(widget)

            callback = partial(self._on_field_changed, widget)
            widget.valueChanged.connect(callback)

            self._fields_frame.layout().addWidget(widget)

        self.load_persistent_values()

    def validator(self):
        """
        Returns the validator for the form
        :return: fn
        """

        return self._validator

    def set_validator(self, validator):
        """
        Sets the validator for the options
        :param validator: fn
        """

        self._validator = validator

    def reset(self):
        """
        Reset all option widget back to the ir default values
        """

        for widget in self._widgets:
            widget.reset()
        self.validate()

    def validate(self, widget=None):
        """
        Validates the current options using the validator
        """

        if not self._validator:
            return

        values = dict()
        for name, value in self.values().items():
            data = self.widget(name).data()
            if data.get('validate', True):
                values[name] = value

        if widget:
            values['fieldChanged'] = widget.name()

        fields = self._validator(**values)
        if fields is not None:
            self._set_state(fields)

        self.validated.emit()

    def errors(self):
        """
        Returns all form errors
        :return: list(str)
        """

        errors = list()
        for widget in self._widgets:
            error = widget.data().get('error')
            if error:
                errors.append(error)

        return errors

    def has_errors(self):
        """
        Returns whether the form contains any error
        :return: bool
        """

        return bool(self.errors())

    def save_persistent_values(self):
        """
        Saves form widget values
        Triggered when the user changes field values
        """

        data = dict()

        for widget in self._widgets:
            name = widget.data().get('name')
            if name and widget.data().get('persistent'):
                key = self.objectName() or 'FormWidget'
                key = widget.data().get('persistentKey', key)
                data.setdefault(key, dict())
                data[key][name] = widget.value()

        for key in data:
            settings.set(key, data[key])

    def load_persistent_values(self):
        """
        Returns the options from the user settings
        :return: dict
        """

        values = dict()
        default_values = self.default_values()

        for field in self.schema():
            name = field.get('name')
            persistent = field.get('persistent')
            if persistent:
                key = self.objectName() or 'FormWidget'
                key = field.get('persistentKey', key)
                value = settings.get(key, dict()).get(name)
            else:
                value = default_values.get(name)

            if value is not None:
                values[name] = value

        self.set_values(values)

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

    def _sort_schema(self, schema):
        """
        Internal function that sorts the schema depending on the group order
        :param schema: list(dict)
        :return: list(dict)
        """
        def _key(field):
            return field['order']

        order = 0

        for i, field in enumerate(schema):
            if field.get('type') == 'group':
                order = field.get('order', order)
            field['order'] = order

        return sorted(schema, key=_key)

    def _set_state(self, fields):
        """
        Internal function that sets fields state
        :param fields: list(dict)
        """

        for widget in self._widgets:
            widget.blockSignals(True)

        try:
            for widget in self._widgets:
                widget.set_error('')
                for field in fields:
                    if field.get('name') == widget.data().get('name'):
                        widget.set_data(field)
        finally:
            for widget in self._widgets:
                widget.blockSignals(False)

        self.stateChanged.emit()

    # ============================================================================================================
    # CALLBACKS
    # ============================================================================================================

    def _on_title_clicked(self, toggle):
        """
        Internal callback function that is triggered when the user clicks in the title widget
        """

        self.set_expanded(toggle)
        self.stateChanged.emit()

    def _on_field_changed(self, widget):
        """
        Internal callback function triggered when the given option widget changes its value
        :param widget: FieldWidget
        """

        self.validate(widget=widget)
Exemple #2
0
    def ui(self):
        super(LoadWidget, self).ui()

        tabs_widget = tabs.BaseTabWidget(parent=self)

        info_widget = QWidget()
        info_layout = layouts.VerticalLayout(spacing=0, margins=(0, 0, 0, 0))
        info_widget.setLayout(info_layout)

        if self.OPTIONS_WIDGET:
            self._options_widget = self.OPTIONS_WIDGET(parent=self)

        title_layout = layouts.HorizontalLayout(spacing=1,
                                                margins=(1, 1, 0, 0))
        self._icon_lbl = label.BaseLabel('', parent=self)
        self._icon_lbl.setMaximumSize(QSize(14, 14))
        self._icon_lbl.setMinimumSize(QSize(14, 14))
        self._icon_lbl.setScaledContents(True)
        self._title_lbl = label.BaseLabel('Title', parent=self)
        title_layout.addWidget(self._icon_lbl)
        title_layout.addWidget(self._title_lbl)

        icon_toggle_box = QFrame()
        icon_toggle_box.setFrameShape(QFrame.NoFrame)
        icon_toggle_box.setFrameShadow(QFrame.Plain)
        icon_toggle_box_lyt = layouts.VerticalLayout(spacing=1,
                                                     margins=(0, 1, 0, 0))
        icon_toggle_box.setLayout(icon_toggle_box_lyt)

        icon_toggle_box_header = QFrame()
        icon_toggle_box_header.setFrameShape(QFrame.NoFrame)
        icon_toggle_box_header.setFrameShadow(QFrame.Plain)
        icon_toggle_box_header_lyt = layouts.VerticalLayout(spacing=0,
                                                            margins=(0, 0, 0,
                                                                     0))
        icon_toggle_box_header.setLayout(icon_toggle_box_header_lyt)

        self._icon_toggle_box_btn = buttons.BaseButton('ICON', parent=self)
        self._icon_toggle_box_btn.setObjectName('iconButton')
        self._icon_toggle_box_btn.setCheckable(True)
        self._icon_toggle_box_btn.setChecked(True)
        icon_toggle_box_header_lyt.addWidget(self._icon_toggle_box_btn)

        self._icon_toggle_box_frame = QFrame()
        self._icon_toggle_box_frame.setFrameShape(QFrame.NoFrame)
        self._icon_toggle_box_frame.setFrameShadow(QFrame.Plain)
        icon_toggle_box_frame_lyt = layouts.VerticalLayout(spacing=1,
                                                           margins=(0, 1, 0,
                                                                    0))
        self._icon_toggle_box_frame.setLayout(icon_toggle_box_frame_lyt)

        thumbnail_layout = layouts.HorizontalLayout(spacing=0,
                                                    margins=(0, 0, 0, 0))
        icon_toggle_box_frame_lyt.addLayout(thumbnail_layout)

        thumbnail_frame_layout = layouts.VerticalLayout(spacing=0,
                                                        margins=(0, 0, 0, 0))
        self._thumbnail_frame = QFrame()
        self._thumbnail_frame.setFrameShape(QFrame.NoFrame)
        self._thumbnail_frame.setFrameShadow(QFrame.Plain)
        self._thumbnail_frame.setLayout(thumbnail_frame_layout)
        thumbnail_layout.addWidget(self._thumbnail_frame)
        self._thumbnail_btn = QToolButton()
        self._thumbnail_btn.setObjectName('thumbnailButton')
        self._thumbnail_btn.setMinimumSize(QSize(0, 0))
        self._thumbnail_btn.setMaximumSize(QSize(150, 150))
        self._thumbnail_btn.setStyleSheet(
            'color: rgb(40, 40, 40);\nborder: 1px solid rgb(0, 0, 0, 0);\nbackground-color: rgb(254, 255, 230, 0);'
        )
        self._thumbnail_btn.setLayoutDirection(Qt.LeftToRight)
        self._thumbnail_btn.setText('Snapshot')
        self._thumbnail_btn.setIcon(resources.icon('thumbnail'))
        thumbnail_frame_layout.addWidget(self._thumbnail_btn)

        icon_toggle_box_lyt.addWidget(icon_toggle_box_header)
        icon_toggle_box_lyt.addWidget(self._icon_toggle_box_frame)

        info_toggle_box = QFrame()
        info_toggle_box.setFrameShape(QFrame.NoFrame)
        info_toggle_box.setFrameShadow(QFrame.Plain)
        info_toggle_box_lyt = layouts.VerticalLayout(spacing=0,
                                                     margins=(0, 0, 0, 0))
        info_toggle_box.setLayout(info_toggle_box_lyt)

        info_toggle_box_header = QFrame()
        info_toggle_box_header.setFrameShape(QFrame.NoFrame)
        info_toggle_box_header.setFrameShadow(QFrame.Plain)
        info_toggle_box_header_lyt = layouts.VerticalLayout(spacing=0,
                                                            margins=(0, 0, 0,
                                                                     0))
        info_toggle_box_header.setLayout(info_toggle_box_header_lyt)

        self._info_toggle_box_btn = buttons.BaseButton('INFO', parent=self)
        self._info_toggle_box_btn.setObjectName('infoButton')
        self._info_toggle_box_btn.setCheckable(True)
        self._info_toggle_box_btn.setChecked(True)
        info_toggle_box_header_lyt.addWidget(self._info_toggle_box_btn)

        self._info_toggle_box_frame = QFrame()
        self._info_toggle_box_frame.setFrameShape(QFrame.NoFrame)
        self._info_toggle_box_frame.setFrameShadow(QFrame.Plain)
        info_toggle_box_frame_lyt = layouts.VerticalLayout(spacing=1,
                                                           margins=(0, 1, 0,
                                                                    0))
        self._info_toggle_box_frame.setLayout(info_toggle_box_frame_lyt)

        self._info_frame = QFrame()
        self._info_frame.setFrameShape(QFrame.NoFrame)
        self._info_frame.setFrameShadow(QFrame.Plain)
        info_frame_lyt = layouts.VerticalLayout(spacing=0,
                                                margins=(0, 0, 0, 0))
        self._info_frame.setLayout(info_frame_lyt)
        info_toggle_box_frame_lyt.addWidget(self._info_frame)

        info_toggle_box_lyt.addWidget(info_toggle_box_header)
        info_toggle_box_lyt.addWidget(self._info_toggle_box_frame)

        version_toggle_box = QFrame()
        version_toggle_box.setFrameShape(QFrame.NoFrame)
        version_toggle_box.setFrameShadow(QFrame.Plain)
        version_toggle_box_lyt = layouts.VerticalLayout(spacing=0,
                                                        margins=(0, 0, 0, 0))
        version_toggle_box.setLayout(version_toggle_box_lyt)

        version_toggle_box_header = QFrame()
        version_toggle_box_header.setFrameShape(QFrame.NoFrame)
        version_toggle_box_header.setFrameShadow(QFrame.Plain)
        version_toggle_box_header_lyt = layouts.VerticalLayout(spacing=0,
                                                               margins=(0, 0,
                                                                        0, 0))
        version_toggle_box_header.setLayout(version_toggle_box_header_lyt)

        self._version_toggle_box_btn = buttons.BaseButton('VERSION',
                                                          parent=self)
        self._version_toggle_box_btn.setObjectName('versionButton')
        self._version_toggle_box_btn.setCheckable(True)
        self._version_toggle_box_btn.setChecked(True)
        version_toggle_box_header_lyt.addWidget(self._version_toggle_box_btn)

        self._version_toggle_box_frame = QFrame()
        self._version_toggle_box_frame.setFrameShape(QFrame.NoFrame)
        self._version_toggle_box_frame.setFrameShadow(QFrame.Plain)
        version_toggle_box_frame_lyt = layouts.VerticalLayout(spacing=1,
                                                              margins=(0, 1, 0,
                                                                       0))
        self._version_toggle_box_frame.setLayout(version_toggle_box_frame_lyt)

        self._version_frame = QFrame()
        self._version_frame.setFrameShape(QFrame.NoFrame)
        self._version_frame.setFrameShadow(QFrame.Plain)
        version_frame_lyt = layouts.VerticalLayout(spacing=0,
                                                   margins=(0, 0, 0, 0))
        self._version_frame.setLayout(version_frame_lyt)
        version_toggle_box_frame_lyt.addWidget(self._version_frame)

        self._history_widget = self.HISTORY_WIDGET()
        version_frame_lyt.addWidget(self._history_widget)

        version_toggle_box_lyt.addWidget(version_toggle_box_header)
        version_toggle_box_lyt.addWidget(self._version_toggle_box_frame)

        preview_buttons_frame = QFrame()
        preview_buttons_frame.setObjectName('previewButtons')
        preview_buttons_frame.setFrameShape(QFrame.NoFrame)
        preview_buttons_frame.setFrameShadow(QFrame.Plain)
        self._preview_buttons_frame_lyt = layouts.VerticalLayout(spacing=0,
                                                                 margins=(2, 2,
                                                                          2,
                                                                          2))
        self._preview_buttons_lyt = layouts.HorizontalLayout(spacing=2,
                                                             margins=(0, 0, 0,
                                                                      0))
        self._load_btn = buttons.BaseButton('Load', parent=self)
        self._load_btn.setObjectName('loadButton')
        self._load_btn.setMinimumSize(QSize(60, 35))
        self._load_btn.setMaximumSize(QSize(125, 35))
        self._preview_buttons_frame_lyt.addStretch()
        self._preview_buttons_frame_lyt.addLayout(self._preview_buttons_lyt)
        self._preview_buttons_frame_lyt.addStretch()
        self._preview_buttons_lyt.addWidget(self._load_btn)
        preview_buttons_frame.setLayout(self._preview_buttons_frame_lyt)

        info_layout.addLayout(title_layout)
        info_layout.addWidget(icon_toggle_box)
        info_layout.addWidget(info_toggle_box)
        info_layout.addWidget(version_toggle_box)

        tabs_widget.addTab(info_widget, 'Info')
        if self._options_widget:
            tabs_widget.addTab(self._options_widget, 'Options')

        self.main_layout.addWidget(tabs_widget)
        self.main_layout.addWidget(dividers.Divider())
        self.main_layout.addWidget(preview_buttons_frame)
        self.main_layout.addItem(
            QSpacerItem(0, 250, QSizePolicy.Preferred, QSizePolicy.Expanding))
Exemple #3
0
class GroupBoxWidget(base.BaseFrame):

    toggled = Signal(bool)

    def __init__(self,
                 title,
                 widget,
                 persistent=False,
                 settings=None,
                 *args,
                 **kwargs):

        self._title = title
        self._widget = None
        self._persistent = None
        self._settings = settings

        super(GroupBoxWidget, self).__init__(*args, **kwargs)

        if widget:
            self.set_widget(widget)
            # We force the update of the check status to make sure that the wrapped widget visibility is updated
            self.set_checked(self.is_checked())

        self.set_persistent(persistent)

    # ============================================================================================================
    # OVERRIDES
    # ============================================================================================================

    def get_main_layout(self):
        return layouts.VerticalLayout(spacing=0, margins=(0, 0, 0, 0))

    def ui(self):
        super(GroupBoxWidget, self).ui()

        self._title_widget = buttons.BaseButton(self._title, parent=self)
        self._title_widget.setCheckable(True)

        self._on_icon = resources.icon('down_button')
        self._off_icon = resources.icon('right_button')
        self._title_widget.setIcon(self._off_icon)

        self._widget_frame = QFrame(self)
        self._widget_frame.setObjectName('contentsWidget')
        widget_frame_layout = layouts.VerticalLayout(spacing=2,
                                                     margins=(0, 0, 0, 0))
        self._widget_frame.setLayout(widget_frame_layout)

        self.main_layout.addWidget(self._title_widget)
        self.main_layout.addWidget(self._widget_frame)

    def setup_signals(self):
        self._title_widget.toggled.connect(self._on_toggled_title)

    # ============================================================================================================
    # BASE
    # ============================================================================================================

    def is_checked(self):
        """
        Returns whether or not group box is checked
        :return: bool
        """

        return self._title_widget.isChecked()

    def set_checked(self, flag):
        """
        Sets the check statue of the group box
        :param flag: bool
        """

        self._title_widget.setChecked(flag)
        self._title_widget.setIcon(self._on_icon if flag else self._off_icon)
        self._widget_frame.setVisible(flag)
        if self._widget:
            self._widget.setVisible(flag)

    def is_persistent(self):
        """
        Returns whether or not widget state is stored in settings
        :return: bool
        """

        return self._persistent

    def set_persistent(self, flag):
        """
        Sets whether or not widget state is stored in settings
        :param flag: bool
        """

        self._persistent = flag
        self.load_settings()

    def title(self):
        """
        Returns group box title
        :return: str
        """

        return self._title_widget.text()

    def set_widget(self, widget):
        """
        Sets the widget to hide when the user clicks the title
        :param widget: QWidget
        """

        self._widget = widget
        self._widget.setParent(self._widget_frame)
        self._widget_frame.layout().addWidget(self._widget)

    # ============================================================================================================
    # SETTINGS
    # ============================================================================================================

    def load_settings(self):
        """
        Loads widget state from given settings
        """

        if not self._settings or not self._persistent:
            return
        if not self.objectName():
            raise NameError(
                'Impossible to save "{}" widget state because no objectName is defined!'
                .format(self))

        data = {self.objectName(): {'checked': self.is_checked()}}
        self._settings.save(data)

    def save_settings(self):
        """
        Saves current widget state into settings
        """

        if not self._settings or not self._persistent:
            return
        if not self.objectName():
            raise NameError(
                'Impossible to load "{}" widget state because no objectName is defined!'
                .format(self))

        data = self._settings.read()
        data = data.get(self.objectName(), dict())
        if data and isinstance(data, dict):
            checked = data.get('checked', True)
            self.set_checked(checked)

    # ============================================================================================================
    # CALLBACKS
    # ============================================================================================================

    def _on_toggled_title(self, flag):
        """
        Internal callback function that is called each time title group widget is toggled
        :param flag: bool
        """

        self.save_settings()
        self.set_checked(flag)
        self.toggled.emit(flag)
Exemple #4
0
class MessageBox(QDialog, object):

    MAX_WIDTH = 320
    MAX_HEIGHT = 220

    @staticmethod
    def input(parent, title, text, input_text='', width=None, height=None, buttons=None,
              header_pixmap=None, header_color=None, theme_to_apply=None):
        """
        Helper dialog function to get a single text value from the user
        :param parent: QWidget
        :param title: str
        :param text: str
        :param input_text: str
        :param width: int
        :param height: int
        :param buttons: list(QDialogButtonBox.StandardButton)
        :param header_pixmap: QPixmap
        :param header_color: str
        :param theme_to_apply: Theme
        :return: QMessageBox.StandardButton
        """

        buttons = buttons or QDialogButtonBox.Ok | QDialogButtonBox.Cancel
        dialog = create_message_box(parent=parent, title=title, text=text, width=width, height=height,
                                    buttons=buttons, header_pixmap=header_pixmap, header_color=header_color,
                                    enable_input_edit=True, theme_to_apply=theme_to_apply)
        dialog.set_input_text(input_text)
        dialog.exec_()
        clicked_btn = dialog.clicked_standard_button()

        return dialog.input_text(), clicked_btn

    @staticmethod
    def question(parent, title, text, width=None, height=None, buttons=None, header_pixmap=None,
                 header_color=None, enable_dont_show_checkbox=False, theme_to_apply=None):
        """
        Helper dialog function to get a single text value from the user
        :param parent: QWidget
        :param title: str
        :param text: str
        :param width: int
        :param height: int
        :param buttons: list(QDialogButtonBox.StandardButton)
        :param header_pixmap: QPixmap
        :param header_color: str
        :param enable_dont_show_checkbox: bool
        :param theme_to_apply: Theme
        :return: QDialogButtonBox.StandardButton
        """

        buttons = buttons or QDialogButtonBox.Yes | QDialogButtonBox.No | QDialogButtonBox.Cancel
        clicked_btn = show_message_box(parent=parent, title=title, text=text, width=width, height=height,
                                       buttons=buttons, header_pixmap=header_pixmap, header_color=header_color,
                                       enable_dont_show_checkbox=enable_dont_show_checkbox,
                                       theme_to_apply=theme_to_apply)
        return clicked_btn

    @staticmethod
    def warning(parent, title, text, width=None, height=None, buttons=None, header_pixmap=None,
                header_color='rgb(250, 160, 0)', enable_dont_show_checkbox=False, force=False):
        """
        Helper dialog function to open a warning message box with the given options
        :param parent: QWidget
        :param title: str
        :param text: str
        :param width: int
        :param height: int
        :param buttons: list(QDialogButtonBox.StandardButton)
        :param header_pixmap: QPixmap
        :param header_color: str
        :param enable_dont_show_checkbox: bool
        :param force: bool
        :return: QDialogButtonBox.StandardButton
        """

        buttons = buttons or QDialogButtonBox.Yes | QDialogButtonBox.No
        clicked_btn = show_message_box(parent=parent, title=title, text=text, width=width, height=height,
                                       buttons=buttons, header_pixmap=header_pixmap, header_color=header_color,
                                       enable_dont_show_checkbox=enable_dont_show_checkbox, force=force)
        return clicked_btn

    @staticmethod
    def critical(parent, title, text, width=None, height=None, buttons=None, header_pixmap=None,
                 header_color='rgb(230, 80, 80)'):
        """
        Helper dialog function to open a critical/error message box with the given options
        :param parent: QWidget
        :param title: str
        :param text: str
        :param width: int
        :param height: int
        :param buttons: list(QDialogButtonBox.StandardButton)
        :param header_pixmap: QPixmap
        :param header_color: str
        :return: QDialogButtonBox.StandardButton
        """

        buttons = buttons or QDialogButtonBox.Ok | QDialogButtonBox.Cancel
        clicked_btn = show_message_box(parent=parent, title=title, text=text, width=width, height=height,
                                       buttons=buttons, header_pixmap=header_pixmap, header_color=header_color)
        return clicked_btn

    def __init__(self, name='messageBox', width=None, height=None, enable_input_edit=False,
                 enable_dont_show_checkbox=False, parent=None):

        super(MessageBox, self).__init__(parent=parent)

        self._frame = None
        self._animation = None
        self._dont_show_checkbox = False
        self._clicked_button = None
        self._clicked_standard_button = None

        self.setMinimumWidth(width or self.MAX_WIDTH)
        self.setMinimumHeight(height or self.MAX_HEIGHT)
        self.setObjectName(name)
        self.setWindowFlags(self.windowFlags() | Qt.FramelessWindowHint)
        # self.setAttribute(Qt.WA_TranslucentBackground)
        # self.setStyleSheet('background-color: rgb(68, 68, 68, 255);')

        parent = self.parent()
        self._frame = None
        if parent and parent != dcc.get_main_window():
            parent.installEventFilter(self)
            self._frame = QFrame(parent)
            self._frame.setStyleSheet('background-color: rgba(25, 25, 25, 150);')
            self._frame.setObjectName('messageBoxFrame')
            self._frame.show()
            self.setParent(self._frame)

        self.main_layout = layouts.VerticalLayout(spacing=0, margins=(0, 0, 0, 0))
        self.setLayout(self.main_layout)

        self._header = QFrame(self)
        self._header.setFixedHeight(46)
        self._header.setObjectName('messageBoxHeaderFrame')
        self._header.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)

        self._icon = label.BaseLabel(parent=self._header)
        self._icon.hide()
        self._icon.setFixedHeight(32)
        self._icon.setFixedHeight(32)
        self._icon.setScaledContents(True)
        self._icon.setAlignment(Qt.AlignTop)
        self._icon.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)

        self._title = label.BaseLabel(parent=self._header)
        self._title.setObjectName('messageBoxHeaderLabel')
        self._title.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)

        hlayout = layouts.HorizontalLayout(spacing=10, margins=(15, 7, 15, 10))
        hlayout.addWidget(self._icon)
        hlayout.addWidget(self._title)
        self._header.setLayout(hlayout)

        body_layout = layouts.VerticalLayout()
        self._body = QFrame(self)
        self._body.setObjectName('messageBoxBody')
        self._body.setLayout(body_layout)

        self._message = label.BaseLabel(parent=self._body)
        self._message.setWordWrap(True)
        self._message.setMinimumHeight(15)
        self._message.setAlignment(Qt.AlignLeft)
        self._message.setTextInteractionFlags(Qt.TextSelectableByMouse)
        self._message.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        body_layout.addWidget(self._message)
        body_layout.setContentsMargins(15, 15, 15, 15)

        if enable_input_edit:
            self._input_edit = lineedit.BaseLineEdit(parent=self._body)
            self._input_edit.setObjectName('messageBoxInputEdit')
            self._input_edit.setMinimumHeight(32)
            self._input_edit.setFocus()
            body_layout.addStretch(1)
            body_layout.addWidget(self._input_edit)
            body_layout.addStretch(10)

        if enable_dont_show_checkbox:
            msg = 'Do not show this message again'
            self._dont_show_checkbox = checkbox.BaseCheckBox(msg, parent=self._body)
            body_layout.addStretch(10)
            body_layout.addWidget(self._dont_show_checkbox)
            body_layout.addStretch(2)

        self._button_box = QDialogButtonBox(None, Qt.Horizontal, self)
        self._button_box.clicked.connect(self._on_clicked)
        self._button_box.accepted.connect(self._on_accept)
        self._button_box.rejected.connect(self._on_reject)

        self.main_layout.addWidget(self._header)
        self.main_layout.addWidget(self._body)
        body_layout.addWidget(self._button_box)

        self.updateGeometry()

    def eventFilter(self, object, event):
        """
        Overrides base QDialog eventFilter function
        Updates the geometry when the parnet widget changes size
        :param object: QWidget
        :param event: QEvent
        """

        if event.type() == QEvent.Resize:
            self.updateGeometry()
        return super(MessageBox, self).eventFilter(object, event)

    def showEvent(self, event):
        """
        Overrides base QDialog showEvent function
        Fade in hte dialog on show
        :param event: QEvent
        """

        self.updateGeometry()
        self._fade_in()

    def keyPressEvent(self, event):
        if event.key() != Qt.Key_Escape:
            super(MessageBox, self).keyPressEvent(event)

    def updateGeometry(self):
        """
        Overrides base QDialog updateGeometry function
        Updates the geometry to be in the center of it's parent
        """

        frame = self._frame
        if frame:
            frame.setGeometry(self._frame.parent().geometry())
            frame.move(0, 0)
            geometry = self.geometry()
            center_point = frame.geometry().center()
            geometry.moveCenter(center_point)
            geometry.setY(geometry.y() - 50)
            self.move(geometry.topLeft())

    def exec_(self):
        """
        Overrides base QDialog exec_ function
        Shows the dialog as a modal dialog
        :return: variant, int or None
        """

        super(MessageBox, self).exec_()
        return self.clicked_index()

    def button_box(self):
        """
        Returns the button box widget for the dialog
        :return: QDialogButtonBox
        """

        return self._button_box

    def header(self):
        """
        Returns the header frame
        :return: QFrame
        """

        return self._header

    def set_header_color(self, color):
        """
        Sets the header color for the message box
        :param color: str
        """

        self.header().setStyleSheet('background-color: {}'.format(color))

    def set_title_text(self, text):
        """
        Sets the title text to be displayed
        :param text: str
        """

        self._title.setText(text)

    def set_text(self, text):
        """
        Sets the text message to be displayed
        :param text: str
        """

        self._message.setText(str(text))

    def input_text(self):
        """
        Returns the text that the user has given in the input edit
        :return: str
        """

        return self._input_edit.text()

    def set_input_text(self, text):
        """
        Sets the input text
        :param text: str
        """

        self._input_edit.setText(text)
        if text:
            self._input_edit.selectAll()

    def add_button(self, *args):
        """
        Adds a new upsh button with the given text and roled
        """

        self.button_box().addButton(*args)

    def set_buttons(self, buttons):
        """
        Sets the buttons to be displayed in message box
        :param buttons: QMessageBox.StandardButton
        """

        self.button_box().setStandardButtons(buttons)

    def set_pixmap(self, pixmap):
        """
        Sets the pixmap for the message box
        :param pixmap: QPixmap
        """

        self._icon.setPixmap(pixmap)
        self._icon.show()

    def clicked_button(self):
        """
        Returns the button that was clicked
        :return: variant, QPushButton or None
        """

        return self._clicked_button

    def clicked_index(self):
        """
        Returns the button that was clicked by its index
        :return: variant, int or None
        """

        for i, btn in enumerate(self.button_box().buttons()):
            if btn == self.clicked_button():
                return i

    def clicked_standard_button(self):
        """
        Returns the button that was clicked by the user
        :return: variant, QMessageBox.StandardButton or None
        """

        return self._clicked_standard_button

    def is_dont_show_checkbox_checked(self):
        """
        Returns the checked state of the dont show again checkbox
        :return: bool
        """

        if self._dont_show_checkbox:
            return self._dont_show_checkbox.isChecked()
        else:
            return False

    def _fade_in(self, duration=200):
        """
        Internal function that fade in the dialog using opacity effect
        :param duration: int
        :return: QPropertyAnimation
        """
        if self._frame:
            self._animation = animation.fade_in_widget(self._frame, duration=duration)
        return self._animation

    def _fade_out(self, duration=200):
        """
        Internal function that fade out the dialog using opacity effect
        :param duration: int
        :return: QPropertyAnimation
        """
        if self._frame:
            self._animation = animation.fade_out_widget(self._frame, duration=duration)
        return self._animation

    def _on_clicked(self, button):
        """
        Internal callback function triggered when the user clicks a button
        :param button: QPushButton
        """

        self._clicked_button = button
        self._clicked_standard_button = self.button_box().standardButton(button)

    def _on_accept(self):
        """
        Internal callback function triggered when the DialogButtonBox has been accepted
        """

        anim = self._fade_out()
        if anim:
            anim.finished.connect(self._on_accept_animation_finished)
        else:
            self._on_accept_animation_finished()

    def _on_reject(self):
        """
        Internal callback function triggered when the DialogButtonBox has been rejected
        """

        anim = self._fade_out()
        if anim:
            anim.finished.connect(self._on_reject_animation_finished)
        else:
            self._on_reject_animation_finished()

    def _on_accept_animation_finished(self):
        """
        Internal callback function triggered when the animation has finished on accepted
        """

        parent = self._frame or self
        parent.close()
        self.accept()

    def _on_reject_animation_finished(self):
        parent = self._frame or self
        parent.close()
        self.reject()