Add a way to delete entries in the recent projects list
This commit is contained in:
@@ -652,12 +652,12 @@ class Config:
|
|||||||
}
|
}
|
||||||
|
|
||||||
conf["Sizes"] = {
|
conf["Sizes"] = {
|
||||||
"mainwindow": self._packList(self._mainWinSize),
|
"mainwindow": self._packList(self._mainWinSize),
|
||||||
"welcome": self._packList(self._welcomeSize),
|
"welcome": self._packList(self._welcomeSize),
|
||||||
"preferences": self._packList(self._prefsWinSize),
|
"preferences": self._packList(self._prefsWinSize),
|
||||||
"mainpane": self._packList(self._mainPanePos),
|
"mainpane": self._packList(self._mainPanePos),
|
||||||
"viewpane": self._packList(self._viewPanePos),
|
"viewpane": self._packList(self._viewPanePos),
|
||||||
"outlinepane": self._packList(self._outlnPanePos),
|
"outlinepane": self._packList(self._outlnPanePos),
|
||||||
}
|
}
|
||||||
|
|
||||||
conf["Project"] = {
|
conf["Project"] = {
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ from PyQt5.QtCore import (
|
|||||||
)
|
)
|
||||||
from PyQt5.QtWidgets import (
|
from PyQt5.QtWidgets import (
|
||||||
QComboBox, QDialog, QDialogButtonBox, QFileDialog, QFormLayout,
|
QComboBox, QDialog, QDialogButtonBox, QFileDialog, QFormLayout,
|
||||||
QHBoxLayout, QLabel, QLineEdit, QListView, QMenu, QPushButton, QScrollArea,
|
QHBoxLayout, QLabel, QLineEdit, QListView, QMenu, QPushButton, QScrollArea, QShortcut,
|
||||||
QSpinBox, QStackedWidget, QStyle, QStyleOptionViewItem, QStyledItemDelegate,
|
QSpinBox, QStackedWidget, QStyle, QStyleOptionViewItem, QStyledItemDelegate,
|
||||||
QToolButton, QVBoxLayout, QWidget, qApp
|
QToolButton, QVBoxLayout, QWidget, qApp
|
||||||
)
|
)
|
||||||
@@ -76,6 +76,9 @@ class GuiWelcome(QDialog):
|
|||||||
|
|
||||||
self.resize(*CONFIG.welcomeWinSize)
|
self.resize(*CONFIG.welcomeWinSize)
|
||||||
|
|
||||||
|
# Elements
|
||||||
|
# ========
|
||||||
|
|
||||||
self.bgImage = SHARED.theme.loadDecoration("welcome")
|
self.bgImage = SHARED.theme.loadDecoration("welcome")
|
||||||
self.nwImage = SHARED.theme.loadDecoration("nw-text", h=hD)
|
self.nwImage = SHARED.theme.loadDecoration("nw-text", h=hD)
|
||||||
|
|
||||||
@@ -102,8 +105,9 @@ class GuiWelcome(QDialog):
|
|||||||
|
|
||||||
# Buttons
|
# Buttons
|
||||||
# =======
|
# =======
|
||||||
|
|
||||||
self.btnBox = QDialogButtonBox(QDialogButtonBox.Open | QDialogButtonBox.Cancel, self)
|
self.btnBox = QDialogButtonBox(QDialogButtonBox.Open | QDialogButtonBox.Cancel, self)
|
||||||
self.btnBox.accepted.connect(self._openSelectedProject)
|
self.btnBox.accepted.connect(self.tabOpen.openSelectedItem)
|
||||||
self.btnBox.rejected.connect(self.close)
|
self.btnBox.rejected.connect(self.close)
|
||||||
|
|
||||||
self.newButton = self.btnBox.addButton(self.tr("New Project"), QDialogButtonBox.ActionRole)
|
self.newButton = self.btnBox.addButton(self.tr("New Project"), QDialogButtonBox.ActionRole)
|
||||||
@@ -116,6 +120,7 @@ class GuiWelcome(QDialog):
|
|||||||
|
|
||||||
# Assemble
|
# Assemble
|
||||||
# ========
|
# ========
|
||||||
|
|
||||||
self.innerBox = QVBoxLayout()
|
self.innerBox = QVBoxLayout()
|
||||||
self.innerBox.addSpacing(hB)
|
self.innerBox.addSpacing(hB)
|
||||||
self.innerBox.addWidget(self.nwLabel)
|
self.innerBox.addWidget(self.nwLabel)
|
||||||
@@ -187,13 +192,6 @@ class GuiWelcome(QDialog):
|
|||||||
self._openProjectPath(path)
|
self._openProjectPath(path)
|
||||||
return
|
return
|
||||||
|
|
||||||
@pyqtSlot()
|
|
||||||
def _openSelectedProject(self) -> None:
|
|
||||||
"""Open the selected project."""
|
|
||||||
if selected := self.tabOpen.listWidget.selectedIndexes():
|
|
||||||
self._openProjectPath(Path(str(selected[0].data()[1])))
|
|
||||||
return
|
|
||||||
|
|
||||||
@pyqtSlot(Path)
|
@pyqtSlot(Path)
|
||||||
def _openProjectPath(self, path: Path) -> None:
|
def _openProjectPath(self, path: Path) -> None:
|
||||||
"""Emit a project open signal."""
|
"""Emit a project open signal."""
|
||||||
@@ -225,19 +223,28 @@ class _OpenProjectPage(QWidget):
|
|||||||
hPx = CONFIG.pxInt(6)
|
hPx = CONFIG.pxInt(6)
|
||||||
vPx = CONFIG.pxInt(4)
|
vPx = CONFIG.pxInt(4)
|
||||||
|
|
||||||
|
# List View
|
||||||
self.listModel = _ProjectListModel(self)
|
self.listModel = _ProjectListModel(self)
|
||||||
self.itemDelegate = _ProjectListItem(self)
|
self.itemDelegate = _ProjectListItem(self)
|
||||||
|
|
||||||
self.listWidget = QListView(self)
|
self.listWidget = QListView(self)
|
||||||
self.listWidget.setItemDelegate(self.itemDelegate)
|
self.listWidget.setItemDelegate(self.itemDelegate)
|
||||||
self.listWidget.setModel(self.listModel)
|
self.listWidget.setModel(self.listModel)
|
||||||
|
self.listWidget.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu)
|
||||||
self.listWidget.clicked.connect(self._projectClicked)
|
self.listWidget.clicked.connect(self._projectClicked)
|
||||||
self.listWidget.doubleClicked.connect(self._projectDoubleClicked)
|
self.listWidget.doubleClicked.connect(self._projectDoubleClicked)
|
||||||
|
self.listWidget.customContextMenuRequested.connect(self._openContextMenu)
|
||||||
|
|
||||||
|
# Info / Tool
|
||||||
self.selectedPath = QLineEdit(self)
|
self.selectedPath = QLineEdit(self)
|
||||||
self.selectedPath.setContentsMargins(hPx, vPx, hPx, vPx)
|
self.selectedPath.setContentsMargins(hPx, vPx, hPx, vPx)
|
||||||
self.selectedPath.setReadOnly(True)
|
self.selectedPath.setReadOnly(True)
|
||||||
|
|
||||||
|
self.keyDelete = QShortcut(self)
|
||||||
|
self.keyDelete.setKey(Qt.Key.Key_Delete)
|
||||||
|
self.keyDelete.activated.connect(self._deleteSelectedItem)
|
||||||
|
|
||||||
|
# Assemble
|
||||||
self.outerBox = QVBoxLayout()
|
self.outerBox = QVBoxLayout()
|
||||||
self.outerBox.addWidget(self.listWidget)
|
self.outerBox.addWidget(self.listWidget)
|
||||||
self.outerBox.addWidget(self.selectedPath)
|
self.outerBox.addWidget(self.selectedPath)
|
||||||
@@ -256,6 +263,17 @@ class _OpenProjectPage(QWidget):
|
|||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
|
##
|
||||||
|
# Public Slots
|
||||||
|
##
|
||||||
|
|
||||||
|
@pyqtSlot()
|
||||||
|
def openSelectedItem(self) -> None:
|
||||||
|
"""Open the currently selected project item."""
|
||||||
|
if (selection := self.listWidget.selectedIndexes()) and (index := selection[0]).isValid():
|
||||||
|
self.openProjectRequest.emit(Path(str(index.data()[1])))
|
||||||
|
return
|
||||||
|
|
||||||
##
|
##
|
||||||
# Private Slots
|
# Private Slots
|
||||||
##
|
##
|
||||||
@@ -275,6 +293,30 @@ class _OpenProjectPage(QWidget):
|
|||||||
self.openProjectRequest.emit(Path(str(index.data()[1])))
|
self.openProjectRequest.emit(Path(str(index.data()[1])))
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@pyqtSlot()
|
||||||
|
def _deleteSelectedItem(self) -> None:
|
||||||
|
"""Delete the currently selected project item."""
|
||||||
|
if (selection := self.listWidget.selectedIndexes()) and (index := selection[0]).isValid():
|
||||||
|
text = self.tr(
|
||||||
|
"Remove '{0}' from the recent projects list? "
|
||||||
|
"The project files will not be deleted."
|
||||||
|
).format(index.data()[0])
|
||||||
|
if SHARED.question(text):
|
||||||
|
self.listModel.removeEntry(index)
|
||||||
|
return
|
||||||
|
|
||||||
|
@pyqtSlot("QPoint")
|
||||||
|
def _openContextMenu(self, pos: QPoint) -> None:
|
||||||
|
"""Open the custom context menu."""
|
||||||
|
ctxMenu = QMenu(self)
|
||||||
|
action = ctxMenu.addAction(self.tr("Open Project"))
|
||||||
|
action.triggered.connect(self.openSelectedItem)
|
||||||
|
action = ctxMenu.addAction(self.tr("Remove Project"))
|
||||||
|
action.triggered.connect(self._deleteSelectedItem)
|
||||||
|
ctxMenu.exec_(self.mapToGlobal(pos))
|
||||||
|
ctxMenu.deleteLater()
|
||||||
|
return
|
||||||
|
|
||||||
# END Class _OpenProjectPage
|
# END Class _OpenProjectPage
|
||||||
|
|
||||||
|
|
||||||
@@ -358,6 +400,19 @@ class _ProjectListModel(QAbstractListModel):
|
|||||||
"""Return data for an individual item."""
|
"""Return data for an individual item."""
|
||||||
return self._data[index.row()] if index.isValid() else ("", "", "")
|
return self._data[index.row()] if index.isValid() else ("", "", "")
|
||||||
|
|
||||||
|
def removeEntry(self, index: QModelIndex) -> bool:
|
||||||
|
"""Remove an entry in the model."""
|
||||||
|
if index.isValid() and (path := index.data()[1]):
|
||||||
|
try:
|
||||||
|
self.beginRemoveRows(index.parent(), index.row(), index.row())
|
||||||
|
self._data.pop(index.row())
|
||||||
|
self.endRemoveRows()
|
||||||
|
except IndexError:
|
||||||
|
return False
|
||||||
|
CONFIG.recentProjects.remove(path)
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
# END Class _ProjectListModel
|
# END Class _ProjectListModel
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user