/*************************************************************************** qcommandline.cpp - description ------------------- begin : ven avr 19 13:21:00 CET 2002 copyright : (C) 2002 by Romain Vinot email : vinot@aist.enst.fr ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifdef _WIN32 #pragma warning (disable : 4786) #endif #include // For sscanf #include #include #include #include #include #include #include #include #include #include #include #include "qcommandline.h" #include "qinterfaceimpl.h" #include "qmyevent.h" #include "qdirectiondialogimpl.h" #include "qlevelinfoimpl.h" #include "qcreature.h" #include "qpixmapboard.h" #include "gamemanager.h" #include "qdatastoring.h" #include "qnewgameimpl.h" #include "qmaildialogimpl.h" QCommandLine::QCommandLine(QPixmapBoard *x, QCreature *c, QInterfaceImpl *main) : GUICommandLine(x,c), QThread(), qmain(main), qinfo(main->qinfo), qview(main->qViewLabel), qsel(main->qSelectedLabel), qlist(main->qListCreatures), qViewButton(main->qViewButton), qturninfo(main->qTurnLabel), qstate(Q_NONE) { QThread::start(); } QCommandLine::~QCommandLine(void) {} QState QCommandLine::getState(void) { return qstate; } void QCommandLine::endOfExecution(void) { currCmd="exit"; gameLock.wakeOne(); } void QCommandLine::run() { gameMutex.lock(); while (1) { Game_Wait(); GUICommandLine::getCommand(currCmd); } } // This method is executed by the GUI-thread. void QCommandLine::Game_Wake(void) { // cout << "DEBUG: *GUI thread* : Just before waking game thread.\n"; gameLock.wakeOne(); // cout << "DEBUG: *GUI thread* : Just after waking game thread.\n"; } void QCommandLine::Game_Wait(void) { // cout << "DEBUG: *Game thread* : Just before beginning the waiting.\n"; gameLock.wait(&gameMutex); if (currCmd=="exit") QThread::exit(); //cout << "DEBUG: *Game thread* : Just being woken.\n"; } // This method is executed by the GUI-thread. void QCommandLine::getCommand(QString command) { currCmd = command; Game_Wake(); } void QCommandLine::GetEvent(void) { switch(qstate) { case Q_DIRECTION: GUI_GetDirection(); break; case Q_LEVEL: GUI_GetLevelToPlay(); break; case Q_BOOLEAN: GUI_GetYesOrNo(); break; case Q_ENDOFGAME: GUI_EndOfGame(); break; case Q_LEVELINFO: GUI_PrintLevelInfo(); break; case Q_POPUPMSG: GUI_PrintPopupMessage(); break; case Q_NEWGAME: GUI_GetGameType(); break; case Q_FILENAME: GUI_GetFilename(); break; case Q_IPADRESS: GUI_GetIPAdress(); break; case Q_SMTPINFOS: GUI_GetSmtpInfos(); break; default: break; } } void QCommandLine::Write(QString w, bool isCommand) { postEvent(qmain, new WriteCustomEvent(1000,w)); } void QCommandLine::ResizeBoard(int x, int y) { postEvent(qmain, new ResizeCustomEvent(x,y)); } void QCommandLine::setObjectButtonsVisible(bool vis) { postEvent(qmain, new ButtonShowHideCustomEvent(vis)); } void QCommandLine::DrawInterface(void) { postEvent(qmain, new DrawInterfaceCustomEvent(0)); man->printAllCreaturesInfo(); man->printSelectedCreature(); man->printOnViewCreature(); } void QCommandLine::GUIDrawInterface(void) { qview->clear(); qsel->clear(); guiboard->printBoard(); if (man->onViewIsSelectable()) qViewButton->setEnabled(TRUE); else qViewButton->setEnabled(false); qturninfo->setText(man->getLevelMessage()); qmain->EnableDisableButtons(); } void QCommandLine::ClearListCreatures(void) { postEvent(qmain, new DrawInterfaceCustomEvent(1)); } void QCommandLine::GUIClearListCreatures(void) { qlist->clear(); } void QCommandLine::ClearInfoPanel(void) { postEvent(qmain, new DrawInterfaceCustomEvent(2)); } void QCommandLine::GUI_ClearInfoPanel(void) { qinfo->clear(); } void QCommandLine::boardClick(int xcoord, int ycoord, bool isLeftButton) { char com[64]; if (isLeftButton) { sprintf(com, "%d %d", xcoord, ycoord); getCommand(com); } else { QString tmp = man->chooseAction(xcoord,ycoord); getCommand(tmp.latin1()); } } pair QCommandLine::GetDirection(QString txt, bool enableReuse) { gui_dir=NODIRECTION; gui_msg = txt; if (man->isInReplayMode()) { QString val = man->getRecord(); if (val.startsWith("get direction")) { int idx = val.find(' ',14); QString dir = val.mid(14,idx-14); return pair(string2dir(dir),val.find("noreuse",idx)==-1); } else { cout << "Problem, received [" << val << "] instead of [get dir xxx]!\n"; printPopupMessage("Error during replay mode. Game will be stopped"); endOfExecution(); } } qstate = Q_DIRECTION; gui_res=enableReuse; // Hack: this variable should not be used for that. postEvent(qmain, new QCustomEvent(346798)); Game_Wait(); // The GUI-thread will put the info on the gui_dir variable. return pair (gui_dir,gui_res); } void QCommandLine::GUI_GetDirection(void) { QDirectionDialogImpl ask(&gui_dir,&gui_res,gui_res); // Hack : gui_res is used as input and as output... ask.setLabel(gui_msg); ask.exec(); qstate = Q_NONE; Game_Wake(); } QString QCommandLine::GetLevelToPlay(void) { gui_str=""; qstate = Q_LEVEL; postEvent(qmain, new QCustomEvent(346798)); Game_Wait(); // The GUI-thread will put the info on the gui_level variable. return gui_str; } void QCommandLine::GUI_GetLevelToPlay(void) { char path[1024]; sprintf(path,"%s%clevels",levelDir.latin1(), DIR_DELIMITER); QString s( QFileDialog::getOpenFileName( path, "Mission file (*.lvl)") ); // if ( s.isEmpty() ) // return; gui_str = s; qstate = Q_NONE; Game_Wake(); } QString QCommandLine::GetFilename(bool PbemExt) { gui_str=""; gui_res = PbemExt; qstate = Q_FILENAME; postEvent(qmain, new QCustomEvent(346798)); Game_Wait(); return gui_str; } void QCommandLine::GUI_GetFilename(void) { QString fn; while (fn.isNull()) { if (gui_res) { fn = QFileDialog::getSaveFileName(homeDir+DIR_DELIMITER+"savegame", "PBEM Savegame for spacehulk (*.pbem)"); if (!fn.isNull() && fn.findRev(".pbem")!=(int) fn.length()-5) fn += ".pbem"; } else { fn = QFileDialog::getSaveFileName(homeDir+DIR_DELIMITER+"savegame", "Savegame for spacehulk (*.sav)"); if (!fn.isNull() && fn.findRev(".sav")!=(int) fn.length()-4) fn += ".sav"; } } gui_str = fn; qstate = Q_NONE; Game_Wake(); } int QCommandLine::GetCase(set *cases, QString txt) { int caseId = -1; Write(txt); if (man->isInReplayMode()) { QString val = man->getRecord(); if (val.startsWith("get case ")) { val.remove(0,9); return val.toInt(); } else { cout << "Problem, received [" << val << "] instead of [get case xxx]!\n"; printPopupMessage("Error during replay mode. Game will be stopped"); endOfExecution(); } } guiboard->setYellowCases(cases); DrawInterface(); while (1) { qstate = Q_DIRECTION; Game_Wait(); if (!getMainCommands(currCmd)) { int xcoord, ycoord; int nb = sscanf(currCmd.latin1(),"%d %d", &xcoord, &ycoord); caseId = xcoord+ycoord*board->Xmax; if (nb!=2) { Write("You must choose a yellow square. No other command is allowed."); } else if (cases->find(caseId)!=cases->end()) break; else { QString msg="This square is not allowed. Please choose another one.\n"; msg += "Only yellow squares are allowed."; Write(msg); } } } qstate = Q_NONE; guiboard->delYellowCases(); return caseId; } pair > QCommandLine::GetCaseAndDirection(set *ca,QString txt,bool enableReuse) { if (man->isInReplayMode()) { QString val = man->getRecord(); if (val.startsWith("get casedir ")) { val.remove(0,12); int idx = val.find(' '); int nb = val.mid(0,idx).toInt(); val.remove(0,idx+1); idx = val.find(' '); QString dir = val.mid(0,idx); val.remove(0,idx+1); return pair > (nb,pair(string2dir(dir),val.find("noreuse")==-1)); } else { cout << "Problem, received [" << val << "] instead of [get casedir xxx xxx]!\n"; printPopupMessage("Error during replay mode. Game will be stopped"); endOfExecution(); } } int caseId = GetCase(ca, txt); pair dir=GetDirection("Give an orientation.\n",enableReuse); return pair >(caseId, dir); } bool QCommandLine::GetYesOrNo(QString txt) { gui_res=false; gui_msg = txt; if (man->isInReplayMode()) { QString val = man->getRecord(); if (val.startsWith("get yesorno ")) { val.remove(0,12); return val.toInt(); } else { cout << "Problem, received [" << val << "] instead of [get yesorno xxx]!\n"; printPopupMessage("Error during replay mode. Game will be stopped"); endOfExecution(); } } qstate = Q_BOOLEAN; postEvent(qmain, new QCustomEvent(346798)); Game_Wait(); // The GUI-thread will put the info on the gui_dir variable. return gui_res; } void QCommandLine::GUI_GetYesOrNo(void) { int res=QMessageBox::information(qmain, "QSpacehulk - Answer the question", gui_msg, "Yes", "No"); gui_res = (res==0); qstate = Q_NONE; Game_Wake(); } void QCommandLine::endOfGame(QString txt) { gui_msg = txt; qstate = Q_ENDOFGAME; postEvent(qmain, new QCustomEvent(346798)); Game_Wait(); } void QCommandLine::GUI_EndOfGame(void) { QMessageBox::about( qmain, "QSpaceHulk - End Of Game", gui_msg); qstate = Q_NONE; Game_Wake(); } void QCommandLine::printLevelInfo(QString &title, QString &auth, QString &nar, QString &obj, QString &forc, QString &cond) { leveltitle = title; levelauthor = auth; levelnarration = nar; levelobjectives = obj; levelforces = forc; levelcond = cond; qstate = Q_LEVELINFO; postEvent(qmain, new QCustomEvent(346798)); Game_Wait(); } void QCommandLine::printLevelInfo(void) { man->getLevelInfo(leveltitle, levelauthor, levelnarration, levelobjectives, levelforces, levelcond); qstate = Q_LEVELINFO; postEvent(qmain, new QCustomEvent(346798)); Game_Wait(); } void QCommandLine::GUI_PrintLevelInfo(void) { QLevelInfoImpl lev(qmain, leveltitle, levelauthor, levelnarration, levelobjectives, levelforces, levelcond); lev.exec(); qstate = Q_NONE; Game_Wake(); } void QCommandLine::printPopupMessage(QString msg) { gui_msg = msg; qstate = Q_POPUPMSG; postEvent(qmain, new QCustomEvent(346798)); Game_Wait(); } void QCommandLine::GUI_PrintPopupMessage(void) { QMessageBox::about( qmain, "QSpaceHulk - Message", gui_msg); qstate = Q_NONE; Game_Wake(); } gameType QCommandLine::GetGameType(bool *heurisTurn, int *cheatProtection) { qstate = Q_NEWGAME; heuris = heurisTurn; cheat = cheatProtection; postEvent(qmain, new QCustomEvent(346798)); Game_Wait(); return gType; } void QCommandLine::GUI_GetGameType(void) { QNewGameImpl ng(qmain, heuris, &gType, cheat); ng.exec(); qstate = Q_NONE; Game_Wake(); } QString QCommandLine::GetIPAdress(void) { qstate = Q_IPADRESS; postEvent(qmain, new QCustomEvent(346798)); Game_Wait(); return gui_str; } void QCommandLine::GUI_GetIPAdress(void) { IPAdressDialog ip(qmain,&gui_str); ip.exec(); qstate = Q_NONE; Game_Wake(); } void QCommandLine::CenterView(int caseId) { postEvent(qmain, new CenterCustomEvent(caseId)); } void QCommandLine::GetSmtpInfos(SmtpInfo *info) { qstate = Q_SMTPINFOS; gui_info = info; postEvent(qmain, new QCustomEvent(346798)); Game_Wait(); } void QCommandLine::GUI_GetSmtpInfos(void) { QMailDialogImpl md(qmain, gui_info); md.exec(); qstate = Q_NONE; Game_Wake(); } // Done by the Game Thread. void QCommandLine::GetNetworkCommand(void) { qstate = Q_NETWORK; while (qstate==Q_NETWORK) Game_Wait(); } // Done by the GUI Thread. void QCommandLine::PostNetworkCommand(void) { if (qstate==Q_NETWORK) { qstate=Q_NONE; Game_Wake(); } } IPAdressDialog::IPAdressDialog(QWidget *parent, QString *m) : QDialog( parent, "Specify IP adress", true ), msg(m) { setName( "Specify IP adress" ); resize( 318, 138 ); // setCaption( tr( "Form1" ) ); Form1Layout = new QVBoxLayout( this ); Form1Layout->setSpacing( 6 ); Form1Layout->setMargin( 11 ); label = new QLabel( this, "DialogIP" ); label->setText( tr( "Specify the IP adress of the other player\n" "(the IP adress is four numbers from 0-255 separated by dot.)" ) ); label->setAlignment( int( QLabel::AlignCenter ) ); Form1Layout->addWidget( label ); ip = new QLineEdit( this, "ip" ); Form1Layout->addWidget( ip ); Layout1 = new QHBoxLayout; Layout1->setSpacing( 6 ); Layout1->setMargin( 0 ); QSpacerItem* spacer = new QSpacerItem( 20, 20, QSizePolicy::Expanding, QSizePolicy::Minimum ); Layout1->addItem( spacer ); ok = new QPushButton( this, "PushButton1" ); ok->setText( tr( "Ok" ) ); Layout1->addWidget( ok ); QSpacerItem* spacer_2 = new QSpacerItem( 20, 20, QSizePolicy::Expanding, QSizePolicy::Minimum ); Layout1->addItem( spacer_2 ); Form1Layout->addLayout( Layout1 ); // signals and slots connections connect( ok, SIGNAL( clicked() ), this, SLOT( clickOk() ) ); connect( ip, SIGNAL( returnPressed() ), this, SLOT( clickOk() ) ); } void IPAdressDialog::clickOk() { *msg = ip->text(); done(0); }