1 /*******************************************************************
2 
3 Part of the Fritzing project - http://fritzing.org
4 Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de
5 
6 Fritzing is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10 
11 Fritzing is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15 
16 You should have received a copy of the GNU General Public License
17 along with Fritzing.  If not, see <http://www.gnu.org/licenses/>.
18 
19 ********************************************************************
20 
21 $Revision: 6141 $:
22 $Author: cohen@irascible.com $:
23 $Date: 2012-07-04 21:20:05 +0200 (Mi, 04. Jul 2012) $
24 
25 ********************************************************************/
26 
27 #include "cursormaster.h"
28 #include "../debugdialog.h"
29 
30 
31 #include <QApplication>
32 #include <QBitmap>
33 #include <QString>
34 #include <QKeyEvent>
35 #include <QEvent>
36 #include <QGraphicsItem>
37 #include <QGraphicsPixmapItem>
38 #include <QGraphicsScene>
39 #include <QGraphicsView>
40 #include <QGraphicsSceneMouseEvent>
41 #include <QTimer>
42 
43 QCursor * CursorMaster::BendpointCursor = NULL;
44 QCursor * CursorMaster::NewBendpointCursor = NULL;
45 QCursor * CursorMaster::MakeWireCursor = NULL;
46 QCursor * CursorMaster::MakeCurveCursor = NULL;
47 QCursor * CursorMaster::RubberbandCursor = NULL;
48 QCursor * CursorMaster::MoveCursor = NULL;
49 QCursor * CursorMaster::BendlegCursor = NULL;
50 QCursor * CursorMaster::RotateCursor = NULL;
51 QCursor * CursorMaster::ScaleCursor = NULL;
52 
53 //static QTimer timer;
54 
55 CursorMaster CursorMaster::TheCursorMaster;
56 static QList<QObject *> Listeners;
57 
58 static QHash<QGraphicsScene *, QGraphicsPixmapItem *> CursorItems;
59 static QList<QCursor **> Cursors;
60 
61 
CursorMaster()62 CursorMaster::CursorMaster() : QObject()
63 {
64     m_blocked = false;
65 }
66 
cleanup()67 void CursorMaster::cleanup() {
68     foreach (QCursor ** cursor, Cursors) {
69         delete *cursor;
70     }
71     Cursors.clear();
72 }
73 
initCursors()74 void CursorMaster::initCursors()
75 {
76 	if (BendpointCursor == NULL) {
77 		//timer.setSingleShot(true);
78 		//timer.setInterval(0);
79 		//connect(&timer, SIGNAL(timeout()), &TheCursorMaster, SLOT(moveCursor()));
80 
81 		QStringList names;
82 		QStringList masks;
83 
84 		names << ":resources/images/cursor/bendpoint.bmp"
85 			<< ":resources/images/cursor/new_bendpoint.bmp"
86 			<< ":resources/images/cursor/make_wire.bmp"
87 			<< ":resources/images/cursor/curve.bmp"
88 			<< ":resources/images/cursor/rubberband_move.bmp"
89 			<< ":resources/images/cursor/part_move.bmp"
90 			<< ":resources/images/cursor/bendleg.bmp"
91 			<< ":resources/images/cursor/rotate.bmp"
92 			<< ":resources/images/cursor/scale.bmp";
93 
94 		masks << ":resources/images/cursor/bendpoint_mask.bmp"
95 			<< ":resources/images/cursor/new_bendpoint_mask.bmp"
96 			<< ":resources/images/cursor/make_wire_mask.bmp"
97 			<< ":resources/images/cursor/curve_mask.bmp"
98 			<< ":resources/images/cursor/rubberband_move_mask.bmp"
99 			<< ":resources/images/cursor/part_move_mask.bmp"
100 			<< ":resources/images/cursor/bendleg_mask.bmp"
101 			<< ":resources/images/cursor/rotate_mask.bmp"
102 			<< ":resources/images/cursor/scale_mask.bmp";
103 
104 		Cursors << &BendpointCursor
105 			<< &NewBendpointCursor
106 			<< &MakeWireCursor
107 			<< &MakeCurveCursor
108 			<< &RubberbandCursor
109 			<< &MoveCursor
110 			<< &BendlegCursor
111 			<< &RotateCursor
112 			<< &ScaleCursor;
113 
114 		for (int i = 0; i < Cursors.count(); i++) {
115 			QBitmap bitmap1(names.at(i));
116 			QBitmap bitmap1m(masks.at(i));
117 			*Cursors.at(i) = new QCursor(bitmap1, bitmap1m, 0, 0);
118 		}
119 
120 		QApplication::instance()->installEventFilter(instance());
121 	}
122 }
123 
instance()124 CursorMaster * CursorMaster::instance()
125 {
126 	return &TheCursorMaster;
127 }
128 
addCursor(QObject * object,const QCursor & cursor)129 void CursorMaster::addCursor(QObject * object, const QCursor & cursor)
130 {
131     if (m_blocked) return;
132 
133 	if (object == NULL) return;
134 
135 
136 	/*
137 	QGraphicsItem * item = dynamic_cast<QGraphicsItem *>(object);
138 	if (item == NULL) return;
139 
140 	QGraphicsScene * scene = item->scene();
141 	if (scene == NULL) return;
142 
143 	QGraphicsView * view = dynamic_cast<QGraphicsView *>(scene->parent());
144 	if (view == NULL) return;
145 
146 	QGraphicsPixmapItem * pixmapItem = CursorItems.value(scene, NULL);
147 	if (pixmapItem == NULL) {
148 		pixmapItem = new QGraphicsPixmapItem();
149 		pixmapItem->setZValue(10000);			// always on top
150 		pixmapItem->setVisible(true);
151 		pixmapItem->setAcceptedMouseButtons(0);
152 		pixmapItem->setAcceptDrops(false);
153 		pixmapItem->setAcceptTouchEvents(false);
154 		pixmapItem->setAcceptHoverEvents(false);
155 		pixmapItem->setEnabled(false);
156 		pixmapItem->setFlags(QGraphicsItem::ItemIgnoresTransformations);
157 		CursorItems.insert(scene, pixmapItem);
158 		scene->addItem(pixmapItem);
159 		scene->installEventFilter(this);
160 	}
161 
162 	pixmapItem->setPixmap(*cursor.mask());
163 	pixmapItem->setPos(view->mapToScene(view->mapFromGlobal(QCursor::pos())) + cursor.hotSpot());
164 	*/
165 
166 	if (Listeners.contains(object)) {
167 		if (Listeners.first() != object) {
168 			Listeners.removeOne(object);
169 			Listeners.push_front(object);
170 		}
171 		//DebugDialog::debug(QString("changing cursor %1").arg((long) object));
172 		QApplication::changeOverrideCursor(cursor);
173 		return;
174 	}
175 
176 	Listeners.push_front(object);
177 	connect(object, SIGNAL(destroyed(QObject *)), this, SLOT(deleteCursor(QObject *)));
178 	QApplication::setOverrideCursor(cursor);
179 	//DebugDialog::debug(QString("addding cursor %1").arg((long) object));
180 }
181 
removeCursor(QObject * object)182 void CursorMaster::removeCursor(QObject * object)
183 {
184 	if (object == NULL) return;
185 
186 	if (Listeners.contains(object)) {
187 		disconnect(object, SIGNAL(destroyed(QObject *)), this, SLOT(deleteCursor(QObject *)));
188 		Listeners.removeOne(object);
189 		QApplication::restoreOverrideCursor();
190 		//DebugDialog::debug(QString("removing cursor %1").arg((long) object));
191 	}
192 
193 
194 	/*
195 	QGraphicsItem * item = dynamic_cast<QGraphicsItem *>(object);
196 	if (item == NULL) return;
197 
198 	QGraphicsScene * scene = item->scene();
199 	if (scene == NULL) return;
200 
201 	QGraphicsPixmapItem * pixmapItem = CursorItems.value(scene, NULL);
202 	if (pixmapItem == NULL) return;
203 
204 	pixmapItem->hide();
205 	*/
206 }
207 
deleteCursor(QObject * object)208 void CursorMaster::deleteCursor(QObject * object)
209 {
210 	removeCursor(object);
211 }
212 
eventFilter(QObject * object,QEvent * event)213 bool CursorMaster::eventFilter(QObject * object, QEvent * event)
214 {
215 	Q_UNUSED(object);
216 	//QGraphicsScene * scene = NULL;
217 
218 	switch (event->type()) {
219 		case QEvent::KeyPress:
220 		case QEvent::KeyRelease:
221 			//scene = dynamic_cast<QGraphicsScene *>(object);
222 			//DebugDialog::debug(QString("event filter %1").arg(object->metaObject()->className()));
223 			//if (scene)
224 			{
225 				QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
226 				foreach (QObject * listener, Listeners) {
227 					if (listener) {
228 						dynamic_cast<CursorKeyListener *>(listener)->cursorKeyEvent(keyEvent->modifiers());
229 						break;
230 					}
231 				}
232 			}
233 			break;
234 /*
235 		case QEvent::GraphicsSceneMouseMove:
236 
237 			scene = dynamic_cast<QGraphicsScene *>(object);
238 			if (scene) {
239 				QGraphicsPixmapItem * pixmapItem = CursorItems.value(scene, NULL);
240 				if (pixmapItem) {
241 					timer.setProperty("loc", ((QGraphicsSceneMouseEvent *) event)->scenePos());
242 					timer.setUserData(1, (QObjectUserData *) pixmapItem);
243 				}
244 			}
245 			break;
246 
247 		case QEvent::Leave:
248 			scene = dynamic_cast<QGraphicsScene *>(object);
249 			if (scene) {
250 				QGraphicsPixmapItem * pixmapItem = CursorItems.value(scene, NULL);
251 				if (pixmapItem) {
252 					//DebugDialog::debug("pos", ((QGraphicsSceneMouseEvent *) event)->scenePos());
253 					pixmapItem->hide();
254 				}
255 			}
256 			break;
257 */
258 		default:
259 			break;
260 	}
261 
262 
263 	return false;
264 }
265 
moveCursor()266 void CursorMaster::moveCursor() {
267 	//QObject * t = sender();
268 	//if (t == NULL) return;
269 
270 	//QPointF p = t->property("loc").toPointF();
271 	//QGraphicsPixmapItem * item = (QGraphicsPixmapItem *) t->userData(1);
272 
273 	//DebugDialog::debug("move", p);
274 	//item->setPos(p);   // + cursor->hotspot
275 	//item->show();
276 }
277 
block()278 void CursorMaster::block() {
279     m_blocked = true;
280 }
281 
unblock()282 void CursorMaster::unblock() {
283     m_blocked = false;
284 }
285