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 "AssemblyBrowserFactory.h"
23 
24 #include <U2Core/AppContext.h>
25 #include <U2Core/AssemblyObject.h>
26 #include <U2Core/DocumentModel.h>
27 #include <U2Core/ProjectModel.h>
28 #include <U2Core/SelectionUtils.h>
29 #include <U2Core/U2SafePoints.h>
30 
31 #include "AssemblyBrowserState.h"
32 #include "AssemblyBrowserTasks.h"
33 
34 namespace U2 {
35 
36 //==============================================================================
37 // AssemblyBrowserFactory
38 //==============================================================================
39 
40 const GObjectViewFactoryId AssemblyBrowserFactory::ID = "assembly-browser-factory";
41 
AssemblyBrowserFactory(QObject * parent)42 AssemblyBrowserFactory::AssemblyBrowserFactory(QObject *parent /* = 0 */)
43     : GObjectViewFactory(ID, tr("Assembly Browser"), parent) {
44 }
45 
canCreateView(const MultiGSelection & multiSelection)46 bool AssemblyBrowserFactory::canCreateView(const MultiGSelection &multiSelection) {
47     bool hasAssembly = !SelectionUtils::findDocumentsWithObjects(GObjectTypes::ASSEMBLY, &multiSelection, UOF_LoadedAndUnloaded, true).isEmpty();
48     return hasAssembly;
49 }
50 
51 #define MAX_VIEWS 5
52 
addAsmObjs(QList<GObject * > & asmObjs,const QList<GObject * > & docObjs)53 void addAsmObjs(QList<GObject *> &asmObjs, const QList<GObject *> &docObjs) {
54     foreach (GObject *go, docObjs) {
55         if (!asmObjs.contains(go)) {
56             asmObjs.append(go);
57         }
58     }
59 }
60 
createViewTask(const MultiGSelection & multiSelection,bool single)61 Task *AssemblyBrowserFactory::createViewTask(const MultiGSelection &multiSelection, bool single /* = false */) {
62     QList<GObject *> asmObjects = SelectionUtils::findObjects(GObjectTypes::ASSEMBLY, &multiSelection, UOF_LoadedAndUnloaded);
63     QSet<Document *> docsWithAsm = SelectionUtils::findDocumentsWithObjects(GObjectTypes::ASSEMBLY,
64                                                                             &multiSelection,
65                                                                             UOF_LoadedAndUnloaded,
66                                                                             false);
67     QList<OpenAssemblyBrowserTask *> resTasks;
68 
69     foreach (Document *doc, docsWithAsm) {
70         QList<GObject *> docObjs = doc->findGObjectByType(GObjectTypes::ASSEMBLY, UOF_LoadedAndUnloaded);
71         if (!docObjs.isEmpty()) {
72             addAsmObjs(asmObjects, docObjs);
73         } else {
74             resTasks.append(new OpenAssemblyBrowserTask(doc));
75             if (resTasks.size() == MAX_VIEWS) {
76                 break;
77             }
78         }
79     }
80 
81     if (!asmObjects.isEmpty()) {
82         foreach (GObject *o, asmObjects) {
83             if (resTasks.size() == MAX_VIEWS) {
84                 break;
85             }
86             if (o->getGObjectType() == GObjectTypes::UNLOADED) {
87                 resTasks.append(new OpenAssemblyBrowserTask(qobject_cast<UnloadedObject *>(o)));
88             } else {
89                 SAFE_POINT(o->getGObjectType() == GObjectTypes::ASSEMBLY, "Invalid assembly object!", nullptr);
90                 resTasks.append(new OpenAssemblyBrowserTask(qobject_cast<AssemblyObject *>(o)));
91             }
92         }
93     }
94 
95     if (resTasks.isEmpty()) {
96         return nullptr;
97     }
98 
99     if (resTasks.size() == 1 || single) {
100         return resTasks.first();
101     }
102 
103     Task *result = new Task(tr("Open multiple views"), TaskFlag_NoRun);
104     foreach (Task *t, resTasks) {
105         result->addSubTask(t);
106     }
107     return result;
108 }
109 
isStateInSelection(const MultiGSelection & multiSelection,const QVariantMap & stateData)110 bool AssemblyBrowserFactory::isStateInSelection(const MultiGSelection &multiSelection, const QVariantMap &stateData) {
111     // TODO: this method of AssemblyBrowser, AnnotatedDNAView and MSAEditor is copypaste a little more than entirely
112     AssemblyBrowserState state(stateData);
113     if (!state.isValid()) {
114         return false;
115     }
116     GObjectReference ref = state.getGObjectRef();
117     Document *doc = AppContext::getProject()->findDocumentByURL(ref.docUrl);
118     if (doc == nullptr) {  // todo: accept to use invalid state removal routines of ObjectViewTask ???
119         return false;
120     }
121     // check that document is in selection
122     QList<Document *> selectedDocs = SelectionUtils::getSelectedDocs(multiSelection);
123     if (selectedDocs.contains(doc)) {
124         return true;
125     }
126     // check that object is in selection
127     QList<GObject *> selectedObjects = SelectionUtils::getSelectedObjects(multiSelection);
128     GObject *obj = doc->findGObjectByName(ref.objName);
129     bool res = obj != nullptr && selectedObjects.contains(obj);
130     return res;
131 }
132 
createViewTask(const QString & viewName,const QVariantMap & stateData)133 Task *AssemblyBrowserFactory::createViewTask(const QString &viewName, const QVariantMap &stateData) {
134     return new OpenSavedAssemblyBrowserTask(viewName, stateData);
135 }
136 
137 }  // namespace U2
138