Generated on Tue Feb 11 2025 17:33:26 for Gecode by doxygen 1.12.0
treecanvas.cpp
Go to the documentation of this file.
1/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
2/*
3 * Main authors:
4 * Guido Tack <tack@gecode.org>
5 *
6 * Copyright:
7 * Guido Tack, 2006
8 *
9 * This file is part of Gecode, the generic constraint
10 * development environment:
11 * http://www.gecode.org
12 *
13 * Permission is hereby granted, free of charge, to any person obtaining
14 * a copy of this software and associated documentation files (the
15 * "Software"), to deal in the Software without restriction, including
16 * without limitation the rights to use, copy, modify, merge, publish,
17 * distribute, sublicense, and/or sell copies of the Software, and to
18 * permit persons to whom the Software is furnished to do so, subject to
19 * the following conditions:
20 *
21 * The above copyright notice and this permission notice shall be
22 * included in all copies or substantial portions of the Software.
23 *
24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 *
32 */
33
34#include <QtGui/QPainter>
35#include <QPrinter>
36#include <QPrintDialog>
37
38#include <stack>
39#include <fstream>
40
42
46
47#include <gecode/search.hh>
49
50namespace Gecode { namespace Gist {
51
53 QWidget* parent, const Options& opt)
54 : QWidget(parent)
55 , mutex(QMutex::Recursive)
56 , layoutMutex(QMutex::Recursive)
57 , finishedFlag(false)
58 , compareNodes(false), compareNodesBeforeFP(false)
59 , autoHideFailed(true), autoZoom(false)
60 , refresh(500), refreshPause(0), smoothScrollAndZoom(false)
61 , moveDuringSearch(false)
62 , zoomTimeLine(500)
63 , scrollTimeLine(1000), targetX(0), sourceX(0), targetY(0), sourceY(0)
64 , targetW(0), targetH(0), targetScale(0)
65 , layoutDoneTimerId(0) {
66 QMutexLocker locker(&mutex);
67 curBest = (bab ? new BestNode(NULL) : NULL);
68 if (rootSpace->status() == SS_FAILED) {
69 if (!opt.clone)
70 delete rootSpace;
71 rootSpace = NULL;
72 } else {
73 rootSpace = Gecode::Search::snapshot(rootSpace,opt);
74 }
76 int rootIdx = na->allocate(rootSpace);
77 assert(rootIdx == 0); (void) rootIdx;
78 root = (*na)[0];
79 root->layout(*na);
80 root->setMarked(true);
82 pathHead = root;
84
85 setAutoFillBackground(true);
86
87 connect(&searcher, SIGNAL(update(int,int,int)), this,
88 SLOT(layoutDone(int,int,int)));
89 connect(&searcher, SIGNAL(statusChanged(bool)), this,
90 SLOT(statusChanged(bool)));
91
92 connect(&searcher, SIGNAL(solution(const Space*)),
93 this, SIGNAL(solution(const Space*)),
94 Qt::BlockingQueuedConnection);
95 connect(this, SIGNAL(solution(const Space*)),
96 this, SLOT(inspectSolution(const Space*)));
97
98 connect(&searcher, SIGNAL(moveToNode(VisualNode*,bool)),
99 this, SLOT(setCurrentNode(VisualNode*,bool)),
100 Qt::BlockingQueuedConnection);
101
102 connect(&searcher, SIGNAL(searchFinished(void)), this, SIGNAL(searchFinished(void)));
103
104 connect(&scrollTimeLine, SIGNAL(frameChanged(int)),
105 this, SLOT(scroll(int)));
106 scrollTimeLine.setCurveShape(QTimeLine::EaseInOutCurve);
107
108 scaleBar = new QSlider(Qt::Vertical, this);
109 scaleBar->setObjectName("scaleBar");
110 scaleBar->setMinimum(LayoutConfig::minScale);
111 scaleBar->setMaximum(LayoutConfig::maxScale);
113 connect(scaleBar, SIGNAL(valueChanged(int)),
114 this, SLOT(scaleTree(int)));
115 connect(this, SIGNAL(scaleChanged(int)), scaleBar, SLOT(setValue(int)));
116 connect(&searcher, SIGNAL(scaleChanged(int)),
117 scaleBar, SLOT(setValue(int)));
118
119 connect(&zoomTimeLine, SIGNAL(frameChanged(int)),
120 scaleBar, SLOT(setValue(int)));
121 zoomTimeLine.setCurveShape(QTimeLine::EaseInOutCurve);
122
123 qRegisterMetaType<Statistics>("Statistics");
124 update();
125 }
126
128 if (root) {
129 DisposeCursor dc(root,*na);
131 }
132 delete na;
133 }
134
135 void
137 doubleClickInspectors.append(QPair<Inspector*,bool>(i,false));
138 }
139
140 void
142 assert(i < doubleClickInspectors.size());
143 doubleClickInspectors[i].second = active;
144 }
145
146 void
148 solutionInspectors.append(QPair<Inspector*,bool>(i,false));
149 }
150
151 void
153 assert(i < solutionInspectors.size());
154 solutionInspectors[i].second = active;
155 }
156
157 void
159 moveInspectors.append(QPair<Inspector*,bool>(i,false));
160 }
161
162 void
164 assert(i < moveInspectors.size());
165 moveInspectors[i].second = active;
166 }
167
168 void
170 comparators.append(QPair<Comparator*,bool>(c,false));
171 }
172
173 void
174 TreeCanvas::activateComparator(int i, bool active) {
175 assert(i < comparators.size());
176 comparators[i].second = active;
177 }
178
179 void
180 TreeCanvas::scaleTree(int scale0, int zoomx, int zoomy) {
181 QMutexLocker locker(&layoutMutex);
182
183 QSize viewport_size = size();
184 QAbstractScrollArea* sa =
185 static_cast<QAbstractScrollArea*>(parentWidget()->parentWidget());
186
187 if (zoomx==-1)
188 zoomx = viewport_size.width()/2;
189 if (zoomy==-1)
190 zoomy = viewport_size.height()/2;
191
192 int xoff = (sa->horizontalScrollBar()->value()+zoomx)/scale;
193 int yoff = (sa->verticalScrollBar()->value()+zoomy)/scale;
194
195 BoundingBox bb;
196 scale0 = std::min(std::max(scale0, LayoutConfig::minScale),
198 scale = (static_cast<double>(scale0)) / 100.0;
199 bb = root->getBoundingBox();
200 int w =
201 static_cast<int>((bb.right-bb.left+Layout::extent)*scale);
202 int h =
203 static_cast<int>(2*Layout::extent+
204 root->getShape()->depth()*Layout::dist_y*scale);
205
206 sa->horizontalScrollBar()->setRange(0,w-viewport_size.width());
207 sa->verticalScrollBar()->setRange(0,h-viewport_size.height());
208 sa->horizontalScrollBar()->setPageStep(viewport_size.width());
209 sa->verticalScrollBar()->setPageStep(viewport_size.height());
210 sa->horizontalScrollBar()->setSingleStep(Layout::extent);
211 sa->verticalScrollBar()->setSingleStep(Layout::extent);
212
213 xoff *= scale;
214 yoff *= scale;
215
216 sa->horizontalScrollBar()->setValue(xoff-zoomx);
217 sa->verticalScrollBar()->setValue(yoff-zoomy);
218
219 emit scaleChanged(scale0);
220 QWidget::update();
221 }
222
223 void
225 QMutexLocker locker(&mutex);
226 layoutMutex.lock();
227 if (root != NULL) {
228 root->layout(*na);
230
231 int w = static_cast<int>((bb.right-bb.left+Layout::extent)*scale);
232 int h =
233 static_cast<int>(2*Layout::extent+
234 root->getShape()->depth()*Layout::dist_y*scale);
235 xtrans = -bb.left+(Layout::extent / 2);
236
237 QSize viewport_size = size();
238 QAbstractScrollArea* sa =
239 static_cast<QAbstractScrollArea*>(parentWidget()->parentWidget());
240 sa->horizontalScrollBar()->setRange(0,w-viewport_size.width());
241 sa->verticalScrollBar()->setRange(0,h-viewport_size.height());
242 sa->horizontalScrollBar()->setPageStep(viewport_size.width());
243 sa->verticalScrollBar()->setPageStep(viewport_size.height());
244 sa->horizontalScrollBar()->setSingleStep(Layout::extent);
245 sa->verticalScrollBar()->setSingleStep(Layout::extent);
246 }
247 if (autoZoom)
248 zoomToFit();
249 layoutMutex.unlock();
250 QWidget::update();
251 }
252
253 void
255 QWidget::update();
256 }
257
258 void
259 TreeCanvas::layoutDone(int w, int h, int scale0) {
260 targetW = w; targetH = h; targetScale = scale0;
261
262 QSize viewport_size = size();
263 QAbstractScrollArea* sa =
264 static_cast<QAbstractScrollArea*>(parentWidget()->parentWidget());
265 sa->horizontalScrollBar()->setRange(0,w-viewport_size.width());
266 sa->verticalScrollBar()->setRange(0,h-viewport_size.height());
267
268 if (layoutDoneTimerId == 0)
269 layoutDoneTimerId = startTimer(15);
270 }
271
272 void
273 TreeCanvas::statusChanged(bool finished) {
274 if (finished) {
275 update();
277 }
278 emit statusChanged(currentNode, stats, finished);
279 }
280
281 void
283 node = n;
284
285 depth = -1;
286 for (VisualNode* p = n; p != NULL; p = p->getParent(*ti->na))
287 depth++;
288
289 a = all;
290 t = ti;
291 start();
292 }
293
294 void
295 SearcherThread::updateCanvas(void) {
296 t->layoutMutex.lock();
297 if (t->root == NULL)
298 return;
299
300 if (t->autoHideFailed) {
301 t->root->hideFailed(*t->na,true);
302 }
303 for (VisualNode* n = t->currentNode; n != NULL; n=n->getParent(*t->na)) {
304 if (n->isHidden()) {
305 t->currentNode->setMarked(false);
306 t->currentNode = n;
307 t->currentNode->setMarked(true);
308 break;
309 }
310 }
311
312 t->root->layout(*t->na);
313 BoundingBox bb = t->root->getBoundingBox();
314
315 int w = static_cast<int>((bb.right-bb.left+Layout::extent)*t->scale);
316 int h = static_cast<int>(2*Layout::extent+
317 t->root->getShape()->depth()
319 t->xtrans = -bb.left+(Layout::extent / 2);
320
321 int scale0 = static_cast<int>(t->scale*100);
322 if (t->autoZoom) {
323 QWidget* p = t->parentWidget();
324 if (p) {
325 double newXScale =
326 static_cast<double>(p->width()) / (bb.right - bb.left +
328 double newYScale =
329 static_cast<double>(p->height()) /
330 (t->root->getShape()->depth() * Layout::dist_y + 2*Layout::extent);
331
332 scale0 = static_cast<int>(std::min(newXScale, newYScale)*100);
333 if (scale0<LayoutConfig::minScale)
334 scale0 = LayoutConfig::minScale;
337 double scale = (static_cast<double>(scale0)) / 100.0;
338
339 w = static_cast<int>((bb.right-bb.left+Layout::extent)*scale);
340 h = static_cast<int>(2*Layout::extent+
341 t->root->getShape()->depth()*Layout::dist_y*scale);
342 }
343 }
344
345 t->layoutMutex.unlock();
346 emit update(w,h,scale0);
347 }
348
351 public:
355 int i;
359 SearchItem(VisualNode* n0, int noOfChildren0)
360 : n(n0), i(-1), noOfChildren(noOfChildren0) {}
361 };
362
363 void
365 {
366 if (!node->isOpen())
367 return;
368 t->mutex.lock();
369 emit statusChanged(false);
370
371 unsigned int kids =
372 node->getNumberOfChildNodes(*t->na, t->curBest, t->stats,
373 t->c_d, t->a_d);
374 if (kids == 0 || node->getStatus() == STOP) {
375 t->mutex.unlock();
376 updateCanvas();
377 emit statusChanged(true);
378 return;
379 }
380
381 std::stack<SearchItem> stck;
382 stck.push(SearchItem(node,kids));
383 t->stats.maxDepth =
384 std::max(static_cast<long unsigned int>(t->stats.maxDepth),
385 static_cast<long unsigned int>(depth+stck.size()));
386
387 VisualNode* sol = NULL;
388 int nodeCount = 0;
389 t->stopSearchFlag = false;
390 while (!stck.empty() && !t->stopSearchFlag) {
391 if (t->refresh > 0 && nodeCount >= t->refresh) {
392 node->dirtyUp(*t->na);
393 updateCanvas();
394 emit statusChanged(false);
395 nodeCount = 0;
396 if (t->refreshPause > 0)
397 msleep(t->refreshPause);
398 }
399 SearchItem& si = stck.top();
400 si.i++;
401 if (si.i == si.noOfChildren) {
402 stck.pop();
403 } else {
404 VisualNode* n = si.n->getChild(*t->na,si.i);
405 if (n->isOpen()) {
406 if (n->getStatus() == UNDETERMINED)
407 nodeCount++;
408 kids = n->getNumberOfChildNodes(*t->na, t->curBest, t->stats,
409 t->c_d, t->a_d);
410 if (t->moveDuringSearch)
411 emit moveToNode(n,false);
412 if (kids == 0) {
413 if (n->getStatus() == SOLVED) {
414 assert(n->hasCopy());
415 emit solution(n->getWorkingSpace());
416 n->purge(*t->na);
417 sol = n;
418 if (!a)
419 break;
420 }
421 } else {
422 if ( n->getStatus() != STOP )
423 stck.push(SearchItem(n,kids));
424 else if (!a)
425 break;
426 t->stats.maxDepth =
427 std::max(static_cast<long unsigned int>(t->stats.maxDepth),
428 static_cast<long unsigned int>(depth+stck.size()));
429 }
430 }
431 }
432 }
433 node->dirtyUp(*t->na);
434 t->stopSearchFlag = false;
435 t->mutex.unlock();
436 if (sol != NULL) {
437 t->setCurrentNode(sol,true,false);
438 } else {
439 t->setCurrentNode(node,true,false);
440 }
441 }
442 updateCanvas();
443 emit statusChanged(true);
444 if (t->finishedFlag)
445 emit searchFinished();
446 }
447
448 void
450 QMutexLocker locker(&mutex);
451 searcher.search(currentNode, true, this);
452 }
453
454 void
456 QMutexLocker locker(&mutex);
457 searcher.search(currentNode, false, this);
458 }
459
460 void
462 QMutexLocker locker(&mutex);
464 update();
466 emit statusChanged(currentNode, stats, true);
467 }
468
469 void
471 QMutexLocker locker(&mutex);
473 update();
475 emit statusChanged(currentNode, stats, true);
476 }
477
478 void
480 QMutexLocker locker(&mutex);
481 QMutexLocker layoutLocker(&layoutMutex);
483 update();
485 emit statusChanged(currentNode, stats, true);
486 }
487
488 void
490 QMutexLocker locker(&mutex);
492 update();
494 emit statusChanged(currentNode, stats, true);
495 }
496
497 void
499 QMutexLocker locker(&mutex);
500 QMutexLocker layoutLocker(&layoutMutex);
502 update();
504 emit statusChanged(currentNode, stats, true);
505 }
506
507 void
508 TreeCanvas::timerEvent(QTimerEvent* e) {
509 if (e->timerId() == layoutDoneTimerId) {
510 if (!smoothScrollAndZoom) {
512 } else {
513 zoomTimeLine.stop();
514 int zoomCurrent = static_cast<int>(scale*100);
515 int targetZoom = targetScale;
516 targetZoom = std::min(std::max(targetZoom, LayoutConfig::minScale),
518 zoomTimeLine.setFrameRange(zoomCurrent,targetZoom);
519 zoomTimeLine.start();
520 }
521 QWidget::update();
522 killTimer(layoutDoneTimerId);
524 }
525 }
526
527 void
529 QMutexLocker locker(&layoutMutex);
530 if (root != NULL) {
531 BoundingBox bb;
532 bb = root->getBoundingBox();
533 QWidget* p = parentWidget();
534 if (p) {
535 double newXScale =
536 static_cast<double>(p->width()) / (bb.right - bb.left +
538 double newYScale =
539 static_cast<double>(p->height()) / (root->getShape()->depth() *
542 int scale0 = static_cast<int>(std::min(newXScale, newYScale)*100);
543 if (scale0<LayoutConfig::minScale)
544 scale0 = LayoutConfig::minScale;
547
548 if (!smoothScrollAndZoom) {
549 scaleTree(scale0);
550 } else {
551 zoomTimeLine.stop();
552 int zoomCurrent = static_cast<int>(scale*100);
553 int targetZoom = scale0;
554 targetZoom = std::min(std::max(targetZoom, LayoutConfig::minScale),
556 zoomTimeLine.setFrameRange(zoomCurrent,targetZoom);
557 zoomTimeLine.start();
558 }
559 }
560 }
561 }
562
563 void
565 QMutexLocker locker(&mutex);
566 int x=0;
567 int y=0;
568
570 while (c != NULL) {
571 x += c->getOffset();
572 y += Layout::dist_y;
573 c = c->getParent(*na);
574 }
575
576 x = static_cast<int>((xtrans+x)*scale); y = static_cast<int>(y*scale);
577
578 QAbstractScrollArea* sa =
579 static_cast<QAbstractScrollArea*>(parentWidget()->parentWidget());
580
581 x -= sa->viewport()->width() / 2;
582 y -= sa->viewport()->height() / 2;
583
584 sourceX = sa->horizontalScrollBar()->value();
585 targetX = std::max(sa->horizontalScrollBar()->minimum(), x);
586 targetX = std::min(sa->horizontalScrollBar()->maximum(),
587 targetX);
588 sourceY = sa->verticalScrollBar()->value();
589 targetY = std::max(sa->verticalScrollBar()->minimum(), y);
590 targetY = std::min(sa->verticalScrollBar()->maximum(),
591 targetY);
592 if (!smoothScrollAndZoom) {
593 sa->horizontalScrollBar()->setValue(targetX);
594 sa->verticalScrollBar()->setValue(targetY);
595 } else {
596 scrollTimeLine.stop();
597 scrollTimeLine.setFrameRange(0,100);
598 scrollTimeLine.setDuration(std::max(200,
599 std::min(1000,
600 std::min(std::abs(sourceX-targetX),
601 std::abs(sourceY-targetY)))));
602 scrollTimeLine.start();
603 }
604 }
605
606 void
607 TreeCanvas::scroll(int i) {
608 QAbstractScrollArea* sa =
609 static_cast<QAbstractScrollArea*>(parentWidget()->parentWidget());
610 double p = static_cast<double>(i)/100.0;
611 double xdiff = static_cast<double>(targetX-sourceX)*p;
612 double ydiff = static_cast<double>(targetY-sourceY)*p;
613 sa->horizontalScrollBar()->setValue(sourceX+static_cast<int>(xdiff));
614 sa->verticalScrollBar()->setValue(sourceY+static_cast<int>(ydiff));
615 }
616
617 void
618 TreeCanvas::inspectCurrentNode(bool fix, int inspectorNo) {
619 QMutexLocker locker(&mutex);
620
621 if (currentNode->isHidden()) {
622 toggleHidden();
623 return;
624 }
625
626 int failedInspectorType = -1;
627 int failedInspector = -1;
628 bool needCentering = false;
629 try {
630 switch (currentNode->getStatus()) {
631 case UNDETERMINED:
632 {
633 unsigned int kids =
635 int depth = -1;
636 for (VisualNode* p = currentNode; p != NULL; p=p->getParent(*na))
637 depth++;
638 if (kids > 0) {
639 needCentering = true;
640 depth++;
641 }
643 std::max(stats.maxDepth, depth);
644 if (currentNode->getStatus() == SOLVED) {
645 assert(currentNode->hasCopy());
647 }
649 for (int i=0; i<moveInspectors.size(); i++) {
650 if (moveInspectors[i].second) {
651 failedInspectorType = 0;
652 failedInspector = i;
653 if (currentNode->getStatus() == FAILED) {
654 if (!currentNode->isRoot()) {
655 Space* curSpace =
657 moveInspectors[i].first->inspect(*curSpace);
658 delete curSpace;
659 }
660 } else {
661 moveInspectors[i].first->
662 inspect(*currentNode->getWorkingSpace());
663 }
664 failedInspectorType = -1;
665 }
666 }
667 if (currentNode->getStatus() == SOLVED) {
669 }
670 }
671 break;
672 case FAILED:
673 case STOP:
674 case UNSTOP:
675 case BRANCH:
676 case SOLVED:
677 {
678 Space* curSpace;
679
680 if (fix) {
682 break;
683 curSpace = currentNode->getSpace(*na,curBest,c_d,a_d);
684 if (currentNode->getStatus() == SOLVED &&
685 curSpace->status() != SS_SOLVED) {
686 // in the presence of weakly monotonic propagators, we may have
687 // to use search to find the solution here
688 assert(curSpace->status() == SS_BRANCH &&
689 "Something went wrong - probably an incorrect brancher");
690 Space* dfsSpace = Gecode::dfs(curSpace);
691 delete curSpace;
692 curSpace = dfsSpace;
693 }
694 } else {
695 if (currentNode->isRoot())
696 break;
698 curSpace = p->getSpace(*na,curBest,c_d,a_d);
699 switch (curSpace->status()) {
700 case SS_SOLVED:
701 case SS_FAILED:
702 break;
703 case SS_BRANCH:
704 curSpace->commit(*p->getChoice(),
706 break;
707 default:
709 }
710 }
711
712 if (inspectorNo==-1) {
713 for (int i=0; i<doubleClickInspectors.size(); i++) {
714 if (doubleClickInspectors[i].second) {
715 failedInspectorType = 1;
716 failedInspector = i;
717 doubleClickInspectors[i].first->inspect(*curSpace);
718 failedInspectorType = -1;
719 }
720 }
721 } else {
722 failedInspectorType = 1;
723 failedInspector = inspectorNo;
724 doubleClickInspectors[inspectorNo].first->inspect(*curSpace);
725 failedInspectorType = -1;
726 }
727 delete curSpace;
728 }
729 break;
730 }
731 } catch (Exception& e) {
732 switch (failedInspectorType) {
733 case 0:
734 qFatal("Exception in move inspector %d: %s.\n Stopping.",
735 failedInspector, e.what());
736 break;
737 case 1:
738 qFatal("Exception in double click inspector %d: %s.\n Stopping.",
739 failedInspector, e.what());
740 break;
741 default:
742 qFatal("Exception: %s.\n Stopping.", e.what());
743 break;
744 }
745 }
746
748 update();
749 if (needCentering)
751 }
752
753 void
757
758 void
760 QMutexLocker locker(&mutex);
762 update();
764 emit statusChanged(currentNode, stats, true);
765 }
766 void
768 QMutexLocker locker(&mutex);
770 update();
772 emit statusChanged(currentNode, stats, true);
773 }
774
775 void
776 TreeCanvas::inspectSolution(const Space* s) {
777 int failedInspectorType = -1;
778 int failedInspector = -1;
779 try {
780 Space* c = NULL;
781 for (int i=0; i<solutionInspectors.size(); i++) {
782 if (solutionInspectors[i].second) {
783 if (c == NULL)
784 c = s->clone();
785 failedInspectorType = 1;
786 failedInspector = i;
787 solutionInspectors[i].first->inspect(*c);
788 failedInspectorType = -1;
789 }
790 }
791 delete c;
792 } catch (Exception& e) {
793 switch (failedInspectorType) {
794 case 0:
795 qFatal("Exception in move inspector %d: %s.\n Stopping.",
796 failedInspector, e.what());
797 break;
798 case 1:
799 qFatal("Exception in solution inspector %d: %s.\n Stopping.",
800 failedInspector, e.what());
801 break;
802 default:
803 qFatal("Exception: %s.\n Stopping.", e.what());
804 break;
805 }
806 }
807 }
808
809 void
811 stopSearchFlag = true;
812 layoutDoneTimerId = startTimer(15);
813 }
814
815 void
817 QMutexLocker locker(&mutex);
818 Space* rootSpace =
819 root->getStatus() == FAILED ? NULL :
821 if (curBest != NULL) {
822 delete curBest;
823 curBest = new BestNode(NULL);
824 }
825 if (root) {
826 DisposeCursor dc(root,*na);
828 }
829 delete na;
830 na = new Node::NodeAllocator(curBest != NULL);
831 int rootIdx = na->allocate(rootSpace);
832 assert(rootIdx == 0); (void) rootIdx;
833 root = (*na)[0];
834 root->setMarked(true);
836 pathHead = root;
837 scale = 1.0;
838 stats = Statistics();
839 for (int i=bookmarks.size(); i--;)
840 emit removedBookmark(i);
841 bookmarks.clear();
842 root->layout(*na);
843
844 emit statusChanged(currentNode, stats, true);
845 update();
846 }
847
848 void
850 QMutexLocker locker(&mutex);
851 if (!currentNode->isBookmarked()) {
852 bool ok;
853 QString text =
854 QInputDialog::getText(this, "Add bookmark", "Name:",
855 QLineEdit::Normal,"",&ok);
856 if (ok) {
858 bookmarks.append(currentNode);
859 if (text == "")
860 text = QString("Node ")+QString().setNum(bookmarks.size());
861 emit addedBookmark(text);
862 }
863 } else {
865 int idx = bookmarks.indexOf(currentNode);
866 bookmarks.remove(idx);
867 emit removedBookmark(idx);
868 }
870 update();
871 }
872
873 void
875 QMutexLocker locker(&mutex);
876 if(currentNode == pathHead)
877 return;
878
881
884 update();
885 }
886
887 void
889 QMutexLocker locker(&mutex);
891 if (currentNode->isOnPath()) {
893 int nextAlt = currentNode->getPathAlternative(*na);
894 while (nextAlt >= 0) {
897 nextAlt = currentNode->getPathAlternative(*na);
898 }
899 }
900 update();
901 }
902
903 void
905 QMutexLocker locker(&mutex);
906 compareNodes = true;
907 compareNodesBeforeFP = false;
908 setCursor(QCursor(Qt::CrossCursor));
909 }
910
911 void
913 QMutexLocker locker(&mutex);
914 compareNodes = true;
916 setCursor(QCursor(Qt::CrossCursor));
917 }
918
919 void
923
924 void
926 QMutexLocker locker(&mutex);
927
929
931
932 if (p != NULL) {
934 }
935 }
936
937 void
939 QMutexLocker locker(&mutex);
940 if (!currentNode->isHidden()) {
941 switch (currentNode->getStatus()) {
942 case STOP:
943 case UNSTOP:
944 case BRANCH:
945 {
946 int alt = std::max(0, currentNode->getPathAlternative(*na));
950 break;
951 }
952 case SOLVED:
953 case FAILED:
954 case UNDETERMINED:
955 break;
956 }
957 }
958 }
959
960 void
962 QMutexLocker locker(&mutex);
964 if (p != NULL) {
965 int alt = currentNode->getAlternative(*na);
966 if (alt > 0) {
967 VisualNode* n = p->getChild(*na,alt-1);
970 }
971 }
972 }
973
974 void
976 QMutexLocker locker(&mutex);
978 if (p != NULL) {
979 unsigned int alt = currentNode->getAlternative(*na);
980 if (alt + 1 < p->getNumberOfChildren()) {
981 VisualNode* n = p->getChild(*na,alt+1);
984 }
985 }
986 }
987
988 void
990 QMutexLocker locker(&mutex);
993 }
994
995 void
997 QMutexLocker locker(&mutex);
998 NextSolCursor nsc(currentNode,back,*na);
1000 nsv.run();
1001 VisualNode* n = nsv.getCursor().node();
1002 if (n != root) {
1005 }
1006 }
1007
1008 void
1010 navNextSol(true);
1011 }
1012
1013 void
1014 TreeCanvas::exportNodePDF(VisualNode* n) {
1015#if QT_VERSION >= 0x040400
1016 QString filename = QFileDialog::getSaveFileName(this, tr("Export tree as pdf"), "", tr("PDF (*.pdf)"));
1017 if (filename != "") {
1018 QPrinter printer(QPrinter::ScreenResolution);
1019 QMutexLocker locker(&mutex);
1020
1021 BoundingBox bb = n->getBoundingBox();
1022 printer.setFullPage(true);
1023 printer.setPaperSize(QSizeF(bb.right-bb.left+Layout::extent,
1024 n->getShape()->depth() * Layout::dist_y +
1025 Layout::extent), QPrinter::Point);
1026 printer.setOutputFileName(filename);
1027 QPainter painter(&printer);
1028
1029 painter.setRenderHint(QPainter::Antialiasing);
1030
1031 QRect pageRect = printer.pageRect();
1032 double newXScale =
1033 static_cast<double>(pageRect.width()) / (bb.right - bb.left +
1035 double newYScale =
1036 static_cast<double>(pageRect.height()) /
1037 (n->getShape()->depth() * Layout::dist_y +
1039 double printScale = std::min(newXScale, newYScale);
1040 painter.scale(printScale,printScale);
1041
1042 int printxtrans = -bb.left+(Layout::extent / 2);
1043
1044 painter.translate(printxtrans, Layout::dist_y / 2);
1045 QRect clip(0,0,0,0);
1046 DrawingCursor dc(n, *na, curBest, painter, clip, showCopies);
1047 currentNode->setMarked(false);
1049 currentNode->setMarked(true);
1050 }
1051#else
1052 (void) n;
1053#endif
1054 }
1055
1056 void
1058#if QT_VERSION >= 0x040400
1059 exportNodePDF(root);
1060#endif
1061 }
1062
1063 void
1065#if QT_VERSION >= 0x040400
1066 exportNodePDF(currentNode);
1067#endif
1068 }
1069
1070 void
1072 QPrinter printer;
1073 if (QPrintDialog(&printer, this).exec() == QDialog::Accepted) {
1074 QMutexLocker locker(&mutex);
1075
1077 QRect pageRect = printer.pageRect();
1078 double newXScale =
1079 static_cast<double>(pageRect.width()) / (bb.right - bb.left +
1081 double newYScale =
1082 static_cast<double>(pageRect.height()) /
1083 (root->getShape()->depth() * Layout::dist_y +
1084 2*Layout::extent);
1085 double printScale = std::min(newXScale, newYScale)*100;
1086 if (printScale<1.0)
1087 printScale = 1.0;
1088 if (printScale > 400.0)
1089 printScale = 400.0;
1090 printScale = printScale / 100.0;
1091
1092 QPainter painter(&printer);
1093 painter.setRenderHint(QPainter::Antialiasing);
1094 painter.scale(printScale,printScale);
1095 painter.translate(xtrans, 0);
1096 QRect clip(0,0,0,0);
1097 DrawingCursor dc(root, *na, curBest, painter, clip, showCopies);
1099 }
1100 }
1101
1102 VisualNode*
1103 TreeCanvas::eventNode(QEvent* event) {
1104 int x = 0;
1105 int y = 0;
1106 switch (event->type()) {
1107 case QEvent::ToolTip:
1108 {
1109 QHelpEvent* he = static_cast<QHelpEvent*>(event);
1110 x = he->x();
1111 y = he->y();
1112 break;
1113 }
1114 case QEvent::MouseButtonDblClick:
1115 case QEvent::MouseButtonPress:
1116 case QEvent::MouseButtonRelease:
1117 case QEvent::MouseMove:
1118 {
1119 QMouseEvent* me = static_cast<QMouseEvent*>(event);
1120 x = me->x();
1121 y = me->y();
1122 break;
1123 }
1124 case QEvent::ContextMenu:
1125 {
1126 QContextMenuEvent* ce = static_cast<QContextMenuEvent*>(event);
1127 x = ce->x();
1128 y = ce->y();
1129 break;
1130 }
1131 default:
1132 return NULL;
1133 }
1134 QAbstractScrollArea* sa =
1135 static_cast<QAbstractScrollArea*>(parentWidget()->parentWidget());
1136 int xoff = sa->horizontalScrollBar()->value()/scale;
1137 int yoff = sa->verticalScrollBar()->value()/scale;
1138
1140 int w =
1141 static_cast<int>((bb.right-bb.left+Layout::extent)*scale);
1142 if (w < sa->viewport()->width())
1143 xoff -= (sa->viewport()->width()-w)/2;
1144
1145 VisualNode* n;
1146 n = root->findNode(*na,
1147 static_cast<int>(x/scale-xtrans+xoff),
1148 static_cast<int>((y-30)/scale+yoff));
1149 return n;
1150 }
1151
1152 bool
1153 TreeCanvas::event(QEvent* event) {
1154 if (mutex.tryLock()) {
1155 if (event->type() == QEvent::ToolTip) {
1157 if (n != NULL) {
1158 QHelpEvent* he = static_cast<QHelpEvent*>(event);
1159 QToolTip::showText(he->globalPos(),
1160 QString(n->toolTip(*na,curBest,
1161 c_d,a_d).c_str()));
1162 } else {
1163 QToolTip::hideText();
1164 }
1165 }
1166 mutex.unlock();
1167 }
1168 return QWidget::event(event);
1169 }
1170
1171 void
1173 if (autoZoom)
1174 zoomToFit();
1175 }
1176
1177 void
1178 TreeCanvas::paintEvent(QPaintEvent* event) {
1179 QMutexLocker locker(&layoutMutex);
1180 QPainter painter(this);
1181 painter.setRenderHint(QPainter::Antialiasing);
1182
1183 QAbstractScrollArea* sa =
1184 static_cast<QAbstractScrollArea*>(parentWidget()->parentWidget());
1185 int xoff = sa->horizontalScrollBar()->value()/scale;
1186 int yoff = sa->verticalScrollBar()->value()/scale;
1187
1189 int w =
1190 static_cast<int>((bb.right-bb.left+Layout::extent)*scale);
1191 if (w < sa->viewport()->width())
1192 xoff -= (sa->viewport()->width()-w)/2;
1193
1194 QRect origClip = event->rect();
1195 painter.translate(0, 30);
1196 painter.scale(scale,scale);
1197 painter.translate(xtrans-xoff, -yoff);
1198 QRect clip(static_cast<int>(origClip.x()/scale-xtrans+xoff),
1199 static_cast<int>(origClip.y()/scale+yoff),
1200 static_cast<int>(origClip.width()/scale),
1201 static_cast<int>(origClip.height()/scale));
1202 DrawingCursor dc(root, *na, curBest, painter, clip, showCopies);
1204
1205 // int nodesLayouted = 1;
1206 // clock_t t0 = clock();
1207 // while (v.next()) { nodesLayouted++; }
1208 // double t = (static_cast<double>(clock()-t0) / CLOCKS_PER_SEC) * 1000.0;
1209 // double nps = static_cast<double>(nodesLayouted) /
1210 // (static_cast<double>(clock()-t0) / CLOCKS_PER_SEC);
1211 // std::cout << "Drawing done. " << nodesLayouted << " nodes in "
1212 // << t << " ms. " << nps << " nodes/s." << std::endl;
1213
1214 }
1215
1216 void
1218 if (mutex.tryLock()) {
1219 if(event->button() == Qt::LeftButton) {
1221 if(n == currentNode) {
1223 event->accept();
1224 mutex.unlock();
1225 return;
1226 }
1227 }
1228 mutex.unlock();
1229 }
1230 event->ignore();
1231 }
1232
1233 void
1234 TreeCanvas::contextMenuEvent(QContextMenuEvent* event) {
1235 if (mutex.tryLock()) {
1237 if (n != NULL) {
1239 emit contextMenu(event);
1240 event->accept();
1241 mutex.unlock();
1242 return;
1243 }
1244 mutex.unlock();
1245 }
1246 event->ignore();
1247 }
1248
1249 void
1250 TreeCanvas::resizeEvent(QResizeEvent* e) {
1251 QAbstractScrollArea* sa =
1252 static_cast<QAbstractScrollArea*>(parentWidget()->parentWidget());
1253
1254 int w = sa->horizontalScrollBar()->maximum()+e->oldSize().width();
1255 int h = sa->verticalScrollBar()->maximum()+e->oldSize().height();
1256
1257 sa->horizontalScrollBar()->setRange(0,w-e->size().width());
1258 sa->verticalScrollBar()->setRange(0,h-e->size().height());
1259 sa->horizontalScrollBar()->setPageStep(e->size().width());
1260 sa->verticalScrollBar()->setPageStep(e->size().height());
1261 }
1262
1263 void
1264 TreeCanvas::wheelEvent(QWheelEvent* event) {
1265 if (event->modifiers() & Qt::ShiftModifier) {
1266 event->accept();
1267 if (event->orientation() == Qt::Vertical && !autoZoom)
1268 scaleTree(scale*100+ceil(static_cast<double>(event->delta())/4.0),
1269 event->x(), event->y());
1270 } else {
1271 event->ignore();
1272 }
1273 }
1274
1275 bool
1277 if (finishedFlag)
1278 return true;
1279 stopSearchFlag = true;
1280 finishedFlag = true;
1281 for (int i=0; i<doubleClickInspectors.size(); i++)
1282 doubleClickInspectors[i].first->finalize();
1283 for (int i=0; i<solutionInspectors.size(); i++)
1284 solutionInspectors[i].first->finalize();
1285 for (int i=0; i<moveInspectors.size(); i++)
1286 moveInspectors[i].first->finalize();
1287 for (int i=0; i<comparators.size(); i++)
1288 comparators[i].first->finalize();
1289 return !searcher.isRunning();
1290 }
1291
1292 void
1294 if (finished)
1295 mutex.lock();
1296 if (update && n != NULL && n != currentNode &&
1297 n->getStatus() != UNDETERMINED && !n->isHidden()) {
1298 Space* curSpace = NULL;
1299 for (int i=0; i<moveInspectors.size(); i++) {
1300 if (moveInspectors[i].second) {
1301 if (curSpace == NULL)
1302 curSpace = n->getSpace(*na,curBest,c_d,a_d);
1303 try {
1304 moveInspectors[i].first->inspect(*curSpace);
1305 } catch (Exception& e) {
1306 qFatal("Exception in move inspector %d: %s.\n Stopping.",
1307 i, e.what());
1308 }
1309 }
1310 }
1311 }
1312 if (n != NULL) {
1313 currentNode->setMarked(false);
1314 currentNode = n;
1315 currentNode->setMarked(true);
1316 emit statusChanged(currentNode,stats,finished);
1317 if (update) {
1318 compareNodes = false;
1319 setCursor(QCursor(Qt::ArrowCursor));
1320 QWidget::update();
1321 }
1322 }
1323 if (finished)
1324 mutex.unlock();
1325 }
1326
1327 void
1328 TreeCanvas::mousePressEvent(QMouseEvent* event) {
1329 if (mutex.tryLock()) {
1330 if (event->button() == Qt::LeftButton) {
1332 if (compareNodes) {
1333 if (n != NULL && n->getStatus() != UNDETERMINED &&
1334 currentNode != NULL &&
1336 Space* curSpace = NULL;
1337 Space* compareSpace = NULL;
1338 for (int i=0; i<comparators.size(); i++) {
1339 if (comparators[i].second) {
1340 if (curSpace == NULL) {
1341 curSpace = currentNode->getSpace(*na,curBest,c_d,a_d);
1342
1343 if (!compareNodesBeforeFP || n->isRoot()) {
1344 compareSpace = n->getSpace(*na,curBest,c_d,a_d);
1345 } else {
1346 VisualNode* p = n->getParent(*na);
1347 compareSpace = p->getSpace(*na,curBest,c_d,a_d);
1348 switch (compareSpace->status()) {
1349 case SS_SOLVED:
1350 case SS_FAILED:
1351 break;
1352 case SS_BRANCH:
1353 compareSpace->commit(*p->getChoice(),
1354 n->getAlternative(*na));
1355 break;
1356 default:
1358 }
1359 }
1360 }
1361 try {
1362 comparators[i].first->compare(*curSpace,*compareSpace);
1363 } catch (Exception& e) {
1364 qFatal("Exception in comparator %d: %s.\n Stopping.",
1365 i, e.what());
1366 }
1367 }
1368 }
1369 }
1370 } else {
1372 }
1373 compareNodes = false;
1374 setCursor(QCursor(Qt::ArrowCursor));
1375 if (n != NULL) {
1376 event->accept();
1377 mutex.unlock();
1378 return;
1379 }
1380 }
1381 mutex.unlock();
1382 }
1383 event->ignore();
1384 }
1385
1386 void
1388 c_d = c_d0; a_d = a_d0;
1389 }
1390
1391 void
1395
1396 void
1398 autoZoom = b;
1399 if (autoZoom) {
1400 zoomToFit();
1401 }
1402 emit autoZoomChanged(b);
1403 scaleBar->setEnabled(!b);
1404 }
1405
1406 void
1408 showCopies = b;
1409 }
1410 bool
1412 return showCopies;
1413 }
1414
1415 bool
1419
1420 bool
1422 return autoZoom;
1423 }
1424
1425 void
1427 refresh = i;
1428 }
1429
1430 void
1432 refreshPause = i;
1433 if (refreshPause > 0)
1434 refresh = 1;
1435 }
1436
1437 bool
1441
1442 void
1446
1447 bool
1451
1452 void
1456
1457}}
1458
1459// STATISTICS: gist-any
struct Gecode::@603::NNF::@65::@66 b
For binary nodes (and, or, eqv)
int p
Number of positive literals for node type.
int n
Number of negative literals for node type.
int size(void) const
Return size of array (number of elements)
Definition array.hpp:1607
Exception: Base-class for exceptions
Definition exception.hpp:42
virtual const char * what(void) const
Return information.
Definition exception.cpp:55
Static reference to the currently best space.
Definition spacenode.hh:80
int right
Right coordinate.
Definition visualnode.hh:57
int left
Left coordinate.
Definition visualnode.hh:55
Abstract base class for comparators.
Definition gist.hh:119
A cursor that frees all memory.
A cursor that draws a tree on a QWidget.
Abstract base class for inspectors.
Definition gist.hh:99
static const int dist_y
Definition visualnode.hh:46
static const int extent
Definition visualnode.hh:47
A cursor that finds the next solution.
Cursor & getCursor(void)
Return the cursor.
NodeAllocatorBase< VisualNode > NodeAllocator
Definition node.hh:143
int getParent(void) const
Return the parent.
Definition node.hpp:182
int getChild(int n) const
Return index of child no n.
Definition node.hpp:195
bool isRoot(void) const
Check if this node is the root of a tree.
Definition node.hpp:211
Options for Gist
Definition gist.hh:234
Run a cursor over a tree, processing nodes in pre-order.
void run(void)
Execute visitor.
A stack item for depth first search.
VisualNode * n
The node.
int noOfChildren
The number of children.
SearchItem(VisualNode *n0, int noOfChildren0)
Constructor.
int i
The currently explored child.
void update(int w, int h, int scale0)
void solution(const Space *)
void search(VisualNode *n, bool all, TreeCanvas *ti)
void moveToNode(VisualNode *n, bool)
bool hasCopy(void)
Return whether the node has a copy.
const Space * getWorkingSpace(void) const
Return working space (if present).
int getNumberOfChildNodes(NodeAllocator &na, BestNode *curBest, Statistics &stats, int c_d, int a_d)
Compute and return the number of children.
int getAlternative(const NodeAllocator &na) const
Return alternative number of this node.
bool isOpen(void)
Return whether this node still has open children.
NodeStatus getStatus(void) const
Return current status of the node.
Definition spacenode.hpp:71
Space * getSpace(NodeAllocator &na, BestNode *curBest, int c_d, int a_d)
Return working space. Receiver must delete the space.
Definition spacenode.hpp:98
void purge(const NodeAllocator &na)
Clear working space and copy (if present and this is not the root).
Statistics about the search tree
Definition spacenode.hh:59
int maxDepth
Maximum depth of the tree.
Definition spacenode.hh:70
A canvas that displays the search tree.
Definition treecanvas.hh:87
double scale
Current scale factor.
void navNextSol(bool back=false)
Move selection to next solution (in DFS order)
void update(void)
Update display.
void zoomToFit(void)
Zoom the canvas so that the whole tree fits.
void resizeToOuter(void)
Resize to the outer widget size if auto zoom is enabled.
void activateComparator(int i, bool active)
Set active comparator.
void exportPDF(void)
Export pdf of the current subtree.
int targetX
Target x coordinate after smooth scrolling.
void wheelEvent(QWheelEvent *event)
Handle mouse wheel events.
Statistics stats
Statistics about the search tree.
void resizeEvent(QResizeEvent *event)
Handle resize event.
int targetScale
Target scale after layout.
QVector< VisualNode * > bookmarks
The bookmarks map.
SearcherThread searcher
Search engine thread.
VisualNode * currentNode
The currently selected node.
bool finish(void)
Stop search and wait for it to finish.
void exportWholeTreePDF(void)
Export pdf of the whole tree.
int xtrans
Offset on the x axis so that the tree is centered.
void activateDoubleClickInspector(int i, bool active)
Set active inspector.
void navUp(void)
Move selection to the parent of the selected node.
bool autoHideFailed
Whether to hide failed subtrees automatically.
void labelBranches(void)
Label all branches in subtree under current node.
VisualNode * eventNode(QEvent *event)
Return the node corresponding to the event position.
void contextMenuEvent(QContextMenuEvent *event)
Handle context menu event.
void startCompareNodesBeforeFP(void)
Wait for click on node to compare with current node before fixpoint.
void startCompareNodes(void)
Wait for click on node to compare with current node.
void addComparator(Comparator *c)
Add comparator c.
QMutex mutex
Mutex for synchronizing acccess to the tree.
void inspectBeforeFP(void)
Calls inspectCurrentNode(false)
void hideFailed(void)
Hide failed subtrees of selected node.
bool getAutoZoom(void)
Return preference whether to automatically zoom to fit.
void setRefreshPause(int i)
Set refresh pause in msec.
void bookmarkNode(void)
Bookmark current node.
void print(void)
Print the tree.
void searchAll(void)
Explore complete subtree of selected node.
int refresh
Refresh rate.
QTimeLine scrollTimeLine
Timer for smooth scrolling.
int layoutDoneTimerId
Timer id for delaying the update.
void addSolutionInspector(Inspector *i)
Add inspector i.
int targetH
Target height after layout.
bool smoothScrollAndZoom
Whether to use smooth scrolling and zooming.
QTimeLine zoomTimeLine
Timer for smooth zooming.
void setPath(void)
Set the current node to be the head of the path.
void navRoot(void)
Move selection to the root node.
void statusChanged(VisualNode *, const Statistics &, bool)
Status bar update.
TreeCanvas(Space *rootSpace, bool bab, QWidget *parent, const Options &opt)
Constructor.
~TreeCanvas(void)
Destructor.
bool event(QEvent *event)
General event handler, used for displaying tool tips.
void setMoveDuringSearch(bool b)
Set preference whether to move cursor during search.
void searchOne(void)
Find next solution below selected node.
void scroll(void)
React to scroll events.
void navDown(void)
Move selection to the first child of the selected node.
QVector< QPair< Comparator *, bool > > comparators
The registered comparators, and whether they are active.
bool compareNodes
Whether node comparison action is running.
void scaleTree(int scale0, int zoomx=-1, int zoomy=-1)
Set scale factor to scale0.
void activateSolutionInspector(int i, bool active)
Set active inspector.
int c_d
The recomputation distance.
void mousePressEvent(QMouseEvent *event)
Handle mouse press event.
void navLeft(void)
Move selection to the left sibling of the selected node.
QSlider * scaleBar
The scale bar.
QMutex layoutMutex
Mutex for synchronizing layout and drawing.
int targetY
Target y coordinate after smooth scrolling.
QVector< QPair< Inspector *, bool > > doubleClickInspectors
The registered click inspectors, and whether they are active.
void autoZoomChanged(bool)
The auto-zoom state was changed.
void setRefresh(int i)
Set refresh rate.
Node::NodeAllocator * na
Allocator for nodes.
BestNode * curBest
The currently best solution (for branch-and-bound)
void paintEvent(QPaintEvent *event)
Paint the tree.
void unstopAll(void)
Do not stop at any stop node.
bool moveDuringSearch
Whether to move cursor during search.
bool getSmoothScrollAndZoom(void)
Return preference whether to use smooth scrolling and zooming.
void mouseDoubleClickEvent(QMouseEvent *event)
Handle mouse double click event.
int a_d
The adaptive recomputation distance.
void unhideAll(void)
Unhide all nodes below selected node.
void reset(void)
Reset.
void searchFinished(void)
Signals that Gist is finished.
int sourceX
Source x coordinate after smooth scrolling.
void scaleChanged(int)
The scale factor has changed.
bool getAutoHideFailed(void)
Return preference whether to automatically hide failed subtrees.
void solution(const Space *)
Signals that a solution has been found.
int targetW
Target width after layout.
void setRecompDistances(int c_d, int a_d)
Set recomputation distances.
void addMoveInspector(Inspector *i)
Add inspector i.
bool autoZoom
Whether to zoom automatically.
void emitStatusChanged(void)
Re-emit status change information for current node.
void setAutoZoom(bool b)
Set preference whether to automatically zoom to fit.
void centerCurrentNode(void)
Center the view on the currently selected node.
void setSmoothScrollAndZoom(bool b)
Set preference whether to use smooth scrolling and zooming.
bool finishedFlag
Flag signalling that Gist is ready to be closed.
void removedBookmark(int idx)
Signals that a bookmark has been removed.
VisualNode * pathHead
The head of the currently selected path.
void activateMoveInspector(int i, bool active)
Set active inspector.
void setCurrentNode(VisualNode *n, bool finished=true, bool update=true)
Set the selected node to n.
void contextMenu(QContextMenuEvent *)
Context menu triggered.
bool stopSearchFlag
Flag signalling the search to stop.
void setShowCopies(bool b)
Set preference whether to show copies in the tree.
void labelPath(void)
Label all branches on path to root node.
void layoutDone(int w, int h, int scale0)
Layout done.
virtual void timerEvent(QTimerEvent *e)
Timer invoked for smooth zooming and scrolling.
bool getMoveDuringSearch(void)
Return preference whether to move cursor during search.
bool compareNodesBeforeFP
Whether node comparison action computes fixpoint.
void toggleStop(void)
Do not stop at selected stop node.
void toggleHidden(void)
Toggle hidden state of selected node.
void navRight(void)
Move selection to the right sibling of the selected node.
void navPrevSol(void)
Move selection to previous solution (in DFS order)
bool showCopies
Whether to show copies in the tree.
void inspectPath(void)
Call the double click inspector for all nodes on the path from root to head of the path.
bool getShowCopies(void)
Return preference whether to show copies in the tree.
VisualNode * root
The root node of the tree.
void stopSearch(void)
Stop current search.
void inspectCurrentNode(bool fix=true, int inspectorNo=-1)
Call the double click inspector for the currently selected node.
int sourceY
Target y coordinate after smooth scrolling.
void setAutoHideFailed(bool b)
Set preference whether to automatically hide failed subtrees.
void addDoubleClickInspector(Inspector *i)
Add inspector i.
int refreshPause
Time (in msec) to pause after each refresh.
QVector< QPair< Inspector *, bool > > moveInspectors
The registered move inspectors, and whether they are active.
QVector< QPair< Inspector *, bool > > solutionInspectors
The registered solution inspectors, and whether they are active.
void addedBookmark(const QString &id)
Signals that a bookmark has been added.
Node class that supports visual layout
void unstopAll(const NodeAllocator &na)
Do not stop at any stop node in the subtree of this node.
int getPathAlternative(const NodeAllocator &na)
Return the alternative of the child that is on the path (-1 if none)
void unPathUp(const NodeAllocator &na)
Set all nodes from the node to the root not to be on the path.
void unhideAll(const NodeAllocator &na)
Unhide all nodes in the subtree of this node.
bool isBookmarked(void)
Return whether node is bookmarked.
bool isHidden(void)
Return if node is hidden.
void toggleStop(const NodeAllocator &na)
Do not stop at this node.
void labelBranches(NodeAllocator &na, BestNode *curBest, int c_d, int a_d)
Create or clear branch labels in subtree.
void setBookmarked(bool m)
Set bookmark of this node.
void toggleHidden(const NodeAllocator &na)
Toggle whether this node is hidden.
void labelPath(NodeAllocator &na, BestNode *curBest, int c_d, int a_d)
Create or clear branch labels on path to root.
void pathUp(const NodeAllocator &na)
Set all nodes from the node to the root to be on the path.
void dirtyUp(const NodeAllocator &na)
Mark all nodes up the path to the parent as dirty.
void layout(const NodeAllocator &na)
Compute layout for the subtree of this node.
void hideFailed(const NodeAllocator &na, bool onlyDirty=false)
Hide all failed subtrees of this node.
BoundingBox getBoundingBox(void)
Return the bounding box.
VisualNode * findNode(const NodeAllocator &na, int x, int y)
Find a node in this subtree at coordinates x, y.
bool isOnPath(void)
Return whether node is on the path.
void setMarked(bool m)
Set mark of this node.
Shape * getShape(void)
Return the shape of this node.
Computation spaces.
Definition core.hpp:1742
VarImp * x
Pointer to variable implementation.
Definition var.hpp:50
void update(const NoOffset &)
Integer-precision integer scale view.
Definition view.hpp:638
int bab(Space *root, const Gist::Options &opt=Gist::Options::def)
Create a new stand-alone Gist for branch-and-bound search of root.
Definition gist.hpp:208
void commit(const Choice &c, unsigned int a, CommitStatistics &stat=unused_commit)
Commit choice c for alternative a.
Definition core.hpp:3232
SpaceStatus status(StatusStatistics &stat=unused_status)
Query space status.
Definition core.cpp:252
Space * clone(CloneStatistics &stat=unused_clone) const
Clone space.
Definition core.hpp:3224
@ SS_BRANCH
Space must be branched (at least one brancher left)
Definition core.hpp:1684
@ SS_SOLVED
Space is solved (no brancher left)
Definition core.hpp:1683
@ SS_FAILED
Space is failed
Definition core.hpp:1682
const int maxScale
Maximum scale factor.
Definition treecanvas.hh:54
const int defScale
Default scale factor.
Definition treecanvas.hh:56
const int minScale
Minimum scale factor.
Definition treecanvas.hh:52
const int maxAutoZoomScale
Maximum scale factor for automatic zoom.
Definition treecanvas.hh:58
@ UNDETERMINED
Node that has not been explored yet.
Definition spacenode.hh:48
@ UNSTOP
Node representing ignored stop point.
Definition spacenode.hh:50
@ FAILED
Node representing failure.
Definition spacenode.hh:46
@ STOP
Node representing stop point.
Definition spacenode.hh:49
@ SOLVED
Node representing a solution.
Definition spacenode.hh:45
@ BRANCH
Node representing a branch.
Definition spacenode.hh:47
Space * snapshot(Space *s, const Options &o)
Clone space s dependening on options o.
Definition support.hh:71
Gecode toplevel namespace
Post propagator for SetVar SetOpType SetVar y
Definition set.hh:767
T * dfs(T *s, const Search::Options &o=Search::Options::def)
Invoke depth-first search engine for subclass T of space s with options o.
Definition dfs.hpp:73
Post propagator for SetVar x
Definition set.hh:767
#define GECODE_NEVER
Assert that this command is never executed.
Definition macros.hpp:56