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
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 {
00101 doc = QJsonDocument::fromJson(file.readAll());
00102 }
00103 SharedEGraph eg = fromJSON(doc.object());
00104
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);
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
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 }