Generated on Mon Nov 30 23:53:19 2009 for Gecode by doxygen 1.6.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: 2009-05-14 19:49:13 +0200 (Thu, 14 May 2009) $ by $Author: tack $
00011  *     $Revision: 9119 $
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     QScrollArea* scrollArea = new QScrollArea(this);
00051 
00052     scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
00053     scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
00054     scrollArea->setAlignment(Qt::AlignHCenter);
00055     scrollArea->setAutoFillBackground(true);
00056     QPalette myPalette(scrollArea->palette());
00057     myPalette.setColor(QPalette::Window, Qt::white);
00058     scrollArea->setPalette(myPalette);
00059     canvas = new TreeCanvas(root, bab, this,opt);
00060     canvas->setPalette(myPalette);
00061     canvas->setObjectName("canvas");
00062 
00063     scrollArea->setWidget(canvas);
00064 
00065     connect(canvas, SIGNAL(solution(const Space*)),
00066             this, SIGNAL(solution(const Space*)));
00067 
00068     connect(canvas, SIGNAL(finished(void)), this, SIGNAL(finished(void)));
00069 
00070     QPixmap myPic;
00071     myPic.loadFromData(zoomToFitIcon, sizeof(zoomToFitIcon));
00072 
00073     QToolButton* autoZoomButton = new QToolButton();
00074     autoZoomButton->setCheckable(true);
00075     autoZoomButton->setIcon(myPic);
00076 
00077     QSlider* scaleBar = new QSlider(Qt::Vertical, this);
00078     canvas->scaleBar = scaleBar;
00079     scaleBar->setObjectName("scaleBar");
00080     scaleBar->setMinimum(LayoutConfig::minScale);
00081     scaleBar->setMaximum(LayoutConfig::maxScale);
00082     scaleBar->setValue(LayoutConfig::defScale);
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     stop = new QAction("Stop search", this);
00094     stop->setShortcut(QKeySequence("Esc"));
00095     connect(stop, SIGNAL(triggered()), canvas,
00096                     SLOT(stopSearch()));
00097 
00098     reset = new QAction("Reset", this);
00099     reset->setShortcut(QKeySequence("Ctrl+R"));
00100     connect(reset, SIGNAL(triggered()), canvas,
00101             SLOT(reset()));
00102 
00103     navUp = new QAction("Up", this);
00104     navUp->setShortcut(QKeySequence("Up"));
00105     connect(navUp, SIGNAL(triggered()), canvas,
00106                    SLOT(navUp()));
00107 
00108     navDown = new QAction("Down", this);
00109     navDown->setShortcut(QKeySequence("Down"));
00110     connect(navDown, SIGNAL(triggered()), canvas,
00111                      SLOT(navDown()));
00112 
00113     navLeft = new QAction("Left", this);
00114     navLeft->setShortcut(QKeySequence("Left"));
00115     connect(navLeft, SIGNAL(triggered()), canvas,
00116                      SLOT(navLeft()));
00117 
00118     navRight = new QAction("Right", this);
00119     navRight->setShortcut(QKeySequence("Right"));
00120     connect(navRight, SIGNAL(triggered()), canvas,
00121                       SLOT(navRight()));
00122 
00123     navRoot = new QAction("Root", this);
00124     navRoot->setShortcut(QKeySequence("R"));
00125     connect(navRoot, SIGNAL(triggered()), canvas,
00126                       SLOT(navRoot()));
00127 
00128     navNextSol = new QAction("To next solution", this);
00129     navNextSol->setShortcut(QKeySequence("Shift+Right"));
00130     connect(navNextSol, SIGNAL(triggered()), canvas,
00131                       SLOT(navNextSol()));
00132 
00133     navPrevSol = new QAction("To previous solution", this);
00134     navPrevSol->setShortcut(QKeySequence("Shift+Left"));
00135     connect(navPrevSol, SIGNAL(triggered()), canvas,
00136                       SLOT(navPrevSol()));
00137 
00138     searchNext = new QAction("Next solution", this);
00139     searchNext->setShortcut(QKeySequence("N"));
00140     connect(searchNext, SIGNAL(triggered()), canvas, SLOT(searchOne()));
00141 
00142     searchAll = new QAction("All solutions", this);
00143     searchAll->setShortcut(QKeySequence("A"));
00144     connect(searchAll, SIGNAL(triggered()), canvas, SLOT(searchAll()));
00145 
00146     toggleHidden = new QAction("Hide/unhide", this);
00147     toggleHidden->setShortcut(QKeySequence("H"));
00148     connect(toggleHidden, SIGNAL(triggered()), canvas, SLOT(toggleHidden()));
00149 
00150     hideFailed = new QAction("Hide failed subtrees", this);
00151     hideFailed->setShortcut(QKeySequence("F"));
00152     connect(hideFailed, SIGNAL(triggered()), canvas, SLOT(hideFailed()));
00153 
00154     unhideAll = new QAction("Unhide all", this);
00155     unhideAll->setShortcut(QKeySequence("U"));
00156     connect(unhideAll, SIGNAL(triggered()), canvas, SLOT(unhideAll()));
00157 
00158     zoomToFit = new QAction("Zoom to fit", this);
00159     zoomToFit->setShortcut(QKeySequence("Z"));
00160     connect(zoomToFit, SIGNAL(triggered()), canvas, SLOT(zoomToFit()));
00161 
00162     center = new QAction("Center current node", this);
00163     center->setShortcut(QKeySequence("C"));
00164     connect(center, SIGNAL(triggered()), canvas, SLOT(centerCurrentNode()));
00165 
00166     exportPDF = new QAction("Export subtree PDF...", this);
00167     exportPDF->setShortcut(QKeySequence("P"));
00168     connect(exportPDF, SIGNAL(triggered()), canvas,
00169             SLOT(exportPDF()));
00170 
00171     exportWholeTreePDF = new QAction("Export PDF...", this);
00172     exportWholeTreePDF->setShortcut(QKeySequence("Ctrl+Shift+P"));
00173     connect(exportWholeTreePDF, SIGNAL(triggered()), canvas,
00174             SLOT(exportWholeTreePDF()));
00175 
00176     print = new QAction("Print...", this);
00177     print->setShortcut(QKeySequence("Ctrl+P"));
00178     connect(print, SIGNAL(triggered()), canvas,
00179             SLOT(print()));
00180 
00181     setPath = new QAction("Set path", this);
00182     setPath->setShortcut(QKeySequence("Shift+P"));
00183     connect(setPath, SIGNAL(triggered()), canvas, SLOT(setPath()));
00184 
00185     inspectPath = new QAction("Inspect path", this);
00186     inspectPath->setShortcut(QKeySequence("Shift+I"));
00187     connect(inspectPath, SIGNAL(triggered()), canvas, SLOT(inspectPath()));
00188 
00189     showNodeStats = new QAction("Node statistics", this);
00190     showNodeStats->setShortcut(QKeySequence("S"));
00191     connect(showNodeStats, SIGNAL(triggered()),
00192             this, SLOT(showStats()));
00193 
00194     addAction(inspect);
00195     addAction(stop);
00196     addAction(reset);
00197     addAction(navUp);
00198     addAction(navDown);
00199     addAction(navLeft);
00200     addAction(navRight);
00201     addAction(navRoot);
00202     addAction(navNextSol);
00203     addAction(navPrevSol);
00204 
00205     addAction(searchNext);
00206     addAction(searchAll);
00207     addAction(toggleHidden);
00208     addAction(hideFailed);
00209     addAction(unhideAll);
00210     addAction(zoomToFit);
00211     addAction(center);
00212     addAction(exportPDF);
00213     addAction(exportWholeTreePDF);
00214     addAction(print);
00215 
00216     addAction(setPath);
00217     addAction(inspectPath);
00218     addAction(showNodeStats);
00219 
00220     nullSolutionInspector = new QAction("<none>",this);
00221     nullSolutionInspector->setCheckable(true);
00222     nullSolutionInspector->setChecked(false);
00223     nullSolutionInspector->setEnabled(false);
00224     solutionInspectorGroup = new QActionGroup(this);
00225     solutionInspectorGroup->setExclusive(false);
00226     solutionInspectorGroup->addAction(nullSolutionInspector);
00227     connect(solutionInspectorGroup, SIGNAL(triggered(QAction*)),
00228             this, SLOT(selectSolutionInspector(QAction*)));
00229 
00230     nullDoubleClickInspector = new QAction("<none>",this);
00231     nullDoubleClickInspector->setCheckable(true);
00232     nullDoubleClickInspector->setChecked(false);
00233     nullDoubleClickInspector->setEnabled(false);
00234     doubleClickInspectorGroup = new QActionGroup(this);
00235     doubleClickInspectorGroup->setExclusive(false);
00236     doubleClickInspectorGroup->addAction(nullDoubleClickInspector);
00237     connect(doubleClickInspectorGroup, SIGNAL(triggered(QAction*)),
00238             this, SLOT(selectDoubleClickInspector(QAction*)));
00239 
00240     solutionInspectorMenu = new QMenu("Solution inspectors");
00241     solutionInspectorMenu->addActions(solutionInspectorGroup->actions());
00242     doubleClickInspectorMenu = new QMenu("Double click inspectors");
00243     doubleClickInspectorMenu->addActions(
00244       doubleClickInspectorGroup->actions());
00245 
00246     contextMenu = new QMenu(this);
00247     contextMenu->addAction(inspect);
00248     contextMenu->addAction(showNodeStats);
00249     contextMenu->addAction(center);
00250 
00251     contextMenu->addSeparator();
00252 
00253     contextMenu->addAction(searchNext);
00254     contextMenu->addAction(searchAll);
00255 
00256     contextMenu->addSeparator();
00257 
00258     contextMenu->addAction(toggleHidden);
00259     contextMenu->addAction(hideFailed);
00260     contextMenu->addAction(unhideAll);
00261 
00262     contextMenu->addSeparator();
00263 
00264     contextMenu->addAction(setPath);
00265     contextMenu->addAction(inspectPath);
00266 
00267     contextMenu->addSeparator();
00268 
00269     contextMenu->addMenu(doubleClickInspectorMenu);
00270     contextMenu->addMenu(solutionInspectorMenu);
00271 
00272     connect(scaleBar, SIGNAL(valueChanged(int)), canvas, SLOT(scaleTree(int)));
00273 
00274     connect(canvas, SIGNAL(scaleChanged(int)), scaleBar, SLOT(setValue(int)));
00275 
00276     connect(autoZoomButton, SIGNAL(toggled(bool)), canvas,
00277             SLOT(setAutoZoom(bool)));
00278 
00279     connect(canvas, SIGNAL(autoZoomChanged(bool)),
00280             autoZoomButton, SLOT(setChecked(bool)));
00281 
00282     connect(&canvas->searcher, SIGNAL(scaleChanged(int)),
00283             scaleBar, SLOT(setValue(int)));
00284 
00285     layout->addWidget(scrollArea, 0,0,-1,1);
00286     layout->addWidget(scaleBar, 1,1, Qt::AlignHCenter);
00287     layout->addWidget(autoZoomButton, 0,1, Qt::AlignHCenter);
00288 
00289     setLayout(layout);
00290 
00291     canvas->show();
00292 
00293     resize(500, 400);
00294 
00295     // enables on_<sender>_<signal>() mechanism
00296     QMetaObject::connectSlotsByName(this);
00297   }
00298 
00299   void
00300   Gist::resizeEvent(QResizeEvent*) {
00301     canvas->resizeToOuter();
00302   }
00303 
00304   void
00305   Gist::addInspector(Inspector* i0, bool solutionInspector) {
00306     if (doubleClickInspectorGroup->
00307       actions().indexOf(nullDoubleClickInspector) != -1) {
00308       doubleClickInspectorGroup->removeAction(nullDoubleClickInspector);
00309       solutionInspectorGroup->removeAction(nullSolutionInspector);
00310     }
00311     canvas->addSolutionInspector(i0);
00312     canvas->addDoubleClickInspector(i0);
00313     QAction* nas = new QAction(i0->name().c_str(), this);
00314     nas->setCheckable(true);
00315     solutionInspectorGroup->addAction(nas);
00316     solutionInspectorMenu->clear();
00317     solutionInspectorMenu->addActions(solutionInspectorGroup->actions());
00318 
00319     QAction* nad = new QAction(i0->name().c_str(), this);
00320     nad->setCheckable(true);
00321     doubleClickInspectorGroup->addAction(nad);
00322     doubleClickInspectorMenu->clear();
00323     doubleClickInspectorMenu->addActions(
00324       doubleClickInspectorGroup->actions());
00325 
00326     if (solutionInspector) {
00327       nas->setChecked(true);
00328       selectSolutionInspector(nas);
00329     } else {
00330       nad->setChecked(true);
00331       selectDoubleClickInspector(nad);
00332     }
00333   }
00334 
00335   void
00336   Gist::addSolutionInspector(Inspector* i) {
00337     addInspector(i, true);
00338   }
00339 
00340   void
00341   Gist::addDoubleClickInspector(Inspector* i) {
00342     addInspector(i, false);
00343   }
00344 
00345   Gist::~Gist(void) { delete canvas; }
00346 
00347   void
00348   Gist::on_canvas_contextMenu(QContextMenuEvent* event) {
00349     contextMenu->popup(event->globalPos());
00350   }
00351 
00352   void
00353   Gist::on_canvas_statusChanged(VisualNode* n, const Statistics& stats,
00354                                 bool finished) {
00355     if (!finished) {
00356       inspect->setEnabled(false);
00357       stop->setEnabled(true);
00358       reset->setEnabled(false);
00359       navUp->setEnabled(false);
00360       navDown->setEnabled(false);
00361       navLeft->setEnabled(false);
00362       navRight->setEnabled(false);
00363       navRoot->setEnabled(false);
00364       navNextSol->setEnabled(false);
00365       navPrevSol->setEnabled(false);
00366 
00367       searchNext->setEnabled(false);
00368       searchAll->setEnabled(false);
00369       toggleHidden->setEnabled(false);
00370       hideFailed->setEnabled(false);
00371       unhideAll->setEnabled(false);
00372       zoomToFit->setEnabled(false);
00373       center->setEnabled(false);
00374       exportPDF->setEnabled(false);
00375       exportWholeTreePDF->setEnabled(false);
00376       print->setEnabled(false);
00377 
00378       setPath->setEnabled(false);
00379       inspectPath->setEnabled(false);
00380     } else {
00381       inspect->setEnabled(true);
00382       stop->setEnabled(false);
00383       reset->setEnabled(true);
00384 
00385       if ( (n->isOpen() || n->hasOpenChildren()) && (!n->isHidden()) ) {
00386         searchNext->setEnabled(true);
00387         searchAll->setEnabled(true);
00388       } else {
00389         searchNext->setEnabled(false);
00390         searchAll->setEnabled(false);
00391       }
00392       if (n->getNumberOfChildren() > 0) {
00393         navDown->setEnabled(true);
00394         toggleHidden->setEnabled(true);
00395         hideFailed->setEnabled(true);
00396         unhideAll->setEnabled(true);
00397       } else {
00398         navDown->setEnabled(false);
00399         toggleHidden->setEnabled(false);
00400         hideFailed->setEnabled(false);
00401         unhideAll->setEnabled(false);
00402       }
00403 
00404       VisualNode* p = n->getParent();
00405       if (p == NULL) {
00406         navRoot->setEnabled(false);
00407         navUp->setEnabled(false);
00408         navRight->setEnabled(false);
00409         navLeft->setEnabled(false);
00410       } else {
00411         navRoot->setEnabled(true);
00412         navUp->setEnabled(true);
00413         unsigned int alt = n->getAlternative();
00414         navRight->setEnabled(alt + 1 < p->getNumberOfChildren());
00415         navLeft->setEnabled(alt > 0);
00416       }
00417 
00418       VisualNode* root = n;
00419       while (!root->isRoot())
00420         root = root->getParent();
00421       NextSolCursor nsc(n, false);
00422       PreorderNodeVisitor<NextSolCursor> nsv(nsc);
00423       while (nsv.next()) {}
00424       navNextSol->setEnabled(nsv.getCursor().node() != root);
00425 
00426       NextSolCursor psc(n, true);
00427       PreorderNodeVisitor<NextSolCursor> psv(psc);
00428       while (psv.next()) {}
00429       navPrevSol->setEnabled(psv.getCursor().node() != root);
00430 
00431       zoomToFit->setEnabled(true);
00432       center->setEnabled(true);
00433       exportPDF->setEnabled(true);
00434       exportWholeTreePDF->setEnabled(true);
00435       print->setEnabled(true);
00436 
00437       setPath->setEnabled(true);
00438       inspectPath->setEnabled(true);
00439     }
00440     emit statusChanged(stats,finished);
00441   }
00442 
00443   bool
00444   Gist::finish(void) {
00445     return canvas->finish();
00446   }
00447 
00448   void
00449   Gist::selectDoubleClickInspector(QAction* a) {
00450     canvas->activateDoubleClickInspector(
00451       doubleClickInspectorGroup->actions().indexOf(a),
00452       a->isChecked());
00453   }
00454   void
00455   Gist::selectSolutionInspector(QAction* a) {
00456     canvas->activateSolutionInspector(
00457       solutionInspectorGroup->actions().indexOf(a),
00458       a->isChecked());
00459   }
00460 
00461   void
00462   Gist::setAutoHideFailed(bool b) { canvas->setAutoHideFailed(b); }
00463   void
00464   Gist::setAutoZoom(bool b) { canvas->setAutoZoom(b); }
00465   bool
00466   Gist::getAutoHideFailed(void) { return canvas->getAutoHideFailed(); }
00467   bool
00468   Gist::getAutoZoom(void) { return canvas->getAutoZoom(); }
00469   void
00470   Gist::setRefresh(int i) { canvas->setRefresh(i); }
00471   bool
00472   Gist::getSmoothScrollAndZoom(void) {
00473     return canvas->getSmoothScrollAndZoom();
00474   }
00475   void
00476   Gist::setSmoothScrollAndZoom(bool b) {
00477     canvas->setSmoothScrollAndZoom(b);
00478   }
00479   void
00480   Gist::setRecompDistances(int c_d, int a_d) {
00481     canvas->setRecompDistances(c_d, a_d);
00482   }
00483 
00484   int
00485   Gist::getCd(void) {
00486     return canvas->c_d;
00487   }
00488   int
00489   Gist::getAd(void) {
00490     return canvas->a_d;
00491   }
00492 
00493   void
00494   Gist::setShowCopies(bool b) {
00495     canvas->setShowCopies(b);
00496   }
00497   bool
00498   Gist::getShowCopies(void) {
00499     return canvas->getShowCopies();
00500   }
00501 
00502   void
00503   Gist::showStats(void) {
00504     nodeStatInspector->showStats();
00505     canvas->emitStatusChanged();
00506   }
00507 
00508 }}
00509 
00510 // STATISTICS: gist-any