1 
2 // SPDX-License-Identifier: LGPL-2.1-or-later
3 //
4 // SPDX-FileCopyrightText: 2008 Patrick Spendrin <ps_ml@gmx.de>
5 //
6 
7 #include "FileViewFloatItem.h"
8 
9 #include <QRect>
10 #include <QPoint>
11 #include <QApplication>
12 #include <QFileDialog>
13 #include <QListView>
14 #include <QMenu>
15 #include <QSlider>
16 #include <QMouseEvent>
17 
18 #include "MarbleDebug.h"
19 #include "FileViewModel.h"
20 #include "GeoPainter.h"
21 #include "ViewportParams.h"
22 #include "MarbleWidget.h"
23 
24 
25 using namespace Marble;
26 
FileViewFloatItem(const QPointF & point,const QSizeF & size)27 FileViewFloatItem::FileViewFloatItem(const QPointF &point,
28         const QSizeF &size) :
29     AbstractFloatItem(point, size), m_marbleWidget(0),
30             m_fileView(0), m_fileViewParent(0),
31             m_repaintScheduled(true), m_persIndex(0)
32 {
33     // Plugin is not enabled by default
34     setEnabled(false);
35 }
36 
~FileViewFloatItem()37 FileViewFloatItem::~FileViewFloatItem()
38 {
39     delete m_fileViewParent;
40 }
41 
backendTypes() const42 QStringList FileViewFloatItem::backendTypes() const
43 {
44     return QStringList(QStringLiteral("fileview"));
45 }
46 
name() const47 QString FileViewFloatItem::name() const
48 {
49     return tr("File View");
50 }
51 
guiString() const52 QString FileViewFloatItem::guiString() const
53 {
54     return tr("&File View");
55 }
56 
nameId() const57 QString FileViewFloatItem::nameId() const
58 {
59     return QStringLiteral("fileview");
60 }
61 
description() const62 QString FileViewFloatItem::description() const
63 {
64     return tr("A list of currently opened files");
65 }
66 
icon() const67 QIcon FileViewFloatItem::icon() const
68 {
69     return QIcon();
70 }
71 
initialize()72 void FileViewFloatItem::initialize()
73 {
74     m_fileViewParent = new QWidget(0);
75     m_fileViewParent->setFixedSize(size().toSize() - QSize(2 * padding(), 2
76             * padding()));
77     m_fileView = new QListView(m_fileViewParent);
78     m_fileView->resize(100, 240);
79     m_fileView->setResizeMode(QListView::Adjust);
80     m_fileView->setContextMenuPolicy( Qt::CustomContextMenu );
81     connect(m_fileView, SIGNAL(customContextMenuRequested(QPoint)),
82             this,       SLOT(contextMenu(QPoint)));
83 }
84 
isInitialized() const85 bool FileViewFloatItem::isInitialized() const
86 {
87     return m_fileViewParent != 0;
88 }
89 
backgroundShape() const90 QPainterPath FileViewFloatItem::backgroundShape() const
91 {
92     QPainterPath path;
93     QSizeF paintedSize = paintedRect().size();
94     path.addRoundedRect( QRectF( 0.0, 0.0, paintedSize.width() - 1, paintedSize.height() - 1 ), 6, 6 );
95     return path;
96 }
97 
changeViewport(ViewportParams * viewport)98 void FileViewFloatItem::changeViewport( ViewportParams *viewport )
99 {
100     Q_UNUSED( viewport );
101     update();
102 }
103 
paintContent(GeoPainter * painter,ViewportParams * viewport,const QString & renderPos,GeoSceneLayer * layer)104 void FileViewFloatItem::paintContent( GeoPainter *painter, ViewportParams *viewport,
105                                       const QString& renderPos, GeoSceneLayer * layer)
106 {
107     Q_UNUSED( viewport );
108     Q_UNUSED( layer );
109     Q_UNUSED( renderPos );
110 
111     if( !m_fileView->model() ) {
112         m_fileView->setModel(marbleModel()->fileViewModel());
113     }
114     painter->end();
115     // Paint widget without a background
116     m_fileViewParent->render( painter->device(),
117           QPoint( padding(), padding() ), QRegion(),QWidget::RenderFlags(QWidget::DrawChildren));
118 
119     painter->begin( painter->device() );
120     m_fileView->update();
121 }
122 
eventFilter(QObject * object,QEvent * e)123 bool FileViewFloatItem::eventFilter(QObject *object, QEvent *e)
124 {
125     if ( !enabled() || !visible() ) {
126         return false;
127     }
128 
129     MarbleWidget *widget = dynamic_cast<MarbleWidget*> (object);
130     if ( !widget ) {
131         return AbstractFloatItem::eventFilter(object, e);
132     }
133 
134     if ( m_marbleWidget != widget ) {
135         // Delayed initialization
136         m_marbleWidget = widget;
137     }
138 
139     Q_ASSERT( m_marbleWidget );
140     // Mouse events are forwarded to the underlying widget
141     QMouseEvent *event = static_cast<QMouseEvent*> (e);
142     QRectF floatItemRect = QRectF( positivePosition(), size() );
143 
144     QPoint shiftedPos = event->pos() - floatItemRect.topLeft().toPoint()
145             - QPoint( padding(), padding() );
146     if( e->type() == QEvent::MouseMove ) {
147         m_itemPosition = event->globalPos();
148     }
149 
150     if( floatItemRect.contains( event->pos() ) ) {
151         QWidget *child = m_fileViewParent->childAt( shiftedPos );
152 
153         if( child ) {
154             m_marbleWidget->setCursor( Qt::ArrowCursor );
155 
156             // there needs to be some extra handling for the scrollbars
157             // these need some special treatment due to them not forwarding
158             // their mouseevents to their scrollbars.
159             if( reinterpret_cast<QScrollBar*>( child ) == m_fileView->horizontalScrollBar() ) {
160                 shiftedPos -= QPoint( 0, m_fileView->viewport()->size().height() );
161             } else if( reinterpret_cast<QScrollBar*>( child ) == m_fileView->verticalScrollBar() ) {
162                 shiftedPos -= QPoint( m_fileView->viewport()->size().width(), 0 );
163             }
164             QMouseEvent shiftedEvent( e->type(), shiftedPos,
165                     event->globalPos(), event->button(), event->buttons(),
166                     event->modifiers() );
167             if( QApplication::sendEvent(child, &shiftedEvent) ) {
168                 if( e->type() == QEvent::MouseButtonPress ||
169                     e->type() == QEvent::MouseButtonRelease ||
170                     e->type() == QEvent::MouseButtonDblClick ||
171                     e->type() == QEvent::MouseMove )
172                     updateFileView();
173                 return true;
174             }
175 
176         }
177     }
178 
179     return AbstractFloatItem::eventFilter(object, e);
180 }
181 
selectTheme(const QString & theme)182 void FileViewFloatItem::selectTheme(const QString& theme)
183 {
184     Q_UNUSED(theme);
185 
186     if ( m_marbleWidget ) {
187     }
188 }
189 
updateFileView()190 void FileViewFloatItem::updateFileView()
191 {
192     if (m_marbleWidget)
193     {
194         // Trigger a repaint of the float item. Otherwise button state updates
195         // are delayed
196         QRectF floatItemRect = QRectF(positivePosition(), size()).toRect();
197         QRegion dirtyRegion(floatItemRect.toRect());
198 
199         m_marbleWidget->update(dirtyRegion);
200     }
201 }
202 
contextMenu(const QPoint & pos)203 void FileViewFloatItem::contextMenu( const QPoint& pos )
204 {
205     if( !m_marbleWidget )
206         return;
207 
208     QPointer<QMenu> test = new QMenu( m_fileView );
209     // We need the global position to move the menu.
210     // pos contains the relative position.
211     test->move( m_itemPosition );
212     connect( test->addAction( tr( "Open file..." ) ), SIGNAL(triggered()),
213              this, SLOT(addFile()) );
214     connect( test->addAction( tr( "Close this file" ) ), SIGNAL(triggered()),
215              this, SLOT(removeFile()) );
216     m_persIndex = new QPersistentModelIndex( m_fileView->indexAt( pos ) );
217     test->exec();
218     delete test;
219 }
220 
addFile()221 void FileViewFloatItem::addFile()
222 {
223     QString fileName;
224     fileName = QFileDialog::getOpenFileName(m_marbleWidget, tr("Open File"),
225                                             QString(),
226                                             tr("All Supported Files (*.gpx *.kml *.pnt);;GPS Data (*.gpx);;Google Earth KML (*.kml);PNT Data (*.pnt)"));
227 
228     if ( ! fileName.isEmpty() ) {
229         m_marbleWidget->model()->addGeoDataFile( fileName );
230     }
231 }
232 
removeFile()233 void FileViewFloatItem::removeFile()
234 {
235     //reinterpret_cast<FileViewModel*>(m_fileView->model())->setSelectedIndex( *m_persIndex );
236     mDebug() << m_fileView->model()->data( *m_persIndex, Qt::DisplayRole ).toString();
237     // close selected file
238     reinterpret_cast<FileViewModel*>(m_fileView->model())->closeFile();
239 }
240 
241 #include "moc_FileViewFloatItem.cpp"
242