Texts group item can be rotate.

The keybord shortcut for texts group alignment change. Now it's ctrl + arrow-left/up/right


git-svn-id: svn+ssh://svn.tuxfamily.org/svnroot/qet/qet/trunk@5141 bfdf4180-ca20-0410-9c96-a3a8aa849046
This commit is contained in:
blacksun
2017-12-05 20:51:54 +00:00
parent 0f2f8f0f2f
commit 89c019a10e
17 changed files with 736 additions and 524 deletions

View File

@@ -39,6 +39,8 @@
#include "element.h" #include "element.h"
#include "diagramview.h" #include "diagramview.h"
#include "dynamicelementtextitem.h" #include "dynamicelementtextitem.h"
#include "elementtextitemgroup.h"
#include "undocommand/addelementtextcommand.h"
const int Diagram::xGrid = 10; const int Diagram::xGrid = 10;
const int Diagram::yGrid = 10; const int Diagram::yGrid = 10;
@@ -291,10 +293,10 @@ void Diagram::wheelEvent(QGraphicsSceneWheelEvent *event)
* Else move selected elements * Else move selected elements
* @param e * @param e
*/ */
void Diagram::keyPressEvent(QKeyEvent *e) void Diagram::keyPressEvent(QKeyEvent *event)
{ {
if (m_event_interface) if (m_event_interface)
if(m_event_interface->keyPressEvent(e)) if(m_event_interface->keyPressEvent(event))
{ {
if(!m_event_interface->isRunning()) if(!m_event_interface->isRunning())
{ {
@@ -303,44 +305,76 @@ void Diagram::keyPressEvent(QKeyEvent *e)
return; return;
} }
bool transmit_event = true; if (!isReadOnly())
if (!isReadOnly()) { {
QPointF movement; QPointF movement;
qreal top_position = 0; qreal top_position = 0;
qreal left_position = 0; qreal left_position = 0;
QList<QGraphicsItem*> selected_elmts = this->selectedContent().items(); DiagramContent dc(this);
if (!this->selectedContent().items(DiagramContent::All).isEmpty()) { if (!dc.items(DiagramContent::All).isEmpty())
switch(e -> key()) { {
//Move item with the keyborb arrow
if(event->modifiers() == Qt::NoModifier)
{
switch(event->key())
{
case Qt::Key_Left: case Qt::Key_Left:
foreach (Element *item, selectedContent().m_elements) { for (Element *item : dc.m_elements)
{
left_position = item->mapRectFromScene(item->boundingRect()).x(); left_position = item->mapRectFromScene(item->boundingRect()).x();
if (left_position >= this->sceneRect().left() - item->boundingRect().width()) if (left_position >= this->sceneRect().left() - item->boundingRect().width())
return; return;
} }
movement = QPointF(-xGrid, 0.0); movement = QPointF(-xGrid, 0.0);
break; break;
case Qt::Key_Right: movement = QPointF(+xGrid, 0.0); break; case Qt::Key_Right:
movement = QPointF(+xGrid, 0.0);
break;
case Qt::Key_Up: case Qt::Key_Up:
foreach (Element *item, selectedContent().m_elements) { for(Element *item : dc.m_elements)
{
top_position = item->mapRectFromScene(item->boundingRect()).y(); top_position = item->mapRectFromScene(item->boundingRect()).y();
if (top_position >= this->sceneRect().top() - item->boundingRect().height()) if (top_position >= this->sceneRect().top() - item->boundingRect().height())
return; return;
} }
movement = QPointF(0.0, -yGrid); movement = QPointF(0.0, -yGrid);
break; break;
case Qt::Key_Down: movement = QPointF(0.0, +yGrid); break; case Qt::Key_Down:
movement = QPointF(0.0, +yGrid);
break;
} }
if (!movement.isNull() && !focusItem()) {
if (!movement.isNull() && !focusItem())
{
beginMoveElements(); beginMoveElements();
continueMoveElements(movement); continueMoveElements(movement);
e -> accept(); event->accept();
transmit_event = false; return;
} }
} }
if (transmit_event) { else if(event->modifiers() == Qt::ControlModifier)
QGraphicsScene::keyPressEvent(e); {
//Adjust the alignment of a texts group
if(selectedItems().size() == 1 && selectedItems().first()->type() == QGraphicsItemGroup::Type)
{
if(ElementTextItemGroup *etig = dynamic_cast<ElementTextItemGroup *>(selectedItems().first()))
{
if(event->key() == Qt::Key_Left && etig->alignment() != Qt::AlignLeft)
undoStack().push(new AlignmentTextsGroupCommand(etig, Qt::AlignLeft));
else if (event->key() == Qt::Key_Up && etig->alignment() != Qt::AlignVCenter)
undoStack().push(new AlignmentTextsGroupCommand(etig, Qt::AlignVCenter));
else if (event->key() == Qt::Key_Right && etig->alignment() != Qt::AlignRight)
undoStack().push(new AlignmentTextsGroupCommand(etig, Qt::AlignRight));
} }
} }
}
}
event->ignore();
QGraphicsScene::keyPressEvent(event);
}
} }
/** /**
@@ -1659,25 +1693,6 @@ QSet<Conductor *> Diagram::selectedConductors() const {
return(conductors_set); return(conductors_set);
} }
/**
* @brief Diagram::selectedTexts
* @return A list of every selected texts (every kind of texts)
*/
QSet<DiagramTextItem *> Diagram::selectedTexts() const
{
QSet<DiagramTextItem *> selected_texts;
for(QGraphicsItem *qgi : selectedItems())
{
if (qgi->type() == ConductorTextItem::Type ||
qgi->type() == ElementTextItem::Type ||
qgi->type() == IndependentTextItem::Type ||
qgi->type() == DynamicElementTextItem::Type)
selected_texts << static_cast<DiagramTextItem *>(qgi);
}
return(selected_texts);
}
/// @return true si le presse-papier semble contenir un schema /// @return true si le presse-papier semble contenir un schema
bool Diagram::clipboardMayContainDiagram() { bool Diagram::clipboardMayContainDiagram() {
QString clipboard_text = QApplication::clipboard() -> text().trimmed(); QString clipboard_text = QApplication::clipboard() -> text().trimmed();
@@ -1760,62 +1775,6 @@ DiagramContent Diagram::content() const {
return(dc); return(dc);
} }
/**
* @brief Diagram::selectedContent
* @return the selected items, stored in a DiagramContent
*/
DiagramContent Diagram::selectedContent()
{
DiagramContent dc;
//Get the selected items
for (QGraphicsItem *item : selectedItems())
{
if (Element *elmt = qgraphicsitem_cast<Element *>(item))
dc.m_elements << elmt;
else if (IndependentTextItem *iti = qgraphicsitem_cast<IndependentTextItem *>(item))
dc.m_text_fields << iti;
else if (Conductor *c = qgraphicsitem_cast<Conductor *>(item))
{
// recupere les conducteurs selectionnes isoles (= non deplacables mais supprimables)
if (
!c -> terminal1 -> parentItem() -> isSelected() &&\
!c -> terminal2 -> parentItem() -> isSelected()
) {
dc.m_other_conductors << c;
}
}
else if (DiagramImageItem *dii = qgraphicsitem_cast<DiagramImageItem *>(item))
dc.m_images << dii;
else if (QetShapeItem *dsi = qgraphicsitem_cast<QetShapeItem *>(item))
dc.m_shapes << dsi;
else if (DynamicElementTextItem *deti = qgraphicsitem_cast<DynamicElementTextItem *>(item))
dc.m_element_texts << deti;
}
//For each selected element, we determine if conductors must be moved or updated.
for(Element *elmt : dc.m_elements) {
for(Terminal *terminal : elmt -> terminals()) {
for(Conductor *conductor : terminal -> conductors()) {
Terminal *other_terminal;
if (conductor -> terminal1 == terminal) {
other_terminal = conductor -> terminal2;
} else {
other_terminal = conductor -> terminal1;
}
// si les deux elements du conducteur sont deplaces
if (dc.m_elements.contains(other_terminal -> parentElement())) {
dc.m_conductors_to_move << conductor;
} else {
dc.m_conductors_to_update << conductor;
}
}
}
}
return(dc);
}
/** /**
* @brief Diagram::canRotateSelection * @brief Diagram::canRotateSelection
* @return True if a least one of selected items can be rotated * @return True if a least one of selected items can be rotated
@@ -1829,7 +1788,12 @@ bool Diagram::canRotateSelection() const
qgi->type() == DiagramImageItem::Type || qgi->type() == DiagramImageItem::Type ||
qgi->type() == ElementTextItem::Type || qgi->type() == ElementTextItem::Type ||
qgi->type() == Element::Type || qgi->type() == Element::Type ||
qgi->type() == DynamicElementTextItem::Type) return true; qgi->type() == DynamicElementTextItem::Type)
return true;
if(qgi->type() == QGraphicsItemGroup::Type)
if(dynamic_cast<ElementTextItemGroup *>(qgi))
return true;
} }
return false; return false;

View File

@@ -121,7 +121,7 @@ class Diagram : public QGraphicsScene
void mouseMoveEvent (QGraphicsSceneMouseEvent *event) override; void mouseMoveEvent (QGraphicsSceneMouseEvent *event) override;
void mouseReleaseEvent (QGraphicsSceneMouseEvent *event) override; void mouseReleaseEvent (QGraphicsSceneMouseEvent *event) override;
void wheelEvent (QGraphicsSceneWheelEvent *event) override; void wheelEvent (QGraphicsSceneWheelEvent *event) override;
void keyPressEvent (QKeyEvent *) override; void keyPressEvent (QKeyEvent *event) override;
void keyReleaseEvent (QKeyEvent *) override; void keyReleaseEvent (QKeyEvent *) override;
public: public:
@@ -187,10 +187,8 @@ class Diagram : public QGraphicsScene
QList<CustomElement *> customElements() const; QList<CustomElement *> customElements() const;
QList<Element *> elements() const; QList<Element *> elements() const;
QList<Conductor *> conductors() const; QList<Conductor *> conductors() const;
QSet<DiagramTextItem *> selectedTexts() const;
QSet<Conductor *> selectedConductors() const; QSet<Conductor *> selectedConductors() const;
DiagramContent content() const; DiagramContent content() const;
DiagramContent selectedContent();
bool canRotateSelection() const; bool canRotateSelection() const;
int beginMoveElements(QGraphicsItem * = nullptr); int beginMoveElements(QGraphicsItem * = nullptr);
void continueMoveElements(const QPointF &); void continueMoveElements(const QPointF &);

View File

@@ -26,6 +26,7 @@
#include "diagram.h" #include "diagram.h"
#include "qetgraphicsitem/diagramtextitem.h" #include "qetgraphicsitem/diagramtextitem.h"
#include "qetgraphicsitem/diagramimageitem.h" #include "qetgraphicsitem/diagramimageitem.h"
#include "elementtextitemgroup.h"
#include <QPropertyAnimation> #include <QPropertyAnimation>
QString itemText(const QetGraphicsItem *item) { QString itemText(const QetGraphicsItem *item) {
@@ -266,32 +267,36 @@ void MoveElementsCommand::redo() {
* Move item and conductor to @actual_movement * Move item and conductor to @actual_movement
* @param actual_movement movement to be applied * @param actual_movement movement to be applied
*/ */
void MoveElementsCommand::move(const QPointF &actual_movement) { void MoveElementsCommand::move(const QPointF &actual_movement)
{
typedef DiagramContent dc; typedef DiagramContent dc;
//Move every movable item, except conductor //Move every movable items, except conductor
foreach (QGraphicsItem *qgi, content_to_move.items(dc::Elements | dc::TextFields | dc::Images | dc::Shapes)) { for (QGraphicsItem *qgi : content_to_move.items(dc::Elements | dc::TextFields | dc::Images | dc::Shapes | dc::TextGroup))
{
//If curent item have parent, and parent item is in content_to_move //If curent item have parent, and parent item is in content_to_move
//we don't apply movement to this item, because this item will be moved by is parent. //we don't apply movement to this item, because this item will be moved by is parent.
if (qgi->parentItem()) { if (qgi->parentItem())
if (content_to_move.items().contains(qgi->parentItem())) if (content_to_move.items().contains(qgi->parentItem()))
continue; continue;
}
if(qgi->toGraphicsObject()) { if(qgi->toGraphicsObject())
setupAnimation(qgi->toGraphicsObject(), "pos", qgi->pos(), qgi->pos() + actual_movement); setupAnimation(qgi->toGraphicsObject(), "pos", qgi->pos(), qgi->pos() + actual_movement);
else if(qgi->type() == QGraphicsItemGroup::Type) //ElementTextItemGroup is a QObject but not a QGraphicsObject
{
if(ElementTextItemGroup *etig = dynamic_cast<ElementTextItemGroup *>(qgi))
setupAnimation(etig, "pos", etig->pos(), etig->pos() + actual_movement);
} }
else qgi -> setPos(qgi->pos() + actual_movement); else qgi -> setPos(qgi->pos() + actual_movement);
} }
// Move some conductors // Move some conductors
foreach(Conductor *conductor, content_to_move.m_conductors_to_move) { for (Conductor *conductor : content_to_move.m_conductors_to_move)
setupAnimation(conductor, "pos", conductor->pos(), conductor->pos() + actual_movement); setupAnimation(conductor, "pos", conductor->pos(), conductor->pos() + actual_movement);
}
// Recalcul the path of other conductor // Recalcul the path of other conductor
foreach(Conductor *conductor, content_to_move.m_conductors_to_update) { for (Conductor *conductor : content_to_move.m_conductors_to_update)
setupAnimation(conductor, "animPath", 1, 1); setupAnimation(conductor, "animPath", 1, 1);
}
} }
/** /**
@@ -440,137 +445,6 @@ void ChangeDiagramTextCommand::redo() {
} }
} }
/**
Constructeur
@param elements Elements a pivoter associes a leur orientation d'origine
@param texts Textes a pivoter
@param parent QUndoCommand parent
*/
RotateElementsCommand::RotateElementsCommand(const QList<Element *> &elements, const QList<DiagramTextItem *> &texts, const QList<DiagramImageItem *> &images, QUndoCommand *parent) :
QUndoCommand(parent),
elements_to_rotate(elements),
texts_to_rotate(texts),
images_to_rotate(images),
applied_rotation_angle_(90.0)
{
if(elements_to_rotate.size()) diagram = elements_to_rotate.first()->diagram();
else if (texts_to_rotate.size()) diagram = texts_to_rotate.first()->diagram();
else if (images_to_rotate.size()) diagram = images_to_rotate.first()->diagram();
setText(
QString(
QObject::tr(
"pivoter %1",
"undo caption - %1 is a sentence listing the rotated content"
)
).arg(QET::ElementsAndConductorsSentence(elements.count(), 0, texts.count(), images.count()))
);
}
/// Destructeur
RotateElementsCommand::~RotateElementsCommand() {
}
/// defait le pivotement
void RotateElementsCommand::undo() {
diagram -> showMe();
foreach(Element *e, elements_to_rotate) {
e -> rotateBy(-applied_rotation_angle_);
}
foreach(DiagramTextItem *dti, texts_to_rotate) {
//ConductorTextItem have a default rotation angle, we apply a specific treatment
if (ConductorTextItem *cti = qgraphicsitem_cast<ConductorTextItem *>(dti)) {
cti -> forceRotateByUser(previous_rotate_by_user_[cti]);
(cti -> wasRotateByUser()) ? cti -> rotateBy(-applied_rotation_angle_) :
cti -> parentConductor() -> calculateTextItemPosition();
}
else {dti -> rotateBy(-applied_rotation_angle_);}
}
foreach(DiagramImageItem *dii, images_to_rotate) dii -> rotateBy(-applied_rotation_angle_);
}
/// refait le pivotement
void RotateElementsCommand::redo() {
diagram -> showMe();
foreach(Element *e, elements_to_rotate) {
e -> rotateBy(applied_rotation_angle_);
}
foreach(DiagramTextItem *dti, texts_to_rotate) {
//we grab the previous rotation by user of each ConductorTextItem
if (ConductorTextItem *cti = qgraphicsitem_cast<ConductorTextItem *>(dti)) {
previous_rotate_by_user_.insert(cti, cti -> wasRotateByUser());
cti -> forceRotateByUser(true);
}
dti -> rotateBy(applied_rotation_angle_);
}
foreach(DiagramImageItem *dii, images_to_rotate) dii -> rotateBy(applied_rotation_angle_);
}
/**
Constructeur
@param texts Liste des textes impactes par l'action. L'objet retiendra leur angle de rotation au moment de sa construction.
@param applied_rotation Nouvel angle de rotation, a appliquer au textes concernes
@param parent QUndoCommand parent
*/
RotateTextsCommand::RotateTextsCommand(const QList<DiagramTextItem *> &texts, double applied_rotation, QUndoCommand *parent) :
QUndoCommand(parent),
m_applied_rotation_angle(applied_rotation),
m_diagram(texts.first()->diagram())
{
foreach(DiagramTextItem *text, texts) {
m_texts_to_rotate.insert(text, text -> rotationAngle());
}
defineCommandName();
}
/**
Destructeur
*/
RotateTextsCommand::~RotateTextsCommand() {
}
/**
Annule la rotation des textes
*/
void RotateTextsCommand::undo() {
m_diagram -> showMe();
foreach(DiagramTextItem *text, m_texts_to_rotate.keys()) {
if (ConductorTextItem *cti = qgraphicsitem_cast<ConductorTextItem *>(text))
cti -> forceRotateByUser(m_previous_rotate_by_user[cti]);
text -> setRotationAngle(m_texts_to_rotate[text]);
}
}
/**
Applique l'angle de rotation aux textes
*/
void RotateTextsCommand::redo() {
m_diagram -> showMe();
foreach(DiagramTextItem *text, m_texts_to_rotate.keys()) {
if (ConductorTextItem *cti = qgraphicsitem_cast<ConductorTextItem *>(text)) {
//we grab the previous rotation by user of each ConductorTextItem
m_previous_rotate_by_user.insert(cti, cti -> wasRotateByUser());
cti -> forceRotateByUser(true);
}
text -> setRotationAngle(m_applied_rotation_angle);
}
}
/**
Definit le nom de la commande d'annulation
*/
void RotateTextsCommand::defineCommandName() {
setText(
QString(
QObject::tr(
"orienter %1 à %2°",
"undo caption - %1 looks like '42 texts', %2 is a rotation angle"
)
).arg(QET::ElementsAndConductorsSentence(0, 0, m_texts_to_rotate.count()))
.arg(m_applied_rotation_angle)
);
}
/** /**
Constructeur Constructeur
@param c Conducteur modifie @param c Conducteur modifie

View File

@@ -215,69 +215,6 @@ class ChangeDiagramTextCommand : public QUndoCommand {
Diagram *diagram; Diagram *diagram;
}; };
/**
This command rotates several elements or text items by a particular angle.
*/
class RotateElementsCommand : public QUndoCommand {
// constructors, destructor
public:
RotateElementsCommand(const QList<Element *> &elements, const QList<DiagramTextItem *> &, const QList<DiagramImageItem *> &, QUndoCommand * = nullptr);
~RotateElementsCommand() override;
private:
RotateElementsCommand(const RotateElementsCommand &);
// methods
public:
void undo() override;
void redo() override;
// attributes
private:
/// hold rotated elements along with their former orientation
QList<Element *> elements_to_rotate;
/// text items to be rotated
QList<DiagramTextItem *> texts_to_rotate;
/// images item to be rotated
QList<DiagramImageItem *> images_to_rotate;
/// angle of rotation to be applied to text items
qreal applied_rotation_angle_;
/// previous state of each conductor text item
QHash<ConductorTextItem *, bool> previous_rotate_by_user_;
Diagram *diagram;
};
/**
This command directs several text items to a same particular angle of
rotation.
*/
class RotateTextsCommand : public QUndoCommand
{
// constructors, destructor
public:
RotateTextsCommand(const QList<DiagramTextItem *> &, double, QUndoCommand * = nullptr);
~RotateTextsCommand() override;
private:
RotateTextsCommand(const RotateTextsCommand &);
// methods
public:
void undo() override;
void redo() override;
private:
void defineCommandName();
// attributes
private:
/// hold rotated text items along with their former angle of rotation
QHash<DiagramTextItem *, double> m_texts_to_rotate;
/// angle of rotation of all text items after the command
double m_applied_rotation_angle;
/// previous state of each conductor text item
QHash<ConductorTextItem *, bool> m_previous_rotate_by_user;
Diagram *m_diagram;
};
/** /**
This command changes a particular conductor. This command changes a particular conductor.
*/ */

View File

@@ -24,12 +24,73 @@
#include "elementtextitem.h" #include "elementtextitem.h"
#include "qetshapeitem.h" #include "qetshapeitem.h"
#include "dynamicelementtextitem.h" #include "dynamicelementtextitem.h"
#include "elementtextitemgroup.h"
#include "diagram.h"
#include "terminal.h"
#include "conductortextitem.h"
/** /**
* @brief DiagramContent::DiagramContent * @brief DiagramContent::DiagramContent
*/ */
DiagramContent::DiagramContent() {} DiagramContent::DiagramContent() {}
/**
* @brief DiagramContent::DiagramContent
* Constructor
* @param diagram : Construct a diagramContent and fill it with the selected item of @diagram
*/
DiagramContent::DiagramContent(Diagram *diagram) :
m_selected_items(diagram->selectedItems())
{
//Get the selected items
for (QGraphicsItem *item : m_selected_items)
{
if (Element *elmt = qgraphicsitem_cast<Element *>(item))
m_elements << elmt;
else if (IndependentTextItem *iti = qgraphicsitem_cast<IndependentTextItem *>(item))
m_text_fields << iti;
else if (Conductor *c = qgraphicsitem_cast<Conductor *>(item))
{
//Get the isolated selected conductor (= not movable, but deletable)
if (!c->terminal1->parentItem()->isSelected() &&\
!c->terminal2->parentItem()->isSelected()) {
m_other_conductors << c;
}
}
else if (DiagramImageItem *dii = qgraphicsitem_cast<DiagramImageItem *>(item))
m_images << dii;
else if (QetShapeItem *dsi = qgraphicsitem_cast<QetShapeItem *>(item))
m_shapes << dsi;
else if (DynamicElementTextItem *deti = qgraphicsitem_cast<DynamicElementTextItem *>(item))
m_element_texts << deti;
else if (QGraphicsItemGroup *group = qgraphicsitem_cast<QGraphicsItemGroup *>(item))
if(ElementTextItemGroup *etig = dynamic_cast<ElementTextItemGroup *>(group))
m_texts_groups << etig;
}
//For each selected element, we determine if conductors must be moved or updated.
for(Element *elmt : m_elements)
{
for(Terminal *terminal : elmt->terminals())
{
for(Conductor *conductor : terminal->conductors())
{
Terminal *other_terminal;
if (conductor->terminal1 == terminal)
other_terminal = conductor->terminal2;
else
other_terminal = conductor->terminal1;
//If the two elements of conductor are movable
if (m_elements.contains(other_terminal -> parentElement()))
m_conductors_to_move << conductor;
else
m_conductors_to_update << conductor;
}
}
}
}
/** /**
* @brief DiagramContent::DiagramContent * @brief DiagramContent::DiagramContent
* Copy constructor * Copy constructor
@@ -43,7 +104,9 @@ DiagramContent::DiagramContent(const DiagramContent &other) :
m_conductors_to_update(other.m_conductors_to_update), m_conductors_to_update(other.m_conductors_to_update),
m_conductors_to_move(other.m_conductors_to_move), m_conductors_to_move(other.m_conductors_to_move),
m_other_conductors(other.m_other_conductors), m_other_conductors(other.m_other_conductors),
m_element_texts(other.m_element_texts) m_element_texts(other.m_element_texts),
m_texts_groups(other.m_texts_groups),
m_selected_items(other.m_selected_items)
{} {}
/** /**
@@ -51,6 +114,47 @@ DiagramContent::DiagramContent(const DiagramContent &other) :
*/ */
DiagramContent::~DiagramContent() {} DiagramContent::~DiagramContent() {}
/**
* @brief DiagramContent::selectedTexts
* @return a list of every selected texts (every kind of texts)
* Note that the returned list of texts, correspond to the selected texts
* at the moment of the creation of this DiagramContent,
* with the constructor : DiagramContent::DiagramContent(Diagram *diagram)
*/
QList<DiagramTextItem *> DiagramContent::selectedTexts() const
{
QList<DiagramTextItem *> selected_texts;
for(QGraphicsItem *qgi : m_selected_items)
{
if (qgi->type() == ConductorTextItem::Type ||
qgi->type() == ElementTextItem::Type ||
qgi->type() == IndependentTextItem::Type ||
qgi->type() == DynamicElementTextItem::Type)
selected_texts << static_cast<DiagramTextItem *>(qgi);
}
return(selected_texts);
}
/**
* @brief DiagramContent::selectedTextsGroup
* @return a list of selected texts group
* Note that the returned list of texts group, correspond to the selected texts group
* at the moment of the creation of this DiagramContent,
* with the constructor : DiagramContent::DiagramContent(Diagram *diagram)
*/
QList<ElementTextItemGroup *> DiagramContent::selectedTextsGroup() const
{
QList<ElementTextItemGroup *> groups;
for(QGraphicsItem *qgi : m_selected_items)
if(qgi->type() == QGraphicsItemGroup::Type)
if(ElementTextItemGroup *grp = dynamic_cast<ElementTextItemGroup *>(qgi))
groups << grp;
return groups;
}
/** /**
* @brief DiagramContent::conductors * @brief DiagramContent::conductors
* @param filter * @param filter
@@ -84,6 +188,8 @@ void DiagramContent::clear()
m_conductors_to_move.clear(); m_conductors_to_move.clear();
m_other_conductors.clear(); m_other_conductors.clear();
m_element_texts.clear(); m_element_texts.clear();
m_texts_groups.clear();
m_selected_items.clear();
} }
/** /**
@@ -138,6 +244,7 @@ QList<QGraphicsItem *> DiagramContent::items(int filter) const
if (filter & Images) for(QGraphicsItem *qgi : m_images) items_list << qgi; if (filter & Images) for(QGraphicsItem *qgi : m_images) items_list << qgi;
if (filter & Shapes) for(QGraphicsItem *qgi : m_shapes) items_list << qgi; if (filter & Shapes) for(QGraphicsItem *qgi : m_shapes) items_list << qgi;
if (filter & ElementTextFields) for(QGraphicsItem *qgi : m_element_texts) items_list << qgi; if (filter & ElementTextFields) for(QGraphicsItem *qgi : m_element_texts) items_list << qgi;
if (filter & TextGroup) for(QGraphicsItem *qgi : m_texts_groups) items_list << qgi;
if (filter & SelectedOnly) { if (filter & SelectedOnly) {
for(QGraphicsItem *qgi : items_list) { for(QGraphicsItem *qgi : items_list) {
@@ -164,6 +271,7 @@ int DiagramContent::count(int filter) const
if (filter & ConductorsToUpdate) for(Conductor *conductor : m_conductors_to_update) { if (conductor -> isSelected()) ++ count; } if (filter & ConductorsToUpdate) for(Conductor *conductor : m_conductors_to_update) { if (conductor -> isSelected()) ++ count; }
if (filter & OtherConductors) for(Conductor *conductor : m_other_conductors) { if (conductor -> isSelected()) ++ count; } if (filter & OtherConductors) for(Conductor *conductor : m_other_conductors) { if (conductor -> isSelected()) ++ count; }
if (filter & ElementTextFields) for(DynamicElementTextItem *deti : m_element_texts) { if (deti -> isSelected()) ++ count; } if (filter & ElementTextFields) for(DynamicElementTextItem *deti : m_element_texts) { if (deti -> isSelected()) ++ count; }
if (filter & TextGroup) for(ElementTextItemGroup *etig : m_texts_groups) { if (etig -> isSelected()) ++ count; }
} }
else { else {
if (filter & Elements) count += m_elements.count(); if (filter & Elements) count += m_elements.count();
@@ -174,6 +282,7 @@ int DiagramContent::count(int filter) const
if (filter & ConductorsToUpdate) count += m_conductors_to_update.count(); if (filter & ConductorsToUpdate) count += m_conductors_to_update.count();
if (filter & OtherConductors) count += m_other_conductors.count(); if (filter & OtherConductors) count += m_other_conductors.count();
if (filter & ElementTextFields) count += m_element_texts.count(); if (filter & ElementTextFields) count += m_element_texts.count();
if (filter & TextGroup) count += m_texts_groups.count();
} }
return(count); return(count);
} }

View File

@@ -28,6 +28,9 @@ class DiagramImageItem;
class ElementTextItem; class ElementTextItem;
class QetShapeItem; class QetShapeItem;
class DynamicElementTextItem; class DynamicElementTextItem;
class ElementTextItemGroup;
class Diagram;
class DiagramTextItem;
/** /**
This class provides a container that makes the transmission of diagram content This class provides a container that makes the transmission of diagram content
@@ -42,6 +45,7 @@ class DiagramContent
{ {
public: public:
DiagramContent(); DiagramContent();
DiagramContent(Diagram *diagram);
DiagramContent(const DiagramContent &); DiagramContent(const DiagramContent &);
~DiagramContent(); ~DiagramContent();
@@ -56,8 +60,9 @@ class DiagramContent
OtherConductors = 64, OtherConductors = 64,
AnyConductor = 112, AnyConductor = 112,
Shapes = 128, Shapes = 128,
All = 255, TextGroup = 256,
SelectedOnly = 256 All = 511,
SelectedOnly = 512
}; };
QSet<Element *> m_elements; QSet<Element *> m_elements;
@@ -68,7 +73,11 @@ class DiagramContent
QSet<Conductor *> m_conductors_to_move; QSet<Conductor *> m_conductors_to_move;
QSet<Conductor *> m_other_conductors; QSet<Conductor *> m_other_conductors;
QSet<DynamicElementTextItem *> m_element_texts; QSet<DynamicElementTextItem *> m_element_texts;
QSet<ElementTextItemGroup *> m_texts_groups;
QList<QGraphicsItem *> m_selected_items;
QList<DiagramTextItem *> selectedTexts() const;
QList<ElementTextItemGroup *> selectedTextsGroup() const;
QList<Conductor *> conductors(int = AnyConductor) const; QList<Conductor *> conductors(int = AnyConductor) const;
QList<QGraphicsItem *> items(int = All) const; QList<QGraphicsItem *> items(int = All) const;
QString sentence(int = All) const; QString sentence(int = All) const;

View File

@@ -28,14 +28,12 @@
#include "qetgraphicsitem/independenttextitem.h" #include "qetgraphicsitem/independenttextitem.h"
#include "qetgraphicsitem/diagramimageitem.h" #include "qetgraphicsitem/diagramimageitem.h"
#include "templatelocation.h" #include "templatelocation.h"
#include "qetapp.h"
#include "qetproject.h" #include "qetproject.h"
#include "projectview.h" #include "projectview.h"
#include "integrationmovetemplateshandler.h" #include "integrationmovetemplateshandler.h"
#include "qetdiagrameditor.h" #include "qetdiagrameditor.h"
#include "qeticons.h" #include "qeticons.h"
#include "qetmessagebox.h" #include "qetmessagebox.h"
#include "qtextorientationspinboxwidget.h"
#include <QGraphicsObject> #include <QGraphicsObject>
#include <QGraphicsPixmapItem> #include <QGraphicsPixmapItem>
#include <QGraphicsSceneMouseEvent> #include <QGraphicsSceneMouseEvent>
@@ -136,111 +134,12 @@ void DiagramView::deleteSelection()
{ {
if (m_diagram -> isReadOnly()) if (m_diagram -> isReadOnly())
return; return;
DiagramContent removed_content = m_diagram->selectedContent(); DiagramContent removed_content = DiagramContent(m_diagram);
m_diagram->clearSelection(); m_diagram->clearSelection();
m_diagram->undoStack().push(new DeleteQGraphicsItemCommand(m_diagram, removed_content)); m_diagram->undoStack().push(new DeleteQGraphicsItemCommand(m_diagram, removed_content));
adjustSceneRect(); adjustSceneRect();
} }
/**
* @brief DiagramView::rotateSelection
* Rotate the selected items
*/
void DiagramView::rotateSelection()
{
if (m_diagram->isReadOnly())
return;
QList<Element *> elements_to_rotate;
QList<DiagramTextItem *> texts_to_rotate;
QList<DiagramImageItem *> images_to_rotate;
for (QGraphicsItem *item : m_diagram->selectedItems())
{
if (Element *e = qgraphicsitem_cast<Element *>(item))
elements_to_rotate << e;
else if (ConductorTextItem *cti = qgraphicsitem_cast<ConductorTextItem *>(item))
texts_to_rotate << cti;
else if (IndependentTextItem *iti = qgraphicsitem_cast<IndependentTextItem *>(item))
texts_to_rotate << iti;
else if (ElementTextItem *eti = qgraphicsitem_cast<ElementTextItem *>(item))
{
//We rotate element text item only if is parent element is not selected
if (eti->parentItem() && !eti->parentItem()->isSelected())
texts_to_rotate << eti;
}
else if (DynamicElementTextItem *deti = qgraphicsitem_cast<DynamicElementTextItem *>(item))
{
//We rotate dynamic element text item only if is parent element is not selected
if (deti->parentItem() && !deti->parentItem()->isSelected())
texts_to_rotate << deti;
}
else if (DiagramImageItem *dii = qgraphicsitem_cast<DiagramImageItem *>(item))
images_to_rotate << dii;
}
//Do the rotation
if (elements_to_rotate.isEmpty() && texts_to_rotate.isEmpty() && images_to_rotate.isEmpty())
return;
m_diagram->undoStack().push(new RotateElementsCommand(elements_to_rotate, texts_to_rotate, images_to_rotate));
}
/**
* @brief DiagramView::rotateTexts
* Open a dialog to set the rotation angle, and apply it to the selected texts.
*/
void DiagramView::rotateTexts()
{
if (m_diagram->isReadOnly())
return;
//Get the texts fields
QList<DiagramTextItem *> texts_to_rotate;
for (QGraphicsItem *item : m_diagram->selectedItems())
{
if (ConductorTextItem *cti = qgraphicsitem_cast<ConductorTextItem *>(item))
texts_to_rotate << cti;
else if (IndependentTextItem *iti = qgraphicsitem_cast<IndependentTextItem *>(item))
texts_to_rotate << iti;
else if (ElementTextItem *eti = qgraphicsitem_cast<ElementTextItem *>(item))
texts_to_rotate << eti;
else if (DynamicElementTextItem *deti = qgraphicsitem_cast<DynamicElementTextItem *>(item))
texts_to_rotate << deti;
}
if (texts_to_rotate.isEmpty())
return;
//Open the dialog
QDialog ori_text_dialog(diagramEditor());
ori_text_dialog.setSizeGripEnabled(false);
#ifdef Q_OS_MAC
ori_text_dialog.setWindowFlags(Qt::Sheet);
#endif
ori_text_dialog.setWindowTitle(tr("Orienter les textes sélectionnés", "window title"));
QTextOrientationSpinBoxWidget *ori_widget = QETApp::createTextOrientationSpinBoxWidget();
ori_widget -> setParent(&ori_text_dialog);
if (texts_to_rotate.count() == 1) {
ori_widget -> setOrientation(texts_to_rotate.at(0) -> rotationAngle());
}
ori_widget -> spinBox() -> selectAll();
QDialogButtonBox buttons(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
connect(&buttons, SIGNAL(accepted()), &ori_text_dialog, SLOT(accept()));
connect(&buttons, SIGNAL(rejected()), &ori_text_dialog, SLOT(reject()));
QVBoxLayout layout_v(&ori_text_dialog);
layout_v.setSizeConstraint(QLayout::SetFixedSize);
layout_v.addWidget(ori_widget);
layout_v.addStretch();
layout_v.addWidget(&buttons);
if (ori_text_dialog.exec() == QDialog::Accepted)
m_diagram -> undoStack().push(new RotateTextsCommand(texts_to_rotate, ori_widget -> orientation()));
}
/** /**
Accepte ou refuse le drag'n drop en fonction du type de donnees entrant Accepte ou refuse le drag'n drop en fonction du type de donnees entrant
@param e le QDragEnterEvent correspondant au drag'n drop tente @param e le QDragEnterEvent correspondant au drag'n drop tente
@@ -257,14 +156,6 @@ void DiagramView::dragEnterEvent(QDragEnterEvent *e) {
} }
} }
/**
Gere les dragleave
@param e le QDragEnterEvent correspondant au drag'n drop sortant
*/
void DiagramView::dragLeaveEvent(QDragLeaveEvent *e) {
Q_UNUSED(e);
}
/** /**
Accepte ou refuse le drag'n drop en fonction du type de donnees entrant Accepte ou refuse le drag'n drop en fonction du type de donnees entrant
@param e le QDragMoveEvent correspondant au drag'n drop tente @param e le QDragMoveEvent correspondant au drag'n drop tente
@@ -451,7 +342,7 @@ void DiagramView::zoomReset() {
*/ */
void DiagramView::cut() { void DiagramView::cut() {
copy(); copy();
DiagramContent cut_content = m_diagram -> selectedContent(); DiagramContent cut_content(m_diagram);
m_diagram -> clearSelection(); m_diagram -> clearSelection();
m_diagram -> undoStack().push(new CutDiagramCommand(m_diagram, cut_content)); m_diagram -> undoStack().push(new CutDiagramCommand(m_diagram, cut_content));
} }
@@ -651,6 +542,7 @@ void DiagramView::keyPressEvent(QKeyEvent *e)
return; return;
ProjectView *current_project = this->diagramEditor()->acessCurrentProject(); ProjectView *current_project = this->diagramEditor()->acessCurrentProject();
DiagramContent dc(m_diagram);
switch(e -> key()) switch(e -> key())
{ {
case Qt::Key_PageUp: case Qt::Key_PageUp:
@@ -702,22 +594,22 @@ void DiagramView::keyPressEvent(QKeyEvent *e)
} }
break; break;
case Qt::Key_Up: { case Qt::Key_Up: {
if(!(m_diagram->selectedContent().items(DiagramContent::All).isEmpty())) if(!(dc.items(DiagramContent::All).isEmpty()))
scrollOnMovement(e); scrollOnMovement(e);
} }
break; break;
case Qt::Key_Down: { case Qt::Key_Down: {
if(!(m_diagram->selectedContent().items(DiagramContent::All).isEmpty())) if(!(dc.items(DiagramContent::All).isEmpty()))
scrollOnMovement(e); scrollOnMovement(e);
} }
break; break;
case Qt::Key_Left: { case Qt::Key_Left: {
if(!(m_diagram->selectedContent().items(DiagramContent::All).isEmpty())) if(!(dc.items(DiagramContent::All).isEmpty()))
scrollOnMovement(e); scrollOnMovement(e);
} }
break; break;
case Qt::Key_Right: { case Qt::Key_Right: {
if(!(m_diagram->selectedContent().items(DiagramContent::All).isEmpty())) if(!(dc.items(DiagramContent::All).isEmpty()))
scrollOnMovement(e); scrollOnMovement(e);
} }
break; break;
@@ -743,8 +635,9 @@ void DiagramView::keyReleaseEvent(QKeyEvent *e) {
and horizontal bar. If element is moved to the right side of the editor and horizontal bar. If element is moved to the right side of the editor
or below the editor SceneRect is expanded or below the editor SceneRect is expanded
*/ */
void DiagramView::scrollOnMovement(QKeyEvent *e){ void DiagramView::scrollOnMovement(QKeyEvent *e)
QList<QGraphicsItem *> selected_elmts = m_diagram->selectedContent().items(DiagramContent::All); {
QList<QGraphicsItem *> selected_elmts = DiagramContent(m_diagram).items(DiagramContent::All);
QRectF viewed_scene = viewedSceneRect(); QRectF viewed_scene = viewedSceneRect();
foreach (QGraphicsItem *qgi, selected_elmts){ foreach (QGraphicsItem *qgi, selected_elmts){
if (qgraphicsitem_cast<Conductor *>(qgi)) continue; if (qgraphicsitem_cast<Conductor *>(qgi)) continue;
@@ -822,13 +715,6 @@ void DiagramView::editDiagramProperties() {
DiagramPropertiesDialog::diagramPropertiesDialog(m_diagram, diagramEditor()); DiagramPropertiesDialog::diagramPropertiesDialog(m_diagram, diagramEditor());
} }
/**
@return true s'il y a des items selectionnes sur le schema, false sinon
*/
bool DiagramView::hasSelectedItems() {
return(m_diagram -> selectedItems().size() > 0);
}
/** /**
@return true s'il y a des items selectionnes sur le schema et que ceux-ci @return true s'il y a des items selectionnes sur le schema et que ceux-ci
peuvent etre copies dans le presse-papier, false sinon peuvent etre copies dans le presse-papier, false sinon
@@ -1011,11 +897,13 @@ void DiagramView::applyReadOnly() {
} }
/** /**
Edite les proprietes des objets selectionnes * @brief DiagramView::editSelectionProperties
*/ * Edit the properties of the selected items
void DiagramView::editSelectionProperties() { */
void DiagramView::editSelectionProperties()
{
// get selection // get selection
DiagramContent selection = m_diagram -> selectedContent(); DiagramContent selection(m_diagram);
// if selection contains nothing return // if selection contains nothing return
int selected_items_count = selection.count(DiagramContent::All | DiagramContent::SelectedOnly); int selected_items_count = selection.count(DiagramContent::All | DiagramContent::SelectedOnly);
@@ -1048,11 +936,13 @@ void DiagramView::editSelectionProperties() {
} }
/** /**
Edit the color of the selected conductor; does nothing if multiple conductors are selected * @brief DiagramView::editSelectedConductorColor
*/ * Edit the color of the selected conductor; does nothing if multiple conductors are selected
void DiagramView::editSelectedConductorColor() { */
// retrieve selected content void DiagramView::editSelectedConductorColor()
DiagramContent selection = m_diagram -> selectedContent(); {
//retrieve selected content
DiagramContent selection(m_diagram);
// we'll focus on the selected conductor (we do not handle multiple conductors edition) // we'll focus on the selected conductor (we do not handle multiple conductors edition)
QList<Conductor *> selected_conductors = selection.conductors(DiagramContent::AnyConductor | DiagramContent::SelectedOnly); QList<Conductor *> selected_conductors = selection.conductors(DiagramContent::AnyConductor | DiagramContent::SelectedOnly);

View File

@@ -49,10 +49,10 @@ class DiagramView : public QGraphicsView
// attributes // attributes
Diagram *m_diagram; Diagram *m_diagram = nullptr;
DVEventInterface *m_event_interface = nullptr; DVEventInterface *m_event_interface = nullptr;
QMenu *m_context_menu; QMenu *m_context_menu = nullptr;
QAction *m_paste_here; QAction *m_paste_here = nullptr;
QPoint m_paste_here_pos; QPoint m_paste_here_pos;
QPointF m_rubber_band_origin; QPointF m_rubber_band_origin;
bool m_fresh_focus_in, bool m_fresh_focus_in,
@@ -64,10 +64,8 @@ class DiagramView : public QGraphicsView
void removeColumn(); void removeColumn();
void addRow(); void addRow();
void removeRow(); void removeRow();
/// @return the diagram rendered by this view
Diagram *diagram() { return(m_diagram); } Diagram *diagram() { return(m_diagram); }
QETDiagramEditor *diagramEditor() const; QETDiagramEditor *diagramEditor() const;
bool hasSelectedItems();
bool hasCopiableItems(); bool hasCopiableItems();
bool hasTextItems(); bool hasTextItems();
bool hasDeletableItems(); bool hasDeletableItems();
@@ -92,7 +90,6 @@ class DiagramView : public QGraphicsView
void mouseMoveEvent(QMouseEvent *) override; void mouseMoveEvent(QMouseEvent *) override;
void mouseReleaseEvent(QMouseEvent *) override; void mouseReleaseEvent(QMouseEvent *) override;
void dragEnterEvent(QDragEnterEvent *) override; void dragEnterEvent(QDragEnterEvent *) override;
void dragLeaveEvent(QDragLeaveEvent *) override;
void dragMoveEvent(QDragMoveEvent *) override; void dragMoveEvent(QDragMoveEvent *) override;
void dropEvent(QDropEvent *) override; void dropEvent(QDropEvent *) override;
void handleElementDrop(QDropEvent *); void handleElementDrop(QDropEvent *);
@@ -123,8 +120,6 @@ class DiagramView : public QGraphicsView
void selectAll(); void selectAll();
void selectInvert(); void selectInvert();
void deleteSelection(); void deleteSelection();
void rotateSelection();
void rotateTexts();
void setVisualisationMode(); void setVisualisationMode();
void setSelectionMode(); void setSelectionMode();
void zoom(const qreal zoom_factor); void zoom(const qreal zoom_factor);

View File

@@ -33,8 +33,8 @@ ElementsMover::ElementsMover() :
movement_running_(false), movement_running_(false),
current_movement_(), current_movement_(),
diagram_(nullptr), diagram_(nullptr),
movement_driver_(nullptr), m_movement_driver(nullptr),
moved_content_() m_moved_content()
{ {
} }
@@ -70,21 +70,21 @@ int ElementsMover::beginMovement(Diagram *diagram, QGraphicsItem *driver_item) {
diagram_ = diagram; diagram_ = diagram;
// Take count of driver item // Take count of driver item
movement_driver_ = driver_item; m_movement_driver = driver_item;
// At the beginning of movement, move is NULL // At the beginning of movement, move is NULL
current_movement_ = QPointF(0.0, 0.0); current_movement_ = QPointF(0.0, 0.0);
moved_content_ = diagram -> selectedContent(); m_moved_content = DiagramContent(diagram);
moved_content_.removeNonMovableItems(); m_moved_content.removeNonMovableItems();
if (!moved_content_.count()) return(-1); if (!m_moved_content.count()) return(-1);
/* At this point, we've got all info to manage movement. /* At this point, we've got all info to manage movement.
* There is now a move in progress */ * There is now a move in progress */
movement_running_ = true; movement_running_ = true;
return(moved_content_.count()); return(m_moved_content.count());
} }
/** /**
@@ -99,18 +99,20 @@ void ElementsMover::continueMovement(const QPointF &movement) {
//Move every movable item, except conductor //Move every movable item, except conductor
typedef DiagramContent dc; typedef DiagramContent dc;
foreach (QGraphicsItem *qgi, moved_content_.items(dc::Elements | dc::TextFields | dc::Images | dc::Shapes)) { for (QGraphicsItem *qgi : m_moved_content.items(dc::Elements | dc::TextFields | dc::Images | dc::Shapes | dc::TextGroup))
if (qgi == movement_driver_) continue; {
if (qgi == m_movement_driver)
continue;
qgi -> setPos(qgi->pos() + movement); qgi -> setPos(qgi->pos() + movement);
} }
// Move some conductors // Move some conductors
foreach(Conductor *conductor, moved_content_.m_conductors_to_move) { foreach(Conductor *conductor, m_moved_content.m_conductors_to_move) {
conductor -> setPos(conductor -> pos() + movement); conductor -> setPos(conductor -> pos() + movement);
} }
// Recalcul the path of other conductors // Recalcul the path of other conductors
foreach(Conductor *conductor, moved_content_.m_conductors_to_update) { foreach(Conductor *conductor, m_moved_content.m_conductors_to_update) {
conductor -> updatePath(); conductor -> updatePath();
} }
} }
@@ -131,18 +133,18 @@ void ElementsMover::endMovement()
//Create undo move if there is a movement //Create undo move if there is a movement
if (!current_movement_.isNull()) { if (!current_movement_.isNull()) {
QUndoCommand *quc = new MoveElementsCommand(diagram_, moved_content_, current_movement_, undo_object); QUndoCommand *quc = new MoveElementsCommand(diagram_, m_moved_content, current_movement_, undo_object);
undo_object->setText(quc->text()); undo_object->setText(quc->text());
} }
//There is only one element moved, and project authorize auto conductor, //There is only one element moved, and project authorize auto conductor,
//we try auto connection of conductor; //we try auto connection of conductor;
typedef DiagramContent dc; typedef DiagramContent dc;
if (moved_content_.items(dc::TextFields | dc::Images | dc::Shapes).size() == 0 && if (m_moved_content.items(dc::TextFields | dc::Images | dc::Shapes).size() == 0 &&
moved_content_.items(dc::Elements).size() == 1 && m_moved_content.items(dc::Elements).size() == 1 &&
diagram_ -> project() -> autoConductor()) diagram_ -> project() -> autoConductor())
{ {
Element *elmt = moved_content_.m_elements.toList().first(); Element *elmt = m_moved_content.m_elements.toList().first();
int acc = elmt->AlignedFreeTerminals().size(); int acc = elmt->AlignedFreeTerminals().size();

View File

@@ -55,7 +55,7 @@ class ElementsMover {
bool movement_running_; bool movement_running_;
QPointF current_movement_; QPointF current_movement_;
Diagram *diagram_; Diagram *diagram_;
QGraphicsItem *movement_driver_; QGraphicsItem *m_movement_driver;
DiagramContent moved_content_; DiagramContent m_moved_content;
}; };
#endif #endif

View File

@@ -45,6 +45,8 @@
#include "dynamicelementtextitem.h" #include "dynamicelementtextitem.h"
#include "conductortextitem.h" #include "conductortextitem.h"
#include "elementtextitem.h" #include "elementtextitem.h"
#include "undocommand/rotateselectioncommand.h"
#include "rotatetextscommand.h"
#include <QMessageBox> #include <QMessageBox>
#include <QStandardPaths> #include <QStandardPaths>
@@ -1038,12 +1040,15 @@ DiagramView *QETDiagramEditor::currentDiagram() const {
* no element is selected * no element is selected
* more than one element is selected * more than one element is selected
*/ */
Element *QETDiagramEditor::currentElement() const { Element *QETDiagramEditor::currentElement() const
{
DiagramView *dv = currentDiagram(); DiagramView *dv = currentDiagram();
if (!dv) return(nullptr); if (!dv)
return(nullptr);
QList<Element *> selected_elements = dv -> diagram() -> selectedContent().m_elements.toList(); QList<Element *> selected_elements = DiagramContent(dv->diagram()).m_elements.toList();
if (selected_elements.count() != 1) return(nullptr); if (selected_elements.count() != 1)
return(nullptr);
return(selected_elements.first()); return(selected_elements.first());
} }
@@ -1262,9 +1267,17 @@ void QETDiagramEditor::selectionGroupTriggered(QAction *action)
if (value == "delete_selection") if (value == "delete_selection")
dv->deleteSelection(); dv->deleteSelection();
else if (value == "rotate_selection") else if (value == "rotate_selection")
dv->rotateSelection(); {
Diagram *d = dv->diagram();
RotateSelectionCommand *c = new RotateSelectionCommand(d);
if(c->isValid())
d->undoStack().push(c);
}
else if (value == "rotate_selected_text") else if (value == "rotate_selected_text")
dv->rotateTexts(); {
Diagram *d = dv->diagram();
d->undoStack().push(new RotateTextsCommand(d));
}
else if (value == "find_selected_element" && currentCustomElement()) else if (value == "find_selected_element" && currentCustomElement())
findElementInPanel(currentCustomElement()->location()); findElementInPanel(currentCustomElement()->location());
else if (value == "edit_selected_element") else if (value == "edit_selected_element")
@@ -1400,6 +1413,7 @@ void QETDiagramEditor::slot_updateComplexActions()
} }
Diagram *diagram_ = dv->diagram(); Diagram *diagram_ = dv->diagram();
DiagramContent dc(diagram_);
bool ro = diagram_->isReadOnly(); bool ro = diagram_->isReadOnly();
@@ -1408,7 +1422,7 @@ void QETDiagramEditor::slot_updateComplexActions()
m_conductor_reset->setEnabled(!ro && selected_conductors_count); m_conductor_reset->setEnabled(!ro && selected_conductors_count);
// number of selected elements // number of selected elements
int selected_elements_count = diagram_->selectedContent().count(DiagramContent::Elements); int selected_elements_count = dc.count(DiagramContent::Elements);
m_find_element->setEnabled(selected_elements_count == 1); m_find_element->setEnabled(selected_elements_count == 1);
//Action that need items (elements, conductors, texts...) selected, to be enabled //Action that need items (elements, conductors, texts...) selected, to be enabled
@@ -1419,17 +1433,19 @@ void QETDiagramEditor::slot_updateComplexActions()
m_delete_selection -> setEnabled(!ro && deletable_items); m_delete_selection -> setEnabled(!ro && deletable_items);
m_rotate_selection -> setEnabled(!ro && diagram_->canRotateSelection()); m_rotate_selection -> setEnabled(!ro && diagram_->canRotateSelection());
//Action that need selected texts //Action that need selected texts or texts group
int selected_texts = diagram_->selectedTexts().count(); QList<DiagramTextItem *> texts = DiagramContent(diagram_).selectedTexts();
int selected_conductor_texts = 0; for(DiagramTextItem *dti : diagram_->selectedTexts()) {if(dti->type() == ConductorTextItem::Type) selected_conductor_texts++;} QList<ElementTextItemGroup *> groups = DiagramContent(diagram_).selectedTextsGroup();
int selected_element_texts = 0; for(DiagramTextItem *dti : diagram_->selectedTexts()) {if(dti->type() == ElementTextItem::Type) selected_element_texts++;} int selected_texts = texts.count();
int selected_dynamic_elmt_text = 0; for(DiagramTextItem *dti : diagram_->selectedTexts()) {if(dti->type() == DynamicElementTextItem::Type) selected_dynamic_elmt_text++;} int selected_conductor_texts = 0; for(DiagramTextItem *dti : texts) {if(dti->type() == ConductorTextItem::Type) selected_conductor_texts++;}
m_rotate_texts -> setEnabled(!ro && selected_texts); int selected_element_texts = 0; for(DiagramTextItem *dti : texts) {if(dti->type() == ElementTextItem::Type) selected_element_texts++;}
int selected_dynamic_elmt_text = 0; for(DiagramTextItem *dti : texts) {if(dti->type() == DynamicElementTextItem::Type) selected_dynamic_elmt_text++;}
m_rotate_texts->setEnabled(!ro && (selected_texts || groups.size()));
// actions need only one editable item // actions need only one editable item
int selected_image = diagram_-> selectedContent().count(DiagramContent::Images); int selected_image = dc.count(DiagramContent::Images);
int selected_shape = diagram_-> selectedContent().count(DiagramContent::Shapes); int selected_shape = dc.count(DiagramContent::Shapes);
int selected_editable = selected_elements_count + int selected_editable = selected_elements_count +
(selected_texts - selected_conductor_texts - selected_element_texts - selected_dynamic_elmt_text) + (selected_texts - selected_conductor_texts - selected_element_texts - selected_dynamic_elmt_text) +
selected_image + selected_image +

View File

@@ -20,6 +20,7 @@
#include "element.h" #include "element.h"
#include "diagram.h" #include "diagram.h"
#include "addelementtextcommand.h" #include "addelementtextcommand.h"
#include "QPropertyUndoCommand/qpropertyundocommand.h"
#include <QPainter> #include <QPainter>
#include <QGraphicsSceneMouseEvent> #include <QGraphicsSceneMouseEvent>
@@ -37,7 +38,7 @@ ElementTextItemGroup::ElementTextItemGroup(const QString &name, Element *parent)
QGraphicsItemGroup(parent), QGraphicsItemGroup(parent),
m_name(name) m_name(name)
{ {
setFlags(QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsFocusable); setFlags(QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemIsMovable);
} }
ElementTextItemGroup::~ElementTextItemGroup() ElementTextItemGroup::~ElementTextItemGroup()
@@ -127,7 +128,6 @@ void ElementTextItemGroup::updateAlignment()
item->setPos(ref.x(), ref.y()+y_offset); item->setPos(ref.x(), ref.y()+y_offset);
y_offset+=item->boundingRect().height(); y_offset+=item->boundingRect().height();
} }
return;
} }
else if(m_alignment == Qt::AlignVCenter) else if(m_alignment == Qt::AlignVCenter)
{ {
@@ -140,8 +140,6 @@ void ElementTextItemGroup::updateAlignment()
ref.y() + y_offset); ref.y() + y_offset);
y_offset+=item->boundingRect().height(); y_offset+=item->boundingRect().height();
} }
return;
} }
else if (m_alignment == Qt::AlignRight) else if (m_alignment == Qt::AlignRight)
{ {
@@ -154,8 +152,9 @@ void ElementTextItemGroup::updateAlignment()
ref.y() + y_offset); ref.y() + y_offset);
y_offset+=item->boundingRect().height(); y_offset+=item->boundingRect().height();
} }
return;
} }
setTransformOriginPoint(boundingRect().topLeft());
} }
} }
@@ -381,26 +380,30 @@ void ElementTextItemGroup::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
*/ */
void ElementTextItemGroup::keyPressEvent(QKeyEvent *event) void ElementTextItemGroup::keyPressEvent(QKeyEvent *event)
{ {
if(event->key() == Qt::Key_A && m_alignment != Qt::AlignLeft) if(event->modifiers() == Qt::ControlModifier)
{
if(event->key() == Qt::Key_Left && m_alignment != Qt::AlignLeft)
{ {
if(diagram()) if(diagram())
diagram()->undoStack().push(new AlignmentTextsGroupCommand(this, Qt::AlignLeft)); diagram()->undoStack().push(new AlignmentTextsGroupCommand(this, Qt::AlignLeft));
else else
setAlignment(Qt::AlignLeft); setAlignment(Qt::AlignLeft);
} }
else if (event->key() == Qt::Key_Z && m_alignment != Qt::AlignVCenter) else if (event->key() == Qt::Key_Up && m_alignment != Qt::AlignVCenter)
{ {
if(diagram()) if(diagram())
diagram()->undoStack().push(new AlignmentTextsGroupCommand(this, Qt::AlignVCenter)); diagram()->undoStack().push(new AlignmentTextsGroupCommand(this, Qt::AlignVCenter));
else else
setAlignment(Qt::AlignVCenter); setAlignment(Qt::AlignVCenter);
} }
else if (event->key() == Qt::Key_E && m_alignment != Qt::AlignRight) else if (event->key() == Qt::Key_Right && m_alignment != Qt::AlignRight)
{ {
if(diagram()) if(diagram())
diagram()->undoStack().push(new AlignmentTextsGroupCommand(this, Qt::AlignRight)); diagram()->undoStack().push(new AlignmentTextsGroupCommand(this, Qt::AlignRight));
else else
setAlignment(Qt::AlignRight); setAlignment(Qt::AlignRight);
} }
}
event->ignore();
} }

View File

@@ -36,6 +36,7 @@ class ElementTextItemGroup : public QObject, public QGraphicsItemGroup
Q_OBJECT Q_OBJECT
Q_PROPERTY(QPointF pos READ pos WRITE setPos) Q_PROPERTY(QPointF pos READ pos WRITE setPos)
Q_PROPERTY(qreal rotation READ rotation WRITE setRotation)
public: public:
ElementTextItemGroup(const QString &name, Element *parent); ElementTextItemGroup(const QString &name, Element *parent);

View File

@@ -0,0 +1,154 @@
/*
Copyright 2006-2017 The QElectroTech Team
This file is part of QElectroTech.
QElectroTech 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.
QElectroTech is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with QElectroTech. If not, see <http://www.gnu.org/licenses/>.
*/
#include "rotateselectioncommand.h"
#include "element.h"
#include "conductortextitem.h"
#include "independenttextitem.h"
#include "elementtextitem.h"
#include "dynamicelementtextitem.h"
#include "elementtextitemgroup.h"
#include "diagramimageitem.h"
#include "diagram.h"
#include "conductor.h"
#include <QGraphicsItem>
RotateSelectionCommand::RotateSelectionCommand(Diagram *diagram, qreal angle, QUndoCommand *parent) :
QUndoCommand(parent),
m_diagram(diagram),
m_angle(angle)
{
setText(QObject::tr("Pivoter la selection"));
if(!m_diagram->isReadOnly())
{
for (QGraphicsItem *item : m_diagram->selectedItems())
{
switch (item->type())
{
case Element::Type:
m_element << static_cast<Element *>(item);
break;
case ConductorTextItem::Type:
m_text << static_cast<DiagramTextItem *>(item);
break;
case IndependentTextItem::Type:
m_text << static_cast<DiagramTextItem *>(item);
break;
case ElementTextItem::Type:
if(item->parentItem() && !item->parentItem()->isSelected())
m_text << static_cast<DiagramTextItem *>(item);
break;
case DynamicElementTextItem::Type:
if(item->parentItem() && !item->parentItem()->isSelected())
m_text << static_cast<DiagramTextItem *>(item);
break;
case QGraphicsItemGroup::Type:
if(ElementTextItemGroup *grp = dynamic_cast<ElementTextItemGroup *>(item))
if(grp->parentElement() && !grp->parentElement()->isSelected())
m_group << grp;
break;
case DiagramImageItem::Type:
m_image << static_cast<DiagramImageItem *>(item);
break;
default:
break;
}
}
}
}
/**
* @brief RotateSelectionCommand::undo
*/
void RotateSelectionCommand::undo()
{
m_diagram->showMe();
for(QPointer<Element> elmt : m_element)
if(elmt)
elmt.data()->rotateBy(-m_angle);
for(QPointer<DiagramTextItem> text : m_text)
{
if(text)
{
if(text.data()->type() == ConductorTextItem::Type)
{
ConductorTextItem *cti = static_cast<ConductorTextItem *>(text.data());
cti->forceRotateByUser(m_rotate_by_user.value(text.data()));
if(cti->wasRotateByUser())
cti->rotateBy(-m_angle);
else
cti->parentConductor()->calculateTextItemPosition();
}
else
text.data()->rotateBy(-m_angle);
}
}
for(QPointer<DiagramImageItem> image : m_image)
if(image)
image.data()->rotateBy(-m_angle);
for(QPointer<ElementTextItemGroup> group : m_group)
if(group)
group.data()->setRotation(group.data()->rotation() - m_angle);
}
/**
* @brief RotateSelectionCommand::redo
*/
void RotateSelectionCommand::redo()
{
m_diagram->showMe();
for(QPointer<Element> elmt : m_element)
if(elmt)
elmt.data()->rotateBy(m_angle);
for(QPointer<DiagramTextItem> text : m_text)
{
if(text)
{
if(text.data()->type() == ConductorTextItem::Type)
{
ConductorTextItem *cti = static_cast<ConductorTextItem *>(text.data());
m_rotate_by_user.insert(text.data(), cti->wasRotateByUser());
cti->forceRotateByUser(true);
}
text.data()->rotateBy(m_angle);
}
}
for(QPointer<DiagramImageItem> image : m_image)
if(image)
image.data()->rotateBy(m_angle);
for(QPointer<ElementTextItemGroup> group : m_group)
if(group)
group.data()->setRotation(group.data()->rotation() + m_angle);
}
/**
* @brief RotateSelectionCommand::isValid
* @return true if this command rotate a least one item.
*/
bool RotateSelectionCommand::isValid()
{
if(m_element.size()) return true;
if(m_image.size()) return true;
if(m_group.size()) return true;
if(m_text.size()) return true;
return false;
}

View File

@@ -0,0 +1,56 @@
/*
Copyright 2006-2017 The QElectroTech Team
This file is part of QElectroTech.
QElectroTech 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.
QElectroTech is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with QElectroTech. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ROTATESELECTIONCOMMAND_H
#define ROTATESELECTIONCOMMAND_H
#include <QUndoCommand>
#include <QPointer>
class Diagram;
class Element;
class QGraphicsObject;
class ElementTextItemGroup;
class DiagramTextItem;
class DiagramImageItem;
/**
* @brief The RotateSelectionCommand class
* Rotate the selected items in the given diagram
*/
class RotateSelectionCommand : public QUndoCommand
{
public:
RotateSelectionCommand(Diagram *diagram, qreal angle=90, QUndoCommand *parent=nullptr);
void undo() override;
void redo() override;
bool isValid();
private:
Diagram *m_diagram =nullptr;
qreal m_angle;
QList<QPointer<Element>> m_element;
QList<QPointer<DiagramImageItem>> m_image;
QList<QPointer<ElementTextItemGroup>> m_group;
QList<QPointer<DiagramTextItem>> m_text;
QHash<DiagramTextItem *, bool> m_rotate_by_user;
};
#endif // ROTATESELECTIONCOMMAND_H

View File

@@ -0,0 +1,152 @@
/*
Copyright 2006-2017 The QElectroTech Team
This file is part of QElectroTech.
QElectroTech 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.
QElectroTech is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with QElectroTech. If not, see <http://www.gnu.org/licenses/>.
*/
#include "rotatetextscommand.h"
#include "diagramcontent.h"
#include "diagram.h"
#include "diagramtextitem.h"
#include "elementtextitemgroup.h"
#include "conductortextitem.h"
#include "qetapp.h"
#include "qtextorientationspinboxwidget.h"
/**
* @brief RotateTextsCommand::RotateTextsCommand
* @param diagram : Apply the rotation to the selected texts and group of texts
* of diagram at construction time.
* @param parent : undo parent
*/
RotateTextsCommand::RotateTextsCommand(Diagram *diagram, QUndoCommand *parent) :
QUndoCommand(parent),
m_diagram(diagram)
{
DiagramContent dc(m_diagram);
QList <DiagramTextItem *> texts_list;
QList <ElementTextItemGroup *> groups_list;
for(DiagramTextItem *dti : dc.selectedTexts())
{
texts_list << dti;
if(dti->type() == ConductorTextItem::Type)
{
ConductorTextItem *cti = static_cast<ConductorTextItem *>(dti);
m_cond_texts.insert(cti, cti->wasRotateByUser());
}
}
for(ElementTextItemGroup *etig : dc.selectedTextsGroup())
groups_list << etig;
if(texts_list.count() || groups_list.count())
{
openDialog();
QString text;
if(texts_list.count())
text.append(QObject::tr("Pivoter %1 textes").arg(texts_list.count()));
if(groups_list.count())
{
if(text.isEmpty())
text.append(QObject::tr("Pivoter"));
else
text.append(QObject::tr(" et"));
text.append(QObject::tr(" %1 groupes de textes").arg(groups_list.count()));
}
if(!text.isNull())
setText(text);
for(DiagramTextItem *dti : texts_list)
setupAnimation(dti, "rotation", dti->rotation(), m_rotation);
for(ElementTextItemGroup *grp : groups_list)
setupAnimation(grp, "rotation", grp->rotation(), m_rotation);
}
#if QT_VERSION >= 0x050900
else
setObsolete(true);
#endif
}
void RotateTextsCommand::undo()
{
if(m_diagram)
m_diagram.data()->showMe();
m_anim_group->setDirection(QAnimationGroup::Backward);
m_anim_group->start();
for(ConductorTextItem *cti : m_cond_texts.keys())
cti->forceMovedByUser(m_cond_texts.value(cti));
}
void RotateTextsCommand::redo()
{
if(m_diagram)
m_diagram.data()->showMe();
m_anim_group->setDirection(QAnimationGroup::Forward);
m_anim_group->start();
for(ConductorTextItem *cti : m_cond_texts.keys())
cti->forceMovedByUser(true);
}
void RotateTextsCommand::openDialog()
{
//Open the dialog
QDialog ori_text_dialog;
ori_text_dialog.setSizeGripEnabled(false);
#ifdef Q_OS_MAC
ori_text_dialog.setWindowFlags(Qt::Sheet);
#endif
ori_text_dialog.setWindowTitle(QObject::tr("Orienter les textes sélectionnés", "window title"));
QTextOrientationSpinBoxWidget *ori_widget = QETApp::createTextOrientationSpinBoxWidget();
ori_widget->setParent(&ori_text_dialog);
ori_widget->spinBox()->selectAll();
QDialogButtonBox buttons(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
QObject::connect(&buttons, SIGNAL(accepted()), &ori_text_dialog, SLOT(accept()));
QObject::connect(&buttons, SIGNAL(rejected()), &ori_text_dialog, SLOT(reject()));
QVBoxLayout layout_v(&ori_text_dialog);
layout_v.setSizeConstraint(QLayout::SetFixedSize);
layout_v.addWidget(ori_widget);
layout_v.addStretch();
layout_v.addWidget(&buttons);
if (ori_text_dialog.exec() == QDialog::Accepted)
m_rotation = ori_widget->orientation();
#if QT_VERSION >= 0x050900
else
setObsolete(true);
#endif
}
void RotateTextsCommand::setupAnimation(QObject *target, const QByteArray &propertyName, const QVariant start, const QVariant end)
{
if(m_anim_group == nullptr)
m_anim_group = new QParallelAnimationGroup();
QPropertyAnimation *animation = new QPropertyAnimation(target, propertyName);
animation->setDuration(300);
animation->setStartValue(start);
animation->setEndValue(end);
animation->setEasingCurve(QEasingCurve::OutQuad);
m_anim_group->addAnimation(animation);
}

View File

@@ -0,0 +1,52 @@
/*
Copyright 2006-2017 The QElectroTech Team
This file is part of QElectroTech.
QElectroTech 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.
QElectroTech is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with QElectroTech. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ROTATETEXTSCOMMAND_H
#define ROTATETEXTSCOMMAND_H
#include <QUndoCommand>
#include <QPointer>
class ConductorTextItem;
class Diagram;
class QParallelAnimationGroup;
/**
* @brief The RotateTextsCommand class
* Open a dialog for edit the rotation of the current selected texts and texts group in diagram.
* Just instantiate this undo command and push it in a QUndoStack.
*/
class RotateTextsCommand : public QUndoCommand
{
public:
RotateTextsCommand(Diagram *diagram, QUndoCommand *parent=nullptr);
void undo() override;
void redo() override;
private:
void openDialog();
void setupAnimation(QObject *target, const QByteArray &propertyName, const QVariant start, const QVariant end);
private:
QPointer<Diagram> m_diagram;
QHash<ConductorTextItem *, bool> m_cond_texts;
qreal m_rotation=0;
QParallelAnimationGroup *m_anim_group = nullptr;
};
#endif // ROTATETEXTSCOMMAND_H