PyQt5 removeRowsを使ってQTreeViewの行を削除する

2020/02/26 categories:PyQt5| tags:Python|PyQt5|QTreeView|

QTreeViewのremoveRowsメソッドを使って行の削除を試してみました。

removeRowsメソッド

removeRowsメソッドの処理はbeginRemoveRowsを発行してからアイテムを削除した後にendRemoveRowsを発行するだけです。

def removeRows(self, row, count, parent=QtCore.QModelIndex()):
    if not parent.isValid():
        parent_item = self.root_item
    else:
        parent_item = parent.internalPointer()
    self.beginRemoveRows(parent, row, row + count - 1)
    parent_item.removeChildren(row, row + count)
    self.endRemoveRows()

選択したインデックスの削除

QMainwindowなどから選択したアイテムを削除する場合は少し処理が面倒になります。まずは選択したアイテムから行番号の重複がないリストを作成します。

def unique_row_indexes(self, indexes):
    indexes2 = []
    for index in indexes:
        if not index.row() in set( i.row() for i in indexes2 if i.parent() == index.parent() ):
            indexes2.append(index)
    return indexes2

selected = self.unique_row_indexes(self.ui.treeView.selectedIndexes())

次に、先ほど作成したリストから、階層が最も浅いインデックスだけを再帰的に抽出します。例えば、Aの子がBでAとBが選択されていた場合はAのみを抽出します。

def is_selected_parent(index, selected):
    if index == QtCore.QModelIndex():
        return False
    parent = index.parent()
    if parent in selected:
        return True
    return is_selected_parent(parent, selected)

indexes = [ index for index in selected if not is_selected_parent(index, selected) ]

その後、アイテムを親ごとのリストに分けます。

parent_splited = {}
for index in indexes:
    if not index.parent() in parent_splited:
        parent_splited[index.parent()] = []
    parent_splited[index.parent()].append(index)

そして最後に、親ごとに分けられたリストの最後からアイテムを削除していきます。

for key in parent_splited:
    _sorted = sorted( parent_splited[key], key=lambda t:t.row() )[::-1]
    for index in _sorted:
        self.model.removeRows(index.row(), 1, index.parent())

以上をまとめて、下記のようなメソッドにしました。

def delete_item(self):
    def is_selected_parent(index, selected):
        if index == QtCore.QModelIndex():
            return False
        parent = index.parent()
        if parent in selected:
            return True
        return is_selected_parent(parent, selected)

    selected = self.unique_row_indexes(self.ui.treeView.selectedIndexes())
    indexes = [ index for index in selected if not is_selected_parent(index, selected) ]

    parent_splited = {}
    for index in indexes:
        if not index.parent() in parent_splited:
            parent_splited[index.parent()] = []
        parent_splited[index.parent()].append(index)
    
    for key in parent_splited:
        _sorted = sorted( parent_splited[key], key=lambda t:t.row() )[::-1]
        for index in _sorted:
            self.model.removeRows(index.row(), 1, index.parent())

Share post

Related Posts

コメント