Chris@127
|
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
|
Chris@127
|
2
|
Chris@127
|
3 /*
|
Chris@127
|
4 Sonic Visualiser
|
Chris@127
|
5 An audio file viewer and annotation editor.
|
Chris@127
|
6 Centre for Digital Music, Queen Mary, University of London.
|
Chris@182
|
7 This file copyright 2006 Chris Cannam and QMUL.
|
Chris@127
|
8
|
Chris@127
|
9 This program is free software; you can redistribute it and/or
|
Chris@127
|
10 modify it under the terms of the GNU General Public License as
|
Chris@127
|
11 published by the Free Software Foundation; either version 2 of the
|
Chris@127
|
12 License, or (at your option) any later version. See the file
|
Chris@127
|
13 COPYING included with this distribution for more information.
|
Chris@127
|
14 */
|
Chris@127
|
15
|
Chris@127
|
16 #include "Layer.h"
|
Chris@128
|
17 #include "view/View.h"
|
Chris@128
|
18 #include "data/model/Model.h"
|
Chris@268
|
19 #include "base/CommandHistory.h"
|
Chris@127
|
20
|
Chris@127
|
21 #include <iostream>
|
Chris@127
|
22
|
Chris@131
|
23 #include <QMutexLocker>
|
Chris@267
|
24 #include <QMouseEvent>
|
Chris@131
|
25
|
Chris@131
|
26 #include "LayerFactory.h"
|
Chris@128
|
27 #include "base/PlayParameterRepository.h"
|
Chris@127
|
28
|
Chris@272
|
29 #include <cmath>
|
Chris@272
|
30
|
Chris@267
|
31 Layer::Layer() :
|
Chris@267
|
32 m_haveDraggingRect(false)
|
Chris@127
|
33 {
|
Chris@127
|
34 }
|
Chris@127
|
35
|
Chris@127
|
36 Layer::~Layer()
|
Chris@127
|
37 {
|
Chris@127
|
38 // std::cerr << "Layer::~Layer(" << this << ")" << std::endl;
|
Chris@127
|
39 }
|
Chris@127
|
40
|
Chris@127
|
41 QString
|
Chris@127
|
42 Layer::getPropertyContainerIconName() const
|
Chris@127
|
43 {
|
Chris@127
|
44 return LayerFactory::getInstance()->getLayerIconName
|
Chris@127
|
45 (LayerFactory::getInstance()->getLayerType(this));
|
Chris@127
|
46 }
|
Chris@127
|
47
|
Chris@127
|
48 QString
|
Chris@127
|
49 Layer::getLayerPresentationName() const
|
Chris@127
|
50 {
|
Chris@203
|
51 // QString layerName = objectName();
|
Chris@203
|
52
|
Chris@203
|
53 LayerFactory *factory = LayerFactory::getInstance();
|
Chris@203
|
54 QString layerName = factory->getLayerPresentationName
|
Chris@203
|
55 (factory->getLayerType(this));
|
Chris@203
|
56
|
Chris@127
|
57 QString modelName;
|
Chris@127
|
58 if (getModel()) modelName = getModel()->objectName();
|
Chris@127
|
59
|
Chris@127
|
60 QString text;
|
Chris@127
|
61 if (modelName != "") {
|
Chris@127
|
62 text = QString("%1: %2").arg(modelName).arg(layerName);
|
Chris@127
|
63 } else {
|
Chris@127
|
64 text = layerName;
|
Chris@127
|
65 }
|
Chris@127
|
66
|
Chris@127
|
67 return text;
|
Chris@127
|
68 }
|
Chris@127
|
69
|
Chris@127
|
70 void
|
Chris@127
|
71 Layer::setObjectName(const QString &name)
|
Chris@127
|
72 {
|
Chris@127
|
73 QObject::setObjectName(name);
|
Chris@127
|
74 emit layerNameChanged();
|
Chris@127
|
75 }
|
Chris@127
|
76
|
Chris@127
|
77 PlayParameters *
|
Chris@127
|
78 Layer::getPlayParameters()
|
Chris@127
|
79 {
|
Chris@127
|
80 // std::cerr << "Layer (" << this << ", " << objectName().toStdString() << ")::getPlayParameters: model is "<< getModel() << std::endl;
|
Chris@127
|
81 const Model *model = getModel();
|
Chris@127
|
82 if (model) {
|
Chris@127
|
83 return PlayParameterRepository::getInstance()->getPlayParameters(model);
|
Chris@127
|
84 }
|
Chris@127
|
85 return 0;
|
Chris@127
|
86 }
|
Chris@127
|
87
|
Chris@127
|
88 void
|
Chris@131
|
89 Layer::setLayerDormant(const View *v, bool dormant)
|
Chris@131
|
90 {
|
Chris@131
|
91 const void *vv = (const void *)v;
|
Chris@131
|
92 QMutexLocker locker(&m_dormancyMutex);
|
Chris@131
|
93 m_dormancy[vv] = dormant;
|
Chris@131
|
94 }
|
Chris@131
|
95
|
Chris@131
|
96 bool
|
Chris@131
|
97 Layer::isLayerDormant(const View *v) const
|
Chris@131
|
98 {
|
Chris@131
|
99 const void *vv = (const void *)v;
|
Chris@131
|
100 QMutexLocker locker(&m_dormancyMutex);
|
Chris@131
|
101 if (m_dormancy.find(vv) == m_dormancy.end()) return false;
|
Chris@131
|
102 return m_dormancy.find(vv)->second;
|
Chris@131
|
103 }
|
Chris@131
|
104
|
Chris@131
|
105 void
|
Chris@127
|
106 Layer::showLayer(View *view, bool show)
|
Chris@127
|
107 {
|
Chris@127
|
108 setLayerDormant(view, !show);
|
Chris@127
|
109 emit layerParametersChanged();
|
Chris@127
|
110 }
|
Chris@127
|
111
|
Chris@260
|
112 bool
|
Chris@267
|
113 Layer::getXScaleValue(const View *v, int x, float &value, QString &unit) const
|
Chris@260
|
114 {
|
Chris@260
|
115 if (!hasTimeXAxis()) return false;
|
Chris@260
|
116
|
Chris@260
|
117 const Model *m = getModel();
|
Chris@260
|
118 if (!m) return false;
|
Chris@260
|
119
|
Chris@260
|
120 value = float(v->getFrameForX(x)) / m->getSampleRate();
|
Chris@260
|
121 unit = "s";
|
Chris@260
|
122 return true;
|
Chris@260
|
123 }
|
Chris@260
|
124
|
Chris@268
|
125 bool
|
Chris@268
|
126 Layer::MeasureRect::operator<(const MeasureRect &mr) const
|
Chris@268
|
127 {
|
Chris@268
|
128 if (haveFrames) {
|
Chris@268
|
129 if (startFrame == mr.startFrame) {
|
Chris@268
|
130 if (endFrame != mr.endFrame) {
|
Chris@268
|
131 return endFrame < mr.endFrame;
|
Chris@268
|
132 }
|
Chris@268
|
133 } else {
|
Chris@268
|
134 return startFrame < mr.startFrame;
|
Chris@268
|
135 }
|
Chris@268
|
136 } else {
|
Chris@268
|
137 if (pixrect.x() == mr.pixrect.x()) {
|
Chris@268
|
138 if (pixrect.width() != mr.pixrect.width()) {
|
Chris@268
|
139 return pixrect.width() < mr.pixrect.width();
|
Chris@268
|
140 }
|
Chris@268
|
141 } else {
|
Chris@268
|
142 return pixrect.x() < mr.pixrect.x();
|
Chris@268
|
143 }
|
Chris@268
|
144 }
|
Chris@268
|
145
|
Chris@268
|
146 // the two rects are equal in x and width
|
Chris@268
|
147
|
Chris@268
|
148 if (pixrect.y() == mr.pixrect.y()) {
|
Chris@268
|
149 return pixrect.height() < mr.pixrect.height();
|
Chris@268
|
150 } else {
|
Chris@268
|
151 return pixrect.y() < mr.pixrect.y();
|
Chris@268
|
152 }
|
Chris@268
|
153 }
|
Chris@268
|
154
|
Chris@268
|
155 QString
|
Chris@269
|
156 Layer::MeasureRect::toXmlString(QString indent) const
|
Chris@269
|
157 {
|
Chris@269
|
158 QString s;
|
Chris@269
|
159
|
Chris@269
|
160 s += indent;
|
Chris@269
|
161 s += QString("<measurement ");
|
Chris@269
|
162
|
Chris@269
|
163 if (haveFrames) {
|
Chris@269
|
164 s += QString("startFrame=\"%1\" endFrame=\"%2\" ")
|
Chris@269
|
165 .arg(startFrame).arg(endFrame);
|
Chris@269
|
166 } else {
|
Chris@269
|
167 s += QString("startX=\"%1\" endX=\"%2\" ")
|
Chris@269
|
168 .arg(pixrect.x()).arg(pixrect.x() + pixrect.width());
|
Chris@269
|
169 }
|
Chris@269
|
170
|
Chris@269
|
171 s += QString("startY=\"%1\" endY=\"%2\"/>\n")
|
Chris@273
|
172 .arg(startY).arg(endY);
|
Chris@269
|
173
|
Chris@269
|
174 return s;
|
Chris@269
|
175 }
|
Chris@269
|
176
|
Chris@269
|
177 void
|
Chris@269
|
178 Layer::addMeasurementRect(const QXmlAttributes &attributes)
|
Chris@269
|
179 {
|
Chris@269
|
180 MeasureRect rect;
|
Chris@269
|
181 QString fs = attributes.value("startFrame");
|
Chris@273
|
182 int x0 = 0, x1 = 0;
|
Chris@269
|
183 if (fs != "") {
|
Chris@269
|
184 rect.startFrame = fs.toLong();
|
Chris@269
|
185 rect.endFrame = attributes.value("endFrame").toLong();
|
Chris@269
|
186 rect.haveFrames = true;
|
Chris@269
|
187 } else {
|
Chris@269
|
188 x0 = attributes.value("startX").toInt();
|
Chris@269
|
189 x1 = attributes.value("endX").toInt();
|
Chris@269
|
190 rect.haveFrames = false;
|
Chris@269
|
191 }
|
Chris@273
|
192 rect.startY = attributes.value("startY").toDouble();
|
Chris@273
|
193 rect.endY = attributes.value("endY").toDouble();
|
Chris@273
|
194 rect.pixrect = QRect(x0, 0, x1 - x0, 0);
|
Chris@269
|
195 addMeasureRectToSet(rect);
|
Chris@269
|
196 }
|
Chris@269
|
197
|
Chris@269
|
198 QString
|
Chris@268
|
199 Layer::AddMeasurementRectCommand::getName() const
|
Chris@268
|
200 {
|
Chris@268
|
201 return tr("Make Measurement");
|
Chris@268
|
202 }
|
Chris@268
|
203
|
Chris@268
|
204 void
|
Chris@268
|
205 Layer::AddMeasurementRectCommand::execute()
|
Chris@268
|
206 {
|
Chris@269
|
207 m_layer->addMeasureRectToSet(m_rect);
|
Chris@268
|
208 }
|
Chris@268
|
209
|
Chris@268
|
210 void
|
Chris@268
|
211 Layer::AddMeasurementRectCommand::unexecute()
|
Chris@268
|
212 {
|
Chris@269
|
213 m_layer->deleteMeasureRectFromSet(m_rect);
|
Chris@268
|
214 }
|
Chris@268
|
215
|
Chris@267
|
216 void
|
Chris@267
|
217 Layer::measureStart(View *v, QMouseEvent *e)
|
Chris@267
|
218 {
|
Chris@267
|
219 m_draggingRect.pixrect = QRect(e->x(), e->y(), 0, 0);
|
Chris@267
|
220 if (hasTimeXAxis()) {
|
Chris@268
|
221 m_draggingRect.haveFrames = true;
|
Chris@267
|
222 m_draggingRect.startFrame = v->getFrameForX(e->x());
|
Chris@267
|
223 m_draggingRect.endFrame = m_draggingRect.startFrame;
|
Chris@268
|
224 } else {
|
Chris@268
|
225 m_draggingRect.haveFrames = false;
|
Chris@267
|
226 }
|
Chris@273
|
227 setMeasureRectYCoord(v, m_draggingRect, true, e->y());
|
Chris@267
|
228 m_haveDraggingRect = true;
|
Chris@267
|
229 }
|
Chris@267
|
230
|
Chris@267
|
231 void
|
Chris@267
|
232 Layer::measureDrag(View *v, QMouseEvent *e)
|
Chris@267
|
233 {
|
Chris@267
|
234 if (!m_haveDraggingRect) return;
|
Chris@268
|
235
|
Chris@267
|
236 m_draggingRect.pixrect = QRect(m_draggingRect.pixrect.x(),
|
Chris@267
|
237 m_draggingRect.pixrect.y(),
|
Chris@267
|
238 e->x() - m_draggingRect.pixrect.x(),
|
Chris@268
|
239 e->y() - m_draggingRect.pixrect.y())
|
Chris@268
|
240 .normalized();
|
Chris@268
|
241
|
Chris@273
|
242 setMeasureRectYCoord(v, m_draggingRect, false, e->y());
|
Chris@273
|
243
|
Chris@267
|
244 if (hasTimeXAxis()) {
|
Chris@267
|
245 m_draggingRect.endFrame = v->getFrameForX(e->x());
|
Chris@267
|
246 }
|
Chris@267
|
247 }
|
Chris@267
|
248
|
Chris@267
|
249 void
|
Chris@267
|
250 Layer::measureEnd(View *v, QMouseEvent *e)
|
Chris@267
|
251 {
|
Chris@267
|
252 if (!m_haveDraggingRect) return;
|
Chris@267
|
253 measureDrag(v, e);
|
Chris@268
|
254
|
Chris@268
|
255 CommandHistory::getInstance()->addCommand
|
Chris@268
|
256 (new AddMeasurementRectCommand(this, m_draggingRect));
|
Chris@268
|
257
|
Chris@267
|
258 m_haveDraggingRect = false;
|
Chris@267
|
259 }
|
Chris@267
|
260
|
Chris@267
|
261 void
|
Chris@272
|
262 Layer::paintMeasurementRects(View *v, QPainter &paint,
|
Chris@272
|
263 bool showFocus, QPoint focusPoint) const
|
Chris@267
|
264 {
|
Chris@273
|
265 updateMeasurePixrects(v);
|
Chris@272
|
266
|
Chris@272
|
267 MeasureRectSet::const_iterator focusRectItr = m_measureRects.end();
|
Chris@272
|
268
|
Chris@267
|
269 if (m_haveDraggingRect) {
|
Chris@272
|
270
|
Chris@270
|
271 paintMeasurementRect(v, paint, m_draggingRect, true);
|
Chris@272
|
272
|
Chris@272
|
273 } else if (showFocus) {
|
Chris@272
|
274
|
Chris@272
|
275 focusRectItr = findFocusedMeasureRect(focusPoint);
|
Chris@267
|
276 }
|
Chris@267
|
277
|
Chris@268
|
278 for (MeasureRectSet::const_iterator i = m_measureRects.begin();
|
Chris@268
|
279 i != m_measureRects.end(); ++i) {
|
Chris@272
|
280 paintMeasurementRect(v, paint, *i, i == focusRectItr);
|
Chris@267
|
281 }
|
Chris@267
|
282 }
|
Chris@267
|
283
|
Chris@272
|
284 bool
|
Chris@272
|
285 Layer::nearestMeasurementRectChanged(View *v, QPoint prev, QPoint now) const
|
Chris@272
|
286 {
|
Chris@273
|
287 updateMeasurePixrects(v);
|
Chris@272
|
288
|
Chris@272
|
289 MeasureRectSet::const_iterator i0 = findFocusedMeasureRect(prev);
|
Chris@272
|
290 MeasureRectSet::const_iterator i1 = findFocusedMeasureRect(now);
|
Chris@272
|
291
|
Chris@272
|
292 return (i0 != i1);
|
Chris@272
|
293 }
|
Chris@272
|
294
|
Chris@272
|
295 void
|
Chris@273
|
296 Layer::updateMeasurePixrects(View *v) const
|
Chris@272
|
297 {
|
Chris@272
|
298 long sf = v->getStartFrame();
|
Chris@272
|
299 long ef = v->getEndFrame();
|
Chris@272
|
300
|
Chris@272
|
301 for (MeasureRectSet::const_iterator i = m_measureRects.begin();
|
Chris@272
|
302 i != m_measureRects.end(); ++i) {
|
Chris@272
|
303
|
Chris@273
|
304 // This logic depends on the fact that if one measure rect in
|
Chris@273
|
305 // a layer has frame values, they all will. That is in fact
|
Chris@273
|
306 // the case, because haveFrames is based on whether the layer
|
Chris@273
|
307 // hasTimeXAxis() or not. Measure rect ordering in the rect
|
Chris@273
|
308 // set wouldn't work correctly either, if haveFrames could
|
Chris@273
|
309 // vary.
|
Chris@272
|
310
|
Chris@273
|
311 if (i->haveFrames) {
|
Chris@273
|
312 if (i->startFrame >= ef) break;
|
Chris@273
|
313 if (i->endFrame <= sf) continue;
|
Chris@273
|
314 }
|
Chris@272
|
315
|
Chris@273
|
316 int x0 = i->pixrect.x();
|
Chris@273
|
317 int x1 = x0 + i->pixrect.width();
|
Chris@273
|
318
|
Chris@273
|
319 if (i->haveFrames) {
|
Chris@273
|
320 if (i->startFrame >= v->getStartFrame()) {
|
Chris@273
|
321 x0 = v->getXForFrame(i->startFrame);
|
Chris@273
|
322 }
|
Chris@273
|
323 if (i->endFrame <= long(v->getEndFrame())) {
|
Chris@273
|
324 x1 = v->getXForFrame(i->endFrame);
|
Chris@273
|
325 }
|
Chris@272
|
326 }
|
Chris@272
|
327
|
Chris@273
|
328 i->pixrect = QRect(x0, i->pixrect.y(), x1 - x0, i->pixrect.height());
|
Chris@273
|
329
|
Chris@273
|
330 updateMeasureRectYCoords(v, *i);
|
Chris@272
|
331
|
Chris@273
|
332 i->pixrect = i->pixrect.normalized();
|
Chris@273
|
333 }
|
Chris@273
|
334 }
|
Chris@273
|
335
|
Chris@273
|
336 void
|
Chris@273
|
337 Layer::updateMeasureRectYCoords(View *v, const MeasureRect &r) const
|
Chris@273
|
338 {
|
Chris@273
|
339 int y0 = lrint(r.startY * v->height());
|
Chris@273
|
340 int y1 = lrint(r.endY * v->height());
|
Chris@273
|
341 r.pixrect = QRect(r.pixrect.x(), y0, r.pixrect.width(), y1 - y0);
|
Chris@273
|
342 }
|
Chris@273
|
343
|
Chris@273
|
344 void
|
Chris@273
|
345 Layer::setMeasureRectYCoord(View *v, MeasureRect &r, bool start, int y) const
|
Chris@273
|
346 {
|
Chris@273
|
347 if (start) {
|
Chris@273
|
348 r.startY = double(y) / double(v->height());
|
Chris@273
|
349 r.endY = r.startY;
|
Chris@273
|
350 } else {
|
Chris@273
|
351 r.endY = double(y) / double(v->height());
|
Chris@272
|
352 }
|
Chris@272
|
353 }
|
Chris@272
|
354
|
Chris@272
|
355 Layer::MeasureRectSet::const_iterator
|
Chris@272
|
356 Layer::findFocusedMeasureRect(QPoint focusPoint) const
|
Chris@272
|
357 {
|
Chris@272
|
358 float frDist = 0;
|
Chris@272
|
359 MeasureRectSet::const_iterator focusRectItr = m_measureRects.end();
|
Chris@272
|
360
|
Chris@272
|
361 for (MeasureRectSet::const_iterator i = m_measureRects.begin();
|
Chris@272
|
362 i != m_measureRects.end(); ++i) {
|
Chris@272
|
363
|
Chris@272
|
364 if (!i->pixrect.adjusted(-2, -2, 2, 2).contains(focusPoint)) continue;
|
Chris@272
|
365
|
Chris@272
|
366 int cx = i->pixrect.x() + i->pixrect.width()/2;
|
Chris@272
|
367 int cy = i->pixrect.y() + i->pixrect.height()/2;
|
Chris@272
|
368 int xd = focusPoint.x() - cx;
|
Chris@272
|
369 int yd = focusPoint.y() - cy;
|
Chris@272
|
370
|
Chris@272
|
371 float d = sqrt(xd * xd + yd * yd);
|
Chris@272
|
372
|
Chris@272
|
373 if (focusRectItr == m_measureRects.end() || d < frDist) {
|
Chris@272
|
374 focusRectItr = i;
|
Chris@272
|
375 frDist = d;
|
Chris@272
|
376 }
|
Chris@272
|
377 }
|
Chris@272
|
378
|
Chris@272
|
379 return focusRectItr;
|
Chris@272
|
380 }
|
Chris@272
|
381
|
Chris@268
|
382 void
|
Chris@270
|
383 Layer::paintMeasurementRect(View *v, QPainter &paint,
|
Chris@270
|
384 const MeasureRect &r, bool focus) const
|
Chris@268
|
385 {
|
Chris@268
|
386 if (r.haveFrames) {
|
Chris@268
|
387
|
Chris@268
|
388 int x0 = -1;
|
Chris@268
|
389 int x1 = v->width() + 1;
|
Chris@268
|
390
|
Chris@268
|
391 if (r.startFrame >= v->getStartFrame()) {
|
Chris@268
|
392 x0 = v->getXForFrame(r.startFrame);
|
Chris@268
|
393 }
|
Chris@272
|
394 if (r.endFrame <= long(v->getEndFrame())) {
|
Chris@268
|
395 x1 = v->getXForFrame(r.endFrame);
|
Chris@268
|
396 }
|
Chris@268
|
397
|
Chris@272
|
398 QRect pr = QRect(x0, r.pixrect.y(), x1 - x0, r.pixrect.height());
|
Chris@268
|
399
|
Chris@268
|
400 r.pixrect = pr;
|
Chris@268
|
401 }
|
Chris@268
|
402
|
Chris@270
|
403 v->drawMeasurementRect(paint, this, r.pixrect, focus);
|
Chris@268
|
404 }
|
Chris@268
|
405
|
Chris@268
|
406 QString
|
Chris@268
|
407 Layer::toXmlString(QString indent, QString extraAttributes) const
|
Chris@268
|
408 {
|
Chris@268
|
409 QString s;
|
Chris@268
|
410
|
Chris@268
|
411 s += indent;
|
Chris@268
|
412
|
Chris@269
|
413 s += QString("<layer id=\"%2\" type=\"%1\" name=\"%3\" model=\"%4\" %5")
|
Chris@268
|
414 .arg(encodeEntities(LayerFactory::getInstance()->getLayerTypeName
|
Chris@268
|
415 (LayerFactory::getInstance()->getLayerType(this))))
|
Chris@268
|
416 .arg(getObjectExportId(this))
|
Chris@268
|
417 .arg(encodeEntities(objectName()))
|
Chris@268
|
418 .arg(getObjectExportId(getModel()))
|
Chris@268
|
419 .arg(extraAttributes);
|
Chris@268
|
420
|
Chris@269
|
421 if (m_measureRects.empty()) {
|
Chris@269
|
422 s += QString("/>\n");
|
Chris@269
|
423 return s;
|
Chris@269
|
424 }
|
Chris@269
|
425
|
Chris@269
|
426 s += QString(">\n");
|
Chris@269
|
427
|
Chris@269
|
428 for (MeasureRectSet::const_iterator i = m_measureRects.begin();
|
Chris@269
|
429 i != m_measureRects.end(); ++i) {
|
Chris@269
|
430 s += i->toXmlString(indent + " ");
|
Chris@269
|
431 }
|
Chris@269
|
432
|
Chris@269
|
433 s += QString("</layer>\n");
|
Chris@269
|
434
|
Chris@268
|
435 return s;
|
Chris@268
|
436 }
|
Chris@269
|
437
|
Chris@269
|
438 QString
|
Chris@269
|
439 Layer::toBriefXmlString(QString indent, QString extraAttributes) const
|
Chris@269
|
440 {
|
Chris@269
|
441 QString s;
|
Chris@269
|
442
|
Chris@269
|
443 s += indent;
|
Chris@269
|
444
|
Chris@269
|
445 s += QString("<layer id=\"%2\" type=\"%1\" name=\"%3\" model=\"%4\" %5/>\n")
|
Chris@269
|
446 .arg(encodeEntities(LayerFactory::getInstance()->getLayerTypeName
|
Chris@269
|
447 (LayerFactory::getInstance()->getLayerType(this))))
|
Chris@269
|
448 .arg(getObjectExportId(this))
|
Chris@269
|
449 .arg(encodeEntities(objectName()))
|
Chris@269
|
450 .arg(getObjectExportId(getModel()))
|
Chris@269
|
451 .arg(extraAttributes);
|
Chris@269
|
452
|
Chris@269
|
453 return s;
|
Chris@269
|
454 }
|
Chris@269
|
455
|