From 23e094d850ba875fee0de4a8b2a70e1c846aae4f Mon Sep 17 00:00:00 2001 From: GriffinR Date: Tue, 29 Oct 2024 22:18:16 -0400 Subject: [PATCH] Update map list delete functionality --- include/mainwindow.h | 4 +- include/ui/maplistmodels.h | 18 ++-- include/ui/newmappopup.h | 2 +- src/mainwindow.cpp | 163 ++++++++++++------------------------- src/project.cpp | 8 +- src/ui/maplistmodels.cpp | 56 +++++++++++-- src/ui/newmappopup.cpp | 8 +- 7 files changed, 127 insertions(+), 132 deletions(-) diff --git a/include/mainwindow.h b/include/mainwindow.h index 160c138a..ea1c62de 100644 --- a/include/mainwindow.h +++ b/include/mainwindow.h @@ -383,9 +383,6 @@ private: void mapListAddGroup(); void mapListAddLayout(); void mapListAddArea(); - void mapListRemoveGroup(); - void mapListRemoveArea(); - void mapListRemoveLayout(); void openMapListItem(const QModelIndex &index); void saveMapListTab(int index); @@ -424,6 +421,7 @@ private: void redrawMetatileSelection(); void scrollMetatileSelectorToSelection(); MapListToolBar* getCurrentMapListToolBar(); + MapTree* getCurrentMapList(); QObjectList shortcutableObjects() const; void addCustomHeaderValue(QString key, QJsonValue value, bool isNew = false); diff --git a/include/ui/maplistmodels.h b/include/ui/maplistmodels.h index 8d00c492..fbcd9710 100644 --- a/include/ui/maplistmodels.h +++ b/include/ui/maplistmodels.h @@ -26,8 +26,12 @@ public: MapTree(QWidget *parent) : QTreeView(parent) { this->setDropIndicatorShown(true); this->setFont(QFontDatabase::systemFont(QFontDatabase::FixedFont)); + this->setFocusPolicy(Qt::StrongFocus); } +protected: + virtual void keyPressEvent(QKeyEvent *event) override; + public slots: void removeSelected(); }; @@ -61,6 +65,9 @@ public: ~MapListModel() { } virtual QModelIndex indexOf(QString id) const = 0; + virtual void removeFolder(int index) = 0; + virtual void removeItem(const QModelIndex &index); + virtual QStandardItem *getItem(const QModelIndex &index) const = 0; }; class MapGroupModel : public MapListModel { @@ -87,9 +94,9 @@ public: QStandardItem *insertGroupItem(QString groupName); QStandardItem *insertMapItem(QString mapName, QString groupName); - void removeGroup(int groupIndex); + virtual void removeFolder(int index) override; - QStandardItem *getItem(const QModelIndex &index) const; + virtual QStandardItem *getItem(const QModelIndex &index) const override; virtual QModelIndex indexOf(QString mapName) const override; void initialize(); @@ -130,9 +137,9 @@ public: QStandardItem *insertAreaItem(QString areaName); QStandardItem *insertMapItem(QString mapName, QString areaName, int groupIndex); - void removeArea(int groupIndex); + virtual void removeFolder(int index) override; - QStandardItem *getItem(const QModelIndex &index) const; + virtual QStandardItem *getItem(const QModelIndex &index) const override; virtual QModelIndex indexOf(QString mapName) const override; void initialize(); @@ -170,8 +177,9 @@ public: QStandardItem *insertLayoutItem(QString layoutId); QStandardItem *insertMapItem(QString mapName, QString layoutId); + virtual void removeFolder(int index) override; - QStandardItem *getItem(const QModelIndex &index) const; + virtual QStandardItem *getItem(const QModelIndex &index) const override; virtual QModelIndex indexOf(QString layoutName) const override; void initialize(); diff --git a/include/ui/newmappopup.h b/include/ui/newmappopup.h index 66a15a91..f160876a 100644 --- a/include/ui/newmappopup.h +++ b/include/ui/newmappopup.h @@ -24,7 +24,7 @@ public: QString layoutId; void init(); void initUi(); - void init(int tabIndex, QVariant data); + void init(int tabIndex, QString data); void init(Layout *); static void setDefaultSettings(Project *project); diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 9bac433a..df62341a 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -153,10 +153,11 @@ void MainWindow::initExtraShortcuts() { shortcutDuplicate_Events->setObjectName("shortcutDuplicate_Events"); shortcutDuplicate_Events->setWhatsThis("Duplicate Selected Event(s)"); - auto *shortcutDelete_Object = new Shortcut( + // TODO: Reimplement this using keyPressEvent on the relevant widgets. Otherwise it steals the key event from anything else trying to use delete. + /*auto *shortcutDelete_Object = new Shortcut( {QKeySequence("Del"), QKeySequence("Backspace")}, this, SLOT(onDeleteKeyPressed())); shortcutDelete_Object->setObjectName("shortcutDelete_Object"); - shortcutDelete_Object->setWhatsThis("Delete Selected Item(s)"); + shortcutDelete_Object->setWhatsThis("Delete Selected Item(s)");*/ auto *shortcutToggle_Border = new Shortcut(QKeySequence(), ui->checkBox_ToggleBorder, SLOT(toggle())); shortcutToggle_Border->setObjectName("shortcutToggle_Border"); @@ -874,11 +875,6 @@ bool MainWindow::setMap(QString map_name) { return false; } - // TODO: Redundant? - if (editor->map && !editor->map->name.isNull()) { - ui->mapList->setExpanded(groupListProxyModel->mapFromSource(mapGroupModel->indexOf(map_name)), false); - } - setLayoutOnlyMode(false); this->lastSelectedEvent.clear(); @@ -1301,11 +1297,7 @@ void MainWindow::scrollMapList(MapTree *list, QString itemName) { if (!list || itemName.isEmpty()) return; auto model = static_cast(list->model()); - if (!model) - return; auto sourceModel = static_cast(model->sourceModel()); - if (!sourceModel) - return; QModelIndex sourceIndex = sourceModel->indexOf(itemName); if (!sourceIndex.isValid()) return; @@ -1332,66 +1324,53 @@ void MainWindow::scrollMapListToCurrentLayout(MapTree *list) { } void MainWindow::onOpenMapListContextMenu(const QPoint &point) { - QStandardItemModel *model; - int dataRole; - FilterChildrenProxyModel *proxy; - QTreeView *list; - QString actionText; - - int currentTab = ui->mapListContainer->currentIndex(); - - switch (currentTab) { - case MapListTab::Groups: - model = this->mapGroupModel; - dataRole = MapListUserRoles::GroupRole; - proxy = this->groupListProxyModel; - list = this->ui->mapList; - actionText = "Add New Map to Group"; - break; - case MapListTab::Areas: - model = this->mapAreaModel; - dataRole = Qt::UserRole; - proxy = this->areaListProxyModel; - list = this->ui->areaList; - actionText = "Add New Map to Area"; - break; - case MapListTab::Layouts: - model = this->layoutTreeModel; - dataRole = Qt::UserRole; - proxy = this->layoutListProxyModel; - list = this->ui->layoutList; - actionText = "Add New Map with Layout"; - break; - } - - QModelIndex index = proxy->mapToSource(list->indexAt(point)); - if (!index.isValid()) { - return; - } - - QStandardItem *selectedItem = model->itemFromIndex(index); - - if (selectedItem->parent()) { - // TODO: Right-click delete on maps? - return; - } - - QVariant itemData = selectedItem->data(dataRole); - if (!itemData.isValid()) { - return; - } + // Get selected item from list + auto list = getCurrentMapList(); + if (!list) return; + auto model = static_cast(list->model()); + QModelIndex index = model->mapToSource(list->indexAt(point)); + if (!index.isValid()) return; + auto sourceModel = static_cast(model->sourceModel()); + QStandardItem *selectedItem = sourceModel->itemFromIndex(index); + const QString itemType = selectedItem->data(MapListUserRoles::TypeRole).toString(); + const QString itemName = selectedItem->data(Qt::UserRole).toString(); QMenu menu(this); - QActionGroup actions(&menu); - actions.addAction(menu.addAction(actionText))->setData(itemData); + QAction* addToFolderAction = nullptr; + QAction* deleteFolderAction = nullptr; + if (itemType == "map_name") { + // Right-clicking on a map. + // TODO: Add action to delete map once deleting maps is supported + } else if (itemType == "map_group") { + // Right-clicking on a map group folder + addToFolderAction = menu.addAction("Add New Map to Group"); + deleteFolderAction = menu.addAction("Delete Map Group"); + } else if (itemType == "map_section") { + // Right-clicking on an MAPSEC folder + addToFolderAction = menu.addAction("Add New Map to Area"); + } else if (itemType == "map_layout") { + // Right-clicking on a map layout + addToFolderAction = menu.addAction("Add New Map with Layout"); + } - auto triggeredAction = menu.exec(QCursor::pos()); - if (!triggeredAction) - return; + if (addToFolderAction) { + connect(addToFolderAction, &QAction::triggered, [this, itemName] { + openNewMapPopupWindow(); + this->newMapPrompt->init(ui->mapListContainer->currentIndex(), itemName); + }); + } + if (deleteFolderAction) { + connect(deleteFolderAction, &QAction::triggered, [sourceModel, index] { + sourceModel->removeFolder(index.row()); + }); + if (selectedItem->hasChildren()){ + // TODO: No support for deleting maps, so you may only delete folders if they don't contain any maps. + deleteFolderAction->setEnabled(false); + } + } - // At the moment all the actions do the same thing (add new map/layout). - openNewMapPopupWindow(); - this->newMapPrompt->init(currentTab, triggeredAction->data()); + if (menu.actions().length() != 0) + menu.exec(QCursor::pos()); } void MainWindow::mapListAddGroup() { @@ -1589,49 +1568,6 @@ void MainWindow::mapListAddArea() { } } -// TODO: Connect to right-click on map group folder in list -void MainWindow::mapListRemoveGroup() { - QItemSelectionModel *selectionModel = this->ui->mapList->selectionModel(); - if (selectionModel->hasSelection()) { - QModelIndexList selectedIndexes = selectionModel->selectedRows(); - for (QModelIndex proxyIndex : selectedIndexes) { - QModelIndex index = this->groupListProxyModel->mapToSource(proxyIndex); - QStandardItem *item = this->mapGroupModel->getItem(index)->child(index.row(), index.column()); - if (!item) continue; - QString type = item->data(MapListUserRoles::TypeRole).toString(); - if (type == "map_group" && !item->hasChildren()) { - QString groupName = item->data(Qt::UserRole).toString(); - // delete empty group - this->mapGroupModel->removeGroup(index.row()); - } - } - } -} - -// TODO: Decide what to do about this. Currently unused. -void MainWindow::mapListRemoveArea() { - QItemSelectionModel *selectionModel = this->ui->areaList->selectionModel(); - if (selectionModel->hasSelection()) { - QModelIndexList selectedIndexes = selectionModel->selectedRows(); - for (QModelIndex proxyIndex : selectedIndexes) { - QModelIndex index = this->areaListProxyModel->mapToSource(proxyIndex); - QStandardItem *item = this->mapAreaModel->getItem(index)->child(index.row(), index.column()); - if (!item) continue; - QString type = item->data(MapListUserRoles::TypeRole).toString(); - if (type == "map_section" && !item->hasChildren()) { - QString groupName = item->data(Qt::UserRole).toString(); - // delete empty section - this->mapAreaModel->removeArea(index.row()); - } - } - } -} - -// TODO: Connect to right-click on layout -void MainWindow::mapListRemoveLayout() { - // TODO: consider this in the future -} - void MainWindow::onNewMapCreated() { QString newMapName = this->newMapPrompt->map->name; int newMapGroup = this->newMapPrompt->group; @@ -3186,6 +3122,13 @@ MapListToolBar* MainWindow::getCurrentMapListToolBar() { } } +MapTree* MainWindow::getCurrentMapList() { + auto toolbar = getCurrentMapListToolBar(); + if (toolbar) + return toolbar->list(); + return nullptr; +} + // Clear the search filters on all the map lists. // When the search filter is cleared the map lists will (if possible) display the currently-selected map/layout. void MainWindow::resetMapListFilters() { diff --git a/src/project.cpp b/src/project.cpp index e7a9beeb..657bd89c 100644 --- a/src/project.cpp +++ b/src/project.cpp @@ -3001,15 +3001,15 @@ bool Project::hasUnsavedChanges() { // Check layouts for unsaved changes for (auto i = this->mapLayouts.constBegin(); i != this->mapLayouts.constEnd(); i++) { - auto map = i.value(); - if (map && map->hasUnsavedChanges()) + auto layout = i.value(); + if (layout && layout->hasUnsavedChanges()) return true; } // Check loaded maps for unsaved changes for (auto i = this->mapCache.constBegin(); i != this->mapCache.constEnd(); i++) { - auto layout = i.value(); - if (layout && layout->hasUnsavedChanges()) + auto map = i.value(); + if (map && map->hasUnsavedChanges()) return true; } return false; diff --git a/src/ui/maplistmodels.cpp b/src/ui/maplistmodels.cpp index 46297892..af8149d8 100644 --- a/src/ui/maplistmodels.cpp +++ b/src/ui/maplistmodels.cpp @@ -15,6 +15,45 @@ void MapTree::removeSelected() { } } +void MapTree::keyPressEvent(QKeyEvent *event) { + if (event->key() == Qt::Key_Delete || event->key() == Qt::Key_Backspace) { + // Delete selected items in the tree + auto selectionModel = this->selectionModel(); + if (!selectionModel->hasSelection()) + return; + + auto model = static_cast(this->model()); + auto sourceModel = static_cast(model->sourceModel()); + + QModelIndexList selectedIndexes = selectionModel->selectedRows(); + QList persistentIndexes; + for (const auto &index : selectedIndexes) { + persistentIndexes.append(model->mapToSource(index)); + } + for (const auto &index : persistentIndexes) { + sourceModel->removeItem(index); + } + } else { + QWidget::keyPressEvent(event); + } +} + +void MapListModel::removeItem(const QModelIndex &index) { + QStandardItem *item = this->getItem(index)->child(index.row(), index.column()); + if (!item) + return; + + const QString type = item->data(MapListUserRoles::TypeRole).toString(); + if (type == "map_name") { + // TODO: No support for deleting maps + } else { + // TODO: Because there's no support for deleting maps we can only delete empty folders + if (!item->hasChildren()) { + this->removeFolder(index.row()); + } + } +} + QWidget *GroupNameDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &, const QModelIndex &) const { @@ -244,8 +283,8 @@ QStandardItem *MapGroupModel::insertGroupItem(QString groupName) { return group; } -void MapGroupModel::removeGroup(int groupIndex) { - this->removeRow(groupIndex); +void MapGroupModel::removeFolder(int index) { + this->removeRow(index); this->updateProject(); } @@ -365,6 +404,8 @@ bool MapGroupModel::setData(const QModelIndex &index, const QVariant &value, int } } +// TODO: Deleting MAPSEC support? Currently it has no limits on drag/drop etc, so editing is disabled (so delete key from the map list is ignored) +// and it has no delete action in the context menu. MapAreaModel::MapAreaModel(Project *project, QObject *parent) : MapListModel(parent) { @@ -422,9 +463,9 @@ QStandardItem *MapAreaModel::insertMapItem(QString mapName, QString areaName, in return map; } -void MapAreaModel::removeArea(int areaIndex) { - this->removeRow(areaIndex); - this->project->mapSectionNameToValue.remove(this->project->mapSectionValueToName.take(areaIndex)); +void MapAreaModel::removeFolder(int index) { + this->removeRow(index); + this->project->mapSectionNameToValue.remove(this->project->mapSectionValueToName.take(index)); } void MapAreaModel::initialize() { @@ -583,6 +624,11 @@ QStandardItem *LayoutTreeModel::insertMapItem(QString mapName, QString layoutId) return map; } +void LayoutTreeModel::removeFolder(int) { + // TODO: Deleting layouts not supported +} + + void LayoutTreeModel::initialize() { this->layoutItems.clear(); this->mapItems.clear(); diff --git a/src/ui/newmappopup.cpp b/src/ui/newmappopup.cpp index a9d661da..a9e50c93 100644 --- a/src/ui/newmappopup.cpp +++ b/src/ui/newmappopup.cpp @@ -102,19 +102,19 @@ void NewMapPopup::init() { } // Creating new map by right-clicking in the map list -void NewMapPopup::init(int tabIndex, QVariant data) { +void NewMapPopup::init(int tabIndex, QString fieldName) { initUi(); switch (tabIndex) { case MapListTab::Groups: - settings.group = project->groupNames.at(data.toInt()); + settings.group = fieldName; break; case MapListTab::Areas: - settings.location = data.toString(); + settings.location = fieldName; break; case MapListTab::Layouts: this->ui->checkBox_UseExistingLayout->setCheckState(Qt::Checked); - useLayout(data.toString()); + useLayout(fieldName); break; } init();