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"