Commit 5a4b0a91 authored by Yann Boucher's avatar Yann Boucher
Browse files

Résolution d'un bug avec la sélection du GridView, ajout du support pour la...

Résolution d'un bug avec la sélection du GridView, ajout du support pour la modification des paramètres des règles de voisinage
parent b5d375b1
Pipeline #78420 passed with stages
in 17 seconds
......@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>1092</width>
<height>754</height>
<width>1056</width>
<height>771</height>
</rect>
</property>
<property name="windowTitle">
......@@ -249,7 +249,7 @@ pattern recorded :</string>
<item>
<widget class="QGroupBox" name="gridPatternGroupBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
......@@ -393,7 +393,7 @@ pattern recorded :</string>
<item>
<widget class="QGroupBox" name="rulesGroupBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
......@@ -402,45 +402,55 @@ pattern recorded :</string>
<string>Rules</string>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<item row="0" column="0" colspan="3">
<widget class="QPushButton" name="openRuleButton">
<property name="text">
<string>Load rule</string>
</property>
</widget>
</item>
<item row="1" column="0" colspan="2">
<layout class="QFormLayout" name="formLayout_2">
<property name="labelAlignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
<property name="formAlignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Name : </string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="rule_name">
<property name="text">
<string>RuleName</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="2">
<widget class="QPushButton" name="customize_button">
<property name="text">
<string>Customize...</string>
</property>
</widget>
</item>
<item row="4" column="0" colspan="3">
<widget class="QGroupBox" name="rule_settings">
<property name="enabled">
<bool>false</bool>
<bool>true</bool>
</property>
<property name="title">
<string>Settings</string>
</property>
<layout class="QFormLayout" name="formLayout">
<item row="2" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="transitionFunctionLabel">
<property name="text">
<string>Transition function :</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="0" column="0" colspan="2">
<layout class="QGridLayout" name="statesNeighborhoodLayout_3">
<item row="1" column="0">
<widget class="QLabel" name="neighborhoodLabel">
<property name="text">
<string>Neighborhood :</string>
</property>
<property name="buddy">
<cstring>neighborhood_list</cstring>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="neighborhood_list">
<property name="currentIndex">
<number>-1</number>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QPushButton" name="statesSettingsButton">
<property name="text">
......@@ -448,16 +458,6 @@ pattern recorded :</string>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QPushButton" name="cusumNeighborhoodButton">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Custom neighborhood</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="nbrStatesComboBox">
<item>
......@@ -507,90 +507,69 @@ pattern recorded :</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLabel" name="radiusLabel">
<property name="text">
<string>Radius r :</string>
</property>
<property name="buddy">
<cstring>radiusSpinBox</cstring>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QSpinBox" name="radiusSpinBox">
<property name="minimum">
<number>1</number>
</property>
</widget>
</item>
</layout>
</item>
<item row="2" column="0">
<widget class="QLabel" name="neighborhoodLabel">
<property name="text">
<string>Neighborhood :</string>
</property>
<property name="buddy">
<cstring>neighborhood_list</cstring>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QComboBox" name="neighborhood_list">
<property name="currentIndex">
<number>-1</number>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QComboBox" name="transition_list"/>
</item>
<item row="3" column="0" colspan="2">
<item row="6" column="0" colspan="2">
<widget class="QGroupBox" name="rule_settings_area">
<property name="title">
<string>Transition rule settings</string>
</property>
</widget>
</item>
<item row="4" column="0" colspan="2">
<item row="7" column="0" colspan="2">
<widget class="QLabel" name="informationLabel">
<property name="text">
<string>New rule must be saved before running simulation</string>
</property>
</widget>
</item>
<item row="5" column="0" colspan="2">
<item row="8" column="0" colspan="2">
<widget class="QPushButton" name="saveRuleButton">
<property name="text">
<string>Save rule</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="transitionFunctionLabel">
<property name="text">
<string>Transition function :</string>
</property>
</widget>
</item>
<item row="4" column="0" colspan="2">
<widget class="QGroupBox" name="neighborhood_settings_area">
<property name="enabled">
<bool>true</bool>
</property>
<property name="title">
<string>Neighborhood settings</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="0" column="0" colspan="3">
<widget class="QPushButton" name="openRuleButton">
<property name="text">
<string>Load rule</string>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QPushButton" name="customize_button">
<property name="text">
<string>Customize...</string>
</property>
</widget>
</item>
<item row="1" column="0" colspan="2">
<layout class="QFormLayout" name="formLayout_2">
<property name="labelAlignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
<property name="formAlignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Name : </string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="rule_name">
<property name="text">
<string>RuleName</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
......@@ -626,7 +605,7 @@ pattern recorded :</string>
<rect>
<x>0</x>
<y>0</y>
<width>1092</width>
<width>1056</width>
<height>25</height>
</rect>
</property>
......
......@@ -36,8 +36,8 @@ private slots:
//! \brief Ouverture d'une règle depuis le navigateur de fichier
void on_openRuleButton_clicked();
//! \brief Envoie un signal lors du changement de voisinage. Lorsque Custom est sélectionné, le bouton "Custom Neighborhood" est actif
void on_neighborhood_list_currentTextChanged(const QString &arg1);
//! \brief Envoie un signal lors du changement de voisinage.
void on_neighborhood_list_currentTextChanged(const QString &);
//! \brief Envoie le signal que la dimension de la grille a été modifié
void on_validateGridDim_clicked();
......@@ -75,6 +75,9 @@ private:
//! \brief Mets à jour le widget contenant les paramètres pour la règle de transition choisie
void update_transition_settings();
//! \brief Mets à jour le widget contenant les paramètres pour la règle de voisinage choisie
void update_neighborhood_settings();
//! \brief Configure pour activer la customisation d'une règle actuelle
void enable_rule_customization();
......
......@@ -14,15 +14,15 @@ Représente un voisinage arbitraire, défini par l'utilisateur.
#include "neighborhoodrule.hpp"
#include "property.hpp"
class ArbitraryNeighborhoodRule : public NeighborhoodRule, public HasUserProperties
class ArbitraryNeighborhoodRule : public NeighborhoodRule
{
public:
Neighborhood getNeighborhood(const Grid& grid, Coord pos) const override;
std::vector<NeighborhoodFormat> getFormats() const override;
public:
DEFINE_CONFIGURABLE_DYNLIST (CoordinateProperty, neighbors, "neighbors", ());
private:
DEFINE_CONFIGURABLE_DYNLIST (CoordinateProperty, neighbors, "Neighbors", ());
};
REGISTER_FACTORY_ENTRY(NeighborhoodRule, ArbitraryNeighborhoodRule, "Arbitrary");
......
......@@ -15,8 +15,6 @@ Contient la classe de la règle de Moore (semblable à VonNeumann avec les diago
class mooreNeighborhoodRule : public NeighborhoodRule
{
//! \brief Rayon du voisinage (en nombre de cellule)
int radius;
NeighborhoodFormat format;
public:
mooreNeighborhoodRule(int _radius = 1);
......@@ -28,6 +26,10 @@ public:
//! \brief Retourne 'format' de Moore dans un vecteur (méthode dérivée)
//! \return Retourne les formats de voisinage possible dans un std::vector.
std::vector<NeighborhoodFormat> getFormats() const;
private:
//! \brief Rayon du voisinage (en nombre de cellule)
DEFINE_CONFIGURABLE_PROPERTY(IntegerProperty, radius, "Radius", 1);
};
REGISTER_FACTORY_ENTRY(NeighborhoodRule, mooreNeighborhoodRule, "Moore");
......
......@@ -16,8 +16,6 @@ Contient la classe de la règle de Von Neumann.
class vonNeumannNeighborhoodRule : public NeighborhoodRule
{
//! \brief Rayon du voisinage (en nombre de cellule)
int radius;
NeighborhoodFormat format;
public:
vonNeumannNeighborhoodRule(int _radius = 1);
......@@ -29,6 +27,10 @@ public:
//! \brief Retourne 'format' de VonNeumann dans un vecteur (méthode dérivée)
//! \return Retourne les formats de voisinage possible dans un std::vector.
std::vector<NeighborhoodFormat> getFormats() const;
private:
//! \brief Rayon du voisinage (en nombre de cellule)
DEFINE_CONFIGURABLE_PROPERTY(IntegerProperty, radius, "Radius", 1);
};
REGISTER_FACTORY_ENTRY(NeighborhoodRule, vonNeumannNeighborhoodRule, "Von Neumann");
......
......@@ -19,6 +19,7 @@ Cette classe peut aussi fournir l'ensemble des positions de voisins qu'elle peut
#include "grid.h"
#include "neighborhood.hpp"
#include "factory.hpp"
#include "property.hpp"
/**
\struct NeighborhoodFormat
......@@ -32,7 +33,7 @@ struct NeighborhoodFormat
std::vector<Coord> positions;
};
class NeighborhoodRule
class NeighborhoodRule : public HasUserProperties
{
public:
//! \brief Retourne l'ensemble des voisins d'une cellule de position 'pos' sur la grille 'grid' sous la forme d'une structure 'Neighborhood'
......
{
"alphabet": [
],
"author": "JM",
"date": "lun. mai 24 2021",
"desc": "Desciprtion test 2",
"neighborhood_data": {
},
"neighborhood_name": "Moore",
"title": "Test_Gol_2",
"transition_data": {
},
"transition_name": "Game of Life"
}
{
"alphabet": [
],
"author": "JM",
"date": "lun. mai 24 2021",
"desc": "aaa",
"neighborhood_data": {
"Radius": 4
},
"neighborhood_name": "Von Neumann",
"title": "test3",
"transition_data": {
"Nombre d'états": 4,
"Seuil": 3
},
"transition_name": "Circular"
}
{
"alphabet": [
],
"author": "JM",
"date": "lun. mai 24 2021",
"desc": "Description test",
"neighborhood_data": {
},
"neighborhood_name": "Von Neumann",
"title": "Test_gol1",
"transition_data": {
},
"transition_name": "Game of Life"
}
......@@ -132,12 +132,15 @@ void GridGraphicsView::mousePressEvent(QMouseEvent *event)
QGraphicsItem* gitem_ptr = itemAt(event->pos());
GridItem* item = dynamic_cast<GridItem*>(gitem_ptr);
if (event->button() == Qt::LeftButton && item)
if (event->button() == Qt::LeftButton)
{
unsigned state = m_gridview.current_pen();
item->setBrush(QBrush(stateColor_to_QColor(m_gridview.alphabet().getState(state).getColor())));
item->cell_state = state;
item->update();
if (item)
{
unsigned state = m_gridview.current_pen();
item->setBrush(QBrush(stateColor_to_QColor(m_gridview.alphabet().getState(state).getColor())));
item->cell_state = state;
item->update();
}
}
else if (event->button() == Qt::RightButton && item)
{
......@@ -154,13 +157,15 @@ void GridGraphicsView::mouseMoveEvent(QMouseEvent *event)
QGraphicsItem* gitem_ptr = itemAt(event->pos());
GridItem* item = dynamic_cast<GridItem*>(gitem_ptr);
if (event->buttons() == Qt::LeftButton && item)
if (event->buttons() == Qt::LeftButton)
{
unsigned state = m_gridview.current_pen();
item->setBrush(QBrush(stateColor_to_QColor(m_gridview.alphabet().getState(state).getColor())));
item->cell_state = state;
item->update();
if (item)
{
unsigned state = m_gridview.current_pen();
item->setBrush(QBrush(stateColor_to_QColor(m_gridview.alphabet().getState(state).getColor())));
item->cell_state = state;
item->update();
}
}
else if (event->buttons() == Qt::RightButton && item)
{
......
......@@ -19,6 +19,7 @@ MainWindow::MainWindow(QWidget *parent)
init_transition_neighborhood_list();
update_transition_settings();
update_neighborhood_settings();
connect(ui->action_save_struct, &QAction::triggered, this, &MainWindow::afficher_interface_sauvegarde_structure);
connect(ui->struct_library, &StructureLibraryView::structure_copied, this, &MainWindow::copy_structure_clicked);
......@@ -69,15 +70,9 @@ void MainWindow::on_openRuleButton_clicked()
load_model(dialog.model());
}
void MainWindow::on_neighborhood_list_currentTextChanged(const QString &arg1)
void MainWindow::on_neighborhood_list_currentTextChanged(const QString &)
{
if(arg1 == "Custom"){
ui->cusumNeighborhoodButton->setEnabled(true);
}
else
{
ui->cusumNeighborhoodButton->setEnabled(false);
}
update_neighborhood_settings();
}
void MainWindow::on_widthSpinBox_valueChanged(int)
......@@ -256,6 +251,7 @@ void MainWindow::init_transition_neighborhood_list()
// TODO FIXME quand on aura une classe simulation commune
static std::unique_ptr<TransitionRule> transition_rule;
static std::unique_ptr<NeighborhoodRule> neighborhood_rule;
void MainWindow::update_transition_settings()
{
std::string selected = ui->transition_list->currentText().toStdString();
......@@ -274,6 +270,24 @@ void MainWindow::update_transition_settings()
prop->accept(visit);
}
}
void MainWindow::update_neighborhood_settings()
{
std::string selected = ui->neighborhood_list->currentText().toStdString();
neighborhood_rule = Factory<NeighborhoodRule>::make(selected);
if (!neighborhood_rule)
return;
if (neighborhood_rule->get_properties().size() == 0)
ui->neighborhood_settings_area->hide();
else
{
ui->neighborhood_settings_area->show();
UIBuilderVisitor visit(ui->neighborhood_settings_area);
for (auto& prop : neighborhood_rule->get_properties())
prop->accept(visit);
}
}
void MainWindow::enable_rule_customization()
{
......@@ -294,16 +308,29 @@ void MainWindow::load_model(const QJsonObject &obj)
ui->rule_name->setText(obj.value("title").toString());
// TODO : load alphabet
ui->transition_list->setCurrentText(obj.value("transition_name").toString());
ui->neighborhood_list->setCurrentText(obj.value("neighborhood_name").toString());
update_transition_settings();
update_neighborhood_settings();
disable_rule_customization();
PropertyLoaderVisitor loader(obj.value("transition_data").toObject());
for (auto& prop : transition_rule->get_properties())
prop->accept(loader);
UIBuilderVisitor visit(ui->rule_settings_area);
for (auto& prop : transition_rule->get_properties())
prop->accept(visit);
{
PropertyLoaderVisitor loader(obj.value("transition_data").toObject());
for (auto& prop : transition_rule->get_properties())
prop->accept(loader);
UIBuilderVisitor visit(ui->rule_settings_area);
for (auto& prop : transition_rule->get_properties())
prop->accept(visit);
}
{
PropertyLoaderVisitor loader(obj.value("neighborhood_data").toObject());
for (auto& prop : neighborhood_rule->get_properties())
prop->accept(loader);
UIBuilderVisitor visit(ui->neighborhood_settings_area);
for (auto& prop : neighborhood_rule->get_properties())
prop->accept(visit);
}
}
void MainWindow::save_model()
......@@ -316,9 +343,13 @@ void MainWindow::save_model()
// TODO : permettre de choisir auteur/titre/année/description
PropertySaverVisitor saver;
PropertySaverVisitor trans_saver;
for (auto& prop : transition_rule->get_properties())
prop->accept(saver);
prop->accept(trans_saver);
PropertySaverVisitor neighborhood_saver;
for (auto& prop : neighborhood_rule->get_properties())
prop->accept(neighborhood_saver);
QJsonObject root;
root["title"] = dialog.titre();
......@@ -327,7 +358,10 @@ void MainWindow::save_model()
root["date"] = dialog.date().toString();
root["transition_name"] = ui->transition_list->currentText();
root["transition_data"] = saver.save();
root["transition_data"] = trans_saver.save();
root["neighborhood_name"] = ui->neighborhood_list->currentText();
root["neighborhood_data"] = neighborhood_saver.save();
// TODO : sauvegarder l'alphabet quand on pourra y accéder avec Simulation
QJsonArray alphabet;
......
......@@ -33,7 +33,8 @@ QJsonObject ModelLoadingDialog::model() const
void ModelLoadingDialog::load_models()
{
// clear the previously watched directories
m_watcher.removePaths(m_watcher.directories());
if (!m_watcher.directories().empty())
m_watcher.removePaths(m_watcher.directories());
QTreeWidgetItem* model_list = add_directory_contents(QDir("models/"));
model_list->setText(0, "Models");
......
#include "mooreNeighborhoodRule.hpp"
mooreNeighborhoodRule::mooreNeighborhoodRule(int _radius) : radius(_radius)
mooreNeighborhoodRule::mooreNeighborhoodRule(int _radius)
{
radius.val = _radius;
if(_radius == 0)
throw NeighborhoodException("Le rayon ne peut pas être égal à 0");
// Les coordonnées sont copiées dans le vecteur
// N(i,j) = {(k, l)|abs(k−i) ≤ r et abs(l−j) ≤ r} ;
Coord newCord;
for(int i = -radius; i <= radius; i++){
for(int j = -radius; j <= radius; j++){
for(int i = -_radius; i <= _radius; i++){
for(int j = -_radius; j <= _radius; j++){
newCord.x = i;
newCord.y = j;
format.positions.push_back(newCord);
......