treecanvas.cpp
Go to the documentation of this file.
/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
/*
* Main authors:
* Guido Tack <tack@gecode.org>
*
* Copyright:
* Guido Tack, 2006
*
* This file is part of Gecode, the generic constraint
* development environment:
* http://www.gecode.org
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
#include <QtGui/QPainter>
#include <QPrinter>
#include <QPrintDialog>
#include <stack>
#include <fstream>
#include <gecode/gist/treecanvas.hh>
#include <gecode/gist/nodevisitor.hh>
#include <gecode/gist/visualnode.hh>
#include <gecode/gist/drawingcursor.hh>
#include <gecode/search.hh>
#include <gecode/search/support.hh>
namespace Gecode { namespace Gist {
TreeCanvas::TreeCanvas(Space* rootSpace, bool bab,
QWidget* parent, const Options& opt)
: QWidget(parent)
, mutex(QMutex::Recursive)
, layoutMutex(QMutex::Recursive)
, finishedFlag(false)
, compareNodes(false), compareNodesBeforeFP(false)
, autoHideFailed(true), autoZoom(false)
, refresh(500), refreshPause(0), smoothScrollAndZoom(false)
, moveDuringSearch(false)
, zoomTimeLine(500)
, scrollTimeLine(1000), targetX(0), sourceX(0), targetY(0), sourceY(0)
, targetW(0), targetH(0), targetScale(0)
, layoutDoneTimerId(0) {
QMutexLocker locker(&mutex);
curBest = (bab ? new BestNode(NULL) : NULL);
if (rootSpace->status() == SS_FAILED) {
if (!opt.clone)
delete rootSpace;
rootSpace = NULL;
} else {
rootSpace = Gecode::Search::snapshot(rootSpace,opt);
}
na = new Node::NodeAllocator(bab);
int rootIdx = na->allocate(rootSpace);
assert(rootIdx == 0); (void) rootIdx;
root = (*na)[0];
root->layout(*na);
root->setMarked(true);
currentNode = root;
pathHead = root;
scale = LayoutConfig::defScale / 100.0;
setAutoFillBackground(true);
connect(&searcher, SIGNAL(update(int,int,int)), this,
SLOT(layoutDone(int,int,int)));
connect(&searcher, SIGNAL(statusChanged(bool)), this,
SLOT(statusChanged(bool)));
connect(&searcher, SIGNAL(solution(const Space*)),
this, SIGNAL(solution(const Space*)),
Qt::BlockingQueuedConnection);
connect(this, SIGNAL(solution(const Space*)),
this, SLOT(inspectSolution(const Space*)));
connect(&searcher, SIGNAL(moveToNode(VisualNode*,bool)),
this, SLOT(setCurrentNode(VisualNode*,bool)),
Qt::BlockingQueuedConnection);
connect(&searcher, SIGNAL(searchFinished(void)), this, SIGNAL(searchFinished(void)));
connect(&scrollTimeLine, SIGNAL(frameChanged(int)),
this, SLOT(scroll(int)));
scrollTimeLine.setCurveShape(QTimeLine::EaseInOutCurve);
scaleBar = new QSlider(Qt::Vertical, this);
scaleBar->setObjectName("scaleBar");
scaleBar->setMinimum(LayoutConfig::minScale);
scaleBar->setMaximum(LayoutConfig::maxScale);
scaleBar->setValue(LayoutConfig::defScale);
connect(scaleBar, SIGNAL(valueChanged(int)),
this, SLOT(scaleTree(int)));
connect(this, SIGNAL(scaleChanged(int)), scaleBar, SLOT(setValue(int)));
connect(&searcher, SIGNAL(scaleChanged(int)),
scaleBar, SLOT(setValue(int)));
connect(&zoomTimeLine, SIGNAL(frameChanged(int)),
scaleBar, SLOT(setValue(int)));
zoomTimeLine.setCurveShape(QTimeLine::EaseInOutCurve);
qRegisterMetaType<Statistics>("Statistics");
update();
}
TreeCanvas::~TreeCanvas(void) {
if (root) {
DisposeCursor dc(root,*na);
PreorderNodeVisitor<DisposeCursor>(dc).run();
}
delete na;
}
void
TreeCanvas::addDoubleClickInspector(Inspector* i) {
doubleClickInspectors.append(QPair<Inspector*,bool>(i,false));
}
void
TreeCanvas::activateDoubleClickInspector(int i, bool active) {
assert(i < doubleClickInspectors.size());
doubleClickInspectors[i].second = active;
}
void
TreeCanvas::addSolutionInspector(Inspector* i) {
solutionInspectors.append(QPair<Inspector*,bool>(i,false));
}
void
TreeCanvas::activateSolutionInspector(int i, bool active) {
assert(i < solutionInspectors.size());
solutionInspectors[i].second = active;
}
void
TreeCanvas::addMoveInspector(Inspector* i) {
moveInspectors.append(QPair<Inspector*,bool>(i,false));
}
void
TreeCanvas::activateMoveInspector(int i, bool active) {
assert(i < moveInspectors.size());
moveInspectors[i].second = active;
}
void
TreeCanvas::addComparator(Comparator* c) {
comparators.append(QPair<Comparator*,bool>(c,false));
}
void
TreeCanvas::activateComparator(int i, bool active) {
assert(i < comparators.size());
comparators[i].second = active;
}
void
TreeCanvas::scaleTree(int scale0, int zoomx, int zoomy) {
QMutexLocker locker(&layoutMutex);
QSize viewport_size = size();
QAbstractScrollArea* sa =
static_cast<QAbstractScrollArea*>(parentWidget()->parentWidget());
if (zoomx==-1)
zoomx = viewport_size.width()/2;
if (zoomy==-1)
zoomy = viewport_size.height()/2;
int xoff = (sa->horizontalScrollBar()->value()+zoomx)/scale;
int yoff = (sa->verticalScrollBar()->value()+zoomy)/scale;
BoundingBox bb;
scale0 = std::min(std::max(scale0, LayoutConfig::minScale),
LayoutConfig::maxScale);
scale = (static_cast<double>(scale0)) / 100.0;
bb = root->getBoundingBox();
int w =
static_cast<int>((bb.right-bb.left+Layout::extent)*scale);
int h =
static_cast<int>(2*Layout::extent+
root->getShape()->depth()*Layout::dist_y*scale);
sa->horizontalScrollBar()->setRange(0,w-viewport_size.width());
sa->verticalScrollBar()->setRange(0,h-viewport_size.height());
sa->horizontalScrollBar()->setPageStep(viewport_size.width());
sa->verticalScrollBar()->setPageStep(viewport_size.height());
sa->horizontalScrollBar()->setSingleStep(Layout::extent);
sa->verticalScrollBar()->setSingleStep(Layout::extent);
xoff *= scale;
yoff *= scale;
sa->horizontalScrollBar()->setValue(xoff-zoomx);
sa->verticalScrollBar()->setValue(yoff-zoomy);
emit scaleChanged(scale0);
QWidget::update();
}
void
TreeCanvas::update(void) {
QMutexLocker locker(&mutex);
layoutMutex.lock();
if (root != NULL) {
root->layout(*na);
BoundingBox bb = root->getBoundingBox();
int w = static_cast<int>((bb.right-bb.left+Layout::extent)*scale);
int h =
static_cast<int>(2*Layout::extent+
root->getShape()->depth()*Layout::dist_y*scale);
xtrans = -bb.left+(Layout::extent / 2);
QSize viewport_size = size();
QAbstractScrollArea* sa =
static_cast<QAbstractScrollArea*>(parentWidget()->parentWidget());
sa->horizontalScrollBar()->setRange(0,w-viewport_size.width());
sa->verticalScrollBar()->setRange(0,h-viewport_size.height());
sa->horizontalScrollBar()->setPageStep(viewport_size.width());
sa->verticalScrollBar()->setPageStep(viewport_size.height());
sa->horizontalScrollBar()->setSingleStep(Layout::extent);
sa->verticalScrollBar()->setSingleStep(Layout::extent);
}
if (autoZoom)
zoomToFit();
layoutMutex.unlock();
QWidget::update();
}
void
TreeCanvas::scroll(void) {
QWidget::update();
}
void
TreeCanvas::layoutDone(int w, int h, int scale0) {
targetW = w; targetH = h; targetScale = scale0;
QSize viewport_size = size();
QAbstractScrollArea* sa =
static_cast<QAbstractScrollArea*>(parentWidget()->parentWidget());
sa->horizontalScrollBar()->setRange(0,w-viewport_size.width());
sa->verticalScrollBar()->setRange(0,h-viewport_size.height());
if (layoutDoneTimerId == 0)
layoutDoneTimerId = startTimer(15);
}
void
TreeCanvas::statusChanged(bool finished) {
if (finished) {
update();
centerCurrentNode();
}
emit statusChanged(currentNode, stats, finished);
}
void
SearcherThread::search(VisualNode* n, bool all, TreeCanvas* ti) {
node = n;
depth = -1;
for (VisualNode* p = n; p != NULL; p = p->getParent(*ti->na))
depth++;
a = all;
t = ti;
start();
}
void
SearcherThread::updateCanvas(void) {
t->layoutMutex.lock();
if (t->root == NULL)
return;
if (t->autoHideFailed) {
t->root->hideFailed(*t->na,true);
}
for (VisualNode* n = t->currentNode; n != NULL; n=n->getParent(*t->na)) {
if (n->isHidden()) {
t->currentNode->setMarked(false);
t->currentNode = n;
t->currentNode->setMarked(true);
break;
}
}
t->root->layout(*t->na);
BoundingBox bb = t->root->getBoundingBox();
int w = static_cast<int>((bb.right-bb.left+Layout::extent)*t->scale);
int h = static_cast<int>(2*Layout::extent+
t->root->getShape()->depth()
*Layout::dist_y*t->scale);
t->xtrans = -bb.left+(Layout::extent / 2);
int scale0 = static_cast<int>(t->scale*100);
if (t->autoZoom) {
QWidget* p = t->parentWidget();
if (p) {
double newXScale =
static_cast<double>(p->width()) / (bb.right - bb.left +
Layout::extent);
double newYScale =
static_cast<double>(p->height()) /
(t->root->getShape()->depth() * Layout::dist_y + 2*Layout::extent);
scale0 = static_cast<int>(std::min(newXScale, newYScale)*100);
if (scale0<LayoutConfig::minScale)
scale0 = LayoutConfig::minScale;
if (scale0>LayoutConfig::maxAutoZoomScale)
scale0 = LayoutConfig::maxAutoZoomScale;
double scale = (static_cast<double>(scale0)) / 100.0;
w = static_cast<int>((bb.right-bb.left+Layout::extent)*scale);
h = static_cast<int>(2*Layout::extent+
t->root->getShape()->depth()*Layout::dist_y*scale);
}
}
t->layoutMutex.unlock();
emit update(w,h,scale0);
}
class SearchItem {
public:
VisualNode* n;
int i;
int noOfChildren;
SearchItem(VisualNode* n0, int noOfChildren0)
: n(n0), i(-1), noOfChildren(noOfChildren0) {}
};
void
SearcherThread::run(void) {
{
if (!node->isOpen())
return;
t->mutex.lock();
emit statusChanged(false);
unsigned int kids =
node->getNumberOfChildNodes(*t->na, t->curBest, t->stats,
t->c_d, t->a_d);
if (kids == 0 || node->getStatus() == STOP) {
t->mutex.unlock();
updateCanvas();
emit statusChanged(true);
return;
}
std::stack<SearchItem> stck;
stck.push(SearchItem(node,kids));
t->stats.maxDepth =
std::max(static_cast<long unsigned int>(t->stats.maxDepth),
static_cast<long unsigned int>(depth+stck.size()));
VisualNode* sol = NULL;
int nodeCount = 0;
t->stopSearchFlag = false;
while (!stck.empty() && !t->stopSearchFlag) {
if (t->refresh > 0 && nodeCount >= t->refresh) {
node->dirtyUp(*t->na);
updateCanvas();
emit statusChanged(false);
nodeCount = 0;
if (t->refreshPause > 0)
msleep(t->refreshPause);
}
SearchItem& si = stck.top();
si.i++;
if (si.i == si.noOfChildren) {
stck.pop();
} else {
VisualNode* n = si.n->getChild(*t->na,si.i);
if (n->isOpen()) {
if (n->getStatus() == UNDETERMINED)
nodeCount++;
kids = n->getNumberOfChildNodes(*t->na, t->curBest, t->stats,
t->c_d, t->a_d);
if (t->moveDuringSearch)
emit moveToNode(n,false);
if (kids == 0) {
if (n->getStatus() == SOLVED) {
assert(n->hasCopy());
emit solution(n->getWorkingSpace());
n->purge(*t->na);
sol = n;
if (!a)
break;
}
} else {
if ( n->getStatus() != STOP )
stck.push(SearchItem(n,kids));
else if (!a)
break;
t->stats.maxDepth =
std::max(static_cast<long unsigned int>(t->stats.maxDepth),
static_cast<long unsigned int>(depth+stck.size()));
}
}
}
}
node->dirtyUp(*t->na);
t->stopSearchFlag = false;
t->mutex.unlock();
if (sol != NULL) {
t->setCurrentNode(sol,true,false);
} else {
t->setCurrentNode(node,true,false);
}
}
updateCanvas();
emit statusChanged(true);
if (t->finishedFlag)
emit searchFinished();
}
void
TreeCanvas::searchAll(void) {
QMutexLocker locker(&mutex);
searcher.search(currentNode, true, this);
}
void
TreeCanvas::searchOne(void) {
QMutexLocker locker(&mutex);
searcher.search(currentNode, false, this);
}
void
TreeCanvas::toggleHidden(void) {
QMutexLocker locker(&mutex);
currentNode->toggleHidden(*na);
update();
centerCurrentNode();
emit statusChanged(currentNode, stats, true);
}
void
TreeCanvas::hideFailed(void) {
QMutexLocker locker(&mutex);
currentNode->hideFailed(*na);
update();
centerCurrentNode();
emit statusChanged(currentNode, stats, true);
}
void
TreeCanvas::unhideAll(void) {
QMutexLocker locker(&mutex);
QMutexLocker layoutLocker(&layoutMutex);
currentNode->unhideAll(*na);
update();
centerCurrentNode();
emit statusChanged(currentNode, stats, true);
}
void
TreeCanvas::toggleStop(void) {
QMutexLocker locker(&mutex);
currentNode->toggleStop(*na);
update();
centerCurrentNode();
emit statusChanged(currentNode, stats, true);
}
void
TreeCanvas::unstopAll(void) {
QMutexLocker locker(&mutex);
QMutexLocker layoutLocker(&layoutMutex);
currentNode->unstopAll(*na);
update();
centerCurrentNode();
emit statusChanged(currentNode, stats, true);
}
void
TreeCanvas::timerEvent(QTimerEvent* e) {
if (e->timerId() == layoutDoneTimerId) {
if (!smoothScrollAndZoom) {
scaleTree(targetScale);
} else {
zoomTimeLine.stop();
int zoomCurrent = static_cast<int>(scale*100);
int targetZoom = targetScale;
targetZoom = std::min(std::max(targetZoom, LayoutConfig::minScale),
LayoutConfig::maxAutoZoomScale);
zoomTimeLine.setFrameRange(zoomCurrent,targetZoom);
zoomTimeLine.start();
}
QWidget::update();
killTimer(layoutDoneTimerId);
layoutDoneTimerId = 0;
}
}
void
TreeCanvas::zoomToFit(void) {
QMutexLocker locker(&layoutMutex);
if (root != NULL) {
BoundingBox bb;
bb = root->getBoundingBox();
QWidget* p = parentWidget();
if (p) {
double newXScale =
static_cast<double>(p->width()) / (bb.right - bb.left +
Layout::extent);
double newYScale =
static_cast<double>(p->height()) / (root->getShape()->depth() *
Layout::dist_y +
2*Layout::extent);
int scale0 = static_cast<int>(std::min(newXScale, newYScale)*100);
if (scale0<LayoutConfig::minScale)
scale0 = LayoutConfig::minScale;
if (scale0>LayoutConfig::maxAutoZoomScale)
scale0 = LayoutConfig::maxAutoZoomScale;
if (!smoothScrollAndZoom) {
scaleTree(scale0);
} else {
zoomTimeLine.stop();
int zoomCurrent = static_cast<int>(scale*100);
int targetZoom = scale0;
targetZoom = std::min(std::max(targetZoom, LayoutConfig::minScale),
LayoutConfig::maxAutoZoomScale);
zoomTimeLine.setFrameRange(zoomCurrent,targetZoom);
zoomTimeLine.start();
}
}
}
}
void
TreeCanvas::centerCurrentNode(void) {
QMutexLocker locker(&mutex);
int x=0;
int y=0;
VisualNode* c = currentNode;
while (c != NULL) {
x += c->getOffset();
y += Layout::dist_y;
c = c->getParent(*na);
}
x = static_cast<int>((xtrans+x)*scale); y = static_cast<int>(y*scale);
QAbstractScrollArea* sa =
static_cast<QAbstractScrollArea*>(parentWidget()->parentWidget());
x -= sa->viewport()->width() / 2;
y -= sa->viewport()->height() / 2;
sourceX = sa->horizontalScrollBar()->value();
targetX = std::max(sa->horizontalScrollBar()->minimum(), x);
targetX = std::min(sa->horizontalScrollBar()->maximum(),
targetX);
sourceY = sa->verticalScrollBar()->value();
targetY = std::max(sa->verticalScrollBar()->minimum(), y);
targetY = std::min(sa->verticalScrollBar()->maximum(),
targetY);
if (!smoothScrollAndZoom) {
sa->horizontalScrollBar()->setValue(targetX);
sa->verticalScrollBar()->setValue(targetY);
} else {
scrollTimeLine.stop();
scrollTimeLine.setFrameRange(0,100);
scrollTimeLine.setDuration(std::max(200,
std::min(1000,
std::min(std::abs(sourceX-targetX),
std::abs(sourceY-targetY)))));
scrollTimeLine.start();
}
}
void
TreeCanvas::scroll(int i) {
QAbstractScrollArea* sa =
static_cast<QAbstractScrollArea*>(parentWidget()->parentWidget());
double p = static_cast<double>(i)/100.0;
double xdiff = static_cast<double>(targetX-sourceX)*p;
double ydiff = static_cast<double>(targetY-sourceY)*p;
sa->horizontalScrollBar()->setValue(sourceX+static_cast<int>(xdiff));
sa->verticalScrollBar()->setValue(sourceY+static_cast<int>(ydiff));
}
void
TreeCanvas::inspectCurrentNode(bool fix, int inspectorNo) {
QMutexLocker locker(&mutex);
if (currentNode->isHidden()) {
toggleHidden();
return;
}
int failedInspectorType = -1;
int failedInspector = -1;
bool needCentering = false;
try {
switch (currentNode->getStatus()) {
case UNDETERMINED:
{
unsigned int kids =
currentNode->getNumberOfChildNodes(*na,curBest,stats,c_d,a_d);
int depth = -1;
for (VisualNode* p = currentNode; p != NULL; p=p->getParent(*na))
depth++;
if (kids > 0) {
needCentering = true;
depth++;
}
stats.maxDepth =
std::max(stats.maxDepth, depth);
if (currentNode->getStatus() == SOLVED) {
assert(currentNode->hasCopy());
emit solution(currentNode->getWorkingSpace());
}
emit statusChanged(currentNode,stats,true);
for (int i=0; i<moveInspectors.size(); i++) {
if (moveInspectors[i].second) {
failedInspectorType = 0;
failedInspector = i;
if (currentNode->getStatus() == FAILED) {
if (!currentNode->isRoot()) {
Space* curSpace =
currentNode->getSpace(*na,curBest,c_d,a_d);
moveInspectors[i].first->inspect(*curSpace);
delete curSpace;
}
} else {
moveInspectors[i].first->
inspect(*currentNode->getWorkingSpace());
}
failedInspectorType = -1;
}
}
if (currentNode->getStatus() == SOLVED) {
currentNode->purge(*na);
}
}
break;
case FAILED:
case STOP:
case UNSTOP:
case BRANCH:
case SOLVED:
{
Space* curSpace;
if (fix) {
if (currentNode->isRoot() && currentNode->getStatus() == FAILED)
break;
curSpace = currentNode->getSpace(*na,curBest,c_d,a_d);
if (currentNode->getStatus() == SOLVED &&
curSpace->status() != SS_SOLVED) {
// in the presence of weakly monotonic propagators, we may have
// to use search to find the solution here
assert(curSpace->status() == SS_BRANCH &&
"Something went wrong - probably an incorrect brancher");
Space* dfsSpace = Gecode::dfs(curSpace);
delete curSpace;
curSpace = dfsSpace;
}
} else {
if (currentNode->isRoot())
break;
VisualNode* p = currentNode->getParent(*na);
curSpace = p->getSpace(*na,curBest,c_d,a_d);
switch (curSpace->status()) {
case SS_SOLVED:
case SS_FAILED:
break;
case SS_BRANCH:
curSpace->commit(*p->getChoice(),
currentNode->getAlternative(*na));
break;
default:
GECODE_NEVER;
}
}
if (inspectorNo==-1) {
for (int i=0; i<doubleClickInspectors.size(); i++) {
if (doubleClickInspectors[i].second) {
failedInspectorType = 1;
failedInspector = i;
doubleClickInspectors[i].first->inspect(*curSpace);
failedInspectorType = -1;
}
}
} else {
failedInspectorType = 1;
failedInspector = inspectorNo;
doubleClickInspectors[inspectorNo].first->inspect(*curSpace);
failedInspectorType = -1;
}
delete curSpace;
}
break;
}
} catch (Exception& e) {
switch (failedInspectorType) {
case 0:
qFatal("Exception in move inspector %d: %s.\n Stopping.",
failedInspector, e.what());
break;
case 1:
qFatal("Exception in double click inspector %d: %s.\n Stopping.",
failedInspector, e.what());
break;
default:
qFatal("Exception: %s.\n Stopping.", e.what());
break;
}
}
currentNode->dirtyUp(*na);
update();
if (needCentering)
centerCurrentNode();
}
void
TreeCanvas::inspectBeforeFP(void) {
inspectCurrentNode(false);
}
void
TreeCanvas::labelBranches(void) {
QMutexLocker locker(&mutex);
currentNode->labelBranches(*na,curBest,c_d,a_d);
update();
centerCurrentNode();
emit statusChanged(currentNode, stats, true);
}
void
TreeCanvas::labelPath(void) {
QMutexLocker locker(&mutex);
currentNode->labelPath(*na,curBest,c_d,a_d);
update();
centerCurrentNode();
emit statusChanged(currentNode, stats, true);
}
void
TreeCanvas::inspectSolution(const Space* s) {
int failedInspectorType = -1;
int failedInspector = -1;
try {
Space* c = NULL;
for (int i=0; i<solutionInspectors.size(); i++) {
if (solutionInspectors[i].second) {
if (c == NULL)
c = s->clone();
failedInspectorType = 1;
failedInspector = i;
solutionInspectors[i].first->inspect(*c);
failedInspectorType = -1;
}
}
delete c;
} catch (Exception& e) {
switch (failedInspectorType) {
case 0:
qFatal("Exception in move inspector %d: %s.\n Stopping.",
failedInspector, e.what());
break;
case 1:
qFatal("Exception in solution inspector %d: %s.\n Stopping.",
failedInspector, e.what());
break;
default:
qFatal("Exception: %s.\n Stopping.", e.what());
break;
}
}
}
void
TreeCanvas::stopSearch(void) {
stopSearchFlag = true;
layoutDoneTimerId = startTimer(15);
}
void
TreeCanvas::reset(void) {
QMutexLocker locker(&mutex);
Space* rootSpace =
root->getStatus() == FAILED ? NULL :
root->getSpace(*na,curBest,c_d,a_d);
if (curBest != NULL) {
delete curBest;
curBest = new BestNode(NULL);
}
if (root) {
DisposeCursor dc(root,*na);
PreorderNodeVisitor<DisposeCursor>(dc).run();
}
delete na;
na = new Node::NodeAllocator(curBest != NULL);
int rootIdx = na->allocate(rootSpace);
assert(rootIdx == 0); (void) rootIdx;
root = (*na)[0];
root->setMarked(true);
currentNode = root;
pathHead = root;
scale = 1.0;
stats = Statistics();
for (int i=bookmarks.size(); i--;)
emit removedBookmark(i);
bookmarks.clear();
root->layout(*na);
emit statusChanged(currentNode, stats, true);
update();
}
void
TreeCanvas::bookmarkNode(void) {
QMutexLocker locker(&mutex);
if (!currentNode->isBookmarked()) {
bool ok;
QString text =
QInputDialog::getText(this, "Add bookmark", "Name:",
QLineEdit::Normal,"",&ok);
if (ok) {
currentNode->setBookmarked(true);
bookmarks.append(currentNode);
if (text == "")
text = QString("Node ")+QString().setNum(bookmarks.size());
emit addedBookmark(text);
}
} else {
currentNode->setBookmarked(false);
int idx = bookmarks.indexOf(currentNode);
bookmarks.remove(idx);
emit removedBookmark(idx);
}
currentNode->dirtyUp(*na);
update();
}
void
TreeCanvas::setPath(void) {
QMutexLocker locker(&mutex);
if(currentNode == pathHead)
return;
pathHead->unPathUp(*na);
pathHead = currentNode;
currentNode->pathUp(*na);
currentNode->dirtyUp(*na);
update();
}
void
TreeCanvas::inspectPath(void) {
QMutexLocker locker(&mutex);
setCurrentNode(root);
if (currentNode->isOnPath()) {
inspectCurrentNode();
int nextAlt = currentNode->getPathAlternative(*na);
while (nextAlt >= 0) {
setCurrentNode(currentNode->getChild(*na,nextAlt));
inspectCurrentNode();
nextAlt = currentNode->getPathAlternative(*na);
}
}
update();
}
void
TreeCanvas::startCompareNodes(void) {
QMutexLocker locker(&mutex);
compareNodes = true;
compareNodesBeforeFP = false;
setCursor(QCursor(Qt::CrossCursor));
}
void
TreeCanvas::startCompareNodesBeforeFP(void) {
QMutexLocker locker(&mutex);
compareNodes = true;
compareNodesBeforeFP = true;
setCursor(QCursor(Qt::CrossCursor));
}
void
TreeCanvas::emitStatusChanged(void) {
emit statusChanged(currentNode, stats, true);
}
void
TreeCanvas::navUp(void) {
QMutexLocker locker(&mutex);
VisualNode* p = currentNode->getParent(*na);
setCurrentNode(p);
if (p != NULL) {
centerCurrentNode();
}
}
void
TreeCanvas::navDown(void) {
QMutexLocker locker(&mutex);
if (!currentNode->isHidden()) {
switch (currentNode->getStatus()) {
case STOP:
case UNSTOP:
case BRANCH:
{
int alt = std::max(0, currentNode->getPathAlternative(*na));
VisualNode* n = currentNode->getChild(*na,alt);
setCurrentNode(n);
centerCurrentNode();
break;
}
case SOLVED:
case FAILED:
case UNDETERMINED:
break;
}
}
}
void
TreeCanvas::navLeft(void) {
QMutexLocker locker(&mutex);
VisualNode* p = currentNode->getParent(*na);
if (p != NULL) {
int alt = currentNode->getAlternative(*na);
if (alt > 0) {
VisualNode* n = p->getChild(*na,alt-1);
setCurrentNode(n);
centerCurrentNode();
}
}
}
void
TreeCanvas::navRight(void) {
QMutexLocker locker(&mutex);
VisualNode* p = currentNode->getParent(*na);
if (p != NULL) {
unsigned int alt = currentNode->getAlternative(*na);
if (alt + 1 < p->getNumberOfChildren()) {
VisualNode* n = p->getChild(*na,alt+1);
setCurrentNode(n);
centerCurrentNode();
}
}
}
void
TreeCanvas::navRoot(void) {
QMutexLocker locker(&mutex);
setCurrentNode(root);
centerCurrentNode();
}
void
TreeCanvas::navNextSol(bool back) {
QMutexLocker locker(&mutex);
NextSolCursor nsc(currentNode,back,*na);
PreorderNodeVisitor<NextSolCursor> nsv(nsc);
nsv.run();
VisualNode* n = nsv.getCursor().node();
if (n != root) {
setCurrentNode(n);
centerCurrentNode();
}
}
void
TreeCanvas::navPrevSol(void) {
navNextSol(true);
}
void
TreeCanvas::exportNodePDF(VisualNode* n) {
#if QT_VERSION >= 0x040400
QString filename = QFileDialog::getSaveFileName(this, tr("Export tree as pdf"), "", tr("PDF (*.pdf)"));
if (filename != "") {
QPrinter printer(QPrinter::ScreenResolution);
QMutexLocker locker(&mutex);
BoundingBox bb = n->getBoundingBox();
printer.setFullPage(true);
printer.setPaperSize(QSizeF(bb.right-bb.left+Layout::extent,
n->getShape()->depth() * Layout::dist_y +
Layout::extent), QPrinter::Point);
printer.setOutputFileName(filename);
QPainter painter(&printer);
painter.setRenderHint(QPainter::Antialiasing);
QRect pageRect = printer.pageRect();
double newXScale =
static_cast<double>(pageRect.width()) / (bb.right - bb.left +
Layout::extent);
double newYScale =
static_cast<double>(pageRect.height()) /
(n->getShape()->depth() * Layout::dist_y +
Layout::extent);
double printScale = std::min(newXScale, newYScale);
painter.scale(printScale,printScale);
int printxtrans = -bb.left+(Layout::extent / 2);
painter.translate(printxtrans, Layout::dist_y / 2);
QRect clip(0,0,0,0);
DrawingCursor dc(n, *na, curBest, painter, clip, showCopies);
currentNode->setMarked(false);
PreorderNodeVisitor<DrawingCursor>(dc).run();
currentNode->setMarked(true);
}
#else
(void) n;
#endif
}
void
TreeCanvas::exportWholeTreePDF(void) {
#if QT_VERSION >= 0x040400
exportNodePDF(root);
#endif
}
void
TreeCanvas::exportPDF(void) {
#if QT_VERSION >= 0x040400
exportNodePDF(currentNode);
#endif
}
void
TreeCanvas::print(void) {
QPrinter printer;
if (QPrintDialog(&printer, this).exec() == QDialog::Accepted) {
QMutexLocker locker(&mutex);
BoundingBox bb = root->getBoundingBox();
QRect pageRect = printer.pageRect();
double newXScale =
static_cast<double>(pageRect.width()) / (bb.right - bb.left +
Layout::extent);
double newYScale =
static_cast<double>(pageRect.height()) /
(root->getShape()->depth() * Layout::dist_y +
2*Layout::extent);
double printScale = std::min(newXScale, newYScale)*100;
if (printScale<1.0)
printScale = 1.0;
if (printScale > 400.0)
printScale = 400.0;
printScale = printScale / 100.0;
QPainter painter(&printer);
painter.setRenderHint(QPainter::Antialiasing);
painter.scale(printScale,printScale);
painter.translate(xtrans, 0);
QRect clip(0,0,0,0);
DrawingCursor dc(root, *na, curBest, painter, clip, showCopies);
PreorderNodeVisitor<DrawingCursor>(dc).run();
}
}
VisualNode*
TreeCanvas::eventNode(QEvent* event) {
int x = 0;
int y = 0;
switch (event->type()) {
case QEvent::ToolTip:
{
QHelpEvent* he = static_cast<QHelpEvent*>(event);
x = he->x();
y = he->y();
break;
}
case QEvent::MouseButtonDblClick:
case QEvent::MouseButtonPress:
case QEvent::MouseButtonRelease:
case QEvent::MouseMove:
{
QMouseEvent* me = static_cast<QMouseEvent*>(event);
x = me->x();
y = me->y();
break;
}
case QEvent::ContextMenu:
{
QContextMenuEvent* ce = static_cast<QContextMenuEvent*>(event);
x = ce->x();
y = ce->y();
break;
}
default:
return NULL;
}
QAbstractScrollArea* sa =
static_cast<QAbstractScrollArea*>(parentWidget()->parentWidget());
int xoff = sa->horizontalScrollBar()->value()/scale;
int yoff = sa->verticalScrollBar()->value()/scale;
BoundingBox bb = root->getBoundingBox();
int w =
static_cast<int>((bb.right-bb.left+Layout::extent)*scale);
if (w < sa->viewport()->width())
xoff -= (sa->viewport()->width()-w)/2;
VisualNode* n;
n = root->findNode(*na,
static_cast<int>(x/scale-xtrans+xoff),
static_cast<int>((y-30)/scale+yoff));
return n;
}
bool
TreeCanvas::event(QEvent* event) {
if (mutex.tryLock()) {
if (event->type() == QEvent::ToolTip) {
VisualNode* n = eventNode(event);
if (n != NULL) {
QHelpEvent* he = static_cast<QHelpEvent*>(event);
QToolTip::showText(he->globalPos(),
QString(n->toolTip(*na,curBest,
c_d,a_d).c_str()));
} else {
QToolTip::hideText();
}
}
mutex.unlock();
}
return QWidget::event(event);
}
void
TreeCanvas::resizeToOuter(void) {
if (autoZoom)
zoomToFit();
}
void
TreeCanvas::paintEvent(QPaintEvent* event) {
QMutexLocker locker(&layoutMutex);
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);
QAbstractScrollArea* sa =
static_cast<QAbstractScrollArea*>(parentWidget()->parentWidget());
int xoff = sa->horizontalScrollBar()->value()/scale;
int yoff = sa->verticalScrollBar()->value()/scale;
BoundingBox bb = root->getBoundingBox();
int w =
static_cast<int>((bb.right-bb.left+Layout::extent)*scale);
if (w < sa->viewport()->width())
xoff -= (sa->viewport()->width()-w)/2;
QRect origClip = event->rect();
painter.translate(0, 30);
painter.scale(scale,scale);
painter.translate(xtrans-xoff, -yoff);
QRect clip(static_cast<int>(origClip.x()/scale-xtrans+xoff),
static_cast<int>(origClip.y()/scale+yoff),
static_cast<int>(origClip.width()/scale),
static_cast<int>(origClip.height()/scale));
DrawingCursor dc(root, *na, curBest, painter, clip, showCopies);
PreorderNodeVisitor<DrawingCursor>(dc).run();
// int nodesLayouted = 1;
// clock_t t0 = clock();
// while (v.next()) { nodesLayouted++; }
// double t = (static_cast<double>(clock()-t0) / CLOCKS_PER_SEC) * 1000.0;
// double nps = static_cast<double>(nodesLayouted) /
// (static_cast<double>(clock()-t0) / CLOCKS_PER_SEC);
// std::cout << "Drawing done. " << nodesLayouted << " nodes in "
// << t << " ms. " << nps << " nodes/s." << std::endl;
}
void
TreeCanvas::mouseDoubleClickEvent(QMouseEvent* event) {
if (mutex.tryLock()) {
if(event->button() == Qt::LeftButton) {
VisualNode* n = eventNode(event);
if(n == currentNode) {
inspectCurrentNode();
event->accept();
mutex.unlock();
return;
}
}
mutex.unlock();
}
event->ignore();
}
void
TreeCanvas::contextMenuEvent(QContextMenuEvent* event) {
if (mutex.tryLock()) {
VisualNode* n = eventNode(event);
if (n != NULL) {
setCurrentNode(n);
emit contextMenu(event);
event->accept();
mutex.unlock();
return;
}
mutex.unlock();
}
event->ignore();
}
void
TreeCanvas::resizeEvent(QResizeEvent* e) {
QAbstractScrollArea* sa =
static_cast<QAbstractScrollArea*>(parentWidget()->parentWidget());
int w = sa->horizontalScrollBar()->maximum()+e->oldSize().width();
int h = sa->verticalScrollBar()->maximum()+e->oldSize().height();
sa->horizontalScrollBar()->setRange(0,w-e->size().width());
sa->verticalScrollBar()->setRange(0,h-e->size().height());
sa->horizontalScrollBar()->setPageStep(e->size().width());
sa->verticalScrollBar()->setPageStep(e->size().height());
}
void
TreeCanvas::wheelEvent(QWheelEvent* event) {
if (event->modifiers() & Qt::ShiftModifier) {
event->accept();
if (event->orientation() == Qt::Vertical && !autoZoom)
scaleTree(scale*100+ceil(static_cast<double>(event->delta())/4.0),
event->x(), event->y());
} else {
event->ignore();
}
}
bool
TreeCanvas::finish(void) {
if (finishedFlag)
return true;
stopSearchFlag = true;
finishedFlag = true;
for (int i=0; i<doubleClickInspectors.size(); i++)
doubleClickInspectors[i].first->finalize();
for (int i=0; i<solutionInspectors.size(); i++)
solutionInspectors[i].first->finalize();
for (int i=0; i<moveInspectors.size(); i++)
moveInspectors[i].first->finalize();
for (int i=0; i<comparators.size(); i++)
comparators[i].first->finalize();
return !searcher.isRunning();
}
void
TreeCanvas::setCurrentNode(VisualNode* n, bool finished, bool update) {
if (finished)
mutex.lock();
if (update && n != NULL && n != currentNode &&
n->getStatus() != UNDETERMINED && !n->isHidden()) {
Space* curSpace = NULL;
for (int i=0; i<moveInspectors.size(); i++) {
if (moveInspectors[i].second) {
if (curSpace == NULL)
curSpace = n->getSpace(*na,curBest,c_d,a_d);
try {
moveInspectors[i].first->inspect(*curSpace);
} catch (Exception& e) {
qFatal("Exception in move inspector %d: %s.\n Stopping.",
i, e.what());
}
}
}
}
if (n != NULL) {
currentNode->setMarked(false);
currentNode = n;
currentNode->setMarked(true);
emit statusChanged(currentNode,stats,finished);
if (update) {
compareNodes = false;
setCursor(QCursor(Qt::ArrowCursor));
QWidget::update();
}
}
if (finished)
mutex.unlock();
}
void
TreeCanvas::mousePressEvent(QMouseEvent* event) {
if (mutex.tryLock()) {
if (event->button() == Qt::LeftButton) {
VisualNode* n = eventNode(event);
if (compareNodes) {
if (n != NULL && n->getStatus() != UNDETERMINED &&
currentNode != NULL &&
currentNode->getStatus() != UNDETERMINED) {
Space* curSpace = NULL;
Space* compareSpace = NULL;
for (int i=0; i<comparators.size(); i++) {
if (comparators[i].second) {
if (curSpace == NULL) {
curSpace = currentNode->getSpace(*na,curBest,c_d,a_d);
if (!compareNodesBeforeFP || n->isRoot()) {
compareSpace = n->getSpace(*na,curBest,c_d,a_d);
} else {
VisualNode* p = n->getParent(*na);
compareSpace = p->getSpace(*na,curBest,c_d,a_d);
switch (compareSpace->status()) {
case SS_SOLVED:
case SS_FAILED:
break;
case SS_BRANCH:
compareSpace->commit(*p->getChoice(),
n->getAlternative(*na));
break;
default:
GECODE_NEVER;
}
}
}
try {
comparators[i].first->compare(*curSpace,*compareSpace);
} catch (Exception& e) {
qFatal("Exception in comparator %d: %s.\n Stopping.",
i, e.what());
}
}
}
}
} else {
setCurrentNode(n);
}
compareNodes = false;
setCursor(QCursor(Qt::ArrowCursor));
if (n != NULL) {
event->accept();
mutex.unlock();
return;
}
}
mutex.unlock();
}
event->ignore();
}
void
TreeCanvas::setRecompDistances(int c_d0, int a_d0) {
c_d = c_d0; a_d = a_d0;
}
void
TreeCanvas::setAutoHideFailed(bool b) {
autoHideFailed = b;
}
void
TreeCanvas::setAutoZoom(bool b) {
autoZoom = b;
if (autoZoom) {
zoomToFit();
}
emit autoZoomChanged(b);
scaleBar->setEnabled(!b);
}
void
TreeCanvas::setShowCopies(bool b) {
showCopies = b;
}
bool
TreeCanvas::getShowCopies(void) {
return showCopies;
}
bool
TreeCanvas::getAutoHideFailed(void) {
return autoHideFailed;
}
bool
TreeCanvas::getAutoZoom(void) {
return autoZoom;
}
void
TreeCanvas::setRefresh(int i) {
refresh = i;
}
void
TreeCanvas::setRefreshPause(int i) {
refreshPause = i;
if (refreshPause > 0)
refresh = 1;
}
bool
TreeCanvas::getSmoothScrollAndZoom(void) {
return smoothScrollAndZoom;
}
void
TreeCanvas::setSmoothScrollAndZoom(bool b) {
smoothScrollAndZoom = b;
}
bool
TreeCanvas::getMoveDuringSearch(void) {
return moveDuringSearch;
}
void
TreeCanvas::setMoveDuringSearch(bool b) {
moveDuringSearch = b;
}
}}
// STATISTICS: gist-any
Gecode::ArgArrayBase::size
int size(void) const
Return size of array (number of elements).
Definition array.hpp:1607
Gecode::Exception
Exception: Base-class for exceptions
Definition exception.hpp:42
Gecode::Exception::what
virtual const char * what(void) const
Return information.
Definition exception.cpp:55
Gecode::Gist::BestNode
Static reference to the currently best space.
Definition spacenode.hh:80
Gecode::Gist::BoundingBox
Bounding box.
Definition visualnode.hh:52
Gecode::Gist::BoundingBox::right
int right
Right coordinate.
Definition visualnode.hh:57
Gecode::Gist::BoundingBox::left
int left
Left coordinate.
Definition visualnode.hh:55
Gecode::Gist::Comparator
Abstract base class for comparators.
Definition gist.hh:119
Gecode::Gist::DisposeCursor
A cursor that frees all memory.
Definition nodecursor.hh:215
Gecode::Gist::DrawingCursor
A cursor that draws a tree on a QWidget.
Definition drawingcursor.hh:44
Gecode::Gist::Inspector
Abstract base class for inspectors.
Definition gist.hh:99
Gecode::Gist::Layout::dist_y
static const int dist_y
Definition visualnode.hh:46
Gecode::Gist::Layout::extent
static const int extent
Definition visualnode.hh:47
Gecode::Gist::NextSolCursor
A cursor that finds the next solution.
Definition nodecursor.hh:130
Gecode::Gist::NodeVisitor::getCursor
Cursor & getCursor(void)
Return the cursor.
Definition nodevisitor.hpp:46
Gecode::Gist::Node::NodeAllocator
NodeAllocatorBase< VisualNode > NodeAllocator
Definition node.hh:143
Gecode::Gist::Node::getNumberOfChildren
unsigned int getNumberOfChildren(void) const
Return the number of children.
Definition node.hpp:214
Gecode::Gist::Node::getParent
int getParent(void) const
Return the parent.
Definition node.hpp:182
Gecode::Gist::Node::getChild
int getChild(int n) const
Return index of child no n.
Definition node.hpp:195
Gecode::Gist::Node::isRoot
bool isRoot(void) const
Check if this node is the root of a tree.
Definition node.hpp:211
Gecode::Gist::Options
Options for Gist
Definition gist.hh:234
Gecode::Gist::PreorderNodeVisitor
Run a cursor over a tree, processing nodes in pre-order.
Definition nodevisitor.hh:72
Gecode::Gist::PreorderNodeVisitor::run
void run(void)
Execute visitor.
Definition nodevisitor.hpp:117
Gecode::Gist::SearchItem
A stack item for depth first search.
Definition treecanvas.cpp:350
Gecode::Gist::SearchItem::n
VisualNode * n
The node.
Definition treecanvas.cpp:353
Gecode::Gist::SearchItem::noOfChildren
int noOfChildren
The number of children.
Definition treecanvas.cpp:357
Gecode::Gist::SearchItem::SearchItem
SearchItem(VisualNode *n0, int noOfChildren0)
Constructor.
Definition treecanvas.cpp:359
Gecode::Gist::SearchItem::i
int i
The currently explored child.
Definition treecanvas.cpp:355
Gecode::Gist::SearcherThread::statusChanged
void statusChanged(bool)
Gecode::Gist::SearcherThread::update
void update(int w, int h, int scale0)
Gecode::Gist::SearcherThread::solution
void solution(const Space *)
Gecode::Gist::SearcherThread::searchFinished
void searchFinished(void)
Gecode::Gist::SearcherThread::search
void search(VisualNode *n, bool all, TreeCanvas *ti)
Definition treecanvas.cpp:282
Gecode::Gist::SearcherThread::run
void run(void)
Definition treecanvas.cpp:364
Gecode::Gist::SearcherThread::moveToNode
void moveToNode(VisualNode *n, bool)
Gecode::Gist::Shape::depth
int depth(void) const
Return depth of the shape.
Definition visualnode.hpp:60
Gecode::Gist::SpaceNode::hasCopy
bool hasCopy(void)
Return whether the node has a copy.
Definition spacenode.hpp:159
Gecode::Gist::SpaceNode::getChoice
const Choice * getChoice(void)
Return choice of this node.
Definition spacenode.hpp:181
Gecode::Gist::SpaceNode::getWorkingSpace
const Space * getWorkingSpace(void) const
Return working space (if present).
Definition spacenode.hpp:112
Gecode::Gist::SpaceNode::getNumberOfChildNodes
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
Gecode::Gist::SpaceNode::getAlternative
int getAlternative(const NodeAllocator &na) const
Return alternative number of this node.
Definition spacenode.hpp:169
Gecode::Gist::SpaceNode::isOpen
bool isOpen(void)
Return whether this node still has open children.
Definition spacenode.hpp:138
Gecode::Gist::SpaceNode::getStatus
NodeStatus getStatus(void) const
Return current status of the node.
Definition spacenode.hpp:71
Gecode::Gist::SpaceNode::getSpace
Space * getSpace(NodeAllocator &na, BestNode *curBest, int c_d, int a_d)
Return working space. Receiver must delete the space.
Definition spacenode.hpp:98
Gecode::Gist::SpaceNode::purge
void purge(const NodeAllocator &na)
Clear working space and copy (if present and this is not the root).
Definition spacenode.hpp:120
Gecode::Gist::Statistics
Statistics about the search tree
Definition spacenode.hh:59
Gecode::Gist::TreeCanvas
A canvas that displays the search tree.
Definition treecanvas.hh:87
Gecode::Gist::TreeCanvas::scale
double scale
Current scale factor.
Definition treecanvas.hh:289
Gecode::Gist::TreeCanvas::navNextSol
void navNextSol(bool back=false)
Move selection to next solution (in DFS order).
Definition treecanvas.cpp:996
Gecode::Gist::TreeCanvas::update
void update(void)
Update display.
Definition treecanvas.cpp:224
Gecode::Gist::TreeCanvas::zoomToFit
void zoomToFit(void)
Zoom the canvas so that the whole tree fits.
Definition treecanvas.cpp:528
Gecode::Gist::TreeCanvas::resizeToOuter
void resizeToOuter(void)
Resize to the outer widget size if auto zoom is enabled.
Definition treecanvas.cpp:1172
Gecode::Gist::TreeCanvas::activateComparator
void activateComparator(int i, bool active)
Set active comparator.
Definition treecanvas.cpp:174
Gecode::Gist::TreeCanvas::exportPDF
void exportPDF(void)
Export pdf of the current subtree.
Definition treecanvas.cpp:1064
Gecode::Gist::TreeCanvas::targetX
int targetX
Target x coordinate after smooth scrolling.
Definition treecanvas.hh:335
Gecode::Gist::TreeCanvas::wheelEvent
void wheelEvent(QWheelEvent *event)
Handle mouse wheel events.
Definition treecanvas.cpp:1264
Gecode::Gist::TreeCanvas::stats
Statistics stats
Statistics about the search tree.
Definition treecanvas.hh:286
Gecode::Gist::TreeCanvas::resizeEvent
void resizeEvent(QResizeEvent *event)
Handle resize event.
Definition treecanvas.cpp:1250
Gecode::Gist::TreeCanvas::targetScale
int targetScale
Target scale after layout.
Definition treecanvas.hh:348
Gecode::Gist::TreeCanvas::bookmarks
QVector< VisualNode * > bookmarks
The bookmarks map.
Definition treecanvas.hh:275
Gecode::Gist::TreeCanvas::searcher
SearcherThread searcher
Search engine thread.
Definition treecanvas.hh:250
Gecode::Gist::TreeCanvas::currentNode
VisualNode * currentNode
The currently selected node.
Definition treecanvas.hh:262
Gecode::Gist::TreeCanvas::finish
bool finish(void)
Stop search and wait for it to finish.
Definition treecanvas.cpp:1276
Gecode::Gist::TreeCanvas::exportWholeTreePDF
void exportWholeTreePDF(void)
Export pdf of the whole tree.
Definition treecanvas.cpp:1057
Gecode::Gist::TreeCanvas::xtrans
int xtrans
Offset on the x axis so that the tree is centered.
Definition treecanvas.hh:291
Gecode::Gist::TreeCanvas::activateDoubleClickInspector
void activateDoubleClickInspector(int i, bool active)
Set active inspector.
Definition treecanvas.cpp:141
Gecode::Gist::TreeCanvas::navUp
void navUp(void)
Move selection to the parent of the selected node.
Definition treecanvas.cpp:925
Gecode::Gist::TreeCanvas::autoHideFailed
bool autoHideFailed
Whether to hide failed subtrees automatically.
Definition treecanvas.hh:294
Gecode::Gist::TreeCanvas::labelBranches
void labelBranches(void)
Label all branches in subtree under current node.
Definition treecanvas.cpp:759
Gecode::Gist::TreeCanvas::eventNode
VisualNode * eventNode(QEvent *event)
Return the node corresponding to the event position.
Definition treecanvas.cpp:1103
Gecode::Gist::TreeCanvas::contextMenuEvent
void contextMenuEvent(QContextMenuEvent *event)
Handle context menu event.
Definition treecanvas.cpp:1234
Gecode::Gist::TreeCanvas::startCompareNodesBeforeFP
void startCompareNodesBeforeFP(void)
Wait for click on node to compare with current node before fixpoint.
Definition treecanvas.cpp:912
Gecode::Gist::TreeCanvas::startCompareNodes
void startCompareNodes(void)
Wait for click on node to compare with current node.
Definition treecanvas.cpp:904
Gecode::Gist::TreeCanvas::addComparator
void addComparator(Comparator *c)
Add comparator c.
Definition treecanvas.cpp:169
Gecode::Gist::TreeCanvas::mutex
QMutex mutex
Mutex for synchronizing acccess to the tree.
Definition treecanvas.hh:246
Gecode::Gist::TreeCanvas::inspectBeforeFP
void inspectBeforeFP(void)
Calls inspectCurrentNode(false).
Definition treecanvas.cpp:754
Gecode::Gist::TreeCanvas::hideFailed
void hideFailed(void)
Hide failed subtrees of selected node.
Definition treecanvas.cpp:470
Gecode::Gist::TreeCanvas::getAutoZoom
bool getAutoZoom(void)
Return preference whether to automatically zoom to fit.
Definition treecanvas.cpp:1421
Gecode::Gist::TreeCanvas::setRefreshPause
void setRefreshPause(int i)
Set refresh pause in msec.
Definition treecanvas.cpp:1431
Gecode::Gist::TreeCanvas::bookmarkNode
void bookmarkNode(void)
Bookmark current node.
Definition treecanvas.cpp:849
Gecode::Gist::TreeCanvas::print
void print(void)
Print the tree.
Definition treecanvas.cpp:1071
Gecode::Gist::TreeCanvas::searchAll
void searchAll(void)
Explore complete subtree of selected node.
Definition treecanvas.cpp:449
Gecode::Gist::TreeCanvas::refresh
int refresh
Refresh rate.
Definition treecanvas.hh:300
Gecode::Gist::TreeCanvas::scrollTimeLine
QTimeLine scrollTimeLine
Timer for smooth scrolling.
Definition treecanvas.hh:333
Gecode::Gist::TreeCanvas::layoutDoneTimerId
int layoutDoneTimerId
Timer id for delaying the update.
Definition treecanvas.hh:350
Gecode::Gist::TreeCanvas::addSolutionInspector
void addSolutionInspector(Inspector *i)
Add inspector i.
Definition treecanvas.cpp:147
Gecode::Gist::TreeCanvas::targetH
int targetH
Target height after layout.
Definition treecanvas.hh:346
Gecode::Gist::TreeCanvas::smoothScrollAndZoom
bool smoothScrollAndZoom
Whether to use smooth scrolling and zooming.
Definition treecanvas.hh:304
Gecode::Gist::TreeCanvas::zoomTimeLine
QTimeLine zoomTimeLine
Timer for smooth zooming.
Definition treecanvas.hh:331
Gecode::Gist::TreeCanvas::setPath
void setPath(void)
Set the current node to be the head of the path.
Definition treecanvas.cpp:874
Gecode::Gist::TreeCanvas::navRoot
void navRoot(void)
Move selection to the root node.
Definition treecanvas.cpp:989
Gecode::Gist::TreeCanvas::statusChanged
void statusChanged(VisualNode *, const Statistics &, bool)
Status bar update.
Gecode::Gist::TreeCanvas::TreeCanvas
TreeCanvas(Space *rootSpace, bool bab, QWidget *parent, const Options &opt)
Constructor.
Definition treecanvas.cpp:52
Gecode::Gist::TreeCanvas::~TreeCanvas
~TreeCanvas(void)
Destructor.
Definition treecanvas.cpp:127
Gecode::Gist::TreeCanvas::event
bool event(QEvent *event)
General event handler, used for displaying tool tips.
Definition treecanvas.cpp:1153
Gecode::Gist::TreeCanvas::setMoveDuringSearch
void setMoveDuringSearch(bool b)
Set preference whether to move cursor during search.
Definition treecanvas.cpp:1453
Gecode::Gist::TreeCanvas::searchOne
void searchOne(void)
Find next solution below selected node.
Definition treecanvas.cpp:455
Gecode::Gist::TreeCanvas::scroll
void scroll(void)
React to scroll events.
Definition treecanvas.cpp:254
Gecode::Gist::TreeCanvas::navDown
void navDown(void)
Move selection to the first child of the selected node.
Definition treecanvas.cpp:938
Gecode::Gist::TreeCanvas::comparators
QVector< QPair< Comparator *, bool > > comparators
The registered comparators, and whether they are active.
Definition treecanvas.hh:272
Gecode::Gist::TreeCanvas::compareNodes
bool compareNodes
Whether node comparison action is running.
Definition treecanvas.hh:278
Gecode::Gist::TreeCanvas::scaleTree
void scaleTree(int scale0, int zoomx=-1, int zoomy=-1)
Set scale factor to scale0.
Definition treecanvas.cpp:180
Gecode::Gist::TreeCanvas::activateSolutionInspector
void activateSolutionInspector(int i, bool active)
Set active inspector.
Definition treecanvas.cpp:152
Gecode::Gist::TreeCanvas::c_d
int c_d
The recomputation distance.
Definition treecanvas.hh:309
Gecode::Gist::TreeCanvas::mousePressEvent
void mousePressEvent(QMouseEvent *event)
Handle mouse press event.
Definition treecanvas.cpp:1328
Gecode::Gist::TreeCanvas::navLeft
void navLeft(void)
Move selection to the left sibling of the selected node.
Definition treecanvas.cpp:961
Gecode::Gist::TreeCanvas::scaleBar
QSlider * scaleBar
The scale bar.
Definition treecanvas.hh:283
Gecode::Gist::TreeCanvas::layoutMutex
QMutex layoutMutex
Mutex for synchronizing layout and drawing.
Definition treecanvas.hh:248
Gecode::Gist::TreeCanvas::targetY
int targetY
Target y coordinate after smooth scrolling.
Definition treecanvas.hh:339
Gecode::Gist::TreeCanvas::doubleClickInspectors
QVector< QPair< Inspector *, bool > > doubleClickInspectors
The registered click inspectors, and whether they are active.
Definition treecanvas.hh:266
Gecode::Gist::TreeCanvas::autoZoomChanged
void autoZoomChanged(bool)
The auto-zoom state was changed.
Gecode::Gist::TreeCanvas::setRefresh
void setRefresh(int i)
Set refresh rate.
Definition treecanvas.cpp:1426
Gecode::Gist::TreeCanvas::na
Node::NodeAllocator * na
Allocator for nodes.
Definition treecanvas.hh:256
Gecode::Gist::TreeCanvas::curBest
BestNode * curBest
The currently best solution (for branch-and-bound).
Definition treecanvas.hh:260
Gecode::Gist::TreeCanvas::paintEvent
void paintEvent(QPaintEvent *event)
Paint the tree.
Definition treecanvas.cpp:1178
Gecode::Gist::TreeCanvas::unstopAll
void unstopAll(void)
Do not stop at any stop node.
Definition treecanvas.cpp:498
Gecode::Gist::TreeCanvas::moveDuringSearch
bool moveDuringSearch
Whether to move cursor during search.
Definition treecanvas.hh:306
Gecode::Gist::TreeCanvas::getSmoothScrollAndZoom
bool getSmoothScrollAndZoom(void)
Return preference whether to use smooth scrolling and zooming.
Definition treecanvas.cpp:1438
Gecode::Gist::TreeCanvas::mouseDoubleClickEvent
void mouseDoubleClickEvent(QMouseEvent *event)
Handle mouse double click event.
Definition treecanvas.cpp:1217
Gecode::Gist::TreeCanvas::a_d
int a_d
The adaptive recomputation distance.
Definition treecanvas.hh:311
Gecode::Gist::TreeCanvas::unhideAll
void unhideAll(void)
Unhide all nodes below selected node.
Definition treecanvas.cpp:479
Gecode::Gist::TreeCanvas::reset
void reset(void)
Reset.
Definition treecanvas.cpp:816
Gecode::Gist::TreeCanvas::searchFinished
void searchFinished(void)
Signals that Gist is finished.
Gecode::Gist::TreeCanvas::sourceX
int sourceX
Source x coordinate after smooth scrolling.
Definition treecanvas.hh:337
Gecode::Gist::TreeCanvas::scaleChanged
void scaleChanged(int)
The scale factor has changed.
Gecode::Gist::TreeCanvas::getAutoHideFailed
bool getAutoHideFailed(void)
Return preference whether to automatically hide failed subtrees.
Definition treecanvas.cpp:1416
Gecode::Gist::TreeCanvas::solution
void solution(const Space *)
Signals that a solution has been found.
Gecode::Gist::TreeCanvas::targetW
int targetW
Target width after layout.
Definition treecanvas.hh:344
Gecode::Gist::TreeCanvas::setRecompDistances
void setRecompDistances(int c_d, int a_d)
Set recomputation distances.
Definition treecanvas.cpp:1387
Gecode::Gist::TreeCanvas::addMoveInspector
void addMoveInspector(Inspector *i)
Add inspector i.
Definition treecanvas.cpp:158
Gecode::Gist::TreeCanvas::autoZoom
bool autoZoom
Whether to zoom automatically.
Definition treecanvas.hh:296
Gecode::Gist::TreeCanvas::emitStatusChanged
void emitStatusChanged(void)
Re-emit status change information for current node.
Definition treecanvas.cpp:920
Gecode::Gist::TreeCanvas::setAutoZoom
void setAutoZoom(bool b)
Set preference whether to automatically zoom to fit.
Definition treecanvas.cpp:1397
Gecode::Gist::TreeCanvas::centerCurrentNode
void centerCurrentNode(void)
Center the view on the currently selected node.
Definition treecanvas.cpp:564
Gecode::Gist::TreeCanvas::setSmoothScrollAndZoom
void setSmoothScrollAndZoom(bool b)
Set preference whether to use smooth scrolling and zooming.
Definition treecanvas.cpp:1443
Gecode::Gist::TreeCanvas::finishedFlag
bool finishedFlag
Flag signalling that Gist is ready to be closed.
Definition treecanvas.hh:254
Gecode::Gist::TreeCanvas::removedBookmark
void removedBookmark(int idx)
Signals that a bookmark has been removed.
Gecode::Gist::TreeCanvas::pathHead
VisualNode * pathHead
The head of the currently selected path.
Definition treecanvas.hh:264
Gecode::Gist::TreeCanvas::activateMoveInspector
void activateMoveInspector(int i, bool active)
Set active inspector.
Definition treecanvas.cpp:163
Gecode::Gist::TreeCanvas::setCurrentNode
void setCurrentNode(VisualNode *n, bool finished=true, bool update=true)
Set the selected node to n.
Definition treecanvas.cpp:1293
Gecode::Gist::TreeCanvas::contextMenu
void contextMenu(QContextMenuEvent *)
Context menu triggered.
Gecode::Gist::TreeCanvas::stopSearchFlag
bool stopSearchFlag
Flag signalling the search to stop.
Definition treecanvas.hh:252
Gecode::Gist::TreeCanvas::setShowCopies
void setShowCopies(bool b)
Set preference whether to show copies in the tree.
Definition treecanvas.cpp:1407
Gecode::Gist::TreeCanvas::labelPath
void labelPath(void)
Label all branches on path to root node.
Definition treecanvas.cpp:767
Gecode::Gist::TreeCanvas::layoutDone
void layoutDone(int w, int h, int scale0)
Layout done.
Definition treecanvas.cpp:259
Gecode::Gist::TreeCanvas::timerEvent
virtual void timerEvent(QTimerEvent *e)
Timer invoked for smooth zooming and scrolling.
Definition treecanvas.cpp:508
Gecode::Gist::TreeCanvas::getMoveDuringSearch
bool getMoveDuringSearch(void)
Return preference whether to move cursor during search.
Definition treecanvas.cpp:1448
Gecode::Gist::TreeCanvas::compareNodesBeforeFP
bool compareNodesBeforeFP
Whether node comparison action computes fixpoint.
Definition treecanvas.hh:280
Gecode::Gist::TreeCanvas::toggleStop
void toggleStop(void)
Do not stop at selected stop node.
Definition treecanvas.cpp:489
Gecode::Gist::TreeCanvas::toggleHidden
void toggleHidden(void)
Toggle hidden state of selected node.
Definition treecanvas.cpp:461
Gecode::Gist::TreeCanvas::navRight
void navRight(void)
Move selection to the right sibling of the selected node.
Definition treecanvas.cpp:975
Gecode::Gist::TreeCanvas::navPrevSol
void navPrevSol(void)
Move selection to previous solution (in DFS order).
Definition treecanvas.cpp:1009
Gecode::Gist::TreeCanvas::showCopies
bool showCopies
Whether to show copies in the tree.
Definition treecanvas.hh:298
Gecode::Gist::TreeCanvas::inspectPath
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
Gecode::Gist::TreeCanvas::getShowCopies
bool getShowCopies(void)
Return preference whether to show copies in the tree.
Definition treecanvas.cpp:1411
Gecode::Gist::TreeCanvas::root
VisualNode * root
The root node of the tree.
Definition treecanvas.hh:258
Gecode::Gist::TreeCanvas::stopSearch
void stopSearch(void)
Stop current search.
Definition treecanvas.cpp:810
Gecode::Gist::TreeCanvas::inspectCurrentNode
void inspectCurrentNode(bool fix=true, int inspectorNo=-1)
Call the double click inspector for the currently selected node.
Definition treecanvas.cpp:618
Gecode::Gist::TreeCanvas::sourceY
int sourceY
Target y coordinate after smooth scrolling.
Definition treecanvas.hh:341
Gecode::Gist::TreeCanvas::setAutoHideFailed
void setAutoHideFailed(bool b)
Set preference whether to automatically hide failed subtrees.
Definition treecanvas.cpp:1392
Gecode::Gist::TreeCanvas::addDoubleClickInspector
void addDoubleClickInspector(Inspector *i)
Add inspector i.
Definition treecanvas.cpp:136
Gecode::Gist::TreeCanvas::refreshPause
int refreshPause
Time (in msec) to pause after each refresh.
Definition treecanvas.hh:302
Gecode::Gist::TreeCanvas::moveInspectors
QVector< QPair< Inspector *, bool > > moveInspectors
The registered move inspectors, and whether they are active.
Definition treecanvas.hh:270
Gecode::Gist::TreeCanvas::solutionInspectors
QVector< QPair< Inspector *, bool > > solutionInspectors
The registered solution inspectors, and whether they are active.
Definition treecanvas.hh:268
Gecode::Gist::TreeCanvas::addedBookmark
void addedBookmark(const QString &id)
Signals that a bookmark has been added.
Gecode::Gist::VisualNode
Node class that supports visual layout
Definition visualnode.hh:125
Gecode::Gist::VisualNode::isHidden
bool isHidden(void)
Return if node is hidden.
Definition visualnode.hpp:129
Gecode::Gist::VisualNode::dirtyUp
void dirtyUp(const NodeAllocator &na)
Mark all nodes up the path to the parent as dirty.
Definition visualnode.cpp:102
Gecode::Gist::VisualNode::toolTip
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:279
Gecode::Gist::VisualNode::hideFailed
void hideFailed(const NodeAllocator &na, bool onlyDirty=false)
Hide all failed subtrees of this node.
Definition visualnode.cpp:159
Gecode::Gist::VisualNode::getBoundingBox
BoundingBox getBoundingBox(void)
Return the bounding box.
Definition visualnode.hpp:208
Gecode::Gist::VisualNode::setMarked
void setMarked(bool m)
Set mark of this node.
Definition visualnode.hpp:178
Gecode::Gist::VisualNode::getShape
Shape * getShape(void)
Return the shape of this node.
Definition visualnode.hpp:203
Gecode::Space
Computation spaces.
Definition core.hpp:1742
drawingcursor.hh
Gecode::Gist::bab
int bab(Space *root, const Gist::Options &opt=Gist::Options::def)
Create a new stand-alone Gist for branch-and-bound search of root.
Definition gist.hpp:208
Gecode::Space::commit
void commit(const Choice &c, unsigned int a, CommitStatistics &stat=unused_commit)
Commit choice c for alternative a.
Definition core.hpp:3232
Gecode::Space::status
SpaceStatus status(StatusStatistics &stat=unused_status)
Query space status.
Definition core.cpp:252
Gecode::Space::clone
Space * clone(CloneStatistics &stat=unused_clone) const
Clone space.
Definition core.hpp:3224
Gecode::SS_BRANCH
@ SS_BRANCH
Space must be branched (at least one brancher left)
Definition core.hpp:1684
Gecode::SS_SOLVED
@ SS_SOLVED
Space is solved (no brancher left)
Definition core.hpp:1683
Gecode::SS_FAILED
@ SS_FAILED
Space is failed
Definition core.hpp:1682
Gecode::Gist::LayoutConfig::maxScale
const int maxScale
Maximum scale factor.
Definition treecanvas.hh:54
Gecode::Gist::LayoutConfig::defScale
const int defScale
Default scale factor.
Definition treecanvas.hh:56
Gecode::Gist::LayoutConfig::minScale
const int minScale
Minimum scale factor.
Definition treecanvas.hh:52
Gecode::Gist::LayoutConfig::maxAutoZoomScale
const int maxAutoZoomScale
Maximum scale factor for automatic zoom.
Definition treecanvas.hh:58
Gecode::Gist
The Gecode Interactive Search Tool.
Gecode::Gist::UNDETERMINED
@ UNDETERMINED
Node that has not been explored yet.
Definition spacenode.hh:48
Gecode::Gist::UNSTOP
@ UNSTOP
Node representing ignored stop point.
Definition spacenode.hh:50
Gecode::Gist::FAILED
@ FAILED
Node representing failure.
Definition spacenode.hh:46
Gecode::Gist::STOP
@ STOP
Node representing stop point.
Definition spacenode.hh:49
Gecode::Gist::SOLVED
@ SOLVED
Node representing a solution.
Definition spacenode.hh:45
Gecode::Gist::BRANCH
@ BRANCH
Node representing a branch.
Definition spacenode.hh:47
Gecode::Search::snapshot
Space * snapshot(Space *s, const Options &o)
Clone space s dependening on options o.
Definition support.hh:71
Gecode
Gecode toplevel namespace
Gecode::dfs
T * dfs(T *s, const Search::Options &o=Search::Options::def)
Invoke depth-first search engine for subclass T of space s with options o.
Definition dfs.hpp:73
nodevisitor.hh
support.hh
search.hh
GECODE_NEVER
#define GECODE_NEVER
Assert that this command is never executed.
Definition macros.hpp:56
treecanvas.hh
visualnode.hh