1 
2 /*
3  * wangdock.cpp
4  * Copyright 2017, Benjamin Trotter <bdtrotte@ucsc.edu>
5  *
6  * This file is part of Tiled.
7  *
8  * This program is free software; you can redistribute it and/or modify it
9  * under the terms of the GNU General Public License as published by the Free
10  * Software Foundation; either version 2 of the License, or (at your option)
11  * any later version.
12  *
13  * This program is distributed in the hope that it will be useful, but WITHOUT
14  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
16  * more details.
17  *
18  * You should have received a copy of the GNU General Public License along with
19  * this program. If not, see <http://www.gnu.org/licenses/>.
20  */
21 
22 #include "wangdock.h"
23 
24 #include "changeevents.h"
25 #include "changewangsetdata.h"
26 #include "documentmanager.h"
27 #include "wangcolormodel.h"
28 #include "wangcolorview.h"
29 #include "wangoverlay.h"
30 #include "wangsetmodel.h"
31 #include "wangsetview.h"
32 #include "wangtemplatemodel.h"
33 #include "wangtemplateview.h"
34 #include "map.h"
35 #include "mapdocument.h"
36 #include "tilesetdocument.h"
37 #include "tilesetdocumentsmodel.h"
38 #include "tilesetwangsetmodel.h"
39 #include "utils.h"
40 
41 #include <QAction>
42 #include <QEvent>
43 #include <QBoxLayout>
44 #include <QPushButton>
45 #include <QSortFilterProxyModel>
46 #include <QSplitter>
47 #include <QTabWidget>
48 #include <QToolBar>
49 #include <QTreeView>
50 #include <QUndoStack>
51 #include <QToolButton>
52 #include <QMenu>
53 #include <QPainter>
54 #include <QScopedValueRollback>
55 #include <QStackedWidget>
56 #include <QLabel>
57 
58 using namespace Tiled;
59 
60 namespace Tiled {
61 
62 class NoWangSetWidget : public QWidget
63 {
64     Q_OBJECT
65 
66 public:
NoWangSetWidget(QWidget * parent=nullptr)67     explicit NoWangSetWidget(QWidget *parent = nullptr)
68         : QWidget(parent)
69     {
70         QLabel *label = new QLabel(this);
71         label->setWordWrap(true);
72         label->setText(tr("<p>No tileset with Terrain Sets available.</p>"
73                           "<p>Open a tileset with a Terrain Set or set up a new Terrain Set to be able to use the Terrain Brush or the Terrain Fill Mode.</p>"));
74 
75         QGridLayout *gridLayout = new QGridLayout(this);
76         gridLayout->addWidget(label, 0, 0, Qt::AlignTop);
77     }
78 };
79 
firstWangSet(MapDocument * mapDocument)80 static WangSet *firstWangSet(MapDocument *mapDocument)
81 {
82     for (const SharedTileset &tileset : mapDocument->map()->tilesets())
83         if (tileset->wangSetCount() > 0)
84             return tileset->wangSet(0);
85 
86     return nullptr;
87 }
88 
firstWangSet(TilesetDocument * tilesetDocument)89 static WangSet *firstWangSet(TilesetDocument *tilesetDocument)
90 {
91     Tileset *tileset = tilesetDocument->tileset().data();
92     if (tileset->wangSetCount() > 0)
93         return tileset->wangSet(0);
94 
95     return nullptr;
96 }
97 
98 class HasChildrenFilterModel : public QSortFilterProxyModel
99 {
100 public:
HasChildrenFilterModel(QObject * parent=nullptr)101     explicit HasChildrenFilterModel(QObject *parent = nullptr)
102         : QSortFilterProxyModel(parent)
103         , mEnabled(true)
104     {
105     }
106 
setEnabled(bool enabled)107     void setEnabled(bool enabled) { mEnabled = enabled; }
108 
109 protected:
filterAcceptsRow(int sourceRow,const QModelIndex & sourceParent) const110     bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override
111     {
112         if (!mEnabled)
113             return true;
114         if (sourceParent.isValid())
115             return true;
116 
117         const QAbstractItemModel *model = sourceModel();
118         const QModelIndex index = model->index(sourceRow, 0, sourceParent);
119         return index.isValid() && model->hasChildren(index);
120     }
121 
122     bool mEnabled;
123 };
124 
125 } // namespace Tiled
126 
WangDock(QWidget * parent)127 WangDock::WangDock(QWidget *parent)
128     : QDockWidget(parent)
129     , mWangSetToolBar(new QToolBar(this))
130     , mWangColorToolBar(new QToolBar(this))
131     , mNewWangSetButton(new QToolButton(this))
132     , mNewWangSetMenu(new QMenu(this))
133     , mAddCornerWangSet(new QAction(this))
134     , mAddEdgeWangSet(new QAction(this))
135     , mAddMixedWangSet(new QAction(this))
136     , mDuplicateWangSet(new QAction(this))
137     , mRemoveWangSet(new QAction(this))
138     , mAddColor(new QAction(this))
139     , mRemoveColor(new QAction(this))
140     , mStack(new QStackedWidget)
141     , mTilesetDocumentFilterModel(new TilesetDocumentsFilterModel(this))
142     , mWangColorModel(nullptr)
143     , mWangColorFilterModel(new QSortFilterProxyModel(this))
144     , mWangSetModel(new WangSetModel(mTilesetDocumentFilterModel, this))
145     , mWangSetProxyModel(new HasChildrenFilterModel(this))
146     , mWangTemplateModel(new WangTemplateModel(nullptr, this))
147 {
148     setObjectName(QLatin1String("WangSetDock"));
149 
150     mWangSetView = new WangSetView;
151     mWangSetView->setModel(mWangSetProxyModel);
152     connect(mWangSetView->selectionModel(), &QItemSelectionModel::currentRowChanged,
153             this, &WangDock::refreshCurrentWangSet);
154     connect(mWangSetView, &QAbstractItemView::pressed,
155             this, &WangDock::wangSetIndexPressed);
156 
157     connect(mWangSetProxyModel, &QAbstractItemModel::rowsRemoved,
158             this, &WangDock::checkAnyWangSets);
159     connect(mWangSetProxyModel, &QAbstractItemModel::rowsInserted,
160             this, &WangDock::checkAnyWangSets);
161     connect(mWangSetProxyModel, &QAbstractItemModel::modelReset,
162             this, &WangDock::checkAnyWangSets);
163     connect(mWangSetProxyModel, &QAbstractItemModel::rowsInserted,
164             this, &WangDock::expandRows);
165 
166     mNewWangSetMenu->addAction(mAddCornerWangSet);
167     mNewWangSetMenu->addAction(mAddEdgeWangSet);
168     mNewWangSetMenu->addAction(mAddMixedWangSet);
169 
170     mNewWangSetButton->setPopupMode(QToolButton::InstantPopup);
171     mNewWangSetButton->setMenu(mNewWangSetMenu);
172     mNewWangSetButton->setIcon(QIcon(QStringLiteral(":/images/22/add.png")));
173 
174     mAddCornerWangSet->setIcon(wangSetIcon(WangSet::Corner));
175     mAddEdgeWangSet->setIcon(wangSetIcon(WangSet::Edge));
176     mAddMixedWangSet->setIcon(wangSetIcon(WangSet::Mixed));
177 
178     mDuplicateWangSet->setIcon(QIcon(QStringLiteral(":/images/16/stock-duplicate-16.png")));
179     mDuplicateWangSet->setEnabled(false);
180     mRemoveWangSet->setIcon(QIcon(QStringLiteral(":/images/22/remove.png")));
181     mRemoveWangSet->setEnabled(false);
182 
183     mAddColor->setIcon(QIcon(QStringLiteral(":/images/22/add-edge.png")));
184     mAddColor->setEnabled(false);
185     mRemoveColor->setIcon(QIcon(QStringLiteral(":/images/22/remove.png")));
186     mRemoveColor->setEnabled(false);
187 
188     Utils::setThemeIcon(mNewWangSetButton, "add");
189     Utils::setThemeIcon(mRemoveWangSet, "remove");
190     Utils::setThemeIcon(mAddColor, "add");
191     Utils::setThemeIcon(mRemoveColor, "remove");
192 
193     mWangSetToolBar->setFloatable(false);
194     mWangSetToolBar->setMovable(false);
195     mWangSetToolBar->setIconSize(Utils::smallIconSize());
196 
197     mWangSetToolBar->addWidget(mNewWangSetButton);
198     mWangSetToolBar->addAction(mDuplicateWangSet);
199     mWangSetToolBar->addAction(mRemoveWangSet);
200 
201     connect(mAddCornerWangSet, &QAction::triggered, this, [this] { addWangSetRequested(WangSet::Corner); });
202     connect(mAddEdgeWangSet, &QAction::triggered, this, [this] { addWangSetRequested(WangSet::Edge); });
203     connect(mAddMixedWangSet, &QAction::triggered, this, [this] { addWangSetRequested(WangSet::Mixed); });
204     connect(mDuplicateWangSet, &QAction::triggered, this, &WangDock::duplicateWangSetRequested);
205     connect(mRemoveWangSet, &QAction::triggered, this, &WangDock::removeWangSetRequested);
206 
207     mWangColorToolBar->setFloatable(false);
208     mWangColorToolBar->setMovable(false);
209     mWangColorToolBar->setIconSize(Utils::smallIconSize());
210 
211     mWangColorToolBar->addAction(mAddColor);
212     mWangColorToolBar->addAction(mRemoveColor);
213 
214     connect(mAddColor, &QAction::triggered,
215             this, &WangDock::addColor);
216     connect(mRemoveColor, &QAction::triggered,
217             this, &WangDock::removeColor);
218 
219     mWangTemplateView = new WangTemplateView;
220     mWangTemplateView->setModel(mWangTemplateModel);
221 
222     connect(mWangTemplateView->selectionModel(), &QItemSelectionModel::currentChanged,
223             this, &WangDock::refreshCurrentWangId);
224 
225     mWangColorView = new WangColorView;
226     mWangColorView->setModel(mWangColorFilterModel);
227 
228     connect(mWangColorView->selectionModel(), &QItemSelectionModel::currentRowChanged,
229             this, &WangDock::refreshCurrentWangColor);
230     connect(mWangColorView, &QAbstractItemView::pressed,
231             this, &WangDock::wangColorIndexPressed);
232 
233     mEraseWangIdsButton = new QPushButton(this);
234     mEraseWangIdsButton->setIconSize(Utils::smallIconSize());
235     mEraseWangIdsButton->setIcon(QIcon(QLatin1String(":images/22/stock-tool-eraser.png")));
236     mEraseWangIdsButton->setCheckable(true);
237     mEraseWangIdsButton->setAutoExclusive(true);
238     mEraseWangIdsButton->setChecked(mCurrentWangId == 0);
239 
240     connect(mEraseWangIdsButton, &QPushButton::clicked,
241             this, &WangDock::activateErase);
242 
243     // WangSet layout
244 
245     QHBoxLayout *wangSetHorizontal = new QHBoxLayout;
246     wangSetHorizontal->addSpacerItem(new QSpacerItem(0, 0, QSizePolicy::MinimumExpanding));
247     wangSetHorizontal->addWidget(mWangSetToolBar);
248 
249     QWidget *wangSetWidget = new QWidget;
250     QVBoxLayout *wangSetVertical = new QVBoxLayout(wangSetWidget);
251     wangSetVertical->setContentsMargins(0, 0, 0, 0);
252     wangSetVertical->addWidget(mWangSetView);
253     wangSetVertical->addLayout(wangSetHorizontal);
254 
255     // WangColor and templates layout
256 
257     QHBoxLayout *colorViewHorizontal = new QHBoxLayout;
258     colorViewHorizontal->addSpacerItem(new QSpacerItem(0, 0, QSizePolicy::MinimumExpanding));
259     colorViewHorizontal->addWidget(mWangColorToolBar);
260 
261     mWangColorWidget = new QWidget;
262     QVBoxLayout *colorViewVertical = new QVBoxLayout(mWangColorWidget);
263     colorViewVertical->setContentsMargins(0, 0, 0, 0);
264     colorViewVertical->addWidget(mWangColorView);
265     colorViewVertical->addLayout(colorViewHorizontal);
266 
267     mTemplateAndColorView = new QTabWidget;
268     mTemplateAndColorView->setDocumentMode(true);
269     mTemplateAndColorView->addTab(mWangColorWidget, tr("Terrains"));
270     mTemplateAndColorView->addTab(mWangTemplateView, tr("Patterns"));
271 
272     QHBoxLayout *templateAndColorHorizontal = new QHBoxLayout;
273     templateAndColorHorizontal->addWidget(mEraseWangIdsButton);
274     templateAndColorHorizontal->addSpacerItem(new QSpacerItem(0, 0, QSizePolicy::MinimumExpanding));
275 
276     mTemplateAndColorWidget = new QWidget;
277     QVBoxLayout *templateAndColorVertical = new QVBoxLayout(mTemplateAndColorWidget);
278     templateAndColorVertical->setContentsMargins(0, 0, 0, 0);
279     templateAndColorVertical->addWidget(mTemplateAndColorView);
280     templateAndColorVertical->addLayout(templateAndColorHorizontal);
281 
282     // Splitter combining the WangSet and WangColor views
283 
284     QSplitter *wangViews = new QSplitter;
285     wangViews->setOrientation(Qt::Vertical);
286     wangViews->addWidget(wangSetWidget);
287     wangViews->addWidget(mTemplateAndColorWidget);
288     wangViews->setCollapsible(1, false);
289 
290     // View stack for showing the "No Terrain Sets defined" widget
291 
292     mStack->insertWidget(0, new NoWangSetWidget);
293     mStack->insertWidget(1, wangViews);
294     mStack->setCurrentIndex(1);
295 
296     hideTemplateColorView();
297     setWidget(mStack);
298     retranslateUi();
299 }
300 
~WangDock()301 WangDock::~WangDock()
302 {
303 }
304 
setDocument(Document * document)305 void WangDock::setDocument(Document *document)
306 {
307     if (mDocument == document)
308         return;
309 
310     if (auto tilesetDocument = qobject_cast<TilesetDocument*>(mDocument))
311         tilesetDocument->disconnect(this);
312 
313     mDocument = document;
314     QScopedValueRollback<bool> initializing(mInitializing, true);
315 
316     if (auto mapDocument = qobject_cast<MapDocument*>(document)) {
317         mTilesetDocumentFilterModel->setMapDocument(mapDocument);
318 
319         mWangSetProxyModel->setEnabled(true);
320         mWangSetProxyModel->setSourceModel(mWangSetModel);
321         mWangSetView->expandAll();
322 
323         setCurrentWangSet(firstWangSet(mapDocument));
324 
325         setColorView();
326         mWangSetToolBar->setVisible(false);
327         mWangColorToolBar->setVisible(false);
328         mWangColorView->setReadOnly(true);
329 
330         mTemplateAndColorView->setTabEnabled(1, false);
331         mTemplateAndColorView->tabBar()->hide();
332     } else if (auto tilesetDocument = qobject_cast<TilesetDocument*>(document)) {
333         TilesetWangSetModel *wangSetModel = tilesetDocument->wangSetModel();
334 
335         mWangSetView->setTilesetDocument(tilesetDocument);
336         mWangSetProxyModel->setEnabled(false);
337         mWangSetProxyModel->setSourceModel(wangSetModel);
338 
339         setCurrentWangSet(firstWangSet(tilesetDocument));
340 
341         connect(wangSetModel, &TilesetWangSetModel::wangSetChanged,
342                 mWangTemplateModel, &WangTemplateModel::wangSetChanged);
343         connect(wangSetModel, &TilesetWangSetModel::wangSetChanged,
344                 this, &WangDock::wangSetChanged);
345 
346         mWangSetToolBar->setVisible(true);
347         mWangColorToolBar->setVisible(true);
348         mWangColorView->setReadOnly(false);
349 
350         mTemplateAndColorView->setTabEnabled(1, true);
351         mTemplateAndColorView->tabBar()->show();
352 
353         /*
354          * Removing a WangSet usually changes the selected WangSet without the
355          * selection changing rows, so we can't rely on the currentRowChanged
356          * signal.
357          */
358         connect(wangSetModel, &TilesetWangSetModel::wangSetRemoved,
359                 this, &WangDock::refreshCurrentWangSet);
360 
361         connect(tilesetDocument, &Document::changed, this, &WangDock::documentChanged);
362 
363     } else {
364         mWangSetProxyModel->setSourceModel(nullptr);
365         setCurrentWangSet(nullptr);
366         mWangSetToolBar->setVisible(false);
367         mWangColorToolBar->setVisible(false);
368     }
369 }
370 
editWangSetName(WangSet * wangSet)371 void WangDock::editWangSetName(WangSet *wangSet)
372 {
373     const QModelIndex index = wangSetIndex(wangSet);
374 
375     QItemSelectionModel *selectionModel = mWangSetView->selectionModel();
376     selectionModel->setCurrentIndex(index,
377                                     QItemSelectionModel::ClearAndSelect |
378                                     QItemSelectionModel::Rows);
379 
380     mWangSetView->edit(index);
381 }
382 
editWangColorName(int colorIndex)383 void WangDock::editWangColorName(int colorIndex)
384 {
385     const QModelIndex index = mWangColorModel->colorIndex(colorIndex);
386     if (!index.isValid())
387         return;
388 
389     const QModelIndex viewIndex = static_cast<QAbstractProxyModel*>(mWangColorView->model())->mapFromSource(index);
390     if (!viewIndex.isValid())
391         return;
392 
393     QItemSelectionModel *selectionModel = mWangColorView->selectionModel();
394     selectionModel->setCurrentIndex(viewIndex,
395                                     QItemSelectionModel::ClearAndSelect |
396                                     QItemSelectionModel::Rows);
397 
398     mWangColorView->edit(viewIndex);
399 }
400 
changeEvent(QEvent * event)401 void WangDock::changeEvent(QEvent *event)
402 {
403     QDockWidget::changeEvent(event);
404     switch (event->type()) {
405     case QEvent::LanguageChange:
406         retranslateUi();
407         break;
408     default:
409         break;
410     }
411 }
412 
refreshCurrentWangSet()413 void WangDock::refreshCurrentWangSet()
414 {
415     QItemSelectionModel *selectionModel = mWangSetView->selectionModel();
416     WangSet *wangSet = mWangSetView->wangSetAt(selectionModel->currentIndex());
417     setCurrentWangSet(wangSet);
418 }
419 
refreshCurrentWangId()420 void WangDock::refreshCurrentWangId()
421 {
422     QItemSelectionModel *selectionModel = mWangTemplateView->selectionModel();
423     WangId wangId = mWangTemplateModel->wangIdAt(selectionModel->currentIndex());
424 
425     if (mCurrentWangId == wangId)
426         return;
427 
428     mCurrentWangId = wangId;
429 
430     mEraseWangIdsButton->setChecked(!mCurrentWangId);
431 
432     emit currentWangIdChanged(mCurrentWangId);
433 }
434 
refreshCurrentWangColor()435 void WangDock::refreshCurrentWangColor()
436 {
437     QItemSelectionModel *selectionModel = mWangColorView->selectionModel();
438     const auto currentIndex = selectionModel->currentIndex();
439     int color = 0;
440 
441     if (currentIndex.isValid()) {
442         QModelIndex index = static_cast<QAbstractProxyModel*>(mWangColorView->model())->mapToSource(currentIndex);
443         color = mWangColorModel->colorAt(index);
444     }
445 
446     mEraseWangIdsButton->setChecked(color == 0);
447     mRemoveColor->setEnabled(color != 0);
448     emit wangColorChanged(color);
449 }
450 
wangColorIndexPressed(const QModelIndex & index)451 void WangDock::wangColorIndexPressed(const QModelIndex &index)
452 {
453     const int color = mWangColorModel->colorAt(index);
454     if (!color)
455         return;
456 
457     WangColor *currentWangColor = mCurrentWangSet->colorAt(color).data();
458     mDocument->setCurrentObject(currentWangColor, mWangColorModel->tilesetDocument());
459 
460     emit selectWangBrush();
461 }
462 
documentChanged(const ChangeEvent & change)463 void WangDock::documentChanged(const ChangeEvent &change)
464 {
465     switch (change.type) {
466     case ChangeEvent::WangSetChanged:
467         if (static_cast<const WangSetChangeEvent&>(change).properties & WangSetChangeEvent::TypeProperty)
468             mWangTemplateModel->wangSetChanged();
469         break;
470     default:
471         break;
472     }
473 }
474 
wangSetChanged()475 void WangDock::wangSetChanged()
476 {
477     mWangColorModel->resetModel();
478     mWangColorView->expandAll();
479 
480     refreshCurrentWangColor();
481     refreshCurrentWangId();
482 
483     updateAddColorStatus();
484 }
485 
wangSetIndexPressed(const QModelIndex & index)486 void WangDock::wangSetIndexPressed(const QModelIndex &index)
487 {
488     if (WangSet *wangSet = mWangSetView->wangSetAt(index)) {
489         mDocument->setCurrentObject(wangSet,
490                                     mWangSetView->tilesetDocumentAt(index));
491     }
492 }
493 
expandRows(const QModelIndex & parent,int first,int last)494 void WangDock::expandRows(const QModelIndex &parent, int first, int last)
495 {
496     if (parent.isValid())
497         return;
498 
499     for (int row = first; row <= last; ++row)
500         mWangSetView->expand(mWangSetProxyModel->index(row, 0, parent));
501 }
502 
checkAnyWangSets()503 void WangDock::checkAnyWangSets()
504 {
505     if (mDocument && mDocument->type() == Document::MapDocumentType) {
506         const int rows = mWangSetProxyModel->rowCount();
507         mStack->setCurrentIndex(rows > 0 ? 1 : 0);
508     }
509     refreshCurrentWangSet();
510 }
511 
addColor()512 void WangDock::addColor()
513 {
514     Q_ASSERT(mCurrentWangSet);
515 
516     if (TilesetDocument *tilesetDocument = qobject_cast<TilesetDocument*>(mDocument)) {
517         tilesetDocument->undoStack()->push(new ChangeWangSetColorCount(tilesetDocument,
518                                                                        mCurrentWangSet,
519                                                                        mCurrentWangSet->colorCount() + 1));
520         editWangColorName(mCurrentWangSet->colorCount());
521     }
522 }
523 
removeColor()524 void WangDock::removeColor()
525 {
526     Q_ASSERT(mCurrentWangSet);
527 
528     TilesetDocument *tilesetDocument = qobject_cast<TilesetDocument*>(mDocument);
529     if (!tilesetDocument)
530         return;
531 
532     const QItemSelectionModel *selectionModel = mWangColorView->selectionModel();
533     const QModelIndex index = static_cast<QAbstractProxyModel*>(mWangColorView->model())->mapToSource(selectionModel->currentIndex());
534     const int color = mWangColorModel->colorAt(index);
535     tilesetDocument->undoStack()->push(new RemoveWangSetColor(tilesetDocument,
536                                                               mCurrentWangSet,
537                                                               color));
538 }
539 
setCurrentWangSet(WangSet * wangSet)540 void WangDock::setCurrentWangSet(WangSet *wangSet)
541 {
542     if (mCurrentWangSet == wangSet)
543         return;
544 
545     mWangColorModel = nullptr;
546     TilesetDocument *tilesetDocument = nullptr;
547 
548     if (wangSet) {
549         auto sharedTileset = wangSet->tileset()->sharedPointer();
550         auto documentManager = DocumentManager::instance();
551 
552         tilesetDocument = documentManager->findTilesetDocument(sharedTileset);
553         if (tilesetDocument)
554             mWangColorModel = tilesetDocument->wangColorModel(wangSet);
555 
556         mWangColorView->setTileSize(sharedTileset->tileSize());
557     }
558 
559     mCurrentWangSet = wangSet;
560 
561     emit currentWangSetChanged(mCurrentWangSet);
562 
563     mWangTemplateModel->setWangSet(wangSet);
564     mWangColorFilterModel->setSourceModel(mWangColorModel);
565     mWangColorView->expandAll();
566 
567     mRemoveColor->setEnabled(false);
568 
569     activateErase();
570 
571     if (wangSet) {
572         mWangSetView->setCurrentIndex(wangSetIndex(wangSet));
573 
574         if (!mWangTemplateView->isVisible() && !mWangColorView->isVisible())
575             setColorView();
576 
577         if (wangSet->colorCount() > 0 && !mWangTemplateView->isVisible()) {
578             const QModelIndex index = mWangColorModel->colorIndex(1);
579             mWangColorView->setCurrentIndex(static_cast<QAbstractProxyModel*>(mWangColorView->model())->mapFromSource(index));
580         }
581 
582         updateAddColorStatus();
583     } else {
584         mWangSetView->selectionModel()->clearCurrentIndex();
585         mWangSetView->selectionModel()->clearSelection();
586 
587         hideTemplateColorView();
588 
589         mAddColor->setEnabled(false);
590     }
591 
592     if (wangSet && !mInitializing && tilesetDocument)
593         mDocument->setCurrentObject(wangSet, tilesetDocument);
594 
595     mDuplicateWangSet->setEnabled(wangSet);
596     mRemoveWangSet->setEnabled(wangSet);
597 }
598 
activateErase()599 void WangDock::activateErase()
600 {
601     mEraseWangIdsButton->setChecked(true);
602 
603     mCurrentWangId = WangId();
604 
605     mWangTemplateView->selectionModel()->clearCurrentIndex();
606     mWangTemplateView->selectionModel()->clearSelection();
607     mWangColorView->selectionModel()->clearCurrentIndex();
608     mWangColorView->selectionModel()->clearSelection();
609 
610     emit wangColorChanged(0);
611 }
612 
updateAddColorStatus()613 void WangDock::updateAddColorStatus()
614 {
615     mAddColor->setEnabled(mCurrentWangSet->colorCount() < WangId::MAX_COLOR_COUNT);
616 }
617 
retranslateUi()618 void WangDock::retranslateUi()
619 {
620     setWindowTitle(tr("Terrain Sets"));
621 
622     mEraseWangIdsButton->setText(tr("Erase Terrain"));
623     mNewWangSetButton->setToolTip(tr("Add Terrain Set"));
624     mAddCornerWangSet->setText(tr("New Corner Set"));
625     mAddEdgeWangSet->setText(tr("New Edge Set"));
626     mAddMixedWangSet->setText(tr("New Mixed Set"));
627     mDuplicateWangSet->setText(tr("Duplicate Terrain Set"));
628     mRemoveWangSet->setText(tr("Remove Terrain Set"));
629     mAddColor->setText(tr("Add Terrain"));
630     mRemoveColor->setText(tr("Remove Terrain"));
631 
632     mTemplateAndColorView->setTabText(0, tr("Terrains"));
633     mTemplateAndColorView->setTabText(1, tr("Patterns"));
634 }
635 
wangSetIndex(WangSet * wangSet) const636 QModelIndex WangDock::wangSetIndex(WangSet *wangSet) const
637 {
638     QModelIndex sourceIndex;
639 
640     if (mDocument->type() == Document::MapDocumentType)
641         sourceIndex = mWangSetModel->index(wangSet);
642     else if (auto tilesetDocument = qobject_cast<TilesetDocument*>(mDocument))
643         sourceIndex = tilesetDocument->wangSetModel()->index(wangSet);
644 
645     return mWangSetProxyModel->mapFromSource(sourceIndex);
646 }
647 
onWangIdUsedChanged(WangId wangId)648 void WangDock::onWangIdUsedChanged(WangId wangId)
649 {
650     const QModelIndex index = mWangTemplateModel->wangIdIndex(wangId);
651 
652     if (index.isValid())
653         mWangTemplateView->update(index);
654 }
655 
onColorCaptured(int color)656 void WangDock::onColorCaptured(int color)
657 {
658     const QModelIndex index = mWangColorModel->colorIndex(color);
659 
660     if (index.isValid()) {
661         mWangColorView->setCurrentIndex(static_cast<QAbstractProxyModel*>(mWangColorView->model())->mapFromSource(index));
662     } else {
663         mWangColorView->selectionModel()->clearCurrentIndex();
664         mWangColorView->selectionModel()->clearSelection();
665     }
666 }
667 
onCurrentWangIdChanged(WangId wangId)668 void WangDock::onCurrentWangIdChanged(WangId wangId)
669 {
670     const QModelIndex index = mWangTemplateModel->wangIdIndex(wangId);
671     if (!index.isValid()) {
672         activateErase();
673         return;
674     }
675 
676     QItemSelectionModel *selectionModel = mWangTemplateView->selectionModel();
677 
678     //this emits current changed, and thus updates the wangId and such.
679     selectionModel->setCurrentIndex(index, QItemSelectionModel::SelectCurrent);
680 }
681 
setColorView()682 void WangDock::setColorView()
683 {
684     mTemplateAndColorWidget->setVisible(true);
685     mTemplateAndColorView->setCurrentWidget(mWangColorWidget);
686     retranslateUi();
687 }
688 
hideTemplateColorView()689 void WangDock::hideTemplateColorView()
690 {
691     mTemplateAndColorWidget->setVisible(false);
692 }
693 
694 #include "wangdock.moc"
695 #include "moc_wangdock.cpp"
696