Commit 01f285b8 authored by Florent D'Halluin's avatar Florent D'Halluin
Browse files

[yavgui] Add & enable addTransition.

Only for boolean_automaton and z_automaton.
To be rewritten.

* yavgui/src/Makefile.am: Add files.
* yavgui/src/dialog_get_label.cc,
* yavgui/src/dialog_get_label.hh: New.  Input dialog for label.
* yavgui/src/g_state.cc,
* yavgui/src/g_state.hh: Add signals/slots/connections, visual tweaks.
* yavgui/src/g_scene.cc,
* yavgui/src/g_scene.hh,
* yavgui/src/g_state.hxx,
* yavgui/src/g_vcsn_handler.cc,
* yavgui/src/g_vcsn_handler.hh: Add signals/slots/connections.
* yavgui/src/g_vcsn_handler_internal.hh,
* yavgui/src/g_vcsn_handler_internal.hxx: Implement addTransition.
parent b91f82b8
2009-08-06 d-halluin <d-halluin@lrde.epita.fr>
[yavgui] Add & enable addTransition.
Only for boolean_automaton and z_automaton.
To be rewritten.
* yavgui/src/Makefile.am: Add files.
* yavgui/src/dialog_get_label.cc,
* yavgui/src/dialog_get_label.hh: New. Input dialog for label.
* yavgui/src/g_state.cc,
* yavgui/src/g_state.hh: Add signals/slots/connections, visual tweaks.
* yavgui/src/g_scene.cc,
* yavgui/src/g_scene.hh,
* yavgui/src/g_state.hxx,
* yavgui/src/g_vcsn_handler.cc,
* yavgui/src/g_vcsn_handler.hh: Add signals/slots/connections.
* yavgui/src/g_vcsn_handler_internal.hh,
* yavgui/src/g_vcsn_handler_internal.hxx: Implement addTransition.
2009-08-06 d-halluin <d-halluin@lrde.epita.fr>
 
[yavgui] Add temporary setTransition implementation.
......
......@@ -27,6 +27,8 @@ COMMON_SOURCES = main.cc \
dialog_help.moc.cc \
dialog_get_instance.cc \
dialog_get_instance.moc.cc \
dialog_get_label.cc \
dialog_get_label.moc.cc \
dialog_get_automaton_type.cc \
dialog_get_automaton_type.moc.cc \
dialog_get_layout.cc \
......
// dialog_get_label.cc: this file is part of Vaucanson.
//
// Vaucanson, a generic library for finite state machines.
//
// Copyright (C) 2006 The Vaucanson Group.
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// The complete GNU General Public Licence Notice can be found as the
// `COPYING' file in the root directory.
//
// The Vaucanson Group consists of people listed in the `AUTHORS' file.
//
/**
* @file dialog_get_label.cc
* @author Florent D'Halluin <d-halluin@lrde.epita.fr>
*
*
*/
#include "dialog_get_label.hh"
namespace gui
{
namespace dialogs
{
DialogGetLabel::DialogGetLabel (QString* str)
: str_ (str),
input_ (new QLineEdit ())
{
QPushButton *closeButton = new QPushButton(tr("Ok"));
connect(closeButton, SIGNAL(clicked()), this, SLOT(done()));
QHBoxLayout *buttonsLayout = new QHBoxLayout;
buttonsLayout->addStretch(1);
buttonsLayout->addWidget(closeButton);
QVBoxLayout *mainLayout = new QVBoxLayout;
mainLayout->addWidget(input_);
mainLayout->addLayout(buttonsLayout);
setLayout(mainLayout);
setWindowTitle(tr("Enter a label"));
}
void DialogGetLabel::done ()
{
if (str_)
*str_ = input_->text();
emit close ();
}
} // ! namespace dialogs
} // ! namespace gui
// dialog_get_label.hh: this file is part of Vaucanson.
//
// Vaucanson, a generic library for finite state machines.
//
// Copyright (C) 2006 The Vaucanson Group.
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// The complete GNU General Public Licence Notice can be found as the
// `COPYING' file in the root directory.
//
// The Vaucanson Group consists of people listed in the `AUTHORS' file.
//
/**
* @file dialog_get_label.hh
* @author Florent D'Halluin <d-halluin@lrde.epita.fr>
*
*
*/
#ifndef DIALOG_GET_LABEL_HH_
# define DIALOG_GET_LABEL_HH_
# include <QtGui>
# include "common.hh"
# include "g_common.hh"
namespace gui
{
namespace dialogs
{
class DialogGetLabel : public QDialog
{
Q_OBJECT
public:
DialogGetLabel (QString* str);
public slots:
void done ();
private:
QString* str_;
QLineEdit* input_;
};
} // ! namespace dialogs
} // ! namespace gui
#endif /* !DIALOG_GET_LABEL_HH_ */
......@@ -30,7 +30,7 @@ namespace gui
namespace display
{
GScene::GScene ()
: item_selected_(false)
: item_selected_(0)
{
}
......@@ -57,6 +57,8 @@ namespace gui
this, SLOT(itemSelected()));
connect(state, SIGNAL(deselected()),
this, SLOT(itemDeselected()));
connect(state, SIGNAL(addTransition(GState*, QString)),
this, SLOT(addTransition(GState*, QString)));
}
void
......@@ -96,6 +98,13 @@ namespace gui
emit delTransition(dynamic_cast<GTransition*>(sender()));
}
void
GScene::addTransition(GState* other, QString label)
{
emit addTransition(dynamic_cast<GState*>(sender()),
other, label);
}
void
GScene::setTransitionLabel(QString label)
{
......@@ -105,13 +114,13 @@ namespace gui
void
GScene::itemSelected()
{
item_selected_ = true;
item_selected_ += 1;
}
void
GScene::itemDeselected()
{
item_selected_ = false;
item_selected_ -= 1;
}
} // ! namespace display
......
......@@ -53,6 +53,7 @@ namespace gui
void setInitial(QString entry);
void setFinal(QString entry);
void setTransitionLabel(QString label);
void addTransition(GState* other, QString entry);
// Used to ignore right click events.
void itemSelected();
......@@ -63,13 +64,14 @@ namespace gui
// Connect GVcsnHandler to those.
void delState(GState* state);
void addState(QPointF pos);
void addTransition(GState* src, GState* dst, QString entry);
void setInitial(GState* state, QString entry);
void setFinal(GState* state, QString entry);
void delTransition(GTransition* transition);
void setTransitionLabel(GTransition* transition, QString label);
private:
bool item_selected_;
int item_selected_;
};
} // ! namespace display
......
......@@ -30,6 +30,7 @@
#include "g_state.hh"
#include "dialog_properties_state.hh"
#include "dialog_get_label.hh"
#include "common.hh"
......@@ -47,32 +48,55 @@ namespace gui
final_entry_ (final_entry),
index_ (index),
selected_ (false),
drawing_transition_ (false),
looping_transitions_ (0)
{
setCursor (QCursor (Qt::ArrowCursor));
setAcceptsHoverEvents (true);
setAcceptHoverEvents (true);
setFlag (ItemIsMovable);
shape_.addEllipse(QRectF(-radius_, -radius_,
2 * radius_, 2 * radius_));
update_bounding_rect_();
std::stringstream str;
str << index_;
label_ = str.str ().c_str ();
}
void
GState::update_bounding_rect_()
{
prepareGeometryChange();
bounding_rect_ = QRectF(-radius_, -radius_,
2 * radius_, 2 * radius_);
if (!initial_entry_.isNull())
bounding_rect_ = bounding_rect_.united(QRectF(-radius_ - 40, -radius_,
40, radius_));
if (!final_entry_.isNull())
bounding_rect_ = bounding_rect_.united(QRectF(radius_, -radius_,
40, radius_));
if (drawing_transition_)
bounding_rect_ = bounding_rect_.united(QRectF(mouse_pos_.x() - 5,
mouse_pos_.y() - 5,
10,
10));
}
QRectF
GState::boundingRect () const
{
BENCH_TASK_SCOPED("GState::boundingRect ()");
return QRectF (-radius_, -radius_,
2 * radius_, 2 * radius_);
return bounding_rect_;
}
QPainterPath
GState::shape () const
{
BENCH_TASK_SCOPED("GState::shape ()");
QPainterPath path;
path.addEllipse (boundingRect ());
return path;
return shape_;
}
void
......@@ -84,7 +108,14 @@ namespace gui
painter->setPen (QColor ("black"));
painter->setBrush (color_);
painter->drawEllipse (boundingRect ());
QRectF box = QRectF(-radius_, -radius_,
2 * radius_, 2 * radius_);
painter->drawEllipse(box);
painter->drawText(box, Qt::AlignCenter
| Qt::AlignVCenter,
label_);
if (!final_entry_.isNull())
{
......@@ -116,10 +147,6 @@ namespace gui
final_entry_);
}
painter->drawText (boundingRect (), Qt::AlignCenter
| Qt::AlignVCenter,
label_);
if (!initial_entry_.isNull())
{
painter->setPen ("black");
......@@ -149,6 +176,34 @@ namespace gui
| Qt::AlignTop,
initial_entry_);
}
if (drawing_transition_)
{
painter->setPen("black");
painter->setBrush(QColor("black"));
QPainterPath path;
path.lineTo(mouse_pos_);
qreal dx = mouse_pos_.x ();
qreal dy = mouse_pos_.y ();
qreal d = std::sqrt ((double) (dx * dx + dy * dy));
if (d != 0)
{
QPointF c2 (mouse_pos_.x () - 8 * dx / d - 4 * dy / d,
mouse_pos_.y () - 8 * dy / d + 4 * dx / d);
QPointF c3 (mouse_pos_.x () - 8 * dx / d + 4 * dy / d,
mouse_pos_.y () - 8 * dy / d - 4 * dx / d);
path.lineTo (c2);
path.lineTo (c3);
path.lineTo (mouse_pos_);
}
painter->drawPath (path);
}
}
QVariant GState::itemChange (GraphicsItemChange,
......@@ -178,9 +233,58 @@ namespace gui
event->ignore();
return;
}
if (event->button () == Qt::RightButton)
{
setZValue(1);
drawing_transition_ = true;
mouse_pos_ = event->pos();
update_bounding_rect_();
update();
return;
}
QGraphicsItem::mousePressEvent(event);
}
void
GState::mouseReleaseEvent (QGraphicsSceneMouseEvent* event)
{
if (drawing_transition_)
{
drawing_transition_ = false;
setZValue(0);
GState* s = dynamic_cast<GState*>(scene()->itemAt(event->scenePos()));
if (s && s != this)
{
QString str;
dialogs::DialogGetLabel dlg(&str);
dlg.exec();
emit addTransition(s, str);
}
}
QGraphicsItem::mouseReleaseEvent(event);
}
void
GState::mouseMoveEvent (QGraphicsSceneMouseEvent* event)
{
if (!selected_)
{
event->ignore();
return;
}
if (drawing_transition_)
{
event->ignore();
mouse_pos_ = event->pos();
update_bounding_rect_();
update();
return;
}
QGraphicsItem::mouseMoveEvent(event);
}
void
GState::mouseDoubleClickEvent (QGraphicsSceneMouseEvent* event)
{
......@@ -214,6 +318,8 @@ namespace gui
void
GState::select ()
{
if (selected_)
return;
color_ = highlight_color_;
selected_ = true;
......@@ -224,6 +330,8 @@ namespace gui
void
GState::deselect ()
{
if (!selected_)
return;
color_ = default_color_;
selected_ = false;
......
......@@ -54,9 +54,14 @@ namespace gui
inline qreal radius ();
// Note: Drag/drop events do not work for highlighting with the
// current implementation for add transition.
void hoverEnterEvent (QGraphicsSceneHoverEvent* event);
void hoverLeaveEvent (QGraphicsSceneHoverEvent* event);
void mouseMoveEvent (QGraphicsSceneMouseEvent* event);
void mousePressEvent (QGraphicsSceneMouseEvent* event);
void mouseReleaseEvent (QGraphicsSceneMouseEvent* event);
void mouseDoubleClickEvent (QGraphicsSceneMouseEvent* event);
inline int looping_transitions ();
......@@ -88,6 +93,8 @@ namespace gui
inline int index () const;
inline bool is_drawing_transition() const;
public slots:
void refresh ();
void select ();
......@@ -104,8 +111,12 @@ namespace gui
void setInitial(QString entry);
void setFinal(QString entry);
void addTransition(GState* other, QString label);
private:
void update_bounding_rect_();
// Background colors
QColor default_color_;
QColor highlight_color_;
......@@ -113,6 +124,9 @@ namespace gui
qreal radius_;
QRectF bounding_rect_;
QPainterPath shape_;
// is initial;
QString initial_entry_;
QString final_entry_;
......@@ -125,6 +139,10 @@ namespace gui
// True if the state is selected
bool selected_;
// True if a transition is being drawn.
bool drawing_transition_;
QPointF mouse_pos_;
int looping_transitions_;
};
......
......@@ -78,6 +78,7 @@ namespace gui
void GState::set_initial_entry (QString initial_entry)
{
initial_entry_ = initial_entry;
update_bounding_rect_();
}
QString GState::final_entry ()
......@@ -93,6 +94,7 @@ namespace gui
void GState::set_final_entry (QString final_entry)
{
final_entry_ = final_entry;
update_bounding_rect_();
}
int
......@@ -101,6 +103,12 @@ namespace gui
return index_;
}
bool
GState::is_drawing_transition() const
{
return drawing_transition_;
}
} // ! namespace display
} // ! namespace gui
......
......@@ -78,6 +78,21 @@ namespace gui
boost::apply_visitor(op, **(info_.automaton));
}
void
GVcsnHandler::addTransition(GState* src, GState* dst, QString label)
{
if (! *(info_.automaton))
throw exceptions::NoAutomatonStructure ();
if (!src || !dst)
throw exceptions::NullParameter ();
if (label.isNull())
return;
AddTransition op(info_, src, dst, label);
boost::apply_visitor(op, **(info_.automaton));
}
void
GVcsnHandler::delTransition(GTransition* transition)
{
......@@ -111,6 +126,8 @@ namespace gui
info_.automaton = automaton;
connect(scene, SIGNAL(addState(QPointF)),
this, SLOT(addState(QPointF)));
connect(scene, SIGNAL(addTransition(GState*, GState*, QString)),
this, SLOT(addTransition(GState*, GState*, QString)));
connect(scene, SIGNAL(delState(GState*)),
this, SLOT(delState(GState*)));
connect(scene, SIGNAL(setInitial(GState*, QString)),
......
......@@ -65,6 +65,7 @@ namespace gui
void addState(QPointF pos);
void delState(GState* state);
void delTransition(GTransition* transition);
void addTransition(GState* src, GState* dst, QString label);
void setTransitionLabel(GTransition* transition, QString label);
......
......@@ -101,6 +101,25 @@ namespace gui
QString label;
};
struct AddTransition: public boost::static_visitor<>
{
AddTransition(SceneInfo& info,
GState* src,
GState* dst,
QString label);
void operator()(vcsn::boolean_automaton::automaton_t& automaton);
void operator()(vcsn::z_automaton::automaton_t& automaton);
template<typename Automaton>
void operator()(Automaton& automaton);
SceneInfo& info;
GState* src;
GState* dst;
QString label;
};
struct SetInitial: public boost::static_visitor<>
{
SetInitial(SceneInfo& info,
......
......@@ -197,7 +197,77 @@ namespace gui
// FIXME: implement this.
QMessageBox::warning(0, "Set transition label",
"Cannot set the transition label of this kind "
"of automaton.");
"of automaton (not implemented).");
}
AddTransition::AddTransition(SceneInfo& i, GState* s, GState* d, QString l)
: info(i),
src(s),
dst(d),
label(l)
{
}
void
AddTransition::operator()(vcsn::z_automaton::automaton_t& automaton)
{
using namespace vcsn::z_automaton;
// FIXME: Only for labels_are_series.
series_set_t s = automaton.series();
series_set_elt_t se = make_rat_exp(s.monoid().alphabet(),
label.toStdString(),
*(s.monoid().representation()),
*(s.representation()));
htransition_t i = automaton.add_series_transition(src->index(),
dst->index(),
se);
std::stringstream str;
str << automaton.series_of(i);
GTransition* t = new GTransition(i, *src, *dst,
QString(str.str().c_str()));
info.scene->addItem(t);
info.scene->connectTransition(t);
}
void
AddTransition::operator()(vcsn::boolean_automaton::automaton_t& automaton)
{
using namespace vcsn::boolean_automaton;
// FIXME: Only for labels_are_series.
series_set_t s = automaton.series();
series_set_elt_t se = make_rat_exp(s.monoid().alphabet(),
label.toStdString(),
*(s.monoid().