/*
Copyright 2006-2020 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 .
*/
#include "dynamicelementtextmodel.h"
#include "../QPropertyUndoCommand/qpropertyundocommand.h"
#include "../diagram.h"
#include "../qetapp.h"
#include "../qetgraphicsitem/conductor.h"
#include "../qetgraphicsitem/dynamicelementtextitem.h"
#include "../qetgraphicsitem/element.h"
#include "../qetgraphicsitem/elementtextitemgroup.h"
#include "../qetgraphicsitem/terminal.h"
#include "../qeticons.h"
#include "../qetinformation.h"
#include "../undocommand/addelementtextcommand.h"
#include "alignmenttextdialog.h"
#include "compositetexteditdialog.h"
#include
#include
#include
#include
#include
#include
static int src_txt_row = 0;
static int usr_txt_row = 1;
static int info_txt_row = 2;
static int compo_txt_row = 3;
static int size_txt_row = 4;
static int font_txt_row = 5;
static int color_txt_row = 6;
static int frame_txt_row = 7;
static int width_txt_row = 8;
static int x_txt_row = 9;
static int y_txt_row = 10;
static int rot_txt_row = 11;
static int keep_rot_row = 12;
static int align_txt_row = 13;
static int align_grp_row = 0;
static int x_grp_row = 1;
static int y_grp_row = 2;
static int rot_grp_row = 3;
static int adjust_grp_row = 4;
static int frame_grp_row = 5;
static int hold_to_bottom_grp_row = 6;
DynamicElementTextModel::DynamicElementTextModel(Element *element, QObject *parent) :
QStandardItemModel(parent),
m_element(element)
{
setColumnCount(2);
setHeaderData(0, Qt::Horizontal, tr("Propriété"), Qt::DisplayRole);
setHeaderData(1, Qt::Horizontal, tr("Valeur"), Qt::DisplayRole);
connect(this, &DynamicElementTextModel::itemChanged, this, &DynamicElementTextModel::itemDataChanged);
connect(m_element.data(), &Element::textsGroupAdded, this, &DynamicElementTextModel::addGroup, Qt::DirectConnection);
connect(m_element.data(), &Element::textsGroupAboutToBeRemoved, this, &DynamicElementTextModel::removeGroup, Qt::DirectConnection);
connect(m_element.data(), &Element::textRemoved, this, &DynamicElementTextModel::removeText, Qt::DirectConnection);
connect(m_element.data(), &Element::textRemovedFromGroup, this, &DynamicElementTextModel::removeTextFromGroup, Qt::DirectConnection);
connect(m_element.data(), &Element::textAdded, this, &DynamicElementTextModel::addText, Qt::DirectConnection);
connect(m_element.data(), &Element::textAddedToGroup, this, &DynamicElementTextModel::addTextToGroup, Qt::DirectConnection);
for (ElementTextItemGroup *grp : m_element.data()->textGroups())
addGroup(grp);
for (DynamicElementTextItem *deti : m_element.data()->dynamicTextItems())
this->appendRow(itemsForText(deti));
}
DynamicElementTextModel::~DynamicElementTextModel()
{
//Connection is not destroy automaticaly,
//because was not connected to a slot, but a lambda
for(DynamicElementTextItem *deti : m_hash_text_connect.keys())
setConnection(deti, false);
for(ElementTextItemGroup *group : m_hash_group_connect.keys())
setConnection(group, false);
}
/**
@brief DynamicElementTextModel::indexIsInGroup
@param index
@return True if the index represent a group or an item in a group
*/
bool DynamicElementTextModel::indexIsInGroup(const QModelIndex &index) const
{
QStandardItem *item = itemFromIndex(index);
if(item)
{
while (item->parent())
item = item->parent();
if(m_groups_list.values().contains(item))
return true;
else
return false;
}
return false;
}
/**
@brief DynamicElementTextModel::itemsForText
@param deti
@return The items for the text deti,
if the text deti is already managed by this model
the returned list is empty
The returned items haven't got the same number
of childs if the text is in a group or not.
*/
QList DynamicElementTextModel::itemsForText(
DynamicElementTextItem *deti)
{
QList qsi_list;
if(m_texts_list.keys().contains(deti))
return qsi_list;
QStandardItem *qsi = new QStandardItem(deti->toPlainText());
qsi->setFlags(Qt::ItemIsSelectable
| Qt::ItemIsEnabled
|Qt::ItemIsDragEnabled);
qsi->setIcon(QET::Icons::PartText);
//Source of text
QStandardItem *src = new QStandardItem(tr("Source du texte"));
src->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
QString title;
if (deti->textFrom() == DynamicElementTextItem::UserText)
title = tr("Texte utilisateur");
else if (deti->textFrom() == DynamicElementTextItem::ElementInfo)
title = tr("Information de l'élément");
else title = tr("Texte composé");
QStandardItem *srca = new QStandardItem(title);
srca->setFlags(Qt::ItemIsSelectable
| Qt::ItemIsEnabled
| Qt::ItemIsEditable);
srca->setData(textFrom, Qt::UserRole+1);
qsi_list << src << srca;
qsi->appendRow(qsi_list);
//User text
QStandardItem *usr = new QStandardItem(tr("Texte"));
usr->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
QStandardItem *usra = new QStandardItem(deti->toPlainText());
usra->setFlags(Qt::ItemIsSelectable
| Qt::ItemIsEnabled
| Qt::ItemIsEditable);
usra->setData(DynamicElementTextModel::userText, Qt::UserRole+1);
qsi_list.clear();
qsi_list << usr << usra;
qsi->appendRow(qsi_list);
//Info text
QStandardItem *info = new QStandardItem(tr("Information"));
info->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
QStandardItem *infoa =
new QStandardItem(
QETInformation::translatedInfoKey(
deti->infoName()));
infoa->setFlags(Qt::ItemIsSelectable
| Qt::ItemIsEnabled
| Qt::ItemIsEditable);
//Use to know the edited thing
infoa->setData(DynamicElementTextModel::infoText, Qt::UserRole+1);
//Use to know to element info name
infoa->setData(deti->infoName(), Qt::UserRole+2);
qsi_list.clear();
qsi_list << info << infoa;
qsi->appendRow(qsi_list);
//Composite text
QStandardItem *composite = new QStandardItem(tr("Texte composé"));
composite->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
DiagramContext dc;
if(deti->elementUseForInfo())
dc = deti->elementUseForInfo()->elementInformations();
QStandardItem *compositea = new QStandardItem(deti->compositeText().isEmpty()
? tr("Mon texte composé")
: autonum::AssignVariables::replaceVariable(
deti->compositeText(), dc));
compositea->setFlags(Qt::ItemIsSelectable
| Qt::ItemIsEnabled
| Qt::ItemIsEditable);
//Use to know the edited thing
compositea->setData(DynamicElementTextModel::compositeText,
Qt::UserRole+1);
//Use to know to element composite formula
compositea->setData(deti->compositeText(), Qt::UserRole+2);
qsi_list.clear();
qsi_list << composite << compositea;
qsi->appendRow(qsi_list);
//Size
QStandardItem *size = new QStandardItem(tr("Taille"));
size->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
QStandardItem *siza = new QStandardItem();
siza->setData(deti->font().pointSize(), Qt::EditRole);
siza->setData(DynamicElementTextModel::size, Qt::UserRole+1);
siza->setFlags(Qt::ItemIsSelectable
| Qt::ItemIsEnabled
| Qt::ItemIsEditable);
qsi_list.clear();
qsi_list << size << siza;
qsi->appendRow(qsi_list);
//Font
QStandardItem *font = new QStandardItem(tr("Police"));
font->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
QStandardItem *fonta = new QStandardItem();
fonta->setData(deti->font().family(), Qt::EditRole);
fonta->setData(DynamicElementTextModel::font, Qt::UserRole+1);
fonta->setData(deti->font(), Qt::UserRole+2);
fonta->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsEditable);
qsi_list.clear();
qsi_list << font << fonta;
qsi->appendRow(qsi_list);
//Color
QStandardItem *color = new QStandardItem(tr("Couleur"));
color->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
QStandardItem *colora = new QStandardItem;
colora->setData(deti->color(), Qt::ForegroundRole);
colora->setData(deti->color(), Qt::EditRole);
colora->setData(DynamicElementTextModel::color, Qt::UserRole+1);
colora->setFlags(Qt::ItemIsSelectable
| Qt::ItemIsEnabled
| Qt::ItemIsEditable);
qsi_list.clear();
qsi_list << color << colora;
qsi->appendRow(qsi_list);
//Frame
QStandardItem *frame = new QStandardItem(tr("Cadre"));
frame->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
QStandardItem *frame_a = new QStandardItem;
frame_a->setCheckable(true);
frame_a->setCheckState(deti->frame()? Qt::Checked : Qt::Unchecked);
frame_a->setData(DynamicElementTextModel::frame, Qt::UserRole+1);
frame_a->setFlags(Qt::ItemIsSelectable
| Qt::ItemIsEnabled
| Qt::ItemIsUserCheckable);
qsi_list.clear();
qsi_list << frame << frame_a;
qsi->appendRow(qsi_list);
//Width
QStandardItem *width = new QStandardItem(tr("Largeur"));
width->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
QStandardItem *width_a = new QStandardItem;
width_a->setData(deti->textWidth(), Qt::EditRole);
width_a->setData(DynamicElementTextModel::textWidth, Qt::UserRole+1);
width_a->setFlags(Qt::ItemIsSelectable
| Qt::ItemIsEnabled
| Qt::ItemIsEditable);
qsi_list.clear();
qsi_list << width << width_a;
qsi->appendRow(qsi_list);
if(deti->parentGroup() == nullptr)
{
//X pos
QStandardItem *x_pos = new QStandardItem(tr("Position X"));
x_pos->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
QStandardItem *x_pos_a = new QStandardItem;
x_pos_a->setData(deti->pos().x(), Qt::EditRole);
x_pos_a->setData(DynamicElementTextModel::pos, Qt::UserRole+1);
x_pos_a->setFlags(Qt::ItemIsSelectable
| Qt::ItemIsEnabled
| Qt::ItemIsEditable);
qsi_list.clear();
qsi_list << x_pos << x_pos_a;
qsi->appendRow(qsi_list);
//Y pos
QStandardItem *y_pos = new QStandardItem(tr("Position Y"));
y_pos->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
QStandardItem *y_pos_a = new QStandardItem;
y_pos_a->setData(deti->pos().y(), Qt::EditRole);
y_pos_a->setData(DynamicElementTextModel::pos, Qt::UserRole+1);
y_pos_a->setFlags(Qt::ItemIsSelectable
| Qt::ItemIsEnabled
| Qt::ItemIsEditable);
qsi_list.clear();
qsi_list << y_pos << y_pos_a;
qsi->appendRow(qsi_list);
//Rotation
QStandardItem *rot = new QStandardItem(tr("Rotation"));
rot->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
QStandardItem *rot_a = new QStandardItem;
rot_a->setData(deti->rotation(), Qt::EditRole);
rot_a->setData(DynamicElementTextModel::rotation,
Qt::UserRole+1);
rot_a->setFlags(Qt::ItemIsSelectable
| Qt::ItemIsEnabled
| Qt::ItemIsEditable);
qsi_list.clear();
qsi_list << rot << rot_a;
qsi->appendRow(qsi_list);
//keep visual rotation
auto keep_rotation = new QStandardItem(tr("Conserver la rotation visuel"));
keep_rotation->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
auto keep_rotation_a = new QStandardItem;
keep_rotation_a->setCheckable(true);
keep_rotation_a->setCheckState(deti->keepVisualRotation() ? Qt::Checked : Qt::Unchecked);
keep_rotation_a->setData(DynamicElementTextModel::keepVisualRotation, Qt::UserRole+1);
keep_rotation_a->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsUserCheckable);
qsi_list.clear();
qsi_list << keep_rotation << keep_rotation_a;
qsi->appendRow(qsi_list);
//Alignment
QStandardItem *alignment = new QStandardItem(tr("Alignement"));
alignment->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
QStandardItem *alignmenta = new QStandardItem(tr("Éditer"));
alignmenta->setFlags(Qt::ItemIsSelectable
| Qt::ItemIsEnabled
| Qt::ItemIsEditable);
alignmenta->setData(DynamicElementTextModel::txtAlignment,
Qt::UserRole+1);
alignmenta->setData(QVariant::fromValue(deti->alignment()),
Qt::UserRole+2);
qsi_list.clear();
qsi_list << alignment << alignmenta;
qsi->appendRow(qsi_list);
}
qsi_list.clear();
QStandardItem *empty_qsi = new QStandardItem(0);
empty_qsi->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
qsi_list << qsi << empty_qsi;
m_texts_list.insert(deti, qsi);
blockSignals(true);
enableSourceText(deti, deti->textFrom());
blockSignals(false);
setConnection(deti, true);
return qsi_list;
}
/**
@brief DynamicElementTextModel::addText
@param deti
*/
void DynamicElementTextModel::addText(DynamicElementTextItem *deti)
{
this->appendRow(itemsForText(deti));
}
/**
@brief DynamicElementTextModel::removeText
@param deti
*/
void DynamicElementTextModel::removeText(DynamicElementTextItem *deti)
{
if (!m_texts_list.contains(deti))
return;
QModelIndex text_index = m_texts_list.value(deti)->index();
this->removeRow(text_index.row(), text_index.parent());
m_texts_list.remove(deti);
setConnection(deti, false);
}
/**
@brief DynamicElementTextModel::textFromIndex
@param index
@return the text associated with index. Returned value can be nullptr
Index can be a child of an index associated with a text
and can be the column 0 or 1.
*/
DynamicElementTextItem *DynamicElementTextModel::textFromIndex(
const QModelIndex &index) const
{
if(!index.isValid())
return nullptr;
if (QStandardItem *item = itemFromIndex(index))
return textFromItem(item);
else
return nullptr;
}
/**
@brief DynamicElementTextModel::textFromItem
@param item
@return the text associated with item. Return value can be nullptr
item can be a child of an item associated with a text
and can be the column 0 or 1.
Note can return nullptr
*/
DynamicElementTextItem *DynamicElementTextModel::textFromItem(
QStandardItem *item) const
{
//Get the item of the column 0
if(item->column() == 1)
{
if(item->parent())
item = item->parent()->child(item->row(), 0);
else
item = itemFromIndex(index(item->row(),0));
}
//Item haven't got parent, so they can be only a text or a group
if(!item->parent())
{
if(m_texts_list.values().contains(item))
return m_texts_list.key(item);
else
return nullptr;
}
QStandardItem *text_item = item;
while (text_item->parent())
text_item = text_item->parent();
if (m_texts_list.values().contains(text_item)) //The item is a text
return m_texts_list.key(text_item);
else if (m_groups_list.values().contains(text_item)) //The item is a group
{
QStandardItem *previous = item;
QStandardItem *top = item;
//At the end of the while, previous must be the text
//and top the group
while(top->parent())
{
previous = top;
top = top->parent();
}
if(m_texts_list.values().contains(previous))
return m_texts_list.key(previous);
else
return nullptr;
}
else
return nullptr;
}
/**
@brief DynamicElementTextModel::indexFromText
@param text
@return the QModelIndex for text, or a default QModelIndex if not match
*/
QModelIndex DynamicElementTextModel::indexFromText(
DynamicElementTextItem *text) const
{
if(m_texts_list.contains(text))
return m_texts_list.value(text)->index();
else
return QModelIndex();
}
/**
@brief DynamicElementTextModel::undoForEditedText
@param deti
@param parent_undo
@return A QUndoCommand that describe all changes made for deti.
Each change made for deti is append as a child of the returned QUndoCommand.
In other word, if the returned QUndoCommand have no child,
that mean there is no change.
*/
QUndoCommand *DynamicElementTextModel::undoForEditedText(
DynamicElementTextItem *deti,
QUndoCommand *parent_undo) const
{
QUndoCommand *undo = nullptr;
if(parent_undo)
undo = parent_undo;
else
undo = new QUndoCommand(tr("Éditer un texte d'élément"));
if (!m_texts_list.contains(deti))
return undo;
QStandardItem *text_qsi = m_texts_list.value(deti);
QString from = text_qsi->child(src_txt_row,1)->data(Qt::DisplayRole).toString();
if ((from == tr("Texte utilisateur")) && (deti->textFrom() != DynamicElementTextItem::UserText))
new QPropertyUndoCommand(deti, "textFrom", QVariant(deti->textFrom()), QVariant(DynamicElementTextItem::UserText), undo);
else if ((from == tr("Information de l'élément")) && (deti->textFrom() != DynamicElementTextItem::ElementInfo))
new QPropertyUndoCommand(deti, "textFrom", QVariant(deti->textFrom()), QVariant(DynamicElementTextItem::ElementInfo), undo);
else if ((from == tr("Texte composé")) && (deti->textFrom() != DynamicElementTextItem::CompositeText))
new QPropertyUndoCommand(deti, "textFrom", QVariant(deti->textFrom()), QVariant(DynamicElementTextItem::CompositeText), undo);
if(from == tr("Texte utilisateur"))
{
QString text = text_qsi->child(usr_txt_row,1)->data(Qt::DisplayRole).toString();
if (text != deti->text())
new QPropertyUndoCommand(deti, "text", QVariant(deti->text()), QVariant(text), undo);
}
else if (from == tr("Information de l'élément"))
{
QString info_name = text_qsi->child(info_txt_row,1)->data(Qt::UserRole+2).toString();
if(info_name != deti->infoName())
new QPropertyUndoCommand(deti, "infoName", QVariant(deti->infoName()), QVariant(info_name), undo);
}
else if (from == tr("Texte composé"))
{
QString composite_text = text_qsi->child(compo_txt_row,1)->data(Qt::UserRole+2).toString();
if(composite_text != deti->compositeText())
new QPropertyUndoCommand(deti, "compositeText", QVariant(deti->compositeText()), QVariant(composite_text), undo);
}
int fs = text_qsi->child(size_txt_row,1)->data(Qt::EditRole).toInt();
if (fs != deti->font().pointSize())
{
QFont font = deti->font();
font.setPointSize(fs);
QPropertyUndoCommand *quc = new QPropertyUndoCommand(deti, "font", QVariant(deti->font()), QVariant(font), undo);
quc->setText(tr("Modifier la taille d'un texte d'élément"));
}
QFont font = text_qsi->child(font_txt_row, 1)->data(Qt::UserRole+2).value();
if (font != deti->font())
{
QPropertyUndoCommand *quc = new QPropertyUndoCommand(deti, "font", QVariant(deti->font()), QVariant(font), undo);
quc->setText(tr("Modifier la police d'un texte d'élément"));
}
QColor color = text_qsi->child(color_txt_row,1)->data(Qt::EditRole).value();
if(color != deti->color())
{
QUndoCommand *quc = new QPropertyUndoCommand(deti, "color", QVariant(deti->color()), QVariant(color), undo);
quc->setText(tr("Modifier la couleur d'un texte d'élément"));
}
bool frame = text_qsi->child(frame_txt_row,1)->checkState() == Qt::Checked? true : false;
if(frame != deti->frame())
{
QUndoCommand *quc = new QPropertyUndoCommand(deti, "frame", QVariant(deti->frame()), QVariant(frame), undo);
quc->setText(tr("Modifier le cadre d'un texte d'élément"));
}
qreal text_width = text_qsi->child(width_txt_row, 1)->data(Qt::EditRole).toDouble();
if(text_width != deti->textWidth())
{
QPropertyUndoCommand *quc = new QPropertyUndoCommand(deti, "textWidth", QVariant(deti->textWidth()), QVariant(text_width), undo);
quc->setAnimated(true, false);
quc->setText(tr("Modifier la largeur d'un texte d'élément"));
}
//When text is in a group, they're isn't item for position of the text
if(text_qsi->child(x_txt_row,1) && text_qsi->child(y_txt_row,1))
{
QPointF p(text_qsi->child(x_txt_row,1)->data(Qt::EditRole).toDouble(),
text_qsi->child(y_txt_row,1)->data(Qt::EditRole).toDouble());
if(p != deti->pos())
{
QPropertyUndoCommand *quc = new QPropertyUndoCommand(deti, "pos", QVariant(deti->pos()), QVariant(p), undo);
quc->setAnimated(true, false);
quc->setText(tr("Déplacer un texte d'élément"));
}
}
//When text is in a group, they're isn't item for the rotation of the text
if(text_qsi->child(rot_txt_row,1))
{
qreal rot = text_qsi->child(rot_txt_row,1)->data(Qt::EditRole).toDouble();
rot = QET::correctAngle(rot);
if(rot != deti->rotation())
{
QPropertyUndoCommand *quc = new QPropertyUndoCommand(deti, "rotation", QVariant(deti->rotation()), QVariant(rot), undo);
quc->setAnimated(true, false);
quc->setText(tr("Pivoter un texte d'élément"));
}
}
if (text_qsi->child(keep_rot_row,1))
{
bool keep_rot = text_qsi->child(keep_rot_row, 1)->checkState() == Qt::Checked? true : false;
if (keep_rot != deti->keepVisualRotation())
{
auto qpuc = new QPropertyUndoCommand(deti, "keepVisualRotation", QVariant(deti->keepVisualRotation()), QVariant(keep_rot), undo);
qpuc->setText(tr("Modifier le maintient de la rotation d'un texte d'élément"));
}
}
//When text is in a groupe, they're isn't item for alignment of the text
if(text_qsi->child(align_txt_row, 1))
{
Qt::Alignment alignment = text_qsi->child(align_txt_row, 1)->data(Qt::UserRole+2).value();
if (alignment != deti->alignment())
{
QPropertyUndoCommand *quc = new QPropertyUndoCommand(deti, "alignment", QVariant(deti->alignment()), QVariant(alignment), undo);
quc->setText(tr("Modifier l'alignement d'un texte d'élément"));
}
}
return undo;
}
/**
@brief DynamicElementTextModel::undoForEditedGroup
@param group
@param parent_undo
@return A QUndoCommand that describe all changes made for group.
Each change made for group is append as a child of the returned QUndoCommand.
In other word, if the returned QUndoCommand have no child,
that mean there is no change.
*/
QUndoCommand *DynamicElementTextModel::undoForEditedGroup(
ElementTextItemGroup *group,
QUndoCommand *parent_undo) const
{
QUndoCommand *undo = nullptr;
if(parent_undo)
undo = parent_undo;
else
undo = new QUndoCommand(tr("Éditer un groupe de textes"));
if (!m_groups_list.contains(group))
return undo;
QStandardItem *group_qsi = m_groups_list.value(group);
QString alignment = group_qsi->child(align_grp_row,1)->data(Qt::DisplayRole).toString();
if((alignment == tr("Gauche")) && (group->alignment() != Qt::AlignLeft))
new QPropertyUndoCommand(group, "alignment", QVariant(group->alignment()), QVariant(Qt::AlignLeft), undo);
else if((alignment == tr("Droite")) && (group->alignment() != Qt::AlignRight))
new QPropertyUndoCommand(group, "alignment", QVariant(group->alignment()), QVariant(Qt::AlignRight), undo);
else if((alignment == tr("Centre")) && (group->alignment() != Qt::AlignVCenter))
new QPropertyUndoCommand(group, "alignment", QVariant(group->alignment()), QVariant(Qt::AlignVCenter), undo);
if (group_qsi->child(hold_to_bottom_grp_row, 1)->checkState() == Qt::Unchecked)
{
QPointF pos(group_qsi->child(x_grp_row,1)->data(Qt::EditRole).toDouble(),
group_qsi->child(y_grp_row,1)->data(Qt::EditRole).toDouble());
if(group->pos() != pos)
{
QPropertyUndoCommand *qpuc = new QPropertyUndoCommand(group, "pos", QVariant(group->pos()), QVariant(pos), undo);
qpuc->setAnimated(true, false);
}
qreal rotation = group_qsi->child(rot_grp_row,1)->data(Qt::EditRole).toDouble();
if(group->rotation() != rotation)
{
QPropertyUndoCommand *qpuc = new QPropertyUndoCommand(group, "rotation", QVariant(group->rotation()), QVariant(rotation), undo);
qpuc->setAnimated(true, false);
}
}
int v_adjustment = group_qsi->child(adjust_grp_row,1)->data(Qt::EditRole).toInt();
if(group->verticalAdjustment() != v_adjustment)
new QPropertyUndoCommand(group, "verticalAdjustment", QVariant(group->verticalAdjustment()), QVariant(v_adjustment), undo);
QString name = group_qsi->data(Qt::DisplayRole).toString();
if(group->name() != name)
new QPropertyUndoCommand(group, "name", QVariant(group->name()), QVariant(name), undo);
bool hold_to_bottom = group_qsi->child(hold_to_bottom_grp_row, 1)->checkState() == Qt::Checked? true : false;
if(group->holdToBottomPage() != hold_to_bottom)
new QPropertyUndoCommand(group, "holdToBottomPage", QVariant(group->holdToBottomPage()), QVariant(hold_to_bottom), undo);
bool frame_ = group_qsi->child(frame_grp_row, 1)->checkState() == Qt::Checked? true : false;
if(group->frame() != frame_)
new QPropertyUndoCommand(group, "frame", QVariant(group->frame()), QVariant(frame_), undo);
return undo;
}
/**
@brief DynamicElementTextModel::AddGroup
Add a text item group to this model
@param group
*/
void DynamicElementTextModel::addGroup(ElementTextItemGroup *group)
{
if(m_groups_list.keys().contains(group))
return;
//Group
QStandardItem *grp = new QStandardItem(group->name());
grp->setFlags(Qt::ItemIsSelectable
| Qt::ItemIsEnabled
| Qt::ItemIsDropEnabled
| Qt::ItemIsEditable);
grp->setIcon(QET::Icons::textGroup);
QStandardItem *empty_qsi = new QStandardItem(0);
empty_qsi->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
QList qsi_list;
qsi_list << grp << empty_qsi;
this->insertRow(0, qsi_list);
m_groups_list.insert(group, grp);
//Alignment
QStandardItem *alignment = new QStandardItem(tr("Alignement"));
alignment->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
QString text;
switch (group->alignment()) {
case Qt::AlignLeft: text = tr("Gauche"); break;
case Qt::AlignRight: text = tr("Droite"); break;
case Qt::AlignVCenter: text = tr("Centre"); break;
default: break;}
QStandardItem *alignment_a = new QStandardItem(text);
alignment_a->setData(DynamicElementTextModel::grpAlignment,
Qt::UserRole+1);
alignment_a->setFlags(Qt::ItemIsSelectable
| Qt::ItemIsEnabled
| Qt::ItemIsEditable);
qsi_list.clear();
qsi_list << alignment << alignment_a;
grp->appendRow(qsi_list);
//X pos
QStandardItem *x_pos = new QStandardItem(tr("Position X"));
x_pos->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
QStandardItem *x_pos_a = new QStandardItem;
x_pos_a->setData(group->pos().x(), Qt::EditRole);
x_pos_a->setData(DynamicElementTextModel::grpPos, Qt::UserRole+1);
x_pos_a->setFlags(Qt::ItemIsSelectable
| Qt::ItemIsEnabled
| Qt::ItemIsEditable);
qsi_list.clear();
qsi_list << x_pos << x_pos_a;
grp->appendRow(qsi_list);
//Y pos
QStandardItem *y_pos = new QStandardItem(tr("Position Y"));
y_pos->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
QStandardItem *y_pos_a = new QStandardItem;
y_pos_a->setData(group->pos().y(), Qt::EditRole);
y_pos_a->setData(DynamicElementTextModel::grpPos, Qt::UserRole+1);
y_pos_a->setFlags(Qt::ItemIsSelectable
| Qt::ItemIsEnabled
| Qt::ItemIsEditable);
qsi_list.clear();
qsi_list << y_pos << y_pos_a;
grp->appendRow(qsi_list);
//Rotation
QStandardItem *rot = new QStandardItem(tr("Rotation"));
rot->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
QStandardItem *rot_a = new QStandardItem;
rot_a->setData(group->rotation(), Qt::EditRole);
rot_a->setData(DynamicElementTextModel::grpRotation, Qt::UserRole+1);
rot_a->setFlags(Qt::ItemIsSelectable
| Qt::ItemIsEnabled
| Qt::ItemIsEditable);
qsi_list.clear();
qsi_list << rot << rot_a;
grp->appendRow(qsi_list);
//Vertical adjustment
QStandardItem *v_adj = new QStandardItem(tr("Ajustement vertical"));
v_adj->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);
QStandardItem *v_adj_a = new QStandardItem;
v_adj_a->setData(group->verticalAdjustment(), Qt::EditRole);
v_adj_a->setData(DynamicElementTextModel::grpVAdjust, Qt::UserRole+1);
v_adj_a->setFlags(Qt::ItemIsSelectable
| Qt::ItemIsEnabled
| Qt::ItemIsEditable);
qsi_list.clear();
qsi_list << v_adj << v_adj_a;
grp->appendRow(qsi_list);
//Frame
QStandardItem *frame_ = new QStandardItem(tr("Cadre"));
frame_->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);
QStandardItem *frame_a = new QStandardItem;
frame_a->setCheckable(true);
frame_a->setCheckState(group->frame()? Qt::Checked : Qt::Unchecked);
frame_a->setData(DynamicElementTextModel::grpFrame, Qt::UserRole+1);
frame_a->setFlags(Qt::ItemIsSelectable
| Qt::ItemIsEnabled
| Qt::ItemIsUserCheckable);
qsi_list.clear();
qsi_list << frame_ << frame_a;
grp->appendRow(qsi_list);
//Hold to the bottom of the page
QStandardItem *hold_bottom = new QStandardItem(tr("Maintenir en bas de page"));
hold_bottom->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);
QStandardItem *hold_bottom_a = new QStandardItem();
hold_bottom_a->setCheckable(true);
hold_bottom_a->setCheckState(group->holdToBottomPage()
? Qt::Checked
: Qt::Unchecked);
hold_bottom_a->setData(DynamicElementTextModel::grpHoldBottom,
Qt::UserRole+1);
hold_bottom_a->setFlags(Qt::ItemIsSelectable
| Qt::ItemIsEnabled
| Qt::ItemIsUserCheckable);
qsi_list.clear();
qsi_list << hold_bottom << hold_bottom_a;
grp->appendRow(qsi_list);
//Add the texts of the group
for(DynamicElementTextItem *deti : group->texts())
{
QStandardItem *group_item = m_groups_list.value(group);
group_item->appendRow(itemsForText(deti));
}
setConnection(group, true);
enableGroupRotationAndPos(group);
}
/**
@brief DynamicElementTextModel::removeGroup
Remove the text item group from this model
@param group
*/
void DynamicElementTextModel::removeGroup(ElementTextItemGroup *group)
{
if(m_groups_list.keys().contains(group))
{
QModelIndex group_index = m_groups_list.value(group)->index();
this->removeRow(group_index.row(), group_index.parent());
m_groups_list.remove(group);
setConnection(group, false);
}
}
/**
@brief DynamicElementTextModel::textAddedToGroup
Add the text text to the group group
@param deti
@param group
*/
void DynamicElementTextModel::addTextToGroup(DynamicElementTextItem *deti,
ElementTextItemGroup *group)
{
QStandardItem *group_item = m_groups_list.value(group);
group_item->appendRow(itemsForText(deti));
}
void DynamicElementTextModel::removeTextFromGroup(DynamicElementTextItem *deti,
ElementTextItemGroup *group)
{
Q_UNUSED(group)
if(m_texts_list.keys().contains(deti))
{
QStandardItem *text_item = m_texts_list.value(deti);
QModelIndex text_index = indexFromItem(text_item);
removeRow(text_index.row(), text_index.parent());
m_texts_list.remove(deti);
}
}
/**
@brief DynamicElementTextModel::groupFromIndex
@param index
@return the group associated with index. Return value can be nullptr
Index can be a child of an index associated with a group
and can be the column 0 or 1.
*/
ElementTextItemGroup *DynamicElementTextModel::groupFromIndex(
const QModelIndex &index) const
{
if(!index.isValid())
return nullptr;
if (QStandardItem *item = itemFromIndex(index))
return groupFromItem(item);
else
return nullptr;
}
/**
@brief DynamicElementTextModel::groupFromItem
@param item
@return the group associated with item. Return value can be nullptr
item can be a child of an item associated with a group
and can be the column 0 or 1.
*/
ElementTextItemGroup *DynamicElementTextModel::groupFromItem(
QStandardItem *item) const
{
//Get the item of the column 0
if(item->column() == 1)
{
if(item->parent())
item = item->parent()->child(item->row(), 0);
else
item = itemFromIndex(index(item->row(),0));
}
while (item->parent())
item = item->parent();
if(m_groups_list.values().contains(item))
return m_groups_list.key(item);
else
return nullptr;
}
/**
@brief DynamicElementTextModel::indexFromGroup
@param group
@return The index associated to the group group
or a default QModelIndex if not match
*/
QModelIndex DynamicElementTextModel::indexFromGroup(
ElementTextItemGroup *group) const
{
if(m_groups_list.keys().contains(group))
return m_groups_list.value(group)->index();
else
return QModelIndex();
}
/**
@brief DynamicElementTextModel::indexIsText
@param index
@return True if index represente a text, both for the column 0 and 1.
Return false if index is a child of an index associated to a text.
*/
bool DynamicElementTextModel::indexIsText(const QModelIndex &index) const
{
QStandardItem *item = nullptr;
//The item represent the second column
if(index.column() == 1)
{
if(index.parent().isValid())
item = itemFromIndex(index.parent()
.QModelIndex::model()->index(
index.row(),
0));
else
item = itemFromIndex(this->index(index.row(),0));
}
else
item = itemFromIndex(index);
if(item && m_texts_list.values().contains(item))
return true;
else
return false;
}
/**
@brief DynamicElementTextModel::indexIsGroup
@param index
@return True if index represente a group, both for the column 0 and 1.
Return false if index is a child of an index associated to a group.
*/
bool DynamicElementTextModel::indexIsGroup(const QModelIndex &index) const
{
QStandardItem *item = nullptr;
//The item represent the second column
if(index.column() == 1)
{
if(index.parent().isValid())
item = itemFromIndex(index.parent()
.QModelIndex::model()->index(
index.row(),0));
else
item = itemFromIndex(this->index(index.row(),0));
}
else
item = itemFromIndex(index);
if(item && m_groups_list.values().contains(item))
return true;
else
return false;
}
bool DynamicElementTextModel::canDropMimeData(
const QMimeData *data,
Qt::DropAction action,
int row,
int column,
const QModelIndex &parent) const
{
Q_UNUSED(action);
if(data->hasFormat("application/x-qet-element-text-uuid"))
{
QModelIndex index;
if(parent.isValid() && row != -1 && column !=1) //Insert in child of parent
index = parent.QModelIndex::model()->index(row, column);
else if (parent.isValid() && row == -1 && column == -1) //Drop in parent
index = parent;
QUuid uuid(data->text());
//The data is drop in a group
if(indexIsInGroup(index))
{
//Data is dragged from a text direct child of element
for(DynamicElementTextItem *text : m_element.data()->dynamicTextItems())
if(text->uuid() == uuid)
return true;
//Data is dragged from a text in a group
for(ElementTextItemGroup *group : m_element.data()->textGroups())
{
for(DynamicElementTextItem *text : group->texts())
if(text->uuid() == uuid)
return true;
}
return false;
}
else //The data is not drop in a group, then the action must be a drag of text from a group to the element
{
for(ElementTextItemGroup *group : m_element.data()->textGroups())
{
for(DynamicElementTextItem *text : group->texts())
if(text->uuid() == uuid)
return true;
}
}
}
return false;
}
/**
@brief DynamicElementTextModel::dropMimeData
@param data
@param action
@param row
@param column
@param parent
@return In any case return false,
for overwrite the default behavior of model.
*/
bool DynamicElementTextModel::dropMimeData(const QMimeData *data,
Qt::DropAction action,
int row,
int column,
const QModelIndex &parent)
{
Q_UNUSED(action)
if(data->hasFormat("application/x-qet-element-text-uuid"))
{
QUuid uuid(data->text());
DynamicElementTextItem *deti = nullptr;
ElementTextItemGroup *group = nullptr;
QModelIndex index;
if(parent.isValid() && row != -1 && column !=1) //Insert in child of parent
index = parent.QModelIndex::model()->index(row, column);
else if (parent.isValid() && row == -1 && column == -1) //Drop in parent
index = parent;
//Darg and drop in a group of text
if(indexIsInGroup(index))
{
//The dragged text is a direct child of element
for(DynamicElementTextItem *text : m_element.data()->dynamicTextItems())
{
if(text->uuid() == uuid)
{
deti = text;
group = groupFromIndex(index);
if(group && deti) //Text successfully added in a group
{
m_element.data()->diagram()->undoStack().push(new AddTextToGroupCommand(deti, group));
return true;
}
}
}
//The dragged text is in a group
for(ElementTextItemGroup *grp : m_element.data()->textGroups())
{
for(DynamicElementTextItem *text : grp->texts())
{
if(text->uuid() == uuid)
{
deti = text;
group = groupFromIndex(index);
//Text successfully moved from a group to another group
if(group && deti)
{
QUndoStack &stack = m_element.data()->diagram()->undoStack();
stack.beginMacro(tr("Déplacer un texte dans un autre groupe"));
stack.push(new RemoveTextFromGroupCommand(deti, grp));
stack.push(new AddTextToGroupCommand(deti, group));
stack.endMacro();
return true;
}
}
}
}
return false;
}
else //Drag and drop in anaother place
{
//Get the dropped text
for(ElementTextItemGroup *grp : m_element.data()->textGroups())
{
for(DynamicElementTextItem *text : grp->texts())
{
if(text->uuid() == uuid)
{
deti = text;
group = grp;
break;
}
}
if(deti)
break;
}
if(deti && group) //Text successfully removed from group
{
m_element.data()->diagram()->undoStack().push((new RemoveTextFromGroupCommand(deti, group)));
return true;
}
return false;
}
}
return false;
}
QMimeData *DynamicElementTextModel::mimeData(const QModelIndexList &indexes) const
{
QModelIndex index = indexes.first();
if (index.isValid())
{
QStandardItem *item = itemFromIndex(index);
if(item)
{
DynamicElementTextItem *deti = m_texts_list.key(item);
if(deti)
{
QMimeData *mime_data = new QMimeData();
mime_data->setText(deti->uuid().toString());
mime_data->setData("application/x-qet-element-text-uuid", deti->uuid().toString().toLatin1());
return mime_data;
}
}
}
return QStandardItemModel::mimeData(indexes);
}
/**
@brief DynamicElementTextModel::mimeTypes
@return
*/
QStringList DynamicElementTextModel::mimeTypes() const
{
QStringList mime_list = QAbstractItemModel::mimeTypes();
mime_list << "application/x-qet-element-text-uuid";
return mime_list;
}
/**
@brief DynamicElementTextModel::enableSourceText
Enable the good field, according to the current source of text,
for the edited text deti
@param deti
@param tf
*/
void DynamicElementTextModel::enableSourceText(
DynamicElementTextItem *deti,
DynamicElementTextItem::TextFrom tf)
{
if (!m_texts_list.contains(deti))
return;
QStandardItem *qsi = m_texts_list.value(deti);
bool usr = false, info = false, compo = false;
switch (tf) {
case DynamicElementTextItem::UserText: usr = true; break;
case DynamicElementTextItem::ElementInfo: info = true; break;
case DynamicElementTextItem::CompositeText: compo = true;break;
}
//User text
qsi->child(usr_txt_row,0)->setEnabled(usr);
qsi->child(usr_txt_row,1)->setEnabled(usr);
//Info text
qsi->child(info_txt_row,0)->setEnabled(info);
qsi->child(info_txt_row,1)->setEnabled(info);
//Composite text
qsi->child(compo_txt_row,0)->setEnabled(compo);
qsi->child(compo_txt_row,1)->setEnabled(compo);
}
/**
@brief DynamicElementTextModel::enableGroupRotation
Enable/disable the item "group rotation" according the option hold to bottom
@param group
*/
void DynamicElementTextModel::enableGroupRotationAndPos(
ElementTextItemGroup *group)
{
if(!m_groups_list.contains(group))
return;
QStandardItem *qsi = m_groups_list.value(group);
if(group->holdToBottomPage())
{
qsi->child(x_grp_row, 0)->setFlags(Qt::ItemIsSelectable);
qsi->child(x_grp_row, 1)->setFlags(Qt::ItemIsSelectable);
qsi->child(y_grp_row, 0)->setFlags(Qt::ItemIsSelectable);
qsi->child(y_grp_row, 1)->setFlags(Qt::ItemIsSelectable);
qsi->child(rot_grp_row, 0)->setFlags(Qt::ItemIsSelectable);
qsi->child(rot_grp_row, 1)->setFlags(Qt::ItemIsSelectable);
}
else
{
qsi->child(x_grp_row, 0)->setFlags(Qt::ItemIsSelectable
| Qt::ItemIsEnabled);
qsi->child(x_grp_row, 1)->setFlags(Qt::ItemIsSelectable
| Qt::ItemIsEnabled
| Qt::ItemIsEditable);
qsi->child(y_grp_row, 0)->setFlags(Qt::ItemIsSelectable
| Qt::ItemIsEnabled);
qsi->child(y_grp_row, 1)->setFlags(Qt::ItemIsSelectable
| Qt::ItemIsEnabled
| Qt::ItemIsEditable);
qsi->child(rot_grp_row, 0)->setFlags(Qt::ItemIsSelectable
| Qt::ItemIsEnabled);
qsi->child(rot_grp_row, 1)->setFlags(Qt::ItemIsSelectable
| Qt::ItemIsEnabled
| Qt::ItemIsEditable);
}
}
void DynamicElementTextModel::itemDataChanged(QStandardItem *qsi)
{
DynamicElementTextItem *deti = textFromItem(qsi);
ElementTextItemGroup *etig = groupFromItem(qsi);
if (!deti && !etig)
return;
if(deti)
{
QStandardItem *text_qsi = m_texts_list.value(deti);
DiagramContext dc;
if(deti->elementUseForInfo())
dc = deti->elementUseForInfo()->elementInformations();
if (qsi->data().toInt() == textFrom)
{
QString from = qsi->data(Qt::DisplayRole).toString();
if (from == tr("Texte utilisateur"))
{
enableSourceText(deti, DynamicElementTextItem::UserText);
text_qsi->setData(text_qsi->child(usr_txt_row,1)->data(Qt::DisplayRole).toString());
}
else if (from == tr("Information de l'élément"))
{
enableSourceText(deti, DynamicElementTextItem::ElementInfo);
QString info = text_qsi->child(info_txt_row,1)->data(Qt::UserRole+2).toString();
text_qsi->setData(dc.value(info), Qt::DisplayRole);
}
else
{
enableSourceText(deti, DynamicElementTextItem::CompositeText);
QString compo = text_qsi->child(compo_txt_row,1)->data(Qt::UserRole+2).toString();
text_qsi->setData(autonum::AssignVariables::replaceVariable(compo, dc), Qt::DisplayRole);
}
}
else if (qsi->data().toInt() == userText)
{
QString text = qsi->data(Qt::DisplayRole).toString();
text_qsi->setData(text, Qt::DisplayRole);
}
else if (qsi->data().toInt() == infoText && deti->elementUseForInfo())
{
QString info = qsi->data(Qt::UserRole+2).toString();
text_qsi->setData(dc.value(info), Qt::DisplayRole);
}
else if (qsi->data().toInt() == compositeText && deti->elementUseForInfo())
{
QString compo = qsi->data(Qt::UserRole+2).toString();
text_qsi->setData(autonum::AssignVariables::replaceVariable(compo, dc), Qt::DisplayRole);
}
}
//We emit the signal only if qsi is in the second column,
//because the data are stored on this column
//the first column is use only for display the title of the property,
//except for the name of texts group
if((m_groups_list.values().contains(qsi) || qsi->column() == 1)
&& !m_block_dataChanged)
emit dataChanged();
if(deti) deti->updateXref();
}
/**
@brief DynamicElementTextModel::setConnection
Set up the connection for deti to keep up to date
the data of this model and the text.
Is notably use with the use of QUndoCommand.
@param deti - text to setup connection
@param set - true = set connection - false unset connection
*/
void DynamicElementTextModel::setConnection(DynamicElementTextItem *deti, bool set)
{
if(set)
{
if(m_hash_text_connect.keys().contains(deti))
return;
QList connection_list;
connection_list << connect(deti, &DynamicElementTextItem::colorChanged, [deti,this](){this->updateDataFromText(deti, color);});
connection_list << connect(deti, &DynamicElementTextItem::fontChanged, [deti,this](){this->updateDataFromText(deti, font);});
connection_list << connect(deti, &DynamicElementTextItem::textFromChanged, [deti,this](){this->updateDataFromText(deti, textFrom);});
connection_list << connect(deti, &DynamicElementTextItem::textChanged, [deti,this](){this->updateDataFromText(deti, userText);});
connection_list << connect(deti, &DynamicElementTextItem::infoNameChanged, [deti,this](){this->updateDataFromText(deti, infoText);});
connection_list << connect(deti, &DynamicElementTextItem::xChanged, [deti,this](){this->updateDataFromText(deti, pos);});
connection_list << connect(deti, &DynamicElementTextItem::yChanged, [deti,this](){this->updateDataFromText(deti, pos);});
connection_list << connect(deti, &DynamicElementTextItem::frameChanged, [deti,this](){this->updateDataFromText(deti, frame);});
connection_list << connect(deti, &DynamicElementTextItem::rotationChanged, [deti,this](){this->updateDataFromText(deti, rotation);});
connection_list << connect(deti, &DynamicElementTextItem::textWidthChanged,[deti,this](){this->updateDataFromText(deti, textWidth);});
connection_list << connect(deti, &DynamicElementTextItem::compositeTextChanged, [deti, this]() {this->updateDataFromText(deti, compositeText);});
m_hash_text_connect.insert(deti, connection_list);
}
else
{
if(!m_hash_text_connect.keys().contains(deti))
return;
for (const QMetaObject::Connection& con : m_hash_text_connect.value(deti))
disconnect(con);
m_hash_text_connect.remove(deti);
}
}
/**
@brief DynamicElementTextModel::setConnection
Set up the connection for group to keep up to date
the data of this model and the group.
Is notably use with the use of QUndoCommand.
@param group group to setup the connection
@param set true = set connection - false unset connection
*/
void DynamicElementTextModel::setConnection(ElementTextItemGroup *group, bool set)
{
if(set)
{
if(m_hash_group_connect.keys().contains(group))
return;
QList connection_list;
connection_list << connect(group, &ElementTextItemGroup::alignmentChanged, [group, this]() {this->updateDataFromGroup(group, grpAlignment);});
connection_list << connect(group, &ElementTextItemGroup::rotationChanged, [group, this]() {this->updateDataFromGroup(group, grpRotation);});
connection_list << connect(group, &ElementTextItemGroup::verticalAdjustmentChanged, [group, this]() {this->updateDataFromGroup(group, grpVAdjust);});
connection_list << connect(group, &ElementTextItemGroup::verticalAdjustmentChanged, [group, this]() {this->updateDataFromGroup(group, grpName);});
connection_list << connect(group, &ElementTextItemGroup::holdToBottomPageChanged, [group, this]() {this->updateDataFromGroup(group, grpHoldBottom);});
connection_list << connect(group, &ElementTextItemGroup::xChanged, [group, this]() {this->updateDataFromGroup(group, grpPos);});
connection_list << connect(group, &ElementTextItemGroup::yChanged, [group, this]() {this->updateDataFromGroup(group, grpPos);});
connection_list << connect(group, &ElementTextItemGroup::frameChanged, [group, this]() {this->updateDataFromGroup(group, grpFrame);});
m_hash_group_connect.insert(group, connection_list);
}
else
{
if(!m_hash_group_connect.keys().contains(group))
return;
for (const QMetaObject::Connection& con : m_hash_group_connect.value(group))
disconnect(con);
m_hash_group_connect.remove(group);
}
}
void DynamicElementTextModel::updateDataFromText(DynamicElementTextItem *deti,
ValueType type)
{
QStandardItem *qsi = m_texts_list.value(deti);
if (!qsi)
return;
m_block_dataChanged = true;
switch (type)
{
case textFrom:
{
switch (deti->textFrom())
{
case DynamicElementTextItem::UserText: qsi->child(0,1)->setData(tr("Texte utilisateur"), Qt::DisplayRole); break;
case DynamicElementTextItem::ElementInfo : qsi->child(0,1)->setData(tr("Information de l'élément"), Qt::DisplayRole); break;
case DynamicElementTextItem::CompositeText : qsi->child(0,1)->setData(tr("Texte composé"), Qt::DisplayRole); break;
}
enableSourceText(deti, deti->textFrom());
qsi->setData(deti->toPlainText(), Qt::DisplayRole);
break;
}
case userText:
{
qsi->setData(deti->toPlainText(), Qt::DisplayRole);
qsi->child(usr_txt_row,1)->setData(deti->toPlainText(), Qt::DisplayRole);
qsi->setData(deti->toPlainText(), Qt::DisplayRole);
break;
}
case infoText:
{
qsi->setData(deti->toPlainText(), Qt::DisplayRole);
QString info_name = deti->infoName();
qsi->child(info_txt_row,1)->setData(info_name, Qt::UserRole+2);
qsi->child(info_txt_row,1)->setData(QETInformation::translatedInfoKey(info_name), Qt::DisplayRole);
break;
}
case compositeText:
{
qsi->setData(deti->toPlainText(), Qt::DisplayRole);
qsi->child(compo_txt_row,1)->setData(deti->compositeText(), Qt::UserRole+2);
qsi->child(compo_txt_row,1)->setData(deti->toPlainText(), Qt::DisplayRole);
qsi->setData(deti->toPlainText(), Qt::DisplayRole);
break;
}
case size:
//qsi->child(size_txt_row,1)->setData(deti->fontSize(), Qt::EditRole);
break;
case font:
{
QFont f(deti->font());
qsi->child(font_txt_row,1)->setData(f.family(), Qt::EditRole);
qsi->child(font_txt_row,1)->setData(f, Qt::UserRole+2);
qsi->child(size_txt_row,1)->setData(f.pointSize(), Qt::EditRole);
break;
}
case color:
{
qsi->child(color_txt_row,1)->setData(deti->color(), Qt::EditRole);
qsi->child(color_txt_row,1)->setData(deti->color(), Qt::ForegroundRole);
break;
}
case pos:
{
if(qsi->child(x_txt_row,1))
qsi->child(x_txt_row,1)->setData(deti->pos().x(), Qt::EditRole);
if(qsi->child(y_txt_row,1))
qsi->child(y_txt_row,1)->setData(deti->pos().y(), Qt::EditRole);
break;
}
case frame:
{
qsi->child(frame_txt_row,1)->setCheckState(deti->frame()? Qt::Checked : Qt::Unchecked);
break;
}
case rotation:
{
if(qsi->child(rot_txt_row,1))
qsi->child(rot_txt_row,1)->setData(deti->rotation(), Qt::EditRole);
break;
}
case textWidth:
{
qsi->child(width_txt_row,1)->setData(deti->textWidth(), Qt::EditRole);
break;
}
default:break;
}
m_block_dataChanged = false;
}
void DynamicElementTextModel::updateDataFromGroup(
ElementTextItemGroup *group,
DynamicElementTextModel::ValueType type)
{
QStandardItem *qsi = m_groups_list.value(group);
if (!qsi)
return;
m_block_dataChanged = true;
switch (type)
{
case grpAlignment:
{
switch (group->alignment())
{
case Qt::AlignLeft: qsi->child(align_grp_row,1)->setData(tr("Gauche"), Qt::DisplayRole); break;
case Qt::AlignRight : qsi->child(align_grp_row,1)->setData(tr("Droite"), Qt::DisplayRole); break;
case Qt::AlignVCenter : qsi->child(align_grp_row,1)->setData(tr("Centre"), Qt::DisplayRole); break;
default: qsi->child(0,1)->setData("", Qt::DisplayRole); break;
}
break;
}
case grpPos:
{
qsi->child(x_grp_row,1)->setData(group->pos().x(), Qt::EditRole);
qsi->child(y_grp_row,1)->setData(group->pos().y(), Qt::EditRole);
break;
}
case grpRotation:
qsi->child(rot_grp_row,1)->setData(group->rotation(), Qt::EditRole);
break;
case grpVAdjust:
qsi->child(adjust_grp_row,1)->setData(group->verticalAdjustment(), Qt::EditRole);
break;
case grpName:
qsi->setData(group->name(), Qt::DisplayRole);
break;
case grpHoldBottom:
{
qsi->child(hold_to_bottom_grp_row,1)->setCheckState(group->holdToBottomPage()? Qt::Checked : Qt::Unchecked);
enableGroupRotationAndPos(group);
break;
}
case grpFrame:
qsi->child(frame_grp_row, 1)->setCheckState(group->frame()? Qt::Checked : Qt::Unchecked);
break;
default:break;
}
m_block_dataChanged = false;
}
/***************************************************
A little delegate only for add a combobox and a color dialog,
for use with the model
***************************************************/
DynamicTextItemDelegate::DynamicTextItemDelegate(QObject *parent) :
QStyledItemDelegate(parent)
{}
QWidget *DynamicTextItemDelegate::createEditor(
QWidget *parent,
const QStyleOptionViewItem &option,
const QModelIndex &index) const
{
switch (index.data(Qt::UserRole+1).toInt())
{
case DynamicElementTextModel::textFrom:
{
QComboBox *qcb = new QComboBox(parent);
qcb->setObjectName("text_from");
qcb->addItem(tr("Texte utilisateur"));
qcb->addItem(tr("Information de l'élément"));
qcb->addItem(tr("Texte composé"));
return qcb;
}
case DynamicElementTextModel::infoText:
{
const DynamicElementTextModel *detm = static_cast(index.model());
QStandardItem *qsi = detm->itemFromIndex(index);
if(!qsi)
break;
DynamicElementTextItem *deti = detm->textFromIndex(index);
if(!deti)
break;
//We use a QMap because the keys of the map are sorted, then no matter the curent local,
//the value of the combo box are always alphabetically sorted
QMap info_map;
for(const QString& str : availableInfo(deti)) {
info_map.insert(QETInformation::translatedInfoKey(str), str);
}
QComboBox *qcb = new QComboBox(parent);
qcb->setObjectName("info_text");
for (const QString& key : info_map.keys()) {
qcb->addItem(key, info_map.value(key));
}
return qcb;
}
case DynamicElementTextModel::compositeText:
{
const DynamicElementTextModel *detm = static_cast(index.model());
QStandardItem *qsi = detm->itemFromIndex(index);
if(!qsi)
break;
DynamicElementTextItem *deti = detm->textFromIndex(index);
if(!deti)
break;
CompositeTextEditDialog *cted = new CompositeTextEditDialog(deti, parent);
cted->setObjectName("composite_text");
return cted;
}
case DynamicElementTextModel::txtAlignment:
{
const DynamicElementTextModel *detm = static_cast(index.model());
QStandardItem *qsi = detm->itemFromIndex(index);
if(!qsi)
break;
DynamicElementTextItem *deti = detm->textFromIndex(index);
if(!deti)
break;
AlignmentTextDialog *atd = new AlignmentTextDialog(deti->alignment(), parent);
atd->setObjectName("alignment_text");
return atd;
}
case DynamicElementTextModel::size:
{
QSpinBox *sb = new QSpinBox(parent);
sb->setObjectName("font_size");
sb->setFrame(false);
return sb;
}
case DynamicElementTextModel::font:
{
bool ok;
QFont font = QFontDialog::getFont(&ok, index.data(Qt::UserRole+2).value(), parent);
QWidget *w = new QWidget(parent);
if (ok)
{
w->setFont(font);
w->setProperty("ok", ok);
}
w->setObjectName("font_dialog");
return w;
}
case DynamicElementTextModel::color:
{
QColorDialog *cd = new QColorDialog(index.data(Qt::EditRole).value(), parent);
cd->setObjectName("color_dialog");
return cd;
}
case DynamicElementTextModel::pos:
{
QSpinBox *sb = new QSpinBox(parent);
sb->setObjectName("pos_dialog");
sb->setRange(-1000,10000);
sb->setFrame(false);
sb->setSuffix(" px");
return sb;
}
case DynamicElementTextModel::rotation:
{
QSpinBox *sb = new QSpinBox(parent);
sb->setObjectName("rot_spinbox");
sb->setRange(0, 359);
sb->setWrapping(true);
sb->setFrame(false);
sb->setSuffix(" °");
return sb;
}
case DynamicElementTextModel::textWidth:
{
QSpinBox *sb = new QSpinBox(parent);
sb->setObjectName("width_spinbox");
sb->setRange(-1, 500);
sb->setFrame(false);
sb->setSuffix(" px");
return sb;
}
case DynamicElementTextModel::grpAlignment:
{
QComboBox *qcb = new QComboBox(parent);
qcb->setFrame(false);
qcb->setObjectName("group_alignment");
qcb->addItem(tr("Gauche"));
qcb->addItem(tr("Centre"));
qcb->addItem(tr("Droite"));
return qcb;
}
case DynamicElementTextModel::grpPos:
{
QSpinBox *sb = new QSpinBox(parent);
sb->setObjectName("group_pos");
sb->setRange(-1000,10000);
sb->setFrame(false);
sb->setSuffix(" px");
return sb;
}
case DynamicElementTextModel::grpRotation:
{
QSpinBox *sb = new QSpinBox(parent);
sb->setObjectName("group_rotation");
sb->setRange(0, 359);
sb->setWrapping(true);
sb->setFrame(false);
sb->setSuffix(" °");
return sb;
}
case DynamicElementTextModel::grpVAdjust:
{
QSpinBox *sb = new QSpinBox(parent);
sb->setObjectName("group_v_adjustment");
sb->setRange(-20, 20);
sb->setFrame(false);
sb->setSuffix(" px");
return sb;
}
}
return QStyledItemDelegate::createEditor(parent, option, index);
}
void DynamicTextItemDelegate::setModelData(
QWidget *editor,
QAbstractItemModel *model,
const QModelIndex &index) const
{
if (index.isValid())
{
if (editor->objectName() == "font_dialog")
{
if (QStandardItemModel *qsim = dynamic_cast(model))
{
if(QStandardItem *qsi = qsim->itemFromIndex(index))
{
if (editor->property("ok").toBool() == true)
{
qsi->setData(editor->font().family(), Qt::EditRole);
qsi->setData(editor->font(), Qt::UserRole+2);
}
return;
}
}
}
else if(editor->objectName() == "color_dialog")
{
if (QStandardItemModel *qsim = dynamic_cast(model))
{
if(QStandardItem *qsi = qsim->itemFromIndex(index))
{
QColorDialog *cd = static_cast (editor);
if (cd->result() == QDialog::Accepted)
{
qsi->setData(cd->selectedColor(), Qt::EditRole);
qsi->setData(cd->selectedColor(), Qt::ForegroundRole);
}
return;
}
}
}
else if (editor->objectName() == "info_text")
{
if (QStandardItemModel *qsim = dynamic_cast(model))
{
if(QStandardItem *qsi = qsim->itemFromIndex(index))
{
QComboBox *cb = static_cast(editor);
qsi->setData(cb->currentText(), Qt::DisplayRole);
qsi->setData(cb->currentData(), Qt::UserRole+2);
return;
}
}
}
else if (editor->objectName() == "composite_text")
{
if (QStandardItemModel *qsim = dynamic_cast(model))
{
if(QStandardItem *qsi = qsim->itemFromIndex(index))
{
CompositeTextEditDialog *cted = static_cast(editor);
QString edited_text = cted->plainText();
QString assigned_text;
const DynamicElementTextModel *detm = static_cast(index.model());
DynamicElementTextItem *deti = detm->textFromIndex(index);
if(deti)
{
DiagramContext dc;
if(deti->elementUseForInfo())
dc = deti->elementUseForInfo()->elementInformations();
assigned_text = autonum::AssignVariables::replaceVariable(edited_text, dc);
}
qsi->setData(assigned_text, Qt::DisplayRole);
qsi->setData(edited_text, Qt::UserRole+2);
return;
}
}
}
else if (editor->objectName() == "alignment_text")
{
if(QStandardItemModel *qsim = dynamic_cast(model))
{
if(QStandardItem *qsi = qsim->itemFromIndex(index))
{
AlignmentTextDialog *atd = static_cast(editor);
Qt::Alignment align = atd->alignment();
qsi->setData(QVariant::fromValue(align), Qt::UserRole+2);
return;
}
}
}
else if (editor->objectName() == "group_alignment")
{
if(QStandardItemModel *qsim = dynamic_cast(model))
{
if(QStandardItem *qsi = qsim->itemFromIndex(index))
{
QComboBox *cb = static_cast(editor);
qsi->setData(cb->currentText(), Qt::DisplayRole);
}
}
}
}
QStyledItemDelegate::setModelData(editor, model, index);
}
bool DynamicTextItemDelegate::eventFilter(QObject *object, QEvent *event)
{
//This is a bad hack, for change the normal behavior :
//in normal behavior,
//the value is commited when the spinbox lose focus or enter key is pressed
//With this hack the value is commited each time the value change without the need to validate.
//then the change is apply in live
if(object->objectName() == "pos_dialog" || object->objectName() == "font_size" || object->objectName() == "rot_spinbox" || \
object->objectName() == "group_rotation" || object->objectName() == "group_v_adjustment" || object->objectName() == "width_spinbox" ||\
object->objectName() == "group_pos")
{
object->event(event);
QSpinBox *sb = static_cast(object);
switch (event->type()) {
case QEvent::KeyPress:
emit commitData(sb); break;
case QEvent::KeyRelease:
emit commitData(sb); break;
case QEvent::MouseButtonPress:
emit commitData(sb); break;
case QEvent::MouseButtonRelease:
emit commitData(sb); break;
case QEvent::Wheel:
emit commitData(sb); break;
default:break;
}
return true;
}
//Like the hack above, change the current index of the combobox,
// apply the change immediately, no need to lose focus or press enter.
if((object->objectName() == "text_from" || object->objectName() == "info_text" || object->objectName() == "group_alignment") && event->type() == QEvent::FocusIn)
{
QComboBox *qcb = static_cast(object);
connect(qcb, static_cast(&QComboBox::currentIndexChanged), [this,qcb](){emit commitData(qcb);});
}
return QStyledItemDelegate::eventFilter(object, event);
}
/**
@brief DynamicTextItemDelegate::availableInfo
@param deti
@return A list of available info of element
*/
QStringList DynamicTextItemDelegate::availableInfo(
DynamicElementTextItem *deti) const
{
QStringList qstrl;
if(deti->parentElement()->linkType() & Element::AllReport) //Special treatment for text owned by a folio report
{
return QETInformation::folioReportInfoKeys();
}
else
{
Element *elmt = deti->elementUseForInfo();
if(!elmt)
return qstrl;
QStringList info_list = QETInformation::elementInfoKeys();
info_list.removeAll("formula"); //No need to have formula
DiagramContext dc = elmt->elementInformations();
for(const QString& info : info_list)
{
if(dc.contains(info))
qstrl << info;
}
}
return qstrl;
}