1 // SPDX-License-Identifier: LGPL-2.1-or-later
2 //
3 // SPDX-FileCopyrightText: 2008 Torsten Rahn <rahn@kde.org>
4 //
5 
6 // Self
7 #include "AbstractFloatItem.h"
8 
9 // Qt
10 #include <QMenu>
11 #include <QAction>
12 #include <QContextMenuEvent>
13 #include <QDialog>
14 #include <QHelpEvent>
15 #include <QPen>
16 
17 // Marble
18 #include "DialogConfigurationInterface.h"
19 #include "GeoPainter.h"
20 #include "MarbleDebug.h"
21 
22 namespace Marble
23 {
24 
25 class AbstractFloatItemPrivate
26 {
27   public:
AbstractFloatItemPrivate()28     AbstractFloatItemPrivate() : m_contextMenu( nullptr )
29     {
30     }
31 
~AbstractFloatItemPrivate()32     ~AbstractFloatItemPrivate()
33     {
34         delete m_contextMenu;
35     }
36 
37 
38     static QPen         s_pen;
39     static QFont        s_font;
40 
41     QMenu* m_contextMenu;
42 };
43 
44 QPen         AbstractFloatItemPrivate::s_pen = QPen( Qt::black );
45 #ifdef Q_OS_MACX
46     QFont AbstractFloatItemPrivate::s_font = QFont( QStringLiteral("Sans Serif"), 10 );
47 #else
48     QFont AbstractFloatItemPrivate::s_font = QFont( QStringLiteral("Sans Serif"), 8 );
49 #endif
50 
AbstractFloatItem(const MarbleModel * marbleModel,const QPointF & point,const QSizeF & size)51 AbstractFloatItem::AbstractFloatItem( const MarbleModel *marbleModel, const QPointF &point, const QSizeF &size )
52     : RenderPlugin( marbleModel ),
53       FrameGraphicsItem(),
54       d( new AbstractFloatItemPrivate() )
55 {
56     setCacheMode( ItemCoordinateCache );
57     setFrame( RectFrame );
58     setPadding( 4.0 );
59     setContentSize( size );
60     setPosition( point );
61 }
62 
~AbstractFloatItem()63 AbstractFloatItem::~AbstractFloatItem()
64 {
65     delete d;
66 }
67 
settings() const68 QHash<QString,QVariant> AbstractFloatItem::settings() const
69 {
70     QHash<QString,QVariant> updated = RenderPlugin::settings();
71 #ifdef Q_OS_OSX
72     updated.insert(QStringLiteral("position"), position().toPoint());
73 #else
74     updated.insert(QStringLiteral("position"), position());
75 #endif
76     return updated;
77 }
78 
setSettings(const QHash<QString,QVariant> & settings)79 void AbstractFloatItem::setSettings(const QHash<QString, QVariant> &settings)
80 {
81     if (settings.value(QStringLiteral("position")).type() == QVariant::String) {
82 #ifdef Q_OS_OSX
83         setPosition(settings.value(QStringLiteral("position"), position()).toPointF());
84 #else
85         // work around KConfig turning QPointFs into QStrings
86         const QStringList coordinates = settings.value(QStringLiteral("position")).toString().split(QLatin1Char(','));
87         setPosition( QPointF( coordinates.at( 0 ).toFloat(), coordinates.at( 1 ).toFloat() ) );
88 #endif
89     }
90     else {
91         setPosition(settings.value(QStringLiteral("position"), position()).toPointF());
92     }
93 
94     RenderPlugin::setSettings(settings);
95 }
96 
renderType() const97 RenderPlugin::RenderType AbstractFloatItem::renderType() const
98 {
99     return RenderPlugin::PanelRenderType;
100 }
101 
pen() const102 QPen AbstractFloatItem::pen() const
103 {
104     return d->s_pen;
105 }
106 
setPen(const QPen & pen)107 void AbstractFloatItem::setPen( const QPen &pen )
108 {
109     d->s_pen = pen;
110     update();
111 }
112 
font() const113 QFont AbstractFloatItem::font() const
114 {
115     return d->s_font;
116 }
117 
setFont(const QFont & font)118 void AbstractFloatItem::setFont( const QFont &font )
119 {
120     d->s_font = font;
121     update();
122 }
123 
renderPolicy() const124 QString AbstractFloatItem::renderPolicy() const
125 {
126     return QStringLiteral("ALWAYS");
127 }
128 
renderPosition() const129 QStringList AbstractFloatItem::renderPosition() const
130 {
131     return QStringList(QStringLiteral("FLOAT_ITEM"));
132 }
133 
setVisible(bool visible)134 void AbstractFloatItem::setVisible( bool visible )
135 {
136     // Reimplemented since AbstractFloatItem does multiple inheritance
137     // and the (set)Visible() methods are available in both base classes!
138     RenderPlugin::setVisible( visible );
139 }
140 
visible() const141 bool AbstractFloatItem::visible() const
142 {
143     // Reimplemented since AbstractFloatItem does multiple inheritance
144     // and the (set)Visible() methods are available in both base classes!
145     return RenderPlugin::visible();
146 }
147 
setPositionLocked(bool lock)148 void AbstractFloatItem::setPositionLocked( bool lock )
149 {
150     ScreenGraphicsItem::GraphicsItemFlags flags = this->flags();
151 
152     if ( lock ) {
153         flags &= ~ScreenGraphicsItem::ItemIsMovable;
154     }
155     else {
156         flags |= ScreenGraphicsItem::ItemIsMovable;
157     }
158 
159     setFlags( flags );
160 }
161 
positionLocked() const162 bool AbstractFloatItem::positionLocked() const
163 {
164     return ( flags() & ScreenGraphicsItem::ItemIsMovable ) == 0;
165 }
166 
eventFilter(QObject * object,QEvent * e)167 bool AbstractFloatItem::eventFilter( QObject *object, QEvent *e )
168 {
169     if ( !enabled() || !visible() ) {
170         return false;
171     }
172 
173     if( e->type() == QEvent::ContextMenu )
174     {
175         QWidget *widget = qobject_cast<QWidget *>( object );
176         QContextMenuEvent *menuEvent = dynamic_cast<QContextMenuEvent *> ( e );
177         if( widget != nullptr && menuEvent != nullptr && contains( menuEvent->pos() ) )
178         {
179             contextMenuEvent( widget, menuEvent );
180             return true;
181         }
182         return false;
183     }
184     else if( e->type() == QEvent::ToolTip )
185     {
186         QHelpEvent *helpEvent = dynamic_cast<QHelpEvent *>( e );
187         if( helpEvent != nullptr && contains( helpEvent->pos() ) )
188         {
189             toolTipEvent( helpEvent );
190             return true;
191         }
192         return false;
193     }
194     else
195         return ScreenGraphicsItem::eventFilter( object, e );
196 }
197 
contextMenuEvent(QWidget * w,QContextMenuEvent * e)198 void AbstractFloatItem::contextMenuEvent ( QWidget *w, QContextMenuEvent *e )
199 {
200     contextMenu()->exec( w->mapToGlobal( e->pos() ) );
201 }
202 
toolTipEvent(QHelpEvent * e)203 void AbstractFloatItem::toolTipEvent ( QHelpEvent *e )
204 {
205     Q_UNUSED( e );
206 }
207 
render(GeoPainter * painter,ViewportParams * viewport,const QString & renderPos,GeoSceneLayer * layer)208 bool AbstractFloatItem::render( GeoPainter *painter, ViewportParams *viewport,
209              const QString& renderPos, GeoSceneLayer * layer )
210 {
211     Q_UNUSED(painter)
212     Q_UNUSED(viewport)
213     Q_UNUSED(renderPos)
214     Q_UNUSED(layer)
215 
216     return true;
217 }
218 
show()219 void AbstractFloatItem::show()
220 {
221     setVisible( true );
222 }
223 
hide()224 void AbstractFloatItem::hide()
225 {
226     setVisible( false );
227 }
228 
contextMenu()229 QMenu* AbstractFloatItem::contextMenu()
230 {
231     if ( !d->m_contextMenu )
232     {
233         d->m_contextMenu = new QMenu;
234 
235         QAction *lockAction = d->m_contextMenu->addAction(QIcon(QStringLiteral(":/icons/unlock.png")), tr("&Lock"));
236         lockAction->setCheckable( true );
237         lockAction->setChecked( positionLocked() );
238         connect( lockAction, SIGNAL(triggered(bool)), this, SLOT(setPositionLocked(bool)) );
239 
240         if(!(flags() & ItemIsHideable)) {
241             QAction *hideAction = d->m_contextMenu->addAction( tr( "&Hide" ) );
242             connect( hideAction, SIGNAL(triggered()), this, SLOT(hide()) );
243         }
244 
245         DialogConfigurationInterface *configInterface = qobject_cast<DialogConfigurationInterface *>( this );
246         QDialog *dialog = configInterface ? configInterface->configDialog() : nullptr;
247         if( dialog )
248         {
249             d->m_contextMenu->addSeparator();
250             QAction *configAction = d->m_contextMenu->addAction(QIcon(QStringLiteral(":/icons/settings-configure.png")), tr("&Configure..."));
251             connect( configAction, SIGNAL(triggered()), dialog, SLOT(exec()) );
252         }
253     }
254 
255     Q_ASSERT( d->m_contextMenu );
256     return d->m_contextMenu;
257 }
258 
259 }
260 
261 #include "moc_AbstractFloatItem.cpp"
262