1 // SPDX-License-Identifier: LGPL-2.1-or-later
2 //
3 // SPDX-FileCopyrightText: 2010 Bastian Holst <bastianholst@gmx.de>
4 //
5 
6 // Self
7 #include "FileViewWidget.h"
8 
9 // Qt
10 #include <QFileDialog>
11 #include <QMenu>
12 #include <QAction>
13 #include <QPointer>
14 
15 // Marble
16 #include "GeoDataLatLonAltBox.h"
17 #include "GeoDataContainer.h"
18 #include "GeoDataDocument.h"
19 #include "GeoDataDocumentWriter.h"
20 #include "GeoDataPlacemark.h"
21 #include "GeoDataTreeModel.h"
22 #include "FileManager.h"
23 #include "KmlElementDictionary.h"
24 #include "MarblePlacemarkModel.h"
25 #include "MarbleModel.h"
26 #include "MarbleWidget.h"
27 #include "TreeViewDecoratorModel.h"
28 #include "EditPlacemarkDialog.h"
29 
30 using namespace Marble;
31 // Ui
32 #include "ui_FileViewWidget.h"
33 
34 namespace Marble
35 {
36 
37 class FileViewWidgetPrivate
38 {
39 
40  public:
41     explicit FileViewWidgetPrivate( FileViewWidget *parent );
42     void setTreeModel( GeoDataTreeModel *model );
43     void setFileManager( FileManager *manager );
44 
45 
46  public Q_SLOTS:
47     void saveFile();
48     void closeFile();
49     void enableFileViewActions();
50     void contextMenu(const QPoint &pt);
51     void showPlacemarkDialog();
52 
53  public:
54     FileViewWidget *q;
55     Ui::FileViewWidget  m_fileViewUi;
56     MarbleWidget *m_widget;
57     TreeViewDecoratorModel m_treeSortProxy;
58     FileManager *m_fileManager;
59 
60     QMenu *m_contextMenu;
61     QAction *m_viewPropertiesAction;
62 };
63 
FileViewWidgetPrivate(FileViewWidget * parent)64 FileViewWidgetPrivate::FileViewWidgetPrivate( FileViewWidget *parent )
65     :q( parent ),
66     m_widget( nullptr ),
67     m_fileManager( nullptr )
68 {
69     m_contextMenu = new QMenu(q);
70     m_viewPropertiesAction = new QAction(q);
71     m_viewPropertiesAction->setText(QObject::tr("View Properties"));
72     m_contextMenu->addAction(m_viewPropertiesAction);
73     QObject::connect(m_viewPropertiesAction, SIGNAL(triggered()),
74                      q, SLOT(showPlacemarkDialog()));
75 }
76 
FileViewWidget(QWidget * parent,Qt::WindowFlags f)77 FileViewWidget::FileViewWidget( QWidget *parent, Qt::WindowFlags f )
78     : QWidget( parent, f ),
79       d( new FileViewWidgetPrivate( this ) )
80 {
81     d->m_fileViewUi.setupUi( this );
82     layout()->setMargin( 0 );
83 }
84 
~FileViewWidget()85 FileViewWidget::~FileViewWidget()
86 {
87     delete d;
88 }
89 
setMarbleWidget(MarbleWidget * widget)90 void FileViewWidget::setMarbleWidget( MarbleWidget *widget )
91 {
92     d->m_widget = widget;
93     d->setTreeModel( d->m_widget->model()->treeModel() );
94     d->setFileManager( d->m_widget->model()->fileManager() );
95 
96     connect( this, SIGNAL(centerOn(GeoDataPlacemark,bool)),
97              d->m_widget, SLOT(centerOn(GeoDataPlacemark,bool)) );
98     connect( this, SIGNAL(centerOn(GeoDataLatLonBox,bool)),
99              d->m_widget, SLOT(centerOn(GeoDataLatLonBox,bool)) );
100 }
101 
setTreeModel(GeoDataTreeModel * model)102 void FileViewWidgetPrivate::setTreeModel( GeoDataTreeModel *model )
103 {
104     m_treeSortProxy.setSourceModel( model );
105     m_treeSortProxy.setDynamicSortFilter( true );
106     m_fileViewUi.m_treeView->setModel( &m_treeSortProxy );
107     m_fileViewUi.m_treeView->setSortingEnabled( true );
108     m_fileViewUi.m_treeView->sortByColumn( 0, Qt::AscendingOrder );
109     m_fileViewUi.m_treeView->resizeColumnToContents( 0 );
110     m_fileViewUi.m_treeView->resizeColumnToContents( 1 );
111     m_fileViewUi.m_treeView->setContextMenuPolicy(Qt::CustomContextMenu);
112 
113     QObject::connect( m_fileViewUi.m_treeView,
114              SIGNAL(expanded(QModelIndex)),
115              &m_treeSortProxy, SLOT(trackExpandedState(QModelIndex)) );
116     QObject::connect( m_fileViewUi.m_treeView,
117              SIGNAL(collapsed(QModelIndex)),
118              &m_treeSortProxy, SLOT(trackCollapsedState(QModelIndex)) );
119     QObject::connect( m_fileViewUi.m_treeView->selectionModel(),
120              SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
121              q, SLOT(enableFileViewActions()) );
122     QObject::connect( m_fileViewUi.m_treeView, SIGNAL(activated(QModelIndex)),
123              q, SLOT(mapCenterOnTreeViewModel(QModelIndex)) );
124     QObject::connect( m_fileViewUi.m_treeView, SIGNAL(customContextMenuRequested(QPoint)),
125                       q, SLOT(contextMenu(QPoint)) );
126 }
127 
setFileManager(FileManager * manager)128 void FileViewWidgetPrivate::setFileManager( FileManager *manager )
129 {
130     m_fileManager = manager;
131     QObject::connect( m_fileViewUi.m_saveButton,  SIGNAL(clicked()) ,
132              q, SLOT(saveFile()) );
133     QObject::connect( m_fileViewUi.m_closeButton, SIGNAL(clicked()) ,
134              q, SLOT(closeFile()) );
135 }
136 
saveFile()137 void FileViewWidgetPrivate::saveFile()
138 {
139     QModelIndex index = m_fileViewUi.m_treeView->selectionModel()->selectedRows().first();
140     const GeoDataObject *object
141         = index.model()->data( index, MarblePlacemarkModel::ObjectPointerRole ).value<GeoDataObject*>();
142     const GeoDataDocument *document = geodata_cast<GeoDataDocument>(object);
143     if ( document && !document->fileName().isEmpty() ) {
144         const QString saveFileName = QFileDialog::getSaveFileName(q, QObject::tr("Select filename for KML document"));
145         GeoDataDocumentWriter::write(saveFileName, *document, kml::kmlTag_nameSpaceOgc22);
146     }
147 }
148 
closeFile()149 void FileViewWidgetPrivate::closeFile()
150 {
151     QModelIndex index = m_fileViewUi.m_treeView->selectionModel()->selectedRows().first();
152     GeoDataObject *object
153         = index.model()->data( index, MarblePlacemarkModel::ObjectPointerRole ).value<GeoDataObject*>();
154     GeoDataDocument *document = geodata_cast<GeoDataDocument>(object);
155     if ( document ) {
156         m_fileManager->closeFile( document );
157     }
158 }
159 
enableFileViewActions()160 void FileViewWidgetPrivate::enableFileViewActions()
161 {
162     bool isUserDocument = false;
163     if ( !m_fileViewUi.m_treeView->selectionModel()->selectedRows().isEmpty() ) {
164         QModelIndex index = m_fileViewUi.m_treeView->selectionModel()->selectedRows().first();
165         const GeoDataObject *object
166             = index.model()->data( index, MarblePlacemarkModel::ObjectPointerRole ).value<GeoDataObject*>();
167         const GeoDataDocument *document = geodata_cast<GeoDataDocument>(object);
168         if ( document ) {
169             isUserDocument = document->documentRole() == Marble::UserDocument;
170         }
171     }
172     m_fileViewUi.m_saveButton->setEnabled( isUserDocument );
173     m_fileViewUi.m_closeButton->setEnabled( isUserDocument );
174 }
175 
contextMenu(const QPoint & pt)176 void FileViewWidgetPrivate::contextMenu(const QPoint &pt)
177 {
178     const QModelIndex index = m_fileViewUi.m_treeView->indexAt(pt);
179     const QAbstractItemModel *model = m_fileViewUi.m_treeView->model();
180     if (index.isValid()) {
181         const GeoDataObject *obj = model->data(index, MarblePlacemarkModel::ObjectPointerRole).value<GeoDataObject*>();
182         const GeoDataPlacemark *placemark = geodata_cast<GeoDataPlacemark>(obj);
183 
184         if (placemark) {
185             m_contextMenu->popup(m_fileViewUi.m_treeView->mapToGlobal(pt));
186         }
187     }
188 }
189 
showPlacemarkDialog()190 void FileViewWidgetPrivate::showPlacemarkDialog()
191 {
192     const QModelIndex index = m_fileViewUi.m_treeView->currentIndex();
193     const QAbstractItemModel *model = m_fileViewUi.m_treeView->model();
194 
195     GeoDataObject *obj = model->data(index, MarblePlacemarkModel::ObjectPointerRole).value<GeoDataObject*>();
196     GeoDataPlacemark *placemark = geodata_cast<GeoDataPlacemark>(obj);
197     if (placemark) {
198         QPointer<EditPlacemarkDialog> dialog = new EditPlacemarkDialog(placemark, nullptr, q);
199         dialog->setReadOnly(true);
200         dialog->exec();
201         delete dialog;
202     }
203 }
204 
mapCenterOnTreeViewModel(const QModelIndex & index)205 void FileViewWidget::mapCenterOnTreeViewModel( const QModelIndex &index )
206 {
207     if( !index.isValid() ) {
208         return;
209     }
210 
211     const GeoDataObject *object
212         = index.model()->data( index, MarblePlacemarkModel::ObjectPointerRole ).value<GeoDataObject*>();
213     if (const GeoDataPlacemark *placemark = geodata_cast<GeoDataPlacemark>(object)) {
214         d->m_widget->model()->placemarkSelectionModel()->select( index, QItemSelectionModel::ClearAndSelect );
215         emit centerOn( *placemark, true );
216     }
217     else if (const GeoDataContainer *container = dynamic_cast<const GeoDataContainer *>(object)) {
218         const GeoDataLatLonAltBox box = container->latLonAltBox();
219         emit centerOn( box, true );
220     }
221 }
222 
223 }
224 
225 #include "moc_FileViewWidget.cpp"
226