1 /**
2 * UGENE - Integrated Bioinformatics Tools.
3 * Copyright (C) 2008-2021 UniPro <ugene@unipro.ru>
4 * http://ugene.net
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 * MA 02110-1301, USA.
20 */
21
22 #include "ObjectViewModel.h"
23
24 #include <QScrollArea>
25 #include <QSplitter>
26 #include <QVBoxLayout>
27
28 #include <U2Core/AppContext.h>
29 #include <U2Core/DocumentModel.h>
30 #include <U2Core/GObject.h>
31 #include <U2Core/Log.h>
32 #include <U2Core/ProjectModel.h>
33 #include <U2Core/TextUtils.h>
34 #include <U2Core/U2SafePoints.h>
35
36 #include <U2Gui/OptionsPanel.h>
37 #include <U2Gui/OptionsPanelWidget.h>
38
39 // BUG:535 refactor closing interface.
40 // Idea: make it QObject and call 'deleteLater' on it
41
42 namespace U2 {
43
44 const QString GObjectViewState::APP_CLOSING_STATE_NAME("Auto saved");
45 const GObjectViewFactoryId GObjectViewFactory::SIMPLE_TEXT_FACTORY("SimpleTextView");
46 const QString GObjectViewMenuType::CONTEXT("gobject-view-menu-type-context");
47 const QString GObjectViewMenuType::STATIC("object-view-menu-type-static");
48
setViewName(const QString & newName)49 void GObjectViewState::setViewName(const QString &newName) {
50 // this method is not a real state modification: state caches view name as a reference, but not its internal data
51 // it is used only on view renaming
52 viewName = newName;
53 }
54
setStateName(const QString & newName)55 void GObjectViewState::setStateName(const QString &newName) {
56 if (newName == stateName) {
57 return;
58 }
59 stateName = newName;
60 emit si_stateModified(this);
61 }
62
setStateData(const QVariantMap & data)63 void GObjectViewState::setStateData(const QVariantMap &data) {
64 stateData = data;
65 emit si_stateModified(this);
66 }
67
registerGObjectViewFactory(GObjectViewFactory * f)68 void GObjectViewFactoryRegistry::registerGObjectViewFactory(GObjectViewFactory *f) {
69 mapping[f->getId()] = f;
70 }
71
unregisterGObjectViewFactory(GObjectViewFactory * f)72 void GObjectViewFactoryRegistry::unregisterGObjectViewFactory(GObjectViewFactory *f) {
73 assert(GObjectViewUtils::findViewsByFactoryId(f->getId()).isEmpty());
74 mapping.remove(f->getId());
75 }
76
getFactoryById(GObjectViewFactoryId t) const77 GObjectViewFactory *GObjectViewFactoryRegistry::getFactoryById(GObjectViewFactoryId t) const {
78 return mapping.value(t, nullptr);
79 }
80
81 //////////////////////////////////////////////////////////////////////////
82 /// GObjectViewFactory
83
isStateInSelection(const MultiGSelection &,const QVariantMap &)84 bool GObjectViewFactory::isStateInSelection(const MultiGSelection &, const QVariantMap &) {
85 return false;
86 }
87
createViewTask(const QString &,const QVariantMap &)88 Task *GObjectViewFactory::createViewTask(const QString &, const QVariantMap &) {
89 SAFE_POINT(false, "createViewTask from state is not supported by the view", nullptr);
90 }
91
92 //////////////////////////////////////////////////////////////////////////
93 /// GObjectView
GObjectView(GObjectViewFactoryId _factoryId,const QString & _viewName,QObject * prnt)94 GObjectView::GObjectView(GObjectViewFactoryId _factoryId, const QString &_viewName, QObject *prnt)
95 : QObject(prnt) {
96 factoryId = _factoryId;
97 viewName = _viewName;
98 widget = nullptr;
99 optionsPanel = nullptr;
100 closeInterface = nullptr;
101 closing = false;
102
103 Project *project = AppContext::getProject();
104 SAFE_POINT(project != nullptr, "project is null in GObjectView()", );
105
106 connect(project, SIGNAL(si_documentAdded(Document *)), SLOT(sl_onDocumentAdded(Document *)));
107 connect(project, SIGNAL(si_documentRemoved(Document *)), SLOT(sl_onDocumentRemoved(Document *)));
108 for (Document *document : qAsConst(project->getDocuments())) {
109 sl_onDocumentAdded(document);
110 }
111 }
112
canAddObject(GObject * obj)113 bool GObjectView::canAddObject(GObject *obj) {
114 if (objects.contains(obj)) {
115 // the 'obj' is already in the view.
116 return false;
117 }
118 for (GObjectViewObjectHandler *objectHandler : qAsConst(objectHandlers)) {
119 if (objectHandler->canHandle(this, obj)) {
120 return true;
121 }
122 }
123 return false;
124 }
125
addObject(GObject * o)126 QString GObjectView::addObject(GObject *o) {
127 if (closing) {
128 return tr("Can't add object: %1 to the closing view").arg(o->getGObjectName());
129 }
130 if (objects.contains(o)) {
131 return tr("Object is already added to view %1!").arg(o->getGObjectName());
132 }
133
134 bool canBeAdded = canAddObject(o);
135 if (!canBeAdded) {
136 for (GObjectViewObjectHandler *objectHandler : qAsConst(objectHandlers)) {
137 canBeAdded = objectHandler->canHandle(this, o);
138 if (canBeAdded) {
139 break;
140 }
141 }
142 }
143
144 if (!canBeAdded) {
145 return tr("Can't add object: %1").arg(o->getGObjectName());
146 }
147
148 objects << o;
149 onObjectAdded(o);
150 emit si_objectAdded(this, o);
151 return QString();
152 }
153
_removeObject(GObject * o)154 void GObjectView::_removeObject(GObject *o) {
155 o->disconnect(this);
156 int i = objects.removeAll(o);
157 assert(i == 1);
158 Q_UNUSED(i);
159 closing = onObjectRemoved(o) || closing;
160 emit si_objectRemoved(this, o);
161
162 if (requiredObjects.contains(o)) {
163 closing = true;
164 }
165 }
166
removeObject(GObject * o)167 void GObjectView::removeObject(GObject *o) {
168 assert(!closing);
169 _removeObject(o);
170 if (closing) {
171 SAFE_POINT(closeInterface != nullptr, "No close interface", );
172 closeInterface->closeView();
173 }
174 }
175
sl_onObjectRemovedFromDocument(GObject * o)176 void GObjectView::sl_onObjectRemovedFromDocument(GObject *o) {
177 if (objects.contains(o)) {
178 _removeObject(o);
179 if (closing) {
180 SAFE_POINT(closeInterface != nullptr, "No close interface", );
181 closeInterface->closeView();
182 }
183 }
184 }
185
onObjectRemoved(GObject * obj)186 bool GObjectView::onObjectRemoved(GObject *obj) {
187 for (GObjectViewObjectHandler *objectHandler : qAsConst(objectHandlers)) {
188 objectHandler->onObjectRemoved(this, obj);
189 }
190 return false;
191 }
192
onObjectAdded(GObject * obj)193 void GObjectView::onObjectAdded(GObject *obj) {
194 connect(obj, SIGNAL(si_nameChanged(const QString &)), SLOT(sl_onObjectNameChanged(const QString &)));
195 for (GObjectViewObjectHandler *objectHandler : qAsConst(objectHandlers)) {
196 objectHandler->onObjectAdded(this, obj);
197 }
198 }
199
onObjectRenamed(GObject *,const QString &)200 void GObjectView::onObjectRenamed(GObject *, const QString &) {
201 // Do nothing by default.
202 }
203
sl_onDocumentAdded(Document * d)204 void GObjectView::sl_onDocumentAdded(Document *d) {
205 connect(d, SIGNAL(si_objectRemoved(GObject *)), SLOT(sl_onObjectRemovedFromDocument(GObject *)));
206 connect(d, SIGNAL(si_loadedStateChanged()), SLOT(sl_onDocumentLoadedStateChanged()));
207 }
208
sl_onDocumentRemoved(Document * d)209 void GObjectView::sl_onDocumentRemoved(Document *d) {
210 if (closing) {
211 return;
212 }
213 d->disconnect(this);
214 for (GObject *object : qAsConst(d->getObjects())) {
215 if (objects.contains(object)) {
216 _removeObject(object);
217 }
218 if (closing) {
219 SAFE_POINT(closeInterface != nullptr, "No close interface", );
220 closeInterface->closeView();
221 break;
222 }
223 }
224 }
225
sl_onDocumentLoadedStateChanged()226 void GObjectView::sl_onDocumentLoadedStateChanged() {
227 }
228
sl_onObjectNameChanged(const QString & oldName)229 void GObjectView::sl_onObjectNameChanged(const QString &oldName) {
230 CHECK(AppContext::getProject() != nullptr, );
231 GObject *object = qobject_cast<GObject *>(sender());
232 SAFE_POINT(object != nullptr, "Can't locate renamed object!", );
233 onObjectRenamed(object, oldName);
234 }
235
getWidget()236 QWidget *GObjectView::getWidget() {
237 if (widget == nullptr) {
238 assert(closeInterface != nullptr);
239 widget = createWidget();
240 }
241 return widget;
242 }
243
getOptionsPanel()244 OptionsPanel *GObjectView::getOptionsPanel() {
245 return 0;
246 }
247
setClosingInterface(GObjectViewCloseInterface * i)248 void GObjectView::setClosingInterface(GObjectViewCloseInterface *i) {
249 closeInterface = i;
250 }
251
buildStaticToolbar(QToolBar * tb)252 void GObjectView::buildStaticToolbar(QToolBar *tb) {
253 emit si_buildStaticToolbar(this, tb);
254 }
255
buildMenu(QMenu * m,const QString & type)256 void GObjectView::buildMenu(QMenu *m, const QString &type) {
257 emit si_buildMenu(this, m, type);
258 }
259
260 // Returns true if view contains this object
containsObject(GObject * obj) const261 bool GObjectView::containsObject(GObject *obj) const {
262 return objects.contains(obj);
263 }
264
265 // Returns true if view contains any objects from the document
containsDocumentObjects(Document * doc) const266 bool GObjectView::containsDocumentObjects(Document *doc) const {
267 for (GObject *object : qAsConst(doc->getObjects())) {
268 if (containsObject(object)) {
269 return true;
270 }
271 }
272 return false;
273 }
274
setName(const QString & newName)275 void GObjectView::setName(const QString &newName) {
276 QString oldName = viewName;
277 if (oldName == newName) {
278 return;
279 }
280 viewName = newName;
281 emit si_nameChanged(oldName);
282 }
283
284 //////////////////////////////////////////////////////////////////////////
285 /// GObjectViewWindow
286
GObjectViewWindow(GObjectView * v,const QString & _viewName,bool _persistent)287 GObjectViewWindow::GObjectViewWindow(GObjectView *v, const QString &_viewName, bool _persistent)
288 : MWMDIWindow(_viewName), view(v), persistent(_persistent) {
289 v->setParent(this);
290 v->setClosingInterface(this);
291 // Get the GObject widget and options panel
292 QWidget *viewWidget = v->getWidget();
293 if (viewWidget == nullptr) {
294 coreLog.error("Internal error: Object View widget is not initialized");
295 v->setClosingInterface(nullptr);
296 v->setParent(nullptr);
297 return;
298 }
299 // Initialize the layout of the whole windows
300 QHBoxLayout *windowLayout = new QHBoxLayout();
301 windowLayout->setContentsMargins(0, 0, 0, 0);
302 windowLayout->setSpacing(0);
303
304 QWidget *objectWidget = new QWidget(this);
305 // Initialize the layout of the object part only
306 QVBoxLayout *objectLayout = new QVBoxLayout(objectWidget);
307 objectLayout->setContentsMargins(0, 0, 0, 0);
308 objectLayout->setSpacing(0);
309
310 // Add the widget to the layout and "parent" it
311 objectLayout->addWidget(viewWidget);
312
313 OptionsPanel *optionsPanel = v->getOptionsPanel();
314 if (optionsPanel == nullptr) {
315 // Set the layout of the whole window
316 windowLayout->addWidget(objectWidget);
317 } else {
318 OptionsPanelWidget *optionsPanelWidget = optionsPanel->getMainWidget();
319 QSplitter *splitter = new QSplitter();
320 splitter->setObjectName("OPTIONS_PANEL_SPLITTER");
321 splitter->setOrientation(Qt::Horizontal);
322 splitter->setChildrenCollapsible(false);
323 splitter->addWidget(objectWidget);
324 splitter->addWidget(optionsPanelWidget->getOptionsWidget());
325 splitter->setStretchFactor(0, 1);
326 splitter->setStretchFactor(1, 0);
327
328 windowLayout->addWidget(splitter);
329 windowLayout->addWidget(optionsPanelWidget);
330 }
331
332 QScrollArea *windowScrollArea = new QScrollArea();
333 windowScrollArea->setFrameStyle(QFrame::NoFrame);
334 windowScrollArea->setWidgetResizable(true);
335
336 auto windowContentWidget = new QWidget();
337 windowContentWidget->setObjectName("object_view_window_content_widget");
338 windowContentWidget->setLayout(windowLayout);
339 windowScrollArea->setWidget(windowContentWidget);
340
341 QHBoxLayout *l = new QHBoxLayout();
342 l->setContentsMargins(0, 0, 0, 0);
343 l->addWidget(windowScrollArea);
344 setLayout(l);
345
346 // Set the icon
347 setWindowIcon(viewWidget->windowIcon());
348 }
349
setPersistent(bool v)350 void GObjectViewWindow::setPersistent(bool v) {
351 if (persistent == v) {
352 return;
353 }
354 persistent = v;
355 emit si_persistentStateChanged(this);
356 }
357
closeView()358 void GObjectViewWindow::closeView() {
359 AppContext::getMainWindow()->getMDIManager()->closeMDIWindow(this);
360 emit si_windowClosed(this);
361 }
362
onCloseEvent()363 bool GObjectViewWindow::onCloseEvent() {
364 view->saveWidgetState();
365 return view->onCloseEvent();
366 }
367
getViewFactory() const368 GObjectViewFactory *GObjectViewWindow::getViewFactory() const {
369 GObjectViewFactory *viewFactory = AppContext::getObjectViewFactoryRegistry()->getFactoryById(view->getFactoryId());
370 SAFE_POINT(viewFactory != nullptr, "viewFactory is null!", nullptr)
371 return viewFactory;
372 }
373
setupMDIToolbar(QToolBar * tb)374 void GObjectViewWindow::setupMDIToolbar(QToolBar *tb) {
375 view->buildStaticToolbar(tb);
376 }
377
setupViewMenu(QMenu * m)378 void GObjectViewWindow::setupViewMenu(QMenu *m) {
379 view->buildMenu(m, GObjectViewMenuType::STATIC);
380 }
381
382 //////////////////////////////////////////////////////////////////////////
383 /// Utils
384
findViewByName(const QString & name)385 GObjectViewWindow *GObjectViewUtils::findViewByName(const QString &name) {
386 QList<MWMDIWindow *> mdiWindows = AppContext::getMainWindow()->getMDIManager()->getWindows();
387 for (MWMDIWindow *mdiWindow : qAsConst(mdiWindows)) {
388 if (mdiWindow->windowTitle() == name) {
389 GObjectViewWindow *objectViewWindow = qobject_cast<GObjectViewWindow *>(mdiWindow);
390 if (objectViewWindow != nullptr) {
391 return objectViewWindow;
392 }
393 }
394 }
395 return nullptr;
396 }
397
genUniqueViewName(const QString & name)398 QString GObjectViewUtils::genUniqueViewName(const QString &name) {
399 SAFE_POINT(!name.isEmpty(), "genUniqueViewName got empty name!", "");
400
401 QSet<QString> usedNames; // set of names is derived from active views & saved states
402 QList<MWMDIWindow *> windows = AppContext::getMainWindow()->getMDIManager()->getWindows();
403 for (const MWMDIWindow *w : qAsConst(windows)) {
404 usedNames.insert(w->windowTitle());
405 }
406 Project *project = AppContext::getProject();
407 if (project != nullptr) {
408 for (const GObjectViewState *state : qAsConst(project->getGObjectViewStates())) {
409 usedNames.insert(state->getViewName());
410 }
411 }
412 return TextUtils::variate(name, " ", usedNames, false, 2);
413 }
414
genUniqueStateName(const QString & stateName)415 QString GObjectViewUtils::genUniqueStateName(const QString &stateName) {
416 SAFE_POINT(!stateName.isEmpty(), "genUniqueStateName got empty state name!", "");
417
418 QSet<QString> usedNames;
419 const QList<GObjectViewState *> states = AppContext::getProject()->getGObjectViewStates();
420 for (const GObjectViewState *state : qAsConst(states)) {
421 usedNames.insert(state->getStateName());
422 }
423 return TextUtils::variate(stateName, " ", usedNames, false, 2);
424 }
425
genUniqueViewName(const Document * doc,const GObject * obj)426 QString GObjectViewUtils::genUniqueViewName(const Document *doc, const GObject *obj) {
427 QString fileName = doc->getURL().fileName();
428 QString viewName = obj->getGObjectName() + (fileName.isEmpty() ? "" : " [" + fileName + "]");
429 return genUniqueViewName(viewName);
430 }
431
findStatesByViewName(const QString & viewName)432 QList<GObjectViewState *> GObjectViewUtils::findStatesByViewName(const QString &viewName) {
433 QList<GObjectViewState *> result;
434 Project *project = AppContext::getProject();
435 if (project != nullptr) {
436 for (GObjectViewState *state : qAsConst(project->getGObjectViewStates())) {
437 if (state->getViewName() == viewName) {
438 result << state;
439 }
440 }
441 }
442 return result;
443 }
444
findStateByName(const QString & viewName,const QString & stateName)445 GObjectViewState *GObjectViewUtils::findStateByName(const QString &viewName, const QString &stateName) {
446 Project *project = AppContext::getProject();
447 SAFE_POINT(project != nullptr, "project is null!", nullptr);
448 const QList<GObjectViewState *> &allStates = project->getGObjectViewStates();
449 return findStateInList(viewName, stateName, allStates);
450 }
451
findStateInList(const QString & viewName,const QString & stateName,const QList<GObjectViewState * > & states)452 GObjectViewState *GObjectViewUtils::findStateInList(const QString &viewName, const QString &stateName, const QList<GObjectViewState *> &states) {
453 for (GObjectViewState *state : qAsConst(states)) {
454 if (state->getViewName() == viewName && state->getStateName() == stateName) {
455 return state;
456 }
457 }
458 return nullptr;
459 }
460
getAllActiveViews()461 QList<GObjectViewWindow *> GObjectViewUtils::getAllActiveViews() {
462 QList<MWMDIWindow *> mdiWindows = AppContext::getMainWindow()->getMDIManager()->getWindows();
463 QList<GObjectViewWindow *> objectViewWindows;
464 for (MWMDIWindow *mdiWindow : qAsConst(mdiWindows)) {
465 GObjectViewWindow *objectViewWindow = qobject_cast<GObjectViewWindow *>(mdiWindow);
466 if (objectViewWindow != nullptr) {
467 objectViewWindows << objectViewWindow;
468 }
469 }
470 return objectViewWindows;
471 }
472
findViewsByFactoryId(GObjectViewFactoryId id)473 QList<GObjectViewWindow *> GObjectViewUtils::findViewsByFactoryId(GObjectViewFactoryId id) {
474 QList<GObjectViewWindow *> resultWindowList;
475 MainWindow *mainWindow = AppContext::getMainWindow();
476 if (mainWindow == nullptr || mainWindow->getMDIManager() == nullptr) {
477 return resultWindowList; // Main window is closed.
478 }
479 QList<MWMDIWindow *> mdiWindows = mainWindow->getMDIManager()->getWindows();
480 for (MWMDIWindow *mdiWindow : qAsConst(mdiWindows)) {
481 GObjectViewWindow *objectViewWindow = qobject_cast<GObjectViewWindow *>(mdiWindow);
482 if (objectViewWindow != nullptr && objectViewWindow->getViewFactoryId() == id) {
483 resultWindowList << objectViewWindow;
484 }
485 }
486 return resultWindowList;
487 }
488
selectStates(const MultiGSelection & ms,const QList<GObjectViewState * > & states)489 QList<GObjectViewState *> GObjectViewUtils::selectStates(const MultiGSelection &ms, const QList<GObjectViewState *> &states) {
490 QList<GObjectViewFactory *> objectViewFactoryList = AppContext::getObjectViewFactoryRegistry()->getAllFactories();
491
492 QList<GObjectViewState *> resultStateList;
493 for (GObjectViewFactory *objectViewFactory : qAsConst(objectViewFactoryList)) {
494 QList<GObjectViewState *> stateList = selectStates(objectViewFactory, ms, states);
495 resultStateList += stateList;
496 }
497 return resultStateList;
498 }
499
selectStates(GObjectViewFactory * f,const MultiGSelection & ms,const QList<GObjectViewState * > & states)500 QList<GObjectViewState *> GObjectViewUtils::selectStates(GObjectViewFactory *f, const MultiGSelection &ms, const QList<GObjectViewState *> &states) {
501 QList<GObjectViewState *> resultStateList;
502 for (GObjectViewState *state : qAsConst(states)) {
503 if (state->getViewFactoryId() == f->getId()) {
504 if (f->isStateInSelection(ms, state->getStateData())) {
505 resultStateList << state;
506 }
507 }
508 }
509 return resultStateList;
510 }
511
findViewsWithObject(GObject * obj)512 QList<GObjectViewWindow *> GObjectViewUtils::findViewsWithObject(GObject *obj) {
513 QList<GObjectViewWindow *> resultWindowList;
514 QList<GObjectViewWindow *> activeViewWindowList = getAllActiveViews();
515 for (GObjectViewWindow *activeViewWindow : qAsConst(activeViewWindowList)) {
516 if (activeViewWindow->getObjects().contains(obj)) {
517 resultWindowList << activeViewWindow;
518 }
519 }
520 return resultWindowList;
521 }
522
findViewsWithAnyOfObjects(const QList<GObject * > & objs)523 QList<GObjectViewWindow *> GObjectViewUtils::findViewsWithAnyOfObjects(const QList<GObject *> &objs) {
524 QList<GObjectViewWindow *> resultViewWindowList;
525 for (GObject *object : qAsConst(objs)) {
526 QList<GObjectViewWindow *> viewWindowWithObjectList = findViewsWithObject(object);
527 for (GObjectViewWindow *viewWindow : qAsConst(viewWindowWithObjectList)) {
528 if (!resultViewWindowList.contains(viewWindow)) {
529 resultViewWindowList += viewWindowWithObjectList;
530 }
531 }
532 }
533 return resultViewWindowList;
534 }
535
getActiveObjectViewWindow()536 GObjectViewWindow *GObjectViewUtils::getActiveObjectViewWindow() {
537 MWMDIWindow *activeWindow = AppContext::getMainWindow()->getMDIManager()->getActiveWindow();
538 return qobject_cast<GObjectViewWindow *>(activeWindow);
539 }
540
541 //////////////////////////////////////////////////////////////////////////
542 // GObjectViewWindowContext
543
GObjectViewWindowContext(QObject * p,const GObjectViewFactoryId & _id)544 GObjectViewWindowContext::GObjectViewWindowContext(QObject *p, const GObjectViewFactoryId &_id)
545 : QObject(p), id(_id) {
546 }
547
init()548 void GObjectViewWindowContext::init() {
549 MWMDIManager *mdiManager = AppContext::getMainWindow()->getMDIManager();
550 connect(mdiManager, SIGNAL(si_windowAdded(MWMDIWindow *)), SLOT(sl_windowAdded(MWMDIWindow *)));
551 connect(mdiManager, SIGNAL(si_windowClosing(MWMDIWindow *)), SLOT(sl_windowClosing(MWMDIWindow *)));
552 const QList<MWMDIWindow *> windowList = mdiManager->getWindows();
553 for (MWMDIWindow *mdiWindow : qAsConst(windowList)) {
554 sl_windowAdded(mdiWindow);
555 }
556 }
557
~GObjectViewWindowContext()558 GObjectViewWindowContext::~GObjectViewWindowContext() {
559 MWMDIManager *mdiManager = AppContext::getMainWindow()->getMDIManager();
560 if (mdiManager == nullptr) { // TODO: disconnect context on view removal and assert (mdi!=NULL) here.
561 return;
562 }
563 const QList<MWMDIWindow *> windowList = mdiManager->getWindows();
564 for (MWMDIWindow *window : qAsConst(windowList)) {
565 GObjectViewWindow *objectViewWindow = qobject_cast<GObjectViewWindow *>(window);
566 if (objectViewWindow == nullptr || (!id.isEmpty() && objectViewWindow->getViewFactoryId() != id)) {
567 continue;
568 }
569 GObjectView *objectView = objectViewWindow->getObjectView();
570 disconnectView(objectView);
571 }
572 }
573
sl_windowAdded(MWMDIWindow * w)574 void GObjectViewWindowContext::sl_windowAdded(MWMDIWindow *w) {
575 GObjectViewWindow *objectViewWindow = qobject_cast<GObjectViewWindow *>(w);
576 if (objectViewWindow == nullptr || (!id.isEmpty() && objectViewWindow->getViewFactoryId() != id)) {
577 return;
578 }
579 GObjectView *objectView = objectViewWindow->getObjectView();
580 assert(!viewResources.contains(objectView));
581
582 objectView->addObjectHandler(this);
583
584 initViewContext(objectView);
585
586 connect(objectView, SIGNAL(si_buildMenu(GObjectView *, QMenu *, const QString &)), SLOT(sl_buildMenu(GObjectView *, QMenu *, const QString &)));
587 }
588
sl_windowClosing(MWMDIWindow * w)589 void GObjectViewWindowContext::sl_windowClosing(MWMDIWindow *w) {
590 GObjectViewWindow *objectViewWindow = qobject_cast<GObjectViewWindow *>(w);
591 if (objectViewWindow == nullptr || (!id.isEmpty() && objectViewWindow->getViewFactoryId() != id)) {
592 return;
593 }
594 GObjectView *objectView = objectViewWindow->getObjectView();
595 disconnectView(objectView);
596 }
597
sl_buildMenu(GObjectView * v,QMenu * m,const QString & type)598 void GObjectViewWindowContext::sl_buildMenu(GObjectView *v, QMenu *m, const QString &type) {
599 if (type == GObjectViewMenuType::STATIC) {
600 buildStaticMenu(v, m);
601 } else if (type == GObjectViewMenuType::CONTEXT) {
602 buildContextMenu(v, m);
603 } else {
604 buildActionMenu(v, m, type);
605 }
606 }
607
buildStaticMenu(GObjectView * view,QMenu * menu)608 void GObjectViewWindowContext::buildStaticMenu(GObjectView *view, QMenu *menu) {
609 buildStaticOrContextMenu(view, menu);
610 }
611
buildContextMenu(GObjectView * view,QMenu * menu)612 void GObjectViewWindowContext::buildContextMenu(GObjectView *view, QMenu *menu) {
613 buildStaticOrContextMenu(view, menu);
614 }
615
buildStaticOrContextMenu(GObjectView *,QMenu *)616 void GObjectViewWindowContext::buildStaticOrContextMenu(GObjectView *, QMenu *) {
617 // No extra static/context menu items by default.
618 }
619
buildActionMenu(GObjectView * view,QMenu * menu,const QString & menuType)620 void GObjectViewWindowContext::buildActionMenu(GObjectView *view, QMenu *menu, const QString &menuType) {
621 QList<GObjectViewAction *> viewActions = getViewActions(view);
622 for (GObjectViewAction *action : viewActions) {
623 if (action->isInMenu(menuType)) {
624 action->addToMenuWithOrder(menu);
625 }
626 }
627 }
628
disconnectView(GObjectView * v)629 void GObjectViewWindowContext::disconnectView(GObjectView *v) {
630 QList<QObject *> resourceObjectList = viewResources[v];
631 for (QObject *resourceObject : qAsConst(resourceObjectList)) {
632 resourceObject->deleteLater(); // deliver close signals, save view states first
633 }
634 viewResources.remove(v);
635 v->removeObjectHandler(this);
636 }
637
addViewResource(GObjectView * v,QObject * r)638 void GObjectViewWindowContext::addViewResource(GObjectView *v, QObject *r) {
639 assert(v != nullptr && (!id.isEmpty() || v->getFactoryId() == id));
640
641 QList<QObject *> resources = viewResources[v];
642 assert(!resources.contains(r));
643 resources.append(r);
644 viewResources[v] = resources;
645 }
646
addViewAction(GObjectViewAction * a)647 void GObjectViewWindowContext::addViewAction(GObjectViewAction *a) {
648 addViewResource(a->getObjectView(), a);
649 }
650
findViewAction(GObjectView * v,const QString & actionName) const651 GObjectViewAction *GObjectViewWindowContext::findViewAction(GObjectView *v, const QString &actionName) const {
652 const QList<GObjectViewAction *> viewActionList = getViewActions(v);
653 for (GObjectViewAction *viewAction : qAsConst(viewActionList)) {
654 if (viewAction->objectName() == actionName) {
655 return viewAction;
656 }
657 }
658 return nullptr;
659 }
660
getViewActions(GObjectView * v) const661 QList<GObjectViewAction *> GObjectViewWindowContext::getViewActions(GObjectView *v) const {
662 QList<GObjectViewAction *> actions;
663 QList<QObject *> resourceObjectList = viewResources[v];
664 for (QObject *resourceObject : qAsConst(resourceObjectList)) {
665 GObjectViewAction *viewAction = qobject_cast<GObjectViewAction *>(resourceObject);
666 if (viewAction != nullptr) {
667 actions << viewAction;
668 }
669 }
670 return actions;
671 }
672
onObjectRemoved(GObjectView * v,GObject * obj)673 void GObjectViewWindowContext::onObjectRemoved(GObjectView *v, GObject *obj) {
674 GObjectViewObjectHandler::onObjectRemoved(v, obj);
675 const QList<GObjectViewAction *> viewActionList = getViewActions(v);
676 for (GObjectViewAction *action : qAsConst(viewActionList)) {
677 obj->disconnect(action);
678 }
679 }
680
681 //////////////////////////////////////////////////////////////////////////
682 // GObjectViewAction
683
GObjectViewAction(QObject * p,GObjectView * v,const QString & text,int order)684 GObjectViewAction::GObjectViewAction(QObject *p, GObjectView *v, const QString &text, int order)
685 : QAction(text, p), view(v), actionOrder(order) {
686 }
687
getObjectView() const688 GObjectView *GObjectViewAction::getObjectView() const {
689 return view;
690 }
691
getActionOrder() const692 int GObjectViewAction::getActionOrder() const {
693 return actionOrder;
694 }
695
isInMenu(const QString & menuType) const696 bool GObjectViewAction::isInMenu(const QString &menuType) const {
697 return menuTypes.contains(menuType);
698 }
699
setMenuTypes(const QList<QString> & newMenuTypes)700 void GObjectViewAction::setMenuTypes(const QList<QString> &newMenuTypes) {
701 menuTypes = newMenuTypes;
702 }
703
addToMenuWithOrder(QMenu * menu)704 void GObjectViewAction::addToMenuWithOrder(QMenu *menu) {
705 QList<QAction *> actionList = menu->actions();
706 for (QAction *action : actionList) {
707 GObjectViewAction *viewAction = qobject_cast<GObjectViewAction *>(action);
708 if (viewAction != nullptr && viewAction->getActionOrder() > actionOrder) {
709 menu->insertAction(action, this);
710 return;
711 }
712 }
713 menu->addAction(this);
714 }
715
canHandle(GObjectView *,GObject *)716 bool GObjectViewObjectHandler::canHandle(GObjectView *, GObject *) {
717 return false;
718 }
719
onObjectAdded(GObjectView *,GObject *)720 void GObjectViewObjectHandler::onObjectAdded(GObjectView *, GObject *) {
721 }
722
onObjectRemoved(GObjectView *,GObject *)723 void GObjectViewObjectHandler::onObjectRemoved(GObjectView *, GObject *) {
724 }
725
726 } // namespace U2
727