예제 #1
0
    def setupTabs(self):
        """ Setup the various tabs in the AddressWidget. """
        groups = ["ABC", "DEF", "GHI", "JKL", "MNO", "PQR", "STU", "VW", "XYZ"]

        for group in groups:
            proxyModel = QSortFilterProxyModel(self)
            proxyModel.setSourceModel(self.tableModel)
            proxyModel.setDynamicSortFilter(True)

            tableView = QTableView()
            tableView.setModel(proxyModel)
            tableView.setSortingEnabled(True)
            tableView.setSelectionBehavior(QAbstractItemView.SelectRows)
            tableView.horizontalHeader().setStretchLastSection(True)
            tableView.verticalHeader().hide()
            tableView.setEditTriggers(QAbstractItemView.NoEditTriggers)
            tableView.setSelectionMode(QAbstractItemView.SingleSelection)

            # This here be the magic: we use the group name (e.g. "ABC") to
            # build the regex for the QSortFilterProxyModel for the group's
            # tab. The regex will end up looking like "^[ABC].*", only
            # allowing this tab to display items where the name starts with
            # "A", "B", or "C". Notice that we set it to be case-insensitive.
            reFilter = "^[%s].*" % group

            proxyModel.setFilterRegExp(QRegExp(reFilter, Qt.CaseInsensitive))
            proxyModel.setFilterKeyColumn(0) # Filter on the "name" column
            proxyModel.sort(0, Qt.AscendingOrder)

            # This prevents an application crash (see: http://www.qtcentre.org/threads/58874-QListView-SelectionModel-selectionChanged-Crash)
            viewselectionmodel = tableView.selectionModel()
            tableView.selectionModel().selectionChanged.connect(self.selectionChanged)

            self.addTab(tableView, group)
예제 #2
0
    def setupTabs(self):
        """ Setup the various tabs in the AddressWidget. """
        groups = ["ABC", "DEF", "GHI", "JKL", "MNO", "PQR", "STU", "VW", "XYZ"]

        for group in groups:
            proxyModel = QSortFilterProxyModel(self)
            proxyModel.setSourceModel(self.tableModel)
            proxyModel.setDynamicSortFilter(True)

            tableView = QTableView()
            tableView.setModel(proxyModel)
            tableView.setSortingEnabled(True)
            tableView.setSelectionBehavior(QAbstractItemView.SelectRows)
            tableView.horizontalHeader().setStretchLastSection(True)
            tableView.verticalHeader().hide()
            tableView.setEditTriggers(QAbstractItemView.NoEditTriggers)
            tableView.setSelectionMode(QAbstractItemView.SingleSelection)

            # This here be the magic: we use the group name (e.g. "ABC") to
            # build the regex for the QSortFilterProxyModel for the group's
            # tab. The regex will end up looking like "^[ABC].*", only
            # allowing this tab to display items where the name starts with
            # "A", "B", or "C". Notice that we set it to be case-insensitive.
            reFilter = "^[%s].*" % group

            proxyModel.setFilterRegExp(QRegExp(reFilter, Qt.CaseInsensitive))
            proxyModel.setFilterKeyColumn(0)  # Filter on the "name" column
            proxyModel.sort(0, Qt.AscendingOrder)

            # This prevents an application crash (see: http://www.qtcentre.org/threads/58874-QListView-SelectionModel-selectionChanged-Crash)
            viewselectionmodel = tableView.selectionModel()
            tableView.selectionModel().selectionChanged.connect(
                self.selectionChanged)

            self.addTab(tableView, group)
예제 #3
0
    class __HPasteCollectionWidget(CollectionWidget):
        def __init__(self, parent=None):
            super(HPasteCollectionWidget.__HPasteCollectionWidget,
                  self).__init__(parent,
                                 metadataExposedKeys=('raw_url', 'nettype'))
            for x in xrange(1, 5):
                self.ui.mainView.horizontalHeader().hideSection(x)

            self.__nepane = None
            self.__netType = ''

            self.__nettypeFilter = QSortFilterProxyModel(self)
            self.__nettypeFilter.setFilterKeyColumn(4)
            self.__nettypeFilter.setFilterRegExp(
                QRegExp("*", Qt.CaseInsensitive, QRegExp.Wildcard))
            self.appendFilter(self.__nettypeFilter)

            self.accepted.connect(self.doOnAccept)

        def setNetworkEditor(self, pane):
            if (not isinstance(pane, hou.NetworkEditor)):
                pane = None

            self.__nepane = pane  #save to position pasted nodes in it

            if (pane is None):
                nettype = '*'
                self.__netType = ''  #Used to create new snippet types
            else:
                nettype = hpaste.getChildContext(pane.pwd(),
                                                 hou.applicationVersion())
                self.__netType = nettype
            self.__nettypeFilter.setFilterRegExp(
                QRegExp(nettype, Qt.CaseInsensitive, QRegExp.Wildcard))

        @Slot(object)
        def doOnAccept(self, item):
            if (item is None): return
            try:
                hou.clearAllSelected()
                hpaste.stringToNodes(item.content(), ne=self.__nepane)
            except Exception as e:
                hou.ui.displayMessage("could not paste: %s" % e.message,
                                      severity=hou.severityType.Warning)

        def _addItem(self, collection):
            #Please, dont throw from here!
            try:
                nodes = hou.selectedItems()
            except:
                nodes = hou.selectedNodes()
            if (len(nodes) == 0):
                QMessageBox.warning(self, 'not created',
                                    'selection is empty, nothing to add')
                return

            while True:
                #btn,(name,desc) = (0,('1','2'))#hou.ui.readMultiInput('enter some information about new item',('name','description'),buttons=('Ok','Cancel'))
                name, desc, public, good = QDoubleInputDialog.getDoubleTextCheckbox(
                    self, 'adding a new item to %s' % collection.name(),
                    'enter new item details', 'name', 'description', 'public',
                    '', 'a snippet', False)
                if (not good): return

                if (len(name) > 0):
                    break
                    #validity check

            try:
                #print(name)
                #print(desc)
                #print(hpaste.nodesToString(nodes))
                self.model().addItemToCollection(
                    collection,
                    name,
                    desc,
                    hpaste.nodesToString(nodes),
                    public,
                    metadata={'nettype': self.__netType})
            except CollectionSyncError as e:
                QMessageBox.critical(self, 'something went wrong!',
                                     'Server error occured: %s' % e.message)

        def _changeAccess(self, index):
            item = index.internalPointer()
            text, good = QInputDialog.getItem(
                None,
                'modify item access',
                'choose new access type:', ['private', 'public'],
                current=item.access() == CollectionItem.AccessType.public,
                editable=False)
            if (not good): return
            newaccess = CollectionItem.AccessType.public if text == 'public' else CollectionItem.AccessType.private
            if (newaccess == item.access()): return
            item.setAccess(newaccess)

        def _replaceContent(self, index):
            try:
                nodes = hou.selectedItems()
            except:
                nodes = hou.selectedNodes()
            if (len(nodes) == 0):
                QMessageBox.warning(self, 'cannot replace',
                                    'selection is empty')
                return
            item = index.internalPointer()
            good = QMessageBox.warning(
                self, 'sure?',
                'confirm that you want to replace the content of selected item "%s". This operation can not be undone.'
                % item.name(),
                QMessageBox.Ok | QMessageBox.Cancel) == QMessageBox.Ok
            if (not good): return
            try:
                item.setContent(hpaste.nodesToString(nodes))
            except CollectionSyncError as e:
                QMessageBox.critical(self, 'something went wrong!',
                                     'Server error occured: %s' % e.message)

        def _itemInfo(self, index):
            item = index.internalPointer()
            accesstext = 'public' if item.access(
            ) == CollectionItem.AccessType.public else 'private'
            readonlytext = 'readonly' if item.readonly() else 'editable'
            info = 'name: %s\n%s\naccess: %s\n%s\n\ncollection id: %s\n\nmetadata:\n' % (
                item.name(), item.description(), accesstext, readonlytext,
                item.id())
            info += '\n'.join(('%s : %s' % (key, item.metadata()[key])
                               for key in item.metadata()))

            QMessageBox.information(self, 'item information', info)

        def _renameItem(self, index):
            item = index.internalPointer()
            oldname = item.name()
            olddesc = item.description()
            newname, newdesc, good = QDoubleInputDialog.getDoubleText(
                self, 'modify item info',
                'Enter new item name and description', 'name', 'description',
                oldname, olddesc)
            if (not good): return
            if (newname != oldname): item.setName(newname)
            if (newdesc != olddesc): item.setDescription(newdesc)

        #def _replaceContent(self, index):
        #pass

        def _confirmRemove(self, index):
            return QMessageBox.warning(
                self, 'sure?',
                'confirm removing the item from collection. This operation can not be undone.',
                QMessageBox.Ok | QMessageBox.Cancel) == QMessageBox.Ok
예제 #4
0
class FE14CharacterEditor(Ui_FE14CharacterEditor):
    def __init__(self, is_person=False, parent=None):
        super().__init__(parent)
        self.is_person = is_person
        self.module: TableModule = locator.get_scoped(
            "ModuleService").get_module("Characters")
        self.proxy_model = QSortFilterProxyModel()
        self.proxy_model.setFilterCaseSensitivity(QtCore.Qt.CaseInsensitive)
        self.proxy_model.setSourceModel(self.module.entries_model)
        self.characters_list_view.setModel(self.proxy_model)
        self.selection: Optional[PropertyContainer] = None

        self.character_details_form_1 = PropertyForm(
            self.module.element_template, category="character_description_1")
        self.character_details_form_contents_1.setLayout(
            self.character_details_form_1)
        self.character_details_form_2 = PropertyForm(
            self.module.element_template, category="character_description_2")
        self.character_details_form_contents_2.setLayout(
            self.character_details_form_2)
        self.character_details_form_2.fix_editor_width(100)
        self.stats_editor = MergedStatsEditor(
            ["Bases", "Growths", "Modifiers", "Penalties", "Bonuses"])
        self.stats_form = PropertyForm(self.module.element_template,
                                       category="stats")
        self.stats_layout.addWidget(self.stats_editor)
        self.stats_layout.addLayout(self.stats_form)
        self.skills_form = PropertyForm(self.module.element_template,
                                        category="skills",
                                        sort_editors=True)
        self.skills_contents.setLayout(self.skills_form)
        self.flags_editor = MergedFlagsEditor(
            ["Bitflags (1)", "Bitflags (2)", "Bitflags (3)", "Bitflags (4)"],
            self.module.element_template)
        self.flags_editor_2 = MergedFlagsEditor(
            ["Bitflags (5)", "Bitflags (6)", "Bitflags (7)", "Bitflags (8)"],
            self.module.element_template)
        self.misc_form = PropertyForm(self.module.element_template,
                                      category="misc")
        self.misc_layout.addWidget(self.flags_editor)
        self.misc_layout.addWidget(self.flags_editor_2)
        self.misc_layout.addLayout(self.misc_form)
        self.ids_form = PropertyForm(self.module.element_template,
                                     category="ids")
        self.ids_tab.setLayout(self.ids_form)
        self.classes_form = PropertyForm(self.module.element_template,
                                         category="classes",
                                         sort_editors=True)
        self.classes_tab.setLayout(self.classes_form)
        if not self.is_person:
            self.dialogue_tab = DialogueEditor()
            self.supports_tab = QWidget()
            self.supports_layout = QHBoxLayout()
            self.supports_widget = FE14SupportWidget()
            self.supports_scroll = QScrollArea()
            self.supports_scroll_contents = QWidget()
            self.supports_scroll.setWidget(self.supports_scroll_contents)
            self.supports_scroll.setWidgetResizable(True)
            self.supports_layout.addWidget(self.supports_widget)
            self.supports_layout.addWidget(self.supports_scroll)
            self.supports_tab.setLayout(self.supports_layout)
            self.supports_form = PropertyForm(self.module.element_template,
                                              category="supports")
            self.supports_scroll_contents.setLayout(self.supports_form)
            self.tab_widget.addTab(self.supports_tab, "Supports")
            self.tab_widget.addTab(self.dialogue_tab, "Dialogue")

        self.context_menu = QMenu(self)
        self.context_menu.addActions(
            [self.action_add, self.action_remove, self.action_copy_to])
        self.clear_selection_shortcut = QShortcut(QKeySequence.Cancel, self)

        self._install_signals()
        self._clear()

    def set_module(self, module: TableModule):
        self.module = module
        if self.module:
            self.proxy_model.setSourceModel(self.module.entries_model)
        else:
            self.proxy_model.setSourceModel(None)
        self.setEnabled(self.module is not None)
        self._clear()

    def _on_context_menu_requested(self, point: QPoint):
        self.context_menu.exec_(self.characters_list_view.mapToGlobal(point))

    def _install_signals(self):
        self.characters_list_view.selectionModel().currentRowChanged.connect(
            self._update_selection)
        self.characters_list_view.customContextMenuRequested.connect(
            self._on_context_menu_requested)
        self.search_bar.textChanged.connect(self._update_filter)
        self.action_add.triggered.connect(self._on_add_character_triggered)
        self.action_remove.triggered.connect(
            self._on_remove_character_triggered)
        self.action_copy_to.triggered.connect(self._on_copy_to_triggered)
        self.clear_selection_shortcut.activated.connect(self._clear)
        if self.character_details_form_1.editors['Name'] != None:
            self.character_details_form_1.editors[
                'Name'].value_editor.editingFinished.connect(
                    self._update_conversation_widget)

    def _clear(self):
        self.characters_list_view.clearSelection()
        self.characters_list_view.selectionModel().clearCurrentIndex()

    def _update_selection(self, index: QModelIndex):
        self.selection = self.proxy_model.data(index, QtCore.Qt.UserRole)
        self.portraits_tab.update_target(self.selection)
        self.character_details_form_1.update_target(self.selection)
        self.character_details_form_2.update_target(self.selection)
        self.stats_editor.update_target(self.selection)
        self.ids_form.update_target(self.selection)
        self.classes_form.update_target(self.selection)
        self.stats_form.update_target(self.selection)
        self.skills_form.update_target(self.selection)
        self.flags_editor.update_target(self.selection)
        self.flags_editor_2.update_target(self.selection)
        self.misc_form.update_target(self.selection)
        if not self.is_person:
            self.dialogue_tab.update_target(self.selection)
            self.supports_widget.update_target(self.selection)
            self.supports_form.update_target(self.selection)
        if self.selection:
            locator.get_scoped("SpriteService").get_sprite_for_character(
                self.selection, 0)
        self.action_remove.setEnabled(self.selection is not None)
        self.action_copy_to.setEnabled(self.selection is not None)
        self._update_portrait_box()

    def _update_portrait_box(self):
        portrait_service = locator.get_scoped("PortraitService")
        mini_portraits = portrait_service.get_sorted_portraits_for_character(
            self.selection, "bu")
        if mini_portraits:
            _, texture = mini_portraits[0]
            scene = QGraphicsScene()
            scene.addPixmap(QPixmap.fromImage(texture.image()))
            self.portrait_display.setScene(scene)
        else:
            self.portrait_display.setScene(None)

    def _update_filter(self):
        self.proxy_model.setFilterRegExp(self.search_bar.text())

    def _on_add_character_triggered(self):
        model = self.module.entries_model
        model.insertRow(model.rowCount())
        source = self.module.entries[0]
        destination = self.module.entries[-1]
        source.copy_to(destination)
        # Update any present conversation widget with the new obj list
        self._update_conversation_widget()

    def _on_remove_character_triggered(self):
        if self.characters_list_view.currentIndex().isValid():
            model = self.module.entries_model
            model.removeRow(self.characters_list_view.currentIndex().row())
            model.beginResetModel()
            model.endResetModel()
            # Update any present conversation widget with the new obj list
            self._update_conversation_widget()

    def _update_conversation_widget(self):
        for editor in self.supports_widget.service._conversation_editors:
            editor: FE14ConversationEditor
            character_list = list()
            [
                character_list.append(child[1])
                for child in self.module.children()
            ]
            editor.text_area._character_list = character_list

    def _on_copy_to_triggered(self):
        if not self.selection:
            return

        logging.info("Beginning copy to for " + self.module.name)
        choices = []
        for i in range(0, len(self.module.entries)):
            choices.append(
                str(i + 1) + ". " + self.module.entries[i].get_display_name())
        choice = QInputDialog.getItem(self, "Select Destination",
                                      "Destination", choices)
        if choice[1]:
            for i in range(0, len(choices)):
                if choice[0] == choices[i]:
                    self.selection.copy_to(self.module.entries[i])
            # Update any present conversation widget with the new obj list
            self._update_conversation_widget()
        else:
            logging.info("No choice selected for " + self.module.name +
                         " copy to. Aborting.")
예제 #5
0
class SearchBarEditor(QTableView):
    """A Google-like search bar, implemented as a QTableView with a _CustomLineEditDelegate in the first row.
    """

    data_committed = Signal()

    def __init__(self, parent, tutor=None):
        """Initializes instance.

        Args:
            parent (QWidget): parent widget
            tutor (QWidget, NoneType): another widget used for positioning.
        """
        super().__init__(parent)
        self._tutor = tutor
        self._base_size = QSize()
        self._base_offset = QPoint()
        self._original_text = None
        self._orig_pos = None
        self.first_index = QModelIndex()
        self.model = QStandardItemModel(self)
        self.proxy_model = QSortFilterProxyModel(self)
        self.proxy_model.setSourceModel(self.model)
        self.proxy_model.filterAcceptsRow = self._proxy_model_filter_accepts_row
        self.setModel(self.proxy_model)
        self.verticalHeader().hide()
        self.horizontalHeader().hide()
        self.setShowGrid(False)
        self.setMouseTracking(True)
        self.setTabKeyNavigation(False)
        delegate = _CustomLineEditDelegate(self)
        delegate.text_edited.connect(self._handle_delegate_text_edited)
        self.setItemDelegateForRow(0, delegate)

    def set_data(self, current, items):
        """Populates model.

        Args:
            current (str)
            items (Sequence(str))
        """
        item_list = [QStandardItem(current)]
        for item in items:
            qitem = QStandardItem(item)
            item_list.append(qitem)
            qitem.setFlags(~Qt.ItemIsEditable)
        self.model.invisibleRootItem().appendRows(item_list)
        self.first_index = self.proxy_model.mapFromSource(
            self.model.index(0, 0))

    def set_base_size(self, size):
        self._base_size = size

    def set_base_offset(self, offset):
        self._base_offset = offset

    def update_geometry(self):
        """Updates geometry.
        """
        self.horizontalHeader().setDefaultSectionSize(self._base_size.width())
        self.verticalHeader().setDefaultSectionSize(self._base_size.height())
        self._orig_pos = self.pos() + self._base_offset
        if self._tutor:
            self._orig_pos += self._tutor.mapTo(self.parent(),
                                                self._tutor.rect().topLeft())
        self.refit()

    def refit(self):
        self.move(self._orig_pos)
        table_height = self.verticalHeader().length()
        size = QSize(self._base_size.width(),
                     table_height + 2).boundedTo(self.parent().size())
        self.resize(size)
        # Adjust position if widget is outside parent's limits
        bottom_right = self.mapToGlobal(self.rect().bottomRight())
        parent_bottom_right = self.parent().mapToGlobal(
            self.parent().rect().bottomRight())
        x_offset = max(0, bottom_right.x() - parent_bottom_right.x())
        y_offset = max(0, bottom_right.y() - parent_bottom_right.y())
        self.move(self.pos() - QPoint(x_offset, y_offset))

    def data(self):
        return self.first_index.data(Qt.EditRole)

    @Slot("QString")
    def _handle_delegate_text_edited(self, text):
        """Filters model as the first row is being edited."""
        self._original_text = text
        self.proxy_model.setFilterRegExp("^" + text)
        self.proxy_model.setData(self.first_index, text)
        self.refit()

    def _proxy_model_filter_accepts_row(self, source_row, source_parent):
        """Always accept first row.
        """
        if source_row == 0:
            return True
        return QSortFilterProxyModel.filterAcceptsRow(self.proxy_model,
                                                      source_row,
                                                      source_parent)

    def keyPressEvent(self, event):
        """Sets data from current index into first index as the user navigates
        through the table using the up and down keys.
        """
        super().keyPressEvent(event)
        event.accept(
        )  # Important to avoid unhandled behavior when trying to navigate outside view limits
        # Initialize original text. TODO: Is there a better place for this?
        if self._original_text is None:
            self.proxy_model.setData(self.first_index, event.text())
            self._handle_delegate_text_edited(event.text())
        # Set data from current index in model
        if event.key() in (Qt.Key_Up, Qt.Key_Down):
            current = self.currentIndex()
            if current.row() == 0:
                self.proxy_model.setData(self.first_index, self._original_text)
            else:
                self.proxy_model.setData(self.first_index, current.data())

    def currentChanged(self, current, previous):
        super().currentChanged(current, previous)
        self.edit_first_index()

    def edit_first_index(self):
        """Edits first index if valid and not already being edited.
        """
        if not self.first_index.isValid():
            return
        if self.isPersistentEditorOpen(self.first_index):
            return
        self.edit(self.first_index)

    def mouseMoveEvent(self, event):
        """Sets the current index to the one hovered by the mouse."""
        if not self.currentIndex().isValid():
            return
        index = self.indexAt(event.pos())
        if index.row() == 0:
            return
        self.setCurrentIndex(index)

    def mousePressEvent(self, event):
        """Commits data."""
        index = self.indexAt(event.pos())
        if index.row() == 0:
            return
        self.proxy_model.setData(self.first_index, index.data(Qt.EditRole))
        self.data_committed.emit()
예제 #6
0
    class __HPasteCollectionWidget(CollectionWidget):
        def __init__(self, parent=None):
            super(HPasteCollectionWidget.__HPasteCollectionWidget,
                  self).__init__(parent,
                                 metadataExposedKeys=('raw_url', 'nettype'))
            for x in xrange(1, 5):
                self.ui.mainView.horizontalHeader().hideSection(x)

            self.__nepane = None
            self.__netType = ''

            self.__nettypeFilter = QSortFilterProxyModel(self)
            self.__nettypeFilter.setFilterKeyColumn(4)
            self.__nettypeFilter.setFilterRegExp(
                QRegExp("*", Qt.CaseInsensitive, QRegExp.Wildcard))
            self.appendFilter(self.__nettypeFilter)

            self.accepted.connect(self.doOnAccept)

            self.__insideAuthCallback = False
            #self.setProperty("houdiniStyle", True)
            ss = "QTableView{border : 0px solid; gridline-color: rgb(48,48,48)}"
            ss += "QHeaderView::section{border-style: none; border-bottom: 0px; border-right: 0px;}"
            self.setStyleSheet(ss)

            self.__savedNetworkViewPos = None

        def setNetworkEditor(self, pane):
            if (not isinstance(pane, hou.NetworkEditor)):
                pane = None

            self.__nepane = pane  #save to position pasted nodes in it
            self.__savedNetworkViewPos = pane.cursorPosition()

            if (pane is None):
                nettype = '*'
                self.__netType = ''  #Used to create new snippet types
            else:
                nettype = hpaste.getChildContext(pane.pwd(),
                                                 hou.applicationVersion())
                self.__netType = nettype
            self.__nettypeFilter.setFilterRegExp(
                QRegExp(nettype, Qt.CaseInsensitive, QRegExp.Wildcard))

        @Slot(object)
        def doOnAccept(self, item):
            if (item is None): return
            try:
                try:  #>h16
                    hou.clearAllSelected()
                except:  #<=h15.5
                    hou.node("/obj").setSelected(False,
                                                 clear_all_selected=True)
                hpaste.stringToNodes(
                    item.content(),
                    ne=self.__nepane,
                    override_network_position=self.__savedNetworkViewPos)
            except RuntimeWarning as e:
                log('Warnings encountered during load:\n%s' % e.message, 2)
            except Exception as e:
                hou.ui.displayMessage("could not paste: %s" % e.message,
                                      severity=hou.severityType.Warning)

        def _addItem(self, collection):
            #Please, dont throw from here!
            try:
                nodes = hou.selectedItems()
            except:
                nodes = hou.selectedNodes()
            if (len(nodes) == 0):
                QMessageBox.warning(self, 'not created',
                                    'selection is empty, nothing to add')
                return

            while True:
                #btn,(name,desc) = (0,('1','2'))#hou.ui.readMultiInput('enter some information about new item',('name','description'),buttons=('Ok','Cancel'))
                name, desc, public, good = QDoubleInputDialog.getDoubleTextCheckbox(
                    self, 'adding a new item to %s' % collection.name(),
                    'enter new item details', 'name', 'description', 'public',
                    '', 'a snippet', False)
                if (not good): return

                if (len(name) > 0):
                    break
                    #validity check

            try:
                #print(name)
                #print(desc)
                #print(hpaste.nodesToString(nodes))
                self.model().addItemToCollection(
                    collection,
                    name,
                    desc,
                    hpaste.nodesToString(nodes),
                    public,
                    metadata={'nettype': self.__netType})
            except CollectionSyncError as e:
                QMessageBox.critical(self, 'something went wrong!',
                                     'Server error occured: %s' % e.message)

        def _changeAccess(self, index):
            item = index.internalPointer()
            text, good = QInputDialog.getItem(
                None,
                'modify item access',
                'choose new access type:', ['private', 'public'],
                current=item.access() == CollectionItem.AccessType.public,
                editable=False)
            if (not good): return
            newaccess = CollectionItem.AccessType.public if text == 'public' else CollectionItem.AccessType.private
            if (newaccess == item.access()): return
            item.setAccess(newaccess)

        def _replaceContent(self, index):
            try:
                nodes = hou.selectedItems()
            except:
                nodes = hou.selectedNodes()
            if (len(nodes) == 0):
                QMessageBox.warning(self, 'cannot replace',
                                    'selection is empty')
                return
            item = index.internalPointer()
            good = QMessageBox.warning(
                self, 'sure?',
                'confirm that you want to replace the content of selected item "%s". This operation can not be undone.'
                % item.name(),
                QMessageBox.Ok | QMessageBox.Cancel) == QMessageBox.Ok
            if (not good): return
            try:
                item.setContent(hpaste.nodesToString(nodes))
            except CollectionSyncError as e:
                QMessageBox.critical(self, 'something went wrong!',
                                     'Server error occured: %s' % e.message)

        def _itemInfo(self, index):
            item = index.internalPointer()
            accesstext = 'public' if item.access(
            ) == CollectionItem.AccessType.public else 'private'
            readonlytext = 'readonly' if item.readonly() else 'editable'
            info = 'name: %s\n%s\naccess: %s\n%s\n\ncollection id: %s\n\nmetadata:\n' % (
                item.name(), item.description(), accesstext, readonlytext,
                item.id())
            info += '\n'.join(('%s : %s' % (key, item.metadata()[key])
                               for key in item.metadata()))

            QMessageBox.information(self, 'item information', info)

        def _renameItem(self, index):
            item = index.internalPointer()
            oldname = item.name()
            olddesc = item.description()
            newname, newdesc, good = QDoubleInputDialog.getDoubleText(
                self, 'modify item info',
                'Enter new item name and description', 'name', 'description',
                oldname, olddesc)
            if (not good): return
            if (newname != oldname): item.setName(newname)
            if (newdesc != olddesc): item.setDescription(newdesc)

        def _removeIcon(self, index):
            ok = QMessageBox.warning(
                self, 'sure?',
                'confirm removing Icon. This operation can not be undone.',
                QMessageBox.Ok | QMessageBox.Cancel) == QMessageBox.Ok
            if ok:
                super(HPasteCollectionWidget.__HPasteCollectionWidget,
                      self)._removeIcon(index)

        def _confirmRemove(self, index):
            return QMessageBox.warning(
                self, 'sure?',
                'confirm removing the item from collection. This operation can not be undone.',
                QMessageBox.Ok | QMessageBox.Cancel) == QMessageBox.Ok

        # a callback for authoriser
        def _authCallback(self, callbackinfo):
            auth, public, action = callbackinfo

            if self.__insideAuthCallback: return  # prevent looping
            self.__insideAuthCallback = True

            try:
                if action == 0 or (action == 2 and not auth['enabled']):
                    good = self.removeCollection(auth['user'])
                    if not good:  # means something went wrong during  removal attempt - probably async collection syncing problem. Try later
                        if public:
                            GithubAuthorizator.setPublicCollsctionEnabled(
                                auth['user'], True)
                        else:
                            GithubAuthorizator.setAuthorizationEnabled(
                                auth['user'], True)

                elif action == 1 or (action == 2 and auth['enabled']):
                    if public:
                        self.addCollection(
                            GithubCollection(auth['user'], public=True),
                            async=True
                        )  # TODO: reuse some token for public access
                    else:
                        self.addCollection(GithubCollection(auth['token']),
                                           async=True)
            except CollectionSyncError as e:
                QMessageBox.critical(
                    self, 'something went wrong!',
                    'could not add/remove collection: %s' % e.message)
            finally:
                self.__insideAuthCallback = False
예제 #7
0
class FE14SupportEditor(QWidget, Ui_support_editor):
    def __init__(self):
        super().__init__()
        self.setupUi(self)
        self.pushButton_2.setEnabled(False)
        self.pushButton_3.setEnabled(False)
        self.comboBox.setEnabled(False)
        self.setWindowTitle("Support Editor")
        self.setWindowIcon(QIcon("paragon.ico"))
        self.error_dialog = None

        module_service = locator.get_scoped("ModuleService")
        self.service = None
        self.current_character = None
        self.current_supports = None
        self.current_support = None
        self.model = module_service.get_module("Characters").entries_model
        self.proxy_model = QSortFilterProxyModel(self)
        self.proxy_model.setSourceModel(self.model)
        self.proxy_model.setFilterCaseSensitivity(QtCore.Qt.CaseInsensitive)
        self.characters_list_view.setModel(self.proxy_model)

        self.characters_list_view.selectionModel().currentRowChanged.connect(self._update_selection)
        self.listWidget.selectionModel().currentRowChanged.connect(self._on_target_character_changed)
        self.listWidget_2.selectionModel().currentRowChanged.connect(self._update_support_selection)
        self.lineEdit.textChanged.connect(self._update_filter)
        self.pushButton_2.clicked.connect(self._on_add_support_pressed)
        self.pushButton_3.clicked.connect(self._on_remove_support_pressed)
        self.comboBox.currentIndexChanged.connect(self._on_support_type_changed)

    def show(self):
        super().show()
        self.service = locator.get_scoped("SupportsService")
        self.service.set_in_use()
        success = True
        try:
            self.service.check_support_id_validity()
        except:
            logging.exception("Support IDs are invalid.")
            self.error_dialog = ErrorDialog("Support IDs are invalid. This could mean an ID was out of bounds or not "
                                            "unique. See the log for details.")
            self.error_dialog.show()
            success = False
        self.setDisabled(not success)

    def _update_filter(self):
        self.proxy_model.setFilterRegExp(self.lineEdit.text())

    def _update_selection(self, index: QtCore.QModelIndex):
        if index.isValid():
            character = self.proxy_model.data(index, QtCore.Qt.UserRole)
            self._refresh_lists(character)
            self.current_character = character

    def _refresh_lists(self, character):
        self._update_supports_list(character)
        self._update_add_list(character)
        self.current_support = None
        self.comboBox.setEnabled(False)
        self.pushButton_2.setEnabled(False)
        self.pushButton_3.setEnabled(False)

    def _update_add_list(self, character):
        supported_characters = self._create_supported_characters_set(character)
        module_service = locator.get_scoped("ModuleService")

        self.listWidget.clear()
        characters = module_service.get_module("Characters").entries
        for target_character in characters:
            if target_character["PID"] not in supported_characters:
                model_index = self._get_model_index_of_character(target_character)
                display_name = self.model.data(model_index, QtCore.Qt.DisplayRole)
                item = QListWidgetItem(display_name)
                item.setData(QtCore.Qt.UserRole, target_character)
                self.listWidget.addItem(item)

    # Dict is not hashable. PIDs should be unique, so we'll use those instead.
    # Might be able to use IDs instead.
    def _create_supported_characters_set(self, character):
        supports = self.service.get_supports_for_character(character)
        result = set()
        for support in supports:
            result.add(support.character["PID"])
        return result

    def _update_supports_list(self, character):
        supports = self.service.get_supports_for_character(character)
        self.listWidget_2.clear()
        for support in supports:
            model_index = self._get_model_index_of_character(support.character)
            display_name = self.model.data(model_index, QtCore.Qt.DisplayRole)
            item = QListWidgetItem(display_name)
            item.setData(QtCore.Qt.UserRole, support)
            self.listWidget_2.addItem(item)
        self.current_supports = supports

    def _get_model_index_of_character(self, character):
        module_service = locator.get_scoped("ModuleService")
        entries = module_service.get_module("Characters").entries
        for i in range(0, len(entries)):
            if entries[i] == character:
                return self.model.index(i)
        return QModelIndex()

    def _update_support_selection(self, index):
        if not index.isValid() or not self.current_supports:
            return
        self.current_support = self.current_supports[index.row()]
        index = SUPPORT_TYPE_TO_INDEX[self.current_support.support_type]
        self.comboBox.setCurrentIndex(index)
        self.comboBox.setEnabled(True)
        self.pushButton_3.setEnabled(True)

    def _on_support_type_changed(self, index):
        if not self.current_character or not self.current_support:
            return
        support_type = INDEX_TO_SUPPORT_TYPE[index]
        self.service.set_support_type(self.current_character, self.current_support, support_type)

    def _on_target_character_changed(self):
        self.pushButton_2.setEnabled(self.listWidget.currentIndex().isValid())

    def _on_add_support_pressed(self):
        if not self.current_character or not self.listWidget.currentIndex().isValid():
            return
        other_character = self.listWidget.currentItem().data(QtCore.Qt.UserRole)
        support_type = INDEX_TO_SUPPORT_TYPE[0]  # Default to romantic.
        self.service.add_support_between_characters(self.current_character, other_character, support_type)
        self._refresh_lists(self.current_character)

    def _on_remove_support_pressed(self):
        if not self.current_character or not self.current_support:
            return
        self.service.remove_support(self.current_character, self.current_support)
        self._refresh_lists(self.current_character)
class LayersList(QWidget):
    '''
    LayerList class which acts as collapsable list.
    '''
    def __init__(self, name, layers, filter, expand=True):
        super().__init__()
        self.setWindowModality(QtCore.Qt.WindowModal)
        self.currently_expanded = True
        self.main_layout = QVBoxLayout()
        self.main_layout.setMargin(0)
        self.main_layout.setSpacing(0)
        self.main_layout.setContentsMargins(0, 0, 0, 0)

        self.expand_button = QPushButton(name)
        self.expand_button.setToolTip(f"List of {name} Layers")
        self.expand_button.setIcon(
            QIcon(os.path.join(PATH, 'LayersList_Down.png')))

        self.layer_list = QListView()
        self.layer_list.setDragEnabled(True)
        self.layer_list.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.layer_list.setWrapping(False)
        self.layer_list.setViewMode(self.layer_list.ListMode)

        self.container_model = QStandardItemModel()
        self.model = QSortFilterProxyModel()
        self.model.setSourceModel(self.container_model)
        self.model.setFilterCaseSensitivity(QtCore.Qt.CaseInsensitive)
        #self.model.cas
        filter.textChanged.connect(self.filter_model)

        for l in layers:
            self.container_model.appendRow(
                QStandardItem(
                    QIcon(os.path.join(PATH, 'LayersList_Layer_Icon.png')), l))

        self.layer_list.setModel(self.model)

        self.main_layout.addWidget(self.expand_button, 0, Qt.AlignTop)
        self.main_layout.addWidget(self.layer_list, 0, Qt.AlignTop)
        self.expand_button.clicked.connect(self.expand)

        self.setLayout(self.main_layout)
        self.resized_size = len(layers) * (self.layer_list.sizeHintForRow(0) +
                                           self.layer_list.frameWidth())

        self.layer_list.setMaximumHeight(self.resized_size)
        self.layer_list.setMinimumHeight(self.resized_size)

        self.setMinimumWidth(self.layer_list.frameWidth())

        self.set_styling()

        if not expand:
            self.expand()

    @QtCore.Slot()
    def expand(self):
        if self.currently_expanded:
            self.layer_list.setMinimumHeight(0)
            self.currently_expanded = False
            self.expand_button.setIcon(
                QIcon(os.path.join(PATH, 'LayersList_Up2.png')))
            self.layer_list.setMaximumHeight(0)
        else:
            self.layer_list.setMinimumHeight(self.resized_size)
            self.currently_expanded = True
            self.expand_button.setIcon(
                QIcon(os.path.join(PATH, 'LayersList_Down.png')))
            self.layer_list.setMaximumHeight(self.resized_size)

    def set_styling(self):
        self.setStyleSheet('''
                           background-color:white;
                           ''')
        self.expand_button.setStyleSheet('''
                                        background-color:#d6d2d2;
                                        text-align:left;
                                        ''')

    @QtCore.Slot()
    def filter_model(self, text):
        self.show()
        self.model.setFilterRegExp(QRegExp(text, QtCore.Qt.CaseInsensitive))
        if not self.currently_expanded:
            self.expand()
        if self.model.rowCount() == 0:
            self.hide()
예제 #9
0
class QStringTable(QTableView):
    def __init__(self, parent, selection_callback=None):
        super(QStringTable, self).__init__(parent)

        self._selected = selection_callback
        self._filter = None

        self.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.setShowGrid(False)
        self.verticalHeader().setVisible(False)
        self.verticalHeader().setDefaultSectionSize(24)
        self.setHorizontalScrollMode(self.ScrollPerPixel)

        self._model = QStringModel(None)
        self._proxy = QSortFilterProxyModel(self)
        self._proxy.setSourceModel(self._model)
        self._proxy.setFilterCaseSensitivity(Qt.CaseInsensitive)
        self.setModel(self._proxy)

        self.setSortingEnabled(True)
        self.setSelectionMode(QAbstractItemView.SingleSelection)

        # let the last column (string) fill table width
        self.horizontalHeader().setSectionResizeMode(QHeaderView.Fixed)
        self.horizontalHeader().setSectionResizeMode(2, QHeaderView.Stretch)

        self.doubleClicked.connect(self._on_string_selected)

    #
    # Properties
    #

    @property
    def cfg(self):
        return self._model.cfg

    @cfg.setter
    def cfg(self, v):
        self._model.cfg = v
        self.fast_resize()

    @property
    def xrefs(self):
        return self._model.xrefs

    @xrefs.setter
    def xrefs(self, v):
        self._model.xrefs = v

    @property
    def function(self):
        return self._model.function

    @function.setter
    def function(self, v):
        self._model.function = v
        self.fast_resize()

    @property
    def filter_string(self):
        return self._filter

    @filter_string.setter
    def filter_string(self, v):
        self._filter = v
        if isinstance(v, re.Pattern):
            self._proxy.setFilterRegExp(self._filter.pattern)
        else:
            self._proxy.setFilterWildcard(self._filter)
        self._proxy.setFilterKeyColumn(2)

    #
    # Public methods
    #

    def fast_resize(self):
        self.setVisible(False)
        self.resizeColumnsToContents()
        self.setVisible(True)

    #
    # Event handlers
    #

    def _on_string_selected(self, model_index):
        model_index = self._proxy.mapToSource(model_index)
        selected_index = model_index.row()
        if self._model is None:
            return
        if 0 <= selected_index < len(self._model.values):
            selected_item = self._model.values[selected_index]
        else:
            selected_item = None

        if self._selected is not None:
            self._selected(selected_item)
예제 #10
0
class FE14ChapterEditor(Ui_FE14ChapterEditor):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("Chapter Editor")
        self.setWindowIcon(QIcon("paragon.ico"))
        self.error_dialog = None

        module_service = locator.get_scoped("ModuleService")
        self.chapter_module = module_service.get_module("Chapters")
        self.proxy_model = QSortFilterProxyModel()
        self.proxy_model.setSourceModel(self.chapter_module.entries_model)
        self.proxy_model.setFilterCaseSensitivity(QtCore.Qt.CaseInsensitive)
        self.chapter_list_view.setModel(self.proxy_model)

        self.chapter_search_bar.textChanged.connect(self._update_filter)
        self.chapter_list_view.selectionModel().currentRowChanged.connect(
            self._update_selection)
        self.add_chapter_action.triggered.connect(
            self._on_add_chapter_triggered)
        self.hide_selector_action.triggered.connect(
            self._on_toggle_selector_triggered)

        self._update_selection(QModelIndex())

    def _update_filter(self):
        self.proxy_model.setFilterRegExp(self.search_field.text())

    def _update_selection(self, index):
        service = locator.get_scoped("ChapterService")
        data = self.proxy_model.data(index, QtCore.Qt.UserRole)
        chapter_data: Optional[
            ChapterData] = service.get_chapter_data_from_chapter(
                data) if data else None
        person_module = chapter_data.person if chapter_data else None
        message_archive = chapter_data.conversation_data if chapter_data else None
        self.config_tab.update_chapter_data(chapter_data)
        self.map_tab.update_chapter_data(chapter_data)
        self.characters_tab.set_module(person_module)
        self.conversation_tab.set_archive(message_archive)

    def _on_add_chapter_triggered(self):
        # Get the chapter to use as a base
        choices = self._create_chapter_choice_list()
        (choice, ok) = QInputDialog.getItem(self, "Select Base Chapter",
                                            "Base Chapter", choices)
        if not ok:
            return
        source_chapter = self._get_chapter_from_choice(choice, choices)

        # Get the desired CID.
        (desired_cid,
         ok) = QInputDialog.getText(self, "Enter a CID for the new chapter.",
                                    "CID")
        if not ok:
            return

        # Validate the CID.
        service = locator.get_scoped("ChapterService")
        if service.is_cid_in_use(desired_cid):
            self.error_dialog = ErrorDialog("The CID \"" + desired_cid +
                                            "\" is already in use.")
            self.error_dialog.show()
            return
        if not desired_cid.startswith("CID_"):
            self.error_dialog = ErrorDialog("CID must start with the \"CID_\"")
            self.error_dialog.show()
            return

        # Create the chapter
        service.create_chapter(source_chapter, desired_cid)

    def _create_chapter_choice_list(self):
        choices = []
        for i in range(0, len(self.chapter_module.entries)):
            chapter = self.chapter_module.entries[i]
            cid = chapter["CID"].value
            choices.append(str(i) + ". " + cid)
        return choices

    def _get_chapter_from_choice(self, choice, choices_list):
        for i in range(0, len(choices_list)):
            if choice == choices_list[i]:
                return self.chapter_module.entries[i]
        raise ValueError

    def _on_toggle_selector_triggered(self):
        self.selector_widget.setVisible(not self.selector_widget.isVisible())
        self.visual_splitter.setVisible(not self.visual_splitter.isVisible())
class InstallPluginDialog(QDialog):

    item_selected = Signal(str)

    def __init__(self, parent):
        """Initialize class"""
        super().__init__(parent)
        self.setWindowTitle('Install plugin')
        QVBoxLayout(self)
        self._line_edit = QLineEdit(self)
        self._line_edit.setPlaceholderText("Search registry...")
        self._list_view = QListView(self)
        self._model = QSortFilterProxyModel(self)
        self._source_model = _InstallPluginModel(self)
        self._model.setSourceModel(self._source_model)
        self._model.setFilterCaseSensitivity(Qt.CaseInsensitive)
        self._list_view.setModel(self._model)
        self._timer = QTimer(self)
        self._timer.setInterval(200)
        self._button_box = QDialogButtonBox(self)
        self._button_box.setStandardButtons(QDialogButtonBox.Cancel
                                            | QDialogButtonBox.Ok)
        self._button_box.button(QDialogButtonBox.Ok).setEnabled(False)
        self.layout().addWidget(self._line_edit)
        self.layout().addWidget(self._list_view)
        self.layout().addWidget(self._button_box)
        self.setAttribute(Qt.WA_DeleteOnClose)
        self.setMinimumWidth(400)
        self._button_box.button(QDialogButtonBox.Cancel).clicked.connect(
            self.close)
        self._button_box.button(QDialogButtonBox.Ok).clicked.connect(
            self._handle_ok_clicked)
        self._list_view.doubleClicked.connect(self._emit_item_selected)
        self._list_view.selectionModel().selectionChanged.connect(
            self._update_ok_button_enabled)
        self._line_edit.textEdited.connect(self._handle_search_text_changed)
        self._timer.timeout.connect(self._filter_model)

    def populate_list(self, names):
        for name in names:
            self._source_model.appendRow(QStandardItem(name))

    @Slot(str)
    def _handle_search_text_changed(self, _text):
        self._timer.start()

    def _filter_model(self):
        self._model.setFilterRegExp(self._line_edit.text())

    @Slot(bool)
    def _handle_ok_clicked(self, _=False):
        index = self._list_view.currentIndex()
        self._emit_item_selected(index)

    @Slot("QModelIndex")
    def _emit_item_selected(self, index):
        if not index.isValid():
            return
        self.item_selected.emit(index.data(Qt.DisplayRole))
        self.close()

    @Slot("QItemSelection", "QItemSelection")
    def _update_ok_button_enabled(self, _selected, _deselected):
        on = self._list_view.selectionModel().hasSelection()
        self._button_box.button(QDialogButtonBox.Ok).setEnabled(on)