Generated on Thu Apr 5 2018 19:44:19 for Gecode by doxygen 1.8.13
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$ by $Author$
11  * $Revision$
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 
102  connect(&searcher, SIGNAL(moveToNode(VisualNode*,bool)),
103  this, SLOT(setCurrentNode(VisualNode*,bool)),
104  Qt::BlockingQueuedConnection);
105 
106  connect(&searcher, SIGNAL(searchFinished(void)), this, SIGNAL(searchFinished(void)));
107 
108  connect(&scrollTimeLine, SIGNAL(frameChanged(int)),
109  this, SLOT(scroll(int)));
110  scrollTimeLine.setCurveShape(QTimeLine::EaseInOutCurve);
111 
112  scaleBar = new QSlider(Qt::Vertical, this);
113  scaleBar->setObjectName("scaleBar");
114  scaleBar->setMinimum(LayoutConfig::minScale);
115  scaleBar->setMaximum(LayoutConfig::maxScale);
116  scaleBar->setValue(LayoutConfig::defScale);
117  connect(scaleBar, SIGNAL(valueChanged(int)),
118  this, SLOT(scaleTree(int)));
119  connect(this, SIGNAL(scaleChanged(int)), scaleBar, SLOT(setValue(int)));
120  connect(&searcher, SIGNAL(scaleChanged(int)),
121  scaleBar, SLOT(setValue(int)));
122 
123  connect(&zoomTimeLine, SIGNAL(frameChanged(int)),
124  scaleBar, SLOT(setValue(int)));
125  zoomTimeLine.setCurveShape(QTimeLine::EaseInOutCurve);
126 
127  qRegisterMetaType<Statistics>("Statistics");
128  update();
129  }
130 
132  if (root) {
133  DisposeCursor dc(root,*na);
135  }
136  delete na;
137  }
138 
139  void
141  doubleClickInspectors.append(QPair<Inspector*,bool>(i,false));
142  }
143 
144  void
146  assert(i < doubleClickInspectors.size());
147  doubleClickInspectors[i].second = active;
148  }
149 
150  void
152  solutionInspectors.append(QPair<Inspector*,bool>(i,false));
153  }
154 
155  void
157  assert(i < solutionInspectors.size());
158  solutionInspectors[i].second = active;
159  }
160 
161  void
163  moveInspectors.append(QPair<Inspector*,bool>(i,false));
164  }
165 
166  void
168  assert(i < moveInspectors.size());
169  moveInspectors[i].second = active;
170  }
171 
172  void
174  comparators.append(QPair<Comparator*,bool>(c,false));
175  }
176 
177  void
178  TreeCanvas::activateComparator(int i, bool active) {
179  assert(i < comparators.size());
180  comparators[i].second = active;
181  }
182 
183  void
184  TreeCanvas::scaleTree(int scale0, int zoomx, int zoomy) {
185  QMutexLocker locker(&layoutMutex);
186 
187  QSize viewport_size = size();
188  QAbstractScrollArea* sa =
189  static_cast<QAbstractScrollArea*>(parentWidget()->parentWidget());
190 
191  if (zoomx==-1)
192  zoomx = viewport_size.width()/2;
193  if (zoomy==-1)
194  zoomy = viewport_size.height()/2;
195 
196  int xoff = (sa->horizontalScrollBar()->value()+zoomx)/scale;
197  int yoff = (sa->verticalScrollBar()->value()+zoomy)/scale;
198 
199  BoundingBox bb;
200  scale0 = std::min(std::max(scale0, LayoutConfig::minScale),
202  scale = (static_cast<double>(scale0)) / 100.0;
203  bb = root->getBoundingBox();
204  int w =
205  static_cast<int>((bb.right-bb.left+Layout::extent)*scale);
206  int h =
207  static_cast<int>(2*Layout::extent+
209 
210  sa->horizontalScrollBar()->setRange(0,w-viewport_size.width());
211  sa->verticalScrollBar()->setRange(0,h-viewport_size.height());
212  sa->horizontalScrollBar()->setPageStep(viewport_size.width());
213  sa->verticalScrollBar()->setPageStep(viewport_size.height());
214  sa->horizontalScrollBar()->setSingleStep(Layout::extent);
215  sa->verticalScrollBar()->setSingleStep(Layout::extent);
216 
217  xoff *= scale;
218  yoff *= scale;
219 
220  sa->horizontalScrollBar()->setValue(xoff-zoomx);
221  sa->verticalScrollBar()->setValue(yoff-zoomy);
222 
223  emit scaleChanged(scale0);
224  QWidget::update();
225  }
226 
227  void
229  QMutexLocker locker(&mutex);
230  layoutMutex.lock();
231  if (root != NULL) {
232  root->layout(*na);
234 
235  int w = static_cast<int>((bb.right-bb.left+Layout::extent)*scale);
236  int h =
237  static_cast<int>(2*Layout::extent+
239  xtrans = -bb.left+(Layout::extent / 2);
240 
241  QSize viewport_size = size();
242  QAbstractScrollArea* sa =
243  static_cast<QAbstractScrollArea*>(parentWidget()->parentWidget());
244  sa->horizontalScrollBar()->setRange(0,w-viewport_size.width());
245  sa->verticalScrollBar()->setRange(0,h-viewport_size.height());
246  sa->horizontalScrollBar()->setPageStep(viewport_size.width());
247  sa->verticalScrollBar()->setPageStep(viewport_size.height());
248  sa->horizontalScrollBar()->setSingleStep(Layout::extent);
249  sa->verticalScrollBar()->setSingleStep(Layout::extent);
250  }
251  if (autoZoom)
252  zoomToFit();
253  layoutMutex.unlock();
254  QWidget::update();
255  }
256 
257  void
259  QWidget::update();
260  }
261 
262  void
263  TreeCanvas::layoutDone(int w, int h, int scale0) {
264  targetW = w; targetH = h; targetScale = scale0;
265 
266  QSize viewport_size = size();
267  QAbstractScrollArea* sa =
268  static_cast<QAbstractScrollArea*>(parentWidget()->parentWidget());
269  sa->horizontalScrollBar()->setRange(0,w-viewport_size.width());
270  sa->verticalScrollBar()->setRange(0,h-viewport_size.height());
271 
272  if (layoutDoneTimerId == 0)
273  layoutDoneTimerId = startTimer(15);
274  }
275 
276  void
277  TreeCanvas::statusChanged(bool finished) {
278  if (finished) {
279  update();
281  }
282  emit statusChanged(currentNode, stats, finished);
283  }
284 
285  void
287  node = n;
288 
289  depth = -1;
290  for (VisualNode* p = n; p != NULL; p = p->getParent(*ti->na))
291  depth++;
292 
293  a = all;
294  t = ti;
295  start();
296  }
297 
298  void
299  SearcherThread::updateCanvas(void) {
300  t->layoutMutex.lock();
301  if (t->root == NULL)
302  return;
303 
304  if (t->autoHideFailed) {
305  t->root->hideFailed(*t->na,true);
306  }
307  for (VisualNode* n = t->currentNode; n != NULL; n=n->getParent(*t->na)) {
308  if (n->isHidden()) {
309  t->currentNode->setMarked(false);
310  t->currentNode = n;
311  t->currentNode->setMarked(true);
312  break;
313  }
314  }
315 
316  t->root->layout(*t->na);
317  BoundingBox bb = t->root->getBoundingBox();
318 
319  int w = static_cast<int>((bb.right-bb.left+Layout::extent)*t->scale);
320  int h = static_cast<int>(2*Layout::extent+
321  t->root->getShape()->depth()
322  *Layout::dist_y*t->scale);
323  t->xtrans = -bb.left+(Layout::extent / 2);
324 
325  int scale0 = static_cast<int>(t->scale*100);
326  if (t->autoZoom) {
327  QWidget* p = t->parentWidget();
328  if (p) {
329  double newXScale =
330  static_cast<double>(p->width()) / (bb.right - bb.left +
332  double newYScale =
333  static_cast<double>(p->height()) /
334  (t->root->getShape()->depth() * Layout::dist_y + 2*Layout::extent);
335 
336  scale0 = static_cast<int>(std::min(newXScale, newYScale)*100);
337  if (scale0<LayoutConfig::minScale)
338  scale0 = LayoutConfig::minScale;
341  double scale = (static_cast<double>(scale0)) / 100.0;
342 
343  w = static_cast<int>((bb.right-bb.left+Layout::extent)*scale);
344  h = static_cast<int>(2*Layout::extent+
345  t->root->getShape()->depth()*Layout::dist_y*scale);
346  }
347  }
348 
349  t->layoutMutex.unlock();
350  emit update(w,h,scale0);
351  }
352 
354  class SearchItem {
355  public:
359  int i;
363  SearchItem(VisualNode* n0, int noOfChildren0)
364  : n(n0), i(-1), noOfChildren(noOfChildren0) {}
365  };
366 
367  void
369  {
370  if (!node->isOpen())
371  return;
372  t->mutex.lock();
373  emit statusChanged(false);
374 
375  unsigned int kids =
376  node->getNumberOfChildNodes(*t->na, t->curBest, t->stats,
377  t->c_d, t->a_d);
378  if (kids == 0 || node->getStatus() == STOP) {
379  t->mutex.unlock();
380  updateCanvas();
381  emit statusChanged(true);
382  return;
383  }
384 
385  std::stack<SearchItem> stck;
386  stck.push(SearchItem(node,kids));
387  t->stats.maxDepth =
388  std::max(static_cast<long unsigned int>(t->stats.maxDepth),
389  static_cast<long unsigned int>(depth+stck.size()));
390 
391  VisualNode* sol = NULL;
392  int nodeCount = 0;
393  t->stopSearchFlag = false;
394  while (!stck.empty() && !t->stopSearchFlag) {
395  if (t->refresh > 0 && nodeCount >= t->refresh) {
396  node->dirtyUp(*t->na);
397  updateCanvas();
398  emit statusChanged(false);
399  nodeCount = 0;
400  if (t->refreshPause > 0)
401  msleep(t->refreshPause);
402  }
403  SearchItem& si = stck.top();
404  si.i++;
405  if (si.i == si.noOfChildren) {
406  stck.pop();
407  } else {
408  VisualNode* n = si.n->getChild(*t->na,si.i);
409  if (n->isOpen()) {
410  if (n->getStatus() == UNDETERMINED)
411  nodeCount++;
412  kids = n->getNumberOfChildNodes(*t->na, t->curBest, t->stats,
413  t->c_d, t->a_d);
414  if (t->moveDuringSearch)
415  emit moveToNode(n,false);
416  if (kids == 0) {
417  if (n->getStatus() == SOLVED) {
418  assert(n->hasCopy());
419  emit solution(n->getWorkingSpace());
420  n->purge(*t->na);
421  sol = n;
422  if (!a)
423  break;
424  }
425  } else {
426  if ( n->getStatus() != STOP )
427  stck.push(SearchItem(n,kids));
428  else if (!a)
429  break;
430  t->stats.maxDepth =
431  std::max(static_cast<long unsigned int>(t->stats.maxDepth),
432  static_cast<long unsigned int>(depth+stck.size()));
433  }
434  }
435  }
436  }
437  node->dirtyUp(*t->na);
438  t->stopSearchFlag = false;
439  t->mutex.unlock();
440  if (sol != NULL) {
441  t->setCurrentNode(sol,true,false);
442  } else {
443  t->setCurrentNode(node,true,false);
444  }
445  }
446  updateCanvas();
447  emit statusChanged(true);
448  if (t->finishedFlag)
449  emit searchFinished();
450  }
451 
452  void
454  QMutexLocker locker(&mutex);
455  searcher.search(currentNode, true, this);
456  }
457 
458  void
460  QMutexLocker locker(&mutex);
461  searcher.search(currentNode, false, this);
462  }
463 
464  void
466  QMutexLocker locker(&mutex);
468  update();
470  emit statusChanged(currentNode, stats, true);
471  }
472 
473  void
475  QMutexLocker locker(&mutex);
477  update();
479  emit statusChanged(currentNode, stats, true);
480  }
481 
482  void
484  QMutexLocker locker(&mutex);
485  QMutexLocker layoutLocker(&layoutMutex);
487  update();
489  emit statusChanged(currentNode, stats, true);
490  }
491 
492  void
494  QMutexLocker locker(&mutex);
496  update();
498  emit statusChanged(currentNode, stats, true);
499  }
500 
501  void
503  QMutexLocker locker(&mutex);
504  QMutexLocker layoutLocker(&layoutMutex);
506  update();
508  emit statusChanged(currentNode, stats, true);
509  }
510 
511  void
512  TreeCanvas::timerEvent(QTimerEvent* e) {
513  if (e->timerId() == layoutDoneTimerId) {
514  if (!smoothScrollAndZoom) {
516  } else {
517  zoomTimeLine.stop();
518  int zoomCurrent = static_cast<int>(scale*100);
519  int targetZoom = targetScale;
520  targetZoom = std::min(std::max(targetZoom, LayoutConfig::minScale),
522  zoomTimeLine.setFrameRange(zoomCurrent,targetZoom);
523  zoomTimeLine.start();
524  }
525  QWidget::update();
526  killTimer(layoutDoneTimerId);
527  layoutDoneTimerId = 0;
528  }
529  }
530 
531  void
533  QMutexLocker locker(&layoutMutex);
534  if (root != NULL) {
535  BoundingBox bb;
536  bb = root->getBoundingBox();
537  QWidget* p = parentWidget();
538  if (p) {
539  double newXScale =
540  static_cast<double>(p->width()) / (bb.right - bb.left +
542  double newYScale =
543  static_cast<double>(p->height()) / (root->getShape()->depth() *
545  2*Layout::extent);
546  int scale0 = static_cast<int>(std::min(newXScale, newYScale)*100);
547  if (scale0<LayoutConfig::minScale)
548  scale0 = LayoutConfig::minScale;
551 
552  if (!smoothScrollAndZoom) {
553  scaleTree(scale0);
554  } else {
555  zoomTimeLine.stop();
556  int zoomCurrent = static_cast<int>(scale*100);
557  int targetZoom = scale0;
558  targetZoom = std::min(std::max(targetZoom, LayoutConfig::minScale),
560  zoomTimeLine.setFrameRange(zoomCurrent,targetZoom);
561  zoomTimeLine.start();
562  }
563  }
564  }
565  }
566 
567  void
569  QMutexLocker locker(&mutex);
570  int x=0;
571  int y=0;
572 
574  while (c != NULL) {
575  x += c->getOffset();
576  y += Layout::dist_y;
577  c = c->getParent(*na);
578  }
579 
580  x = static_cast<int>((xtrans+x)*scale); y = static_cast<int>(y*scale);
581 
582  QAbstractScrollArea* sa =
583  static_cast<QAbstractScrollArea*>(parentWidget()->parentWidget());
584 
585  x -= sa->viewport()->width() / 2;
586  y -= sa->viewport()->height() / 2;
587 
588  sourceX = sa->horizontalScrollBar()->value();
589  targetX = std::max(sa->horizontalScrollBar()->minimum(), x);
590  targetX = std::min(sa->horizontalScrollBar()->maximum(),
591  targetX);
592  sourceY = sa->verticalScrollBar()->value();
593  targetY = std::max(sa->verticalScrollBar()->minimum(), y);
594  targetY = std::min(sa->verticalScrollBar()->maximum(),
595  targetY);
596  if (!smoothScrollAndZoom) {
597  sa->horizontalScrollBar()->setValue(targetX);
598  sa->verticalScrollBar()->setValue(targetY);
599  } else {
600  scrollTimeLine.stop();
601  scrollTimeLine.setFrameRange(0,100);
602  scrollTimeLine.setDuration(std::max(200,
603  std::min(1000,
604  std::min(std::abs(sourceX-targetX),
605  std::abs(sourceY-targetY)))));
606  scrollTimeLine.start();
607  }
608  }
609 
610  void
611  TreeCanvas::scroll(int i) {
612  QAbstractScrollArea* sa =
613  static_cast<QAbstractScrollArea*>(parentWidget()->parentWidget());
614  double p = static_cast<double>(i)/100.0;
615  double xdiff = static_cast<double>(targetX-sourceX)*p;
616  double ydiff = static_cast<double>(targetY-sourceY)*p;
617  sa->horizontalScrollBar()->setValue(sourceX+static_cast<int>(xdiff));
618  sa->verticalScrollBar()->setValue(sourceY+static_cast<int>(ydiff));
619  }
620 
621  void
622  TreeCanvas::inspectCurrentNode(bool fix, int inspectorNo) {
623  QMutexLocker locker(&mutex);
624 
625  if (currentNode->isHidden()) {
626  toggleHidden();
627  return;
628  }
629 
630  int failedInspectorType = -1;
631  int failedInspector = -1;
632  bool needCentering = false;
633  try {
634  switch (currentNode->getStatus()) {
635  case UNDETERMINED:
636  {
637  unsigned int kids =
639  int depth = -1;
640  for (VisualNode* p = currentNode; p != NULL; p=p->getParent(*na))
641  depth++;
642  if (kids > 0) {
643  needCentering = true;
644  depth++;
645  }
646  stats.maxDepth =
647  std::max(stats.maxDepth, depth);
648  if (currentNode->getStatus() == SOLVED) {
649  assert(currentNode->hasCopy());
651  }
652  emit statusChanged(currentNode,stats,true);
653  for (int i=0; i<moveInspectors.size(); i++) {
654  if (moveInspectors[i].second) {
655  failedInspectorType = 0;
656  failedInspector = i;
657  if (currentNode->getStatus() == FAILED) {
658  if (!currentNode->isRoot()) {
659  Space* curSpace =
661  moveInspectors[i].first->inspect(*curSpace);
662  delete curSpace;
663  }
664  } else {
665  moveInspectors[i].first->
666  inspect(*currentNode->getWorkingSpace());
667  }
668  failedInspectorType = -1;
669  }
670  }
671  if (currentNode->getStatus() == SOLVED) {
672  currentNode->purge(*na);
673  }
674  }
675  break;
676  case FAILED:
677  case STOP:
678  case UNSTOP:
679  case BRANCH:
680  case SOLVED:
681  {
682  Space* curSpace;
683 
684  if (fix) {
686  break;
687  curSpace = currentNode->getSpace(*na,curBest,c_d,a_d);
688  if (currentNode->getStatus() == SOLVED &&
689  curSpace->status() != SS_SOLVED) {
690  // in the presence of weakly monotonic propagators, we may have
691  // to use search to find the solution here
692  assert(curSpace->status() == SS_BRANCH &&
693  "Something went wrong - probably an incorrect brancher");
694  Space* dfsSpace = Gecode::dfs(curSpace);
695  delete curSpace;
696  curSpace = dfsSpace;
697  }
698  } else {
699  if (currentNode->isRoot())
700  break;
702  curSpace = p->getSpace(*na,curBest,c_d,a_d);
703  switch (curSpace->status()) {
704  case SS_SOLVED:
705  case SS_FAILED:
706  break;
707  case SS_BRANCH:
708  curSpace->commit(*p->getChoice(),
710  break;
711  default:
712  GECODE_NEVER;
713  }
714  }
715 
716  if (inspectorNo==-1) {
717  for (int i=0; i<doubleClickInspectors.size(); i++) {
718  if (doubleClickInspectors[i].second) {
719  failedInspectorType = 1;
720  failedInspector = i;
721  doubleClickInspectors[i].first->inspect(*curSpace);
722  failedInspectorType = -1;
723  }
724  }
725  } else {
726  failedInspectorType = 1;
727  failedInspector = inspectorNo;
728  doubleClickInspectors[inspectorNo].first->inspect(*curSpace);
729  failedInspectorType = -1;
730  }
731  delete curSpace;
732  }
733  break;
734  }
735  } catch (Exception& e) {
736  switch (failedInspectorType) {
737  case 0:
738  qFatal("Exception in move inspector %d: %s.\n Stopping.",
739  failedInspector, e.what());
740  break;
741  case 1:
742  qFatal("Exception in double click inspector %d: %s.\n Stopping.",
743  failedInspector, e.what());
744  break;
745  default:
746  qFatal("Exception: %s.\n Stopping.", e.what());
747  break;
748  }
749  }
750 
752  update();
753  if (needCentering)
755  }
756 
757  void
759  inspectCurrentNode(false);
760  }
761 
762  void
764  QMutexLocker locker(&mutex);
766  update();
768  emit statusChanged(currentNode, stats, true);
769  }
770  void
772  QMutexLocker locker(&mutex);
774  update();
776  emit statusChanged(currentNode, stats, true);
777  }
778 
779  void
780  TreeCanvas::inspectSolution(const Space* s) {
781  int failedInspectorType = -1;
782  int failedInspector = -1;
783  try {
784  Space* c = NULL;
785  for (int i=0; i<solutionInspectors.size(); i++) {
786  if (solutionInspectors[i].second) {
787  if (c == NULL)
788  c = s->clone();
789  failedInspectorType = 1;
790  failedInspector = i;
791  solutionInspectors[i].first->inspect(*c);
792  failedInspectorType = -1;
793  }
794  }
795  delete c;
796  } catch (Exception& e) {
797  switch (failedInspectorType) {
798  case 0:
799  qFatal("Exception in move inspector %d: %s.\n Stopping.",
800  failedInspector, e.what());
801  break;
802  case 1:
803  qFatal("Exception in solution inspector %d: %s.\n Stopping.",
804  failedInspector, e.what());
805  break;
806  default:
807  qFatal("Exception: %s.\n Stopping.", e.what());
808  break;
809  }
810  }
811  }
812 
813  void
815  stopSearchFlag = true;
816  layoutDoneTimerId = startTimer(15);
817  }
818 
819  void
821  QMutexLocker locker(&mutex);
822  Space* rootSpace =
823  root->getStatus() == FAILED ? NULL :
825  if (curBest != NULL) {
826  delete curBest;
827  curBest = new BestNode(NULL);
828  }
829  if (root) {
830  DisposeCursor dc(root,*na);
832  }
833  delete na;
834  na = new Node::NodeAllocator(curBest != NULL);
835  int rootIdx = na->allocate(rootSpace);
836  assert(rootIdx == 0); (void) rootIdx;
837  root = (*na)[0];
838  root->setMarked(true);
839  currentNode = root;
840  pathHead = root;
841  scale = 1.0;
842  stats = Statistics();
843  for (int i=bookmarks.size(); i--;)
844  emit removedBookmark(i);
845  bookmarks.clear();
846  root->layout(*na);
847 
848  emit statusChanged(currentNode, stats, true);
849  update();
850  }
851 
852  void
854  QMutexLocker locker(&mutex);
855  if (!currentNode->isBookmarked()) {
856  bool ok;
857  QString text =
858  QInputDialog::getText(this, "Add bookmark", "Name:",
859  QLineEdit::Normal,"",&ok);
860  if (ok) {
861  currentNode->setBookmarked(true);
862  bookmarks.append(currentNode);
863  if (text == "")
864  text = QString("Node ")+QString().setNum(bookmarks.size());
865  emit addedBookmark(text);
866  }
867  } else {
868  currentNode->setBookmarked(false);
869  int idx = bookmarks.indexOf(currentNode);
870  bookmarks.remove(idx);
871  emit removedBookmark(idx);
872  }
874  update();
875  }
876 
877  void
879  QMutexLocker locker(&mutex);
880  if(currentNode == pathHead)
881  return;
882 
883  pathHead->unPathUp(*na);
885 
886  currentNode->pathUp(*na);
888  update();
889  }
890 
891  void
893  QMutexLocker locker(&mutex);
895  if (currentNode->isOnPath()) {
897  int nextAlt = currentNode->getPathAlternative(*na);
898  while (nextAlt >= 0) {
901  nextAlt = currentNode->getPathAlternative(*na);
902  }
903  }
904  update();
905  }
906 
907  void
909  QMutexLocker locker(&mutex);
910  compareNodes = true;
911  compareNodesBeforeFP = false;
912  setCursor(QCursor(Qt::CrossCursor));
913  }
914 
915  void
917  QMutexLocker locker(&mutex);
918  compareNodes = true;
919  compareNodesBeforeFP = true;
920  setCursor(QCursor(Qt::CrossCursor));
921  }
922 
923  void
925  emit statusChanged(currentNode, stats, true);
926  }
927 
928  void
930  QMutexLocker locker(&mutex);
931 
933 
934  setCurrentNode(p);
935 
936  if (p != NULL) {
938  }
939  }
940 
941  void
943  QMutexLocker locker(&mutex);
944  if (!currentNode->isHidden()) {
945  switch (currentNode->getStatus()) {
946  case STOP:
947  case UNSTOP:
948  case BRANCH:
949  {
950  int alt = std::max(0, currentNode->getPathAlternative(*na));
951  VisualNode* n = currentNode->getChild(*na,alt);
952  setCurrentNode(n);
954  break;
955  }
956  case SOLVED:
957  case FAILED:
958  case UNDETERMINED:
959  break;
960  }
961  }
962  }
963 
964  void
966  QMutexLocker locker(&mutex);
968  if (p != NULL) {
969  int alt = currentNode->getAlternative(*na);
970  if (alt > 0) {
971  VisualNode* n = p->getChild(*na,alt-1);
972  setCurrentNode(n);
974  }
975  }
976  }
977 
978  void
980  QMutexLocker locker(&mutex);
982  if (p != NULL) {
983  unsigned int alt = currentNode->getAlternative(*na);
984  if (alt + 1 < p->getNumberOfChildren()) {
985  VisualNode* n = p->getChild(*na,alt+1);
986  setCurrentNode(n);
988  }
989  }
990  }
991 
992  void
994  QMutexLocker locker(&mutex);
997  }
998 
999  void
1001  QMutexLocker locker(&mutex);
1002  NextSolCursor nsc(currentNode,back,*na);
1004  nsv.run();
1005  VisualNode* n = nsv.getCursor().node();
1006  if (n != root) {
1007  setCurrentNode(n);
1009  }
1010  }
1011 
1012  void
1014  navNextSol(true);
1015  }
1016 
1017  void
1018  TreeCanvas::exportNodePDF(VisualNode* n) {
1019 #if QT_VERSION >= 0x040400
1020  QString filename = QFileDialog::getSaveFileName(this, tr("Export tree as pdf"), "", tr("PDF (*.pdf)"));
1021  if (filename != "") {
1022  QPrinter printer(QPrinter::ScreenResolution);
1023  QMutexLocker locker(&mutex);
1024 
1025  BoundingBox bb = n->getBoundingBox();
1026  printer.setFullPage(true);
1027  printer.setPaperSize(QSizeF(bb.right-bb.left+Layout::extent,
1028  n->getShape()->depth() * Layout::dist_y +
1029  Layout::extent), QPrinter::Point);
1030  printer.setOutputFileName(filename);
1031  QPainter painter(&printer);
1032 
1033  painter.setRenderHint(QPainter::Antialiasing);
1034 
1035  QRect pageRect = printer.pageRect();
1036  double newXScale =
1037  static_cast<double>(pageRect.width()) / (bb.right - bb.left +
1038  Layout::extent);
1039  double newYScale =
1040  static_cast<double>(pageRect.height()) /
1041  (n->getShape()->depth() * Layout::dist_y +
1042  Layout::extent);
1043  double printScale = std::min(newXScale, newYScale);
1044  painter.scale(printScale,printScale);
1045 
1046  int printxtrans = -bb.left+(Layout::extent / 2);
1047 
1048  painter.translate(printxtrans, Layout::dist_y / 2);
1049  QRect clip(0,0,0,0);
1050  DrawingCursor dc(n, *na, curBest, painter, clip, showCopies);
1051  currentNode->setMarked(false);
1053  currentNode->setMarked(true);
1054  }
1055 #else
1056  (void) n;
1057 #endif
1058  }
1059 
1060  void
1062 #if QT_VERSION >= 0x040400
1063  exportNodePDF(root);
1064 #endif
1065  }
1066 
1067  void
1069 #if QT_VERSION >= 0x040400
1070  exportNodePDF(currentNode);
1071 #endif
1072  }
1073 
1074  void
1076  QPrinter printer;
1077  if (QPrintDialog(&printer, this).exec() == QDialog::Accepted) {
1078  QMutexLocker locker(&mutex);
1079 
1081  QRect pageRect = printer.pageRect();
1082  double newXScale =
1083  static_cast<double>(pageRect.width()) / (bb.right - bb.left +
1084  Layout::extent);
1085  double newYScale =
1086  static_cast<double>(pageRect.height()) /
1087  (root->getShape()->depth() * Layout::dist_y +
1088  2*Layout::extent);
1089  double printScale = std::min(newXScale, newYScale)*100;
1090  if (printScale<1.0)
1091  printScale = 1.0;
1092  if (printScale > 400.0)
1093  printScale = 400.0;
1094  printScale = printScale / 100.0;
1095 
1096  QPainter painter(&printer);
1097  painter.setRenderHint(QPainter::Antialiasing);
1098  painter.scale(printScale,printScale);
1099  painter.translate(xtrans, 0);
1100  QRect clip(0,0,0,0);
1101  DrawingCursor dc(root, *na, curBest, painter, clip, showCopies);
1103  }
1104  }
1105 
1106  VisualNode*
1108  int x = 0;
1109  int y = 0;
1110  switch (event->type()) {
1111  case QEvent::ToolTip:
1112  {
1113  QHelpEvent* he = static_cast<QHelpEvent*>(event);
1114  x = he->x();
1115  y = he->y();
1116  break;
1117  }
1118  case QEvent::MouseButtonDblClick:
1119  case QEvent::MouseButtonPress:
1120  case QEvent::MouseButtonRelease:
1121  case QEvent::MouseMove:
1122  {
1123  QMouseEvent* me = static_cast<QMouseEvent*>(event);
1124  x = me->x();
1125  y = me->y();
1126  break;
1127  }
1128  case QEvent::ContextMenu:
1129  {
1130  QContextMenuEvent* ce = static_cast<QContextMenuEvent*>(event);
1131  x = ce->x();
1132  y = ce->y();
1133  break;
1134  }
1135  default:
1136  return NULL;
1137  }
1138  QAbstractScrollArea* sa =
1139  static_cast<QAbstractScrollArea*>(parentWidget()->parentWidget());
1140  int xoff = sa->horizontalScrollBar()->value()/scale;
1141  int yoff = sa->verticalScrollBar()->value()/scale;
1142 
1144  int w =
1145  static_cast<int>((bb.right-bb.left+Layout::extent)*scale);
1146  if (w < sa->viewport()->width())
1147  xoff -= (sa->viewport()->width()-w)/2;
1148 
1149  VisualNode* n;
1150  n = root->findNode(*na,
1151  static_cast<int>(x/scale-xtrans+xoff),
1152  static_cast<int>((y-30)/scale+yoff));
1153  return n;
1154  }
1155 
1156  bool
1158  if (mutex.tryLock()) {
1159  if (event->type() == QEvent::ToolTip) {
1160  VisualNode* n = eventNode(event);
1161  if (n != NULL) {
1162  QHelpEvent* he = static_cast<QHelpEvent*>(event);
1163  QToolTip::showText(he->globalPos(),
1164  QString(n->toolTip(*na,curBest,
1165  c_d,a_d).c_str()));
1166  } else {
1167  QToolTip::hideText();
1168  }
1169  }
1170  mutex.unlock();
1171  }
1172  return QWidget::event(event);
1173  }
1174 
1175  void
1177  if (autoZoom)
1178  zoomToFit();
1179  }
1180 
1181  void
1183  QMutexLocker locker(&layoutMutex);
1184  QPainter painter(this);
1185  painter.setRenderHint(QPainter::Antialiasing);
1186 
1187  QAbstractScrollArea* sa =
1188  static_cast<QAbstractScrollArea*>(parentWidget()->parentWidget());
1189  int xoff = sa->horizontalScrollBar()->value()/scale;
1190  int yoff = sa->verticalScrollBar()->value()/scale;
1191 
1193  int w =
1194  static_cast<int>((bb.right-bb.left+Layout::extent)*scale);
1195  if (w < sa->viewport()->width())
1196  xoff -= (sa->viewport()->width()-w)/2;
1197 
1198  QRect origClip = event->rect();
1199  painter.translate(0, 30);
1200  painter.scale(scale,scale);
1201  painter.translate(xtrans-xoff, -yoff);
1202  QRect clip(static_cast<int>(origClip.x()/scale-xtrans+xoff),
1203  static_cast<int>(origClip.y()/scale+yoff),
1204  static_cast<int>(origClip.width()/scale),
1205  static_cast<int>(origClip.height()/scale));
1206  DrawingCursor dc(root, *na, curBest, painter, clip, showCopies);
1208 
1209  // int nodesLayouted = 1;
1210  // clock_t t0 = clock();
1211  // while (v.next()) { nodesLayouted++; }
1212  // double t = (static_cast<double>(clock()-t0) / CLOCKS_PER_SEC) * 1000.0;
1213  // double nps = static_cast<double>(nodesLayouted) /
1214  // (static_cast<double>(clock()-t0) / CLOCKS_PER_SEC);
1215  // std::cout << "Drawing done. " << nodesLayouted << " nodes in "
1216  // << t << " ms. " << nps << " nodes/s." << std::endl;
1217 
1218  }
1219 
1220  void
1222  if (mutex.tryLock()) {
1223  if(event->button() == Qt::LeftButton) {
1224  VisualNode* n = eventNode(event);
1225  if(n == currentNode) {
1227  event->accept();
1228  mutex.unlock();
1229  return;
1230  }
1231  }
1232  mutex.unlock();
1233  }
1234  event->ignore();
1235  }
1236 
1237  void
1238  TreeCanvas::contextMenuEvent(QContextMenuEvent* event) {
1239  if (mutex.tryLock()) {
1240  VisualNode* n = eventNode(event);
1241  if (n != NULL) {
1242  setCurrentNode(n);
1243  emit contextMenu(event);
1244  event->accept();
1245  mutex.unlock();
1246  return;
1247  }
1248  mutex.unlock();
1249  }
1250  event->ignore();
1251  }
1252 
1253  void
1254  TreeCanvas::resizeEvent(QResizeEvent* e) {
1255  QAbstractScrollArea* sa =
1256  static_cast<QAbstractScrollArea*>(parentWidget()->parentWidget());
1257 
1258  int w = sa->horizontalScrollBar()->maximum()+e->oldSize().width();
1259  int h = sa->verticalScrollBar()->maximum()+e->oldSize().height();
1260 
1261  sa->horizontalScrollBar()->setRange(0,w-e->size().width());
1262  sa->verticalScrollBar()->setRange(0,h-e->size().height());
1263  sa->horizontalScrollBar()->setPageStep(e->size().width());
1264  sa->verticalScrollBar()->setPageStep(e->size().height());
1265  }
1266 
1267  void
1269  if (event->modifiers() & Qt::ShiftModifier) {
1270  event->accept();
1271  if (event->orientation() == Qt::Vertical && !autoZoom)
1272  scaleTree(scale*100+ceil(static_cast<double>(event->delta())/4.0),
1273  event->x(), event->y());
1274  } else {
1275  event->ignore();
1276  }
1277  }
1278 
1279  bool
1281  if (finishedFlag)
1282  return true;
1283  stopSearchFlag = true;
1284  finishedFlag = true;
1285  for (int i=0; i<doubleClickInspectors.size(); i++)
1286  doubleClickInspectors[i].first->finalize();
1287  for (int i=0; i<solutionInspectors.size(); i++)
1288  solutionInspectors[i].first->finalize();
1289  for (int i=0; i<moveInspectors.size(); i++)
1290  moveInspectors[i].first->finalize();
1291  for (int i=0; i<comparators.size(); i++)
1292  comparators[i].first->finalize();
1293  return !searcher.isRunning();
1294  }
1295 
1296  void
1297  TreeCanvas::setCurrentNode(VisualNode* n, bool finished, bool update) {
1298  if (finished)
1299  mutex.lock();
1300  if (update && n != NULL && n != currentNode &&
1301  n->getStatus() != UNDETERMINED && !n->isHidden()) {
1302  Space* curSpace = NULL;
1303  for (int i=0; i<moveInspectors.size(); i++) {
1304  if (moveInspectors[i].second) {
1305  if (curSpace == NULL)
1306  curSpace = n->getSpace(*na,curBest,c_d,a_d);
1307  try {
1308  moveInspectors[i].first->inspect(*curSpace);
1309  } catch (Exception& e) {
1310  qFatal("Exception in move inspector %d: %s.\n Stopping.",
1311  i, e.what());
1312  }
1313  }
1314  }
1315  }
1316  if (n != NULL) {
1317  currentNode->setMarked(false);
1318  currentNode = n;
1319  currentNode->setMarked(true);
1320  emit statusChanged(currentNode,stats,finished);
1321  if (update) {
1322  compareNodes = false;
1323  setCursor(QCursor(Qt::ArrowCursor));
1324  QWidget::update();
1325  }
1326  }
1327  if (finished)
1328  mutex.unlock();
1329  }
1330 
1331  void
1333  if (mutex.tryLock()) {
1334  if (event->button() == Qt::LeftButton) {
1335  VisualNode* n = eventNode(event);
1336  if (compareNodes) {
1337  if (n != NULL && n->getStatus() != UNDETERMINED &&
1338  currentNode != NULL &&
1340  Space* curSpace = NULL;
1341  Space* compareSpace = NULL;
1342  for (int i=0; i<comparators.size(); i++) {
1343  if (comparators[i].second) {
1344  if (curSpace == NULL) {
1345  curSpace = currentNode->getSpace(*na,curBest,c_d,a_d);
1346 
1347  if (!compareNodesBeforeFP || n->isRoot()) {
1348  compareSpace = n->getSpace(*na,curBest,c_d,a_d);
1349  } else {
1350  VisualNode* p = n->getParent(*na);
1351  compareSpace = p->getSpace(*na,curBest,c_d,a_d);
1352  switch (compareSpace->status()) {
1353  case SS_SOLVED:
1354  case SS_FAILED:
1355  break;
1356  case SS_BRANCH:
1357  compareSpace->commit(*p->getChoice(),
1358  n->getAlternative(*na));
1359  break;
1360  default:
1361  GECODE_NEVER;
1362  }
1363  }
1364  }
1365  try {
1366  comparators[i].first->compare(*curSpace,*compareSpace);
1367  } catch (Exception& e) {
1368  qFatal("Exception in comparator %d: %s.\n Stopping.",
1369  i, e.what());
1370  }
1371  }
1372  }
1373  }
1374  } else {
1375  setCurrentNode(n);
1376  }
1377  compareNodes = false;
1378  setCursor(QCursor(Qt::ArrowCursor));
1379  if (n != NULL) {
1380  event->accept();
1381  mutex.unlock();
1382  return;
1383  }
1384  }
1385  mutex.unlock();
1386  }
1387  event->ignore();
1388  }
1389 
1390  void
1391  TreeCanvas::setRecompDistances(int c_d0, int a_d0) {
1392  c_d = c_d0; a_d = a_d0;
1393  }
1394 
1395  void
1397  autoHideFailed = b;
1398  }
1399 
1400  void
1402  autoZoom = b;
1403  if (autoZoom) {
1404  zoomToFit();
1405  }
1406  emit autoZoomChanged(b);
1407  scaleBar->setEnabled(!b);
1408  }
1409 
1410  void
1412  showCopies = b;
1413  }
1414  bool
1416  return showCopies;
1417  }
1418 
1419  bool
1421  return autoHideFailed;
1422  }
1423 
1424  bool
1426  return autoZoom;
1427  }
1428 
1429  void
1431  refresh = i;
1432  }
1433 
1434  void
1436  refreshPause = i;
1437  if (refreshPause > 0)
1438  refresh = 1;
1439  }
1440 
1441  bool
1443  return smoothScrollAndZoom;
1444  }
1445 
1446  void
1449  }
1450 
1451  bool
1453  return moveDuringSearch;
1454  }
1455 
1456  void
1458  moveDuringSearch = b;
1459  }
1460 
1461 }}
1462 
1463 // 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:286
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:763
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:493
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
NodeStatus getStatus(void) const
Return current status of the node.
Definition: spacenode.hpp:75
void stopSearch(void)
Stop current search.
Definition: treecanvas.cpp:814
NodeType t
Type of node.
Definition: bool-expr.cpp:234
Space must be branched (at least one brancher left)
Definition: core.hpp:1610
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.
bool isRoot(void) const
Check if this node is the root of a tree.
Definition: node.hpp:215
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:622
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:483
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:848
int refresh
Refresh rate.
Definition: treecanvas.hh:304
void addMoveInspector(Inspector *i)
Add inspector i.
Definition: treecanvas.cpp:162
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:140
~TreeCanvas(void)
Destructor.
Definition: treecanvas.cpp:131
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:942
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:173
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:45
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
void zoomToFit(void)
Zoom the canvas so that the whole tree fits.
Definition: treecanvas.cpp:532
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:178
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:878
int targetScale
Target scale after layout.
Definition: treecanvas.hh:352
void navRoot(void)
Move selection to the root node.
Definition: treecanvas.cpp:993
int targetW
Target width after layout.
Definition: treecanvas.hh:348
VisualNode * n
The node.
Definition: treecanvas.cpp:357
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:474
void statusChanged(VisualNode *, const Statistics &, bool)
Status bar update.
unsigned int getNumberOfChildren(void) const
Return the number of children.
Definition: node.hpp:218
void toggleStop(const NodeAllocator &na)
Do not stop at this node.
Definition: visualnode.cpp:218
Computation spaces.
Definition: core.hpp:1668
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:363
Node that has not been explored yet.
Definition: spacenode.hh:52
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:892
bool finishedFlag
Flag signalling that Gist is ready to be closed.
Definition: treecanvas.hh:258
int i
The currently explored child.
Definition: treecanvas.cpp:359
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 p
Number of positive literals for node type.
Definition: bool-expr.cpp:236
bool getMoveDuringSearch(void)
Return preference whether to move cursor during search.
const FloatNum min
Smallest allowed float value.
Definition: float.hh:850
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:459
const Space * getWorkingSpace(void) const
Return working space (if present).
Definition: spacenode.hpp:116
Space * clone(CloneStatistics &stat=unused_clone) const
Clone space.
Definition: core.hpp:3144
VarImp * x
Pointer to variable implementation.
Definition: var.hpp:54
virtual const char * what(void) const
Return information.
Definition: exception.cpp:59
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:184
void commit(const Choice &c, unsigned int a, CommitStatistics &stat=unused_commit)
Commit choice c for alternative a.
Definition: core.hpp:3152
void labelPath(void)
Label all branches on path to root node.
Definition: treecanvas.cpp:771
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:751
void activateDoubleClickInspector(int i, bool active)
Set active inspector.
Definition: treecanvas.cpp:145
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:156
void setRefresh(int i)
Set refresh rate.
int a_d
The adaptive recomputation distance.
Definition: treecanvas.hh:315
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:924
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:929
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:502
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
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:758
void scroll(void)
React to scroll events.
Definition: treecanvas.cpp:258
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
struct Gecode::@585::NNF::@62::@63 b
For binary nodes (and, or, eqv)
int getParent(void) const
Return the parent.
Definition: node.hpp:186
bool smoothScrollAndZoom
Whether to use smooth scrolling and zooming.
Definition: treecanvas.hh:308
Post propagator for SetVar SetOpType SetVar y
Definition: set.hh:769
void scaleChanged(int)
The scale factor has changed.
Exception: Base-class for exceptions
Definition: exception.hpp:46
void print(void)
Print the tree.
bool getSmoothScrollAndZoom(void)
Return preference whether to use smooth scrolling and zooming.
struct Gecode::@585::NNF::@62::@64 a
For atomic nodes.
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:453
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:820
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:361
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
int getAlternative(const NodeAllocator &na) const
Return alternative number of this node.
Definition: spacenode.hpp:173
void addSolutionInspector(Inspector *i)
Add inspector i.
Definition: treecanvas.cpp:151
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:229
void startCompareNodes(void)
Wait for click on node to compare with current node.
Definition: treecanvas.cpp:908
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.
Post propagator for SetVar x
Definition: set.hh:769
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:568
bool autoZoom
Whether to zoom automatically.
Definition: treecanvas.hh:300
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:916
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:512
A stack item for depth first search.
Definition: treecanvas.cpp:354
void navRight(void)
Move selection to the right sibling of the selected node.
Definition: treecanvas.cpp:979
int getChild(int n) const
Return index of child no n.
Definition: node.hpp:199
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:965
bool hasCopy(void)
Return whether the node has a copy.
Definition: spacenode.hpp:163
Gecode toplevel namespace
void setAutoHideFailed(bool b)
Set preference whether to automatically hide failed subtrees.
int sourceY
Target y coordinate after smooth scrolling.
Definition: treecanvas.hh:345
Space * snapshot(Space *s, const Options &o)
Clone space s dependening on options o.
Definition: support.hh:75
void bookmarkNode(void)
Bookmark current node.
Definition: treecanvas.cpp:853
bool isOpen(void)
Return whether this node still has open children.
Definition: spacenode.hpp:142
Space is failed
Definition: core.hpp:1608
int targetH
Target height after layout.
Definition: treecanvas.hh:350
Options for Gist
Definition: gist.hh:238
QTimeLine zoomTimeLine
Timer for smooth zooming.
Definition: treecanvas.hh:335
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:167
void update(IntSet &y, Space &home, IntSet &py)
Definition: rel.hpp:107
void update(void)
Update display.
Definition: treecanvas.cpp:228
void toggleHidden(void)
Toggle hidden state of selected node.
Definition: treecanvas.cpp:465
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:263
void hideFailed(const NodeAllocator &na, bool onlyDirty=false)
Hide all failed subtrees of this node.
Definition: visualnode.cpp:163
int depth(void) const
Return depth of the shape.
Definition: visualnode.hpp:64
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:1609