manuskript/src/mainWindow.py

932 lines
35 KiB
Python
Raw Normal View History

2015-05-28 13:32:09 +12:00
#!/usr/bin/env python
#--!-- coding: utf8 --!--
2015-06-23 07:34:11 +12:00
2015-06-04 04:40:19 +12:00
from qt import *
2015-05-28 13:32:09 +12:00
from ui.mainWindow import *
2015-06-04 05:25:03 +12:00
from ui.helpLabel import helpLabel
2015-05-31 16:03:07 +12:00
from loadSave import *
2015-06-01 22:29:06 +12:00
from enums import *
2015-06-02 10:06:17 +12:00
from models.outlineModel import *
from models.plotModel import *
2015-06-04 17:08:49 +12:00
from models.persosProxyModel import *
2015-06-05 06:22:37 +12:00
from functions import *
from settingsWindow import *
import settings
2015-05-28 13:32:09 +12:00
2015-06-07 05:10:44 +12:00
# Spell checker support
try:
import enchant
except ImportError:
enchant = None
2015-06-23 07:34:11 +12:00
2015-05-28 13:32:09 +12:00
class MainWindow(QMainWindow, Ui_MainWindow):
2015-06-23 07:34:11 +12:00
2015-06-08 08:06:57 +12:00
dictChanged = pyqtSignal(str)
2015-06-23 07:34:11 +12:00
2015-05-28 13:32:09 +12:00
def __init__(self):
QMainWindow.__init__(self)
self.setupUi(self)
2015-06-23 07:34:11 +12:00
2015-05-31 16:03:07 +12:00
self.readSettings()
2015-06-23 07:34:11 +12:00
2015-05-29 05:15:57 +12:00
# UI
2015-06-04 05:25:03 +12:00
self.setupMoreUi()
2015-06-23 07:34:11 +12:00
2015-05-31 16:03:07 +12:00
# Word count
self.mprWordCount = QSignalMapper(self)
2015-05-28 13:32:09 +12:00
for t, i in [
(self.txtSummarySentance, 0),
(self.txtSummaryPara, 1),
(self.txtSummaryPage, 2),
(self.txtSummaryFull, 3)
]:
2015-05-31 16:03:07 +12:00
t.textChanged.connect(self.mprWordCount.map)
self.mprWordCount.setMapping(t, i)
self.mprWordCount.mapped.connect(self.wordCount)
2015-06-23 07:34:11 +12:00
2015-05-28 13:32:09 +12:00
# Snowflake Method Cycle
self.mapperCycle = QSignalMapper(self)
for t, i in [
(self.btnStepTwo, 0),
(self.btnStepThree, 1),
(self.btnStepFour, 2),
(self.btnStepFive, 3),
(self.btnStepSix, 4),
(self.btnStepSeven, 5),
(self.btnStepEight, 6)
]:
t.clicked.connect(self.mapperCycle.map)
self.mapperCycle.setMapping(t, i)
2015-06-23 07:34:11 +12:00
2015-05-28 13:32:09 +12:00
self.mapperCycle.mapped.connect(self.clickCycle)
2015-06-21 21:29:35 +12:00
self.cmbSummary.currentIndexChanged.connect(self.summaryPageChanged)
self.cmbSummary.setCurrentIndex(0)
self.cmbSummary.currentIndexChanged.emit(0)
2015-06-23 07:34:11 +12:00
2015-05-31 16:03:07 +12:00
# Données
self.mdlFlatData = QStandardItemModel(2, 8)
2015-06-23 07:34:11 +12:00
2015-05-31 16:03:07 +12:00
# Persos
2015-06-21 21:54:52 +12:00
self.mdlPersos = QStandardItemModel(0, 0)
2015-06-22 23:11:45 +12:00
#self.mdlPersosProxy = None # persosProxyModel() # None
self.mdlPersosProxy = persosProxyModel(self)
2015-06-23 07:34:11 +12:00
2015-06-01 08:41:32 +12:00
self.mdlPersosInfos = QStandardItemModel(1, 0)
2015-06-01 22:29:06 +12:00
self.mdlPersosInfos.insertColumn(0, [QStandardItem("ID")])
2015-05-31 16:03:07 +12:00
self.mdlPersosInfos.setHorizontalHeaderLabels(["Description"])
2015-06-23 07:34:11 +12:00
2015-06-10 00:03:22 +12:00
# Labels
self.mdlLabels = QStandardItemModel()
for color, text in [
(Qt.transparent, ""),
2015-06-11 01:57:44 +12:00
(Qt.yellow, self.tr("Idea")),
(Qt.green, self.tr("Note")),
(Qt.blue, self.tr("Chapter")),
2015-06-16 02:35:23 +12:00
(Qt.red, self.tr("Scene")),
(Qt.cyan, self.tr("Research"))
2015-06-10 00:03:22 +12:00
]:
self.mdlLabels.appendRow(QStandardItem(iconFromColor(color), text))
2015-06-23 07:34:11 +12:00
2015-06-11 01:57:44 +12:00
# Status
self.mdlStatus = QStandardItemModel()
for text in [
"",
self.tr("TODO"),
self.tr("First draft"),
self.tr("Second draft"),
self.tr("Final")
]:
self.mdlStatus.appendRow(QStandardItem(text))
2015-06-23 07:34:11 +12:00
# Plot
self.mdlPlots = plotModel()
2015-06-23 07:34:11 +12:00
2015-06-02 10:06:17 +12:00
# Outline
self.mdlOutline = outlineModel()
2015-06-23 07:34:11 +12:00
# Main Menu
2015-06-17 22:00:03 +12:00
self.actSave.setEnabled(False)
self.actSaveAs.setEnabled(False)
self.actSave.triggered.connect(self.saveDatas)
self.actLabels.triggered.connect(self.settingsLabel)
self.actStatus.triggered.connect(self.settingsStatus)
self.actSettings.triggered.connect(self.settingsWindow)
2015-06-23 07:34:11 +12:00
self.actQuit.triggered.connect(self.close)
self.generateViewMenu()
2015-06-23 07:34:11 +12:00
2015-05-31 16:03:07 +12:00
#Debug
self.mdlFlatData.setVerticalHeaderLabels(["Infos générales", "Summary"])
self.tblDebugFlatData.setModel(self.mdlFlatData)
2015-06-01 22:29:06 +12:00
self.tblDebugPersos.setModel(self.mdlPersos)
self.tblDebugPersosInfos.setModel(self.mdlPersosInfos)
self.tblDebugPlots.setModel(self.mdlPlots)
self.tblDebugPlotsPersos.setModel(self.mdlPlots)
self.tblDebugSubPlots.setModel(self.mdlPlots)
self.tblDebugPlots.selectionModel().currentChanged.connect(
lambda: self.tblDebugPlotsPersos.setRootIndex(self.mdlPlots.index(
self.tblDebugPlots.selectionModel().currentIndex().row(),
Plot.persos.value)))
self.tblDebugPlots.selectionModel().currentChanged.connect(
lambda: self.tblDebugSubPlots.setRootIndex(self.mdlPlots.index(
self.tblDebugPlots.selectionModel().currentIndex().row(),
Plot.subplots.value)))
2015-06-02 10:06:17 +12:00
self.treeDebugOutline.setModel(self.mdlOutline)
2015-06-10 00:03:22 +12:00
self.lstDebugLabels.setModel(self.mdlLabels)
2015-06-11 01:57:44 +12:00
self.lstDebugStatus.setModel(self.mdlStatus)
2015-06-23 07:34:11 +12:00
2015-06-19 01:03:16 +12:00
self.loadProject(os.path.join(appPath(), "test_project.zip"))
2015-06-23 07:34:11 +12:00
###############################################################################
# SUMMARY
###############################################################################
2015-06-21 21:29:35 +12:00
def summaryPageChanged(self, index):
fractalButtons = [
self.btnStepTwo,
self.btnStepThree,
self.btnStepFive,
self.btnStepSeven,
]
for b in fractalButtons:
b.setVisible(fractalButtons.index(b) == index)
2015-06-23 07:34:11 +12:00
###############################################################################
# OUTLINE
###############################################################################
2015-06-11 05:45:42 +12:00
def outlineSelectionChanged(self):
2015-06-23 07:34:11 +12:00
if len(self.treeRedacOutline.selectionModel().
selection().indexes()) == 0:
2015-06-11 05:45:42 +12:00
hidden = False
else:
idx = self.treeRedacOutline.currentIndex()
if idx.isValid():
hidden = not idx.internalPointer().isFolder()
else:
hidden = False
2015-06-23 07:34:11 +12:00
2015-06-11 05:45:42 +12:00
self.btnRedacFolderText.setHidden(hidden)
self.btnRedacFolderCork.setHidden(hidden)
self.btnRedacFolderOutline.setHidden(hidden)
self.sldCorkSizeFactor.setHidden(hidden)
2015-06-21 10:36:25 +12:00
self.btnRedacFullscreen.setVisible(hidden)
2015-06-23 07:34:11 +12:00
2015-06-03 00:40:48 +12:00
def outlineRemoveItems(self):
for idx in self.treeRedacOutline.selectedIndexes():
if idx.isValid():
self.mdlOutline.removeIndex(idx)
2015-06-23 07:34:11 +12:00
###############################################################################
# PERSOS
###############################################################################
2015-06-01 08:41:32 +12:00
2015-05-31 16:03:07 +12:00
def createPerso(self):
2015-06-23 07:34:11 +12:00
"""Creates a perso by adding a row in mdlPersos
and a column in mdlPersosInfos with same ID"""
2015-06-08 22:01:45 +12:00
p = QStandardItem(self.tr("New character"))
2015-06-01 08:41:32 +12:00
self.mdlPersos.appendRow(p)
pid = self.getPersosID()
self.checkPersosID() # Attributes a persoID (which is logically pid)
2015-06-23 07:34:11 +12:00
self.setPersoColor(self.mdlPersos.rowCount() - 1,
randomColor(QColor(Qt.white)))
2015-06-01 08:41:32 +12:00
# Add column in persos infos
2015-06-23 07:34:11 +12:00
self.mdlPersosInfos.insertColumn(self.mdlPersosInfos.columnCount(),
[QStandardItem(pid)])
self.mdlPersosInfos.setHorizontalHeaderItem(
self.mdlPersosInfos.columnCount() - 1,
QStandardItem("Valeur"))
2015-06-01 08:41:32 +12:00
def getPersosID(self):
2015-06-23 07:34:11 +12:00
"""Returns an unused perso ID (row 1)."""
2015-06-01 08:41:32 +12:00
vals = []
for i in range(self.mdlPersos.rowCount()):
2015-06-01 22:29:06 +12:00
item = self.mdlPersos.item(i, Perso.ID.value)
2015-06-01 08:41:32 +12:00
if item and item.text():
vals.append(int(item.text()))
2015-06-23 07:34:11 +12:00
2015-06-01 08:41:32 +12:00
k = 0
2015-06-23 07:34:11 +12:00
while k in vals:
k += 1
2015-06-01 08:41:32 +12:00
return str(k)
2015-06-23 07:34:11 +12:00
2015-06-01 08:41:32 +12:00
def checkPersosID(self):
2015-06-23 07:34:11 +12:00
"""Checks whether some persos ID (row 1) are empty.
If so, assign an ID"""
2015-06-01 08:41:32 +12:00
for i in range(self.mdlPersos.rowCount()):
2015-06-01 22:29:06 +12:00
item = self.mdlPersos.item(i, Perso.ID.value)
2015-06-01 08:41:32 +12:00
if not item:
item = QStandardItem()
item.setText(self.getPersosID())
2015-06-01 22:29:06 +12:00
self.mdlPersos.setItem(i, Perso.ID.value, item)
2015-06-23 07:34:11 +12:00
2015-05-31 16:03:07 +12:00
def removePerso(self):
2015-06-16 02:35:23 +12:00
if self.mdlPersosProxy:
i = self.mdlPersosProxy.mapToSource(self.lstPersos.currentIndex())
else:
i = self.lstPersos.currentIndex()
2015-05-31 16:03:07 +12:00
self.mdlPersos.takeRow(i.row())
2015-06-23 07:34:11 +12:00
self.mdlPersosInfos.takeColumn(i.row() + 1)
2015-06-01 08:41:32 +12:00
def changeCurrentPerso(self, trash=None):
2015-06-16 02:35:23 +12:00
if self.mdlPersosProxy:
idx = self.mdlPersosProxy.mapToSource(self.lstPersos.currentIndex())
else:
idx = self.lstPersos.currentIndex()
2015-06-23 07:34:11 +12:00
2015-06-04 17:08:49 +12:00
self.mprPersos.setCurrentModelIndex(idx)
2015-06-23 07:34:11 +12:00
2015-06-16 02:35:23 +12:00
# Button color
self.updatePersoColor()
2015-06-23 07:34:11 +12:00
2015-06-16 02:35:23 +12:00
# detailed infos
2015-06-01 22:29:06 +12:00
pid = self.mdlPersos.item(idx.row(), Perso.ID.value).text()
for c in range(self.mdlPersosInfos.columnCount()):
pid2 = self.mdlPersosInfos.item(0, c).text()
2015-06-08 08:06:57 +12:00
self.tblPersoInfos.setColumnHidden(c, c != 0 and pid != pid2)
2015-06-23 07:34:11 +12:00
2015-06-01 08:41:32 +12:00
self.resizePersosInfos()
2015-06-23 07:34:11 +12:00
def updatePersoColor(self):
2015-06-16 02:35:23 +12:00
if self.mdlPersosProxy:
idx = self.mdlPersosProxy.mapToSource(self.lstPersos.currentIndex())
else:
idx = self.lstPersos.currentIndex()
2015-06-23 07:34:11 +12:00
2015-06-16 02:35:23 +12:00
icon = self.mdlPersos.item(idx.row()).icon()
2015-06-18 07:17:12 +12:00
color = iconColor(icon).name() if icon else ""
self.btnPersoColor.setStyleSheet("background:{};".format(color))
2015-06-23 07:34:11 +12:00
2015-06-01 08:41:32 +12:00
def resizePersosInfos(self):
self.tblPersoInfos.resizeColumnToContents(0)
w = self.tblPersoInfos.viewport().width()
w2 = self.tblPersoInfos.columnWidth(0)
2015-06-23 07:34:11 +12:00
2015-06-16 02:35:23 +12:00
if self.mdlPersosProxy:
2015-06-23 07:34:11 +12:00
current = self.mdlPersosProxy.mapToSource(
self.lstPersos.currentIndex()).row() + 1
2015-06-16 02:35:23 +12:00
else:
current = self.lstPersos.currentIndex().row() + 1
2015-06-23 07:34:11 +12:00
2015-06-01 08:41:32 +12:00
self.tblPersoInfos.setColumnWidth(current, w - w2)
2015-06-23 07:34:11 +12:00
2015-06-16 03:24:02 +12:00
def chosePersoColor(self):
2015-06-16 02:35:23 +12:00
if self.mdlPersosProxy:
idx = self.mdlPersosProxy.mapToSource(self.lstPersos.currentIndex())
else:
idx = self.lstPersos.currentIndex()
2015-06-23 07:34:11 +12:00
2015-06-16 02:35:23 +12:00
item = self.mdlPersos.item(idx.row(), Perso.name.value)
if item:
color = iconColor(item.icon())
else:
color = Qt.white
self.colorDialog = QColorDialog(color, self)
color = self.colorDialog.getColor(color)
2015-06-18 07:17:12 +12:00
if color.isValid():
self.setPersoColor(idx.row(), color)
self.updatePersoColor()
2015-06-23 07:34:11 +12:00
2015-06-16 03:24:02 +12:00
def setPersoColor(self, row, color):
2015-06-16 02:35:23 +12:00
px = QPixmap(32, 32)
px.fill(color)
2015-06-16 03:24:02 +12:00
self.mdlPersos.item(row, Perso.name.value).setIcon(QIcon(px))
2015-06-23 07:34:11 +12:00
###############################################################################
# PLOTS
###############################################################################
2015-06-22 23:11:45 +12:00
def changeCurrentPlot(self):
2015-06-23 06:30:43 +12:00
index = self.lstPlots.currentPlotIndex()
2015-06-23 07:34:11 +12:00
2015-06-22 23:11:45 +12:00
if not index.isValid():
self.tabPlot.setEnabled(False)
return
2015-06-23 07:34:11 +12:00
2015-06-22 23:11:45 +12:00
self.tabPlot.setEnabled(True)
self.txtPlotName.setCurrentModelIndex(index)
self.txtPlotDescription.setCurrentModelIndex(index)
self.txtPlotResult.setCurrentModelIndex(index)
self.sldPlotImportance.setCurrentModelIndex(index)
2015-06-23 07:34:11 +12:00
self.lstPlotPerso.setRootIndex(index.sibling(index.row(),
Plot.persos.value))
self.lstSubPlots.setRootIndex(index.sibling(index.row(),
Plot.subplots.value))
2015-06-22 23:11:45 +12:00
#self.txtSubPlotSummary.setCurrentModelIndex(QModelIndex())
self.txtSubPlotSummary.setEnabled(False)
2015-06-23 07:07:38 +12:00
self._updatingSubPlot = True
2015-06-22 23:11:45 +12:00
self.txtSubPlotSummary.setPlainText("")
2015-06-23 07:07:38 +12:00
self._updatingSubPlot = False
2015-06-23 07:34:11 +12:00
2015-06-22 23:11:45 +12:00
def changeCurrentSubPlot(self, index):
2015-06-23 07:34:11 +12:00
# Got segfaults when using textEditView model system, so ad hoc stuff.
2015-06-22 23:11:45 +12:00
index = index.sibling(index.row(), 3)
item = self.mdlPlots.itemFromIndex(index)
if not item:
self.txtSubPlotSummary.setEnabled(False)
return
self.txtSubPlotSummary.setEnabled(True)
txt = item.text()
self._updatingSubPlot = True
self.txtSubPlotSummary.setPlainText(txt)
self._updatingSubPlot = False
2015-06-23 07:34:11 +12:00
2015-06-22 23:11:45 +12:00
def updateSubPlotSummary(self):
if self._updatingSubPlot:
return
2015-06-23 07:34:11 +12:00
2015-06-22 23:11:45 +12:00
index = self.lstSubPlots.currentIndex()
if not index.isValid():
return
index = index.sibling(index.row(), 3)
item = self.mdlPlots.itemFromIndex(index)
2015-06-23 07:34:11 +12:00
2015-06-22 23:11:45 +12:00
self._updatingSubPlot = True
item.setText(self.txtSubPlotSummary.toPlainText())
self._updatingSubPlot = False
2015-06-23 07:34:11 +12:00
###############################################################################
# GENERAL
###############################################################################
2015-06-01 08:41:32 +12:00
def loadProject(self, project):
self.currentProject = project
2015-06-23 07:34:11 +12:00
2015-06-17 22:00:03 +12:00
# Load data
self.loadDatas()
self.makeConnections()
2015-06-23 07:34:11 +12:00
2015-06-17 22:00:03 +12:00
# Load settings
self.generateViewMenu()
self.sldCorkSizeFactor.setValue(settings.corkSizeFactor)
self.actSpellcheck.setChecked(settings.spellcheck)
self.updateMenuDict()
self.setDictionary()
self.redacEditor.setFolderView(settings.folderView)
if settings.folderView == "text":
self.btnRedacFolderText.setChecked(True)
elif settings.folderView == "cork":
self.btnRedacFolderCork.setChecked(True)
elif settings.folderView == "outline":
self.btnRedacFolderOutline.setChecked(True)
2015-06-16 06:30:18 +12:00
self.tabMain.setCurrentIndex(settings.lastTab)
2015-06-23 07:34:11 +12:00
self.treeRedacOutline.setCurrentIndex(
self.mdlOutline.indexFromPath(settings.lastIndex))
2015-06-18 06:45:24 +12:00
self.redacEditor.corkView.updateBackground()
2015-06-23 07:34:11 +12:00
2015-06-17 22:00:03 +12:00
# Set autosave
2015-06-18 04:40:55 +12:00
self.saveTimer = QTimer()
self.saveTimer.setInterval(settings.autoSaveDelay * 60 * 1000)
self.saveTimer.setSingleShot(False)
self.saveTimer.timeout.connect(self.saveDatas)
2015-06-17 22:00:03 +12:00
if settings.autoSave:
self.saveTimer.start()
2015-06-23 07:34:11 +12:00
2015-06-18 04:40:55 +12:00
# Set autosave if no changes
self.saveTimerNoChanges = QTimer()
2015-06-23 07:34:11 +12:00
self.saveTimerNoChanges.setInterval(settings.autoSaveNoChangesDelay
* 1000)
2015-06-18 04:40:55 +12:00
self.saveTimerNoChanges.setSingleShot(True)
self.mdlOutline.dataChanged.connect(self.startTimerNoChanges)
2015-06-18 06:48:20 +12:00
self.mdlPersos.dataChanged.connect(self.startTimerNoChanges)
self.mdlPersosInfos.dataChanged.connect(self.startTimerNoChanges)
self.mdlStatus.dataChanged.connect(self.startTimerNoChanges)
self.mdlLabels.dataChanged.connect(self.startTimerNoChanges)
2015-06-23 07:34:11 +12:00
2015-06-18 04:40:55 +12:00
self.saveTimerNoChanges.timeout.connect(self.saveDatas)
self.saveTimerNoChanges.stop()
2015-06-23 07:34:11 +12:00
2015-06-17 22:00:03 +12:00
# UI
self.actSave.setEnabled(True)
self.actSaveAs.setEnabled(True)
#FIXME: set Window's name: project name
2015-06-23 07:34:11 +12:00
2015-06-01 08:41:32 +12:00
# Stuff
self.checkPersosID()
2015-06-23 07:34:11 +12:00
2015-06-01 22:29:06 +12:00
# Adds header labels
2015-06-19 00:38:26 +12:00
self.mdlPersos.setHorizontalHeaderLabels([i.name for i in Perso])
def makeConnections(self):
2015-06-23 07:34:11 +12:00
# Flat datas (Summary and general infos)
for widget, col in [
(self.txtSummarySituation, 0),
(self.txtSummarySentance, 1),
(self.txtSummarySentance_2, 1),
(self.txtSummaryPara, 2),
(self.txtSummaryPara_2, 2),
(self.txtPlotSummaryPara, 2),
(self.txtSummaryPage, 3),
(self.txtSummaryPage_2, 3),
(self.txtPlotSummaryPage, 3),
(self.txtSummaryFull, 4),
(self.txtPlotSummaryFull, 4),
]:
2015-06-23 07:34:11 +12:00
widget.setModel(self.mdlFlatData)
widget.setColumn(col)
widget.setCurrentModelIndex(self.mdlFlatData.index(1, col))
2015-06-23 07:34:11 +12:00
for widget, col in [
(self.txtGeneralTitle, 0),
(self.txtGeneralSubtitle, 1),
(self.txtGeneralSerie, 2),
(self.txtGeneralVolume, 3),
(self.txtGeneralGenre, 4),
(self.txtGeneralLicense, 5),
(self.txtGeneralAuthor, 6),
(self.txtGeneralEmail, 7),
]:
2015-06-23 07:34:11 +12:00
widget.setModel(self.mdlFlatData)
widget.setColumn(col)
widget.setCurrentModelIndex(self.mdlFlatData.index(0, col))
2015-06-23 07:34:11 +12:00
# Persos
if self.mdlPersosProxy:
self.mdlPersosProxy.setSourceModel(self.mdlPersos)
self.lstPersos.setModel(self.mdlPersosProxy)
else:
self.lstPersos.setModel(self.mdlPersos)
2015-06-23 07:34:11 +12:00
self.tblPersoInfos.setModel(self.mdlPersosInfos)
self.tblPersoInfos.setRowHidden(0, True)
2015-06-23 07:34:11 +12:00
self.btnAddPerso.clicked.connect(self.createPerso)
self.btnRmPerso.clicked.connect(self.removePerso)
self.btnPersoColor.clicked.connect(self.chosePersoColor)
2015-06-23 07:34:11 +12:00
self.btnPersoAddInfo.clicked.connect(lambda:
self.mdlPersosInfos.insertRow(self.mdlPersosInfos.rowCount()))
self.mprPersos = QDataWidgetMapper()
self.mprPersos.setModel(self.mdlPersos)
2015-06-23 07:34:11 +12:00
mapping = [
(self.txtPersoName, Perso.name.value),
(self.txtPersoMotivation, Perso.motivation.value),
(self.txtPersoGoal, Perso.goal.value),
(self.txtPersoConflict, Perso.conflict.value),
(self.txtPersoEpiphany, Perso.epiphany.value),
(self.txtPersoSummarySentance, Perso.summarySentance.value),
(self.txtPersoSummaryPara, Perso.summaryPara.value),
(self.txtPersoSummaryFull, Perso.summaryFull.value),
(self.txtPersoNotes, Perso.notes.value)
]
for w, i in mapping:
2015-06-23 07:34:11 +12:00
self.mprPersos.addMapping(w, i)
self.mprPersos.addMapping(self.sldPersoImportance,
Perso.importance.value, "importance")
self.sldPersoImportance.importanceChanged.connect(self.mprPersos.submit)
self.tabMain.currentChanged.connect(self.mprPersos.submit)
2015-06-23 07:34:11 +12:00
self.mprPersos.setCurrentIndex(0)
2015-06-23 07:34:11 +12:00
self.lstPersos.selectionModel().currentChanged.connect(
self.changeCurrentPerso)
self.tabPersos.currentChanged.connect(self.resizePersosInfos)
2015-06-23 07:34:11 +12:00
# Plots
2015-06-22 23:11:45 +12:00
self.lstPlots.setPlotModel(self.mdlPlots)
self.txtPlotFilter.textChanged.connect(self.lstPlots.setFilter)
2015-06-23 06:30:43 +12:00
self.lstPlots.currentItemChanged.connect(self.changeCurrentPlot)
2015-06-22 23:11:45 +12:00
self.lstPlotPerso.setModel(self.mdlPlots)
self.lstSubPlots.setModel(self.mdlPlots)
2015-06-23 07:07:38 +12:00
self._updatingSubPlot = False
2015-06-23 07:34:11 +12:00
self.txtSubPlotSummary.document().contentsChanged.connect(
self.updateSubPlotSummary)
2015-06-23 07:07:38 +12:00
self.lstSubPlots.activated.connect(self.changeCurrentSubPlot)
self.btnAddPlot.clicked.connect(self.mdlPlots.addPlot)
2015-06-23 07:34:11 +12:00
self.btnRmPlot.clicked.connect(lambda:
self.mdlPlots.removePlot(self.lstPlots.currentPlotIndex()))
self.btnAddSubPlot.clicked.connect(self.mdlPlots.addSubPlot)
self.btnRmSubPlot.clicked.connect(self.mdlPlots.removeSubPlot)
self.btnRmPlotPerso.clicked.connect(self.mdlPlots.removePlotPerso)
2015-06-23 07:34:11 +12:00
for w, c in [
(self.txtPlotName, Plot.name.value),
(self.txtPlotDescription, Plot.description.value),
(self.txtPlotResult, Plot.result.value),
(self.sldPlotImportance, Plot.importance.value),
]:
w.setModel(self.mdlPlots)
w.setColumn(c)
2015-06-23 07:34:11 +12:00
self.tabPlot.setEnabled(False)
2015-06-23 07:34:11 +12:00
2015-06-23 06:30:43 +12:00
self.lstOutlinePlots.setPlotModel(self.mdlPlots)
self.lstOutlinePlots.setShowSubPlot(True)
2015-06-23 07:34:11 +12:00
# Outline
self.treeRedacOutline.setModel(self.mdlOutline)
self.treePlanOutline.setModelPersos(self.mdlPersos)
self.treePlanOutline.setModelLabels(self.mdlLabels)
self.treePlanOutline.setModelStatus(self.mdlStatus)
2015-06-23 07:34:11 +12:00
self.redacMetadata.setModels(self.mdlOutline, self.mdlPersos,
self.mdlLabels, self.mdlStatus)
self.outlineItemEditor.setModels(self.mdlOutline, self.mdlPersos,
self.mdlLabels, self.mdlStatus)
self.treePlanOutline.setModel(self.mdlOutline)
self.redacEditor.setModel(self.mdlOutline)
2015-06-23 07:34:11 +12:00
self.treePlanOutline.selectionModel().selectionChanged.connect(lambda:
self.outlineItemEditor.selectionChanged(self.treePlanOutline))
self.treePlanOutline.clicked.connect(lambda:
self.outlineItemEditor.selectionChanged(self.treePlanOutline))
self.treeRedacOutline.setSelectionModel(self.treePlanOutline
.selectionModel())
self.btnRedacAddFolder.clicked.connect(self.treeRedacOutline.addFolder)
self.btnPlanAddFolder.clicked.connect(self.treePlanOutline.addFolder)
self.btnRedacAddText.clicked.connect(self.treeRedacOutline.addText)
self.btnPlanAddText.clicked.connect(self.treePlanOutline.addText)
self.btnRedacRemoveItem.clicked.connect(self.outlineRemoveItems)
self.btnPlanRemoveItem.clicked.connect(self.outlineRemoveItems)
2015-06-23 07:34:11 +12:00
self.treeRedacOutline.selectionModel().selectionChanged.connect(
lambda: self.redacMetadata.selectionChanged(self.treeRedacOutline))
self.treeRedacOutline.clicked.connect(
lambda: self.redacMetadata.selectionChanged(self.treeRedacOutline))
2015-06-23 07:34:11 +12:00
#self.treeRedacOutline.selectionModel().currentChanged.connect(self.redacEditor.setCurrentModelIndex)
self.treeRedacOutline.selectionModel().selectionChanged.connect(self.redacEditor.setView)
self.treeRedacOutline.selectionModel().currentChanged.connect(self.redacEditor.txtRedacText.setCurrentModelIndex)
2015-06-23 07:34:11 +12:00
self.treeRedacOutline.selectionModel().selectionChanged.connect(self.outlineSelectionChanged)
self.treeRedacOutline.selectionModel().selectionChanged.connect(self.outlineSelectionChanged)
self.treePlanOutline.selectionModel().selectionChanged.connect(self.outlineSelectionChanged)
self.treePlanOutline.selectionModel().selectionChanged.connect(self.outlineSelectionChanged)
2015-06-23 07:34:11 +12:00
self.sldCorkSizeFactor.valueChanged.connect(
self.redacEditor.setCorkSizeFactor)
self.btnRedacFolderCork.toggled.connect(
self.sldCorkSizeFactor.setVisible)
self.btnRedacFolderText.clicked.connect(
lambda v: self.redacEditor.setFolderView("text"))
self.btnRedacFolderCork.clicked.connect(
lambda v: self.redacEditor.setFolderView("cork"))
self.btnRedacFolderOutline.clicked.connect(
lambda v: self.redacEditor.setFolderView("outline"))
2015-05-31 16:03:07 +12:00
def readSettings(self):
# Load State and geometry
settings = QSettings(qApp.organizationName(), qApp.applicationName())
2015-06-19 00:38:26 +12:00
if settings.contains("geometry"):
self.restoreGeometry(settings.value("geometry"))
if settings.contains("windowState"):
self.restoreState(settings.value("windowState"))
2015-06-23 07:34:11 +12:00
2015-05-31 16:03:07 +12:00
def closeEvent(self, event):
# Save State and geometry
stgs = QSettings(qApp.organizationName(), qApp.applicationName())
stgs.setValue("geometry", self.saveGeometry())
stgs.setValue("windowState", self.saveState())
2015-06-23 07:34:11 +12:00
2015-06-16 06:30:18 +12:00
# Specific settings to save before quitting
settings.lastTab = self.tabMain.currentIndex()
if len(self.treeRedacOutline.selectedIndexes()) == 0:
sel = QModelIndex()
else:
sel = self.treeRedacOutline.currentIndex()
settings.lastIndex = self.mdlOutline.pathToIndex(sel)
2015-06-23 07:34:11 +12:00
2015-05-31 16:03:07 +12:00
# Save data from models
if settings.saveOnQuit:
2015-06-17 22:00:03 +12:00
self.saveDatas()
2015-06-23 07:34:11 +12:00
2015-05-31 16:03:07 +12:00
# closeEvent
QMainWindow.closeEvent(self, event)
2015-06-23 07:34:11 +12:00
2015-06-18 04:40:55 +12:00
def startTimerNoChanges(self):
if settings.autoSaveNoChanges:
self.saveTimerNoChanges.start()
2015-06-23 07:34:11 +12:00
2015-06-17 22:00:03 +12:00
def saveDatas(self):
2015-06-17 23:25:46 +12:00
# Saving
files = []
2015-06-23 07:34:11 +12:00
files.append((saveStandardItemModelXML(self.mdlFlatData),
"flatModel.xml"))
files.append((saveStandardItemModelXML(self.mdlPersos),
"perso.xml"))
files.append((saveStandardItemModelXML(self.mdlPersosInfos),
"persoInfos.xml"))
files.append((saveStandardItemModelXML(self.mdlLabels),
"labels.xml"))
files.append((saveStandardItemModelXML(self.mdlStatus),
"status.xml"))
files.append((saveStandardItemModelXML(self.mdlPlots),
"plots.xml"))
files.append((self.mdlOutline.saveToXML(),
"outline.xml"))
files.append((settings.save(),
"settings.pickle"))
2015-06-17 23:25:46 +12:00
saveFilesToZip(files, self.currentProject)
2015-06-23 07:34:11 +12:00
2015-06-17 23:25:46 +12:00
# Giving some feedback
2015-06-17 22:00:03 +12:00
print(self.tr("Project {} saved.").format(self.currentProject))
2015-06-23 07:34:11 +12:00
self.statusBar().showMessage(
self.tr("Project {} saved.").format(self.currentProject), 5000)
2015-06-17 22:00:03 +12:00
def loadDatas(self):
2015-06-17 23:25:46 +12:00
# Loading
files = loadFilesFromZip(self.currentProject)
2015-06-23 07:34:11 +12:00
2015-06-17 23:25:46 +12:00
if "flatModel.xml" in files:
2015-06-23 07:34:11 +12:00
loadStandardItemModelXML(self.mdlFlatData,
files["flatModel.xml"], fromString=True)
2015-06-17 23:25:46 +12:00
if "perso.xml" in files:
2015-06-23 07:34:11 +12:00
loadStandardItemModelXML(self.mdlPersos,
files["perso.xml"], fromString=True)
2015-06-17 23:25:46 +12:00
if "persoInfos.xml" in files:
2015-06-23 07:34:11 +12:00
loadStandardItemModelXML(self.mdlPersosInfos,
files["persoInfos.xml"], fromString=True)
2015-06-17 23:25:46 +12:00
if "labels.xml" in files:
2015-06-23 07:34:11 +12:00
loadStandardItemModelXML(self.mdlLabels,
files["labels.xml"], fromString=True)
2015-06-17 23:25:46 +12:00
if "status.xml" in files:
2015-06-23 07:34:11 +12:00
loadStandardItemModelXML(self.mdlStatus,
files["status.xml"], fromString=True)
if "plots.xml" in files:
2015-06-23 07:34:11 +12:00
loadStandardItemModelXML(self.mdlPlots,
files["plots.xml"], fromString=True)
2015-06-17 23:25:46 +12:00
if "outline.xml" in files:
self.mdlOutline.loadFromXML(files["outline.xml"], fromString=True)
if "settings.pickle" in files:
settings.load(files["settings.pickle"], fromString=True)
2015-06-23 07:34:11 +12:00
2015-06-17 23:25:46 +12:00
# Giving some feedback
2015-06-17 22:00:03 +12:00
print(self.tr("Project {} loaded.").format(self.currentProject))
2015-06-23 07:34:11 +12:00
self.statusBar().showMessage(
self.tr("Project {} loaded.").format(self.currentProject), 5000)
2015-05-28 13:32:09 +12:00
def clickCycle(self, i):
2015-06-23 07:34:11 +12:00
if i == 0: # step 2 - paragraph summary
2015-05-28 13:32:09 +12:00
self.tabMain.setCurrentIndex(1)
self.tabSummary.setCurrentIndex(1)
2015-06-23 07:34:11 +12:00
if i == 1: # step 3 - characters summary
2015-05-28 13:32:09 +12:00
self.tabMain.setCurrentIndex(2)
self.tabPersos.setCurrentIndex(0)
2015-06-23 07:34:11 +12:00
if i == 2: # step 4 - page summary
2015-05-28 13:32:09 +12:00
self.tabMain.setCurrentIndex(1)
self.tabSummary.setCurrentIndex(2)
2015-06-23 07:34:11 +12:00
if i == 3: # step 5 - characters description
2015-05-28 13:32:09 +12:00
self.tabMain.setCurrentIndex(2)
self.tabPersos.setCurrentIndex(1)
2015-06-23 07:34:11 +12:00
if i == 4: # step 6 - four page synopsis
2015-05-28 13:32:09 +12:00
self.tabMain.setCurrentIndex(1)
self.tabSummary.setCurrentIndex(3)
2015-06-23 07:34:11 +12:00
if i == 5: # step 7 - full character charts
2015-05-28 13:32:09 +12:00
self.tabMain.setCurrentIndex(2)
self.tabPersos.setCurrentIndex(2)
2015-06-23 07:34:11 +12:00
if i == 6: # step 8 - scene list
2015-05-28 13:32:09 +12:00
self.tabMain.setCurrentIndex(3)
2015-06-23 07:34:11 +12:00
2015-05-31 16:03:07 +12:00
def wordCount(self, i):
2015-06-23 07:34:11 +12:00
src = {
0: self.txtSummarySentance,
1: self.txtSummaryPara,
2: self.txtSummaryPage,
3: self.txtSummaryFull
2015-05-28 13:32:09 +12:00
}[i]
2015-06-23 07:34:11 +12:00
2015-05-28 13:32:09 +12:00
lbl = {
2015-06-23 07:34:11 +12:00
0: self.lblSummaryWCSentance,
1: self.lblSummaryWCPara,
2: self.lblSummaryWCPage,
3: self.lblSummaryWCFull
2015-05-28 13:32:09 +12:00
}[i]
2015-06-23 07:34:11 +12:00
2015-06-05 06:22:37 +12:00
wc = wordCount(src.toPlainText())
2015-06-23 07:34:11 +12:00
if i in [2, 3]:
pages = self.tr(" (~{} pages)").format(int(wc / 25) / 10.)
else:
pages = ""
2015-06-08 22:01:45 +12:00
lbl.setText(self.tr("Words: {}{}").format(wc, pages))
2015-06-23 07:34:11 +12:00
2015-06-04 05:25:03 +12:00
def setupMoreUi(self):
# Splitters
self.splitterPersos.setStretchFactor(0, 25)
self.splitterPersos.setStretchFactor(1, 75)
2015-06-23 07:34:11 +12:00
2015-06-04 05:25:03 +12:00
self.splitterPlot.setStretchFactor(0, 20)
2015-06-05 06:22:37 +12:00
self.splitterPlot.setStretchFactor(1, 60)
self.splitterPlot.setStretchFactor(2, 30)
2015-06-23 07:34:11 +12:00
2015-06-05 06:22:37 +12:00
self.splitterOutlineH.setStretchFactor(0, 25)
self.splitterOutlineH.setStretchFactor(1, 75)
self.splitterOutlineV.setStretchFactor(0, 75)
self.splitterOutlineV.setStretchFactor(1, 25)
2015-06-23 07:34:11 +12:00
2015-06-04 05:25:03 +12:00
self.splitterRedac.setStretchFactor(0, 20)
self.splitterRedac.setStretchFactor(1, 60)
self.splitterRedac.setStretchFactor(2, 20)
2015-06-23 07:34:11 +12:00
2015-06-04 05:25:03 +12:00
# Help box
references = [
(self.lytTabOverview,
2015-06-21 21:29:35 +12:00
self.tr("Enter infos about your book, and yourself."),
0),
(self.lytSituation,
self.tr("The basic situation, in the form of a 'What if...?' question. Ex: 'What if the most dangerous evil wizard could wasn't abled to kill a baby?' (Harry Potter)"),
1),
(self.lytSummary,
self.tr("Take time to think about a one sentance (~50 words) summary of your book. Then expand it to a paragraph, then to a page, then to a full summary."),
1),
2015-06-04 05:25:03 +12:00
(self.lytTabPersos,
2015-06-21 21:29:35 +12:00
self.tr("Create your characters."),
0),
2015-06-04 05:25:03 +12:00
(self.lytTabPlot,
2015-06-21 21:29:35 +12:00
self.tr("Develop plots."),
0),
2015-06-04 05:25:03 +12:00
(self.lytTabOutline,
2015-06-21 21:29:35 +12:00
self.tr("Create the outline of your masterpiece."),
0),
2015-06-04 05:25:03 +12:00
(self.lytTabRedac,
2015-06-21 21:29:35 +12:00
self.tr("Write."),
0),
2015-06-04 05:25:03 +12:00
(self.lytTabDebug,
2015-06-21 21:29:35 +12:00
self.tr("Debug infos. Sometimes useful."),
0)
2015-06-04 05:25:03 +12:00
]
2015-06-21 21:29:35 +12:00
for widget, text, pos in references:
2015-06-04 05:25:03 +12:00
label = helpLabel(text)
self.actShowHelp.toggled.connect(label.setVisible)
2015-06-21 21:29:35 +12:00
widget.layout().insertWidget(pos, label)
2015-06-23 07:34:11 +12:00
2015-06-07 05:10:44 +12:00
self.actShowHelp.setChecked(False)
2015-06-23 07:34:11 +12:00
2015-06-07 05:10:44 +12:00
# Spellcheck
if enchant:
2015-06-08 22:01:45 +12:00
self.menuDict = QMenu(self.tr("Dictionary"))
2015-06-07 05:10:44 +12:00
self.menuDictGroup = QActionGroup(self)
self.updateMenuDict()
2015-06-07 05:10:44 +12:00
self.menuTools.addMenu(self.menuDict)
2015-06-23 07:34:11 +12:00
self.actSpellcheck.toggled.connect(self.toggleSpellcheck)
2015-06-07 05:10:44 +12:00
self.dictChanged.connect(self.redacEditor.setDict)
self.dictChanged.connect(self.redacMetadata.setDict)
self.dictChanged.connect(self.outlineItemEditor.setDict)
2015-06-23 07:34:11 +12:00
2015-06-07 05:10:44 +12:00
else:
# No Spell check support
self.actSpellcheck.setVisible(False)
2015-06-08 22:01:45 +12:00
a = QAction(self.tr("Install PyEnchant to use spellcheck"), self)
2015-06-07 05:10:44 +12:00
a.setIcon(self.style().standardIcon(QStyle.SP_MessageBoxWarning))
a.triggered.connect(self.openPyEnchantWebPage)
self.menuTools.addAction(a)
2015-06-23 07:34:11 +12:00
self.btnRedacFullscreen.clicked.connect(
lambda: self.redacEditor.showFullscreen(
self.treeRedacOutline.currentIndex()))
def updateMenuDict(self):
2015-06-23 07:34:11 +12:00
2015-06-16 18:15:24 +12:00
if not enchant:
return
2015-06-23 07:34:11 +12:00
self.menuDict.clear()
for i in enchant.list_dicts():
a = QAction(str(i[0]), self)
a.setCheckable(True)
a.triggered.connect(self.setDictionary)
2015-06-23 07:34:11 +12:00
if settings.dict is None:
settings.dict = enchant.get_default_language()
if str(i[0]) == settings.dict:
a.setChecked(True)
self.menuDictGroup.addAction(a)
self.menuDict.addAction(a)
2015-06-23 07:34:11 +12:00
2015-06-07 05:10:44 +12:00
def setDictionary(self):
2015-06-16 18:15:24 +12:00
if not enchant:
return
2015-06-23 07:34:11 +12:00
2015-06-07 05:10:44 +12:00
for i in self.menuDictGroup.actions():
if i.isChecked():
self.dictChanged.emit(i.text().replace("&", ""))
settings.dict = i.text().replace("&", "")
2015-06-23 07:34:11 +12:00
# Find all textEditView from self, and toggle spellcheck
2015-06-23 07:34:11 +12:00
for w in self.findChildren(textEditView, QRegExp(".*"),
Qt.FindChildrenRecursively):
w.setDict(settings.dict)
2015-06-07 05:10:44 +12:00
def openPyEnchantWebPage(self):
QDesktopServices.openUrl(QUrl("http://pythonhosted.org/pyenchant/"))
2015-06-23 07:34:11 +12:00
def toggleSpellcheck(self, val):
settings.spellcheck = val
self.redacEditor.toggleSpellcheck(val)
self.redacMetadata.toggleSpellcheck(val)
self.outlineItemEditor.toggleSpellcheck(val)
2015-06-23 07:34:11 +12:00
# Find all textEditView from self, and toggle spellcheck
2015-06-23 07:34:11 +12:00
for w in self.findChildren(textEditView, QRegExp(".*"),
Qt.FindChildrenRecursively):
w.toggleSpellcheck(val)
2015-06-23 07:34:11 +12:00
###############################################################################
# SETTINGS
###############################################################################
def settingsLabel(self):
2015-06-18 06:45:24 +12:00
self.settingsWindow("Labels")
2015-06-23 07:34:11 +12:00
def settingsStatus(self):
2015-06-18 06:45:24 +12:00
self.settingsWindow("Status")
2015-06-23 07:34:11 +12:00
def settingsWindow(self, tab=None):
self.sw = settingsWindow(self)
self.sw.hide()
self.sw.setWindowModality(Qt.ApplicationModal)
self.sw.setWindowFlags(Qt.Dialog)
r = self.sw.geometry()
r2 = self.geometry()
self.sw.move(r2.center() - r.center())
if tab:
2015-06-18 06:45:24 +12:00
self.sw.setTab(tab)
self.sw.show()
2015-06-23 07:34:11 +12:00
###############################################################################
# VIEW MENU
###############################################################################
def generateViewMenu(self):
values = [
(self.tr("Nothing"), "Nothing"),
(self.tr("POV"), "POV"),
(self.tr("Label"), "Label"),
(self.tr("Progress"), "Progress"),
(self.tr("Compile"), "Compile"),
]
2015-06-23 07:34:11 +12:00
menus = [
(self.tr("Tree"), "Tree"),
(self.tr("Index cards"), "Cork"),
(self.tr("Outline"), "Outline")
]
2015-06-23 07:34:11 +12:00
submenus = {
"Tree": [
(self.tr("Icon color"), "Icon"),
(self.tr("Text color"), "Text"),
(self.tr("Background color"), "Background"),
],
"Cork": [
(self.tr("Icon"), "Icon"),
(self.tr("Text"), "Text"),
(self.tr("Background"), "Background"),
(self.tr("Border"), "Border"),
(self.tr("Corner"), "Corner"),
],
"Outline": [
(self.tr("Icon color"), "Icon"),
(self.tr("Text color"), "Text"),
(self.tr("Background color"), "Background"),
],
}
2015-06-23 07:34:11 +12:00
self.menuView.clear()
2015-06-23 07:34:11 +12:00
#print("Generating menus with", settings.viewSettings)
2015-06-23 07:34:11 +12:00
for mnu, mnud in menus:
m = QMenu(mnu, self.menuView)
for s, sd in submenus[mnud]:
m2 = QMenu(s, m)
agp = QActionGroup(m2)
for v, vd in values:
a = QAction(v, m)
a.setCheckable(True)
a.setData("{},{},{}".format(mnud, sd, vd))
if settings.viewSettings[mnud][sd] == vd:
a.setChecked(True)
2015-06-18 04:40:55 +12:00
a.triggered.connect(self.setViewSettingsAction)
agp.addAction(a)
m2.addAction(a)
m.addMenu(m2)
self.menuView.addMenu(m)
2015-06-23 07:34:11 +12:00
2015-06-18 04:40:55 +12:00
def setViewSettingsAction(self):
action = self.sender()
item, part, element = action.data().split(",")
2015-06-18 04:40:55 +12:00
self.setViewSettings(item, part, element)
2015-06-23 07:34:11 +12:00
2015-06-18 04:40:55 +12:00
def setViewSettings(self, item, part, element):
2015-06-16 09:15:10 +12:00
settings.viewSettings[item][part] = element
if item == "Cork":
2015-06-18 03:15:13 +12:00
self.redacEditor.corkView.viewport().update()
if item == "Outline":
self.redacEditor.outlineView.viewport().update()
self.treePlanOutline.viewport().update()
if item == "Tree":
self.treeRedacOutline.viewport().update()