Generated on Thu Jul 21 2022 00:00:00 for Gecode by doxygen 1.9.4
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
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+
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);
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+
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();
251 }
252
253 void
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()) /
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 }
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,
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
755 inspectCurrentNode(false);
756 }
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
921 emit statusChanged(currentNode, stats, true);
922 }
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()) /
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));
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
1393 autoHideFailed = b;
1394 }
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
1417 return autoHideFailed;
1418 }
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
1439 return smoothScrollAndZoom;
1440 }
1441
1442 void
1445 }
1446
1447 bool
1449 return moveDuringSearch;
1450 }
1451
1452 void
1455 }
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.
Definition: bool-expr.cpp:232
int n
Number of negative literals for node type.
Definition: bool-expr.cpp:234
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.
Definition: nodecursor.hh:215
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.
Definition: nodecursor.hh:130
Cursor & getCursor(void)
Return the cursor.
Definition: nodevisitor.hpp:46
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.
Definition: nodevisitor.hh:72
void run(void)
Execute visitor.
A stack item for depth first search.
Definition: treecanvas.cpp:350
VisualNode * n
The node.
Definition: treecanvas.cpp:353
int noOfChildren
The number of children.
Definition: treecanvas.cpp:357
SearchItem(VisualNode *n0, int noOfChildren0)
Constructor.
Definition: treecanvas.cpp:359
int i
The currently explored child.
Definition: treecanvas.cpp:355
void update(int w, int h, int scale0)
void solution(const Space *)
void search(VisualNode *n, bool all, TreeCanvas *ti)
Definition: treecanvas.cpp:282
void moveToNode(VisualNode *n, bool)
int depth(void) const
Return depth of the shape.
Definition: visualnode.hpp:60
bool hasCopy(void)
Return whether the node has a copy.
Definition: spacenode.hpp:159
const Space * getWorkingSpace(void) const
Return working space (if present).
Definition: spacenode.hpp:112
int getNumberOfChildNodes(NodeAllocator &na, BestNode *curBest, Statistics &stats, int c_d, int a_d)
Compute and return the number of children.
Definition: spacenode.cpp:298
int getAlternative(const NodeAllocator &na) const
Return alternative number of this node.
Definition: spacenode.hpp:169
bool isOpen(void)
Return whether this node still has open children.
Definition: spacenode.hpp:138
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).
Definition: spacenode.hpp:120
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.
Definition: treecanvas.hh:289
void navNextSol(bool back=false)
Move selection to next solution (in DFS order)
Definition: treecanvas.cpp:996
void update(void)
Update display.
Definition: treecanvas.cpp:224
void zoomToFit(void)
Zoom the canvas so that the whole tree fits.
Definition: treecanvas.cpp:528
void resizeToOuter(void)
Resize to the outer widget size if auto zoom is enabled.
void activateComparator(int i, bool active)
Set active comparator.
Definition: treecanvas.cpp:174
void exportPDF(void)
Export pdf of the current subtree.
int targetX
Target x coordinate after smooth scrolling.
Definition: treecanvas.hh:335
void wheelEvent(QWheelEvent *event)
Handle mouse wheel events.
Statistics stats
Statistics about the search tree.
Definition: treecanvas.hh:286
void resizeEvent(QResizeEvent *event)
Handle resize event.
int targetScale
Target scale after layout.
Definition: treecanvas.hh:348
QVector< VisualNode * > bookmarks
The bookmarks map.
Definition: treecanvas.hh:275
SearcherThread searcher
Search engine thread.
Definition: treecanvas.hh:250
VisualNode * currentNode
The currently selected node.
Definition: treecanvas.hh:262
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.
Definition: treecanvas.hh:291
void activateDoubleClickInspector(int i, bool active)
Set active inspector.
Definition: treecanvas.cpp:141
void navUp(void)
Move selection to the parent of the selected node.
Definition: treecanvas.cpp:925
bool autoHideFailed
Whether to hide failed subtrees automatically.
Definition: treecanvas.hh:294
void labelBranches(void)
Label all branches in subtree under current node.
Definition: treecanvas.cpp:759
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.
Definition: treecanvas.cpp:912
void startCompareNodes(void)
Wait for click on node to compare with current node.
Definition: treecanvas.cpp:904
void addComparator(Comparator *c)
Add comparator c.
Definition: treecanvas.cpp:169
QMutex mutex
Mutex for synchronizing acccess to the tree.
Definition: treecanvas.hh:246
void inspectBeforeFP(void)
Calls inspectCurrentNode(false)
Definition: treecanvas.cpp:754
void hideFailed(void)
Hide failed subtrees of selected node.
Definition: treecanvas.cpp:470
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.
Definition: treecanvas.cpp:849
void print(void)
Print the tree.
void searchAll(void)
Explore complete subtree of selected node.
Definition: treecanvas.cpp:449
int refresh
Refresh rate.
Definition: treecanvas.hh:300
QTimeLine scrollTimeLine
Timer for smooth scrolling.
Definition: treecanvas.hh:333
int layoutDoneTimerId
Timer id for delaying the update.
Definition: treecanvas.hh:350
void addSolutionInspector(Inspector *i)
Add inspector i.
Definition: treecanvas.cpp:147
int targetH
Target height after layout.
Definition: treecanvas.hh:346
bool smoothScrollAndZoom
Whether to use smooth scrolling and zooming.
Definition: treecanvas.hh:304
QTimeLine zoomTimeLine
Timer for smooth zooming.
Definition: treecanvas.hh:331
void setPath(void)
Set the current node to be the head of the path.
Definition: treecanvas.cpp:874
void navRoot(void)
Move selection to the root node.
Definition: treecanvas.cpp:989
void statusChanged(VisualNode *, const Statistics &, bool)
Status bar update.
TreeCanvas(Space *rootSpace, bool bab, QWidget *parent, const Options &opt)
Constructor.
Definition: treecanvas.cpp:52
~TreeCanvas(void)
Destructor.
Definition: treecanvas.cpp:127
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.
Definition: treecanvas.cpp:455
void scroll(void)
React to scroll events.
Definition: treecanvas.cpp:254
void navDown(void)
Move selection to the first child of the selected node.
Definition: treecanvas.cpp:938
QVector< QPair< Comparator *, bool > > comparators
The registered comparators, and whether they are active.
Definition: treecanvas.hh:272
bool compareNodes
Whether node comparison action is running.
Definition: treecanvas.hh:278
void scaleTree(int scale0, int zoomx=-1, int zoomy=-1)
Set scale factor to scale0.
Definition: treecanvas.cpp:180
void activateSolutionInspector(int i, bool active)
Set active inspector.
Definition: treecanvas.cpp:152
int c_d
The recomputation distance.
Definition: treecanvas.hh:309
void mousePressEvent(QMouseEvent *event)
Handle mouse press event.
void navLeft(void)
Move selection to the left sibling of the selected node.
Definition: treecanvas.cpp:961
QSlider * scaleBar
The scale bar.
Definition: treecanvas.hh:283
QMutex layoutMutex
Mutex for synchronizing layout and drawing.
Definition: treecanvas.hh:248
int targetY
Target y coordinate after smooth scrolling.
Definition: treecanvas.hh:339
QVector< QPair< Inspector *, bool > > doubleClickInspectors
The registered click inspectors, and whether they are active.
Definition: treecanvas.hh:266
void autoZoomChanged(bool)
The auto-zoom state was changed.
void setRefresh(int i)
Set refresh rate.
Node::NodeAllocator * na
Allocator for nodes.
Definition: treecanvas.hh:256
BestNode * curBest
The currently best solution (for branch-and-bound)
Definition: treecanvas.hh:260
void paintEvent(QPaintEvent *event)
Paint the tree.
void unstopAll(void)
Do not stop at any stop node.
Definition: treecanvas.cpp:498
bool moveDuringSearch
Whether to move cursor during search.
Definition: treecanvas.hh:306
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.
Definition: treecanvas.hh:311
void unhideAll(void)
Unhide all nodes below selected node.
Definition: treecanvas.cpp:479
void reset(void)
Reset.
Definition: treecanvas.cpp:816
void searchFinished(void)
Signals that Gist is finished.
int sourceX
Source x coordinate after smooth scrolling.
Definition: treecanvas.hh:337
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.
Definition: treecanvas.hh:344
void setRecompDistances(int c_d, int a_d)
Set recomputation distances.
void addMoveInspector(Inspector *i)
Add inspector i.
Definition: treecanvas.cpp:158
bool autoZoom
Whether to zoom automatically.
Definition: treecanvas.hh:296
void emitStatusChanged(void)
Re-emit status change information for current node.
Definition: treecanvas.cpp:920
void setAutoZoom(bool b)
Set preference whether to automatically zoom to fit.
void centerCurrentNode(void)
Center the view on the currently selected node.
Definition: treecanvas.cpp:564
void setSmoothScrollAndZoom(bool b)
Set preference whether to use smooth scrolling and zooming.
bool finishedFlag
Flag signalling that Gist is ready to be closed.
Definition: treecanvas.hh:254
void removedBookmark(int idx)
Signals that a bookmark has been removed.
VisualNode * pathHead
The head of the currently selected path.
Definition: treecanvas.hh:264
void activateMoveInspector(int i, bool active)
Set active inspector.
Definition: treecanvas.cpp:163
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.
Definition: treecanvas.hh:252
void setShowCopies(bool b)
Set preference whether to show copies in the tree.
void labelPath(void)
Label all branches on path to root node.
Definition: treecanvas.cpp:767
void layoutDone(int w, int h, int scale0)
Layout done.
Definition: treecanvas.cpp:259
virtual void timerEvent(QTimerEvent *e)
Timer invoked for smooth zooming and scrolling.
Definition: treecanvas.cpp:508
bool getMoveDuringSearch(void)
Return preference whether to move cursor during search.
bool compareNodesBeforeFP
Whether node comparison action computes fixpoint.
Definition: treecanvas.hh:280
void toggleStop(void)
Do not stop at selected stop node.
Definition: treecanvas.cpp:489
void toggleHidden(void)
Toggle hidden state of selected node.
Definition: treecanvas.cpp:461
void navRight(void)
Move selection to the right sibling of the selected node.
Definition: treecanvas.cpp:975
void navPrevSol(void)
Move selection to previous solution (in DFS order)
bool showCopies
Whether to show copies in the tree.
Definition: treecanvas.hh:298
void inspectPath(void)
Call the double click inspector for all nodes on the path from root to head of the path.
Definition: treecanvas.cpp:888
bool getShowCopies(void)
Return preference whether to show copies in the tree.
VisualNode * root
The root node of the tree.
Definition: treecanvas.hh:258
void stopSearch(void)
Stop current search.
Definition: treecanvas.cpp:810
void inspectCurrentNode(bool fix=true, int inspectorNo=-1)
Call the double click inspector for the currently selected node.
Definition: treecanvas.cpp:618
int sourceY
Target y coordinate after smooth scrolling.
Definition: treecanvas.hh:341
void setAutoHideFailed(bool b)
Set preference whether to automatically hide failed subtrees.
void addDoubleClickInspector(Inspector *i)
Add inspector i.
Definition: treecanvas.cpp:136
int refreshPause
Time (in msec) to pause after each refresh.
Definition: treecanvas.hh:302
QVector< QPair< Inspector *, bool > > moveInspectors
The registered move inspectors, and whether they are active.
Definition: treecanvas.hh:270
QVector< QPair< Inspector *, bool > > solutionInspectors
The registered solution inspectors, and whether they are active.
Definition: treecanvas.hh:268
void addedBookmark(const QString &id)
Signals that a bookmark has been added.
Node class that supports visual layout
Definition: visualnode.hh:125
void unstopAll(const NodeAllocator &na)
Do not stop at any stop node in the subtree of this node.
Definition: visualnode.cpp:223
int getPathAlternative(const NodeAllocator &na)
Return the alternative of the child that is on the path (-1 if none)
Definition: visualnode.cpp:144
void unPathUp(const NodeAllocator &na)
Set all nodes from the node to the root not to be on the path.
Definition: visualnode.cpp:135
void unhideAll(const NodeAllocator &na)
Unhide all nodes in the subtree of this node.
Definition: visualnode.cpp:207
bool isBookmarked(void)
Return whether node is bookmarked.
Definition: visualnode.hpp:183
bool isHidden(void)
Return if node is hidden.
Definition: visualnode.hpp:129
void toggleStop(const NodeAllocator &na)
Do not stop at this node.
Definition: visualnode.cpp:214
void labelBranches(NodeAllocator &na, BestNode *curBest, int c_d, int a_d)
Create or clear branch labels in subtree.
Definition: visualnode.cpp:166
void setBookmarked(bool m)
Set bookmark of this node.
Definition: visualnode.hpp:188
void toggleHidden(const NodeAllocator &na)
Toggle whether this node is hidden.
Definition: visualnode.cpp:153
void labelPath(NodeAllocator &na, BestNode *curBest, int c_d, int a_d)
Create or clear branch labels on path to root.
Definition: visualnode.cpp:175
void pathUp(const NodeAllocator &na)
Set all nodes from the node to the root to be on the path.
Definition: visualnode.cpp:127
void dirtyUp(const NodeAllocator &na)
Mark all nodes up the path to the parent as dirty.
Definition: visualnode.cpp:102
void layout(const NodeAllocator &na)
Compute layout for the subtree of this node.
Definition: visualnode.cpp:113
void hideFailed(const NodeAllocator &na, bool onlyDirty=false)
Hide all failed subtrees of this node.
Definition: visualnode.cpp:159
BoundingBox getBoundingBox(void)
Return the bounding box.
Definition: visualnode.hpp:208
VisualNode * findNode(const NodeAllocator &na, int x, int y)
Find a node in this subtree at coordinates x, y.
Definition: visualnode.cpp:249
bool isOnPath(void)
Return whether node is on the path.
Definition: visualnode.hpp:193
void setMarked(bool m)
Set mark of this node.
Definition: visualnode.hpp:178
Shape * getShape(void)
Return the shape of this node.
Definition: visualnode.hpp:203
Computation spaces.
Definition: core.hpp:1742
VarImp * x
Pointer to variable implementation.
Definition: var.hpp:50
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 FloatNum max
Largest allowed float value.
Definition: float.hh:844
const FloatNum min
Smallest allowed float value.
Definition: float.hh:846
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
void update(VY &y, Space &home, bool shared, VY py)
Update view y from py.
unsigned int size(I &i)
Size of all ranges of range iterator i.
Space * snapshot(Space *s, const Options &o)
Clone space s dependening on options o.
Definition: support.hh:71
Gecode toplevel namespace
void abs(Home home, FloatVar x0, FloatVar x1)
Post propagator for .
Definition: arithmetic.cpp:41
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
Gecode::FloatVal c(-8, 8)
Gecode::IntArgs i({1, 2, 3, 4})
const SetInstr * si[]
Definition: mm-set.cpp:4341
Options opt
The options.
Definition: test.cpp:97
#define GECODE_NEVER
Assert that this command is never executed.
Definition: macros.hpp:56