void TilesetDock::removeTiles() { TilesetView *view = currentTilesetView(); if (!view) return; if (!view->selectionModel()->hasSelection()) return; const QModelIndexList indexes = view->selectionModel()->selectedIndexes(); const TilesetModel *model = view->tilesetModel(); QList<Tile*> tiles; for (const QModelIndex &index : indexes) if (Tile *tile = model->tileAt(index)) tiles.append(tile); auto matchesAnyTile = [&tiles] (const Cell &cell) { if (Tile *tile = cell.tile) return tiles.contains(tile); return false; }; const bool inUse = hasTileReferences(mMapDocument, matchesAnyTile); // If the tileset is in use, warn the user and confirm removal if (inUse) { QMessageBox warning(QMessageBox::Warning, tr("Remove Tiles"), tr("One or more of the tiles to be removed are " "still in use by the map!"), QMessageBox::Yes | QMessageBox::No, this); warning.setDefaultButton(QMessageBox::Yes); warning.setInformativeText(tr("Remove all references to these tiles?")); if (warning.exec() != QMessageBox::Yes) return; } QUndoStack *undoStack = mMapDocument->undoStack(); undoStack->beginMacro(tr("Remove Tiles")); if (inUse) removeTileReferences(mMapDocument, matchesAnyTile); Tileset *tileset = view->tilesetModel()->tileset(); undoStack->push(new RemoveTiles(mMapDocument, tileset, tiles)); undoStack->endMacro(); // Clear the current tiles, will be referencing the removed tiles setCurrentTiles(nullptr); setCurrentTile(nullptr); }
void TilesetEditor::removeTiles() { TilesetView *view = currentTilesetView(); if (!view) return; if (!view->selectionModel()->hasSelection()) return; const QModelIndexList indexes = view->selectionModel()->selectedIndexes(); const TilesetModel *model = view->tilesetModel(); QList<Tile*> tiles; for (const QModelIndex &index : indexes) if (Tile *tile = model->tileAt(index)) tiles.append(tile); auto matchesAnyTile = [&tiles] (const Cell &cell) { if (Tile *tile = cell.tile()) return tiles.contains(tile); return false; }; QList<MapDocument *> mapsUsingTiles; for (MapDocument *mapDocument : mCurrentTilesetDocument->mapDocuments()) if (hasTileReferences(mapDocument, matchesAnyTile)) mapsUsingTiles.append(mapDocument); // If the tileset is in use, warn the user and confirm removal if (!mapsUsingTiles.isEmpty()) { QMessageBox warning(QMessageBox::Warning, tr("Remove Tiles"), tr("Tiles to be removed are in use by open maps!"), QMessageBox::Yes | QMessageBox::No, mMainWindow->window()); warning.setDefaultButton(QMessageBox::Yes); warning.setInformativeText(tr("Remove all references to these tiles?")); if (warning.exec() != QMessageBox::Yes) return; } for (MapDocument *mapDocument : mapsUsingTiles) removeTileReferences(mapDocument, matchesAnyTile); mCurrentTilesetDocument->undoStack()->push(new RemoveTiles(mCurrentTilesetDocument, tiles)); // todo: make sure any current brushes are no longer referring to removed tiles setCurrentTile(nullptr); }
/** * Synchronizes the selection with the given stamp. Ignored when the stamp is * changing because of a selection change in the TilesetDock. */ void TilesetDock::selectTilesInStamp(const TileStamp &stamp) { if (mEmittingStampCaptured) return; QSet<Tile*> processed; QMap<QItemSelectionModel*, QItemSelection> selections; for (const TileStampVariation &variation : stamp.variations()) { const TileLayer &tileLayer = *variation.tileLayer(); for (const Cell &cell : tileLayer) { if (Tile *tile = cell.tile) { if (processed.contains(tile)) continue; processed.insert(tile); // avoid spending time on duplicates Tileset *tileset = tile->tileset(); int tilesetIndex = mTilesets.indexOf(tileset->sharedPointer()); if (tilesetIndex != -1) { TilesetView *view = tilesetViewAt(tilesetIndex); if (!view->model()) // Lazily set up the model setupTilesetModel(view, tileset); const TilesetModel *model = view->tilesetModel(); const QModelIndex modelIndex = model->tileIndex(tile); QItemSelectionModel *selectionModel = view->selectionModel(); selections[selectionModel].select(modelIndex, modelIndex); } } } } if (!selections.isEmpty()) { mSynchronizingSelection = true; // Mark captured tiles as selected for (auto i = selections.constBegin(); i != selections.constEnd(); ++i) { QItemSelectionModel *selectionModel = i.key(); const QItemSelection &selection = i.value(); selectionModel->select(selection, QItemSelectionModel::SelectCurrent); } // Show/edit properties of all captured tiles mMapDocument->setSelectedTiles(processed.toList()); // Update the current tile (useful for animation and collision editors) auto first = selections.begin(); QItemSelectionModel *selectionModel = first.key(); const QItemSelection &selection = first.value(); const QModelIndex currentIndex = selection.first().topLeft(); if (selectionModel->currentIndex() != currentIndex) selectionModel->setCurrentIndex(currentIndex, QItemSelectionModel::NoUpdate); else currentChanged(currentIndex); mSynchronizingSelection = false; } }
void TilesetDock::insertTilesetView(int index, Tileset *tileset) { TilesetView *view = new TilesetView(mMapDocument); view->setModel(new TilesetModel(tileset, view)); connect(view->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), SLOT(updateCurrentTiles())); mTabBar->insertTab(index, tileset->name()); mViewStack->insertWidget(index, view); }
void TilesetDock::insertTilesetView(int index, Tileset *tileset) { TilesetView *view = new TilesetView(mMapDocument); view->setModel(new TilesetModel(tileset, view)); connect(view->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), SLOT(updateCurrentTiles())); mViewStack->insertWidget(index, view); QVariant userdata = QVariant::fromValue(view); mDropDown->addItem(tileset->name(), userdata); mDropDown->model()->sort(0); mDropDown->setCurrentIndex(mDropDown->findData(userdata)); }
void TilesetDock::insertTilesetView(int index, Tileset *tileset) { TilesetView *view = new TilesetView(mMapDocument); view->setModel(new TilesetModel(tileset, view)); connect(view->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), SLOT(updateCurrentTiles())); connect(view, SIGNAL(deleteRequested(TilesetView*)), SLOT(deleteRequested(TilesetView*))); mViewStack->insertWidget(index, view); mDropDown->insertItem(index, QIcon(), tileset->name()); mDropDown->setCurrentIndex(index); }
void TilesetEditor::addDocument(Document *document) { TilesetDocument *tilesetDocument = qobject_cast<TilesetDocument*>(document); Q_ASSERT(tilesetDocument); TilesetView *view = new TilesetView(mWidgetStack); view->setTilesetDocument(tilesetDocument); Tileset *tileset = tilesetDocument->tileset().data(); QString path = QLatin1String("TilesetEditor/TilesetScale/") + tileset->name(); qreal scale = Preferences::instance()->settings()->value(path, 1).toReal(); view->zoomable()->setScale(scale); view->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn); view->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); TilesetModel *tilesetModel = new TilesetModel(tileset, view); view->setModel(tilesetModel); connect(tilesetDocument, &TilesetDocument::tileTerrainChanged, tilesetModel, &TilesetModel::tilesChanged); connect(tilesetDocument, &TilesetDocument::tileWangSetChanged, tilesetModel, &TilesetModel::tilesChanged); connect(tilesetDocument, &TilesetDocument::tileImageSourceChanged, tilesetModel, &TilesetModel::tileChanged); connect(tilesetDocument, &TilesetDocument::tileAnimationChanged, tilesetModel, &TilesetModel::tileChanged); connect(tilesetDocument, &TilesetDocument::tilesetChanged, this, &TilesetEditor::tilesetChanged); connect(view, &TilesetView::createNewTerrain, this, &TilesetEditor::addTerrainType); connect(view, &TilesetView::terrainImageSelected, this, &TilesetEditor::setTerrainImage); connect(view, &TilesetView::wangSetImageSelected, this, &TilesetEditor::setWangSetImage); connect(view, &TilesetView::wangColorImageSelected, this, &TilesetEditor::setWangColorImage); connect(view, &TilesetView::wangIdUsedChanged, mWangDock, &WangDock::onWangIdUsedChanged); connect(view, &TilesetView::currentWangIdChanged, mWangDock, &WangDock::onCurrentWangIdChanged); QItemSelectionModel *s = view->selectionModel(); connect(s, &QItemSelectionModel::selectionChanged, this, &TilesetEditor::selectionChanged); connect(s, &QItemSelectionModel::currentChanged, this, &TilesetEditor::currentChanged); connect(view, &TilesetView::pressed, this, &TilesetEditor::indexPressed); mViewForTileset.insert(tilesetDocument, view); mWidgetStack->addWidget(view); }
void TilesetDock::updateCurrentTiles() { TilesetView *view = currentTilesetView(); if (!view) return; const QItemSelectionModel *s = view->selectionModel(); if (!s) return; const QModelIndexList indexes = s->selection().indexes(); if (indexes.isEmpty()) return; const QModelIndex &first = indexes.first(); int minX = first.column(); int maxX = first.column(); int minY = first.row(); int maxY = first.row(); for (const QModelIndex &index : indexes) { if (minX > index.column()) minX = index.column(); if (maxX < index.column()) maxX = index.column(); if (minY > index.row()) minY = index.row(); if (maxY < index.row()) maxY = index.row(); } // Create a tile layer from the current selection TileLayer *tileLayer = new TileLayer(QString(), 0, 0, maxX - minX + 1, maxY - minY + 1); const TilesetModel *model = view->tilesetModel(); for (const QModelIndex &index : indexes) { tileLayer->setCell(index.column() - minX, index.row() - minY, Cell(model->tileAt(index))); } setCurrentTiles(tileLayer); }
void TilesetEditor::selectionChanged() { TilesetView *view = currentTilesetView(); if (!view) return; updateAddRemoveActions(); const QItemSelectionModel *s = view->selectionModel(); const QModelIndexList indexes = s->selection().indexes(); if (indexes.isEmpty()) return; const TilesetModel *model = view->tilesetModel(); QList<Tile*> selectedTiles; for (const QModelIndex &index : indexes) if (Tile *tile = model->tileAt(index)) selectedTiles.append(tile); mCurrentTilesetDocument->setSelectedTiles(selectedTiles); }
void TilesetDock::updateActions() { bool external = false; bool isCollection = false; bool hasSelection = false; TilesetView *view = nullptr; const int index = mTabBar->currentIndex(); if (index > -1) { view = tilesetViewAt(index); if (view) { Tileset *tileset = mTilesets.at(index).data(); if (!view->model()) // Lazily set up the model setupTilesetModel(view, tileset); mViewStack->setCurrentIndex(index); external = tileset->isExternal(); isCollection = tileset->isCollection(); hasSelection = view->selectionModel()->hasSelection(); } } const bool tilesetIsDisplayed = view != nullptr; const bool mapIsDisplayed = mMapDocument != nullptr; mNewTileset->setEnabled(mapIsDisplayed); mImportTileset->setEnabled(tilesetIsDisplayed && external); mExportTileset->setEnabled(tilesetIsDisplayed && !external); mPropertiesTileset->setEnabled(tilesetIsDisplayed); mDeleteTileset->setEnabled(tilesetIsDisplayed); mEditTerrain->setEnabled(tilesetIsDisplayed && !external); mAddTiles->setEnabled(tilesetIsDisplayed && isCollection && !external); mRemoveTiles->setEnabled(tilesetIsDisplayed && isCollection && hasSelection && !external); }