ELVE  1
ELVE Logic Visualization Explorer
/home/travis/build/stdgregwar/elve/Core/ExtendedGraph.cpp
00001 #include "ExtendedGraph.h"
00002 #include <memory>
00003 #include <QJsonDocument>
00004 #include <QJsonArray>
00005 #include <QFile>
00006 #include "PluginManager.h"
00007 #include <random>
00008 #include "GraphWidget.h"
00009 
00010 namespace Elve {
00011 
00012 using namespace std;
00013 
00014 ExtendedGraph::ExtendedGraph(const SharedGraph &g, const NodePositions &positions) :
00015     mGraph(g),
00016     mPositions(positions),
00017     mPosDirty(false),
00018     mView(nullptr),
00019     mMaskId(1)
00020 {
00021 
00022 }
00023 
00024 SharedEGraph ExtendedGraph::fromJSON(const QJsonObject &obj)
00025 {
00026     SharedGraph g = Graph::fromJson(obj.value("graph").toObject());
00027     //positions
00028     NodePositions positions; positions.reserve(g->nodeCount());
00029     QJsonObject jpositions = obj["layout"].toObject()["positions"].toObject();
00030     QString layoutName = obj["layout"].toObject()["name"].toString();
00031     for(QJsonObject::const_iterator it = jpositions.constBegin();
00032         it != jpositions.constEnd();
00033         it++) {
00034 
00035         QJsonArray jpos = it.value().toArray();
00036         positions.emplace(std::piecewise_construct,
00037                           std::forward_as_tuple(it.key().toInt()),
00038                           std::forward_as_tuple(jpos.at(0).toDouble(),jpos.at(1).toDouble()));
00039     }
00040 
00041     QJsonObject selections = obj["selections"].toObject();
00042 
00043     int i = 0;
00044     SelectionMasks masks;
00045     for(Selection& s : masks) {
00046         s = Selection::fromJson(selections.value(QString::number(i++)).toArray());
00047     }
00048     CommandHistory ch(obj["history"]);
00049     SharedEGraph eg = std::make_shared<ExtendedGraph>(g,positions);
00050     eg->mHistory = ch;
00051     eg->selections() = masks;
00052     eg->setMask(obj["mask"].toInt());
00053     eg->setLook(PluginManager::get().defaultLook());
00054     SharedLayout lay = PluginManager::get().getLayout(layoutName);
00055     lay->fromJson(obj["layout"].toObject());
00056     eg->setLayout(lay);
00057     return eg;
00058 }
00059 
00060 SharedEGraph ExtendedGraph::fromGraph(const SharedGraph& g)
00061 {
00062     SharedEGraph eg =  std::make_shared<ExtendedGraph>(g);
00063     eg->setLayout(PluginManager::get().defaultLayout());
00064     return eg;
00065 }
00066 
00067 QJsonObject ExtendedGraph::json() const
00068 {
00069     if(!mGraph) {
00070         return QJsonObject();
00071     }
00072 
00073     QJsonObject main;
00074     main.insert("graph",mGraph->json());
00075 
00076     if(mLayout) {
00077         main.insert("layout",mLayout->json());
00078     }
00079 
00080     main.insert("mask",mMaskId);
00081 
00082     QJsonObject selections;
00083     int i = 0;
00084     for(const Selection& s : mSelections) {
00085         selections.insert(QString::number(i++),s.json());
00086     }
00087     main.insert("selections",selections);
00088     main.insert("history",mHistory.json());
00089     return main;
00090 }
00091 
00092 SharedEGraph ExtendedGraph::fromFile(const QString& filename)
00093 {
00094     QString ext = filename.split(".").last();
00095     QFile file(filename);
00096     if(file.open(QFile::ReadOnly)) {
00097         QJsonDocument doc;
00098         if(ext.toLower() == "elve") {
00099             doc = QJsonDocument::fromBinaryData(file.readAll());
00100         } else { //Assume it's json
00101             doc = QJsonDocument::fromJson(file.readAll());
00102         }
00103         SharedEGraph eg = fromJSON(doc.object());
00104         //eg->graph()->setFilename(filename.toStdString());
00105         return eg;
00106     } else {
00107         throw std::runtime_error("Couldn't open file " + filename.toStdString() + " for reading.");
00108     }
00109 }
00110 
00111 void ExtendedGraph::toFile(const QString& filename) {
00112     QString suffix = filename.split(".").last();
00113     QJsonDocument doc(json());
00114 
00115     QFile file(filename);
00116     if(file.open(QFile::WriteOnly)) {
00117         if(suffix == "elve") {
00118             file.write(doc.toBinaryData());
00119         } else {
00120             file.write(doc.toJson());
00121         }
00122         file.close();
00123     } else {
00124         throw std::runtime_error("Couldn't write to file " + filename.toStdString());
00125     }
00126 }
00127 
00128 CommandHistory& ExtendedGraph::history() {
00129     return mHistory;
00130 }
00131 
00132 SharedEGraph ExtendedGraph::group(const NodeIDSet& names, const NodeName &groupName)
00133 {
00134     if(names.size() == 0) return shared_from_this();
00135     mPosDirty = true;
00136     NodePositions poss = positions();
00137     NodeID nid = mGraph->newID();
00138     QVector2D groupCenter;
00139     for(const NodeID& id : names) {
00140         groupCenter += poss.at(id);
00141     }
00142     groupCenter /= names.size();
00143 
00144     poss[nid] = groupCenter;
00145     SharedEGraph eg = clone(mGraph->group(names,nid,groupName),poss);
00146 
00147     for(int i = 0; i < 10; i++) {
00148         for(const NodeID& id : selection(i)) {
00149             eg->selection(i).add(eg->graph()->inputAlias(i).id); //TODO : check if arbitrary inputAlias choice work
00150         }
00151     }
00152     return eg;
00153 }
00154 
00155 SharedEGraph ExtendedGraph::ungroup(const NodeIDSet & names) const
00156 {
00157     mPosDirty = true;
00158     NodePositions poss = positions();
00159     SharedGraph g = mGraph;
00160     for(const NodeID& name : names) {
00161         QVector2D base = poss.at(name);
00162         const Dependencies& ids = g->data(name).dependencies();
00163         static qreal radius = 128;
00164         for(size_t i = 0; i < ids.size(); ++i) {
00165             qreal p = M_PI*((qreal)i)/ids.size();
00166             poss[ids[i].id] = base + QVector2D(radius*cos(p),radius*sin(p));
00167         }
00168         g = g->ungroup(name);
00169     }
00170     return clone(g,poss);
00171 }
00172 
00173 SharedEGraph ExtendedGraph::clone(const SharedGraph& graph, const NodePositions& positions) const {
00174     SharedEGraph eg =std::make_shared<ExtendedGraph>(graph,positions);
00175     eg->setLook(mLook);
00176     eg->setLayout(mLayout->create());
00177     eg->setView(mView);
00178     eg->history() = mHistory;
00179     eg->mMaskId = mMaskId;
00180     //eg->mSelections = mSelections;
00181     return eg;
00182 }
00183 
00184 SelectionMasks& ExtendedGraph::selections() {
00185     return mSelections;
00186 }
00187 
00188 Selection& ExtendedGraph::selection(size_t i) {
00189     return mSelections[i];
00190 }
00191 
00192 
00193 ExtendedGraph::~ExtendedGraph()
00194 {
00195 }
00196 
00197 const NodePositions& ExtendedGraph::positions() const
00198 {
00199     if(mPosDirty && mLayout) {
00200         mPositions = mLayout->system().positions();
00201 
00202     }
00203     mPosDirty = false;
00204     return mPositions;
00205 }
00206 
00207 void ExtendedGraph::setView(GraphWidget *view) {
00208     mView = view;
00209 }
00210 
00211 GraphWidget* ExtendedGraph::view() {
00212     return mView;
00213 }
00214 
00215 const SharedGraph& ExtendedGraph::graph() const
00216 {
00217     return mGraph;
00218 }
00219 
00220 void ExtendedGraph::setMask(int id) {
00221     mMaskId = id;
00222 }
00223 
00224 int ExtendedGraph::mask() const {
00225     return mMaskId;
00226 }
00227 
00228 Selection& ExtendedGraph::currentSelection() {
00229     return selection(mMaskId);
00230 }
00231 
00232 Selection ExtendedGraph::invertedSelection(size_t i) const {
00233     const Selection& sel = mSelections.at(i);
00234     Selection isel;
00235     for(const auto& pn : mGraph->nodes()) {
00236         if(!sel.count(pn.first)) {
00237             isel.insert(pn.first);
00238         }
00239     }
00240     return isel;
00241 }
00242 
00243 void ExtendedGraph::setLayout(const SharedLayout &l)
00244 {
00245     if(!l) return;
00246     mPosDirty = true;
00247     if(mLook) {
00248         if(mLayout) {
00249             for(const PointsByID::value_type& p : mLayout->system().pinnedPoints()) {
00250                 l->system().pin(p.first,p.second->pos());
00251             }
00252         }
00253         l->setGraph(shared_from_this(),positions());
00254     }
00255     mLayout = l;
00256     if(mView && mLook) mView->reflect(l->system(),mGraph,mLook);
00257 }
00258 
00259 void ExtendedGraph::setLook(const SharedLook& l) {
00260     mLook = l;
00261     if(mLayout) {
00262         mLayout->clear();
00263         mLayout->setGraph(shared_from_this(),positions());
00264     }
00265     if(mView && mLayout) mView->reflect(mLayout->system(),mGraph,mLook);
00266 }
00267 
00268 const SharedLayout &ExtendedGraph::layout()
00269 {
00270     return mLayout;
00271 }
00272 
00273 const SharedLook& ExtendedGraph::look()
00274 {
00275     return mLook;
00276 }
00277 
00278 }
 All Classes Functions