Add map list tool tips / copy actions, simplify MapListModel

This commit is contained in:
GriffinR 2024-11-26 11:36:11 -05:00
parent b230f21e8d
commit ff04a41db2
4 changed files with 263 additions and 483 deletions

View File

@ -180,6 +180,7 @@ private slots:
void duplicate();
void setClipboardData(poryjson::Json::object);
void setClipboardData(QImage);
void setClipboardData(const QString &text);
void copy();
void paste();
@ -350,7 +351,7 @@ private:
void openNewMapDialog();
void openNewLayoutDialog();
void openSubWindow(QWidget * window);
void scrollMapList(MapTree *list, QString itemName);
void scrollMapList(MapTree *list, const QString &itemName);
void scrollMapListToCurrentMap(MapTree *list);
void scrollMapListToCurrentLayout(MapTree *list);
void resetMapListFilters();

View File

@ -61,15 +61,42 @@ class MapListModel : public QStandardItemModel {
Q_OBJECT
public:
MapListModel(QObject *parent = nullptr) : QStandardItemModel(parent) {};
MapListModel(Project *project, QObject *parent = nullptr);
~MapListModel() { }
virtual QModelIndex indexOf(QString id) const = 0;
void setActiveItem(const QString &itemName) { this->activeItemName = itemName; }
virtual QStandardItem *insertMapItem(const QString &mapName, const QString &folderName);
virtual QStandardItem *insertMapFolderItem(const QString &folderName);
virtual QModelIndex indexOf(const QString &itemName) const;
virtual void removeItemAt(const QModelIndex &index);
virtual QStandardItem *getItem(const QModelIndex &index) const = 0;
virtual QStandardItem *getItem(const QModelIndex &index) const;
virtual QVariant data(const QModelIndex &index, int role) const override;
protected:
virtual void removeItem(QStandardItem *item) = 0;
Project *project;
QStandardItem *root = nullptr;
QString activeItemName;
QString folderTypeName;
bool sortingEnabled = false;
bool editable = false;
QIcon mapGrayIcon;
QIcon mapIcon;
QIcon mapEditedIcon;
QIcon mapOpenedIcon;
QIcon mapFolderIcon;
QIcon emptyMapFolderIcon;
QMap<QString, QStandardItem *> mapFolderItems;
QMap<QString, QStandardItem *> mapItems;
virtual QStandardItem *createMapItem(const QString &mapName, QStandardItem *map = nullptr);
virtual QStandardItem *createMapFolderItem(const QString &groupName, QStandardItem *fromItem = nullptr);
virtual void removeItem(QStandardItem *item) = 0;
};
class MapGroupModel : public MapListModel {
@ -80,44 +107,20 @@ public:
~MapGroupModel() { }
QVariant data(const QModelIndex &index, int role) const override;
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
Qt::DropActions supportedDropActions() const override;
QStringList mimeTypes() const override;
virtual QMimeData *mimeData(const QModelIndexList &indexes) const override;
virtual bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) override;
virtual bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
public:
void setMap(QString mapName) { this->openMap = mapName; }
QStandardItem *createGroupItem(QString groupName, QStandardItem *fromItem = nullptr);
QStandardItem *createMapItem(QString mapName, QStandardItem *fromItem = nullptr);
QStandardItem *insertGroupItem(QString groupName);
QStandardItem *insertMapItem(QString mapName, QString groupName);
virtual QStandardItem *getItem(const QModelIndex &index) const override;
virtual QModelIndex indexOf(QString mapName) const override;
void initialize();
QMimeData *mimeData(const QModelIndexList &indexes) const override;
bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) override;
protected:
virtual void removeItem(QStandardItem *item) override;
void removeItem(QStandardItem *item) override;
private:
friend class MapTree;
void updateProject();
private:
Project *project;
QStandardItem *root = nullptr;
QMap<QString, QStandardItem *> groupItems;
QMap<QString, QStandardItem *> mapItems;
QString openMap;
signals:
void dragMoveCompleted();
};
@ -131,36 +134,8 @@ public:
MapAreaModel(Project *project, QObject *parent = nullptr);
~MapAreaModel() {}
QVariant data(const QModelIndex &index, int role) const override;
public:
void setMap(QString mapName) { this->openMap = mapName; }
QStandardItem *createAreaItem(QString areaName);
QStandardItem *createMapItem(QString mapName);
QStandardItem *insertAreaItem(QString areaName);
QStandardItem *insertMapItem(QString mapName, QString areaName);
virtual QStandardItem *getItem(const QModelIndex &index) const override;
virtual QModelIndex indexOf(QString mapName) const override;
void initialize();
protected:
virtual void removeItem(QStandardItem *item) override;
private:
Project *project;
QStandardItem *root = nullptr;
QMap<QString, QStandardItem *> areaItems;
QMap<QString, QStandardItem *> mapItems;
QString openMap;
signals:
void edited();
void removeItem(QStandardItem *item) override;
};
@ -174,34 +149,8 @@ public:
QVariant data(const QModelIndex &index, int role) const override;
public:
void setLayout(QString layoutId) { this->openLayout = layoutId; }
QStandardItem *createLayoutItem(QString layoutId);
QStandardItem *createMapItem(QString mapName);
QStandardItem *insertLayoutItem(QString layoutId);
QStandardItem *insertMapItem(QString mapName, QString layoutId);
virtual QStandardItem *getItem(const QModelIndex &index) const override;
virtual QModelIndex indexOf(QString layoutName) const override;
void initialize();
protected:
virtual void removeItem(QStandardItem *item) override;
private:
Project *project;
QStandardItem *root = nullptr;
QMap<QString, QStandardItem *> layoutItems;
QMap<QString, QStandardItem *> mapItems;
QString openLayout;
signals:
void edited();
void removeItem(QStandardItem *item) override;
};
#endif // MAPLISTMODELS_H

View File

@ -956,9 +956,6 @@ bool MainWindow::setLayout(QString layoutId) {
logInfo("Switching to layout-only editing mode. Disabling map-related edits.");
unsetMap();
layoutTreeModel->setLayout(layoutId);
refreshMapScene();
updateWindowTitle();
updateMapList();
@ -1163,7 +1160,7 @@ void MainWindow::clearProjectUI() {
Event::clearIcons();
}
void MainWindow::scrollMapList(MapTree *list, QString itemName) {
void MainWindow::scrollMapList(MapTree *list, const QString &itemName) {
if (!list || itemName.isEmpty())
return;
auto model = static_cast<FilterChildrenProxyModel*>(list->model());
@ -1208,9 +1205,16 @@ void MainWindow::onOpenMapListContextMenu(const QPoint &point) {
QAction* addToFolderAction = nullptr;
QAction* deleteFolderAction = nullptr;
QAction* openItemAction = nullptr;
QAction* copyDisplayNameAction = nullptr;
QAction* copyToolTipAction = nullptr;
if (itemType == "map_name") {
// Right-clicking on a map.
openItemAction = menu.addAction("Open Map");
menu.addSeparator();
copyDisplayNameAction = menu.addAction("Copy Map Name");
copyToolTipAction = menu.addAction("Copy Map ID");
menu.addSeparator();
connect(menu.addAction("Duplicate Map"), &QAction::triggered, [this, itemName] {
auto dialog = new NewMapDialog(this->editor->project, this->editor->project->getMap(itemName), this);
dialog->open();
@ -1226,12 +1230,18 @@ void MainWindow::onOpenMapListContextMenu(const QPoint &point) {
// Right-clicking on a MAPSEC folder
addToFolderAction = menu.addAction("Add New Map to Area");
menu.addSeparator();
copyDisplayNameAction = menu.addAction("Copy Area Name");
menu.addSeparator();
deleteFolderAction = menu.addAction("Delete Area");
if (itemName == this->editor->project->getEmptyMapsecName())
deleteFolderAction->setEnabled(false); // Disallow deleting the default name
} else if (itemType == "map_layout") {
// Right-clicking on a map layout
openItemAction = menu.addAction("Open Layout");
menu.addSeparator();
copyDisplayNameAction = menu.addAction("Copy Layout Name");
copyToolTipAction = menu.addAction("Copy Layout ID");
menu.addSeparator();
connect(menu.addAction("Duplicate Layout"), &QAction::triggered, [this, itemName] {
auto layout = this->editor->project->loadLayout(itemName);
if (layout) {
@ -1261,8 +1271,21 @@ void MainWindow::onOpenMapListContextMenu(const QPoint &point) {
deleteFolderAction->setEnabled(false);
}
}
if (openItemAction) {
connect(openItemAction, &QAction::triggered, [this, index] { openMapListItem(index); });
connect(openItemAction, &QAction::triggered, [this, index] {
openMapListItem(index);
});
}
if (copyDisplayNameAction) {
connect(copyDisplayNameAction, &QAction::triggered, [this, sourceModel, index] {
setClipboardData(sourceModel->data(index, Qt::DisplayRole).toString());
});
}
if (copyToolTipAction) {
connect(copyToolTipAction, &QAction::triggered, [this, sourceModel, index] {
setClipboardData(sourceModel->data(index, Qt::ToolTipRole).toString());
});
}
if (menu.actions().length() != 0)
@ -1399,17 +1422,17 @@ void MainWindow::onNewLayoutCreated(Layout *layout) {
}
// Add new layout to the Layouts map list view
this->layoutTreeModel->insertLayoutItem(layout->id);
this->layoutTreeModel->insertMapFolderItem(layout->id);
}
void MainWindow::onNewMapGroupCreated(const QString &groupName) {
// Add new map group to the Groups map list view
this->mapGroupModel->insertGroupItem(groupName);
this->mapGroupModel->insertMapFolderItem(groupName);
}
void MainWindow::onNewMapSectionCreated(const QString &idName) {
// Add new map section to the Areas map list view
this->mapAreaModel->insertAreaItem(idName);
this->mapAreaModel->insertMapFolderItem(idName);
// TODO: Refresh Region Map Editor's map section dropdown, if it's open
}
@ -1627,28 +1650,28 @@ void MainWindow::openMapListItem(const QModelIndex &index) {
}
void MainWindow::updateMapList() {
// Get the name of the open map/layout (or clear the relevant selection if there is none).
QString activeItemName;
if (this->editor->map) {
this->mapGroupModel->setMap(this->editor->map->name());
this->groupListProxyModel->layoutChanged();
this->mapAreaModel->setMap(this->editor->map->name());
this->areaListProxyModel->layoutChanged();
activeItemName = this->editor->map->name();
} else {
this->mapGroupModel->setMap(QString());
this->groupListProxyModel->layoutChanged();
this->ui->mapList->clearSelection();
this->mapAreaModel->setMap(QString());
this->areaListProxyModel->layoutChanged();
this->ui->areaList->clearSelection();
ui->mapList->clearSelection();
ui->areaList->clearSelection();
if (this->editor->layout) {
activeItemName = this->editor->layout->id;
} else {
ui->layoutList->clearSelection();
}
}
if (this->editor->layout) {
this->layoutTreeModel->setLayout(this->editor->layout->id);
this->layoutListProxyModel->layoutChanged();
} else {
this->layoutTreeModel->setLayout(QString());
this->layoutListProxyModel->layoutChanged();
this->ui->layoutList->clearSelection();
}
this->mapGroupModel->setActiveItem(activeItemName);
this->mapAreaModel->setActiveItem(activeItemName);
this->layoutTreeModel->setActiveItem(activeItemName);
this->groupListProxyModel->layoutChanged();
this->areaListProxyModel->layoutChanged();
this->layoutListProxyModel->layoutChanged();
}
void MainWindow::on_action_Save_Project_triggered() {
@ -1782,6 +1805,11 @@ void MainWindow::setClipboardData(OrderedJson::object object) {
clipboard->setText(newText);
}
void MainWindow::setClipboardData(const QString &text) {
QClipboard *clipboard = QGuiApplication::clipboard();
clipboard->setText(text);
}
void MainWindow::setClipboardData(QImage image) {
QClipboard *clipboard = QGuiApplication::clipboard();
clipboard->setImage(image);

View File

@ -38,6 +38,43 @@ void MapTree::keyPressEvent(QKeyEvent *event) {
}
}
MapListModel::MapListModel(Project *project, QObject *parent) : QStandardItemModel(parent) {
this->project = project;
this->root = invisibleRootItem();
this->mapGrayIcon = QIcon(QStringLiteral(":/icons/map_grayed.ico"));
this->mapIcon = QIcon(QStringLiteral(":/icons/map.ico"));
this->mapEditedIcon = QIcon(QStringLiteral(":/icons/map_edited.ico"));
this->mapOpenedIcon = QIcon(QStringLiteral(":/icons/map_opened.ico"));
this->mapFolderIcon.addFile(QStringLiteral(":/icons/folder_closed_map.ico"), QSize(), QIcon::Normal, QIcon::Off);
this->mapFolderIcon.addFile(QStringLiteral(":/icons/folder_map.ico"), QSize(), QIcon::Normal, QIcon::On);
this->emptyMapFolderIcon.addFile(QStringLiteral(":/icons/folder_closed.ico"), QSize(), QIcon::Normal, QIcon::Off);
this->emptyMapFolderIcon.addFile(QStringLiteral(":/icons/folder.ico"), QSize(), QIcon::Normal, QIcon::On);
}
QStandardItem *MapListModel::getItem(const QModelIndex &index) const {
if (index.isValid()) {
QStandardItem *item = static_cast<QStandardItem*>(index.internalPointer());
if (item)
return item;
}
return this->root;
}
QModelIndex MapListModel::indexOf(const QString &itemName) const {
if (this->mapItems.contains(itemName))
return this->mapItems.value(itemName)->index();
if (this->mapFolderItems.contains(itemName))
return this->mapFolderItems.value(itemName)->index();
return QModelIndex();
}
void MapListModel::removeItemAt(const QModelIndex &index) {
QStandardItem *item = this->getItem(index)->child(index.row(), index.column());
if (!item)
@ -49,11 +86,89 @@ void MapListModel::removeItemAt(const QModelIndex &index) {
} else {
// TODO: Because there's no support for deleting maps we can only delete empty folders
if (!item->hasChildren()) {
this->removeItem(item);
removeItem(item);
}
}
}
QStandardItem *MapListModel::createMapItem(const QString &mapName, QStandardItem *map) {
if (!map) map = new QStandardItem;
map->setText(mapName);
map->setData(mapName, MapListUserRoles::NameRole);
map->setData("map_name", MapListUserRoles::TypeRole);
map->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemNeverHasChildren);
map->setEditable(this->editable); // Will override flags if necessary
this->mapItems.insert(mapName, map);
return map;
}
QStandardItem *MapListModel::createMapFolderItem(const QString &folderName, QStandardItem *folder) {
if (!folder) folder = new QStandardItem;
folder->setText(folderName);
folder->setData(folderName, MapListUserRoles::NameRole);
folder->setData(this->folderTypeName, MapListUserRoles::TypeRole);
folder->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled);
folder->setEditable(this->editable); // Will override flags if necessary
this->mapFolderItems.insert(folderName, folder);
return folder;
}
QStandardItem *MapListModel::insertMapItem(const QString &mapName, const QString &folderName) {
// Disallow adding MAP_DYNAMIC to the map list.
if (mapName == this->project->getDynamicMapName())
return nullptr;
QStandardItem *folder = this->mapFolderItems[folderName];
if (!folder) folder = insertMapFolderItem(folderName);
QStandardItem *map = createMapItem(mapName);
folder->appendRow(map);
if (this->sortingEnabled)
this->sort(0, Qt::AscendingOrder);
return map;
}
QStandardItem *MapListModel::insertMapFolderItem(const QString &folderName) {
QStandardItem *item = createMapFolderItem(folderName);
this->root->appendRow(item);
if (this->sortingEnabled)
this->sort(0, Qt::AscendingOrder);
return item;
}
QVariant MapListModel::data(const QModelIndex &index, int role) const {
if (!index.isValid())
return QVariant();
int row = index.row();
int col = index.column();
const QStandardItem *item = this->getItem(index)->child(row, col);
const QString type = item->data(MapListUserRoles::TypeRole).toString();
const QString name = item->data(MapListUserRoles::NameRole).toString();
if (type == "map_name") {
// Data for maps in the map list
if (role == Qt::DecorationRole) {
if (name == this->activeItemName)
return this->mapOpenedIcon;
const Map* map = this->project->mapCache.value(name);
if (!map)
return this->mapGrayIcon;
return map->hasUnsavedChanges() ? this->mapEditedIcon : this->mapIcon;
} else if (role == Qt::ToolTipRole) {
return this->project->mapNamesToMapConstants.value(name);
}
} else if (type == this->folderTypeName) {
// Data for map folders in the map list
if (role == Qt::DecorationRole) {
return item->hasChildren() ? this->mapFolderIcon : this->emptyMapFolderIcon;
}
}
return QStandardItemModel::data(index, role);
}
QWidget *GroupNameDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &, const QModelIndex &) const {
@ -83,11 +198,15 @@ void GroupNameDelegate::updateEditorGeometry(QWidget *editor, const QStyleOption
MapGroupModel::MapGroupModel(Project *project, QObject *parent) : MapListModel(parent) {
this->project = project;
this->root = this->invisibleRootItem();
MapGroupModel::MapGroupModel(Project *project, QObject *parent) : MapListModel(project, parent) {
this->folderTypeName = "map_group";
this->editable = true;
initialize();
for (const auto &groupName : this->project->groupNames) {
for (const auto &mapName : this->project->groupNameToMapNames.value(groupName)) {
insertMapItem(mapName, groupName);
}
}
}
Qt::DropActions MapGroupModel::supportedDropActions() const {
@ -173,7 +292,7 @@ bool MapGroupModel::dropMimeData(const QMimeData *data, Qt::DropAction action, i
QModelIndex groupIndex = index(row, 0, parentIndex);
QStandardItem *groupItem = this->itemFromIndex(groupIndex);
createGroupItem(groupName, groupItem);
createMapFolderItem(groupName, groupItem);
for (QString mapName : mapsToMove) {
QStandardItem *mapItem = createMapItem(mapName);
@ -251,143 +370,36 @@ void MapGroupModel::updateProject() {
this->project->hasUnsavedDataChanges = true;
}
QStandardItem *MapGroupModel::createGroupItem(QString groupName, QStandardItem *group) {
if (!group) group = new QStandardItem;
group->setText(groupName);
group->setData(groupName, MapListUserRoles::NameRole);
group->setData("map_group", MapListUserRoles::TypeRole);
group->setFlags(Qt::ItemIsEnabled | Qt::ItemIsDropEnabled | Qt::ItemIsEditable | Qt::ItemIsDragEnabled | Qt::ItemIsSelectable);
this->groupItems.insert(groupName, group);
return group;
}
QStandardItem *MapGroupModel::createMapItem(QString mapName, QStandardItem *map) {
if (!map) map = new QStandardItem;
map->setData(mapName, MapListUserRoles::NameRole);
map->setData("map_name", MapListUserRoles::TypeRole);
map->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled);
this->mapItems[mapName] = map;
return map;
}
QStandardItem *MapGroupModel::insertGroupItem(QString groupName) {
QStandardItem *group = createGroupItem(groupName);
this->root->appendRow(group);
return group;
}
void MapGroupModel::removeItem(QStandardItem *item) {
this->removeRow(item->row());
this->updateProject();
}
QStandardItem *MapGroupModel::insertMapItem(QString mapName, QString groupName) {
QStandardItem *group = this->groupItems[groupName];
if (!group) {
group = insertGroupItem(groupName);
}
QStandardItem *map = createMapItem(mapName);
group->appendRow(map);
return map;
}
void MapGroupModel::initialize() {
this->groupItems.clear();
this->mapItems.clear();
for (const auto &groupName : this->project->groupNames) {
QStandardItem *group = createGroupItem(groupName);
root->appendRow(group);
for (const auto &mapName : this->project->groupNameToMapNames.value(groupName)) {
group->appendRow(createMapItem(mapName));
}
}
}
QStandardItem *MapGroupModel::getItem(const QModelIndex &index) const {
if (index.isValid()) {
QStandardItem *item = static_cast<QStandardItem*>(index.internalPointer());
if (item)
return item;
}
return this->root;
}
QModelIndex MapGroupModel::indexOf(QString mapName) const {
if (this->mapItems.contains(mapName)) {
return this->mapItems[mapName]->index();
}
return QModelIndex();
}
QVariant MapGroupModel::data(const QModelIndex &index, int role) const {
if (!index.isValid()) return QVariant();
if (!index.isValid())
return QVariant();
int row = index.row();
int col = index.column();
if (role == Qt::DecorationRole) {
static QIcon mapGrayIcon = QIcon(QStringLiteral(":/icons/map_grayed.ico"));
static QIcon mapIcon = QIcon(QStringLiteral(":/icons/map.ico"));
static QIcon mapEditedIcon = QIcon(QStringLiteral(":/icons/map_edited.ico"));
static QIcon mapOpenedIcon = QIcon(QStringLiteral(":/icons/map_opened.ico"));
static QIcon mapFolderIcon;
static QIcon folderIcon;
static bool loaded = false;
if (!loaded) {
mapFolderIcon.addFile(QStringLiteral(":/icons/folder_closed_map.ico"), QSize(), QIcon::Normal, QIcon::Off);
mapFolderIcon.addFile(QStringLiteral(":/icons/folder_map.ico"), QSize(), QIcon::Normal, QIcon::On);
folderIcon.addFile(QStringLiteral(":/icons/folder_closed.ico"), QSize(), QIcon::Normal, QIcon::Off);
folderIcon.addFile(QStringLiteral(":/icons/folder.ico"), QSize(), QIcon::Normal, QIcon::On);
loaded = true;
}
QStandardItem *item = this->getItem(index)->child(row, col);
QString type = item->data(MapListUserRoles::TypeRole).toString();
if (type == "map_group") {
if (!item->hasChildren()) {
return folderIcon;
}
return mapFolderIcon;
} else if (type == "map_name") {
QString mapName = item->data(MapListUserRoles::NameRole).toString();
if (mapName == this->openMap) {
return mapOpenedIcon;
}
else if (this->project->mapCache.contains(mapName)) {
if (this->project->mapCache.value(mapName)->hasUnsavedChanges()) {
return mapEditedIcon;
}
else {
return mapIcon;
}
}
return mapGrayIcon;
}
}
else if (role == Qt::DisplayRole) {
QStandardItem *item = this->getItem(index)->child(row, col);
QString type = item->data(MapListUserRoles::TypeRole).toString();
const QStandardItem *item = this->getItem(index)->child(row, col);
const QString type = item->data(MapListUserRoles::TypeRole).toString();
const QString name = item->data(MapListUserRoles::NameRole).toString();
if (role == Qt::DisplayRole) {
if (type == "map_name") {
return QString("[%1.%2] ").arg(this->getItem(index)->row()).arg(row, 2, 10, QLatin1Char('0')) + item->data(MapListUserRoles::NameRole).toString();
return QString("[%1.%2] ").arg(this->getItem(index)->row()).arg(row, 2, 10, QLatin1Char('0')) + name;
}
else if (type == "map_group") {
return item->data(MapListUserRoles::NameRole).toString();
else if (type == this->folderTypeName) {
return name;
}
}
return QStandardItemModel::data(index, role);
return MapListModel::data(index, role);
}
bool MapGroupModel::setData(const QModelIndex &index, const QVariant &value, int role) {
if (role == MapListUserRoles::NameRole && data(index, MapListUserRoles::TypeRole).toString() == "map_group") {
// verify uniqueness of new group name
// TODO: Check that the name is a valid symbol name (i.e. only word characters, not starting with a number)
if (this->project->groupNames.contains(value.toString())) {
if (!this->project->isIdentifierUnique(value.toString())) {
return false;
}
}
@ -399,50 +411,15 @@ bool MapGroupModel::setData(const QModelIndex &index, const QVariant &value, int
MapAreaModel::MapAreaModel(Project *project, QObject *parent) : MapListModel(parent) {
this->project = project;
this->root = this->invisibleRootItem();
MapAreaModel::MapAreaModel(Project *project, QObject *parent) : MapListModel(project, parent) {
this->folderTypeName = "map_section";
initialize();
}
QStandardItem *MapAreaModel::createAreaItem(QString mapsecName) {
QStandardItem *area = new QStandardItem;
area->setText(mapsecName);
area->setEditable(false);
area->setData(mapsecName, MapListUserRoles::NameRole);
area->setData("map_section", MapListUserRoles::TypeRole);
// group->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled);
this->areaItems.insert(mapsecName, area);
return area;
}
QStandardItem *MapAreaModel::createMapItem(QString mapName) {
QStandardItem *map = new QStandardItem;
map->setText(mapName);
map->setEditable(false);
map->setData(mapName, MapListUserRoles::NameRole);
map->setData("map_name", MapListUserRoles::TypeRole);
// map->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled);
this->mapItems.insert(mapName, map);
return map;
}
QStandardItem *MapAreaModel::insertAreaItem(QString areaName) {
QStandardItem *item = createAreaItem(areaName);
this->root->appendRow(item);
this->sort(0, Qt::AscendingOrder);
return item;
}
QStandardItem *MapAreaModel::insertMapItem(QString mapName, QString areaName) {
QStandardItem *area = this->areaItems[areaName];
if (!area) {
return nullptr;
for (const auto &mapName : this->project->mapNames) {
insertMapItem(mapName, this->project->mapNameToMapSectionName.value(mapName));
}
QStandardItem *map = createMapItem(mapName);
area->appendRow(map);
return map;
this->sortingEnabled = true;
sort(0, Qt::AscendingOrder);
}
void MapAreaModel::removeItem(QStandardItem *item) {
@ -450,227 +427,52 @@ void MapAreaModel::removeItem(QStandardItem *item) {
this->removeRow(item->row());
}
void MapAreaModel::initialize() {
this->areaItems.clear();
this->mapItems.clear();
for (const auto &idName : this->project->mapSectionIdNames) {
this->root->appendRow(createAreaItem(idName));
}
LayoutTreeModel::LayoutTreeModel(Project *project, QObject *parent) : MapListModel(project, parent) {
this->folderTypeName = "map_layout";
for (const auto &mapName : this->project->mapNames) {
const QString mapsecName = this->project->mapNameToMapSectionName.value(mapName);
if (this->areaItems.contains(mapsecName))
this->areaItems[mapsecName]->appendRow(createMapItem(mapName));
insertMapItem(mapName, this->project->mapNameToLayoutId.value(mapName));
}
this->sort(0, Qt::AscendingOrder);
}
QStandardItem *MapAreaModel::getItem(const QModelIndex &index) const {
if (index.isValid()) {
QStandardItem *item = static_cast<QStandardItem*>(index.internalPointer());
if (item)
return item;
}
return this->root;
}
QModelIndex MapAreaModel::indexOf(QString mapName) const {
if (this->mapItems.contains(mapName)) {
return this->mapItems[mapName]->index();
}
return QModelIndex();
}
QVariant MapAreaModel::data(const QModelIndex &index, int role) const {
if (!index.isValid()) return QVariant();
int row = index.row();
int col = index.column();
if (role == Qt::DecorationRole) {
static QIcon mapGrayIcon = QIcon(QStringLiteral(":/icons/map_grayed.ico"));
static QIcon mapIcon = QIcon(QStringLiteral(":/icons/map.ico"));
static QIcon mapEditedIcon = QIcon(QStringLiteral(":/icons/map_edited.ico"));
static QIcon mapOpenedIcon = QIcon(QStringLiteral(":/icons/map_opened.ico"));
static QIcon mapFolderIcon;
static QIcon folderIcon;
static bool loaded = false;
if (!loaded) {
mapFolderIcon.addFile(QStringLiteral(":/icons/folder_closed_map.ico"), QSize(), QIcon::Normal, QIcon::Off);
mapFolderIcon.addFile(QStringLiteral(":/icons/folder_map.ico"), QSize(), QIcon::Normal, QIcon::On);
folderIcon.addFile(QStringLiteral(":/icons/folder_closed.ico"), QSize(), QIcon::Normal, QIcon::Off);
folderIcon.addFile(QStringLiteral(":/icons/folder.ico"), QSize(), QIcon::Normal, QIcon::On);
loaded = true;
}
QStandardItem *item = this->getItem(index)->child(row, col);
QString type = item->data(MapListUserRoles::TypeRole).toString();
if (type == "map_section") {
if (item->hasChildren()) {
return mapFolderIcon;
}
return folderIcon;
} else if (type == "map_name") {
QString mapName = item->data(MapListUserRoles::NameRole).toString();
if (mapName == this->openMap) {
return mapOpenedIcon;
}
else if (this->project->mapCache.contains(mapName)) {
if (this->project->mapCache.value(mapName)->hasUnsavedChanges()) {
return mapEditedIcon;
}
else {
return mapIcon;
}
}
return mapGrayIcon;
}
}
else if (role == Qt::DisplayRole) {
QStandardItem *item = this->getItem(index)->child(row, col);
QString type = item->data(MapListUserRoles::TypeRole).toString();
if (type == "map_section") {
return item->data(MapListUserRoles::NameRole).toString();
}
}
return QStandardItemModel::data(index, role);
}
LayoutTreeModel::LayoutTreeModel(Project *project, QObject *parent) : MapListModel(parent) {
this->project = project;
this->root = this->invisibleRootItem();
initialize();
}
QStandardItem *LayoutTreeModel::createLayoutItem(QString layoutId) {
QStandardItem *layout = new QStandardItem;
layout->setText(this->project->mapLayouts[layoutId]->name);
layout->setEditable(false);
layout->setData(layoutId, MapListUserRoles::NameRole);
layout->setData("map_layout", MapListUserRoles::TypeRole);
// // group->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled);
this->layoutItems.insert(layoutId, layout);
return layout;
}
QStandardItem *LayoutTreeModel::createMapItem(QString mapName) {
QStandardItem *map = new QStandardItem;
map->setText(mapName);
map->setEditable(false);
map->setData(mapName, MapListUserRoles::NameRole);
map->setData("map_name", MapListUserRoles::TypeRole);
map->setFlags(Qt::NoItemFlags | Qt::ItemNeverHasChildren);
this->mapItems.insert(mapName, map);
return map;
}
QStandardItem *LayoutTreeModel::insertLayoutItem(QString layoutId) {
QStandardItem *layoutItem = this->createLayoutItem(layoutId);
this->root->appendRow(layoutItem);
this->sort(0, Qt::AscendingOrder);
return layoutItem;
}
QStandardItem *LayoutTreeModel::insertMapItem(QString mapName, QString layoutId) {
QStandardItem *layout = nullptr;
if (this->layoutItems.contains(layoutId)) {
layout = this->layoutItems[layoutId];
}
else {
layout = createLayoutItem(layoutId);
this->root->appendRow(layout);
}
if (!layout) {
return nullptr;
}
QStandardItem *map = createMapItem(mapName);
layout->appendRow(map);
return map;
this->sortingEnabled = true;
sort(0, Qt::AscendingOrder);
}
void LayoutTreeModel::removeItem(QStandardItem *) {
// TODO: Deleting layouts not supported
}
void LayoutTreeModel::initialize() {
this->layoutItems.clear();
this->mapItems.clear();
for (const auto &layoutId : this->project->layoutIds) {
this->root->appendRow(createLayoutItem(layoutId));
}
for (const auto &mapName : this->project->mapNames) {
QString layoutId = project->mapNameToLayoutId.value(mapName);
if (this->layoutItems.contains(layoutId))
this->layoutItems[layoutId]->appendRow(createMapItem(mapName));
}
this->sort(0, Qt::AscendingOrder);
}
QStandardItem *LayoutTreeModel::getItem(const QModelIndex &index) const {
if (index.isValid()) {
QStandardItem *item = static_cast<QStandardItem*>(index.internalPointer());
if (item)
return item;
}
return this->root;
}
QModelIndex LayoutTreeModel::indexOf(QString layoutName) const {
if (this->layoutItems.contains(layoutName)) {
return this->layoutItems[layoutName]->index();
}
return QModelIndex();
}
QVariant LayoutTreeModel::data(const QModelIndex &index, int role) const {
if (!index.isValid()) return QVariant();
if (!index.isValid())
return QVariant();
int row = index.row();
int col = index.column();
if (role == Qt::DecorationRole) {
static QIcon mapGrayIcon = QIcon(QStringLiteral(":/icons/map_grayed.ico"));
static QIcon mapIcon = QIcon(QStringLiteral(":/icons/map.ico"));
static QIcon mapEditedIcon = QIcon(QStringLiteral(":/icons/map_edited.ico"));
static QIcon mapOpenedIcon = QIcon(QStringLiteral(":/icons/map_opened.ico"));
const QStandardItem *item = this->getItem(index)->child(row, col);
const QString type = item->data(MapListUserRoles::TypeRole).toString();
const QString name = item->data(MapListUserRoles::NameRole).toString();
QStandardItem *item = this->getItem(index)->child(row, col);
QString type = item->data(MapListUserRoles::TypeRole).toString();
if (type == this->folderTypeName) {
const Layout* layout = this->project->mapLayouts.value(name);
if (type == "map_layout") {
QString layoutId = item->data(MapListUserRoles::NameRole).toString();
if (layoutId == this->openLayout) {
return mapOpenedIcon;
}
else if (this->project->mapLayouts.contains(layoutId)) {
if (this->project->mapLayouts.value(layoutId)->hasUnsavedChanges()) {
return mapEditedIcon;
}
else if (!this->project->mapLayouts[layoutId]->loaded) {
return mapGrayIcon;
}
}
return mapIcon;
if (role == Qt::DecorationRole) {
// Map layouts are used as folders, but we display them with the same icons as maps.
if (name == this->activeItemName)
return this->mapOpenedIcon;
if (!layout || !layout->loaded)
return this->mapGrayIcon;
return layout->hasUnsavedChanges() ? this->mapEditedIcon : this->mapIcon;
}
else if (type == "map_name") {
return QVariant();
else if (role == Qt::DisplayRole) {
// Despite using layout IDs internally, the Layouts map list shows layouts using their file path name.
if (layout) return layout->name;
} else if (role == Qt::ToolTipRole) {
if (layout) return layout->id;
}
return QVariant();
}
return QStandardItemModel::data(index, role);
return MapListModel::data(index, role);
}