Exemplo n.º 1
0
    def get_indexes(self):
        indexes = []
        row_count = self.rowCount(QtCore.QModelIndex())
        for row in range(row_count):
            idx = self.index(row, 0, QtCore.QModelIndex())
            indexes.append(idx)

        return indexes
Exemplo n.º 2
0
class SelectorWidget(QtWidgets.QWidget):

    container_picked = QtCore.Signal(str, dict)
    host_selected = QtCore.Signal(str)
    version_changed = QtCore.Signal(str, io.ObjectId)

    def __init__(self, side, parent=None):
        super(SelectorWidget, self).__init__(parent=parent)

        def icon(name):
            return qtawesome.icon("fa.{}".format(name), color=SIDE_COLOR[side])

        body = {
            "tab": QtWidgets.QTabWidget(),
        }

        selector = {
            "host": HostSelectorWidget(),
            "databse": DatabaseSelectorWidget(),
        }

        body["tab"].addTab(selector["databse"], icon("cloud"), "Published")
        body["tab"].addTab(selector["host"], icon("home"), "In Scene")

        layout = QtWidgets.QHBoxLayout(self)
        layout.addWidget(body["tab"])

        # Connect

        selector["host"].container_picked.connect(self.on_container_picked)
        selector["host"].host_selected.connect(self.on_host_selected)
        selector["databse"].version_changed.connect(self.on_version_changed)

        # Init

        self.selector = selector
        self.side = side

        if not has_host() or side == SIDE_B:
            body["tab"].setCurrentIndex(0)
        else:
            body["tab"].setCurrentIndex(1)

    def connect_comparer(self, comparer):
        self.container_picked.connect(comparer.on_container_picked)
        self.host_selected.connect(comparer.on_host_selected)
        self.version_changed.connect(comparer.on_version_changed)

    def on_container_picked(self, container):
        self.container_picked.emit(self.side, container)

    def on_host_selected(self):
        self.host_selected.emit(self.side)

    def on_version_changed(self, version_id):
        self.version_changed.emit(self.side, version_id)
Exemplo n.º 3
0
    def calculate_window_geometry(self):
        """Respond to status changes

        On creation, align window with screen bottom right.

        """

        window = self

        width = window.width()
        width = max(width, window.minimumWidth())

        height = window.height()
        height = max(height, window.sizeHint().height())

        desktop_geometry = QtWidgets.QDesktopWidget().availableGeometry()
        screen_geometry = window.geometry()

        screen_width = screen_geometry.width()
        screen_height = screen_geometry.height()

        # Calculate width and height of system tray
        systray_width = screen_geometry.width() - desktop_geometry.width()
        systray_height = screen_geometry.height() - desktop_geometry.height()

        padding = 10

        x = screen_width - width
        y = screen_height - height

        x -= systray_width + padding
        y -= systray_height + padding

        return QtCore.QRect(x, y, width, height)
Exemplo n.º 4
0
class ResolutionDelegate(QtWidgets.QStyledItemDelegate):
    # DEPRECATED

    value_changed = QtCore.Signal(list)

    def displayText(self, value, locale):
        return "{} x {}".format(*value)

    def createEditor(self, parent, option, index):
        editor = ResolutionEditor(parent)

        def commit_data(value):
            self.commitData.emit(editor)  # Update model data
            self.value_changed.emit(value)

        editor.value_changed.connect(commit_data)

        return editor

    def setEditorData(self, editor, index):
        value = index.data(QtCore.Qt.DisplayRole)
        editor.set_value(value)

    def setModelData(self, editor, model, index):
        value = editor.get_value()
        model.setData(index, value)

    def updateEditorGeometry(self, editor, option, index):
        editor.setGeometry(option.rect)
Exemplo n.º 5
0
class NameEditDelegate(QtWidgets.QStyledItemDelegate):

    name_changed = QtCore.Signal()

    def displayText(self, value, locale):
        return value

    def createEditor(self, parent, option, index):
        editor = QtWidgets.QLineEdit(parent)

        def commit_data():
            self.commitData.emit(editor)  # Update model data
            self.name_changed.emit()  # Display model data

        editor.editingFinished.connect(commit_data)

        return editor

    def setEditorData(self, editor, index):
        value = index.data(QtCore.Qt.DisplayRole)
        editor.setText(value)

    def setModelData(self, editor, model, index):
        name = editor.text()
        model.setData(index, name)

    def updateEditorGeometry(self, editor, option, index):
        editor.setGeometry(option.rect)
Exemplo n.º 6
0
    def copy_file_to_clipboard(path):
        from avalon.vendor.Qt import QtCore, QtWidgets

        app = QtWidgets.QApplication.instance()
        assert app, "Must have running QApplication instance"

        # Build mime data for clipboard
        file_path = QtCore.QUrl.fromLocalFile(path)
        byte_array = QtCore.QByteArray("copy\n").append(file_path)

        mime = QtCore.QMimeData()
        mime.setData("text/uri-list", byte_array)

        # Set to Clipboard
        clipboard = app.clipboard()
        clipboard.setMimeData(mime)
Exemplo n.º 7
0
class MatchOutliner(QtWidgets.QWidget):

    selection_changed = QtCore.Signal()

    def __init__(self, parent=None):
        QtWidgets.QWidget.__init__(self, parent)

        # look manager layout
        layout = QtWidgets.QVBoxLayout(self)
        layout.setContentsMargins(0, 0, 0, 0)
        layout.setSpacing(10)

        # Looks from database
        title = QtWidgets.QLabel("Matches:")
        title.setAlignment(QtCore.Qt.AlignLeft)
        title.setStyleSheet("font-weight: bold; font-size: 12px")

        model = models.MatchModel()
        view = views.View()
        view.setModel(model)
        view.setSortingEnabled(False)
        view.setHeaderHidden(True)
        view.setMinimumHeight(180)
        view.setIndentation(10)

        layout.addWidget(title)
        layout.addWidget(view)

        selection_model = view.selectionModel()
        selection_model.selectionChanged.connect(self.selection_changed)

        self.view = view
        self.model = model
        self._selection_model = selection_model

    def clear(self):
        self.model.clear()

    def add_items(self, items):
        self.model.add_items(items)

    def clear_selection(self):
        flags = self._selection_model.Clear
        self._selection_model.select(QtCore.QModelIndex(), flags)

    def select_index(self, index, flags=None):
        flags = flags or self._selection_model.ClearAndSelect
        self._selection_model.select(index, flags)

    def get_selected_items(self):
        """Get current selected items from view

        Returns:
            list: list of dictionaries
        """

        datas = [i.data(NODEROLE) for i in self.view.get_indices()]
        items = [d for d in datas if d is not None]  # filter Nones

        return items
Exemplo n.º 8
0
    def __init__(self, parent=None):
        QtWidgets.QWidget.__init__(self, parent)

        # look manager layout
        layout = QtWidgets.QVBoxLayout(self)
        layout.setContentsMargins(0, 0, 0, 0)
        layout.setSpacing(10)

        # Looks from database
        title = QtWidgets.QLabel("Looks")
        title.setAlignment(QtCore.Qt.AlignCenter)
        title.setStyleSheet("font-weight: bold; font-size: 12px")
        title.setAlignment(QtCore.Qt.AlignCenter)

        model = models.LookModel()

        # Proxy for dynamic sorting
        proxy = QtCore.QSortFilterProxyModel()
        proxy.setSourceModel(model)

        view = views.View()
        view.setModel(proxy)
        view.setMinimumHeight(180)
        view.setToolTip("Use right mouse button menu for direct actions")
        view.customContextMenuRequested.connect(self.right_mouse_menu)
        view.sortByColumn(0, QtCore.Qt.AscendingOrder)

        layout.addWidget(title)
        layout.addWidget(view)

        self.view = view
        self.model = model
Exemplo n.º 9
0
class Navigation(QtWidgets.QWidget):
    """Navigation panel widget"""

    index_changed = QtCore.Signal(int)
    log = logging.getLogger("Navigation")

    def __init__(self, parent=None):
        QtWidgets.QWidget.__init__(self, parent=parent)

        # self.setWindowFlag()
        self.setStyleSheet(style.flat_button)

        layout = QtWidgets.QVBoxLayout()

        dynamic_layout = QtWidgets.QVBoxLayout()
        static_layout = QtWidgets.QVBoxLayout()
        static_layout.addStretch()

        layout.addLayout(dynamic_layout)
        layout.addStretch()
        layout.addLayout(static_layout)

        self.dynamic_layout = dynamic_layout
        self.static_layout = static_layout

        self.setLayout(layout)
        self.layout = layout

    def add_button(self, label, order, widget=None):
        """Add a button to the navigation panel with the given label and order

        Args:
            label(str): Name displayed on the button
            order(int): Number which dictates its order in the panel
            widget(QtWidgets.QWidget): Instance of a widget

        Returns:
            None
        """

        if order < 0:
            layout = self.static_layout
        else:
            layout = self.dynamic_layout

        # Check new position
        widget_at_item = layout.itemAt(abs(order))
        if widget_at_item:
            self.log.warning("Found multiple items for the same order: `%i`" %
                             order)
            return

        button = QtWidgets.QPushButton(label)
        if widget:
            button.clicked.connect(partial(widget.show))

        layout.insertWidget(order, button)

        return button
Exemplo n.º 10
0
    def __init__(self, parent=None):
        super(ComparingTable, self).__init__(parent=parent)

        data = {
            "model": models.ComparerModel(),
            "proxy": QtCore.QSortFilterProxyModel(),
            "view": QtWidgets.QTreeView(),
            "diff": delegates.DiffDelegate(),
            "path": delegates.PathTextDelegate(),
        }

        data["view"].setIndentation(20)
        data["view"].setStyleSheet("""
            QTreeView::item{
                padding: 6px 1px;
                border: 0px;
            }
        """)
        data["view"].setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
        data["view"].setAllColumnsShowFocus(True)
        data["view"].setAlternatingRowColors(True)
        data["view"].setSortingEnabled(True)
        data["view"].setSelectionBehavior(
            QtWidgets.QAbstractItemView.SelectItems)
        data["view"].setSelectionMode(
            QtWidgets.QAbstractItemView.ExtendedSelection)

        header = data["view"].header()
        header.setMinimumSectionSize(delegates.DiffDelegate.ICON_SPACE)

        # Delegate
        diff_delegate = data["diff"]
        column = data["model"].Columns.index("diff")
        data["view"].setItemDelegateForColumn(column, diff_delegate)

        path_delegate = data["path"]
        column = data["model"].Columns.index(SIDE_A)
        data["view"].setItemDelegateForColumn(column, path_delegate)
        column = data["model"].Columns.index(SIDE_B)
        data["view"].setItemDelegateForColumn(column, path_delegate)

        # Set Model
        data["proxy"].setSourceModel(data["model"])
        data["view"].setModel(data["proxy"])

        layout = QtWidgets.QHBoxLayout(self)
        layout.addWidget(data["view"])

        # Connect
        data["view"].customContextMenuRequested.connect(self.on_context_menu)

        # Init

        data["view"].setColumnWidth(0, 90)  # "diff" column
        data["view"].setColumnWidth(1, 310)   # "side A" column

        self.data = data
Exemplo n.º 11
0
def _parseMapString(exprText):
    """Return a list of map file item from expression in an object attribute

    This function was modified from `ExpressionUI.parseMapString`.

    """
    from xgenm.ui.widgets.xgExpressionUI import ExpressionUI

    # vmap and map expressions
    mapExprStrings = _getMapExprStrings()

    exprStrings = [
        [mapExprStrings[0], "3dpaint"],
        [mapExprStrings[1], "file"],
        [mapExprStrings[2], "vpaint"],
        [mapExprStrings[3], ""],  # map() without comment
        [mapExprStrings[4], ""],  # vmap() without comment
        [mapExprStrings[5], "_plain"],  # plain map(), no comment
        [mapExprStrings[6], "_plain"],  # plain vmap(), no comment
    ]

    poses = []
    retMaps = []
    for s in exprStrings:
        re = QtCore.QRegExp(s[0])
        offset = 0
        while True:
            item = ExpressionUI.MapItem()
            pos = re.indexIn(exprText, offset)
            if (pos < 0):
                break

            offset = pos + 1

            if pos in poses:
                # Possible already matched via previous regex if current
                # regex does no matching comment string.
                continue
            poses.append(pos)

            if s[1] == "_plain":
                item.name = ""
                item.file = re.cap(1)
                item.mode = ""
            else:
                item.name = re.cap(1)
                item.file = re.cap(2)
                item.mode = s[1]

            if s[1] == "3dpaint":
                item.mode = item.mode + "," + re.cap(3)

            item.pos = pos

            retMaps.append(item)

    return retMaps
Exemplo n.º 12
0
 def data(self, index, role=None):
     if not index.isValid() or not (0 <= index.row() < len(self.items)):
         return QtCore.QVariant()
     if role == QtCore.Qt.DisplayRole:
         return self.items[index.row()][1]
     elif role == QtCore.Qt.DecorationRole:
         return self.icons[self.items[index.row()][0]]
     elif role == QtCore.Qt.UserRole:
         return self.items[index.row()]
Exemplo n.º 13
0
    def parent(self, index):

        item = index.internalPointer()
        parent_item = item.parent()

        # If it has no parents we return invalid
        if parent_item == self._root_item or not parent_item:
            return QtCore.QModelIndex()

        return self.createIndex(parent_item.row(), 0, parent_item)
Exemplo n.º 14
0
    def mousePressEvent(self, event):

        index = self.indexAt(event.pos())
        if not index.isValid():
            # clear the selection
            self.clearSelection()
            # clear the current index
            self.setCurrentIndex(QtCore.QModelIndex())

        QtWidgets.QTreeView.mousePressEvent(self, event)
Exemplo n.º 15
0
    def parent(self, index):

        node = index.internalPointer()
        parent_node = node.parent()

        # If it has no parents we return invalid
        if parent_node == self._root_node or not parent_node:
            return QtCore.QModelIndex()

        return self.createIndex(parent_node.row(), 0, parent_node)
Exemplo n.º 16
0
    def filterAcceptsRow(self, row=0, parent=QtCore.QModelIndex()):
        model = self.sourceModel()
        index = model.index(row, 0, parent=parent)

        # Ensure index is valid
        if not index.isValid() or index is None:
            return True

        node = model.data(index, TreeModel.ItemRole)

        return node.get("status", 0) > 0
Exemplo n.º 17
0
    def refresh_side(self, side, profile, host=False):

        items = self._root_item.children()
        root_index = QtCore.QModelIndex()

        # Remove previous data of this side

        remove = list()
        for item in items:
            if item.has_other(side):
                item.pop_this(side)
            else:
                remove.append(item)

        for item in remove:
            row = item.row()
            self.beginRemoveRows(root_index, row, row)
            items.remove(item)
            self.endRemoveRows()

        # Place new data

        shared_root = self.extract_shared_root(profile)
        self._origin_shared_root = shared_root

        for name, data in profile.items():

            data["longName"] = data.get("fullPath", name)
            data["shortName"] = name[len(shared_root):]
            data["fromHost"] = host

            if name in items:
                # Has matched
                item = items[items.index(name)]
                item.add_this(side, data, matched=1)
                item.compare()
            else:
                id = data["avalonId"]

                for item in items:
                    if item.id == id:
                        # Matched by Id
                        item.add_this(side, data, matched=2)
                        item.compare()
                        break

                else:
                    # No match
                    item = ComparerItem(name, id)
                    item.add_this(side, data)
                    last = self.rowCount(root_index)
                    self.beginInsertRows(root_index, last, last)
                    self.add_child(item)
                    self.endInsertRows()
Exemplo n.º 18
0
    def _validate_queue_entry(self, entry):
        """If an entry already exists return false"""

        parent = QtCore.QModelIndex()
        for row in range(self.queue_model.rowCount(parent)):
            idx = self.queue_model.index(row, 0, parent)
            data = idx.data(self._noderole)
            if entry == data:
                self.log.info("Already in queue")
                return False

        return True
Exemplo n.º 19
0
    def on_selected(self, *args, **kwargs):
        # Sync view selection

        if not self._selection_sync:
            return

        OBJ = {
            "view": self.widgets["view"],
            "model": self.widgets["view"].model(),
        }

        if not OBJ["model"].rowCount(QtCore.QModelIndex()):
            return

        OBJ["view"].clearSelection()

        selected = set()

        sel = OpenMaya.MGlobal.getActiveSelectionList()
        iter = OpenMaya.MItSelectionList(sel)

        # Loop though iterator objects
        while not iter.isDone():
            try:
                obj = iter.getDependNode()
                dagPath = OpenMaya.MDagPath.getAPathTo(obj)
                fullname = dagPath.fullPathName()
            except RuntimeError:
                pass
            else:
                selected.add(fullname)
            finally:
                iter.next()

        if not selected:
            return

        # Hightlight item
        selection_model = OBJ["view"].selectionModel()
        selection = selection_model.selection()

        for index in tools_lib.iter_model_rows(OBJ["model"], 0):
            item = index.data(model.SelectionModel.ItemRole)
            node = item.get("node")
            if node in selected:
                selection.select(index, index.sibling(index.row(), 1))
                selected.remove(node)

            if len(selected) == 0:
                break

        selection_model.select(selection, selection_model.Select)
        OBJ["view"].scrollTo(index)  # Ensure visible
Exemplo n.º 20
0
Arquivo: app.py Projeto: kalisp/pype
 def resizeEvent(self, event=None):
     ''' Helps resize shadow widget
     '''
     position_x = (self.frameGeometry().width() -
                   self.shadow_widget.frameGeometry().width()) / 2
     position_y = (self.frameGeometry().height() -
                   self.shadow_widget.frameGeometry().height()) / 2
     self.shadow_widget.move(position_x, position_y)
     w = self.frameGeometry().width()
     h = self.frameGeometry().height()
     self.shadow_widget.resize(QtCore.QSize(w, h))
     if event:
         super().resizeEvent(event)
Exemplo n.º 21
0
    def copy_file_to_clipboard(path):
        from avalon.vendor.Qt import QtCore, QtWidgets

        clipboard = QtWidgets.QApplication.clipboard()
        assert clipboard, "Must have running QApplication instance"

        # Build mime data for clipboard
        data = QtCore.QMimeData()
        url = QtCore.QUrl.fromLocalFile(path)
        data.setUrls([url])

        # Set to Clipboard
        clipboard.setMimeData(data)
Exemplo n.º 22
0
    def index(self, row, column, parent):
        """Return index for row/column under parent"""

        if not parent.isValid():
            parent_item = self._root_item
        else:
            parent_item = parent.internalPointer()

        child_item = parent_item.child(row)
        if child_item:
            return self.createIndex(row, column, child_item)
        else:
            return QtCore.QModelIndex()
Exemplo n.º 23
0
def main(launch_args):
    # Be sure server won't crash at any moment but just print traceback
    sys.excepthook = safe_excepthook

    # Create QtApplication for tools
    # - QApplicaiton is also main thread/event loop of the server
    qt_app = QtWidgets.QApplication([])

    # Execute pipeline installation
    api.install(tvpaint)

    # Create Communicator object and trigger launch
    # - this must be done before anything is processed
    communicator = CommunicationWrapper.create_communicator(qt_app)
    communicator.launch(launch_args)

    def process_in_main_thread():
        """Execution of `MainThreadItem`."""
        item = communicator.main_thread_listen()
        if item:
            item.execute()

    timer = QtCore.QTimer()
    timer.setInterval(100)
    timer.timeout.connect(process_in_main_thread)
    timer.start()

    # Register terminal signal handler
    def signal_handler(*_args):
        print("You pressed Ctrl+C. Process ended.")
        communicator.stop()

    signal.signal(signal.SIGINT, signal_handler)
    signal.signal(signal.SIGTERM, signal_handler)

    qt_app.setQuitOnLastWindowClosed(False)
    qt_app.setStyleSheet(style.load_stylesheet())

    # Load avalon icon
    icon_path = get_icon_path()
    if icon_path:
        icon = QtGui.QIcon(icon_path)
        qt_app.setWindowIcon(icon)

    # Set application name to be able show application icon in task bar
    if platform.system().lower() == "windows":
        ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID(
            u"WebsocketServer")

    # Run Qt application event processing
    sys.exit(qt_app.exec_())
Exemplo n.º 24
0
    def __init__(self, parent=None):
        super(SequenceWidget, self).__init__(parent=parent)

        data = {
            "model": SequenceModel(),
            "proxy": QtCore.QSortFilterProxyModel(),
            "view": QtWidgets.QTreeView(),
            "fpatternDel": None,
            "nameDel": None,
        }

        data["proxy"].setSourceModel(data["model"])
        data["view"].setModel(data["proxy"])
        data["fpatternDel"] = delegates.LineHTMLDelegate(data["view"])
        data["nameDel"] = delegates.NameEditDelegate()

        fpattern_delegate = data["fpatternDel"]
        column = data["model"].Columns.index("fpattern")
        data["view"].setItemDelegateForColumn(column, fpattern_delegate)

        name_delegate = data["nameDel"]
        column = data["model"].Columns.index("name")
        data["view"].setItemDelegateForColumn(column, name_delegate)

        data["proxy"].setSortCaseSensitivity(QtCore.Qt.CaseInsensitive)
        data["view"].setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
        data["view"].setSelectionMode(ExtendedSelection)
        data["view"].setSortingEnabled(True)
        data["view"].sortByColumn(0, QtCore.Qt.AscendingOrder)
        data["view"].setAlternatingRowColors(True)
        data["view"].setAllColumnsShowFocus(True)
        data["view"].setIndentation(6)
        data["view"].setStyleSheet("""
            QTreeView::item{
                padding: 8px 1px;
                border: 0px;
            }
        """)

        data["view"].setColumnWidth(0, 360)  # fpattern
        data["view"].setColumnWidth(1, 100)  # name
        data["view"].setColumnWidth(2, 80)  # frames

        layout = QtWidgets.QVBoxLayout(self)
        layout.addWidget(data["view"])
        layout.setContentsMargins(0, 0, 0, 0)

        data["view"].customContextMenuRequested.connect(self.on_context_menu)

        self.data = data
    def copy_id_to_clipboard(path):
        from avalon.vendor.Qt import QtCore, QtWidgets

        app = QtWidgets.QApplication.instance()
        assert app, "Must have running QApplication instance"

        # Build mime data for clipboard
        mime = QtCore.QMimeData()
        mime.setText(path)
        mime.setUrls([QtCore.QUrl.fromLocalFile(path)])

        # Set to Clipboard
        clipboard = app.clipboard()
        clipboard.setMimeData(mime)
Exemplo n.º 26
0
    def _get_queued_items(self):
        """Get all queued items in form of dictionaries
        Returns:
            list
        """

        items = []

        parent = QtCore.QModelIndex()
        for row in range(self.queue_model.rowCount(parent)):
            idx = self.queue_model.index(row, 0, parent)
            data = idx.data(self._noderole)
            items.append(data)

        return items
Exemplo n.º 27
0
    def collected(self, with_keys=None):
        model = self.data["model"]
        with_keys = with_keys or list()
        sequences = dict()
        root_index = QtCore.QModelIndex()
        for row in range(model.rowCount(root_index)):
            index = model.index(row, column=0, parent=root_index)
            item = index.internalPointer()
            if all(item.get(k) for k in with_keys):
                if model._stereo:
                    item["fpattern"] = item["stereoPattern"]

                if item["name"] not in sequences:
                    sequences[item["name"]] = item

        return sequences
Exemplo n.º 28
0
    def clear_stage(self):
        all_nodes = self._root_item.children()

        if all(n.get("status", 0) == 0 for n in all_nodes):
            # All staged, clear all
            self.clear()
            return

        # Remove staged only
        root = QtCore.QModelIndex()
        for node in list(all_nodes):
            if node.get("status", 0) == 0:
                row = node.row()
                self.beginRemoveRows(root, row, row)
                all_nodes.remove(node)
                self.endRemoveRows()
Exemplo n.º 29
0
def _iter_model_rows(model, column, include_root=False):
    """Iterate over all row indices in a model"""
    indices = [QtCore.QModelIndex()]  # start iteration at root

    for index in indices:

        # Add children to the iterations
        child_rows = model.rowCount(index)
        for child_row in range(child_rows):
            child_index = model.index(child_row, column, index)
            indices.append(child_index)

        if not include_root and not index.isValid():
            continue

        yield index
Exemplo n.º 30
0
class View(QtWidgets.QTreeView):
    data_changed = QtCore.Signal()

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

        # view settings
        self.setAlternatingRowColors(False)
        self.setSortingEnabled(True)
        self.setSelectionMode(self.SingleSelection)
        self.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)

    def get_indices(self):
        """Get the selected rows"""
        selection_model = self.selectionModel()
        return selection_model.selectedRows()