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