I have JSON data something like this
{"books":{
"web":{
"front-end":{
"html":["the missing manual", "core html5 canvas"],
"css":["css pocket reference", "css in depth"],
"js":["you don't know js", "eloquent javascript"]
},
"back-end":{
"php":["modern php", "php web services"],
"python":["dive into python", "python for everybody",
"Think Python", "Effective Python", "Fluent Python"]
}
},
"database":{
"sql":{
"mysql":["mysql in a nutshell", "mysql cookbook"],
"postgresql":["postgresql up and running", "practical postgresql"]
},
"nosql":{
"mongodb":["mongodb in action", "scaling mongodb"],
"cassandra":["practical cassandra", "mastering cassandra"]
}}}}
Now I want to populate this data in QListView
using QAbstractListModel
with the QToolBar
as breadcrumb navigation (QAction). QListView
will update as user
triggers key. So how can I implement this?
(source: gifyu.com)
The first thing is to convert the json into a model, in this case QStandardItemModel
is used. Then we use that model in the QListView
using setRootIndex()
to indicate the items that will be displayed, on the other hand QActions
are added to the QToolBar
using the parent tree.
from PyQt5 import QtCore, QtGui, QtWidgets
data = {"books":{
"web":{
"front-end":{
"html":["the missing manual", "core html5 canvas"],
"css":["css pocket reference", "css in depth"],
"js":["you don't know js", "eloquent javascript"]
},
"back-end":{
"php":["modern php", "php web services"],
"python":["dive into python", "python for everybody",
"Think Python", "Effective Python", "Fluent Python"]
}
},
"database":{
"sql":{
"mysql":["mysql in a nutshell", "mysql cookbook"],
"postgresql":["postgresql up and running", "practical postgresql"]
},
"nosql":{
"mongodb":["mongodb in action", "scaling mongodb"],
"cassandra":["practical cassandra", "mastering cassandra"]
}}}}
def dict_to_model(item, d):
if isinstance(d, dict):
for k, v in d.items():
it = QtGui.QStandardItem(k)
item.appendRow(it)
dict_to_model(it, v)
elif isinstance(d, list):
for v in d:
dict_to_model(item, v)
else:
item.appendRow(QtGui.QStandardItem(str(d)))
class Navigation(QtCore.QObject):
clicked = QtCore.pyqtSignal(QtCore.QModelIndex)
def __init__(self, json_data, parent=None):
super(Navigation, self).__init__(parent)
self.toolbar = QtWidgets.QToolBar()
self.toolbar.actionTriggered.connect(self.on_actionTriggered)
self.model = QtGui.QStandardItemModel(self)
dict_to_model(self.model.invisibleRootItem(), json_data)
it = self.model.item(0, 0)
ix = self.model.indexFromItem(it)
root_action = self.toolbar.addAction(it.text())
root_action.setData(QtCore.QPersistentModelIndex(ix))
self.listview = QtWidgets.QListView()
self.listview.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
self.listview.clicked.connect(self.on_clicked)
self.listview.setModel(self.model)
self.listview.setRootIndex(ix)
@QtCore.pyqtSlot(QtCore.QModelIndex)
def on_clicked(self, index):
if not self.model.hasChildren(index):
self.clicked.emit(index)
return
action = self.toolbar.addAction(index.data())
action.setData(QtCore.QPersistentModelIndex(index))
self.listview.setRootIndex(index)
@QtCore.pyqtSlot(QtWidgets.QAction)
def on_actionTriggered(self, action):
ix = action.data()
model = ix.model()
self.listview.setRootIndex(QtCore.QModelIndex(ix))
self.toolbar.clear()
ixs = []
while ix.isValid():
ixs.append(ix)
ix = ix.parent()
for ix in reversed(ixs):
action = self.toolbar.addAction(ix.data())
action.setData(ix)
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
navigation = Navigation(data, self)
navigation.clicked.connect(self.on_clicked)
tree_view = QtWidgets.QTreeView()
tree_view.setModel(navigation.model)
navigation.model.setHorizontalHeaderLabels(["Tree Example"])
tree_view.expandAll()
self.addToolBar(navigation.toolbar)
widget = QtWidgets.QWidget()
self.setCentralWidget(widget)
lay = QtWidgets.QHBoxLayout(widget)
lay.addWidget(navigation.listview)
lay.addWidget(tree_view)
@QtCore.pyqtSlot(QtCore.QModelIndex)
def on_clicked(self, index):
print(index.data())
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())