1 /*
2 For general Scribus (>=1.3.2) copyright and licensing information please refer
3 to the COPYING file provided with the program. Following this notice may exist
4 a copyright and/or license notice that predates the release of Scribus 1.3.2
5 for which a new license (GPL+exception) is in place.
6 */
7 /**************************************************************************
8 *   Copyright (C) 2010 by Franz Schmid                                    *
9 *   franz.schmid@altmuehlnet.de                                           *
10 *                                                                         *
11 *   This program is free software; you can redistribute it and/or modify  *
12 *   it under the terms of the GNU General Public License as published by  *
13 *   the Free Software Foundation; either version 2 of the License, or     *
14 *   (at your option) any later version.                                   *
15 *                                                                         *
16 *   This program is distributed in the hope that it will be useful,       *
17 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
18 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
19 *   GNU General Public License for more details.                          *
20 *                                                                         *
21 *   You should have received a copy of the GNU General Public License     *
22 *   along with this program; if not, write to the                         *
23 *   Free Software Foundation, Inc.,                                       *
24 *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.             *
25 ***************************************************************************/
26 
27 #include <QCheckBox>
28 #include <QCursor>
29 #include <QDir>
30 #include <QDomDocument>
31 #include <QEventLoop>
32 #include <QFileDialog>
33 #include <QImageReader>
34 #include <QMenu>
35 #include <QMessageBox>
36 
37 #include "cmykfw.h"
38 #include "colorlistbox.h"
39 #include "colorsandfills.h"
40 #include "commonstrings.h"
41 #include "dcolor.h"
42 #include "fileloader.h"
43 #include "gradientaddedit.h"
44 #include "iconmanager.h"
45 #include "loadsaveplugin.h"
46 #include "plugins/formatidlist.h"
47 #include "prefsfile.h"
48 #include "prefsmanager.h"
49 #include "query.h"
50 #include "scclocale.h"
51 #include "sccolor.h"
52 #include "sccolorengine.h"
53 #include "scconfig.h"
54 #include "sclimits.h"
55 #include "sclistboxpixmap.h"
56 #include "scpainter.h"
57 #include "scpaths.h"
58 #include "scribus.h"
59 #include "scribusview.h"
60 #include "scribusXml.h"
61 #include "sctextstream.h"
62 #include "ui/customfdialog.h"
63 #include "undomanager.h"
64 #include "util.h"
65 #include "util_color.h"
66 #include "util_formats.h"
67 
68 
ColorsAndFillsDialog(QWidget * parent,QHash<QString,VGradient> * docGradients,const ColorList & doco,const QString & docColSet,QHash<QString,ScPattern> * docPatterns,ScribusDoc * doc,ScribusMainWindow * scMW)69 ColorsAndFillsDialog::ColorsAndFillsDialog(QWidget* parent, QHash<QString, VGradient> *docGradients, const ColorList& doco, const QString& docColSet, QHash<QString, ScPattern> *docPatterns, ScribusDoc *doc, ScribusMainWindow *scMW) : QDialog(parent)
70 {
71 	setupUi(this);
72 	setModal(true);
73 	paletteLocked = false;
74 	modified = false;
75 	sortRule = 0;
76 	m_doc = doc;
77 	m_colorList = doco;
78 	mainWin = scMW;
79 	setWindowIcon(IconManager::instance().loadIcon("AppIcon.png"));
80 	dataTree->setContextMenuPolicy(Qt::CustomContextMenu);
81 	dataTree->setIconSize(QSize(60, 48));
82 	colorItems = new QTreeWidgetItem(dataTree);
83 	colorItems->setText(0, tr("Solid Colors"));
84 	gradientItems = new QTreeWidgetItem(dataTree);
85 	gradientItems->setText(0, tr("Gradients"));
86 	for (QHash<QString, VGradient>::Iterator it = docGradients->begin(); it != docGradients->end(); ++it)
87 	{
88 		dialogGradients.insert(it.key(), it.value());
89 		origNames.insert(it.key(), it.key());
90 	}
91 	origGradients = docGradients->keys();
92 
93 	patternItems = new QTreeWidgetItem(dataTree);
94 	patternItems->setText(0, tr("Patterns"));
95 	for (QHash<QString, ScPattern>::Iterator it = docPatterns->begin(); it != docPatterns->end(); ++it)
96 	{
97 		dialogPatterns.insert(it.key(), it.value());
98 		origNamesPatterns.insert(it.key(), it.key());
99 	}
100 	origPatterns = docPatterns->keys();
101 
102 	csm.findPaletteLocations();
103 	systemSwatches = LoadColSet->addTopLevelItem( tr("Scribus Swatches"));
104 	csm.findPalettes(systemSwatches);
105 	LoadColSet->addSubItem("Scribus Small", systemSwatches);
106 	systemSwatches->setExpanded(true);
107 	userSwatches = LoadColSet->addTopLevelItem( tr("User Swatches"));
108 	csm.findUserPalettes(userSwatches);
109 	customColSet = csm.userPaletteNames();
110 	userSwatches->setExpanded(true);
111 //	QFileInfo fi(docColSet);
112 	LoadColSet->setCurrentComboItem(docColSet);
113 	if (mainWin->HaveDoc)
114 	{
115 		label->setText( tr("Merge Color Set"));
116 		m_doc->getUsedColors(inDocUsedColors);
117 		paletteLocked = false;
118 	}
119 	else
120 	{
121 		if (docColSet != "Scribus Small")
122 		{
123 			QString pfad;
124 			if (customColSet.contains(docColSet))
125 				pfad = csm.userPaletteFileFromName(docColSet);
126 			else
127 				pfad = csm.paletteFileFromName(docColSet);
128 			QFileInfo fi(pfad);
129 			if (fi.absolutePath().contains(ScPaths::applicationDataDir()+"swatches/locked"))
130 				paletteLocked = true;
131 			else
132 				paletteLocked = !fi.isWritable();
133 		}
134 	}
135 	importButton->setEnabled(false);
136 	newButton->setEnabled(false);
137 	editButton->setEnabled(false);
138 	duplicateButton->setEnabled(false);
139 	deleteButton->setEnabled(false);
140 	deleteUnusedButton->setEnabled(false);
141 	updateColorList();
142 	updateGradientList();
143 	updatePatternList();
144 	dataTree->expandItem(colorItems);
145 	dataTree->expandItem(gradientItems);
146 	dataTree->expandItem(patternItems);
147 	dataTree->setSelectionMode(QAbstractItemView::ExtendedSelection);
148 	connect(dataTree, SIGNAL(itemClicked(QTreeWidgetItem*, int)), this, SLOT(itemSelected(QTreeWidgetItem*)));
149 	connect(dataTree, SIGNAL(itemDoubleClicked(QTreeWidgetItem*, int)), this, SLOT(selEditColor(QTreeWidgetItem*)));
150 	connect(dataTree, SIGNAL(itemSelectionChanged()), this, SLOT(itemSelectionChanged()));
151 	connect(dataTree, SIGNAL(customContextMenuRequested (const QPoint &)), this, SLOT(slotRightClick(QPoint)));
152 	connect(newButton, SIGNAL(clicked()), this, SLOT(createNew()));
153 	connect(editButton, SIGNAL(clicked()), this, SLOT(editColorItem()));
154 	connect(duplicateButton, SIGNAL(clicked()), this, SLOT(duplicateColorItem()));
155 	connect(deleteButton, SIGNAL(clicked()), this, SLOT(removeColorItem()));
156 	connect(deleteUnusedButton, SIGNAL(clicked()), this, SLOT(removeUnusedColorItem()));
157 	connect(importButton, SIGNAL(clicked()), this, SLOT(importColorItems()));
158 	connect(okButton, SIGNAL(clicked()), this, SLOT(leaveDialog()));
159 	connect(cancelButton, SIGNAL(clicked()), this, SLOT(reject()));
160 	connect(SaveColSet, SIGNAL(clicked()), this, SLOT(saveDefaults()));
161 	connect(LoadColSet, SIGNAL(activated(QTreeWidgetItem*)), this, SLOT(loadDefaults(QTreeWidgetItem*)));
162 }
163 
leaveDialog()164 void ColorsAndFillsDialog::leaveDialog()
165 {
166 /*	if (!mainWin->HaveDoc)
167 	{
168 		if (modified)
169 		{
170 			if (paletteLocked)
171 				saveDefaults();
172 			else
173 				doSaveDefaults(LoadColSet->text(), true);
174 		}
175 	} */
176 	accept();
177 }
178 
updatePatternList(const QString & addedName)179 QTreeWidgetItem* ColorsAndFillsDialog::updatePatternList(const QString& addedName)
180 {
181 	QList<QTreeWidgetItem*> lg = patternItems->takeChildren();
182 	for (int i = 0; i < lg.count(); i++)
183 	{
184 		delete lg[i];
185 	}
186 	QTreeWidgetItem* ret = nullptr;
187 	QStringList patK = dialogPatterns.keys();
188 	patK.sort();
189 	for (int a = 0; a < patK.count(); a++)
190 	{
191 		ScPattern sp = dialogPatterns.value(patK[a]);
192 		QPixmap pm;
193 		if (sp.getPattern()->width() >= sp.getPattern()->height())
194 			pm = QPixmap::fromImage(sp.getPattern()->scaledToWidth(48, Qt::SmoothTransformation));
195 		else
196 			pm = QPixmap::fromImage(sp.getPattern()->scaledToHeight(48, Qt::SmoothTransformation));
197 		QPixmap pm2(48, 48);
198 		pm2.fill(palette().color(QPalette::Base));
199 		QPainter p;
200 		p.begin(&pm2);
201 		p.drawPixmap(24 - pm.width() / 2, 24 - pm.height() / 2, pm);
202 		p.end();
203 		QTreeWidgetItem *item = new QTreeWidgetItem(patternItems);
204 		item->setText(0, patK[a]);
205 		if (patK[a] == addedName)
206 			ret = item;
207 		item->setIcon(0, pm2);
208 		item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
209 	}
210 	return ret;
211 }
212 
updateGradientList(const QString & addedName)213 QTreeWidgetItem* ColorsAndFillsDialog::updateGradientList(const QString& addedName)
214 {
215 	QList<QTreeWidgetItem*> lg = gradientItems->takeChildren();
216 	for (int i = 0; i < lg.count(); i++)
217 	{
218 		delete lg[i];
219 	}
220 	QTreeWidgetItem* ret = nullptr;
221 	QStringList patK = dialogGradients.keys();
222 	patK.sort();
223 	for (int a = 0; a < patK.count(); a++)
224 	{
225 		VGradient gr = dialogGradients.value(patK[a]);
226 		QImage pixm(48, 12, QImage::Format_ARGB32);
227 		QPainter pb;
228 		QBrush b(QColor(205,205,205), IconManager::instance().loadPixmap("testfill.png"));
229 		pb.begin(&pixm);
230 		pb.fillRect(0, 0, 48, 12, b);
231 		pb.end();
232 		ScPainter *p = new ScPainter(&pixm, 48, 12);
233 		p->setPen(Qt::black, 1, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin);
234 		p->setFillMode(ScPainter::Gradient);
235 		p->fill_gradient = gr;
236 		p->setGradient(VGradient::linear, FPoint(0,6), FPoint(48, 6), FPoint(0, 0), 1.0, 0.0);
237 		p->drawRect(0, 0, 48, 12);
238 		p->end();
239 		delete p;
240 		QPixmap pm;
241 		pm = QPixmap::fromImage(pixm);
242 		QTreeWidgetItem *item = new QTreeWidgetItem(gradientItems);
243 		item->setText(0, patK[a]);
244 		if (patK[a] == addedName)
245 			ret = item;
246 		item->setIcon(0, pm);
247 		item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
248 	}
249 	return ret;
250 }
251 
updateColorList(const QString & addedName)252 QTreeWidgetItem* ColorsAndFillsDialog::updateColorList(const QString& addedName)
253 {
254 	QList<QTreeWidgetItem*> lg = colorItems->takeChildren();
255 	for (int a = 0; a < lg.count(); a++)
256 	{
257 		delete lg[a];
258 	}
259 	QTreeWidgetItem* ret = nullptr;
260 	if (sortRule > 0)
261 	{
262 		QMap<QString, QString> sortMap;
263 		ColorList::Iterator it;
264 		for (it = m_colorList.begin(); it != m_colorList.end(); ++it)
265 		{
266 			if (sortRule == 1)
267 			{
268 				QColor c = it.value().getRawRGBColor();
269 				QString sortString = QString("%1-%2-%3-%4").arg(c.hue(), 3, 10, QChar('0')).arg(c.saturation(), 3, 10, QChar('0')).arg(c.value(), 3, 10, QChar('0')).arg(it.key());
270 				sortMap.insert(sortString, it.key());
271 			}
272 			else if (sortRule == 2)
273 			{
274 				QString sortString = QString("%1-%2");
275 				if (it.value().isRegistrationColor())
276 					sortMap.insert(sortString.arg("A", it.key()), it.key());
277 				else if (it.value().isSpotColor())
278 					sortMap.insert(sortString.arg("B", it.key()), it.key());
279 				else if (it.value().getColorModel() == colorModelCMYK)
280 					sortMap.insert(sortString.arg("C", it.key()), it.key());
281 				else
282 					sortMap.insert(sortString.arg("D", it.key()), it.key());
283 			}
284 		}
285 		QMap<QString, QString>::Iterator itc;
286 		for (itc = sortMap.begin(); itc != sortMap.end(); ++itc)
287 		{
288 			const ScColor& color = m_colorList[itc.value()];
289 			QTreeWidgetItem *item = new QTreeWidgetItem(colorItems);
290 			item->setText(0, itc.value());
291 			if (itc.value() == addedName)
292 				ret = item;
293 			QPixmap* pPixmap = getFancyPixmap(color, m_doc);
294 			item->setIcon(0, *pPixmap);
295 			item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
296 			item->setData(0, Qt::ToolTipRole, getColorTooltip(color));
297 		}
298 	}
299 	else
300 	{
301 		ColorList::Iterator it;
302 		for (it = m_colorList.begin(); it != m_colorList.end(); ++it)
303 		{
304 			const ScColor& color = it.value();
305 			QTreeWidgetItem *item = new QTreeWidgetItem(colorItems);
306 			item->setText(0, it.key());
307 			if (it.key() == addedName)
308 				ret = item;
309 			QPixmap* pPixmap = getFancyPixmap(color, m_doc);
310 			item->setIcon(0, *pPixmap);
311 			item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
312 			item->setData(0, Qt::ToolTipRole, getColorTooltip(color));
313 		}
314 	}
315 	return ret;
316 }
317 
slotRightClick(QPoint p)318 void ColorsAndFillsDialog::slotRightClick(QPoint p)
319 {
320 	QTreeWidgetItem* it = dataTree->itemAt(p);
321 	if (!it)
322 		return;
323 
324 	if ((it->parent() == colorItems) || (it == colorItems))
325 	{
326 		QMenu *pmen = new QMenu();
327 //			qApp->changeOverrideCursor(QCursor(Qt::ArrowCursor));
328 		pmen->addAction( tr("Sort by Name"));
329 		pmen->addAction( tr("Sort by Color"));
330 		pmen->addAction( tr("Sort by Type"));
331 		sortRule = pmen->actions().indexOf(pmen->exec(QCursor::pos()));
332 		delete pmen;
333 		updateColorList();
334 	}
335 }
336 
selEditColor(QTreeWidgetItem * it)337 void ColorsAndFillsDialog::selEditColor(QTreeWidgetItem *it)
338 {
339 	if ((it) && (!paletteLocked))
340 	{
341 		if ((it->parent() == colorItems) || (it->parent() == gradientItems))
342 		{
343 			QString curCol = it->text(0);
344 			bool enableDel  = (!isMandatoryColor(curCol)) && (m_colorList.count() > 1);
345 			bool enableEdit = (!isMandatoryColor(curCol));
346 			duplicateButton->setEnabled(curCol != "Registration");
347 			deleteButton->setEnabled(enableDel);
348 			editButton->setEnabled(enableEdit);
349 			if (enableEdit)
350 				editColorItem();
351 		}
352 	}
353 }
354 
itemSelectionChanged()355 void ColorsAndFillsDialog::itemSelectionChanged()
356 {
357 	QList<QTreeWidgetItem *> selItems = dataTree->selectedItems();
358 	if (selItems.count() > 1)
359 		deleteButton->setEnabled(true);
360 }
361 
itemSelected(QTreeWidgetItem * it)362 void ColorsAndFillsDialog::itemSelected(QTreeWidgetItem* it)
363 {
364 	QList<QTreeWidgetItem *> selItems = dataTree->selectedItems();
365 	importButton->setText( tr("&Import"));
366 	newButton->setText( tr("Add"));
367 	editButton->setText( tr("&Edit"));
368 	if ((it) && (!paletteLocked))
369 	{
370 		if ((it->parent() == colorItems) || (it->parent() == gradientItems))
371 		{
372 			importButton->setEnabled(false);
373 			newButton->setEnabled(true);
374 			deleteUnusedButton->setEnabled(it->parent() == colorItems);
375 			if (it->parent() == colorItems)
376 			{
377 				QString curCol = it->text(0);
378 				//ScColor tmpColor = m_colorList[curCol];
379 				bool enableDel  = (!isMandatoryColor(curCol)) && (m_colorList.count() > 1);
380 				bool enableEdit = (!isMandatoryColor(curCol));
381 				duplicateButton->setEnabled(curCol != "Registration");
382 				deleteButton->setEnabled(enableDel);
383 				editButton->setEnabled(enableEdit);
384 			}
385 			else
386 			{
387 				editButton->setEnabled(true);
388 				duplicateButton->setEnabled(true);
389 				deleteButton->setEnabled(true);
390 			}
391 		}
392 		else if (it->parent() == patternItems)
393 		{
394 			importButton->setText( tr("Load File"));
395 			newButton->setText( tr("Load Set"));
396 			editButton->setText( tr("Rename"));
397 			importButton->setEnabled(true);
398 			newButton->setEnabled(true);
399 			editButton->setEnabled(true);
400 			duplicateButton->setEnabled(false);
401 			deleteButton->setEnabled(true);
402 		}
403 		else if (it == patternItems)
404 		{
405 			importButton->setText( tr("Load File"));
406 			newButton->setText( tr("Load Set"));
407 			importButton->setEnabled(true);
408 			newButton->setEnabled(true);
409 			editButton->setEnabled(false);
410 			duplicateButton->setEnabled(false);
411 			if (selItems.count() < 2)
412 				deleteButton->setEnabled(it->childCount() > 0);
413 			else
414 				deleteButton->setEnabled(true);
415 		}
416 		else
417 		{
418 			importButton->setEnabled(true);
419 			newButton->setEnabled(true);
420 			editButton->setEnabled(false);
421 			duplicateButton->setEnabled(false);
422 			if (selItems.count() < 2)
423 				deleteButton->setEnabled(it->childCount() > 0);
424 			else
425 				deleteButton->setEnabled(true);
426 			deleteUnusedButton->setEnabled((it == colorItems) && (it->childCount() > 0));
427 		}
428 	}
429 	else
430 	{
431 		importButton->setEnabled(false);
432 		newButton->setEnabled(false);
433 		editButton->setEnabled(false);
434 		duplicateButton->setEnabled(false);
435 		deleteButton->setEnabled(false);
436 		deleteUnusedButton->setEnabled(false);
437 		dataTree->clearSelection();
438 	}
439 }
440 
createNew()441 void ColorsAndFillsDialog::createNew()
442 {
443 	if (paletteLocked)
444 		return;
445 	QTreeWidgetItem* it = dataTree->currentItem();
446 	if (!it)
447 		return;
448 
449 	if ((it->parent() == gradientItems) || (it == gradientItems))
450 	{
451 		VGradient fill_gradient = VGradient(VGradient::linear);
452 		fill_gradient.clearStops();
453 		fill_gradient.addStop(QColor(Qt::black), 0.0, 0.5, 1.0, "Black", 100);
454 		fill_gradient.addStop(QColor(Qt::white), 1.0, 0.5, 1.0, "White", 100);
455 		gradientEditDialog *dia = new gradientEditDialog(this, tr("New Gradient"), fill_gradient, m_colorList, m_doc, &dialogGradients, true);
456 		if (dia->exec())
457 		{
458 			dialogGradients.insert(dia->name(), dia->gradient());
459 			QTreeWidgetItem *lg = updateGradientList(dia->name());
460 			if (lg != nullptr)
461 			{
462 				dataTree->expandItem(lg->parent());
463 				dataTree->setCurrentItem(lg, 0, QItemSelectionModel::ClearAndSelect);
464 			}
465 			itemSelected(dataTree->currentItem());
466 			modified = true;
467 		}
468 		delete dia;
469 	}
470 	else if ((it->parent() == colorItems) || (it == colorItems))
471 	{
472 		ScColor tmpColor = ScColor(0, 0, 0, 0);
473 		CMYKChoose* dia = new CMYKChoose(this, m_doc, tmpColor, tr("New Color"), &m_colorList, true);
474 		if (dia->exec())
475 		{
476 			dia->Farbe.setSpotColor(dia->isSpotColor());
477 			m_colorList.insert(dia->colorName(), dia->Farbe);
478 			QTreeWidgetItem *lg = updateColorList(dia->colorName());
479 			if (lg != nullptr)
480 			{
481 				dataTree->expandItem(lg->parent());
482 				dataTree->setCurrentItem(lg, 0, QItemSelectionModel::ClearAndSelect);
483 			}
484 			itemSelected(dataTree->currentItem());
485 			modified = true;
486 		}
487 		delete dia;
488 	}
489 	else if ((it->parent() == patternItems) || (it == patternItems))
490 	{
491 		loadPatternDir();
492 		updateColorList();
493 		updateGradientList();
494 		updatePatternList();
495 		itemSelected(nullptr);
496 	}
497 }
498 
editColorItem()499 void ColorsAndFillsDialog::editColorItem()
500 {
501 	if (paletteLocked)
502 		return;
503 	QTreeWidgetItem* it = dataTree->currentItem();
504 	if (!it)
505 		return;
506 
507 	if (it->parent() == gradientItems)
508 	{
509 		QString gradN = it->text(0);
510 		QString patternName = origNames[it->text(0)];
511 		QString newName;
512 		gradientEditDialog *dia = new gradientEditDialog(this, gradN, dialogGradients[gradN], m_colorList, m_doc, &dialogGradients, false);
513 		if (dia->exec())
514 		{
515 			newName = dia->name();
516 			if (newName != gradN)
517 			{
518 				origNames.remove(patternName);
519 				origNames.insert(newName, patternName);
520 				replaceMap.insert(patternName, newName);
521 				dialogGradients.remove(gradN);
522 				dialogGradients.insert(newName, dia->gradient());
523 			}
524 			else
525 				dialogGradients[gradN] = dia->gradient();
526 			QStringList patterns = dialogPatterns.keys();
527 			for (int c = 0; c < dialogPatterns.count(); ++c)
528 			{
529 				ScPattern pa = dialogPatterns[patterns[c]];
530 				for (int o = 0; o < pa.items.count(); o++)
531 				{
532 					PageItem *ite = pa.items.at(o);
533 					if (ite->gradient() == gradN)
534 						ite->setGradient(newName);
535 					if (ite->strokeGradient() == gradN)
536 						ite->setStrokeGradient(newName);
537 					if (ite->gradientMask() == gradN)
538 						ite->setGradientMask(newName);
539 				}
540 				PageItem *ite = pa.items.at(0);
541 				dialogPatterns[patterns[c]].pattern = ite->DrawObj_toImage(pa.items, 1.0);
542 			}
543 			QTreeWidgetItem *lg = updateGradientList(dia->name());
544 			if (lg != nullptr)
545 			{
546 				dataTree->expandItem(lg->parent());
547 				dataTree->setCurrentItem(lg, 0, QItemSelectionModel::ClearAndSelect);
548 			}
549 			itemSelected(dataTree->currentItem());
550 			modified = true;
551 		}
552 		delete dia;
553 	}
554 	else if (it->parent() == colorItems)
555 	{
556 		ScColor tmpColor = m_colorList[it->text(0)];
557 		CMYKChoose* dia = new CMYKChoose(this, m_doc, tmpColor, it->text(0), &m_colorList, false);
558 		if (dia->exec())
559 		{
560 			dia->Farbe.setSpotColor(dia->isSpotColor());
561 			dia->Farbe.setRegistrationColor(tmpColor.isRegistrationColor());
562 			m_colorList[dia->colorName()] = dia->Farbe;
563 			if (it->text(0) != dia->colorName())
564 			{
565 				replaceColorMap.insert(it->text(0), dia->colorName());
566 				m_colorList.remove(it->text(0));
567 			}
568 			updateGradientColors(dia->colorName(), it->text(0));
569 			updateGradientList();
570 			updatePatternList();
571 			QTreeWidgetItem *lg = updateColorList(dia->colorName());
572 			if (lg != nullptr)
573 			{
574 				dataTree->expandItem(lg->parent());
575 				dataTree->setCurrentItem(lg, 0, QItemSelectionModel::ClearAndSelect);
576 			}
577 			itemSelected(dataTree->currentItem());
578 			modified = true;
579 		}
580 		delete dia;
581 	}
582 	else if (it->parent() == patternItems)
583 	{
584 		QString patternName = origNames[it->text(0)];
585 		QString newName = "";
586 		Query dia(this, "tt", true, tr("&Name:"), tr("Rename Entry"));
587 		dia.setEditText(it->text(0), true);
588 		dia.setTestList(dialogPatterns.keys());
589 		if (dia.exec())
590 		{
591 			newName = dia.getEditText();
592 			ScPattern pat = dialogPatterns.take(it->text(0));
593 			dialogPatterns.insert(newName, pat);
594 			replaceMapPatterns.insert(patternName, newName);
595 			origNamesPatterns.remove(it->text(0));
596 			origNamesPatterns.insert(newName, patternName);
597 			QStringList patterns = dialogPatterns.keys();
598 			for (int c = 0; c < dialogPatterns.count(); ++c)
599 			{
600 				ScPattern pa = dialogPatterns[patterns[c]];
601 				for (int o = 0; o < pa.items.count(); o++)
602 				{
603 					PageItem *ite = pa.items.at(o);
604 					if ((ite->pattern() == patternName) && ((ite->GrType == 8) || (ite->itemType() == PageItem::Symbol)))
605 						ite->setPattern(newName);
606 					if (!ite->strokePattern().isEmpty())
607 					{
608 						if (ite->strokePattern() == patternName)
609 							ite->setStrokePattern(newName);
610 					}
611 					if (!ite->patternMask().isEmpty())
612 					{
613 						if (ite->patternMask() == patternName)
614 							ite->setPatternMask(newName);
615 					}
616 				}
617 			}
618 			QTreeWidgetItem *lg = updatePatternList(newName);
619 			if (lg != nullptr)
620 			{
621 				dataTree->expandItem(lg->parent());
622 				dataTree->setCurrentItem(lg, 0, QItemSelectionModel::ClearAndSelect);
623 			}
624 			itemSelected(dataTree->currentItem());
625 		}
626 		else
627 			return;
628 	}
629 }
630 
duplicateColorItem()631 void ColorsAndFillsDialog::duplicateColorItem()
632 {
633 	if (paletteLocked)
634 		return;
635 	QTreeWidgetItem* it = dataTree->currentItem();
636 	if (!it)
637 		return;
638 
639 	if (it->parent() == gradientItems)
640 	{
641 		QString gradN = tr("Copy of %1").arg(it->text(0));
642 		dialogGradients.insert(gradN, dialogGradients[it->text(0)]);
643 		origNames.insert(gradN, gradN);
644 		QString patternName = origNames[gradN];
645 		QString newName;
646 		gradientEditDialog *dia = new gradientEditDialog(this, gradN, dialogGradients[gradN], m_colorList, m_doc, &dialogGradients, false);
647 		if (dia->exec())
648 		{
649 			newName = dia->name();
650 			if (newName != gradN)
651 			{
652 				origNames.remove(patternName);
653 				origNames.insert(newName, patternName);
654 				replaceMap.insert(patternName, newName);
655 				dialogGradients.remove(gradN);
656 				dialogGradients.insert(newName, dia->gradient());
657 			}
658 			else
659 				dialogGradients[gradN] = dia->gradient();
660 			updatePatternList();
661 			QTreeWidgetItem *lg = updateGradientList(dia->name());
662 			if (lg != nullptr)
663 			{
664 				dataTree->expandItem(lg->parent());
665 				dataTree->setCurrentItem(lg, 0, QItemSelectionModel::ClearAndSelect);
666 			}
667 			itemSelected(dataTree->currentItem());
668 			modified = true;
669 		}
670 		else
671 		{
672 			dialogGradients.remove(gradN);
673 			origNames.remove(gradN);
674 		}
675 		delete dia;
676 	}
677 	else if (it->parent() == colorItems)
678 	{
679 		QString nam = tr("Copy of %1").arg(it->text(0));
680 		m_colorList.insert(nam, m_colorList[it->text(0)]);
681 		ScColor tmpColor = m_colorList[nam];
682 		CMYKChoose* dia = new CMYKChoose(this, m_doc, tmpColor, nam, &m_colorList, false);
683 		if (dia->exec())
684 		{
685 			dia->Farbe.setSpotColor(dia->isSpotColor());
686 			dia->Farbe.setRegistrationColor(tmpColor.isRegistrationColor());
687 			m_colorList[dia->colorName()] = dia->Farbe;
688 			if (nam != dia->colorName())
689 			{
690 				replaceColorMap.insert(nam, dia->colorName());
691 				m_colorList.remove(nam);
692 			}
693 			updateGradientColors(dia->colorName(), nam);
694 			updateGradientList();
695 			updatePatternList();
696 			QTreeWidgetItem *lg = updateColorList(dia->colorName());
697 			if (lg != nullptr)
698 			{
699 				dataTree->expandItem(lg->parent());
700 				dataTree->setCurrentItem(lg, 0, QItemSelectionModel::ClearAndSelect);
701 			}
702 			itemSelected(dataTree->currentItem());
703 			modified = true;
704 		}
705 		else
706 			m_colorList.remove(nam);
707 		delete dia;
708 	}
709 }
710 
removeColorItem()711 void ColorsAndFillsDialog::removeColorItem()
712 {
713 	if (paletteLocked)
714 		return;
715 	QList<QTreeWidgetItem *> selItems = dataTree->selectedItems();
716 	if (selItems.count() > 1)
717 	{
718 		QStringList usedColors;
719 		QStringList colors;
720 		QStringList gradients;
721 		QStringList patterns;
722 		for (int a = 0; a < selItems.count(); a++)
723 		{
724 			QTreeWidgetItem* it = selItems[a];
725 			if (it == gradientItems)
726 				continue;
727 			if (it == colorItems)
728 				continue;
729 			if (it == patternItems)
730 				continue;
731 			if (isMandatoryColor(it->text(0)))
732 				continue;
733 			if (it->parent() == gradientItems)
734 				gradients.append(it->text(0));
735 			if (it->parent() == colorItems)
736 				colors.append(it->text(0));
737 			if (it->parent() == patternItems)
738 				patterns.append(it->text(0));
739 		}
740 		for (int a = 0; a < gradients.count(); a++)
741 		{
742 			dialogGradients.remove(gradients[a]);
743 			replaceMap.insert(gradients[a], "");
744 		}
745 		bool hasUsed = false;
746 		ColorList UsedCG = getGradientColors();
747 		for (int a = 0; a < colors.count(); a++)
748 		{
749 			if (UsedCG.contains(colors[a]) || inDocUsedColors.contains(colors[a]))
750 			{
751 				hasUsed = true;
752 				usedColors.append(colors[a]);
753 			}
754 		}
755 		if (hasUsed)
756 		{
757 			ColorList dCols = m_colorList;
758 			QString dColor = tr("Selected Colors");
759 			for (int i = 0; i < usedColors.count(); i++)
760 			{
761 				dCols.remove(usedColors[i]);
762 			}
763 			dCols.insert(dColor , ScColor());
764 			DelColor *dia = new DelColor(this, dCols, dColor, true);
765 			if (dia->exec())
766 			{
767 				QString replacementColor(dia->getReplacementColor());
768 				for (int i = 0; i < colors.count(); i++)
769 				{
770 					dColor = colors[i];
771 					if (replacementColor == CommonStrings::tr_NoneColor)
772 						replacementColor = CommonStrings::None;
773 					if (replaceColorMap.values().contains(dColor))
774 					{
775 						QMap<QString,QString>::Iterator itt;
776 						for (itt = replaceColorMap.begin(); itt != replaceColorMap.end(); ++itt)
777 						{
778 							if (itt.value() == dColor)
779 								itt.value() = replacementColor;
780 						}
781 					}
782 					replaceColorMap.insert(dColor, replacementColor);
783 					m_colorList.remove(dColor);
784 					updateGradientColors(replacementColor, dColor);
785 				}
786 				modified = true;
787 			}
788 			delete dia;
789 		}
790 		else
791 		{
792 			for (int a = 0; a < colors.count(); a++)
793 			{
794 				replaceColorMap.insert(colors[a], "Black");
795 				m_colorList.remove(colors[a]);
796 			}
797 			modified = true;
798 		}
799 		updatePatternList();
800 		updateGradientList();
801 		updateColorList();
802 		itemSelected(nullptr);
803 	}
804 	else
805 	{
806 		QTreeWidgetItem* it = dataTree->currentItem();
807 		if (!it)
808 			return;
809 		if ((it->parent() == gradientItems) || (it == gradientItems))
810 		{
811 			if (it == gradientItems)
812 			{
813 				int t = ScMessageBox::warning(this, CommonStrings::trWarning, tr("Do you really want to clear all your gradients?"),
814 						QMessageBox::Yes | QMessageBox::No,
815 						QMessageBox::No,	// GUI default
816 						QMessageBox::Yes);	// batch default
817 				if (t == QMessageBox::No)
818 					return;
819 				replaceMap.clear();
820 				for (QHash<QString, VGradient>::Iterator it = dialogGradients.begin(); it != dialogGradients.end(); ++it)
821 				{
822 					replaceMap.insert(it.key(), "");
823 				}
824 				dialogGradients.clear();
825 			}
826 			else
827 			{
828 				dialogGradients.remove(it->text(0));
829 				replaceMap.insert(it->text(0), "");
830 			}
831 		}
832 		else if ((it->parent() == colorItems) || (it == colorItems))
833 		{
834 			if (it == colorItems)
835 			{
836 				int t = ScMessageBox::warning(this, CommonStrings::trWarning, tr("Do you really want to clear all your colors and gradients?"),
837 						QMessageBox::Yes | QMessageBox::No,
838 						QMessageBox::No,	// GUI default
839 						QMessageBox::Yes);	// batch default
840 				if (t == QMessageBox::No)
841 					return;
842 				replaceMap.clear();
843 				for (QHash<QString, VGradient>::Iterator it = dialogGradients.begin(); it != dialogGradients.end(); ++it)
844 				{
845 					replaceMap.insert(it.key(), "");
846 				}
847 				replaceColorMap.clear();
848 				for (ColorList::Iterator it = m_colorList.begin(); it != m_colorList.end(); ++it)
849 				{
850 					replaceColorMap.insert(it.key(), "Black");
851 				}
852 				dialogPatterns.clear();
853 				dialogGradients.clear();
854 				m_colorList.clear();
855 				m_colorList.ensureDefaultColors();
856 			}
857 			else
858 			{
859 				QString dColor = it->text(0);
860 				if (isMandatoryColor(dColor))
861 					return;
862 				ColorList UsedCG = getGradientColors();
863 				if (inDocUsedColors.contains(dColor) || UsedCG.contains(dColor))
864 				{
865 					DelColor *dia = new DelColor(this, m_colorList, dColor, true);
866 					if (dia->exec())
867 					{
868 						QString replacementColor(dia->getReplacementColor());
869 						if (replacementColor == CommonStrings::tr_NoneColor)
870 							replacementColor = CommonStrings::None;
871 						if (replaceColorMap.values().contains(dColor))
872 						{
873 							QMap<QString,QString>::Iterator itt;
874 							for (itt = replaceColorMap.begin(); itt != replaceColorMap.end(); ++itt)
875 							{
876 								if (itt.value() == dColor)
877 									itt.value() = replacementColor;
878 							}
879 						}
880 						replaceColorMap.insert(dColor, replacementColor);
881 						m_colorList.remove(dColor);
882 						updateGradientColors(replacementColor, dColor);
883 					}
884 					delete dia;
885 				}
886 				else
887 				{
888 					replaceColorMap.insert(dColor, "Black");
889 					updateGradientColors("Black", dColor);
890 					m_colorList.remove(dColor);
891 				}
892 			}
893 		}
894 		else if ((it->parent() == patternItems) || (it == patternItems))
895 		{
896 			if (it == patternItems)
897 			{
898 				int t = ScMessageBox::warning(this, CommonStrings::trWarning, tr("Do you really want to clear all your patterns?"),
899 							QMessageBox::Yes | QMessageBox::No,
900 							QMessageBox::No,	// GUI default
901 							QMessageBox::Yes);	// batch default
902 				if (t == QMessageBox::No)
903 					return;
904 				replaceMapPatterns.clear();
905 				for (QHash<QString, ScPattern>::Iterator it = dialogPatterns.begin(); it != dialogPatterns.end(); ++it)
906 				{
907 					replaceMapPatterns.insert(it.key(), "");
908 				}
909 				dialogPatterns.clear();
910 			}
911 			else if (it->parent() == patternItems)
912 			{
913 				QStringList patterns2Del;
914 				QStringList mainPatterns = dialogPatterns.keys();
915 				for (int a = 0; a < mainPatterns.count(); a++)
916 				{
917 					if (mainPatterns[a] != it->text(0))
918 					{
919 						QStringList subPatterns;
920 						subPatterns = getUsedPatternsHelper(mainPatterns[a], subPatterns);
921 						if (subPatterns.contains(it->text(0)))
922 							patterns2Del.append(mainPatterns[a]);
923 					}
924 				}
925 				patterns2Del.append(it->text(0));
926 				for (int a = 0; a < patterns2Del.count(); a++)
927 				{
928 					dialogPatterns.remove(patterns2Del[a]);
929 				}
930 			}
931 		}
932 		updatePatternList();
933 		updateGradientList();
934 		updateColorList();
935 		itemSelected(nullptr);
936 		modified = true;
937 	}
938 }
939 
getUsedPatternsHelper(const QString & pattern,QStringList & results)940 QStringList ColorsAndFillsDialog::getUsedPatternsHelper(const QString& pattern, QStringList &results)
941 {
942 	ScPattern *pat = &dialogPatterns[pattern];
943 	QStringList pats;
944 	pats.clear();
945 	for (int c = 0; c < pat->items.count(); ++c)
946 	{
947 		if ((pat->items.at(c)->GrType == Gradient_Pattern) || (pat->items.at(c)->itemType() == PageItem::Symbol))
948 		{
949 			const QString& patName = pat->items.at(c)->pattern();
950 			if (!patName.isEmpty() && !results.contains(patName))
951 				pats.append(patName);
952 		}
953 		const QString& pat2 = pat->items.at(c)->strokePattern();
954 		if (!pat2.isEmpty() && !results.contains(pat2))
955 			pats.append(pat->items.at(c)->strokePattern());
956 		const QString& pat3 = pat->items.at(c)->patternMask();
957 		if (!pat3.isEmpty() && !results.contains(pat3))
958 			pats.append(pat->items.at(c)->patternMask());
959 	}
960 	if (!pats.isEmpty())
961 	{
962 		results = pats;
963 		for (int c = 0; c < pats.count(); ++c)
964 		{
965 			getUsedPatternsHelper(pats[c], results);
966 		}
967 	}
968 /*	QStringList pats;
969 	pats.clear();
970 	for (int c = 0; c < pat->items.count(); ++c)
971 	{
972 		if ((!results.contains(pat->items.at(c)->pattern())) && ((pat->items.at(c)->GrType == Gradient_Pattern) || (pat->items.at(c)->itemType() == PageItem::Symbol)))
973 			pats.append(pat->items.at(c)->pattern());
974 	}
975 	if (!pats.isEmpty())
976 	{
977 		results = pats;
978 		for (int c = 0; c < pats.count(); ++c)
979 		{
980 			getUsedPatternsHelper(pats[c], results);
981 		}
982 	} */
983 	return results;
984 }
985 
removeUnusedColorItem()986 void ColorsAndFillsDialog::removeUnusedColorItem()
987 {
988 	if (paletteLocked)
989 		return;
990 	QTreeWidgetItem* it = dataTree->currentItem();
991 	if (!it)
992 		return;
993 
994 	if ((it->parent() == colorItems) || (it == colorItems))
995 	{
996 		ColorList UsedC;
997 		ColorList::Iterator it;
998 		ColorList UsedCG = getGradientColors();
999 		if (mainWin->HaveDoc)
1000 		{
1001 			m_colorList = inDocUsedColors;
1002 			for (it = UsedCG.begin(); it != UsedCG.end(); ++it)
1003 			{
1004 				if (!m_colorList.contains(it.key()))
1005 					m_colorList.insert(it.key(), it.value());
1006 			}
1007 		}
1008 		else
1009 			m_colorList = UsedCG;
1010 		m_colorList.ensureDefaultColors();
1011 		updatePatternList();
1012 		updateGradientList();
1013 		updateColorList();
1014 		itemSelected(nullptr);
1015 		modified = true;
1016 	}
1017 }
1018 
importColorItems()1019 void ColorsAndFillsDialog::importColorItems()
1020 {
1021 	QTreeWidgetItem* it = dataTree->currentItem();
1022 	if (!it)
1023 		return;
1024 
1025 	if ((it->parent() == gradientItems) || (it == gradientItems))
1026 	{
1027 		QString fileName;
1028 		QString allFormats = tr("All Supported Formats")+" (";
1029 		allFormats += "*.sgr *.SGR";
1030 		allFormats += " *.ggr *.GGR";
1031 		allFormats += ");;";
1032 		QString formats = tr("Scribus Gradient Files \"*.sgr\" (*.sgr *.SGR);;");
1033 		formats += tr("Gimp Gradient Files \"*.ggr\" (*.ggr *.GGR);;");
1034 		formats += tr("All Files (*)");
1035 		allFormats += formats;
1036 		PrefsContext* dirs = PrefsManager::instance().prefsFile->getContext("dirs");
1037 		QString wdir = dirs->get("gradients", ".");
1038 		CustomFDialog dia(this, wdir, tr("Open"), allFormats, fdHidePreviewCheckBox | fdExistingFiles | fdDisableOk);
1039 		if (dia.exec() == QDialog::Accepted)
1040 			fileName = dia.selectedFile();
1041 		else
1042 			return;
1043 		if (!fileName.isEmpty())
1044 		{
1045 			PrefsManager::instance().prefsFile->getContext("dirs")->set("gradients", fileName.left(fileName.lastIndexOf("/")));
1046 			QFileInfo fi(fileName);
1047 			QString ext = fi.suffix().toLower();
1048 			if (ext == "sgr")
1049 				loadScribusFormat(fileName);
1050 			else if (ext == "ggr")
1051 				loadGimpFormat(fileName);
1052 			updateGradientList();
1053 			updateColorList();
1054 			itemSelected(nullptr);
1055 			modified = true;
1056 		}
1057 	}
1058 	else if ((it->parent() == colorItems) || (it == colorItems))
1059 	{
1060 		QStringList allFormatsV = LoadSavePlugin::getExtensionsForColors();
1061 		allFormatsV.removeAll("sla");
1062 		allFormatsV.removeAll("scd");
1063 		allFormatsV.removeAll("sla.gz");
1064 		allFormatsV.removeAll("scd.gz");
1065 		allFormatsV.removeAll("ai");
1066 		QString extra = allFormatsV.join(" *.");
1067 		extra.prepend(" *.");
1068 		QString fileName;
1069 		PrefsContext* dirs = PrefsManager::instance().prefsFile->getContext("dirs");
1070 		QString wdir = dirs->get("colors", ".");
1071 		QString docexts("*.sla *.sla.gz *.scd *.scd.gz");
1072 		QString aiepsext(FormatsManager::instance()->extensionListForFormat(FormatsManager::EPS|FormatsManager::PS|FormatsManager::AI, 0));
1073 		QString ooexts(" *.acb *.aco *.ase *.cxf *.gpl *.sbz *.skp *.soc *.xml");
1074 		ooexts += extra;
1075 		QString filter = tr("All Supported Formats (%1);;Documents (%2);;Other Files (%3);;All Files (*)").arg(docexts+" "+aiepsext+ooexts, docexts, aiepsext+ooexts);
1076 		CustomFDialog dia(this, wdir, tr("Import Colors"), filter, fdHidePreviewCheckBox | fdDisableOk);
1077 		if (dia.exec() == QDialog::Accepted)
1078 			fileName = dia.selectedFile();
1079 		else
1080 			return;
1081 		if (!fileName.isEmpty())
1082 			dirs->set("colors", fileName.left(fileName.lastIndexOf("/")));
1083 		if (!importColorsFromFile(fileName, m_colorList))
1084 			ScMessageBox::information(this, tr("Information"), "<qt>" + tr("The file %1 does not contain colors which can be imported.\nIf the file was a PostScript-based, try to import it with File -&gt; Import. \nNot all files have DSC conformant comments where the color descriptions are located.\n This prevents importing colors from some files.\nSee the Edit Colors section of the documentation for more details.").arg(fileName) + "</qt>");
1085 		else
1086 		{
1087 			m_colorList.ensureDefaultColors();
1088 			updateGradientList();
1089 			updateColorList();
1090 			modified = true;
1091 		}
1092 		itemSelected(nullptr);
1093 	}
1094 	else if ((it->parent() == patternItems) || (it == patternItems))
1095 	{
1096 		QString fileName;
1097 		QStringList formats;
1098 		QString allFormats = tr("All Supported Formats")+" (";
1099 		int fmtCode = FORMATID_FIRSTUSER;
1100 		const FileFormat *fmt = LoadSavePlugin::getFormatById(fmtCode);
1101 		while (fmt != nullptr)
1102 		{
1103 			if (fmt->load)
1104 			{
1105 				formats.append(fmt->filter);
1106 				int an = fmt->filter.indexOf("(");
1107 				int en = fmt->filter.indexOf(")");
1108 				while (an != -1)
1109 				{
1110 					allFormats += fmt->filter.mid(an+1, en-an-1)+" ";
1111 					an = fmt->filter.indexOf("(", en);
1112 					en = fmt->filter.indexOf(")", an);
1113 				}
1114 			}
1115 			fmtCode++;
1116 			fmt = LoadSavePlugin::getFormatById(fmtCode);
1117 		}
1118 		allFormats += "*.sce *.SCE ";
1119 		formats.append("Scribus Objects (*.sce *.SCE)");
1120 		QString form1 = "";
1121 		QString form2 = "";
1122 		QStringList imgFormats;
1123 		bool jpgFound = false;
1124 		bool tiffFound = false;
1125 		for (int i = 0; i < QImageReader::supportedImageFormats().count(); ++i )
1126 		{
1127 			form1 = QString(QImageReader::supportedImageFormats().at(i)).toLower();
1128 			form2 = QString(QImageReader::supportedImageFormats().at(i)).toUpper();
1129 			if ((form1 == "png") || (form1 == "xpm") || (form1 == "gif"))
1130 			{
1131 				formats.append(form2 + " (*."+form1+" *."+form2+")");
1132 				allFormats += "*."+form1+" *."+form2+" ";
1133 				imgFormats.append(form1);
1134 			}
1135 			else if ((form1 == "jpg") || (form1 == "jpeg"))
1136 			{
1137 				// JPEG is a special case because both .jpg and .jpeg
1138 				// are acceptable extensions.
1139 				if (!jpgFound)
1140 				{
1141 					formats.append("JPEG (*.jpg *.jpeg *.JPG *.JPEG)");
1142 					allFormats += "*.jpg *.jpeg *.JPG *.JPEG ";
1143 					imgFormats.append("jpeg");
1144 					imgFormats.append("jpg");
1145 					jpgFound = true;
1146 				}
1147 			}
1148 			else if ((form1 == "tif") || (form1 == "tiff"))
1149 			{
1150 				if (!tiffFound)
1151 				{
1152 					formats.append("TIFF (*.tif *.tiff *.TIF *.TIFF)");
1153 					allFormats += "*.tif *.tiff *.TIF *.TIFF ";
1154 					imgFormats.append("tif");
1155 					imgFormats.append("tiff");
1156 					tiffFound = true;
1157 				}
1158 			}
1159 			else if (form1 != "svg")
1160 			{
1161 				imgFormats.append(form1);
1162 				allFormats += "*."+form1+" *."+form2+" ";
1163 			}
1164 		}
1165 		if (!tiffFound)
1166 		{
1167 			formats.append("TIFF (*.tif *.tiff *.TIF *.TIFF)");
1168 			allFormats += "*.tif *.tiff *.TIF *.TIFF ";
1169 		}
1170 		if (!jpgFound)
1171 		{
1172 			formats.append("JPEG (*.jpg *.jpeg *.JPG *.JPEG)");
1173 			allFormats += "*.jpg *.jpeg *.JPG *.JPEG ";
1174 		}
1175 		formats.append("PSD (*.psd *.PSD)");
1176 		formats.append("Gimp Patterns (*.pat *.PAT)");
1177 		allFormats += "*.psd *.PSD ";
1178 		allFormats += "*.pat *.PAT);;";
1179 		imgFormats.append("tif");
1180 		imgFormats.append("tiff");
1181 		imgFormats.append("pat");
1182 		imgFormats.append("psd");
1183 	//	imgFormats.append("pdf");
1184 		imgFormats.append("eps");
1185 		imgFormats.append("epsi");
1186 		imgFormats.append("ps");
1187 		formats.sort();
1188 		allFormats += formats.join(";;");
1189 		PrefsContext* dirs = PrefsManager::instance().prefsFile->getContext("dirs");
1190 		QString wdir = dirs->get("patterns", ".");
1191 		CustomFDialog dia(this, wdir, tr("Open"), allFormats, fdHidePreviewCheckBox | fdExistingFiles | fdDisableOk);
1192 		if (dia.exec() != QDialog::Accepted)
1193 			return;
1194 		fileName = dia.selectedFile();
1195 		if (fileName.isEmpty())
1196 			return;
1197 		qApp->setOverrideCursor(QCursor(Qt::WaitCursor));
1198 		PrefsManager::instance().prefsFile->getContext("dirs")->set("patterns", fileName.left(fileName.lastIndexOf("/")));
1199 		QFileInfo fi(fileName);
1200 		if ((fi.suffix().toLower() == "sce") || (!imgFormats.contains(fi.suffix().toLower())))
1201 		{
1202 			loadVectors(fileName);
1203 		}
1204 		else
1205 		{
1206 			QString patNam = fi.baseName().trimmed().simplified().replace(" ", "_");
1207 			ScPattern pat = ScPattern();
1208 			pat.setDoc(m_doc);
1209 			pat.setPattern(fileName);
1210 			if (!dialogPatterns.contains(patNam))
1211 			{
1212 				dialogPatterns.insert(patNam, pat);
1213 				origNamesPatterns.insert(patNam, patNam);
1214 			}
1215 		}
1216 		updateColorList();
1217 		updateGradientList();
1218 		updatePatternList();
1219 		itemSelected(nullptr);
1220 		qApp->restoreOverrideCursor();
1221 	}
1222 }
1223 
loadPatternDir()1224 void ColorsAndFillsDialog::loadPatternDir()
1225 {
1226 	PrefsContext* dirs = PrefsManager::instance().prefsFile->getContext("dirs");
1227 	QString wdir = dirs->get("patterndir", ".");
1228 	QString fileName = QFileDialog::getExistingDirectory(this, tr("Choose a Directory"), wdir);
1229 	if (fileName.isEmpty())
1230 		return;
1231 
1232 	QStringList formats;
1233 	formats += "eps";
1234 	formats += "epsi";
1235 	formats += "pdf";
1236 	QString form1 = "";
1237 	for (int i = 0; i < QImageReader::supportedImageFormats().count(); ++i)
1238 	{
1239 		form1 = QString(QImageReader::supportedImageFormats().at(i)).toLower();
1240 		if (form1 == "jpeg")
1241 			form1 = "jpg";
1242 		if ((form1 == "png") || (form1 == "xpm") || (form1 == "gif"))
1243 		formats += form1;
1244 		else if (form1 == "jpg")
1245 		{
1246 			formats += "jpg";
1247 			formats += "jpeg";
1248 		}
1249 	}
1250 	formats += "tif";
1251 	formats += "tiff";
1252 	formats += "psd";
1253 	formats += "pat";
1254 	QDir d(fileName, "*", QDir::Name, QDir::Files | QDir::Readable | QDir::NoSymLinks);
1255 	if ((!d.exists()) || (d.count() == 0))
1256 		return;
1257 
1258 	mainWin->setStatusBarInfoText( tr("Loading Patterns"));
1259 	mainWin->mainWindowProgressBar->reset();
1260 	mainWin->mainWindowProgressBar->setMaximum(d.count() * 2);
1261 	qApp->setOverrideCursor(QCursor(Qt::WaitCursor));
1262 	qApp->processEvents(QEventLoop::ExcludeUserInputEvents);
1263 	for (uint dc = 0; dc < d.count(); ++dc)
1264 	{
1265 		mainWin->mainWindowProgressBar->setValue(dc);
1266 		qApp->processEvents(QEventLoop::ExcludeUserInputEvents);
1267 		QFileInfo fi(QDir::cleanPath(QDir::toNativeSeparators(fileName + "/" + d[dc])));
1268 		QString ext = fi.suffix().toLower();
1269 		if ((ext == "sce") || (!formats.contains(ext)))
1270 			loadVectors(QDir::cleanPath(QDir::toNativeSeparators(fileName + "/" + d[dc])));
1271 	}
1272 	for (uint dc = 0; dc < d.count(); ++dc)
1273 	{
1274 		mainWin->mainWindowProgressBar->setValue(d.count() + dc);
1275 		qApp->processEvents(QEventLoop::ExcludeUserInputEvents);
1276 
1277 		QFileInfo fi(QDir::cleanPath(QDir::toNativeSeparators(fileName + "/" + d[dc])));
1278 		QString ext = fi.suffix().toLower();
1279 		if ((ext == "sce") || (!formats.contains(ext)))
1280 			continue;
1281 		if (!formats.contains(ext))
1282 			continue;
1283 
1284 		QString patNam = fi.baseName().trimmed().simplified().replace(" ", "_");
1285 		if (!dialogPatterns.contains(patNam))
1286 		{
1287 			ScPattern pat = ScPattern();
1288 			pat.setDoc(m_doc);
1289 			pat.setPattern(QDir::cleanPath(QDir::toNativeSeparators(fileName + "/" + d[dc])));
1290 			dialogPatterns.insert(patNam, pat);
1291 			origNamesPatterns.insert(patNam, patNam);
1292 		}
1293 	}
1294 	d.cdUp();
1295 	dirs->set("patterndir", d.absolutePath());
1296 	qApp->restoreOverrideCursor();
1297 	mainWin->setStatusBarInfoText("");
1298 	mainWin->mainWindowProgressBar->reset();
1299 }
1300 
loadVectors(const QString & data)1301 void ColorsAndFillsDialog::loadVectors(const QString& data)
1302 {
1303 	int storedPageNum = m_doc->currentPageNumber();
1304 	int storedContentsX = m_doc->view()->contentsX();
1305 	int storedContentsY = m_doc->view()->contentsY();
1306 	double storedViewScale = m_doc->view()->scale();
1307 	FPoint stored_minCanvasCoordinate = m_doc->minCanvasCoordinate;
1308 	FPoint stored_maxCanvasCoordinate = m_doc->maxCanvasCoordinate;
1309 
1310 	m_doc->PageColors = m_colorList;
1311 	m_doc->docGradients = dialogGradients;
1312 	UndoManager::instance()->setUndoEnabled(false);
1313 	m_doc->setLoading(true);
1314 	QFileInfo fi(data);
1315 	QString patNam = fi.baseName().trimmed().simplified().replace(" ", "_");
1316 	uint ac = m_doc->Items->count();
1317 	uint ap = m_doc->docPatterns.count();
1318 	bool savedAlignGrid = m_doc->SnapGrid;
1319 	bool savedAlignGuides = m_doc->SnapGuides;
1320 	bool savedAlignElement = m_doc->SnapElement;
1321 	m_doc->SnapGrid = false;
1322 	m_doc->SnapGuides = false;
1323 	m_doc->SnapElement = false;
1324 	if (fi.suffix().toLower() == "sce")
1325 	{
1326 		ScriXmlDoc ss;
1327 		ss.readElem(data, m_doc, m_doc->currentPage()->xOffset(), m_doc->currentPage()->yOffset(), true, true);
1328 	}
1329 	else
1330 	{
1331 		FileLoader *fileLoader = new FileLoader(data);
1332 		int testResult = fileLoader->testFile();
1333 		delete fileLoader;
1334 		if ((testResult != -1) && (testResult >= FORMATID_FIRSTUSER))
1335 		{
1336 			const FileFormat * fmt = LoadSavePlugin::getFormatById(testResult);
1337 			if (fmt)
1338 			{
1339 				fmt->setupTargets(m_doc, nullptr, mainWin, nullptr, &(PrefsManager::instance().appPrefs.fontPrefs.AvailFonts));
1340 				fmt->loadFile(data, LoadSavePlugin::lfUseCurrentPage|LoadSavePlugin::lfInteractive|LoadSavePlugin::lfScripted|LoadSavePlugin::lfKeepPatterns|LoadSavePlugin::lfLoadAsPattern);
1341 			}
1342 		}
1343 	}
1344 	m_doc->SnapGrid = savedAlignGrid;
1345 	m_doc->SnapGuides = savedAlignGuides;
1346 	m_doc->SnapElement = savedAlignElement;
1347 	uint ae = m_doc->Items->count();
1348 	if (ac != ae)
1349 	{
1350 		for (uint as = ac; as < ae; ++as)
1351 		{
1352 			PageItem* ite = m_doc->Items->at(ac);
1353 			if (ite->itemType() == PageItem::PathText)
1354 				ite->updatePolyClip();
1355 			else
1356 				ite->layout();
1357 		}
1358 		ScPattern pat = ScPattern();
1359 		pat.setDoc(m_doc);
1360 		PageItem* currItem = m_doc->Items->at(ac);
1361 		double minx =  std::numeric_limits<double>::max();
1362 		double miny =  std::numeric_limits<double>::max();
1363 		double maxx = -std::numeric_limits<double>::max();
1364 		double maxy = -std::numeric_limits<double>::max();
1365 		double x1, x2, y1, y2;
1366 		currItem->getVisualBoundingRect(&x1, &y1, &x2, &y2);
1367 		minx = qMin(minx, x1);
1368 		miny = qMin(miny, y1);
1369 		maxx = qMax(maxx, x2);
1370 		maxy = qMax(maxy, y2);
1371 		pat.pattern = currItem->DrawObj_toImage(qMin(qMax(maxx - minx, maxy - miny), 500.0));
1372 		pat.width = maxx - minx;
1373 		pat.height = maxy - miny;
1374 		currItem->setXYPos(0, 0, true);
1375 		currItem->setWidthHeight(maxx - minx, maxy - miny, true);
1376 		currItem->groupWidth = maxx - minx;
1377 		currItem->groupHeight = maxy - miny;
1378 		currItem->gWidth = maxx - minx;
1379 		currItem->gHeight = maxy - miny;
1380 		for (uint as = ac; as < ae; ++as)
1381 		{
1382 			pat.items.append(m_doc->Items->takeAt(ac));
1383 		}
1384 		if (!dialogPatterns.contains(patNam))
1385 		{
1386 			dialogPatterns.insert(patNam, pat);
1387 			origNamesPatterns.insert(patNam, patNam);
1388 		}
1389 		for (QHash<QString, ScPattern>::Iterator it = m_doc->docPatterns.begin(); it != m_doc->docPatterns.end(); ++it)
1390 		{
1391 			if (!origPatterns.contains(it.key()))
1392 			{
1393 				dialogPatterns.insert(it.key(), it.value());
1394 				origNamesPatterns.insert(it.key(), it.key());
1395 			}
1396 		}
1397 	}
1398 	else
1399 	{
1400 		uint ape = m_doc->docPatterns.count();
1401 		if (ap != ape)
1402 		{
1403 			for (QHash<QString, ScPattern>::Iterator it = m_doc->docPatterns.begin(); it != m_doc->docPatterns.end(); ++it)
1404 			{
1405 				if (!origPatterns.contains(it.key()))
1406 				{
1407 					dialogPatterns.insert(it.key(), it.value());
1408 					origNamesPatterns.insert(it.key(), it.key());
1409 				}
1410 			}
1411 		}
1412 	}
1413 	m_doc->setLoading(false);
1414 	m_colorList = m_doc->PageColors;
1415 	dialogGradients = m_doc->docGradients;
1416 	UndoManager::instance()->setUndoEnabled(true);
1417 
1418 	m_doc->minCanvasCoordinate = stored_minCanvasCoordinate;
1419 	m_doc->maxCanvasCoordinate = stored_maxCanvasCoordinate;
1420 	m_doc->view()->setScale(storedViewScale);
1421 	m_doc->setCurrentPage(m_doc->DocPages.at(storedPageNum));
1422 	m_doc->view()->setContentsPos(static_cast<int>(storedContentsX * storedViewScale), static_cast<int>(storedContentsY * storedViewScale));
1423 }
1424 
isMandatoryColor(const QString & colorName)1425 bool ColorsAndFillsDialog::isMandatoryColor(const QString& colorName)
1426 {
1427 	if (colorName == "Black" || colorName == "White")
1428 		return true;
1429 	ScColor color = m_colorList.value(colorName, ScColor());
1430 	return color.isRegistrationColor();
1431 }
1432 
getColorTooltip(const ScColor & color)1433 QString ColorsAndFillsDialog::getColorTooltip(const ScColor& color)
1434 {
1435 	QString tooltip;
1436 	if (color.getColorModel() == colorModelRGB)
1437 	{
1438 		int r, g, b;
1439 		color.getRawRGBColor(&r, &g, &b);
1440 		tooltip = tr("R: %1 G: %2 B: %3").arg(r).arg(g).arg(b);
1441 	}
1442 	else if (color.getColorModel() == colorModelCMYK)
1443 	{
1444 		double c, m, y, k;
1445 		color.getCMYK(&c, &m, &y, &k);
1446 		return tr("C: %1% M: %2% Y: %3% K: %4%").arg(c * 100, 0, 'f', 2).arg(m * 100, 0, 'f', 2).arg(y * 100, 0, 'f', 2).arg(k * 100, 0, 'f', 2);
1447 	}
1448 	else if (color.getColorModel() == colorModelLab)
1449 	{
1450 		double L, a, b;
1451 		color.getLab(&L, &a, &b);
1452 		tooltip = tr("L: %1 a: %2 b: %3").arg(L, 0, 'f', 2).arg(a, 0, 'f', 2).arg(b, 0, 'f', 2);
1453 	}
1454 	return tooltip;
1455 }
1456 
getGradientColors()1457 ColorList ColorsAndFillsDialog::getGradientColors()
1458 {
1459 	ColorList colorList;
1460 	QHash<QString,VGradient>::Iterator itg;
1461 	for (itg = dialogGradients.begin(); itg != dialogGradients.end(); ++itg)
1462 	{
1463 		QList<VColorStop*> cstops = itg.value().colorStops();
1464 		for (int cst = 0; cst < itg.value().stops(); ++cst)
1465 		{
1466 			if ((!colorList.contains(cstops.at(cst)->name)) && (cstops.at(cst)->name != CommonStrings::None))
1467 				colorList.insert(cstops.at(cst)->name, m_colorList[cstops.at(cst)->name]);
1468 		}
1469 	}
1470 	QStringList patterns = dialogPatterns.keys();
1471 	for (int c = 0; c < dialogPatterns.count(); ++c)
1472 	{
1473 		ScPattern pa = dialogPatterns[patterns[c]];
1474 		for (int o = 0; o < pa.items.count(); o++)
1475 		{
1476 			PageItem *ite = pa.items.at(o);
1477 			if ((!colorList.contains(ite->lineColor())) && (ite->lineColor() != CommonStrings::None))
1478 				colorList.insert(ite->lineColor(), m_colorList[ite->lineColor()]);
1479 			if ((!colorList.contains(ite->fillColor())) && (ite->fillColor() != CommonStrings::None))
1480 				colorList.insert(ite->fillColor(), m_colorList[ite->fillColor()]);
1481 			QString gCol1, gCol2, gCol3, gCol4;
1482 			ite->get4ColorColors(gCol1, gCol2, gCol3, gCol4);
1483 			if ((!colorList.contains(gCol1)) && (gCol1 != CommonStrings::None))
1484 				colorList.insert(gCol1, m_colorList[gCol1]);
1485 			if ((!colorList.contains(gCol2)) && (gCol2 != CommonStrings::None))
1486 				colorList.insert(gCol2, m_colorList[gCol2]);
1487 			if ((!colorList.contains(gCol3)) && (gCol3 != CommonStrings::None))
1488 				colorList.insert(gCol3, m_colorList[gCol3]);
1489 			if ((!colorList.contains(gCol4)) && (gCol4 != CommonStrings::None))
1490 				colorList.insert(gCol4, m_colorList[gCol4]);
1491 			for (int grow = 0; grow < ite->meshGradientArray.count(); grow++)
1492 			{
1493 				for (int gcol = 0; gcol < ite->meshGradientArray[grow].count(); gcol++)
1494 				{
1495 					MeshPoint mp = ite->meshGradientArray[grow][gcol];
1496 					if ((!colorList.contains(mp.colorName)) && (mp.colorName != CommonStrings::None))
1497 						colorList.insert(mp.colorName, m_colorList[mp.colorName]);
1498 				}
1499 			}
1500 			QList<VColorStop*> cstops = ite->fill_gradient.colorStops();
1501 			for (int cst = 0; cst < ite->fill_gradient.stops(); ++cst)
1502 			{
1503 				if ((!colorList.contains(cstops.at(cst)->name)) && (cstops.at(cst)->name != CommonStrings::None))
1504 					colorList.insert(cstops.at(cst)->name, m_colorList[cstops.at(cst)->name]);
1505 			}
1506 			cstops = ite->stroke_gradient.colorStops();
1507 			for (int cst = 0; cst < ite->stroke_gradient.stops(); ++cst)
1508 			{
1509 				if ((!colorList.contains(cstops.at(cst)->name)) && (cstops.at(cst)->name != CommonStrings::None))
1510 					colorList.insert(cstops.at(cst)->name, m_colorList[cstops.at(cst)->name]);
1511 			}
1512 			cstops = ite->mask_gradient.colorStops();
1513 			for (int cst = 0; cst < ite->mask_gradient.stops(); ++cst)
1514 			{
1515 				if ((!colorList.contains(cstops.at(cst)->name)) && (cstops.at(cst)->name != CommonStrings::None))
1516 					colorList.insert(cstops.at(cst)->name, m_colorList[cstops.at(cst)->name]);
1517 			}
1518 		}
1519 	}
1520 	colorList.remove(CommonStrings::None);
1521 	return colorList;
1522 }
1523 
updateGradientColors(const QString & newName,const QString & oldName)1524 void ColorsAndFillsDialog::updateGradientColors(const QString& newName, const QString& oldName)
1525 {
1526 	QHash<QString,VGradient>::Iterator itg;
1527 	for (itg = dialogGradients.begin(); itg != dialogGradients.end(); ++itg)
1528 	{
1529 		QList<VColorStop*> cstops = itg.value().colorStops();
1530 		for (int cst = 0; cst < itg.value().stops(); ++cst)
1531 		{
1532 			if (oldName == cstops.at(cst)->name)
1533 			{
1534 				cstops.at(cst)->name = newName;
1535 				const ScColor& col = m_colorList[cstops.at(cst)->name];
1536 				cstops.at(cst)->color = ScColorEngine::getShadeColorProof(col, m_doc, cstops.at(cst)->shade);
1537 			}
1538 		}
1539 	}
1540 	ColorList colorListBack = m_doc->PageColors;
1541 	m_doc->PageColors = m_colorList;
1542 	QStringList patterns = dialogPatterns.keys();
1543 	for (int c = 0; c < dialogPatterns.count(); ++c)
1544 	{
1545 		ScPattern pa = dialogPatterns[patterns[c]];
1546 		for (int o = 0; o < pa.items.count(); o++)
1547 		{
1548 			PageItem *ite = pa.items.at(o);
1549 			if (oldName == ite->lineColor())
1550 				ite->setLineColor(newName);
1551 			if (oldName == ite->fillColor())
1552 				ite->setFillColor(newName);
1553 			QString gCol1, gCol2, gCol3, gCol4;
1554 			ite->get4ColorColors(gCol1, gCol2, gCol3, gCol4);
1555 			if (oldName == gCol1)
1556 				gCol1 = newName;
1557 			if (oldName == gCol2)
1558 				gCol2 = newName;
1559 			if (oldName == gCol3)
1560 				gCol3 = newName;
1561 			if (oldName == gCol4)
1562 				gCol4 = newName;
1563 			ite->set4ColorColors(gCol1, gCol2, gCol3, gCol4);
1564 			for (int grow = 0; grow < ite->meshGradientArray.count(); grow++)
1565 			{
1566 				for (int gcol = 0; gcol < ite->meshGradientArray[grow].count(); gcol++)
1567 				{
1568 					MeshPoint mp = ite->meshGradientArray[grow][gcol];
1569 					if (mp.colorName == oldName)
1570 					{
1571 						mp.colorName = newName;
1572 						ite->setMeshPointColor(grow, gcol, mp.colorName, mp.shade, mp.transparency);
1573 					}
1574 				}
1575 			}
1576 			QList<VColorStop*> cstops = ite->fill_gradient.colorStops();
1577 			for (int cst = 0; cst < ite->fill_gradient.stops(); ++cst)
1578 			{
1579 				if (oldName == cstops.at(cst)->name)
1580 				{
1581 					cstops.at(cst)->name = newName;
1582 					ite->SetQColor(&cstops.at(cst)->color, cstops.at(cst)->name, cstops.at(cst)->shade);
1583 				}
1584 			}
1585 			cstops = ite->stroke_gradient.colorStops();
1586 			for (int cst = 0; cst < ite->stroke_gradient.stops(); ++cst)
1587 			{
1588 				if (oldName == cstops.at(cst)->name)
1589 				{
1590 					cstops.at(cst)->name = newName;
1591 					ite->SetQColor(&cstops.at(cst)->color, cstops.at(cst)->name, cstops.at(cst)->shade);
1592 				}
1593 			}
1594 			cstops = ite->mask_gradient.colorStops();
1595 			for (int cst = 0; cst < ite->mask_gradient.stops(); ++cst)
1596 			{
1597 				if (oldName == cstops.at(cst)->name)
1598 				{
1599 					cstops.at(cst)->name = newName;
1600 					ite->SetQColor(&cstops.at(cst)->color, cstops.at(cst)->name, cstops.at(cst)->shade);
1601 				}
1602 			}
1603 		}
1604 		PageItem *ite = pa.items.at(0);
1605 		dialogPatterns[patterns[c]].pattern = ite->DrawObj_toImage(pa.items, 1.0);
1606 	}
1607 	m_doc->PageColors = colorListBack;
1608 }
1609 
loadGimpFormat(const QString & fileName)1610 void ColorsAndFillsDialog::loadGimpFormat(const QString& fileName)
1611 {
1612 	QFile f(fileName);
1613 	if (f.open(QIODevice::ReadOnly))
1614 	{
1615 		ScTextStream ts(&f);
1616 		QString tmp, dummy;
1617 		QString gradientName = "";
1618 		int numEntrys = 0;
1619 		int entryCount = 0;
1620 		int stopCount = 0;
1621 		double left, middle, right, r0, g0, b0, a0, r1, g1, b1, a1;
1622 		double oldr1 = 0.0;
1623 		double oldg1 = 0.0;
1624 		double oldb1 = 0.0;
1625 		double olda1 = 0.0;
1626 		tmp = ts.readLine();
1627 		if (tmp.startsWith("GIMP Gradient"))
1628 		{
1629 			tmp = ts.readLine();
1630 			ScTextStream CoE(&tmp, QIODevice::ReadOnly);
1631 			CoE >> dummy;
1632 			gradientName = CoE.readAll().trimmed();
1633 		}
1634 		if (!gradientName.isEmpty())
1635 		{
1636 			QString stopName = gradientName+QString("_Stop%1");
1637 			QString stopNameInUse;
1638 			VGradient gra = VGradient(VGradient::linear);
1639 			gra.clearStops();
1640 			QColor color;
1641 			tmp = ts.readLine();
1642 			ScTextStream CoE(&tmp, QIODevice::ReadOnly);
1643 			CoE >> numEntrys;
1644 			while (!ts.atEnd())
1645 			{
1646 				entryCount++;
1647 				tmp = ts.readLine();
1648 				ScTextStream Cval(&tmp, QIODevice::ReadOnly);
1649 				Cval >> left >> middle >> right >> r0 >> g0 >> b0 >> a0 >> r1 >> g1 >> b1 >> a1;
1650 				if ((entryCount == 1) && (entryCount < numEntrys))
1651 				{
1652 					stopNameInUse = stopName.arg(stopCount);
1653 					addGimpColor(stopNameInUse, r0, g0, b0);
1654 					color = QColor(qRound(r0 * 255), qRound(g0 * 255), qRound(b0 * 255));
1655 					gra.addStop(color, left, 0.5, a0, stopNameInUse, 100);
1656 					stopCount++;
1657 				}
1658 				else if (entryCount == numEntrys)
1659 				{
1660 					if ((entryCount != 1) && ((r0 != oldr1) || (g0 != oldg1) || (b0 != oldb1) || (a0 != olda1)))
1661 					{
1662 						stopNameInUse = stopName.arg(stopCount);
1663 						addGimpColor(stopNameInUse, oldr1, oldg1, oldb1);
1664 						color = QColor(qRound(oldr1 * 255), qRound(oldg1 * 255), qRound(oldb1 * 255));
1665 						gra.addStop(color, left, 0.5, olda1, stopNameInUse, 100);
1666 						stopCount++;
1667 					}
1668 					stopNameInUse = stopName.arg(stopCount);
1669 					addGimpColor(stopNameInUse, r0, g0, b0);
1670 					color = QColor(qRound(r0 * 255), qRound(g0 * 255), qRound(b0 * 255));
1671 					gra.addStop(color, left, 0.5, a0, stopNameInUse, 100);
1672 					stopCount++;
1673 					stopNameInUse = stopName.arg(stopCount);
1674 					addGimpColor(stopNameInUse, r1, g1, b1);
1675 					color = QColor(qRound(r1 * 255), qRound(g1 * 255), qRound(b1 * 255));
1676 					gra.addStop(color, right, 0.5, a1, stopNameInUse, 100);
1677 					stopCount++;
1678 				}
1679 				else
1680 				{
1681 					if ((r0 == oldr1) && (g0 == oldg1) && (b0 == oldb1) && (a0 == olda1))
1682 					{
1683 						stopNameInUse = stopName.arg(stopCount);
1684 						addGimpColor(stopNameInUse, r0, g0, b0);
1685 						color = QColor(qRound(r0 * 255), qRound(g0 * 255), qRound(b0 * 255));
1686 						gra.addStop(color, left, 0.5, a0, stopNameInUse, 100);
1687 						stopCount++;
1688 					}
1689 					else
1690 					{
1691 						stopNameInUse = stopName.arg(stopCount);
1692 						addGimpColor(stopNameInUse, oldr1, oldg1, oldb1);
1693 						color = QColor(qRound(oldr1 * 255), qRound(oldg1 * 255), qRound(oldb1 * 255));
1694 						gra.addStop(color, left, 0.5, olda1, stopNameInUse, 100);
1695 						stopCount++;
1696 						stopNameInUse = stopName.arg(stopCount);
1697 						addGimpColor(stopNameInUse, r0, g0, b0);
1698 						color = QColor(qRound(r0 * 255), qRound(g0 * 255), qRound(b0 * 255));
1699 						gra.addStop(color, left, 0.5, a0, stopNameInUse, 100);
1700 						stopCount++;
1701 					}
1702 				}
1703 				oldr1 = r1;
1704 				oldg1 = g1;
1705 				oldb1 = b1;
1706 				olda1 = a1;
1707 			}
1708 			if (!dialogGradients.contains(gradientName))
1709 				dialogGradients.insert(gradientName, gra);
1710 			else
1711 			{
1712 				QString tmp;
1713 				gradientName += "("+tmp.setNum(dialogGradients.count())+")";
1714 				dialogGradients.insert(gradientName, gra);
1715 			}
1716 		}
1717 		f.close();
1718 	}
1719 	/* File format is:
1720    *
1721    *   GIMP Gradient
1722    *   Name: name
1723    *   number_of_segments
1724    *   left middle right r0 g0 b0 a0 r1 g1 b1 a1 type coloring left_color_type
1725    *   left middle right r0 g0 b0 a0 r1 g1 b1 a1 type coloring right_color_type
1726    *   ...
1727    */
1728 }
1729 
addGimpColor(QString & colorName,double r,double g,double b)1730 void ColorsAndFillsDialog::addGimpColor(QString &colorName, double r, double g, double b)
1731 {
1732 	ScColor lf = ScColor();
1733 	bool found = false;
1734 	int Rc, Gc, Bc, hR, hG, hB;
1735 	Rc = qRound(r * 255);
1736 	Gc = qRound(g * 255);
1737 	Bc = qRound(b * 255);
1738 	lf.setRgbColor(Rc, Gc, Bc);
1739 	for (ColorList::Iterator it = m_colorList.begin(); it != m_colorList.end(); ++it)
1740 	{
1741 		if (it.value().getColorModel() == colorModelRGB)
1742 		{
1743 			it.value().getRGB(&hR, &hG, &hB);
1744 			if ((Rc == hR) && (Gc == hG) && (Bc == hB))
1745 			{
1746 				colorName = it.key();
1747 				found = true;
1748 				return;
1749 			}
1750 		}
1751 	}
1752 	if (!found)
1753 	{
1754 		m_colorList.insert(colorName, lf);
1755 		hasImportedColors = true;
1756 	}
1757 }
1758 
loadScribusFormat(const QString & fileName)1759 void ColorsAndFillsDialog::loadScribusFormat(const QString& fileName)
1760 {
1761 	QFile f(fileName);
1762 	if (!f.open(QIODevice::ReadOnly))
1763 		return;
1764 	QDomDocument docu("scridoc");
1765 	QTextStream ts(&f);
1766 	ts.setCodec("UTF-8");
1767 	QString errorMsg;
1768 	int errorLine = 0, errorColumn = 0;
1769 	if (!docu.setContent(ts.readAll(), &errorMsg, &errorLine, &errorColumn) )
1770 	{
1771 		f.close();
1772 		return;
1773 	}
1774 	f.close();
1775 	QDomElement elem = docu.documentElement();
1776 	if (elem.tagName() != "SCRIBUSGRADIENT")
1777 		return;
1778 	QDomNode DOC = elem.firstChild();
1779 	while (!DOC.isNull())
1780 	{
1781 		QDomElement dc = DOC.toElement();
1782 		if (dc.tagName()=="COLOR")
1783 		{
1784 			ScColor lf = ScColor();
1785 			if (dc.hasAttribute("SPACE"))
1786 			{
1787 				QString space = dc.attribute("SPACE");
1788 				if (space == "CMYK")
1789 				{
1790 					double c = dc.attribute("C", "0").toDouble() / 100.0;
1791 					double m = dc.attribute("M", "0").toDouble() / 100.0;
1792 					double y = dc.attribute("Y", "0").toDouble() / 100.0;
1793 					double k = dc.attribute("K", "0").toDouble() / 100.0;
1794 					lf.setCmykColorF(c, m, y, k);
1795 				}
1796 				else if (space == "RGB")
1797 				{
1798 					double r = dc.attribute("R", "0").toDouble() / 255.0;
1799 					double g = dc.attribute("G", "0").toDouble() / 255.0;
1800 					double b = dc.attribute("B", "0").toDouble() / 255.0;
1801 					lf.setRgbColorF(r, g, b);
1802 				}
1803 				else if (space == "Lab")
1804 				{
1805 					double L = dc.attribute("L", "0").toDouble();
1806 					double a = dc.attribute("A", "0").toDouble();
1807 					double b = dc.attribute("B", "0").toDouble();
1808 					lf.setLabColor(L, a, b);
1809 				}
1810 			}
1811 			else if (dc.hasAttribute("CMYK"))
1812 				lf.setNamedColor(dc.attribute("CMYK"));
1813 			else if (dc.hasAttribute("RGB"))
1814 				lf.fromQColor(QColor(dc.attribute("RGB")));
1815 			else
1816 			{
1817 				double L = dc.attribute("L", "0").toDouble();
1818 				double a = dc.attribute("A", "0").toDouble();
1819 				double b = dc.attribute("B", "0").toDouble();
1820 				lf.setLabColor(L, a, b);
1821 			}
1822 			if (dc.hasAttribute("Spot"))
1823 				lf.setSpotColor(static_cast<bool>(dc.attribute("Spot").toInt()));
1824 			else
1825 				lf.setSpotColor(false);
1826 			if (dc.hasAttribute("Register"))
1827 				lf.setRegistrationColor(static_cast<bool>(dc.attribute("Register").toInt()));
1828 			else
1829 				lf.setRegistrationColor(false);
1830 			if (!m_colorList.contains(dc.attribute("NAME")))
1831 			{
1832 				m_colorList.insert(dc.attribute("NAME"), lf);
1833 				hasImportedColors = true;
1834 			}
1835 		}
1836 		if (dc.tagName() == "Gradient")
1837 		{
1838 			VGradient gra = VGradient(VGradient::linear);
1839 			gra.clearStops();
1840 			QDomNode grad = dc.firstChild();
1841 			while (!grad.isNull())
1842 			{
1843 				QDomElement stop = grad.toElement();
1844 				QString name = stop.attribute("NAME");
1845 				double ramp  = ScCLocale::toDoubleC(stop.attribute("RAMP"), 0.0);
1846 				int shade    = stop.attribute("SHADE", "100").toInt();
1847 				double opa   = ScCLocale::toDoubleC(stop.attribute("TRANS"), 1.0);
1848 				QColor color;
1849 				if (name == CommonStrings::None)
1850 					color = QColor(255, 255, 255, 0);
1851 				else
1852 				{
1853 					const ScColor& col = m_colorList[name];
1854 					color = ScColorEngine::getShadeColorProof(col, nullptr, shade);
1855 				}
1856 				gra.addStop(color, ramp, 0.5, opa, name, shade);
1857 				grad = grad.nextSibling();
1858 			}
1859 			if (!dialogGradients.contains(dc.attribute("Name")))
1860 				dialogGradients.insert(dc.attribute("Name"), gra);
1861 			else
1862 			{
1863 				QString tmp;
1864 				QString name = dc.attribute("Name");
1865 				name += "("+tmp.setNum(dialogGradients.count())+")";
1866 				dialogGradients.insert(name, gra);
1867 			}
1868 		}
1869 		DOC=DOC.nextSibling();
1870 	}
1871 }
1872 
loadDefaults(QTreeWidgetItem * item)1873 void ColorsAndFillsDialog::loadDefaults(QTreeWidgetItem* item)
1874 {
1875 	QString txt = item->data(0, Qt::UserRole).toString() + "/" + item->text(0);
1876 	if (!mainWin->HaveDoc)
1877 	{
1878 		m_colorList.clear();
1879 		dialogGradients.clear();
1880 		dialogPatterns.clear();
1881 	}
1882 	QString pfadC2 = "";
1883 	if (item->text(0) == "Scribus Small")
1884 	{
1885 		m_colorList.insert("White", ScColor(0, 0, 0, 0));
1886 		m_colorList.insert("Black", ScColor(0, 0, 0, 255));
1887 		ScColor cc = ScColor(255, 255, 255, 255);
1888 		cc.setRegistrationColor(true);
1889 		m_colorList.insert("Registration", cc);
1890 		m_colorList.insert("Blue", ScColor(255, 255, 0, 0));
1891 		m_colorList.insert("Cyan", ScColor(255, 0, 0, 0));
1892 		m_colorList.insert("Green", ScColor(255, 0, 255, 0));
1893 		m_colorList.insert("Red", ScColor(0, 255, 255, 0));
1894 		m_colorList.insert("Yellow", ScColor(0, 0, 255, 0));
1895 		m_colorList.insert("Magenta", ScColor(0, 255, 0, 0));
1896 		paletteLocked = false;
1897 	}
1898 	else
1899 	{
1900 		if (!customColSet.contains(txt))
1901 			pfadC2 = csm.paletteFileFromName(txt);
1902 		else
1903 			pfadC2 = csm.userPaletteFileFromName(txt);
1904 		if (!mainWin->HaveDoc)
1905 		{
1906 			QFileInfo fi(pfadC2);
1907 			if (fi.absolutePath().contains(ScPaths::applicationDataDir()+"swatches/locked"))
1908 				paletteLocked = true;
1909 			else
1910 				paletteLocked = !fi.isWritable();
1911 		}
1912 		else
1913 			paletteLocked = false;
1914 		if (!csm.loadPalette(pfadC2, m_doc, m_colorList, dialogGradients, dialogPatterns, mainWin->HaveDoc))
1915 		{
1916 			m_colorList.insert("White", ScColor(0, 0, 0, 0));
1917 			m_colorList.insert("Black", ScColor(0, 0, 0, 255));
1918 			ScColor cc = ScColor(255, 255, 255, 255);
1919 			cc.setRegistrationColor(true);
1920 			m_colorList.insert("Registration", cc);
1921 			m_colorList.insert("Blue", ScColor(255, 255, 0, 0));
1922 			m_colorList.insert("Cyan", ScColor(255, 0, 0, 0));
1923 			m_colorList.insert("Green", ScColor(255, 0, 255, 0));
1924 			m_colorList.insert("Red", ScColor(0, 255, 255, 0));
1925 			m_colorList.insert("Yellow", ScColor(0, 0, 255, 0));
1926 			m_colorList.insert("Magenta", ScColor(0, 255, 0, 0));
1927 		}
1928 	}
1929 	updateColorList();
1930 	updateGradientList();
1931 	updatePatternList();
1932 	itemSelected(nullptr);
1933 }
1934 
saveDefaults()1935 void ColorsAndFillsDialog::saveDefaults()
1936 {
1937 	QTreeWidgetItem* item = LoadColSet->currentItem();
1938 	QString NameK = item->data(0, Qt::UserRole).toString() + "/" + item->text(0);
1939 	QString Name = LoadColSet->text();
1940 	Query* dia = new Query(this, "Name", 1, tr("&Name:"), tr("Choose a Name"));
1941 	if ((customColSet.contains(NameK)) && (!paletteLocked))
1942 		dia->setEditText(Name, false);
1943 	else
1944 		dia->setEditText("", false);
1945 	if (dia->exec())
1946 		doSaveDefaults(dia->getEditText(), (dia->getEditText() != Name));
1947 	delete dia;
1948 }
1949 
doSaveDefaults(const QString & name,bool changed)1950 void ColorsAndFillsDialog::doSaveDefaults(const QString& name, bool changed)
1951 {
1952 	QString filename = name;
1953 	filename.replace(" ", "_");
1954 	filename  = QDir::toNativeSeparators(ScPaths::userPaletteFilesDir(true)) + filename;
1955 	filename += ".xml";
1956 	const FileFormat *fmt = LoadSavePlugin::getFormatById(FORMATID_SLA150EXPORT);
1957 	if (fmt)
1958 	{
1959 		ScribusDoc *s_doc = new ScribusDoc();
1960 		s_doc->setup(0, 1, 1, 1, 1, "Custom", "Custom");
1961 		s_doc->setPage(100, 100, 0, 0, 0, 0, 0, 0, false, false);
1962 		s_doc->addPage(0);
1963 		s_doc->setGUI(false, mainWin, nullptr);
1964 		s_doc->PageColors = m_colorList;
1965 		s_doc->setGradients(dialogGradients);
1966 		s_doc->setPatterns(dialogPatterns);
1967 		fmt->setupTargets(s_doc, nullptr, mainWin, nullptr, &(PrefsManager::instance().appPrefs.fontPrefs.AvailFonts));
1968 		fmt->savePalette(filename);
1969 		delete s_doc;
1970 	}
1971 	if (changed)
1972 	{
1973 		QString nameC = name;
1974 		nameC.replace(" ", "_");
1975 		nameC += ".xml";
1976 		QFileInfo fi(filename);
1977 		customColSet.append(fi.absolutePath() + "/" + nameC);
1978 		QTreeWidgetItem *item = LoadColSet->addSubItem(name, userSwatches);
1979 		item->setData(0, Qt::UserRole, fi.absolutePath());
1980 		disconnect(LoadColSet, SIGNAL(activated(QTreeWidgetItem*)), this, SLOT(loadDefaults(QTreeWidgetItem*)));
1981 		LoadColSet->setCurrentComboItem(fi.absolutePath() + "/" + name);
1982 		connect(LoadColSet, SIGNAL(activated(QTreeWidgetItem*)), this, SLOT(loadDefaults(QTreeWidgetItem*)));
1983 	}
1984 }
1985 
getColorSetName()1986 QString ColorsAndFillsDialog::getColorSetName()
1987 {
1988 	QString NameK;
1989 	QTreeWidgetItem* item = LoadColSet->currentItem();
1990 	if (item->text(0) == "Scribus Small")
1991 		NameK = "Scribus Small";
1992 	else
1993 		NameK = item->data(0, Qt::UserRole).toString() + "/" + item->text(0);
1994 	return NameK;
1995 }
1996 
selectedColor()1997 ScColor ColorsAndFillsDialog::selectedColor()
1998 {
1999 	QTreeWidgetItem* it = dataTree->currentItem();
2000 	if (it)
2001 	{
2002 		if (it->parent() == colorItems)
2003 			return m_colorList[it->text(0)];
2004 	}
2005 	return ScColor();
2006 }
2007 
selectedColorName()2008 QString ColorsAndFillsDialog::selectedColorName()
2009 {
2010 	QTreeWidgetItem* it = dataTree->currentItem();
2011 	if (it)
2012 	{
2013 		if (it->parent() == colorItems)
2014 			return it->text(0);
2015 	}
2016 	return CommonStrings::None;
2017 }
2018 
keyPressEvent(QKeyEvent * k)2019 void ColorsAndFillsDialog::keyPressEvent(QKeyEvent* k)
2020 {
2021 	if (k->modifiers()!=Qt::NoModifier || (k->key()!=Qt::Key_Delete && k->key()!=Qt::Key_Backspace))
2022 		return;
2023 
2024 	QString belowText;
2025 	QList<QTreeWidgetItem *> selItems = dataTree->selectedItems();
2026 	if (selItems.count() > 0)
2027 	{
2028 		QTreeWidgetItem* belowItem = dataTree->itemBelow(selItems.last());
2029 		if (belowItem)
2030 			belowText = belowItem->text(0);
2031 	}
2032 
2033 	removeColorItem();
2034 
2035 	QList<QTreeWidgetItem *> belowItems = dataTree->findItems(belowText, Qt::MatchFixedString|Qt::MatchCaseSensitive|Qt::MatchRecursive);
2036 	if (belowItems.count() > 0)
2037 	{
2038 		// In case non deletable colors have been selected, some items
2039 		//may still be selected, so clear selection first
2040 		dataTree->selectionModel()->clearSelection();
2041 		dataTree->setCurrentItem(belowItems[0]);
2042 	}
2043 }
2044