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) 2008 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 "transformdialog.h"
28 
29 #include "commonstrings.h"
30 #include "selection.h"
31 #include "units.h"
32 #include "iconmanager.h"
33 
34 #if defined(_MSC_VER) && !defined(_USE_MATH_DEFINES)
35 #define _USE_MATH_DEFINES
36 #endif
37 #include <cmath>
38 
TransformItem(const QString & text,QListWidget * parent,int type,double val1,double val2)39 TransformItem::TransformItem(const QString& text, QListWidget* parent, int type, double val1, double val2) : QListWidgetItem(text, parent, type)
40 {
41 	firstValue = val1;
42 	secondValue = val2;
43 }
44 
TransformDialog(QWidget * parent,ScribusDoc * doc)45 TransformDialog::TransformDialog(QWidget* parent, ScribusDoc *doc) : QDialog(parent)
46 {
47 	setupUi(this);
48 	setModal(true);
49 	setWindowIcon(IconManager::instance().loadIcon("AppIcon.png"));
50 	transformStack->setCurrentIndex(0);
51 	newTransformMenu = new QMenu(buttonAdd);
52 	newTransformMenu->addAction( tr("Scaling"), this, SLOT(newScaling()));
53 	newTransformMenu->addAction( tr("Translation"), this, SLOT(newTranslation()));
54 	newTransformMenu->addAction( tr("Rotation"), this, SLOT(newRotation()));
55 	newTransformMenu->addAction( tr("Skewing"), this, SLOT(newSkewing()));
56 	buttonAdd->setMenu(newTransformMenu);
57 	scaleLink->setChecked(true);
58 	buttonUp->setText( "" );
59 	buttonUp->setIcon(IconManager::instance().loadIcon("16/go-up.png"));
60 	buttonDown->setText( "" );
61 	buttonDown->setIcon(IconManager::instance().loadIcon("16/go-down.png"));
62 	buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
63 	m_doc = doc;
64 	m_unitRatio = unitGetRatioFromIndex(m_doc->unitIndex());
65 	m_suffix = unitGetSuffixFromIndex(m_doc->unitIndex());
66 	translateHorizontal->setNewUnit(m_doc->unitIndex());
67 	translateVertical->setNewUnit(m_doc->unitIndex());
68 	rotationValue->setWrapping( true );
69 	rotationValue->setValues( -180.0, 180.0, 1, 0);
70 	rotationValue->setSuffix(unitGetSuffixFromIndex(6));
71 	horizontalSkew->setSuffix(unitGetSuffixFromIndex(6));
72 	verticalSkew->setSuffix(unitGetSuffixFromIndex(6));
73 	linkSkew->setChecked(true);
74 	numberOfCopies->setValue(0);
75 	basePoint->setCheckedId(m_doc->rotationMode());
76 	connect(transformSelector, SIGNAL(itemClicked(QListWidgetItem*)), this, SLOT(setCurrentTransform(QListWidgetItem*)));
77 	connect(horizontalScale, SIGNAL(valueChanged(double)), this, SLOT(changeHScale(double)));
78 	connect(verticalScale, SIGNAL(valueChanged(double)), this, SLOT(changeVScale(double)));
79 	connect(scaleLink, SIGNAL(clicked()), this, SLOT(toggleLink()));
80 	connect(translateHorizontal, SIGNAL(valueChanged(double)), this, SLOT(changeHTranslation(double)));
81 	connect(translateVertical, SIGNAL(valueChanged(double)), this, SLOT(changeVTranslation(double)));
82 	connect(rotationValue, SIGNAL(valueChanged(double)), this, SLOT(changeRotation(double)));
83 	connect(horizontalSkew, SIGNAL(valueChanged(double)), this, SLOT(changeHSkew(double)));
84 	connect(verticalSkew, SIGNAL(valueChanged(double)), this, SLOT(changeVSkew(double)));
85 	connect(linkSkew, SIGNAL(clicked()), this, SLOT(toggleLinkSkew()));
86 	connect(buttonUp, SIGNAL(clicked()), this, SLOT(moveTransformUp()));
87 	connect(buttonDown, SIGNAL(clicked()), this, SLOT(moveTransformDown()));
88 	connect(buttonRemove, SIGNAL(clicked()), this, SLOT(removeTransform()));
89 }
90 
newScaling()91 void TransformDialog::newScaling()
92 {
93 	TransformItem *item = new TransformItem( tr("Scale"), transformSelector, 1001, 100.0, 100.0);
94 	transformSelector->setCurrentItem(item);
95 	setCurrentTransform(item);
96 	item->setText( tr("Scale H = %1 % V = %2 %").arg(100.0).arg(100.0));
97 	buttonRemove->setEnabled(true);
98 }
99 
newTranslation()100 void TransformDialog::newTranslation()
101 {
102 	TransformItem *item = new TransformItem( tr("Translate"), transformSelector, 1002, 0.0, 0.0);
103 	transformSelector->setCurrentItem(item);
104 	setCurrentTransform(item);
105 	item->setText( tr("Translate H = %1%2 V = %3%4").arg(0.0).arg(m_suffix).arg(0.0).arg(m_suffix));
106 	buttonRemove->setEnabled(true);
107 }
108 
newRotation()109 void TransformDialog::newRotation()
110 {
111 	TransformItem *item = new TransformItem( tr("Rotate"), transformSelector, 1003, 0.0, 0.0);
112 	transformSelector->setCurrentItem(item);
113 	setCurrentTransform(item);
114 	item->setText( tr("Rotate Angle = %1%2").arg(0.0).arg(unitGetSuffixFromIndex(6)));
115 	buttonRemove->setEnabled(true);
116 }
117 
newSkewing()118 void TransformDialog::newSkewing()
119 {
120 	TransformItem *item = new TransformItem( tr("Skew"), transformSelector, 1004, 0.0, 0.0);
121 	transformSelector->setCurrentItem(item);
122 	setCurrentTransform(item);
123 	item->setText( tr("Skew H = %1%2 V = %3%4").arg(0.0).arg(unitGetSuffixFromIndex(6)).arg(0.0).arg(unitGetSuffixFromIndex(6)));
124 	buttonRemove->setEnabled(true);
125 }
126 
setCurrentTransform(QListWidgetItem * item)127 void TransformDialog::setCurrentTransform(QListWidgetItem* item)
128 {
129 	if (item == nullptr)
130 	{
131 		transformStack->setCurrentIndex(0);
132 		buttonRemove->setEnabled(false);
133 		buttonUp->setEnabled(false);
134 		buttonDown->setEnabled(false);
135 		return;
136 	}
137 
138 	TransformItem *ite = (TransformItem*) item;
139 	switch (item->type())
140 	{
141 		case 1001:
142 			transformStack->setCurrentIndex(1);
143 			horizontalScale->setValue(ite->firstValue);
144 			verticalScale->setValue(ite->secondValue);
145 			break;
146 		case 1002:
147 			transformStack->setCurrentIndex(2);
148 			translateHorizontal->setValue(ite->firstValue);
149 			translateVertical->setValue(ite->secondValue);
150 			break;
151 		case 1003:
152 			transformStack->setCurrentIndex(3);
153 			rotationValue->setValue(ite->firstValue);
154 			break;
155 		case 1004:
156 			transformStack->setCurrentIndex(4);
157 			horizontalSkew->setValue(ite->firstValue);
158 			verticalSkew->setValue(ite->secondValue);
159 			break;
160 		default:
161 			transformStack->setCurrentIndex(0);
162 			break;
163 	}
164 	if (transformSelector->count() > 1)
165 	{
166 		buttonUp->setEnabled(true);
167 		buttonDown->setEnabled(true);
168 		if (transformSelector->currentRow() == 0)
169 			buttonUp->setEnabled(false);
170 		if (transformSelector->currentRow() == transformSelector->count()-1)
171 			buttonDown->setEnabled(false);
172 	}
173 	else
174 	{
175 		buttonUp->setEnabled(false);
176 		buttonDown->setEnabled(false);
177 	}
178 	buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true);
179 }
180 
changeHScale(double val)181 void TransformDialog::changeHScale(double val)
182 {
183 	QListWidgetItem* item = transformSelector->currentItem();
184 	TransformItem *ite = (TransformItem*)item;
185 	ite->firstValue = val;
186 	if (scaleLink->isChecked())
187 	{
188 		verticalScale->setValue(horizontalScale->value());
189 		ite->secondValue = val;
190 	}
191 	item->setText( tr("Scale H = %1 % V = %2 %").arg(ite->firstValue).arg(ite->secondValue));
192 }
193 
changeVScale(double val)194 void TransformDialog::changeVScale(double val)
195 {
196 	QListWidgetItem* item = transformSelector->currentItem();
197 	TransformItem *ite = (TransformItem*)item;
198 	ite->secondValue = val;
199 	if (scaleLink->isChecked())
200 	{
201 		horizontalScale->setValue(verticalScale->value());
202 		ite->firstValue = val;
203 	}
204 	item->setText( tr("Scale H = %1 % V = %2 %").arg(ite->firstValue).arg(ite->secondValue));
205 }
206 
toggleLink()207 void TransformDialog::toggleLink()
208 {
209 	if (scaleLink->isChecked())
210 		verticalScale->setValue(horizontalScale->value());
211 	QListWidgetItem* item = transformSelector->currentItem();
212 	TransformItem *ite = (TransformItem*)item;
213 	item->setText( tr("Scale H = %1 % V = %2 %").arg(ite->firstValue).arg(ite->secondValue));
214 }
215 
changeHTranslation(double val)216 void TransformDialog::changeHTranslation(double val)
217 {
218 	QListWidgetItem* item = transformSelector->currentItem();
219 	TransformItem *ite = (TransformItem*)item;
220 	ite->firstValue = val;
221 	item->setText( tr("Translate H = %1%2 V = %3%4").arg(ite->firstValue).arg(m_suffix).arg(ite->secondValue).arg(m_suffix));
222 }
223 
changeVTranslation(double val)224 void TransformDialog::changeVTranslation(double val)
225 {
226 	QListWidgetItem* item = transformSelector->currentItem();
227 	TransformItem *ite = (TransformItem*)item;
228 	ite->secondValue = val;
229 	item->setText( tr("Translate H = %1%2 V = %3%4").arg(ite->firstValue).arg(m_suffix).arg(ite->secondValue).arg(m_suffix));
230 }
231 
changeRotation(double val)232 void TransformDialog::changeRotation(double val)
233 {
234 	QListWidgetItem* item = transformSelector->currentItem();
235 	TransformItem *ite = (TransformItem*)item;
236 	ite->firstValue = -val;
237 	item->setText( tr("Rotate Angle = %1%2").arg(-ite->firstValue).arg(unitGetSuffixFromIndex(6)));
238 }
239 
changeHSkew(double val)240 void TransformDialog::changeHSkew(double val)
241 {
242 	QListWidgetItem* item = transformSelector->currentItem();
243 	TransformItem *ite = (TransformItem*)item;
244 	ite->firstValue = val;
245 	if (linkSkew->isChecked())
246 	{
247 		verticalSkew->setValue(horizontalSkew->value());
248 		ite->secondValue = val;
249 	}
250 	item->setText( tr("Skew H = %1%2 V = %3%4").arg(ite->firstValue).arg(unitGetSuffixFromIndex(6)).arg(ite->secondValue).arg(unitGetSuffixFromIndex(6)));
251 }
252 
changeVSkew(double val)253 void TransformDialog::changeVSkew(double val)
254 {
255 	QListWidgetItem* item = transformSelector->currentItem();
256 	TransformItem *ite = (TransformItem*)item;
257 	ite->secondValue = val;
258 	if (linkSkew->isChecked())
259 	{
260 		horizontalSkew->setValue(verticalSkew->value());
261 		ite->firstValue = val;
262 	}
263 	item->setText( tr("Skew H = %1%2 V = %3%4").arg(ite->firstValue).arg(unitGetSuffixFromIndex(6)).arg(ite->secondValue).arg(unitGetSuffixFromIndex(6)));
264 }
265 
toggleLinkSkew()266 void TransformDialog::toggleLinkSkew()
267 {
268 	if (linkSkew->isChecked())
269 		verticalSkew->setValue(horizontalSkew->value());
270 	QListWidgetItem* item = transformSelector->currentItem();
271 	TransformItem *ite = (TransformItem*)item;
272 	item->setText( tr("Skew H = %1%2 V = %3%4").arg(ite->firstValue).arg(unitGetSuffixFromIndex(6)).arg(ite->secondValue).arg(unitGetSuffixFromIndex(6)));
273 }
274 
moveTransformUp()275 void TransformDialog::moveTransformUp()
276 {
277 	int curr = transformSelector->currentRow();
278 	if (curr == 0)
279 		return;
280 	QListWidgetItem *it = transformSelector->takeItem(curr);
281 	transformSelector->insertItem(curr-1, it);
282 	transformSelector->setCurrentItem(it);
283 	setCurrentTransform(it);
284 }
285 
moveTransformDown()286 void TransformDialog::moveTransformDown()
287 {
288 	int curr = transformSelector->currentRow();
289 	if (curr == transformSelector->count()-1)
290 		return;
291 	QListWidgetItem *it = transformSelector->takeItem(curr);
292 	transformSelector->insertItem(curr+1, it);
293 	transformSelector->setCurrentItem(it);
294 	setCurrentTransform(it);
295 }
296 
removeTransform()297 void TransformDialog::removeTransform()
298 {
299 	int curr = transformSelector->currentRow();
300 	QListWidgetItem *it = transformSelector->takeItem(curr);
301 	delete it;
302 	transformSelector->clearSelection();
303 	if (transformSelector->count() == 0)
304 	{
305 		transformStack->setCurrentIndex(0);
306 		buttonRemove->setEnabled(false);
307 		buttonUp->setEnabled(false);
308 		buttonDown->setEnabled(false);
309 		buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
310 	}
311 	else
312 	{
313 		transformSelector->setCurrentItem(transformSelector->item(qMax(curr-1, 0)));
314 		transformSelector->currentItem()->setSelected(true);
315 		setCurrentTransform(transformSelector->currentItem());
316 		buttonRemove->setEnabled(true);
317 	}
318 }
319 
getTransformMatrix()320 QTransform TransformDialog::getTransformMatrix()
321 {
322 	QTransform ret = QTransform();
323 	for (int a = 0; a < transformSelector->count(); a++)
324 	{
325 		QListWidgetItem *it = transformSelector->item(a);
326 		TransformItem *ite = (TransformItem*)it;
327 		switch (it->type())
328 		{
329 			case 1001:
330 				ret.scale(ite->firstValue / 100.0, ite->secondValue / 100.0);
331 				break;
332 			case 1002:
333 				ret.translate(ite->firstValue / m_unitRatio, ite->secondValue / m_unitRatio);
334 				break;
335 			case 1003:
336 				ret.rotate(ite->firstValue);
337 				break;
338 			case 1004:
339 				ret.shear(-sin(ite->firstValue / 180.0 * M_PI), -sin(ite->secondValue / 180.0 * M_PI));
340 				break;
341 			default:
342 				break;
343 		}
344 	}
345 	return ret;
346 }
347 
getCount()348 int TransformDialog::getCount()
349 {
350 	return numberOfCopies->value();
351 }
352 
getBasepoint()353 int TransformDialog::getBasepoint()
354 {
355 	return basePoint->checkedId();
356 }
357