Skip to content

Commit b72e27f

Browse files
committed
Merge branch 'release/0.2.0'
2 parents 53ebecb + dc79ba1 commit b72e27f

File tree

14 files changed

+755
-129
lines changed

14 files changed

+755
-129
lines changed

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,6 @@ Notes.t2t
88
manuskript/pycallgraph.txt
99
ExportTest
1010
icons/Numix
11-
.idea
11+
.idea
12+
dist
13+
build

makefile

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,10 @@ linguist:
3232
lrelease i18n/manuskript_fr.ts
3333

3434
i18n: $(QMs)
35-
35+
36+
pyinstaller:
37+
python3 /usr/local/bin/pyinstaller manuskript.spec
38+
3639
%_rc.py : %.qrc
3740
pyrcc5 "$<" -o "$@"
3841

manuskript.spec

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# -*- mode: python -*-
2+
3+
block_cipher = None
4+
5+
6+
a = Analysis(['bin/manuskript'],
7+
pathex=['/home/olivier/Dropbox/Documents/Travail/Geekeries/Python/PyCharmProjects/manuskript_pyinstaller tests'],
8+
binaries=None,
9+
datas=[
10+
("icons", "icons"),
11+
("libs", "libs"),
12+
("resources", "resources"),
13+
("sample-projects", "sample-projects"),
14+
],
15+
hiddenimports=[],
16+
hookspath=[],
17+
runtime_hooks=[],
18+
excludes=[],
19+
win_no_prefer_redirects=False,
20+
win_private_assemblies=False,
21+
cipher=block_cipher)
22+
pyz = PYZ(a.pure, a.zipped_data,
23+
cipher=block_cipher)
24+
exe = EXE(pyz,
25+
a.scripts,
26+
exclude_binaries=True,
27+
name='manuskript',
28+
debug=False,
29+
strip=False,
30+
upx=True,
31+
console=True )
32+
coll = COLLECT(exe,
33+
a.binaries,
34+
a.zipfiles,
35+
a.datas,
36+
strip=False,
37+
upx=True,
38+
name='manuskript')

manuskript/main.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,12 @@
44
import sys
55

66
from PyQt5.QtCore import QLocale, QTranslator, QSettings
7-
from PyQt5.QtWidgets import QApplication
8-
from .functions import *
7+
from PyQt5.QtGui import QIcon
8+
from PyQt5.QtWidgets import QApplication, qApp
99

10-
_version = "0.1.1"
10+
from manuskript.functions import appPath
11+
12+
_version = "0.2.0"
1113

1214
faulthandler.enable()
1315

manuskript/mainWindow.py

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,8 @@ def loadProject(self, project, loadFromFile=True):
322322
self.mainEditor.setFolderView(settings.folderView)
323323
self.mainEditor.updateFolderViewButtons(settings.folderView)
324324
self.tabMain.setCurrentIndex(settings.lastTab)
325+
# We force to emit even if it opens on the current tab
326+
self.tabMain.currentChanged.emit(settings.lastTab)
325327
self.mainEditor.updateCorkBackground()
326328

327329
# Set autosave
@@ -406,15 +408,27 @@ def readSettings(self):
406408
if sttgns.contains("revisionsState"):
407409
state = [False if v == "false" else True for v in sttgns.value("revisionsState")]
408410
self.redacMetadata.revisions.restoreState(state)
411+
if sttgns.contains("splitterRedacH"):
412+
self.splitterRedacH.restoreState(sttgns.value("splitterRedacH"))
413+
if sttgns.contains("splitterRedacV"):
414+
self.splitterRedacV.restoreState(sttgns.value("splitterRedacV"))
415+
if sttgns.contains("toolbar"):
416+
# self.toolbar is not initialized yet, so we just store balue
417+
self._toolbarState = sttgns.value("toolbar")
418+
else:
419+
self._toolbarState = ""
420+
409421

410422
def closeEvent(self, event):
411423
# Save State and geometry and other things
412424
sttgns = QSettings(qApp.organizationName(), qApp.applicationName())
413425
sttgns.setValue("geometry", self.saveGeometry())
414426
sttgns.setValue("windowState", self.saveState())
415427
sttgns.setValue("metadataState", self.redacMetadata.saveState())
416-
sttgns.setValue("metadataState", self.redacMetadata.saveState())
417428
sttgns.setValue("revisionsState", self.redacMetadata.revisions.saveState())
429+
sttgns.setValue("splitterRedacH", self.splitterRedacH.saveState())
430+
sttgns.setValue("splitterRedacV", self.splitterRedacV.saveState())
431+
sttgns.setValue("toolbar", self.toolbar.saveState())
418432

419433
# Specific settings to save before quitting
420434
settings.lastTab = self.tabMain.currentIndex()
@@ -699,6 +713,7 @@ def makeConnections(self):
699713

700714
self.treeOutlineOutline.setModel(self.mdlOutline)
701715
# self.redacEditor.setModel(self.mdlOutline)
716+
self.storylineView.setModels(self.mdlOutline, self.mdlPersos, self.mdlPlots)
702717

703718
self.treeOutlineOutline.selectionModel().selectionChanged.connect(lambda:
704719
self.outlineItemEditor.selectionChanged(
@@ -799,6 +814,9 @@ def setupMoreUi(self):
799814
self.toolbar.addCustomWidget(self.tr("Book summary"), self.grpPlotSummary, self.TabPlots)
800815
self.toolbar.addCustomWidget(self.tr("Project tree"), self.treeRedacWidget, self.TabRedac)
801816
self.toolbar.addCustomWidget(self.tr("Metadata"), self.redacMetadata, self.TabRedac)
817+
self.toolbar.addCustomWidget(self.tr("Story line"), self.storylineView, self.TabRedac)
818+
if self._toolbarState:
819+
self.toolbar.restoreState(self._toolbarState)
802820

803821
# Custom "tab" bar on the left
804822
self.lstTabs.setIconSize(QSize(48, 48))
@@ -838,9 +856,12 @@ def setupMoreUi(self):
838856
self.splitterOutlineV.setStretchFactor(0, 75)
839857
self.splitterOutlineV.setStretchFactor(1, 25)
840858

841-
self.splitterRedac.setStretchFactor(0, 30)
842-
self.splitterRedac.setStretchFactor(1, 40)
843-
self.splitterRedac.setStretchFactor(2, 30)
859+
self.splitterRedacV.setStretchFactor(0, 75)
860+
self.splitterRedacV.setStretchFactor(1, 25)
861+
862+
self.splitterRedacH.setStretchFactor(0, 30)
863+
self.splitterRedacH.setStretchFactor(1, 40)
864+
self.splitterRedacH.setStretchFactor(2, 30)
844865

845866
# QFormLayout stretch
846867
for w in [self.txtWorldDescription, self.txtWorldPassion, self.txtWorldConflict]:

manuskript/models/outlineModel.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -836,11 +836,20 @@ def findItemsByPOV(self, POV):
836836

837837
return lst
838838

839-
def findItemsContaining(self, text, columns, mainWindow, caseSensitive=False):
839+
def findItemsContaining(self, text, columns, mainWindow=mainWindow(), caseSensitive=False, recursive=True):
840840
"""Returns a list if IDs of all subitems
841841
containing ``text`` in columns ``columns``
842842
(being a list of int).
843843
"""
844+
lst = self.itemContains(text, columns, mainWindow, caseSensitive)
845+
846+
if recursive:
847+
for c in self.children():
848+
lst.extend(c.findItemsContaining(text, columns, mainWindow, caseSensitive))
849+
850+
return lst
851+
852+
def itemContains(self, text, columns, mainWindow=mainWindow(), caseSensitive=False):
844853
lst = []
845854
text = text.lower() if not caseSensitive else text
846855
for c in columns:
@@ -863,9 +872,6 @@ def findItemsContaining(self, text, columns, mainWindow, caseSensitive=False):
863872
if not self.ID() in lst:
864873
lst.append(self.ID())
865874

866-
for c in self.children():
867-
lst.extend(c.findItemsContaining(text, columns, mainWindow, caseSensitive))
868-
869875
return lst
870876

871877
###############################################################################

manuskript/models/references.py

Lines changed: 56 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -21,30 +21,47 @@
2121
RegExNonCapturing = r"{\w:\d+:?.*?}"
2222
# The basic format of the references
2323
EmptyRef = "{{{}:{}:{}}}"
24+
EmptyRefSearchable = "{{{}:{}:"
2425
PersoLetter = "C"
2526
TextLetter = "T"
2627
PlotLetter = "P"
2728
WorldLetter = "W"
2829

2930

30-
def plotReference(ID):
31-
"""Takes the ID of a plot and returns a reference for that plot."""
32-
return EmptyRef.format(PlotLetter, ID, "")
31+
def plotReference(ID, searchable=False):
32+
"""Takes the ID of a plot and returns a reference for that plot.
33+
@searchable: returns a stripped version that allows simple text search."""
34+
if not searchable:
35+
return EmptyRef.format(PlotLetter, ID, "")
36+
else:
37+
return EmptyRefSearchable.format(PlotLetter, ID, "")
3338

3439

35-
def persoReference(ID):
36-
"""Takes the ID of a character and returns a reference for that character."""
37-
return EmptyRef.format(PersoLetter, ID, "")
40+
def persoReference(ID, searchable=False):
41+
"""Takes the ID of a character and returns a reference for that character.
42+
@searchable: returns a stripped version that allows simple text search."""
43+
if not searchable:
44+
return EmptyRef.format(PersoLetter, ID, "")
45+
else:
46+
return EmptyRefSearchable.format(PersoLetter, ID, "")
3847

3948

40-
def textReference(ID):
41-
"""Takes the ID of an outline item and returns a reference for that item."""
42-
return EmptyRef.format(TextLetter, ID, "")
49+
def textReference(ID, searchable=False):
50+
"""Takes the ID of an outline item and returns a reference for that item.
51+
@searchable: returns a stripped version that allows simple text search."""
52+
if not searchable:
53+
return EmptyRef.format(TextLetter, ID, "")
54+
else:
55+
return EmptyRefSearchable.format(TextLetter, ID, "")
4356

4457

45-
def worldReference(ID):
46-
"""Takes the ID of a world item and returns a reference for that item."""
47-
return EmptyRef.format(WorldLetter, ID, "")
58+
def worldReference(ID, searchable=False):
59+
"""Takes the ID of a world item and returns a reference for that item.
60+
@searchable: returns a stripped version that allows simple text search."""
61+
if not searchable:
62+
return EmptyRef.format(WorldLetter, ID, "")
63+
else:
64+
return EmptyRefSearchable.format(WorldLetter, ID, "")
4865

4966

5067
###############################################################################
@@ -375,7 +392,10 @@ def tooltip(ref):
375392

376393
item = idx.internalPointer()
377394

378-
tt = qApp.translate("references", "Text: <b>{}</b>").format(item.title())
395+
if item.isFolder():
396+
tt = qApp.translate("references", "Folder: <b>{}</b>").format(item.title())
397+
else:
398+
tt = qApp.translate("references", "Text: <b>{}</b>").format(item.title())
379399
tt += "<br><i>{}</i>".format(item.path())
380400

381401
return tt
@@ -451,11 +471,32 @@ def linkifyAllRefs(text):
451471
return re.sub(RegEx, lambda m: refToLink(m.group(0)), text)
452472

453473

474+
def findReferencesTo(ref, parent=None, recursive=True):
475+
"""List of text items containing references ref, and returns IDs.
476+
Starts from item parent. If None, starts from root."""
477+
oM = mainWindow().mdlOutline
478+
479+
if parent == None:
480+
parent = oM.rootItem
481+
482+
# Removes everything after the second ':': '{L:ID:random text}' → '{L:ID:'
483+
ref = ref[:ref.index(":", ref.index(":") + 1)+1]
484+
485+
# Bare form '{L:ID}'
486+
ref2 = ref[:-1] + "}"
487+
488+
# Since it's a simple search (no regex), we search for both.
489+
lst = parent.findItemsContaining(ref, [Outline.notes.value], recursive=recursive)
490+
lst += parent.findItemsContaining(ref2, [Outline.notes.value], recursive=recursive)
491+
492+
return lst
493+
454494
def listReferences(ref, title=qApp.translate("references", "Referenced in:")):
455495
oM = mainWindow().mdlOutline
456496
listRefs = ""
457-
ref = ref[:ref.index(":", ref.index(":") + 1)]
458-
lst = oM.findItemsContaining(ref, [Outline.notes.value])
497+
498+
lst = findReferencesTo(ref)
499+
459500
for t in lst:
460501
idx = oM.getIndexByID(t)
461502
listRefs += "<li><a href='{link}'>{text}</a></li>".format(

manuskript/ui/collapsibleDockWidgets.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ def addCustomWidget(self, text, widget, group=None):
6969
# widget.installEventFilter(self)
7070
b = verticalButton(self)
7171
b.setDefaultAction(a)
72+
#b.setChecked(widget.isVisible())
7273
a2 = self.addWidget(b)
7374
self.otherWidgets.append((b, a2, widget, group))
7475

@@ -87,6 +88,22 @@ def setCurrentGroup(self, group):
8788
else:
8889
action.setVisible(True)
8990

91+
def saveState(self):
92+
# We just need to save states of the custom widgets.
93+
state = []
94+
for btn, act, w, grp in self.otherWidgets:
95+
state.append(
96+
(grp, btn.text(), btn.isChecked())
97+
)
98+
return state
99+
100+
def restoreState(self, state):
101+
for group, title, status in state:
102+
for btn, act, widget, grp in self.otherWidgets:
103+
if group == grp and title == btn.text():
104+
btn.setChecked(status)
105+
widget.setVisible(status)
106+
90107

91108
class verticalButton(QToolButton):
92109
def __init__(self, parent):

0 commit comments

Comments
 (0)