1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 Jochen Becher
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of Qt Creator.
7 **
8 ** Commercial License Usage
9 ** Licensees holding valid commercial Qt licenses may use this file in
10 ** accordance with the commercial license agreement provided with the
11 ** Software or, alternatively, in accordance with the terms contained in
12 ** a written agreement between you and The Qt Company. For licensing terms
13 ** and conditions see https://www.qt.io/terms-conditions. For further
14 ** information use the contact form at https://www.qt.io/contact-us.
15 **
16 ** GNU General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU
18 ** General Public License version 3 as published by the Free Software
19 ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
20 ** included in the packaging of this file. Please review the following
21 ** information to ensure the GNU General Public License requirements will
22 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
23 **
24 ****************************************************************************/
25
26 #include "elementtasks.h"
27
28 #include "modelsmanager.h"
29 #include "openelementvisitor.h"
30 #include "modeleditor_plugin.h"
31 #include "componentviewcontroller.h"
32
33 #include "qmt/diagram/delement.h"
34 #include "qmt/diagram/dpackage.h"
35 #include "qmt/document_controller/documentcontroller.h"
36 #include "qmt/infrastructure/contextmenuaction.h"
37 #include "qmt/model/melement.h"
38 #include "qmt/model/mclass.h"
39 #include "qmt/model/mdiagram.h"
40 #include "qmt/model/mcanvasdiagram.h"
41 #include "qmt/model/mpackage.h"
42 #include "qmt/model_controller/modelcontroller.h"
43 #include "qmt/tasks/finddiagramvisitor.h"
44 #include "qmt/project_controller/projectcontroller.h"
45 #include "qmt/project/project.h"
46
47 #include <extensionsystem/pluginmanager.h>
48 #include <cpptools/cppclassesfilter.h>
49 #include <cpptools/indexitem.h>
50 #include <cpptools/searchsymbols.h>
51 #include <coreplugin/editormanager/editormanager.h>
52 #include <coreplugin/locator/ilocatorfilter.h>
53 #include <utils/qtcassert.h>
54
55 #include <QMenu>
56
57 namespace ModelEditor {
58 namespace Internal {
59
60 class ElementTasks::ElementTasksPrivate {
61 public:
62 qmt::DocumentController *documentController = nullptr;
63 ComponentViewController *componentViewController = nullptr;
64 };
65
ElementTasks(QObject * parent)66 ElementTasks::ElementTasks(QObject *parent)
67 : QObject(parent),
68 d(new ElementTasksPrivate)
69 {
70 }
71
~ElementTasks()72 ElementTasks::~ElementTasks()
73 {
74 delete d;
75 }
76
setDocumentController(qmt::DocumentController * documentController)77 void ElementTasks::setDocumentController(qmt::DocumentController *documentController)
78 {
79 d->documentController = documentController;
80 }
81
setComponentViewController(ComponentViewController * componentViewController)82 void ElementTasks::setComponentViewController(ComponentViewController *componentViewController)
83 {
84 d->componentViewController = componentViewController;
85 }
86
openElement(const qmt::MElement * element)87 void ElementTasks::openElement(const qmt::MElement *element)
88 {
89 OpenModelElementVisitor visitor;
90 visitor.setElementTasks(this);
91 element->accept(&visitor);
92 }
93
openElement(const qmt::DElement * element,const qmt::MDiagram * diagram)94 void ElementTasks::openElement(const qmt::DElement *element, const qmt::MDiagram *diagram)
95 {
96 Q_UNUSED(diagram)
97
98 OpenDiagramElementVisitor visitor;
99 visitor.setModelController(d->documentController->modelController());
100 visitor.setElementTasks(this);
101 element->accept(&visitor);
102 }
103
hasClassDefinition(const qmt::MElement * element) const104 bool ElementTasks::hasClassDefinition(const qmt::MElement *element) const
105 {
106 if (auto klass = dynamic_cast<const qmt::MClass *>(element)) {
107 QString qualifiedClassName = klass->umlNamespace().isEmpty()
108 ? klass->name()
109 : klass->umlNamespace() + "::" + klass->name();
110
111 Core::ILocatorFilter *classesFilter
112 = CppTools::CppModelManager::instance()->classesFilter();
113 if (!classesFilter)
114 return false;
115
116 QFutureInterface<Core::LocatorFilterEntry> dummyInterface;
117 QList<Core::LocatorFilterEntry> matches = classesFilter->matchesFor(dummyInterface,
118 qualifiedClassName);
119 foreach (const Core::LocatorFilterEntry &entry, matches) {
120 CppTools::IndexItem::Ptr info = qvariant_cast<CppTools::IndexItem::Ptr>(entry.internalData);
121 if (info->scopedSymbolName() != qualifiedClassName)
122 continue;
123 return true;
124 }
125 }
126 return false;
127 }
128
hasClassDefinition(const qmt::DElement * element,const qmt::MDiagram * diagram) const129 bool ElementTasks::hasClassDefinition(const qmt::DElement *element,
130 const qmt::MDiagram *diagram) const
131 {
132 Q_UNUSED(diagram)
133
134 qmt::MElement *melement = d->documentController->modelController()->findElement(
135 element->modelUid());
136 if (!melement)
137 return false;
138 return hasClassDefinition(melement);
139 }
140
openClassDefinition(const qmt::MElement * element)141 void ElementTasks::openClassDefinition(const qmt::MElement *element)
142 {
143 if (auto klass = dynamic_cast<const qmt::MClass *>(element)) {
144 QString qualifiedClassName = klass->umlNamespace().isEmpty()
145 ? klass->name()
146 : klass->umlNamespace() + "::" + klass->name();
147
148 Core::ILocatorFilter *classesFilter
149 = CppTools::CppModelManager::instance()->classesFilter();
150 if (!classesFilter)
151 return;
152
153 QFutureInterface<Core::LocatorFilterEntry> dummyInterface;
154 QList<Core::LocatorFilterEntry> matches = classesFilter->matchesFor(dummyInterface, qualifiedClassName);
155 foreach (const Core::LocatorFilterEntry &entry, matches) {
156 CppTools::IndexItem::Ptr info = qvariant_cast<CppTools::IndexItem::Ptr>(entry.internalData);
157 if (info->scopedSymbolName() != qualifiedClassName)
158 continue;
159 if (Core::EditorManager::instance()->openEditorAt(info->fileName(), info->line(), info->column()))
160 return;
161 }
162 }
163 }
164
openClassDefinition(const qmt::DElement * element,const qmt::MDiagram * diagram)165 void ElementTasks::openClassDefinition(const qmt::DElement *element, const qmt::MDiagram *diagram)
166 {
167 Q_UNUSED(diagram)
168
169 qmt::MElement *melement = d->documentController->modelController()->findElement(element->modelUid());
170 if (!melement)
171 return;
172 openClassDefinition(melement);
173 }
174
hasHeaderFile(const qmt::MElement * element) const175 bool ElementTasks::hasHeaderFile(const qmt::MElement *element) const
176 {
177 // TODO implement
178 Q_UNUSED(element)
179 return false;
180 }
181
hasHeaderFile(const qmt::DElement * element,const qmt::MDiagram * diagram) const182 bool ElementTasks::hasHeaderFile(const qmt::DElement *element, const qmt::MDiagram *diagram) const
183 {
184 Q_UNUSED(diagram)
185
186 qmt::MElement *melement = d->documentController->modelController()->findElement(element->modelUid());
187 if (!melement)
188 return false;
189 return hasHeaderFile(melement);
190 }
191
hasSourceFile(const qmt::MElement * element) const192 bool ElementTasks::hasSourceFile(const qmt::MElement *element) const
193 {
194 // TODO implement
195 Q_UNUSED(element)
196 return false;
197 }
198
hasSourceFile(const qmt::DElement * element,const qmt::MDiagram * diagram) const199 bool ElementTasks::hasSourceFile(const qmt::DElement *element, const qmt::MDiagram *diagram) const
200 {
201 Q_UNUSED(diagram)
202
203 qmt::MElement *melement = d->documentController->modelController()->findElement(element->modelUid());
204 if (!melement)
205 return false;
206 return hasSourceFile(melement);
207 }
208
openHeaderFile(const qmt::MElement * element)209 void ElementTasks::openHeaderFile(const qmt::MElement *element)
210 {
211 // TODO implement
212 Q_UNUSED(element)
213 }
214
openHeaderFile(const qmt::DElement * element,const qmt::MDiagram * diagram)215 void ElementTasks::openHeaderFile(const qmt::DElement *element, const qmt::MDiagram *diagram)
216 {
217 Q_UNUSED(diagram)
218
219 qmt::MElement *melement = d->documentController->modelController()->findElement(element->modelUid());
220 if (!melement)
221 return;
222 openHeaderFile(melement);
223 }
224
openSourceFile(const qmt::MElement * element)225 void ElementTasks::openSourceFile(const qmt::MElement *element)
226 {
227 // TODO implement
228 Q_UNUSED(element)
229 }
230
openSourceFile(const qmt::DElement * element,const qmt::MDiagram * diagram)231 void ElementTasks::openSourceFile(const qmt::DElement *element, const qmt::MDiagram *diagram)
232 {
233 Q_UNUSED(diagram)
234
235 qmt::MElement *melement = d->documentController->modelController()->findElement(element->modelUid());
236 if (!melement)
237 return;
238 openSourceFile(melement);
239 }
240
hasFolder(const qmt::MElement * element) const241 bool ElementTasks::hasFolder(const qmt::MElement *element) const
242 {
243 // TODO implement
244 Q_UNUSED(element)
245 return false;
246 }
247
hasFolder(const qmt::DElement * element,const qmt::MDiagram * diagram) const248 bool ElementTasks::hasFolder(const qmt::DElement *element, const qmt::MDiagram *diagram) const
249 {
250 Q_UNUSED(diagram)
251
252 qmt::MElement *melement = d->documentController->modelController()->findElement(element->modelUid());
253 if (!melement)
254 return false;
255 return hasFolder(melement);
256 }
257
showFolder(const qmt::MElement * element)258 void ElementTasks::showFolder(const qmt::MElement *element)
259 {
260 // TODO implement
261 Q_UNUSED(element)
262 }
263
showFolder(const qmt::DElement * element,const qmt::MDiagram * diagram)264 void ElementTasks::showFolder(const qmt::DElement *element, const qmt::MDiagram *diagram)
265 {
266 Q_UNUSED(diagram)
267
268 qmt::MElement *melement = d->documentController->modelController()->findElement(element->modelUid());
269 if (!melement)
270 return;
271 showFolder(melement);
272 }
273
hasDiagram(const qmt::MElement * element) const274 bool ElementTasks::hasDiagram(const qmt::MElement *element) const
275 {
276 qmt::FindDiagramVisitor visitor;
277 element->accept(&visitor);
278 const qmt::MDiagram *diagram = visitor.diagram();
279 return diagram != nullptr;
280 }
281
hasDiagram(const qmt::DElement * element,const qmt::MDiagram * diagram) const282 bool ElementTasks::hasDiagram(const qmt::DElement *element, const qmt::MDiagram *diagram) const
283 {
284 Q_UNUSED(diagram)
285
286 qmt::MElement *melement = d->documentController->modelController()->findElement(element->modelUid());
287 if (!melement)
288 return false;
289 return hasDiagram(melement);
290 }
291
openDiagram(const qmt::MElement * element)292 void ElementTasks::openDiagram(const qmt::MElement *element)
293 {
294 qmt::FindDiagramVisitor visitor;
295 element->accept(&visitor);
296 const qmt::MDiagram *diagram = visitor.diagram();
297 if (diagram) {
298 ModelEditorPlugin::modelsManager()->openDiagram(
299 d->documentController->projectController()->project()->uid(),
300 diagram->uid());
301 }
302 }
303
openDiagram(const qmt::DElement * element,const qmt::MDiagram * diagram)304 void ElementTasks::openDiagram(const qmt::DElement *element, const qmt::MDiagram *diagram)
305 {
306 Q_UNUSED(diagram)
307
308 qmt::MElement *melement = d->documentController->modelController()->findElement(element->modelUid());
309 if (!melement)
310 return;
311 openDiagram(melement);
312 }
313
hasParentDiagram(const qmt::MElement * element) const314 bool ElementTasks::hasParentDiagram(const qmt::MElement *element) const
315 {
316 while (element && element->owner()) {
317 qmt::MObject *parentObject = element->owner()->owner();
318 if (parentObject) {
319 qmt::FindDiagramVisitor visitor;
320 parentObject->accept(&visitor);
321 const qmt::MDiagram *parentDiagram = visitor.diagram();
322 if (parentDiagram) {
323 return true;
324 }
325 }
326 element = element->owner();
327 }
328 return false;
329 }
330
hasParentDiagram(const qmt::DElement * element,const qmt::MDiagram * diagram) const331 bool ElementTasks::hasParentDiagram(const qmt::DElement *element, const qmt::MDiagram *diagram) const
332 {
333 Q_UNUSED(diagram)
334
335 if (!element)
336 return false;
337
338 qmt::MElement *melement = d->documentController->modelController()->findElement(element->modelUid());
339 if (!melement)
340 return false;
341 return hasParentDiagram(melement);
342 }
343
openParentDiagram(const qmt::MElement * element)344 void ElementTasks::openParentDiagram(const qmt::MElement *element)
345 {
346 while (element && element->owner()) {
347 qmt::MObject *parentObject = element->owner()->owner();
348 if (parentObject) {
349 qmt::FindDiagramVisitor visitor;
350 parentObject->accept(&visitor);
351 const qmt::MDiagram *parentDiagram = visitor.diagram();
352 if (parentDiagram) {
353 ModelEditorPlugin::modelsManager()->openDiagram(
354 d->documentController->projectController()->project()->uid(),
355 parentDiagram->uid());
356 return;
357 }
358 }
359 element = element->owner();
360 }
361 }
362
openParentDiagram(const qmt::DElement * element,const qmt::MElement * diagram)363 void ElementTasks::openParentDiagram(const qmt::DElement *element, const qmt::MElement *diagram)
364 {
365 Q_UNUSED(diagram)
366
367 if (!element)
368 return;
369
370 qmt::MElement *melement = d->documentController->modelController()->findElement(element->modelUid());
371 if (!melement)
372 return;
373 openParentDiagram(melement);
374 }
375
mayCreateDiagram(const qmt::MElement * element) const376 bool ElementTasks::mayCreateDiagram(const qmt::MElement *element) const
377 {
378 return dynamic_cast<const qmt::MPackage *>(element) != nullptr;
379 }
380
mayCreateDiagram(const qmt::DElement * element,const qmt::MDiagram * diagram) const381 bool ElementTasks::mayCreateDiagram(const qmt::DElement *element,
382 const qmt::MDiagram *diagram) const
383 {
384 Q_UNUSED(diagram)
385
386 qmt::MElement *melement = d->documentController->modelController()->findElement(element->modelUid());
387 if (!melement)
388 return false;
389 return mayCreateDiagram(melement);
390 }
391
createAndOpenDiagram(const qmt::MElement * element)392 void ElementTasks::createAndOpenDiagram(const qmt::MElement *element)
393 {
394 if (auto package = dynamic_cast<const qmt::MPackage *>(element)) {
395 qmt::FindDiagramVisitor visitor;
396 element->accept(&visitor);
397 const qmt::MDiagram *diagram = visitor.diagram();
398 if (diagram) {
399 ModelEditorPlugin::modelsManager()->openDiagram(
400 d->documentController->projectController()->project()->uid(),
401 diagram->uid());
402 } else {
403 auto newDiagram = new qmt::MCanvasDiagram();
404 newDiagram->setName(package->name());
405 qmt::MPackage *parentPackage = d->documentController->modelController()->findObject<qmt::MPackage>(package->uid());
406 QMT_ASSERT(parentPackage, delete newDiagram; return);
407 d->documentController->modelController()->addObject(parentPackage, newDiagram);
408 ModelEditorPlugin::modelsManager()->openDiagram(
409 d->documentController->projectController()->project()->uid(),
410 newDiagram->uid());
411 }
412 }
413 }
414
createAndOpenDiagram(const qmt::DElement * element,const qmt::MDiagram * diagram)415 void ElementTasks::createAndOpenDiagram(const qmt::DElement *element, const qmt::MDiagram *diagram)
416 {
417 Q_UNUSED(diagram)
418
419 qmt::MElement *melement = d->documentController->modelController()->findElement(element->modelUid());
420 if (!melement)
421 return;
422 createAndOpenDiagram(melement);
423 }
424
extendContextMenu(const qmt::DElement * delement,const qmt::MDiagram *,QMenu * menu)425 bool ElementTasks::extendContextMenu(const qmt::DElement *delement, const qmt::MDiagram *, QMenu *menu)
426 {
427 bool extended = false;
428 if (dynamic_cast<const qmt::DPackage *>(delement)) {
429 menu->addAction(new qmt::ContextMenuAction(tr("Update Include Dependencies"), "updateIncludeDependencies", menu));
430 extended = true;
431 }
432 return extended;
433 }
434
handleContextMenuAction(const qmt::DElement * element,const qmt::MDiagram *,const QString & id)435 bool ElementTasks::handleContextMenuAction(const qmt::DElement *element, const qmt::MDiagram *, const QString &id)
436 {
437 if (id == "updateIncludeDependencies") {
438 qmt::MPackage *mpackage = d->documentController->modelController()->findElement<qmt::MPackage>(element->modelUid());
439 if (mpackage)
440 d->componentViewController->updateIncludeDependencies(mpackage);
441 return true;
442 }
443 return false;
444 }
445
446 } // namespace Internal
447 } // namespace ModelEditor
448