mirror of
https://github.com/olivierkes/manuskript.git
synced 2024-05-25 07:09:42 +12:00
Adds: drag and drop
This commit is contained in:
parent
a3b9a8597e
commit
215a29d325
|
@ -64,6 +64,8 @@ def loadStandardItemModelXML(mdl, xml):
|
|||
for l in root.find("header").find("vertical").findall("label"):
|
||||
vLabels.append(l.attrib["text"])
|
||||
|
||||
#print(root.find("header").find("vertical").text)
|
||||
|
||||
mdl.setVerticalHeaderLabels(vLabels)
|
||||
mdl.setHorizontalHeaderLabels(hLabels)
|
||||
|
||||
|
|
|
@ -143,14 +143,15 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|||
self.treePlanOutline.hideColumn(c)
|
||||
self.btnRedacAddFolder.clicked.connect(lambda: self.outlineAddItem("folder"))
|
||||
self.btnRedacAddScene.clicked.connect(lambda: self.outlineAddItem("scene"))
|
||||
self.btnRedacRemoveItem.clicked.connect(self.outlineRemoveItem)
|
||||
self.btnRedacRemoveItem.clicked.connect(self.outlineRemoveItems)
|
||||
|
||||
#Debug
|
||||
self.mdlFlatData.setVerticalHeaderLabels(["Infos générales", "Summary"])
|
||||
self.tblDebugFlatData.setModel(self.mdlFlatData)
|
||||
self.tblDebugPersos.setModel(self.mdlPersos)
|
||||
self.tblDebugPersosInfos.setModel(self.mdlPersosInfos)
|
||||
self.treeDebugOutline.setModel(self.mdlOutline)
|
||||
|
||||
self.btnRedacPreview.clicked.connect(self.mdlOutline.saveToXML)
|
||||
|
||||
self.loadProject("test_project")
|
||||
|
||||
|
@ -161,11 +162,12 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|||
def outlineAddItem(self, type="folder"):
|
||||
currentIndex = self.treeRedacOutline.currentIndex()
|
||||
item = outlineItem("Nouveau", type)
|
||||
self.mdlOutline.appendRow(item, currentIndex)
|
||||
self.mdlOutline.appendItem(item, currentIndex)
|
||||
|
||||
def outlineRemoveItem(self):
|
||||
currentIndex = self.treeRedacOutline.currentIndex()
|
||||
self.mdlOutline.removeIndex(currentIndex)
|
||||
def outlineRemoveItems(self):
|
||||
for idx in self.treeRedacOutline.selectedIndexes():
|
||||
if idx.isValid():
|
||||
self.mdlOutline.removeIndex(idx)
|
||||
|
||||
|
||||
####################################################################################################
|
||||
|
|
|
@ -7,6 +7,7 @@ from __future__ import unicode_literals
|
|||
from PyQt4.QtCore import *
|
||||
from PyQt4.QtGui import *
|
||||
from enum import Enum
|
||||
from lxml import etree as ET
|
||||
|
||||
class Outline(Enum):
|
||||
title = 0
|
||||
|
@ -24,7 +25,7 @@ class outlineModel(QAbstractItemModel):
|
|||
def __init__(self):
|
||||
QAbstractItemModel.__init__(self)
|
||||
|
||||
self.rootItem = outlineItem()
|
||||
self.rootItem = outlineItem("root", "folder")
|
||||
|
||||
def index(self, row, column, parent):
|
||||
|
||||
|
@ -84,14 +85,6 @@ class outlineModel(QAbstractItemModel):
|
|||
item.setData(index.column(), value)
|
||||
self.dataChanged.emit(index, index)
|
||||
return True
|
||||
|
||||
def flags(self, index):
|
||||
flags = Qt.ItemIsEnabled | Qt.ItemIsEditable | Qt.ItemIsSelectable | Qt.ItemIsDragEnabled
|
||||
|
||||
if index.isValid() and index.internalPointer().isFolder():
|
||||
flags |= Qt.ItemIsDropEnabled
|
||||
|
||||
return flags
|
||||
|
||||
|
||||
def headerData(self, section, orientation, role=Qt.DisplayRole):
|
||||
|
@ -99,6 +92,141 @@ class outlineModel(QAbstractItemModel):
|
|||
return [i.name for i in Outline][section]
|
||||
else:
|
||||
return QVariant()
|
||||
return True
|
||||
|
||||
#################### DRAG AND DROP ########################
|
||||
# http://doc.qt.io/qt-5/model-view-programming.html#using-drag-and-drop-with-item-views
|
||||
|
||||
def flags(self, index):
|
||||
flags = QAbstractItemModel.flags(self, index) | Qt.ItemIsEditable
|
||||
|
||||
if index.isValid() and index.internalPointer().isFolder():
|
||||
flags |= Qt.ItemIsDropEnabled | Qt.ItemIsDragEnabled
|
||||
|
||||
elif index.isValid():
|
||||
flags |= Qt.ItemIsDragEnabled
|
||||
|
||||
else:
|
||||
flags |= Qt.ItemIsDropEnabled
|
||||
|
||||
return flags
|
||||
|
||||
def mimeTypes(self):
|
||||
return ["application/xml"]
|
||||
|
||||
def mimeData(self, indexes):
|
||||
mimeData = QMimeData()
|
||||
#encodedData = QByteArray()
|
||||
#stream = QDataStream(encodedData, QIODevice.WriteOnly)
|
||||
encodedData = ""
|
||||
|
||||
root = ET.Element("outlineItems")
|
||||
for index in indexes:
|
||||
if index.isValid():
|
||||
item = ET.XML(index.internalPointer().toXML())
|
||||
root.append(item)
|
||||
|
||||
encodedData = ET.tostring(root)
|
||||
|
||||
mimeData.setData("application/xml", encodedData)
|
||||
return mimeData
|
||||
|
||||
def supportedDropActions(self):
|
||||
|
||||
return Qt.MoveAction # Qt.CopyAction |
|
||||
return Qt.CopyAction | Qt.MoveAction
|
||||
|
||||
def dropMimeData(self, data, action, row, column, parent):
|
||||
|
||||
if action == Qt.IgnoreAction:
|
||||
return True # What is that?
|
||||
|
||||
if not data.hasFormat("application/xml"):
|
||||
return False
|
||||
|
||||
if column > 0:
|
||||
column = 0
|
||||
|
||||
if row <> -1:
|
||||
beginRow = row
|
||||
elif parent.isValid():
|
||||
beginRow = self.rowCount(parent) + 1
|
||||
else:
|
||||
beginRow = self.rowCount() + 1
|
||||
|
||||
encodedData = str(data.data("application/xml"))
|
||||
root = ET.XML(encodedData)
|
||||
|
||||
if root.tag <> "outlineItems":
|
||||
return False
|
||||
|
||||
items = []
|
||||
for child in root:
|
||||
if child.tag == "outlineItem":
|
||||
items.append(outlineItem(xml=ET.tostring(child)))
|
||||
|
||||
if not items:
|
||||
return False
|
||||
|
||||
self.insertItems(items, beginRow, parent)
|
||||
|
||||
return True
|
||||
|
||||
################# ADDING AND REMOVING #################
|
||||
|
||||
def insertItem(self, item, row, parent=QModelIndex()):
|
||||
return self.insertItems([item], row, parent)
|
||||
|
||||
def insertItems(self, items, row, parent=QModelIndex()):
|
||||
if not parent.isValid():
|
||||
parentItem = self.rootItem
|
||||
else:
|
||||
parentItem = parent.internalPointer()
|
||||
|
||||
# Insert only if parent is folder
|
||||
if parentItem.isFolder():
|
||||
self.beginInsertRows(parent, row, row + len(items) - 1)
|
||||
|
||||
for i in items:
|
||||
parentItem.insertChild(row + items.index(i), i)
|
||||
|
||||
self.endInsertRows()
|
||||
|
||||
return True
|
||||
|
||||
def appendItem(self, item, parent=QModelIndex()):
|
||||
if not parent.isValid():
|
||||
parentItem = self.rootItem
|
||||
else:
|
||||
parentItem = parent.internalPointer()
|
||||
|
||||
# If parent is folder, write into
|
||||
if parentItem.isFolder():
|
||||
self.insertItem(item, self.rowCount(parent), parent)
|
||||
|
||||
# If parent is not folder, write next to
|
||||
else:
|
||||
self.insertItem(item, parent.row()+1, parent.parent())
|
||||
|
||||
def removeIndex(self, index):
|
||||
item = index.internalPointer()
|
||||
self.removeRow(item.row(), index.parent())
|
||||
|
||||
def removeRow(self, row, parent=QModelIndex()):
|
||||
return self.removeRows(row, 1, parent)
|
||||
|
||||
def removeRows(self, row, count, parent=QModelIndex()):
|
||||
if not parent.isValid():
|
||||
parentItem = self.rootItem
|
||||
else:
|
||||
parentItem = parent.internalPointer()
|
||||
|
||||
self.beginRemoveRows(parent, row, row + count - 1)
|
||||
for i in range(count):
|
||||
parentItem.removeChild(row)
|
||||
|
||||
self.endRemoveRows()
|
||||
return True
|
||||
|
||||
#def insertRow(self, row, item, parent=QModelIndex()):
|
||||
#self.beginInsertRows(parent, row, row)
|
||||
|
@ -112,44 +240,28 @@ class outlineModel(QAbstractItemModel):
|
|||
|
||||
#self.endInsertRows()
|
||||
|
||||
def appendRow(self, item, parent=QModelIndex()):
|
||||
if not parent.isValid():
|
||||
parentItem = self.rootItem
|
||||
else:
|
||||
parentItem = parent.internalPointer()
|
||||
|
||||
if parentItem.isFolder():
|
||||
self.beginInsertRows(parent, parentItem.childCount(), parentItem.childCount())
|
||||
parentItem.appendChild(item)
|
||||
self.endInsertRows()
|
||||
|
||||
def removeIndex(self, index):
|
||||
item = index.internalPointer()
|
||||
self.removeRow(item.row(), 1, index.parent())
|
||||
|
||||
|
||||
def removeRow(self, row, count, parent=QModelIndex()):
|
||||
if not parent.isValid():
|
||||
parentItem = self.rootItem
|
||||
else:
|
||||
parentItem = parent.internalPointer()
|
||||
|
||||
self.beginRemoveRows(parent, row, row)
|
||||
parentItem.removeChild(row)
|
||||
self.endRemoveRows()
|
||||
return True
|
||||
################# XML #################
|
||||
|
||||
def saveToXML(self):
|
||||
root = ET.XML(self.rootItem.toXML())
|
||||
print(ET.tostring(root, pretty_print=True))
|
||||
# FIXME
|
||||
|
||||
|
||||
class outlineItem():
|
||||
def __init__(self, title="", type="folder", parent=None):
|
||||
|
||||
self._parent = parent
|
||||
|
||||
def __init__(self, title="", type="folder", xml=""):
|
||||
|
||||
self._data = {}
|
||||
self.childItems = []
|
||||
|
||||
self._data[Outline.title] = title
|
||||
if title: self._data[Outline.title] = title
|
||||
self._data[Outline.type] = type
|
||||
|
||||
if xml:
|
||||
self.setFromXML(xml)
|
||||
|
||||
|
||||
def child(self, row):
|
||||
return self.childItems[row]
|
||||
|
@ -165,7 +277,7 @@ class outlineItem():
|
|||
if Outline(column) in self._data:
|
||||
return self._data[Outline(column)]
|
||||
else:
|
||||
return QVariant()
|
||||
return None
|
||||
elif role == Qt.DecorationRole and column == Outline.title.value:
|
||||
if self.isFolder():
|
||||
return QIcon.fromTheme("folder")
|
||||
|
@ -173,18 +285,18 @@ class outlineItem():
|
|||
return QIcon.fromTheme("document-new")
|
||||
|
||||
def setData(self, column, data):
|
||||
self._data[Outline(column)] = data
|
||||
self._data[Outline(column)] = str(data.toString())
|
||||
|
||||
def row(self):
|
||||
if self.parent:
|
||||
return self.parent().childItems.index(self)
|
||||
|
||||
def appendChild(self, child):
|
||||
self.childItems.append(child)
|
||||
child._parent = self
|
||||
self.insertChild(self.childCount(), child)
|
||||
|
||||
def insertChild(self, row, child):
|
||||
self.childItems.insert(row, child)
|
||||
child._parent = self
|
||||
|
||||
def removeChild(self, row):
|
||||
self.childItems.pop(row)
|
||||
|
@ -196,4 +308,28 @@ class outlineItem():
|
|||
return self._data[Outline.type] == "folder"
|
||||
|
||||
def isScene(self):
|
||||
return self._data[Outline.type] == "scene"
|
||||
return self._data[Outline.type] == "scene"
|
||||
|
||||
def toXML(self):
|
||||
item = ET.Element("outlineItem")
|
||||
|
||||
for attrib in Outline:
|
||||
val = self.data(attrib)
|
||||
if val:
|
||||
item.set(attrib.name, val)
|
||||
|
||||
for i in self.childItems:
|
||||
item.append(ET.XML(i.toXML()))
|
||||
|
||||
return ET.tostring(item)
|
||||
|
||||
def setFromXML(self, xml):
|
||||
root = ET.XML(xml)
|
||||
|
||||
for k in root.attrib:
|
||||
if k in Outline.__members__:
|
||||
self._data[Outline.__members__[k]] = root.attrib[k]
|
||||
|
||||
for child in root:
|
||||
item = outlineItem(xml=ET.tostring(child))
|
||||
self.appendChild(item)
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
# Form implementation generated from reading ui file 'src/ui/mainWindow.ui'
|
||||
#
|
||||
# Created: Mon Jun 1 23:58:06 2015
|
||||
# Created: Tue Jun 2 13:54:35 2015
|
||||
# by: PyQt4 UI code generator 4.11.3
|
||||
#
|
||||
# WARNING! All changes made in this file will be lost!
|
||||
|
@ -774,6 +774,8 @@ class Ui_MainWindow(object):
|
|||
self.verticalLayout_19.setObjectName(_fromUtf8("verticalLayout_19"))
|
||||
self.treeRedacOutline = QtGui.QTreeView(self.layoutWidget1)
|
||||
self.treeRedacOutline.setDragDropMode(QtGui.QAbstractItemView.DragDrop)
|
||||
self.treeRedacOutline.setDefaultDropAction(QtCore.Qt.MoveAction)
|
||||
self.treeRedacOutline.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection)
|
||||
self.treeRedacOutline.setObjectName(_fromUtf8("treeRedacOutline"))
|
||||
self.verticalLayout_19.addWidget(self.treeRedacOutline)
|
||||
self.horizontalLayout_31 = QtGui.QHBoxLayout()
|
||||
|
@ -798,6 +800,12 @@ class Ui_MainWindow(object):
|
|||
self.horizontalLayout_31.addWidget(self.btnRedacRemoveItem)
|
||||
spacerItem9 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
|
||||
self.horizontalLayout_31.addItem(spacerItem9)
|
||||
self.btnRedacPreview = QtGui.QPushButton(self.layoutWidget1)
|
||||
self.btnRedacPreview.setText(_fromUtf8(""))
|
||||
icon = QtGui.QIcon.fromTheme(_fromUtf8("document-print"))
|
||||
self.btnRedacPreview.setIcon(icon)
|
||||
self.btnRedacPreview.setObjectName(_fromUtf8("btnRedacPreview"))
|
||||
self.horizontalLayout_31.addWidget(self.btnRedacPreview)
|
||||
self.verticalLayout_19.addLayout(self.horizontalLayout_31)
|
||||
self.layoutWidget2 = QtGui.QWidget(self.splitterRedac)
|
||||
self.layoutWidget2.setObjectName(_fromUtf8("layoutWidget2"))
|
||||
|
|
|
@ -1452,6 +1452,12 @@
|
|||
<property name="dragDropMode">
|
||||
<enum>QAbstractItemView::DragDrop</enum>
|
||||
</property>
|
||||
<property name="defaultDropAction">
|
||||
<enum>Qt::MoveAction</enum>
|
||||
</property>
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::ExtendedSelection</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
|
@ -1505,6 +1511,16 @@
|
|||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnRedacPreview">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="document-print"/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
|
|
Loading…
Reference in a new issue