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