Beispiel #1
0
    def __init__(self, base):
        Window.__init__(self, base, i18n.get('image_preview'))

        self.loader = BarLoadIndicator()

        self.view = QLabel()
        self.view.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored)
        self.view.setScaledContents(True)

        scroll_area = QScrollArea()
        scroll_area.setBackgroundRole(QPalette.Dark)
        scroll_area.setWidget(self.view)
        scroll_area.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        scroll_area.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)

        self.error_label = QLabel(i18n.get('error_loading_image'))
        self.error_label.setAlignment(Qt.AlignHCenter)
        self.error_label.setStyleSheet("QLabel {background-color: #ffecec;}")

        layout = QVBoxLayout()
        layout.setSpacing(0)
        layout.setContentsMargins(0, 0, 0, 0)
        layout.addWidget(self.loader)
        layout.addWidget(self.error_label)
        layout.addWidget(scroll_area)

        self.setLayout(layout)
        self.__clear()
Beispiel #2
0
 def init_ui(self):
     self.setFrameShape(QFrame.Box)
     inner = QWidget()
     self.layout = QVBoxLayout()
     self.layout.setSpacing(1)
     self.layout.setMargin(1)
     self.layout.setAlignment(Qt.AlignTop)
     inner.setLayout(self.layout)
     scroll = QScrollArea()
     scroll.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
     scroll.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
     scroll.setWidgetResizable(True)
     scroll.setWidget(inner)
     layout = QVBoxLayout(self)
     layout.addWidget(scroll)
     self.setLayout(layout)
Beispiel #3
0
class UIWellPlotPG(QtCore.QObject):
    def setupUI(self):
        self.mainWidget = WellPlotWidget()
        vBox = QtGui.QVBoxLayout()

        self.splitter = QSplitter(QtCore.Qt.Vertical)

        self.headerScrollArea = QScrollArea()
        self.headerScrollArea.setVerticalScrollBarPolicy(
            QtCore.Qt.ScrollBarAlwaysOn)
        self.headerScrollArea.setHorizontalScrollBarPolicy(
            QtCore.Qt.ScrollBarAlwaysOff)
        self.headerScrollArea.setWidgetResizable(False)

        self.scrollArea = QScrollArea()
        self.scrollArea.setVerticalScrollBarPolicy(
            QtCore.Qt.ScrollBarAlwaysOff)
        self.scrollArea.setHorizontalScrollBarPolicy(
            QtCore.Qt.ScrollBarAlwaysOn)
        #Needs to be true to allow widget in scroll area size to change
        self.scrollArea.setWidgetResizable(True)
        #self.scrollArea.setWidget(self.dataWidget)
        #see http://stackoverflow.com/questions/29583927/pyqt-qscrollarea-within-qscrollarea/29584939#29584939
        self.scrollArea.horizontalScrollBar().valueChanged.connect(
            self.headerScrollArea.horizontalScrollBar().setValue)

        self.splitter.addWidget(self.headerScrollArea)
        self.splitter.addWidget(self.scrollArea)

        #test
        hBox = QtGui.QHBoxLayout()
        #set parent so can access it for widget sizing
        self.scaleWidget = QWidget()
        self.scaleWidgetLayout = QtGui.QVBoxLayout()
        self.scaleWidget.setLayout(self.scaleWidgetLayout)
        self.scaleWidget.setMinimumWidth(30)
        hBox.addWidget(self.splitter, 1)
        hBox.addWidget(self.scaleWidget)
        self.mainWidget.setLayout(hBox)
        #end test
        '''
class SkillWidget(TraitWidget):
    """
	@brief Das Widget, in welchem sämtliche Fertigkeiten angeordnet sind.

	Wird bei irgendeiner Fertigkeit der Spazialisierungen-Knopf gedrückt, werden alle anderen Spezialisierungs-Knöpfe ausgeschalten.
	"""

    specialtiesActivated = Signal(bool, object)

    def __init__(self, template, character, parent=None):
        super(SkillWidget, self).__init__(template, character, parent)

        self.__layout = QVBoxLayout()
        self.setLayout(self.__layout)

        self.__scrollArea = QScrollArea()
        ## Die Auflistung der Fertigkeiten soll auch unter Windows einen transparenten Hintergrund haben.
        self.__scrollArea.setObjectName("transparentWidget")
        ## \todo Sollte nicht vom Betriebssystem, sondern vom verwendeten Style abhängen.
        if os.name == "nt":
            self.__scrollArea.setStyleSheet(
                "QWidget#transparentWidget { background: transparent; }")
        self.__layout.addWidget(self.__scrollArea)

        self.__scrollLayout = QVBoxLayout()

        self.__scrollWidget = QWidget()
        ## Die Auflistung der Fertigkeiten soll auch unter Windows einen transparenten Hintergrund haben. Indem ich den selben Namen wie zuvor vergebe, wirkt auch das Stylsheet auf dieses Widget.
        self.__scrollWidget.setObjectName("transparentWidget")
        #self.__scrollWidget.setStyleSheet( "QWidget#transparentWidget { background-color:transparent; }" )
        #scrollWidget.setMinimumSize(this.width(), 400);
        self.__scrollWidget.setLayout(self.__scrollLayout)

        typ = "Skill"

        ## Eine Liste, in der alle Eigenschafts-Widgets aufgelistet werden.
        self.__traitWidgets = []

        for item in Config.CATEGORIES_MAIN:
            #Debug.debug(self._character.traits)

            # Für jede Kategorie wird ein eigener Abschnitt erzeugt.
            widgetSkillCategory = QGroupBox()
            widgetSkillCategory.setTitle(item)
            widgetSkillCategory.setFlat(True)

            layoutSkillCategory = QVBoxLayout()
            widgetSkillCategory.setLayout(layoutSkillCategory)

            self.__scrollLayout.addWidget(widgetSkillCategory)

            __list = list(self._character.traits[typ][item].items())
            __list.sort()
            for skill in __list:
                # Anlegen des Widgets, das diese Eigenschaft repräsentiert.
                traitWidget = CharaTrait(skill[1], self)
                traitWidget.buttonText = 0
                traitWidget.setDescriptionHidden(True)
                traitWidget.enableButton(
                    0
                )  # Zu Beginn sollen die Spezailisierungen nicht enabled sein.

                # Dieses Widget auch an Liste anhängen, damit ich einfacher darauf zugreifen kann.
                traitListItem = traitWidget
                self.__traitWidgets.append(traitListItem)

                # Es werden nur Fertigkeiten der richtigen Alters- und Zeit-Kategorie angezeigt.
                self.hideReasonChanged.connect(traitWidget.hideOrShowTrait)
                # Fertigkeiten haben Spezialisierungen.
                traitWidget.specialtiesClicked.connect(
                    self.uncheckOtherButtons)
                traitWidget.specialtiesClicked.connect(
                    self.specialtiesActivated.emit)
                ## Wenn sich die Spezialisierungen ändern, sollen die veränderten Spezialisierungen auch angezeigt werden. Das wird so gelöst, als wäre der Knopf für die Spezialisierungen erneut gedrückt worden.
                #skill.specialtiesChanged.connect(self.emitSpecialtiesActivated)

                layoutSkillCategory.addWidget(traitWidget)

                self.maxTraitChanged.connect(traitWidget.setMaximum)

            # Stretch einfügen, damit die Eigenschaften besser angeordnet sind.
            self.__scrollLayout.addStretch()

        self.__scrollArea.setWidget(self.__scrollWidget)
        self.__scrollArea.setWidgetResizable(True)
        self.__scrollArea.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.__scrollArea.setMinimumWidth(
            self.__scrollArea.viewport().minimumWidth())

    def uncheckOtherButtons(self, sw, trait):
        """
		Über diese Funktion werden alle anderen Spezialisierungs-Knöpfe deaktiviert, sobald einer aktiviert wird.
		"""

        #Debug.debug("Drücke {}".format(skillName))
        if sw:
            for item in self.__traitWidgets:
                if item.name != trait.name:
                    item.setSpecialtyButtonChecked(False)
class ScrollArea(QFrame):

    def __init__(self, parent=None, horizontal=True, vertical=True,
                 color=None):
        QFrame.__init__(self, parent)
        
        self.scrollarea = QScrollArea(self)
        self.scrollarea.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.scrollarea.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        
        self.v_pad = scrollbar.ScrollPad(self)
        self.v_pad.setOrientation(Qt.Vertical)
        self.v_pad.setMinimumWidth(30)
        if color:
            self.v_pad.set_color(color)

        self.h_pad = scrollbar.ScrollPad(self)
        self.h_pad.setOrientation(Qt.Horizontal)
        self.h_pad.setMinimumHeight(30)
        if color:
            self.h_pad.set_color(color)

        QObject.connect(self.v_pad, SIGNAL('valueChanged(int)'),
                        self.v_scroll)
        QObject.connect(self.h_pad, SIGNAL('valueChanged(int)'),
                        self.h_scroll)

        for name in ('setWidgetResizable',):
            setattr(self, name, getattr(self.scrollarea, name))
        self.horizontal(horizontal)
        self.vertical(vertical)

        Layout1 = QVBoxLayout(self)
        Layout1.setSpacing(0)
        Layout1.setMargin(0)
        Layout2 = QHBoxLayout()
        Layout2.setSpacing(0)
        Layout2.setMargin(0)
        Layout2.addWidget(self.scrollarea)
        Layout2.addWidget(self.v_pad)
        Layout1.addLayout(Layout2)
        Layout1.addWidget(self.h_pad)

    def setWidget(self, widget):
        self.scrollarea.setWidget(widget)

    def horizontal(self, on):
        if on:
            self.h_pad.show()
        else:
            self.h_pad.hide()

    def vertical(self, on):
        if on:
            self.v_pad.show()
        else:
            self.v_pad.hide()

    def v_scroll(self, value):
        sb = self.v_pad
        target_sb = self.scrollarea.verticalScrollBar()
        percent = sb.value() / float(sb.maximum())
        target_sb.setValue(int(percent * target_sb.maximum()))

    def h_scroll(self, value):
        sb = self.h_pad
        target_sb = self.scrollarea.horizontalScrollBar()
        percent = sb.value() / float(sb.maximum())
        target_sb.setValue(int(percent * target_sb.maximum()))
    def __init__(self, parent=0, dmd=None, *args, **kwargs):
        super(CheckListViewWidget, self).__init__(
            parent=parent, *args, **kwargs)
        self.parent = parent
        self.dmd = dmd
        self.check_list = self.dmd.check_list
        self.parentWidget().set_window_title("Check-list")
        row = 0
        self.piecesGroupBox = QGroupBox("")
        # self.piecesGroupBox.setStyleSheet("color: gray; background:#fff")
        pieces_v_gribox = QGridLayout()
        css = "font-size:26px;border: 3px solid #000;background: black;color: white;"
        pieces_v_gribox.addWidget(FHeader(
            "I. Pièces à vérifier (au dépôt)", css), row, 0, 1, 6)
        row += 1
        self.qualite_declarant_check = self.check_box(QCheckBox())
        self.qualite_declarant_check.setChecked(
            self.check_list.qualite_declarant_check)
        pieces_v_gribox.addWidget(FRLabel(
            "Qualité du déclarant (Président, mandataire ou auxiliaire de Justice) "), row, 0)
        pieces_v_gribox.addWidget(self.qualite_declarant_check, row, 1)
        # row += 1
        self.status_check = self.check_box(QCheckBox("(4)"))
        self.status_check.setChecked(self.check_list.status_check)
        pieces_v_gribox.addWidget(FRLabel("Statuts "), row, 2)
        pieces_v_gribox.addWidget(self.status_check, row, 3)
        self.pieces_check = self.check_box(QCheckBox("(4)"))
        self.pieces_check.setChecked(self.check_list.pieces_check)
        pieces_v_gribox.addWidget(
            FRLabel("Règlement Intérieur "), row, 4)
        pieces_v_gribox.addWidget(self.pieces_check, row, 5)
        row += 1
        self.autorisation_pre_immt_check = self.check_box(QCheckBox())
        self.autorisation_pre_immt_check.setChecked(
            self.check_list.autorisation_pre_immt_check)
        pieces_v_gribox.addWidget(FRLabel(
            "Autorisations préalables pour les activités réglementées "), row, 0)
        pieces_v_gribox.addWidget(self.autorisation_pre_immt_check, row, 1)
        self.demande_immt_check = self.check_box(QCheckBox("(2)"))
        self.demande_immt_check.setChecked(self.check_list.demande_immt_check)
        pieces_v_gribox.addWidget(
            FRLabel("Demande d’Immatriculation "), row, 2)
        pieces_v_gribox.addWidget(self.demande_immt_check, row, 3)
        self.pv_check = self.check_box(QCheckBox("(4)"))
        self.pv_check.setChecked(self.check_list.pv_check)
        pieces_v_gribox.addWidget(FRLabel("PV "), row, 4)
        pieces_v_gribox.addWidget(self.pv_check, row, 5)
        row = 0
        pieces_gribox = QGridLayout()
        self.chronologique_check = self.check_box(QCheckBox())
        self.chronologique_check.setChecked(
            self.check_list.chronologique_check)
        pieces_gribox.addWidget(FLabel(
            "Vérifier l’existence du registre des membres tenu par ordre chronologique "), row, 0)
        pieces_gribox.addWidget(self.chronologique_check, row, 1)
        pieces_gribox.addWidget(FHeader(
            "SCOOPS Art 235 et 236 COOP-CA Art 320, 321, 322 et 323", "font-size:15px"), row, 2)
        row += 1
        self.compte_check = self.check_box(QCheckBox())
        self.compte_check.setChecked(self.check_list.compte_check)
        pieces_gribox.addWidget(FLabel(
            "Vérifier l’existence d’un compte bancaire / Institution de Micro Finance"), row, 0)
        pieces_gribox.addWidget(self.compte_check, row, 1)
        pieces_gribox.addWidget(FHeader(
            "Art 213", "font-size:15px"), row, 2)
        row += 1
        self.dispositions_check = self.check_box(QCheckBox())
        self.dispositions_check.setChecked(self.check_list.dispositions_check)
        pieces_gribox.addWidget(FLabel(
            "Vérifier le respect des dispositions sur le non cumul des mandats"), row, 0)
        pieces_gribox.addWidget(self.dispositions_check, row, 1)
        pieces_gribox.addWidget(FHeader(
            "Art 300 et 326", "font-size:15px"), row, 2)
        row += 1
        self.pv_delib_ca_check = self.check_box(QCheckBox())
        self.pv_delib_ca_check.setChecked(self.check_list.pv_delib_ca_check)
        pieces_gribox.addWidget(FLabel(
            "Vérifier l’existence du registre des procès- verbaux de délibération du CA <br/> des COOP-CA coté et paraphé par le tribunal civil compétent"), row, 0)
        pieces_gribox.addWidget(self.pv_delib_ca_check, row, 1)
        pieces_gribox.addWidget(FHeader(
            "Art : 235, (d’ordre général) et COOP-CA 320", "font-size:15px"), row, 2)
        pieces_gribox.setColumnStretch(row, 2)
        row = 0
        mentions_gribox = QGridLayout()
        mentions_gribox.addWidget(FHeader(
            " II. Mentions à vérifier dans les Statuts et le Règlement Intérieur", css), row, 0, 1, 4)
        row += 1
        css = "color:blue;font-size:26px;border: 1px solid #000;background: black;color: white;"
        mentions_gribox.addWidget(FHeader("Mentions", css=css), row, 0)
        mentions_gribox.addWidget(
            FHeader("N° Art des Statuts", css=css), row, 1)
        mentions_gribox.addWidget(FHeader("N° Art du R.I", css=css), row, 2)
        mentions_gribox.addWidget(
            FHeader("Référence OHADA", css=css), row, 3)
        row += 1
        self.forme_scoop_status_field = IntLineEdit(self.rest_d(
            self.check_list.forme_scoop_status))
        self.forme_scoop_ri_field = IntLineEdit(self.rest_d(
            self.check_list.forme_scoop_ri))
        self.add_element(mentions_gribox, row, "<b>01.</b> La forme de la société coopérative",
                         self.forme_scoop_status_field, self.forme_scoop_ri_field,
                         "Art 204 ,215 et 216 Pour la SCOOPS / Art 267 et de 271 à 290 Pour la COOP-CA")
        row += 1
        self.denomination_status_field = IntLineEdit(self.rest_d(
            self.check_list.denomination_status))
        self.denomination_ri_field = IntLineEdit(self.rest_d(
            self.check_list.denomination_ri))
        self.add_element(mentions_gribox, row, "<b>02.</b> Sa dénomination suivie, le cas échéant, de son sigle",
                         self.denomination_status_field, self.denomination_ri_field,
                         "Art 19 et Art 205 Pour la SCOOPS<br/> Art 19 et 205 Pour COOP-CA")
        row += 1
        self.nature_domaine_status_field = IntLineEdit(self.rest_d(
            self.check_list.nature_domaine_status))
        self.nature_domaine_ri_field = IntLineEdit(self.rest_d(
            self.check_list.nature_domaine_ri))
        self.add_element(mentions_gribox, row, "<b>03.</b> La nature et le domaine de son activité et qui forment son objet social",
                         self.nature_domaine_status_field, self.nature_domaine_ri_field,
                         "Art 5, Art 20 et 21 Pour toutes les formes<br/> de Sociétés Coopératives")
        row += 1
        self.duree_status_field = IntLineEdit(self.rest_d(
            self.check_list.duree_status))
        self.duree_ri_field = IntLineEdit(self.rest_d(
            self.check_list.duree_ri))
        self.add_element(mentions_gribox, row, "<b>04.</b> Son siège et sa durée",
                         self.duree_status_field, self.duree_ri_field,
                         "Pour le Siège : Art 22 ,23 et 24 et Pour<br/> la Durée : Art 25, 26, 27et 28")
        row += 1
        self.lien_commun_status_field = IntLineEdit(self.rest_d(
            self.check_list.lien_commun_status))
        self.lien_commun_ri_field = IntLineEdit(self.rest_d(
            self.check_list.lien_commun_ri))
        self.add_element(mentions_gribox, row, "<b>05.</b> Le lien commun qui réunit les membres,",
                         self.lien_commun_status_field, self.lien_commun_ri_field, "Art 8")
        row += 1
        self.coord_initiateur_status_field = IntLineEdit(self.rest_d(
            self.check_list.coord_initiateur_status))
        self.coord_initiateur_ri_field = IntLineEdit(self.rest_d(
            self.check_list.coord_initiateur_ri))
        self.add_element(mentions_gribox, row, "<b>06.</b> Les noms, prénoms et adresse résidentielle de chaque initiateur",
                         self.coord_initiateur_status_field, self.coord_initiateur_ri_field, "Art 87")
        row += 1
        self.max_min_admin_cg_status_field = IntLineEdit(self.rest_d(
            self.check_list.max_min_admin_cg_status))
        self.max_min_admin_cg_ri_field = IntLineEdit(self.rest_d(
            self.check_list.max_min_admin_cg_ri))
        self.add_element(mentions_gribox, row, "<b>07. a.</b> Le nombre précis ou les nombres minimal et maximal de ses administrateurs <br/>  	ou membres du comité de gestion</p>",
                         self.max_min_admin_cg_status_field, self.max_min_admin_cg_ri_field, "Art 204 et Art 223 Pour la SCOOPS : <br/> (Effectif : 5 Pers au mini : CG=3 au plus si adh de 5 à 99 et CG = 5 si adh de 100 et +.")
        row += 1
        self.max_min_admin_ca_status_field = IntLineEdit(self.rest_d(
            self.check_list.max_min_admin_ca_status))
        self.max_min_admin_ca_ri_field = IntLineEdit(self.rest_d(
            self.check_list.max_min_admin_ca_ri))
        self.add_element(mentions_gribox, row, "<b>07. b.</b> Le nombre précis ou les nombres minimal et maximal de ses <br/> administrateurs ou membres du Conseil d’Administration;",
                         self.max_min_admin_ca_status_field, self.max_min_admin_ca_ri_field, "Art 207 et Art 223 Pour la COOP-CA: (Effectif : 15 Pers au mini : CA=3 au moins et 12 au plus.")
        row += 1
        self.dispositions_cg_status_field = IntLineEdit(self.rest_d(
            self.check_list.dispositions_cg_status))
        self.dispositions_cg_ri_field = IntLineEdit(self.rest_d(
            self.check_list.dispositions_cg_ri))
        self.add_element(mentions_gribox, row, "<b>07. c.</b> Les dispositions portant limitation des pouvoirs des <br/> administrateurs ou membres du comité de gestion",
                         self.dispositions_cg_status_field, self.dispositions_cg_ri_field, "Art 224 à Art 230 Pour la SCOOPS")
        row += 1
        self.dispositions_ca_status_field = IntLineEdit(self.rest_d(
            self.check_list.dispositions_ca_status))
        self.dispositions_ca_ri_field = IntLineEdit(self.rest_d(
            self.check_list.dispositions_ca_ri))
        self.add_element(mentions_gribox, row, "<b>07. d.</b> Les dispositions portant limitation des pouvoirs des administrateurs ou <br/>membres du Conseil d’Administration",
                         self.dispositions_ca_status_field, self.dispositions_ca_ri_field, "Art 296 à Art 307 Pour la COOP-CA et autres pouvoirs de l’Art 314 à l’Art 333")
        row += 1
        self.max_min_cs_s_status_field = IntLineEdit(self.rest_d(
            self.check_list.max_min_cs_s_status))
        self.max_min_cs_s_ri_field = IntLineEdit(self.rest_d(
            self.check_list.max_min_cs_s_ri))
        self.add_element(mentions_gribox, row, "<b>08.</b> Le nombre précis ou les nombres minimal et maximal des membres de la <br/>Commission de Surveillance",
                         self.max_min_cs_s_status_field, self.max_min_cs_s_ri_field, "Art 258 Pour la SCOOPS (de 3 à 5 Pers)")
        row += 1
        self.max_min_cs_ca_status_field = IntLineEdit(self.rest_d(
            self.check_list.max_min_cs_ca_status))
        self.max_min_cs_ca_ri_field = IntLineEdit(self.rest_d(
            self.check_list.max_min_cs_ca_ri))
        self.add_element(mentions_gribox, row, "<b>08. a.</b> Le nombre précis ou les nombres minimal et maximal des membres du <br/>Conseil de Surveillance",
                         self.max_min_cs_ca_status_field, self.max_min_cs_ca_ri_field, "Art 335 Pour la COOP-CA (de 3 à 5 Pers)")
        row += 1
        self.dispositions_mo_status_field = IntLineEdit(self.rest_d(
            self.check_list.dispositions_mo_status))
        self.dispositions_mo_ri_field = IntLineEdit(self.rest_d(
            self.check_list.dispositions_mo_ri))
        self.add_element(mentions_gribox, row, "<b>08. b.</b> Les dispositions relatives à l’exercice efficace des missions de ces organes",
                         self.dispositions_mo_status_field, self.dispositions_mo_ri_field, "Art 263 Pour la SCOOPS /Art 341 Pour la COOP-CA")
        row += 1
        self.mandat_cs_status_field = IntLineEdit(self.rest_d(
            self.check_list.mandat_cs_status))
        self.mandat_cs_ri_field = IntLineEdit(self.rest_d(
            self.check_list.mandat_cs_ri))
        self.add_element(mentions_gribox, row, "<b>09.</b> La durée du mandat des membres du comité de gestion, du conseil d’administration, <br/> du comité de surveillance et du conseil de surveillance",
                         self.mandat_cs_status_field, self.mandat_cs_ri_field, "Art 224 (Réf aux statuts) Pour la SCOOPS /Art 295 Pour la COOP-CA (Réf aux statuts)")
        row += 1
        self.parts_sociales_status_field = IntLineEdit(self.rest_d(
            self.check_list.parts_sociales_status))
        self.parts_sociales_ri_field = IntLineEdit(self.rest_d(
            self.check_list.parts_sociales_ri))
        self.add_element(mentions_gribox, row, "<b>10.</b> Toute limite relative au pourcentage maximal de parts sociales que peut détenir <br/> un seul membre Pour la SCOOPS",
                         self.parts_sociales_status_field, self.parts_sociales_ri_field, "Art 210 Réf aux statuts et ne peut excéder 5 fois <br/> le montant des parts sociales souscrites) Pour la COOP-CA Art 371")
        row += 1
        self.declatation_status_field = IntLineEdit(self.rest_d(
            self.check_list.declatation_status))
        self.declatation_ri_field = IntLineEdit(self.rest_d(
            self.check_list.declatation_ri))
        self.add_element(mentions_gribox, row, "<b>11.</b> Une déclaration précisant que la société coopérative est organisée et exploitée <br/> et exerce ses activités selon les principes coopératifs et le rappel de ces principes",
                         self.declatation_status_field, self.declatation_ri_field, "Art 6")
        row += 1
        self.id_apport_numeraire_status_field = IntLineEdit(self.rest_d(
            self.check_list.id_apport_numeraire_status))
        self.id_apport_numeraire_ri_field = IntLineEdit(self.rest_d(
            self.check_list.id_apport_numeraire_ri))
        self.add_element(mentions_gribox, row, "<b>12.</b> L’identité des apporteurs en numéraires avec pour chacun d’eux le montant des <br/> apports, le nombre et la valeur des parts sociales remis en contrepartie de chaque apport",
                         self.id_apport_numeraire_status_field, self.id_apport_numeraire_ri_field, "Art 30, 31, 32, 33,35, 36,")
        row += 1
        self.id_apport_nature_status_field = IntLineEdit(self.rest_d(
            self.check_list.id_apport_nature_status))
        self.id_apport_nature_ri_field = IntLineEdit(self.rest_d(
            self.check_list.id_apport_nature_ri))
        self.add_element(mentions_gribox, row, "<b>13. a.</b> L’identité des apporteurs en nature",
                         self.id_apport_nature_status_field, self.id_apport_nature_ri_field, "Point 12 de l’Art 18")
        row += 1
        self.evaluation_apport_status_field = IntLineEdit(self.rest_d(
            self.check_list.evaluation_apport_status))
        self.evaluation_apport_ri_field = IntLineEdit(self.rest_d(
            self.check_list.evaluation_apport_ri))
        self.add_element(mentions_gribox, row, "<b>13. b.</b> La nature et l’évaluation de l’apport effectué par chacun d’eux, le nombre et la valeur <br/>des parts sociales remises en contrepartie de chaque apport,  Le régime des biens ou valeurs apportés <br/>lorsque leur valeur excède celle des apports exigés ;",
                         self.evaluation_apport_status_field, self.evaluation_apport_ri_field, "Point 13 de l’Art 18")
        row += 1
        self.capital_social_status_field = IntLineEdit(self.rest_d(
            self.check_list.capital_social_status))
        self.capital_social_ri_field = IntLineEdit(self.rest_d(
            self.check_list.capital_social_ri))
        self.add_element(mentions_gribox, row, "<b>14. a.</b> Le montant du capital social, les limitations minimales et maximales y afférentes",
                         self.capital_social_status_field, self.capital_social_ri_field, "Art 53, 57 et 58 en général. Art 207 Pour la SCOOPS et 269 Pour la COOP-CA")
        row += 1
        self.valeur_nominale_status_field = IntLineEdit(self.rest_d(
            self.check_list.valeur_nominale_status))
        self.valeur_nominale_ri_field = IntLineEdit(self.rest_d(
            self.check_list.valeur_nominale_ri))
        self.add_element(mentions_gribox, row, "<b>14. b.</b> La valeur nominale des diverses catégories de parts, les conditions précises de leur émission<br/> ou souscription ;",
                         self.valeur_nominale_status_field, self.valeur_nominale_ri_field, "Art 44 et 45 en général. Pour la COOP-CA Art 376 et 377")
        row += 1
        self.stipulations_status_field = IntLineEdit(self.rest_d(
            self.check_list.stipulations_status))
        self.stipulations_ri_field = IntLineEdit(self.rest_d(
            self.check_list.stipulations_ri))
        self.add_element(mentions_gribox, row, "<b>15.</b> Les stipulations relatives à la répartition du résultat et notamment, des excédents<br/> et des réserves ;",
                         self.stipulations_status_field, self.stipulations_ri_field, "Art 46 alinéa en général. Pour SCOOPS alinéa 2 de l’Art 209 Pour la COOP-CA Art 363 alinéa 4")
        row += 1
        self.modalite_status_field = IntLineEdit(self.rest_d(
            self.check_list.modalite_status))
        self.modalite_ri_field = IntLineEdit(self.rest_d(
            self.check_list.modalite_ri))
        self.add_element(mentions_gribox, row, "<b>16.</b> Les modalités de fonctionnement de la société coopérative ;",
                         self.modalite_status_field, self.modalite_ri_field, "Art 95 à 121 en général .Pour SCOOPS art 217 à 263 Pour la COOP-CA Art 291 à 368")
        row += 1
        self.signature_int_status_field = IntLineEdit(self.rest_d(
            self.check_list.signature_int_status))
        self.signature_int_ri_field = IntLineEdit(self.rest_d(
            self.check_list.signature_int_ri))
        self.add_element(mentions_gribox, row, "<b>17.</b> La signature des initiateurs ou l’apposition de leur empreinte digitale",
                         self.signature_int_status_field, self.signature_int_ri_field, "Point 17 de l’Art 18")
        row += 1
        self.etendue_status_field = IntLineEdit(self.rest_d(
            self.check_list.etendue_status))
        self.etendue_ri_field = IntLineEdit(self.rest_d(
            self.check_list.etendue_ri))
        self.add_element(mentions_gribox, row, "<b>18.</b> L’étendue des transactions avec les usagers non coopérateurs, tout en ayant en vue<br/>la sauvegarde de l’autonomie de la société coopérative ;",
                         self.etendue_status_field, self.etendue_ri_field, "Art 4 al. 2")
        row += 1
        qss = "padding:5px;padding-left:25px;padding-right:25px;background: gray;font-size:30px;color:#fff"
        mentions_gribox.addWidget(FHeader(
            "Les mentions facultatives", qss), row, 0, 1, 4)
        row += 1
        self.rendement_status_field = IntLineEdit(self.rest_d(
            self.check_list.rendement_status))
        self.rendement_ri_field = IntLineEdit(self.rest_d(
            self.check_list.rendement_ri))
        self.add_element(mentions_gribox, row, "<b>1. a.</b> Le taux de rendement maximal qui peut être appliqué aux prêts et aux épargnes des membres",
                         self.rendement_status_field, self.rendement_ri_field, "Art 18. 1bis alinéa 1")
        row += 1
        self.remuneration_status_field = IntLineEdit(self.rest_d(
            self.check_list.remuneration_status))
        self.remuneration_ri_field = IntLineEdit(self.rest_d(
            self.check_list.remuneration_ri))
        self.add_element(mentions_gribox, row, "<b>1. b.</b> Le taux de rémunération maximale qui peut être appliqué aux parts de membres ;",
                         self.remuneration_status_field, self.remuneration_ri_field, "Art 239 ; 240 alinéa4 et 231(Art 18. 1bis alinéa 1)")
        row += 1
        self.limite_imposee_status_field = IntLineEdit(self.rest_d(
            self.check_list.limite_imposee_status))
        self.limite_imposee_ri_field = IntLineEdit(self.rest_d(
            self.check_list.limite_imposee_ri))
        self.add_element(mentions_gribox, row, "<b>2.</b> Toute limite imposée aux activités commerciales de la société coopérative.",
                         self.limite_imposee_status_field, self.limite_imposee_ri_field, "COOP–CA Art 313,SCOOPS Art 258 et 259")
        row += 1
        mentions_gribox.addWidget(FHeader(
            "Règlement Intérieur, outre les mentions obligatoires des statuts, le règlement intérieur contient les prescriptions suivantes :", qss), row, 0, 1, 4)
        row += 1
        self.indemnit_status_field = IntLineEdit(self.rest_d(
            self.check_list.indemnit_status))
        self.indemnit_ri_field = IntLineEdit(self.rest_d(
            self.check_list.indemnit_ri))
        self.add_element(mentions_gribox, row, "<b>1.</b> Les conditions de paiement d’indemnités aux membres du conseil d’administration ou du comité<br/> de gestion, du conseil ou du comité de surveillance, définies dans le respect des dispositions<br/> des articles 225 et 305 ;",
                         self.indemnit_status_field, self.indemnit_ri_field, "Scoops : Art 225; Scoop-CA : Art 305")
        row += 1
        self.souscription_status_field = IntLineEdit(self.rest_d(
            self.check_list.souscription_status))
        self.souscription_ri_field = IntLineEdit(self.rest_d(
            self.check_list.souscription_ri))
        self.add_element(mentions_gribox, row, "<b>2.</b> La souscription de parts sociales supplémentaires et leur nombre par coopérateur ;",
                         self.souscription_status_field, self.souscription_ri_field, "Pour la SCOOPS Art 210 Réf aux statuts et ne peut excéder <br/>5 fois le montant des parts sociales souscrites) Pour la COOP-CA Art 371")
        row += 1
        self.suspension_status_field = IntLineEdit(self.rest_d(
            self.check_list.suspension_status))
        self.suspension_ri_field = IntLineEdit(self.rest_d(
            self.check_list.suspension_ri))
        self.add_element(mentions_gribox, row, "<b>3.</b> Les critères et conditions de suspension des coopérateurs;",
                         self.suspension_status_field, self.suspension_ri_field, "Statut (initiateurs)")
        row += 1
        self.attribution_status_field = IntLineEdit(self.rest_d(
            self.check_list.attribution_status))
        self.attribution_ri_field = IntLineEdit(self.rest_d(
            self.check_list.attribution_ri))
        self.add_element(mentions_gribox, row, "<b>4.</b> La possibilité d’attribution d’un droit de vote plural dans le cas des unions, des fédérations et<br/>des confédérations ;",
                         self.attribution_status_field, self.attribution_ri_field, "Art 138")
        row += 1
        self.prescriptions_status_field = IntLineEdit(self.rest_d(
            self.check_list.prescriptions_status))
        self.prescriptions_ri_field = IntLineEdit(self.rest_d(
            self.check_list.prescriptions_ri))
        self.add_element(mentions_gribox, row, "<b>5.</b> Toutes autres prescriptions jugées nécessaires pour la réalisation de l’objet de la société <br/>coopérative et conformes aux principes coopératifs et aux dispositions impératives du présent<br/> Acte uniforme.",
                         self.prescriptions_status_field, self.prescriptions_ri_field, "AUSCOOP")
        vbox = QVBoxLayout()
        vbox.addLayout(pieces_v_gribox)
        vbox.addLayout(pieces_gribox)
        vbox.addLayout(mentions_gribox)
        self.piecesGroupBox.setLayout(vbox)
        # Durée statutaire de la société coopérative
        duree_fbox = QFormLayout()
        self.butt_continous = Button_save(u"Continuer")
        self.butt_continous.clicked.connect(self.goto_immatriculation)
        self.butt_continous.setMaximumWidth(200)
        duree_fbox.addRow("", self.butt_continous)

        if not self.check_integrity_validation():
            self.butt_continous.setEnabled(False)

        scroll = QScrollArea(self)
        scroll.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
        scroll.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
        scroll.setWidgetResizable(True)
        # scroll.setFixedHeight(200)
        vbox = QVBoxLayout()
        vbox.addWidget(FHeader(
            "<h2>Check-list de Contrôle de dossiers des sociétés coopératives avant l’immatriculation et l’enregistrement par le SLDS-ES</h2>", css="color:green"))
        vbox.addWidget(FHeader(
            "<h4>Société Coopérative : {} </h4>".format(self.dmd.scoop)))
        scroll.setWidget(self.piecesGroupBox)
        vbox.addWidget(scroll)
        vbox.addLayout(duree_fbox)
        self.setLayout(vbox)
Beispiel #7
0
class SectionsContainerWidget(QWidget):
    def __init__(self, parent=None, isLinacSection=True, sectionClass=None):
        QWidget.__init__(self, parent)
        self.isLinacSection = isLinacSection
        self.sectionClass = sectionClass
        self.setParent(parent)
        self.sectionWidgets = list()
        self.setMinimumWidth(460)
        self.setMinimumHeight(600)
        self.sumSize = 0

        self.setupLayout()
        self.setupScrollArea()
        self.addSectionButton = QPushButton(self.containerWidget)
        self.addSectionButton.setText("Add new section")
        self.layout.addWidget(self.addSectionButton)

        self.connect(self.addSectionButton, QtCore.SIGNAL("clicked()"),
                     self.addNewSection)

    def setupLayout(self):
        self.containerWidget = QWidget(self)
        self.widgetHeight = 120
        self.containerWidget.setGeometry(QRect(0, 0, 460, self.widgetHeight))

        self.layout = QVBoxLayout()
        self.containerWidget.setLayout(self.layout)

    def setupScrollArea(self):
        self.scrollArea = QScrollArea(self)
        self.scrollArea.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded)
        self.scrollArea.setHorizontalScrollBarPolicy(
            QtCore.Qt.ScrollBarAlwaysOff)
        self.scrollArea.setMaximumWidth(460)
        self.scrollArea.setMinimumHeight(600)
        self.scrollArea.setWidgetResizable(False)
        self.scrollArea.setWidget(self.containerWidget)

    def addNewSection(self):
        newSection = self.sectionClass(self.containerWidget)
        widgetPosition = len(self.sectionWidgets)
        self.layout.insertWidget(widgetPosition, newSection)
        self.sectionWidgets.append(newSection)
        self.setDefaultValues(newSection)

        self.widgetHeight += 80
        self.containerWidget.resize(460, self.widgetHeight)

        self.connect(newSection, QtCore.SIGNAL("remove()"), self.removeSection)
        self.connect(newSection, QtCore.SIGNAL("sizeValueChanged(QWidget*)"),
                     self.updateSumOfSize)

    def setDefaultValues(self, section):
        pass
        # section.colorLabel.setColor(SettingsCloud.getParameter("subsectionColor"))
        # self.setSectionSize(section)

    def setSectionSize(self, section):
        pass

    # def setSubsectionSize(self, section):
    #     if self.isLinacSection:
    #         defaultSize = SettingsCloud.getParameter("linacSubsectionSize")
    #     else:
    #         defaultSize = SettingsCloud.getParameter("ringSubsectionSize")
    #     section.sizeEdit.setValue(defaultSize)
    #     self.updateSumOfSize(section)

    def updateSumOfSize(self, sectionWidget):
        self.sumSize = 0
        for section in self.sectionWidgets:
            self.sumSize += section.getSize()
        if self.sumSize > 100:
            diff = self.sumSize - 100.0
            actualSize = sectionWidget.getSize()
            sectionWidget.setSize(actualSize - diff)

    def removeSection(self):
        messageBox = QMessageBox(self)
        userReply = messageBox.question(self, "Are you sure?",
                                        "Do you want to remove this section?",
                                        QMessageBox.Yes | QMessageBox.No)
        if userReply == QMessageBox.Yes:
            sender = self.sender()
            self.layout.removeWidget(sender)
            self.sectionWidgets.remove(sender)
            sender.setVisible(False)

            self.widgetHeight -= 80
            self.containerWidget.resize(460, self.widgetHeight)

    def getNumberOfSections(self):
        return len(self.sectionWidgets)

    def getSections(self):
        return self.sectionWidgets

    def getSectionsData(self):
        subsectionsData = list()
        for subsection in self.sectionWidgets:
            subsectionsData.append(subsection.getSectionData())
        return subsectionsData
class SectionsContainerWidget(QWidget):
    def __init__(self, parent=None, isLinacSection=True, sectionClass=None):
        QWidget.__init__(self, parent)
        self.isLinacSection = isLinacSection
        self.sectionClass = sectionClass
        self.setParent(parent)
        self.sectionWidgets = list()
        self.setMinimumWidth(460)
        self.setMinimumHeight(600)
        self.sumSize = 0

        self.setupLayout()
        self.setupScrollArea()
        self.addSectionButton = QPushButton(self.containerWidget)
        self.addSectionButton.setText("Add new section")
        self.layout.addWidget(self.addSectionButton)

        self.connect(self.addSectionButton, QtCore.SIGNAL("clicked()"), self.addNewSection)

    def setupLayout(self):
        self.containerWidget = QWidget(self)
        self.widgetHeight = 120
        self.containerWidget.setGeometry(QRect(0,0,460,self.widgetHeight))

        self.layout = QVBoxLayout()
        self.containerWidget.setLayout(self.layout)

    def setupScrollArea(self):
        self.scrollArea = QScrollArea(self)
        self.scrollArea.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded)
        self.scrollArea.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
        self.scrollArea.setMaximumWidth(460)
        self.scrollArea.setMinimumHeight(600)
        self.scrollArea.setWidgetResizable(False)
        self.scrollArea.setWidget(self.containerWidget)

    def addNewSection(self):
        newSection = self.sectionClass(self.containerWidget)
        widgetPosition = len(self.sectionWidgets)
        self.layout.insertWidget(widgetPosition, newSection)
        self.sectionWidgets.append(newSection)
        self.setDefaultValues(newSection)

        self.widgetHeight += 80
        self.containerWidget.resize(460,self.widgetHeight)

        self.connect(newSection, QtCore.SIGNAL("remove()"), self.removeSection)
        self.connect(newSection, QtCore.SIGNAL("sizeValueChanged(QWidget*)"), self.updateSumOfSize)

    def setDefaultValues(self, section):
        pass
        # section.colorLabel.setColor(SettingsCloud.getParameter("subsectionColor"))
        # self.setSectionSize(section)

    def setSectionSize(self, section):
        pass
    # def setSubsectionSize(self, section):
    #     if self.isLinacSection:
    #         defaultSize = SettingsCloud.getParameter("linacSubsectionSize")
    #     else:
    #         defaultSize = SettingsCloud.getParameter("ringSubsectionSize")
    #     section.sizeEdit.setValue(defaultSize)
    #     self.updateSumOfSize(section)

    def updateSumOfSize(self, sectionWidget):
        self.sumSize = 0
        for section in self.sectionWidgets:
            self.sumSize += section.getSize()
        if self.sumSize > 100:
            diff = self.sumSize - 100.0
            actualSize = sectionWidget.getSize()
            sectionWidget.setSize(actualSize - diff)

    def removeSection(self):
        messageBox = QMessageBox(self)
        userReply = messageBox.question(self, "Are you sure?", "Do you want to remove this section?",
                                        QMessageBox.Yes|QMessageBox.No)
        if userReply == QMessageBox.Yes:
            sender = self.sender()
            self.layout.removeWidget(sender)
            self.sectionWidgets.remove(sender)
            sender.setVisible(False)

            self.widgetHeight -= 80
            self.containerWidget.resize(460,self.widgetHeight)

    def getNumberOfSections(self):
        return len(self.sectionWidgets)

    def getSections(self):
        return self.sectionWidgets

    def getSectionsData(self):
        subsectionsData = list()
        for subsection in self.sectionWidgets:
            subsectionsData.append(subsection.getSectionData())
        return subsectionsData
class XPopupWidget(QWidget):
    """ """
    Direction = enum('North', 'South', 'East', 'West')
    Mode      = enum('Popup', 'Dialog', 'ToolTip')
    Anchor    = enum('TopLeft',
                     'TopCenter',
                     'TopRight',
                     'LeftTop',
                     'LeftCenter',
                     'LeftBottom',
                     'RightTop',
                     'RightCenter',
                     'RightBottom',
                     'BottomLeft',
                     'BottomCenter',
                     'BottomRight')
    
    aboutToShow     = qt.Signal()
    accepted        = qt.Signal()
    closed          = qt.Signal()
    rejected        = qt.Signal()
    resetRequested  = qt.Signal()
    shown           = qt.Signal()
    buttonClicked   = qt.Signal(QAbstractButton)
    
    def __init__(self, parent=None, buttons=None):
        super(XPopupWidget, self).__init__(parent)
        
        # define custom properties
        self._anchor                = XPopupWidget.Anchor.TopCenter
        self._autoCalculateAnchor   = False
        self._autoCloseOnAccept     = True
        self._autoCloseOnReject     = True
        self._autoCloseOnFocusOut   = False
        self._autoDefault           = True
        self._first                 = True
        self._animated              = False
        self._currentMode           = None
        self._positionLinkedTo      = []
        
        # define controls
        self._resizable     = True
        self._popupPadding  = 10
        self._titleBarVisible = True
        self._buttonBoxVisible = True
        self._dialogButton  = QToolButton(self)
        self._closeButton   = QToolButton(self)
        self._scrollArea    = QScrollArea(self)
        self._sizeGrip      = QSizeGrip(self)
        self._sizeGrip.setFixedWidth(12)
        self._sizeGrip.setFixedHeight(12)
        
        self._leftSizeGrip  = QSizeGrip(self)
        self._leftSizeGrip.setFixedWidth(12)
        self._leftSizeGrip.setFixedHeight(12)
        
        if buttons is None:
            buttons = QDialogButtonBox.NoButton
        
        self._buttonBox     = QDialogButtonBox(buttons, Qt.Horizontal, self)
        self._buttonBox.setContentsMargins(3, 0, 3, 9)
        
        self._scrollArea.setWidgetResizable(True)
        self._scrollArea.setFrameShape(QScrollArea.NoFrame)
        self._scrollArea.setSizePolicy(QSizePolicy.Expanding,
                                       QSizePolicy.Expanding)
        
        palette = self.palette()
        self._scrollArea.setPalette(palette)
        
        self._dialogButton.setToolTip('Popout to Dialog')
        self._closeButton.setToolTip('Close Popup')
        
        for btn in (self._dialogButton, self._closeButton):
            btn.setAutoRaise(True)
            btn.setIconSize(QSize(14, 14))
            btn.setMaximumSize(16, 16)
        
        # setup the icons
        icon = QIcon(projexui.resources.find('img/dialog.png'))
        self._dialogButton.setIcon(icon)
        
        icon = QIcon(projexui.resources.find('img/close.png'))
        self._closeButton.setIcon(icon)
        
        # define the ui
        hlayout = QHBoxLayout()
        hlayout.setSpacing(0)
        hlayout.addStretch(1)
        hlayout.addWidget(self._dialogButton)
        hlayout.addWidget(self._closeButton)
        hlayout.setContentsMargins(0, 0, 0, 0)
        
        hlayout2 = QHBoxLayout()
        hlayout2.addWidget(self._buttonBox)
        hlayout2.setContentsMargins(0, 0, 3, 0)
        
        vlayout = QVBoxLayout()
        vlayout.addLayout(hlayout)
        vlayout.addWidget(self._scrollArea)
        vlayout.addLayout(hlayout2)
        vlayout.setContentsMargins(3, 2, 3, 2)
        vlayout.setSpacing(0)
        
        self.setLayout(vlayout)
        self.setPositionLinkedTo(parent)
        
        # set default properties
        self.setAutoFillBackground(True)
        self.setBackgroundRole(QPalette.Button)
        self.setWindowTitle('Popup')
        self.setFocusPolicy(Qt.StrongFocus)
        self.setCurrentMode(XPopupWidget.Mode.Popup)
        
        # create connections
        self._dialogButton.clicked.connect(self.setDialogMode)
        self._closeButton.clicked.connect(self.reject)
        self._buttonBox.accepted.connect(self.accept)
        self._buttonBox.rejected.connect(self.reject)
        self._buttonBox.clicked.connect(self.handleButtonClick)
    
    def addButton(self, button, role=QDialogButtonBox.ActionRole):
        """
        Adds a custom button to the button box for this popup widget.
        
        :param      button | <QAbstractButton> || <str>
        
        :return     <button> || None (based on if a button or string was given)
        """
        return self._buttonBox.addButton(button, role)
    
    def adjustContentsMargins( self ):
        """
        Adjusts the contents for this widget based on the anchor and \
        mode.
        """
        anchor = self.anchor()
        mode   = self.currentMode()
        
        # margins for a dialog
        if ( mode == XPopupWidget.Mode.Dialog ):
            self.setContentsMargins(0, 0, 0, 0)
        
        # margins for a top anchor point
        elif ( anchor & (XPopupWidget.Anchor.TopLeft |
                         XPopupWidget.Anchor.TopCenter |
                         XPopupWidget.Anchor.TopRight) ):
            self.setContentsMargins(0, self.popupPadding() + 5, 0, 0)
        
        # margins for a bottom anchor point
        elif ( anchor & (XPopupWidget.Anchor.BottomLeft |
                         XPopupWidget.Anchor.BottomCenter |
                         XPopupWidget.Anchor.BottomRight) ):
            self.setContentsMargins(0, 0, 0, self.popupPadding())
        
        # margins for a left anchor point
        elif ( anchor & (XPopupWidget.Anchor.LeftTop |
                         XPopupWidget.Anchor.LeftCenter |
                         XPopupWidget.Anchor.LeftBottom) ):
            self.setContentsMargins(self.popupPadding(), 0, 0, 0)
        
        # margins for a right anchor point
        else:
            self.setContentsMargins(0, 0, self.popupPadding(), 0)
        
        self.adjustMask()
    
    def adjustMask(self):
        """
        Updates the alpha mask for this popup widget.
        """
        if self.currentMode() == XPopupWidget.Mode.Dialog:
            self.clearMask()
            return
        
        path = self.borderPath()
        bitmap = QBitmap(self.width(), self.height())
        bitmap.fill(QColor('white'))
        
        painter = QPainter()
        painter.begin(bitmap)
        painter.setRenderHint(QPainter.Antialiasing)
        pen = QPen(QColor('black'))
        pen.setWidthF(0.75)
        painter.setPen(pen)
        painter.setBrush(QColor('black'))
        painter.drawPath(path)
        painter.end()
        
        self.setMask(bitmap)
    
    def adjustSize(self):
        """
        Adjusts the size of this popup to best fit the new widget size.
        """
        widget = self.centralWidget()
        if widget is None:
            super(XPopupWidget, self).adjustSize()
            return
        
        widget.adjustSize()
        hint = widget.minimumSizeHint()
        size = widget.minimumSize()
        
        width  = max(size.width(),  hint.width())
        height = max(size.height(), hint.height())
        
        width += 20
        height += 20
        
        if self._buttonBoxVisible:
            height += self.buttonBox().height() + 10
            
        if self._titleBarVisible:
            height += max(self._dialogButton.height(),
                          self._closeButton.height()) + 10
        
        curr_w = self.width()
        curr_h = self.height()
        
        # determine if we need to move based on our anchor
        anchor = self.anchor()
        if anchor & (self.Anchor.LeftBottom | self.Anchor.RightBottom | \
                       self.Anchor.BottomLeft | self.Anchor.BottomCenter | \
                       self.Anchor.BottomRight):
            delta_y = height - curr_h
        
        elif anchor & (self.Anchor.LeftCenter | self.Anchor.RightCenter):
            delta_y = (height - curr_h) / 2
        
        else:
            delta_y = 0
        
        if anchor & (self.Anchor.RightTop | self.Anchor.RightCenter | \
                       self.Anchor.RightTop | self.Anchor.TopRight):
            delta_x = width - curr_w
        
        elif anchor & (self.Anchor.TopCenter | self.Anchor.BottomCenter):
            delta_x = (width - curr_w) / 2
        
        else:
            delta_x = 0
        
        self.setMinimumSize(width, height)
        self.resize(width, height)
        
        pos = self.pos()
        pos.setX(pos.x() - delta_x)
        pos.setY(pos.y() - delta_y)
        
        self.move(pos)
    
    @qt.Slot()
    def accept(self):
        """
        Emits the accepted signal and closes the popup.
        """
        if not self.signalsBlocked():
            self.accepted.emit()
        
        if self.autoCloseOnAccept():
            self.close()
    
    def anchor( self ):
        """
        Returns the anchor point for this popup widget.
        
        :return     <XPopupWidget.Anchor>
        """
        return self._anchor
    
    def autoCalculateAnchor( self ):
        """
        Returns whether or not this popup should calculate the anchor point
        on popup based on the parent widget and the popup point.
        
        :return     <bool>
        """
        return self._autoCalculateAnchor
    
    def autoCloseOnAccept( self ):
        """
        Returns whether or not this popup widget manages its own close on accept
        behavior.
        
        :return     <bool>
        """
        return self._autoCloseOnAccept
    
    def autoCloseOnReject( self ):
        """
        Returns whether or not this popup widget manages its own close on reject
        behavior.
        
        :return     <bool>
        """
        return self._autoCloseOnReject
    
    def autoCloseOnFocusOut(self):
        """
        Returns whether or not this popup widget should auto-close when the user
        clicks off the view.
        
        :return     <bool>
        """
        return self._autoCloseOnFocusOut
    
    def autoDefault(self):
        """
        Returns whether or not clicking enter should default to the accept key.
        
        :return     <bool>
        """
        return self._autoDefault
    
    def borderPath(self):
        """
        Returns the border path that will be drawn for this widget.
        
        :return     <QPainterPath>
        """
        
        path = QPainterPath()
        
        x = 1
        y = 1
        w = self.width() - 2
        h = self.height() - 2
        pad = self.popupPadding()
        anchor = self.anchor()
        
        # create a path for a top-center based popup
        if anchor == XPopupWidget.Anchor.TopCenter:
            path.moveTo(x, y + pad)
            path.lineTo(x + ((w/2) - pad), y + pad)
            path.lineTo(x + (w/2), y)
            path.lineTo(x + ((w/2) + pad), y + pad)
            path.lineTo(x + w, y + pad)
            path.lineTo(x + w, y + h)
            path.lineTo(x, y + h)
            path.lineTo(x, y + pad)
        
        # create a path for a top-left based popup
        elif anchor == XPopupWidget.Anchor.TopLeft:
            path.moveTo(x, y + pad)
            path.lineTo(x + pad, y)
            path.lineTo(x + 2 * pad, y + pad)
            path.lineTo(x + w, y + pad)
            path.lineTo(x + w, y + h)
            path.lineTo(x, y + h)
            path.lineTo(x, y + pad)
        
        # create a path for a top-right based popup
        elif anchor == XPopupWidget.Anchor.TopRight:
            path.moveTo(x, y + pad)
            path.lineTo(x + w - 2 * pad, y + pad)
            path.lineTo(x + w - pad, y)
            path.lineTo(x + w, y + pad)
            path.lineTo(x + w, y + h)
            path.lineTo(x, y + h)
            path.lineTo(x, y + pad)
        
        # create a path for a bottom-left based popup
        elif anchor == XPopupWidget.Anchor.BottomLeft:
            path.moveTo(x, y)
            path.lineTo(x + w, y)
            path.lineTo(x + w, y + h - pad)
            path.lineTo(x + 2 * pad, y + h - pad)
            path.lineTo(x + pad, y + h)
            path.lineTo(x, y + h - pad)
            path.lineTo(x, y)
        
        # create a path for a south based popup
        elif anchor == XPopupWidget.Anchor.BottomCenter:
            path.moveTo(x, y)
            path.lineTo(x + w, y)
            path.lineTo(x + w, y + h - pad)
            path.lineTo(x + ((w/2) + pad), y + h - pad)
            path.lineTo(x + (w/2), y + h)
            path.lineTo(x + ((w/2) - pad), y + h - pad)
            path.lineTo(x, y + h - pad)
            path.lineTo(x, y)
        
        # create a path for a bottom-right based popup
        elif anchor == XPopupWidget.Anchor.BottomRight:
            path.moveTo(x, y)
            path.lineTo(x + w, y)
            path.lineTo(x + w, y + h - pad)
            path.lineTo(x + w - pad, y + h)
            path.lineTo(x + w - 2 * pad, y + h - pad)
            path.lineTo(x, y + h - pad)
            path.lineTo(x, y)
        
        # create a path for a right-top based popup
        elif anchor == XPopupWidget.Anchor.RightTop:
            path.moveTo(x, y)
            path.lineTo(x + w - pad, y)
            path.lineTo(x + w, y + pad)
            path.lineTo(x + w - pad, y + 2 * pad)
            path.lineTo(x + w - pad, y + h)
            path.lineTo(x, y + h)
            path.lineTo(x, y)
        
        # create a path for a right-center based popup
        elif anchor == XPopupWidget.Anchor.RightCenter:
            path.moveTo(x, y)
            path.lineTo(x + w - pad, y)
            path.lineTo(x + w - pad, y + ((h/2) - pad))
            path.lineTo(x + w, y + (h/2))
            path.lineTo(x + w - pad, y + ((h/2) + pad))
            path.lineTo(x + w - pad, y + h)
            path.lineTo(x, y + h)
            path.lineTo(x, y)
        
        # create a path for a right-bottom based popup
        elif anchor == XPopupWidget.Anchor.RightBottom:
            path.moveTo(x, y)
            path.lineTo(x + w - pad, y)
            path.lineTo(x + w - pad, y + h - 2 * pad)
            path.lineTo(x + w, y + h - pad)
            path.lineTo(x + w - pad, y + h)
            path.lineTo(x, y + h)
            path.lineTo(x, y)
        
        # create a path for a left-top based popup
        elif anchor == XPopupWidget.Anchor.LeftTop:
            path.moveTo(x + pad, y)
            path.lineTo(x + w, y)
            path.lineTo(x + w, y + h)
            path.lineTo(x + pad, y + h)
            path.lineTo(x + pad, y + 2 * pad)
            path.lineTo(x, y + pad)
            path.lineTo(x + pad, y)
        
        # create a path for an left-center based popup
        elif anchor == XPopupWidget.Anchor.LeftCenter:
            path.moveTo(x + pad, y)
            path.lineTo(x + w, y)
            path.lineTo(x + w, y + h)
            path.lineTo(x + pad, y + h)
            path.lineTo(x + pad, y + ((h/2) + pad))
            path.lineTo(x, y + (h/2))
            path.lineTo(x + pad, y + ((h/2) - pad))
            path.lineTo(x + pad, y)
        
        # create a path for a left-bottom based popup
        elif anchor == XPopupWidget.Anchor.LeftBottom:
            path.moveTo(x + pad, y)
            path.lineTo(x + w, y)
            path.lineTo(x + w, y + h)
            path.lineTo(x + pad, y + h)
            path.lineTo(x, y + h - pad)
            path.lineTo(x + pad, y + h - 2 * pad)
            path.lineTo(x + pad, y)
        
        return path
    
    def buttonBox( self ):
        """
        Returns the button box that is used to control this popup widget.
        
        :return     <QDialogButtonBox>
        """
        return self._buttonBox
    
    def centralWidget( self ):
        """
        Returns the central widget that is being used by this popup.
        
        :return     <QWidget>
        """
        return self._scrollArea.widget()
    
    def close(self):
        """
        Closes the popup widget and central widget.
        """
        widget = self.centralWidget()
        if widget and not widget.close():
            return
            
        super(XPopupWidget, self).close()
    
    def closeEvent(self, event):
        widget = self.centralWidget()
        if widget and not widget.close() and \
           self.currentMode() != XPopupWidget.Mode.ToolTip:
            event.ignore()
        else:
            super(XPopupWidget, self).closeEvent(event)
        
        self.closed.emit()
    
    def currentMode( self ):
        """
        Returns the current mode for this widget.
        
        :return     <XPopupWidget.Mode>
        """
        return self._currentMode
    
    @deprecatedmethod('XPopupWidget', 
                      'Direction is no longer used, use anchor instead')
    def direction( self ):
        """
        Returns the current direction parameter for this widget.
        
        :return     <XPopupWidget.Direction>
        """
        anchor = self.anchor()
        if ( anchor & (XPopupWidget.Anchor.TopLeft |
                       XPopupWidget.Anchor.TopCenter |
                       XPopupWidget.Anchor.TopRight) ):
            return XPopupWidget.Direction.North
        
        elif ( anchor & (XPopupWidget.Anchor.BottomLeft |
                         XPopupWidget.Anchor.BottomCenter |
                         XPopupWidget.Anchor.BottomRight) ):
            return XPopupWidget.Direction.South
        
        elif ( anchor & (XPopupWidget.Anchor.LeftTop |
                         XPopupWidget.Anchor.LeftCenter |
                         XPopupWidget.Anchor.LeftBottom) ):
            return XPopupWidget.Direction.East
        
        else:
            return XPopupWidget.Direction.West
    
    def eventFilter(self, object, event):
        """
        Processes when the window is moving to update the position for the
        popup if in popup mode.
        
        :param      object | <QObject>
                    event  | <QEvent>
        """
        links = self.positionLinkedTo()
        is_dialog = self.currentMode() == self.Mode.Dialog
        if object not in links:
            return False
        
        if event.type() == event.Close:
            self.close()
            return False
        
        if event.type() == event.Hide and not is_dialog:
            self.hide()
            return False
        
        if event.type() == event.Move and not is_dialog:
            deltaPos = event.pos() - event.oldPos()
            self.move(self.pos() + deltaPos)
            return False
        
        if self.currentMode() != self.Mode.ToolTip:
            return False
        
        if event.type() == event.Leave:
            pos = object.mapFromGlobal(QCursor.pos())
            if (not object.rect().contains(pos)):
                self.close()
                event.accept()
                return True
        
        if event.type() in (event.MouseButtonPress, event.MouseButtonDblClick):
            self.close()
            event.accept()
            return True
        
        return False
    
    @qt.Slot(QAbstractButton)
    def handleButtonClick(self, button):
        """
        Handles the button click for this widget.  If the Reset button was
        clicked, then the resetRequested signal will be emitted.  All buttons
        will emit the buttonClicked signal.
        
        :param      button | <QAbstractButton>
        """
        if ( self.signalsBlocked() ):
            return
        
        if ( button == self._buttonBox.button(QDialogButtonBox.Reset) ):
            self.resetRequested.emit()
        
        self.buttonClicked.emit(button)
    
    def isAnimated(self):
        """
        Returns whether or not the popup widget should animate its opacity
        when it is shown.
        
        :return     <bool>
        """
        return self._animated
    
    def isResizable(self):
        """
        Returns if this popup is resizable or not.
        
        :return     <bool>
        """
        return self._resizable
    
    def keyPressEvent( self, event ):
        """
        Looks for the Esc key to close the popup.
        
        :param      event | <QKeyEvent>
        """
        if ( event.key() == Qt.Key_Escape ):
            self.reject()
            event.accept()
            return
        
        elif ( event.key() in (Qt.Key_Return, Qt.Key_Enter) ):
            if self._autoDefault:
                self.accept()
                event.accept()
            return
        
        super(XPopupWidget, self).keyPressEvent(event)
    
    def mapAnchorFrom( self, widget, globalPos ):
        """
        Returns the anchor point that best fits within the given widget from
        the inputed global position.
        
        :param      widget      | <QWidget>
                    globalPos   | <QPoint>
        
        :return     <XPopupWidget.Anchor>
        """
        localPos = widget.mapFromGlobal(globalPos)
        
        x = localPos.x()
        y = localPos.y()
        w = widget.width()
        h = widget.height()
        
        cw = self.width() / 2
        ch = self.height() / 2
        
        # by default, try to do a center point, so make sure the center point
        # is at least 1/2 the width longer from each edge
        if x < cw and h - y < ch:
            return XPopupWidget.Anchor.BottomLeft
        elif x < cw:
            return XPopupWidget.Anchor.TopLeft
        elif w - x < cw and h - y < ch:
            return XPopupWidget.Anchor.BottomRight
        elif w - x < cw:
            return XPopupWidget.Anchor.TopRight
        elif h - y < ch:
            return XPopupWidget.Anchor.BottomCenter
        else:
            return XPopupWidget.Anchor.TopCenter
    
    def popup(self, pos=None):
        """
        Pops up this widget at the inputed position.  The inputed point should \
        be in global space.
        
        :param      pos | <QPoint>
        
        :return     <bool> success
        """
        if self._first and self.centralWidget() is not None:
            self.adjustSize()
            self._first = False
        
        if not self.signalsBlocked():
            self.aboutToShow.emit()
        
        if not pos:
            pos = QCursor.pos()
        
        if self.currentMode() == XPopupWidget.Mode.Dialog and \
             self.isVisible():
            return False
        
        elif self.currentMode() == XPopupWidget.Mode.Dialog:
            self.setPopupMode()
        
        # auto-calculate the point
        if self.autoCalculateAnchor():
            self.setAnchor(self.mapAnchorFrom( self.parent(), pos ))
        
        pad = self.popupPadding()
        
        # determine where to move based on the anchor
        anchor = self.anchor()
        
        # MODIFY X POSITION
        # align x-left
        if ( anchor & (XPopupWidget.Anchor.TopLeft |
                       XPopupWidget.Anchor.BottomLeft) ):
            pos.setX(pos.x() - pad)
        
        # align x-center
        elif ( anchor & (XPopupWidget.Anchor.TopCenter |
                         XPopupWidget.Anchor.BottomCenter) ):
            pos.setX(pos.x() - self.width() / 2)
        
        # align x-right
        elif ( anchor & (XPopupWidget.Anchor.TopRight |
                         XPopupWidget.Anchor.BottomRight) ):
            pos.setX(pos.x() - self.width() + pad)
        
        # align x-padded
        elif ( anchor & (XPopupWidget.Anchor.RightTop |
                         XPopupWidget.Anchor.RightCenter |
                         XPopupWidget.Anchor.RightBottom) ):
            pos.setX(pos.x() - self.width())
        
        # MODIFY Y POSITION
        # align y-top
        if ( anchor & (XPopupWidget.Anchor.LeftTop |
                       XPopupWidget.Anchor.RightTop) ):
            pos.setY(pos.y() - pad)
        
        # align y-center
        elif ( anchor & (XPopupWidget.Anchor.LeftCenter |
                         XPopupWidget.Anchor.RightCenter) ):
            pos.setY(pos.y() - self.height() / 2)
        
        # align y-bottom
        elif ( anchor & (XPopupWidget.Anchor.LeftBottom |
                         XPopupWidget.Anchor.RightBottom) ):
            pos.setY(pos.y() - self.height() + pad)
        
        # align y-padded
        elif ( anchor & (XPopupWidget.Anchor.BottomLeft |
                         XPopupWidget.Anchor.BottomCenter |
                         XPopupWidget.Anchor.BottomRight) ):
            pos.setY(pos.y() - self.height())
        
        self.adjustMask()
        self.move(pos)
        self.update()
        self.setUpdatesEnabled(True)
        
        if self.isAnimated():
            anim = QPropertyAnimation(self, 'windowOpacity')
            anim.setParent(self)
            anim.setStartValue(0.0)
            anim.setEndValue(self.windowOpacity())
            anim.setDuration(500)
            anim.finished.connect(anim.deleteLater)
            self.setWindowOpacity(0.0)
        else:
            anim = None
            
        
        self.show()
        
        if self.currentMode() != XPopupWidget.Mode.ToolTip:
            self.activateWindow()
            
            widget = self.centralWidget()
            if widget:
                self.centralWidget().setFocus()
            
        
        if anim:
            anim.start()
        
        if not self.signalsBlocked():
            self.shown.emit()
        
        return True
        
    def paintEvent(self, event):
        """
        Overloads the paint event to handle painting pointers for the popup \
        mode.
        
        :param      event | <QPaintEvent>
        """
        # use the base technique for the dialog mode
        if self.currentMode() == XPopupWidget.Mode.Dialog:
            super(XPopupWidget, self).paintEvent(event)
            return
        
        # setup the coloring options
        palette = self.palette()
        
        painter = QPainter()
        painter.begin(self)
        
        pen = QPen(palette.color(palette.Window).darker(130))
        pen.setWidthF(1.75)
        painter.setPen(pen)
        painter.setRenderHint(painter.Antialiasing)
        painter.setBrush(palette.color(palette.Window))
        painter.drawPath(self.borderPath())
        painter.end()
    
    def popupPadding(self):
        """
        Returns the amount of pixels to pad the popup arrow for this widget.
        
        :return     <int>
        """
        return self._popupPadding
    
    def positionLinkedTo(self):
        """
        Returns the widget that this popup is linked to for positional changes.
        
        :return     [<QWidget>, ..]
        """
        return self._positionLinkedTo
    
    @qt.Slot()
    def reject(self):
        """
        Emits the accepted signal and closes the popup.
        """
        if not self.signalsBlocked():
            self.rejected.emit()
        
        if self.autoCloseOnReject():
            self.close()
        
    def resizeEvent(self, event):
        """
        Resizes this widget and updates the mask.
        
        :param      event | <QResizeEvent>
        """
        self.setUpdatesEnabled(False)
        super(XPopupWidget, self).resizeEvent(event)
        
        self.adjustMask()
        self.setUpdatesEnabled(True)
        
        x = self.width() - self._sizeGrip.width()
        y = self.height() - self._sizeGrip.height()
        
        self._leftSizeGrip.move(0, y)
        self._sizeGrip.move(x, y)
    
    def scrollArea(self):
        """
        Returns the scroll area widget for this popup.
        
        :return     <QScrollArea>
        """
        return self._scrollArea
    
    def setAnimated(self, state):
        """
        Sets whether or not the popup widget should animate its opacity
        when it is shown.
        
        :param      state | <bool>
        """
        self._animated = state
        self.setAttribute(Qt.WA_TranslucentBackground, state)
    
    def setAutoCloseOnAccept( self, state ):
        """
        Sets whether or not the popup handles closing for accepting states.
        
        :param      state | <bool>
        """
        self._autoCloseOnAccept = state
    
    def setAutoCloseOnReject( self, state ):
        """
        Sets whether or not the popup handles closing for rejecting states.
        
        :param      state | <bool>
        """
        self._autoCloseOnReject = state
    
    def setAutoDefault(self, state):
        """
        Sets whether or not the buttons should respond to defaulting options
        when the user is interacting with it.
        
        :param      state | <bool>
        """
        self._autoDefault = state
        for button in self.buttonBox().buttons():
            button.setAutoDefault(state)
            button.setDefault(state)
    
    def setAnchor( self, anchor ):
        """
        Sets the anchor position for this popup widget to the inputed point.
        
        :param      anchor | <XPopupWidget.Anchor>
        """
        self._anchor = anchor
        self.adjustContentsMargins()
    
    def setAutoCalculateAnchor( self, state ):
        """
        Sets whether or not this widget should auto-calculate the anchor point
        based on the parent position when the popup is triggered.
        
        :param      state | <bool>
        """
        self._autoCalculateAnchor = state
    
    def setAutoCloseOnFocusOut(self, state):
        """
        Sets whether or not this popup widget should auto-close when the user
        clicks off the view.
        
        :param     state | <bool>
        """
        self._autoCloseOnFocusOut = state
        self.updateModeSettings()
    
    def setCentralWidget( self, widget ):
        """
        Sets the central widget that will be used by this popup.
        
        :param      widget | <QWidget> || None
        """
        self._scrollArea.takeWidget()
        self._scrollArea.setWidget(widget)
        
        self.adjustSize()
    
    def setCurrentMode( self, mode ):
        """
        Sets the current mode for this dialog to the inputed mode.
        
        :param      mode | <XPopupWidget.Mode>
        """
        if ( self._currentMode == mode ):
            return
        
        self._currentMode = mode
        self.updateModeSettings()
    
    @qt.Slot()
    def setDialogMode(self):
        """
        Sets the current mode value to Dialog.
        """
        self.setCurrentMode(XPopupWidget.Mode.Dialog)
    
    @deprecatedmethod('XPopupWidget',
                      'Direction is no longer used, use setAnchor instead')
    def setDirection( self, direction ):
        """
        Sets the direction for this widget to the inputed direction.
        
        :param      direction | <XPopupWidget.Direction>
        """
        if ( direction == XPopupWidget.Direction.North ):
            self.setAnchor(XPopupWidget.Anchor.TopCenter)
        
        elif ( direction == XPopupWidget.Direction.South ):
            self.setAnchor(XPopupWidget.Anchor.BottomCenter)
        
        elif ( direction == XPopupWidget.Direction.East ):
            self.setAnchor(XPopupWidget.Anchor.LeftCenter)
        
        else:
            self.setAnchor(XPopupWidget.Anchor.RightCenter)
    
    def setPalette(self, palette):
        """
        Sets the palette for this widget and the scroll area.
        
        :param      palette | <QPalette>
        """
        super(XPopupWidget, self).setPalette(palette)
        self._scrollArea.setPalette(palette)
    
    def setPopupMode( self ):
        """
        Sets the current mode value to Popup.
        """
        self.setCurrentMode(XPopupWidget.Mode.Popup)
    
    def setPopupPadding( self, padding ):
        """
        Sets the amount to pad the popup area when displaying this widget.
        
        :param      padding | <int>
        """
        self._popupPadding = padding
        self.adjustContentsMargins()
    
    def setPositionLinkedTo(self, widgets):
        """
        Sets the widget that this popup will be linked to for positional
        changes.
        
        :param      widgets | <QWidget> || [<QWidget>, ..]
        """
        if type(widgets) in (list, set, tuple):
            new_widgets = list(widgets)
        else:
            new_widgets = []
            widget = widgets
            while widget:
                widget.installEventFilter(self)
                new_widgets.append(widget)
                widget = widget.parent()
        
        self._positionLinkedTo = new_widgets
    
    def setResizable( self, state ):
        self._resizable = state
        self._sizeGrip.setVisible(state)
        self._leftSizeGrip.setVisible(state)
    
    def setShowButtonBox(self, state):
        self._buttonBoxVisible = state
        self.buttonBox().setVisible(state)
    
    def setShowTitleBar(self, state):
        self._titleBarVisible = state
        self._dialogButton.setVisible(state)
        self._closeButton.setVisible(state)
    
    def setToolTipMode(self):
        """
        Sets the mode for this popup widget to ToolTip
        """
        self.setCurrentMode(XPopupWidget.Mode.ToolTip)
    
    def setVisible(self, state):
        super(XPopupWidget, self).setVisible(state)
        widget = self.centralWidget()
        if widget:
            widget.setVisible(state)
    
    def timerEvent( self, event ):
        """
        When the timer finishes, hide the tooltip popup widget.
        
        :param      event | <QEvent>
        """
        if self.currentMode() == XPopupWidget.Mode.ToolTip:
            self.killTimer(event.timerId())
            event.accept()
            self.close()
        else:
            super(XPopupWidget, self).timerEvent(event)
        
    def updateModeSettings(self):
        mode = self.currentMode()
        is_visible = self.isVisible()
        
        # display as a floating dialog
        if mode == XPopupWidget.Mode.Dialog:
            self.setWindowFlags(Qt.Dialog | Qt.Tool)
            self.setAttribute(Qt.WA_TransparentForMouseEvents, False)
            self._closeButton.setVisible(False)
            self._dialogButton.setVisible(False)
        
        # display as a user tooltip
        elif mode == XPopupWidget.Mode.ToolTip:
            flags = Qt.Popup | Qt.FramelessWindowHint
            
            self.setWindowFlags(flags)
            self.setBackgroundRole(QPalette.Window)
            self.setAttribute(Qt.WA_TransparentForMouseEvents)
            self.setShowTitleBar(False)
            self.setShowButtonBox(False)
            self.setFocusPolicy(Qt.NoFocus)
            
            # hide the scrollbars
            policy = Qt.ScrollBarAlwaysOff
            self._scrollArea.setVerticalScrollBarPolicy(policy)
            self._scrollArea.setHorizontalScrollBarPolicy(policy)
        
        # display as a popup widget
        else:
            flags = Qt.Popup | Qt.FramelessWindowHint
            
            if not self.autoCloseOnFocusOut():
                flags |= Qt.Tool
            
            self.setWindowFlags(flags)
            self._closeButton.setVisible(self._titleBarVisible)
            self._dialogButton.setVisible(self._titleBarVisible)
            self.setBackgroundRole(QPalette.Button)
        
        self.adjustContentsMargins()
        
        if ( is_visible ):
            self.show()
    
    @staticmethod
    @deprecatedmethod('XPopupWidget',
                      'This method no longer has an effect as we are not '\
                      'storing references to the tooltip.')
    def hideToolTip(key = None):
        """
        Hides any existing tooltip popup widgets.
        
        :warning    This method is deprecated!
        """
        pass
    
    @staticmethod
    def showToolTip( text,
                     point      = None,
                     anchor     = None,
                     parent     = None,
                     background = None,
                     foreground = None,
                     key        = None,
                     seconds    = 5 ):
        """
        Displays a popup widget as a tooltip bubble.
        
        :param      text        | <str>
                    point       | <QPoint> || None
                    anchor      | <XPopupWidget.Mode.Anchor> || None
                    parent      | <QWidget> || None
                    background  | <QColor> || None
                    foreground  | <QColor> || None
                    key         | <str> || None
                    seconds     | <int>
        """
        if point is None:
            point = QCursor.pos()
            
        if parent is None:
            parent = QApplication.activeWindow()
        
        if anchor is None and parent is None:
            anchor = XPopupWidget.Anchor.TopCenter
        
        # create a new tooltip widget
        widget = XPopupWidget(parent)
        widget.setToolTipMode()
        widget.setResizable(False)
        
        # create the tooltip label
        label = QLabel(text, widget)
        label.setOpenExternalLinks(True)
        label.setAlignment(Qt.AlignLeft | Qt.AlignVCenter)
        label.setMargin(3)
        label.setIndent(3)
        label.adjustSize()
    
        widget.setCentralWidget(label)
        
        # update the tip
        label.adjustSize()
        widget.adjustSize()
        
        palette = widget.palette()
        if not background:
            background = palette.color(palette.ToolTipBase)
        if not foreground:
            foreground = palette.color(palette.ToolTipText)
        
        palette.setColor(palette.Window,     QColor(background))
        palette.setColor(palette.WindowText, QColor(foreground))
        widget.setPalette(palette)
        widget.centralWidget().setPalette(palette)
        
        if anchor is None:
            widget.setAutoCalculateAnchor(True)
        else:
            widget.setAnchor(anchor)
        
        widget.setAutoCloseOnFocusOut(True)
        widget.setAttribute(Qt.WA_DeleteOnClose)
        widget.popup(point)
        widget.startTimer(1000 * seconds)
        
        return widget
class SkillWidget(TraitWidget):
	"""
	@brief Das Widget, in welchem sämtliche Fertigkeiten angeordnet sind.

	Wird bei irgendeiner Fertigkeit der Spazialisierungen-Knopf gedrückt, werden alle anderen Spezialisierungs-Knöpfe ausgeschalten.
	"""


	specialtiesActivated = Signal(bool, object)


	def __init__(self, template, character, parent=None):
		super(SkillWidget, self).__init__(template, character, parent)

		self.__layout = QVBoxLayout()
		self.setLayout( self.__layout )

		self.__scrollArea = QScrollArea()
		## Die Auflistung der Fertigkeiten soll auch unter Windows einen transparenten Hintergrund haben.
		self.__scrollArea.setObjectName("transparentWidget")
		## \todo Sollte nicht vom Betriebssystem, sondern vom verwendeten Style abhängen.
		if os.name == "nt":
			self.__scrollArea.setStyleSheet( "QWidget#transparentWidget { background: transparent; }" )
		self.__layout.addWidget( self.__scrollArea)

		self.__scrollLayout = QVBoxLayout()

		self.__scrollWidget = QWidget()
		## Die Auflistung der Fertigkeiten soll auch unter Windows einen transparenten Hintergrund haben. Indem ich den selben Namen wie zuvor vergebe, wirkt auch das Stylsheet auf dieses Widget.
		self.__scrollWidget.setObjectName("transparentWidget")
		#self.__scrollWidget.setStyleSheet( "QWidget#transparentWidget { background-color:transparent; }" )
		#scrollWidget.setMinimumSize(this.width(), 400);
		self.__scrollWidget.setLayout(self.__scrollLayout)

		typ = "Skill"

		## Eine Liste, in der alle Eigenschafts-Widgets aufgelistet werden.
		self.__traitWidgets = []

		for item in Config.CATEGORIES_MAIN:
			#Debug.debug(self._character.traits)

			# Für jede Kategorie wird ein eigener Abschnitt erzeugt.
			widgetSkillCategory = QGroupBox()
			widgetSkillCategory.setTitle(item)
			widgetSkillCategory.setFlat(True)

			layoutSkillCategory = QVBoxLayout()
			widgetSkillCategory.setLayout( layoutSkillCategory );

			self.__scrollLayout.addWidget( widgetSkillCategory )

			__list = list( self._character.traits[typ][item].items() )
			__list.sort()
			for skill in __list:
				# Anlegen des Widgets, das diese Eigenschaft repräsentiert.
				traitWidget = CharaTrait( skill[1], self )
				traitWidget.buttonText = 0
				traitWidget.setDescriptionHidden( True )
				traitWidget.enableButton(0)	# Zu Beginn sollen die Spezailisierungen nicht enabled sein.

				# Dieses Widget auch an Liste anhängen, damit ich einfacher darauf zugreifen kann.
				traitListItem = traitWidget
				self.__traitWidgets.append(traitListItem)

				# Es werden nur Fertigkeiten der richtigen Alters- und Zeit-Kategorie angezeigt.
				self.hideReasonChanged.connect(traitWidget.hideOrShowTrait)
				# Fertigkeiten haben Spezialisierungen.
				traitWidget.specialtiesClicked.connect(self.uncheckOtherButtons)
				traitWidget.specialtiesClicked.connect(self.specialtiesActivated.emit)
				## Wenn sich die Spezialisierungen ändern, sollen die veränderten Spezialisierungen auch angezeigt werden. Das wird so gelöst, als wäre der Knopf für die Spezialisierungen erneut gedrückt worden.
				#skill.specialtiesChanged.connect(self.emitSpecialtiesActivated)

				layoutSkillCategory.addWidget( traitWidget )

				self.maxTraitChanged.connect(traitWidget.setMaximum)

			# Stretch einfügen, damit die Eigenschaften besser angeordnet sind.
			self.__scrollLayout.addStretch()

		self.__scrollArea.setWidget(self.__scrollWidget)
		self.__scrollArea.setWidgetResizable(True)
		self.__scrollArea.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
		self.__scrollArea.setMinimumWidth(self.__scrollArea.viewport().minimumWidth())


	def uncheckOtherButtons( self, sw, trait ):
		"""
		Über diese Funktion werden alle anderen Spezialisierungs-Knöpfe deaktiviert, sobald einer aktiviert wird.
		"""

		#Debug.debug("Drücke {}".format(skillName))
		if sw:
			for item in self.__traitWidgets:
				if item.name != trait.name:
					item.setSpecialtyButtonChecked(False)
Beispiel #11
0
class XNavigationEdit(XLineEdit):
    """ """
    navigationChanged = Signal()
    
    __designer_icon__ = projexui.resources.find('img/ui/navigate.png')
    
    def __init__( self, parent = None ):
        super(XNavigationEdit, self).__init__( parent )
        
        # define custom properties
        self._separator             = '/'
        self._partsEditingEnabled   = True
        self._originalText          = ''
        self._scrollWidget          = QScrollArea(self)
        self._partsWidget           = QWidget(self._scrollWidget)
        self._buttonGroup           = QButtonGroup(self)
        self._scrollAmount          = 0
        self._navigationModel       = None
        
        # create the completer tree
        palette = self.palette()
        palette.setColor(palette.Base, palette.color(palette.Window))
        palette.setColor(palette.Text, palette.color(palette.WindowText))
        
        bg      = palette.color(palette.Highlight)
        abg     = bg.darker(115)
        fg      = palette.color(palette.HighlightedText)
        sbg     = 'rgb(%s, %s, %s)' % (bg.red(), bg.green(), bg.blue())
        sabg    = 'rgb(%s, %s, %s)' % (abg.red(), abg.green(), abg.blue())
        sfg     = 'rgb(%s, %s, %s)' % (fg.red(), fg.green(), fg.blue())
        style   = 'QTreeView::item:hover { '\
                  '     color: %s;'\
                  '     background: qlineargradient(x1:0,'\
                  '                                 y1:0,'\
                  '                                 x2:0,'\
                  '                                 y2:1,'\
                  '                                 stop: 0 %s,'\
                  '                                 stop: 1 %s);'\
                  '}' % (sfg, sbg, sabg)
        
        self._completerTree = QTreeView(self)
        self._completerTree.setStyleSheet(style)
        self._completerTree.header().hide()
        self._completerTree.setFrameShape(QTreeView.Box)
        self._completerTree.setFrameShadow(QTreeView.Plain)
        self._completerTree.setPalette(palette)
        self._completerTree.setEditTriggers(QTreeView.NoEditTriggers)
        self._completerTree.setWindowFlags(Qt.Popup)
        self._completerTree.installEventFilter(self)
        self._completerTree.setRootIsDecorated(False)
        self._completerTree.setItemsExpandable(False)
        
        # create the editing widget
        layout = QHBoxLayout()
        layout.setContentsMargins(0, 0, 0, 0)
        layout.setSpacing(0)
        layout.addStretch()
        
        self._scrollWidget.setFrameShape( QScrollArea.NoFrame )
        self._scrollWidget.setFocusPolicy(Qt.NoFocus)
        self._scrollWidget.setWidget(self._partsWidget)
        self._scrollWidget.setWidgetResizable(True)
        self._scrollWidget.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self._scrollWidget.setAlignment(Qt.AlignTop | Qt.AlignRight)
        self._scrollWidget.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self._scrollWidget.setContentsMargins(0, 0, 0, 0)
        self._scrollWidget.setViewportMargins(0, 0, 0, 0)
        self._scrollWidget.move(2, 2)
        
        self._partsWidget.setLayout(layout)
        self._partsWidget.setCursor(Qt.ArrowCursor)
        self._partsWidget.setAutoFillBackground(True)
        self._partsWidget.setFixedHeight(self.height() - 12)
        
        palette = self._partsWidget.palette()
        palette.setColor(palette.Background, palette.color(palette.Base))
        self._partsWidget.setPalette(palette)
        
        # create connections
        self._completerTree.clicked.connect( self.navigateToIndex )
        self._buttonGroup.buttonClicked.connect( self.handleButtonClick )
        self._scrollWidget.horizontalScrollBar().valueChanged.connect( 
                                                        self.scrollParts )
    
    def acceptEdit( self ):
        """
        Accepts the current text and rebuilds the parts widget.
        """
        
        if ( self._partsWidget.isVisible() ):
            return False
        
        use_completion = self.completer().popup().isVisible()
        completion     = self.completer().currentCompletion()
        
        self._completerTree.hide()
        self.completer().popup().hide()
        
        if ( use_completion ):
            self.setText(completion)
        else:
            self.rebuild()
            
        return True
    
    def cancelEdit( self ):
        """
        Rejects the current edit and shows the parts widget.
        """
        
        if ( self._partsWidget.isVisible() ):
            return False
            
        self._completerTree.hide()
        self.completer().popup().hide()
        
        self.setText(self._originalText)
        return True
    
    def currentItem( self ):
        """
        Returns the current navigation item from the current path.
        
        :return     <XNavigationItem> || None
        """
        model = self.navigationModel()
        if ( not model ):
            return None
        
        return model.itemByPath(self.text())
    
    def eventFilter( self, object, event ):
        """
        Filters the events for the inputed object through this edit.
        
        :param      object | <QObject>
                    event  | <QEvent>
        
        :return     <bool> | consumed
        """
        if ( event.type() == event.KeyPress ):
            if ( event.key() == Qt.Key_Escape ):
                self._completerTree.hide()
                self.completer().popup().hide()
                
                self.cancelEdit()
                
            elif ( event.key() in (Qt.Key_Return, Qt.Key_Enter) ):
                self.acceptEdit()
                return True
                
            elif ( event.key() == Qt.Key_Tab ):
                if ( self.completer().popup().isVisible() ):
                    text   = str(self.completer().currentCompletion())
                    super(XNavigationEdit, self).setText(text)
                    return True
                else:
                    self.acceptEdit()
                    return False
            
        elif ( event.type() == event.MouseButtonPress ):
            if ( not self._completerTree.rect().contains(event.pos()) ):
                self._completerTree.hide()
                self.completer().popup().hide()
                
                self.cancelEdit()
        
        return False
    
    def focusOutEvent( self, event ):
        """
        Overloads the focus out event to cancel editing when the widget loses
        focus.
        
        :param      event | <QFocusEvent>
        """
        super(XNavigationEdit, self).focusOutEvent(event)
        
        self.cancelEdit()
    
    def handleButtonClick( self, button ):
        """
        Handle the event when a user clicks on one of the part buttons.
        
        :param      button | <QToolButton>
        """
        path            = button.property('path')
        is_completer    = button.property('is_completer')
        
        # popup a completion menu
        if ( unwrapVariant(is_completer) ):
            model = self.navigationModel()
            if ( not model ):
                return
            
            sep  = self.separator()
            path = str(unwrapVariant(path))
            item = model.itemByPath(path, includeRoot = True)
            if ( not item ):
                return
            
            curr_path = str(self.text()).strip(self.separator())
            curr_path = curr_path.replace(path, '').strip(self.separator())
            
            child_name = ''
            if ( curr_path ):
                child_name = curr_path.split(self.separator())[0]
            
            index = model.indexFromItem(item)
            
            self._completerTree.move(QCursor.pos())
            self._completerTree.setRootIndex(index)
            self._completerTree.verticalScrollBar().setValue(0)
            
            if ( child_name ):
                child_item = None
                for i in range(item.rowCount()):
                    child = item.child(i)
                    if ( child.text() == child_name ):
                        child_item = child
                        break
                
                if ( child_item ):
                    child_index = model.indexFromItem(child_item)
                    self._completerTree.setCurrentIndex(child_index)
                    self._completerTree.scrollTo(child_index)
            
            self._completerTree.show()
            self._completerTree.setUpdatesEnabled(True)
        else:
            self.setText(unwrapVariant(path))
    
    def keyPressEvent( self, event ):
        """
        Overloads the key press event to listen for escape calls to cancel the
        parts editing.
        
        :param      event | <QKeyPressEvent>
        """
        if ( self.scrollWidget().isHidden() ):
            if ( event.key() == Qt.Key_Escape ):
                self.cancelEdit()
                return
                
            elif ( event.key() in (Qt.Key_Return, Qt.Key_Enter) ):
                self.acceptEdit()
                return
            
        elif ( event.key() == Qt.Key_A and 
               event.modifiers() == Qt.ControlModifier ):
            self.startEdit()
        
        super(XNavigationEdit, self).keyPressEvent(event)
    
    def mouseDoubleClickEvent( self, event ):
        """
        Overloads the system to enable editing when a user double clicks.
        
        :param      event | <QMouseEvent>
        """
        super(XNavigationEdit, self).mouseDoubleClickEvent(event)
        
        self.startEdit()
    
    def navigationModel( self ):
        """
        Returns the navigation model linked with this edit.
        
        :return     <XNavigationModel> || None
        """
        return self._navigationModel
    
    def navigateToIndex( self, index ):
        """
        Navigates to the inputed action's path.
        
        :param      action | <QAction>
        """
        self._completerTree.hide()
        item = self._navigationModel.itemFromIndex(index)
        self.setText(self._navigationModel.itemPath(item))
    
    def parts( self ):
        """
        Returns the parts that are used for this system.
        
        :return     [<str>, ..]
        """
        path = str(self.text()).strip(self.separator())
        if ( not path ):
            return []
        return path.split(self.separator())
    
    def partsWidget( self ):
        """
        Returns the widget that contains the parts system.
        
        :return     <QScrollArea>
        """
        return self._partsWidget
    
    def startEdit( self ):
        """
        Rebuilds the pathing based on the parts.
        """
        self._originalText = self.text()
        self.scrollWidget().hide()
        self.setFocus()
        self.selectAll()
    
    def rebuild( self ):
        """
        Rebuilds the parts widget with the latest text.
        """
        navitem = self.currentItem()
        if ( navitem ):
            navitem.initialize()
            
        self.setUpdatesEnabled(False)
        self.scrollWidget().show()
        self._originalText = ''
        
        partsw = self.partsWidget()
        for button in self._buttonGroup.buttons():
            self._buttonGroup.removeButton(button)
            button.close()
            button.setParent(None)
            button.deleteLater()
        
        # create the root button
        layout = partsw.layout()
        parts  = self.parts()
        
        button = QToolButton(partsw)
        button.setAutoRaise(True)
        button.setMaximumWidth(12)
        button.setArrowType(Qt.RightArrow)
        
        button.setProperty('path',          wrapVariant(''))
        button.setProperty('is_completer',  wrapVariant(True))
        last_button = button
            
        self._buttonGroup.addButton(button)
        layout.insertWidget(0, button)
        
        # check to see if we have a navigation model setup
        if ( self._navigationModel ):
            last_item = self._navigationModel.itemByPath(self.text())
            show_last =  last_item and last_item.rowCount() > 0
        else:
            show_last = False
        
        # load the navigation system
        count = len(parts)
        for i, part in enumerate(parts):
            path = self.separator().join(parts[:i+1])
            
            button = QToolButton(partsw)
            button.setAutoRaise(True)
            button.setText(part)
            
            if ( self._navigationModel ):
                item = self._navigationModel.itemByPath(path)
                if ( item ):
                    button.setIcon(item.icon())
                    button.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)
            
            button.setProperty('path',         wrapVariant(path))
            button.setProperty('is_completer', wrapVariant(False))
            
            self._buttonGroup.addButton(button)
            layout.insertWidget((i * 2) + 1, button)
            
            # determine if we should show the final button
            if ( show_last or i < (count - 1) ):
                button = QToolButton(partsw)
                button.setAutoRaise(True)
                button.setMaximumWidth(12)
                button.setArrowType(Qt.RightArrow)
                
                button.setProperty('path',          wrapVariant(path))
                button.setProperty('is_completer',  wrapVariant(True))
            
                self._buttonGroup.addButton(button)
                layout.insertWidget((i * 2) + 2, button)
                
                last_button = button
        
        if ( self.scrollWidget().width() < partsw.width() ):
            self.scrollParts(partsw.width() - self.scrollWidget().width())
            
        self.setUpdatesEnabled(True)
        self.navigationChanged.emit()
    
    def resizeEvent( self, event ):
        """
        Resizes the current widget and its parts widget.
        
        :param      event | <QResizeEvent>
        """
        super(XNavigationEdit, self).resizeEvent(event)
        
        w = self.width()
        h = self.height()
        
        self._scrollWidget.resize(w - 4, h - 4)
        
        if ( self._scrollWidget.width() < self._partsWidget.width() ):
           self.scrollParts( self._partsWidget.width() - self._scrollWidget.width() )
    
    def scrollParts( self, amount ):
        """
        Scrolls the parts to offset the scrolling amount.
        
        :param      amount | <int>
        """
        change = self._scrollAmount - amount
        self._partsWidget.scroll(change, 0)
        self._scrollAmount = amount
    
    def scrollWidget( self ):
        """
        Returns the scrolling widget.
        
        :return     <QScrollArea>
        """
        return self._scrollWidget
    
    def separator( self ):
        """
        Returns the separation character that is used for this edit.
        
        :return     <str>
        """
        return self._separator
    
    def setTopLevelItems( self, items ):
        """
        Initializes the navigation system to start with the inputed root \
        item.
        
        :param      item | <XNavigationItem>
        """
        if ( not self._navigationModel ):
            self.setNavigationModel(XNavigationModel(self))
        
        self._navigationModel.setTopLevelItems(items)
    
    def setNavigationModel( self, model ):
        """
        Sets the navigation model for this edit.
        
        :param      model | <XNavigationModel>
        """
        self._navigationModel = model
        self._completerTree.setModel(model)
        
        if ( model ):
            model.setSeparator(self.separator())
            completer = XNavigationCompleter(model, self)
            self.setCompleter(completer)
            completer.popup().installEventFilter(self)
        else:
            self.setCompleter(None)
        
        self.rebuild()
    
    def setParts( self, parts ):
        """
        Sets the path for this edit widget by providing the parts to the path.
        
        :param      parts | [<str>, ..]
        """
        self.setText(self.separator().join(map(str, parts)))
    
    def setSeparator( self, separator ):
        """
        Sets the separator to the inputed character.
        
        :param      separator | <str>
        """
        self._separator = separator
        if ( self._navigationModel ):
            self._navigationModel.setSeparator(separator)
        self.rebuild()
    
    def setText( self, text ):
        """
        Sets the text for this edit to the inputed text.
        
        :param      text | <str>
        """
        super(XNavigationEdit, self).setText(text)
        
        self.scrollWidget().show()
        if ( text == '' or self._originalText != text ):
            self.rebuild()
Beispiel #12
0
class XPopupWidget(QWidget):
    """ """
    Direction = enum('North', 'South', 'East', 'West')
    Mode = enum('Popup', 'Dialog', 'ToolTip')
    Anchor = enum('TopLeft', 'TopCenter', 'TopRight', 'LeftTop', 'LeftCenter',
                  'LeftBottom', 'RightTop', 'RightCenter', 'RightBottom',
                  'BottomLeft', 'BottomCenter', 'BottomRight')

    aboutToShow = qt.Signal()
    accepted = qt.Signal()
    closed = qt.Signal()
    rejected = qt.Signal()
    resetRequested = qt.Signal()
    shown = qt.Signal()
    buttonClicked = qt.Signal(QAbstractButton)

    def __init__(self, parent=None, buttons=None):
        super(XPopupWidget, self).__init__(parent)

        # define custom properties
        self._anchor = XPopupWidget.Anchor.TopCenter
        self._autoCalculateAnchor = False
        self._autoCloseOnAccept = True
        self._autoCloseOnReject = True
        self._autoCloseOnFocusOut = False
        self._autoDefault = True
        self._first = True
        self._animated = False
        self._currentMode = None
        self._positionLinkedTo = []

        # define controls
        self._resizable = True
        self._popupPadding = 10
        self._titleBarVisible = True
        self._buttonBoxVisible = True
        self._dialogButton = QToolButton(self)
        self._closeButton = QToolButton(self)
        self._scrollArea = QScrollArea(self)
        self._sizeGrip = QSizeGrip(self)
        self._sizeGrip.setFixedWidth(12)
        self._sizeGrip.setFixedHeight(12)

        self._leftSizeGrip = QSizeGrip(self)
        self._leftSizeGrip.setFixedWidth(12)
        self._leftSizeGrip.setFixedHeight(12)

        if buttons is None:
            buttons = QDialogButtonBox.NoButton

        self._buttonBox = QDialogButtonBox(buttons, Qt.Horizontal, self)
        self._buttonBox.setContentsMargins(3, 0, 3, 9)

        self._scrollArea.setWidgetResizable(True)
        self._scrollArea.setFrameShape(QScrollArea.NoFrame)
        self._scrollArea.setSizePolicy(QSizePolicy.Expanding,
                                       QSizePolicy.Expanding)

        palette = self.palette()
        self._scrollArea.setPalette(palette)

        self._dialogButton.setToolTip('Popout to Dialog')
        self._closeButton.setToolTip('Close Popup')

        for btn in (self._dialogButton, self._closeButton):
            btn.setAutoRaise(True)
            btn.setIconSize(QSize(14, 14))
            btn.setMaximumSize(16, 16)

        # setup the icons
        icon = QIcon(projexui.resources.find('img/dialog.png'))
        self._dialogButton.setIcon(icon)

        icon = QIcon(projexui.resources.find('img/close.png'))
        self._closeButton.setIcon(icon)

        # define the ui
        hlayout = QHBoxLayout()
        hlayout.setSpacing(0)
        hlayout.addStretch(1)
        hlayout.addWidget(self._dialogButton)
        hlayout.addWidget(self._closeButton)
        hlayout.setContentsMargins(0, 0, 0, 0)

        hlayout2 = QHBoxLayout()
        hlayout2.addWidget(self._buttonBox)
        hlayout2.setContentsMargins(0, 0, 3, 0)

        vlayout = QVBoxLayout()
        vlayout.addLayout(hlayout)
        vlayout.addWidget(self._scrollArea)
        vlayout.addLayout(hlayout2)
        vlayout.setContentsMargins(3, 2, 3, 2)
        vlayout.setSpacing(0)

        self.setLayout(vlayout)
        self.setPositionLinkedTo(parent)

        # set default properties
        self.setAutoFillBackground(True)
        self.setBackgroundRole(QPalette.Button)
        self.setWindowTitle('Popup')
        self.setFocusPolicy(Qt.StrongFocus)
        self.setCurrentMode(XPopupWidget.Mode.Popup)

        # create connections
        self._dialogButton.clicked.connect(self.setDialogMode)
        self._closeButton.clicked.connect(self.reject)
        self._buttonBox.accepted.connect(self.accept)
        self._buttonBox.rejected.connect(self.reject)
        self._buttonBox.clicked.connect(self.handleButtonClick)

    def addButton(self, button, role=QDialogButtonBox.ActionRole):
        """
        Adds a custom button to the button box for this popup widget.
        
        :param      button | <QAbstractButton> || <str>
        
        :return     <button> || None (based on if a button or string was given)
        """
        return self._buttonBox.addButton(button, role)

    def adjustContentsMargins(self):
        """
        Adjusts the contents for this widget based on the anchor and \
        mode.
        """
        anchor = self.anchor()
        mode = self.currentMode()

        # margins for a dialog
        if (mode == XPopupWidget.Mode.Dialog):
            self.setContentsMargins(0, 0, 0, 0)

        # margins for a top anchor point
        elif (anchor &
              (XPopupWidget.Anchor.TopLeft | XPopupWidget.Anchor.TopCenter
               | XPopupWidget.Anchor.TopRight)):
            self.setContentsMargins(0, self.popupPadding() + 5, 0, 0)

        # margins for a bottom anchor point
        elif (
                anchor &
            (XPopupWidget.Anchor.BottomLeft | XPopupWidget.Anchor.BottomCenter
             | XPopupWidget.Anchor.BottomRight)):
            self.setContentsMargins(0, 0, 0, self.popupPadding())

        # margins for a left anchor point
        elif (anchor &
              (XPopupWidget.Anchor.LeftTop | XPopupWidget.Anchor.LeftCenter
               | XPopupWidget.Anchor.LeftBottom)):
            self.setContentsMargins(self.popupPadding(), 0, 0, 0)

        # margins for a right anchor point
        else:
            self.setContentsMargins(0, 0, self.popupPadding(), 0)

        self.adjustMask()

    def adjustMask(self):
        """
        Updates the alpha mask for this popup widget.
        """
        if self.currentMode() == XPopupWidget.Mode.Dialog:
            self.clearMask()
            return

        path = self.borderPath()
        bitmap = QBitmap(self.width(), self.height())
        bitmap.fill(QColor('white'))

        painter = QPainter()
        painter.begin(bitmap)
        painter.setRenderHint(QPainter.Antialiasing)
        pen = QPen(QColor('black'))
        pen.setWidthF(0.75)
        painter.setPen(pen)
        painter.setBrush(QColor('black'))
        painter.drawPath(path)
        painter.end()

        self.setMask(bitmap)

    def adjustSize(self):
        """
        Adjusts the size of this popup to best fit the new widget size.
        """
        widget = self.centralWidget()
        if widget is None:
            super(XPopupWidget, self).adjustSize()
            return

        widget.adjustSize()
        hint = widget.minimumSizeHint()
        size = widget.minimumSize()

        width = max(size.width(), hint.width())
        height = max(size.height(), hint.height())

        width += 20
        height += 20

        if self._buttonBoxVisible:
            height += self.buttonBox().height() + 10

        if self._titleBarVisible:
            height += max(self._dialogButton.height(),
                          self._closeButton.height()) + 10

        curr_w = self.width()
        curr_h = self.height()

        # determine if we need to move based on our anchor
        anchor = self.anchor()
        if anchor & (self.Anchor.LeftBottom | self.Anchor.RightBottom | \
                       self.Anchor.BottomLeft | self.Anchor.BottomCenter | \
                       self.Anchor.BottomRight):
            delta_y = height - curr_h

        elif anchor & (self.Anchor.LeftCenter | self.Anchor.RightCenter):
            delta_y = (height - curr_h) / 2

        else:
            delta_y = 0

        if anchor & (self.Anchor.RightTop | self.Anchor.RightCenter | \
                       self.Anchor.RightTop | self.Anchor.TopRight):
            delta_x = width - curr_w

        elif anchor & (self.Anchor.TopCenter | self.Anchor.BottomCenter):
            delta_x = (width - curr_w) / 2

        else:
            delta_x = 0

        self.setMinimumSize(width, height)
        self.resize(width, height)

        pos = self.pos()
        pos.setX(pos.x() - delta_x)
        pos.setY(pos.y() - delta_y)

        self.move(pos)

    @qt.Slot()
    def accept(self):
        """
        Emits the accepted signal and closes the popup.
        """
        if not self.signalsBlocked():
            self.accepted.emit()

        if self.autoCloseOnAccept():
            self.close()

    def anchor(self):
        """
        Returns the anchor point for this popup widget.
        
        :return     <XPopupWidget.Anchor>
        """
        return self._anchor

    def autoCalculateAnchor(self):
        """
        Returns whether or not this popup should calculate the anchor point
        on popup based on the parent widget and the popup point.
        
        :return     <bool>
        """
        return self._autoCalculateAnchor

    def autoCloseOnAccept(self):
        """
        Returns whether or not this popup widget manages its own close on accept
        behavior.
        
        :return     <bool>
        """
        return self._autoCloseOnAccept

    def autoCloseOnReject(self):
        """
        Returns whether or not this popup widget manages its own close on reject
        behavior.
        
        :return     <bool>
        """
        return self._autoCloseOnReject

    def autoCloseOnFocusOut(self):
        """
        Returns whether or not this popup widget should auto-close when the user
        clicks off the view.
        
        :return     <bool>
        """
        return self._autoCloseOnFocusOut

    def autoDefault(self):
        """
        Returns whether or not clicking enter should default to the accept key.
        
        :return     <bool>
        """
        return self._autoDefault

    def borderPath(self):
        """
        Returns the border path that will be drawn for this widget.
        
        :return     <QPainterPath>
        """

        path = QPainterPath()

        x = 1
        y = 1
        w = self.width() - 2
        h = self.height() - 2
        pad = self.popupPadding()
        anchor = self.anchor()

        # create a path for a top-center based popup
        if anchor == XPopupWidget.Anchor.TopCenter:
            path.moveTo(x, y + pad)
            path.lineTo(x + ((w / 2) - pad), y + pad)
            path.lineTo(x + (w / 2), y)
            path.lineTo(x + ((w / 2) + pad), y + pad)
            path.lineTo(x + w, y + pad)
            path.lineTo(x + w, y + h)
            path.lineTo(x, y + h)
            path.lineTo(x, y + pad)

        # create a path for a top-left based popup
        elif anchor == XPopupWidget.Anchor.TopLeft:
            path.moveTo(x, y + pad)
            path.lineTo(x + pad, y)
            path.lineTo(x + 2 * pad, y + pad)
            path.lineTo(x + w, y + pad)
            path.lineTo(x + w, y + h)
            path.lineTo(x, y + h)
            path.lineTo(x, y + pad)

        # create a path for a top-right based popup
        elif anchor == XPopupWidget.Anchor.TopRight:
            path.moveTo(x, y + pad)
            path.lineTo(x + w - 2 * pad, y + pad)
            path.lineTo(x + w - pad, y)
            path.lineTo(x + w, y + pad)
            path.lineTo(x + w, y + h)
            path.lineTo(x, y + h)
            path.lineTo(x, y + pad)

        # create a path for a bottom-left based popup
        elif anchor == XPopupWidget.Anchor.BottomLeft:
            path.moveTo(x, y)
            path.lineTo(x + w, y)
            path.lineTo(x + w, y + h - pad)
            path.lineTo(x + 2 * pad, y + h - pad)
            path.lineTo(x + pad, y + h)
            path.lineTo(x, y + h - pad)
            path.lineTo(x, y)

        # create a path for a south based popup
        elif anchor == XPopupWidget.Anchor.BottomCenter:
            path.moveTo(x, y)
            path.lineTo(x + w, y)
            path.lineTo(x + w, y + h - pad)
            path.lineTo(x + ((w / 2) + pad), y + h - pad)
            path.lineTo(x + (w / 2), y + h)
            path.lineTo(x + ((w / 2) - pad), y + h - pad)
            path.lineTo(x, y + h - pad)
            path.lineTo(x, y)

        # create a path for a bottom-right based popup
        elif anchor == XPopupWidget.Anchor.BottomRight:
            path.moveTo(x, y)
            path.lineTo(x + w, y)
            path.lineTo(x + w, y + h - pad)
            path.lineTo(x + w - pad, y + h)
            path.lineTo(x + w - 2 * pad, y + h - pad)
            path.lineTo(x, y + h - pad)
            path.lineTo(x, y)

        # create a path for a right-top based popup
        elif anchor == XPopupWidget.Anchor.RightTop:
            path.moveTo(x, y)
            path.lineTo(x + w - pad, y)
            path.lineTo(x + w, y + pad)
            path.lineTo(x + w - pad, y + 2 * pad)
            path.lineTo(x + w - pad, y + h)
            path.lineTo(x, y + h)
            path.lineTo(x, y)

        # create a path for a right-center based popup
        elif anchor == XPopupWidget.Anchor.RightCenter:
            path.moveTo(x, y)
            path.lineTo(x + w - pad, y)
            path.lineTo(x + w - pad, y + ((h / 2) - pad))
            path.lineTo(x + w, y + (h / 2))
            path.lineTo(x + w - pad, y + ((h / 2) + pad))
            path.lineTo(x + w - pad, y + h)
            path.lineTo(x, y + h)
            path.lineTo(x, y)

        # create a path for a right-bottom based popup
        elif anchor == XPopupWidget.Anchor.RightBottom:
            path.moveTo(x, y)
            path.lineTo(x + w - pad, y)
            path.lineTo(x + w - pad, y + h - 2 * pad)
            path.lineTo(x + w, y + h - pad)
            path.lineTo(x + w - pad, y + h)
            path.lineTo(x, y + h)
            path.lineTo(x, y)

        # create a path for a left-top based popup
        elif anchor == XPopupWidget.Anchor.LeftTop:
            path.moveTo(x + pad, y)
            path.lineTo(x + w, y)
            path.lineTo(x + w, y + h)
            path.lineTo(x + pad, y + h)
            path.lineTo(x + pad, y + 2 * pad)
            path.lineTo(x, y + pad)
            path.lineTo(x + pad, y)

        # create a path for an left-center based popup
        elif anchor == XPopupWidget.Anchor.LeftCenter:
            path.moveTo(x + pad, y)
            path.lineTo(x + w, y)
            path.lineTo(x + w, y + h)
            path.lineTo(x + pad, y + h)
            path.lineTo(x + pad, y + ((h / 2) + pad))
            path.lineTo(x, y + (h / 2))
            path.lineTo(x + pad, y + ((h / 2) - pad))
            path.lineTo(x + pad, y)

        # create a path for a left-bottom based popup
        elif anchor == XPopupWidget.Anchor.LeftBottom:
            path.moveTo(x + pad, y)
            path.lineTo(x + w, y)
            path.lineTo(x + w, y + h)
            path.lineTo(x + pad, y + h)
            path.lineTo(x, y + h - pad)
            path.lineTo(x + pad, y + h - 2 * pad)
            path.lineTo(x + pad, y)

        return path

    def buttonBox(self):
        """
        Returns the button box that is used to control this popup widget.
        
        :return     <QDialogButtonBox>
        """
        return self._buttonBox

    def centralWidget(self):
        """
        Returns the central widget that is being used by this popup.
        
        :return     <QWidget>
        """
        return self._scrollArea.widget()

    def close(self):
        """
        Closes the popup widget and central widget.
        """
        widget = self.centralWidget()
        if widget and not widget.close():
            return

        super(XPopupWidget, self).close()

    def closeEvent(self, event):
        widget = self.centralWidget()
        if widget and not widget.close() and \
           self.currentMode() != XPopupWidget.Mode.ToolTip:
            event.ignore()
        else:
            super(XPopupWidget, self).closeEvent(event)

        self.closed.emit()

    def currentMode(self):
        """
        Returns the current mode for this widget.
        
        :return     <XPopupWidget.Mode>
        """
        return self._currentMode

    @deprecatedmethod('XPopupWidget',
                      'Direction is no longer used, use anchor instead')
    def direction(self):
        """
        Returns the current direction parameter for this widget.
        
        :return     <XPopupWidget.Direction>
        """
        anchor = self.anchor()
        if (anchor &
            (XPopupWidget.Anchor.TopLeft | XPopupWidget.Anchor.TopCenter
             | XPopupWidget.Anchor.TopRight)):
            return XPopupWidget.Direction.North

        elif (
                anchor &
            (XPopupWidget.Anchor.BottomLeft | XPopupWidget.Anchor.BottomCenter
             | XPopupWidget.Anchor.BottomRight)):
            return XPopupWidget.Direction.South

        elif (anchor &
              (XPopupWidget.Anchor.LeftTop | XPopupWidget.Anchor.LeftCenter
               | XPopupWidget.Anchor.LeftBottom)):
            return XPopupWidget.Direction.East

        else:
            return XPopupWidget.Direction.West

    def eventFilter(self, object, event):
        """
        Processes when the window is moving to update the position for the
        popup if in popup mode.
        
        :param      object | <QObject>
                    event  | <QEvent>
        """
        links = self.positionLinkedTo()
        is_dialog = self.currentMode() == self.Mode.Dialog
        if object not in links:
            return False

        if event.type() == event.Close:
            self.close()
            return False

        if event.type() == event.Hide and not is_dialog:
            self.hide()
            return False

        if event.type() == event.Move and not is_dialog:
            deltaPos = event.pos() - event.oldPos()
            self.move(self.pos() + deltaPos)
            return False

        if self.currentMode() != self.Mode.ToolTip:
            return False

        if event.type() == event.Leave:
            pos = object.mapFromGlobal(QCursor.pos())
            if (not object.rect().contains(pos)):
                self.close()
                event.accept()
                return True

        if event.type() in (event.MouseButtonPress, event.MouseButtonDblClick):
            self.close()
            event.accept()
            return True

        return False

    @qt.Slot(QAbstractButton)
    def handleButtonClick(self, button):
        """
        Handles the button click for this widget.  If the Reset button was
        clicked, then the resetRequested signal will be emitted.  All buttons
        will emit the buttonClicked signal.
        
        :param      button | <QAbstractButton>
        """
        if (self.signalsBlocked()):
            return

        if (button == self._buttonBox.button(QDialogButtonBox.Reset)):
            self.resetRequested.emit()

        self.buttonClicked.emit(button)

    def isAnimated(self):
        """
        Returns whether or not the popup widget should animate its opacity
        when it is shown.
        
        :return     <bool>
        """
        return self._animated

    def isResizable(self):
        """
        Returns if this popup is resizable or not.
        
        :return     <bool>
        """
        return self._resizable

    def keyPressEvent(self, event):
        """
        Looks for the Esc key to close the popup.
        
        :param      event | <QKeyEvent>
        """
        if (event.key() == Qt.Key_Escape):
            self.reject()
            event.accept()
            return

        elif (event.key() in (Qt.Key_Return, Qt.Key_Enter)):
            if self._autoDefault:
                self.accept()
                event.accept()
            return

        super(XPopupWidget, self).keyPressEvent(event)

    def mapAnchorFrom(self, widget, globalPos):
        """
        Returns the anchor point that best fits within the given widget from
        the inputed global position.
        
        :param      widget      | <QWidget>
                    globalPos   | <QPoint>
        
        :return     <XPopupWidget.Anchor>
        """
        localPos = widget.mapFromGlobal(globalPos)

        x = localPos.x()
        y = localPos.y()
        w = widget.width()
        h = widget.height()

        cw = self.width() / 2
        ch = self.height() / 2

        # by default, try to do a center point, so make sure the center point
        # is at least 1/2 the width longer from each edge
        if x < cw and h - y < ch:
            return XPopupWidget.Anchor.BottomLeft
        elif x < cw:
            return XPopupWidget.Anchor.TopLeft
        elif w - x < cw and h - y < ch:
            return XPopupWidget.Anchor.BottomRight
        elif w - x < cw:
            return XPopupWidget.Anchor.TopRight
        elif h - y < ch:
            return XPopupWidget.Anchor.BottomCenter
        else:
            return XPopupWidget.Anchor.TopCenter

    def popup(self, pos=None):
        """
        Pops up this widget at the inputed position.  The inputed point should \
        be in global space.
        
        :param      pos | <QPoint>
        
        :return     <bool> success
        """
        if self._first and self.centralWidget() is not None:
            self.adjustSize()
            self._first = False

        if not self.signalsBlocked():
            self.aboutToShow.emit()

        if not pos:
            pos = QCursor.pos()

        if self.currentMode() == XPopupWidget.Mode.Dialog and \
             self.isVisible():
            return False

        elif self.currentMode() == XPopupWidget.Mode.Dialog:
            self.setPopupMode()

        # auto-calculate the point
        if self.autoCalculateAnchor():
            self.setAnchor(self.mapAnchorFrom(self.parent(), pos))

        pad = self.popupPadding()

        # determine where to move based on the anchor
        anchor = self.anchor()

        # MODIFY X POSITION
        # align x-left
        if (anchor &
            (XPopupWidget.Anchor.TopLeft | XPopupWidget.Anchor.BottomLeft)):
            pos.setX(pos.x() - pad)

        # align x-center
        elif (anchor & (XPopupWidget.Anchor.TopCenter
                        | XPopupWidget.Anchor.BottomCenter)):
            pos.setX(pos.x() - self.width() / 2)

        # align x-right
        elif (
                anchor &
            (XPopupWidget.Anchor.TopRight | XPopupWidget.Anchor.BottomRight)):
            pos.setX(pos.x() - self.width() + pad)

        # align x-padded
        elif (anchor &
              (XPopupWidget.Anchor.RightTop | XPopupWidget.Anchor.RightCenter
               | XPopupWidget.Anchor.RightBottom)):
            pos.setX(pos.x() - self.width())

        # MODIFY Y POSITION
        # align y-top
        if (anchor &
            (XPopupWidget.Anchor.LeftTop | XPopupWidget.Anchor.RightTop)):
            pos.setY(pos.y() - pad)

        # align y-center
        elif (anchor & (XPopupWidget.Anchor.LeftCenter
                        | XPopupWidget.Anchor.RightCenter)):
            pos.setY(pos.y() - self.height() / 2)

        # align y-bottom
        elif (anchor & (XPopupWidget.Anchor.LeftBottom
                        | XPopupWidget.Anchor.RightBottom)):
            pos.setY(pos.y() - self.height() + pad)

        # align y-padded
        elif (
                anchor &
            (XPopupWidget.Anchor.BottomLeft | XPopupWidget.Anchor.BottomCenter
             | XPopupWidget.Anchor.BottomRight)):
            pos.setY(pos.y() - self.height())

        self.adjustMask()
        self.move(pos)
        self.update()
        self.setUpdatesEnabled(True)

        if self.isAnimated():
            anim = QPropertyAnimation(self, 'windowOpacity')
            anim.setParent(self)
            anim.setStartValue(0.0)
            anim.setEndValue(self.windowOpacity())
            anim.setDuration(500)
            anim.finished.connect(anim.deleteLater)
            self.setWindowOpacity(0.0)
        else:
            anim = None

        self.show()

        if self.currentMode() != XPopupWidget.Mode.ToolTip:
            self.activateWindow()

            widget = self.centralWidget()
            if widget:
                self.centralWidget().setFocus()

        if anim:
            anim.start()

        if not self.signalsBlocked():
            self.shown.emit()

        return True

    def paintEvent(self, event):
        """
        Overloads the paint event to handle painting pointers for the popup \
        mode.
        
        :param      event | <QPaintEvent>
        """
        # use the base technique for the dialog mode
        if self.currentMode() == XPopupWidget.Mode.Dialog:
            super(XPopupWidget, self).paintEvent(event)
            return

        # setup the coloring options
        palette = self.palette()

        painter = QPainter()
        painter.begin(self)

        pen = QPen(palette.color(palette.Window).darker(130))
        pen.setWidthF(1.75)
        painter.setPen(pen)
        painter.setRenderHint(painter.Antialiasing)
        painter.setBrush(palette.color(palette.Window))
        painter.drawPath(self.borderPath())
        painter.end()

    def popupPadding(self):
        """
        Returns the amount of pixels to pad the popup arrow for this widget.
        
        :return     <int>
        """
        return self._popupPadding

    def positionLinkedTo(self):
        """
        Returns the widget that this popup is linked to for positional changes.
        
        :return     [<QWidget>, ..]
        """
        return self._positionLinkedTo

    @qt.Slot()
    def reject(self):
        """
        Emits the accepted signal and closes the popup.
        """
        if not self.signalsBlocked():
            self.rejected.emit()

        if self.autoCloseOnReject():
            self.close()

    def resizeEvent(self, event):
        """
        Resizes this widget and updates the mask.
        
        :param      event | <QResizeEvent>
        """
        self.setUpdatesEnabled(False)
        super(XPopupWidget, self).resizeEvent(event)

        self.adjustMask()
        self.setUpdatesEnabled(True)

        x = self.width() - self._sizeGrip.width()
        y = self.height() - self._sizeGrip.height()

        self._leftSizeGrip.move(0, y)
        self._sizeGrip.move(x, y)

    def scrollArea(self):
        """
        Returns the scroll area widget for this popup.
        
        :return     <QScrollArea>
        """
        return self._scrollArea

    def setAnimated(self, state):
        """
        Sets whether or not the popup widget should animate its opacity
        when it is shown.
        
        :param      state | <bool>
        """
        self._animated = state
        self.setAttribute(Qt.WA_TranslucentBackground, state)

    def setAutoCloseOnAccept(self, state):
        """
        Sets whether or not the popup handles closing for accepting states.
        
        :param      state | <bool>
        """
        self._autoCloseOnAccept = state

    def setAutoCloseOnReject(self, state):
        """
        Sets whether or not the popup handles closing for rejecting states.
        
        :param      state | <bool>
        """
        self._autoCloseOnReject = state

    def setAutoDefault(self, state):
        """
        Sets whether or not the buttons should respond to defaulting options
        when the user is interacting with it.
        
        :param      state | <bool>
        """
        self._autoDefault = state
        for button in self.buttonBox().buttons():
            button.setAutoDefault(state)
            button.setDefault(state)

    def setAnchor(self, anchor):
        """
        Sets the anchor position for this popup widget to the inputed point.
        
        :param      anchor | <XPopupWidget.Anchor>
        """
        self._anchor = anchor
        self.adjustContentsMargins()

    def setAutoCalculateAnchor(self, state):
        """
        Sets whether or not this widget should auto-calculate the anchor point
        based on the parent position when the popup is triggered.
        
        :param      state | <bool>
        """
        self._autoCalculateAnchor = state

    def setAutoCloseOnFocusOut(self, state):
        """
        Sets whether or not this popup widget should auto-close when the user
        clicks off the view.
        
        :param     state | <bool>
        """
        self._autoCloseOnFocusOut = state
        self.updateModeSettings()

    def setCentralWidget(self, widget):
        """
        Sets the central widget that will be used by this popup.
        
        :param      widget | <QWidget> || None
        """
        self._scrollArea.takeWidget()
        self._scrollArea.setWidget(widget)

        self.adjustSize()

    def setCurrentMode(self, mode):
        """
        Sets the current mode for this dialog to the inputed mode.
        
        :param      mode | <XPopupWidget.Mode>
        """
        if (self._currentMode == mode):
            return

        self._currentMode = mode
        self.updateModeSettings()

    @qt.Slot()
    def setDialogMode(self):
        """
        Sets the current mode value to Dialog.
        """
        self.setCurrentMode(XPopupWidget.Mode.Dialog)

    @deprecatedmethod('XPopupWidget',
                      'Direction is no longer used, use setAnchor instead')
    def setDirection(self, direction):
        """
        Sets the direction for this widget to the inputed direction.
        
        :param      direction | <XPopupWidget.Direction>
        """
        if (direction == XPopupWidget.Direction.North):
            self.setAnchor(XPopupWidget.Anchor.TopCenter)

        elif (direction == XPopupWidget.Direction.South):
            self.setAnchor(XPopupWidget.Anchor.BottomCenter)

        elif (direction == XPopupWidget.Direction.East):
            self.setAnchor(XPopupWidget.Anchor.LeftCenter)

        else:
            self.setAnchor(XPopupWidget.Anchor.RightCenter)

    def setPalette(self, palette):
        """
        Sets the palette for this widget and the scroll area.
        
        :param      palette | <QPalette>
        """
        super(XPopupWidget, self).setPalette(palette)
        self._scrollArea.setPalette(palette)

    def setPopupMode(self):
        """
        Sets the current mode value to Popup.
        """
        self.setCurrentMode(XPopupWidget.Mode.Popup)

    def setPopupPadding(self, padding):
        """
        Sets the amount to pad the popup area when displaying this widget.
        
        :param      padding | <int>
        """
        self._popupPadding = padding
        self.adjustContentsMargins()

    def setPositionLinkedTo(self, widgets):
        """
        Sets the widget that this popup will be linked to for positional
        changes.
        
        :param      widgets | <QWidget> || [<QWidget>, ..]
        """
        if type(widgets) in (list, set, tuple):
            new_widgets = list(widgets)
        else:
            new_widgets = []
            widget = widgets
            while widget:
                widget.installEventFilter(self)
                new_widgets.append(widget)
                widget = widget.parent()

        self._positionLinkedTo = new_widgets

    def setResizable(self, state):
        self._resizable = state
        self._sizeGrip.setVisible(state)
        self._leftSizeGrip.setVisible(state)

    def setShowButtonBox(self, state):
        self._buttonBoxVisible = state
        self.buttonBox().setVisible(state)

    def setShowTitleBar(self, state):
        self._titleBarVisible = state
        self._dialogButton.setVisible(state)
        self._closeButton.setVisible(state)

    def setToolTipMode(self):
        """
        Sets the mode for this popup widget to ToolTip
        """
        self.setCurrentMode(XPopupWidget.Mode.ToolTip)

    def setVisible(self, state):
        super(XPopupWidget, self).setVisible(state)
        widget = self.centralWidget()
        if widget:
            widget.setVisible(state)

    def timerEvent(self, event):
        """
        When the timer finishes, hide the tooltip popup widget.
        
        :param      event | <QEvent>
        """
        if self.currentMode() == XPopupWidget.Mode.ToolTip:
            self.killTimer(event.timerId())
            event.accept()
            self.close()
        else:
            super(XPopupWidget, self).timerEvent(event)

    def updateModeSettings(self):
        mode = self.currentMode()
        is_visible = self.isVisible()

        # display as a floating dialog
        if mode == XPopupWidget.Mode.Dialog:
            self.setWindowFlags(Qt.Dialog | Qt.Tool)
            self.setAttribute(Qt.WA_TransparentForMouseEvents, False)
            self._closeButton.setVisible(False)
            self._dialogButton.setVisible(False)

        # display as a user tooltip
        elif mode == XPopupWidget.Mode.ToolTip:
            flags = Qt.Popup | Qt.FramelessWindowHint

            self.setWindowFlags(flags)
            self.setBackgroundRole(QPalette.Window)
            self.setAttribute(Qt.WA_TransparentForMouseEvents)
            self.setShowTitleBar(False)
            self.setShowButtonBox(False)
            self.setFocusPolicy(Qt.NoFocus)

            # hide the scrollbars
            policy = Qt.ScrollBarAlwaysOff
            self._scrollArea.setVerticalScrollBarPolicy(policy)
            self._scrollArea.setHorizontalScrollBarPolicy(policy)

        # display as a popup widget
        else:
            flags = Qt.Popup | Qt.FramelessWindowHint

            if not self.autoCloseOnFocusOut():
                flags |= Qt.Tool

            self.setWindowFlags(flags)
            self._closeButton.setVisible(self._titleBarVisible)
            self._dialogButton.setVisible(self._titleBarVisible)
            self.setBackgroundRole(QPalette.Button)

        self.adjustContentsMargins()

        if (is_visible):
            self.show()

    @staticmethod
    @deprecatedmethod('XPopupWidget',
                      'This method no longer has an effect as we are not '\
                      'storing references to the tooltip.')
    def hideToolTip(key=None):
        """
        Hides any existing tooltip popup widgets.
        
        :warning    This method is deprecated!
        """
        pass

    @staticmethod
    def showToolTip(text,
                    point=None,
                    anchor=None,
                    parent=None,
                    background=None,
                    foreground=None,
                    key=None,
                    seconds=5):
        """
        Displays a popup widget as a tooltip bubble.
        
        :param      text        | <str>
                    point       | <QPoint> || None
                    anchor      | <XPopupWidget.Mode.Anchor> || None
                    parent      | <QWidget> || None
                    background  | <QColor> || None
                    foreground  | <QColor> || None
                    key         | <str> || None
                    seconds     | <int>
        """
        if point is None:
            point = QCursor.pos()

        if parent is None:
            parent = QApplication.activeWindow()

        if anchor is None and parent is None:
            anchor = XPopupWidget.Anchor.TopCenter

        # create a new tooltip widget
        widget = XPopupWidget(parent)
        widget.setToolTipMode()
        widget.setResizable(False)

        # create the tooltip label
        label = QLabel(text, widget)
        label.setOpenExternalLinks(True)
        label.setAlignment(Qt.AlignLeft | Qt.AlignVCenter)
        label.setMargin(3)
        label.setIndent(3)
        label.adjustSize()

        widget.setCentralWidget(label)

        # update the tip
        label.adjustSize()
        widget.adjustSize()

        palette = widget.palette()
        if not background:
            background = palette.color(palette.ToolTipBase)
        if not foreground:
            foreground = palette.color(palette.ToolTipText)

        palette.setColor(palette.Window, QColor(background))
        palette.setColor(palette.WindowText, QColor(foreground))
        widget.setPalette(palette)
        widget.centralWidget().setPalette(palette)

        if anchor is None:
            widget.setAutoCalculateAnchor(True)
        else:
            widget.setAnchor(anchor)

        widget.setAutoCloseOnFocusOut(True)
        widget.setAttribute(Qt.WA_DeleteOnClose)
        widget.popup(point)
        widget.startTimer(1000 * seconds)

        return widget
Beispiel #13
0
class WellPlotMPL(QtCore.QObject):
    def __init__(self, logs, well, logSet=None, parent=None):
        super(WellPlotMPL, self).__init__(parent)

        self._well = well
        self._logSet = logSet
        self._logs = logs
        self.plots = []
        self.canvas = None
        self.depthPlot = None
        self.headerPlot = None
        centralWidget = centraltabwidget.CentralTabWidget()
        #id(self) returns the 'hash' of this object
        self.uid = (centralWidget.count(), id(self))
        self.wellPlotSignals = WellPlotSignals()

        self.setupUI()
        self.createTabView()
        self.connectSlots()
        self.plotMultiLogs()
        self.setSplitterStretch()
        self.createToolWidget()

    def setupUI(self):
        self.mainWidget = WellPlotWidget()
        vBox = QtGui.QVBoxLayout()
        self.mainWidget.setLayout(vBox)

        self.headerWidget = QWidget()
        self.headerLayout = QtGui.QHBoxLayout()
        self.headerWidget.setLayout(self.headerLayout)

        self.dataWidget = QWidget()
        self.dataLayout = QtGui.QHBoxLayout()
        self.dataWidget.setLayout(self.dataLayout)

        #if don't set a minimum, get matplotlib error when is very small
        self.dataWidget.setMinimumHeight(self.getMinimumVerticalHeight())

        self.splitter = QSplitter(QtCore.Qt.Vertical)

        self.headerScrollArea = QScrollArea()
        self.headerScrollArea.setVerticalScrollBarPolicy(
            QtCore.Qt.ScrollBarAlwaysOn)
        self.headerScrollArea.setHorizontalScrollBarPolicy(
            QtCore.Qt.ScrollBarAlwaysOff)
        self.headerScrollArea.setWidgetResizable(False)
        self.headerScrollArea.setWidget(self.headerWidget)

        self.scrollArea = QScrollArea()
        self.scrollArea.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)
        self.scrollArea.setHorizontalScrollBarPolicy(
            QtCore.Qt.ScrollBarAlwaysOn)
        self.scrollArea.setWidgetResizable(False)
        self.scrollArea.setWidget(self.dataWidget)
        #see http://stackoverflow.com/questions/29583927/pyqt-qscrollarea-within-qscrollarea/29584939#29584939
        self.scrollArea.horizontalScrollBar().valueChanged.connect(
            self.headerScrollArea.horizontalScrollBar().setValue)

        self.splitter.addWidget(self.headerScrollArea)
        self.splitter.addWidget(self.scrollArea)
        self.splitter.setStretchFactor(1, 10)

        vBox.addWidget(self.splitter)

    def getMinimumVerticalHeight(self):
        screenRect = QtGui.QDesktopWidget().screenGeometry()
        #need to set a minimum size otherwise get matplotlib error when rezizing to too small
        twentythOfScreen = int(round(screenRect.width() / 20))
        return twentythOfScreen

    def plotMultiLogs(self):
        logPlotModelAccess = WellPlotModelAccess()
        logPlotData = logPlotModelAccess.createWellPlotData(self._logs)
        self.createCanvas(logPlotData)
        self.plotHeaderFields(logPlotData)

    def createCanvas(self, logPlotData):
        logger.debug(">>createCanvas()")
        #test
        for subPlotData in logPlotData.sub_plots:
            logger.debug(
                "--createCanvas() plot_index:{0} track_width:{1} track_gap:{2}"
                .format(subPlotData.plot_index, subPlotData.track_width,
                        subPlotData.track_gap))
            for log in subPlotData._logs:
                logger.debug("--createCanvas id:{0}, name:{1}".format(
                    log.id, log.name))
        #end test
        if len(logPlotData.sub_plots) > 0:
            WidgetUtils.removeWidgets(self.dataLayout)

            #test
            #time.sleep(1) # delays for 1 second
            #end test

            #There may be a better way to link plots with the toolbar
            self.mainWidget.setLogPlotData(logPlotData)

            self.depthPlot = DepthAxis(logPlotData, self.dataWidget)
            self.dataLayout.addWidget(self.depthPlot)

            self.canvas = MultiLogCanvas(logPlotData, self.dataWidget)
            self.canvas.setAutoFillBackground(True)
            self.dataLayout.addWidget(self.canvas)

            spacerItem = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding,
                                           QtGui.QSizePolicy.Minimum)
            self.dataLayout.addItem(spacerItem)
        else:
            logger.error("--plotMultiLogs() Error: no logs to plot")
            if AppSettings.isDebugMode:
                raise ValueError

    def plotHeaderFields(self, logPlotData):
        logger.debug(">>plotMultiLogs()")
        WidgetUtils.removeWidgets(self.headerLayout)
        self.headerPlot = HeaderPlotMPL(depthPlot=self.depthPlot,
                                        mainPlot=self.canvas,
                                        logPlotData=logPlotData)
        self.headerLayout.addWidget(self.headerPlot)

    def setSplitterStretch(self):
        #Minimum size is required for the QScrollArea.setWidgetResizable(False) setting'''
        headerW = self.headerPlot.width()
        headerH = self.headerPlot.height()
        self.headerWidget.setMinimumSize(headerW, headerH)

        #test
        (totalW, dataH) = MplUtils.calcFigCanvasWidthHeight(self.canvas.figure)
        #end test
        dWidth, dHeight = self.canvas.figure.canvas.get_width_height()

        self.dataWidget.setMinimumSize(dWidth, dHeight)

    def connectSlots(self):
        logger.debug(">>connectSlots")
        self.wellPlotSignals.logPlotSettingsModified.connect(self.replotLogs)

    @pyqtSlot(WellPlotData)
    def replotLogs(self, logPlotData):
        logger.debug(">>replotLogs len(logPlotData.sub_plots): " +
                     str(len(logPlotData.sub_plots)))
        #check uid's before accessing them, where uid is a (number widgets in central widget, id) tuple
        logger.debug(
            "--replotLogs() len(self.uid):{0}, len(logPlotData.uid):{1}".
            format(len(self.uid), len(logPlotData.uid)))
        if (len(self.uid) == 2) and (len(logPlotData.uid) == 2):
            #ensure this object is associated with the plot object
            if self.uid[0] == logPlotData.uid[0] and self.uid[
                    1] == logPlotData.uid[1]:
                logger.debug("--replotLogs() match found uid: " +
                             str(self.uid[0]))

                self.createCanvas(logPlotData)
                self.plotHeaderFields(logPlotData)

    def spacePlots(self, bottomLayout):
        rightSpacer = QtGui.QWidget()
        rightSpacer.setSizePolicy(QtGui.QSizePolicy.Expanding,
                                  QtGui.QSizePolicy.Expanding)
        #topLayout.addWidget(rightSpacer)
        bottomLayout.addWidget(rightSpacer)
        #self.topWidget.setLayout(topLayout)
        self.dataWidget.setLayout(bottomLayout)

    def createTabView(self):
        centralWidget = centraltabwidget.CentralTabWidget()
        self.mainWidget.setData(self.uid)
        #centralWidget.addTab(self.scrollArea, "Well plot "+str(self.uid[0]))
        centralWidget.addTab(self.mainWidget, "Well plot " + str(self.uid[0]))

    def createToolWidget(self):
        if len(self._logs) > 0:
            toolbar = logsettingstoolbar.LogSettingsToolbar()
            toolbar.setData(self._well, self._logSet, self.canvas,
                            self.depthPlot, self.headerPlot)
            toolbar.emitShowToolbarSignal()
            logger.debug("<<createToolWidget() toolbar created")

if __name__ == '__main__':
    from PyQt4.QtCore import Qt
    from PyQt4.QtGui import QApplication, QSlider, QScrollArea
    from PyQt4.QtGui import QPushButton, QWidget, QVBoxLayout
    
    app = QApplication([])

    widget = QWidget()
    Layout = QVBoxLayout(widget)
    for i in range(10):
        button = QPushButton('button %i' % i, widget)
        Layout.addWidget(button)
    widget.setFixedSize(600, 800)
    widget.show()

    scrollarea = QScrollArea()
    scrollarea.setWidget(widget)
    scrollarea.resize(300, 300)
    scrollarea.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
    scrollarea.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
    scrollarea.show()

    scroller = PreviewScroller(scrollarea)
    scroller.resize(400, 400)
    scroller.show()
    
    app.exec_()

Beispiel #15
0
class DeviceOrderWidget(QWidget):
    def __init__(self, parent=None):
        QWidget.__init__(self, parent)
        self.section = None
        self.deviceWidgets = list()
        self.setMinimumWidth(520)
        self.setMinimumHeight(600)
        self.iconAssigner = IconAssigner()

        self.setupLayout()
        self.setupScrollArea()

        # self.addNewDeviceWidget(device = Device("ABC", None, None))
        # self.addNewDeviceWidget(device = Device("XD", None, None))
        # self.addNewDeviceWidget(device = Device("1313XD", None, None))
        # self.addNewDeviceWidget(device = Device(":-(", None, None))

    def setupLayout(self):
        self.containerWidget = QWidget(self)
        self.widgetHeight = 0
        self.containerWidget.setGeometry(QRect(0,0,451,self.widgetHeight))

        self.layout = QVBoxLayout()
        self.containerWidget.setLayout(self.layout)

    def setupScrollArea(self):
        self.scrollArea = QScrollArea(self)
        self.scrollArea.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded)
        self.scrollArea.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
        self.scrollArea.setMaximumWidth(530)
        self.scrollArea.setMinimumHeight(600)
        self.scrollArea.setWidgetResizable(False)
        self.scrollArea.setWidget(self.containerWidget)

    def setSection(self, section):
        self.section = section
        devices = section.devices
        devices = sorted(devices, key=lambda device: device.getShortName())
        for device in devices:
            self.addNewDeviceWidget(device)

    def addNewDeviceWidget(self, device=None):
        newWidget = DeviceWidget(self, device = device)
        newWidget.position = len(self.deviceWidgets)

        iconPath = self.iconAssigner.getIconPath(device)
        newWidget.deviceIcon.setIcon(iconPath)

        self.deviceWidgets.append(newWidget)
        self.layout.addWidget(newWidget)

        self.widgetHeight += 70
        self.containerWidget.resize(530, self.widgetHeight)

        self.connect(newWidget, QtCore.SIGNAL("up()"), self.upWidget)
        self.connect(newWidget, QtCore.SIGNAL("down()"), self.downWidget)

    def upWidget(self):
        widget = self.sender()
        if widget.position > 0:
            self.swap(widget.position, widget.position-1)

    def downWidget(self):
        widget = self.sender()
        if widget.position < len(self.deviceWidgets)-1:
            self.swap(widget.position, widget.position+1)

    def swap(self, first, second):
        firstWidget = self.deviceWidgets[first]
        secondWidget = self.deviceWidgets[second]

        firstWidget.position = second
        secondWidget.position = first

        self.layout.removeWidget(firstWidget)
        self.layout.removeWidget(secondWidget)
        self.deviceWidgets.remove(firstWidget)
        self.deviceWidgets.remove(secondWidget)
        if first > second:
            self.layout.insertWidget(second, firstWidget)
            self.layout.insertWidget(first, secondWidget)
            self.deviceWidgets.insert(second, firstWidget)
            self.deviceWidgets.insert(first, secondWidget)
        else:
            self.layout.insertWidget(first, secondWidget)
            self.layout.insertWidget(second, firstWidget)
            self.deviceWidgets.insert(first, secondWidget)
            self.deviceWidgets.insert(second, firstWidget)

    def getSortedDevices(self):
        devices = list()
        for deviceWidget in self.deviceWidgets:
            devices.append(deviceWidget.device)
        return devices