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 "diagramview.h"
#include "dynamicelementtextitem.h"
#include "elementtextitemgroup.h"
#include "undocommand/addelementtextcommand.h"
const int Diagram::xGrid = 10;
const int Diagram::yGrid = 10;
@@ -291,10 +293,10 @@ void Diagram::wheelEvent(QGraphicsSceneWheelEvent *event)
* Else move selected elements
* @param e
*/
void Diagram::keyPressEvent(QKeyEvent *e)
void Diagram::keyPressEvent(QKeyEvent *event)
{
if (m_event_interface)
if(m_event_interface->keyPressEvent(e))
if(m_event_interface->keyPressEvent(event))
{
if(!m_event_interface->isRunning())
{
@@ -303,45 +305,77 @@ void Diagram::keyPressEvent(QKeyEvent *e)
return;
}
bool transmit_event = true;
if (!isReadOnly()) {
if (!isReadOnly())
{
QPointF movement;
qreal top_position = 0;
qreal left_position = 0;
QList<QGraphicsItem*> selected_elmts = this->selectedContent().items();
if (!this->selectedContent().items(DiagramContent::All).isEmpty()) {
switch(e -> key()) {
DiagramContent dc(this);
if (!dc.items(DiagramContent::All).isEmpty())
{
//Move item with the keyborb arrow
if(event->modifiers() == Qt::NoModifier)
{
switch(event->key())
{
case Qt::Key_Left:
foreach (Element *item, selectedContent().m_elements) {
for (Element *item : dc.m_elements)
{
left_position = item->mapRectFromScene(item->boundingRect()).x();
if (left_position >= this->sceneRect().left() - item->boundingRect().width())
return;
}
movement = QPointF(-xGrid, 0.0);
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:
foreach (Element *item, selectedContent().m_elements) {
for(Element *item : dc.m_elements)
{
top_position = item->mapRectFromScene(item->boundingRect()).y();
if (top_position >= this->sceneRect().top() - item->boundingRect().height())
return;
}
movement = QPointF(0.0, -yGrid);
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();
continueMoveElements(movement);
e -> accept();
transmit_event = false;
event->accept();
return;
}
}
if (transmit_event) {
QGraphicsScene::keyPressEvent(e);
else if(event->modifiers() == Qt::ControlModifier)
{
//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);
}
}
/**
* @brief Diagram::keyReleaseEvent
@@ -1659,25 +1693,6 @@ QSet<Conductor *> Diagram::selectedConductors() const {
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
bool Diagram::clipboardMayContainDiagram() {
QString clipboard_text = QApplication::clipboard() -> text().trimmed();
@@ -1760,62 +1775,6 @@ DiagramContent Diagram::content() const {
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
* @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() == ElementTextItem::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;

View File

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

View File

@@ -26,6 +26,7 @@
#include "diagram.h"
#include "qetgraphicsitem/diagramtextitem.h"
#include "qetgraphicsitem/diagramimageitem.h"
#include "elementtextitemgroup.h"
#include <QPropertyAnimation>
QString itemText(const QetGraphicsItem *item) {
@@ -266,33 +267,37 @@ void MoveElementsCommand::redo() {
* Move item and conductor to @actual_movement
* @param actual_movement movement to be applied
*/
void MoveElementsCommand::move(const QPointF &actual_movement) {
void MoveElementsCommand::move(const QPointF &actual_movement)
{
typedef DiagramContent dc;
//Move every movable item, except conductor
foreach (QGraphicsItem *qgi, content_to_move.items(dc::Elements | dc::TextFields | dc::Images | dc::Shapes)) {
//Move every movable items, except conductor
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
//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()))
continue;
}
if(qgi->toGraphicsObject()) {
if(qgi->toGraphicsObject())
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);
}
// 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);
}
// 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);
}
}
/**
* @brief MoveElementsCommand::setupAnimation
@@ -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
@param c Conducteur modifie

View File

@@ -215,69 +215,6 @@ class ChangeDiagramTextCommand : public QUndoCommand {
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.
*/

View File

@@ -24,12 +24,73 @@
#include "elementtextitem.h"
#include "qetshapeitem.h"
#include "dynamicelementtextitem.h"
#include "elementtextitemgroup.h"
#include "diagram.h"
#include "terminal.h"
#include "conductortextitem.h"
/**
* @brief 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
* Copy constructor
@@ -43,7 +104,9 @@ DiagramContent::DiagramContent(const DiagramContent &other) :
m_conductors_to_update(other.m_conductors_to_update),
m_conductors_to_move(other.m_conductors_to_move),
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() {}
/**
* @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
* @param filter
@@ -84,6 +188,8 @@ void DiagramContent::clear()
m_conductors_to_move.clear();
m_other_conductors.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 & Shapes) for(QGraphicsItem *qgi : m_shapes) 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) {
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 & 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 & TextGroup) for(ElementTextItemGroup *etig : m_texts_groups) { if (etig -> isSelected()) ++ count; }
}
else {
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 & OtherConductors) count += m_other_conductors.count();
if (filter & ElementTextFields) count += m_element_texts.count();
if (filter & TextGroup) count += m_texts_groups.count();
}
return(count);
}

View File

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

View File

@@ -28,14 +28,12 @@
#include "qetgraphicsitem/independenttextitem.h"
#include "qetgraphicsitem/diagramimageitem.h"
#include "templatelocation.h"
#include "qetapp.h"
#include "qetproject.h"
#include "projectview.h"
#include "integrationmovetemplateshandler.h"
#include "qetdiagrameditor.h"
#include "qeticons.h"
#include "qetmessagebox.h"
#include "qtextorientationspinboxwidget.h"
#include <QGraphicsObject>
#include <QGraphicsPixmapItem>
#include <QGraphicsSceneMouseEvent>
@@ -136,111 +134,12 @@ void DiagramView::deleteSelection()
{
if (m_diagram -> isReadOnly())
return;
DiagramContent removed_content = m_diagram->selectedContent();
DiagramContent removed_content = DiagramContent(m_diagram);
m_diagram->clearSelection();
m_diagram->undoStack().push(new DeleteQGraphicsItemCommand(m_diagram, removed_content));
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
@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
@param e le QDragMoveEvent correspondant au drag'n drop tente
@@ -451,7 +342,7 @@ void DiagramView::zoomReset() {
*/
void DiagramView::cut() {
copy();
DiagramContent cut_content = m_diagram -> selectedContent();
DiagramContent cut_content(m_diagram);
m_diagram -> clearSelection();
m_diagram -> undoStack().push(new CutDiagramCommand(m_diagram, cut_content));
}
@@ -651,6 +542,7 @@ void DiagramView::keyPressEvent(QKeyEvent *e)
return;
ProjectView *current_project = this->diagramEditor()->acessCurrentProject();
DiagramContent dc(m_diagram);
switch(e -> key())
{
case Qt::Key_PageUp:
@@ -702,22 +594,22 @@ void DiagramView::keyPressEvent(QKeyEvent *e)
}
break;
case Qt::Key_Up: {
if(!(m_diagram->selectedContent().items(DiagramContent::All).isEmpty()))
if(!(dc.items(DiagramContent::All).isEmpty()))
scrollOnMovement(e);
}
break;
case Qt::Key_Down: {
if(!(m_diagram->selectedContent().items(DiagramContent::All).isEmpty()))
if(!(dc.items(DiagramContent::All).isEmpty()))
scrollOnMovement(e);
}
break;
case Qt::Key_Left: {
if(!(m_diagram->selectedContent().items(DiagramContent::All).isEmpty()))
if(!(dc.items(DiagramContent::All).isEmpty()))
scrollOnMovement(e);
}
break;
case Qt::Key_Right: {
if(!(m_diagram->selectedContent().items(DiagramContent::All).isEmpty()))
if(!(dc.items(DiagramContent::All).isEmpty()))
scrollOnMovement(e);
}
break;
@@ -743,8 +635,9 @@ void DiagramView::keyReleaseEvent(QKeyEvent *e) {
and horizontal bar. If element is moved to the right side of the editor
or below the editor SceneRect is expanded
*/
void DiagramView::scrollOnMovement(QKeyEvent *e){
QList<QGraphicsItem *> selected_elmts = m_diagram->selectedContent().items(DiagramContent::All);
void DiagramView::scrollOnMovement(QKeyEvent *e)
{
QList<QGraphicsItem *> selected_elmts = DiagramContent(m_diagram).items(DiagramContent::All);
QRectF viewed_scene = viewedSceneRect();
foreach (QGraphicsItem *qgi, selected_elmts){
if (qgraphicsitem_cast<Conductor *>(qgi)) continue;
@@ -822,13 +715,6 @@ void DiagramView::editDiagramProperties() {
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
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
DiagramContent selection = m_diagram -> selectedContent();
DiagramContent selection(m_diagram);
// if selection contains nothing return
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() {
void DiagramView::editSelectedConductorColor()
{
//retrieve selected content
DiagramContent selection = m_diagram -> selectedContent();
DiagramContent selection(m_diagram);
// we'll focus on the selected conductor (we do not handle multiple conductors edition)
QList<Conductor *> selected_conductors = selection.conductors(DiagramContent::AnyConductor | DiagramContent::SelectedOnly);

View File

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

View File

@@ -33,8 +33,8 @@ ElementsMover::ElementsMover() :
movement_running_(false),
current_movement_(),
diagram_(nullptr),
movement_driver_(nullptr),
moved_content_()
m_movement_driver(nullptr),
m_moved_content()
{
}
@@ -70,21 +70,21 @@ int ElementsMover::beginMovement(Diagram *diagram, QGraphicsItem *driver_item) {
diagram_ = diagram;
// Take count of driver item
movement_driver_ = driver_item;
m_movement_driver = driver_item;
// At the beginning of movement, move is NULL
current_movement_ = QPointF(0.0, 0.0);
moved_content_ = diagram -> selectedContent();
moved_content_.removeNonMovableItems();
m_moved_content = DiagramContent(diagram);
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.
* There is now a move in progress */
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
typedef DiagramContent dc;
foreach (QGraphicsItem *qgi, moved_content_.items(dc::Elements | dc::TextFields | dc::Images | dc::Shapes)) {
if (qgi == movement_driver_) continue;
for (QGraphicsItem *qgi : m_moved_content.items(dc::Elements | dc::TextFields | dc::Images | dc::Shapes | dc::TextGroup))
{
if (qgi == m_movement_driver)
continue;
qgi -> setPos(qgi->pos() + movement);
}
// 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);
}
// 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();
}
}
@@ -131,18 +133,18 @@ void ElementsMover::endMovement()
//Create undo move if there is a movement
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());
}
//There is only one element moved, and project authorize auto conductor,
//we try auto connection of conductor;
typedef DiagramContent dc;
if (moved_content_.items(dc::TextFields | dc::Images | dc::Shapes).size() == 0 &&
moved_content_.items(dc::Elements).size() == 1 &&
if (m_moved_content.items(dc::TextFields | dc::Images | dc::Shapes).size() == 0 &&
m_moved_content.items(dc::Elements).size() == 1 &&
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();

View File

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

View File

@@ -45,6 +45,8 @@
#include "dynamicelementtextitem.h"
#include "conductortextitem.h"
#include "elementtextitem.h"
#include "undocommand/rotateselectioncommand.h"
#include "rotatetextscommand.h"
#include <QMessageBox>
#include <QStandardPaths>
@@ -1038,12 +1040,15 @@ DiagramView *QETDiagramEditor::currentDiagram() const {
* no element is selected
* more than one element is selected
*/
Element *QETDiagramEditor::currentElement() const {
Element *QETDiagramEditor::currentElement() const
{
DiagramView *dv = currentDiagram();
if (!dv) return(nullptr);
if (!dv)
return(nullptr);
QList<Element *> selected_elements = dv -> diagram() -> selectedContent().m_elements.toList();
if (selected_elements.count() != 1) return(nullptr);
QList<Element *> selected_elements = DiagramContent(dv->diagram()).m_elements.toList();
if (selected_elements.count() != 1)
return(nullptr);
return(selected_elements.first());
}
@@ -1262,9 +1267,17 @@ void QETDiagramEditor::selectionGroupTriggered(QAction *action)
if (value == "delete_selection")
dv->deleteSelection();
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")
dv->rotateTexts();
{
Diagram *d = dv->diagram();
d->undoStack().push(new RotateTextsCommand(d));
}
else if (value == "find_selected_element" && currentCustomElement())
findElementInPanel(currentCustomElement()->location());
else if (value == "edit_selected_element")
@@ -1400,6 +1413,7 @@ void QETDiagramEditor::slot_updateComplexActions()
}
Diagram *diagram_ = dv->diagram();
DiagramContent dc(diagram_);
bool ro = diagram_->isReadOnly();
@@ -1408,7 +1422,7 @@ void QETDiagramEditor::slot_updateComplexActions()
m_conductor_reset->setEnabled(!ro && selected_conductors_count);
// 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);
//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_rotate_selection -> setEnabled(!ro && diagram_->canRotateSelection());
//Action that need selected texts
int selected_texts = diagram_->selectedTexts().count();
int selected_conductor_texts = 0; for(DiagramTextItem *dti : diagram_->selectedTexts()) {if(dti->type() == ConductorTextItem::Type) selected_conductor_texts++;}
int selected_element_texts = 0; for(DiagramTextItem *dti : diagram_->selectedTexts()) {if(dti->type() == ElementTextItem::Type) selected_element_texts++;}
int selected_dynamic_elmt_text = 0; for(DiagramTextItem *dti : diagram_->selectedTexts()) {if(dti->type() == DynamicElementTextItem::Type) selected_dynamic_elmt_text++;}
m_rotate_texts -> setEnabled(!ro && selected_texts);
//Action that need selected texts or texts group
QList<DiagramTextItem *> texts = DiagramContent(diagram_).selectedTexts();
QList<ElementTextItemGroup *> groups = DiagramContent(diagram_).selectedTextsGroup();
int selected_texts = texts.count();
int selected_conductor_texts = 0; for(DiagramTextItem *dti : texts) {if(dti->type() == ConductorTextItem::Type) selected_conductor_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
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 +
(selected_texts - selected_conductor_texts - selected_element_texts - selected_dynamic_elmt_text) +
selected_image +

View File

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

View File

@@ -36,6 +36,7 @@ class ElementTextItemGroup : public QObject, public QGraphicsItemGroup
Q_OBJECT
Q_PROPERTY(QPointF pos READ pos WRITE setPos)
Q_PROPERTY(qreal rotation READ rotation WRITE setRotation)
public:
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