1 // SPDX-License-Identifier: LGPL-2.1-or-later
2 //
3 // SPDX-FileCopyrightText: 2008 Torsten Rahn <tackat@kde.org>
4 // SPDX-FileCopyrightText: 2010 Dennis Nienhüser <nienhueser@kde.org>
5 //
6 
7 #include "CompassFloatItem.h"
8 #include "ui_CompassConfigWidget.h"
9 
10 #include "MarbleDebug.h"
11 #include "MarbleDirs.h"
12 #include "ViewportParams.h"
13 
14 #include <QRect>
15 #include <QColor>
16 #include <QPainter>
17 #include <QPainterPath>
18 #include <QPushButton>
19 #include <QSvgRenderer>
20 
21 namespace Marble
22 {
23 
CompassFloatItem()24 CompassFloatItem::CompassFloatItem()
25     : AbstractFloatItem( nullptr ),
26       m_svgobj( nullptr ),
27       m_polarity( 0 ),
28       m_themeIndex( 0 ),
29       m_configDialog( nullptr ),
30       m_uiConfigWidget( nullptr )
31 {
32 }
33 
CompassFloatItem(const MarbleModel * marbleModel)34 CompassFloatItem::CompassFloatItem( const MarbleModel *marbleModel )
35     : AbstractFloatItem( marbleModel, QPointF( -1.0, 10.0 ), QSizeF( 75.0, 75.0 ) ),
36       m_isInitialized( false ),
37       m_svgobj( nullptr ),
38       m_compass(),
39       m_polarity( 0 ),
40       m_themeIndex( 0 ),
41       m_configDialog( nullptr ),
42       m_uiConfigWidget( nullptr )
43 {
44 }
45 
~CompassFloatItem()46 CompassFloatItem::~CompassFloatItem ()
47 {
48     delete m_svgobj;
49 }
50 
backendTypes() const51 QStringList CompassFloatItem::backendTypes() const
52 {
53     return QStringList(QStringLiteral("compass"));
54 }
55 
name() const56 QString CompassFloatItem::name() const
57 {
58     return tr( "Compass" );
59 }
60 
guiString() const61 QString CompassFloatItem::guiString() const
62 {
63     return tr( "&Compass" );
64 }
65 
nameId() const66 QString CompassFloatItem::nameId() const
67 {
68     return QStringLiteral("compass");
69 }
70 
version() const71 QString CompassFloatItem::version() const
72 {
73     return QStringLiteral("1.0");
74 }
75 
description() const76 QString CompassFloatItem::description() const
77 {
78     return tr( "This is a float item that provides a compass." );
79 }
80 
copyrightYears() const81 QString CompassFloatItem::copyrightYears() const
82 {
83     return QStringLiteral("2009, 2010");
84 }
85 
pluginAuthors() const86 QVector<PluginAuthor> CompassFloatItem::pluginAuthors() const
87 {
88     return QVector<PluginAuthor>()
89             << PluginAuthor(QStringLiteral("Dennis Nienhüser"), QStringLiteral("nienhueser@kde.org"))
90             << PluginAuthor(QStringLiteral("Torsten Rahn"), QStringLiteral("tackat@kde.org"));
91 }
92 
icon() const93 QIcon CompassFloatItem::icon() const
94 {
95     return QIcon(QStringLiteral(":/icons/compass.png"));
96 }
97 
initialize()98 void CompassFloatItem::initialize()
99 {
100     readSettings();
101     m_isInitialized = true;
102 }
103 
isInitialized() const104 bool CompassFloatItem::isInitialized() const
105 {
106     return m_isInitialized;
107 }
108 
backgroundShape() const109 QPainterPath CompassFloatItem::backgroundShape() const
110 {
111     QRectF contentRect = this->contentRect();
112     QPainterPath path;
113     int fontheight = QFontMetrics( font() ).ascent();
114     int compassLength = static_cast<int>( contentRect.height() ) - 5 - fontheight;
115 
116     path.addEllipse( QRectF( QPointF( marginLeft() + padding() + ( contentRect.width() - compassLength ) / 2,
117                                       marginTop() + padding() + 5 + fontheight ),
118                              QSize( compassLength, compassLength ) ).toRect() );
119     return path;
120 }
121 
setProjection(const ViewportParams * viewport)122 void CompassFloatItem::setProjection( const ViewportParams *viewport )
123 {
124     // figure out the polarity ...
125     if ( m_polarity != viewport->polarity() ) {
126         m_polarity = viewport->polarity();
127         update();
128     }
129 
130     AbstractFloatItem::setProjection( viewport );
131 }
132 
paintContent(QPainter * painter)133 void CompassFloatItem::paintContent( QPainter *painter )
134 {
135     painter->save();
136 
137     QRectF compassRect( contentRect() );
138 
139     const QString dirstr =
140         (m_polarity == +1) ? tr("N") :
141         (m_polarity == -1) ? tr("S") :
142         /*else*/             QString();
143 
144     int fontheight = QFontMetrics( font() ).ascent();
145     int fontwidth = QFontMetrics( font() ).boundingRect( dirstr ).width();
146 
147     QPen outlinepen( background().color() );
148     outlinepen.setWidth( 2 );
149     QBrush outlinebrush( pen().color() );
150 
151     QPainterPath   outlinepath;
152     const QPointF  baseline( 0.5 * (qreal)( compassRect.width() - fontwidth ),
153                              (qreal)(fontheight) + 2.0 );
154 
155     outlinepath.addText( baseline, font(), dirstr );
156 
157     painter->setPen( outlinepen );
158     painter->setBrush( outlinebrush );
159     painter->drawPath( outlinepath );
160 
161     painter->setPen( Qt::NoPen );
162     painter->drawPath( outlinepath );
163 
164     int compassLength = static_cast<int>( compassRect.height() ) - 5 - fontheight;
165 
166     QSize compassSize( compassLength, compassLength );
167 
168     // Rerender compass pixmap if the size has changed
169     if ( m_compass.isNull() || m_compass.size() != compassSize ) {
170         m_compass = QPixmap( compassSize );
171         m_compass.fill( Qt::transparent );
172         QPainter mapPainter( &m_compass );
173         mapPainter.setViewport( m_compass.rect() );
174         m_svgobj->render( &mapPainter );
175     }
176     painter->drawPixmap( QPoint( static_cast<int>( compassRect.width() - compassLength ) / 2, fontheight + 5 ), m_compass );
177 
178     painter->restore();
179 }
180 
configDialog()181 QDialog *CompassFloatItem::configDialog()
182 {
183     if ( !m_configDialog ) {
184         m_configDialog = new QDialog();
185         m_uiConfigWidget = new Ui::CompassConfigWidget;
186         m_uiConfigWidget->setupUi( m_configDialog );
187         readSettings();
188         connect( m_uiConfigWidget->m_buttonBox, SIGNAL(accepted()),
189                 SLOT(writeSettings()) );
190         connect( m_uiConfigWidget->m_buttonBox, SIGNAL(rejected()),
191                 SLOT(readSettings()) );
192         QPushButton *applyButton = m_uiConfigWidget->m_buttonBox->button( QDialogButtonBox::Apply );
193         connect( applyButton, SIGNAL(clicked()),
194                  this,        SLOT(writeSettings()) );
195     }
196 
197     return m_configDialog;
198 }
199 
settings() const200 QHash<QString,QVariant> CompassFloatItem::settings() const
201 {
202     QHash<QString, QVariant> result = AbstractFloatItem::settings();
203 
204     result.insert(QStringLiteral("theme"), m_themeIndex);
205 
206     return result;
207 }
208 
setSettings(const QHash<QString,QVariant> & settings)209 void CompassFloatItem::setSettings( const QHash<QString,QVariant> &settings )
210 {
211     AbstractFloatItem::setSettings( settings );
212 
213     m_themeIndex = settings.value(QStringLiteral("theme"), 0).toInt();
214 
215     readSettings();
216 }
217 
readSettings()218 void CompassFloatItem::readSettings()
219 {
220     if ( m_uiConfigWidget && m_themeIndex >= 0 && m_themeIndex < m_uiConfigWidget->m_themeList->count() ) {
221         m_uiConfigWidget->m_themeList->setCurrentRow( m_themeIndex );
222     }
223 
224     QString theme = QStringLiteral(":/compass.svg");
225     switch( m_themeIndex ) {
226     case 1:
227         theme = QStringLiteral(":/compass-arrows.svg");
228         break;
229     case 2:
230         theme = QStringLiteral(":/compass-atom.svg");
231         break;
232     case 3:
233         theme = QStringLiteral(":/compass-magnet.svg");
234         break;
235     }
236 
237     delete m_svgobj;
238     m_svgobj = new QSvgRenderer( theme, this );
239     m_compass = QPixmap();
240 }
241 
writeSettings()242 void CompassFloatItem::writeSettings()
243 {
244     if ( m_uiConfigWidget ) {
245         m_themeIndex = m_uiConfigWidget->m_themeList->currentRow();
246     }
247     readSettings();
248     update();
249     emit settingsChanged( nameId() );
250 }
251 
252 }
253 
254 #include "moc_CompassFloatItem.cpp"
255