Fixes more bugs in drag n drop: seg fault when creating an item after deleting an item that was open for editing, and other small stuff

This commit is contained in:
Olivier Keshavjee 2017-10-20 23:39:57 +02:00
parent 1a8d4c5c72
commit 648b4b67eb
8 changed files with 97 additions and 43 deletions

View file

@ -124,14 +124,14 @@ class MainWindow(QMainWindow, Ui_MainWindow):
self.makeUIConnections()
# self.loadProject(os.path.join(appPath(), "test_project.zip"))
def updateDockVisibility(self, restore=False):
"""
Saves the state of the docks visibility. Or if `restore` is True,
Saves the state of the docks visibility. Or if `restore` is True,
restores from `self._dckVisibility`. This allows to hide the docks
while showing the welcome screen, and then restore them as they
were.
If `self._dckVisibility` contains "LOCK", then we don't override values
with current visibility state. This is used the first time we load.
"LOCK" is then removed.
@ -141,7 +141,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
self.dckNavigation,
self.dckSearch,
]
for d in docks:
if not restore:
# We store the values, but only if "LOCK" is not present
@ -152,11 +152,11 @@ class MainWindow(QMainWindow, Ui_MainWindow):
else:
# Restore the dock's visibily based on stored value
d.setVisible(self._dckVisibility[d.objectName()])
# Lock is used only once, at start up. We can remove it
if "LOCK" in self._dckVisibility:
self._dckVisibility.pop("LOCK")
def switchToWelcome(self):
"""
While switching to welcome screen, we have to hide all the docks.
@ -171,7 +171,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
self.toolbar.setVisible(False)
# Switch to welcome screen
self.stack.setCurrentIndex(0)
def switchToProject(self):
"""Restores docks and toolbar visibility, and switch to project."""
# Restores the docks visibility
@ -549,14 +549,14 @@ class MainWindow(QMainWindow, Ui_MainWindow):
sttgns.setValue("splitterRedacH", self.splitterRedacH.saveState())
sttgns.setValue("splitterRedacV", self.splitterRedacV.saveState())
sttgns.setValue("toolbar", self.toolbar.saveState())
# If we are not in the welcome window, we update the visibility
# of the docks widgets
if self.stack.currentIndex() == 1:
self.updateDockVisibility()
# Storing the visibility of docks to restore it on restart
sttgns.setValue("docks", self._dckVisibility)
# Specific settings to save before quitting
settings.lastTab = self.tabMain.currentIndex()
@ -588,7 +588,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
r = loadSave.saveProject() # version=0
self.saveTimerNoChanges.stop()
if r:
feedback = self.tr("Project {} saved.").format(self.currentProject)
else:
@ -976,7 +976,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
#""
#]
#self.tabMain.setTabIcon(i, QIcon(appPath("icons/Custom/Tabs/{}".format(icons[i]))))
icons = [QIcon.fromTheme("stock_view-details"), #info
QIcon.fromTheme("application-text-template"), #applications-publishing
F.themeIcon("characters"),
@ -987,7 +987,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
QIcon.fromTheme("applications-debugging")
]
self.tabMain.setTabIcon(i, icons[i])
item = QListWidgetItem(self.tabMain.tabIcon(i),
self.tabMain.tabText(i))
item.setSizeHint(QSize(item.sizeHint().width(), 64))

View file

@ -25,10 +25,11 @@ class outlineModel(QAbstractItemModel):
def __init__(self, parent):
QAbstractItemModel.__init__(self, parent)
self.rootItem = outlineItem(self, title="root", ID="0")
self.rootItem = outlineItem(self, title="Root", ID="0")
# Stores removed item, in order to remove them on disk when saving, depending on the file format.
self.removed = []
self._removingRows = False
def index(self, row, column, parent):
@ -266,13 +267,13 @@ class outlineModel(QAbstractItemModel):
items = self.decodeMimeData(data)
if items is None:
return False
# Get the parent item
if not parent.isValid():
parentItem = self.rootItem
else:
parentItem = parent.internalPointer()
for item in items:
# Get parentItem's parents IDs in a list
path = parentItem.pathID() # path to item in the form [(ID, title), ...]
@ -281,7 +282,7 @@ class outlineModel(QAbstractItemModel):
# as a children of himself.
if item.ID() in path:
return False
return True
def decodeMimeData(self, data):
@ -300,7 +301,7 @@ class outlineModel(QAbstractItemModel):
if child.tag == "outlineItem":
item = outlineItem(xml=ET.tostring(child))
items.append(item)
return items
def dropMimeData(self, data, action, row, column, parent):
@ -311,7 +312,7 @@ class outlineModel(QAbstractItemModel):
items = self.decodeMimeData(data)
if items is None:
return False
if column > 0:
column = 0
@ -408,11 +409,14 @@ class outlineModel(QAbstractItemModel):
else:
parentItem = parent.internalPointer()
self._removingRows = True # Views that are updating can easily know
# if this is due to row removal.
self.beginRemoveRows(parent, row, row + count - 1)
for i in range(count):
item = parentItem.removeChild(row)
self.removed.append(item)
self._removingRows = False
self.endRemoveRows()
return True

View file

@ -53,6 +53,7 @@ class editorWidget(QWidget, Ui_editorWidget_ui):
self.spellcheck = True
self.folderView = "cork"
self.mw = mainWindow()
self._tabWidget = None # set by mainEditor on creation
# def setModel(self, model):
# self._model = model
@ -88,6 +89,25 @@ class editorWidget(QWidget, Ui_editorWidget_ui):
for c in range(count):
self.corkView.itemDelegate().sizeHintChanged.emit(r.child(c, 0))
def updateTabTitle(self):
"""
`editorWidget` belongs to a `QTabWidget` in a `tabSplitter`. We update
the tab title to reflect that of current item.
"""
# `self._tabWidget` is set by mainEditor when creating tab and `editorWidget`.
# if `editorWidget` is ever used out of `mainEditor`, this could throw
# an error.
if not self._tabWidget:
return
if self.currentIndex.isValid():
item = self.currentIndex.internalPointer()
else:
item = self.mw.mdlOutline.rootItem
i = self._tabWidget.indexOf(self)
self._tabWidget.setTabText(i, item.title())
def setView(self):
# index = mainWindow().treeRedacOutline.currentIndex()
@ -110,6 +130,8 @@ class editorWidget(QWidget, Ui_editorWidget_ui):
else:
item = self.mw.mdlOutline.rootItem
self.updateTabTitle()
def addTitle(itm):
edt = textEditView(self, html="<h{l}>{t}</h{l}>".format(l=min(itm.level() + 1, 5), t=itm.title()),
autoResize=True)
@ -213,14 +235,17 @@ class editorWidget(QWidget, Ui_editorWidget_ui):
except TypeError:
pass
else:
if item and item.isText():
self.txtRedacText.setCurrentModelIndex(self.currentIndex)
self.stack.setCurrentIndex(0) # Single text item
else:
self.txtRedacText.setCurrentModelIndex(QModelIndex())
try:
self.mw.mdlOutline.dataChanged.connect(self.modelDataChanged, AUC)
self.mw.mdlOutline.rowsInserted.connect(self.updateIndexFromID, AUC)
self.mw.mdlOutline.rowsRemoved.connect(self.updateIndexFromID, AUC)
#self.mw.mdlOutline.rowsAboutToBeRemoved.connect(self.rowsAboutToBeRemoved, AUC)
except TypeError:
pass
@ -233,16 +258,30 @@ class editorWidget(QWidget, Ui_editorWidget_ui):
# self._model = index.model()
else:
self.currentIndex = QModelIndex()
self.currentID = None
self.setView()
def updateIndexFromID(self):
"""
Index might have changed (through drag an drop), so we keep current
item's ID and update index.
item's ID and update index. Item might have been deleted too.
"""
idx = self.mw.mdlOutline.getIndexByID(self.currentID)
if idx != self.currentIndex:
# If we have an ID but the ID does not exist, it has been deleted
if self.currentID and idx == QModelIndex():
# Item has been deleted, we open the parent instead
self.setCurrentModelIndex(self.currentIndex.parent())
# FIXME: selection in self.mw.treeRedacOutline is not updated
# but we cannot simply setCurrentIndex through treeRedacOutline
# because this might be a tab in the background / out of focus
# Also the UI of mainEditor is not updated (so the folder icons
# are not display, button "up" doesn't work, etc.).
# Item has been moved
elif idx != self.currentIndex:
# We update the index
self.currentIndex = idx
self.setView()
@ -254,6 +293,13 @@ class editorWidget(QWidget, Ui_editorWidget_ui):
if topLeft.row() <= self.currentIndex.row() <= bottomRight.row():
self.updateStatusBar()
#def rowsAboutToBeRemoved(self, parent, first, last):
#if self.currentIndex:
#if self.currentIndex.parent() == parent and \
#first <= self.currentIndex.row() <= last:
## Item deleted, close tab
#self.mw.mainEditor.tab.removeTab(self.mw.mainEditor.tab.indexOf(self))
def updateStatusBar(self):
# Update progress
# if self.currentIndex and self.currentIndex.isValid():

View file

@ -179,14 +179,17 @@ class mainEditor(QWidget, Ui_mainEditor):
if self._updating:
return
if len(self.mw.treeRedacOutline.selectionModel().
selection().indexes()) == 0:
idx = QModelIndex()
else:
idx = self.mw.treeRedacOutline.currentIndex()
# This might be called during a drag n drop operation, or while deleting
# items. If so, we don't want to do anything.
if not self.mw.mdlOutline._removingRows:
if len(self.mw.treeRedacOutline.selectionModel().
selection().indexes()) == 0:
idx = QModelIndex()
else:
idx = self.mw.treeRedacOutline.currentIndex()
self.setCurrentModelIndex(idx)
self.updateThingsVisible(idx)
self.setCurrentModelIndex(idx)
self.updateThingsVisible(idx)
def openIndexes(self, indexes, newTab=False):
for i in indexes:
@ -194,8 +197,7 @@ class mainEditor(QWidget, Ui_mainEditor):
def goToParentItem(self):
idx = self.currentEditor().currentIndex
from manuskript.functions import MW
MW.treeRedacOutline.setCurrentIndex(idx.parent())
self.mw.treeRedacOutline.setCurrentIndex(idx.parent())
def setCurrentModelIndex(self, index, newTab=False, tabWidget=None):
@ -216,11 +218,12 @@ class mainEditor(QWidget, Ui_mainEditor):
if newTab or not tabWidget.count():
editor = editorWidget(self)
editor.setCurrentModelIndex(index)
editor._tabWidget = tabWidget
tabWidget.addTab(editor, title)
tabWidget.setCurrentIndex(tabWidget.count() - 1)
else:
self.currentEditor(tabWidget).setCurrentModelIndex(index)
tabWidget.setTabText(tabWidget.currentIndex(), title)
#tabWidget.setTabText(tabWidget.currentIndex(), title)
def updateTargets(self):
"""Updates all tabSplitter that are targets. This is called from editorWidget."""

View file

@ -249,4 +249,4 @@ class tabSplitter(QWidget, Ui_tabSplitter):
# }}""".format(self.splitter.objectName()))
self.setStyleSheet(style.mainEditorTabSS())
return QWidget.eventFilter(self, object, event)
return QWidget.eventFilter(self, object, event)

View file

@ -16,9 +16,9 @@ class metadataView(QWidget, Ui_metadataView):
self.txtSummaryFull.setColumn(Outline.summaryFull.value)
self.txtNotes.setColumn(Outline.notes.value)
self.revisions.setEnabled(False)
self.txtSummarySentence.setStyleSheet(style.lineEditSS())
self.txtSummaryFull.setStyleSheet(style.transparentSS() +
self.txtSummaryFull.setStyleSheet(style.transparentSS() +
style.simpleScrollBarV())
self.txtNotes.setStyleSheet(style.transparentSS() +
style.simpleScrollBarV())
@ -60,6 +60,9 @@ class metadataView(QWidget, Ui_metadataView):
if len(indexes) == 0:
self.setEnabled(False)
self.revisions.setEnabled(False)
self.txtSummarySentence.setCurrentModelIndex(QModelIndex())
self.txtSummaryFull.setCurrentModelIndex(QModelIndex())
self.txtNotes.setCurrentModelIndex(QModelIndex())
# One item selected
elif len(indexes) == 1:
@ -89,7 +92,7 @@ class metadataView(QWidget, Ui_metadataView):
# Behavior 2:
# Allow edition of multiple indexes.
# Bug: Multiple selections of items sometimes gets Notes/references
# Bug: Multiple selections of items sometimes gets Notes/references
# field to be ereased. See #10 on github.
#self.txtSummarySentence.setCurrentModelIndexes(indexes)
#self.txtSummaryFull.setCurrentModelIndexes(indexes)

View file

@ -42,9 +42,9 @@ class outlineBasics(QAbstractItemView):
self.actOpen = QAction(QIcon.fromTheme("go-right"), qApp.translate("outlineBasic", "Open Item"), menu)
self.actOpen.triggered.connect(self.openItem)
menu.addAction(self.actOpen)
menu.addSeparator()
# Add / remove items
self.actAddFolder = QAction(QIcon.fromTheme("folder-new"), qApp.translate("outlineBasics", "New Folder"), menu)
self.actAddFolder.triggered.connect(self.addFolder)
@ -154,7 +154,7 @@ class outlineBasics(QAbstractItemView):
idx = self.currentIndex()
from manuskript.functions import MW
MW.openIndex(idx)
def addFolder(self):
self.addItem("folder")

View file

@ -208,11 +208,11 @@ class textEditView(QTextEdit):
if self.parent().__class__ == QWidget:
self.parent().setStyleSheet("background: {bg};".format(
bg=opt["background"]))
cf = QTextCharFormat()
# cf.setFont(f)
# cf.setForeground(QColor(opt["fontColor"]))
self.setCursorWidth(opt["cursorWidth"])
bf = QTextBlockFormat()
@ -237,8 +237,7 @@ class textEditView(QTextEdit):
if self._updating:
return
elif self._index:
elif self._index and self._index.isValid():
if topLeft.parent() != self._index.parent():
return
@ -266,7 +265,6 @@ class textEditView(QTextEdit):
first <= self._index.row() <= last:
self._index = None
self.setEnabled(False)
# FIXME: self._indexes
def disconnectDocument(self):