mirror of
https://github.com/olivierkes/manuskript.git
synced 2024-05-17 19:32:30 +12:00
Word goals
This commit is contained in:
parent
123952ccaa
commit
38a57f9d46
|
@ -39,3 +39,5 @@ class Outline(Enum):
|
|||
wordCount = 10
|
||||
goal = 11
|
||||
goalPercentage = 12
|
||||
setGoal = 13 # The goal set by the user, if any. Can be different from goal which can be computed
|
||||
# (sum of all sub-items' goals)
|
||||
|
|
|
@ -5,4 +5,16 @@ from __future__ import print_function
|
|||
from __future__ import unicode_literals
|
||||
|
||||
def wordCount(text):
|
||||
return len(text.strip().split(" ")) if text else 0
|
||||
return len(text.strip().split(" ")) if text else 0
|
||||
|
||||
def toInt(text):
|
||||
if text:
|
||||
return int(text)
|
||||
else:
|
||||
return 0
|
||||
|
||||
def toFloat(text):
|
||||
if text:
|
||||
return float(text)
|
||||
else:
|
||||
return 0.
|
|
@ -120,7 +120,8 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|||
self.mprPersos.addMapping(w, i)
|
||||
self.mprPersos.addMapping(self.sldPersoImportance, Perso.importance.value, "importance")
|
||||
self.sldPersoImportance.importanceChanged.connect(self.mprPersos.submit)
|
||||
|
||||
self.tabMain.currentChanged.connect(self.mprPersos.submit)
|
||||
|
||||
self.mprPersos.setCurrentIndex(0)
|
||||
self.lstPersos.selectionModel().currentChanged.connect(self.changeCurrentPerso)
|
||||
self.tabPersos.currentChanged.connect(self.resizePersosInfos)
|
||||
|
@ -135,6 +136,8 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|||
self.treePlanOutline.setItemDelegateForColumn(Outline.compile.value, self.treePlanOutlineCompileDelegate)
|
||||
self.treePlanOutlineStatusDelegate = treeOutlineStatusDelegate()
|
||||
self.treePlanOutline.setItemDelegateForColumn(Outline.status.value, self.treePlanOutlineStatusDelegate)
|
||||
self.treePlanOutlineGoalPercentageDelegate = treeOutlineGoalPercentageDelegate()
|
||||
self.treePlanOutline.setItemDelegateForColumn(Outline.goalPercentage.value, self.treePlanOutlineGoalPercentageDelegate)
|
||||
|
||||
self.cmbPlanPOV.setModels(self.mdlPersos, self.mdlOutline)
|
||||
self.treePlanOutline.header().setSectionResizeMode(QHeaderView.ResizeToContents)
|
||||
|
@ -153,7 +156,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|||
self.treePlanOutline.selectionModel().currentChanged.connect(lambda idx: self.mprPlan.setRootIndex(idx.parent()))
|
||||
self.treePlanOutline.selectionModel().currentChanged.connect(self.mprPlan.setCurrentModelIndex)
|
||||
self.treePlanOutline.selectionModel().currentChanged.connect(self.cmbPlanPOV.setCurrentModelIndex)
|
||||
|
||||
self.tabMain.currentChanged.connect(self.mprPlan.submit)
|
||||
|
||||
self.treeRedacOutline.setSelectionModel(self.treePlanOutline.selectionModel())
|
||||
|
||||
|
@ -182,7 +185,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|||
(self.txtRedacSummaryFull, Outline.summaryFull.value),
|
||||
(self.txtRedacNotes, Outline.notes.value),
|
||||
(self.txtRedacTitle, Outline.title.value),
|
||||
(self.txtRedacGoal, Outline.goal.value)
|
||||
(self.txtRedacGoal, Outline.setGoal.value)
|
||||
]
|
||||
for w, i in mapping:
|
||||
self.mprOutline.addMapping(w, i)
|
||||
|
@ -192,6 +195,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|||
self.treeRedacOutline.selectionModel().currentChanged.connect(self.cmbRedacPOV.setCurrentModelIndex)
|
||||
self.treeRedacOutline.selectionModel().currentChanged.connect(self.cmbRedacStatus.setCurrentModelIndex)
|
||||
self.treeRedacOutline.selectionModel().currentChanged.connect(self.chkRedacCompile.setCurrentModelIndex)
|
||||
self.tabMain.currentChanged.connect(self.mprOutline.submit)
|
||||
|
||||
self.treeRedacOutline.selectionModel().currentChanged.connect(lambda idx: self.lblRedacPOV.setHidden(idx.internalPointer().isFolder()))
|
||||
self.treeRedacOutline.selectionModel().currentChanged.connect(lambda idx: self.cmbRedacPOV.setHidden(idx.internalPointer().isFolder()))
|
||||
|
@ -218,7 +222,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|||
else:
|
||||
parent = self.treeRedacOutline.currentIndex()
|
||||
|
||||
item = outlineItem("Nouveau", type)
|
||||
item = outlineItem(title="Nouveau", type=type)
|
||||
self.mdlOutline.appendItem(item, parent)
|
||||
|
||||
def outlineRemoveItems(self):
|
||||
|
|
|
@ -19,7 +19,7 @@ class outlineModel(QAbstractItemModel):
|
|||
def __init__(self):
|
||||
QAbstractItemModel.__init__(self)
|
||||
|
||||
self.rootItem = outlineItem("root", "folder")
|
||||
self.rootItem = outlineItem(self, title="root")
|
||||
self.generateStatuses()
|
||||
|
||||
def index(self, row, column, parent):
|
||||
|
@ -38,6 +38,23 @@ class outlineModel(QAbstractItemModel):
|
|||
else:
|
||||
return QModelIndex()
|
||||
|
||||
def indexFromItem(self, item, column=0):
|
||||
if item == self.rootItem:
|
||||
return None
|
||||
|
||||
parent = item.parent()
|
||||
if not parent:
|
||||
parent = self.rootItem
|
||||
|
||||
if len(parent.children()) == 0:
|
||||
return None
|
||||
|
||||
#print(item.title(), [i.title() for i in parent.children()])
|
||||
|
||||
row = parent.children().index(item)
|
||||
col = column
|
||||
return self.createIndex(row, col, item)
|
||||
|
||||
def parent(self, index=QModelIndex()):
|
||||
if not index.isValid():
|
||||
return QModelIndex()
|
||||
|
@ -112,6 +129,9 @@ class outlineModel(QAbstractItemModel):
|
|||
if index.isValid() and index.column() == Outline.compile.value:
|
||||
flags |= Qt.ItemIsUserCheckable
|
||||
|
||||
if index.column() in [i.value for i in [Outline.wordCount, Outline.goalPercentage]]:
|
||||
flags &= ~ Qt.ItemIsEditable
|
||||
|
||||
return flags
|
||||
|
||||
def mimeTypes(self):
|
||||
|
@ -195,6 +215,9 @@ class outlineModel(QAbstractItemModel):
|
|||
else:
|
||||
parentItem = parent.internalPointer()
|
||||
|
||||
if parent.column() <> 0:
|
||||
parent = parentItem.index()
|
||||
|
||||
# Insert only if parent is folder
|
||||
if parentItem.isFolder():
|
||||
self.beginInsertRows(parent, row, row + len(items) - 1)
|
||||
|
@ -212,6 +235,9 @@ class outlineModel(QAbstractItemModel):
|
|||
else:
|
||||
parentItem = parent.internalPointer()
|
||||
|
||||
if parent.column() <> 0:
|
||||
parent = parentItem.index()
|
||||
|
||||
# If parent is folder, write into
|
||||
if parentItem.isFolder():
|
||||
self.insertItem(item, self.rowCount(parent), parent)
|
||||
|
@ -260,13 +286,13 @@ class outlineModel(QAbstractItemModel):
|
|||
ET.ElementTree(root).write(xml, encoding="UTF-8", xml_declaration=True, pretty_print=True)
|
||||
|
||||
def loadFromXML(self, xml):
|
||||
try:
|
||||
#try:
|
||||
root = ET.parse(xml)
|
||||
self.rootItem = outlineItem(xml=ET.tostring(root))
|
||||
self.rootItem = outlineItem(self, xml=ET.tostring(root))
|
||||
self.generateStatuses()
|
||||
except:
|
||||
print("N'arrive pas à ouvrir {}".format(xml))
|
||||
return
|
||||
#except:
|
||||
#print("N'arrive pas à ouvrir {}".format(xml))
|
||||
#return
|
||||
|
||||
|
||||
################# DIVERS #################
|
||||
|
@ -293,14 +319,16 @@ class outlineModel(QAbstractItemModel):
|
|||
|
||||
class outlineItem():
|
||||
|
||||
def __init__(self, title="", type="folder", xml=None):
|
||||
def __init__(self, model=None, title="", type="folder", xml=None):
|
||||
|
||||
self._data = {}
|
||||
self.childItems = []
|
||||
self._parent = None
|
||||
self._model = model
|
||||
|
||||
if title: self._data[Outline.title] = title
|
||||
self._data[Outline.type] = type
|
||||
|
||||
self._data[Outline.compile] = Qt.Checked
|
||||
if xml is not None:
|
||||
self.setFromXML(xml)
|
||||
|
||||
|
@ -327,6 +355,7 @@ class outlineItem():
|
|||
|
||||
elif Outline(column) in self._data:
|
||||
return self._data[Outline(column)]
|
||||
|
||||
else:
|
||||
return None
|
||||
|
||||
|
@ -341,29 +370,70 @@ class outlineItem():
|
|||
return QBrush(Qt.gray)
|
||||
|
||||
elif role == Qt.CheckStateRole and column == Outline.compile.value:
|
||||
if Outline(column) in self._data and self._data[Outline(column)]:
|
||||
return Qt.Checked
|
||||
else:
|
||||
return Qt.Unchecked
|
||||
return self._data[Outline(column)]
|
||||
|
||||
def setData(self, column, data, role=Qt.DisplayRole):
|
||||
if role not in [Qt.DisplayRole, Qt.EditRole, Qt.CheckStateRole]:
|
||||
print(column, column == Outline.text.value, data, role)
|
||||
return
|
||||
|
||||
if column == Outline.text.value and self.isFolder():
|
||||
# Folder have no text
|
||||
return
|
||||
|
||||
if column == Outline.text.value:
|
||||
wc = wordCount(data)
|
||||
self.setData(Outline.wordCount.value, wc)
|
||||
|
||||
if column in [Outline.wordCount.value, Outline.goal.value]:
|
||||
wc = self.data(Outline.wordCount.value)
|
||||
goal = self.data(Outline.goal.value)
|
||||
if goal and wc:
|
||||
self.setData(Outline.goalPercentage.value, int(wc) / float(goal))
|
||||
else:
|
||||
self.setData(Outline.goalPercentage.value, "0")
|
||||
if column == Outline.goal.value:
|
||||
self._data[Outline.setGoal] = toInt(data) if toInt(data) > 0 else ""
|
||||
|
||||
|
||||
updateWordCount = False
|
||||
if column in [Outline.wordCount.value, Outline.goal.value, Outline.setGoal.value]:
|
||||
updateWordCount = not Outline(column) in self._data or self._data[Outline(column)] <> data
|
||||
|
||||
self._data[Outline(column)] = data
|
||||
|
||||
if updateWordCount:
|
||||
self.updateWordCount()
|
||||
|
||||
def updateWordCount(self):
|
||||
if not self.isFolder():
|
||||
setGoal = toInt(self.data(Outline.setGoal.value))
|
||||
goal = toInt(self.data(Outline.goal.value))
|
||||
|
||||
if goal <> setGoal:
|
||||
self._data[Outline.goal] = setGoal
|
||||
if setGoal:
|
||||
wc = toInt(self.data(Outline.wordCount.value))
|
||||
self.setData(Outline.goalPercentage.value, wc / float(setGoal))
|
||||
|
||||
else:
|
||||
wc = 0
|
||||
for c in self.children():
|
||||
wc += toInt(c.data(Outline.wordCount.value))
|
||||
self._data[Outline.wordCount] = wc
|
||||
|
||||
setGoal = toInt(self.data(Outline.setGoal.value))
|
||||
goal = toInt(self.data(Outline.goal.value))
|
||||
|
||||
if setGoal:
|
||||
if goal <> setGoal:
|
||||
self._data[Outline.goal] = setGoal
|
||||
else:
|
||||
goal = 0
|
||||
for c in self.children():
|
||||
goal += toInt(c.data(Outline.goal.value))
|
||||
self._data[Outline.goal] = goal
|
||||
|
||||
if goal:
|
||||
self.setData(Outline.goalPercentage.value, wc / float(goal))
|
||||
|
||||
self.emitDataChanged()
|
||||
|
||||
if self.parent():
|
||||
self.parent().updateWordCount()
|
||||
|
||||
def row(self):
|
||||
if self.parent:
|
||||
|
@ -375,6 +445,16 @@ class outlineItem():
|
|||
def insertChild(self, row, child):
|
||||
self.childItems.insert(row, child)
|
||||
child._parent = self
|
||||
child._model = self._model
|
||||
self.updateWordCount()
|
||||
|
||||
def index(self, column=0):
|
||||
return self._model.indexFromItem(self, column)
|
||||
|
||||
def emitDataChanged(self):
|
||||
idx = self.index()
|
||||
if idx:
|
||||
self._model.dataChanged.emit(idx, self.index(len(Outline)))
|
||||
|
||||
def removeChild(self, row):
|
||||
self.childItems.pop(row)
|
||||
|
@ -388,13 +468,28 @@ class outlineItem():
|
|||
def isCompile(self):
|
||||
return Outline.compile in self._data and self._data[Outline.compile]
|
||||
|
||||
def title(self):
|
||||
if Outline.title in self._data:
|
||||
return self._data[Outline.title]
|
||||
else:
|
||||
return ""
|
||||
|
||||
def isScene(self):
|
||||
return self._data[Outline.type] == "scene"
|
||||
|
||||
def level(self):
|
||||
if self.parent():
|
||||
return self.parent().level() + 1
|
||||
else:
|
||||
return -1
|
||||
|
||||
def toXML(self):
|
||||
item = ET.Element("outlineItem")
|
||||
|
||||
exclude = [Outline.goal, Outline.goalPercentage]
|
||||
|
||||
for attrib in Outline:
|
||||
if attrib in exclude: continue
|
||||
val = self.data(attrib.value)
|
||||
if val:
|
||||
item.set(attrib.name, unicode(val))
|
||||
|
@ -412,5 +507,5 @@ class outlineItem():
|
|||
self.setData(Outline.__members__[k].value, unicode(root.attrib[k]))
|
||||
|
||||
for child in root:
|
||||
item = outlineItem(xml=ET.tostring(child))
|
||||
item = outlineItem(self._model, xml=ET.tostring(child))
|
||||
self.appendChild(item)
|
|
@ -6,6 +6,7 @@ from __future__ import unicode_literals
|
|||
|
||||
from qt import *
|
||||
from enums import *
|
||||
from functions import *
|
||||
|
||||
class treeOutlinePersoDelegate(QStyledItemDelegate):
|
||||
|
||||
|
@ -48,8 +49,64 @@ class treeOutlineCompileDelegate(QStyledItemDelegate):
|
|||
def __init__(self, parent=None):
|
||||
QStyledItemDelegate.__init__(self, parent)
|
||||
|
||||
#def displayText(self, value, locale):
|
||||
#return ""
|
||||
def displayText(self, value, locale):
|
||||
return ""
|
||||
|
||||
class treeOutlineGoalPercentageDelegate(QStyledItemDelegate):
|
||||
def __init__(self, parent=None):
|
||||
QStyledItemDelegate.__init__(self, parent)
|
||||
|
||||
def paint(self, painter, option, index):
|
||||
if not index.isValid():
|
||||
return QStyledItemDelegate.paint(self, painter, option, index)
|
||||
|
||||
QStyledItemDelegate.paint(self, painter, option, index)
|
||||
|
||||
item = index.internalPointer()
|
||||
|
||||
if not item.data(Outline.goal.value):
|
||||
return
|
||||
|
||||
p = toFloat(item.data(Outline.goalPercentage.value))
|
||||
if p > 1: p = 1.
|
||||
|
||||
typ = item.data(Outline.type.value)
|
||||
|
||||
level = item.level()
|
||||
|
||||
margin = 7
|
||||
#height = 5 if typ == "folder" else 3
|
||||
height = max(12 - 2 * level, 6)
|
||||
painter.save()
|
||||
|
||||
rect = option.rect.adjusted(margin, margin, -margin, -margin)
|
||||
#rect.setWidth(rect.width() - level * rect.width() / 10)
|
||||
rect.setHeight(height)
|
||||
rect.setTop(option.rect.top() + (option.rect.height() - height) / 2)
|
||||
painter.drawRect(rect)
|
||||
|
||||
c1 = QColor(Qt.red)
|
||||
c2 = QColor(Qt.blue)
|
||||
c3 = QColor(Qt.darkGreen)
|
||||
if p < 0.3:
|
||||
painter.setBrush(QBrush(c1))
|
||||
elif p < 0.8:
|
||||
painter.setBrush(QBrush(c2))
|
||||
else:
|
||||
painter.setBrush(QBrush(c3))
|
||||
|
||||
#if typ == "folder":
|
||||
#painter.setBrush(QBrush(Qt.blue))
|
||||
#else:
|
||||
#painter.setBrush(QBrush(Qt.green))
|
||||
|
||||
r2 = QRect(rect)
|
||||
r2.setWidth(r2.width() * p)
|
||||
painter.drawRect(r2)
|
||||
painter.restore()
|
||||
|
||||
def displayText(self, value, locale):
|
||||
return ""
|
||||
|
||||
class treeOutlineStatusDelegate(QStyledItemDelegate):
|
||||
|
||||
|
|
|
@ -1,11 +1,39 @@
|
|||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<outlineItem title="root" type="folder">
|
||||
<outlineItem title="Nouveau" type="folder" summarySentance="a" compile="2">
|
||||
<outlineItem title="Nouveau" type="scene" summarySentance="b" compile="2" text="Le texte de cet élément" wordCount="5" goalPercentage="0"/>
|
||||
<outlineItem title="Nouveau" type="scene" summarySentance="c" compile="2"/>
|
||||
<outlineItem title="Nouveau" type="scene" summarySentance="d" compile="2"/>
|
||||
</outlineItem>
|
||||
<outlineItem title="Nouveau" type="folder" summarySentance="e" compile="2"/>
|
||||
<outlineItem title="root" type="folder" compile="2" wordCount="102" setGoal="112">
|
||||
<outlineItem title="Nouveau" type="folder" compile="2"/>
|
||||
<outlineItem title="Nouveau" type="scene" compile="2" goal="3" goalPercentage="1.0"/>
|
||||
<outlineItem title="Parent" type="folder" compile="2" wordCount="87">
|
||||
<outlineItem title="Nouveau" type="folder" compile="2" wordCount="73">
|
||||
<outlineItem title="Nouveau" type="scene" compile="2" text="Du texteDu texteDu texteDu texteDu texteDu texteDu texteDu texteDu texteDu texteDu texteDu texteDu texteDu texteDu texteDu texteDu texteDu texteDu texteDu texteDu texteDu texteDu texteDu texte Du texteDu texteDu texteDu texteDu texteDu texteDu texteDu texteDu texteDu texteDu texteDu texteDu texteDu texteDu texteDu texteDu texteDu texteDu texteDu texteDu texteDu texteDu texteDu texte Du texteDu texteDu texteDu texteDu texteDu texteDu texteDu texteDu texteDu texteDu texteDu texteDu texteDu texteDu texteDu texteDu texteDu texteDu texteDu texteDu texteDu texteDu texteDu texte " wordCount="73" setGoal="150"/>
|
||||
<outlineItem title="Nouveau" type="scene" compile="2" setGoal="50"/>
|
||||
<outlineItem title="Nouveau" type="scene" compile="2" setGoal="50"/>
|
||||
<outlineItem title="Nouveau" type="folder" compile="2" setGoal="100">
|
||||
<outlineItem title="Nouveau" type="folder" compile="2" setGoal="50">
|
||||
<outlineItem title="Nouveau" type="folder" compile="2" setGoal="200">
|
||||
<outlineItem title="Nouveau" type="folder" compile="2" setGoal="100">
|
||||
<outlineItem title="Nouveau" type="folder" compile="2" setGoal="100">
|
||||
<outlineItem title="Nouveau" type="folder" compile="2" setGoal="100"/>
|
||||
</outlineItem>
|
||||
</outlineItem>
|
||||
</outlineItem>
|
||||
</outlineItem>
|
||||
</outlineItem>
|
||||
</outlineItem>
|
||||
<outlineItem title="MOIMOIMOI" type="scene" compile="2" text="asdasdasdasdasd asd asd asd asd asd asd asd " wordCount="10" setGoal="150"/>
|
||||
<outlineItem title="Nouveau" type="scene" compile="2" text="asd asd asd a" wordCount="4" setGoal="150"/>
|
||||
<outlineItem title="Nouveau" type="folder" compile="2">
|
||||
<outlineItem title="Nouveau" type="folder" compile="2">
|
||||
<outlineItem title="Nouveau" type="folder" compile="2">
|
||||
<outlineItem title="Nouveau" type="folder" compile="2">
|
||||
<outlineItem title="Nouveau" type="folder" compile="2" setGoal="100"/>
|
||||
</outlineItem>
|
||||
</outlineItem>
|
||||
</outlineItem>
|
||||
</outlineItem>
|
||||
</outlineItem>
|
||||
<outlineItem title="MOIMOIMOI" type="scene" compile="2" text=" asd asd asd " wordCount="3" setGoal="3"/>
|
||||
<outlineItem title="Nouveau" type="scene" compile="2" text="asdasd asd " wordCount="2" setGoal="25"/>
|
||||
<outlineItem title="Nouveau" type="folder" compile="2"/>
|
||||
<outlineItem title="Nouveau" type="folder" compile="2"/>
|
||||
<outlineItem title="B" type="scene" compile="2" text="asd asd asd asd asd asd asd asd asd " wordCount="10" setGoal="25"/>
|
||||
<outlineItem title="A" type="scene" compile="2" setGoal="146"/>
|
||||
</outlineItem>
|
||||
|
|
Loading…
Reference in a new issue