移动项目时 QStandardItem 无法正确克隆
QStandardItem does not clone correctly when the items are moved
如以下代码所示,当您拖放一个项目时(使用 clone()
方法从 QStandardItem
子 class 编辑)您会得到一个 QStandardItem
而不是子class。此外 - 存储在 class 中或作为 setData 的一部分的数据丢失。我怀疑这是因为无法 'serialize' 数据。但我对如何 'save' 数据或元数据一无所知。如何保留 QObject
?下面的代码工作正常,但是一旦你移动了一个分支节点,分支中的所有节点和分支中的所有节点都会变成 QStandardItem
而不是 myItem
并且会丢失数据(如果它们有的话)。
# -*- coding: utf-8 -*-
"""
Created on Mon Nov 4 09:10:16 2019
Test of Tree view with subclassed QStandardItem and Drag and Drop
enabled. When you move a parent the parent looses the subclass and thus
the meta - however, it also looses the data: This is likely because
the data cannot be serialized. How to fix?
@author: tcarnaha
"""
import sys
from PyQt5 import QtGui, QtWidgets, QtCore
class myData():
def __init__(self, title):
self._title = title
self._stuff = dict()
self._obj = QtCore.QObject()
@property
def obj(self):
return self._obj
@obj.setter
def obj(self, value):
self._obj = value
@property
def title(self):
return self._title
@title.setter
def title(self, value):
self._title = value
class myItem(QtGui.QStandardItem):
def __init__(self, parent=None):
super(myItem, self).__init__(parent)
self._meta = None
@property
def meta(self):
return self._meta
@meta.setter
def meta(self, value):
self._meta = value
def clone(self):
print "My cloning"
old_data = self.data()
print "Old data [{}]".format(old_data)
old_meta = self.meta
obj = myItem()
obj.setData(old_data)
print "New data [{}]".format(obj.data())
obj.meta = old_meta
print "Clone is a ", obj.__class__
return obj
class mainWidget(QtWidgets.QMainWindow):
def __init__(self):
super(mainWidget, self).__init__()
self.model = QtGui.QStandardItemModel()
self.model.setItemPrototype(myItem())
self.view = QtWidgets.QTreeView()
self.view.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
self.view.customContextMenuRequested.connect(self.list_click)
self.view.setDragDropMode(QtWidgets.QAbstractItemView.InternalMove)
self.view.setDefaultDropAction(QtCore.Qt.MoveAction)
self.view.setDragDropOverwriteMode(False)
self.view.setAcceptDrops(True)
self.view.setDropIndicatorShown(True)
self.view.setDragEnabled(True)
self.view.setModel(self.model)
dataA = myData('A thing')
parentA = myItem()
parentA.setText('A')
parentA.setDragEnabled(True)
parentA.setDropEnabled(True)
parentA.setData(dataA)
parentA.meta = QtCore.QObject()
childa = myItem()
childa.setText('a')
childb = myItem()
childb.setText('b')
childc = myItem()
childc.setText('c')
parentA.appendRows([childa, childb, childc])
dataB = myData('B thing')
parentB = myItem()
parentB.setText('B')
parentB.setDragEnabled(True)
parentB.setDropEnabled(True)
parentB.setData(dataB)
parentB.meta = QtCore.QObject()
childd = myItem()
childd.setText('d')
childe = myItem()
childe.setText('e')
childf = myItem()
childf.setText('f')
parentB.appendRows([childd, childe, childf])
self.model.appendRow(parentA)
self.model.appendRow(parentB)
classAct = QtWidgets.QAction('Class', self)
classAct.triggered.connect(self.classIs)
dataAct = QtWidgets.QAction('Data', self)
dataAct.triggered.connect(self.dataIs)
metaAct = QtWidgets.QAction('Meta', self)
metaAct.triggered.connect(self.metaIs)
self.menu = QtWidgets.QMenu("Item info")
self.menu.addAction(classAct)
self.menu.addAction(dataAct)
self.menu.addAction(metaAct)
self.setCentralWidget(self.view)
@QtCore.pyqtSlot(QtCore.QPoint)
def list_click(self, position):
self.menu.popup(self.view.viewport().mapToGlobal(position))
def classIs(self):
selected_indexes = self.view.selectedIndexes()
for index in selected_indexes:
item = self.model.itemFromIndex(index)
print "Item {} Class {} ".format(item.text(), item.__class__())
def dataIs(self):
selected_indexes = self.view.selectedIndexes()
for index in selected_indexes:
item = self.model.itemFromIndex(index)
try:
print "Item {} data {} Object {}".format(item.text(),
item.data().title,
item.data().obj)
except Exception as exc:
print "Data exception ", exc
def metaIs(self):
selected_indexes = self.view.selectedIndexes()
for index in selected_indexes:
item = self.model.itemFromIndex(index)
try:
print "Item {} meta {} ".format(item.text(), item.meta)
except Exception as exc:
print "Meta exception ", exc
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
main = mainWidget()
main.show()
app.exec_()
你不是在克隆你的 class,而是一个正常的 QStandardItem
:
obj = super(myItem, self).clone()
这实际上意味着"call the clone()
method of the base class"。
当从单个 class 进行 subclass 时,super()
的行为与使用 subclass 实例作为第一个参数调用 class 方法完全一样,所以在这种情况下正是这样做的:
obj = QtGui.QStandardItem.clone(self)
super()
最常见的优点是简单和易于维护(如果您更改基础 class 您将要继承,您只需在子 class 中进行宣言);除此之外,它最重要的好处来自多重继承,即当您从 多个 基础 class 继承时,但由于这在 PyQt 中很少见,所以不是这样的;另外,多继承不可能有一个以上的 Qt class.
如setItemPrototype()
中所述(强调我的):
To provide your own prototype, subclass QStandardItem, reimplement
QStandardItem::clone() and set the prototype to be an instance of your
custom class.
什么 clone()
实际上是 does, indeed, is to use the QStandardItem(other)
构造函数,它创建 other 项目的 copy。
因此,您只需执行以下操作即可获得正确的克隆:
def clone(self):
obj = myItem(self)
obj.setData(self.data())
obj.meta = self.meta
return obj
这里有几个问题与对象如何被 Qt 和 PyQt 序列化有关。首先,在克隆 QStandardItem
时,只会复制标志和数据——其他所有内容都将被忽略(包括动态 python 属性)。其次,没有办法直接复制一个QObject
。这是因为它不能转换为 QVariant
(Qt 用于序列化)并且它不能被 pickle(PyQt 用于序列化)。
为了解决第二个问题,我们需要对所有QObject
个实例保持单独的引用,然后使用间接键稍后再次访问它们。可能有许多不同的方法可以实现这一点,但这里有一个非常简单的方法来说明基本思想:
objects = {}
class MyObject(QtCore.QObject):
def __init__(self, parent=None):
super(MyObject, self).__init__(parent)
self.setProperty('key', max(objects.keys() or [0]) + 1)
objects[self.property('key')] = self
所以这会自动将每个实例添加到全局缓存并为其提供唯一的查找键,以便以后可以轻松找到它。有了这个,myData
class 现在需要调整以使用 MyObject
class 以便 pickling is handled correctly:
class myData():
def __init__(self, title):
self._title = title
self._stuff = dict()
self._obj = MyObject()
def __setstate__(self, state):
self._obj = objects.get(state['obj'])
self._stuff = state['stuff']
self._title = state['title']
def __getstate__(self):
return {
'obj': self._obj and self._obj.property('key'),
'title': self._title,
'stuff': self._stuff,
}
解决第一个问题要简单得多:我们只需要确保任何动态 python 属性使用自定义数据角色将其基础值存储在项目的数据中。在这种特殊情况下,该值必须是项目 MyObject
实例的键,以便在拖放操作后可以检索它:
class myItem(QtGui.QStandardItem):
MetaRole = QtCore.Qt.UserRole + 1000
@property
def meta(self):
return objects.get(self.data(myItem.MetaRole))
@meta.setter
def meta(self, value):
self.setData(value.property('key'), myItem.MetaRole)
def clone(self):
print "My cloning"
obj = myItem(self)
print "Clone is a ", obj.__class__
return obj
以下是实现上述所有内容的原始脚本的工作版本。但是请记住,您几乎肯定需要对其进行调整以使其与您的真实代码一起正常工作。这只是一个有效的概念验证,展示了如何处理上述两个问题。
# -*- coding: utf-8 -*-
import sys
from PyQt5 import QtGui, QtWidgets, QtCore
objects = {}
class MyObject(QtCore.QObject):
def __init__(self, parent=None):
super(MyObject, self).__init__(parent)
self.setProperty('key', max(objects.keys() or [0]) + 1)
objects[self.property('key')] = self
class myData():
def __init__(self, title):
self._title = title
self._stuff = dict()
self._obj = MyObject()
def __setstate__(self, state):
self._obj = objects.get(state['obj'])
self._stuff = state['stuff']
self._title = state['title']
def __getstate__(self):
return {
'obj': self._obj.property('key'),
'title': self._title,
'stuff': self._stuff,
}
@property
def obj(self):
return self._obj
@obj.setter
def obj(self, value):
self._obj = value
@property
def title(self):
return self._title
@title.setter
def title(self, value):
self._title = value
class myItem(QtGui.QStandardItem):
MetaRole = QtCore.Qt.UserRole + 1000
@property
def meta(self):
return objects.get(self.data(myItem.MetaRole))
@meta.setter
def meta(self, value):
self.setData(value.property('key'), myItem.MetaRole)
def clone(self):
print "My cloning"
obj = myItem(self)
print "Clone is a ", obj.__class__
return obj
class mainWidget(QtWidgets.QMainWindow):
def __init__(self):
super(mainWidget, self).__init__()
self.model = QtGui.QStandardItemModel()
self.model.setItemPrototype(myItem())
self.view = QtWidgets.QTreeView()
self.view.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
self.view.customContextMenuRequested.connect(self.list_click)
self.view.setDragDropMode(QtWidgets.QAbstractItemView.InternalMove)
self.view.setDefaultDropAction(QtCore.Qt.MoveAction)
self.view.setDragDropOverwriteMode(False)
self.view.setAcceptDrops(True)
self.view.setDropIndicatorShown(True)
self.view.setDragEnabled(True)
self.view.setModel(self.model)
dataA = myData('A thing')
parentA = myItem()
parentA.setText('A')
parentA.setDragEnabled(True)
parentA.setDropEnabled(True)
parentA.setData(dataA)
parentA.meta = MyObject()
childa = myItem()
childa.setText('a')
childb = myItem()
childb.setText('b')
childc = myItem()
childc.setText('c')
parentA.appendRows([childa, childb, childc])
dataB = myData('B thing')
parentB = myItem()
parentB.setText('B')
parentB.setDragEnabled(True)
parentB.setDropEnabled(True)
parentB.setData(dataB)
parentB.meta = MyObject()
childd = myItem()
childd.setText('d')
childe = myItem()
childe.setText('e')
childf = myItem()
childf.setText('f')
parentB.appendRows([childd, childe, childf])
self.model.appendRow(parentA)
self.model.appendRow(parentB)
classAct = QtWidgets.QAction('Class', self)
classAct.triggered.connect(self.classIs)
dataAct = QtWidgets.QAction('Data', self)
dataAct.triggered.connect(self.dataIs)
metaAct = QtWidgets.QAction('Meta', self)
metaAct.triggered.connect(self.metaIs)
self.menu = QtWidgets.QMenu("Item info")
self.menu.addAction(classAct)
self.menu.addAction(dataAct)
self.menu.addAction(metaAct)
self.setCentralWidget(self.view)
@QtCore.pyqtSlot(QtCore.QPoint)
def list_click(self, position):
self.menu.popup(self.view.viewport().mapToGlobal(position))
def classIs(self):
selected_indexes = self.view.selectedIndexes()
for index in selected_indexes:
item = self.model.itemFromIndex(index)
print "Item {} Class {} ".format(item.text(), item.__class__())
def dataIs(self):
selected_indexes = self.view.selectedIndexes()
for index in selected_indexes:
item = self.model.itemFromIndex(index)
try:
print "Item {} data {} Object {}".format(item.text(),
item.data().title,
item.data().obj)
except Exception as exc:
print "Data exception ", exc
def metaIs(self):
selected_indexes = self.view.selectedIndexes()
for index in selected_indexes:
item = self.model.itemFromIndex(index)
try:
print "Item {} meta {} ".format(item.text(), item.meta)
except Exception as exc:
print "Meta exception ", exc
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
main = mainWidget()
main.show()
app.exec_()
如以下代码所示,当您拖放一个项目时(使用 clone()
方法从 QStandardItem
子 class 编辑)您会得到一个 QStandardItem
而不是子class。此外 - 存储在 class 中或作为 setData 的一部分的数据丢失。我怀疑这是因为无法 'serialize' 数据。但我对如何 'save' 数据或元数据一无所知。如何保留 QObject
?下面的代码工作正常,但是一旦你移动了一个分支节点,分支中的所有节点和分支中的所有节点都会变成 QStandardItem
而不是 myItem
并且会丢失数据(如果它们有的话)。
# -*- coding: utf-8 -*-
"""
Created on Mon Nov 4 09:10:16 2019
Test of Tree view with subclassed QStandardItem and Drag and Drop
enabled. When you move a parent the parent looses the subclass and thus
the meta - however, it also looses the data: This is likely because
the data cannot be serialized. How to fix?
@author: tcarnaha
"""
import sys
from PyQt5 import QtGui, QtWidgets, QtCore
class myData():
def __init__(self, title):
self._title = title
self._stuff = dict()
self._obj = QtCore.QObject()
@property
def obj(self):
return self._obj
@obj.setter
def obj(self, value):
self._obj = value
@property
def title(self):
return self._title
@title.setter
def title(self, value):
self._title = value
class myItem(QtGui.QStandardItem):
def __init__(self, parent=None):
super(myItem, self).__init__(parent)
self._meta = None
@property
def meta(self):
return self._meta
@meta.setter
def meta(self, value):
self._meta = value
def clone(self):
print "My cloning"
old_data = self.data()
print "Old data [{}]".format(old_data)
old_meta = self.meta
obj = myItem()
obj.setData(old_data)
print "New data [{}]".format(obj.data())
obj.meta = old_meta
print "Clone is a ", obj.__class__
return obj
class mainWidget(QtWidgets.QMainWindow):
def __init__(self):
super(mainWidget, self).__init__()
self.model = QtGui.QStandardItemModel()
self.model.setItemPrototype(myItem())
self.view = QtWidgets.QTreeView()
self.view.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
self.view.customContextMenuRequested.connect(self.list_click)
self.view.setDragDropMode(QtWidgets.QAbstractItemView.InternalMove)
self.view.setDefaultDropAction(QtCore.Qt.MoveAction)
self.view.setDragDropOverwriteMode(False)
self.view.setAcceptDrops(True)
self.view.setDropIndicatorShown(True)
self.view.setDragEnabled(True)
self.view.setModel(self.model)
dataA = myData('A thing')
parentA = myItem()
parentA.setText('A')
parentA.setDragEnabled(True)
parentA.setDropEnabled(True)
parentA.setData(dataA)
parentA.meta = QtCore.QObject()
childa = myItem()
childa.setText('a')
childb = myItem()
childb.setText('b')
childc = myItem()
childc.setText('c')
parentA.appendRows([childa, childb, childc])
dataB = myData('B thing')
parentB = myItem()
parentB.setText('B')
parentB.setDragEnabled(True)
parentB.setDropEnabled(True)
parentB.setData(dataB)
parentB.meta = QtCore.QObject()
childd = myItem()
childd.setText('d')
childe = myItem()
childe.setText('e')
childf = myItem()
childf.setText('f')
parentB.appendRows([childd, childe, childf])
self.model.appendRow(parentA)
self.model.appendRow(parentB)
classAct = QtWidgets.QAction('Class', self)
classAct.triggered.connect(self.classIs)
dataAct = QtWidgets.QAction('Data', self)
dataAct.triggered.connect(self.dataIs)
metaAct = QtWidgets.QAction('Meta', self)
metaAct.triggered.connect(self.metaIs)
self.menu = QtWidgets.QMenu("Item info")
self.menu.addAction(classAct)
self.menu.addAction(dataAct)
self.menu.addAction(metaAct)
self.setCentralWidget(self.view)
@QtCore.pyqtSlot(QtCore.QPoint)
def list_click(self, position):
self.menu.popup(self.view.viewport().mapToGlobal(position))
def classIs(self):
selected_indexes = self.view.selectedIndexes()
for index in selected_indexes:
item = self.model.itemFromIndex(index)
print "Item {} Class {} ".format(item.text(), item.__class__())
def dataIs(self):
selected_indexes = self.view.selectedIndexes()
for index in selected_indexes:
item = self.model.itemFromIndex(index)
try:
print "Item {} data {} Object {}".format(item.text(),
item.data().title,
item.data().obj)
except Exception as exc:
print "Data exception ", exc
def metaIs(self):
selected_indexes = self.view.selectedIndexes()
for index in selected_indexes:
item = self.model.itemFromIndex(index)
try:
print "Item {} meta {} ".format(item.text(), item.meta)
except Exception as exc:
print "Meta exception ", exc
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
main = mainWidget()
main.show()
app.exec_()
你不是在克隆你的 class,而是一个正常的 QStandardItem
:
obj = super(myItem, self).clone()
这实际上意味着"call the clone()
method of the base class"。
当从单个 class 进行 subclass 时,super()
的行为与使用 subclass 实例作为第一个参数调用 class 方法完全一样,所以在这种情况下正是这样做的:
obj = QtGui.QStandardItem.clone(self)
super()
最常见的优点是简单和易于维护(如果您更改基础 class 您将要继承,您只需在子 class 中进行宣言);除此之外,它最重要的好处来自多重继承,即当您从 多个 基础 class 继承时,但由于这在 PyQt 中很少见,所以不是这样的;另外,多继承不可能有一个以上的 Qt class.
如setItemPrototype()
中所述(强调我的):
To provide your own prototype, subclass QStandardItem, reimplement QStandardItem::clone() and set the prototype to be an instance of your custom class.
什么 clone()
实际上是 does, indeed, is to use the QStandardItem(other)
构造函数,它创建 other 项目的 copy。
因此,您只需执行以下操作即可获得正确的克隆:
def clone(self):
obj = myItem(self)
obj.setData(self.data())
obj.meta = self.meta
return obj
这里有几个问题与对象如何被 Qt 和 PyQt 序列化有关。首先,在克隆 QStandardItem
时,只会复制标志和数据——其他所有内容都将被忽略(包括动态 python 属性)。其次,没有办法直接复制一个QObject
。这是因为它不能转换为 QVariant
(Qt 用于序列化)并且它不能被 pickle(PyQt 用于序列化)。
为了解决第二个问题,我们需要对所有QObject
个实例保持单独的引用,然后使用间接键稍后再次访问它们。可能有许多不同的方法可以实现这一点,但这里有一个非常简单的方法来说明基本思想:
objects = {}
class MyObject(QtCore.QObject):
def __init__(self, parent=None):
super(MyObject, self).__init__(parent)
self.setProperty('key', max(objects.keys() or [0]) + 1)
objects[self.property('key')] = self
所以这会自动将每个实例添加到全局缓存并为其提供唯一的查找键,以便以后可以轻松找到它。有了这个,myData
class 现在需要调整以使用 MyObject
class 以便 pickling is handled correctly:
class myData():
def __init__(self, title):
self._title = title
self._stuff = dict()
self._obj = MyObject()
def __setstate__(self, state):
self._obj = objects.get(state['obj'])
self._stuff = state['stuff']
self._title = state['title']
def __getstate__(self):
return {
'obj': self._obj and self._obj.property('key'),
'title': self._title,
'stuff': self._stuff,
}
解决第一个问题要简单得多:我们只需要确保任何动态 python 属性使用自定义数据角色将其基础值存储在项目的数据中。在这种特殊情况下,该值必须是项目 MyObject
实例的键,以便在拖放操作后可以检索它:
class myItem(QtGui.QStandardItem):
MetaRole = QtCore.Qt.UserRole + 1000
@property
def meta(self):
return objects.get(self.data(myItem.MetaRole))
@meta.setter
def meta(self, value):
self.setData(value.property('key'), myItem.MetaRole)
def clone(self):
print "My cloning"
obj = myItem(self)
print "Clone is a ", obj.__class__
return obj
以下是实现上述所有内容的原始脚本的工作版本。但是请记住,您几乎肯定需要对其进行调整以使其与您的真实代码一起正常工作。这只是一个有效的概念验证,展示了如何处理上述两个问题。
# -*- coding: utf-8 -*-
import sys
from PyQt5 import QtGui, QtWidgets, QtCore
objects = {}
class MyObject(QtCore.QObject):
def __init__(self, parent=None):
super(MyObject, self).__init__(parent)
self.setProperty('key', max(objects.keys() or [0]) + 1)
objects[self.property('key')] = self
class myData():
def __init__(self, title):
self._title = title
self._stuff = dict()
self._obj = MyObject()
def __setstate__(self, state):
self._obj = objects.get(state['obj'])
self._stuff = state['stuff']
self._title = state['title']
def __getstate__(self):
return {
'obj': self._obj.property('key'),
'title': self._title,
'stuff': self._stuff,
}
@property
def obj(self):
return self._obj
@obj.setter
def obj(self, value):
self._obj = value
@property
def title(self):
return self._title
@title.setter
def title(self, value):
self._title = value
class myItem(QtGui.QStandardItem):
MetaRole = QtCore.Qt.UserRole + 1000
@property
def meta(self):
return objects.get(self.data(myItem.MetaRole))
@meta.setter
def meta(self, value):
self.setData(value.property('key'), myItem.MetaRole)
def clone(self):
print "My cloning"
obj = myItem(self)
print "Clone is a ", obj.__class__
return obj
class mainWidget(QtWidgets.QMainWindow):
def __init__(self):
super(mainWidget, self).__init__()
self.model = QtGui.QStandardItemModel()
self.model.setItemPrototype(myItem())
self.view = QtWidgets.QTreeView()
self.view.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
self.view.customContextMenuRequested.connect(self.list_click)
self.view.setDragDropMode(QtWidgets.QAbstractItemView.InternalMove)
self.view.setDefaultDropAction(QtCore.Qt.MoveAction)
self.view.setDragDropOverwriteMode(False)
self.view.setAcceptDrops(True)
self.view.setDropIndicatorShown(True)
self.view.setDragEnabled(True)
self.view.setModel(self.model)
dataA = myData('A thing')
parentA = myItem()
parentA.setText('A')
parentA.setDragEnabled(True)
parentA.setDropEnabled(True)
parentA.setData(dataA)
parentA.meta = MyObject()
childa = myItem()
childa.setText('a')
childb = myItem()
childb.setText('b')
childc = myItem()
childc.setText('c')
parentA.appendRows([childa, childb, childc])
dataB = myData('B thing')
parentB = myItem()
parentB.setText('B')
parentB.setDragEnabled(True)
parentB.setDropEnabled(True)
parentB.setData(dataB)
parentB.meta = MyObject()
childd = myItem()
childd.setText('d')
childe = myItem()
childe.setText('e')
childf = myItem()
childf.setText('f')
parentB.appendRows([childd, childe, childf])
self.model.appendRow(parentA)
self.model.appendRow(parentB)
classAct = QtWidgets.QAction('Class', self)
classAct.triggered.connect(self.classIs)
dataAct = QtWidgets.QAction('Data', self)
dataAct.triggered.connect(self.dataIs)
metaAct = QtWidgets.QAction('Meta', self)
metaAct.triggered.connect(self.metaIs)
self.menu = QtWidgets.QMenu("Item info")
self.menu.addAction(classAct)
self.menu.addAction(dataAct)
self.menu.addAction(metaAct)
self.setCentralWidget(self.view)
@QtCore.pyqtSlot(QtCore.QPoint)
def list_click(self, position):
self.menu.popup(self.view.viewport().mapToGlobal(position))
def classIs(self):
selected_indexes = self.view.selectedIndexes()
for index in selected_indexes:
item = self.model.itemFromIndex(index)
print "Item {} Class {} ".format(item.text(), item.__class__())
def dataIs(self):
selected_indexes = self.view.selectedIndexes()
for index in selected_indexes:
item = self.model.itemFromIndex(index)
try:
print "Item {} data {} Object {}".format(item.text(),
item.data().title,
item.data().obj)
except Exception as exc:
print "Data exception ", exc
def metaIs(self):
selected_indexes = self.view.selectedIndexes()
for index in selected_indexes:
item = self.model.itemFromIndex(index)
try:
print "Item {} meta {} ".format(item.text(), item.meta)
except Exception as exc:
print "Meta exception ", exc
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
main = mainWidget()
main.show()
app.exec_()