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 <QVBoxLayout>
19 #include <QLabel>
20 #include <QTreeView>
21 #include <QDialogButtonBox>
22 #include <QPushButton>
23 #include <QtConcurrent>
24 
25 #include "elementdialog.h"
26 #include "qetapp.h"
27 #include "qfilenameedit.h"
28 #include "elementcollectionitem.h"
29 #include "elementscollectionmodel.h"
30 #include "qetmessagebox.h"
31 
32 /**
33  * @brief ElementDialog::ElementDialog
34  * @param mode
35  * @param parent
36  */
ElementDialog(uint mode,QWidget * parent)37 ElementDialog::ElementDialog(uint mode, QWidget *parent) :
38 	QDialog(parent),
39 	m_mode(mode)
40 {
41 	setUpWidget();
42 	setUpConnection();
43 }
44 
45 /**
46  * @brief ElementDialog::setUpWidget
47  * Build and setup the widgets of this dialog
48  */
setUpWidget()49 void ElementDialog::setUpWidget()
50 {
51 	setWindowModality(Qt::WindowModal);
52 #ifdef Q_OS_MAC
53 	setWindowFlags(Qt::Sheet);
54 #endif
55 
56 	QVBoxLayout *layout = new QVBoxLayout(this);
57 
58 	QString title_, label_;
59 	switch (m_mode)
60 	{
61 		case OpenElement:
62 			title_ = tr("Ouvrir un élément", "dialog title");
63 			label_ = tr("Choisissez l'élément que vous souhaitez ouvrir.", "dialog content");
64 			break;
65 		case SaveElement:
66 			title_ = tr("Enregistrer un élément", "dialog title");
67 			label_ = tr("Choisissez l'élément dans lequel vous souhaitez enregistrer votre définition.", "dialog content");
68 			break;
69 		case OpenCategory:
70 			title_ = tr("Ouvrir une catégorie", "dialog title");
71 			label_ = tr("Choisissez une catégorie.", "dialog content");
72 			break;
73 		case SaveCategory:
74 			title_ = tr("Enregistrer une catégorie", "dialog title");
75 			label_ = tr("Choisissez une catégorie.", "dialog content");
76 			break;
77 		default:
78 			title_ = tr("Titre");
79 			label_ = tr("Label");
80 			break;
81 	}
82 	setWindowTitle(title_);
83 
84 	layout->addWidget(new QLabel(label_));
85 
86 
87 	m_tree_view = new QTreeView(this);
88 
89 	m_model = new ElementsCollectionModel(m_tree_view);
90 
91 	QList <QETProject *> prjs;
92 	foreach(QETProject *prj, QETApp::registeredProjects())
93 			prjs.append(prj);
94 
95 	if (m_mode == OpenElement)
96 		m_model->loadCollections(true, true, prjs);
97 	else
98 		m_model->loadCollections(false, true, prjs);
99 
100 	m_tree_view->setModel(m_model);
101 	m_tree_view->setHeaderHidden(true);
102 	layout->addWidget(m_tree_view);
103 
104 	m_buttons_box = new QDialogButtonBox(this);
105 
106 	if (m_mode == SaveCategory || m_mode == SaveElement)
107 	{
108 		m_buttons_box->setStandardButtons(QDialogButtonBox::Save | QDialogButtonBox::Cancel);
109 		m_buttons_box->button(QDialogButtonBox::Save)->setDisabled(true);
110 
111 		m_text_field = new QFileNameEdit();
112 		m_text_field->setDisabled(true);
113 		m_text_field->setPlaceholderText(m_mode == SaveCategory? tr("Nom du nouveau dossier") : tr("Nom du nouvel élément"));
114 
115 		layout->addWidget(m_text_field);
116 	}
117 	else
118 	{
119 		m_buttons_box->setStandardButtons(QDialogButtonBox::Open | QDialogButtonBox::Cancel);
120 		m_buttons_box->button(QDialogButtonBox::Open)->setDisabled(true);
121 	}
122 
123 	layout->addWidget(m_buttons_box);
124 }
125 
126 /**
127  * @brief ElementDialog::setUpConnection
128  * Setup connection of this dialog
129  */
setUpConnection()130 void ElementDialog::setUpConnection()
131 {
132 	connect(m_tree_view, &QTreeView::clicked, this, &ElementDialog::indexClicked);
133 	connect(m_buttons_box, &QDialogButtonBox::accepted, this, &ElementDialog::checkAccept);
134 	connect(m_buttons_box, &QDialogButtonBox::rejected, this, &QDialog::reject);
135 
136 	if (m_text_field) { connect(m_text_field, &QFileNameEdit::textChanged, this, &ElementDialog::checkCurrentLocation); }
137 }
138 
139 /**
140  * @brief ElementDialog::indexClicked
141  * @param index
142  */
indexClicked(const QModelIndex & index)143 void ElementDialog::indexClicked(const QModelIndex &index)
144 {
145 	ElementCollectionItem *eci = static_cast<ElementCollectionItem*> (m_model->itemFromIndex(index));
146 	m_location = ElementsLocation(eci->collectionPath());
147 	checkCurrentLocation();
148 }
149 
150 /**
151  * @brief ElementDialog::checkCurrentLocation
152  * Update this dialog according to the current selected location and the current mode
153  */
checkCurrentLocation()154 void ElementDialog::checkCurrentLocation()
155 {
156 	if (m_mode == OpenElement) {
157 		m_buttons_box->button(QDialogButtonBox::Open)->setEnabled(m_location.isElement() && m_location.exist());
158 	}
159 	else if (m_mode == SaveElement)
160 	{
161 		m_buttons_box->button(QDialogButtonBox::Save)->setDisabled(true);
162 
163 			//Location doesn't exist
164 		if (!m_location.exist()) { return; }
165 
166 		if (m_location.isElement())
167 		{
168 			m_text_field->setDisabled(true);
169 			m_buttons_box->button(QDialogButtonBox::Save)->setEnabled(true);
170 		}
171 		else if (m_location.isDirectory())
172 		{
173 			m_text_field->setEnabled(true);
174 
175 			if (m_text_field->text().isEmpty()) { return; }
176 
177 				//Only enable save button if the location at path :
178 				//m_location.collectionPath + m_text_filed.text doesn't exist.
179 			QString new_path = m_text_field->text();
180 			if (!new_path.endsWith(".elmt")) new_path += ".elmt";
181 
182 			ElementsLocation loc = m_location;
183 			loc.addToPath(new_path);
184 
185 			m_buttons_box->button(QDialogButtonBox::Save)->setDisabled(loc.exist() ? true : false);
186 		}
187 	}
188 }
189 
checkAccept()190 void ElementDialog::checkAccept()
191 {
192 	ElementsLocation loc = location();
193 
194 	if (m_mode == OpenElement)
195 	{
196 		if (loc.isElement() && loc.exist()) {accept();}
197 		if (!loc.exist())
198 		{
199 			QET::QetMessageBox::critical(this,
200 										 tr("Sélection inexistante", "message box title"),
201 										 tr("La sélection n'existe pas.", "message box content"));
202 			return;
203 		}
204 		else if (!loc.isElement())
205 		{
206 			QET::QetMessageBox::critical(this,
207 										 tr("Sélection incorrecte", "message box title"),
208 										 tr("La sélection n'est pas un élément.", "message box content"));
209 			return;
210 		}
211 	}
212 	else if (m_mode == SaveElement)
213 	{
214 		if (loc.isElement())
215 		{
216 			if (loc.exist())
217 			{
218 				QMessageBox::StandardButton answer = QET::QetMessageBox::question(this,
219 																				  tr("Écraser l'élément ?", "message box title"),
220 																				  tr("L'élément existe déjà. Voulez-vous l'écraser ?", "message box content"),
221 																				  QMessageBox::Yes | QMessageBox::No,
222 																				  QMessageBox::No);
223 				if (answer == QMessageBox::Yes) {accept();}
224 				else {return;}
225 			}
226 			else {accept();}
227 		}
228 		else
229 		{
230 			QET::QetMessageBox::critical(this,
231 										 tr("Sélection incorrecte", "message box title"),
232 										 tr("Vous devez sélectionner un élément ou une catégorie avec un nom pour l'élément.", "message box content"));
233 			return;
234 		}
235 	}
236 }
237 
238 /**
239  * @brief ElementDialog::location
240  * @return The selected location or a null location if user has selected nothing
241  * or selection isn't compatible with the curent mode
242  */
location() const243 ElementsLocation ElementDialog::location() const
244 {
245 	if (m_mode == OpenElement)
246 	{
247 		if (m_location.isElement()) { return m_location; }
248 		else {return ElementsLocation(); }
249 	}
250 
251 	else if (m_mode == SaveElement)
252 	{
253 			//Current selected location is element, we return this location
254 		if (m_location.isElement()) { return m_location; }
255 
256 			//Current selected location is directory, we return a location at path :
257 			//m_location->collectionPath + m_text_field->text
258 		else if (m_location.isDirectory())
259 		{
260 			QString new_path = m_text_field->text();
261 			if (new_path.isEmpty()) { return ElementsLocation(); }
262 
263 			if (!new_path.endsWith(".elmt")) { new_path += ".elmt"; }
264 
265 			ElementsLocation loc = m_location;
266 			loc.addToPath(new_path);
267 			return loc;
268 		}
269 	}
270 
271 	return ElementsLocation();
272 }
273 
274 /**
275  * @brief ElementDialog::getOpenElementLocation
276  * Display a dialog for open an element through her location
277  * @param parentWidget
278  * @return The location of the selected element
279  */
getOpenElementLocation(QWidget * parentWidget)280 ElementsLocation ElementDialog::getOpenElementLocation(QWidget *parentWidget) {
281 	return(ElementDialog::execConfiguredDialog(ElementDialog::OpenElement, parentWidget));
282 }
283 
284 /**
285  * @brief ElementDialog::getSaveElementLocation
286  * Display a dialog that allow to user to select an element (existing or not) who he want to save
287  * @param parentWidget
288  * @return The location where the element must be save
289  */
getSaveElementLocation(QWidget * parentWidget)290 ElementsLocation ElementDialog::getSaveElementLocation(QWidget *parentWidget) {
291 	return(ElementDialog::execConfiguredDialog(ElementDialog::SaveElement, parentWidget));
292 }
293 
294 /**
295  * @brief ElementDialog::execConfiguredDialog
296  * launch a dialog with the chosen mode
297  * @param mode : mode of the dialog
298  * @param parentWidget : parent widget of the dialog
299  * @return the chosen location
300  */
execConfiguredDialog(int mode,QWidget * parentWidget)301 ElementsLocation ElementDialog::execConfiguredDialog(int mode, QWidget *parentWidget)
302 {
303 	ElementDialog *element_dialog = new ElementDialog(mode, parentWidget);
304 	element_dialog->exec();
305 	ElementsLocation location = element_dialog->location();
306 	delete element_dialog;
307 	return(location);
308 }
309