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 #include <QApplication>
9 #include <QBitmap>
10 #include <QCursor>
11 #include <QDrag>
12 #include <QEvent>
13 #include <QHeaderView>
14 #include <QLabel>
15 #include <QList>
16 #include <QMenu>
17 #include <QMimeData>
18 #include <QMessageBox>
19 #include <QPainter>
20 
21 #include "commonstrings.h"
22 #include "iconmanager.h"
23 #include "pagelayout.h"
24 #include "pagepalette_widgets.h"
25 #include "scpage.h"
26 #include "scribusapp.h"
27 #include "ui/scmessagebox.h"
28 
29 
30 /* IconItems Code */
SeItem(const QString & text,uint nr,const QPixmap & Pix)31 SeItem::SeItem(const QString& text, uint nr, const QPixmap& Pix)
32 	: QTableWidgetItem(QIcon(Pix), "", 1002),
33 	  pageNumber(nr),
34 	  pageName(text)
35 {
36 	setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
37 }
38 
getPageName()39 const QString& SeItem::getPageName()
40 {
41 	return pageName;
42 }
43 
44 /* ListBox Subclass */
SeList(QWidget * parent)45 SeList::SeList(QWidget* parent) : QListWidget(parent)
46 {
47 	setAcceptDrops(true);
48 }
49 
mouseReleaseEvent(QMouseEvent * m)50 void SeList::mouseReleaseEvent(QMouseEvent *m)
51 {
52 	m_mousePressed = false;
53 	if (m->button() == Qt::RightButton)
54 	{
55 		QMenu *pmen = new QMenu();
56 //		qApp->changeOverrideCursor(QCursor(Qt::ArrowCursor));
57 		QAction *px = pmen->addAction( tr("Show Page Previews"), this, SLOT(toggleThumbnail()));
58 		px->setCheckable(true);
59 		if (m_thumb)
60 			px->setChecked(true);
61 		pmen->exec(QCursor::pos());
62 		delete pmen;
63 	}
64 	QListWidget::mouseReleaseEvent(m);
65 }
66 
toggleThumbnail()67 void SeList::toggleThumbnail()
68 {
69 	m_thumb = !m_thumb;
70 	emit thumbnailChanged();
71 }
72 
mousePressEvent(QMouseEvent * e)73 void SeList::mousePressEvent(QMouseEvent* e)
74 {
75 	e->accept();
76 	m_currItem = nullptr;
77 	QListWidgetItem *i = itemAt(e->pos());
78 	if (i)
79 	{
80 		m_currItem = i;
81 		m_mousePos = e->pos();
82 		m_mousePressed = true;
83 	}
84 	QListWidget::mousePressEvent(e);
85 }
86 
mouseMoveEvent(QMouseEvent * e)87 void SeList::mouseMoveEvent(QMouseEvent* e)
88 {
89 	if ((m_mousePressed) && ((m_mousePos - e->pos()).manhattanLength() > 4))
90 	{
91 		m_mousePressed = false;
92 		QListWidgetItem *item = itemAt(m_mousePos);
93 		if (!item)
94 			return;
95 		QMimeData *mimeData = new QMimeData;
96 		QString pageName = item->data(Qt::UserRole).toString();
97 		mimeData->setData("page/magic", "1" + pageName.toLocal8Bit());
98 		mimeData->setText("1" + pageName);
99 		QDrag *dr = new QDrag(this);
100 		dr->setMimeData(mimeData);
101 		const QPixmap& pm = IconManager::instance().loadPixmap("doc.png");
102 		dr->setPixmap(pm);
103 	//	dr->setDragCursor(pm, Qt::CopyAction);
104 	//	dr->setDragCursor(pm, Qt::MoveAction);
105 		dr->exec(Qt::CopyAction | Qt::MoveAction);
106 		QApplication::setOverrideCursor(Qt::ArrowCursor);
107 	}
108 }
109 
keyPressEvent(QKeyEvent * e)110 void SeList::keyPressEvent(QKeyEvent * e)
111 {
112 	int k = e->key();
113 	if (k == Qt::Key_Delete)
114 	{
115 		if (currentItem())
116 		{
117 			e->accept();
118 			emit delMasterRequest(currentItem()->text());
119 			return;
120 		}
121 	}
122 
123 	QListWidget::keyPressEvent(e);
124 }
125 
126 
127 /* QTable Subclass */
SeView(QWidget * parent)128 SeView::SeView(QWidget* parent) : QTableWidget(parent)
129 {
130 	setDragEnabled(true);
131 	setAcceptDrops(true);
132 	setDropIndicatorShown(true);
133 	setShowGrid(false);
134 	setWordWrap(true);
135 }
136 
mousePressEvent(QMouseEvent * e)137 void SeView::mousePressEvent(QMouseEvent* e)
138 {
139 	e->accept();
140 	m_mousePos = e->pos();
141 	m_mousePressed = true;
142 	QTableWidget::mousePressEvent(e);
143 }
144 
mouseReleaseEvent(QMouseEvent * e)145 void SeView::mouseReleaseEvent(QMouseEvent* e)
146 {
147 	e->accept();
148 	m_mousePressed = false;
149 
150 	emit Click(rowAt(e->pos().y()), columnAt(e->pos().x()), e->button());
151 	QTableWidget::mouseReleaseEvent(e);
152 }
153 
mouseMoveEvent(QMouseEvent * e)154 void SeView::mouseMoveEvent(QMouseEvent* e)
155 {
156 	if ((m_mousePressed) && ((m_mousePos - e->pos()).manhattanLength() > 4))
157 	{
158 		m_mousePressed = false;
159 		int a = rowAt(e->pos().y());
160 		int b = columnAt(e->pos().x());
161 		if ((a != -1) && (b != -1))
162 		{
163 			QTableWidgetItem* ite = item(a, b);
164 			if (ite != nullptr)
165 			{
166 				if (ite->type() == 1002)
167 				{
168 					SeItem* it = (SeItem*)ite;
169 					QString str(it->pageName);
170 					bool dummy;
171 					int p = getPage(a, b, &dummy);
172 					QString tmp;
173 					QMimeData *mimeData = new QMimeData;
174 					mimeData->setData("page/magic", "2 " + tmp.setNum(p).toLocal8Bit() + " " + str.toLocal8Bit());
175 					mimeData->setText("2 " + tmp.setNum(p) + " " + str);
176 					QDrag *dr = new QDrag(this);
177 					dr->setMimeData(mimeData);
178 					const QPixmap& pm = IconManager::instance().loadPixmap("doc.png");
179 					dr->setPixmap(pm);
180 				//	dr->setDragCursor(pm, Qt::CopyAction);
181 				//	dr->setDragCursor(pm, Qt::MoveAction);
182 					dr->exec(Qt::CopyAction | Qt::MoveAction);
183 					QApplication::setOverrideCursor(Qt::ArrowCursor);
184 				}
185 			}
186 		}
187 	}
188 	QTableWidget::mouseMoveEvent(e);
189 }
190 
dropEvent(QDropEvent * e)191 void SeView::dropEvent(QDropEvent * e)
192 {
193 	QString str, tmp;
194 	bool lastPage = false;
195 	if (e->mimeData()->hasFormat("page/magic"))
196 	{
197 		e->setDropAction(Qt::MoveAction);
198 		e->accept();
199 		// HACK to prevent strange Qt4 cursor behaviour after dropping. It's examined by Trolltech now - PV.
200 		// It's the one and only reason why to include QApplication here.
201 		// But sadly this destroys our normal Cursors
202 		// Fixed at least in Qt-4.4.2
203 //		QApplication::restoreOverrideCursor();
204 		str = e->mimeData()->text();
205 		clearPix();
206 		if (str.startsWith("1"))
207 		{
208 			int a = rowAt(e->pos().y());
209 			int b = columnAt(e->pos().x());
210 			int p;
211 			tmp = str.remove(0,1);
212 			if ((a == -1) || (b == -1))
213 				return;
214 			if (a == rowCount() - 1)
215 			{
216 				emit NewPage(m_pageCount, tmp);
217 				return;
218 			}
219 			p = getPage(a, b, &lastPage);
220 			if (columnCount() == 1)
221 			{
222 				if ((a % 2) == 0)
223 					emit NewPage(p, tmp);
224 				else
225 				{
226 					emit UseTemp(tmp, p);
227 					QTableWidgetItem* ite = item(a, b);
228 					if (ite == nullptr)
229 						return;
230 					if (ite->type() == 1002)
231 					{
232 						SeItem* it = (SeItem*)ite;
233 						it->pageName = tmp;
234 					}
235 				}
236 				return;
237 			}
238 			if ((b % 2) == 0)
239 			{
240 				if (lastPage)
241 					emit NewPage(p + 1, tmp);
242 				else
243 					emit NewPage(p, tmp);
244 			}
245 			else
246 			{
247 				emit UseTemp(tmp, p);
248 				QTableWidgetItem* ite = item(a, b);
249 				if (ite == nullptr)
250 					return;
251 				if (ite->type() == 1002)
252 				{
253 					SeItem* it = (SeItem*)ite;
254 					it->pageName = tmp;
255 				}
256 			}
257 			return;
258 		}
259 		if (str.startsWith("2"))
260 		{
261 			int st = str.indexOf(" ");
262 			int en = str.indexOf(" ", st + 1);
263 			tmp = str.mid(en+1);
264 			int dr = str.midRef(st, en-st).toInt();
265 			int a = rowAt(e->pos().y());
266 			int b = columnAt(e->pos().x());
267 			if ((a == -1) || (b == -1))
268 				return;
269 			QTableWidgetItem* ite = item(a, b);
270 			int p = getPage(a, b, &lastPage);
271 			if (a == rowCount() - 1)
272 			{
273 				emit movePage(dr, p+1);
274 				return;
275 			}
276 			if (columnCount() == 1)
277 			{
278 				if ((a % 2) == 0)
279 					emit movePage(dr, p);
280 				else
281 				{
282 					emit UseTemp(tmp, p);
283 					if (ite == nullptr)
284 						return;
285 					SeItem* it = (SeItem*)ite;
286 					it->pageName = tmp;
287 				}
288 				return;
289 			}
290 			if ((b % 2) == 0)
291 				emit movePage(dr, lastPage ? p+1 : p);
292 			else
293 			{
294 				emit UseTemp(tmp, p);
295 				if (ite == nullptr)
296 					return;
297 				if (ite->type() == 1002)
298 				{
299 					SeItem* it = (SeItem*)ite;
300 					it->pageName = tmp;
301 				}
302 			}
303 			return;
304 		}
305 	}
306 }
307 
dragEnterEvent(QDragEnterEvent * e)308 void SeView::dragEnterEvent(QDragEnterEvent *e)
309 {
310 	if (e->mimeData()->hasFormat("page/magic"))
311 		e->acceptProposedAction();
312 }
313 
dragLeaveEvent(QDragLeaveEvent *)314 void SeView::dragLeaveEvent(QDragLeaveEvent *)
315 {
316 	clearPix();
317 }
318 
dragMoveEvent(QDragMoveEvent * e)319 void SeView::dragMoveEvent(QDragMoveEvent *e)
320 {
321 	if (!e->mimeData()->hasFormat("page/magic"))
322 		return;
323 	e->acceptProposedAction();
324 	int a = rowAt(e->pos().y());
325 	int b = columnAt(e->pos().x());
326 	clearPix();
327 	if ((a == -1) || (b == -1))
328 		return;
329 	if (columnCount() == 1)
330 	{
331 		if ((a % 2) == 0)
332 		{
333 			item(a, 0)->setBackground(Qt::darkBlue);
334 		}
335 	}
336 	else
337 	{
338 		if (((b % 2) == 0) || (a == rowCount()-1))
339 		{
340 			item(a, b)->setBackground(Qt::darkBlue);
341 		}
342 	}
343 }
344 
keyPressEvent(QKeyEvent * e)345 void SeView::keyPressEvent(QKeyEvent * e)
346 {
347 	int k = e->key();
348 	if (k == Qt::Key_Delete)
349 	{
350 		e->accept();
351 		bool dummy;
352 		int pageToDelete = getPage(currentRow(), currentColumn(), &dummy);
353 		emit delPageRequest(pageToDelete);
354 		return;
355 	}
356 
357 	QTableWidget::keyPressEvent(e);
358 }
359 
clearPix()360 void SeView::clearPix()
361 {
362 	int rowcounter = 0;
363 	for (int i = 0; i < rowCount(); ++i)
364 	{
365 		int counter = 0;
366 		if (columnCount() == 1)
367 		{
368 			if ((i % 2) == 0)
369 			{
370 				item(rowcounter, 0)->setBackground(Qt::white);
371 				rowcounter += 2;
372 			}
373 		}
374 		else
375 		{
376 			for (int j = 0; j < columnCount(); ++j)
377 			{
378 				if ((j % 2) == 0)
379 				{
380 					item(rowcounter, counter)->setBackground(Qt::white);
381 					counter += 2;
382 				}
383 			}
384 			rowcounter++;
385 		}
386 	}
387 	for (int i = 0; i < columnCount(); ++i)
388 	{
389 		item(rowCount()-1, i)->setBackground(Qt::white);
390 	}
391 }
392 
getPage(int r,int c,bool * last)393 int SeView::getPage(int r, int c, bool *last)
394 {
395 	int counter = m_firstPage;
396 	int rowcounter = 0;
397 	int ret = m_pageCount - 1;
398 	*last = false;
399 	if (r == rowCount() - 1)
400 	{
401 		*last = true;
402 		return ret;
403 	}
404 	if ((r == 0) && (c < m_firstPage * m_colmult + m_coladd))
405 		return 0;
406 	for (int a = 0; a < m_pageCount; ++a)
407 	{
408 		if ((rowcounter * m_rowmult + m_rowadd == r) && (counter * m_colmult + m_coladd == c))
409 		{
410 			ret = a;
411 			return ret;
412 		}
413 		if (columnCount() == 1)
414 		{
415 			if ((rowcounter * m_rowmult) == r)
416 			{
417 				ret = a;
418 				return ret;
419 			}
420 		}
421 		else
422 		{
423 			if ((counter * m_colmult == c) && (rowcounter * m_rowmult + m_rowadd == r))
424 			{
425 				ret = a;
426 				return ret;
427 			}
428 		}
429 		counter++;
430 		if (counter > m_cols - 1)
431 		{
432 			counter = 0;
433 			rowcounter++;
434 		}
435 	}
436 	*last = true;
437 	return ret;
438 }
439 
getPageItem(int pageIndex)440 SeItem* SeView::getPageItem(int pageIndex)
441 {
442 	int rows = this->rowCount();
443 	int columns = this->columnCount();
444 	for (int i = 0; i < rows; ++i)
445 	{
446 		for (int j = 0; j < columns; ++j)
447 		{
448 			QTableWidgetItem* tbItem = item(i, j);
449 			SeItem* pageItem = dynamic_cast<SeItem*>(tbItem);
450 			if (pageItem && pageItem->pageNumber == static_cast<uint>(pageIndex))
451 				return pageItem;
452 		}
453 	}
454 	return nullptr;
455 }
456 
457 /* Der Muelleimer */
TrashBin(QWidget * parent)458 TrashBin::TrashBin(QWidget * parent) : QLabel(parent)
459 {
460 	Normal = IconManager::instance().loadPixmap("trashcan.png");
461 	Offen = IconManager::instance().loadPixmap("trashcan2.png");
462 	setPixmap(Normal);
463 	setScaledContents(false);
464 	setAcceptDrops(true);
465 
466 	connect(ScQApp, SIGNAL(iconSetChanged()), this, SLOT(iconSetChange()));
467 }
468 
dragEnterEvent(QDragEnterEvent * e)469 void TrashBin::dragEnterEvent(QDragEnterEvent *e)
470 {
471 	if (e->mimeData()->hasFormat("page/magic"))
472 	{
473 		e->accept();
474 		setPixmap(Offen);
475 	}
476 }
477 
dragLeaveEvent(QDragLeaveEvent *)478 void TrashBin::dragLeaveEvent(QDragLeaveEvent *)
479 {
480 	setPixmap(Normal);
481 }
482 
dropEvent(QDropEvent * e)483 void TrashBin::dropEvent(QDropEvent * e)
484 {
485 	setPixmap(Normal);
486 	QString str, tmp;
487 	if (e->mimeData()->hasFormat("page/magic"))
488 	{
489 		e->accept();
490 		str = e->mimeData()->text();
491 		if (str.startsWith("2"))
492 		{
493 			int st = str.indexOf(" ");
494 			int en = str.indexOf(" ", st+1);
495 			emit delPageRequest(str.midRef(st, en - st).toInt());
496 		}
497 		if (str.startsWith("1"))
498 		{
499 			tmp = str.remove(0,1);
500 			emit delMasterRequest(tmp);
501 		}
502 	}
503 }
504 
iconSetChange()505 void TrashBin::iconSetChange()
506 {
507 	Normal = IconManager::instance().loadPixmap("trashcan.png");
508 	Offen = IconManager::instance().loadPixmap("trashcan2.png");
509 	setPixmap(Normal);
510 }
511