1 /*
2  * objectsdock.cpp
3  * Copyright 2012, Tim Baker <treectrl@hotmail.com>
4  *
5  * This file is part of Tiled.
6  *
7  * This program is free software; you can redistribute it and/or modify it
8  * under the terms of the GNU General Public License as published by the Free
9  * Software Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * This program is distributed in the hope that it will be useful, but WITHOUT
13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
15  * more details.
16  *
17  * You should have received a copy of the GNU General Public License along with
18  * this program. If not, see <http://www.gnu.org/licenses/>.
19  */
20 
21 #include "objectsdock.h"
22 
23 #include "actionmanager.h"
24 #include "documentmanager.h"
25 #include "filteredit.h"
26 #include "grouplayer.h"
27 #include "map.h"
28 #include "mapdocument.h"
29 #include "mapdocumentactionhandler.h"
30 #include "mapobject.h"
31 #include "objectgroup.h"
32 #include "objectsview.h"
33 #include "utils.h"
34 
35 #include <QBoxLayout>
36 #include <QEvent>
37 #include <QLabel>
38 #include <QMenu>
39 #include <QToolBar>
40 #include <QToolButton>
41 #include <QUrl>
42 
43 using namespace Tiled;
44 
ObjectsDock(QWidget * parent)45 ObjectsDock::ObjectsDock(QWidget *parent)
46     : QDockWidget(parent)
47     , mFilterEdit(new FilterEdit(this))
48     , mObjectsView(new ObjectsView)
49     , mMapDocument(nullptr)
50 {
51     setObjectName(QLatin1String("ObjectsDock"));
52 
53     mActionObjectProperties = new QAction(this);
54     mActionObjectProperties->setIcon(QIcon(QLatin1String(":/images/16/document-properties.png")));
55 
56     connect(mActionObjectProperties, &QAction::triggered,
57             this, &ObjectsDock::objectProperties);
58 
59     MapDocumentActionHandler *handler = MapDocumentActionHandler::instance();
60 
61     QWidget *widget = new QWidget(this);
62     QVBoxLayout *layout = new QVBoxLayout(widget);
63     layout->setContentsMargins(0, 0, 0, 0);
64     layout->setSpacing(0);
65     layout->addWidget(mFilterEdit);
66     layout->addWidget(mObjectsView);
67 
68     mFilterEdit->setFilteredView(mObjectsView);
69 
70     connect(mFilterEdit, &QLineEdit::textChanged, mObjectsView, &ObjectsView::setFilter);
71 
72     mActionNewLayer = new QAction(this);
73     mActionNewLayer->setIcon(QIcon(QLatin1String(":/images/16/document-new.png")));
74     connect(mActionNewLayer, &QAction::triggered,
75             handler->actionAddObjectGroup(), &QAction::trigger);
76 
77     mActionMoveToGroup = new QAction(this);
78     mActionMoveToGroup->setIcon(QIcon(QLatin1String(":/images/16/layer-object.png")));
79 
80     mActionMoveUp = new QAction(this);
81     mActionMoveUp->setIcon(QIcon(QLatin1String(":/images/16/go-up.png")));
82     mActionMoveDown = new QAction(this);
83     mActionMoveDown->setIcon(QIcon(QLatin1String(":/images/16/go-down.png")));
84 
85     Utils::setThemeIcon(mActionObjectProperties, "document-properties");
86     Utils::setThemeIcon(mActionMoveUp, "go-up");
87     Utils::setThemeIcon(mActionMoveDown, "go-down");
88 
89     QToolBar *toolBar = new QToolBar;
90     toolBar->setFloatable(false);
91     toolBar->setMovable(false);
92     toolBar->setIconSize(Utils::smallIconSize());
93 
94     toolBar->addAction(mActionNewLayer);
95     toolBar->addAction(handler->actionDuplicateObjects());
96     toolBar->addAction(handler->actionRemoveObjects());
97 
98     toolBar->addAction(mActionMoveUp);
99     toolBar->addAction(mActionMoveDown);
100     toolBar->addAction(mActionMoveToGroup);
101     QToolButton *button;
102     button = dynamic_cast<QToolButton*>(toolBar->widgetForAction(mActionMoveToGroup));
103     mMoveToMenu = new QMenu(this);
104     button->setPopupMode(QToolButton::InstantPopup);
105     button->setMenu(mMoveToMenu);
106     connect(mMoveToMenu, &QMenu::aboutToShow, this, &ObjectsDock::aboutToShowMoveToMenu);
107     connect(mMoveToMenu, &QMenu::triggered, this, &ObjectsDock::triggeredMoveToMenu);
108 
109     toolBar->addAction(mActionObjectProperties);
110 
111     layout->addWidget(toolBar);
112     setWidget(widget);
113     retranslateUi();
114 
115     ActionManager::registerAction(mActionMoveUp, "MoveObjectsUp");
116     ActionManager::registerAction(mActionMoveDown, "MoveObjectsDown");
117 
118     connect(DocumentManager::instance(), &DocumentManager::documentAboutToClose,
119             this, &ObjectsDock::documentAboutToClose);
120 
121     connect(mActionMoveUp, &QAction::triggered, this, &ObjectsDock::moveObjectsUp);
122     connect(mActionMoveDown, &QAction::triggered, this, &ObjectsDock::moveObjectsDown);
123 }
124 
moveObjectsUp()125 void ObjectsDock::moveObjectsUp()
126 {
127     if (mMapDocument)
128         mMapDocument->moveObjectsUp(mMapDocument->selectedObjects());
129 }
130 
moveObjectsDown()131 void ObjectsDock::moveObjectsDown()
132 {
133     if (mMapDocument)
134         mMapDocument->moveObjectsDown(mMapDocument->selectedObjects());
135 }
136 
setMapDocument(MapDocument * mapDoc)137 void ObjectsDock::setMapDocument(MapDocument *mapDoc)
138 {
139     if (mMapDocument) {
140         mObjectsView->saveExpandedLayers();
141         mMapDocument->disconnect(this);
142     }
143 
144     mMapDocument = mapDoc;
145 
146     mObjectsView->setMapDocument(mapDoc);
147 
148     if (mMapDocument) {
149         mObjectsView->restoreExpandedLayers();
150         connect(mMapDocument, &MapDocument::selectedObjectsChanged,
151                 this, &ObjectsDock::updateActions);
152     }
153 
154     updateActions();
155 }
156 
changeEvent(QEvent * e)157 void ObjectsDock::changeEvent(QEvent *e)
158 {
159     QDockWidget::changeEvent(e);
160     switch (e->type()) {
161     case QEvent::LanguageChange:
162         retranslateUi();
163         break;
164     default:
165         break;
166     }
167 }
168 
retranslateUi()169 void ObjectsDock::retranslateUi()
170 {
171     setWindowTitle(tr("Objects"));
172 
173     mFilterEdit->setPlaceholderText(tr("Filter"));
174 
175     mActionNewLayer->setText(tr("Add Object Layer"));
176     mActionObjectProperties->setText(tr("Object Properties"));
177     mActionMoveUp->setText(tr("Move Objects Up"));
178     mActionMoveDown->setText(tr("Move Objects Down"));
179 
180     updateActions();
181 }
182 
updateActions()183 void ObjectsDock::updateActions()
184 {
185     int selectedObjectsCount = 0;
186     int objectGroupCount = 0;
187 
188     if (mMapDocument) {
189         selectedObjectsCount = mMapDocument->selectedObjects().count();
190         objectGroupCount = mMapDocument->map()->objectGroupCount();
191     }
192 
193     mActionObjectProperties->setEnabled(selectedObjectsCount > 0);
194     mActionMoveToGroup->setEnabled(selectedObjectsCount > 0 && objectGroupCount >= 2);
195     mActionMoveToGroup->setToolTip(tr("Move %n Object(s) to Layer", "", selectedObjectsCount));
196     mActionMoveUp->setEnabled(selectedObjectsCount > 0);
197     mActionMoveDown->setEnabled(selectedObjectsCount > 0);
198 }
199 
aboutToShowMoveToMenu()200 void ObjectsDock::aboutToShowMoveToMenu()
201 {
202     mMoveToMenu->clear();
203 
204     for (Layer *layer : mMapDocument->map()->objectGroups()) {
205         QAction *action = mMoveToMenu->addAction(layer->name());
206         action->setData(QVariant::fromValue(static_cast<ObjectGroup*>(layer)));
207     }
208 }
209 
triggeredMoveToMenu(QAction * action)210 void ObjectsDock::triggeredMoveToMenu(QAction *action)
211 {
212     MapDocumentActionHandler *handler = MapDocumentActionHandler::instance();
213 
214     ObjectGroup *objectGroup = action->data().value<ObjectGroup*>();
215     handler->moveObjectsToGroup(objectGroup);
216 }
217 
objectProperties()218 void ObjectsDock::objectProperties()
219 {
220     const auto &selectedObjects = mMapDocument->selectedObjects();
221     mMapDocument->setCurrentObject(selectedObjects.first());
222     emit mMapDocument->editCurrentObject();
223 }
224 
documentAboutToClose(Document * document)225 void ObjectsDock::documentAboutToClose(Document *document)
226 {
227     if (MapDocument *mapDocument = qobject_cast<MapDocument*>(document))
228         mObjectsView->clearExpandedLayers(mapDocument);
229 }
230 
231 #include "moc_objectsdock.cpp"
232