~ubuntu-branches/ubuntu/wily/psi/wily-proposed

« back to all changes in this revision

Viewing changes to src/whiteboarding/wbitem.cpp

  • Committer: Package Import Robot
  • Author(s): Jan Niehusmann
  • Date: 2014-07-01 21:49:34 UTC
  • mfrom: (6.1.7 sid)
  • Revision ID: package-import@ubuntu.com-20140701214934-gt4dkgm94byi4vnn
Tags: 0.15-1
* New upstream version
* set debhelper compat level to 9
* set Standards-Version to 3.9.5 (no further changes)
* add lintian override regarding license-problem-non-free-RFC
* use qconf to regenerate configure script
* implement hardening using buildflags instead of hardening-wrapper

Show diffs side-by-side

added added

removed removed

Lines of Context:
14
14
 *
15
15
 * You should have received a copy of the GNU General Public License
16
16
 * along with this library; if not, write to the Free Software
17
 
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
17
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
18
 *
19
19
 */
20
20
 
60
60
 */
61
61
 
62
62
WbItem::WbItem(SxeSession* session, QSvgRenderer* renderer, QDomElement node, WbScene* scene, WbWidget* widget) : QGraphicsSvgItem() {
63
 
    // Store a pointer to the underlying session, scene and node
64
 
    session_ = session;
65
 
    scene_ = scene;
66
 
    widget_ = widget;
67
 
    node_ = node;
68
 
 
69
 
    // qDebug() << QString("constructing %1.").arg(id()).toAscii();
70
 
 
71
 
    if(node.isNull()) {
72
 
        qDebug("Trying to create a WbItem from a null QDomNode.");
73
 
        return;
74
 
    }
75
 
 
76
 
 
77
 
    // Make the item selectable and movable
78
 
    setFlag(QGraphicsItem::ItemIsSelectable);
79
 
    setFlag(QGraphicsItem::ItemIsMovable);
80
 
 
81
 
    // Enable drag-n-drop
82
 
    setAcceptDrops(true);
83
 
 
84
 
    // Don't cache the SVG
85
 
    setCachingEnabled(false);
86
 
 
87
 
    // Set the renderer for the item
88
 
    setSharedRenderer(renderer);
89
 
 
90
 
    // add the new item to the scene
91
 
    addToScene();
 
63
        // Store a pointer to the underlying session, scene and node
 
64
        session_ = session;
 
65
        scene_ = scene;
 
66
        widget_ = widget;
 
67
        node_ = node;
 
68
 
 
69
        // qDebug() << QString("constructing %1.").arg(id()).toAscii();
 
70
 
 
71
        if(node.isNull()) {
 
72
                qDebug("Trying to create a WbItem from a null QDomNode.");
 
73
                return;
 
74
        }
 
75
 
 
76
 
 
77
        // Make the item selectable and movable
 
78
        setFlag(QGraphicsItem::ItemIsSelectable);
 
79
        setFlag(QGraphicsItem::ItemIsMovable);
 
80
 
 
81
        // Enable drag-n-drop
 
82
        setAcceptDrops(true);
 
83
 
 
84
        // Don't cache the SVG
 
85
        setCachingEnabled(false);
 
86
 
 
87
        // Set the renderer for the item
 
88
        setSharedRenderer(renderer);
 
89
 
 
90
        // add the new item to the scene
 
91
        addToScene();
92
92
}
93
93
 
94
94
WbItem::~WbItem() {
95
 
    // qDebug() << QString("destructing %1.").arg(id()).toAscii();
 
95
        // qDebug() << QString("destructing %1.").arg(id()).toAscii();
96
96
}
97
97
 
98
98
QString WbItem::id() {
99
 
    return node_.toElement().attribute("id");
 
99
        return node_.toElement().attribute("id");
100
100
}
101
101
 
102
102
QDomNode WbItem::node() {
103
 
    return node_;
 
103
        return node_;
104
104
}
105
105
 
106
106
void WbItem::contextMenuEvent (QGraphicsSceneContextMenuEvent * event) {
107
 
     constructContextMenu()->exec(event->screenPos());
 
107
         constructContextMenu()->exec(event->screenPos());
108
108
}
109
109
 
110
110
void WbItem::mouseMoveEvent(QGraphicsSceneMouseEvent * event) {
111
 
    event->accept();
112
 
     
113
 
    if(isSelected()) {
114
 
        if(widget_->mode() == WbWidget::Translate) {
115
 
 
116
 
            // Translate each selected item
117
 
            foreach(QGraphicsItem* graphicsitem, scene()->selectedItems()) {
118
 
                if (!graphicsitem->parentItem() || !graphicsitem->parentItem()->isSelected()) {
119
 
                    QPointF d = graphicsitem->mapFromScene(event->scenePos()) - graphicsitem->mapFromScene(event->lastScenePos());
120
 
                    graphicsitem->translate(d.x(), d.y());
121
 
                    // qDebug() QString("Translated %1 by %2 %3").arg((unsigned int) graphicsitem).arg(d.x()).arg(d.y()).toAscii();
122
 
 
123
 
                    // Regenerate the SVG transformation matrix later
124
 
                    WbItem* wbitem = dynamic_cast<WbItem*>(graphicsitem);
125
 
                    if(wbitem)
126
 
                        scene_->queueTransformationRegeneration(wbitem);
127
 
                }
128
 
            }
129
 
     
130
 
        } else if(widget_->mode() == WbWidget::Rotate) {
131
 
 
132
 
            // Rotate each selected item
133
 
            // get center coordinates of selected items in scene coordinates
134
 
            QPointF scenePivot = scene_->selectionCenter();
135
 
            // Determine the direction relative to the center
136
 
            // Divide the sum by two to reduce the "speed" of rotation
137
 
            QPointF difference = event->scenePos() - event->lastScenePos();
138
 
//          qDebug() << QString("d: %1 %2 = %3 %4 + %5 %6").arg(difference.x()).arg(difference.y()).arg(event->scenePos().x()).arg(event->scenePos().y()).arg(event->lastScenePos().x()).arg(event->lastScenePos().y());
139
 
            QPointF p = event->scenePos();
140
 
            QMatrix delta;
141
 
            if(p.x() >= scenePivot.x() && p.y() >= scenePivot.y()) {
142
 
                 delta.rotate((-difference.x() + difference.y()) / 2);
143
 
            } else if(p.x() < scenePivot.x() && p.y() >= scenePivot.y()) {
144
 
                 delta.rotate((-difference.x() - difference.y()) / 2);
145
 
            } else if(p.x() < scenePivot.x() && p.y() < scenePivot.y()) {
146
 
                 delta.rotate((difference.x() - difference.y()) / 2);
147
 
            } else if(p.x() >= scenePivot.x() && p.y() < scenePivot.y()) {
148
 
                 delta.rotate((difference.x() + difference.y()) / 2);
149
 
            }
150
 
 
151
 
            foreach(QGraphicsItem* graphicsitem, scene()->selectedItems()) {
152
 
                if (!graphicsitem->parentItem() || !graphicsitem->parentItem()->isSelected()) {
153
 
                    QMatrix translation;
154
 
                    // get center coordinates of selected items in item coordinates
155
 
                    QPointF itemPivot = graphicsitem->mapFromScene(scenePivot);
156
 
                    // translates the the item's center to the origin of the item coordinates
157
 
                    translation.translate(-itemPivot.x(), -itemPivot.y());
158
 
                    // set the matrix
159
 
                    graphicsitem->setTransform(QTransform(translation * delta * translation.inverted()), true);
160
 
 
161
 
                    // Regenerate the SVG transformation matrix later
162
 
                    WbItem* wbitem = dynamic_cast<WbItem*>(graphicsitem);
163
 
                    if(wbitem)
164
 
                        scene_->queueTransformationRegeneration(wbitem);
165
 
                }
166
 
            }
167
 
    
168
 
        } else if(widget_->mode() == WbWidget::Scale) {
169
 
 
170
 
            // Scale each selected item
171
 
            foreach(QGraphicsItem* graphicsitem, scene()->selectedItems()) {
172
 
                if (!graphicsitem->parentItem() || !graphicsitem->parentItem()->isSelected()) {
173
 
 
174
 
                    // get center coordinates in item coordinates
175
 
                    QPointF c = center();
176
 
                    QMatrix translation, delta;
177
 
                    // translates the the item's center to the origin of the item coordinates
178
 
                    translation.translate(-c.x(), -c.y());
179
 
                    // Scale.
180
 
                    // Moving mouse up enlarges, down shrinks, y axis.
181
 
                    // Moving mouse right enlarges, left shrinks, x axis.
182
 
                    QPointF difference = event->scenePos() - event->lastScenePos();
183
 
                    // Note: the y axis points downwards in scene coordinates
184
 
                    delta.scale(1 + difference.x()/50, 1 - difference.y()/50);
185
 
                    // set the matrix
186
 
                    setTransform(QTransform(translation * delta * translation.inverted()), true);
 
111
        event->accept();
 
112
 
 
113
        if(isSelected()) {
 
114
                if(widget_->mode() == WbWidget::Translate) {
 
115
 
 
116
                        // Translate each selected item
 
117
                        foreach(QGraphicsItem* graphicsitem, scene()->selectedItems()) {
 
118
                                if (!graphicsitem->parentItem() || !graphicsitem->parentItem()->isSelected()) {
 
119
                                        QPointF d = graphicsitem->mapFromScene(event->scenePos()) - graphicsitem->mapFromScene(event->lastScenePos());
 
120
                                        graphicsitem->translate(d.x(), d.y());
 
121
                                        // qDebug() QString("Translated %1 by %2 %3").arg((unsigned int) graphicsitem).arg(d.x()).arg(d.y()).toAscii();
 
122
 
 
123
                                        // Regenerate the SVG transformation matrix later
 
124
                                        WbItem* wbitem = dynamic_cast<WbItem*>(graphicsitem);
 
125
                                        if(wbitem)
 
126
                                                scene_->queueTransformationRegeneration(wbitem);
 
127
                                }
 
128
                        }
 
129
 
 
130
                } else if(widget_->mode() == WbWidget::Rotate) {
 
131
 
 
132
                        // Rotate each selected item
 
133
                        // get center coordinates of selected items in scene coordinates
 
134
                        QPointF scenePivot = scene_->selectionCenter();
 
135
                        // Determine the direction relative to the center
 
136
                        // Divide the sum by two to reduce the "speed" of rotation
 
137
                        QPointF difference = event->scenePos() - event->lastScenePos();
 
138
//                qDebug() << QString("d: %1 %2 = %3 %4 + %5 %6").arg(difference.x()).arg(difference.y()).arg(event->scenePos().x()).arg(event->scenePos().y()).arg(event->lastScenePos().x()).arg(event->lastScenePos().y());
 
139
                        QPointF p = event->scenePos();
 
140
                        QMatrix delta;
 
141
                        if(p.x() >= scenePivot.x() && p.y() >= scenePivot.y()) {
 
142
                                 delta.rotate((-difference.x() + difference.y()) / 2);
 
143
                        } else if(p.x() < scenePivot.x() && p.y() >= scenePivot.y()) {
 
144
                                 delta.rotate((-difference.x() - difference.y()) / 2);
 
145
                        } else if(p.x() < scenePivot.x() && p.y() < scenePivot.y()) {
 
146
                                 delta.rotate((difference.x() - difference.y()) / 2);
 
147
                        } else if(p.x() >= scenePivot.x() && p.y() < scenePivot.y()) {
 
148
                                 delta.rotate((difference.x() + difference.y()) / 2);
 
149
                        }
 
150
 
 
151
                        foreach(QGraphicsItem* graphicsitem, scene()->selectedItems()) {
 
152
                                if (!graphicsitem->parentItem() || !graphicsitem->parentItem()->isSelected()) {
 
153
                                        QMatrix translation;
 
154
                                        // get center coordinates of selected items in item coordinates
 
155
                                        QPointF itemPivot = graphicsitem->mapFromScene(scenePivot);
 
156
                                        // translates the the item's center to the origin of the item coordinates
 
157
                                        translation.translate(-itemPivot.x(), -itemPivot.y());
 
158
                                        // set the matrix
 
159
                                        graphicsitem->setTransform(QTransform(translation * delta * translation.inverted()), true);
 
160
 
 
161
                                        // Regenerate the SVG transformation matrix later
 
162
                                        WbItem* wbitem = dynamic_cast<WbItem*>(graphicsitem);
 
163
                                        if(wbitem)
 
164
                                                scene_->queueTransformationRegeneration(wbitem);
 
165
                                }
 
166
                        }
 
167
 
 
168
                } else if(widget_->mode() == WbWidget::Scale) {
 
169
 
 
170
                        // Scale each selected item
 
171
                        foreach(QGraphicsItem* graphicsitem, scene()->selectedItems()) {
 
172
                                if (!graphicsitem->parentItem() || !graphicsitem->parentItem()->isSelected()) {
 
173
 
 
174
                                        // get center coordinates in item coordinates
 
175
                                        QPointF c = center();
 
176
                                        QMatrix translation, delta;
 
177
                                        // translates the the item's center to the origin of the item coordinates
 
178
                                        translation.translate(-c.x(), -c.y());
 
179
                                        // Scale.
 
180
                                        // Moving mouse up enlarges, down shrinks, y axis.
 
181
                                        // Moving mouse right enlarges, left shrinks, x axis.
 
182
                                        QPointF difference = event->scenePos() - event->lastScenePos();
 
183
                                        // Note: the y axis points downwards in scene coordinates
 
184
                                        delta.scale(1 + difference.x()/50, 1 - difference.y()/50);
 
185
                                        // set the matrix
 
186
                                        setTransform(QTransform(translation * delta * translation.inverted()), true);
187
187
 
188
 
                    // Regenerate the SVG transformation matrix later
189
 
                    scene_->queueTransformationRegeneration(dynamic_cast<WbItem*>(graphicsitem));
190
 
 
191
 
                }
192
 
            }
193
 
 
194
 
        }
195
 
    }
 
188
                                        // Regenerate the SVG transformation matrix later
 
189
                                        scene_->queueTransformationRegeneration(dynamic_cast<WbItem*>(graphicsitem));
 
190
 
 
191
                                }
 
192
                        }
 
193
 
 
194
                }
 
195
        }
196
196
}
197
197
 
198
198
void WbItem::mouseReleaseEvent(QGraphicsSceneMouseEvent* event) {
199
 
    QGraphicsSvgItem::mouseReleaseEvent(event);
 
199
        QGraphicsSvgItem::mouseReleaseEvent(event);
200
200
 
201
 
    scene_->regenerateTransformations();
 
201
        scene_->regenerateTransformations();
202
202
}
203
203
 
204
204
QMatrix WbItem::parseSvgTransform(QString string) {
205
 
    string = string.trimmed();
206
 
    if(string.isEmpty())
207
 
        return QMatrix();
 
205
        string = string.trimmed();
 
206
        if(string.isEmpty())
 
207
                return QMatrix();
208
208
 
209
 
    return parseTransformationMatrix(string);
 
209
        return parseTransformationMatrix(string);
210
210
}
211
211
 
212
212
QString WbItem::toSvgTransform(const QMatrix &m) {
213
 
    return QString("matrix(%1 %2 %3 %4 %5 %6)").arg(m.m11()).arg(m.m12()).arg(m.m21()).arg(m.m22()).arg(m.dx()).arg(m.dy());
 
213
        return QString("matrix(%1 %2 %3 %4 %5 %6)").arg(m.m11()).arg(m.m12()).arg(m.m21()).arg(m.m22()).arg(m.dx()).arg(m.dy());
214
214
}
215
215
 
216
216
void WbItem::regenerateTransform() {
217
 
    // Replace the QGraphicsItem transformation with an SVG transformation.
218
 
    // Possible as long as no perspective transformations have been applied.
219
 
 
220
 
    // delta is the new transformation to be applied
221
 
    QMatrix delta = transform().toAffine();
222
 
    if(delta.isIdentity())
223
 
        return;
224
 
 
225
 
    // get the existing SVG transformation
226
 
    QString oldValue = node_.attribute("transform");
227
 
    QMatrix oldTransform = parseSvgTransform(oldValue);
228
 
 
229
 
    // construct a translation that translates the item to (0,0) in scene coordinates
230
 
    QMatrix translation;
231
 
    // translates the the item's center to the origin of the item coordinates
232
 
    translation.translate(-pos().x(), -pos().y());
233
 
 
234
 
    // generate the string representation
235
 
    QString newValue = toSvgTransform(oldTransform * translation * delta * translation.inverted());
236
 
 
237
 
    if(newValue != oldValue) {
238
 
        resetTransform();
239
 
        session_->setAttribute(node_, "transform", newValue);
240
 
    }
 
217
        // Replace the QGraphicsItem transformation with an SVG transformation.
 
218
        // Possible as long as no perspective transformations have been applied.
 
219
 
 
220
        // delta is the new transformation to be applied
 
221
        QMatrix delta = transform().toAffine();
 
222
        if(delta.isIdentity())
 
223
                return;
 
224
 
 
225
        // get the existing SVG transformation
 
226
        QString oldValue = node_.attribute("transform");
 
227
        QMatrix oldTransform = parseSvgTransform(oldValue);
 
228
 
 
229
        // construct a translation that translates the item to (0,0) in scene coordinates
 
230
        QMatrix translation;
 
231
        // translates the the item's center to the origin of the item coordinates
 
232
        translation.translate(-pos().x(), -pos().y());
 
233
 
 
234
        // generate the string representation
 
235
        QString newValue = toSvgTransform(oldTransform * translation * delta * translation.inverted());
 
236
 
 
237
        if(newValue != oldValue) {
 
238
                resetTransform();
 
239
                session_->setAttribute(node_, "transform", newValue);
 
240
        }
241
241
}
242
242
 
243
243
void WbItem::addToScene() {
244
 
    // qDebug() << QString("adding %1 to scene.").arg(id()).toAscii();
245
 
    
246
 
    // Do nothing if already added and id matches
247
 
    if(scene_ == scene()
248
 
        && node_.hasAttribute("id")
249
 
        && node_.attribute("id") == elementId())
250
 
        return;
251
 
 
252
 
    // Read or generate an xml:id for the node
253
 
    QString id;
254
 
    if(node_.hasAttribute("id"))
255
 
        id = node_.attribute("id");
256
 
    else {
257
 
        id = "e" + SxeSession::generateUUID();
258
 
        // qDebug() << QString("Setting new id to %1").arg(id).toAscii();
259
 
        session_->setAttribute(node_, "id", id);
260
 
        session_->flush();
261
 
    }
262
 
 
263
 
    // Only render the indicated item
264
 
    setElementId(id);
265
 
 
266
 
    // Set the position
267
 
    resetPos();
268
 
 
269
 
    scene_->addItem(this);
 
244
        // qDebug() << QString("adding %1 to scene.").arg(id()).toAscii();
 
245
 
 
246
        // Do nothing if already added and id matches
 
247
        if(scene_ == scene()
 
248
                && node_.hasAttribute("id")
 
249
                && node_.attribute("id") == elementId())
 
250
        {
 
251
                return;
 
252
        }
 
253
 
 
254
        // Read or generate an xml:id for the node
 
255
        QString id;
 
256
        if(node_.hasAttribute("id")) {
 
257
                id = node_.attribute("id");
 
258
        }
 
259
        else {
 
260
                id = "e" + SxeSession::generateUUID();
 
261
                // qDebug() << QString("Setting new id to %1").arg(id).toAscii();
 
262
                session_->setAttribute(node_, "id", id);
 
263
                session_->flush();
 
264
        }
 
265
 
 
266
        // Only render the indicated item
 
267
        setElementId(id);
 
268
 
 
269
        // Set the position
 
270
        resetPos();
 
271
 
 
272
        scene_->addItem(this);
270
273
}
271
274
 
272
275
void WbItem::removeFromScene() {
273
 
    // qDebug() << QString("removing %1 from scene.").arg(id()).toAscii();
274
 
 
275
 
    scene_->removeItem(this);
276
 
 
277
 
    setElementId(QString());
 
276
        // qDebug() << QString("removing %1 from scene.").arg(id()).toAscii();
 
277
 
 
278
        scene_->removeItem(this);
 
279
 
 
280
        setElementId(QString());
278
281
}
279
282
 
280
283
void WbItem::resetPos() {
281
 
    // set the x & y approriately;
282
 
    setPos(renderer()->boundsOnElement(id()).topLeft());
283
 
 
284
 
    // set the drawing order
285
 
    // TODO: optimize
286
 
    int i = 0;
287
 
    QDomNodeList children = node_.parentNode().childNodes();
288
 
    while(children.at(i) != node_)
289
 
        i++;
290
 
    
291
 
    setZValue(i);
 
284
        // set the x & y approriately;
 
285
        setPos(renderer()->boundsOnElement(id()).topLeft());
 
286
 
 
287
        // set the drawing order
 
288
        // TODO: optimize
 
289
        int i = 0;
 
290
        QDomNodeList children = node_.parentNode().childNodes();
 
291
        while(children.at(i) != node_) {
 
292
                i++;
 
293
        }
 
294
 
 
295
        setZValue(i);
292
296
}
293
297
 
294
298
WbItemMenu* WbItem::constructContextMenu() {
295
 
     WbItemMenu* menu = new WbItemMenu(0);
296
 
 
297
 
     if(scene_) {
298
 
         // Add the default actions
299
 
         QActionGroup* group;
300
 
         // QAction* qaction;
301
 
         QPixmap pixmap;
302
 
 
303
 
         // group = new QActionGroup(0);
304
 
         // pixmap(2, 2);
305
 
         // pixmap.fill(QColor(Qt::black));
306
 
         // qaction = new QAction(QIcon(pixmap), tr("Thin stroke"), group);
307
 
         // qaction->setData(QVariant(1));
308
 
         // pixmap = QPixmap(6, 6);
309
 
         // pixmap.fill(QColor(Qt::black));
310
 
         // qaction = new QAction(QIcon(pixmap), tr("Medium stroke"), group);
311
 
         // qaction->setData(QVariant(3));
312
 
         // pixmap = QPixmap(12, 12);
313
 
         // pixmap.fill(QColor(Qt::black));
314
 
         // qaction = new QAction(QIcon(pixmap), tr("Thick stroke"), group);
315
 
         // qaction->setData(QVariant(6));
316
 
         // connect(group, SIGNAL(triggered(QAction*)), wbscene, SLOT(setStrokeWidth(QAction*)));
317
 
         // menu->addActionGroup(group);
318
 
 
319
 
         // menu->addSeparator();
320
 
         // group = new QActionGroup(0);
321
 
         // pixmap = QPixmap(16, 16);
322
 
         // pixmap.fill(QColor(Qt::darkCyan));
323
 
         // qaction = new QAction(QIcon(pixmap), tr("Change stroke color"), group);
324
 
         // connect(qaction, SIGNAL(triggered()), wbscene, SLOT(setStrokeColor()));
325
 
         // pixmap.fill(QColor(Qt::darkYellow));
326
 
         // qaction = new QAction(QIcon(pixmap), tr("Change fill color"), group);
327
 
         // connect(qaction, SIGNAL(triggered()), wbscene, SLOT(setFillColor()));
328
 
         // menu->addActionGroup(group);
329
 
 
330
 
         // menu->addSeparator();
331
 
         group = new QActionGroup(0);
332
 
         IconAction* action = new IconAction(tr("Bring forward"), "psi/bringForwards", tr("Bring forward"), 0, group);
333
 
         connect(action, SIGNAL(triggered()), scene_, SLOT(bringForward()));
334
 
         action = new IconAction(tr("Bring to front"), "psi/bringToFront", tr("Bring to front"), 0, group);
335
 
         connect(action, SIGNAL(triggered()), scene_, SLOT(bringToFront()));
336
 
         action = new IconAction(tr("Send backwards"), "psi/sendBackwards", tr("Send backwards"), 0, group);
337
 
         connect(action, SIGNAL(triggered()), scene_, SLOT(sendBackwards()));
338
 
         action = new IconAction(tr("Send to back"), "psi/sendToBack", tr("Send to back"), 0, group);
339
 
         connect(action, SIGNAL(triggered()), scene_, SLOT(sendToBack()));
340
 
         menu->addActionGroup(group);
341
 
 
342
 
         menu->addSeparator();
343
 
         group = new QActionGroup(0);
344
 
         action = new IconAction(tr("Group"), "psi/group", tr("Group"), 0, group);
345
 
         connect(action, SIGNAL(triggered()), scene_, SLOT(group()));
346
 
         action = new IconAction(tr("Ungroup"), "psi/ungroup", tr("Ungroup"), 0, group);
347
 
         connect(action, SIGNAL(triggered()), scene_, SLOT(ungroup()));
348
 
         menu->addActionGroup(group);
349
 
     }
350
 
 
351
 
     return menu;
 
299
         WbItemMenu* menu = new WbItemMenu(0);
 
300
 
 
301
         if(scene_) {
 
302
                 // Add the default actions
 
303
                 QActionGroup* group;
 
304
                 // QAction* qaction;
 
305
                 QPixmap pixmap;
 
306
 
 
307
                 // group = new QActionGroup(0);
 
308
                 // pixmap(2, 2);
 
309
                 // pixmap.fill(QColor(Qt::black));
 
310
                 // qaction = new QAction(QIcon(pixmap), tr("Thin stroke"), group);
 
311
                 // qaction->setData(QVariant(1));
 
312
                 // pixmap = QPixmap(6, 6);
 
313
                 // pixmap.fill(QColor(Qt::black));
 
314
                 // qaction = new QAction(QIcon(pixmap), tr("Medium stroke"), group);
 
315
                 // qaction->setData(QVariant(3));
 
316
                 // pixmap = QPixmap(12, 12);
 
317
                 // pixmap.fill(QColor(Qt::black));
 
318
                 // qaction = new QAction(QIcon(pixmap), tr("Thick stroke"), group);
 
319
                 // qaction->setData(QVariant(6));
 
320
                 // connect(group, SIGNAL(triggered(QAction*)), wbscene, SLOT(setStrokeWidth(QAction*)));
 
321
                 // menu->addActionGroup(group);
 
322
 
 
323
                 // menu->addSeparator();
 
324
                 // group = new QActionGroup(0);
 
325
                 // pixmap = QPixmap(16, 16);
 
326
                 // pixmap.fill(QColor(Qt::darkCyan));
 
327
                 // qaction = new QAction(QIcon(pixmap), tr("Change stroke color"), group);
 
328
                 // connect(qaction, SIGNAL(triggered()), wbscene, SLOT(setStrokeColor()));
 
329
                 // pixmap.fill(QColor(Qt::darkYellow));
 
330
                 // qaction = new QAction(QIcon(pixmap), tr("Change fill color"), group);
 
331
                 // connect(qaction, SIGNAL(triggered()), wbscene, SLOT(setFillColor()));
 
332
                 // menu->addActionGroup(group);
 
333
 
 
334
                 // menu->addSeparator();
 
335
                 group = new QActionGroup(0);
 
336
                 IconAction* action = new IconAction(tr("Bring forward"), "psi/bringForwards", tr("Bring forward"), 0, group);
 
337
                 connect(action, SIGNAL(triggered()), scene_, SLOT(bringForward()));
 
338
                 action = new IconAction(tr("Bring to front"), "psi/bringToFront", tr("Bring to front"), 0, group);
 
339
                 connect(action, SIGNAL(triggered()), scene_, SLOT(bringToFront()));
 
340
                 action = new IconAction(tr("Send backwards"), "psi/sendBackwards", tr("Send backwards"), 0, group);
 
341
                 connect(action, SIGNAL(triggered()), scene_, SLOT(sendBackwards()));
 
342
                 action = new IconAction(tr("Send to back"), "psi/sendToBack", tr("Send to back"), 0, group);
 
343
                 connect(action, SIGNAL(triggered()), scene_, SLOT(sendToBack()));
 
344
                 menu->addActionGroup(group);
 
345
 
 
346
                 menu->addSeparator();
 
347
                 group = new QActionGroup(0);
 
348
                 action = new IconAction(tr("Group"), "psi/group", tr("Group"), 0, group);
 
349
                 connect(action, SIGNAL(triggered()), scene_, SLOT(group()));
 
350
                 action = new IconAction(tr("Ungroup"), "psi/ungroup", tr("Ungroup"), 0, group);
 
351
                 connect(action, SIGNAL(triggered()), scene_, SLOT(ungroup()));
 
352
                 menu->addActionGroup(group);
 
353
         }
 
354
 
 
355
         return menu;
352
356
}
353
357
 
354
358
QPointF WbItem::center() {
355
 
    // Determine the center of the item in item coordinates before transformation
356
 
    QRectF r = boundingRect();
357
 
    QPointF c(r.x() + r.width()/2, r.y() + r.height()/2);
358
 
//  qDebug() << QString("center: %1 + %2    %3 + %4").arg(r.x()).arg(r.width()/2).arg(r.y()).arg(r.height()/2);
359
 
    // return the center with transformation applied
360
 
    return transform().map(c);
 
359
        // Determine the center of the item in item coordinates before transformation
 
360
        QRectF r = boundingRect();
 
361
        QPointF c(r.x() + r.width()/2, r.y() + r.height()/2);
 
362
//  qDebug() << QString("center: %1 + %2        %3 + %4").arg(r.x()).arg(r.width()/2).arg(r.y()).arg(r.height()/2);
 
363
        // return the center with transformation applied
 
364
        return transform().map(c);
361
365
}
362
366
 
363
367
 
406
410
 
407
411
static qreal toDouble(const QChar *&str)
408
412
{
409
 
    const int maxLen = 255;//technically doubles can go til 308+ but whatever
410
 
    char temp[maxLen+1];
411
 
    int pos = 0;
412
 
 
413
 
    if (*str == QLatin1Char('-')) {
414
 
        temp[pos++] = '-';
415
 
        ++str;
416
 
    } else if (*str == QLatin1Char('+')) {
417
 
        ++str;
418
 
    }
419
 
    while (*str >= QLatin1Char('0') && *str <= QLatin1Char('9') && pos < maxLen) {
420
 
        temp[pos++] = str->toLatin1();
421
 
        ++str;
422
 
    }
423
 
    if (*str == QLatin1Char('.') && pos < maxLen) {
424
 
        temp[pos++] = '.';
425
 
        ++str;
426
 
    }
427
 
    while (*str >= QLatin1Char('0') && *str <= QLatin1Char('9') && pos < maxLen) {
428
 
        temp[pos++] = str->toLatin1();
429
 
        ++str;
430
 
    }
431
 
    bool exponent = false;
432
 
    if (*str == QLatin1Char('e') && pos < maxLen) {
433
 
        exponent = true;
434
 
        temp[pos++] = 'e';
435
 
        ++str;
436
 
        if ((*str == QLatin1Char('-') || *str == QLatin1Char('+')) && pos < maxLen) {
437
 
            temp[pos++] = str->toLatin1();
438
 
            ++str;
439
 
        }
440
 
        while (*str >= QLatin1Char('0') && *str <= QLatin1Char('9') && pos < maxLen) {
441
 
            temp[pos++] = str->toLatin1();
442
 
            ++str;
443
 
        }
444
 
    }
445
 
    temp[pos] = '\0';
446
 
 
447
 
    qreal val;
448
 
    if (!exponent && pos < 10) {
449
 
        int ival = 0;
450
 
        const char *t = temp;
451
 
        bool neg = false;
452
 
        if(*t == '-') {
453
 
            neg = true;
454
 
            ++t;
455
 
        }
456
 
        while(*t && *t != '.') {
457
 
            ival *= 10;
458
 
            ival += (*t) - '0';
459
 
            ++t;
460
 
        }
461
 
        if(*t == '.') {
462
 
            ++t;
463
 
            int div = 1;
464
 
            while(*t) {
465
 
                ival *= 10;
466
 
                ival += (*t) - '0';
467
 
                div *= 10;
468
 
                ++t;
469
 
            }
470
 
            val = ((qreal)ival)/((qreal)div);
471
 
        } else {
472
 
            val = ival;
473
 
        }
474
 
        if (neg)
475
 
            val = -val;
476
 
    } else {
 
413
        const int maxLen = 255;//technically doubles can go til 308+ but whatever
 
414
        char temp[maxLen+1];
 
415
        int pos = 0;
 
416
 
 
417
        if (*str == QLatin1Char('-')) {
 
418
                temp[pos++] = '-';
 
419
                ++str;
 
420
        }
 
421
        else if (*str == QLatin1Char('+')) {
 
422
                ++str;
 
423
        }
 
424
        while (*str >= QLatin1Char('0') && *str <= QLatin1Char('9') && pos < maxLen) {
 
425
                temp[pos++] = str->toLatin1();
 
426
                ++str;
 
427
        }
 
428
        if (*str == QLatin1Char('.') && pos < maxLen) {
 
429
                temp[pos++] = '.';
 
430
                ++str;
 
431
        }
 
432
        while (*str >= QLatin1Char('0') && *str <= QLatin1Char('9') && pos < maxLen) {
 
433
                temp[pos++] = str->toLatin1();
 
434
                ++str;
 
435
        }
 
436
        bool exponent = false;
 
437
        if (*str == QLatin1Char('e') && pos < maxLen) {
 
438
                exponent = true;
 
439
                temp[pos++] = 'e';
 
440
                ++str;
 
441
                if ((*str == QLatin1Char('-') || *str == QLatin1Char('+')) && pos < maxLen) {
 
442
                        temp[pos++] = str->toLatin1();
 
443
                        ++str;
 
444
                }
 
445
                while (*str >= QLatin1Char('0') && *str <= QLatin1Char('9') && pos < maxLen) {
 
446
                        temp[pos++] = str->toLatin1();
 
447
                        ++str;
 
448
                }
 
449
        }
 
450
        temp[pos] = '\0';
 
451
 
 
452
        qreal val;
 
453
        if (!exponent && pos < 10) {
 
454
                int ival = 0;
 
455
                const char *t = temp;
 
456
                bool neg = false;
 
457
                if(*t == '-') {
 
458
                        neg = true;
 
459
                        ++t;
 
460
                }
 
461
                while(*t && *t != '.') {
 
462
                        ival *= 10;
 
463
                        ival += (*t) - '0';
 
464
                        ++t;
 
465
                }
 
466
                if(*t == '.') {
 
467
                        ++t;
 
468
                        int div = 1;
 
469
                        while(*t) {
 
470
                                ival *= 10;
 
471
                                ival += (*t) - '0';
 
472
                                div *= 10;
 
473
                                ++t;
 
474
                        }
 
475
                        val = ((qreal)ival)/((qreal)div);
 
476
                }
 
477
                else {
 
478
                        val = ival;
 
479
                }
 
480
                if (neg)
 
481
                        val = -val;
 
482
        } else {
477
483
#ifdef Q_WS_QWS
478
 
        if(sizeof(qreal) == sizeof(float))
479
 
            val = strtof(temp, 0);
480
 
        else
 
484
                if(sizeof(qreal) == sizeof(float))
 
485
                        val = strtof(temp, 0);
 
486
                else
481
487
#endif
482
 
        {
483
 
            bool ok = false;
484
 
            val = qstrtod(temp, 0, &ok);
485
 
        }
486
 
    }
487
 
    return val;
 
488
                {
 
489
                        bool ok = false;
 
490
                        val = qstrtod(temp, 0, &ok);
 
491
                }
 
492
        }
 
493
        return val;
488
494
 
489
495
}
490
496
 
491
497
static QVector<qreal> parseNumbersList(const QChar *&str)
492
498
{
493
 
    QVector<qreal> points;
494
 
    if (!str)
495
 
        return points;
496
 
    points.reserve(32);
497
 
 
498
 
    while (*str == QLatin1Char(' '))
499
 
        ++str;
500
 
    while ((*str >= QLatin1Char('0') && *str <= QLatin1Char('9')) ||
501
 
           *str == QLatin1Char('-') || *str == QLatin1Char('+') ||
502
 
           *str == QLatin1Char('.')) {
503
 
 
504
 
        points.append(::toDouble(str));
505
 
 
506
 
        while (*str == QLatin1Char(' '))
507
 
            ++str;
508
 
        if (*str == QLatin1Char(','))
509
 
            ++str;
510
 
 
511
 
        //eat the rest of space
512
 
        while (*str == QLatin1Char(' '))
513
 
            ++str;
514
 
    }
515
 
 
516
 
    return points;
 
499
        QVector<qreal> points;
 
500
        if (!str)
 
501
                return points;
 
502
        points.reserve(32);
 
503
 
 
504
        while (*str == QLatin1Char(' ')) {
 
505
                ++str;
 
506
        }
 
507
        while ((*str >= QLatin1Char('0') && *str <= QLatin1Char('9')) ||
 
508
                   *str == QLatin1Char('-') || *str == QLatin1Char('+') ||
 
509
                   *str == QLatin1Char('.')) {
 
510
 
 
511
                points.append(::toDouble(str));
 
512
 
 
513
                while (*str == QLatin1Char(' ')) {
 
514
                        ++str;
 
515
                }
 
516
                if (*str == QLatin1Char(',')) {
 
517
                        ++str;
 
518
                }
 
519
 
 
520
                //eat the rest of space
 
521
                while (*str == QLatin1Char(' ')) {
 
522
                        ++str;
 
523
                }
 
524
        }
 
525
 
 
526
        return points;
517
527
}
518
528
 
519
529
static QMatrix parseTransformationMatrix(const QString &value)
520
530
{
521
 
    QMatrix matrix;
522
 
    const QChar *str = value.constData();
523
 
 
524
 
    while (*str != QLatin1Char(0)) {
525
 
        if (str->isSpace() || *str == QLatin1Char(',')) {
526
 
            ++str;
527
 
            continue;
528
 
        }
529
 
        enum State {
530
 
            Matrix,
531
 
            Translate,
532
 
            Rotate,
533
 
            Scale,
534
 
            SkewX,
535
 
            SkewY
536
 
        };
537
 
        State state = Matrix;
538
 
        if (*str == QLatin1Char('m')) {  //matrix
539
 
            const char *ident = "atrix";
540
 
            for (int i = 0; i < 5; ++i)
541
 
                if (*(++str) != QLatin1Char(ident[i]))
542
 
                    goto error;
543
 
            ++str;
544
 
            state = Matrix;
545
 
        } else if (*str == QLatin1Char('t')) { //translate
546
 
            const char *ident = "ranslate";
547
 
            for (int i = 0; i < 8; ++i)
548
 
                if (*(++str) != QLatin1Char(ident[i]))
549
 
                    goto error;
550
 
            ++str;
551
 
            state = Translate;
552
 
        } else if (*str == QLatin1Char('r')) { //rotate
553
 
            const char *ident = "otate";
554
 
            for (int i = 0; i < 5; ++i)
555
 
                if (*(++str) != QLatin1Char(ident[i]))
556
 
                    goto error;
557
 
            ++str;
558
 
            state = Rotate;
559
 
        } else if (*str == QLatin1Char('s')) { //scale, skewX, skewY
560
 
            ++str;
561
 
            if (*str == QLatin1Char('c')) {
562
 
                const char *ident = "ale";
563
 
                for (int i = 0; i < 3; ++i)
564
 
                    if (*(++str) != QLatin1Char(ident[i]))
565
 
                        goto error;
566
 
                ++str;
567
 
                state = Scale;
568
 
            } else if (*str == QLatin1Char('k')) {
569
 
                if (*(++str) != QLatin1Char('e'))
570
 
                    goto error;
571
 
                if (*(++str) != QLatin1Char('w'))
572
 
                    goto error;
573
 
                ++str;
574
 
                if (*str == QLatin1Char('X'))
575
 
                    state = SkewX;
576
 
                else if (*str == QLatin1Char('Y'))
577
 
                    state = SkewY;
578
 
                else
579
 
                    goto error;
580
 
                ++str;
581
 
            } else {
582
 
                goto error;
583
 
            }
584
 
        } else {
585
 
            goto error;
586
 
        }
587
 
 
588
 
 
589
 
        while (str->isSpace())
590
 
            ++str;
591
 
        if (*str != QLatin1Char('('))
592
 
            goto error;
593
 
        ++str;
594
 
        QVector<qreal> points = parseNumbersList(str);
595
 
        if (*str != QLatin1Char(')'))
596
 
            goto error;
597
 
        ++str;
598
 
 
599
 
        if(state == Matrix) {
600
 
            if(points.count() != 6)
601
 
                goto error;
602
 
            matrix = matrix * QMatrix(points[0], points[1],
603
 
                                      points[2], points[3],
604
 
                                      points[4], points[5]);
605
 
        } else if (state == Translate) {
606
 
            if (points.count() == 1)
607
 
                matrix.translate(points[0], 0);
608
 
            else if (points.count() == 2)
609
 
                matrix.translate(points[0], points[1]);
610
 
            else
611
 
                goto error;
612
 
        } else if (state == Rotate) {
613
 
            if(points.count() == 1) {
614
 
                matrix.rotate(points[0]);
615
 
            } else if (points.count() == 3) {
616
 
                matrix.translate(points[1], points[2]);
617
 
                matrix.rotate(points[0]);
618
 
                matrix.translate(-points[1], -points[2]);
619
 
            } else {
620
 
                goto error;
621
 
            }
622
 
        } else if (state == Scale) {
623
 
            if (points.count() < 1 || points.count() > 2)
624
 
                goto error;
625
 
            qreal sx = points[0];
626
 
            qreal sy = sx;
627
 
            if(points.count() == 2)
628
 
                sy = points[1];
629
 
            matrix.scale(sx, sy);
630
 
        } else if (state == SkewX) {
631
 
            if (points.count() != 1)
632
 
                goto error;
633
 
            const qreal deg2rad = qreal(0.017453292519943295769);
634
 
            matrix.shear(tan(points[0]*deg2rad), 0);
635
 
        } else if (state == SkewY) {
636
 
            if (points.count() != 1)
637
 
                goto error;
638
 
            const qreal deg2rad = qreal(0.017453292519943295769);
639
 
            matrix.shear(0, tan(points[0]*deg2rad));
640
 
        }
641
 
    }
 
531
        QMatrix matrix;
 
532
        const QChar *str = value.constData();
 
533
 
 
534
        while (*str != QLatin1Char(0)) {
 
535
                if (str->isSpace() || *str == QLatin1Char(',')) {
 
536
                        ++str;
 
537
                        continue;
 
538
                }
 
539
                enum State {
 
540
                        Matrix,
 
541
                        Translate,
 
542
                        Rotate,
 
543
                        Scale,
 
544
                        SkewX,
 
545
                        SkewY
 
546
                };
 
547
                State state = Matrix;
 
548
                if (*str == QLatin1Char('m')) {  //matrix
 
549
                        const char *ident = "atrix";
 
550
                        for (int i = 0; i < 5; ++i) {
 
551
                                if (*(++str) != QLatin1Char(ident[i])) {
 
552
                                        goto error;
 
553
                                }
 
554
                        }
 
555
                        ++str;
 
556
                        state = Matrix;
 
557
                }
 
558
                else if (*str == QLatin1Char('t')) { //translate
 
559
                        const char *ident = "ranslate";
 
560
                        for (int i = 0; i < 8; ++i)
 
561
                                if (*(++str) != QLatin1Char(ident[i]))
 
562
                                        goto error;
 
563
                        ++str;
 
564
                        state = Translate;
 
565
                }
 
566
                else if (*str == QLatin1Char('r')) { //rotate
 
567
                        const char *ident = "otate";
 
568
                        for (int i = 0; i < 5; ++i)
 
569
                                if (*(++str) != QLatin1Char(ident[i]))
 
570
                                        goto error;
 
571
                        ++str;
 
572
                        state = Rotate;
 
573
                }
 
574
                else if (*str == QLatin1Char('s')) { //scale, skewX, skewY
 
575
                        ++str;
 
576
                        if (*str == QLatin1Char('c')) {
 
577
                                const char *ident = "ale";
 
578
                                for (int i = 0; i < 3; ++i)
 
579
                                        if (*(++str) != QLatin1Char(ident[i]))
 
580
                                                goto error;
 
581
                                ++str;
 
582
                                state = Scale;
 
583
                        } else if (*str == QLatin1Char('k')) {
 
584
                                if (*(++str) != QLatin1Char('e'))
 
585
                                        goto error;
 
586
                                if (*(++str) != QLatin1Char('w'))
 
587
                                        goto error;
 
588
                                ++str;
 
589
                                if (*str == QLatin1Char('X'))
 
590
                                        state = SkewX;
 
591
                                else if (*str == QLatin1Char('Y'))
 
592
                                        state = SkewY;
 
593
                                else
 
594
                                        goto error;
 
595
                                ++str;
 
596
                        } else {
 
597
                                goto error;
 
598
                        }
 
599
                }
 
600
                else {
 
601
                        goto error;
 
602
                }
 
603
 
 
604
 
 
605
                while (str->isSpace()) {
 
606
                        ++str;
 
607
                }
 
608
                if (*str != QLatin1Char('(')) {
 
609
                        goto error;
 
610
                }
 
611
                ++str;
 
612
                QVector<qreal> points = parseNumbersList(str);
 
613
                if (*str != QLatin1Char(')')) {
 
614
                        goto error;
 
615
                }
 
616
                ++str;
 
617
 
 
618
                if(state == Matrix) {
 
619
                        if(points.count() != 6) {
 
620
                                goto error;
 
621
                        }
 
622
                        matrix = matrix * QMatrix(points[0], points[1],
 
623
                                                                          points[2], points[3],
 
624
                                                                          points[4], points[5]);
 
625
                }
 
626
                else if (state == Translate) {
 
627
                        if (points.count() == 1)
 
628
                                matrix.translate(points[0], 0);
 
629
                        else if (points.count() == 2)
 
630
                                matrix.translate(points[0], points[1]);
 
631
                        else
 
632
                                goto error;
 
633
                }
 
634
                else if (state == Rotate) {
 
635
                        if(points.count() == 1) {
 
636
                                matrix.rotate(points[0]);
 
637
                        } else if (points.count() == 3) {
 
638
                                matrix.translate(points[1], points[2]);
 
639
                                matrix.rotate(points[0]);
 
640
                                matrix.translate(-points[1], -points[2]);
 
641
                        } else {
 
642
                                goto error;
 
643
                        }
 
644
                }
 
645
                else if (state == Scale) {
 
646
                        if (points.count() < 1 || points.count() > 2)
 
647
                                goto error;
 
648
                        qreal sx = points[0];
 
649
                        qreal sy = sx;
 
650
                        if(points.count() == 2)
 
651
                                sy = points[1];
 
652
                        matrix.scale(sx, sy);
 
653
                }
 
654
                else if (state == SkewX) {
 
655
                        if (points.count() != 1)
 
656
                                goto error;
 
657
                        const qreal deg2rad = qreal(0.017453292519943295769);
 
658
                        matrix.shear(tan(points[0]*deg2rad), 0);
 
659
                }
 
660
                else if (state == SkewY) {
 
661
                        if (points.count() != 1)
 
662
                                goto error;
 
663
                        const qreal deg2rad = qreal(0.017453292519943295769);
 
664
                        matrix.shear(0, tan(points[0]*deg2rad));
 
665
                }
 
666
        }
642
667
  error:
643
 
    return matrix;
 
668
        return matrix;
644
669
}