From e27ff93a9bb26b110f6ccb98b5692ef5fb6d83e3 Mon Sep 17 00:00:00 2001 From: Olivier Keshavjee Date: Mon, 8 Jun 2015 23:36:15 +0200 Subject: [PATCH] Adds: cork view. Great, except that drag n drop doesn't work... --- src/mainWindow.py | 6 + src/models/outlineModel.py | 6 +- src/ui/editors/corkDelegate.py | 299 ++++++++++++++++++++++++++++++ src/ui/editors/editorWidget.py | 36 +++- src/ui/editors/editorWidget_ui.py | 24 ++- src/ui/editors/editorWidget_ui.ui | 30 ++- src/ui/mainWindow.py | 28 ++- src/ui/mainWindow.ui | 60 ++++++ test_project/outline.xml | 40 ++-- 9 files changed, 504 insertions(+), 25 deletions(-) create mode 100644 src/ui/editors/corkDelegate.py diff --git a/src/mainWindow.py b/src/mainWindow.py index ff4c1e7f..2b470b7b 100644 --- a/src/mainWindow.py +++ b/src/mainWindow.py @@ -219,6 +219,9 @@ class MainWindow(QMainWindow, Ui_MainWindow): self.treePlanOutline.selectionModel().currentChanged.connect(self.outlineSelectionChanged) self.treePlanOutline.selectionModel().currentChanged.connect(self.outlineSelectionChanged) + self.sldCorkSizeFactor.valueChanged.connect(self.redacEditor.setCorkSizeFactor) + self.btnRedacFolderCork.toggled.connect(self.sldCorkSizeFactor.setVisible) + self.btnRedacFolderText.toggled.connect(lambda v: self.redacEditor.setFolderView("text" if v else "cork")) #Debug self.mdlFlatData.setVerticalHeaderLabels(["Infos générales", "Summary"]) @@ -244,6 +247,9 @@ class MainWindow(QMainWindow, Ui_MainWindow): self.cmbRedacPOV.setHidden(idx.internalPointer().isFolder()) self.lblPlanPOV.setHidden(idx.internalPointer().isFolder()) self.cmbPlanPOV.setHidden(idx.internalPointer().isFolder()) + self.btnRedacFolderText.setHidden(not idx.internalPointer().isFolder()) + self.btnRedacFolderCork.setHidden(not idx.internalPointer().isFolder()) + self.sldCorkSizeFactor.setHidden(not idx.internalPointer().isFolder()) def outlineAddItem(self, type="folder"): if len(self.treeRedacOutline.selectedIndexes()) == 0: diff --git a/src/models/outlineModel.py b/src/models/outlineModel.py index 47fe48ad..e67828cb 100644 --- a/src/models/outlineModel.py +++ b/src/models/outlineModel.py @@ -138,7 +138,6 @@ class outlineModel(QAbstractItemModel): flags = QAbstractItemModel.flags(self, index) | Qt.ItemIsEditable - if index.isValid() and index.internalPointer().isFolder() and index.column() == 0: flags |= Qt.ItemIsDragEnabled | Qt.ItemIsDropEnabled @@ -177,8 +176,8 @@ class outlineModel(QAbstractItemModel): def supportedDropActions(self): - #return Qt.MoveAction # Qt.CopyAction | - return Qt.CopyAction | Qt.MoveAction + return Qt.MoveAction # Qt.CopyAction | + #return Qt.CopyAction | Qt.MoveAction #def canDropMimeData(self, data, action, row, column, parent): #if not data.hasFormat("application/xml"): @@ -277,6 +276,7 @@ class outlineModel(QAbstractItemModel): return self.removeRows(row, 1, parent) def removeRows(self, row, count, parent=QModelIndex()): + print("Removing") if not parent.isValid(): parentItem = self.rootItem else: diff --git a/src/ui/editors/corkDelegate.py b/src/ui/editors/corkDelegate.py new file mode 100644 index 00000000..afe36b54 --- /dev/null +++ b/src/ui/editors/corkDelegate.py @@ -0,0 +1,299 @@ +#!/usr/bin/env python +#--!-- coding: utf8 --!-- + + + + +from qt import * +from enums import * +from functions import * +from random import randint + +class corkDelegate(QStyledItemDelegate): + + def __init__(self, parent=None): + QStyledItemDelegate.__init__(self, parent) + self.factor = 1 + self.defaultSize = QSize(300, 200) + self.lastPos = None + self.editing = None + self.margin = 5 + + def setCorkSizeFactor(self, v): + self.factor = v / 100. + + def sizeHint(self, option, index): + return self.defaultSize * self.factor + + def editorEvent(self, event, model, option, index): + # We catch the mouse position in the widget to know which part to edit + if type(event) == QMouseEvent: + self.lastPos = event.pos() # - option.rect.topLeft() + return QStyledItemDelegate.editorEvent(self, event, model, option, index) + + def createEditor(self, parent, option, index): + self.updateRects(option, index) + + if self.mainLineRect.contains(self.lastPos): + # One line summary + self.editing = Outline.summarySentance + edt = QLineEdit(parent) + edt.setFocusPolicy(Qt.StrongFocus) + edt.setFrame(False) + edt.setAlignment(Qt.AlignCenter) + edt.setPlaceholderText(self.tr("One line summary")) + f = QFont(option.font) + f.setItalic(True) + edt.setFont(f) + return edt + + elif self.titleRect.contains(self.lastPos): + # Title + self.editing = Outline.title + edt = QLineEdit(parent) + edt.setFocusPolicy(Qt.StrongFocus) + edt.setFrame(False) + f = QFont(option.font) + #f.setPointSize(f.pointSize() + 1) + f.setBold(True) + edt.setFont(f) + edt.setAlignment(Qt.AlignCenter) + #edt.setGeometry(self.titleRect) + return edt + + else: # self.mainTextRect.contains(self.lastPos): + # Summary + self.editing = Outline.summaryFull + edt = QPlainTextEdit(parent) + edt.setFocusPolicy(Qt.StrongFocus) + edt.setFrameShape(QFrame.NoFrame) + edt.setPlaceholderText(self.tr("Full summary")) + return edt + + + def updateEditorGeometry(self, editor, option, index): + + if self.editing == Outline.summarySentance: + # One line summary + editor.setGeometry(self.mainLineRect) + + elif self.editing == Outline.title: + # Title + editor.setGeometry(self.titleRect) + + elif self.editing == Outline.summaryFull: + # Summary + editor.setGeometry(self.mainTextRect) + + def setEditorData(self, editor, index): + item = index.internalPointer() + + if self.editing == Outline.summarySentance: + # One line summary + editor.setText(item.data(Outline.summarySentance.value)) + + elif self.editing == Outline.title: + # Title + editor.setText(index.data()) + + elif self.editing == Outline.summaryFull: + # Summary + editor.setPlainText(item.data(Outline.summaryFull.value)) + + def setModelData(self, editor, model, index): + + if self.editing == Outline.summarySentance: + # One line summary + model.setData(index.sibling(index.row(), Outline.summarySentance.value), editor.text()) + + elif self.editing == Outline.title: + # Title + model.setData(index, editor.text(), Outline.title.value) + + elif self.editing == Outline.summaryFull: + # Summary + model.setData(index.sibling(index.row(), Outline.summaryFull.value), editor.toPlainText()) + print(editor.toPlainText()) + + def updateRects(self, option, index): + margin = self.margin + iconSize = max(16*self.factor, 12) + item = index.internalPointer() + self.itemRect = option.rect.adjusted(margin, margin, -margin, -margin) + self.iconRect = QRect(self.itemRect.topLeft() + QPoint(margin, margin), QSize(iconSize, iconSize)) + self.titleRect = QRect(self.iconRect.topRight().x() + margin, self.iconRect.top(), + self.itemRect.topRight().x() - self.iconRect.right() - 2 * margin, + self.iconRect.height()) + self.bottomRect = QRect(QPoint(self.itemRect.x(), self.iconRect.bottom() + margin), + QPoint(self.itemRect.right(), self.itemRect.bottom())) + self.topRect = QRect(self.itemRect.topLeft(), self.bottomRect.topRight()) + self.mainRect = self.bottomRect.adjusted(margin, margin, -margin, -margin) + self.mainLineRect = QRect(self.mainRect.topLeft(), + self.mainRect.topRight() + QPoint(0, iconSize)) + self.mainTextRect = QRect(self.mainLineRect.bottomLeft() + QPoint(0, margin), + self.mainRect.bottomRight()) + if not item.data(Outline.summarySentance.value) : + self.mainTextRect.setTopLeft(self.mainLineRect.topLeft()) + + + def paint(self, p, option, index): + #QStyledItemDelegate.paint(self, p, option, index) + if not index.isValid(): + return + + item = index.internalPointer() + self.updateRects(option, index) + + style = qApp.style() + + def _rotate(angle): + p.translate(self.mainRect.center()) + p.rotate(angle) + p.translate(-self.mainRect.center()) + + # Draw background + cg = QPalette.ColorGroup(QPalette.Normal if option.state & QStyle.State_Enabled else QPalette.Disabled) + if cg == QPalette.Normal and not option.state & QStyle.State_Active: + cg = QPalette.Inactive + + # Selection + if option.state & QStyle.State_Selected: + p.save() + p.setBrush(option.palette.brush(cg, QPalette.Highlight)) + p.setPen(Qt.NoPen) + p.drawRoundedRect(option.rect, 12, 12) + p.restore() + + # Stack + if item.isFolder() and item.childCount() > 0: + p.save() + angle = [-3, 5, 3] + p.setBrush(Qt.white) + for i in reversed(range(3)): + p.drawRoundedRect(self.itemRect.translated(3*i, 3*i), 10, 10) + p.restore() + + # Background + itemRect = self.itemRect + p.save() + p.setBrush(Qt.white) + pen = p.pen() + pen.setWidth(2) + p.setPen(pen) + p.drawRoundedRect(itemRect, 10, 10) + p.restore() + + # Title bar + topRect = self.topRect + p.save() + if item.isFolder(): + color = QColor(Qt.darkGreen) + else: + color = QColor(Qt.blue).lighter(175) + p.setPen(Qt.NoPen) + p.setBrush(color) + p.setClipRegion(QRegion(topRect)) + p.drawRoundedRect(itemRect, 10, 10) + #p.drawRect(topRect) + p.restore() + + # One line summary background + lineSummary = item.data(Outline.summarySentance.value) + fullSummary = item.data(Outline.summaryFull.value) + if lineSummary or not fullSummary: + m = self.margin + r = self.mainLineRect.adjusted(-m, -m, m, m/2) + p.save() + p.setPen(Qt.NoPen) + p.setBrush(QColor("#EEE")) + p.drawRect(r) + p.restore() + + # Border + p.save() + p.setBrush(Qt.NoBrush) + pen = p.pen() + pen.setWidth(2) + p.setPen(pen) + p.drawRoundedRect(itemRect, 10, 10) + p.restore() + + + # Draw the icon + iconRect = self.iconRect + mode = QIcon.Normal + if not option.state & style.State_Enabled: + mode = QIcon.Disabled + elif option.state & style.State_Selected: + mode = QIcon.Selected + index.data(Qt.DecorationRole).paint(p, iconRect, option.decorationAlignment, mode) + + # Draw title + p.save() + text = index.data() + titleRect = self.titleRect + if text: + f = QFont(option.font) + #f.setPointSize(f.pointSize() + 1) + f.setBold(True) + p.setFont(f) + fm = QFontMetrics(f) + elidedText = fm.elidedText(text, Qt.ElideRight, titleRect.width()) + p.drawText(titleRect, Qt.AlignCenter, elidedText) + p.restore() + + # Draw the line + bottomRect = self.bottomRect + p.save() + #p.drawLine(itemRect.x(), iconRect.bottom() + margin, + #itemRect.right(), iconRect.bottom() + margin) + p.drawLine(bottomRect.topLeft(), bottomRect.topRight()) + p.restore() + + # Draw status + mainRect = self.mainRect + status = item.data(Outline.status.value) + if status: + p.save() + p.setClipRegion(QRegion(mainRect)) + f = p.font() + f.setPointSize(f.pointSize() + 12) + f.setBold(True) + p.setFont(f) + p.setPen(QColor(Qt.red).lighter(175)) + _rotate(-35) + p.drawText(mainRect, Qt.AlignCenter, status) + p.restore() + + # Draw Summary + # One line + if lineSummary: + p.save() + f = QFont(option.font) + f.setItalic(True) + p.setFont(f) + fm = QFontMetrics(f) + elidedText = fm.elidedText(lineSummary, Qt.ElideRight, self.mainLineRect.width()) + p.drawText(self.mainLineRect, Qt.AlignCenter, elidedText) + p.restore() + + # Full summary + if fullSummary: + p.setFont(option.font) + p.drawText(self.mainTextRect, Qt.TextWordWrap, fullSummary) + + # Lines + if True: + p.save() + p.setPen(QColor("#EEE")) + fm = QFontMetrics(option.font) + h = fm.lineSpacing() + l = self.mainTextRect.topLeft() + QPoint(0, h) + while self.mainTextRect.contains(l): + p.drawLine(l, QPoint(self.mainTextRect.right(), l.y())) + l.setY(l.y() + h) + p.restore() + + #Debug + #for r in [self.itemRect, self.iconRect, self.titleRect, self.bottomRect, self.mainLineRect, self.mainTextRect]: + #p.drawRect(r) \ No newline at end of file diff --git a/src/ui/editors/editorWidget.py b/src/ui/editors/editorWidget.py index f368be54..7afc7162 100644 --- a/src/ui/editors/editorWidget.py +++ b/src/ui/editors/editorWidget.py @@ -8,6 +8,7 @@ from qt import * from enums import * from ui.editors.editorWidget_ui import * from ui.editors.customTextEdit import * +from ui.editors.corkDelegate import * from functions import * class editorWidget(QWidget, Ui_editorWidget_ui): @@ -25,6 +26,31 @@ class editorWidget(QWidget, Ui_editorWidget_ui): self.dictChanged.connect(self.txtRedacText.setDict) self.currentDict = "" self.spellcheck = True + self.folderView = "cork" + + self.corkView.setResizeMode(QListView.Adjust) + self.corkView.setWrapping(True) + self.corkView.setItemDelegate(corkDelegate()) + self.corkView.setSpacing(5) + self.corkView.setStyleSheet("""QListView { + background:#926239; + }""") + + def setFolderView(self, v): + oldV = self.folderView + if v == "cork": + self.folderView = "cork" + else: + self.folderView = "text" + + if oldV != self.folderView and self.currentIndex: + self.setCurrentModelIndex(self.currentIndex) + + def setCorkSizeFactor(self, v): + self.corkView.itemDelegate().setCorkSizeFactor(v) + r = self.corkView.rootIndex() + for c in range(r.row()): + self.corkView.itemDelegate().sizeHintChanged.emit(r.child(c, 0)) def setCurrentModelIndex(self, index): @@ -35,7 +61,7 @@ class editorWidget(QWidget, Ui_editorWidget_ui): item = index.internalPointer() - if item.isFolder(): + if item.isFolder() and self.folderView == "text": self.stack.setCurrentIndex(1) w = QWidget() @@ -84,7 +110,11 @@ class editorWidget(QWidget, Ui_editorWidget_ui): l.addItem(QSpacerItem(10, 1000, QSizePolicy.Minimum, QSizePolicy.Expanding)) self.scroll.setWidget(w) - + elif item.isFolder() and self.folderView == "cork": + self.stack.setCurrentIndex(2) + self.corkView.setModel(self._model) + self.corkView.setRootIndex(self.currentIndex) + else: self.stack.setCurrentIndex(0) @@ -95,6 +125,8 @@ class editorWidget(QWidget, Ui_editorWidget_ui): self.currentIndex = None def modelDataChanged(self, topLeft, bottomRight): + if not self.currentIndex: + return if topLeft.row() <= self.currentIndex.row() <= bottomRight.row(): self.updateStatusBar() diff --git a/src/ui/editors/editorWidget_ui.py b/src/ui/editors/editorWidget_ui.py index 21c14ed3..029b8d5e 100644 --- a/src/ui/editors/editorWidget_ui.py +++ b/src/ui/editors/editorWidget_ui.py @@ -12,9 +12,9 @@ class Ui_editorWidget_ui(object): def setupUi(self, editorWidget_ui): editorWidget_ui.setObjectName("editorWidget_ui") editorWidget_ui.resize(400, 300) - self.horizontalLayout = QtWidgets.QHBoxLayout(editorWidget_ui) - self.horizontalLayout.setContentsMargins(0, 0, 0, 0) - self.horizontalLayout.setObjectName("horizontalLayout") + self.verticalLayout_2 = QtWidgets.QVBoxLayout(editorWidget_ui) + self.verticalLayout_2.setContentsMargins(0, 0, 0, 0) + self.verticalLayout_2.setObjectName("verticalLayout_2") self.stack = QtWidgets.QStackedWidget(editorWidget_ui) self.stack.setObjectName("stack") self.scene = QtWidgets.QWidget() @@ -42,10 +42,24 @@ class Ui_editorWidget_ui(object): self.scroll.setWidget(self.scrollAreaWidgetContents) self.verticalLayout.addWidget(self.scroll) self.stack.addWidget(self.folder) - self.horizontalLayout.addWidget(self.stack) + self.cork = QtWidgets.QWidget() + self.cork.setObjectName("cork") + self.horizontalLayout_3 = QtWidgets.QHBoxLayout(self.cork) + self.horizontalLayout_3.setContentsMargins(0, 0, 0, 0) + self.horizontalLayout_3.setObjectName("horizontalLayout_3") + self.corkView = QtWidgets.QListView(self.cork) + self.corkView.setDragDropMode(QtWidgets.QAbstractItemView.DragDrop) + self.corkView.setDefaultDropAction(QtCore.Qt.MoveAction) + self.corkView.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection) + self.corkView.setVerticalScrollMode(QtWidgets.QAbstractItemView.ScrollPerPixel) + self.corkView.setFlow(QtWidgets.QListView.LeftToRight) + self.corkView.setObjectName("corkView") + self.horizontalLayout_3.addWidget(self.corkView) + self.stack.addWidget(self.cork) + self.verticalLayout_2.addWidget(self.stack) self.retranslateUi(editorWidget_ui) - self.stack.setCurrentIndex(0) + self.stack.setCurrentIndex(2) QtCore.QMetaObject.connectSlotsByName(editorWidget_ui) def retranslateUi(self, editorWidget_ui): diff --git a/src/ui/editors/editorWidget_ui.ui b/src/ui/editors/editorWidget_ui.ui index ea72f10a..0ef19368 100644 --- a/src/ui/editors/editorWidget_ui.ui +++ b/src/ui/editors/editorWidget_ui.ui @@ -13,14 +13,14 @@ Form - + 0 - 0 + 2 @@ -62,6 +62,32 @@ + + + + 0 + + + + + QAbstractItemView::DragDrop + + + Qt::MoveAction + + + QAbstractItemView::ExtendedSelection + + + QAbstractItemView::ScrollPerPixel + + + QListView::LeftToRight + + + + + diff --git a/src/ui/mainWindow.py b/src/ui/mainWindow.py index a2ea2846..dc457e48 100644 --- a/src/ui/mainWindow.py +++ b/src/ui/mainWindow.py @@ -857,6 +857,28 @@ class Ui_MainWindow(object): self.btnRedacShowOutline.setChecked(True) self.btnRedacShowOutline.setObjectName("btnRedacShowOutline") self.horizontalLayout_19.addWidget(self.btnRedacShowOutline) + self.btnRedacFolderText = QtWidgets.QPushButton(self.layoutWidget1) + self.btnRedacFolderText.setCheckable(True) + self.btnRedacFolderText.setObjectName("btnRedacFolderText") + self.buttonGroup = QtWidgets.QButtonGroup(MainWindow) + self.buttonGroup.setObjectName("buttonGroup") + self.buttonGroup.addButton(self.btnRedacFolderText) + self.horizontalLayout_19.addWidget(self.btnRedacFolderText) + self.btnRedacFolderCork = QtWidgets.QPushButton(self.layoutWidget1) + self.btnRedacFolderCork.setCheckable(True) + self.btnRedacFolderCork.setChecked(True) + self.btnRedacFolderCork.setObjectName("btnRedacFolderCork") + self.buttonGroup.addButton(self.btnRedacFolderCork) + self.horizontalLayout_19.addWidget(self.btnRedacFolderCork) + self.sldCorkSizeFactor = QtWidgets.QSlider(self.layoutWidget1) + self.sldCorkSizeFactor.setMinimumSize(QtCore.QSize(100, 0)) + self.sldCorkSizeFactor.setMaximumSize(QtCore.QSize(200, 16777215)) + self.sldCorkSizeFactor.setMinimum(50) + self.sldCorkSizeFactor.setMaximum(200) + self.sldCorkSizeFactor.setProperty("value", 100) + self.sldCorkSizeFactor.setOrientation(QtCore.Qt.Horizontal) + self.sldCorkSizeFactor.setObjectName("sldCorkSizeFactor") + self.horizontalLayout_19.addWidget(self.sldCorkSizeFactor) spacerItem11 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) self.horizontalLayout_19.addItem(spacerItem11) self.lblRedacWC = QtWidgets.QLabel(self.layoutWidget1) @@ -1252,6 +1274,8 @@ class Ui_MainWindow(object): self.txtPlanSummarySentance.setPlaceholderText(_translate("MainWindow", "One line scene summary")) self.label_9.setText(_translate("MainWindow", "Few sentences summary:")) self.tabMain.setTabText(self.tabMain.indexOf(self.lytTabOutline), _translate("MainWindow", "Outline")) + self.btnRedacFolderText.setText(_translate("MainWindow", "Text")) + self.btnRedacFolderCork.setText(_translate("MainWindow", "Cork")) self.btnRedacFullscreen.setShortcut(_translate("MainWindow", "F11")) self.groupBox_4.setTitle(_translate("MainWindow", "Properties")) self.lblRedacPOV.setText(_translate("MainWindow", "POV")) @@ -1305,9 +1329,9 @@ class Ui_MainWindow(object): self.actSpellcheck.setText(_translate("MainWindow", "Spellcheck")) self.actSpellcheck.setShortcut(_translate("MainWindow", "F8")) +from ui.collapsibleGroupBox2 import collapsibleGroupBox2 +from ui.sldImportance import sldImportance from ui.cmbOutlineStatusChoser import cmbOutlineStatusChoser from ui.chkOutlineCompile import chkOutlineCompile -from ui.collapsibleGroupBox2 import collapsibleGroupBox2 from ui.cmbOutlinePersoChoser import cmbOutlinePersoChoser -from ui.sldImportance import sldImportance from ui.editors.editorWidget import editorWidget diff --git a/src/ui/mainWindow.ui b/src/ui/mainWindow.ui index c31723ff..7e4da4c7 100644 --- a/src/ui/mainWindow.ui +++ b/src/ui/mainWindow.ui @@ -1660,6 +1660,63 @@ + + + + Text + + + true + + + buttonGroup + + + + + + + Cork + + + true + + + true + + + buttonGroup + + + + + + + + 100 + 0 + + + + + 200 + 16777215 + + + + 50 + + + 200 + + + 100 + + + Qt::Horizontal + + + @@ -2367,4 +2424,7 @@ + + + diff --git a/test_project/outline.xml b/test_project/outline.xml index fdbd1d32..9d928aae 100644 --- a/test_project/outline.xml +++ b/test_project/outline.xml @@ -1,10 +1,10 @@ - + - - + + @@ -13,20 +13,38 @@ + + + + + + + + + + + + - - + + + - - - - + + + + + + + - - + + + +