1 /*
2 	Copyright 2006-2019 The QElectroTech Team
3 	This file is part of QElectroTech.
4 
5 	QElectroTech is free software: you can redistribute it and/or modify
6 	it under the terms of the GNU General Public License as published by
7 	the Free Software Foundation, either version 2 of the License, or
8 	(at your option) any later version.
9 
10 	QElectroTech is distributed in the hope that it will be useful,
11 	but WITHOUT ANY WARRANTY; without even the implied warranty of
12 	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 	GNU General Public License for more details.
14 
15 	You should have received a copy of the GNU General Public License
16 	along with QElectroTech.  If not, see <http://www.gnu.org/licenses/>.
17 */
18 #include "elementinfowidget.h"
19 #include "ui_elementinfowidget.h"
20 #include "qetapp.h"
21 #include "changeelementinformationcommand.h"
22 #include "diagram.h"
23 #include "elementinfopartwidget.h"
24 #include "element.h"
25 
26 /**
27  * @brief ElementInfoWidget::ElementInfoWidget
28  * Constructor
29  * @param elmt element to edit information
30  * @param parent parent widget
31  */
ElementInfoWidget(Element * elmt,QWidget * parent)32 ElementInfoWidget::ElementInfoWidget(Element *elmt, QWidget *parent) :
33 	AbstractElementPropertiesEditorWidget(parent),
34 	ui(new Ui::ElementInfoWidget),
35 	m_first_activation (false)
36 {
37 	ui->setupUi(this);
38 	buildInterface();
39 	setElement(elmt);
40 }
41 
42 /**
43  * @brief ElementInfoWidget::~ElementInfoWidget
44  * Destructor
45  */
~ElementInfoWidget()46 ElementInfoWidget::~ElementInfoWidget()
47 {
48 	qDeleteAll(m_eipw_list);
49 	delete ui;
50 }
51 
52 /**
53  * @brief ElementInfoWidget::setElement
54  * Set @element to be the edited element
55  * @param element
56  */
setElement(Element * element)57 void ElementInfoWidget::setElement(Element *element)
58 {
59 	if (m_element == element) return;
60 
61 	if (m_element)
62 		disconnect(m_element.data(), &Element::elementInfoChange, this, &ElementInfoWidget::elementInfoChange);
63 
64 	m_element = element;
65 	updateUi();
66 
67 	ElementInfoPartWidget *f = infoPartWidgetForKey("formula");
68 	ElementInfoPartWidget *l = infoPartWidgetForKey("label");
69 
70 	if (f && l)
71 	{
72 		if (f->text().isEmpty())
73 			l->setEnabled(true);
74 		else
75 			l->setDisabled(true);
76 
77 		connect(f, &ElementInfoPartWidget::textChanged, [l](const QString text)
78 		{
79 			l->setEnabled(text.isEmpty()? true : false);
80 		});
81 	}
82 
83 	connect(m_element.data(), &Element::elementInfoChange, this, &ElementInfoWidget::elementInfoChange);
84 }
85 
86 /**
87  * @brief ElementInfoWidget::apply
88  * Apply the new information with a new undo command (got with method associatedUndo)
89  * pushed to the stack of element project.
90  */
apply()91 void ElementInfoWidget::apply()
92 {
93 	if (QUndoCommand *undo = associatedUndo())
94 		m_element -> diagram() -> undoStack().push(undo);
95 }
96 
97 /**
98  * @brief ElementInfoWidget::associatedUndo
99  * If the edited info is different of the actual element info,
100  * return a QUndoCommand with the change.
101  * If no change return nullptr;
102  * @return
103  */
associatedUndo() const104 QUndoCommand* ElementInfoWidget::associatedUndo() const
105 {
106 	DiagramContext new_info = currentInfo();
107 	DiagramContext old_info = m_element -> elementInformations();
108 
109 	if (old_info != new_info)
110 		return (new ChangeElementInformationCommand(m_element, old_info, new_info));
111 
112 	return nullptr;
113 }
114 
115 /**
116  * @brief ElementInfoWidget::setLiveEdit
117  * @param live_edit true : enable the live edit mode, false disable
118  * @return always true;
119  */
setLiveEdit(bool live_edit)120 bool ElementInfoWidget::setLiveEdit(bool live_edit)
121 {
122 	if (m_live_edit == live_edit) return true;
123 	m_live_edit = live_edit;
124 
125 	if (m_live_edit)
126 		enableLiveEdit();
127 	else
128 		disableLiveEdit();
129 
130 	return true;
131 }
132 
133 /**
134  * @brief ElementInfoWidget::event
135  * Reimplemented from QWidget::event
136  * Only give focus to the first line edit at first activation.
137  * After send the event to QWidget.
138  * @param event
139  * @return
140  */
event(QEvent * event)141 bool ElementInfoWidget::event(QEvent *event)
142 {
143 	if (m_first_activation)
144 	{
145 		if (event -> type() == QEvent::WindowActivate || event -> type() == QEvent::Show)
146 		{
147 			QTimer::singleShot(250, this, SLOT(firstActivated()));
148 			m_first_activation = false;
149 		}
150 	}
151 	return(QWidget::event(event));
152 }
153 
154 /**
155  * @brief ElementInfoWidget::enableLiveEdit
156  * Enable the live edit mode
157  */
enableLiveEdit()158 void ElementInfoWidget::enableLiveEdit()
159 {
160 	for (ElementInfoPartWidget *eipw : m_eipw_list)
161 		connect(eipw, &ElementInfoPartWidget::textChanged, this, &ElementInfoWidget::apply);
162 }
163 
164 /**
165  * @brief ElementInfoWidget::disableLiveEdit
166  * disable the live edit mode
167  */
disableLiveEdit()168 void ElementInfoWidget::disableLiveEdit()
169 {
170 	for (ElementInfoPartWidget *eipw : m_eipw_list)
171 		disconnect(eipw, &ElementInfoPartWidget::textChanged, this, &ElementInfoWidget::apply);
172 }
173 
174 /**
175  * @brief ElementInfoWidget::buildInterface
176  * Build the widget
177  */
buildInterface()178 void ElementInfoWidget::buildInterface()
179 {
180 	foreach (QString str, QETApp::elementInfoKeys())
181 	{
182 		ElementInfoPartWidget *eipw = new ElementInfoPartWidget(str, QETApp::elementTranslatedInfoKey(str), this);
183 		ui->scroll_vlayout->addWidget(eipw);
184 		m_eipw_list << eipw;
185 	}
186 	ui->scroll_vlayout->addStretch();
187 }
188 
189 /**
190  * @brief ElementInfoWidget::infoPartWidgetForKey
191  * @param key
192  * @return the ElementInfoPartWidget with key @key, if not found return nullptr;
193  */
infoPartWidgetForKey(const QString & key) const194 ElementInfoPartWidget *ElementInfoWidget::infoPartWidgetForKey(const QString &key) const
195 {
196 	foreach (ElementInfoPartWidget *eipw, m_eipw_list)
197 	{
198 		if (eipw->key() == key)
199 			return eipw;
200 	}
201 
202 	return nullptr;
203 }
204 
205 /**
206  * @brief ElementInfoWidget::updateUi
207  * fill information fetch in m_element_info to the
208  * corresponding line edit
209  */
updateUi()210 void ElementInfoWidget::updateUi()
211 {
212 		//We disable live edit to avoid wrong undo when we fill the line edit with new text
213 	if (m_live_edit) disableLiveEdit();
214 
215 	DiagramContext element_info = m_element->elementInformations();
216 
217 	for (ElementInfoPartWidget *eipw : m_eipw_list) {
218 		eipw -> setText (element_info[eipw->key()].toString());
219 	}
220 
221 	if (m_live_edit) {
222 		enableLiveEdit();
223 	}
224 }
225 
226 /**
227  * @brief ElementInfoWidget::currentInfo
228  * @return the info currently edited
229  */
currentInfo() const230 DiagramContext ElementInfoWidget::currentInfo() const
231 {
232 	DiagramContext info_;
233 
234 	for (ElementInfoPartWidget *eipw : m_eipw_list)
235 	{
236 			//add value only if they're something to store
237 		if (!eipw->text().isEmpty())
238 		{
239 			QString txt = eipw->text();
240 				//remove line feed and carriage return
241 			txt.remove("\r");
242 			txt.remove("\n");
243 			info_.addValue(eipw->key(), txt);
244 		}
245 	}
246 
247 	return info_;
248 }
249 
250 /**
251  * @brief ElementInfoWidget::firstActivated
252  * Slot activated when this widget is show.
253  * Set the focus to the first line edit provided by this widget
254  */
firstActivated()255 void ElementInfoWidget::firstActivated() {
256 	m_eipw_list.first() -> setFocusTolineEdit();
257 }
258 
259 /**
260  * @brief ElementInfoWidget::elementInfoChange
261  * This slot is called when m_element::elementInformation change.
262  */
elementInfoChange()263 void ElementInfoWidget::elementInfoChange()
264 {
265 	if(currentInfo() != m_element->elementInformations())
266 		updateUi();
267 }
268