00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
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
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