Adds: split dialog, split at cursor

This commit is contained in:
Olivier Keshavjee 2017-11-10 16:26:23 +01:00
parent 3b17c4e2b4
commit a153606811
8 changed files with 206 additions and 21 deletions

View file

@ -439,23 +439,42 @@ class MainWindow(QMainWindow, Ui_MainWindow):
# mainEditor). So we just pass along the signal.
def documentsCopy(self):
"Copy selected item(s)."
if self._lastFocus: self._lastFocus.copy()
def documentsCut(self):
"Cut selected item(s)."
if self._lastFocus: self._lastFocus.cut()
def documentsPaste(self):
"Paste clipboard item(s) into selected item."
if self._lastFocus: self._lastFocus.paste()
def documentsDuplicate(self):
"Duplicate selected item(s)."
if self._lastFocus: self._lastFocus.duplicate()
def documentsDelete(self):
"Delete selected item(s)."
if self._lastFocus: self._lastFocus.delete()
def documentsMoveUp(self):
"Move up selected item(s)."
if self._lastFocus: self._lastFocus.moveUp()
def documentsMoveDown(self):
"Move Down selected item(s)."
if self._lastFocus: self._lastFocus.moveDown()
def documentsSplitDialog(self):
print("documentsSplitDialog::FIXME")
"Opens a dialog to split selected items."
if self._lastFocus: self._lastFocus.splitDialog()
# current items or selected items?
pass
# use outlineBasics, to do that on all selected items.
# use editorWidget to do that on selected text.
def documentsSplitCursor(self):
print("documentsSplitCursor::FIXME")
"""
Split current item (open in text editor) at cursor position. If there is
a text selection, that selection becomes the title of the new scene.
"""
if self._lastFocus and self._lastFocus == self.mainEditor:
self.mainEditor.splitCursor()
def documentsMerge(self):
print("documentsMerge::FIXME")

View file

@ -652,6 +652,7 @@ class outlineItem():
if column == Outline.text.value:
wc = wordCount(data)
self.setData(Outline.wordCount.value, wc)
self.emitDataChanged(cols=[Outline.text.value]) # new in 0.5.0
if column == Outline.compile.value:
self.emitDataChanged(cols=[Outline.title.value, Outline.compile.value], recursive=True)
@ -894,9 +895,39 @@ class outlineItem():
item.setData(Outline.text.value, subTxt)
# Inserting item
self.parent().insertChild(self.row()+k, item)
#self.parent().insertChild(self.row()+k, item)
self._model.insertItem(item, self.row()+k, self.parent().index())
k += 1
def splitAt(self, position, length=0):
"""
Splits note at position p.
If length is bigger than 0, it describes the length of the title, made
from the character following position.
"""
txt = self.text()
# Stores the new text
self.setData(Outline.text.value, txt[:position])
# Create a copy
item = self.copy()
# Update title
if length > 0:
title = txt[position:position+length].replace("\n", "")
else:
title = "{}_{}".format(item.title(), 2)
item.setData(Outline.title.value, title)
# Set text
item.setData(Outline.text.value, txt[position+length:])
# Inserting item using the model to signal views
self._model.insertItem(item, self.row()+1, self.parent().index())
###############################################################################
# XML
###############################################################################

View file

@ -96,13 +96,14 @@ frequencyAnalyzer = {
viewMode = "fiction" # simple, fiction
saveToZip = True
dontShowDeleteWarning = False
def save(filename=None, protocol=None):
global spellcheck, dict, corkSliderFactor, viewSettings, corkSizeFactor, folderView, lastTab, openIndexes, \
autoSave, autoSaveDelay, saveOnQuit, autoSaveNoChanges, autoSaveNoChangesDelay, outlineViewColumns, \
corkBackground, corkStyle, fullScreenTheme, defaultTextType, textEditor, revisions, frequencyAnalyzer, viewMode, \
saveToZip
saveToZip, dontShowDeleteWarning
allSettings = {
"viewSettings": viewSettings,
@ -127,6 +128,7 @@ def save(filename=None, protocol=None):
"frequencyAnalyzer": frequencyAnalyzer,
"viewMode": viewMode,
"saveToZip": saveToZip,
"dontShowDeleteWarning": dontShowDeleteWarning,
}
#pp=pprint.PrettyPrinter(indent=4, compact=False)
@ -294,3 +296,7 @@ def load(string, fromString=False, protocol=None):
if "saveToZip" in allSettings:
global saveToZip
saveToZip = allSettings["saveToZip"]
if "dontShowDeleteWarning" in allSettings:
global dontShowDeleteWarning
dontShowDeleteWarning = allSettings["dontShowDeleteWarning"]

View file

@ -8,6 +8,7 @@ from manuskript import settings
from manuskript.functions import AUC, mainWindow
from manuskript.ui.editors.editorWidget_ui import Ui_editorWidget_ui
from manuskript.ui.views.textEditView import textEditView
from manuskript.ui.tools.splitDialog import splitDialog
class editorWidget(QWidget, Ui_editorWidget_ui):
@ -330,7 +331,9 @@ class editorWidget(QWidget, Ui_editorWidget_ui):
###############################################################################
def getCurrentItemView(self):
if self.folderView == "outline":
if self.stack.currentIndex() == 0:
return self.txtRedacText
elif self.folderView == "outline":
return self.outlineView
elif self.folderView == "cork":
return self.corkView
@ -351,9 +354,46 @@ class editorWidget(QWidget, Ui_editorWidget_ui):
if self.getCurrentItemView(): self.getCurrentItemView().moveUp()
def moveDown(self):
if self.getCurrentItemView(): self.getCurrentItemView().moveDown()
def documentsSplitDialog(self):
print("documentsSplitDialog::FIXME")
def documentsSplitCursor(self):
print("documentsSplitCursor::FIXME")
def splitDialog(self):
"""
Opens a dialog to split selected items.
"""
if self.getCurrentItemView() == self.txtRedacText:
# Text editor
if not self.currentIndex.isValid():
return
sel = self.txtRedacText.textCursor().selectedText()
# selectedText uses \u2029 instead of \n, no idea why.
sel = sel.replace("\u2029", "\n")
splitDialog(self, [self.currentIndex], mark=sel)
elif self.getCurrentItemView():
# One of the view
self.getCurrentItemView().splitDialog()
def splitCursor(self):
"""
Splits items at cursor position. If there is a selection, that selection
becomes the new item's title.
Call context: Only works when editing a file.
"""
if not self.currentIndex.isValid():
return
if self.getCurrentItemView() == self.txtRedacText:
c = self.txtRedacText.textCursor()
title = c.selectedText()
# selection can be backward
pos = min(c.selectionStart(), c.selectionEnd())
item = self.currentIndex.internalPointer()
item.splitAt(pos, len(title))
def documentsMerge(self):
print("documentsMerge::FIXME")

View file

@ -255,10 +255,8 @@ class mainEditor(QWidget, Ui_mainEditor):
def delete(self): self.currentEditor().delete()
def moveUp(self): self.currentEditor().moveUp()
def moveDown(self): self.currentEditor().moveDown()
def documentsSplitDialog(self):
print("documentsSplitDialog::FIXME")
def documentsSplitCursor(self):
print("documentsSplitCursor::FIXME")
def splitDialog(self): self.currentEditor().splitDialog()
def splitCursor(self): self.currentEditor().splitCursor()
def documentsMerge(self):
print("documentsMerge::FIXME")

View file

@ -0,0 +1,55 @@
#!/usr/bin/env python
# --!-- coding: utf8 --!--
from PyQt5.QtWidgets import QInputDialog
class splitDialog(QInputDialog):
"""
Opens a dialog to split indexes.
"""
def __init__(self, parent, indexes, mark=None):
"""
@param parent: a QWidget, for the dialog.
@param indexes: a list of QModelIndex in the outlineModel
@param default: the default split mark
"""
QInputDialog.__init__(self, parent)
description = self.tr("""
<p>Split selected item(s) at the given mark.</p>
<p>If one of the selected item is a folder, it will be applied
recursively to <i>all</i> of it's children items.</p>
<p>The split mark can contain folling escret ape sequences:
<ul>
<li><b><code>\\n</code></b>: line break</li>
<li><b><code>\\t</code></b>: tab</li>
</ul>
</p>
<p><b>Mark:</b></p>
""")
if not mark:
mark = "\\n---\\n"
mark = mark.replace("\n", "\\n")
mark = mark.replace("\t", "\\t")
self.setLabelText(description)
self.setTextValue(mark)
self.setWindowTitle(self.tr("Split item(s)"))
r = self.exec()
mark = self.textValue()
if r and mark:
mark = mark.replace("\\n", "\n")
mark = mark.replace("\\t", "\t")
for idx in indexes:
if idx.isValid():
item = idx.internalPointer()
item.split(mark)

View file

@ -2,14 +2,16 @@
# --!-- coding: utf8 --!--
from PyQt5.QtCore import Qt, QSignalMapper, QSize
from PyQt5.QtGui import QIcon, QCursor
from PyQt5.QtWidgets import QAbstractItemView, qApp, QMenu, QAction
from PyQt5.QtWidgets import QListWidget, QWidgetAction, QListWidgetItem, QLineEdit
from PyQt5.QtWidgets import QAbstractItemView, qApp, QMenu, QAction, \
QListWidget, QWidgetAction, QListWidgetItem, \
QLineEdit, QInputDialog, QMessageBox, QCheckBox
from manuskript import settings
from manuskript.enums import Outline
from manuskript.functions import mainWindow
from manuskript.functions import toInt, customIcons
from manuskript.models.outlineModel import outlineItem
from manuskript.ui.tools.splitDialog import splitDialog
class outlineBasics(QAbstractItemView):
@ -53,7 +55,7 @@ class outlineBasics(QAbstractItemView):
title = mouseIndex.internalPointer().title()
else:
title = self.tr("Root")
title = qApp.translate("outlineBasics", "Root")
if len(title) > 25:
title = title[:25] + ""
@ -67,10 +69,10 @@ class outlineBasics(QAbstractItemView):
# Open item(s) in new tab
if mouseIndex in sel and len(sel) > 1:
actionTitle = self.tr("Open {} items in new tabs").format(len(sel))
actionTitle = qApp.translate("outlineBasics", "Open {} items in new tabs").format(len(sel))
self._indexesToOpen = sel
else:
actionTitle = self.tr("Open {} in a new tab").format(title)
actionTitle = qApp.translate("outlineBasics", "Open {} in a new tab").format(title)
self._indexesToOpen = [mouseIndex]
self.actNewTab = QAction(QIcon.fromTheme("go-right"), actionTitle, menu)
@ -284,6 +286,27 @@ class outlineBasics(QAbstractItemView):
self.delete()
def delete(self):
"""
Shows a warning, and then deletes currently selected indexes.
"""
if not settings.dontShowDeleteWarning:
msg = QMessageBox(QMessageBox.Warning,
qApp.translate("outlineBasics", "About to remove"),
qApp.translate("outlineBasics",
"<p><b>You're about to delete {} item(s).</b></p><p>Are you sure?</p>"
).format(len(self.getSelection())),
QMessageBox.Yes | QMessageBox.Cancel)
chk = QCheckBox("&Don't show this warning in the future.")
msg.setCheckBox(chk)
ret = msg.exec()
if ret == QMessageBox.Cancel:
return
if chk.isChecked():
settings.dontShowDeleteWarning = True
self.model().removeIndexes(self.getSelection())
def duplicate(self):
@ -295,7 +318,7 @@ class outlineBasics(QAbstractItemView):
Move selected items up or down.
"""
# we store selected indexes
# we store selected indexesret
currentID = self.model().ID(self.currentIndex())
selIDs = [self.model().ID(i) for i in self.selectedIndexes()]
@ -316,7 +339,7 @@ class outlineBasics(QAbstractItemView):
sm.clear()
[sm.select(idx, sm.Select) for idx in selIdx]
sm.setCurrentIndex(self.model().getIndexByID(currentID), sm.Select)
#self.setSelectionModel(sm)
#self.setSmsgBoxelectionModel(sm)
# Unblock signals
self.blockSignals(False)
@ -342,6 +365,19 @@ class outlineBasics(QAbstractItemView):
def moveUp(self): self.move(-1)
def moveDown(self): self.move(+1)
def splitDialog(self):
"""
Opens a dialog to split selected items.
Call context: if at least one index is selected. Folder or text.
"""
indexes = self.getSelection()
if len(indexes) == 0:
return
splitDialog(self, indexes)
def setPOV(self, POV):
for i in self.getSelection():
self.model().setData(i.sibling(i.row(), Outline.POV.value), str(POV))

View file

@ -93,7 +93,7 @@ class textEditView(QTextEdit):
default_locale = QLocale.system().name()
if default_locale is None:
default_locale = enchant.list_dicts()[0][0]
return default_locale
def setModel(self, model):