""" novelWriter – GUI Doc Merge Dialog ================================== File History: Created: 2020-01-23 [0.4.3] GuiDocMerge Rewritten: 2022-10-06 [2.0rc1] GuiDocMerge This file is a part of novelWriter Copyright (C) 2020 Veronica Berglyd Olsen and novelWriter contributors 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 . """ from __future__ import annotations import logging from PyQt6.QtCore import Qt, pyqtSlot from PyQt6.QtWidgets import ( QAbstractItemView, QDialogButtonBox, QGridLayout, QLabel, QListWidget, QListWidgetItem, QVBoxLayout, QWidget ) from novelwriter import SHARED from novelwriter.extensions.configlayout import NColourLabel from novelwriter.extensions.modified import NDialog from novelwriter.extensions.switch import NSwitch from novelwriter.types import QtAccepted, QtDialogCancel, QtDialogOk, QtDialogReset, QtUserRole logger = logging.getLogger(__name__) class GuiDocMerge(NDialog): D_HANDLE = QtUserRole def __init__(self, parent: QWidget, sHandle: str, itemList: list[str]) -> None: super().__init__(parent=parent) logger.debug("Create: GuiDocMerge") self.setObjectName("GuiDocMerge") self.setWindowTitle(self.tr("Merge Documents")) self._data = {} self.headLabel = QLabel(self.tr("Documents to Merge"), self) self.headLabel.setFont(SHARED.theme.guiFontB) self.helpLabel = NColourLabel( self.tr("Drag and drop items to change the order, or uncheck to exclude."), self, color=SHARED.theme.helpText, wrap=True ) iPx = SHARED.theme.baseIconHeight iSz = SHARED.theme.baseIconSize self.listBox = QListWidget(self) self.listBox.setIconSize(iSz) self.listBox.setMinimumWidth(400) self.listBox.setMinimumHeight(180) self.listBox.setSelectionBehavior(QAbstractItemView.SelectionBehavior.SelectRows) self.listBox.setSelectionMode(QAbstractItemView.SelectionMode.SingleSelection) self.listBox.setDragDropMode(QAbstractItemView.DragDropMode.InternalMove) # Merge Options self.trashLabel = QLabel(self.tr("Move merged items to Trash"), self) self.trashSwitch = NSwitch(self, height=iPx) self.optBox = QGridLayout() self.optBox.addWidget(self.trashLabel, 0, 0) self.optBox.addWidget(self.trashSwitch, 0, 1) self.optBox.setHorizontalSpacing(12) self.optBox.setColumnStretch(2, 1) # Buttons self.buttonBox = QDialogButtonBox(QtDialogOk | QtDialogCancel, self) self.buttonBox.accepted.connect(self.accept) self.buttonBox.rejected.connect(self.reject) self.resetButton = self.buttonBox.addButton(QtDialogReset) if self.resetButton: self.resetButton.clicked.connect(self._resetList) # Assemble self.outerBox = QVBoxLayout() self.outerBox.setSpacing(0) self.outerBox.addWidget(self.headLabel) self.outerBox.addWidget(self.helpLabel) self.outerBox.addSpacing(8) self.outerBox.addWidget(self.listBox) self.outerBox.addSpacing(8) self.outerBox.addLayout(self.optBox) self.outerBox.addSpacing(12) self.outerBox.addWidget(self.buttonBox) self.setLayout(self.outerBox) # Load Content self._loadContent(sHandle, itemList) logger.debug("Ready: GuiDocMerge") return def __del__(self) -> None: # pragma: no cover logger.debug("Delete: GuiDocMerge") return def data(self) -> dict: """Return the user's choices.""" finalItems = [] for i in range(self.listBox.count()): item = self.listBox.item(i) if item is not None and item.checkState() == Qt.CheckState.Checked: finalItems.append(item.data(self.D_HANDLE)) self._data["moveToTrash"] = self.trashSwitch.isChecked() self._data["finalItems"] = finalItems return self._data @classmethod def getData(cls, parent: QWidget, handle: str, items: list[str]) -> tuple[dict, bool]: """Pop the dialog and return the result.""" cls = GuiDocMerge(parent, handle, items) cls.exec() data = cls.data() accepted = cls.result() == QtAccepted cls.softDelete() return data, accepted ## # Private Slots ## @pyqtSlot() def _resetList(self) -> None: """Reset the content of the list box to its original state.""" logger.debug("Resetting list box content") sHandle = self._data.get("sHandle", None) itemList = self._data.get("origItems", []) self._loadContent(sHandle, itemList) return ## # Internal Functions ## def _loadContent(self, sHandle: str, itemList: list[str]) -> None: """Load content from a given list of items.""" self._data = {} self._data["sHandle"] = sHandle self._data["origItems"] = itemList self.listBox.clear() for tHandle in itemList: if (nwItem := SHARED.project.tree[tHandle]) and nwItem.isFileType(): item = QListWidgetItem() item.setIcon(nwItem.getMainIcon()) item.setText(nwItem.itemName) item.setData(self.D_HANDLE, tHandle) item.setCheckState(Qt.CheckState.Checked) self.listBox.addItem(item) return