File indexing completed on 2024-04-21 04:04:46

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"