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 "templatelogomanager.h"
19 #include "titleblocktemplate.h"
20 #include "qeticons.h"
21
22 #include <QStandardPaths>
23
24 /**
25 Constructor
26 @param managed_template Title block template this widget manages logos for.
27 @param parent Parent QWidget.
28 */
TitleBlockTemplateLogoManager(TitleBlockTemplate * managed_template,QWidget * parent)29 TitleBlockTemplateLogoManager::TitleBlockTemplateLogoManager(TitleBlockTemplate *managed_template, QWidget *parent) :
30 QWidget(parent),
31 managed_template_(managed_template)
32 {
33 initWidgets();
34 fillView();
35 }
36
37 /**
38 Destructor
39 */
~TitleBlockTemplateLogoManager()40 TitleBlockTemplateLogoManager::~TitleBlockTemplateLogoManager() {
41 }
42
43 /**
44 @return the name of the currently selected logo, or a null QString if none
45 is selected.
46 */
currentLogo() const47 QString TitleBlockTemplateLogoManager::currentLogo() const {
48 if (!managed_template_) return QString();
49
50 QListWidgetItem *current_item = logos_view_ -> currentItem();
51 if (!current_item) return QString();
52
53 return(current_item -> text());
54 }
55
56 /**
57 @return Whether this logo manager should allow logo edition
58 (renaming, addition, deletion).
59 */
isReadOnly() const60 bool TitleBlockTemplateLogoManager::isReadOnly() const {
61 return(read_only_);
62 }
63
64 /**
65 Emit the logosChanged() signal.
66 */
emitLogosChangedSignal()67 void TitleBlockTemplateLogoManager::emitLogosChangedSignal() {
68 emit(logosChanged(const_cast<const TitleBlockTemplate *>(managed_template_)));
69 }
70
71 /**
72 Initialize widgets composing the Logo manager
73 */
initWidgets()74 void TitleBlockTemplateLogoManager::initWidgets() {
75 open_dialog_dir_ = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation);
76
77 setWindowTitle(tr("Gestionnaire de logos"));
78 setWindowIcon(QET::Icons::InsertImage);
79 setWindowFlags(Qt::Dialog);
80 logos_label_ = new QLabel(tr("Logos embarqués dans ce modèle :"));
81 logos_view_ = new QListWidget();
82 logos_view_ -> setViewMode(QListView::IconMode);
83 logos_view_ -> setGridSize(iconsize() * 1.4);
84 logos_view_ -> setMinimumSize(iconsize() * 2.9);
85 logos_view_ -> setIconSize(iconsize());
86 logos_view_ -> setWrapping(true);
87 logos_view_ -> setMovement(QListView::Static);
88 logos_view_ -> setResizeMode(QListView::Adjust);
89 add_button_ = new QPushButton(QET::Icons::Add, tr("Ajouter un logo"));
90 export_button_ = new QPushButton(QET::Icons::DocumentExport, tr("Exporter ce logo"));
91 delete_button_ = new QPushButton(QET::Icons::Remove, tr("Supprimer ce logo"));
92 logo_box_ = new QGroupBox(tr("Propriétés"));
93 logo_name_label_ = new QLabel(tr("Nom :"));
94 logo_name_ = new QLineEdit();
95 rename_button_ = new QPushButton(QET::Icons::EditRename, tr("Renommer"));
96 logo_type_ = new QLabel(tr("Type :"));
97 buttons_ = new QDialogButtonBox(QDialogButtonBox::Ok);
98
99 hlayout1_ = new QHBoxLayout();
100 hlayout1_ -> addWidget(logo_name_label_);
101 hlayout1_ -> addWidget(logo_name_);
102 hlayout1_ -> addWidget(rename_button_);
103
104 hlayout0_ = new QHBoxLayout();
105 hlayout0_ -> addWidget(export_button_);
106 hlayout0_ -> addWidget(delete_button_);
107
108 vlayout1_ = new QVBoxLayout();
109 vlayout1_ -> addLayout(hlayout1_);
110 vlayout1_ -> addWidget(logo_type_);
111 logo_box_ -> setLayout(vlayout1_);
112
113 vlayout0_ = new QVBoxLayout();
114 vlayout0_ -> addWidget(logos_label_);
115 vlayout0_ -> addWidget(logos_view_);
116 vlayout0_ -> addWidget(add_button_);
117 vlayout0_ -> addLayout(hlayout0_);
118 vlayout0_ -> addWidget(logo_box_);
119 setLayout(vlayout0_);
120
121 connect(
122 logos_view_,
123 SIGNAL(currentItemChanged(QListWidgetItem *, QListWidgetItem *)),
124 this,
125 SLOT(updateLogoInformations(QListWidgetItem *, QListWidgetItem *))
126 );
127 connect(add_button_, SIGNAL(released()), this, SLOT(addLogo()));
128 connect(export_button_, SIGNAL(released()), this, SLOT(exportLogo()));
129 connect(delete_button_, SIGNAL(released()), this, SLOT(removeLogo()));
130 connect(rename_button_, SIGNAL(released()), this, SLOT(renameLogo()));
131 }
132
133 /**
134 Update the logos display.
135 */
fillView()136 void TitleBlockTemplateLogoManager::fillView() {
137 if (!managed_template_) return;
138 logos_view_ -> clear();
139
140 foreach (QString logo_name, managed_template_ -> logos()) {
141 QIcon current_icon;
142 QPixmap current_logo = managed_template_ -> bitmapLogo(logo_name);
143 if (!current_logo.isNull()) {
144 current_icon = QIcon(current_logo);
145 } else {
146 QSvgRenderer *svg_logo = managed_template_ -> vectorLogo(logo_name);
147 if (svg_logo) {
148 QPixmap *svg_pixmap = new QPixmap(iconsize());
149 svg_pixmap -> fill();
150 QPainter p;
151 p.begin(svg_pixmap);
152 svg_logo -> render(&p);
153 p.end();
154 current_icon = QIcon(*svg_pixmap);
155 }
156 }
157 QListWidgetItem *qlwi = new QListWidgetItem(current_icon, logo_name);
158 qlwi -> setTextAlignment(Qt::AlignBottom | Qt::AlignHCenter);
159 logos_view_ -> insertItem(0, qlwi);
160 }
161
162 QListWidgetItem *current_item = logos_view_ -> currentItem();
163 updateLogoInformations(current_item, nullptr);
164 }
165
166 /**
167 @return the icon size to display the logos embedded within the managed
168 template.
169 */
iconsize() const170 QSize TitleBlockTemplateLogoManager::iconsize() const {
171 return(QSize(80, 80));
172 }
173
174 /**
175 When adding a logo, it may occur its name is already used by another
176 pre-existing logo. This method asks users whether they want to erase the
177 existing logo, change the initial name or simply cancel the operation.
178 @param initial_name Initial name of the logo to be added
179 @return Either a null QString if the user cancelled the operation, or the
180 name to be used when adding the logo.
181 */
confirmLogoName(const QString & initial_name)182 QString TitleBlockTemplateLogoManager::confirmLogoName(const QString &initial_name) {
183 QString name = initial_name;
184 QDialog *rename_dialog = nullptr;
185 QLabel *rd_label = nullptr;
186 QLineEdit *rd_input = nullptr;
187 while (managed_template_ -> logos().contains(name)) {
188 if (!rename_dialog) {
189 rename_dialog = new QDialog(this);
190 rename_dialog -> setWindowTitle(tr("Logo déjà existant"));
191
192 rd_label = new QLabel();
193 rd_label -> setWordWrap(true);
194 rd_input = new QLineEdit();
195 QDialogButtonBox *rd_buttons = new QDialogButtonBox();
196 QPushButton *replace_button = rd_buttons -> addButton(tr("Remplacer"), QDialogButtonBox::YesRole);
197 QPushButton *rename_button = rd_buttons -> addButton(tr("Renommer"), QDialogButtonBox::NoRole);
198 QPushButton *cancel_button = rd_buttons -> addButton(QDialogButtonBox::Cancel);
199
200 QVBoxLayout *rd_vlayout0 = new QVBoxLayout();
201 rd_vlayout0 -> addWidget(rd_label);
202 rd_vlayout0 -> addWidget(rd_input);
203 rd_vlayout0 -> addWidget(rd_buttons);
204 rename_dialog -> setLayout(rd_vlayout0);
205
206 QSignalMapper *signal_mapper = new QSignalMapper(rename_dialog);
207 signal_mapper -> setMapping(replace_button, QDialogButtonBox::YesRole);
208 signal_mapper -> setMapping(rename_button, QDialogButtonBox::NoRole);
209 signal_mapper -> setMapping(cancel_button, QDialogButtonBox::RejectRole);
210 connect(replace_button, SIGNAL(clicked()), signal_mapper, SLOT(map()));
211 connect(rename_button, SIGNAL(clicked()), signal_mapper, SLOT(map()));
212 connect(cancel_button, SIGNAL(clicked()), signal_mapper, SLOT(map()));
213 connect(signal_mapper, SIGNAL(mapped(int)), rename_dialog, SLOT(done(int)));
214 }
215 rd_label -> setText(
216 QString(tr(
217 "Il existe déjà un logo portant le nom \"%1\" au sein de "
218 "ce modèle de cartouche. Voulez-vous le remplacer ou "
219 "préférez-vous spécifier un autre nom pour ce nouveau "
220 "logo ?"
221 )).arg(name)
222 );
223 rd_input -> setText(name);
224 int answer = rename_dialog -> exec();
225 if (answer == QDialogButtonBox::YesRole) {
226 // we can use the initial name
227 break;
228 } else if (answer == QDialogButtonBox::NoRole) {
229 // the user provided another name
230 name = rd_input -> text();
231 /// TODO prevent the user from entering an empty name
232 } else {
233 // the user cancelled the operation
234 return(QString());
235 }
236 };
237 return(name);
238 }
239
240 /**
241 Update the displayed informations relative to the currently selected logo.
242 @param current Newly selected logo item
243 @param previous Previously selected logo item
244 */
updateLogoInformations(QListWidgetItem * current,QListWidgetItem * previous)245 void TitleBlockTemplateLogoManager::updateLogoInformations(QListWidgetItem *current, QListWidgetItem *previous) {
246 Q_UNUSED(previous);
247 if (current) {
248 QString logo_name = current -> text();
249 logo_name_ -> setText(logo_name);
250 if (managed_template_) {
251 QString logo_type = managed_template_ -> logoType(logo_name);
252 logo_type_ -> setText(tr("Type : %1").arg(logo_type));
253 }
254 } else {
255 logo_name_ -> setText(QString());
256 logo_type_ -> setText(tr("Type :"));
257 }
258 }
259
260 /**
261 Ask the user for a filepath, and add it as a new logo in the managed
262 template.
263 */
addLogo()264 void TitleBlockTemplateLogoManager::addLogo() {
265 if (!managed_template_) return;
266
267 QString filepath = QFileDialog::getOpenFileName(
268 this,
269 tr("Choisir une image / un logo"),
270 open_dialog_dir_.absolutePath(),
271 tr("Images vectorielles (*.svg);;Images bitmap (*.png *.jpg *.jpeg *.gif *.bmp *.xpm);;Tous les fichiers (*)")
272 );
273 if (filepath.isEmpty()) return;
274
275 // that filepath needs to point to a valid, readable file
276 QFileInfo filepath_info(filepath);
277 if (!filepath_info.exists() || !filepath_info.isReadable()) {
278 QMessageBox::critical(this, tr("Erreur"), tr("Impossible d'ouvrir le fichier spécifié"));
279 return;
280 }
281
282 // ensure we can use the file name to add the logo
283 QString logo_name = confirmLogoName(filepath_info.fileName());
284 if (logo_name.isNull()) return;
285
286 open_dialog_dir_ = QDir(filepath);
287 if (managed_template_ -> addLogoFromFile(filepath, logo_name)) {
288 fillView();
289 emitLogosChangedSignal();
290 }
291 }
292
293 /**
294 Export the currently selected logo
295 */
exportLogo()296 void TitleBlockTemplateLogoManager::exportLogo() {
297 QString current_logo = currentLogo();
298 if (current_logo.isNull()) return;
299
300 QString filepath = QFileDialog::getSaveFileName(
301 this,
302 tr("Choisir un fichier pour exporter ce logo"),
303 open_dialog_dir_.absolutePath() + "/" + current_logo,
304 tr("Tous les fichiers (*);;Images vectorielles (*.svg);;Images bitmap (*.png *.jpg *.jpeg *.gif *.bmp *.xpm)")
305 );
306 if (filepath.isEmpty()) return;
307
308 bool save_logo = managed_template_ -> saveLogoToFile(current_logo, filepath);
309 if (!save_logo) {
310 QMessageBox::critical(this, tr("Erreur"), QString(tr("Impossible d'exporter vers le fichier spécifié")));
311 } else {
312 open_dialog_dir_ = QDir(filepath);
313 }
314 }
315
316 /**
317 Delete the currently selected logo.
318 */
removeLogo()319 void TitleBlockTemplateLogoManager::removeLogo() {
320 QString current_logo = currentLogo();
321 if (current_logo.isNull()) return;
322
323 if (managed_template_ -> removeLogo(current_logo)) {
324 fillView();
325 emitLogosChangedSignal();
326 }
327 }
328
329 /**
330 Rename currently selected logo.
331 */
renameLogo()332 void TitleBlockTemplateLogoManager::renameLogo() {
333 QString current_logo = currentLogo();
334 if (current_logo.isNull()) return;
335
336 QString entered_name = logo_name_ -> text();
337 QString warning_title = tr("Renommer un logo");
338 if (entered_name == current_logo) {
339 QMessageBox::warning(
340 this,
341 warning_title,
342 tr("Vous devez saisir un nouveau nom.")
343 );
344 return;
345 }
346
347 if (entered_name.trimmed().isEmpty()) {
348 QMessageBox::warning(
349 this,
350 warning_title,
351 tr("Le nouveau nom ne peut pas être vide.")
352 );
353 return;
354 }
355
356 if (managed_template_ -> logos().contains(entered_name)) {
357 QMessageBox::warning(
358 this,
359 warning_title,
360 tr("Le nom saisi est déjà utilisé par un autre logo.")
361 );
362 return;
363 }
364
365 if (managed_template_ -> renameLogo(current_logo, entered_name)) {
366 fillView();
367 emitLogosChangedSignal();
368 }
369 }
370
371 /**
372 @param read_only Whether this logo manager should allow logo edition
373 (renaming, addition, deletion)
374 */
setReadOnly(bool read_only)375 void TitleBlockTemplateLogoManager::setReadOnly(bool read_only) {
376 if (read_only_ == read_only) return;
377 read_only_ = read_only;
378
379 add_button_ -> setEnabled(!read_only_);
380 delete_button_ -> setEnabled(!read_only_);
381 rename_button_ -> setEnabled(!read_only_);
382 logo_name_ -> setReadOnly(read_only_);
383 }
384