Fix merge conflicts

This commit is contained in:
Veronica K. B. Olsen
2020-02-27 00:19:18 +01:00
52 changed files with 1835 additions and 584 deletions
+6
View File
@@ -1,15 +1,21 @@
# -*- coding: utf-8 -*-
from nw.gui.dialogs.configeditor import GuiConfigEditor
from nw.gui.dialogs.docmerge import GuiDocMerge
from nw.gui.dialogs.docsplit import GuiDocSplit
from nw.gui.dialogs.export import GuiExport
from nw.gui.dialogs.itemeditor import GuiItemEditor
from nw.gui.dialogs.projecteditor import GuiProjectEditor
from nw.gui.dialogs.projectload import GuiProjectLoad
from nw.gui.dialogs.sessionlog import GuiSessionLogView
__all__ = [
"GuiConfigEditor",
"GuiDocMerge",
"GuiDocSplit",
"GuiExport",
"GuiItemEditor",
"GuiProjectEditor",
"GuiProjectLoad",
"GuiSessionLogView",
]
+157
View File
@@ -0,0 +1,157 @@
# -*- coding: utf-8 -*-
"""novelWriter GUI Doc Merge
novelWriter GUI Doc Merge
=============================
Tool for merging multiple documents to one
File History:
Created: 2020-01-23 [0.4.3]
"""
import logging
import nw
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import (
QDialog, QHBoxLayout, QVBoxLayout, QGridLayout, QPushButton,
QListWidget, QAbstractItemView, QListWidgetItem
)
from nw.constants import nwAlert, nwItemType
from nw.project import NWDoc
logger = logging.getLogger(__name__)
class GuiDocMerge(QDialog):
def __init__(self, theParent, theProject):
QDialog.__init__(self, theParent)
logger.debug("Initialising GuiDocMerge ...")
self.mainConf = nw.CONFIG
self.theParent = theParent
self.theProject = theProject
self.sourceItem = None
self.outerBox = QHBoxLayout()
self.innerBox = QVBoxLayout()
self.setWindowTitle("Merge Documents")
self.setLayout(self.outerBox)
self.guiDeco = self.theParent.theTheme.loadDecoration("merge",(64,64))
self.outerBox.addWidget(self.guiDeco, 0, Qt.AlignTop)
self.outerBox.addLayout(self.innerBox)
self.doMergeForm = QGridLayout()
self.doMergeForm.setContentsMargins(0,0,0,0)
self.listBox = QListWidget()
self.listBox.setDragDropMode(QAbstractItemView.InternalMove)
self.mergeButton = QPushButton("Merge")
self.mergeButton.clicked.connect(self._doMerge)
self.closeButton = QPushButton("Close")
self.closeButton.clicked.connect(self._doClose)
self.doMergeForm.addWidget(self.listBox, 0, 0, 1, 3)
self.doMergeForm.addWidget(self.mergeButton, 1, 1)
self.doMergeForm.addWidget(self.closeButton, 1, 2)
self.innerBox.addLayout(self.doMergeForm)
self.rejected.connect(self._doClose)
self.show()
self._populateList()
logger.debug("GuiDocMerge initialisation complete")
return
##
# Buttons
##
def _doMerge(self):
"""Perform the merge of the files in the selected folder, and
create a new file in the same parent folder. The old files are
not removed in the merge process, and must be deleted manually.
"""
logger.verbose("GuiDocMerge merge button clicked")
finalOrder = []
for i in range(self.listBox.count()):
finalOrder.append(self.listBox.item(i).data(Qt.UserRole))
theDoc = NWDoc(self.theProject, self.theParent)
theText = ""
for tHandle in finalOrder:
theText += theDoc.openDocument(tHandle, False).rstrip()
theText += "\n\n"
if self.sourceItem is None:
self.theParent.makeAlert((
"Cannot parse source item."
), nwAlert.ERROR)
return
srcItem = self.theProject.getItem(self.sourceItem)
nHandle = self.theProject.newFile(srcItem.itemName, srcItem.itemClass, srcItem.parHandle)
self.theParent.treeView.revealTreeItem(nHandle)
theDoc.openDocument(nHandle, False)
theDoc.saveDocument(theText)
self.theParent.openDocument(nHandle)
self.close()
return
def _doClose(self):
"""Close the dialog window without doing anything.
"""
logger.verbose("GuiDocMerge close button clicked")
self.close()
return
##
# Internal Functions
##
def _populateList(self):
"""Get the item selected in the tree, check that it is a folder,
and try to find all files associated with it. The valid files
are then added to the list view in order. The list itself can be
reordered by the user.
"""
tHandle = self.theParent.treeView.getSelectedHandle()
self.sourceItem = tHandle
if tHandle is None:
return
nwItem = self.theProject.getItem(tHandle)
if nwItem is None:
return
if nwItem.itemType is not nwItemType.FOLDER:
self.theParent.makeAlert((
"Element selected in the project tree must be a folder."
), nwAlert.ERROR)
return
for sHandle in self.theParent.treeView.getTreeFromHandle(tHandle):
newItem = QListWidgetItem()
nwItem = self.theProject.getItem(sHandle)
if nwItem.itemType is not nwItemType.FILE:
continue
newItem.setText(nwItem.itemName)
newItem.setData(Qt.UserRole, sHandle)
self.listBox.addItem(newItem)
return
# END Class GuiDocMerge
+241
View File
@@ -0,0 +1,241 @@
# -*- coding: utf-8 -*-
"""novelWriter GUI Doc Split
novelWriter GUI Doc Split
=============================
Tool for splitting a single document into multiple documents
File History:
Created: 2020-02-01 [0.4.3]
"""
import logging
import nw
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import (
QDialog, QHBoxLayout, QVBoxLayout, QGridLayout, QPushButton, QComboBox,
QListWidget, QAbstractItemView, QListWidgetItem
)
from nw.constants import nwAlert, nwItemType, nwItemClass, nwItemLayout
from nw.project import NWDoc
logger = logging.getLogger(__name__)
class GuiDocSplit(QDialog):
def __init__(self, theParent, theProject):
QDialog.__init__(self, theParent)
logger.debug("Initialising GuiDocSplit ...")
self.mainConf = nw.CONFIG
self.theParent = theParent
self.theProject = theProject
self.optState = self.theProject.optState
self.sourceItem = None
self.outerBox = QHBoxLayout()
self.innerBox = QVBoxLayout()
self.setWindowTitle("Split Document")
self.setLayout(self.outerBox)
self.guiDeco = self.theParent.theTheme.loadDecoration("split",(64,64))
self.outerBox.addWidget(self.guiDeco, 0, Qt.AlignTop)
self.outerBox.addLayout(self.innerBox)
self.doMergeForm = QGridLayout()
self.doMergeForm.setContentsMargins(0,0,0,0)
self.listBox = QListWidget()
self.listBox.setDragDropMode(QAbstractItemView.NoDragDrop)
self.splitLevel = QComboBox(self)
self.splitLevel.addItem("Split on Header Level 1 (Title)", 1)
self.splitLevel.addItem("Split up to Header Level 2 (Chapter)", 2)
self.splitLevel.addItem("Split up to Header Level 3 (Scene)", 3)
self.splitLevel.addItem("Split up to Header Level 4 (Section)", 4)
spIndex = self.splitLevel.findData(
self.optState.getInt("GuiDocSplit", "spLevel", 3)
)
if spIndex != -1:
self.splitLevel.setCurrentIndex(spIndex)
self.splitLevel.currentIndexChanged.connect(self._populateList)
self.splitButton = QPushButton("Split")
self.splitButton.clicked.connect(self._doSplit)
self.closeButton = QPushButton("Close")
self.closeButton.clicked.connect(self._doClose)
self.doMergeForm.addWidget(self.listBox, 0, 0, 1, 3)
self.doMergeForm.addWidget(self.splitLevel, 1, 0, 1, 3)
self.doMergeForm.addWidget(self.splitButton, 2, 1)
self.doMergeForm.addWidget(self.closeButton, 2, 2)
self.innerBox.addLayout(self.doMergeForm)
self.rejected.connect(self._doClose)
self.show()
self._populateList()
logger.debug("GuiDocSplit initialisation complete")
return
##
# Buttons
##
def _doSplit(self):
"""Perform the split of the file, create a new folder in the
same parent folder, and multiple files depending on split level
settings. The old file is not removed in the merge process, and
must be deleted manually.
"""
logger.verbose("GuiDocSplit split button clicked")
if self.sourceItem is None:
self.theParent.makeAlert((
"No source document selected. Nothing to do."
), nwAlert.ERROR)
return
srcItem = self.theProject.getItem(self.sourceItem)
if srcItem is None:
self.theParent.makeAlert((
"Could not parse source document."
), nwAlert.ERROR)
return
theDoc = NWDoc(self.theProject, self.theParent)
theText = theDoc.openDocument(self.sourceItem, False)
theLines = theText.splitlines()
nLines = len(theLines)
theLines.insert(0, "%Split Doc")
logger.debug(
"Splitting document %s with %d lines" % (self.sourceItem,nLines)
)
finalOrder = []
for i in range(self.listBox.count()):
listItem = self.listBox.item(i)
wTitle = listItem.text()
lineNo = listItem.data(Qt.UserRole)
finalOrder.append([wTitle, lineNo, nLines])
if i > 0:
finalOrder[i-1][2] = lineNo
if len(finalOrder) == 0:
self.theParent.makeAlert((
"No headers found. Nothing to do."
), nwAlert.ERROR)
return
fHandle = self.theProject.newFolder(srcItem.itemName, srcItem.itemClass, srcItem.parHandle)
self.theParent.treeView.revealTreeItem(fHandle)
logger.verbose("Creating folder %s" % fHandle)
for wTitle, iStart, iEnd in finalOrder:
itemLayout = nwItemLayout.NOTE
if srcItem.itemClass == nwItemClass.NOVEL:
if wTitle.startswith("# "):
itemLayout = nwItemLayout.PARTITION
elif wTitle.startswith("## "):
itemLayout = nwItemLayout.CHAPTER
elif wTitle.startswith("### "):
itemLayout = nwItemLayout.SCENE
elif wTitle.startswith("#### "):
itemLayout = nwItemLayout.PAGE
wTitle = wTitle.lstrip("#")
wTitle = wTitle.strip()
nHandle = self.theProject.newFile(wTitle, srcItem.itemClass, fHandle)
newItem = self.theProject.getItem(nHandle)
newItem.setLayout(itemLayout)
logger.verbose(
"Creating new document %s with text from line %d to %d" % (nHandle, iStart, iEnd-1)
)
theText = "\n".join(theLines[iStart:iEnd])
theDoc.openDocument(nHandle, False)
theDoc.saveDocument(theText)
theDoc.clearDocument()
self.theParent.treeView.revealTreeItem(nHandle)
self.close()
return
def _doClose(self):
"""Close the dialog window without doing anything.
"""
logger.verbose("GuiDocSplit close button clicked")
self.optState.saveSettings()
self.close()
return
##
# Internal Functions
##
def _populateList(self):
"""Get the item selected in the tree, check that it is a folder,
and try to find all files associated with it. The valid files
are then added to the list view in order. The list itself can be
reordered by the user.
"""
if self.sourceItem is None:
self.sourceItem = self.theParent.treeView.getSelectedHandle()
if self.sourceItem is None:
return
nwItem = self.theProject.getItem(self.sourceItem)
if nwItem is None:
return
if nwItem.itemType is not nwItemType.FILE:
self.theParent.makeAlert((
"Element selected in the project tree must be a file."
), nwAlert.ERROR)
return
self.listBox.clear()
theDoc = NWDoc(self.theProject, self.theParent)
theText = theDoc.openDocument(self.sourceItem, False)
spLevel = self.splitLevel.currentData()
self.optState.setValue("GuiDocSplit", "spLevel", spLevel)
logger.debug("Scanning document %s for headings level <= %d" % (self.sourceItem, spLevel))
lineNo = 0
for aLine in theText.splitlines():
lineNo += 1
onLine = 0
if aLine.startswith("# ") and spLevel >= 1:
onLine = lineNo
elif aLine.startswith("## ") and spLevel >= 2:
onLine = lineNo
elif aLine.startswith("### ") and spLevel >= 3:
onLine = lineNo
elif aLine.startswith("#### ") and spLevel >= 4:
onLine = lineNo
if onLine > 0:
newItem = QListWidgetItem()
newItem.setText(aLine.strip())
newItem.setData(Qt.UserRole, onLine)
self.listBox.addItem(newItem)
return
# END Class GuiDocSplit
+63 -65
View File
@@ -24,7 +24,6 @@ from PyQt5.QtWidgets import (
)
from nw.convert import TextFile, HtmlFile, MarkdownFile, LaTeXFile, ConcatFile
from nw.tools import OptLastState
from nw.common import packageRefURL
from nw.constants import nwFiles, nwItemType, nwAlert
@@ -40,8 +39,7 @@ class GuiExport(QDialog):
self.mainConf = nw.CONFIG
self.theParent = theParent
self.theProject = theProject
self.optState = ExportLastState(self.theProject,nwFiles.EXPORT_OPT)
self.optState.loadSettings()
self.optState = self.theProject.optState
self.outerBox = QHBoxLayout()
self.innerBox = QVBoxLayout()
@@ -50,8 +48,8 @@ class GuiExport(QDialog):
self.guiDeco = self.theParent.theTheme.loadDecoration("export",(64,64))
self.tabMain = GuiExportMain(self.theParent, self.theProject, self.optState)
self.tabPandoc = GuiExportPandoc(self.theParent, self.theProject, self.optState)
self.tabMain = GuiExportMain(self.theParent, self.theProject)
self.tabPandoc = GuiExportPandoc(self.theParent, self.theProject)
self.tabWidget = QTabWidget()
self.tabWidget.addTab(self.tabMain, "Settings")
@@ -290,24 +288,24 @@ class GuiExport(QDialog):
if saveTo.startswith("~"):
saveTo = path.expanduser(saveTo)
self.optState.setSetting("wNovel", wNovel)
self.optState.setSetting("wNotes", wNotes)
self.optState.setSetting("eFormat", eFormat)
self.optState.setSetting("fixWidth", fixWidth)
self.optState.setSetting("wComments",wComments)
self.optState.setSetting("wKeywords",wKeywords)
self.optState.setSetting("chFormat", chFormat)
self.optState.setSetting("unFormat", unFormat)
self.optState.setSetting("scFormat", scFormat)
self.optState.setSetting("seFormat", seFormat)
self.optState.setSetting("saveTo", saveTo)
self.optState.setSetting("hScene", hScene)
self.optState.setSetting("hSection", hSection)
self.optState.setValue("GuiExport", "wNovel", wNovel)
self.optState.setValue("GuiExport", "wNotes", wNotes)
self.optState.setValue("GuiExport", "eFormat", eFormat)
self.optState.setValue("GuiExport", "fixWidth", fixWidth)
self.optState.setValue("GuiExport", "wComments", wComments)
self.optState.setValue("GuiExport", "wKeywords", wKeywords)
self.optState.setValue("GuiExport", "chFormat", chFormat)
self.optState.setValue("GuiExport", "unFormat", unFormat)
self.optState.setValue("GuiExport", "scFormat", scFormat)
self.optState.setValue("GuiExport", "seFormat", seFormat)
self.optState.setValue("GuiExport", "saveTo", saveTo)
self.optState.setValue("GuiExport", "hScene", hScene)
self.optState.setValue("GuiExport", "hSection", hSection)
# Pandoc Settings
pFormat = self.tabPandoc.outputFormat.currentData()
self.optState.setSetting("pFormat", pFormat)
self.optState.setValue("GuiExport", "pFormat", pFormat)
self.optState.saveSettings()
self.close()
@@ -362,14 +360,14 @@ class GuiExportMain(QWidget):
),
}
def __init__(self, theParent, theProject, optState):
def __init__(self, theParent, theProject):
QWidget.__init__(self, theParent)
self.theParent = theParent
self.theProject = theProject
self.theTheme = theParent.theTheme
self.outerBox = QGridLayout()
self.optState = optState
self.optState = self.theProject.optState
self.currFormat = self.FMT_TXT
# Select Files
@@ -378,19 +376,27 @@ class GuiExportMain(QWidget):
self.guiFiles.setLayout(self.guiFilesForm)
self.expNovel = QCheckBox("Novel files",self)
self.expNovel.setChecked(self.optState.getSetting("wNovel"))
self.expNovel.setChecked(
self.optState.getBool("GuiExport", "wNovel", True)
)
self.expNovel.setToolTip("Include all novel files in the exported document")
self.expNotes = QCheckBox("Note files",self)
self.expNotes.setChecked(self.optState.getSetting("wNotes"))
self.expNotes.setChecked(
self.optState.getBool("GuiExport", "wNotes", False)
)
self.expNotes.setToolTip("Include all note files in the exported document")
self.expComments = QCheckBox("Comments",self)
self.expComments.setChecked(self.optState.getSetting("wComments"))
self.expComments.setChecked(
self.optState.getBool("GuiExport", "wComments", False)
)
self.expComments.setToolTip("Export comments from all files")
self.expKeywords = QCheckBox("Keywords",self)
self.expKeywords.setChecked(self.optState.getSetting("wKeywords"))
self.expKeywords.setChecked(
self.optState.getBool("GuiExport", "wKeywords", False)
)
self.expKeywords.setToolTip("Export @keywords from all files")
self.guiFilesForm.addWidget(self.expNovel, 0, 1)
@@ -406,13 +412,17 @@ class GuiExportMain(QWidget):
self.chapterFormat = QLineEdit()
self.chapterFormat.setMaxLength(200)
self.chapterFormat.setText(self.optState.getSetting("chFormat"))
self.chapterFormat.setText(
self.optState.getString("GuiExport", "chFormat", "Chapter %numword%")
)
self.chapterFormat.setToolTip("Available formats: %num%, %numword%, %title%")
self.chapterFormat.setMinimumWidth(250)
self.unnumFormat = QLineEdit()
self.unnumFormat.setMaxLength(200)
self.unnumFormat.setText(self.optState.getSetting("unFormat"))
self.unnumFormat.setText(
self.optState.getString("GuiExport", "unFormat", "%title%")
)
self.unnumFormat.setToolTip("Available formats: %title%")
self.unnumFormat.setMinimumWidth(250)
@@ -428,22 +438,30 @@ class GuiExportMain(QWidget):
self.sceneFormat = QLineEdit()
self.sceneFormat.setMaxLength(200)
self.sceneFormat.setText(self.optState.getSetting("scFormat"))
self.sceneFormat.setText(
self.optState.getString("GuiExport", "scFormat", "* * *")
)
self.sceneFormat.setToolTip("Available formats: %title%")
self.sceneFormat.setMinimumWidth(100)
self.sectionFormat = QLineEdit()
self.sectionFormat.setMaxLength(200)
self.sectionFormat.setText(self.optState.getSetting("seFormat"))
self.sectionFormat.setText(
self.optState.getString("GuiExport", "seFormat", "")
)
self.sectionFormat.setToolTip("Available formats: %title%")
self.sectionFormat.setMinimumWidth(100)
self.hideScene = QCheckBox("Skip",self)
self.hideScene.setChecked(self.optState.getSetting("hScene"))
self.hideScene.setChecked(
self.optState.getBool("GuiExport", "hScene", False)
)
self.hideScene.setToolTip("Skip scene titles in export")
self.hideSection = QCheckBox("Skip",self)
self.hideSection.setChecked(self.optState.getSetting("hSection"))
self.hideSection.setChecked(
self.optState.getBool("GuiExport", "hSection", False)
)
self.hideSection.setToolTip("Skip section titles in export")
self.guiScenesForm.addWidget(QLabel("Scenes"), 0, 0)
@@ -458,8 +476,9 @@ class GuiExportMain(QWidget):
self.exportToForm = QGridLayout(self)
self.exportTo.setLayout(self.exportToForm)
self.exportPath = QLineEdit(self.optState.getSetting("saveTo"))
self.exportPath = QLineEdit(
self.optState.getString("GuiExport", "saveTo", "")
)
self.exportGetPath = QPushButton(self.theTheme.getIcon("folder"),"")
self.exportGetPath.clicked.connect(self._exportFolder)
@@ -486,7 +505,9 @@ class GuiExportMain(QWidget):
self.outputFormat.addItem("Pandoc via Markdown or HTML", self.FMT_PDOC)
self.outputFormat.currentIndexChanged.connect(self._updateFormat)
optIdx = self.outputFormat.findData(self.optState.getSetting("eFormat"))
optIdx = self.outputFormat.findData(
self.optState.getInt("GuiExport", "eFormat", 1)
)
if optIdx == -1:
self.outputFormat.setCurrentIndex(1)
self._updateFormat(1)
@@ -508,7 +529,9 @@ class GuiExportMain(QWidget):
self.fixedWidth.setMinimum(0)
self.fixedWidth.setMaximum(999)
self.fixedWidth.setSingleStep(1)
self.fixedWidth.setValue(self.optState.getSetting("fixWidth"))
self.fixedWidth.setValue(
self.optState.getInt("GuiExport", "fixWidth", 80)
)
self.fixedWidth.setToolTip(
"Applies to .txt and .md files. A value of '0' disables the feature."
)
@@ -609,13 +632,13 @@ class GuiExportPandoc(QWidget):
FMT_ZIM : "markdown",
}
def __init__(self, theParent, theProject, optState):
def __init__(self, theParent, theProject):
QWidget.__init__(self, theParent)
self.theParent = theParent
self.theProject = theProject
self.outerBox = QGridLayout()
self.optState = optState
self.optState = self.theProject.optState
try:
import pypandoc
@@ -659,7 +682,9 @@ class GuiExportPandoc(QWidget):
self.outputFormat.addItem("ePUB eBook v3 (.epub3)", self.FMT_EPUB3)
self.outputFormat.addItem("Zim Wiki (.txt)", self.FMT_ZIM)
optIdx = self.outputFormat.findData(self.optState.getSetting("pFormat"))
optIdx = self.outputFormat.findData(
self.optState.getInt("GuiExport", "pFormat", 1)
)
if optIdx == -1:
self.outputFormat.setCurrentIndex(1)
else:
@@ -678,30 +703,3 @@ class GuiExportPandoc(QWidget):
return
# END Class GuiExportPandoc
class ExportLastState(OptLastState):
def __init__(self, theProject, theFile):
OptLastState.__init__(self, theProject, theFile)
self.theState = {
"wNovel" : True,
"wNotes" : False,
"eFormat" : 1,
"pFormat" : 1,
"fixWidth" : 80,
"wComments" : False,
"wKeywords" : False,
"chFormat" : "Chapter %numword%",
"unFormat" : "%title%",
"scFormat" : "* * *",
"seFormat" : "",
"saveTo" : "",
"hScene" : False,
"hSection" : False,
}
self.stringOpt = ("chFormat","unFormat","scFormat","seFormat","saveTo")
self.boolOpt = ("wNovel","wNotes","wComments","wKeywords","hScene","hSection")
self.intOpt = ("eFormat","pFormat","fixWidth")
return
# END Class ExportLastState
-2
View File
@@ -13,8 +13,6 @@
import logging
import nw
from os import path
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import (
QDialog, QHBoxLayout, QVBoxLayout, QGroupBox, QFormLayout, QLineEdit,
-2
View File
@@ -13,8 +13,6 @@
import logging
import nw
from os import path
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QIcon, QPixmap, QColor, QBrush
from PyQt5.QtWidgets import (
+169
View File
@@ -0,0 +1,169 @@
# -*- coding: utf-8 -*-
"""novelWriter GUI Open Project
novelWriter GUI Open Project
================================
New and open project dialog
File History:
Created: 2020-02-26 [0.4.5]
"""
import logging
import nw
from datetime import datetime
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import (
QDialog, QHBoxLayout, QVBoxLayout, QGridLayout, QPushButton, QTreeWidget,
QAbstractItemView, QTreeWidgetItem
)
from nw.common import formatInt
logger = logging.getLogger(__name__)
class GuiProjectLoad(QDialog):
def __init__(self, theParent):
QDialog.__init__(self, theParent)
logger.debug("Initialising GuiProjectLoad ...")
self.mainConf = nw.CONFIG
self.theParent = theParent
self.sourceItem = None
self.openPath = None
self.outerBox = QHBoxLayout()
self.innerBox = QVBoxLayout()
self.setWindowTitle("Open Project")
self.setLayout(self.outerBox)
self.guiDeco = self.theParent.theTheme.loadDecoration("nwicon", (128, 128))
self.outerBox.addWidget(self.guiDeco, 0, Qt.AlignTop)
self.outerBox.addLayout(self.innerBox)
self.projectForm = QGridLayout()
self.projectForm.setContentsMargins(0, 0, 0, 0)
self.listBox = QTreeWidget()
self.listBox.setSelectionMode(QAbstractItemView.SingleSelection)
self.listBox.setDragDropMode(QAbstractItemView.NoDragDrop)
self.listBox.setColumnCount(4)
self.listBox.setHeaderLabels(["Working Title","Words","Accessed","Path"])
self.listBox.setRootIsDecorated(False)
treeHead = self.listBox.headerItem()
treeHead.setTextAlignment(1, Qt.AlignRight)
self.recentButton = QPushButton("Open")
self.recentButton.clicked.connect(self._doOpenRecent)
self.browseButton = QPushButton("Browse")
self.browseButton.clicked.connect(self._doBrowse)
self.closeButton = QPushButton("Close")
self.closeButton.clicked.connect(self._doClose)
self.projectForm.addWidget(self.listBox, 0, 0, 1, 4)
self.projectForm.addWidget(self.recentButton, 1, 1)
self.projectForm.addWidget(self.browseButton, 1, 2)
self.projectForm.addWidget(self.closeButton, 1, 3)
self.projectForm.setColumnStretch(0, 1)
self.innerBox.addLayout(self.projectForm)
self.rejected.connect(self._doClose)
self.setModal(True)
self.setMinimumWidth(750)
self.setMinimumHeight(450)
self.show()
self._populateList()
logger.debug("GuiProjectLoad initialisation complete")
return
##
# Buttons
##
def _doOpenRecent(self):
"""Close the dialog window with a recent project selected.
"""
logger.verbose("GuiProjectLoad open button clicked")
selItems = self.listBox.selectedItems()
if selItems:
self.openPath = selItems[0].text(3)
self.accept()
else:
self.openPath = None
return
def _doBrowse(self):
"""Close the dialog window with no selected path, triggering the
project browser dialog.
"""
logger.verbose("GuiProjectLoad browse button clicked")
self.openPath = None
self.accept()
return
def _doClose(self):
"""Close the dialog window without doing anything.
"""
logger.verbose("GuiProjectLoad close button clicked")
self.close()
return
##
# Internal Functions
##
def _populateList(self):
"""Populate the list box with recent project data.
"""
listOrder = []
listData = {}
for projPath in self.mainConf.recentProj.keys():
theEntry = self.mainConf.recentProj[projPath]
theTitle = ""
theTime = 0
theWords = 0
if "title" in theEntry.keys():
theTitle = theEntry["title"]
if "time" in theEntry.keys():
theTime = theEntry["time"]
if "words" in theEntry.keys():
theWords = theEntry["words"]
if theTime > 0:
listOrder.append(theTime)
listData[theTime] = [theTitle, theWords, projPath]
self.listBox.clear()
hasSelection = False
for timeStamp in sorted(listOrder, reverse=True):
newItem = QTreeWidgetItem([""]*4)
newItem.setText(0, listData[timeStamp][0])
newItem.setText(1, formatInt(listData[timeStamp][1]))
newItem.setText(2, datetime.fromtimestamp(timeStamp).strftime("%x %X"))
newItem.setText(3, listData[timeStamp][2])
newItem.setTextAlignment(1, Qt.AlignRight)
self.listBox.addTopLevelItem(newItem)
if not hasSelection:
newItem.setSelected(True)
hasSelection = True
self.listBox.resizeColumnToContents(0)
self.listBox.resizeColumnToContents(1)
self.listBox.resizeColumnToContents(2)
return
# END Class GuiProjectLoad
+20 -37
View File
@@ -24,7 +24,6 @@ from PyQt5.QtWidgets import (
)
from nw.constants import nwConst, nwFiles, nwAlert
from nw.tools import OptLastState
logger = logging.getLogger(__name__)
@@ -38,8 +37,7 @@ class GuiSessionLogView(QDialog):
self.mainConf = nw.CONFIG
self.theProject = theProject
self.theParent = theParent
self.optState = SessionLogLastState(self.theProject,nwFiles.SLOG_OPT)
self.optState.loadSettings()
self.optState = self.theProject.optState
self.timeFilter = 0.0
self.timeTotal = 0.0
@@ -52,13 +50,13 @@ class GuiSessionLogView(QDialog):
self.setMinimumHeight(400)
widthCol0 = self.optState.validIntRange(
self.optState.getSetting("widthCol0"), 30, 999, 180
self.optState.getInt("GuiSession", "widthCol0", 180), 30, 999, 180
)
widthCol1 = self.optState.validIntRange(
self.optState.getSetting("widthCol1"), 30, 999, 80
self.optState.getInt("GuiSession", "widthCol1", 80), 30, 999, 80
)
widthCol2 = self.optState.validIntRange(
self.optState.getSetting("widthCol2"), 30, 999, 80
self.optState.getInt("GuiSession", "widthCol2", 80), 30, 999, 80
)
self.listBox = QTreeWidget()
@@ -77,10 +75,11 @@ class GuiSessionLogView(QDialog):
sortValid = (Qt.AscendingOrder, Qt.DescendingOrder)
sortCol = self.optState.validIntRange(
self.optState.getSetting("sortCol"), 0, 2, 0
self.optState.getInt("GuiSession", "sortCol", 0), 0, 2, 0
)
sortOrder = self.optState.validIntTuple(
self.optState.getSetting("sortOrder"), sortValid, Qt.DescendingOrder
self.optState.getInt("GuiSession", "sortOrder", Qt.DescendingOrder),
sortValid, Qt.DescendingOrder
)
self.listBox.sortByColumn(sortCol, sortOrder)
@@ -110,11 +109,15 @@ class GuiSessionLogView(QDialog):
self.filterBox.setLayout(self.filterBoxForm)
self.hideZeros = QCheckBox("Hide zero word count", self)
self.hideZeros.setChecked(self.optState.getSetting("hideZeros"))
self.hideZeros.setChecked(
self.optState.getBool("GuiSession", "hideZeros", True)
)
self.hideZeros.stateChanged.connect(self._doHideZeros)
self.hideNegative = QCheckBox("Hide negative word count", self)
self.hideNegative.setChecked(self.optState.getSetting("hideNegative"))
self.hideNegative.setChecked(
self.optState.getBool("GuiSession", "hideNegative", False)
)
self.hideNegative.stateChanged.connect(self._doHideNegative)
self.filterBoxForm.addWidget(self.hideZeros, 0, 0)
@@ -208,13 +211,13 @@ class GuiSessionLogView(QDialog):
hideZeros = self.hideZeros.isChecked()
hideNegative = self.hideNegative.isChecked()
self.optState.setSetting("widthCol0", widthCol0)
self.optState.setSetting("widthCol1", widthCol1)
self.optState.setSetting("widthCol2", widthCol2)
self.optState.setSetting("sortCol", sortCol)
self.optState.setSetting("sortOrder", sortOrder)
self.optState.setSetting("hideZeros", hideZeros)
self.optState.setSetting("hideNegative",hideNegative)
self.optState.setValue("GuiSession", "widthCol0", widthCol0)
self.optState.setValue("GuiSession", "widthCol1", widthCol1)
self.optState.setValue("GuiSession", "widthCol2", widthCol2)
self.optState.setValue("GuiSession", "sortCol", sortCol)
self.optState.setValue("GuiSession", "sortOrder", sortOrder)
self.optState.setValue("GuiSession", "hideZeros", hideZeros)
self.optState.setValue("GuiSession", "hideNegative", hideNegative)
self.optState.saveSettings()
self.close()
@@ -237,23 +240,3 @@ class GuiSessionLogView(QDialog):
return "%02d:%02d:%02d" % (tH,tM,tS)
# END Class GuiSessionLogView
class SessionLogLastState(OptLastState):
def __init__(self, theProject, theFile):
OptLastState.__init__(self, theProject, theFile)
self.theState = {
"widthCol0" : 180,
"widthCol1" : 80,
"widthCol2" : 80,
"sortCol" : 0,
"sortOrder" : Qt.DescendingOrder,
"hideZeros" : True,
"hideNegative" : False,
}
self.stringOpt = ()
self.boolOpt = ("hideZeros","hideNegative")
self.intOpt = ("widthCol0","widthCol1","widthCol2","sortCol","sortOrder")
return
# END Class SessionLogLastState