librarymodel progress

This commit is contained in:
olari
2021-06-12 18:58:10 +03:00
parent 1c24573b34
commit 904e3ca57e

225
main.py
View File

@@ -1,13 +1,19 @@
import sys
import json
import sys
from dataclasses import dataclass
from pathlib import Path
from typing import Any
from PySide2.QtCore import QAbstractItemModel, QModelIndex, QObject, QUrl, Qt, Signal, Slot
from PySide2.QtGui import QIcon, QImage, QPicture, QPixmap
from PySide2.QtWebChannel import QWebChannel
from PySide2.QtWebEngineWidgets import QWebEngineView
from PySide2.QtCore import (
QAbstractItemModel,
QModelIndex,
QObject,
QUrl,
Qt,
Signal,
Slot,
)
from PySide2.QtWidgets import (
QApplication,
QDockWidget,
@@ -16,14 +22,21 @@ from PySide2.QtWidgets import (
QPushButton,
QTreeView,
QVBoxLayout,
QWidget
QWidget,
)
from PySide2.QtGui import QIcon, QImage, QPixmap
from PySide2.QtWebChannel import QWebChannel
from PySide2.QtWebEngineWidgets import QWebEngineView
def qurl_from_local(fpath):
return QUrl.fromLocalFile(str(Path(fpath).absolute()))
def file_url_from_local(fpath):
return f'file://{Path(fpath).absolute()}'
return f"file://{Path(fpath).absolute()}"
class Bridge(QObject):
@Slot(str, result=str)
@@ -32,11 +45,12 @@ class Bridge(QObject):
call_javascript = Signal(str)
@dataclass
class TreeItem:
name: str
parent: "TreeItem"
children: list["TreeItem"]
name: str = "Untitled"
parent: "TreeItem" = None
children: list["TreeItem"] = []
def row(self):
return self.parent.children.index(self) if self.parent else 0
@@ -50,14 +64,54 @@ class TreeItem:
item.children.append(TreeItem.load(child, item))
return item
class LibraryModel(QAbstractItemModel):
UNTITLED_NODE_NAME = "Untitled"
def __init__(self):
super().__init__()
self.root = TreeItem.load(
['root', [
['first', [
['second', [
['third', []]]]]]]])
self.root = TreeItem.load(["root", [["first", [["second", [["third", []]]]]]]])
def index(self, row: int, column: int, parent=QModelIndex()) -> QModelIndex:
if not self.hasIndex(row, column, parent):
return QModelIndex()
parent_item = parent.internalPointer() if parent.isValid() else self.root
if len(parent_item.children) > row:
return self.createIndex(row, column, parent_item.children[row])
return QModelIndex()
def parent(self, index: QModelIndex) -> QModelIndex:
if not index.isValid():
return QModelIndex()
child_item = index.internalPointer()
parent_item = child_item.parent
if parent_item == self.root:
return QModelIndex()
return self.createIndex(parent_item.row(), 0, parent_item)
def flags(self, index: QModelIndex) -> Qt.ItemFlags:
if index.isValid():
return (
Qt.ItemIsEnabled
| Qt.ItemIsSelectable
| Qt.ItemIsDragEnabled
| Qt.ItemIsDropEnabled
)
else:
return Qt.ItemIsEnabled
def rowCount(self, parent=QModelIndex()):
parent_item = parent.internalPointer() if parent.isValid() else self.root
return len(parent_item.children)
def columnCount(self, parent=QModelIndex()):
return 1
def data(self, index: QModelIndex, role: Qt.ItemDataRole) -> Any:
if not index.isValid():
@@ -68,20 +122,9 @@ class LibraryModel(QAbstractItemModel):
return item.name
elif role == Qt.DecorationRole:
img = QImage()
img.load('test.png')
img.load("test.png")
return QIcon(QPixmap.fromImage(img))
def insertRows(self, row: int, count: int, parent: QModelIndex) -> bool:
item: TreeItem = parent.internalPointer()
self.beginInsertRows(parent, row, row)
item.children.insert(row, TreeItem('', item, []))
self.endInsertRows()
return True
def setData(self, index: QModelIndex, value: str, role: Qt.ItemDataRole):
if not index.isValid():
return False
@@ -93,47 +136,26 @@ class LibraryModel(QAbstractItemModel):
return True
def index(self, row: int, column: int, parent=QModelIndex()) -> QModelIndex:
if not self.hasIndex(row, column, parent):
return QModelIndex()
def insertRows(self, row: int, count: int, parent: QModelIndex) -> bool:
item: TreeItem = parent.internalPointer() or self.root
self.beginInsertRows(parent, row, row + count)
item.children.insert(row, TreeItem(LibraryModel.UNTITLED_NODE_NAME, item, []))
self.endInsertRows()
return True
if not parent.isValid():
parentItem = self.root
else:
parentItem = parent.internalPointer()
def removeRows(self, row: int, count: int, parent: QModelIndex) -> bool:
item: TreeItem = parent.internalPointer() or self.root
self.beginRemoveRows(parent, row, row + count)
del item.children[row]
self.endRemoveRows()
return True
if len(parentItem.children) > row:
return self.createIndex(row, column, parentItem.children[row])
else:
return QModelIndex()
def supportedDragActions(self) -> Qt.DropActions:
return Qt.CopyAction | Qt.MoveAction
def parent(self, index: QModelIndex) -> QModelIndex:
if not index.isValid():
return QModelIndex()
def supportedDropActions(self) -> Qt.DropActions:
return Qt.CopyAction | Qt.MoveAction
childItem = index.internalPointer()
parentItem = childItem.parent
if parentItem == self.root:
return QModelIndex()
return self.createIndex(parentItem.row(), 0, parentItem)
def rowCount(self, parent=QModelIndex()):
if not parent.isValid():
parentItem = self.root
else:
parentItem = parent.internalPointer()
return len(parentItem.children)
def columnCount(self, parent=QModelIndex()):
return 1
def flags(self, index: QModelIndex) -> Qt.ItemFlags:
flags = super().flags(index)
return Qt.ItemIsEditable | flags
class MainWindow(QMainWindow):
def __init__(self):
@@ -148,18 +170,7 @@ class MainWindow(QMainWindow):
self.web_view = QWebEngineView()
self._layout.addWidget(self.web_view)
self.library_model = LibraryModel()
self.library_view = QTreeView()
self.library_view.setHeaderHidden(True)
self.library_view.setModel(self.library_model)
def on_insert_row(p: QModelIndex, f, l):
self.library_view.setExpanded(p, True)
self.library_view.edit(p.child(f, 0))
self.library_model.rowsInserted.connect(on_insert_row)
self.dock_widget = QDockWidget('Library')
self.dock_widget = QDockWidget("Library")
self.dock_qwidget = QWidget()
self.dock_widget.setWidget(self.dock_qwidget)
@@ -167,28 +178,54 @@ class MainWindow(QMainWindow):
self.dock_layout = QVBoxLayout()
self.dock_qwidget.setLayout(self.dock_layout)
self.new_node = QPushButton("New node")
self.library_model = LibraryModel()
self.library_view = QTreeView()
self.dock_layout.addWidget(self.library_view)
self.library_view.setModel(self.library_model)
self.library_view.setDragEnabled(True)
self.library_view.setAcceptDrops(True)
self.library_view.setDefaultDropAction(Qt.MoveAction)
self.library_view.setHeaderHidden(True)
def on_insert_row(p: QModelIndex, f, l):
self.library_view.setExpanded(p, True)
self.library_view.edit(p.child(f, 0))
self.library_model.rowsInserted.connect(on_insert_row)
self.new_node = QPushButton("New node")
self.dock_layout.addWidget(self.new_node)
self.new_node.clicked.connect(lambda:
self.library_model.insertRow(0, self.library_view.currentIndex())
self.new_node.clicked.connect(
lambda: self.library_model.insertRow(0, self.library_view.currentIndex())
)
self.delete_node = QPushButton("Delete node")
self.dock_layout.addWidget(self.delete_node)
self.delete_node.clicked.connect(
lambda: self.library_model.removeRow(
self.library_view.currentIndex().row(),
self.library_view.currentIndex().parent(),
)
)
self.addDockWidget(Qt.LeftDockWidgetArea, self.dock_widget)
self.web_view.load(qurl_from_local('pdf.js/build/generic/web/viewer.html'))
self.web_view.load(qurl_from_local("pdf.js/build/generic/web/viewer.html"))
def on_load():
def load_javascript_file(filepath):
self.web_view.page().runJavaScript(
'var s = document.createElement("script");'
f's.src="{filepath}";'
'document.body.appendChild(s);'
"document.body.appendChild(s);"
)
load_javascript_file('qrc:///qtwebchannel/qwebchannel.js')
load_javascript_file(file_url_from_local('controller.js'))
load_javascript_file("qrc:///qtwebchannel/qwebchannel.js")
load_javascript_file(file_url_from_local("controller.js"))
self.web_view.loadFinished.connect(on_load)
@@ -196,22 +233,29 @@ class MainWindow(QMainWindow):
self.web_view.page().setWebChannel(self.channel)
self.bridge = Bridge()
self.channel.registerObject('bridge', self.bridge)
self.channel.registerObject("bridge", self.bridge)
def on_command(command):
if command['type'] == 'ready':
print('webchannel ready')
if command["type"] == "ready":
print("webchannel ready")
self.bridge.handler = on_command
def call_javascript(command):
self.bridge.call_javascript.emit(json.dumps(command))
self.button = QPushButton('Load PDF')
self.button = QPushButton("Load PDF")
self._layout.addWidget(self.button)
self.button.clicked.connect(lambda:
call_javascript({'type': 'load_pdf', 'url': file_url_from_local(QFileDialog.getOpenFileName()[0])}))
self.button.clicked.connect(
lambda: call_javascript(
{
"type": "load_pdf",
"url": file_url_from_local(QFileDialog.getOpenFileName()[0]),
}
)
)
def main():
app = QApplication()
@@ -225,5 +269,6 @@ def main():
sys.exit(app.exec_())
if __name__ == '__main__':
if __name__ == "__main__":
main()