~ubuntu-branches/ubuntu/saucy/merkaartor/saucy

« back to all changes in this revision

Viewing changes to src/TagTemplate/TagTemplate.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Bernd Zeimetz
  • Date: 2009-09-13 00:52:12 UTC
  • mto: (1.2.7 upstream) (0.1.3 upstream) (3.1.7 sid)
  • mto: This revision was merged to the branch mainline in revision 10.
  • Revision ID: james.westby@ubuntu.com-20090913005212-pjecal8zxm07x0fj
ImportĀ upstreamĀ versionĀ 0.14+svnfixes~20090912

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//
 
2
// C++ Implementation: TagTemplate
 
3
//
 
4
// Description:
 
5
//
 
6
//
 
7
// Author: Chris Browet <cbro@semperpax.com>, (C) 2008
 
8
//
 
9
// Copyright: See COPYING file that comes with this distribution
 
10
//
 
11
//
 
12
 
 
13
#include "TagTemplate.h"
 
14
 
 
15
#include "Maps/MapFeature.h"
 
16
#include "Maps/TrackPoint.h"
 
17
#include "Maps/Relation.h"
 
18
#include "Maps/Road.h"
 
19
#include "Command/FeatureCommands.h"
 
20
 
 
21
#include <QComboBox>
 
22
#include <QLabel>
 
23
#include <QCheckBox>
 
24
#include <QGroupBox>
 
25
#include <QLineEdit>
 
26
#include <QRegExp> 
 
27
 
 
28
/** TagTemplateWidget **/
 
29
 
 
30
TagTemplateWidget::TagTemplateWidget()
 
31
        : theMainWidget(0), theWidget(0), theLabelWidget(0), theSelector(0)
 
32
{
 
33
}
 
34
 
 
35
TagTemplateWidget::~TagTemplateWidget()
 
36
{
 
37
        // No need to delete; will be destroyed automatically by parent + crash if no active widget.
 
38
        // delete theMainWidget;   
 
39
        for (int i=0; i<theValues.size(); ++i)
 
40
                delete theValues[i];
 
41
        delete theSelector;
 
42
}
 
43
 
 
44
TagTemplateWidget* TagTemplateWidget::fromXml(const QDomElement& e)
 
45
{
 
46
        if (e.tagName() != "widget") {
 
47
                return NULL;
 
48
        }
 
49
 
 
50
        TagTemplateWidget* aTW = NULL;
 
51
        if (e.attribute("type") == "combo") {
 
52
                aTW = TagTemplateWidgetCombo::fromXml(e);
 
53
        } else
 
54
        if (e.attribute("type") == "yesno") {
 
55
                aTW = TagTemplateWidgetYesno::fromXml(e);
 
56
        } else
 
57
        if (e.attribute("type") == "constant") {
 
58
                aTW = TagTemplateWidgetConstant::fromXml(e);
 
59
        } else
 
60
        if (e.attribute("type") == "edit") {
 
61
                aTW = TagTemplateWidgetEdit::fromXml(e);
 
62
        } else
 
63
                Q_ASSERT(false);
 
64
 
 
65
        if (aTW) {
 
66
                aTW->theId = e.attribute("id");
 
67
                aTW->theType = e.attribute("type");
 
68
                aTW->theTag = e.attribute("tag");
 
69
        }
 
70
 
 
71
        return aTW;
 
72
}
 
73
 
 
74
void TagTemplateWidget::parseCommonElements(const QDomElement& e)
 
75
{
 
76
        if (e.tagName() == "description") {
 
77
                theDescriptions.insert(e.attribute("locale"), e.firstChild().toText().nodeValue());
 
78
        } else
 
79
        if (e.tagName() == "link") {
 
80
                theUrl = QUrl(e.attribute("src"));
 
81
        } else
 
82
        if (e.tagName() == "selector") {
 
83
                theSelector = TagSelector::parse(e.attribute("expr"));
 
84
        }
 
85
        if (e.tagName() == "value") {
 
86
                TagTemplateWidgetValue* aTCV = TagTemplateWidgetValue::fromXml(e);
 
87
                if (aTCV)
 
88
                        theValues.append(aTCV);
 
89
        }
 
90
}
 
91
 
 
92
void TagTemplateWidget::generateCommonElements(QDomElement& e)
 
93
{
 
94
        if (!theUrl.isEmpty()) {
 
95
                QDomElement c = e.ownerDocument().createElement("link");
 
96
                e.appendChild(c);
 
97
 
 
98
                c.setAttribute("src", theUrl.toString());
 
99
        }
 
100
 
 
101
        QHashIterator<QString, QString > itD(theDescriptions);
 
102
        while(itD.hasNext()) {
 
103
                itD.next();
 
104
 
 
105
                QDomElement d = e.ownerDocument().createElement("description");
 
106
                e.appendChild(d);
 
107
 
 
108
                d.setAttribute("locale", itD.key());
 
109
 
 
110
                QDomText v = e.ownerDocument().createTextNode(itD.value());
 
111
                d.appendChild(v);
 
112
        }
 
113
 
 
114
        if (theSelector) {
 
115
                QDomElement s = e.ownerDocument().createElement("selector");
 
116
                e.appendChild(s);
 
117
                s.setAttribute("expr", theSelector->asExpression(false));
 
118
        }
 
119
 
 
120
        for (int i=0; i<theValues.size(); ++i) {
 
121
                theValues[i]->toXML(e);
 
122
        }
 
123
}
 
124
 
 
125
/** TagTemplateWidgetValue **/
 
126
 
 
127
TagTemplateWidgetValue* TagTemplateWidgetValue::fromXml(const QDomElement& e)
 
128
{
 
129
        TagTemplateWidgetValue* aTCV = new TagTemplateWidgetValue(e.attribute("tag"));
 
130
 
 
131
        for(QDomNode d = e.firstChild(); !d.isNull(); d = d.nextSibling()) {
 
132
                QDomElement c = d.toElement();
 
133
                if (c.isNull())
 
134
                        continue;
 
135
 
 
136
                aTCV->parseCommonElements(c);
 
137
        }
 
138
        return aTCV;
 
139
}
 
140
 
 
141
bool TagTemplateWidgetValue::toXML(QDomElement& xParent)
 
142
{
 
143
        QDomElement v = xParent.ownerDocument().createElement("value");
 
144
        xParent.appendChild(v);
 
145
 
 
146
        v.setAttribute("tag", theTagValue);
 
147
        generateCommonElements(v);
 
148
 
 
149
        return true;
 
150
}
 
151
 
 
152
 
 
153
/** TagTemplateWidgetCombo **/
 
154
 
 
155
TagTemplateWidgetCombo::~TagTemplateWidgetCombo()
 
156
{
 
157
}
 
158
 
 
159
QWidget* TagTemplateWidgetCombo::getWidget(const MapFeature* F)
 
160
{
 
161
        if (theSelector && (theSelector->matches(F) != TagSelect_Match && theSelector->matches(F) != TagSelect_DefaultMatch))
 
162
                return NULL;
 
163
 
 
164
        QString lang = getDefaultLanguage();
 
165
        QString defLang = "en";
 
166
    if (lang == "-" || !M_PREFS->getTranslateTags())
 
167
                lang = "en";
 
168
 
 
169
        theWidget = new QWidget();
 
170
        QHBoxLayout* aLayout = new QHBoxLayout(theWidget);
 
171
        aLayout->setContentsMargins(0, 0, 0, 0);
 
172
 
 
173
        QLabel* aLabel = new QLabel();
 
174
        aLabel->setOpenExternalLinks(true);
 
175
        aLabel->setWordWrap(true);
 
176
        aLabel->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred);
 
177
        aLabel->setMaximumWidth(55);
 
178
        aLayout->addWidget(aLabel);
 
179
 
 
180
        QString url;
 
181
        if (theDescriptions.count(lang))
 
182
                theDescription = theDescriptions[lang];
 
183
        else
 
184
                if (theDescriptions.count(defLang))
 
185
                        theDescription = theDescriptions[defLang];
 
186
                else
 
187
                        theDescription = theTag;
 
188
        if (!theUrl.isEmpty())
 
189
                url = theUrl.toString();
 
190
 
 
191
        QComboBox* aCombo = new QComboBox();
 
192
        aCombo->setEditable(true);
 
193
        aCombo->setSizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLengthWithIcon);
 
194
        aLayout->addWidget(aCombo);
 
195
 
 
196
        aCombo->addItem(tr("Undefined"), qVariantFromValue(new TagTemplateWidgetValue("__NULL__")));
 
197
        QString val = F->tagValue(theTag, "__NULL__");
 
198
        int idx = -1;
 
199
        for (int i=0; i<theValues.size(); ++i) {
 
200
                if (theValues[i]->theDescriptions.count(lang))
 
201
                        aCombo->addItem(theValues[i]->theDescriptions[lang], qVariantFromValue(theValues[i]));
 
202
                else
 
203
                        if (theValues[i]->theDescriptions.count(defLang))
 
204
                                aCombo->addItem(theValues[i]->theDescriptions[defLang], qVariantFromValue(theValues[i]));
 
205
                        else
 
206
                                aCombo->addItem(theValues[i]->theTagValue,  qVariantFromValue(theValues[i]));
 
207
 
 
208
                if (theValues[i]->theTagValue == val)
 
209
                        idx = aCombo->count() - 1;
 
210
        }
 
211
 
 
212
        if (val != "__NULL__") {
 
213
                if (idx == -1) {
 
214
                        aCombo->insertItem(1, val);
 
215
                        aCombo->setCurrentIndex(1);
 
216
                } else {
 
217
                        aCombo->setCurrentIndex(idx);
 
218
                        if (!theValues[idx-1]->theUrl.isEmpty())
 
219
                                url = theValues[idx-1]->theUrl.toString();
 
220
                }
 
221
        } else 
 
222
                aCombo->setCurrentIndex(0);
 
223
 
 
224
        if (!url.isEmpty())
 
225
                aLabel->setText(QString("<a href=\"%1\">%2</a>").arg(url).arg(theDescription));
 
226
        else
 
227
                aLabel->setText(theDescription);
 
228
 
 
229
        connect(aCombo,SIGNAL(activated(int)), this, SLOT(on_combo_activated(int)));
 
230
        theMainWidget = aCombo;
 
231
        theLabelWidget = aLabel;
 
232
 
 
233
        return theWidget;
 
234
}
 
235
 
 
236
TagTemplateWidgetCombo* TagTemplateWidgetCombo::fromXml(const QDomElement& e)
 
237
{
 
238
        TagTemplateWidgetCombo* aCW = new TagTemplateWidgetCombo();
 
239
 
 
240
        for(QDomNode n = e.firstChild(); !n.isNull(); n = n.nextSibling()) {
 
241
                QDomElement t = n.toElement();
 
242
                if (t.isNull())
 
243
                        continue;
 
244
 
 
245
                aCW->parseCommonElements(t);
 
246
        }
 
247
 
 
248
        return aCW;
 
249
}
 
250
 
 
251
bool TagTemplateWidgetCombo::toXML(QDomElement& xParent, bool header)
 
252
{
 
253
        bool OK = true;
 
254
 
 
255
        if (!header) {
 
256
                QDomElement e = xParent.ownerDocument().createElement("widgetref");
 
257
                xParent.appendChild(e);
 
258
                if (!theId.isEmpty())
 
259
                        e.setAttribute("id", theId);
 
260
                else
 
261
                        e.setAttribute("id", theTag);
 
262
        } else {
 
263
                QDomElement e = xParent.ownerDocument().createElement("widget");
 
264
                xParent.appendChild(e);
 
265
 
 
266
                if (!theId.isEmpty())
 
267
                        e.setAttribute("id", theId);
 
268
                e.setAttribute("type", theType);
 
269
                e.setAttribute("tag", theTag);
 
270
                generateCommonElements(e);
 
271
        }
 
272
 
 
273
        return OK;
 
274
}
 
275
 
 
276
void TagTemplateWidgetCombo::on_combo_activated(int idx)
 
277
{
 
278
        QComboBox* W = dynamic_cast<QComboBox*>(theMainWidget);
 
279
        TagTemplateWidgetValue* aTCV = W->itemData(idx).value<TagTemplateWidgetValue*>();
 
280
 
 
281
        QString val;
 
282
        if (aTCV) {
 
283
                if (!aTCV->theUrl.isEmpty()) {
 
284
                        ((QLabel *)theLabelWidget)->setText(QString("<a href=\"%1\">%2</a>").arg(aTCV->theUrl.toString()).arg(theDescription));
 
285
                } else {
 
286
                        if (!theUrl.isEmpty()) {
 
287
                                ((QLabel *)theLabelWidget)->setText(QString("<a href=\"%1\">%2</a>").arg(theUrl.toString()).arg(theDescription));
 
288
                        } else {
 
289
                                ((QLabel *)theLabelWidget)->setText(theDescription);
 
290
                        }
 
291
                }
 
292
 
 
293
                val = aTCV->theTagValue;
 
294
        } else
 
295
                val = W->currentText();
 
296
 
 
297
        if (val == "__NULL__")
 
298
                emit tagCleared(theTag);
 
299
        else
 
300
                emit tagChanged(theTag, val);
 
301
}
 
302
 
 
303
void TagTemplateWidgetCombo::apply(const MapFeature*)
 
304
{
 
305
}
 
306
 
 
307
/** TagTemplateWidgetYesno **/
 
308
 
 
309
QWidget* TagTemplateWidgetYesno::getWidget(const MapFeature* F)
 
310
{
 
311
        if (theSelector && (theSelector->matches(F) != TagSelect_Match && theSelector->matches(F) != TagSelect_DefaultMatch))
 
312
                return NULL;
 
313
 
 
314
        QString lang = getDefaultLanguage();
 
315
        QString defLang = "en";
 
316
    if (lang == "-" || !M_PREFS->getTranslateTags())
 
317
        lang = "en";
 
318
 
 
319
        theWidget = new QWidget();
 
320
        QHBoxLayout* aLayout = new QHBoxLayout(theWidget);
 
321
        aLayout->setContentsMargins(0, 0, 0, 0);
 
322
 
 
323
        QLabel* aLabel = new QLabel();
 
324
        aLabel->setOpenExternalLinks(true);
 
325
        aLayout->addWidget(aLabel);
 
326
 
 
327
        QCheckBox* aCB = new QCheckBox();
 
328
        aCB->setTristate();
 
329
        aLayout->addWidget(aCB);
 
330
 
 
331
        if (theDescriptions.count(lang))
 
332
                theDescription = theDescriptions[lang];
 
333
        else
 
334
                if (theDescriptions.count(defLang))
 
335
                        theDescription = theDescriptions[defLang];
 
336
                else
 
337
                        theDescription = theTag;
 
338
 
 
339
        QString val = F->tagValue(theTag, "__NULL__");
 
340
        if (val == "yes" || val == "1" || val == "true")
 
341
                aCB->setCheckState(Qt::Checked);
 
342
        else
 
343
        if (val == "no" || val == "0" || val == "false")
 
344
                aCB->setCheckState(Qt::Unchecked);
 
345
        else
 
346
                aCB->setCheckState(Qt::PartiallyChecked);
 
347
 
 
348
        if (!theUrl.isEmpty())
 
349
                aLabel->setText(QString("<a href=\"%1\">%2</a>").arg(theUrl.toString()).arg(theDescription));
 
350
        else
 
351
                aLabel->setText(theDescription);
 
352
 
 
353
        connect(aCB,SIGNAL(stateChanged(int)), this, SLOT(on_checkbox_stateChanged (int)));
 
354
        theMainWidget = aCB;
 
355
        theLabelWidget = aLabel;
 
356
 
 
357
        return theWidget;
 
358
}
 
359
 
 
360
void TagTemplateWidgetYesno::on_checkbox_stateChanged(int state)
 
361
{
 
362
        //QCheckBox* W = dynamic_cast<QCheckBox*>(theMainWidget);
 
363
        if (state == Qt::PartiallyChecked) {
 
364
                emit tagCleared(theTag);
 
365
        } else {
 
366
                QString value = (state == Qt::Checked) ? "yes" : "no";
 
367
                emit tagChanged(theTag, value);
 
368
        }
 
369
}
 
370
 
 
371
void TagTemplateWidgetYesno::apply(const MapFeature*)
 
372
{
 
373
}
 
374
 
 
375
TagTemplateWidgetYesno* TagTemplateWidgetYesno::fromXml(const QDomElement& e)
 
376
{
 
377
        TagTemplateWidgetYesno* aCB = new TagTemplateWidgetYesno();
 
378
 
 
379
        for(QDomNode n = e.firstChild(); !n.isNull(); n = n.nextSibling()) {
 
380
                QDomElement t = n.toElement();
 
381
                if (t.isNull())
 
382
                        continue;
 
383
 
 
384
                aCB->parseCommonElements(t);
 
385
        }
 
386
 
 
387
        return aCB;
 
388
}
 
389
 
 
390
bool TagTemplateWidgetYesno::toXML(QDomElement& xParent, bool header)
 
391
{
 
392
        bool OK = true;
 
393
 
 
394
        if (!header) {
 
395
                QDomElement e = xParent.ownerDocument().createElement("widgetref");
 
396
                xParent.appendChild(e);
 
397
                if (!theId.isEmpty())
 
398
                        e.setAttribute("id", theId);
 
399
                else
 
400
                        e.setAttribute("id", theTag);
 
401
        } else {
 
402
                QDomElement e = xParent.ownerDocument().createElement("widget");
 
403
                xParent.appendChild(e);
 
404
 
 
405
                if (!theId.isEmpty())
 
406
                        e.setAttribute("id", theId);
 
407
                e.setAttribute("type", theType);
 
408
                e.setAttribute("tag", theTag);
 
409
                generateCommonElements(e);
 
410
        }
 
411
 
 
412
        return OK;
 
413
}
 
414
 
 
415
/** TagTemplateWidgetConstant **/
 
416
 
 
417
TagTemplateWidgetConstant::~TagTemplateWidgetConstant()
 
418
{
 
419
}
 
420
 
 
421
QWidget* TagTemplateWidgetConstant::getWidget(const MapFeature* F)
 
422
{
 
423
        if (theSelector && (theSelector->matches(F) != TagSelect_Match && theSelector->matches(F) != TagSelect_DefaultMatch))
 
424
                return NULL;
 
425
 
 
426
        QString lang = getDefaultLanguage();
 
427
        QString defLang = "en";
 
428
    if (lang == "-" || !M_PREFS->getTranslateTags())
 
429
        lang = "en";
 
430
 
 
431
        theWidget = new QWidget();
 
432
        QHBoxLayout* aLayout = new QHBoxLayout(theWidget);
 
433
        aLayout->setContentsMargins(0, 0, 0, 0);
 
434
 
 
435
        QLabel* aLabel = new QLabel();
 
436
        aLabel->setOpenExternalLinks(true);
 
437
        aLabel->setWordWrap(true);
 
438
        aLabel->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred);
 
439
        aLabel->setMaximumWidth(55);
 
440
        aLayout->addWidget(aLabel);
 
441
 
 
442
        QString url;
 
443
        if (theDescriptions.count(lang))
 
444
                theDescription = theDescriptions[lang];
 
445
        else
 
446
                if (theDescriptions.count(defLang))
 
447
                        theDescription = theDescriptions[defLang];
 
448
                else
 
449
                        theDescription = theTag;
 
450
        if (!theUrl.isEmpty())
 
451
                url = theUrl.toString();
 
452
 
 
453
        QLabel* aValue = new QLabel();
 
454
        aValue->setTextInteractionFlags(Qt::TextSelectableByMouse | Qt::TextSelectableByKeyboard);
 
455
        aValue->setWordWrap(true);
 
456
        aLayout->addWidget(aValue);
 
457
 
 
458
        if (theValues.count()) {
 
459
                QString aValueStr;
 
460
                if (theValues[0]->theDescriptions.count(lang))
 
461
                        aValueStr = theValues[0]->theDescriptions[lang];
 
462
                else
 
463
                        if (theValues[0]->theDescriptions.count(defLang))
 
464
                                aValueStr = theValues[0]->theDescriptions[defLang];
 
465
                        else
 
466
                                aValueStr = theValues[0]->theTagValue;
 
467
 
 
468
                aValue->setText(QString("<b>%1</b>").arg(aValueStr));
 
469
 
 
470
                if (!theValues[0]->theUrl.isEmpty())
 
471
                        url = theValues[0]->theUrl.toString();
 
472
 
 
473
                if (!url.isEmpty())
 
474
                        aLabel->setText(QString("<a href=\"%1\">%2</a>").arg(url).arg(theDescription));
 
475
                else
 
476
                        aLabel->setText(theDescription);
 
477
        } else
 
478
                aValue->setText(QString("<b>%1</b>").arg(F->tagValue(theTag, "")));
 
479
 
 
480
        theMainWidget = aValue;
 
481
        theLabelWidget = aLabel;
 
482
 
 
483
        return theWidget;
 
484
}
 
485
 
 
486
void TagTemplateWidgetConstant::apply(const MapFeature* F)
 
487
{
 
488
        if (!theValues.count()) {
 
489
                ((QLabel*)theMainWidget)->setText(QString("<b>%1</b>").arg(F->tagValue(theTag, "")));
 
490
                return;
 
491
        }
 
492
        bool Regexp = false;
 
493
        bool OK = true;
 
494
        QString oldVal = F->tagValue(theTag, "__NULL__");
 
495
        QString newVal = theValues[0]->theTagValue;
 
496
        QRegExp subst("\\$\\[(.+)\\]");
 
497
        subst.setMinimal(true);
 
498
        int pos = 0;
 
499
        while ((pos = subst.indexIn(newVal, pos)) != -1) {
 
500
                Regexp = true;
 
501
                QString rep = F->tagValue(subst.cap(1), "__NULL__");
 
502
                if (rep == "__NULL__") {
 
503
                        OK = false;
 
504
                        break;
 
505
                }
 
506
                newVal.replace(subst.cap(0), rep);
 
507
                pos += rep.length();
 
508
        }
 
509
        if (!Regexp || (Regexp && OK)) {
 
510
                ((QLabel*)theMainWidget)->setText(QString("<b>%1</b>").arg(newVal));
 
511
                if (newVal != oldVal) {
 
512
                        emit tagChanged(theTag, newVal);
 
513
                }
 
514
        } else
 
515
                ((QLabel*)theMainWidget)->setText(QString("<b>%1</b>").arg(F->tagValue(theTag, "")));
 
516
}
 
517
 
 
518
TagTemplateWidgetConstant* TagTemplateWidgetConstant::fromXml(const QDomElement& e)
 
519
{
 
520
        TagTemplateWidgetConstant* aCW = new TagTemplateWidgetConstant();
 
521
 
 
522
        for(QDomNode n = e.firstChild(); !n.isNull(); n = n.nextSibling()) {
 
523
                QDomElement t = n.toElement();
 
524
                if (t.isNull())
 
525
                        continue;
 
526
 
 
527
                aCW->parseCommonElements(t);
 
528
        }
 
529
 
 
530
        return aCW;
 
531
}
 
532
 
 
533
bool TagTemplateWidgetConstant::toXML(QDomElement& xParent, bool header)
 
534
{
 
535
        bool OK = true;
 
536
 
 
537
        if (header) return OK;
 
538
 
 
539
        QDomElement e = xParent.ownerDocument().createElement("widget");
 
540
        xParent.appendChild(e);
 
541
 
 
542
        if (!theId.isEmpty())
 
543
                e.setAttribute("id", theId);
 
544
        e.setAttribute("type", theType);
 
545
        e.setAttribute("tag", theTag);
 
546
        generateCommonElements(e);
 
547
 
 
548
        return OK;
 
549
}
 
550
 
 
551
/** TagTemplateWidgetEdit **/
 
552
 
 
553
QWidget* TagTemplateWidgetEdit::getWidget(const MapFeature* F)
 
554
{
 
555
        if (theSelector && (theSelector->matches(F) != TagSelect_Match && theSelector->matches(F) != TagSelect_DefaultMatch))
 
556
                return NULL;
 
557
 
 
558
        QString lang = getDefaultLanguage();
 
559
        QString defLang = "en";
 
560
    if (lang == "-" || !M_PREFS->getTranslateTags())
 
561
        lang = "en";
 
562
 
 
563
        theWidget = new QWidget();
 
564
        QHBoxLayout* aLayout = new QHBoxLayout(theWidget);
 
565
        aLayout->setContentsMargins(0, 0, 0, 0);
 
566
 
 
567
        QLabel* aLabel = new QLabel();
 
568
        aLabel->setOpenExternalLinks(true);
 
569
        aLabel->setWordWrap(true);
 
570
        aLabel->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred);
 
571
        aLabel->setMaximumWidth(55);
 
572
        aLayout->addWidget(aLabel);
 
573
 
 
574
        QString url;
 
575
        if (theDescriptions.count(lang))
 
576
                theDescription = theDescriptions[lang];
 
577
        else
 
578
                if (theDescriptions.count(defLang))
 
579
                        theDescription = theDescriptions[defLang];
 
580
                else
 
581
                        theDescription = theTag;
 
582
        if (!theUrl.isEmpty())
 
583
                url = theUrl.toString();
 
584
 
 
585
        if (!url.isEmpty())
 
586
                aLabel->setText(QString("<a href=\"%1\">%2</a>").arg(url).arg(theDescription));
 
587
        else
 
588
                aLabel->setText(theDescription);
 
589
 
 
590
        QLineEdit* aValue = new QLineEdit();
 
591
        aLayout->addWidget(aValue);
 
592
 
 
593
        QString val = F->tagValue(theTag, "__NULL__");
 
594
        if (val != "__NULL__")
 
595
                aValue->setText(val);
 
596
 
 
597
        connect(aValue,SIGNAL(editingFinished()),this, SLOT(on_editingFinished()));
 
598
        theMainWidget = aValue;
 
599
        theLabelWidget = aLabel;
 
600
 
 
601
        return theWidget;
 
602
}
 
603
 
 
604
void TagTemplateWidgetEdit::apply(const MapFeature*)
 
605
{
 
606
}
 
607
 
 
608
TagTemplateWidgetEdit* TagTemplateWidgetEdit::fromXml(const QDomElement& e)
 
609
{
 
610
        TagTemplateWidgetEdit* aCW = new TagTemplateWidgetEdit();
 
611
 
 
612
        for(QDomNode n = e.firstChild(); !n.isNull(); n = n.nextSibling()) {
 
613
                QDomElement t = n.toElement();
 
614
                if (t.isNull())
 
615
                        continue;
 
616
 
 
617
                aCW->parseCommonElements(t);
 
618
        }
 
619
 
 
620
        return aCW;
 
621
}
 
622
 
 
623
bool TagTemplateWidgetEdit::toXML(QDomElement& xParent, bool header)
 
624
{
 
625
        bool OK = true;
 
626
 
 
627
        if (!header) {
 
628
                QDomElement e = xParent.ownerDocument().createElement("widgetref");
 
629
                xParent.appendChild(e);
 
630
                if (!theId.isEmpty())
 
631
                        e.setAttribute("id", theId);
 
632
                else
 
633
                        e.setAttribute("id", theTag);
 
634
        } else {
 
635
                QDomElement e = xParent.ownerDocument().createElement("widget");
 
636
                xParent.appendChild(e);
 
637
 
 
638
                if (!theId.isEmpty())
 
639
                        e.setAttribute("id", theId);
 
640
                e.setAttribute("type", theType);
 
641
                e.setAttribute("tag", theTag);
 
642
                generateCommonElements(e);
 
643
        }
 
644
 
 
645
        return OK;
 
646
}
 
647
 
 
648
void TagTemplateWidgetEdit::on_editingFinished()
 
649
{
 
650
        QLineEdit* W = dynamic_cast<QLineEdit*>(theMainWidget);
 
651
 
 
652
        if (W->text().isEmpty()) {
 
653
                emit tagCleared(theTag);
 
654
        } else {
 
655
                emit tagChanged(theTag, W->text());
 
656
        }
 
657
}
 
658
 
 
659
 
 
660
/** TagTemplate **/
 
661
 
 
662
TagTemplate::TagTemplate()
 
663
        : theWidget(0), theSelector(0)
 
664
{
 
665
}
 
666
 
 
667
TagTemplate::TagTemplate(QString aName)
 
668
        : theWidget(0), theSelector(0)
 
669
{
 
670
        Q_UNUSED(aName)
 
671
}
 
672
 
 
673
TagTemplate::TagTemplate(QString aName, QString aSelector)
 
674
        : theWidget(0)
 
675
{
 
676
        Q_UNUSED(aName)
 
677
        theSelector = TagSelector::parse(aSelector);
 
678
}
 
679
 
 
680
TagTemplate::TagTemplate(const TagTemplate& aTemplate)
 
681
        : QObject(), theSelector(aTemplate.theSelector)
 
682
{
 
683
}
 
684
 
 
685
TagTemplate::~TagTemplate()
 
686
{
 
687
        delete theSelector;
 
688
}
 
689
 
 
690
TagSelectorMatchResult TagTemplate::matchesTag(const MapFeature* F)
 
691
{
 
692
        TagSelectorMatchResult res;
 
693
 
 
694
        if (!theSelector) return TagSelect_NoMatch;
 
695
        // Special casing for multipolygon roads
 
696
        if (const Road* R = dynamic_cast<const Road*>(F))
 
697
        {
 
698
                // TODO create a isPartOfMultiPolygon(R) function for this
 
699
                for (int i=0; i<R->sizeParents(); ++i)
 
700
                {
 
701
                        if (const Relation* Parent = dynamic_cast<const Relation*>(R->getParent(i)))
 
702
                                if (Parent->tagValue("type","") == "multipolygon")
 
703
                                        return TagSelect_NoMatch;
 
704
                }
 
705
        }
 
706
        if ((res = theSelector->matches(F)))
 
707
                return res;
 
708
        // Special casing for multipolygon relations
 
709
        if (const Relation* R = dynamic_cast<const Relation*>(F))
 
710
        {
 
711
                for (int i=0; i<R->size(); ++i)
 
712
                        if ((res = theSelector->matches(R->get(i))))
 
713
                                return res;
 
714
        }
 
715
        return TagSelect_NoMatch;
 
716
}
 
717
 
 
718
QWidget* TagTemplate::getWidget(const MapFeature* F)
 
719
{
 
720
        QString lang = getDefaultLanguage();
 
721
        QString defLang = "en";
 
722
    if (lang == "-" || !M_PREFS->getTranslateTags())
 
723
        lang = "en";
 
724
 
 
725
        theWidget = new QWidget();
 
726
        //if (theDescriptions.count(lang))
 
727
        //      theWidget->setTitle(theDescriptions[lang]);
 
728
        //else
 
729
        //      theWidget->setTitle(theDescriptions[defLang]);
 
730
        QVBoxLayout* aLayout = new QVBoxLayout(theWidget);
 
731
        aLayout->setContentsMargins(2, 2, 2, 2);
 
732
 
 
733
        for (int i=0; i<theFields.size(); ++i) {
 
734
                QWidget* W = theFields[i]->getWidget(F);
 
735
                if (W)
 
736
                        aLayout->addWidget(W);
 
737
        }
 
738
 
 
739
        return theWidget;
 
740
}
 
741
 
 
742
void TagTemplate::setSelector(const QString& anExpression)
 
743
{
 
744
        delete theSelector;
 
745
        theSelector = TagSelector::parse(anExpression);
 
746
}
 
747
 
 
748
void TagTemplate::setSelector(TagSelector* aSel)
 
749
{
 
750
        delete theSelector;
 
751
        theSelector = aSel;
 
752
}
 
753
 
 
754
void TagTemplate::apply(const MapFeature* F)
 
755
{
 
756
        for (int i=0; i<theFields.size(); ++i) {
 
757
                theFields[i]->apply(F);
 
758
        }
 
759
}
 
760
 
 
761
TagTemplate* TagTemplate::fromXml(const QDomElement& e, TagTemplates* templates)
 
762
{
 
763
        TagTemplate* aTemplate = new TagTemplate();
 
764
 
 
765
        if (e.tagName() != "template") {
 
766
                return NULL;
 
767
        }
 
768
 
 
769
        for(QDomNode n = e.firstChild(); !n.isNull(); n = n.nextSibling()) {
 
770
                QDomElement t = n.toElement();
 
771
                if (t.isNull())
 
772
                        continue;
 
773
 
 
774
                if (t.tagName() == "description") {
 
775
                        aTemplate->theDescriptions.insert(t.attribute("locale"), t.firstChild().toText().nodeValue());
 
776
                } else
 
777
                if (t.tagName() == "selector") {
 
778
                        TagSelector* aSel = TagSelector::parse(t.attribute("expr"));
 
779
                        if (!aSel)
 
780
                                return NULL;
 
781
                        aTemplate->setSelector(aSel);
 
782
                } else
 
783
                if (t.tagName() == "widget") {
 
784
                        TagTemplateWidget* aTW = TagTemplateWidget::fromXml(t);
 
785
                        if (aTW) {
 
786
                                templates->addWidget(aTW);
 
787
                                aTemplate->theFields.append(aTW);
 
788
                                connect(aTW, SIGNAL(tagChanged(QString, QString)), aTemplate, SLOT(on_tag_changed(QString, QString)));
 
789
                                connect(aTW, SIGNAL(tagCleared(QString)), aTemplate, SLOT(on_tag_cleared(QString)));
 
790
                        }
 
791
                } else
 
792
                if (t.tagName() == "widgetref") {
 
793
                        TagTemplateWidget* aTW = templates->findWidget(t.attribute("id"));
 
794
                        if (aTW) {
 
795
                                aTemplate->theFields.append(aTW);
 
796
                                connect(aTW, SIGNAL(tagChanged(QString, QString)), aTemplate, SLOT(on_tag_changed(QString, QString)));
 
797
                                connect(aTW, SIGNAL(tagCleared(QString)), aTemplate, SLOT(on_tag_cleared(QString)));
 
798
                        }
 
799
                }
 
800
        }
 
801
        return aTemplate;
 
802
}
 
803
 
 
804
bool TagTemplate::toXML(QDomElement& xParent)
 
805
{
 
806
        bool OK = true;
 
807
 
 
808
        QDomElement e = xParent.ownerDocument().createElement("template");
 
809
        xParent.appendChild(e);
 
810
 
 
811
        if (theSelector) {
 
812
                QDomElement s = xParent.ownerDocument().createElement("selector");
 
813
                e.appendChild(s);
 
814
                s.setAttribute("expr", theSelector->asExpression(false));
 
815
        }
 
816
 
 
817
        QHashIterator<QString, QString > itD(theDescriptions);
 
818
        while(itD.hasNext()) {
 
819
                itD.next();
 
820
 
 
821
                QDomElement d = xParent.ownerDocument().createElement("description");
 
822
                e.appendChild(d);
 
823
 
 
824
                d.setAttribute("locale", itD.key());
 
825
 
 
826
                QDomText v = xParent.ownerDocument().createTextNode(itD.value());
 
827
                d.appendChild(v);
 
828
        }
 
829
 
 
830
        for (int i=0; i<theFields.size(); ++i) {
 
831
                theFields[i]->toXML(e, false);
 
832
        }
 
833
 
 
834
        return OK;
 
835
}
 
836
 
 
837
void TagTemplate::on_tag_changed(QString k, QString v)
 
838
{
 
839
        emit tagChanged(k, v);
 
840
}
 
841
 
 
842
void TagTemplate::on_tag_cleared(QString k)
 
843
{
 
844
        emit tagCleared(k);
 
845
}
 
846
 
 
847
/** TagTemplates **/
 
848
 
 
849
TagTemplates::TagTemplates()
 
850
        : theWidget(0), theFeature(0), curTemplate(0)
 
851
{
 
852
}
 
853
 
 
854
TagTemplates::~TagTemplates()
 
855
{
 
856
        for (int i=0; i< widgets.size(); ++i)
 
857
                delete widgets[i];
 
858
        for (int i=0; i< items.size(); ++i)
 
859
                delete items[i];
 
860
}
 
861
 
 
862
QWidget* TagTemplates::getWidget(const MapFeature* F)
 
863
{
 
864
        QString lang = getDefaultLanguage();
 
865
        QString defLang = "en";
 
866
    if (lang == "-" || !M_PREFS->getTranslateTags())
 
867
        lang = "en";
 
868
 
 
869
        if (curTemplate) {
 
870
                disconnect(curTemplate, 0, this, 0);
 
871
                curTemplate = NULL;
 
872
        }
 
873
        if (F != theFeature)
 
874
                forcedTemplate = NULL;
 
875
        else
 
876
                curTemplate = forcedTemplate;
 
877
        theFeature = F;
 
878
 
 
879
        theWidget = new QWidget();
 
880
        //if (theDescriptions.count(lang))
 
881
        //      theWidget->setTitle(theDescriptions[lang]);
 
882
        //else
 
883
        //      theWidget->setTitle(theDescriptions[defLang]);
 
884
        QVBoxLayout* aLayout = new QVBoxLayout(theWidget);
 
885
        aLayout->setContentsMargins(2, 2, 2, 2);
 
886
 
 
887
        QHBoxLayout* headLayout = new QHBoxLayout();
 
888
        headLayout->setContentsMargins(0, 0, 0, 0);
 
889
        aLayout->addLayout(headLayout);
 
890
 
 
891
        theCombo = new QComboBox();
 
892
        theCombo->setEditable(true);
 
893
        theCombo->setInsertPolicy(QComboBox::InsertAtBottom);
 
894
//      QFont f = theCombo->font();
 
895
//      f.setPointSize(6);
 
896
//      theCombo->setFont(f);
 
897
//      theCombo->setMaximumHeight(16);
 
898
        headLayout->addWidget(theCombo);
 
899
 
 
900
        QFrame* line = new QFrame();
 
901
        line->setFrameShape(QFrame::HLine);
 
902
        line->setFrameShadow(QFrame::Sunken);
 
903
        headLayout->addWidget(line);
 
904
 
 
905
        int idx = -1;
 
906
        theCombo->addItem(tr("Undefined"), "__NULL__");
 
907
        for (int i=0; i<items.size(); ++i) {
 
908
                if (items[i]->theDescriptions.count(lang))
 
909
                        theCombo->addItem(items[i]->theDescriptions[lang], qVariantFromValue(items[i]));
 
910
                else
 
911
                        theCombo->addItem(items[i]->theDescriptions[defLang], qVariantFromValue(items[i]));
 
912
 
 
913
                if (forcedTemplate) {
 
914
                        if (items[i] == forcedTemplate) {
 
915
                                idx = i+1;
 
916
                        }
 
917
                }
 
918
        }
 
919
        if (!forcedTemplate) {
 
920
                for (int i=0; i<items.size(); ++i) {
 
921
                        if (idx == -1 && items[i]->matchesTag(F) == TagSelect_Match) {
 
922
                                curTemplate = items[i];
 
923
                                idx = i+1;
 
924
                        }
 
925
                }
 
926
        }
 
927
        if (!forcedTemplate && idx == -1) {
 
928
                for (int i=0; i<items.size(); ++i) {
 
929
                        if (idx == -1 && items[i]->matchesTag(F) == TagSelect_DefaultMatch) {
 
930
                                curTemplate = items[i];
 
931
                                idx = i+1;
 
932
                        }
 
933
                }
 
934
        }
 
935
 
 
936
        if (idx == -1)
 
937
                theCombo->setCurrentIndex(0);
 
938
        else
 
939
                theCombo->setCurrentIndex(idx);
 
940
 
 
941
        if (curTemplate) {
 
942
                aLayout->addWidget(curTemplate->getWidget(F));
 
943
                connect(curTemplate, SIGNAL(tagChanged(QString, QString)), this, SLOT(on_tag_changed(QString, QString)));
 
944
                connect(curTemplate, SIGNAL(tagCleared(QString)), this, SLOT(on_tag_cleared(QString)));
 
945
        }
 
946
        connect(theCombo,SIGNAL(activated(int)), this, SLOT(on_combo_activated(int)));
 
947
 
 
948
        line = new QFrame();
 
949
        line->setFrameShape(QFrame::HLine);
 
950
        line->setFrameShadow(QFrame::Sunken);
 
951
        aLayout->addWidget(line);
 
952
 
 
953
        return theWidget;
 
954
}
 
955
 
 
956
void TagTemplates::on_combo_activated(int idx)
 
957
{
 
958
        if (idx > items.count() -1) {
 
959
                TagTemplate* newTmpl = new TagTemplate(theCombo->currentText());
 
960
                items.append(newTmpl);
 
961
 
 
962
                for (int i=0; i<curTemplate->theFields.count(); ++i) {
 
963
                        curTemplate->theFields[i]->getCurrentValue();
 
964
                }
 
965
        } else {
 
966
                forcedTemplate = theCombo->itemData(idx).value<TagTemplate*>();
 
967
 
 
968
                emit templateChanged(forcedTemplate);
 
969
        }
 
970
}
 
971
 
 
972
TagTemplates* TagTemplates::fromXml(const QDomElement& e)
 
973
{
 
974
        TagTemplates* aTemplates = new TagTemplates();
 
975
 
 
976
        if (e.tagName() != "templates") {
 
977
                return NULL;
 
978
        }
 
979
 
 
980
        for(QDomNode n = e.firstChild(); !n.isNull(); n = n.nextSibling())
 
981
        {
 
982
                QDomElement t = n.toElement();
 
983
                if (t.isNull())
 
984
                        continue;
 
985
 
 
986
                if (t.tagName() == "template") {
 
987
                        TagTemplate* tmpl = TagTemplate::fromXml(t, aTemplates);
 
988
                        if (tmpl)
 
989
                                aTemplates->items.append(tmpl);
 
990
                        else
 
991
                                return NULL;
 
992
                } else 
 
993
                if (t.tagName() == "widgets") {
 
994
                        for(QDomNode n = t.firstChild(); !n.isNull(); n = n.nextSibling())
 
995
                        {
 
996
                                QDomElement w = n.toElement();
 
997
                                if (w.tagName() == "widget") {
 
998
                                        TagTemplateWidget* aTW = TagTemplateWidget::fromXml(w);
 
999
                                        if (aTW)
 
1000
                                                aTemplates->addWidget(aTW);
 
1001
                                        else
 
1002
                                                return NULL;
 
1003
                                }
 
1004
                        }
 
1005
                }
 
1006
        }
 
1007
        return aTemplates;
 
1008
}
 
1009
 
 
1010
bool TagTemplates::mergeXml(const QDomElement& e)
 
1011
{
 
1012
        if (e.tagName() != "templates") {
 
1013
                return false;
 
1014
        }
 
1015
 
 
1016
        for(QDomNode n = e.firstChild(); !n.isNull(); n = n.nextSibling())
 
1017
        {
 
1018
                QDomElement t = n.toElement();
 
1019
                if (t.isNull())
 
1020
                        continue;
 
1021
 
 
1022
                if (t.tagName() == "template") {
 
1023
                        TagTemplate* tmpl = TagTemplate::fromXml(t, this);
 
1024
                        if (tmpl)
 
1025
                                items.append(tmpl);
 
1026
                        else
 
1027
                                return false;
 
1028
                } else
 
1029
                if (t.tagName() == "widgets") {
 
1030
                        for(QDomNode n = t.firstChild(); !n.isNull(); n = n.nextSibling())
 
1031
                        {
 
1032
                                QDomElement w = n.toElement();
 
1033
                                if (w.tagName() == "widget") {
 
1034
                                        TagTemplateWidget* aTW = TagTemplateWidget::fromXml(w);
 
1035
                                        if (aTW)
 
1036
                                                addWidget(aTW);
 
1037
                                        else
 
1038
                                                return false;
 
1039
                                }
 
1040
                        }
 
1041
                }
 
1042
        }
 
1043
        return true;
 
1044
}
 
1045
 
 
1046
TagTemplate* TagTemplates::match(MapFeature* F)
 
1047
{
 
1048
        for (int i=0; i<items.size(); ++i) {
 
1049
                if (items[i]->matchesTag(F) == TagSelect_Match)
 
1050
                        return items[i];
 
1051
        }
 
1052
        for (int i=0; i<items.size(); ++i) {
 
1053
                if (items[i]->matchesTag(F) == TagSelect_DefaultMatch)
 
1054
                        return items[i];
 
1055
        }
 
1056
        return NULL;
 
1057
}
 
1058
 
 
1059
bool TagTemplates::toXML(QDomDocument& doc)
 
1060
{
 
1061
        bool OK = true;
 
1062
 
 
1063
        QDomElement e = doc.createElement("templates");
 
1064
        doc.appendChild(e);
 
1065
 
 
1066
        QDomElement w = doc.createElement("widgets");
 
1067
        e.appendChild(w);
 
1068
 
 
1069
        for (int i=0; i<widgets.size(); ++i)
 
1070
                OK = widgets[i]->toXML(w, true);
 
1071
 
 
1072
        for (int i=0; i<items.size(); ++i)
 
1073
                OK = items[i]->toXML(e);
 
1074
 
 
1075
        return OK;
 
1076
}
 
1077
 
 
1078
TagTemplateWidget* TagTemplates::findWidget(const QString& id)
 
1079
{
 
1080
        for (int i=0; i<widgets.size(); ++i) {
 
1081
                if (widgets[i]->id() == id)
 
1082
                        return widgets[i];
 
1083
        }
 
1084
 
 
1085
        return NULL;
 
1086
}
 
1087
 
 
1088
void TagTemplates::on_tag_changed(QString k, QString v)
 
1089
{
 
1090
        emit tagChanged(k, v);
 
1091
}
 
1092
 
 
1093
void TagTemplates::on_tag_cleared(QString k)
 
1094
{
 
1095
        emit tagCleared(k);
 
1096
}
 
1097
 
 
1098
void TagTemplates::addWidget(TagTemplateWidget* aWidget)
 
1099
{
 
1100
        widgets.append(aWidget);
 
1101
}
 
1102
 
 
1103
void TagTemplates::apply(const MapFeature* F)
 
1104
{
 
1105
        if (curTemplate)
 
1106
                curTemplate->apply(F);
 
1107
}