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