/*************************************************************************** core.cpp - description ------------------- begin : Tue Oct 2 2001 copyright : (C) 2003 by Troy Corbin Jr. email : tcorbin@users.sourceforge.net ***************************************************************************/ /*************************************************************************** * * * 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. * * * ***************************************************************************/ /* KDE */ #include #include /* TQt */ #include /* Local */ #include "core.moc" #include "match.h" #include "list_pgn.h" #include "thinbuttons.h" #include "io_engine.h" #include "io_internet.h" #include "match_param.h" /* Tabs */ #include "tabmanager.h" /////////////////////////////////////// // // core::core // /////////////////////////////////////// core::core(TQWidget *parent, const char *name, resource *Rsrc ) : TQWidget(parent,name) { myResource = Rsrc; listPGN = NULL; currentMatch = NULL; myButtonGroup = new thinbuttons( this, "ButtonGroup", myResource ); myButtonGroup->show(); connect( myButtonGroup, TQ_SIGNAL( leftClick(int) ), this, TQ_SLOT( setMatch(int) ) ); connect( myButtonGroup, TQ_SIGNAL( menuItemSelected(int,int) ), this, TQ_SLOT( thinButtonMenu(int,int) ) ); myCoreClock.start( 100, FALSE ); resize(); } /////////////////////////////////////// // // core::~core // /////////////////////////////////////// core::~core() { myCoreClock.stop(); delete myButtonGroup; } /////////////////////////////////////// // // core::createNewIO // /////////////////////////////////////// void core::createNewIO( int type, int ID, int side, int str ) { io_internet *internetioPtr = NULL; io_engine *engineioPtr = NULL; // io_email *ioEmailPtr = NULL; switch( type ) { /* PLAYERTCP */ case PLAYERTCP: if( ID == Null ) { /* Create a NEW internetIO */ internetioPtr = new io_internet( this, myResource ); myIOMap.add( ID, internetioPtr ); internetioPtr->setID( ID ); connect( internetioPtr, TQ_SIGNAL( sendCMD( const Command& ) ), this, TQ_SLOT( command2Match( const Command& ) ) ); } else { /* Use an existing internetIO */ internetioPtr = (io_internet*) myIOMap.find(Null); if( internetioPtr == NULL ) { kdWarning() << "core::createNewIO: Trying to connect a match to an internetIO that doesn't exsist." << endl; } else { myIOMap.add( ID, internetioPtr ); } } break; /* PLAYEREXAMINE */ case PLAYEREXAMINE: /* examine mode needs only 1 io mapped to it */ if( ID == Null ) { /* Create a NEW internetIO */ internetioPtr = new io_internet( this, myResource ); myIOMap.add( ID, internetioPtr ); internetioPtr->setID( ID ); connect( internetioPtr, TQ_SIGNAL( sendCMD( const Command& ) ), this, TQ_SLOT( command2Match( const Command& ) ) ); } else { internetioPtr = (io_internet*) myIOMap.find(ID); if( internetioPtr == NULL ) { /* no io mapped to the ID yet, use the internetio */ /* Use an existing internetIO */ internetioPtr = (io_internet*) myIOMap.find(Null); if( internetioPtr == NULL ) { kdWarning() << "core::createNewIO: Trying to connect a match to an internetIO that doesn't exsist." << endl; } else { myIOMap.add( ID, internetioPtr ); } } /* this ID is already mapped we don't need another one */ } break; /* PLAYERPC */ case PLAYERPC: engineioPtr = new io_engine( this, myResource ); myIOMap.add( ID, engineioPtr ); engineioPtr->setID( ID ); connect( engineioPtr, TQ_SIGNAL( sendCMD( const Command& ) ), this, TQ_SLOT( command2Match( const Command& ) ) ); engineioPtr->Start( side ); engineioPtr->recvCMD( Command( ID, CMD_Set_Difficulty, TQString().setNum( 1 << str ) ) ); break; /* PLAYEREMAIL */ case PLAYEREMAIL: // ioEmailPtr = new io_email( this, myResource ); // myIOMap.add( ID, ioEmailPtr ); // ioEmailPtr->setID( ID ); // connect( ioEmailPtr, TQ_SIGNAL( sendCMD( const Command& ) ), this, TQ_SLOT( command2Match( const Command& ) ) ); break; default: /* No IO needed */ break; } } /////////////////////////////////////// // // core::newMatch(match_params* param); // /////////////////////////////////////// match* core::newMatch( match_param* param ) { match *match_ptr = NULL; int newID; /* create a new ID for the match */ newID = myIDManager.getNewID(); /* Create the match navigation button */ myButtonGroup->create( newID ); /* Create the match */ match_ptr = new match(this, param, myResource); match_ptr->setID( newID ); myMatchMap.add( newID, match_ptr ); /* Create IOs */ createNewIO( param->type(WHITE), newID, WHITE, param->strength(WHITE) ); createNewIO( param->type(BLACK), newID, BLACK, param->strength(BLACK) ); /* Connect Signals */ connect( match_ptr, TQ_SIGNAL( sendCMD( const Command& ) ), this, TQ_SLOT( command2IO( const Command& ) ) ); connect( &myCoreClock, TQ_SIGNAL( timeout() ), match_ptr, TQ_SLOT( tick() ) ); /* Set this new match as the current match */ setMatch( newID ); setActiveWindow(); /* Save our configuration settings */ myResource->ConfigWrite(); return match_ptr; } /////////////////////////////////////// // // core::setMatch // /////////////////////////////////////// void core::setMatch( int ID ) { /* Disconnect the current match from the display */ if( currentMatch != NULL ) { currentMatch->setCurrent( FALSE ); disconnect( currentMatch, TQ_SIGNAL( setClocks() ), this, TQ_SLOT( slot_setClocks() ) ); disconnect( currentMatch, TQ_SIGNAL( setStatusBar( const int&, const TQString& ) ), this, TQ_SLOT( slot_setStatusBar( const int&, const TQString& ) ) ); disconnect( currentMatch, TQ_SIGNAL( setNotation() ), this, TQ_SLOT( slot_setNotation() ) ); currentMatch->setVisibility( FALSE ); } /* Now display the new match, and connect it's signals to the GUI */ currentMatch = myMatchMap.find( ID ); currentMatch->setVisibility( TRUE ); myButtonGroup->setButton( ID ); connect( currentMatch, TQ_SIGNAL( setClocks() ), this, TQ_SLOT( slot_setClocks() ) ); connect( currentMatch, TQ_SIGNAL( setStatusBar( const int&, const TQString& ) ), this, TQ_SLOT( slot_setStatusBar( const int&, const TQString& ) ) ); connect( currentMatch, TQ_SIGNAL( setNotation() ), this, TQ_SLOT( slot_setNotation() ) ); currentMatch->setCurrent( TRUE ); emit requestResize(); emit initMatch(); currentMatch->resendStatusBar(); /* Give Ourselves Focus */ setActiveWindow(); topLevelWidget()->raise(); } /////////////////////////////////////// // // core::clearAll // /////////////////////////////////////// bool core::clearAll( void ) { while( myMatchMap.count() ) { if( clearMatch() != TRUE ) return FALSE; } return TRUE; } /////////////////////////////////////// // // core::clearMatch // /////////////////////////////////////// bool core::clearMatch( int id ) { match *departingMatch, *nextMatch; io_base *ioPtr; if( id == Null ) { if( currentMatch != NULL ) { id = currentMatch->getID(); } else { return FALSE; } } departingMatch = myMatchMap.find(id); /* A bad ID was passed */ if( departingMatch == NULL ) { kdError() << "core::clearMatch: Bad matchID " << id << " could not be cleared." << endl; return FALSE; } /* Save if needed */ if( departingMatch->modified() ) { if( save( id, TRUE, FALSE ) == FALSE ) { return FALSE; } } /* Get ID of another match so it can become the current match */ if( departingMatch == currentMatch ) { /* Find another match in the map */ nextMatch = --myMatchMap; if( nextMatch == NULL ) { ++myMatchMap; nextMatch = ++myMatchMap; } /* Set the new current match */ if( nextMatch != NULL ) { setMatch( nextMatch->getID() ); } else { currentMatch = NULL; emit initMatch(); } } /* Remove IOs in this match... */ ioPtr = myIOMap.find(id); while( ioPtr != NULL ) { myIOMap.remove( id ); if( ioPtr->getType() != io_base::INTERNET ) { delete ioPtr; } ioPtr = myIOMap.find(id); } /* ...and remove the match */ myMatchMap.remove( id ); myButtonGroup->remove( id ); delete departingMatch; resize(); return TRUE; } /////////////////////////////////////// // // core::resize // /////////////////////////////////////// void core::resize( void ) { int size = 8 + ( 1 * ( myResource->ThemeBorder == TRUE ) ); if( currentMatch != NULL ) { currentMatch->resize(); myButtonGroup->resize( currentMatch->width() ); myButtonGroup->move( 0, currentMatch->height() ); setFixedSize( currentMatch->width(), currentMatch->height() + myButtonGroup->height() ); } else { myButtonGroup->resize( myResource->ThemeSize * size ); myButtonGroup->move( 0, myResource->ThemeSize * size ); setFixedSize( myResource->ThemeSize * size, ( myResource->ThemeSize * size ) + myButtonGroup->height() ); } } /////////////////////////////////////// // // core::command2IO // /////////////////////////////////////// void core::command2IO( const Command &command ) { io_base *io; int id = ((Command)command).getID(); io = myIOMap.find(id); while( io != NULL ) { io->recvCMD(command); io = myIOMap.findNext(); } } /////////////////////////////////////// // // core::command2Match // /////////////////////////////////////// void core::command2Match( const Command &command ) { match_param *paramPtr; match *matchPtr; Command cmd = command; matchPtr = myMatchMap.find( cmd.getID() ); while( matchPtr != NULL ) { /* Catch Commands Meant for Core */ switch( cmd.getCommand() ) { case CMD_Hint: KMessageBox::information( this, cmd.getData(), i18n("Hint") ); break; case CMD_Tell_User: KMessageBox::information( this, cmd.getData(), i18n( "Tell User" ) ); break; case CMD_Tell_User_Error: KMessageBox::sorry( this, cmd.getData(), i18n( "Tell User Error" ) ); break; case CMD_Tell_Opponent: paramPtr = matchPtr->getParam(); if( ( paramPtr->type( WHITE ) == PLAYERLOCAL ) || ( paramPtr->type( BLACK ) == PLAYERLOCAL ) ) KMessageBox::information( this, cmd.getData(), i18n( "Tell Opponent" ) ); else command2IO( command ); break; case CMD_Tell_Others: command2IO( command ); break; case CMD_Tell_ICS: command2IO( command ); break; case CMD_Tell_All: paramPtr = matchPtr->getParam(); if( ( paramPtr->type( WHITE ) == PLAYERLOCAL ) || ( paramPtr->type( BLACK ) == PLAYERLOCAL ) ) KMessageBox::information( this, cmd.getData(), i18n( "Tell All" ) ); command2IO( command ); break; case CMD_Out_Of_Book: // engine[enginePtr - 1]->sendCMD( CMD_Check_Book ); break; default: /* Just send it to the Match */ matchPtr->recvCMD( command ); break; } matchPtr = myMatchMap.findNext(); } } /////////////////////////////////////// // // core::flag // /////////////////////////////////////// bool core::flag( const bool Army ) { if( currentMatch == NULL ) return FALSE; return currentMatch->flag( Army ); return false; } /////////////////////////////////////// // // core::clock // /////////////////////////////////////// TQString core::clock( const bool Army ) { if( currentMatch == NULL ) return TQString(); return currentMatch->clock( Army ); return ""; } /////////////////////////////////////// // // core::modified // /////////////////////////////////////// bool core::modified( void ) { if( currentMatch == NULL ) return FALSE; return currentMatch->modified(); return false; } /////////////////////////////////////// // // core::paused // /////////////////////////////////////// bool core::paused( void ) { if( currentMatch == NULL ) return FALSE; return currentMatch->paused(); return false; } /////////////////////////////////////// // // core::isOnline // /////////////////////////////////////// bool core::isOnline( void ) { unsigned int index; for( index=0; index < myIOMap.count(); index++ ) { if( myIOMap[index]->getType() == io_base::INTERNET ) { return TRUE; } } return FALSE; } /////////////////////////////////////// // // core::onMove // /////////////////////////////////////// char core::onMove( void ) { if( currentMatch == NULL ) return Null; return currentMatch->onMove(); } /////////////////////////////////////// // // core::caption // /////////////////////////////////////// TQString core::caption( void ) { TQButton *Button; if( currentMatch == NULL ) return TQString(); Button = myButtonGroup->find( currentMatch->getID() ); if( Button != NULL ) Button->setText( currentMatch->caption() ); return currentMatch->caption(); } /////////////////////////////////////// // // core::whiteInput // /////////////////////////////////////// char core::whiteInput(void) { if( currentMatch == NULL ) return Null; return currentMatch->input(WHITE); } /////////////////////////////////////// // // core::blackInput // /////////////////////////////////////// char core::blackInput(void) { if( currentMatch == NULL ) return Null; return currentMatch->input(BLACK); } /////////////////////////////////////// // // core::review // /////////////////////////////////////// void core::review( int Index ) { if( currentMatch == NULL ) return; currentMatch->review( Index ); } /////////////////////////////////////// // // core::inputOnMove // /////////////////////////////////////// char core::inputOnMove( bool reverse ) { if( currentMatch == NULL ) return Null; return currentMatch->inputOnMove( reverse ); } /////////////////////////////////////// // // core::notation // /////////////////////////////////////// TQStringList* core::notation( void ) { if( currentMatch == NULL ) return NULL; return currentMatch->notation(); } /////////////////////////////////////// // // core::slot_setNotation // /////////////////////////////////////// void core::slot_setNotation( void ) { emit setNotation(); } /////////////////////////////////////// // // core::slot_setStatusBar // /////////////////////////////////////// void core::slot_setStatusBar( const int &ID, const TQString& MSG ) { emit setStatusBar( ID, MSG ); } /////////////////////////////////////// // // core::slot_setClocks // /////////////////////////////////////// void core::slot_setClocks( void ) { emit setClocks(); } /////////////////////////////////////// // // core::print // /////////////////////////////////////// void core::print( int ID ) { match *m2p; if( ID == Null ) { m2p = currentMatch; } else { m2p = myMatchMap.find( ID ); } if( m2p == NULL ) return; m2p->print(); return; } /////////////////////////////////////// // // core::load // /////////////////////////////////////// bool core::load( void ) { const TQString fileFilter( "*.pgn *.Pgn *.PGN|Portable Game Notation (.pgn)\n*|All Files" ); TQString URL; URL = KFileDialog::getOpenFileName( TQString(), TQString( fileFilter ), this, i18n( "Load PGN..." ) ); if( URL.isEmpty() ) return FALSE; return load( URL ); } bool core::load( const TQString &IncURL ) { listPGN = new list_pgn( 0, "listPGN" ); myResource->tabManager->addTab( listPGN, IncURL.section( '/', -1 ) ); connect( listPGN, TQ_SIGNAL( selected( const TQString&, const int& ) ), this, TQ_SLOT( load( const TQString&, const int& ) ) ); listPGN->setURL( IncURL ); return TRUE; } bool core::load( const TQString &url, const int &pos ) { newMatch( new match_param( myResource, PLAYERLOAD, PLAYERLOAD ) ); return currentMatch->load( url, pos ); } /////////////////////////////////////// // // core::save // /////////////////////////////////////// bool core::save( const int ID, const bool Prompt, const bool SaveAs ) { const TQString fileFilter( "*.pgn *.Pgn *.PGN|Portable Game Notation (.pgn)\n*|All Files" ); match *match2bSaved; int answer; TQString URL; if( ID == Null ) { /* Use current match */ match2bSaved = currentMatch; } else { match2bSaved = myMatchMap.find( ID ); } if( match2bSaved == NULL ) return FALSE; if( Prompt ) { /* Prompt for the save */ myResource->ConfigWrite(); answer = KMessageBox::warningYesNoCancel( this, i18n("Would you like to save this match?"), i18n("Save Match?"), TQString(), TQString(), TQString("PromptForSaving") ); myResource->ConfigRead(); if( answer == KMessageBox::Cancel ) { return FALSE; } if( answer == KMessageBox::No ) { return TRUE; } } /* Get the last URL we used */ URL = match2bSaved->url(); if( ( URL.isEmpty() ) || ( SaveAs ) ) { /* Get a new URL */ URL = KFileDialog::getSaveFileName( TQString(), TQString( fileFilter ), this, i18n( "Save Match..." ) ); if( URL.isNull() ) { return FALSE; } if( URL.findRev( ".pgn", -1, FALSE ) == -1 ) { URL += ".pgn"; } } if( match2bSaved->save( URL ) == FALSE ) { emit setStatusBar( SAVE_ERROR ); return FALSE; } emit setStatusBar( SAVE_OK ); match2bSaved->setModified( FALSE ); return TRUE; } /////////////////////////////////////// // // core::matchMenu // /////////////////////////////////////// void core::matchMenu( int opt ) { unsigned int index; switch(opt) { /* Offer / Accept Draw */ case MENU_OFFER_DRAW: // Fall Through case MENU_ACCEPT_DRAW: if( whiteInput() == PLAYERLOCAL ) { command2Match( Command( currentMatch->getID(), CMD_Offer_Draw, TQString("W") ) ); } if( blackInput() == PLAYERLOCAL ) { command2Match( Command( currentMatch->getID(), CMD_Offer_Draw, TQString("B") ) ); } command2IO( Command( currentMatch->getID(), CMD_Offer_Draw ) ); break; /* Reject Draw */ case MENU_REJECT_DRAW: command2IO( Command( currentMatch->getID(), CMD_Reject_Draw ) ); break; /* Resign */ case MENU_RESIGN: if( ( whiteInput() == PLAYERLOCAL ) && ( currentMatch->onMove() == WHITE ) ) { command2IO( Command( currentMatch->getID(), CMD_White_Resign ) ); currentMatch->recvCMD( Command( currentMatch->getID(), CMD_White_Resign ) ); } if( ( blackInput() == PLAYERLOCAL ) && ( currentMatch->onMove() == BLACK ) ) { command2IO( Command( currentMatch->getID(), CMD_Black_Resign ) ); currentMatch->recvCMD( Command( currentMatch->getID(), CMD_Black_Resign ) ); } break; /* Retract */ case MENU_RETRACT: command2IO( Command( currentMatch->getID(), CMD_Retract_Move ) ); currentMatch->retract(); currentMatch->retract(); emit setNotation(); if( onMove() == WHITE ) emit setStatusBar( WHITE_TURN ); else emit setStatusBar( BLACK_TURN ); break; /* Move Now */ case MENU_MOVE_NOW: command2IO( Command( currentMatch->getID(), CMD_MoveNow ) ); break; /* Hint */ case MENU_HINT: currentMatch->requestHint(); break; /* Orientation */ case MENU_ORIENTATION: currentMatch->flip(); break; /* Ponder */ case MENU_PONDER: if( myResource->OPTION_Ponder ) { command2IO( Command( currentMatch->getID(), CMD_Ponder ) ); } else { command2IO( Command( currentMatch->getID(), CMD_No_Pondering ) ); } break; /* Pause */ case MENU_PAUSE: currentMatch->setPaused( !currentMatch->paused() ); if( currentMatch->paused() ) { command2IO( Command( currentMatch->getID(), CMD_Pause ) ); } else { command2IO( Command( currentMatch->getID(), CMD_Resume ) ); } break; /* Pause All */ case MENU_PAUSEALL: if( myMatchMap.count() ) { for( index = 0; index < myMatchMap.count(); index++ ) { if( ( whiteInput() == PLAYERTCP ) || ( blackInput() == PLAYERTCP ) ) continue; myMatchMap[index]->setPaused( !myMatchMap[index]->paused() ); if( myMatchMap[index]->paused() ) { command2IO( Command( currentMatch->getID(), CMD_Pause ) ); } else { command2IO( Command( currentMatch->getID(), CMD_Resume ) ); } } } break; /* Call Flag */ case MENU_CALL_FLAG: if( whiteInput() == PLAYERLOCAL ) { command2IO( Command( currentMatch->getID(), CMD_White_Called_Flag ) ); currentMatch->recvCMD( Command( currentMatch->getID(), CMD_White_Called_Flag ) ); } if( blackInput() == PLAYERLOCAL ) { command2IO( Command( currentMatch->getID(), CMD_Black_Called_Flag ) ); currentMatch->recvCMD( Command( currentMatch->getID(), CMD_Black_Called_Flag ) ); } break; default: break; } } /////////////////////////////////////// // // core::thinButtonMenu // /////////////////////////////////////// void core::thinButtonMenu( int id, int item ) { switch( item ) { case MENU_SAVE: save( id, FALSE, FALSE ); break; case MENU_SAVEAS: save( id, FALSE, TRUE ); break; case MENU_PRINT: print( id ); break; case MENU_CLOSE: clearMatch( id ); break; default: break; } } /////////////////////////////////////// // // core::resetServer // /////////////////////////////////////// void core::resetServer( void ) { command2IO( Command( Null, CMD_Reset_Server ) ); } /////////////////////////////////////// // // core::goOffline() // /////////////////////////////////////// void core::goOffline(void) { unsigned int index(0); io_base *ioPtr(NULL); while( index < myIOMap.count() ) { if( myIOMap[index]->getType() == io_base::INTERNET ) { ioPtr = myIOMap[index]; if( myIOMap.keyAt(index) != Null ) { clearMatch( myIOMap.keyAt(index) ); } else { myIOMap.remove( Null ); } index = 0; continue; } index++; } if( ioPtr != NULL ) delete ioPtr; }