mirror of
https://github.com/olivierkes/manuskript.git
synced 2024-05-14 18:02:23 +12:00
Adds: split dialog, split at cursor
This commit is contained in:
parent
3b17c4e2b4
commit
a153606811
|
@ -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")
|
||||
|
||||
|
|
|
@ -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
|
||||
###############################################################################
|
||||
|
|
|
@ -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"]
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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")
|
||||
|
||||
|
|
55
manuskript/ui/tools/splitDialog.py
Normal file
55
manuskript/ui/tools/splitDialog.py
Normal 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)
|
|
@ -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))
|
||||
|
|
|
@ -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):
|
||||
|
|
Loading…
Reference in a new issue