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

« back to all changes in this revision

Viewing changes to src/Docks/PropertiesDock.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
#include "PropertiesDock.h"
 
2
#include "InfoDock.h"
 
3
#include "MainWindow.h"
 
4
#include "MapView.h"
 
5
#include "TagModel.h"
 
6
#include "Utils/EditCompleterDelegate.h"
 
7
#include "Utils/ShortcutOverrideFilter.h"
 
8
#include "Command/DocumentCommands.h"
 
9
#include "Command/FeatureCommands.h"
 
10
#include "Command/TrackPointCommands.h"
 
11
#include "Command/RelationCommands.h"
 
12
#include "Maps/Coord.h"
 
13
#include "Maps/MapDocument.h"
 
14
#include "Maps/MapFeature.h"
 
15
#include "Maps/Relation.h"
 
16
#include "Maps/Road.h"
 
17
#include "Maps/FeatureManipulations.h"
 
18
#include "Maps/TrackPoint.h"
 
19
#include "TagTemplate/TagTemplate.h"
 
20
 
 
21
#ifdef GEOIMAGE
 
22
#include "GeoImageDock.h"
 
23
#endif
 
24
 
 
25
#include <QtCore/QTimer>
 
26
#include <QtGui/QHeaderView>
 
27
#include <QtGui/QLineEdit>
 
28
#include <QtGui/QListWidget>
 
29
#include <QtGui/QTableView>
 
30
#include <QClipboard>
 
31
#include <QMessageBox>
 
32
 
 
33
#include <algorithm>
 
34
 
 
35
PropertiesDock::PropertiesDock(MainWindow* aParent)
 
36
: MDockAncestor(aParent), Main(aParent), CurrentUi(0),
 
37
        theTemplates(0), CurrentTagView(0), CurrentMembersView(0), NowShowing(NoUiShowing)
 
38
{
 
39
        setMinimumSize(220,100);
 
40
        switchToNoUi();
 
41
        setObjectName("propertiesDock");
 
42
        theModel = new TagModel(aParent);
 
43
        delegate = new EditCompleterDelegate(aParent);
 
44
 
 
45
        // Set up the shortcut event filter for the tableviews
 
46
        // This allows them to react to keys already bound to
 
47
        // application wide shortcuts
 
48
        shortcutFilter = new ShortcutOverrideFilter();
 
49
        shortcutFilter->addOverride(Qt::Key_Up);
 
50
        shortcutFilter->addOverride(Qt::Key_Down);
 
51
        shortcutFilter->addOverride(Qt::Key_Left);
 
52
        shortcutFilter->addOverride(Qt::Key_Right);
 
53
        shortcutFilter->addOverride(Qt::Key_F2);
 
54
        shortcutFilter->addOverride(Qt::Key_Delete);
 
55
        shortcutFilter->addOverride(Qt::Key_Escape);
 
56
 
 
57
        centerAction = new QAction(NULL, this);
 
58
        connect(centerAction, SIGNAL(triggered()), this, SLOT(on_centerAction_triggered()));
 
59
        centerZoomAction = new QAction(NULL, this);
 
60
        connect(centerZoomAction, SIGNAL(triggered()), this, SLOT(on_centerZoomAction_triggered()));
 
61
        selectAction = new QAction(NULL, this);
 
62
        connect(selectAction, SIGNAL(triggered()), this, SLOT(on_Member_selected()));
 
63
 
 
64
        loadTemplates();
 
65
 
 
66
        retranslateUi();
 
67
}
 
68
 
 
69
PropertiesDock::~PropertiesDock(void)
 
70
{
 
71
        delete theModel;
 
72
        delete theTemplates;
 
73
        delete shortcutFilter;
 
74
}
 
75
 
 
76
static bool isChildOfSingleRoadInner(MapFeature *mapFeature)
 
77
{
 
78
        return Road::GetSingleParentRoadInner(mapFeature) != NULL;
 
79
}
 
80
 
 
81
static bool isChildOfArea(MapFeature *mapFeature)
 
82
{
 
83
        Road* R =  Road::GetSingleParentRoadInner(mapFeature);
 
84
        if (R)
 
85
                return (R->area() > 0.0);
 
86
        return false;
 
87
}
 
88
 
 
89
static bool isChildOfSingleRoad(MapFeature *mapFeature)
 
90
{
 
91
        return Road::GetSingleParentRoad(mapFeature) != NULL;
 
92
}
 
93
 
 
94
static bool isChildOfSingleRelation(MapFeature *mapFeature)
 
95
{
 
96
        int parents = mapFeature->sizeParents();
 
97
 
 
98
        if (parents == 0)
 
99
                return false;
 
100
 
 
101
        int parentRelations = 0;
 
102
 
 
103
        int i;
 
104
        for (i=0; i<parents; i++)
 
105
        {
 
106
                MapFeature * parent = mapFeature->getParent(i);
 
107
                bool isParentRelation = dynamic_cast<Relation*>(parent) != 0;
 
108
                if (isParentRelation)
 
109
                        parentRelations++;
 
110
                        if (parentRelations > 1)
 
111
                                return false;
 
112
        }
 
113
 
 
114
        return (parentRelations == 1);
 
115
}
 
116
 
 
117
static bool isChildOfRelation(MapFeature *mapFeature)
 
118
{
 
119
        int parents = mapFeature->sizeParents();
 
120
 
 
121
        if (parents == 0)
 
122
                return false;
 
123
 
 
124
        int i;
 
125
        for (i=0; i<parents; i++)
 
126
        {
 
127
                MapFeature * parent = mapFeature->getParent(i);
 
128
                if (dynamic_cast<Relation*>(parent))
 
129
                        return true;
 
130
        }
 
131
 
 
132
        return false;
 
133
}
 
134
 
 
135
void PropertiesDock::checkMenuStatus()
 
136
{
 
137
        bool IsPoint = false;
 
138
        bool IsRoad = false;
 
139
        bool IsParentRoad = false;
 
140
        bool IsParentRoadInner = false;
 
141
        bool IsParentRelation = false;
 
142
        bool IsParentArea = false;
 
143
        int NumRoads = 0;
 
144
        int NumCommitableFeature = 0;
 
145
        int NumPoints = 0;
 
146
        int NumRelation = 0;
 
147
        int NumRelationChild = 0;
 
148
        int NumAreas = 0;
 
149
        if (Selection.size() == 1)
 
150
        {
 
151
                IsPoint = dynamic_cast<TrackPoint*>(Selection[0]) != 0;
 
152
                IsRoad = dynamic_cast<Road*>(Selection[0]) != 0;
 
153
                IsParentRoad = IsPoint && isChildOfSingleRoad(Selection[0]);
 
154
                IsParentRoadInner = IsPoint && isChildOfSingleRoadInner(Selection[0]);
 
155
                IsParentRelation = isChildOfSingleRelation(Selection[0]);
 
156
                IsParentArea = isChildOfArea(Selection[0]);
 
157
        }
 
158
        for (int i=0; i<Selection.size(); ++i)
 
159
        {
 
160
                if (CAST_NODE(Selection[i]))
 
161
                        ++NumPoints;
 
162
                if (Road* R = dynamic_cast<Road*>(Selection[i]))
 
163
                {
 
164
                        if (R->area() > 0.0)
 
165
                        {
 
166
                                ++NumAreas;
 
167
                        }
 
168
                        else
 
169
                        {
 
170
                                ++NumRoads;
 
171
                        }
 
172
                }
 
173
                if (CAST_RELATION(Selection[i]))
 
174
                        ++NumRelation;
 
175
                if (isChildOfRelation(Selection[i]))
 
176
                        ++NumRelationChild;
 
177
 
 
178
                if (!Selection[i]->isDirty())
 
179
                        ++NumCommitableFeature;
 
180
        }
 
181
        Main->createRelationAction->setEnabled(Selection.size());
 
182
        Main->editRemoveAction->setEnabled(Selection.size());
 
183
        Main->editMoveAction->setEnabled(true);
 
184
        Main->editReverseAction->setEnabled(IsRoad);
 
185
        Main->roadJoinAction->setEnabled(NumRoads > 1 && canJoinRoads(this));
 
186
        Main->roadCreateJunctionAction->setEnabled(NumRoads > 1 && canCreateJunction(this));
 
187
        Main->roadSplitAction->setEnabled((IsParentRoadInner && !IsParentArea) || (NumRoads && NumPoints) || (NumAreas && NumPoints));
 
188
        Main->roadBreakAction->setEnabled(IsParentRoadInner || (NumRoads == 1 && NumPoints) || (NumRoads > 1 && canBreakRoads(this)));
 
189
        Main->featureCommitAction->setEnabled(NumCommitableFeature);
 
190
        Main->nodeMergeAction->setEnabled(NumPoints > 1);
 
191
        Main->nodeAlignAction->setEnabled(NumPoints > 2);
 
192
        Main->nodeDetachAction->setEnabled(NumPoints && canDetachNodes(this));
 
193
        Main->relationAddMemberAction->setEnabled(NumRelation && Selection.size() > 1);
 
194
        Main->relationRemoveMemberAction->setEnabled((NumRelation && Selection.size() > 1 && NumRelationChild) || IsParentRelation);
 
195
 
 
196
        Main->editCopyAction->setEnabled(Selection.size());
 
197
        Main->clipboardChanged();
 
198
}
 
199
 
 
200
int PropertiesDock::size() const
 
201
{
 
202
        return Selection.size();
 
203
}
 
204
 
 
205
MapFeature* PropertiesDock::selection(int idx)
 
206
{
 
207
        if (idx < Selection.size())
 
208
                return Selection[idx];
 
209
        return 0;
 
210
}
 
211
 
 
212
QList<MapFeature*> PropertiesDock::selection()
 
213
{
 
214
        return Selection;
 
215
}
 
216
 
 
217
void PropertiesDock::setSelection(MapFeature*aFeature)
 
218
{
 
219
        cleanUpUi();
 
220
        Selection.clear();
 
221
        if (aFeature)
 
222
                Selection.push_back(aFeature);
 
223
        FullSelection = Selection;
 
224
        switchUi();
 
225
        fillMultiUiSelectionBox();
 
226
}
 
227
 
 
228
void PropertiesDock::setMultiSelection(const QList<MapFeature*>& aFeatureList)
 
229
{
 
230
        cleanUpUi();
 
231
        Selection.clear();
 
232
        for (int i=0; i<aFeatureList.size(); ++i)
 
233
                Selection.push_back(aFeatureList[i]);
 
234
        FullSelection = Selection;
 
235
        switchToMultiUi();
 
236
        // to prevent slots to change the values also
 
237
        QList<MapFeature*> Current = Selection;
 
238
        Selection.clear();
 
239
        MultiUi.TagView->setModel(theModel);
 
240
        MultiUi.TagView->setItemDelegate(delegate);
 
241
        Main->info()->setHtml("");
 
242
        #ifdef GEOIMAGE
 
243
        Main->geoImage()->setImage((TrackPoint *)NULL);
 
244
        #endif
 
245
        CurrentTagView = MultiUi.TagView;
 
246
        theModel->setFeature(Current);
 
247
        Selection = Current;
 
248
        fillMultiUiSelectionBox();
 
249
}
 
250
 
 
251
void PropertiesDock::toggleSelection(MapFeature* S)
 
252
{
 
253
        cleanUpUi();
 
254
        QList<MapFeature*>::iterator i = std::find(Selection.begin(),Selection.end(),S);
 
255
        if (i == Selection.end())
 
256
                Selection.push_back(S);
 
257
        else
 
258
                Selection.erase(i);
 
259
        FullSelection = Selection;
 
260
        switchUi();
 
261
        fillMultiUiSelectionBox();
 
262
}
 
263
 
 
264
void PropertiesDock::addSelection(MapFeature* S)
 
265
{
 
266
        cleanUpUi();
 
267
        QList<MapFeature*>::iterator i = std::find(Selection.begin(),Selection.end(),S);
 
268
        if (i == Selection.end())
 
269
                Selection.push_back(S);
 
270
        FullSelection = Selection;
 
271
        switchUi();
 
272
        fillMultiUiSelectionBox();
 
273
}
 
274
 
 
275
void PropertiesDock::adjustSelection()
 
276
{
 
277
        QList<MapFeature*> aSelection;
 
278
        int cnt = Selection.size();
 
279
 
 
280
        for (int i=0; i<FullSelection.size(); ++i) {
 
281
                if (Main->document()->exists(FullSelection[i])) {
 
282
                        aSelection.push_back(FullSelection[i]);
 
283
                } else {
 
284
                        QList<MapFeature*>::iterator it = std::find(Selection.begin(),Selection.end(),FullSelection[i]);
 
285
                        if (it != Selection.end())
 
286
                                Selection.erase(it);
 
287
                }
 
288
        }
 
289
 
 
290
        FullSelection = aSelection;
 
291
        if (Selection.size() != cnt)
 
292
                switchUi();
 
293
}
 
294
 
 
295
bool PropertiesDock::isSelected(MapFeature *aFeature)
 
296
{
 
297
        QList<MapFeature*>::iterator i = std::find(Selection.begin(),Selection.end(),aFeature);
 
298
        if (i == Selection.end())
 
299
                return false;
 
300
        else
 
301
                return true;
 
302
}
 
303
 
 
304
void PropertiesDock::fillMultiUiSelectionBox()
 
305
{
 
306
        if (NowShowing == MultiShowing)
 
307
        {
 
308
                // to prevent on_SelectionList_itemSelectionChanged to kick in
 
309
                NowShowing = NoUiShowing;
 
310
                Main->setUpdatesEnabled(false);
 
311
                MultiUi.SelectionList->clear();
 
312
                for (int i=0; i<FullSelection.size(); ++i)
 
313
                {
 
314
                        QListWidgetItem* it = new QListWidgetItem(FullSelection[i]->description(),MultiUi.SelectionList);
 
315
                        it->setData(Qt::UserRole,QVariant(i));
 
316
                        it->setSelected(true);
 
317
                }
 
318
                MultiUi.lbStatus->setText(tr("%1/%1 selected item(s)").arg(FullSelection.size()));
 
319
                Main->setUpdatesEnabled(true);
 
320
                NowShowing = MultiShowing;
 
321
        }
 
322
}
 
323
 
 
324
void PropertiesDock::on_SelectionList_itemSelectionChanged()
 
325
{
 
326
        if (NowShowing == MultiShowing)
 
327
        {
 
328
                Selection.clear();
 
329
                for (int i=0; i<FullSelection.size(); ++i)
 
330
                        if (MultiUi.SelectionList->item(i)->isSelected())
 
331
                                Selection.push_back(FullSelection[i]);
 
332
                if (Selection.size() == 1) {
 
333
                        Main->info()->setHtml(Selection[0]->toHtml());
 
334
 
 
335
                        #ifdef GEOIMAGE
 
336
                        TrackPoint *Pt;
 
337
                        if ((Pt = dynamic_cast<TrackPoint*>(Selection[0]))) Main->geoImage()->setImage(Pt);
 
338
                        #endif
 
339
                }
 
340
                theModel->setFeature(Selection);
 
341
                MultiUi.lbStatus->setText(tr("%1/%2 selected item(s)").arg(Selection.size()).arg(FullSelection.size()));
 
342
                Main->view()->update();
 
343
        }
 
344
}
 
345
 
 
346
void PropertiesDock::on_SelectionList_itemDoubleClicked(QListWidgetItem* item)
 
347
{
 
348
        int i=item->data(Qt::UserRole).toUInt();
 
349
        PendingSelectionChange = i;
 
350
        // changing directly from this method would delete the current Ui from
 
351
        // which this slot is called
 
352
        QTimer::singleShot(0,this,SLOT(executePendingSelectionChange()));
 
353
}
 
354
 
 
355
void PropertiesDock::executePendingSelectionChange()
 
356
{
 
357
        if (PendingSelectionChange < FullSelection.size())
 
358
                setSelection(FullSelection[PendingSelectionChange]);
 
359
}
 
360
 
 
361
void PropertiesDock::cleanUpUi()
 
362
{
 
363
        if (NowShowing == RelationUiShowing)
 
364
        {
 
365
                RelationUi.MembersView->setModel(0);
 
366
                Relation* R = dynamic_cast<Relation*>(FullSelection[0]);
 
367
                R->releaseMemberModel();
 
368
        }
 
369
}
 
370
 
 
371
void PropertiesDock::switchUi()
 
372
{
 
373
    if (CurrentTagView)
 
374
        M_PREFS->setTagListFirstColumnWidth(CurrentTagView->columnWidth(0));
 
375
 
 
376
    if (FullSelection.size() == 0)
 
377
                switchToNoUi();
 
378
        else if (FullSelection.size() == 1)
 
379
        {
 
380
                if (CAST_NODE(FullSelection[0]))
 
381
                        switchToTrackPointUi();
 
382
                else if (CAST_WAY(FullSelection[0]))
 
383
                        switchToRoadUi();
 
384
                else if (CAST_RELATION(FullSelection[0]))
 
385
                        switchToRelationUi();
 
386
                else
 
387
                        switchToNoUi();
 
388
        }
 
389
        else
 
390
                switchToMultiUi();
 
391
        resetValues();
 
392
}
 
393
 
 
394
void PropertiesDock::switchToMultiUi()
 
395
{
 
396
        if (NowShowing == MultiShowing) return;
 
397
        NowShowing = MultiShowing;
 
398
        QWidget* NewUi = new QWidget(this);
 
399
        MultiUi.setupUi(NewUi);
 
400
        MultiUi.TagView->verticalHeader()->hide();
 
401
        MultiUi.SelectionList->setContextMenuPolicy(Qt::CustomContextMenu);
 
402
        MultiUi.lbStatus->setText(tr("Selected items"));
 
403
        setWidget(NewUi);
 
404
        if (CurrentUi)
 
405
                CurrentUi->deleteLater();
 
406
        CurrentUi = NewUi;
 
407
        connect(MultiUi.RemoveTagButton,SIGNAL(clicked()),this, SLOT(on_RemoveTagButton_clicked()));
 
408
        connect(MultiUi.SelectionList,SIGNAL(itemSelectionChanged()),this,SLOT(on_SelectionList_itemSelectionChanged()));
 
409
        connect(MultiUi.SelectionList,SIGNAL(itemDoubleClicked(QListWidgetItem*)),this,SLOT(on_SelectionList_itemDoubleClicked(QListWidgetItem*)));
 
410
        connect(MultiUi.SelectionList, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(on_SelectionList_customContextMenuRequested(const QPoint &)));
 
411
        setWindowTitle(tr("Properties - Multiple elements"));
 
412
}
 
413
 
 
414
void PropertiesDock::switchToTrackPointUi()
 
415
{
 
416
        NowShowing = TrackPointUiShowing;
 
417
        QWidget* NewUi = new QWidget(this);
 
418
        TrackPointUi.setupUi(NewUi);
 
419
        TrackPointUi.TagView->verticalHeader()->hide();
 
420
        setWidget(NewUi);
 
421
        if (CurrentUi)
 
422
                CurrentUi->deleteLater();
 
423
        CurrentUi = NewUi;
 
424
        connect(TrackPointUi.Longitude,SIGNAL(editingFinished()),this, SLOT(on_TrackPointLon_editingFinished()));
 
425
        connect(TrackPointUi.Latitude,SIGNAL(editingFinished()),this, SLOT(on_TrackPointLat_editingFinished()));
 
426
        connect(TrackPointUi.RemoveTagButton,SIGNAL(clicked()),this, SLOT(on_RemoveTagButton_clicked()));
 
427
        setWindowTitle(tr("Properties - Trackpoint"));
 
428
}
 
429
 
 
430
void PropertiesDock::switchToRoadUi()
 
431
{
 
432
        NowShowing = RoadUiShowing;
 
433
        QWidget* NewUi = new QWidget(this);
 
434
        RoadUi.setupUi(NewUi);
 
435
        RoadUi.TagView->verticalHeader()->hide();
 
436
        setWidget(NewUi);
 
437
        if (CurrentUi)
 
438
                CurrentUi->deleteLater();
 
439
        CurrentUi = NewUi;
 
440
        connect(RoadUi.RemoveTagButton,SIGNAL(clicked()),this, SLOT(on_RemoveTagButton_clicked()));
 
441
        setWindowTitle(tr("Properties - Road"));
 
442
}
 
443
 
 
444
void PropertiesDock::switchToRelationUi()
 
445
{
 
446
        NowShowing = RelationUiShowing;
 
447
        QWidget* NewUi = new QWidget(this);
 
448
        RelationUi.setupUi(NewUi);
 
449
        RelationUi.TagView->verticalHeader()->hide();
 
450
        setWidget(NewUi);
 
451
        if (CurrentUi)
 
452
                CurrentUi->deleteLater();
 
453
        CurrentUi = NewUi;
 
454
        RelationUi.MembersView->setContextMenuPolicy(Qt::CustomContextMenu);
 
455
        connect(RelationUi.MembersView, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(on_Member_customContextMenuRequested(const QPoint &)));
 
456
        connect(RelationUi.MembersView, SIGNAL(clicked(QModelIndex)), this, SLOT(on_Member_clicked(QModelIndex)));
 
457
        connect(RelationUi.RemoveMemberButton,SIGNAL(clicked()),this, SLOT(on_RemoveMemberButton_clicked()));
 
458
        connect(RelationUi.RemoveTagButton,SIGNAL(clicked()),this, SLOT(on_RemoveTagButton_clicked()));
 
459
        setWindowTitle(tr("Properties - Relation"));
 
460
}
 
461
 
 
462
void PropertiesDock::switchToNoUi()
 
463
{
 
464
        if (NowShowing == NoUiShowing) return;
 
465
        NowShowing = NoUiShowing;
 
466
        QWidget* NewUi = new QWidget(this);
 
467
        setWidget(NewUi);
 
468
        if (CurrentUi)
 
469
                CurrentUi->deleteLater();
 
470
        CurrentUi = NewUi;
 
471
        setWindowTitle(tr("Properties"));
 
472
}
 
473
 
 
474
void PropertiesDock::resetValues()
 
475
{
 
476
        Highlighted.clear();
 
477
 
 
478
        // Tables that might need column sizing
 
479
    CurrentTagView = NULL;
 
480
    CurrentMembersView = NULL;
 
481
 
 
482
        // to prevent slots to change the values also
 
483
        QList<MapFeature*> Current = Selection;
 
484
        Selection.clear();
 
485
        if (FullSelection.size() == 1)
 
486
        {
 
487
                Main->info()->setHtml(FullSelection[0]->toHtml());
 
488
 
 
489
                TrackPoint* Pt = dynamic_cast<TrackPoint*>(FullSelection[0]);
 
490
                Road* R = dynamic_cast<Road*>(FullSelection[0]);
 
491
                Relation* L = dynamic_cast<Relation*>(FullSelection[0]);
 
492
 
 
493
                if ((Pt) && (NowShowing == TrackPointUiShowing))
 
494
                {
 
495
                        TrackPointUi.Id->setText(Pt->id());
 
496
                        TrackPointUi.Latitude->setText(QString::number(intToAng(Pt->position().lat()),'g',8));
 
497
                        TrackPointUi.Longitude->setText(QString::number(intToAng(Pt->position().lon()),'g',8));
 
498
                        TrackPointUi.TagView->setModel(theModel);
 
499
                        TrackPointUi.TagView->setItemDelegate(delegate);
 
500
 
 
501
                        QWidget* w;
 
502
                        for (int i=0; i<TrackPointUi.variableLayout->count(); ++i) {
 
503
                                w = TrackPointUi.variableLayout->itemAt(i)->widget();
 
504
                                if (w) {
 
505
                                        w->hide();
 
506
                                        w->deleteLater();
 
507
                                }
 
508
                        }
 
509
                        if (theTemplates) {
 
510
                                w = theTemplates->getWidget(Pt);
 
511
                                w->installEventFilter(shortcutFilter);
 
512
                                TrackPointUi.variableLayout->addWidget(w);
 
513
                        }
 
514
 
 
515
                        CurrentTagView = TrackPointUi.TagView;
 
516
 
 
517
                        #ifdef GEOIMAGE
 
518
                        Main->geoImage()->setImage(Pt);
 
519
                        #endif
 
520
                }
 
521
                else if ((R) && (NowShowing == RoadUiShowing))
 
522
                {
 
523
                        RoadUi.Id->setText(R->id());
 
524
                        //RoadUi.Name->setText(R->tagValue("name",""));
 
525
                        RoadUi.TagView->setModel(theModel);
 
526
                        RoadUi.TagView->setItemDelegate(delegate);
 
527
 
 
528
                        QWidget* w;
 
529
                        for (int i=0; i<RoadUi.variableLayout->count(); ++i) {
 
530
                                w = RoadUi.variableLayout->itemAt(i)->widget();
 
531
                                if (w) {
 
532
                                        w->hide();
 
533
                                        w->deleteLater();
 
534
                                }
 
535
                        }
 
536
                        if (theTemplates) {
 
537
                                w = theTemplates->getWidget(R);
 
538
                                w->installEventFilter(shortcutFilter);
 
539
                                RoadUi.variableLayout->addWidget(w);
 
540
                        }
 
541
 
 
542
                        CurrentTagView = RoadUi.TagView;
 
543
                }
 
544
                else if ((L) && (NowShowing == RelationUiShowing))
 
545
                {
 
546
                        RelationUi.MembersView->setModel(L->referenceMemberModel(Main));
 
547
                        RelationUi.TagView->setModel(theModel);
 
548
                        RelationUi.TagView->setItemDelegate(delegate);
 
549
 
 
550
                        QWidget* w;
 
551
                        for (int i=0; i<RelationUi.variableLayout->count(); ++i) {
 
552
                                w = RelationUi.variableLayout->itemAt(i)->widget();
 
553
                                if (w) {
 
554
                                        w->hide();
 
555
                                        w->deleteLater();
 
556
                                }
 
557
                        }
 
558
                        if (theTemplates) {
 
559
                                w = theTemplates->getWidget(L);
 
560
                                w->installEventFilter(shortcutFilter);
 
561
                                RelationUi.variableLayout->addWidget(w);
 
562
                        }
 
563
                        
 
564
                        CurrentTagView     = RelationUi.TagView;
 
565
                        CurrentMembersView = RelationUi.MembersView;
 
566
                }
 
567
 
 
568
                if (theTemplates)
 
569
                        theTemplates->apply(FullSelection[0]);
 
570
        }
 
571
        else if ((FullSelection.size() > 1)  && (NowShowing == MultiShowing))
 
572
        {
 
573
                Main->info()->setHtml("");
 
574
                #ifdef GEOIMAGE
 
575
                Main->geoImage()->setImage((TrackPoint *)NULL);
 
576
                #endif
 
577
                MultiUi.TagView->setModel(theModel);
 
578
                MultiUi.TagView->setItemDelegate(delegate);
 
579
                CurrentTagView = MultiUi.TagView;
 
580
        }
 
581
        theModel->setFeature(Current);
 
582
        Selection = Current;
 
583
        
 
584
        /* If we have standard TableViews in the current UI, set it so that the */
 
585
        /* first column is the width of the default text (Edit this to add...)  */
 
586
        /* And the rest of the space is assigned to the second column           */
 
587
    if (CurrentTagView) {
 
588
        if (M_PREFS->getTagListFirstColumnWidth())
 
589
            CurrentTagView->setColumnWidth(
 
590
                0, M_PREFS->getTagListFirstColumnWidth()
 
591
            );
 
592
        else
 
593
            CurrentTagView->setColumnWidth(
 
594
                0, CurrentTagView->fontMetrics().width(theModel->newKeyText())+10
 
595
            );
 
596
                CurrentTagView->horizontalHeader()->setStretchLastSection(true);
 
597
                CurrentTagView->installEventFilter(shortcutFilter);
 
598
        }
 
599
        if (CurrentMembersView) {
 
600
                CurrentMembersView->setColumnWidth(
 
601
                        0, CurrentMembersView->fontMetrics().width(theModel->newKeyText())+10
 
602
                );
 
603
                CurrentMembersView->horizontalHeader()->setStretchLastSection(true);
 
604
                CurrentMembersView->installEventFilter(shortcutFilter);
 
605
        }
 
606
}
 
607
 
 
608
void PropertiesDock::on_TrackPointLat_editingFinished()
 
609
{
 
610
        if (TrackPointUi.Latitude->text().isEmpty()) return;
 
611
        TrackPoint* Pt = dynamic_cast<TrackPoint*>(selection(0));
 
612
        if (Pt)
 
613
        {
 
614
                Main->document()->addHistory(
 
615
                        new MoveTrackPointCommand(Pt,
 
616
                                Coord(angToInt(TrackPointUi.Latitude->text().toDouble()),Pt->position().lon()), Main->document()->getDirtyOrOriginLayer(Pt->layer()) ));
 
617
                Main->invalidateView(false);
 
618
        }
 
619
}
 
620
 
 
621
void PropertiesDock::on_TrackPointLon_editingFinished()
 
622
{
 
623
        if (TrackPointUi.Longitude->text().isEmpty()) return;
 
624
        TrackPoint* Pt = dynamic_cast<TrackPoint*>(selection(0));
 
625
        if (Pt)
 
626
        {
 
627
                Main->document()->addHistory(
 
628
                        new MoveTrackPointCommand(Pt,
 
629
                                Coord(Pt->position().lat(),angToInt(TrackPointUi.Longitude->text().toDouble())), Main->document()->getDirtyOrOriginLayer(Pt->layer()) ));
 
630
                Main->invalidateView(false);
 
631
        }
 
632
}
 
633
 
 
634
void PropertiesDock::on_tag_changed(QString k, QString v)
 
635
{
 
636
        MapFeature* F = FullSelection[0];
 
637
        if (F->tagValue(k, "__NULL__") != v) {
 
638
                Main->document()->addHistory(new SetTagCommand(F,k,v,Main->document()->getDirtyOrOriginLayer(F->layer())));
 
639
                Main->invalidateView();
 
640
        }
 
641
}
 
642
 
 
643
void PropertiesDock::on_tag_cleared(QString k)
 
644
{
 
645
        MapFeature* F = FullSelection[0];
 
646
        Main->document()->addHistory(new ClearTagCommand(F,k,Main->document()->getDirtyOrOriginLayer(F->layer())));
 
647
        Main->invalidateView();
 
648
}
 
649
 
 
650
void PropertiesDock::on_RemoveTagButton_clicked()
 
651
{
 
652
        QTableView* TagTable = 0;
 
653
        switch (NowShowing)
 
654
        {
 
655
        case TrackPointUiShowing:
 
656
                TagTable = TrackPointUi.TagView; break;
 
657
        case RoadUiShowing:
 
658
                TagTable = RoadUi.TagView; break;
 
659
        case MultiShowing:
 
660
                TagTable = MultiUi.TagView; break;
 
661
        case RelationUiShowing:
 
662
                TagTable = RelationUi.TagView; break;
 
663
        default: break;
 
664
        }
 
665
        if (TagTable)
 
666
        {
 
667
                QModelIndexList indexes = TagTable->selectionModel()->selectedIndexes();
 
668
                QModelIndex index;
 
669
 
 
670
                foreach(index, indexes)
 
671
                {
 
672
                        QModelIndex idx = index.sibling(index.row(),0);
 
673
                        QVariant Content(theModel->data(idx,Qt::DisplayRole));
 
674
                        if (Content.isValid())
 
675
                        {
 
676
                                QString KeyName = Content.toString();
 
677
                                CommandList* L = new CommandList(MainWindow::tr("Clear Tag '%1' on %2").arg(KeyName).arg(Selection[0]->id()), Selection[0]);
 
678
                                for (int i=0; i<Selection.size(); ++i)
 
679
                                        if (Selection[i]->findKey(KeyName) < Selection[i]->tagSize())
 
680
                                                L->add(new ClearTagCommand(Selection[i],KeyName,Main->document()->getDirtyOrOriginLayer(Selection[i]->layer())));
 
681
                                if (L->empty())
 
682
                                        delete L;
 
683
                                else
 
684
                                {
 
685
                                        Main->document()->addHistory(L);
 
686
                                        Main->invalidateView();
 
687
                                        return;
 
688
                                }
 
689
                        }
 
690
                }
 
691
        }
 
692
}
 
693
 
 
694
void PropertiesDock::on_RemoveMemberButton_clicked()
 
695
{
 
696
        if (CurrentMembersView)
 
697
        {
 
698
                Relation* R = dynamic_cast<Relation*>(Selection[0]);
 
699
                if (R) {
 
700
                        QModelIndexList indexes = CurrentMembersView->selectionModel()->selectedIndexes();
 
701
                        QModelIndex index;
 
702
 
 
703
                        foreach(index, indexes)
 
704
                        {
 
705
                                QModelIndex idx = index.sibling(index.row(),0);
 
706
                                QVariant Content(R->referenceMemberModel(Main)->data(idx,Qt::UserRole));
 
707
                                if (Content.isValid())
 
708
                                {
 
709
                                        MapFeature* F = Content.value<MapFeature*>();
 
710
                                        if (F) {
 
711
                                                CommandList* L = new CommandList(MainWindow::tr("Remove member '%1' on %2").arg(F->description()).arg(R->description()), R);
 
712
                                                if (R->find(F) < R->size())
 
713
                                                        L->add(new RelationRemoveFeatureCommand(R,F,Main->document()->getDirtyOrOriginLayer(R->layer())));
 
714
                                                if (L->empty())
 
715
                                                        delete L;
 
716
                                                else
 
717
                                                {
 
718
                                                        Main->document()->addHistory(L);
 
719
                                                        Main->invalidateView();
 
720
                                                        return;
 
721
                                                }
 
722
                                        }
 
723
                                }
 
724
                        }
 
725
                }
 
726
        }
 
727
}
 
728
 
 
729
void PropertiesDock::on_Member_customContextMenuRequested(const QPoint & pos)
 
730
{
 
731
        QModelIndex ix = CurrentMembersView->indexAt(pos);
 
732
        if (ix.isValid()) {
 
733
                QMenu menu(CurrentMembersView);
 
734
                menu.addAction(centerAction);
 
735
                menu.addAction(centerZoomAction);
 
736
                menu.addAction(selectAction);
 
737
                menu.exec(CurrentMembersView->mapToGlobal(pos));
 
738
        }
 
739
}
 
740
 
 
741
void PropertiesDock::on_Member_clicked(const QModelIndex & index)
 
742
{
 
743
        Highlighted.clear();
 
744
 
 
745
        Relation* R = dynamic_cast<Relation*>(Selection[0]);
 
746
        if (R) {
 
747
                QVariant Content(R->referenceMemberModel(Main)->data(index,Qt::UserRole));
 
748
                if (Content.isValid())
 
749
                {
 
750
                        MapFeature* F = Content.value<MapFeature*>();
 
751
                        if (F)
 
752
                                Highlighted.push_back(F);
 
753
                }
 
754
        }
 
755
        Main->view()->update();
 
756
}
 
757
 
 
758
void PropertiesDock::on_Member_selected()
 
759
{
 
760
        Relation* R = dynamic_cast<Relation*>(Selection[0]);
 
761
        if (R) {
 
762
                QModelIndexList indexes = CurrentMembersView->selectionModel()->selectedIndexes();
 
763
                QModelIndex index;
 
764
 
 
765
                foreach(index, indexes)
 
766
                {
 
767
                        QModelIndex idx = index.sibling(index.row(),0);
 
768
                        QVariant Content(R->referenceMemberModel(Main)->data(idx,Qt::UserRole));
 
769
                        if (Content.isValid())
 
770
                        {
 
771
                                MapFeature* F = Content.value<MapFeature*>();
 
772
                                if (F) {
 
773
                                        setSelection(F);
 
774
                                }
 
775
                        }
 
776
                }
 
777
        }
 
778
        Main->invalidateView(false);
 
779
}
 
780
 
 
781
void PropertiesDock::on_SelectionList_customContextMenuRequested(const QPoint & pos)
 
782
{
 
783
        QListWidgetItem *it = MultiUi.SelectionList->itemAt(pos);
 
784
        if (it) {
 
785
                QMenu menu(MultiUi.SelectionList);
 
786
                menu.addAction(centerAction);
 
787
                menu.addAction(centerZoomAction);
 
788
                menu.exec(MultiUi.SelectionList->mapToGlobal(pos));
 
789
        }
 
790
}
 
791
 
 
792
void PropertiesDock::on_centerAction_triggered()
 
793
{
 
794
        CoordBox cb;
 
795
        if (CurrentMembersView)
 
796
        {
 
797
                Relation* R = dynamic_cast<Relation*>(Selection[0]);
 
798
                if (R) {
 
799
                        QModelIndexList indexes = CurrentMembersView->selectionModel()->selectedIndexes();
 
800
                        QModelIndex index;
 
801
 
 
802
                        foreach(index, indexes)
 
803
                        {
 
804
                                QModelIndex idx = index.sibling(index.row(),0);
 
805
                                QVariant Content(R->referenceMemberModel(Main)->data(idx,Qt::UserRole));
 
806
                                if (Content.isValid())
 
807
                                {
 
808
                                        MapFeature* F = Content.value<MapFeature*>();
 
809
                                        if (F) {
 
810
                                                //setSelection(F);
 
811
                                                cb = F->boundingBox();
 
812
                                        }
 
813
                                }
 
814
                        }
 
815
                }
 
816
        } else
 
817
        if (CurrentTagView) {
 
818
                Main->setUpdatesEnabled(false);
 
819
                int idx = MultiUi.SelectionList->selectedItems()[0]->data(Qt::UserRole).toUInt();
 
820
                cb = FullSelection[idx]->boundingBox();
 
821
                for (int i=1; i < MultiUi.SelectionList->selectedItems().size(); i++) {
 
822
                        idx = MultiUi.SelectionList->selectedItems()[i]->data(Qt::UserRole).toUInt();
 
823
                        cb.merge(FullSelection[idx]->boundingBox());
 
824
                }
 
825
        }
 
826
        Coord c = cb.center();
 
827
        Main->view()->setCenter(c, Main->view()->rect());
 
828
        Main->setUpdatesEnabled(true);
 
829
        Main->invalidateView(false);
 
830
}
 
831
 
 
832
void PropertiesDock::on_centerZoomAction_triggered()
 
833
{
 
834
        CoordBox cb;
 
835
        if (CurrentMembersView)
 
836
        {
 
837
                Relation* R = dynamic_cast<Relation*>(Selection[0]);
 
838
                if (R) {
 
839
                        QModelIndexList indexes = CurrentMembersView->selectionModel()->selectedIndexes();
 
840
                        QModelIndex index;
 
841
 
 
842
                        foreach(index, indexes)
 
843
                        {
 
844
                                QModelIndex idx = index.sibling(index.row(),0);
 
845
                                QVariant Content(R->referenceMemberModel(Main)->data(idx,Qt::UserRole));
 
846
                                if (Content.isValid())
 
847
                                {
 
848
                                        MapFeature* F = Content.value<MapFeature*>();
 
849
                                        if (F) {
 
850
                                                //setSelection(F);
 
851
                                                cb = F->boundingBox();
 
852
                                                CoordBox mini(cb.center()-2000, cb.center()+2000);
 
853
                                                cb.merge(mini);
 
854
                                                cb = cb.zoomed(1.1);
 
855
                                        }
 
856
                                }
 
857
                        }
 
858
                }
 
859
        } else
 
860
        if (CurrentTagView) {
 
861
                Main->setUpdatesEnabled(false);
 
862
                int idx = MultiUi.SelectionList->selectedItems()[0]->data(Qt::UserRole).toUInt();
 
863
                cb = FullSelection[idx]->boundingBox();
 
864
                for (int i=1; i < MultiUi.SelectionList->selectedItems().size(); i++) {
 
865
                        idx = MultiUi.SelectionList->selectedItems()[i]->data(Qt::UserRole).toUInt();
 
866
                        cb.merge(FullSelection[idx]->boundingBox());
 
867
                }
 
868
                CoordBox mini(cb.center()-2000, cb.center()+2000);
 
869
                cb.merge(mini);
 
870
                cb = cb.zoomed(1.1);
 
871
        }
 
872
        Main->view()->setViewport(cb, Main->view()->rect());
 
873
        Main->setUpdatesEnabled(true);
 
874
        Main->invalidateView(false);
 
875
}
 
876
 
 
877
bool PropertiesDock::loadTemplates(const QString& filename)
 
878
{
 
879
        SAFE_DELETE(theTemplates);
 
880
 
 
881
        QFile File;
 
882
        if (!filename.isEmpty())
 
883
                File.setFileName(filename);
 
884
        else
 
885
                File.setFileName(M_PREFS->getDefaultTemplate());
 
886
 
 
887
        if (!File.open(QIODevice::ReadOnly)) {
 
888
                QMessageBox::warning(Main,"Template read error", "Error reading template file");
 
889
                return false;
 
890
        }
 
891
 
 
892
        QDomDocument DomDoc;
 
893
        QString ErrorStr;
 
894
        int ErrorLine;
 
895
        int ErrorColumn;
 
896
 
 
897
        if (!DomDoc.setContent(&File, true, &ErrorStr, &ErrorLine,&ErrorColumn))
 
898
        {
 
899
                File.close();
 
900
                QMessageBox::warning(Main,"Parse error",
 
901
                        QString("Parse error at line %1, column %2:\n%3")
 
902
                                  .arg(ErrorLine)
 
903
                                  .arg(ErrorColumn)
 
904
                                  .arg(ErrorStr));
 
905
                return false;
 
906
        }
 
907
 
 
908
        QDomElement root = DomDoc.documentElement();
 
909
        theTemplates = TagTemplates::fromXml(root);
 
910
        if (theTemplates) {
 
911
                connect(theTemplates, SIGNAL(tagChanged(QString, QString)), this, SLOT(on_tag_changed(QString, QString)));
 
912
                connect(theTemplates, SIGNAL(tagCleared(QString)), this, SLOT(on_tag_cleared(QString)));
 
913
                connect(theTemplates, SIGNAL(templateChanged(TagTemplate*)), this, SLOT(on_template_changed(TagTemplate*)));
 
914
        } else {
 
915
                QMessageBox::warning(Main,"Template read error", "Error parsing template file");
 
916
                return false;
 
917
        }
 
918
 
 
919
        return true;
 
920
}
 
921
 
 
922
bool PropertiesDock::mergeTemplates(const QString& filename)
 
923
{
 
924
        QFile File;
 
925
        if (!filename.isEmpty())
 
926
                File.setFileName(filename);
 
927
        else
 
928
                return false;
 
929
 
 
930
        if (!File.open(QIODevice::ReadOnly)) {
 
931
                QMessageBox::warning(Main,"Template read error", "Error reading template file");
 
932
                return false;
 
933
        }
 
934
 
 
935
        QDomDocument DomDoc;
 
936
        QString ErrorStr;
 
937
        int ErrorLine;
 
938
        int ErrorColumn;
 
939
 
 
940
        if (!DomDoc.setContent(&File, true, &ErrorStr, &ErrorLine,&ErrorColumn))
 
941
        {
 
942
                File.close();
 
943
                QMessageBox::warning(Main,"Parse error",
 
944
                        QString("Parse error at line %1, column %2:\n%3")
 
945
                                                                  .arg(ErrorLine)
 
946
                                                                  .arg(ErrorColumn)
 
947
                                                                  .arg(ErrorStr));
 
948
                return false;
 
949
        }
 
950
 
 
951
        QDomElement root = DomDoc.documentElement();
 
952
        if (!theTemplates->mergeXml(root)) {
 
953
                QMessageBox::warning(Main,"Template read error", "Error parsing template file");
 
954
                return false;
 
955
        }
 
956
 
 
957
        return true;
 
958
}
 
959
 
 
960
bool PropertiesDock::saveTemplates(const QString& filename)
 
961
{
 
962
        if (!theTemplates)
 
963
                return false;
 
964
 
 
965
        QDomDocument theXmlDoc;
 
966
        theXmlDoc.appendChild(theXmlDoc.createProcessingInstruction("xml", "version=\"1.0\""));
 
967
 
 
968
        if (!theTemplates->toXML(theXmlDoc)) {
 
969
                QMessageBox::warning(Main,"Tag templates write error", "Unable to generate XML document");
 
970
                return false;
 
971
        }
 
972
 
 
973
        QFile File(filename);
 
974
        if (!File.open(QIODevice::WriteOnly)) {
 
975
                QMessageBox::warning(Main,"Tag templates write error", "Error opening template file for writing");
 
976
                return false;
 
977
        }
 
978
        File.write(theXmlDoc.toString().toUtf8());
 
979
 
 
980
        return true;
 
981
}
 
982
 
 
983
void PropertiesDock::on_template_changed(TagTemplate* /* aNewTemplate */)
 
984
{
 
985
        resetValues();
 
986
}
 
987
 
 
988
void PropertiesDock::changeEvent(QEvent * event)
 
989
{
 
990
        if (event->type() == QEvent::LanguageChange)
 
991
                retranslateUi();
 
992
        MDockAncestor::changeEvent(event);
 
993
}
 
994
 
 
995
void PropertiesDock::retranslateUi()
 
996
{
 
997
        setWindowTitle(tr("Properties"));
 
998
        centerAction->setText(tr("Center map"));
 
999
        centerZoomAction->setText(tr("Center && Zoom map"));
 
1000
        selectAction->setText(tr("Select member"));
 
1001
}
 
1002
 
 
1003
int PropertiesDock::highlightedSize() const
 
1004
{
 
1005
        if (!isVisible())
 
1006
                return 0;
 
1007
        return Highlighted.size();
 
1008
}
 
1009
 
 
1010
MapFeature* PropertiesDock::highlighted(int idx)
 
1011
{
 
1012
        if (idx < Highlighted.size())
 
1013
                return Highlighted[idx];
 
1014
        return 0;
 
1015
}
 
1016
 
 
1017
QList<MapFeature*> PropertiesDock::highlighted()
 
1018
{
 
1019
        return Highlighted;
 
1020
}
 
1021