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                           symbolpalette.cpp  -  description
9                              -------------------
10     begin                : Sat May 8 2010
11     copyright            : (C) 2010 by Franz Schmid
12     email                : Franz.Schmid@altmuehlnet.de
13  ***************************************************************************/
14 
15 /***************************************************************************
16  *                                                                         *
17  *   This program is free software; you can redistribute it and/or modify  *
18  *   it under the terms of the GNU General Public License as published by  *
19  *   the Free Software Foundation; either version 2 of the License, or     *
20  *   (at your option) any later version.                                   *
21  *                                                                         *
22  ***************************************************************************/
23 #include "symbolpalette.h"
24 #include <QPainter>
25 #include <QByteArray>
26 #include <QDrag>
27 #include <QMimeData>
28 #include "scpattern.h"
29 #include "scribusdoc.h"
30 #include "scribus.h"
31 
SymbolView(QWidget * parent)32 SymbolView::SymbolView(QWidget* parent) : QListWidget(parent)
33 {
34 	setDragEnabled(true);
35 	setViewMode(QListView::IconMode);
36 	setFlow(QListView::LeftToRight);
37 	setSortingEnabled(true);
38 	setWrapping(true);
39 	setAcceptDrops(true);
40 	setDropIndicatorShown(true);
41 	setDragDropMode(QAbstractItemView::DragDrop);
42 	setResizeMode(QListView::Adjust);
43 	setSelectionMode(QAbstractItemView::SingleSelection);
44 	setContextMenuPolicy(Qt::CustomContextMenu);
45 	delegate = new ScListWidgetDelegate(this, this);
46 	setItemDelegate(delegate);
47 	setIconSize(QSize(48, 48));
48 	connect(this, SIGNAL(customContextMenuRequested (const QPoint&)), this, SLOT(HandleContextMenu(QPoint)));
49 }
50 
HandleContextMenu(QPoint p)51 void SymbolView::HandleContextMenu(QPoint p)
52 {
53 	QListWidgetItem *item = itemAt(p);
54 	if (!item)
55 	{
56 		QMenu *pmenu = new QMenu();
57 		QAction* viewAct;
58 		viewAct = pmenu->addAction( tr("Display Icons only"));
59 		viewAct->setCheckable(true);
60 		viewAct->setChecked(delegate->iconOnly());
61 		connect(viewAct, SIGNAL(triggered()), this, SLOT(changeDisplay()));
62 		pmenu->exec(QCursor::pos());
63 		delete pmenu;
64 	}
65 }
66 
changeDisplay()67 void SymbolView::changeDisplay()
68 {
69 	reset();
70 	delegate->setIconOnly(!delegate->iconOnly());
71 	repaint();
72 }
73 
dragEnterEvent(QDragEnterEvent * e)74 void SymbolView::dragEnterEvent(QDragEnterEvent *e)
75 {
76 	if (e->source() == this)
77 		e->ignore();
78 	else
79 		e->acceptProposedAction();
80 }
81 
dragMoveEvent(QDragMoveEvent * e)82 void SymbolView::dragMoveEvent(QDragMoveEvent *e)
83 {
84 	if (e->source() == this)
85 		e->ignore();
86 	else
87 		e->acceptProposedAction();
88 }
89 
dropEvent(QDropEvent * e)90 void SymbolView::dropEvent(QDropEvent *e)
91 {
92 	if (e->mimeData()->hasText())
93 	{
94 		e->acceptProposedAction();
95 		if (e->source() == this)
96 			return;
97 		QString text = e->mimeData()->text();
98 		if ((text.startsWith("<SCRIBUSELEM")) || (text.startsWith("SCRIBUSELEMUTF8")))
99 			emit objectDropped();
100 	}
101 	else
102 		e->ignore();
103 }
104 
105 
viewportEvent(QEvent * event)106 bool SymbolView::viewportEvent(QEvent *event)
107 {
108 	if (event != nullptr)
109 	{
110 		if (event->type() == QEvent::ToolTip)
111 		{
112 			QHelpEvent *helpEvent = static_cast<QHelpEvent *>(event);
113 			QListWidgetItem* it = itemAt(helpEvent->pos());
114 			if (it != nullptr)
115 			{
116 				event->accept();
117 				QString tipText = it->text();
118 				QToolTip::showText(helpEvent->globalPos(), tipText, this);
119 				return true;
120 			}
121 		}
122 		else if (event->type() == QEvent::MouseButtonPress)
123 		{
124 			QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
125 			if (mouseEvent->button() == Qt::RightButton)
126 				return true;
127 		}
128 		else if (event->type() == QEvent::MouseButtonRelease)
129 		{
130 			QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
131 			if (mouseEvent->button() == Qt::RightButton)
132 			{
133 				emit customContextMenuRequested(mouseEvent->pos());
134 				return true;
135 			}
136 		}
137 	}
138 	return QListWidget::viewportEvent(event);
139 }
140 
startDrag(Qt::DropActions supportedActions)141  void SymbolView::startDrag(Qt::DropActions supportedActions)
142  {
143 	QMimeData *mimeData = new QMimeData;
144 	QByteArray data = currentItem()->text().toLocal8Bit();
145 	mimeData->setData("text/symbol", data);
146 	QDrag *drag = new QDrag(this);
147 	drag->setMimeData(mimeData);
148 	drag->setPixmap(currentItem()->icon().pixmap(48, 48));
149 	drag->exec(Qt::CopyAction);
150 	clearSelection();
151 }
152 
SymbolPalette(QWidget * parent)153 SymbolPalette::SymbolPalette( QWidget* parent) : ScDockPalette(parent, "Symb", Qt::WindowFlags())
154 {
155 	setContentsMargins(3, 3, 3, 3);
156 	setMinimumSize( QSize( 220, 240 ) );
157 	setObjectName(QString::fromLocal8Bit("Symb"));
158 	setSizePolicy( QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum));
159 	SymbolViewWidget = new SymbolView(this);
160 	SymbolViewWidget->clear();
161 	setWidget( SymbolViewWidget );
162 
163 	unsetDoc();
164 	m_scMW  = nullptr;
165 	editItemNames.clear();
166 	languageChange();
167 	m_item = nullptr;
168 	connect(SymbolViewWidget, SIGNAL(itemDoubleClicked(QListWidgetItem*)), this, SLOT(handleDoubleClick(QListWidgetItem*)));
169 	connect(SymbolViewWidget, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(handleContextMenue(QPoint)));
170 	connect(SymbolViewWidget, SIGNAL(objectDropped()), this, SIGNAL(objectDropped()));
171 }
172 
handleContextMenue(QPoint p)173 void SymbolPalette::handleContextMenue(QPoint p)
174 {
175 	if (!m_doc)
176 		return;
177 	QListWidgetItem *item = SymbolViewWidget->itemAt(p);
178 	if (item)
179 	{
180 		m_item = item;
181 		QMenu *pmenu = new QMenu();
182 		QAction* editAct = pmenu->addAction( tr("Edit Item"));
183 		connect(editAct, SIGNAL(triggered()), this, SLOT(handleEditItem()));
184 		QAction* delAct = pmenu->addAction( tr("Remove Item"));
185 		connect(delAct, SIGNAL(triggered()), this, SLOT(handleDeleteItem()));
186 		pmenu->exec(QCursor::pos());
187 		delete pmenu;
188 	}
189 }
190 
handleDoubleClick(QListWidgetItem * item)191 void SymbolPalette::handleDoubleClick(QListWidgetItem *item)
192 {
193 	if (item)
194 		emit startEdit(item->text());
195 }
196 
handleEditItem()197 void SymbolPalette::handleEditItem()
198 {
199 	if (m_item != nullptr)
200 	{
201 		emit startEdit(m_item->text());
202 		m_item = nullptr;
203 	}
204 }
205 
handleDeleteItem()206 void SymbolPalette::handleDeleteItem()
207 {
208 	if (m_item != nullptr)
209 	{
210 		if (m_doc->docPatterns.contains(m_item->text()))
211 		{
212 			m_doc->removePattern(m_item->text());
213 			updateSymbolList();
214 			m_doc->regionsChanged()->update(QRect());
215 		}
216 		m_item = nullptr;
217 	}
218 }
219 
editingStart(QStringList names)220 void SymbolPalette::editingStart(QStringList names)
221 {
222 	editItemNames = names;
223 	for (int a = 0; a < editItemNames.count(); a++)
224 	{
225 		QList<QListWidgetItem*> items = SymbolViewWidget->findItems(names[a], Qt::MatchExactly);
226 		if (items.count() > 0)
227 			items[0]->setFlags(Qt::NoItemFlags);
228 	}
229 }
230 
editingFinished()231 void SymbolPalette::editingFinished()
232 {
233 	editItemNames.clear();
234 	updateSymbolList();
235 }
236 
setMainWindow(ScribusMainWindow * mw)237 void SymbolPalette::setMainWindow(ScribusMainWindow *mw)
238 {
239 	m_scMW = mw;
240 	if (m_scMW == nullptr)
241 	{
242 		SymbolViewWidget->clear();
243 		disconnect(m_scMW, SIGNAL(UpdateRequest(int)), this, SLOT(handleUpdateRequest(int)));
244 		return;
245 	}
246 	connect(m_scMW, SIGNAL(UpdateRequest(int)), this, SLOT(handleUpdateRequest(int)), Qt::UniqueConnection);
247 }
248 
setDoc(ScribusDoc * newDoc)249 void SymbolPalette::setDoc(ScribusDoc *newDoc)
250 {
251 	if (m_scMW == nullptr)
252 		m_doc = nullptr;
253 	else
254 		m_doc = newDoc;
255 	if (m_doc == nullptr)
256 	{
257 		SymbolViewWidget->clear();
258 		setEnabled(true);
259 	}
260 	else
261 	{
262 		setEnabled(!m_doc->drawAsPreview);
263 		updateSymbolList();
264 	}
265 }
266 
unsetDoc()267 void SymbolPalette::unsetDoc()
268 {
269 	m_doc = nullptr;
270 	SymbolViewWidget->clear();
271 	setEnabled(true);
272 }
273 
handleUpdateRequest(int updateFlags)274 void SymbolPalette::handleUpdateRequest(int updateFlags)
275 {
276 	if (updateFlags & reqSymbolsUpdate)
277 		updateSymbolList();
278 }
279 
updateSymbolList()280 void SymbolPalette::updateSymbolList()
281 {
282 	SymbolViewWidget->clear();
283 	SymbolViewWidget->setWordWrap(true);
284 	if (!m_doc)
285 		return;
286 
287 	QStringList patK = m_doc->docPatterns.keys();
288 	patK.sort();
289 	for (int a = 0; a < patK.count(); a++)
290 	{
291 		ScPattern sp = m_doc->docPatterns.value(patK[a]);
292 		QPixmap pm;
293 		if (sp.getPattern()->width() >= sp.getPattern()->height())
294 			pm = QPixmap::fromImage(sp.getPattern()->scaledToWidth(48, Qt::SmoothTransformation));
295 		else
296 			pm = QPixmap::fromImage(sp.getPattern()->scaledToHeight(48, Qt::SmoothTransformation));
297 		QPixmap pm2(48, 48);
298 		pm2.fill(palette().color(QPalette::Base));
299 		QPainter p;
300 		p.begin(&pm2);
301 		p.drawPixmap(24 - pm.width() / 2, 24 - pm.height() / 2, pm);
302 		p.end();
303 		QListWidgetItem *item = new QListWidgetItem(pm2, patK[a], SymbolViewWidget);
304 		if (editItemNames.contains(patK[a]))
305 			item->setFlags(Qt::NoItemFlags);
306 		else
307 			item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled);
308 	}
309 }
310 
changeEvent(QEvent * e)311 void SymbolPalette::changeEvent(QEvent *e)
312 {
313 	if (e->type() == QEvent::LanguageChange)
314 	{
315 		languageChange();
316 	}
317 	else
318 		ScDockPalette::changeEvent(e);
319 }
320 
languageChange()321 void SymbolPalette::languageChange()
322 {
323 	setWindowTitle( tr( "Symbols" ) );
324 }
325 
keyPressEvent(QKeyEvent * e)326 void SymbolPalette::keyPressEvent(QKeyEvent* e)
327 {
328 	if (!m_doc)
329 		return;
330 	switch (e->key())
331 	{
332 		case Qt::Key_Backspace:
333 		case Qt::Key_Delete:
334 			{
335 				QListWidgetItem* it = SymbolViewWidget->currentItem();
336 				if (it != nullptr)
337 				{
338 					if (m_doc->docPatterns.contains(it->text()))
339 					{
340 						m_doc->removePattern(it->text());
341 						updateSymbolList();
342 						m_doc->regionsChanged()->update(QRect());
343 						e->accept();
344 					}
345 				}
346 			}
347 			break;
348 		default:
349 			break;
350 	}
351 }
352