source: subversion/applications/editors/merkaartor/PropertiesDock.cpp @ 13954

Last change on this file since 13954 was 13926, checked in by schluessler, 11 years ago

FIX : If there is only one opened layer, GeoImage? uses it automatically (without asking the user) (fixes #1450)
FIX : Long image filenames are cutted to fit the GeoImageDock? (fixes #1452)
FIX : ImageView? in GeoImageDock? draws images using an antialiasing painter and images are not copied when displaying them which results in faster drawing. (fixes #1452)
FIX : Much better zoom (and image-moving) for ImageView? in GeoImageDock?
FIX : trackpoints which are associated with an image are highlighted according to the Style's settings (but not by painting an reactangle in paintEvent manually)

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