File indexing completed on 2024-04-21 03:48:25

0001 // SPDX-License-Identifier: LGPL-2.1-or-later
0002 //
0003 // SPDX-FileCopyrightText: 2014 Dennis Nienhüser <nienhueser@kde.org>
0004 // SPDX-FileCopyrightText: 2014 Abhinav Gangwar <abhgang@gmail.com>
0005 //
0006 
0007 
0008 // Self
0009 #include "GameMainWindow.h"
0010 #include "CountryByShape.h"
0011 #include "CountryByFlag.h"
0012 #include "ClickOnThat.h"
0013 
0014 #include "ui_game.h"
0015 
0016 // Qt
0017 #include <QSettings>
0018 #include <QDebug>
0019 #include <QString>
0020 #include <QVector>
0021 #include <QVBoxLayout>
0022 #include <QQuickView>
0023 #include <QQuickItem>
0024 #include <QUrl>
0025 #include <QSize>
0026 #include <QResizeEvent>
0027 #include <QFileInfo>
0028 
0029 // Marble
0030 #include <marble/MarbleDirs.h>
0031 #include <marble/MarbleWidget.h>
0032 #include <marble/MarbleMap.h>
0033 #include <marble/MarbleModel.h>
0034 #include <marble/GeoDataTreeModel.h>
0035 #include <marble/RenderPlugin.h>
0036 #include <marble/MarblePlacemarkModel.h>
0037 
0038 #include <marble/GeoDataDocument.h>
0039 #include <marble/GeoDataPlacemark.h>
0040 #include <marble/GeoDataGeometry.h>
0041 #include <marble/GeoDataMultiGeometry.h>
0042 #include <marble/GeoDataPoint.h>
0043 #include <marble/GeoDataPolygon.h>
0044 #include <marble/GeoDataLinearRing.h>
0045 #include <marble/GeoDataLatLonAltBox.h>
0046 
0047 namespace Marble {
0048 
0049 class Private : public Ui_MainWindow
0050 {
0051 public:
0052     Private( QWidget *parent = nullptr );
0053 
0054     MarbleWidget *m_marbleWidget;
0055     QWidget *m_parent;
0056     QQuickView m_view;
0057     CountryByShape *m_countryByShape;
0058     CountryByFlag *m_countryByFlag;
0059     ClickOnThat *m_clickOnThat;
0060 
0061     QString readMarbleDataPath() const;
0062     void setupMarbleWidget();
0063     void setupGameSignals();
0064 };
0065 
0066 Private::Private(QWidget* parent) :
0067     m_marbleWidget( new MarbleWidget( parent ) ),
0068     m_parent( parent ),
0069     m_view(),
0070     m_countryByShape( new CountryByShape(m_marbleWidget) ),
0071     m_countryByFlag( new CountryByFlag(m_marbleWidget) ),
0072     m_clickOnThat( new ClickOnThat(m_marbleWidget) )
0073 {
0074     // nothing to do
0075 }
0076 
0077 QString Private::readMarbleDataPath() const
0078 {
0079     return QSettings().value(QStringLiteral("MarbleWidget/marbleDataPath"), QString()).toString();
0080 }
0081 
0082 void Private::setupMarbleWidget()
0083 {
0084     m_marbleWidget->setMapThemeId(QStringLiteral( "earth/political/political.dgml"));
0085 
0086     foreach ( RenderPlugin *renderPlugin, m_marbleWidget->renderPlugins() ) {
0087         if (renderPlugin->nameId() == QLatin1String("stars")
0088             || renderPlugin->nameId() == QLatin1String("overviewmap")
0089             || renderPlugin->nameId() == QLatin1String("compass")
0090             || renderPlugin->nameId() == QLatin1String("scalebar")
0091             || renderPlugin->nameId() == QLatin1String("navigation"))
0092         {
0093             renderPlugin->setVisible( false );
0094         }
0095     }
0096 
0097     m_marbleWidget->centerOn( 23.0, 42.0 );
0098     m_marbleWidget->setDistance( 7500 );
0099 
0100     m_parent->connect( m_parent, SIGNAL(announceHighlight(qreal,qreal,GeoDataCoordinates::Unit)),
0101                        m_marbleWidget, SIGNAL(highlightedPlacemarksChanged(qreal,qreal,GeoDataCoordinates::Unit)) );
0102 }
0103 
0104 void Private::setupGameSignals()
0105 {
0106     QObject *root = m_view.rootObject();
0107     if ( root ) {
0108         m_parent->connect( root, SIGNAL(browseMapButtonClicked()),
0109                            m_parent, SLOT(browseMapButtonClicked()) );
0110         QObject *gameOptions = root->findChild<QObject*>(QStringLiteral("gameOptions"));
0111 
0112         m_parent->connect( gameOptions, SIGNAL(nextButtonClicked()),
0113                            m_parent, SLOT(createQuestion()) );
0114         m_parent->connect( gameOptions, SIGNAL(gameClosed()),
0115                            m_parent, SLOT(disableGames()) );
0116 
0117         // For "Identify the highlighted country" game
0118         m_parent->connect( gameOptions, SIGNAL(countryByShapeGameRequested()),
0119                            m_parent, SLOT(enableCountryShapeGame()) );
0120         m_parent->connect( m_countryByShape, SIGNAL(gameInitialized()),
0121                            m_parent, SLOT(createQuestion()) );
0122 
0123         // For "Identify the flag" game
0124         m_parent->connect( gameOptions, SIGNAL(countryByFlagGameRequested()),
0125                            m_parent, SLOT(enableCountryFlagGame()) );
0126         m_parent->connect( m_countryByFlag, SIGNAL(gameInitialized()),
0127                            m_parent, SLOT(createQuestion()) );
0128 
0129         // For "Click on that country" game
0130         m_parent->connect( gameOptions, SIGNAL(clickOnThatGameRequested()),
0131                            m_parent, SLOT(enableClickOnThatGame()) );
0132         m_parent->connect( m_clickOnThat, SIGNAL(gameInitialized()),
0133                            m_parent, SLOT(createQuestion()) );
0134         m_parent->connect( gameOptions, SIGNAL(answerDisplayButtonClicked()),
0135                            m_clickOnThat, SLOT(highlightCorrectAnswer()) );
0136     }
0137 }
0138 
0139 MainWindow::MainWindow( const QString &marbleDataPath, QWidget *parent, Qt::WindowFlags flags ) :
0140     QMainWindow( parent, flags ),
0141     d( new Private( this ) )
0142 {
0143     d->setupUi( this );
0144     QString const dataPath = marbleDataPath.isEmpty() ? d->readMarbleDataPath() : marbleDataPath;
0145     if ( !dataPath.isEmpty() ) {
0146         MarbleDirs::setMarbleDataPath( dataPath );
0147     }
0148 
0149     d->setupMarbleWidget();
0150     setCentralWidget( d->m_marbleWidget );
0151 
0152     d->m_view.setSource(QUrl(QStringLiteral("qrc:/Window.qml")));
0153 
0154     QWidget *leftPanel = QWidget::createWindowContainer( &d->m_view, d->dockWidgetContents );
0155     QVBoxLayout *layout = new QVBoxLayout( d->dockWidgetContents );
0156     layout->addWidget( leftPanel );
0157     d->dockWidgetContents->setLayout( layout );
0158 
0159     d->setupGameSignals();
0160 }
0161 
0162 MainWindow::~MainWindow()
0163 {
0164     delete d;
0165 }
0166 
0167 MarbleWidget *MainWindow::marbleWidget()
0168 {
0169     return d->m_marbleWidget;
0170 }
0171 
0172 void MainWindow::createQuestion()
0173 {
0174     QObject *gameObject = d->m_view.rootObject()->findChild<QObject*>(QStringLiteral("gameOptions"));
0175     if ( gameObject ) {
0176         emit postQuestion( gameObject );
0177     }
0178 }
0179 
0180 void MainWindow::browseMapButtonClicked()
0181 {
0182     d->m_marbleWidget->setMapThemeId(QStringLiteral("earth/political/political.dgml"));
0183 
0184     /**
0185      * Now display the country names which
0186      * were removed to initiate the game
0187      */
0188     const GeoDataTreeModel *const treeModel = d->m_marbleWidget->model()->treeModel();
0189     for ( int i = 0; i < treeModel->rowCount(); ++i ) {
0190         QVariant const data = treeModel->data ( treeModel->index ( i, 0 ), MarblePlacemarkModel::ObjectPointerRole );
0191         GeoDataObject *object = qvariant_cast<GeoDataObject*>( data );
0192         Q_ASSERT_X( object, "MainWindow::browseMapButtonClicked",
0193                     "failed to get valid data from treeModel for GeoDataObject" );
0194         if (auto doc = geodata_cast<GeoDataDocument>(object)) {
0195             QFileInfo fileInfo( doc->fileName() );
0196             QString fileName = fileInfo.fileName();
0197             if (fileName == QLatin1String("boundaryplacemarks.cache")) {
0198                 doc->setVisible( true );
0199                 d->m_marbleWidget->model()->treeModel()->updateFeature( doc );
0200                 d->m_marbleWidget->setHighlightEnabled( true );
0201                 break;
0202             }
0203         }
0204     }
0205 }
0206 
0207 void MainWindow::disableGames()
0208 {
0209     disconnect( this, SIGNAL(postQuestion(QObject*)),
0210                 d->m_countryByShape, SLOT(postQuestion(QObject*)) );
0211 
0212     disconnect( this, SIGNAL(postQuestion(QObject*)),
0213                 d->m_countryByFlag, SLOT(postQuestion(QObject*)) );
0214 
0215     disconnect( this, SIGNAL(postQuestion(QObject*)),
0216                 d->m_clickOnThat, SLOT(postQuestion(QObject*)) );
0217     disconnect( d->m_clickOnThat, SIGNAL(updateResult(bool)),
0218                 this, SLOT(displayResult(bool)) );
0219     disconnect( d->m_marbleWidget, SIGNAL(highlightedPlacemarksChanged(qreal,qreal,GeoDataCoordinates::Unit)),
0220                 d->m_clickOnThat, SLOT(determineResult(qreal,qreal,GeoDataCoordinates::Unit)) );
0221     d->m_clickOnThat->disablePinDocument();
0222 
0223     // Reset the map view
0224     d->m_marbleWidget->centerOn( 23.0, 42.0 );
0225     d->m_marbleWidget->setDistance( 7500 );
0226 }
0227 
0228 void MainWindow::enableCountryShapeGame()
0229 {
0230     connect( this, SIGNAL(postQuestion(QObject*)),
0231              d->m_countryByShape, SLOT(postQuestion(QObject*)) );
0232 
0233     d->m_countryByShape->initiateGame();
0234 }
0235 
0236 void MainWindow::enableCountryFlagGame()
0237 {
0238     connect( this, SIGNAL(postQuestion(QObject*)),
0239              d->m_countryByFlag, SLOT(postQuestion(QObject*)) );
0240 
0241     d->m_countryByFlag->initiateGame();
0242 }
0243 
0244 void MainWindow::enableClickOnThatGame()
0245 {
0246     connect( this, SIGNAL(postQuestion(QObject*)),
0247              d->m_clickOnThat, SLOT(postQuestion(QObject*)) );
0248     connect( d->m_clickOnThat, SIGNAL(updateResult(bool)),
0249              this, SLOT(displayResult(bool)) );
0250     d->m_clickOnThat->initiateGame();
0251 }
0252 
0253 void MainWindow::displayResult(bool result )
0254 {
0255     QObject *gameObject = d->m_view.rootObject()->findChild<QObject*>(QStringLiteral("gameOptions"));
0256     if ( gameObject ) {
0257         QMetaObject::invokeMethod( gameObject, "displayResult",
0258                                    Q_ARG(QVariant, QVariant(result)) );
0259     }
0260 }
0261 
0262 /*
0263  * As the height of main window is changed, update the
0264  * height ( leftPanelHeight ) in window.qml
0265  */
0266 void MainWindow::resizeEvent(QResizeEvent* event)
0267 {
0268     const QSize size = event->size();
0269 
0270     QObject *root = d->m_view.rootObject();
0271 
0272     if ( root ) {
0273         QMetaObject::invokeMethod( root, "resizeWindow",
0274                                    Q_ARG(QVariant, QVariant(size.height()*9/10)) );
0275     }
0276 }
0277 
0278 }   // namespace Marble
0279 
0280 #include "moc_GameMainWindow.cpp"