Generated on Tue Jul 27 2010 21:59:10 for Gecode by doxygen 1.7.1

qtgist.cpp

Go to the documentation of this file.
00001 /* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
00002 /*
00003  *  Main authors:
00004  *     Guido Tack <tack@gecode.org>
00005  *
00006  *  Copyright:
00007  *     Guido Tack, 2006
00008  *
00009  *  Last modified:
00010  *     $Date: 2010-04-21 14:22:14 +0200 (Wed, 21 Apr 2010) $ by $Author: tack $
00011  *     $Revision: 10784 $
00012  *
00013  *  This file is part of Gecode, the generic constraint
00014  *  development environment:
00015  *     http://www.gecode.org
00016  *
00017  * Permission is hereby granted, free of charge, to any person obtaining
00018  * a copy of this software and associated documentation files (the
00019  * "Software"), to deal in the Software without restriction, including
00020  * without limitation the rights to use, copy, modify, merge, publish,
00021  * distribute, sublicense, and/or sell copies of the Software, and to
00022  * permit persons to whom the Software is furnished to do so, subject to
00023  * the following conditions:
00024  *
00025  * The above copyright notice and this permission notice shall be
00026  * included in all copies or substantial portions of the Software.
00027  *
00028  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00029  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00030  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00031  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
00032  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
00033  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
00034  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00035  *
00036  */
00037 
00038 #include <gecode/gist/qtgist.hh>
00039 
00040 #include <gecode/gist/zoomToFitIcon.hpp>
00041 #include <gecode/gist/nodevisitor.hh>
00042 #include <gecode/gist/nodecursor.hh>
00043 
00044 namespace Gecode { namespace Gist {
00045 
00046   Gist::Gist(Space* root, bool bab, QWidget* parent,
00047              const Options& opt) : QWidget(parent) {
00048     QGridLayout* layout = new QGridLayout(this);
00049 
00050     QAbstractScrollArea* scrollArea = new QAbstractScrollArea(this);
00051 
00052     scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
00053     scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
00054     scrollArea->setAutoFillBackground(true);
00055     QPalette myPalette(scrollArea->palette());
00056     myPalette.setColor(QPalette::Window, Qt::white);
00057     scrollArea->setPalette(myPalette);
00058     canvas = new TreeCanvas(root, bab, scrollArea->viewport(),opt);
00059     canvas->setPalette(myPalette);
00060     canvas->setObjectName("canvas");
00061 
00062     connect(scrollArea->horizontalScrollBar(), SIGNAL(valueChanged(int)),
00063             canvas, SLOT(scroll(void)));
00064     connect(scrollArea->verticalScrollBar(), SIGNAL(valueChanged(int)),
00065             canvas, SLOT(scroll(void)));
00066 
00067     QVBoxLayout* sa_layout = new QVBoxLayout();
00068     sa_layout->setContentsMargins(0,0,0,0);
00069     sa_layout->addWidget(canvas);
00070     scrollArea->viewport()->setLayout(sa_layout);
00071 
00072     connect(canvas, SIGNAL(solution(const Space*)),
00073             this, SIGNAL(solution(const Space*)));
00074 
00075     connect(canvas, SIGNAL(searchFinished(void)), this, SIGNAL(searchFinished(void)));
00076 
00077     QPixmap myPic;
00078     myPic.loadFromData(zoomToFitIcon, sizeof(zoomToFitIcon));
00079 
00080     QToolButton* autoZoomButton = new QToolButton();
00081     autoZoomButton->setCheckable(true);
00082     autoZoomButton->setIcon(myPic);
00083 
00084     nodeStatInspector = new NodeStatInspector(this);
00085     connect(canvas, SIGNAL(statusChanged(VisualNode*,const Statistics&, bool)),
00086             nodeStatInspector, SLOT(node(VisualNode*,const Statistics&, bool)));
00087 
00088     inspect = new QAction("Inspect", this);
00089     inspect->setShortcut(QKeySequence("Return"));
00090     connect(inspect, SIGNAL(triggered()), canvas,
00091                        SLOT(inspectCurrentNode()));
00092 
00093     inspectBeforeFP = new QAction("Inspect before fixpoint", this);
00094     inspectBeforeFP->setShortcut(QKeySequence("Ctrl+Return"));
00095     connect(inspectBeforeFP, SIGNAL(triggered()), canvas,
00096             SLOT(inspectBeforeFP(void)));
00097 
00098     stop = new QAction("Stop search", this);
00099     stop->setShortcut(QKeySequence("Esc"));
00100     connect(stop, SIGNAL(triggered()), canvas,
00101                     SLOT(stopSearch()));
00102 
00103     reset = new QAction("Reset", this);
00104     reset->setShortcut(QKeySequence("Ctrl+R"));
00105     connect(reset, SIGNAL(triggered()), canvas,
00106             SLOT(reset()));
00107 
00108     navUp = new QAction("Up", this);
00109     navUp->setShortcut(QKeySequence("Up"));
00110     connect(navUp, SIGNAL(triggered()), canvas,
00111                    SLOT(navUp()));
00112 
00113     navDown = new QAction("Down", this);
00114     navDown->setShortcut(QKeySequence("Down"));
00115     connect(navDown, SIGNAL(triggered()), canvas,
00116                      SLOT(navDown()));
00117 
00118     navLeft = new QAction("Left", this);
00119     navLeft->setShortcut(QKeySequence("Left"));
00120     connect(navLeft, SIGNAL(triggered()), canvas,
00121                      SLOT(navLeft()));
00122 
00123     navRight = new QAction("Right", this);
00124     navRight->setShortcut(QKeySequence("Right"));
00125     connect(navRight, SIGNAL(triggered()), canvas,
00126                       SLOT(navRight()));
00127 
00128     navRoot = new QAction("Root", this);
00129     navRoot->setShortcut(QKeySequence("R"));
00130     connect(navRoot, SIGNAL(triggered()), canvas,
00131                       SLOT(navRoot()));
00132 
00133     navNextSol = new QAction("To next solution", this);
00134     navNextSol->setShortcut(QKeySequence("Shift+Right"));
00135     connect(navNextSol, SIGNAL(triggered()), canvas,
00136                       SLOT(navNextSol()));
00137 
00138     navPrevSol = new QAction("To previous solution", this);
00139     navPrevSol->setShortcut(QKeySequence("Shift+Left"));
00140     connect(navPrevSol, SIGNAL(triggered()), canvas,
00141                       SLOT(navPrevSol()));
00142 
00143     searchNext = new QAction("Next solution", this);
00144     searchNext->setShortcut(QKeySequence("N"));
00145     connect(searchNext, SIGNAL(triggered()), canvas, SLOT(searchOne()));
00146 
00147     searchAll = new QAction("All solutions", this);
00148     searchAll->setShortcut(QKeySequence("A"));
00149     connect(searchAll, SIGNAL(triggered()), canvas, SLOT(searchAll()));
00150 
00151     toggleHidden = new QAction("Hide/unhide", this);
00152     toggleHidden->setShortcut(QKeySequence("H"));
00153     connect(toggleHidden, SIGNAL(triggered()), canvas, SLOT(toggleHidden()));
00154 
00155     hideFailed = new QAction("Hide failed subtrees", this);
00156     hideFailed->setShortcut(QKeySequence("F"));
00157     connect(hideFailed, SIGNAL(triggered()), canvas, SLOT(hideFailed()));
00158 
00159     unhideAll = new QAction("Unhide all", this);
00160     unhideAll->setShortcut(QKeySequence("U"));
00161     connect(unhideAll, SIGNAL(triggered()), canvas, SLOT(unhideAll()));
00162 
00163     toggleStop = new QAction("Stop/unstop", this);
00164     toggleStop->setShortcut(QKeySequence("X"));
00165     connect(toggleStop, SIGNAL(triggered()), canvas, SLOT(toggleStop()));
00166 
00167     unstopAll = new QAction("Do not stop in subtree", this);
00168     unstopAll->setShortcut(QKeySequence("Shift+X"));
00169     connect(unstopAll, SIGNAL(triggered()), canvas, SLOT(unstopAll()));
00170 
00171     zoomToFit = new QAction("Zoom to fit", this);
00172     zoomToFit->setShortcut(QKeySequence("Z"));
00173     connect(zoomToFit, SIGNAL(triggered()), canvas, SLOT(zoomToFit()));
00174 
00175     center = new QAction("Center current node", this);
00176     center->setShortcut(QKeySequence("C"));
00177     connect(center, SIGNAL(triggered()), canvas, SLOT(centerCurrentNode()));
00178 
00179     exportPDF = new QAction("Export subtree PDF...", this);
00180     exportPDF->setShortcut(QKeySequence("P"));
00181     connect(exportPDF, SIGNAL(triggered()), canvas,
00182             SLOT(exportPDF()));
00183 
00184     exportWholeTreePDF = new QAction("Export PDF...", this);
00185     exportWholeTreePDF->setShortcut(QKeySequence("Ctrl+Shift+P"));
00186     connect(exportWholeTreePDF, SIGNAL(triggered()), canvas,
00187             SLOT(exportWholeTreePDF()));
00188 
00189     print = new QAction("Print...", this);
00190     print->setShortcut(QKeySequence("Ctrl+P"));
00191     connect(print, SIGNAL(triggered()), canvas,
00192             SLOT(print()));
00193 
00194     bookmarkNode = new QAction("Add/remove bookmark", this);
00195     bookmarkNode->setShortcut(QKeySequence("Shift+B"));
00196     connect(bookmarkNode, SIGNAL(triggered()), canvas, SLOT(bookmarkNode()));
00197 
00198     compareNode = new QAction("Compare", this);
00199     compareNode->setShortcut(QKeySequence("V"));
00200     connect(compareNode, SIGNAL(triggered()),
00201             canvas, SLOT(startCompareNodes()));
00202 
00203     compareNodeBeforeFP = new QAction("Compare before fixpoint", this);
00204     compareNodeBeforeFP->setShortcut(QKeySequence("Ctrl+V"));
00205     connect(compareNodeBeforeFP, SIGNAL(triggered()),
00206             canvas, SLOT(startCompareNodesBeforeFP()));
00207 
00208     connect(canvas, SIGNAL(addedBookmark(const QString&)),
00209             this, SLOT(addBookmark(const QString&)));
00210     connect(canvas, SIGNAL(removedBookmark(int)),
00211             this, SLOT(removeBookmark(int)));
00212 
00213     nullBookmark = new QAction("<none>",this);
00214     nullBookmark->setCheckable(true);
00215     nullBookmark->setChecked(false);
00216     nullBookmark->setEnabled(false);
00217     bookmarksGroup = new QActionGroup(this);
00218     bookmarksGroup->setExclusive(false);
00219     bookmarksGroup->addAction(nullBookmark);
00220     connect(bookmarksGroup, SIGNAL(triggered(QAction*)),
00221             this, SLOT(selectBookmark(QAction*)));
00222 
00223     bookmarksMenu = new QMenu("Bookmarks");
00224     connect(bookmarksMenu, SIGNAL(aboutToShow()),
00225             this, SLOT(populateBookmarksMenu()));
00226 
00227 
00228     setPath = new QAction("Set path", this);
00229     setPath->setShortcut(QKeySequence("Shift+P"));
00230     connect(setPath, SIGNAL(triggered()), canvas, SLOT(setPath()));
00231 
00232     inspectPath = new QAction("Inspect path", this);
00233     inspectPath->setShortcut(QKeySequence("Shift+I"));
00234     connect(inspectPath, SIGNAL(triggered()), canvas, SLOT(inspectPath()));
00235 
00236     showNodeStats = new QAction("Node statistics", this);
00237     showNodeStats->setShortcut(QKeySequence("S"));
00238     connect(showNodeStats, SIGNAL(triggered()),
00239             this, SLOT(showStats()));
00240 
00241     addAction(inspect);
00242     addAction(inspectBeforeFP);
00243     addAction(compareNode);
00244     addAction(compareNodeBeforeFP);
00245     addAction(stop);
00246     addAction(reset);
00247     addAction(navUp);
00248     addAction(navDown);
00249     addAction(navLeft);
00250     addAction(navRight);
00251     addAction(navRoot);
00252     addAction(navNextSol);
00253     addAction(navPrevSol);
00254 
00255     addAction(searchNext);
00256     addAction(searchAll);
00257     addAction(toggleHidden);
00258     addAction(hideFailed);
00259     addAction(unhideAll);
00260     addAction(toggleStop);
00261     addAction(unstopAll);
00262     addAction(zoomToFit);
00263     addAction(center);
00264     addAction(exportPDF);
00265     addAction(exportWholeTreePDF);
00266     addAction(print);
00267 
00268     addAction(setPath);
00269     addAction(inspectPath);
00270     addAction(showNodeStats);
00271 
00272     nullSolutionInspector = new QAction("<none>",this);
00273     nullSolutionInspector->setCheckable(true);
00274     nullSolutionInspector->setChecked(false);
00275     nullSolutionInspector->setEnabled(false);
00276     solutionInspectorGroup = new QActionGroup(this);
00277     solutionInspectorGroup->setExclusive(false);
00278     solutionInspectorGroup->addAction(nullSolutionInspector);
00279     connect(solutionInspectorGroup, SIGNAL(triggered(QAction*)),
00280             this, SLOT(selectSolutionInspector(QAction*)));
00281 
00282     nullDoubleClickInspector = new QAction("<none>",this);
00283     nullDoubleClickInspector->setCheckable(true);
00284     nullDoubleClickInspector->setChecked(false);
00285     nullDoubleClickInspector->setEnabled(false);
00286     doubleClickInspectorGroup = new QActionGroup(this);
00287     doubleClickInspectorGroup->setExclusive(false);
00288     doubleClickInspectorGroup->addAction(nullDoubleClickInspector);
00289     connect(doubleClickInspectorGroup, SIGNAL(triggered(QAction*)),
00290             this, SLOT(selectDoubleClickInspector(QAction*)));
00291 
00292     nullMoveInspector = new QAction("<none>",this);
00293     nullMoveInspector->setCheckable(true);
00294     nullMoveInspector->setChecked(false);
00295     nullMoveInspector->setEnabled(false);
00296     moveInspectorGroup = new QActionGroup(this);
00297     moveInspectorGroup->setExclusive(false);
00298     moveInspectorGroup->addAction(nullMoveInspector);
00299     connect(moveInspectorGroup, SIGNAL(triggered(QAction*)),
00300             this, SLOT(selectMoveInspector(QAction*)));
00301 
00302     nullComparator = new QAction("<none>",this);
00303     nullComparator->setCheckable(true);
00304     nullComparator->setChecked(false);
00305     nullComparator->setEnabled(false);
00306     comparatorGroup = new QActionGroup(this);
00307     comparatorGroup->setExclusive(false);
00308     comparatorGroup->addAction(nullComparator);
00309     connect(comparatorGroup, SIGNAL(triggered(QAction*)),
00310             this, SLOT(selectComparator(QAction*)));
00311 
00312     solutionInspectorMenu = new QMenu("Solution inspectors");
00313     solutionInspectorMenu->addActions(solutionInspectorGroup->actions());
00314     doubleClickInspectorMenu = new QMenu("Double click inspectors");
00315     doubleClickInspectorMenu->addActions(
00316       doubleClickInspectorGroup->actions());
00317     moveInspectorMenu = new QMenu("Move inspectors");
00318     moveInspectorMenu->addActions(moveInspectorGroup->actions());
00319     comparatorMenu = new QMenu("Comparators");
00320     comparatorMenu->addActions(comparatorGroup->actions());
00321 
00322     inspectGroup = new QActionGroup(this);
00323     connect(inspectGroup, SIGNAL(triggered(QAction*)),
00324             this, SLOT(inspectWithAction(QAction*)));
00325     inspectBeforeFPGroup = new QActionGroup(this);
00326     connect(inspectBeforeFPGroup, SIGNAL(triggered(QAction*)),
00327             this, SLOT(inspectBeforeFPWithAction(QAction*)));
00328 
00329     inspectNodeMenu = new QMenu("Inspect");
00330     inspectNodeMenu->addAction(inspect);
00331     connect(inspectNodeMenu, SIGNAL(aboutToShow()),
00332             this, SLOT(populateInspectors()));
00333 
00334     inspectNodeBeforeFPMenu = new QMenu("Inspect before fixpoint");
00335     inspectNodeBeforeFPMenu->addAction(inspectBeforeFP);
00336     connect(inspectNodeBeforeFPMenu, SIGNAL(aboutToShow()),
00337             this, SLOT(populateInspectors()));
00338     populateInspectors();
00339 
00340     contextMenu = new QMenu(this);
00341     contextMenu->addMenu(inspectNodeMenu);
00342     contextMenu->addMenu(inspectNodeBeforeFPMenu);
00343     contextMenu->addAction(compareNode);
00344     contextMenu->addAction(compareNodeBeforeFP);
00345     contextMenu->addAction(showNodeStats);
00346     contextMenu->addAction(center);
00347 
00348     contextMenu->addSeparator();
00349 
00350     contextMenu->addAction(searchNext);
00351     contextMenu->addAction(searchAll);
00352 
00353     contextMenu->addSeparator();
00354 
00355     contextMenu->addAction(toggleHidden);
00356     contextMenu->addAction(hideFailed);
00357     contextMenu->addAction(unhideAll);
00358 
00359     contextMenu->addAction(toggleStop);
00360     contextMenu->addAction(unstopAll);
00361 
00362     contextMenu->addSeparator();
00363 
00364     contextMenu->addMenu(bookmarksMenu);
00365     contextMenu->addAction(setPath);
00366     contextMenu->addAction(inspectPath);
00367 
00368     contextMenu->addSeparator();
00369 
00370     contextMenu->addMenu(doubleClickInspectorMenu);
00371     contextMenu->addMenu(solutionInspectorMenu);
00372     contextMenu->addMenu(moveInspectorMenu);
00373 
00374     connect(autoZoomButton, SIGNAL(toggled(bool)), canvas,
00375             SLOT(setAutoZoom(bool)));
00376 
00377     connect(canvas, SIGNAL(autoZoomChanged(bool)),
00378             autoZoomButton, SLOT(setChecked(bool)));
00379 
00380     {
00381       unsigned int i = 0;
00382       while (opt.inspect.solution(i)) {
00383         addSolutionInspector(opt.inspect.solution(i++));
00384       }
00385       i = 0;
00386       while (opt.inspect.click(i)) {
00387         addDoubleClickInspector(opt.inspect.click(i++));
00388       }
00389       i = 0;
00390       while (opt.inspect.move(i)) {
00391         addMoveInspector(opt.inspect.move(i++));
00392       }
00393       i = 0;
00394       while (opt.inspect.compare(i)) {
00395         addComparator(opt.inspect.compare(i++));
00396       }
00397     }
00398 
00399 
00400     layout->addWidget(scrollArea, 0,0,-1,1);
00401     layout->addWidget(canvas->scaleBar, 1,1, Qt::AlignHCenter);
00402     layout->addWidget(autoZoomButton, 0,1, Qt::AlignHCenter);
00403 
00404     setLayout(layout);
00405 
00406     canvas->show();
00407 
00408     resize(500, 400);
00409 
00410     // enables on_<sender>_<signal>() mechanism
00411     QMetaObject::connectSlotsByName(this);
00412   }
00413 
00414   void
00415   Gist::resizeEvent(QResizeEvent*) {
00416     canvas->resizeToOuter();
00417   }
00418 
00419   void
00420   Gist::addInspector(Inspector* i0, QAction*& nas, QAction*& nad,
00421                      QAction*&nam) {
00422     if (doubleClickInspectorGroup->
00423       actions().indexOf(nullDoubleClickInspector) != -1) {
00424       doubleClickInspectorGroup->removeAction(nullDoubleClickInspector);
00425       solutionInspectorGroup->removeAction(nullSolutionInspector);
00426       moveInspectorGroup->removeAction(nullMoveInspector);
00427     }
00428     canvas->addSolutionInspector(i0);
00429     canvas->addDoubleClickInspector(i0);
00430     canvas->addMoveInspector(i0);
00431 
00432     nas = new QAction(i0->name().c_str(), this);
00433     nas->setCheckable(true);
00434     solutionInspectorGroup->addAction(nas);
00435     solutionInspectorMenu->clear();
00436     solutionInspectorMenu->addActions(solutionInspectorGroup->actions());
00437 
00438     nad = new QAction(i0->name().c_str(), this);
00439     nad->setCheckable(true);
00440     doubleClickInspectorGroup->addAction(nad);
00441     doubleClickInspectorMenu->clear();
00442     doubleClickInspectorMenu->addActions(
00443       doubleClickInspectorGroup->actions());
00444 
00445     nam = new QAction(i0->name().c_str(), this);
00446     nam->setCheckable(true);
00447     moveInspectorGroup->addAction(nam);
00448     moveInspectorMenu->clear();
00449     moveInspectorMenu->addActions(
00450       moveInspectorGroup->actions());
00451     
00452     QAction* ia = new QAction(i0->name().c_str(), this);
00453     inspectGroup->addAction(ia);
00454     QAction* ibfpa = new QAction(i0->name().c_str(), this);
00455     inspectBeforeFPGroup->addAction(ibfpa);
00456 
00457     if (inspectGroup->actions().size() < 10) {
00458       ia->setShortcut(QKeySequence(
00459         QString("").setNum(inspectGroup->actions().size())));
00460       ibfpa->setShortcut(QKeySequence(QString("Ctrl+")+
00461         QString("").setNum(inspectBeforeFPGroup->actions().size())));
00462     }
00463   }
00464 
00465   void
00466   Gist::addSolutionInspector(Inspector* ins) {
00467     QAction* nas;
00468     QAction* nad;
00469     QAction* nam;
00470     if (doubleClickInspectorGroup->
00471       actions().indexOf(nullDoubleClickInspector) == -1) {
00472       QList<QAction*> is = solutionInspectorGroup->actions();
00473       for (int i=0; i<is.size(); i++) {
00474         canvas->activateSolutionInspector(i,false);
00475         is[i]->setChecked(false);
00476       }
00477     }
00478     addInspector(ins, nas,nad,nam);
00479     nas->setChecked(true);
00480     selectSolutionInspector(nas);
00481   }
00482 
00483   void
00484   Gist::addDoubleClickInspector(Inspector* ins) {
00485     QAction* nas;
00486     QAction* nad;
00487     QAction* nam;
00488     if (doubleClickInspectorGroup->
00489       actions().indexOf(nullDoubleClickInspector) == -1) {
00490       QList<QAction*> is = doubleClickInspectorGroup->actions();
00491       for (int i=0; i<is.size(); i++) {
00492         canvas->activateDoubleClickInspector(i,false);
00493         is[i]->setChecked(false);
00494       }
00495     }
00496     addInspector(ins, nas,nad,nam);
00497     nad->setChecked(true);
00498     selectDoubleClickInspector(nad);
00499   }
00500 
00501   void
00502   Gist::addMoveInspector(Inspector* ins) {
00503     QAction* nas;
00504     QAction* nad;
00505     QAction* nam;
00506     if (doubleClickInspectorGroup->
00507       actions().indexOf(nullDoubleClickInspector) == -1) {
00508       QList<QAction*> is = moveInspectorGroup->actions();
00509       for (int i=0; i<is.size(); i++) {
00510         canvas->activateMoveInspector(i,false);
00511         is[i]->setChecked(false);
00512       }
00513     }
00514     addInspector(ins, nas,nad,nam);
00515     nam->setChecked(true);
00516     selectMoveInspector(nam);
00517   }
00518 
00519   void
00520   Gist::addComparator(Comparator* c) {
00521     if (comparatorGroup->actions().indexOf(nullComparator) == -1) {
00522       QList<QAction*> is = comparatorGroup->actions();
00523       for (int i=0; i<is.size(); i++) {
00524         canvas->activateComparator(i,false);
00525         is[i]->setChecked(false);
00526       }
00527     } else {
00528       comparatorGroup->removeAction(nullComparator);
00529     }
00530     canvas->addComparator(c);
00531 
00532     QAction* ncs = new QAction(c->name().c_str(), this);
00533     ncs->setCheckable(true);
00534     comparatorGroup->addAction(ncs);
00535     comparatorMenu->clear();
00536     comparatorMenu->addActions(comparatorGroup->actions());
00537     ncs->setChecked(true);
00538     selectComparator(ncs);
00539   }
00540 
00541   Gist::~Gist(void) { delete canvas; }
00542 
00543   void
00544   Gist::on_canvas_contextMenu(QContextMenuEvent* event) {
00545     contextMenu->popup(event->globalPos());
00546   }
00547 
00548   void
00549   Gist::on_canvas_statusChanged(VisualNode* n, const Statistics& stats,
00550                                 bool finished) {
00551     if (!finished) {
00552       inspect->setEnabled(false);
00553       inspectGroup->setEnabled(false);
00554       inspectBeforeFP->setEnabled(false);
00555       inspectBeforeFPGroup->setEnabled(false);
00556       compareNode->setEnabled(false);
00557       compareNodeBeforeFP->setEnabled(false);
00558       showNodeStats->setEnabled(false);
00559       stop->setEnabled(true);
00560       reset->setEnabled(false);
00561       navUp->setEnabled(false);
00562       navDown->setEnabled(false);
00563       navLeft->setEnabled(false);
00564       navRight->setEnabled(false);
00565       navRoot->setEnabled(false);
00566       navNextSol->setEnabled(false);
00567       navPrevSol->setEnabled(false);
00568 
00569       searchNext->setEnabled(false);
00570       searchAll->setEnabled(false);
00571       toggleHidden->setEnabled(false);
00572       hideFailed->setEnabled(false);
00573       unhideAll->setEnabled(false);
00574       
00575       toggleStop->setEnabled(false);
00576       unstopAll->setEnabled(false);
00577       
00578       zoomToFit->setEnabled(false);
00579       center->setEnabled(false);
00580       exportPDF->setEnabled(false);
00581       exportWholeTreePDF->setEnabled(false);
00582       print->setEnabled(false);
00583 
00584       setPath->setEnabled(false);
00585       inspectPath->setEnabled(false);
00586       bookmarkNode->setEnabled(false);
00587       bookmarksGroup->setEnabled(false);
00588     } else {
00589       stop->setEnabled(false);
00590       reset->setEnabled(true);
00591 
00592       if ( (n->isOpen() || n->hasOpenChildren()) && (!n->isHidden()) ) {
00593         searchNext->setEnabled(true);
00594         searchAll->setEnabled(true);
00595       } else {
00596         searchNext->setEnabled(false);
00597         searchAll->setEnabled(false);
00598       }
00599       if (n->getNumberOfChildren() > 0) {
00600         navDown->setEnabled(true);
00601         toggleHidden->setEnabled(true);
00602         hideFailed->setEnabled(true);
00603         unhideAll->setEnabled(true);
00604         unstopAll->setEnabled(true);
00605       } else {
00606         navDown->setEnabled(false);
00607         toggleHidden->setEnabled(false);
00608         hideFailed->setEnabled(false);
00609         unhideAll->setEnabled(false);
00610         unstopAll->setEnabled(false);
00611       }
00612       
00613       toggleStop->setEnabled(n->getStatus() == STOP ||
00614         n->getStatus() == UNSTOP);
00615 
00616       showNodeStats->setEnabled(true);
00617       inspect->setEnabled(true);
00618       if (n->getStatus() == UNDETERMINED) {
00619         inspectGroup->setEnabled(false);
00620         inspectBeforeFP->setEnabled(false);
00621         inspectBeforeFPGroup->setEnabled(false);
00622         compareNode->setEnabled(false);
00623         compareNodeBeforeFP->setEnabled(false);
00624       } else {
00625         inspectGroup->setEnabled(true);        
00626         inspectBeforeFP->setEnabled(true);
00627         inspectBeforeFPGroup->setEnabled(true);
00628         compareNode->setEnabled(true);
00629         compareNodeBeforeFP->setEnabled(true);
00630       }
00631 
00632       VisualNode* p = n->getParent();
00633       if (p == NULL) {
00634         inspectBeforeFP->setEnabled(false);
00635         inspectBeforeFPGroup->setEnabled(false);
00636         navRoot->setEnabled(false);
00637         navUp->setEnabled(false);
00638         navRight->setEnabled(false);
00639         navLeft->setEnabled(false);
00640       } else {
00641         navRoot->setEnabled(true);
00642         navUp->setEnabled(true);
00643         unsigned int alt = n->getAlternative();
00644         navRight->setEnabled(alt + 1 < p->getNumberOfChildren());
00645         navLeft->setEnabled(alt > 0);
00646       }
00647 
00648       VisualNode* root = n;
00649       while (!root->isRoot())
00650         root = root->getParent();
00651       NextSolCursor nsc(n, false);
00652       PreorderNodeVisitor<NextSolCursor> nsv(nsc);
00653       while (nsv.next()) {}
00654       navNextSol->setEnabled(nsv.getCursor().node() != root);
00655 
00656       NextSolCursor psc(n, true);
00657       PreorderNodeVisitor<NextSolCursor> psv(psc);
00658       while (psv.next()) {}
00659       navPrevSol->setEnabled(psv.getCursor().node() != root);
00660 
00661       zoomToFit->setEnabled(true);
00662       center->setEnabled(true);
00663       exportPDF->setEnabled(true);
00664       exportWholeTreePDF->setEnabled(true);
00665       print->setEnabled(true);
00666 
00667       setPath->setEnabled(true);
00668       inspectPath->setEnabled(true);
00669 
00670       bookmarkNode->setEnabled(true);
00671       bookmarksGroup->setEnabled(true);
00672     }
00673     emit statusChanged(stats,finished);
00674   }
00675 
00676   void
00677   Gist::inspectWithAction(QAction* a) {
00678     canvas->inspectCurrentNode(true,inspectGroup->actions().indexOf(a));
00679   }
00680 
00681   void
00682   Gist::inspectBeforeFPWithAction(QAction* a) {
00683     canvas->inspectCurrentNode(false,
00684       inspectBeforeFPGroup->actions().indexOf(a));
00685   }
00686 
00687   bool
00688   Gist::finish(void) {
00689     return canvas->finish();
00690   }
00691 
00692   void
00693   Gist::selectDoubleClickInspector(QAction* a) {
00694     canvas->activateDoubleClickInspector(
00695       doubleClickInspectorGroup->actions().indexOf(a),
00696       a->isChecked());
00697   }
00698   void
00699   Gist::selectSolutionInspector(QAction* a) {
00700     canvas->activateSolutionInspector(
00701       solutionInspectorGroup->actions().indexOf(a),
00702       a->isChecked());
00703   }
00704   void
00705   Gist::selectMoveInspector(QAction* a) {
00706     canvas->activateMoveInspector(
00707       moveInspectorGroup->actions().indexOf(a),
00708       a->isChecked());
00709   }
00710   void
00711   Gist::selectComparator(QAction* a) {
00712     canvas->activateComparator(comparatorGroup->actions().indexOf(a),
00713       a->isChecked());
00714   }
00715   void
00716   Gist::selectBookmark(QAction* a) {
00717     int idx = bookmarksGroup->actions().indexOf(a);
00718     canvas->setCurrentNode(canvas->bookmarks[idx]);
00719     canvas->centerCurrentNode();
00720   }
00721 
00722   void
00723   Gist::addBookmark(const QString& id) {
00724     if (bookmarksGroup->actions().indexOf(nullBookmark) != -1) {
00725       bookmarksGroup->removeAction(nullBookmark);
00726     }
00727 
00728     QAction* nb = new QAction(id, this);
00729     nb->setCheckable(true);
00730     bookmarksGroup->addAction(nb);
00731   }
00732 
00733   void
00734   Gist::removeBookmark(int idx) {
00735     QAction* a = bookmarksGroup->actions()[idx];
00736     bookmarksGroup->removeAction(a);
00737     if (bookmarksGroup->actions().size() == 0) {
00738       bookmarksGroup->addAction(nullBookmark);
00739     }
00740   }
00741   
00742   void
00743   Gist::populateBookmarksMenu(void) {
00744     bookmarksMenu->clear();
00745     bookmarksMenu->addAction(bookmarkNode);
00746     bookmarksMenu->addSeparator();
00747     bookmarksMenu->addActions(bookmarksGroup->actions());
00748   }
00749 
00750   void
00751   Gist::populateInspectors(void) {
00752     inspectNodeMenu->clear();
00753     inspectNodeMenu->addAction(inspect);
00754     inspectNodeMenu->addSeparator();
00755     inspectNodeMenu->addActions(inspectGroup->actions());
00756     inspectNodeBeforeFPMenu->clear();
00757     inspectNodeBeforeFPMenu->addAction(inspectBeforeFP);
00758     inspectNodeBeforeFPMenu->addSeparator();
00759     inspectNodeBeforeFPMenu->addActions(inspectBeforeFPGroup->actions());
00760   }
00761   
00762   void
00763   Gist::setAutoHideFailed(bool b) { canvas->setAutoHideFailed(b); }
00764   void
00765   Gist::setAutoZoom(bool b) { canvas->setAutoZoom(b); }
00766   bool
00767   Gist::getAutoHideFailed(void) { return canvas->getAutoHideFailed(); }
00768   bool
00769   Gist::getAutoZoom(void) { return canvas->getAutoZoom(); }
00770   void
00771   Gist::setRefresh(int i) { canvas->setRefresh(i); }
00772   bool
00773   Gist::getSmoothScrollAndZoom(void) {
00774     return canvas->getSmoothScrollAndZoom();
00775   }
00776   void
00777   Gist::setSmoothScrollAndZoom(bool b) {
00778     canvas->setSmoothScrollAndZoom(b);
00779   }
00780   void
00781   Gist::setRecompDistances(int c_d, int a_d) {
00782     canvas->setRecompDistances(c_d, a_d);
00783   }
00784 
00785   int
00786   Gist::getCd(void) {
00787     return canvas->c_d;
00788   }
00789   int
00790   Gist::getAd(void) {
00791     return canvas->a_d;
00792   }
00793 
00794   void
00795   Gist::setShowCopies(bool b) {
00796     canvas->setShowCopies(b);
00797   }
00798   bool
00799   Gist::getShowCopies(void) {
00800     return canvas->getShowCopies();
00801   }
00802 
00803   void
00804   Gist::showStats(void) {
00805     nodeStatInspector->showStats();
00806     canvas->emitStatusChanged();
00807   }
00808 
00809 }}
00810 
00811 // STATISTICS: gist-any