Redesign the Document Merge dialog box
This commit is contained in:
@@ -19,6 +19,7 @@ You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
from novelwriter.core.doctools import DocMerger
|
||||
from novelwriter.core.document import NWDoc
|
||||
from novelwriter.core.index import countWords
|
||||
from novelwriter.core.project import NWProject
|
||||
@@ -28,6 +29,7 @@ from novelwriter.core.toodt import ToOdt
|
||||
from novelwriter.core.tomd import ToMarkdown
|
||||
|
||||
__all__ = [
|
||||
"DocMerger",
|
||||
"countWords",
|
||||
"NWDoc",
|
||||
"NWProject",
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
"""
|
||||
novelWriter – Project Document Tools
|
||||
====================================
|
||||
A collection of tools to create and manipulate documents
|
||||
|
||||
File History:
|
||||
Created: 2022-10-02 [2.0b1]
|
||||
|
||||
This file is a part of novelWriter
|
||||
Copyright 2018–2022, Veronica Berglyd Olsen
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# logger.verbose("GuiDocMerge merge button clicked")
|
||||
|
||||
# finalOrder = []
|
||||
# for i in range(self.listBox.count()):
|
||||
# finalOrder.append(self.listBox.item(i).data(Qt.UserRole))
|
||||
|
||||
# if len(finalOrder) == 0:
|
||||
# self.mainGui.makeAlert(self.tr(
|
||||
# "No source documents found. Nothing to do."
|
||||
# ), nwAlert.ERROR)
|
||||
# return False
|
||||
|
||||
# theText = ""
|
||||
# for tHandle in finalOrder:
|
||||
# inDoc = NWDoc(self.theProject, tHandle)
|
||||
# docText = inDoc.readDocument()
|
||||
# docErr = inDoc.getError()
|
||||
# if docText is None and docErr:
|
||||
# self.mainGui.makeAlert([
|
||||
# self.tr("Failed to open document file."), docErr
|
||||
# ], nwAlert.ERROR)
|
||||
# if docText:
|
||||
# theText += docText.rstrip("\n")+"\n\n"
|
||||
|
||||
# if self.sourceItem is None:
|
||||
# self.mainGui.makeAlert(self.tr(
|
||||
# "No source folder selected. Nothing to do."
|
||||
# ), nwAlert.ERROR)
|
||||
# return False
|
||||
|
||||
# srcItem = self.theProject.tree[self.sourceItem]
|
||||
# if srcItem is None:
|
||||
# self.mainGui.makeAlert(self.tr("Internal error."), nwAlert.ERROR)
|
||||
# return False
|
||||
|
||||
# nHandle = self.theProject.newFile(srcItem.itemName, srcItem.itemParent)
|
||||
# newItem = self.theProject.tree[nHandle]
|
||||
# newItem.setStatus(srcItem.itemStatus)
|
||||
# newItem.setImport(srcItem.itemImport)
|
||||
|
||||
# outDoc = NWDoc(self.theProject, nHandle)
|
||||
# if not outDoc.writeDocument(theText):
|
||||
# self.mainGui.makeAlert([
|
||||
# self.tr("Could not save document."), outDoc.getError()
|
||||
# ], nwAlert.ERROR)
|
||||
# return False
|
||||
|
||||
# self.mainGui.projView.revealNewTreeItem(nHandle)
|
||||
# self.mainGui.openDocument(nHandle, doScroll=True)
|
||||
|
||||
# self._doClose()
|
||||
|
||||
|
||||
class DocMerger:
|
||||
|
||||
def __init__(self, theProject):
|
||||
|
||||
self.theProject = theProject
|
||||
|
||||
self._targetDoc = None
|
||||
|
||||
return
|
||||
|
||||
def setTargetDoc(self, tHandle):
|
||||
return
|
||||
|
||||
def createNewDoc(self, docLabel, pHandle, itemLayout):
|
||||
return
|
||||
|
||||
def appendDoc(self, tHandle):
|
||||
return
|
||||
|
||||
# END Class DocMerger
|
||||
+76
-113
@@ -1,10 +1,11 @@
|
||||
"""
|
||||
novelWriter – GUI Doc Merge Tool
|
||||
================================
|
||||
GUI class for merging multiple documents to one document
|
||||
novelWriter – GUI Doc Merge Dialog
|
||||
==================================
|
||||
Custom dialog class for merging documents.
|
||||
|
||||
File History:
|
||||
Created: 2020-01-23 [0.4.3]
|
||||
Created: 2020-01-23 [0.4.3]
|
||||
Rewritten: 2022-10-06 [2.0b1]
|
||||
|
||||
This file is a part of novelWriter
|
||||
Copyright 2018–2022, Veronica Berglyd Olsen
|
||||
@@ -26,169 +27,131 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
import logging
|
||||
import novelwriter
|
||||
|
||||
from PyQt5.QtCore import Qt
|
||||
from PyQt5.QtCore import Qt, QSize
|
||||
from PyQt5.QtWidgets import (
|
||||
QDialog, QVBoxLayout, QLabel, QListWidget, QAbstractItemView,
|
||||
QListWidgetItem, QDialogButtonBox
|
||||
QListWidgetItem, QDialogButtonBox, QGridLayout
|
||||
)
|
||||
|
||||
from novelwriter.core import NWDoc
|
||||
from novelwriter.enum import nwAlert, nwItemType
|
||||
from novelwriter.gui.custom import QHelpLabel
|
||||
from novelwriter.gui.custom import QHelpLabel, QSwitch
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class GuiDocMerge(QDialog):
|
||||
|
||||
def __init__(self, mainGui):
|
||||
QDialog.__init__(self, mainGui)
|
||||
def __init__(self, mainGui, sHandle, itemList):
|
||||
super().__init__(parent=mainGui)
|
||||
|
||||
logger.debug("Initialising GuiDocMerge ...")
|
||||
self.setObjectName("GuiDocMerge")
|
||||
|
||||
self.mainConf = novelwriter.CONFIG
|
||||
self.mainGui = mainGui
|
||||
self.mainTheme = mainGui.mainTheme
|
||||
self.theProject = mainGui.theProject
|
||||
self.sourceItem = None
|
||||
|
||||
self.outerBox = QVBoxLayout()
|
||||
self._data = {}
|
||||
|
||||
self.setWindowTitle(self.tr("Merge Documents"))
|
||||
|
||||
self.headLabel = QLabel("<b>{0}</b>".format(self.tr("Documents to Merge")))
|
||||
self.helpLabel = QHelpLabel(
|
||||
self.tr("Drag and drop items to change the order."), self.mainGui.mainTheme.helpText
|
||||
)
|
||||
self.helpLabel = QHelpLabel(self.tr(
|
||||
"Drag and drop items to change the order, or uncheck to exclude."
|
||||
), self.mainTheme.helpText)
|
||||
|
||||
iPx = self.mainTheme.baseIconSize
|
||||
hSp = self.mainConf.pxInt(12)
|
||||
vSp = self.mainConf.pxInt(8)
|
||||
bSp = self.mainConf.pxInt(12)
|
||||
|
||||
self.listBox = QListWidget()
|
||||
self.listBox.setDragDropMode(QAbstractItemView.InternalMove)
|
||||
self.listBox.setIconSize(QSize(iPx, iPx))
|
||||
self.listBox.setMinimumWidth(self.mainConf.pxInt(400))
|
||||
self.listBox.setMinimumHeight(self.mainConf.pxInt(180))
|
||||
self.listBox.setSelectionBehavior(QAbstractItemView.SelectRows)
|
||||
self.listBox.setSelectionMode(QAbstractItemView.SingleSelection)
|
||||
self.listBox.setDragDropMode(QAbstractItemView.InternalMove)
|
||||
|
||||
# Merge Options
|
||||
self.trashLabel = QLabel(self.tr("Move merged items to Trash"))
|
||||
self.trashSwitch = QSwitch()
|
||||
|
||||
self.optBox = QGridLayout()
|
||||
self.optBox.addWidget(self.trashLabel, 0, 0)
|
||||
self.optBox.addWidget(self.trashSwitch, 0, 1)
|
||||
self.optBox.setHorizontalSpacing(hSp)
|
||||
self.optBox.setColumnStretch(2, 1)
|
||||
|
||||
# Buttons
|
||||
self.buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
|
||||
self.buttonBox.accepted.connect(self._doMerge)
|
||||
self.buttonBox.rejected.connect(self._doClose)
|
||||
self.buttonBox.accepted.connect(self.accept)
|
||||
self.buttonBox.rejected.connect(self.reject)
|
||||
|
||||
# Assemble
|
||||
self.outerBox = QVBoxLayout()
|
||||
self.outerBox.setSpacing(0)
|
||||
self.outerBox.addWidget(self.headLabel)
|
||||
self.outerBox.addWidget(self.helpLabel)
|
||||
self.outerBox.addSpacing(self.mainConf.pxInt(8))
|
||||
self.outerBox.addSpacing(vSp)
|
||||
self.outerBox.addWidget(self.listBox)
|
||||
self.outerBox.addSpacing(self.mainConf.pxInt(12))
|
||||
self.outerBox.addSpacing(vSp)
|
||||
self.outerBox.addLayout(self.optBox)
|
||||
self.outerBox.addSpacing(bSp)
|
||||
self.outerBox.addWidget(self.buttonBox)
|
||||
self.setLayout(self.outerBox)
|
||||
|
||||
self.rejected.connect(self._doClose)
|
||||
|
||||
self._populateList()
|
||||
# Load Content
|
||||
self._loadContent(sHandle, itemList)
|
||||
|
||||
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.
|
||||
def getData(self):
|
||||
"""Return the user's choices.
|
||||
"""
|
||||
logger.verbose("GuiDocMerge merge button clicked")
|
||||
|
||||
finalOrder = []
|
||||
finalItems = []
|
||||
for i in range(self.listBox.count()):
|
||||
finalOrder.append(self.listBox.item(i).data(Qt.UserRole))
|
||||
item = self.listBox.item(i)
|
||||
if item.checkState() == Qt.Checked:
|
||||
finalItems.append(item.data(Qt.UserRole))
|
||||
|
||||
if len(finalOrder) == 0:
|
||||
self.mainGui.makeAlert(self.tr(
|
||||
"No source documents found. Nothing to do."
|
||||
), nwAlert.ERROR)
|
||||
return False
|
||||
self._data["moveToTrash"] = self.trashSwitch.isChecked()
|
||||
self._data["finalItems"] = finalItems
|
||||
|
||||
theText = ""
|
||||
for tHandle in finalOrder:
|
||||
inDoc = NWDoc(self.theProject, tHandle)
|
||||
docText = inDoc.readDocument()
|
||||
docErr = inDoc.getError()
|
||||
if docText is None and docErr:
|
||||
self.mainGui.makeAlert([
|
||||
self.tr("Failed to open document file."), docErr
|
||||
], nwAlert.ERROR)
|
||||
if docText:
|
||||
theText += docText.rstrip("\n")+"\n\n"
|
||||
|
||||
if self.sourceItem is None:
|
||||
self.mainGui.makeAlert(self.tr(
|
||||
"No source folder selected. Nothing to do."
|
||||
), nwAlert.ERROR)
|
||||
return False
|
||||
|
||||
srcItem = self.theProject.tree[self.sourceItem]
|
||||
if srcItem is None:
|
||||
self.mainGui.makeAlert(self.tr("Internal error."), nwAlert.ERROR)
|
||||
return False
|
||||
|
||||
nHandle = self.theProject.newFile(srcItem.itemName, srcItem.itemParent)
|
||||
newItem = self.theProject.tree[nHandle]
|
||||
newItem.setStatus(srcItem.itemStatus)
|
||||
newItem.setImport(srcItem.itemImport)
|
||||
|
||||
outDoc = NWDoc(self.theProject, nHandle)
|
||||
if not outDoc.writeDocument(theText):
|
||||
self.mainGui.makeAlert([
|
||||
self.tr("Could not save document."), outDoc.getError()
|
||||
], nwAlert.ERROR)
|
||||
return False
|
||||
|
||||
self.mainGui.projView.revealNewTreeItem(nHandle)
|
||||
self.mainGui.openDocument(nHandle, doScroll=True)
|
||||
|
||||
self._doClose()
|
||||
|
||||
return True
|
||||
|
||||
def _doClose(self):
|
||||
"""Close the dialog window without doing anything.
|
||||
"""
|
||||
self.close()
|
||||
return
|
||||
return self._data
|
||||
|
||||
##
|
||||
# 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.
|
||||
def _loadContent(self, sHandle, itemList):
|
||||
"""Load content from a given list of items.
|
||||
"""
|
||||
tHandle = self.mainGui.projView.getSelectedHandle()
|
||||
self.sourceItem = tHandle
|
||||
if tHandle is None:
|
||||
return False
|
||||
self._data = {}
|
||||
self._data["sHandle"] = sHandle
|
||||
self._data["origItems"] = itemList
|
||||
|
||||
nwItem = self.theProject.tree[tHandle]
|
||||
if nwItem is None:
|
||||
return False
|
||||
|
||||
if nwItem.itemType is not nwItemType.FOLDER:
|
||||
self.mainGui.makeAlert(self.tr(
|
||||
"Element selected in the project tree must be a folder."
|
||||
), nwAlert.ERROR)
|
||||
return False
|
||||
|
||||
for sHandle in self.mainGui.projView.getTreeFromHandle(tHandle):
|
||||
newItem = QListWidgetItem()
|
||||
nwItem = self.theProject.tree[sHandle]
|
||||
if not nwItem.isFileType():
|
||||
self.listBox.clear()
|
||||
for tHandle in itemList:
|
||||
nwItem = self.theProject.tree[tHandle]
|
||||
if nwItem is None or not nwItem.isFileType():
|
||||
continue
|
||||
|
||||
hLevel = self.theProject.index.getHandleHeaderLevel(tHandle)
|
||||
itemIcon = self.mainTheme.getItemIcon(
|
||||
nwItem.itemType, nwItem.itemClass, nwItem.itemLayout, hLevel
|
||||
)
|
||||
|
||||
newItem = QListWidgetItem()
|
||||
newItem.setIcon(itemIcon)
|
||||
newItem.setText(nwItem.itemName)
|
||||
newItem.setData(Qt.UserRole, sHandle)
|
||||
newItem.setData(Qt.UserRole, tHandle)
|
||||
newItem.setCheckState(Qt.Checked)
|
||||
|
||||
self.listBox.addItem(newItem)
|
||||
|
||||
return True
|
||||
return
|
||||
|
||||
# END Class GuiDocMerge
|
||||
|
||||
@@ -202,7 +202,7 @@ class QConfigLayout(QGridLayout):
|
||||
class QHelpLabel(QLabel):
|
||||
|
||||
def __init__(self, theText, textCol, fontSize=0.9):
|
||||
QLabel.__init__(self, theText)
|
||||
super().__init__(theText)
|
||||
|
||||
if isinstance(textCol, QColor):
|
||||
qCol = textCol
|
||||
@@ -377,7 +377,7 @@ class QSwitch(QAbstractButton):
|
||||
class PagedDialog(QDialog):
|
||||
|
||||
def __init__(self, parent=None):
|
||||
QDialog.__init__(self, parent=parent)
|
||||
super().__init__(parent=parent)
|
||||
|
||||
self._tabBar = VerticalTabBar(self)
|
||||
self._tabBar.setExpanding(False)
|
||||
@@ -410,13 +410,13 @@ class PagedDialog(QDialog):
|
||||
return
|
||||
|
||||
def addTab(self, widget, label):
|
||||
"""Forwards the adding of tabs to the QTabWidget.
|
||||
"""Forward the adding of tabs to the QTabWidget.
|
||||
"""
|
||||
self._tabBox.addTab(widget, label)
|
||||
return
|
||||
|
||||
def addControls(self, buttonBar):
|
||||
"""Adds a button bar to the dialog.
|
||||
"""Add a button bar to the dialog.
|
||||
"""
|
||||
self._buttonBox.addWidget(buttonBar)
|
||||
return
|
||||
@@ -427,14 +427,14 @@ class PagedDialog(QDialog):
|
||||
class VerticalTabBar(QTabBar):
|
||||
|
||||
def __init__(self, parent=None):
|
||||
QTabBar.__init__(self, parent=parent)
|
||||
super().__init__(parent=parent)
|
||||
self._mW = novelwriter.CONFIG.pxInt(150)
|
||||
return
|
||||
|
||||
def tabSizeHint(self, index):
|
||||
"""Returns a transposed size hint for the rotated bar.
|
||||
"""Return a transposed size hint for the rotated bar.
|
||||
"""
|
||||
tSize = QTabBar.tabSizeHint(self, index)
|
||||
tSize = super().tabSizeHint(index)
|
||||
tSize.transpose()
|
||||
tSize.setWidth(min(tSize.width(), self._mW))
|
||||
return tSize
|
||||
|
||||
+51
-11
@@ -34,15 +34,15 @@ from time import time
|
||||
from PyQt5.QtGui import QPalette
|
||||
from PyQt5.QtCore import Qt, QSize, pyqtSignal, pyqtSlot
|
||||
from PyQt5.QtWidgets import (
|
||||
QAbstractItemView, QFrame, QHBoxLayout, QHeaderView, QLabel,
|
||||
QAbstractItemView, QFrame, QHBoxLayout, QHeaderView, QLabel, QDialog,
|
||||
QMenu, QShortcut, QSizePolicy, QToolButton, QTreeWidget, QTreeWidgetItem,
|
||||
QVBoxLayout, QWidget
|
||||
)
|
||||
|
||||
from novelwriter.core import NWDoc
|
||||
from novelwriter.enum import nwDocMode, nwItemType, nwItemClass, nwItemLayout, nwAlert
|
||||
from novelwriter.dialogs import GuiDocMerge, GuiEditLabel
|
||||
from novelwriter.constants import nwHeaders, trConst, nwLabels
|
||||
from novelwriter.dialogs.editlabel import GuiEditLabel
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -334,7 +334,7 @@ class GuiProjectTree(QTreeWidget):
|
||||
self.mainConf = novelwriter.CONFIG
|
||||
self.projView = projView
|
||||
self.mainGui = projView.mainGui
|
||||
self.mainTheme = projView.mainGui.mainTheme
|
||||
self.mainTheme = projView.mainGui.mainTheme
|
||||
self.theProject = projView.mainGui.theProject
|
||||
|
||||
# Internal Variables
|
||||
@@ -382,9 +382,8 @@ class GuiProjectTree(QTreeWidget):
|
||||
trRoot = self.invisibleRootItem()
|
||||
trRoot.setFlags(trRoot.flags() ^ Qt.ItemIsDropEnabled)
|
||||
|
||||
# Set Multiple Selection by CTRL
|
||||
# Disabled for now, until the merge files option has been added
|
||||
# self.setSelectionMode(QAbstractItemView.ExtendedSelection)
|
||||
# Set selection options
|
||||
self.setSelectionMode(QAbstractItemView.SingleSelection)
|
||||
self.setSelectionBehavior(QAbstractItemView.SelectRows)
|
||||
|
||||
# Connect signals
|
||||
@@ -1077,16 +1076,21 @@ class GuiProjectTree(QTreeWidget):
|
||||
lambda n, key=key: self._changeItemImport(tHandle, key)
|
||||
)
|
||||
|
||||
# Transform Item
|
||||
# ==============
|
||||
|
||||
mTrans = ctxMenu.addMenu(self.tr("Transform"))
|
||||
|
||||
if isFile and tItem.documentAllowed():
|
||||
if tItem.isNoteLayout():
|
||||
ctxMenu.addAction(
|
||||
mTrans.addAction(
|
||||
self.tr("Convert to {0}").format(
|
||||
trConst(nwLabels.LAYOUT_NAME[nwItemLayout.DOCUMENT])
|
||||
),
|
||||
lambda: self._changeItemLayout(tHandle, nwItemLayout.DOCUMENT)
|
||||
)
|
||||
else:
|
||||
ctxMenu.addAction(
|
||||
mTrans.addAction(
|
||||
self.tr("Convert to {0}").format(
|
||||
trConst(nwLabels.LAYOUT_NAME[nwItemLayout.NOTE])
|
||||
),
|
||||
@@ -1094,19 +1098,37 @@ class GuiProjectTree(QTreeWidget):
|
||||
)
|
||||
elif isFolder:
|
||||
if tItem.documentAllowed():
|
||||
ctxMenu.addAction(
|
||||
mTrans.addAction(
|
||||
self.tr("Convert to {0}").format(
|
||||
trConst(nwLabels.LAYOUT_NAME[nwItemLayout.DOCUMENT])
|
||||
),
|
||||
lambda: self._covertFolderToFile(tHandle, nwItemLayout.DOCUMENT)
|
||||
)
|
||||
ctxMenu.addAction(
|
||||
mTrans.addAction(
|
||||
self.tr("Convert to {0}").format(
|
||||
trConst(nwLabels.LAYOUT_NAME[nwItemLayout.NOTE])
|
||||
),
|
||||
lambda: self._covertFolderToFile(tHandle, nwItemLayout.NOTE)
|
||||
)
|
||||
|
||||
if hasChild:
|
||||
if isFile:
|
||||
mTrans.addAction(
|
||||
self.tr("Merge Child Documents"),
|
||||
lambda: self._mergeDocuments(tHandle, isFile)
|
||||
)
|
||||
else:
|
||||
mTrans.addAction(
|
||||
self.tr("Combine Documents in Folder"),
|
||||
lambda: self._mergeDocuments(tHandle, isFile)
|
||||
)
|
||||
|
||||
if isFile:
|
||||
mTrans.addAction(
|
||||
self.tr("Split Document by Header"),
|
||||
lambda: self._splitDocument(tHandle)
|
||||
)
|
||||
|
||||
ctxMenu.addSeparator()
|
||||
|
||||
# Expand/Collapse
|
||||
@@ -1355,6 +1377,24 @@ class GuiProjectTree(QTreeWidget):
|
||||
logger.info("Folder conversion cancelled")
|
||||
return
|
||||
|
||||
def _mergeDocuments(self, tHandle, isFile):
|
||||
"""Merge an item's child documents into a single document.
|
||||
"""
|
||||
logger.info("Request to merge items under handle '%s'", tHandle)
|
||||
itemList = self.getTreeFromHandle(tHandle)
|
||||
itemList.remove(tHandle)
|
||||
|
||||
dlgMerge = GuiDocMerge(self.mainGui, tHandle, itemList)
|
||||
dlgMerge.exec_()
|
||||
|
||||
if dlgMerge.result() == QDialog.Accepted:
|
||||
print(dlgMerge.getData())
|
||||
|
||||
return
|
||||
|
||||
def _splitDocument(self, tHandle):
|
||||
return
|
||||
|
||||
def _scanChildren(self, theList, tItem, tIndex):
|
||||
"""This is a recursive function returning all items in a tree
|
||||
starting at a given QTreeWidgetItem.
|
||||
@@ -1380,7 +1420,7 @@ class GuiProjectTree(QTreeWidget):
|
||||
"""
|
||||
tHandle = nwItem.itemHandle
|
||||
pHandle = nwItem.itemParent
|
||||
newItem = QTreeWidgetItem([""]*4)
|
||||
newItem = QTreeWidgetItem()
|
||||
|
||||
newItem.setText(self.C_NAME, "")
|
||||
newItem.setText(self.C_COUNT, "0")
|
||||
|
||||
Reference in New Issue
Block a user