diff options
author | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2022-08-09 11:30:47 +0200 |
---|---|---|
committer | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2022-08-12 13:00:42 +0200 |
commit | 2d7a4fc710e59d0e766ffa101dba383eff46bb50 (patch) | |
tree | 80d252632940c75acffe5c666be84a62b7be8b51 /sources/pyside6/doc | |
parent | 950b73510bda03c4a4096d2f6aa5daf1a377ab9e (diff) |
Fix the modelview programming tutorial
Add some documentation examples and snippets to fix most outstanding
C++ to Python conversion errors.
The rest looks roughly ok and could be improved by further fixing up
the snippet conversion.
Task-number: PYSIDE-1984
Pick-to: 6.3 6.2
Change-Id: I8c1bdcbc4a07847b2731ef7e2b9ba666cc00ccd6
Reviewed-by: Christian Tismer <tismer@stackless.com>
Diffstat (limited to 'sources/pyside6/doc')
5 files changed, 347 insertions, 0 deletions
diff --git a/sources/pyside6/doc/snippets/qtbase/examples/widgets/itemviews/spinboxdelegate/delegate_0.h.py b/sources/pyside6/doc/snippets/qtbase/examples/widgets/itemviews/spinboxdelegate/delegate_0.h.py new file mode 100644 index 000000000..de386a5ac --- /dev/null +++ b/sources/pyside6/doc/snippets/qtbase/examples/widgets/itemviews/spinboxdelegate/delegate_0.h.py @@ -0,0 +1,18 @@ +class SpinBoxDelegate(QStyledItemDelegate): + """A delegate that allows the user to change integer values from the model + using a spin box widget. """ + + def __init__(self, parent=None): + ... + + def createEditor(self, parent, option, index): + ... + + def setEditorData(self, editor, index): + ... + + def setModelData(self, editor, model, index): + ... + + def updateEditorGeometry(self, editor, option, index): + ... diff --git a/sources/pyside6/doc/snippets/qtbase/src/widgets/doc/snippets/stringlistmodel/model_0.h.py b/sources/pyside6/doc/snippets/qtbase/src/widgets/doc/snippets/stringlistmodel/model_0.h.py new file mode 100644 index 000000000..02a02aaf8 --- /dev/null +++ b/sources/pyside6/doc/snippets/qtbase/src/widgets/doc/snippets/stringlistmodel/model_0.h.py @@ -0,0 +1,24 @@ +class StringListModel(QAbstractListModel): + def __init__(self, strings, parent=None): + ... + + def rowCount(self, parent=QModelIndex()): + ... + + def data(self, index, role): + ... + + def headerData(self, section, orientation, role=Qt.DisplayRole): + ... + + def flags(self, index): + ... + + def setData(self, index, value, role=Qt.EditRole): + ... + + def insertRows(self, position, rows, parent): + ... + + def removeRows(self, position, rows, parent): + ... diff --git a/sources/pyside6/doc/tutorials/modelviewprogramming/qlistview-dnd.py b/sources/pyside6/doc/tutorials/modelviewprogramming/qlistview-dnd.py new file mode 100644 index 000000000..3a37cc0f3 --- /dev/null +++ b/sources/pyside6/doc/tutorials/modelviewprogramming/qlistview-dnd.py @@ -0,0 +1,137 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +import sys + +from PySide6.QtWidgets import (QAbstractItemView, QApplication, QMainWindow, + QListView) +from PySide6.QtCore import (QByteArray, QDataStream, QIODevice, QMimeData, + QModelIndex, QStringListModel, Qt) + + +class DragDropListModel(QStringListModel): + """A simple model that uses a QStringList as its data source.""" + + def __init__(self, strings, parent=None): + super().__init__(strings, parent) + +#! [0] + + def canDropMimeData(self, data, action, row, column, parent): + if not data.hasFormat("application/vnd.text.list"): + return False + + if column > 0: + return False + + return True +#! [0] +#! [1] + def dropMimeData(self, data, action, row, column, parent): + if not self.canDropMimeData(data, action, row, column, parent): + return False + + if action == Qt.IgnoreAction: + return True +#! [1] + +#! [2] + begin_row = 0 + + if row != -1: + begin_row = row +#! [2] #! [3] + elif parent.isValid(): + begin_row = parent.row() +#! [3] #! [4] + else: + begin_row = self.rowCount(QModelIndex()) +#! [4] + +#! [5] + encoded_data = data.data("application/vnd.text.list") + stream = QDataStream(encoded_data, QIODevice.ReadOnly) + new_items = [] + while not stream.atEnd(): + new_items.append(stream.readQString()) +#! [5] + +#! [6] + self.insertRows(begin_row, len(new_items), QModelIndex()) + for text in new_items: + idx = self.index(begin_row, 0, QModelIndex()) + self.setData(idx, text) + begin_row += 1 + + return True +#! [6] + +#! [7] + def flags(self, index): + default_flags = super().flags(index) + if index.isValid(): + return Qt.ItemIsDragEnabled | Qt.ItemIsDropEnabled | default_flags + return Qt.ItemIsDropEnabled | default_flags +#! [7] + +#! [8] + def mimeData(self, indexes): + mime_data = QMimeData() + encoded_data = QByteArray() + stream = QDataStream(encoded_data, QIODevice.WriteOnly) + for index in indexes: + if index.isValid(): + text = self.data(index, Qt.DisplayRole) + stream.writeQString(text) + + mime_data.setData("application/vnd.text.list", encoded_data) + return mime_data +#! [8] + +#! [9] + def mimeTypes(self): + return ["application/vnd.text.list"] +#! [9] + +#! [10] + def supportedDropActions(self): + return Qt.CopyAction | Qt.MoveAction +#! [10] + + +class MainWindow(QMainWindow): + + def __init__(self, parent=None): + super().__init__(parent) + + file_menu = self.menuBar().addMenu("&File") + quit_action = file_menu.addAction("E&xit") + quit_action.setShortcut("Ctrl+Q") + +#! [mainwindow0] + self._list_view = QListView(self) + self._list_view.setSelectionMode(QAbstractItemView.ExtendedSelection) + self._list_view.setDragEnabled(True) + self._list_view.setAcceptDrops(True) + self._list_view.setDropIndicatorShown(True) +#! [mainwindow0] + + quit_action.triggered.connect(self.close) + + self.setup_list_items() + + self.setCentralWidget(self._list_view) + self.setWindowTitle("List View") + + def setup_list_items(self): + items = ["Oak", "Fir", "Pine", "Birch", "Hazel", "Redwood", "Sycamore", + "Chestnut", "Mahogany"] + model = DragDropListModel(items, self) + self._list_view.setModel(model) + + +if __name__ == '__main__': + app = QApplication(sys.argv) + window = MainWindow() + window.show() + sys.exit(app.exec()) diff --git a/sources/pyside6/doc/tutorials/modelviewprogramming/simplemodel-use.py b/sources/pyside6/doc/tutorials/modelviewprogramming/simplemodel-use.py new file mode 100644 index 000000000..1bacfd829 --- /dev/null +++ b/sources/pyside6/doc/tutorials/modelviewprogramming/simplemodel-use.py @@ -0,0 +1,44 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +import sys + +from PySide6.QtWidgets import (QApplication, QFileSystemModel, QLabel, + QVBoxLayout, QWidget) +from PySide6.QtGui import QPalette +from PySide6.QtCore import QDir, Qt + + +if __name__ == '__main__': + app = QApplication(sys.argv) + + window = QWidget() + layout = QVBoxLayout(window) + title = QLabel("Some items from the directory model", window) + title.setBackgroundRole(QPalette.Base) + title.setMargin(8) + layout.addWidget(title) + +#! [0] + model = QFileSystemModel() + model.setRootPath(QDir.currentPath()) + + def on_directory_loaded(directory): + parent_index = model.index(directory) + num_rows = model.rowCount(parent_index) +#! [1] + for row in range(num_rows): + index = model.index(row, 0, parent_index) +#! [1] +#! [2] + text = model.data(index, Qt.DisplayRole) +#! [2] + label = QLabel(text, window) + layout.addWidget(label) + + model.directoryLoaded.connect(on_directory_loaded) +#! [0] + + window.setWindowTitle("A simple model example") + window.show() + sys.exit(app.exec()) diff --git a/sources/pyside6/doc/tutorials/modelviewprogramming/stringlistmodel.py b/sources/pyside6/doc/tutorials/modelviewprogramming/stringlistmodel.py new file mode 100644 index 000000000..2c8493aa9 --- /dev/null +++ b/sources/pyside6/doc/tutorials/modelviewprogramming/stringlistmodel.py @@ -0,0 +1,124 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +import sys + +from PySide6.QtWidgets import (QApplication, QListView) +from PySide6.QtCore import QAbstractListModel, QStringListModel, QModelIndex, Qt + + +#! [0] +class StringListModel(QAbstractListModel): + def __init__(self, strings, parent=None): + super().__init__(parent) + self._strings = strings + +#! [0] + def rowCount(self, parent=QModelIndex()): + """Returns the number of items in the string list as the number of rows + in the model.""" + return len(self._strings) +#! [0] + +#! [1] + def data(self, index, role): + """Returns an appropriate value for the requested data. + If the view requests an invalid index, an invalid variant is returned. + Any valid index that corresponds to a string in the list causes that + string to be returned.""" + row = index.row() + if not index.isValid() or row >= len(self._strings): + return None + if role != Qt.DisplayRole and role != Qt.EditRole: + return None + return self._strings[row] +#! [1] + +#! [2] + def headerData(self, section, orientation, role=Qt.DisplayRole): + """Returns the appropriate header string depending on the orientation of + the header and the section. If anything other than the display role is + requested, we return an invalid variant.""" + if role != Qt.DisplayRole: + return None + if orientation == Qt.Horizontal: + return f"Column {section}" + return f"Row {section}" +#! [2] + +#! [3] + def flags(self, index): + """Returns an appropriate value for the item's flags. Valid items are + enabled, selectable, and editable.""" + + if not index.isValid(): + return Qt.ItemIsEnabled + return super().flags(index) | Qt.ItemIsEditable +#! [3] + + #! [4] + def setData(self, index, value, role=Qt.EditRole): + """Changes an item in the string list, but only if the following conditions + are met: + + # The index supplied is valid. + # The index corresponds to an item to be shown in a view. + # The role associated with editing text is specified. + + The dataChanged() signal is emitted if the item is changed.""" + + if index.isValid() and role == Qt.EditRole: + self._strings[index.row()] = value + self.dataChanged.emit(index, index, {role}) + return True +#! [4] #! [5] + return False +#! [5] + +#! [6] + def insertRows(self, position, rows, parent): + """Inserts a number of rows into the model at the specified position.""" + self.beginInsertRows(QModelIndex(), position, position + rows - 1) + for row in range(rows): + self._strings.insert(position, "") + self.endInsertRows() + return True +#! [6] #! [7] +#! [7] + +#! [8] + def removeRows(self, position, rows, parent): + """Removes a number of rows from the model at the specified position.""" + self.beginRemoveRows(QModelIndex(), position, position + rows - 1) + for row in range(rows): + del self._strings[position] + self.endRemoveRows() + return True +#! [8] #! [9] +#! [9] + + +#! [main0] +if __name__ == '__main__': + app = QApplication(sys.argv) + +#! [main1] + numbers = ["One", "Two", "Three", "Four", "Five"] + model = StringListModel(numbers) +#! [main0] #! [main1] #! [main2] #! [main3] + view = QListView() +#! [main2] + view.setWindowTitle("View onto a string list model") +#! [main4] + view.setModel(model) +#! [main3] #! [main4] + + model.insertRows(5, 7, QModelIndex()) + for row in range(5, 12): + index = model.index(row, 0, QModelIndex()) + model.setData(index, f"{row+1}") + +#! [main5] + view.show() + sys.exit(app.exec()) +#! [main5] |