[go: nahoru, domu]

Skip to content

Commit

Permalink
CommentList and Project Section married
Browse files Browse the repository at this point in the history
The comment list, developed on feature branch `gui_comment_list` is now integrated into the main application files. These already contained code to open a project and select a topic.
  • Loading branch information
podestplatz committed Jul 10, 2019
1 parent a702021 commit 894de41
Show file tree
Hide file tree
Showing 3 changed files with 297 additions and 11 deletions.
152 changes: 152 additions & 0 deletions bcfplugin/gui/plugin_delegate.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
from PySide2.QtWidgets import *
from PySide2.QtGui import *
from PySide2.QtCore import QModelIndex, Slot, QSize, QRect, QPoint, QRectF

from copy import copy


class CommentDelegate(QStyledItemDelegate):

def __init__(self, parent = None):

QStyledItemDelegate.__init__(self, parent)
self.baseFontSize = 12
self.commentFont = QFont("times")
self.updateFonts(self.commentFont)

self.commentYOffset = 10


def paint(self, painter, option, index):

if option.state & QStyle.State_Selected:
painter.fillRect(option.rect, option.palette.highlight())
idx = index.row()

comment = index.model().data(index, Qt.DisplayRole)
# top y coordinate at which drawing will begin downwards
topY = option.rect.y()

# save painter state, since color and font are changed
painter.save()

# whole area that can be drawn onto
boundingRect = painter.viewport()

# extract pen and font from painter
pen = painter.pen()
self.updateFonts(painter.font())
fontMetric = painter.fontMetrics()

# draw comment
commentTextHeight = fontMetric.height()
commentTextWidth = fontMetric.width(comment[0])
commentStart = QPoint(10, topY + fontMetric.height())
painter.drawText(commentStart, comment[0])

# draw separation line
pen.setColor(QColor("lightGray"))
painter.setPen(pen)
lineStart = QPoint(commentStart.x(),
commentStart.y() + commentTextHeight / 2)
lineEnd = QPoint(lineStart.x() + boundingRect.width() - 20,
lineStart.y())
painter.drawLine(lineStart, lineEnd)

# draw author
fontMetric = QFontMetrics(self.authorFont)
pen.setColor(QColor("blue"))
painter.setPen(pen)
painter.setFont(self.authorFont)
authorStart = QPoint(lineStart.x(),
lineStart.y() + fontMetric.height())
authorWidth = fontMetric.width(comment[1])
authorEnd = QPoint(authorStart.x() + authorWidth,
authorStart.y())
painter.drawText(authorStart, comment[1])

dateStart = QPoint(authorEnd.x() + 10, authorEnd.y())
painter.drawText(dateStart, comment[2])

painter.restore()


def createEditor(self, parent, option, index):

""" Makes the comment and the author available in a QLineEdit """

comment = index.model().data(index, Qt.EditRole)
startText = comment[0] + " -- " + comment[1]

editor = QLineEdit(startText, parent)
editor.setFrame(True)

return editor


def setEditorData(self, editor, index):

""" Updates the editor data with the data at `index` in the model """

comment = index.model().data(index, Qt.EditRole)
editorText = comment[0] + " -- " + comment[1]
editor.setText(editorText)


def setModelData(self, editor, model, index):

""" Updates the model at `index` with the current text of the editor """

text = editor.text()
splitText = [ textItem.strip() for textItem in text.split("--") ]
if len(splitText) != 2:
#TODO raise/display an exception
print("Here we have an invalid string")
return

success = model.setData(index, (splitText[0], splitText[1]))
if not success:
print("Well that did not work")


def updateFonts(self, baseFont):

""" Set the internal fonts to baseFont and update their sizes """

self.commentFont = copy(baseFont)
self.commentFont.setBold(True)
self.commentFont.setPointSize(self.baseFontSize)

self.authorFont = copy(baseFont)
self.authorFont.setPointSize(self.baseFontSize - 4)


def calcCommentSize(self, comment, option):

""" Calculate the size of a comment element """

commentFontMetric = QFontMetrics(self.commentFont)
authorFontMetric = QFontMetrics(self.authorFont)

commentTextHeight = commentFontMetric.height()
authorTextHeight = authorFontMetric.height()

# +1 is the separation line that is drawn
# commentTextHeight / 2 is the offset from the comment text towards the
# separation line
height = (commentTextHeight + authorTextHeight +
commentTextHeight / 2 + self.commentYOffset + 1)
width = option.rect.width()

size = QSize(width, height)
return size


def sizeHint(self, option, index):

""" Return the size of a comment element. """

comment = index.model().data(index, Qt.DisplayRole)
size = self.calcCommentSize(comment, option)

return size
115 changes: 110 additions & 5 deletions bcfplugin/gui/plugin_model.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
from PySide2.QtWidgets import *
from PySide2.QtGui import *
from PySide2.QtCore import QAbstractListModel, QModelIndex, Slot
from PySide2.QtCore import QAbstractListModel, QModelIndex, Slot, Signal

import bcfplugin.programmaticInterface as pI
from bcfplugin.rdwr.topic import Topic


def openProjectBtnHandler(file):
Expand All @@ -13,6 +15,8 @@ def getProjectName():

class TopicCBModel(QAbstractListModel):

selectionChanged = Signal((Topic,))

def __init__(self):
QAbstractListModel.__init__(self)
self.updateTopics()
Expand All @@ -21,24 +25,30 @@ def __init__(self):

def updateTopics(self):

self.beginResetModel()

if not pI.isProjectOpen():
self.endResetModel()
return

topics = pI.getTopics()
if topics != pI.OperationResults.FAILURE:
self.items = [ topic[1].title for topic in topics ]
self.items.insert(0, "-- Select your topic --")
self.items = [ topic[1] for topic in topics ]

self.endResetModel()


def rowCount(self, parent = QModelIndex()):
return len(self.items)
return len(self.items) + 1 # plus the dummy element


def data(self, index, role = Qt.DisplayRole):

idx = index.row()
if role == Qt.DisplayRole:
return self.items[idx]
if idx == 0:
return "-- Select your topic --"
return self.items[idx - 1].title # subtract the dummy element

else:
return None
Expand All @@ -51,6 +61,101 @@ def flags(self, index):
return flaggs


@Slot(int)
def newSelection(self, index):

if index > 0: # 0 is the dummy element
self.selectionChanged.emit(self.items[index - 1])


@Slot()
def projectOpened(self):
self.updateTopics()


class CommentModel(QAbstractListModel):


def __init__(self, parent = None):

QAbstractListModel.__init__(self, parent)
self.items = []


@Slot(Topic)
def resetItems(self, topic):

""" Load comments from `topic` """

self.beginResetModel()

if not pI.isProjectOpen():
#TODO: display error
self.endResetModel()
return

comments = pI.getComments(topic)
if comments == pI.OperationResults.FAILURE:
#TODO: display error
self.endResetModel()
return

self.items = [ comment[1] for comment in comments ]

self.endResetModel()


def rowCount(self, parent = QModelIndex()):

return len(self.items)


def data(self, index, role=Qt.DisplayRole):

if not index.isValid() or (role != Qt.DisplayRole and
role != Qt.EditRole):
return None

comment = None
item = self.items[index.row()]
commentText = ""
commentAuthor = ""
commentDate = ""
dateFormat = "%Y-%m-%d %X"
if role == Qt.DisplayRole:
commentText = item.comment
commentAuthor = item.author if item.modAuthor == "" else item.modAuthor
commentDate = (item.date if item.modDate == "" else item.modDate)
commentDate = commentDate.strftime(dateFormat)
comment = (commentText, commentAuthor, commentDate)

elif role == Qt.EditRole: # date is automatically set when editing
commentText = item.comment
commentAuthor = item.author if item.modAuthor == "" else item.modAuthor
comment = (commentText, commentAuthor)

return comment


def flags(self, index):

fl = Qt.ItemIsSelectable | Qt.ItemIsEditable | Qt.ItemIsEnabled
return fl


def setData(self, index, value, role=Qt.EditRole):
# https://doc.qt.io/qtforpython/PySide2/QtCore/QAbstractItemModel.html#PySide2.QtCore.PySide2.QtCore.QAbstractItemModel.roleNames

if not index.isValid() or role != Qt.EditRole:
return False

commentToEdit = self.items[index.row()]
commentToEdit.comment = value[0]
commentToEdit.modAuthor = value[1]

pI.modifyElement(commentToEdit, value[1])
topic = pI.getTopic(commentToEdit)
self.resetItems(topic)

return True

41 changes: 35 additions & 6 deletions bcfplugin/gui/plugin_view.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from PySide2.QtCore import QAbstractListModel, QModelIndex, Slot, QDir

import plugin_model as model
import plugin_delegate as delegate
import bcfplugin.util as util


Expand Down Expand Up @@ -42,6 +43,10 @@ def __init__(self):
self.topicGroup.hide()
self.mainLayout.addWidget(self.topicGroup)

self.commentGroup = self.createCommentGroup()
self.commentGroup.hide()
self.mainLayout.addWidget(self.commentGroup)

self.setLayout(self.mainLayout)


Expand All @@ -55,6 +60,7 @@ def createTopicGroup(self):
self.topicCb = QComboBox()
self.topicCbModel = model.TopicCBModel()
self.topicCb.setModel(self.topicCbModel)
self.topicCb.currentIndexChanged.connect(self.topicCbModel.newSelection)

self.topicHLayout = QHBoxLayout(topicGroup)
self.topicHLayout.addWidget(self.topicLabel)
Expand All @@ -64,8 +70,26 @@ def createTopicGroup(self):


def createCommentGroup(self):
#TODO: implement
pass

commentGroup = QGroupBox()
commentGroup.setObjectName("commentGroup")

self.commentLayout = QVBoxLayout(commentGroup)
self.commentList = QListView()

self.commentModel = model.CommentModel()
self.commentList.setModel(self.commentModel)

self.commentDelegate = delegate.CommentDelegate()
self.commentList.setItemDelegate(self.commentDelegate)

self.commentList.doubleClicked.connect(
lambda idx: self.commentList.edit(idx))
self.topicCbModel.selectionChanged.connect(self.commentModel.resetItems)

self.commentLayout.addWidget(self.commentList)

return commentGroup


def createViewpointGroup(self):
Expand All @@ -75,19 +99,24 @@ def createViewpointGroup(self):

@Slot()
def openProjectBtnHandler(self):
#dflPath = QDir.homePath()
dflPath = "/home/patrick/projects/freecad/plugin/bcf-examples"

dflPath = QDir.homePath()
filename = QFileDialog.getOpenFileName(self, self.tr("Open BCF File"),
dflPath, self.tr("BCF Files (*.bcf *.bcfzip)"))
#TODO: call open project function
if filename[0] != "":
model.openProjectBtnHandler(filename[0])
self.projectGroup.hide()
self.projectNameLbl.setText(model.getProjectName())
self.projectNameLbl.show()
self.topicCbModel.projectOpened()
self.topicGroup.show()
util.printInfo("Project name: '{}'".format(model.getProjectName()))
self.commentGroup.show()


@Slot()
def topicCBCurrentIndexChanged(self, index):
pass



if __name__ == "__main__":
Expand Down

0 comments on commit 894de41

Please sign in to comment.