Element editor : Editor can change several primitive style in same time. Just select several primitive and edit it with the style editor widget.

git-svn-id: svn+ssh://svn.tuxfamily.org/svnroot/qet/qet/trunk@3716 bfdf4180-ca20-0410-9c96-a3a8aa849046
This commit is contained in:
blacksun 2015-02-15 10:21:32 +00:00
parent deeac895c3
commit d1819c967f
9 changed files with 385 additions and 124 deletions

View File

@ -331,14 +331,22 @@ ChangePartCommand::ChangePartCommand(
ChangePartCommand::~ChangePartCommand() { ChangePartCommand::~ChangePartCommand() {
} }
/// Annule le changement /**
void ChangePartCommand::undo() { * @brief ChangePartCommand::undo
*/
void ChangePartCommand::undo()
{
cep -> setProperty(property, old_value); cep -> setProperty(property, old_value);
ElementEditionCommand::undo();
} }
/// Refait le changement /**
void ChangePartCommand::redo() { * @brief ChangePartCommand::redo
*/
void ChangePartCommand::redo()
{
cep -> setProperty(property, new_value); cep -> setProperty(property, new_value);
ElementEditionCommand::redo();
} }
/** /**

View File

@ -26,31 +26,33 @@
#include <QtGui> #include <QtGui>
/** /**
ElementEditionCommand is the base class for all commands classes involved in * @brief The ElementEditionCommand class
* ElementEditionCommand is the base class for all commands classes involved in
the edition of an electrical element. It provides commonly required methods the edition of an electrical element. It provides commonly required methods
and attributes, such as accessors to the modified scene and view. and attributes, such as accessors to the modified scene and view.
*/ */
class ElementEditionCommand : public QUndoCommand { class ElementEditionCommand : public QUndoCommand
// constructors, destructor {
// constructors, destructor
public: public:
ElementEditionCommand(ElementScene * = 0, ElementView * = 0, QUndoCommand * = 0); ElementEditionCommand(ElementScene * = 0, ElementView * = 0, QUndoCommand * = 0);
ElementEditionCommand(const QString &, ElementScene * = 0, ElementView * = 0, QUndoCommand * = 0); ElementEditionCommand(const QString &, ElementScene * = 0, ElementView * = 0, QUndoCommand * = 0);
virtual ~ElementEditionCommand(); virtual ~ElementEditionCommand();
private: private:
ElementEditionCommand(const ElementEditionCommand &); ElementEditionCommand(const ElementEditionCommand &);
// methods // methods
public: public:
ElementScene *elementScene() const; ElementScene *elementScene() const;
void setElementScene(ElementScene *); void setElementScene(ElementScene *);
ElementView *elementView() const; ElementView *elementView() const;
void setElementView(ElementView *); void setElementView(ElementView *);
// attributes // attributes
protected: protected:
/// Element editor/view/scene the command should take place on /// Element editor/view/scene the command should take place on
ElementScene *editor_scene_; ElementScene *editor_scene_;
ElementView *editor_view_; ElementView *editor_view_;
}; };
/** /**

View File

@ -75,6 +75,38 @@ void ElementItemEditor::addChangePartCommand(const QString &desc, CustomElementP
); );
} }
/**
* @brief ElementItemEditor::addChangePartCommand
* Add a ChangePartCommand with child for each part of part_list to the undo stack
* @param undo_text : text of undo command to display
* @param part_list : list of parts to modify
* @param property : QProperty (of CustomElementPart) to modify
* @param new_value : the new value of the QProperty
*/
void ElementItemEditor::addChangePartCommand(const QString &undo_text, QList<CustomElementPart *> part_list, const char *property, const QVariant &new_value)
{
if (part_list.isEmpty()) return;
//Get only the parts concerned by modification
QList <CustomElementPart *> updated_part;
foreach (CustomElementPart *cep, part_list)
if (cep->property(property) != new_value)
updated_part << cep;
//There is not part to modify
if(updated_part.isEmpty()) return;
//Set the first part has parent undo
CustomElementPart *p_cep = updated_part.takeFirst();
QUndoCommand *parent_undo = new ChangePartCommand (undo_text, p_cep, property, p_cep->property(property), new_value);
//And other parts are just child of parent
foreach (CustomElementPart *cep, updated_part)
new ChangePartCommand (undo_text, cep, property, cep->property(property), new_value, parent_undo);
undoStack().push(parent_undo);
}
/// @return Le nom du type d'element edite /// @return Le nom du type d'element edite
QString ElementItemEditor::elementTypeName() const { QString ElementItemEditor::elementTypeName() const {
return(element_type_name); return(element_type_name);

View File

@ -26,31 +26,38 @@ class CustomElementPart;
provides methods to access the editor itself, the undo stack, the edition provides methods to access the editor itself, the undo stack, the edition
scene and even a method to easily take a ChangePartCommand into account. scene and even a method to easily take a ChangePartCommand into account.
*/ */
class ElementItemEditor : public QWidget { class ElementItemEditor : public QWidget
Q_OBJECT {
// constructors, destructor Q_OBJECT
// constructors, destructor
public: public:
ElementItemEditor(QETElementEditor *, QWidget * = 0); ElementItemEditor(QETElementEditor *, QWidget * = 0);
virtual ~ElementItemEditor() {}; virtual ~ElementItemEditor() {};
private: private:
ElementItemEditor(const ElementItemEditor &); ElementItemEditor(const ElementItemEditor &);
// methods // methods
public: public:
virtual QETElementEditor *elementEditor() const; virtual QETElementEditor *elementEditor() const;
virtual ElementScene *elementScene() const; virtual ElementScene *elementScene() const;
virtual QUndoStack &undoStack() const; virtual QUndoStack &undoStack() const;
virtual void addChangePartCommand(const QString &, CustomElementPart *, const char *, const QVariant &);
virtual QString elementTypeName() const;
virtual void setElementTypeName(const QString &);
virtual void detach();
virtual bool setPart(CustomElementPart *) = 0;
virtual CustomElementPart *currentPart() const = 0;
virtual void updateForm() = 0;
// attributes virtual void addChangePartCommand(const QString &, CustomElementPart *, const char *, const QVariant &);
virtual void addChangePartCommand(const QString &, QList<CustomElementPart *>, const char *, const QVariant &);
virtual QString elementTypeName() const;
virtual void setElementTypeName(const QString &);
virtual void detach();
virtual bool setPart(CustomElementPart *) = 0;
virtual bool setParts(QList <CustomElementPart *>) {return false;}
virtual CustomElementPart *currentPart() const = 0;
virtual void updateForm() = 0;
// attributes
private: private:
QETElementEditor *element_editor; QETElementEditor *element_editor;
QString element_type_name; QString element_type_name;
}; };
#endif #endif

View File

@ -65,6 +65,30 @@ void CustomElementGraphicPart::drawCross(const QPointF &center, QPainter *painte
painter -> restore(); painter -> restore();
} }
/**
* @brief CustomElementGraphicPart::setLineStyle
* Set line style to ls
* @param ls
*/
void CustomElementGraphicPart::setLineStyle(const LineStyle ls)
{
if (_linestyle == ls) return;
_linestyle = ls;
update();
}
/**
* @brief CustomElementGraphicPart::setLineWeight
* Set line weight to lw
* @param lw
*/
void CustomElementGraphicPart::setLineWeight(const LineWeight lw)
{
if (_lineweight == lw) return;
_lineweight = lw;
update();
}
/** /**
* @brief CustomElementGraphicPart::penWeight * @brief CustomElementGraphicPart::penWeight
* @return the weight of pen * @return the weight of pen
@ -78,6 +102,42 @@ qreal CustomElementGraphicPart::penWeight() const
return 1; return 1;
} }
/**
* @brief CustomElementGraphicPart::setFilling
* Set filling to f
* @param f
*/
void CustomElementGraphicPart::setFilling(const Filling f)
{
if (_filling == f) return;
_filling = f;
update();
}
/**
* @brief CustomElementGraphicPart::setColor
* Set color to c
* @param c
*/
void CustomElementGraphicPart::setColor(const Color c)
{
if (_color == c) return;
_color = c;
update();
}
/**
* @brief CustomElementGraphicPart::setAntialiased
* Set antialias to b
* @param b
*/
void CustomElementGraphicPart::setAntialiased(const bool b)
{
if (_antialiased == b) return;
_antialiased = b;
update();
}
/** /**
* @brief CustomElementGraphicPart::stylesToXml * @brief CustomElementGraphicPart::stylesToXml
* Write the curent style to xml element. * Write the curent style to xml element.

View File

@ -61,7 +61,6 @@ class CustomElementGraphicPart : public QGraphicsObject, public CustomElementPar
//Line color //Line color
enum Color {BlackColor, WhiteColor, GreenColor, RedColor, BlueColor}; enum Color {BlackColor, WhiteColor, GreenColor, RedColor, BlueColor};
// constructors, destructor // constructors, destructor
public: public:
@ -71,21 +70,21 @@ class CustomElementGraphicPart : public QGraphicsObject, public CustomElementPar
static void drawCross (const QPointF &center, QPainter *painter); static void drawCross (const QPointF &center, QPainter *painter);
//Getter and setter //Getter and setter
LineStyle lineStyle () const {return _linestyle;} LineStyle lineStyle () const {return _linestyle;}
void setLineStyle (const LineStyle ls) {_linestyle = ls;} void setLineStyle (const LineStyle ls);
LineWeight lineWeight () const {return _lineweight;} LineWeight lineWeight () const {return _lineweight;}
void setLineWeight (const LineWeight lw) {_lineweight = lw;} void setLineWeight (const LineWeight lw);
qreal penWeight () const; qreal penWeight () const;
Filling filling () const {return _filling;} Filling filling () const {return _filling;}
void setFilling(const Filling f) {_filling = f;} void setFilling(const Filling f);
Color color () const {return _color;} Color color () const {return _color;}
void setColor(const Color c) {_color = c;} void setColor(const Color c);
bool antialiased () const {return _antialiased;} bool antialiased () const {return _antialiased;}
void setAntialiased(const bool b) {_antialiased = b;} void setAntialiased(const bool b);
//End of getter and setter //End of getter and setter

View File

@ -40,6 +40,7 @@
#include "textfieldeditor.h" #include "textfieldeditor.h"
#include "partterminal.h" #include "partterminal.h"
#include "parttextfield.h" #include "parttextfield.h"
#include "styleeditor.h"
#include "eseventaddline.h" #include "eseventaddline.h"
#include "eseventaddrect.h" #include "eseventaddrect.h"
@ -499,6 +500,7 @@ void QETElementEditor::setupInterface() {
editors_["terminal"] = new TerminalEditor(this); editors_["terminal"] = new TerminalEditor(this);
editors_["text"] = new TextEditor(this); editors_["text"] = new TextEditor(this);
editors_["input"] = new TextFieldEditor(this); editors_["input"] = new TextFieldEditor(this);
editors_["style"] = new StyleEditor(this);
// panel sur le cote pour editer les parties // panel sur le cote pour editer les parties
tools_dock = new QDockWidget(tr("Informations", "dock title"), this); tools_dock = new QDockWidget(tr("Informations", "dock title"), this);
@ -565,33 +567,73 @@ void QETElementEditor::slot_setNoDragToView() {
*/ */
void QETElementEditor::slot_updateInformations() { void QETElementEditor::slot_updateInformations() {
QList<QGraphicsItem *> selected_qgis = ce_scene -> selectedItems(); QList<QGraphicsItem *> selected_qgis = ce_scene -> selectedItems();
QList<CustomElementPart *> cep_list;
bool style_editable = false;
//Test if part are editable by style editor
if (selected_qgis.size() >= 2)
{
style_editable = true;
foreach (QGraphicsItem *qgi, selected_qgis)
{
if (CustomElementPart *cep = dynamic_cast<CustomElementPart *>(qgi))
cep_list << cep;
else
style_editable = false;
}
if (style_editable)
style_editable = StyleEditor::isStyleEditable(cep_list);
}
clearToolsDock(); clearToolsDock();
// s'il n'y a qu'une seule primitive selectionnee //There's one selected item
if (selected_qgis.size() == 1) { if (selected_qgis.size() == 1)
{
QGraphicsItem *qgi = selected_qgis.first(); QGraphicsItem *qgi = selected_qgis.first();
if (CustomElementPart *selection = dynamic_cast<CustomElementPart *>(qgi)) { if (CustomElementPart *selection = dynamic_cast<CustomElementPart *>(qgi))
{
// on en ajoute le widget d'edition // on en ajoute le widget d'edition
QString selection_xml_name = selection -> xmlName(); QString selection_xml_name = selection -> xmlName();
ElementItemEditor *selection_editor = editors_[selection_xml_name]; ElementItemEditor *selection_editor = editors_[selection_xml_name];
if (selection_editor) { if (selection_editor)
if (selection_editor -> setPart(selection)) { {
if (selection_editor -> setPart(selection))
{
tools_dock_scroll_area_ -> setWidget(selection_editor); tools_dock_scroll_area_ -> setWidget(selection_editor);
tools_dock_stack_ -> setCurrentIndex(1); tools_dock_stack_ -> setCurrentIndex(1);
} else { }
else
{
qDebug() << "Editor refused part."; qDebug() << "Editor refused part.";
} }
} }
} }
} else { }
default_informations -> setText( //There's several parts selecteds and all can be edited by style editor.
tr( else if (style_editable)
"%n partie(s) s\351lectionn\351e(s).", {
"", ElementItemEditor *selection_editor = editors_["style"];
selected_qgis.size() if (selection_editor)
) {
); if (selection_editor -> setParts(cep_list))
{
tools_dock_scroll_area_ -> setWidget(selection_editor);
tools_dock_stack_ -> setCurrentIndex(1);
}
else
{
qDebug() << "Editor refused part.";
}
}
}
//Else we only display the number of selected items
else
{
default_informations -> setText(tr("%n partie(s) s\351lectionn\351e(s).",
"",
selected_qgis.size()));
default_informations -> setAlignment(Qt::AlignHCenter | Qt::AlignTop); default_informations -> setAlignment(Qt::AlignHCenter | Qt::AlignTop);
tools_dock_stack_ -> setCurrentIndex(0); tools_dock_stack_ -> setCurrentIndex(0);
} }

View File

@ -112,60 +112,148 @@ void StyleEditor::updatePart() {
} }
/// Update antialiasing with undo command /// Update antialiasing with undo command
void StyleEditor::updatePartAntialiasing() { addChangePartCommand(tr("style antialiasing"), part, "antialias", antialiasing -> isChecked()); } void StyleEditor::updatePartAntialiasing()
{
if (part)
addChangePartCommand(tr("style antialiasing"), part, "antialias", antialiasing -> isChecked());
else if (!m_part_list.isEmpty())
addChangePartCommand(tr("style antialiasing"), m_cep_list, "antialias", antialiasing -> isChecked());
}
/// Update color with undo command /// Update color with undo command
void StyleEditor::updatePartColor() { addChangePartCommand(tr("style couleur"), part, "color", outline_color->itemData(outline_color -> currentIndex()));} void StyleEditor::updatePartColor()
{
if (part)
addChangePartCommand(tr("style couleur"), part, "color", outline_color->itemData(outline_color -> currentIndex()));
else if (!m_part_list.isEmpty())
addChangePartCommand(tr("style couleur"), m_cep_list, "color", outline_color->itemData(outline_color -> currentIndex()));
}
/// Update style with undo command /// Update style with undo command
void StyleEditor::updatePartLineStyle() { addChangePartCommand(tr("style ligne"), part, "line_style", line_style->itemData(line_style -> currentIndex()));} void StyleEditor::updatePartLineStyle()
{
if (part)
addChangePartCommand(tr("style ligne"), part, "line_style", line_style->itemData(line_style -> currentIndex()));
else if (!m_part_list.isEmpty())
addChangePartCommand(tr("style ligne"), m_cep_list, "line_style", line_style->itemData(line_style -> currentIndex()));
}
/// Update weight with undo command /// Update weight with undo command
void StyleEditor::updatePartLineWeight() { addChangePartCommand(tr("style epaisseur"), part, "line_weight", size_weight->itemData(size_weight -> currentIndex()));} void StyleEditor::updatePartLineWeight()
{
if (part)
addChangePartCommand(tr("style epaisseur"), part, "line_weight", size_weight->itemData(size_weight -> currentIndex()));
else if (!m_part_list.isEmpty())
addChangePartCommand(tr("style epaisseur"), m_cep_list, "line_weight", size_weight->itemData(size_weight -> currentIndex()));
}
/// Update color filling with undo command /// Update color filling with undo command
void StyleEditor::updatePartFilling() { addChangePartCommand(tr("style remplissage"), part, "filling", filling_color->itemData(filling_color -> currentIndex()));} void StyleEditor::updatePartFilling()
{
if(part)
addChangePartCommand(tr("style remplissage"), part, "filling", filling_color->itemData(filling_color -> currentIndex()));
else if (!m_part_list.isEmpty())
addChangePartCommand(tr("style remplissage"), m_cep_list, "filling", filling_color->itemData(filling_color -> currentIndex()));
}
/** /**
* @brief StyleEditor::updateForm * @brief StyleEditor::updateForm
* Update the edition form * Update the edition form according to the value of edited part(s)
*/ */
void StyleEditor::updateForm() { void StyleEditor::updateForm()
if (!part) return; {
if (!part && m_part_list.isEmpty()) return;
activeConnections(false); activeConnections(false);
// lit l'antialiasing
antialiasing -> setChecked(part -> antialiased());
// lit la couleur if (part)
outline_color -> setCurrentIndex(part -> color()); {
antialiasing -> setChecked(part -> antialiased());
outline_color -> setCurrentIndex(part -> color());
line_style -> setCurrentIndex(part -> lineStyle());
size_weight -> setCurrentIndex(part -> lineWeight());
filling_color -> setCurrentIndex(part -> filling());
}
else if (m_part_list.size())
{
CustomElementGraphicPart *first_part = m_part_list.first();
antialiasing -> setChecked(first_part -> antialiased());
outline_color -> setCurrentIndex(first_part -> color());
line_style -> setCurrentIndex(first_part -> lineStyle());
size_weight -> setCurrentIndex(first_part -> lineWeight());
filling_color -> setCurrentIndex(first_part -> filling());
// lit le style foreach (CustomElementGraphicPart *cegp, m_part_list)
line_style -> setCurrentIndex(part -> lineStyle()); {
if (first_part -> antialiased() != cegp -> antialiased()) antialiasing -> setChecked(false);
if (first_part -> color() != cegp -> color()) outline_color -> setCurrentIndex(-1);
if (first_part -> lineStyle() != cegp -> lineStyle()) line_style -> setCurrentIndex(-1);
if (first_part -> lineWeight() != cegp -> lineWeight()) size_weight -> setCurrentIndex(-1);
if (first_part -> filling() != cegp -> filling()) filling_color -> setCurrentIndex(-1);
}
}
// lit l'epaisseur
size_weight -> setCurrentIndex(part -> lineWeight());
// lit le remplissage
filling_color -> setCurrentIndex(part -> filling());
activeConnections(true); activeConnections(true);
} }
/** /**
Permet de specifier a cet editeur quelle primitive il doit editer. A noter * @brief StyleEditor::setPart
qu'un editeur peut accepter ou refuser d'editer une primitive. * Set the part to edit by this editor.
L'editeur de ligne acceptera d'editer la primitive new_part s'il s'agit d'un * Note : editor can accept or refuse to edit a part
objet de la classe CustomElementGraphicPart. * @param new_part : part to edit
@param new_part Nouvelle primitive a editer * @return true if editor accept to edit this CustomElementPart otherwise false
@return true si l'editeur a accepter d'editer la primitive, false sinon */
*/
bool StyleEditor::setPart(CustomElementPart *new_part) { bool StyleEditor::setPart(CustomElementPart *new_part) {
if (!new_part) { m_part_list.clear();
part = 0;
if (!new_part)
{
part = nullptr;
return(true); return(true);
} }
if (CustomElementGraphicPart *part_graphic = dynamic_cast<CustomElementGraphicPart *>(new_part)) {
if (CustomElementGraphicPart *part_graphic = dynamic_cast<CustomElementGraphicPart *>(new_part))
{
part = part_graphic; part = part_graphic;
updateForm(); updateForm();
return(true); return(true);
} else {
return(false);
} }
return(false);
}
/**
* @brief StyleEditor::setParts
* Set several parts to edit by this editor.
* Note : editor can accept or refuse to edit several parts.
* @param part_list
* @return true if every customeElementPart stored in part_list can
* be edited by this part editor, otherwise return false
* (see StyleEditor::isStyleEditable)
*/
bool StyleEditor::setParts(QList<CustomElementPart *> part_list)
{
if (part_list.isEmpty()) return false;
if (part_list.size() == 1) return setPart(part_list.first());
part = nullptr;
m_part_list.clear();
m_cep_list.clear();
if (!isStyleEditable(part_list)) return false;
foreach (CustomElementPart *cep, part_list)
{
if (CustomElementGraphicPart *cegp = dynamic_cast<CustomElementGraphicPart *>(cep))
m_part_list << cegp;
else
return false;
}
foreach (CustomElementGraphicPart *cegp, m_part_list)
m_cep_list << cegp;
updateForm();
return true;
} }
/** /**
@ -175,6 +263,23 @@ CustomElementPart *StyleEditor::currentPart() const {
return(part); return(part);
} }
/**
* @brief StyleEditor::isStyleEditable
* @param cep_list
* @return true if all of the content of cep_list can be edited by style editor, else return false.
*/
bool StyleEditor::isStyleEditable(QList<CustomElementPart *> cep_list)
{
QStringList str;
str << "arc" << "ellipse" << "line" << "polygon" << "rect";
foreach (CustomElementPart *cep, cep_list)
if (!str.contains(cep -> xmlName()))
return false;
return true;
}
/** /**
Active ou desactive les connexionx signaux/slots entre les widgets internes. Active ou desactive les connexionx signaux/slots entre les widgets internes.
@param active true pour activer les connexions, false pour les desactiver @param active true pour activer les connexions, false pour les desactiver

View File

@ -26,41 +26,47 @@ class CustomElementGraphicPart;
Its appendWidget() method makes the insertion of another widget below it Its appendWidget() method makes the insertion of another widget below it
easier. easier.
*/ */
class StyleEditor : public ElementItemEditor { class StyleEditor : public ElementItemEditor
Q_OBJECT {
// constructors, destructor Q_OBJECT
// constructors, destructor
public: public:
StyleEditor(QETElementEditor *, CustomElementGraphicPart * = 0, QWidget * = 0); StyleEditor(QETElementEditor *, CustomElementGraphicPart * = 0, QWidget * = 0);
virtual ~StyleEditor(); virtual ~StyleEditor();
private: private:
StyleEditor(const StyleEditor &); StyleEditor(const StyleEditor &);
// attributes // attributes
private: private:
CustomElementGraphicPart *part; CustomElementGraphicPart *part;
QVBoxLayout *main_layout; QList <CustomElementGraphicPart *> m_part_list;
QRadioButton *black_color, *white_color, *normal_style, *dashed_style, *dashdotted_style, *dotted_style, *green_color, *red_color, *blue_color; QList <CustomElementPart *> m_cep_list;
QRadioButton *none_weight, *thin_weight, *normal_weight, *no_filling; QVBoxLayout *main_layout;
QRadioButton *black_filling, *white_filling, *green_filling, *red_filling, *blue_filling; QRadioButton *black_color, *white_color, *normal_style, *dashed_style, *dashdotted_style, *dotted_style, *green_color, *red_color, *blue_color;
QCheckBox *antialiasing; QRadioButton *none_weight, *thin_weight, *normal_weight, *no_filling;
QComboBox *filling_color, *outline_color, *size_weight, *line_style; QRadioButton *black_filling, *white_filling, *green_filling, *red_filling, *blue_filling;
QCheckBox *antialiasing;
QComboBox *filling_color, *outline_color, *size_weight, *line_style;
// methods // methods
public: public:
virtual bool setPart(CustomElementPart *); virtual bool setPart(CustomElementPart *);
virtual CustomElementPart *currentPart() const; virtual bool setParts(QList<CustomElementPart *>);
virtual CustomElementPart *currentPart() const;
static bool isStyleEditable (QList <CustomElementPart *> cep_list);
public slots: public slots:
void updatePart(); void updatePart();
void updateForm(); void updateForm();
void updatePartAntialiasing(); void updatePartAntialiasing();
void updatePartColor(); void updatePartColor();
void updatePartLineStyle(); void updatePartLineStyle();
void updatePartLineWeight(); void updatePartLineWeight();
void updatePartFilling(); void updatePartFilling();
private: private:
void activeConnections(bool); void activeConnections(bool);
}; };
#endif #endif