File indexing completed on 2025-03-23 03:49:10
0001 /* This file is part of KsirK. 0002 Copyright (C) 2001-2007 Gael de Chalendar <kleag@free.fr> 0003 0004 KsirK is free software; you can redistribute it and/or 0005 modify it under the terms of the GNU General Public 0006 License as published by the Free Software Foundation, either version 2 0007 of the License, or (at your option) any later version. 0008 0009 This program is distributed in the hope that it will be useful, 0010 but WITHOUT ANY WARRANTY; without even the implied warranty of 0011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0012 General Public License for more details. 0013 0014 You should have received a copy of the GNU General Public License 0015 along with this program; if not, write to the Free Software 0016 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 0017 02110-1301, USA 0018 */ 0019 0020 /* begin : Thu Jul 19 2001 */ 0021 0022 #include "decoratedgameframe.h" 0023 #include "GameLogic/player.h" 0024 0025 #include <QSize> 0026 #include <QEvent> 0027 #include <QGraphicsSceneMouseEvent> 0028 #include <QScrollBar> 0029 0030 #include <kgamewin.h> 0031 #include <KGameStandardAction> 0032 #include <KStandardAction> 0033 #include <KLocalizedString> 0034 #include "ksirk_debug.h" 0035 #include <KGamePopupItem> 0036 #define USE_UNSTABLE_LIBKDEGAMESPRIVATE_API 0037 #include <libkdegamesprivate/kgame/kgameio.h> 0038 #include <libkdegamesprivate/kgame/kplayer.h> 0039 0040 namespace Ksirk 0041 { 0042 using namespace GameLogic; 0043 0044 0045 DecoratedGameFrame::DecoratedGameFrame(QWidget* parent, 0046 unsigned int mapW, unsigned int mapH, GameAutomaton* automaton) 0047 : QGraphicsView(parent), m_mapW(mapW), m_mapH(mapH), m_parent(parent), 0048 m_automaton(automaton) 0049 { 0050 qCDebug(KSIRK_LOG) << "("<<mapW<<"x"<<mapH<<")"; 0051 setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff ); 0052 setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff ); 0053 setCacheMode(QGraphicsView::CacheBackground); 0054 setMinimumSize(200,100); 0055 setMaximumSize(mapW,mapH); 0056 updateGeometry(); 0057 setMouseTracking(true); 0058 0059 QuitAction = KGameStandardAction::quit(m_automaton->game(), &KGameWindow::close, this); 0060 0061 initMenu (); 0062 initAttackMenu(); 0063 initMoveMenu(); 0064 0065 // redirect the mouse move event to the main windows 0066 connect(this, &DecoratedGameFrame::mouseMoveEventReceived, automaton->game(), &KGameWindow::mouseMoveEvent); 0067 } 0068 0069 DecoratedGameFrame::~DecoratedGameFrame() 0070 { 0071 } 0072 0073 void DecoratedGameFrame::mouseMoveEvent ( QMouseEvent * event ) 0074 { 0075 // qCDebug(KSIRK_LOG); 0076 emit (mouseMoveEventReceived(event)); 0077 // event->ignore(); 0078 } 0079 0080 QSize DecoratedGameFrame::sizeHint() const 0081 { 0082 // qCDebug(KSIRK_LOG) << " " << m_mapW << "/" << m_mapH; 0083 return QSize(m_mapW, m_mapH); 0084 } 0085 0086 void DecoratedGameFrame::initMenu () 0087 { 0088 menu = new QMenu(this); 0089 0090 QAction* newAction = KGameStandardAction::gameNew(m_automaton->game(), &KGameWindow::slotNewGame, this); 0091 0092 QAction* openAction = KGameStandardAction::load(m_automaton->game(), &KGameWindow::slotOpenGame, this); 0093 0094 QAction* saveAction = KGameStandardAction::save(m_automaton->game(), &KGameWindow::slotSaveGame, this); 0095 0096 QAction* zoomInAction = KStandardAction::zoomIn(m_automaton->game(), &KGameWindow::slotZoomIn, this); 0097 0098 QAction* zoomOutAction = KStandardAction::zoomOut(m_automaton->game(), &KGameWindow::slotZoomOut, this); 0099 0100 nextPlayer = new QAction(i18n("Next Player"), this); 0101 connect(nextPlayer, &QAction::triggered, m_automaton->game(), &KGameWindow::slotNextPlayer); 0102 0103 detailsAction = new QAction(i18n("Details"), this); 0104 connect(detailsAction, &QAction::triggered, this, &DecoratedGameFrame::slotDetails); 0105 0106 goalAction = new QAction(QIcon(), i18n("Goal"), this); 0107 goalAction->setShortcut(Qt::CTRL | Qt::Key_G); 0108 connect(goalAction,&QAction::triggered,m_automaton->game(),&KGameWindow::slotShowGoal); 0109 0110 menu->addAction(newAction); 0111 menu->addAction(openAction); 0112 menu->addAction(saveAction); 0113 menu->addSeparator(); 0114 menu->addAction(zoomInAction); 0115 menu->addAction(zoomOutAction); 0116 menu->addAction(detailsAction); 0117 menu->addSeparator(); 0118 menu->addAction(goalAction); 0119 menu->addAction(nextPlayer); 0120 menu->addSeparator(); 0121 menu->addAction(QuitAction); 0122 } 0123 0124 void DecoratedGameFrame::setArenaOptionEnabled(bool option) 0125 { 0126 qCDebug(KSIRK_LOG) << option; 0127 m_arenaAction->setEnabled(option); 0128 if (option == false) 0129 { 0130 emit(arenaStateSignal(false)); 0131 } 0132 } 0133 0134 void DecoratedGameFrame::initAttackMenu () 0135 { 0136 attackMenu = new QMenu(this); 0137 0138 m_arenaAction = new ArenaAction(i18n("Enable Arena"), this); 0139 connect(m_arenaAction, &QAction::triggered, this, &DecoratedGameFrame::arenaState); 0140 connect(this, &DecoratedGameFrame::arenaStateSignal, m_automaton->game(), &KGameWindow::slotArena); 0141 0142 Attack1Action = new QAction(i18n("Attack 1"), this); 0143 connect(Attack1Action, &QAction::triggered, m_automaton->game(), &KGameWindow::slotAttack1); 0144 0145 Attack2Action = new QAction(i18n("Attack 2"), this); 0146 connect(Attack2Action, &QAction::triggered, m_automaton->game(), &KGameWindow::slotAttack2); 0147 0148 Attack3Action = new QAction(i18n("Attack 3"), this); 0149 connect(Attack3Action, &QAction::triggered, m_automaton->game(), &KGameWindow::slotAttack3); 0150 0151 AutoAction = new QAction(i18n("Auto attack"), this); 0152 connect(AutoAction, &QAction::triggered, this, &DecoratedGameFrame::attackAuto); 0153 0154 attackMenu->addAction(AutoAction); 0155 attackMenu->addSeparator(); 0156 attackMenu->addAction(Attack1Action); 0157 attackMenu->addAction(Attack2Action); 0158 attackMenu->addAction(Attack3Action); 0159 attackMenu->addSeparator(); 0160 attackMenu->addAction(m_arenaAction); 0161 // attackMenu->addSeparator(); 0162 // attackMenu->addAction(QuitAction); 0163 } 0164 0165 void DecoratedGameFrame::initMoveMenu () 0166 { 0167 moveMenu = new QMenu(this); 0168 0169 Move1Action = new QAction(i18n("Move 1"), this); 0170 connect(Move1Action, &QAction::triggered,m_automaton->game(), &KGameWindow::slotInvade1); 0171 0172 Move5Action = new QAction(i18n("Move 5"), this); 0173 connect(Move5Action, &QAction::triggered,m_automaton->game(), &KGameWindow::slotInvade5); 0174 0175 Move10Action = new QAction(i18n("Move 10"), this); 0176 connect(Move10Action, &QAction::triggered,m_automaton->game(), &KGameWindow::slotInvade10); 0177 0178 moveMenu->addAction(Move1Action); 0179 moveMenu->addAction(Move5Action); 0180 moveMenu->addAction(Move10Action); 0181 // moveMenu->addSeparator(); 0182 // moveMenu->addAction(QuitAction); 0183 } 0184 0185 void DecoratedGameFrame::contextMenuEvent( QContextMenuEvent * ) 0186 { 0187 menuPoint = QCursor::pos(); 0188 qCDebug(KSIRK_LOG) << "************state decoratedgameframe" << m_automaton->stateName(); 0189 if (m_automaton->state() != GameAutomaton::INIT 0190 && m_automaton->state() != GameAutomaton::INTERLUDE 0191 && m_automaton->state() != GameAutomaton::NEWARMIES 0192 && m_automaton->state() != GameAutomaton::WAIT_RECYCLING) 0193 { 0194 if (!m_automaton-> currentPlayer()->isAI() 0195 && !m_automaton-> currentPlayer()->isVirtual()) 0196 { 0197 if (m_automaton->state() == GameAutomaton::WAIT) 0198 { 0199 nextPlayer->setVisible(true); 0200 } 0201 else 0202 { 0203 nextPlayer->setVisible(false); 0204 } 0205 0206 // set the goal icon to the proper flag 0207 goalAction-> setIcon(QIcon(m_automaton-> currentPlayer()->getFlag()-> image(0))); 0208 0209 goalAction->setVisible(true); 0210 0211 // we cannot see detail of country during the AI or virtual player game 0212 // as the right widget is reserved for combat 0213 // Bug 309863. Disable country details during auto attack also. 0214 if(m_automaton->game()->theWorld()->countryAt(detailPoint)!=nullptr && !m_automaton->isAttackAuto()) 0215 { 0216 detailsAction->setVisible(true); 0217 } 0218 else 0219 { 0220 detailsAction->setVisible(false); 0221 } 0222 } 0223 else 0224 { 0225 // as the context menu can be displayed when AI play 0226 // we disabled the nextPlayer action and the goal 0227 nextPlayer->setVisible(false); 0228 goalAction->setVisible(false); 0229 // Bug 309863. Details of the country and combat are both shown in the right widget. 0230 // Some of the resources are used by both which leads to the crash. Disable detaied view 0231 // of the country when AI is playing. Some of the previous attempts to resolve this (or similar) issue(s) 0232 // disabled this item from context menu, but didn't cover all possible paths. Here, just follow that idea. 0233 // It makes no sense to show just for a moment details of the country when AI combat details will override 0234 // and reuse right widget (no time for human to inspect country details in such short time). 0235 detailsAction->setVisible(false); 0236 } 0237 0238 menu->exec(menuPoint); 0239 } 0240 } 0241 0242 // set the contextual menu event Icon for non-standard action 0243 void DecoratedGameFrame::setIcon() 0244 { 0245 KConfig config(m_automaton->game()->theWorld()->getConfigFileName()); 0246 KConfigGroup onugroup = config.group(QStringLiteral("onu")); 0247 QString skin = onugroup.readEntry("skinpath"); 0248 0249 QString imageFileName; 0250 0251 imageFileName = QStandardPaths::locate(QStandardPaths::AppDataLocation, skin + "/Images/attackOne.png"); 0252 Attack1Action-> setIcon(QIcon(imageFileName)); 0253 0254 imageFileName = QStandardPaths::locate(QStandardPaths::AppDataLocation, skin + "/Images/attackTwo.png"); 0255 Attack2Action-> setIcon(QIcon(imageFileName)); 0256 0257 imageFileName = QStandardPaths::locate(QStandardPaths::AppDataLocation, skin + "/Images/attackThree.png"); 0258 Attack3Action-> setIcon(QIcon(imageFileName)); 0259 0260 imageFileName = QStandardPaths::locate(QStandardPaths::AppDataLocation, skin + "/Images/attackAuto.png"); 0261 AutoAction-> setIcon(QIcon(imageFileName)); 0262 0263 imageFileName = QStandardPaths::locate(QStandardPaths::AppDataLocation, skin + "/Images/moveOne.png"); 0264 Move1Action-> setIcon(QIcon(imageFileName)); 0265 0266 imageFileName = QStandardPaths::locate(QStandardPaths::AppDataLocation, skin + "/Images/moveFive.png"); 0267 Move5Action-> setIcon(QIcon(imageFileName)); 0268 0269 imageFileName = QStandardPaths::locate(QStandardPaths::AppDataLocation, skin + "/Images/moveTen.png"); 0270 Move10Action-> setIcon(QIcon(imageFileName)); 0271 0272 //temporary 0273 imageFileName = QStandardPaths::locate(QStandardPaths::AppDataLocation, skin + "/Images/moveArmies.png"); 0274 m_arenaAction-> setIcon(QIcon(imageFileName)); 0275 0276 imageFileName = QStandardPaths::locate(QStandardPaths::AppDataLocation, skin + '/' + CM_NEXTPLAYER); 0277 nextPlayer-> setIcon(QIcon(imageFileName)); 0278 0279 // temporary 0280 imageFileName = QStandardPaths::locate(QStandardPaths::AppDataLocation, skin + "/Images/newNetGame.png"); 0281 detailsAction-> setIcon(QIcon(imageFileName)); 0282 0283 } 0284 0285 /** 0286 * This slot is called when a mouse key is pressed. As the mouse is used as 0287 * input for all players 0288 * this slot is called to generate a player move out of a mouse input, i.e. 0289 * it converts a QMouseEvent into a move for the game. We do here some 0290 * simple nonsense and use the position of the mouse to generate 0291 * moves containing the keycodes 0292 */ 0293 void DecoratedGameFrame::slotMouseInput(KGameIO *input,QDataStream &stream,QMouseEvent *e,bool *eatevent) 0294 { 0295 qCDebug(KSIRK_LOG) << e; 0296 0297 QGraphicsItem* item = itemAt(mapFromScene(((QGraphicsSceneMouseEvent*)e)->scenePos())); 0298 if (item == nullptr) 0299 { 0300 *eatevent=false; 0301 e->setAccepted(false); 0302 return; 0303 } 0304 0305 while (item->parentItem()!=nullptr && dynamic_cast<KGamePopupItem*>(item)==nullptr) 0306 { 0307 item = item->parentItem(); 0308 } 0309 0310 if (dynamic_cast<KGamePopupItem*>(item)!=nullptr) 0311 { 0312 *eatevent=false; 0313 e->setAccepted(false); 0314 return; 0315 } 0316 0317 KPlayer *player=input->player(); 0318 if (!player->myTurn()) 0319 { 0320 qCDebug(KSIRK_LOG) << "Player " << dynamic_cast<Player*>(player)->name() << ": not my turn!"; 0321 *eatevent=false; 0322 e->setAccepted(false); 0323 return; 0324 } 0325 qCDebug(KSIRK_LOG) << "Player " << dynamic_cast<Player*>(player)->name() << " " << e->type(); 0326 if (e->type() == QEvent::GraphicsSceneMousePress) 0327 { 0328 qCDebug(KSIRK_LOG) << "\tQEvent::MouseButtonPress"; 0329 if (((QGraphicsSceneMouseEvent*)e)->button() == Qt::LeftButton) 0330 { 0331 qCDebug(KSIRK_LOG) << "\tLeft"; 0332 stream << QString("actionLButtonDown"); 0333 } 0334 else if (((QGraphicsSceneMouseEvent*)e)->button() == Qt::RightButton) 0335 { 0336 qCDebug(KSIRK_LOG) << "\tRight"; 0337 stream << QString("actionRButtonDown"); 0338 } 0339 else 0340 { 0341 *eatevent=false; 0342 e->setAccepted(false); 0343 return; 0344 } 0345 } 0346 else if (e->type() == QEvent::GraphicsSceneMouseRelease) 0347 { 0348 qCDebug(KSIRK_LOG) << "\tQEvent::MouseButtonRelease"; 0349 if (((QGraphicsSceneMouseEvent*)e)->button() == Qt::LeftButton) 0350 { 0351 qCDebug(KSIRK_LOG) << "\tLeft"; 0352 stream << QString("actionLButtonUp"); 0353 } 0354 else if (((QGraphicsSceneMouseEvent*)e)->button() == Qt::RightButton) 0355 { 0356 qCDebug(KSIRK_LOG) << "\tRight"; 0357 stream << QString("actionRButtonUp"); 0358 } 0359 else 0360 { 0361 qCDebug(KSIRK_LOG) << "\tOther:" << e->button(); 0362 *eatevent=false; 0363 e->setAccepted(false); 0364 return; 0365 } 0366 } 0367 else if (e->type() == QWheelEvent::GraphicsSceneWheel) 0368 { 0369 qCDebug(KSIRK_LOG) << "Using mouse scroll"; 0370 } 0371 else 0372 { 0373 *eatevent=false; 0374 e->setAccepted(false); 0375 return; 0376 } 0377 QPointF newPoint = ((QGraphicsSceneMouseEvent*)e)->scenePos(); 0378 qCDebug(KSIRK_LOG) << "\tPosition: " << newPoint; 0379 0380 detailPoint.setX((int)newPoint.x()); 0381 detailPoint.setY((int)newPoint.y()); 0382 0383 stream << newPoint; 0384 *eatevent=true; 0385 qCDebug(KSIRK_LOG) << "Mouse input done... eatevent=true"; 0386 } 0387 0388 void DecoratedGameFrame::arenaState() 0389 { 0390 qCDebug(KSIRK_LOG) << m_arenaAction->isArenaEnabled(); 0391 //if (m_arenaAction->isChecked()) 0392 if (m_arenaAction->isArenaEnabled()) 0393 { 0394 m_arenaAction->setText(i18n("Enable Arena")); 0395 m_arenaAction->setArenaEnabled(false); 0396 emit(arenaStateSignal(false)); 0397 } 0398 else 0399 { 0400 m_arenaAction->setText(i18n("Disable Arena")); 0401 m_arenaAction->setArenaEnabled(true); 0402 emit(arenaStateSignal(true)); 0403 } 0404 0405 attackMenu->exec(menuPoint); 0406 } 0407 0408 void DecoratedGameFrame::attackAuto() 0409 { 0410 qCDebug(KSIRK_LOG); 0411 unsigned int firstCountryNbArmies = ( m_automaton!=nullptr && m_automaton->game()!=nullptr && m_automaton->game()->firstCountry()!=nullptr ) 0412 ? m_automaton->game()->firstCountry()->nbArmies() : 0 ; 0413 m_automaton->setAttackAuto(firstCountryNbArmies>0); 0414 if (firstCountryNbArmies > 3) 0415 { 0416 m_automaton->game()->slotAttack3(); 0417 } 0418 else if (firstCountryNbArmies > 2) 0419 { 0420 m_automaton->game()->slotAttack2(); 0421 } 0422 else if (firstCountryNbArmies > 1) 0423 { 0424 m_automaton->game()->slotAttack1(); 0425 } 0426 } 0427 0428 void DecoratedGameFrame::slotDetails() 0429 { 0430 qCDebug(KSIRK_LOG); 0431 m_automaton->game()->getRightDialog()->displayCountryDetails(detailPoint); 0432 m_automaton->game()->getRightDialog()->open(); 0433 } 0434 0435 0436 QMenu * DecoratedGameFrame::getContextMenu() 0437 { 0438 return this->menu; 0439 } 0440 0441 QMenu * DecoratedGameFrame::getAttackContextMenu() 0442 { 0443 return this->attackMenu; 0444 } 0445 0446 QMenu * DecoratedGameFrame::getMoveContextMenu() 0447 { 0448 qCDebug(KSIRK_LOG); 0449 return this->moveMenu; 0450 } 0451 0452 QAction* DecoratedGameFrame::getAttack1Action() 0453 { 0454 return this->Attack1Action; 0455 } 0456 0457 QAction* DecoratedGameFrame::getAttack2Action() 0458 { 0459 return this->Attack2Action; 0460 } 0461 0462 QAction* DecoratedGameFrame::getAttack3Action() 0463 { 0464 return this->Attack3Action; 0465 } 0466 0467 QAction* DecoratedGameFrame::getMove1Action() 0468 { 0469 return this->Move1Action; 0470 } 0471 0472 QAction* DecoratedGameFrame::getMove5Action() 0473 { 0474 return this->Move5Action; 0475 } 0476 0477 QAction* DecoratedGameFrame::getMove10Action() 0478 { 0479 return this->Move10Action; 0480 } 0481 0482 void DecoratedGameFrame::setMenuPoint(QPoint menuPoint) 0483 { 0484 this->menuPoint = menuPoint; 0485 } 0486 0487 bool DecoratedGameFrame::viewportEvent(QEvent* event) 0488 { 0489 bool res = QGraphicsView::viewportEvent(event); 0490 if (event->type() == QEvent::Resize) 0491 { 0492 qCDebug(KSIRK_LOG); 0493 m_automaton->game()->updateScrollArrows(); 0494 } 0495 return res; 0496 } 0497 0498 } 0499 0500 #include "moc_decoratedgameframe.cpp"