diff options
author | toma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2009-11-25 17:56:58 +0000 |
---|---|---|
committer | toma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2009-11-25 17:56:58 +0000 |
commit | c90c389a8a8d9d8661e9772ec4144c5cf2039f23 (patch) | |
tree | 6d8391395bce9eaea4ad78958617edb20c6a7573 /atlantik/client | |
download | tdegames-c90c389a8a8d9d8661e9772ec4144c5cf2039f23.tar.gz tdegames-c90c389a8a8d9d8661e9772ec4144c5cf2039f23.zip |
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdegames@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'atlantik/client')
-rw-r--r-- | atlantik/client/Makefile.am | 11 | ||||
-rw-r--r-- | atlantik/client/atlantik.cpp | 853 | ||||
-rw-r--r-- | atlantik/client/atlantik.h | 268 | ||||
-rw-r--r-- | atlantik/client/configdlg.cpp | 334 | ||||
-rw-r--r-- | atlantik/client/configdlg.h | 139 | ||||
-rw-r--r-- | atlantik/client/event.cpp | 42 | ||||
-rw-r--r-- | atlantik/client/event.h | 40 | ||||
-rw-r--r-- | atlantik/client/eventlogwidget.cpp | 123 | ||||
-rw-r--r-- | atlantik/client/eventlogwidget.h | 73 | ||||
-rw-r--r-- | atlantik/client/main.cpp | 78 | ||||
-rw-r--r-- | atlantik/client/main.h | 29 | ||||
-rw-r--r-- | atlantik/client/monopigator.cpp | 164 | ||||
-rw-r--r-- | atlantik/client/monopigator.h | 79 | ||||
-rw-r--r-- | atlantik/client/selectconfiguration_widget.cpp | 189 | ||||
-rw-r--r-- | atlantik/client/selectconfiguration_widget.h | 80 | ||||
-rw-r--r-- | atlantik/client/selectgame_widget.cpp | 192 | ||||
-rw-r--r-- | atlantik/client/selectgame_widget.h | 65 | ||||
-rw-r--r-- | atlantik/client/selectserver_widget.cpp | 178 | ||||
-rw-r--r-- | atlantik/client/selectserver_widget.h | 73 |
19 files changed, 3010 insertions, 0 deletions
diff --git a/atlantik/client/Makefile.am b/atlantik/client/Makefile.am new file mode 100644 index 00000000..25eb24e1 --- /dev/null +++ b/atlantik/client/Makefile.am @@ -0,0 +1,11 @@ +bin_PROGRAMS = atlantik +INCLUDES = -I$(top_srcdir)/libkdegames -I$(srcdir)/../libatlantic -I$(srcdir)/../libatlantikclient -I$(srcdir)/../libatlantikui $(all_includes) +atlantik_LDFLAGS = $(all_libraries) $(KDE_RPATH) +atlantik_LDADD = ../libatlantikui/libatlantikui.la ../libatlantikclient/libatlantikclient.la $(LIB_KDEGAMES) $(LIB_KIO) +atlantik_DEPENDENCIES = $(LIB_KDEGAMES_DEP) + +atlantik_SOURCES = atlantik.cpp configdlg.cpp event.cpp eventlogwidget.cpp \ + main.cpp monopigator.cpp selectconfiguration_widget.cpp \ + selectgame_widget.cpp selectserver_widget.cpp + +METASOURCES = AUTO diff --git a/atlantik/client/atlantik.cpp b/atlantik/client/atlantik.cpp new file mode 100644 index 00000000..56bae64b --- /dev/null +++ b/atlantik/client/atlantik.cpp @@ -0,0 +1,853 @@ +// Copyright (c) 2002-2004 Rob Kaper <cap@capsi.com> +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// version 2 as published by the Free Software Foundation. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; see the file COPYING. If not, write to +// the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +// Boston, MA 02110-1301, USA. + +#include <errno.h> + +#include <qcolor.h> +#include <qdatetime.h> +#include <qlineedit.h> +#include <qscrollview.h> +#include <qpopupmenu.h> + +#include <kaboutapplication.h> +#include <kaction.h> +#include <kapplication.h> +#include <kcmdlineargs.h> +#include <kconfig.h> +#include <klocale.h> +#include <kmessagebox.h> +#include <knotifyclient.h> +#include <knotifydialog.h> +#include <kstatusbar.h> +#include <kstdgameaction.h> +#include <kstdaction.h> +#include <ktoolbar.h> + +#include <kdeversion.h> +#undef KDE_3_2_FEATURES +#if defined(KDE_MAKE_VERSION) +#if KDE_VERSION >= KDE_MAKE_VERSION(3,2,0) + #define KDE_3_2_FEATURES +#endif +#endif + +#include <kdebug.h> + +#include <atlantic_core.h> +#include <auction.h> +#include <estate.h> +#include <player.h> +#include <trade.h> +#include "atlantik.moc" + +#include <atlantik_network.h> + +#include <board.h> +#include <trade_widget.h> + +#include "eventlogwidget.h" +#include "main.h" +#include "selectserver_widget.h" +#include "selectgame_widget.h" +#include "selectconfiguration_widget.h" + +LogTextEdit::LogTextEdit( QWidget *parent, const char *name ) : QTextEdit( parent, name ) +{ +#ifdef KDE_3_2_FEATURES + m_clear = KStdAction::clear( this, SLOT( clear() ), 0 ); +#else + m_clear = new KAction( i18n("Clear"), "clear", NULL, this, SLOT( clear() ), static_cast<KActionCollection *>(0), "clear" ); +#endif + m_selectAll = KStdAction::selectAll( this, SLOT( selectAll() ), 0 ); + m_copy = KStdAction::copy( this, SLOT( copy() ), 0 ); +} + +LogTextEdit::~LogTextEdit() +{ + delete m_clear; + delete m_selectAll; + delete m_copy; +} + +QPopupMenu *LogTextEdit::createPopupMenu( const QPoint & ) +{ + QPopupMenu *rmbMenu = new QPopupMenu( this ); + m_clear->plug( rmbMenu ); + rmbMenu->insertSeparator(); + m_copy->setEnabled( hasSelectedText() ); + m_copy->plug( rmbMenu ); + m_selectAll->plug( rmbMenu ); + + return rmbMenu; +} + +Atlantik::Atlantik () + : KMainWindow (), + m_runningGame( false ) +{ + // Read application configuration + readConfig(); + + // Toolbar: Game +// KStdGameAction::gameNew(this, SLOT(slotNewGame()), actionCollection(), "game_new"); + m_showEventLog = new KAction(i18n("Show Event &Log")/*, "atlantik_showeventlog"*/, CTRL+Key_L, this, SLOT(showEventLog()), actionCollection(), "showeventlog"); + KStdGameAction::quit(kapp, SLOT(closeAllWindows()), actionCollection(), "game_quit"); + + // Toolbar: Settings + KStdAction::preferences(this, SLOT(slotConfigure()), actionCollection()); + KStdAction::configureNotifications(this, SLOT(configureNotifications()), actionCollection()); + + // Initialize pointers to 0L + m_configDialog = 0; + m_board = 0; + m_eventLogWidget = 0; + m_selectServer = 0; + m_selectGame = 0; + m_selectConfiguration = 0; + m_atlantikNetwork = 0; + + // Game and network core + m_atlanticCore = new AtlanticCore(this, "atlanticCore"); + connect(m_atlanticCore, SIGNAL(createGUI(Player *)), this, SLOT(newPlayer(Player *))); + connect(m_atlanticCore, SIGNAL(removeGUI(Player *)), this, SLOT(removeGUI(Player *))); + connect(m_atlanticCore, SIGNAL(createGUI(Trade *)), this, SLOT(newTrade(Trade *))); + connect(m_atlanticCore, SIGNAL(removeGUI(Trade *)), this, SLOT(removeGUI(Trade *))); + + initEventLog(); + initNetworkObject(); + + // Menu,toolbar: Move + m_roll = KStdGameAction::roll(this, SIGNAL(rollDice()), actionCollection()); + m_roll->setEnabled(false); + m_buyEstate = new KAction(i18n("&Buy"), "atlantik_buy_estate", CTRL+Key_B, this, SIGNAL(buyEstate()), actionCollection(), "buy_estate"); + m_buyEstate->setEnabled(false); + m_auctionEstate = new KAction(i18n("&Auction"), "auction", CTRL+Key_A, this, SIGNAL(auctionEstate()), actionCollection(), "auction"); + m_auctionEstate->setEnabled(false); + m_endTurn = KStdGameAction::endTurn(this, SIGNAL(endTurn()), actionCollection()); + m_endTurn->setEnabled(false); + m_jailCard = new KAction(i18n("Use Card to Leave Jail")/*, "atlantik_move_jail_card"*/, 0, this, SIGNAL(jailCard()), actionCollection(), "move_jailcard"); + m_jailCard->setEnabled(false); + m_jailPay = new KAction(i18n("&Pay to Leave Jail"), "jail_pay", CTRL+Key_P, this, SIGNAL(jailPay()), actionCollection(), "move_jailpay"); + m_jailPay->setEnabled(false); + m_jailRoll = new KAction(i18n("Roll to Leave &Jail")/*, "atlantik_move_jail_roll"*/, CTRL+Key_J, this, SIGNAL(jailRoll()), actionCollection(), "move_jailroll"); + m_jailRoll->setEnabled(false); + + // Mix code and XML into GUI + KMainWindow::createGUI(); + applyMainWindowSettings( KGlobal::config(), "AtlantikMainWindow" ); + KMainWindow::statusBar()->insertItem("Atlantik " ATLANTIK_VERSION_STRING, 0); + KMainWindow::statusBar()->insertItem(QString::null, 1); + connect(statusBar(), SIGNAL(released(int)), this, SLOT(statusBarClick(int))); + + // Main widget, containing all others + m_mainWidget = new QWidget(this, "main"); + m_mainWidget->show(); + m_mainLayout = new QGridLayout(m_mainWidget, 3, 2); + setCentralWidget(m_mainWidget); + + // Vertical view area for portfolios. + m_portfolioScroll = new QScrollView(m_mainWidget, "pfScroll"); + m_mainLayout->addWidget( m_portfolioScroll, 0, 0 ); + m_portfolioScroll->setHScrollBarMode( QScrollView::AlwaysOff ); + m_portfolioScroll->setResizePolicy( QScrollView::AutoOneFit ); + m_portfolioScroll->setFixedHeight( 200 ); + m_portfolioScroll->hide(); + + m_portfolioWidget = new QWidget( m_portfolioScroll->viewport(), "pfWidget" ); + m_portfolioScroll->addChild( m_portfolioWidget ); + m_portfolioWidget->show(); + + m_portfolioLayout = new QVBoxLayout(m_portfolioWidget); + m_portfolioViews.setAutoDelete(true); + + // Nice label +// m_portfolioLabel = new QLabel(i18n("Players"), m_portfolioWidget, "pfLabel"); +// m_portfolioLayout->addWidget(m_portfolioLabel); +// m_portfolioLabel->show(); + + // Text view for chat and status messages from server. + m_serverMsgs = new LogTextEdit(m_mainWidget, "serverMsgs"); + m_serverMsgs->setTextFormat(QTextEdit::PlainText); + m_serverMsgs->setReadOnly(true); + m_serverMsgs->setHScrollBarMode(QScrollView::AlwaysOff); + m_serverMsgs->setMinimumWidth(200); + m_mainLayout->addWidget(m_serverMsgs, 1, 0); + + // LineEdit to enter commands and chat messages. + m_input = new QLineEdit(m_mainWidget, "input"); + m_mainLayout->addWidget(m_input, 2, 0); + + m_serverMsgs->setFocusProxy(m_input); + + connect(m_input, SIGNAL(returnPressed()), this, SLOT(slotSendMsg())); + + // Set stretching where we want it. + m_mainLayout->setRowStretch(1, 1); // make m_board+m_serverMsgs stretch vertically, not the rest + m_mainLayout->setColStretch(1, 1); // make m_board stretch horizontally, not the rest + + // Check command-line args to see if we need to connect or show Monopigator window + KCmdLineArgs *args = KCmdLineArgs::parsedArgs(); + + QCString host = args->getOption("host"); + QCString port = args->getOption("port"); + if (!host.isNull() && !port.isNull()) + m_atlantikNetwork->serverConnect(host, port.toInt()); + else + showSelectServer(); +} + +void Atlantik::readConfig() +{ + // Read configuration settings + KConfig *config = kapp->config(); + + // General configuration + config->setGroup("General"); + m_config.chatTimestamps = config->readBoolEntry("ChatTimeStamps", false); + + // Personalization configuration + config->setGroup("Personalization"); + m_config.playerName = config->readEntry("PlayerName", "Atlantik"); + m_config.playerImage = config->readEntry("PlayerImage", "cube.png"); + + // Board configuration + config->setGroup("Board"); + m_config.indicateUnowned = config->readBoolEntry("IndicateUnowned", true); + m_config.highliteUnowned = config->readBoolEntry("HighliteUnowned", false); + m_config.darkenMortgaged = config->readBoolEntry("DarkenMortgaged", true); + m_config.animateTokens = config->readBoolEntry("AnimateToken", false); + m_config.quartzEffects = config->readBoolEntry("QuartzEffects", true); + + // Meta server configuation + config->setGroup("Monopigator"); + m_config.connectOnStart = config->readBoolEntry("ConnectOnStart", false); + m_config.hideDevelopmentServers = config->readBoolEntry("HideDevelopmentServers", true); + + // Portfolio colors + config->setGroup("WM"); + QColor activeDefault(204, 204, 204), inactiveDefault(153, 153, 153); + m_config.activeColor = config->readColorEntry("activeBackground", &activeDefault); + m_config.inactiveColor = config->readColorEntry("inactiveBlend", &inactiveDefault); +} + +void Atlantik::newPlayer(Player *player) +{ + initBoard(); + m_board->addToken(player); + addPortfolioView(player); + + // Player::changed() is not connected until later this method, so + // we'd better force an update. + playerChanged(player); + + connect(player, SIGNAL(changed(Player *)), this, SLOT(playerChanged(Player *))); + connect(player, SIGNAL(gainedTurn()), this, SLOT(gainedTurn())); + connect(player, SIGNAL(changed(Player *)), m_board, SLOT(playerChanged(Player *))); + + KNotifyClient::event(winId(), "newplayer"); +} + +void Atlantik::newEstate(Estate *estate) +{ + initBoard(); + m_board->addEstateView(estate, m_config.indicateUnowned, m_config.highliteUnowned, m_config.darkenMortgaged, m_config.quartzEffects); +} + +void Atlantik::newTrade(Trade *trade) +{ + TradeDisplay *tradeDisplay = new TradeDisplay(trade, m_atlanticCore, 0, "tradeDisplay"); + m_tradeGUIMap[trade] = tradeDisplay; + tradeDisplay->show(); +} + +void Atlantik::newAuction(Auction *auction) +{ + initBoard(); + m_board->addAuctionWidget(auction); +} + +void Atlantik::removeGUI(Player *player) +{ + // Find and remove portfolioview + PortfolioView *portfolioView = findPortfolioView(player); + if (portfolioView) + m_portfolioViews.remove(portfolioView); + + if (m_board) + m_board->removeToken(player); +} + +void Atlantik::removeGUI(Trade *trade) +{ + if (TradeDisplay *tradeDisplay = m_tradeGUIMap[trade]) + delete tradeDisplay; +} + +void Atlantik::showSelectServer() +{ + if (m_selectServer) + return; + + m_selectServer = new SelectServer(m_config.connectOnStart, m_config.hideDevelopmentServers, m_mainWidget, "selectServer"); + m_mainLayout->addMultiCellWidget(m_selectServer, 0, 2, 1, 1); + m_selectServer->show(); + + if (m_selectGame) + { + delete m_selectGame; + m_selectGame = 0; + } + + m_atlanticCore->reset(true); + initNetworkObject(); + + connect(m_selectServer, SIGNAL(serverConnect(const QString, int)), m_atlantikNetwork, SLOT(serverConnect(const QString, int))); + connect(m_selectServer, SIGNAL(msgStatus(const QString &)), this, SLOT(slotMsgStatus(const QString &))); + + m_selectServer->slotRefresh( m_config.connectOnStart ); +} + +void Atlantik::showSelectGame() +{ + if (m_selectGame) + return; + + m_selectGame = new SelectGame(m_atlanticCore, m_mainWidget, "selectGame"); + m_atlanticCore->emitGames(); + + m_mainLayout->addMultiCellWidget(m_selectGame, 0, 2, 1, 1); + m_selectGame->show(); + + // Reset core and GUI + if (m_board) + { + m_board->hide(); + m_board->reset(); +// delete m_board; +// m_board = 0; + + // m_portfolioViews.clear(); + m_atlanticCore->reset(); + } + + if (m_selectServer) + { + delete m_selectServer; + m_selectServer = 0; + } + if (m_selectConfiguration) + { + delete m_selectConfiguration; + m_selectConfiguration = 0; + } + + connect(m_selectGame, SIGNAL(joinGame(int)), m_atlantikNetwork, SLOT(joinGame(int))); + connect(m_selectGame, SIGNAL(newGame(const QString &)), m_atlantikNetwork, SLOT(newGame(const QString &))); + connect(m_selectGame, SIGNAL(leaveServer()), this, SLOT(showSelectServer())); + connect(m_selectGame, SIGNAL(msgStatus(const QString &)), this, SLOT(slotMsgStatus(const QString &))); +} + +void Atlantik::showSelectConfiguration() +{ + if (m_selectConfiguration) + return; + + if (m_selectGame) + { + delete m_selectGame; + m_selectGame = 0; + } + + m_selectConfiguration = new SelectConfiguration(m_atlanticCore, m_mainWidget, "selectConfiguration"); + m_mainLayout->addMultiCellWidget(m_selectConfiguration, 0, 2, 1, 1); + m_selectConfiguration->show(); + + connect(m_atlanticCore, SIGNAL(createGUI(ConfigOption *)), m_selectConfiguration, SLOT(addConfigOption(ConfigOption *))); + connect(m_atlantikNetwork, SIGNAL(gameOption(QString, QString, QString, QString, QString)), m_selectConfiguration, SLOT(gameOption(QString, QString, QString, QString, QString))); + connect(m_atlantikNetwork, SIGNAL(gameInit()), m_selectConfiguration, SLOT(initGame())); + connect(m_selectConfiguration, SIGNAL(startGame()), m_atlantikNetwork, SLOT(startGame())); + connect(m_selectConfiguration, SIGNAL(leaveGame()), m_atlantikNetwork, SLOT(leaveGame())); + connect(m_selectConfiguration, SIGNAL(changeOption(int, const QString &)), m_atlantikNetwork, SLOT(changeOption(int, const QString &))); + connect(m_selectConfiguration, SIGNAL(buttonCommand(QString)), m_atlantikNetwork, SLOT(writeData(QString))); + connect(m_selectConfiguration, SIGNAL(iconSelected(const QString &)), m_atlantikNetwork, SLOT(setImage(const QString &))); + connect(m_selectConfiguration, SIGNAL(statusMessage(const QString &)), this, SLOT(slotMsgStatus(const QString &))); +} + +void Atlantik::initBoard() +{ + if (m_board) + return; + + m_board = new AtlantikBoard(m_atlanticCore, 40, AtlantikBoard::Play, m_mainWidget, "board"); + m_board->setViewProperties(m_config.indicateUnowned, m_config.highliteUnowned, m_config.darkenMortgaged, m_config.quartzEffects, m_config.animateTokens); + + connect(m_atlantikNetwork, SIGNAL(displayDetails(QString, bool, bool, Estate *)), m_board, SLOT(insertDetails(QString, bool, bool, Estate *))); + connect(m_atlantikNetwork, SIGNAL(addCommandButton(QString, QString, bool)), m_board, SLOT(displayButton(QString, QString, bool))); + connect(m_atlantikNetwork, SIGNAL(addCloseButton()), m_board, SLOT(addCloseButton())); + connect(m_board, SIGNAL(tokenConfirmation(Estate *)), m_atlantikNetwork, SLOT(tokenConfirmation(Estate *))); + connect(m_board, SIGNAL(buttonCommand(QString)), m_atlantikNetwork, SLOT(writeData(QString))); +} + +void Atlantik::showBoard() +{ + if (m_selectGame) + { + delete m_selectGame; + m_selectGame = 0; + } + + if (m_selectConfiguration) + { + delete m_selectConfiguration; + m_selectConfiguration = 0; + } + + if (!m_board) + initBoard(); + + m_runningGame = true; + + m_mainLayout->addMultiCellWidget(m_board, 0, 2, 1, 1); + m_board->displayDefault(); + m_board->show(); + + PortfolioView *portfolioView = 0; + for (QPtrListIterator<PortfolioView> it(m_portfolioViews); *it; ++it) + if ((portfolioView = dynamic_cast<PortfolioView*>(*it))) + portfolioView->buildPortfolio(); +} + +void Atlantik::freezeBoard() +{ + if (!m_board) + showBoard(); + + m_runningGame = false; + // TODO: m_board->freeze(); +} + +void Atlantik::slotNetworkConnected() +{ +} + +void Atlantik::slotNetworkError(int errnum) +{ + QString errMsg(i18n("Error connecting: ")); + + switch (m_atlantikNetwork->status()) + { + case IO_ConnectError: + if (errnum == ECONNREFUSED) + errMsg.append(i18n("connection refused by host.")); + else + errMsg.append(i18n("could not connect to host.")); + break; + + case IO_LookupError: + errMsg.append(i18n("host not found.")); + break; + + default: + errMsg.append(i18n("unknown error.")); + } + + serverMsgsAppend(errMsg); + + // Re-init network object + initNetworkObject(); +} + +void Atlantik::networkClosed(int status) +{ + switch( status ) + { + case KBufferedIO::involuntary: + slotMsgStatus( i18n("Connection with server %1:%2 lost.").arg(m_atlantikNetwork->host()).arg(m_atlantikNetwork->port()), QString("connect_no") ); + showSelectServer(); + break; + default: + if ( !m_atlantikNetwork->host().isEmpty() ) + slotMsgStatus( i18n("Disconnected from %1:%2.").arg(m_atlantikNetwork->host()).arg(m_atlantikNetwork->port()), QString("connect_no") ); + break; + } +} + +void Atlantik::slotConfigure() +{ + if (m_configDialog == 0) + m_configDialog = new ConfigDialog(this); + m_configDialog->show(); + + connect(m_configDialog, SIGNAL(okClicked()), this, SLOT(slotUpdateConfig())); +} + +void Atlantik::showEventLog() +{ + if (!m_eventLogWidget) + m_eventLogWidget = new EventLogWidget(m_eventLog, 0); + m_eventLogWidget->show(); +} + +void Atlantik::configureNotifications() +{ + KNotifyDialog::configure(this); +} + +void Atlantik::slotUpdateConfig() +{ + KConfig *config=kapp->config(); + bool optBool, configChanged = false; + QString optStr; + + optBool = m_configDialog->chatTimestamps(); + if (m_config.chatTimestamps != optBool) + { + m_config.chatTimestamps = optBool; + configChanged = true; + } + + optStr = m_configDialog->playerName(); + if (m_config.playerName != optStr) + { + m_config.playerName = optStr; + m_atlantikNetwork->setName(optStr); + } + + optStr = m_configDialog->playerImage(); + if (m_config.playerImage != optStr) + { + m_config.playerImage = optStr; + m_atlantikNetwork->setImage(optStr); + } + + optBool = m_configDialog->indicateUnowned(); + if (m_config.indicateUnowned != optBool) + { + m_config.indicateUnowned = optBool; + configChanged = true; + } + + optBool = m_configDialog->highliteUnowned(); + if (m_config.highliteUnowned != optBool) + { + m_config.highliteUnowned = optBool; + configChanged = true; + } + + optBool = m_configDialog->darkenMortgaged(); + if (m_config.darkenMortgaged != optBool) + { + m_config.darkenMortgaged = optBool; + configChanged = true; + } + + optBool = m_configDialog->animateToken(); + if (m_config.animateTokens != optBool) + { + m_config.animateTokens = optBool; + configChanged = true; + } + + optBool = m_configDialog->quartzEffects(); + if (m_config.quartzEffects != optBool) + { + m_config.quartzEffects = optBool; + configChanged = true; + } + + optBool = m_configDialog->connectOnStart(); + if (m_config.connectOnStart != optBool) + { + m_config.connectOnStart = optBool; + configChanged = true; + } + + optBool = m_configDialog->hideDevelopmentServers(); + if (m_config.hideDevelopmentServers != optBool) + { + m_config.hideDevelopmentServers = optBool; + if (m_selectServer) + m_selectServer->setHideDevelopmentServers(optBool); + + configChanged = true; + } + + config->setGroup("General"); + config->writeEntry("ChatTimeStamps", m_config.chatTimestamps); + + config->setGroup("Personalization"); + config->writeEntry("PlayerName", m_config.playerName); + config->writeEntry("PlayerImage", m_config.playerImage); + + config->setGroup("Board"); + config->writeEntry("IndicateUnowned", m_config.indicateUnowned); + config->writeEntry("HighliteUnowned", m_config.highliteUnowned); + config->writeEntry("DarkenMortgaged", m_config.darkenMortgaged); + config->writeEntry("AnimateToken", m_config.animateTokens); + config->writeEntry("QuartzEffects", m_config.quartzEffects); + + config->setGroup("Monopigator"); + config->writeEntry("ConnectOnStart", m_config.connectOnStart); + config->writeEntry("HideDevelopmentServers", m_config.hideDevelopmentServers); + + config->sync(); + + if (configChanged && m_board) + m_board->setViewProperties(m_config.indicateUnowned, m_config.highliteUnowned, m_config.darkenMortgaged, m_config.quartzEffects, m_config.animateTokens); +} + +void Atlantik::slotSendMsg() +{ + m_atlantikNetwork->cmdChat(m_input->text()); + m_input->setText(QString::null); +} + +void Atlantik::slotMsgInfo(QString msg) +{ + serverMsgsAppend(msg); +} + +void Atlantik::slotMsgError(QString msg) +{ + serverMsgsAppend("Error: " + msg); +} + +void Atlantik::slotMsgStatus(const QString &message, const QString &icon) +{ + KMainWindow::statusBar()->changeItem(message, 1); + m_eventLog->addEvent(message, icon); +} + +void Atlantik::slotMsgChat(QString player, QString msg) +{ + if (m_config.chatTimestamps) + { + QTime time = QTime::currentTime(); + serverMsgsAppend(QString("[%1] %2: %3").arg(time.toString("hh:mm")).arg(player).arg(msg)); + } + else + serverMsgsAppend(player + ": " + msg); + KNotifyClient::event(winId(), "chat"); +} + +void Atlantik::serverMsgsAppend(QString msg) +{ + // Use append, not setText(old+new) because that one doesn't wrap + m_serverMsgs->append(msg); + m_serverMsgs->ensureVisible(0, m_serverMsgs->contentsHeight()); +} + +void Atlantik::playerChanged(Player *player) +{ + PortfolioView *portfolioView = findPortfolioView(player); + if (!portfolioView) + portfolioView = addPortfolioView(player); + + Player *playerSelf = m_atlanticCore->playerSelf(); + if (player == playerSelf) + { + // We changed ourselves.. + PortfolioView *portfolioView = 0; + for (QPtrListIterator<PortfolioView> it(m_portfolioViews); *it; ++it) + if ((portfolioView = dynamic_cast<PortfolioView*>(*it))) + { + // Clear all portfolios if we're not in game + if ( !player->game() ) + portfolioView->clearPortfolio(); + + // Show players in our game, hide the rest + Player *pTmp = portfolioView->player(); + if (pTmp->game() == playerSelf->game()) + portfolioView->show(); + else + portfolioView->hide(); + } + if (!player->game()) + showSelectGame(); + else + { + if ( !m_board || m_board->isHidden() ) + showSelectConfiguration(); + } + + m_roll->setEnabled(player->canRoll()); + m_buyEstate->setEnabled(player->canBuy()); + m_auctionEstate->setEnabled(player->canAuction()); + + // TODO: Should be more finetuned, but monopd doesn't send can_endturn can_payjail can_jailroll yet + m_endTurn->setEnabled(player->hasTurn() && !(player->canRoll() || player->canBuy() || player->inJail())); + m_jailCard->setEnabled(player->canUseCard()); + m_jailPay->setEnabled(player->hasTurn() && player->inJail()); + m_jailRoll->setEnabled(player->hasTurn() && player->inJail()); + } + else + { + // Another player changed, check if we need to show or hide + // his/her portfolioView. + if (playerSelf) + { + if (player->game() == playerSelf->game()) + portfolioView->show(); + else + portfolioView->hide(); + } + else if ( !player->game() ) + portfolioView->hide(); + } +} + +void Atlantik::gainedTurn() +{ + KNotifyClient::event(winId(), "gainedturn", i18n("It is your turn now.") ); +} + +void Atlantik::initEventLog() +{ + m_eventLog = new EventLog(); +} + +void Atlantik::initNetworkObject() +{ + if (m_atlantikNetwork) + { + m_atlantikNetwork->reset(); + return; + } + + m_atlantikNetwork = new AtlantikNetwork(m_atlanticCore); + connect(m_atlantikNetwork, SIGNAL(msgInfo(QString)), this, SLOT(slotMsgInfo(QString))); + connect(m_atlantikNetwork, SIGNAL(msgError(QString)), this, SLOT(slotMsgError(QString))); + connect(m_atlantikNetwork, SIGNAL(msgStatus(const QString &, const QString &)), this, SLOT(slotMsgStatus(const QString &, const QString &))); + connect(m_atlantikNetwork, SIGNAL(msgChat(QString, QString)), this, SLOT(slotMsgChat(QString, QString))); + + connect(m_atlantikNetwork, SIGNAL(connectionSuccess()), this, SLOT(slotNetworkConnected())); + connect(m_atlantikNetwork, SIGNAL(connectionFailed(int)), this, SLOT(slotNetworkError(int))); + connect(m_atlantikNetwork, SIGNAL(closed(int)), this, SLOT(networkClosed(int))); + + connect(m_atlantikNetwork, SIGNAL(receivedHandshake()), this, SLOT(sendHandshake())); + + connect(m_atlantikNetwork, SIGNAL(gameConfig()), this, SLOT(showSelectConfiguration())); + connect(m_atlantikNetwork, SIGNAL(gameInit()), this, SLOT(initBoard())); + connect(m_atlantikNetwork, SIGNAL(gameRun()), this, SLOT(showBoard())); + connect(m_atlantikNetwork, SIGNAL(gameEnd()), this, SLOT(freezeBoard())); + + connect(m_atlantikNetwork, SIGNAL(newEstate(Estate *)), this, SLOT(newEstate(Estate *))); + connect(m_atlantikNetwork, SIGNAL(newAuction(Auction *)), this, SLOT(newAuction(Auction *))); + + connect(m_atlantikNetwork, SIGNAL(clientCookie(QString)), this, SLOT(clientCookie(QString))); + connect(m_atlantikNetwork, SIGNAL(networkEvent(const QString &, const QString &)), m_eventLog, SLOT(addEvent(const QString &, const QString &))); + + connect(this, SIGNAL(rollDice()), m_atlantikNetwork, SLOT(rollDice())); + connect(this, SIGNAL(buyEstate()), m_atlantikNetwork, SLOT(buyEstate())); + connect(this, SIGNAL(auctionEstate()), m_atlantikNetwork, SLOT(auctionEstate())); + connect(this, SIGNAL(endTurn()), m_atlantikNetwork, SLOT(endTurn())); + connect(this, SIGNAL(jailCard()), m_atlantikNetwork, SLOT(jailCard())); + connect(this, SIGNAL(jailPay()), m_atlantikNetwork, SLOT(jailPay())); + connect(this, SIGNAL(jailRoll()), m_atlantikNetwork, SLOT(jailRoll())); +} + +void Atlantik::clientCookie(QString cookie) +{ + KConfig *config = kapp->config(); + + if (cookie.isNull()) + { + if (config->hasGroup("Reconnection")) + config->deleteGroup("Reconnection", true); + } + else if (m_atlantikNetwork) + { + config->setGroup("Reconnection"); + config->writeEntry("Host", m_atlantikNetwork->host()); + config->writeEntry("Port", m_atlantikNetwork->port()); + config->writeEntry("Cookie", cookie); + } + else + return; + + config->sync(); +} + +void Atlantik::sendHandshake() +{ + m_atlantikNetwork->setName(m_config.playerName); + m_atlantikNetwork->setImage(m_config.playerImage); + + // Check command-line args to see if we need to auto-join + KCmdLineArgs *args = KCmdLineArgs::parsedArgs(); + + QCString game = args->getOption("game"); + if (!game.isNull()) + m_atlantikNetwork->joinGame(game.toInt()); +} + +void Atlantik::statusBarClick(int item) +{ + if ( item == 0 ) + { + KAboutApplication dialog(kapp->aboutData(), this); + dialog.exec(); + } + else if ( item == 1) + showEventLog(); +} + +PortfolioView *Atlantik::addPortfolioView(Player *player) +{ + PortfolioView *portfolioView = new PortfolioView(m_atlanticCore, player, m_config.activeColor, m_config.inactiveColor, m_portfolioWidget); + m_portfolioViews.append(portfolioView); + if ( m_portfolioViews.count() > 0 && m_portfolioScroll->isHidden() ) + m_portfolioScroll->show(); + + connect(player, SIGNAL(changed(Player *)), portfolioView, SLOT(playerChanged())); + connect(portfolioView, SIGNAL(newTrade(Player *)), m_atlantikNetwork, SLOT(newTrade(Player *))); + connect(portfolioView, SIGNAL(kickPlayer(Player *)), m_atlantikNetwork, SLOT(kickPlayer(Player *))); + connect(portfolioView, SIGNAL(estateClicked(Estate *)), m_board, SLOT(prependEstateDetails(Estate *))); + + m_portfolioLayout->addWidget(portfolioView); + portfolioView->show(); + + return portfolioView; +} + +PortfolioView *Atlantik::findPortfolioView(Player *player) +{ + PortfolioView *portfolioView = 0; + for (QPtrListIterator<PortfolioView> it(m_portfolioViews); (portfolioView = *it) ; ++it) + if (player == portfolioView->player()) + return portfolioView; + + return 0; +} + +void Atlantik::closeEvent(QCloseEvent *e) +{ + Game *gameSelf = m_atlanticCore->gameSelf(); + Player *playerSelf = m_atlanticCore->playerSelf(); + + int result = KMessageBox::Continue; + if ( gameSelf && !playerSelf->isBankrupt() && m_runningGame ) + result = KMessageBox::warningContinueCancel( this, i18n("You are currently part of an active game. Are you sure you want to close Atlantik? If you do, you forfeit the game."), i18n("Close & Forfeit?"), i18n("Close && Forfeit") ); + + if ( result == KMessageBox::Continue ) + { + if ( m_atlantikNetwork ) + m_atlantikNetwork->leaveGame(); + + saveMainWindowSettings(kapp->config(), "AtlantikMainWindow"); + KMainWindow::closeEvent(e); + } +} diff --git a/atlantik/client/atlantik.h b/atlantik/client/atlantik.h new file mode 100644 index 00000000..94f2ca7c --- /dev/null +++ b/atlantik/client/atlantik.h @@ -0,0 +1,268 @@ +// Copyright (c) 2002-2003 Rob Kaper <cap@capsi.com> +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// version 2 as published by the Free Software Foundation. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; see the file COPYING. If not, write to +// the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +// Boston, MA 02110-1301, USA. + +#ifndef ATLANTIK_ATLANTIK_H +#define ATLANTIK_ATLANTIK_H + +#include <qwidget.h> +#include <qlayout.h> +#include <qtextedit.h> +#include <qlabel.h> +#include <qptrlist.h> + +#include <kmainwindow.h> + +#include "configdlg.h" +#include "portfolioview.h" +#include "board.h" + +class QScrollView; + +class AtlanticCore; +class AtlantikNetwork; + +struct AtlantikConfig +{ + // General options; + bool chatTimestamps; + + // Personalization options + QString playerName, playerImage; + + // Board options + bool indicateUnowned; + bool highliteUnowned; + bool darkenMortgaged; + bool quartzEffects; + bool animateTokens; + + // Meta server options + bool connectOnStart; + bool hideDevelopmentServers; + + // Portfolio colors + QColor activeColor, inactiveColor; +}; + +class EventLog; +class EventLogWidget; +class SelectServer; +class SelectGame; +class SelectConfiguration; +class TradeDisplay; + +class Player; +class Estate; +class Trade; + +class LogTextEdit : public QTextEdit +{ +Q_OBJECT + +public: + LogTextEdit( QWidget *parent = 0, const char *name = 0 ); + virtual ~LogTextEdit(); + + QPopupMenu *createPopupMenu( const QPoint & pos ); + +private: + KAction *m_clear, *m_selectAll, *m_copy; +}; + +/** + * Main Atlantik window. + * Manages gameboard, portfolios and pretty much everything else. + * + * @author Rob Kaper <cap@capsi.com> + */ +class Atlantik : public KMainWindow +{ +Q_OBJECT + +public: + /** + * Create an Atlantik window. + * + */ + Atlantik(); + + /** + * Read the configuration settings using KConfig. + * + */ + void readConfig(); + + /** + * Appends a message the text view. + * + * @param msg Message to be appended. + */ + void serverMsgsAppend(QString msg); + + AtlantikConfig config() { return m_config; } + +private slots: + void showSelectServer(); + void showSelectGame(); + void showSelectConfiguration(); + void initBoard(); + void showBoard(); + void freezeBoard(); + void clientCookie(QString cookie); + void sendHandshake(); + void statusBarClick(int); + +public slots: + + /** + * A network connection has been established, so we can show the game + * list instead of the server list. + * + */ + void slotNetworkConnected(); + + /** + * An error occurred while setting up the network connection. Inform the + * user. + * + * @param errno See http://doc.trolltech.com/3.0/qsocket.html#Error-enum + */ + void slotNetworkError(int errnum); + + void networkClosed(int status); + + /** + * Creates a new modeless configure dialog or raises it when it already exists. + * + */ + void slotConfigure(); + + /** + * Opens the event log widget. + * + */ + void showEventLog(); + + /** + * Opens the KNotify dialog for configuration events. + * + */ + void configureNotifications(); + + /** + * Reads values from configuration dialog and stores them into + * global configuration struct. If values have changed, appropriate + * methods within the application are called. Configuration is saved + * to file in any case. + * + */ + void slotUpdateConfig(); + + /** + * Writes the contents of the text input field to the network + * interface and clears the text input field. + * + */ + void slotSendMsg(); + + /** + * Informs serverMsgs() to append an incoming message from the + * server to the text view as informational message. + * + * @param msg The message to be appended. + */ + void slotMsgInfo(QString msg); + + void slotMsgStatus(const QString &message, const QString &icon = QString::null); + + /** + * Informs serverMsgs() to append an incoming message from the + * server to the text view as error message. + * + * @param msg The error message to be appended. + */ + void slotMsgError(QString msg); + + /** + * Informs serverMsgs() to append an incoming message from the + * server to the text view as chat message. + * + * @param player The name of the player chatting. + * @param msg The chat message to be appended. + */ + void slotMsgChat(QString player, QString msg); + + void newPlayer(Player *player); + void newEstate(Estate *estate); + void newTrade(Trade *trade); + void newAuction(Auction *auction); + + void removeGUI(Player *player); + void removeGUI(Trade *trade); + + void playerChanged(Player *player); + void gainedTurn(); + +signals: + void rollDice(); + void buyEstate(); + void auctionEstate(); + void endTurn(); + void jailCard(); + void jailPay(); + void jailRoll(); + +protected: + void closeEvent(QCloseEvent *); + +private: + void initEventLog(); + void initNetworkObject(); + PortfolioView *addPortfolioView(Player *player); + PortfolioView *findPortfolioView(Player *player); + + QScrollView *m_portfolioScroll; + QWidget *m_mainWidget, *m_portfolioWidget; + QGridLayout *m_mainLayout; + QVBoxLayout *m_portfolioLayout; + + QLabel *m_portfolioLabel; + QLineEdit *m_input; + QTextEdit *m_serverMsgs; + + KAction *m_roll, *m_buyEstate, *m_auctionEstate, *m_endTurn, + *m_jailCard, *m_jailPay, *m_jailRoll, *m_configure, + *m_showEventLog; + + AtlanticCore *m_atlanticCore; + AtlantikNetwork *m_atlantikNetwork; + AtlantikConfig m_config; + + ConfigDialog *m_configDialog; + AtlantikBoard *m_board; + SelectServer *m_selectServer; + SelectGame *m_selectGame; + SelectConfiguration *m_selectConfiguration; + EventLog *m_eventLog; + EventLogWidget *m_eventLogWidget; + + QPtrList<PortfolioView> m_portfolioViews; + QMap<Trade *, TradeDisplay *> m_tradeGUIMap; + + bool m_runningGame; +}; + +#endif diff --git a/atlantik/client/configdlg.cpp b/atlantik/client/configdlg.cpp new file mode 100644 index 00000000..a8e152b5 --- /dev/null +++ b/atlantik/client/configdlg.cpp @@ -0,0 +1,334 @@ +// Copyright (c) 2002-2003 Rob Kaper <cap@capsi.com> +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// version 2 as published by the Free Software Foundation. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; see the file COPYING. If not, write to +// the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +// Boston, MA 02110-1301, USA. + +#include <qlayout.h> +#include <qgroupbox.h> +#include <qwhatsthis.h> +#include <qlabel.h> + +#include <kdeversion.h> +#undef KDE_3_1_FEATURES +#undef KDE_3_3_FEATURES +#if defined(KDE_MAKE_VERSION) +#if KDE_VERSION >= KDE_MAKE_VERSION(3,1,0) +#define KDE_3_1_FEATURES +#endif +#if KDE_VERSION >= KDE_MAKE_VERSION(3,2,90) +#define KDE_3_3_FEATURES +#endif +#endif + +#include <kicondialog.h> +#include <kiconloader.h> +#include <klocale.h> +#include <kpushbutton.h> +#include <kstandarddirs.h> + +#include "atlantik.h" +#include "configdlg.moc" + +ConfigDialog::ConfigDialog(Atlantik* parent, const char *name) : KDialogBase(IconList, i18n("Configure Atlantik"), Ok|Cancel, Ok, parent, "config_atlantik", false, name) +{ + m_parent = parent; + p_general = addPage(i18n("General"), i18n("General"), BarIcon("configure", KIcon::SizeMedium)); + p_p13n = addPage(i18n("Personalization"), i18n("Personalization"), BarIcon("personal", KIcon::SizeMedium)); + p_board = addPage(i18n("Board"), i18n("Board"), BarIcon("monop_board", KIcon::SizeMedium)); + p_monopigator = addPage(i18n("Meta Server"), i18n("Meta Server"), BarIcon("network", KIcon::SizeMedium)); + + configGeneral = new ConfigGeneral(this, p_general, "configGeneral"); + configPlayer = new ConfigPlayer(this, p_p13n, "configPlayer"); + configBoard = new ConfigBoard(this, p_board, "configBoard"); + configMonopigator = new ConfigMonopigator(this, p_monopigator, "configMonopigator"); + + setMinimumSize(sizeHint()); +} + +bool ConfigDialog::chatTimestamps() +{ + return configGeneral->chatTimestamps(); +} + +bool ConfigDialog::indicateUnowned() +{ + return configBoard->indicateUnowned(); +} + +bool ConfigDialog::highliteUnowned() +{ + return configBoard->highliteUnowned(); +} + +bool ConfigDialog::darkenMortgaged() +{ + return configBoard->darkenMortgaged(); +} + +bool ConfigDialog::animateToken() +{ + return configBoard->animateToken(); +} + +bool ConfigDialog::quartzEffects() +{ + return configBoard->quartzEffects(); +} + +QString ConfigDialog::playerName() +{ + return configPlayer->playerName(); +} + +QString ConfigDialog::playerImage() +{ + return configPlayer->playerImage(); +} + +bool ConfigDialog::connectOnStart() +{ + return configMonopigator->connectOnStart(); +} + +bool ConfigDialog::hideDevelopmentServers() +{ + return configMonopigator->hideDevelopmentServers(); +} + +AtlantikConfig ConfigDialog::config() +{ + return m_parent->config(); +} + +ConfigPlayer::ConfigPlayer(ConfigDialog* configDialog, QWidget *parent, const char *name) : QWidget(parent, name) +{ + m_configDialog = configDialog; + QVBoxLayout *layout = new QVBoxLayout(parent, KDialog::marginHint(), KDialog::spacingHint()); + + QLabel *label = new QLabel(i18n("Player name:"), parent); + layout->addWidget(label); + + m_playerName = new QLineEdit(parent); + layout->addWidget(m_playerName); + + QLabel *label2 = new QLabel(i18n("Player image:"), parent); + layout->addWidget(label2); + + m_playerIcon = new KPushButton(parent, "playerIcon"); + layout->addWidget(m_playerIcon); + + connect( m_playerIcon, SIGNAL(clicked()), this, SLOT(chooseImage()) ); + + layout->addStretch(1); + + reset(); +} + +QString ConfigPlayer::playerName() +{ + return m_playerName->text(); +} + +QString ConfigPlayer::playerImage() +{ + return m_playerImage; +} +void ConfigPlayer::chooseImage() +{ + KIconDialog iconDialog( this, "iconDialog" ); +#ifdef KDE_3_1_FEATURES + iconDialog.setCustomLocation( locate("appdata", "themes/default/tokens/") ); +#endif + +#ifdef KDE_3_3_FEATURES + iconDialog.setup( KIcon::Desktop, KIcon::Application, false, 0, true, true, true ); // begin with user icons, lock editing +#else + iconDialog.setup( KIcon::Desktop, KIcon::Application, false, 0, true ); // begin with user icons +#endif + + QString image = iconDialog.openDialog(); + + if ( image.isEmpty() ) + return; + + QStringList splitPath = QStringList::split( '/', image ); + m_playerImage = splitPath[ splitPath.count()-1 ]; + + setImage(); +} + +void ConfigPlayer::setImage() +{ + QString filename = locate("data", "atlantik/themes/default/tokens/" + m_playerImage); + if (KStandardDirs::exists(filename)) + m_playerIcon->setPixmap( QPixmap(filename) ); +} + +void ConfigPlayer::reset() +{ + m_playerName->setText(m_configDialog->config().playerName); + m_playerImage = m_configDialog->config().playerImage; + setImage(); +} + +ConfigMonopigator::ConfigMonopigator(ConfigDialog *configDialog, QWidget *parent, const char *name) : QWidget(parent, name) +{ + m_configDialog = configDialog; + QVBoxLayout *layout = new QVBoxLayout(parent, KDialog::marginHint(), KDialog::spacingHint()); + + m_connectOnStart = new QCheckBox(i18n("Request list of Internet servers on start-up"), parent); + layout->addWidget(m_connectOnStart); + + QString message=i18n( + "If checked, Atlantik connects to a meta server on start-up to\n" + "request a list of Internet servers.\n"); + QWhatsThis::add(m_connectOnStart, message); + + m_hideDevelopmentServers = new QCheckBox(i18n("Hide development servers"), parent); + layout->addWidget(m_hideDevelopmentServers); + + message=i18n( + "Some of the Internet servers might be running development\n" + "versions of the server software. If checked, Atlantik will not\n" + "display these servers.\n"); + QWhatsThis::add(m_hideDevelopmentServers, message); + + layout->addStretch(1); + + reset(); +} + +bool ConfigMonopigator::connectOnStart() +{ + return m_connectOnStart->isChecked(); +} + +bool ConfigMonopigator::hideDevelopmentServers() +{ + return m_hideDevelopmentServers->isChecked(); +} + +void ConfigMonopigator::reset() +{ + m_connectOnStart->setChecked(m_configDialog->config().connectOnStart); + m_hideDevelopmentServers->setChecked(m_configDialog->config().hideDevelopmentServers); +} + +ConfigGeneral::ConfigGeneral(ConfigDialog *configDialog, QWidget *parent, const char *name) : QWidget(parent, name) +{ + m_configDialog = configDialog; + QVBoxLayout *layout = new QVBoxLayout(parent, KDialog::marginHint(), KDialog::spacingHint()); + + m_chatTimestamps = new QCheckBox(i18n("Show timestamps in chat messages"), parent); + layout->addWidget(m_chatTimestamps); + + QString message=i18n( + "If checked, Atlantik will add timestamps in front of chat\n" + "messages.\n"); + QWhatsThis::add(m_chatTimestamps, message); + + layout->addStretch(1); + + reset(); +} + +bool ConfigGeneral::chatTimestamps() +{ + return m_chatTimestamps->isChecked(); +} + +void ConfigGeneral::reset() +{ + m_chatTimestamps->setChecked(m_configDialog->config().chatTimestamps); +} + +ConfigBoard::ConfigBoard(ConfigDialog *configDialog, QWidget *parent, const char *name) : QWidget(parent, name) +{ + m_configDialog = configDialog; + QVBoxLayout *layout = new QVBoxLayout(parent, KDialog::marginHint(), KDialog::spacingHint()); + + QGroupBox *box = new QGroupBox(1, Qt::Horizontal, i18n("Game Status Feedback"), parent); + layout->addWidget(box); + + m_indicateUnowned = new QCheckBox(i18n("Display title deed card on unowned properties"), box); + QString message=i18n( + "If checked, unowned properties on the board display an estate\n" + "card to indicate the property is for sale.\n"); + QWhatsThis::add(m_indicateUnowned, message); + + m_highliteUnowned = new QCheckBox(i18n("Highlight unowned properties"), box); + message=i18n( + "If checked, unowned properties on the board are highlighted to\n" + "indicate the property is for sale.\n"); + QWhatsThis::add(m_highliteUnowned, message); + + m_darkenMortgaged = new QCheckBox(i18n("Darken mortgaged properties"), box); + message=i18n( + "If checked, mortgaged properties on the board will be colored\n" + "darker than of the default color.\n"); + QWhatsThis::add(m_darkenMortgaged, message); + + m_animateToken = new QCheckBox(i18n("Animate token movement"), box); + message=i18n( + "If checked, tokens will move across the board\n" + "instead of jumping directly to their new location.\n"); + QWhatsThis::add(m_animateToken, message); + + m_quartzEffects = new QCheckBox(i18n("Quartz effects"), box); + message=i18n( + "If checked, the colored headers of street estates on the board " + "will have a Quartz effect similar to the Quartz KWin style.\n"); + QWhatsThis::add(m_quartzEffects, message); + +// box = new QGroupBox(1, Qt::Horizontal, i18n("Size"), parent); +// layout->addWidget(box); + + layout->addStretch(1); + + reset(); +} + +bool ConfigBoard::indicateUnowned() +{ + return m_indicateUnowned->isChecked(); +} + +bool ConfigBoard::highliteUnowned() +{ + return m_highliteUnowned->isChecked(); +} + +bool ConfigBoard::darkenMortgaged() +{ + return m_darkenMortgaged->isChecked(); +} + +bool ConfigBoard::animateToken() +{ + return m_animateToken->isChecked(); +} + +bool ConfigBoard::quartzEffects() +{ + return m_quartzEffects->isChecked(); +} + +void ConfigBoard::reset() +{ + m_indicateUnowned->setChecked(m_configDialog->config().indicateUnowned); + m_highliteUnowned->setChecked(m_configDialog->config().highliteUnowned); + m_darkenMortgaged->setChecked(m_configDialog->config().darkenMortgaged); + m_animateToken->setChecked(m_configDialog->config().animateTokens); + m_quartzEffects->setChecked(m_configDialog->config().quartzEffects); +} diff --git a/atlantik/client/configdlg.h b/atlantik/client/configdlg.h new file mode 100644 index 00000000..c1f74294 --- /dev/null +++ b/atlantik/client/configdlg.h @@ -0,0 +1,139 @@ +// Copyright (c) 2002-2004 Rob Kaper <cap@capsi.com> +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// version 2 as published by the Free Software Foundation. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; see the file COPYING. If not, write to +// the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +// Boston, MA 02110-1301, USA. + +#ifndef ATLANTIK_CONFIGDLG_H +#define ATLANTIK_CONFIGDLG_H + +#include <qwidget.h> +#include <qcheckbox.h> +#include <qlineedit.h> + +#include <kdialogbase.h> + +class QString; + +class KPushButton; + +class Atlantik; +class ConfigDialog; + +struct AtlantikConfig; + +class ConfigPlayer : public QWidget +{ +Q_OBJECT + +public: + ConfigPlayer(ConfigDialog *configDialog, QWidget *parent, const char *name=0); + + QString playerName(); + QString playerImage(); + +private slots: + void chooseImage(); + +private: + void setImage(); + void reset(); + + ConfigDialog *m_configDialog; + QLineEdit *m_playerName; + QString m_playerImage; + KPushButton *m_playerIcon; +}; + +class ConfigBoard : public QWidget +{ +Q_OBJECT + +public: + ConfigBoard(ConfigDialog *configDialog, QWidget *parent, const char *name=0); + + bool indicateUnowned(); + bool highliteUnowned(); + bool darkenMortgaged(); + bool animateToken(); + bool quartzEffects(); + +private: + void reset(); + + ConfigDialog *m_configDialog; + QCheckBox *m_indicateUnowned, *m_highliteUnowned, *m_darkenMortgaged, *m_animateToken, *m_quartzEffects; +}; + +class ConfigMonopigator : public QWidget +{ +Q_OBJECT + +public: + ConfigMonopigator(ConfigDialog *dialog, QWidget *parent, const char *name = 0); + + bool connectOnStart(); + bool hideDevelopmentServers(); + +private: + void reset(); + + ConfigDialog *m_configDialog; + QCheckBox *m_connectOnStart, *m_hideDevelopmentServers; +}; + +class ConfigGeneral : public QWidget +{ +Q_OBJECT + +public: + ConfigGeneral(ConfigDialog *dialog, QWidget *parent, const char *name = 0); + + bool chatTimestamps(); + +private: + void reset(); + + ConfigDialog *m_configDialog; + QCheckBox *m_chatTimestamps; +}; + +class ConfigDialog : public KDialogBase +{ +Q_OBJECT + +public: + ConfigDialog(Atlantik *parent, const char *name=0); + + bool chatTimestamps(); + bool indicateUnowned(); + bool highliteUnowned(); + bool darkenMortgaged(); + bool animateToken(); + bool quartzEffects(); + AtlantikConfig config(); + QString playerName(); + QString playerImage(); + bool connectOnStart(); + bool hideDevelopmentServers(); + +private: + Atlantik *m_parent; + QFrame *p_general, *p_p13n, *p_board, *p_monopigator; + ConfigPlayer *configPlayer; + ConfigBoard *configBoard; + ConfigMonopigator *configMonopigator; + ConfigGeneral *configGeneral; +}; + +#endif diff --git a/atlantik/client/event.cpp b/atlantik/client/event.cpp new file mode 100644 index 00000000..218f6b87 --- /dev/null +++ b/atlantik/client/event.cpp @@ -0,0 +1,42 @@ +// Copyright (c) 2003 Rob Kaper <cap@capsi.com> +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License version 2.1 as published by the Free Software Foundation. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this library; see the file COPYING.LIB. If not, write to +// the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +// Boston, MA 02110-1301, USA. + +#include <qdatetime.h> +#include <qstring.h> + +#include "event.moc" + +Event::Event(const QDateTime &dateTime, const QString &description, const QString &icon) +{ + m_dateTime = dateTime; + m_description = description; + m_icon = icon; +} + +QDateTime Event::dateTime() const +{ + return m_dateTime; +} + +QString Event::description() const +{ + return m_description; +} + +QString Event::icon() const +{ + return m_icon; +} diff --git a/atlantik/client/event.h b/atlantik/client/event.h new file mode 100644 index 00000000..f2f56444 --- /dev/null +++ b/atlantik/client/event.h @@ -0,0 +1,40 @@ +// Copyright (c) 2003 Rob Kaper <cap@capsi.com> +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License version 2.1 as published by the Free Software Foundation. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this library; see the file COPYING.LIB. If not, write to +// the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +// Boston, MA 02110-1301, USA. + +#ifndef ATLANTIK_EVENT_H +#define ATLANTIK_EVENT_H + +#include <qobject.h> + +class QDateTime; +class QString; + +class Event : public QObject +{ +Q_OBJECT + +public: + Event(const QDateTime &dateTime, const QString &description, const QString &icon = QString::null); + QDateTime dateTime() const; + QString description() const; + QString icon() const; + +private: + QDateTime m_dateTime; + QString m_description, m_icon; +}; + +#endif diff --git a/atlantik/client/eventlogwidget.cpp b/atlantik/client/eventlogwidget.cpp new file mode 100644 index 00000000..b0f77ab8 --- /dev/null +++ b/atlantik/client/eventlogwidget.cpp @@ -0,0 +1,123 @@ +// Copyright (c) 2003-2004 Rob Kaper <cap@capsi.com> +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License version 2.1 as published by the Free Software Foundation. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this library; see the file COPYING.LIB. If not, write to +// the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +// Boston, MA 02110-1301, USA. + +#include <iostream> + +#include <qheader.h> +#include <qlayout.h> +#include <qdatetime.h> + +#include <klocale.h> +#include <klistview.h> +#include <kdialogbase.h> +#include <kfiledialog.h> +#include <kiconloader.h> +#include <kpushbutton.h> +#include <kstringhandler.h> + +#include "event.h" +#include "eventlogwidget.moc" + +EventLog::EventLog() +{ +} + +void EventLog::addEvent(const QString &description, const QString &icon) +{ + Event *event = new Event(QDateTime::currentDateTime(), description, icon); + m_events.append(event); + emit newEvent(event); +} + +QPtrList<Event> EventLog::events() +{ + return m_events; +} + +EventLogWidget::EventLogWidget(EventLog *eventLog, QWidget *parent, const char *name) + : QWidget(parent, name, + WType_Dialog | WStyle_Customize | WStyle_DialogBorder | WStyle_Title | + WStyle_Minimize | WStyle_ContextHelp ) +{ + m_eventLog = eventLog; + + connect(m_eventLog, SIGNAL(newEvent(Event *)), this, SLOT(addEvent(Event *))); + + setCaption(i18n("Event Log")); + + QVBoxLayout *listCompBox = new QVBoxLayout(this, KDialog::marginHint()); + + m_eventList = new KListView(this, "eventList"); + listCompBox->addWidget(m_eventList); + + m_eventList->addColumn(i18n("Date/Time")); + m_eventList->addColumn(i18n("Description")); + m_eventList->header()->setClickEnabled( false ); + + QHBoxLayout *actionBox = new QHBoxLayout(this, 0, KDialog::spacingHint()); + listCompBox->addItem(actionBox); + + actionBox->addItem(new QSpacerItem(20, 20, QSizePolicy::Expanding, QSizePolicy::Minimum)); + + m_saveButton = new KPushButton(BarIcon("filesave", KIcon::SizeSmall), i18n("&Save As..."), this); + actionBox->addWidget(m_saveButton); + + connect(m_saveButton, SIGNAL(clicked()), this, SLOT(save())); + + // Populate + QPtrList<Event> events = m_eventLog->events(); + for (QPtrListIterator<Event> it( events ); (*it) ; ++it) + addEvent( (*it) ); +} + +void EventLogWidget::addEvent(Event *event) +{ + // FIXME: allow a way to view non-squeezed message + // FIXME: allow a way to show older messages + + if ( m_eventList->childCount() >= 25 ) + delete m_eventList->firstChild(); + + QString description = KStringHandler::rsqueeze( event->description(), 200 ); + KListViewItem *item = new KListViewItem(m_eventList, event->dateTime().toString("yyyy-MM-dd hh:mm:ss zzz"), description); + if (event->icon().isEmpty()) + item->setPixmap(1, QPixmap(SmallIcon("atlantik"))); + else + item->setPixmap(1, QPixmap(SmallIcon(event->icon()))); + + m_eventList->ensureItemVisible(item); +} + +void EventLogWidget::closeEvent(QCloseEvent *e) +{ + e->accept(); +} + +void EventLogWidget::save() +{ + QFile file( KFileDialog::getSaveFileName() ); + if ( file.open( IO_WriteOnly ) ) + { + QTextStream stream(&file); + + stream << i18n( "Atlantik log file, saved at %1." ).arg( QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss") ) << endl; + + QPtrList<Event> events = m_eventLog->events(); + for (QPtrListIterator<Event> it( events ); (*it) ; ++it) + stream << (*it)->dateTime().toString("yyyy-MM-dd hh:mm:ss") << " " << (*it)->description() << endl; + file.close(); + } +} diff --git a/atlantik/client/eventlogwidget.h b/atlantik/client/eventlogwidget.h new file mode 100644 index 00000000..4b925d47 --- /dev/null +++ b/atlantik/client/eventlogwidget.h @@ -0,0 +1,73 @@ +// Copyright (c) 2003 Rob Kaper <cap@capsi.com> +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License version 2.1 as published by the Free Software Foundation. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this library; see the file COPYING.LIB. If not, write to +// the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +// Boston, MA 02110-1301, USA. + +#ifndef ATLANTIK_EVENTLOGWIDGET_H +#define ATLANTIK_EVENTLOGWIDGET_H + +#include <qwidget.h> +#include <qmap.h> + +class QString; + +class Event; + +class KListView; +class KListViewItem; +class KPushButton; + +class EventLog : public QObject +{ +Q_OBJECT + +public: + EventLog(); + QPtrList<Event> events(); + +public slots: + void addEvent(const QString &description, const QString &icon = QString::null); + +signals: + void newEvent(Event *event); + +private: + QPtrList<Event> m_events; +}; + +class EventLogWidget : public QWidget +{ +Q_OBJECT + +public: + enum EventLogType { Default, Net_In, Net_Out }; + + EventLogWidget(EventLog *eventLog, QWidget *parent=0, const char *name = 0); + +public slots: + void addEvent(Event *event); + +protected: + void closeEvent(QCloseEvent *e); + +private slots: + void save(); + +private: + EventLog *m_eventLog; + KListView *m_eventList; + KPushButton *m_saveButton; +}; + +#endif diff --git a/atlantik/client/main.cpp b/atlantik/client/main.cpp new file mode 100644 index 00000000..5f0e2fc6 --- /dev/null +++ b/atlantik/client/main.cpp @@ -0,0 +1,78 @@ +// Copyright (c) 2002-2003 Rob Kaper <cap@capsi.com> +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// version 2 as published by the Free Software Foundation. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; see the file COPYING. If not, write to +// the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +// Boston, MA 02110-1301, USA. + +#include <kaboutdata.h> +#include <kcmdlineargs.h> +#include <klocale.h> +#include <kapplication.h> +#include <kglobal.h> + +#include "main.h" +#include "atlantik.h" + +static KCmdLineOptions options[] = +{ + { "h", 0, 0 }, + { "host <argument>", I18N_NOOP("Connect to this host"), 0 }, + { "p", 0, 0 }, + { "port <argument>", I18N_NOOP("Connect at this port"), "1234" }, + { "g", 0, 0 }, + { "game <argument>", I18N_NOOP("Join this game"), 0 }, + KCmdLineLastOption +}; + +int main(int argc, char *argv[]) +{ + KAboutData aboutData( + "atlantik", + I18N_NOOP("Atlantik"), ATLANTIK_VERSION_STRING, + I18N_NOOP("The Atlantic board game"), + KAboutData::License_GPL, + I18N_NOOP("(c) 1998-2004 Rob Kaper"), + I18N_NOOP("KDE client for playing Monopoly-like games on the monopd network."), + "http://unixcode.org/atlantik/" + ); + + aboutData.addAuthor("Rob Kaper", I18N_NOOP("main author"), "cap@capsi.com", "http://capsi.com/"); + + // Patches and artists + aboutData.addCredit("Thiago Macieira", I18N_NOOP("KExtendedSocket support"), "thiagom@wanadoo.fr"); + aboutData.addCredit("Albert Astals Cid", I18N_NOOP("various patches"), "tsdgeos@terra.es"); + + aboutData.addCredit("Bart Szyszka", I18N_NOOP("application icon"), "bart@gigabee.com", "http://www.gigabee.com/"); + aboutData.addCredit("Rob Malda", I18N_NOOP("token icons"), "", "http://cmdrtaco.net/"); + aboutData.addCredit("Elhay Achiam", I18N_NOOP("icons"), "elhay_a@bezeqint.net"); + aboutData.addCredit("Carlo Caneva", I18N_NOOP("icons"), "webmaster@molecola.com", "http://www.molecola.com/"); + + KCmdLineArgs::init(argc, argv, &aboutData); + KCmdLineArgs::addCmdLineOptions (options); + + KApplication::addCmdLineOptions(); + KApplication kapplication; + KGlobal::locale()->insertCatalogue("libkdegames"); + + if (kapplication.isRestored()) + RESTORE(Atlantik) + else + { + Atlantik *atlantik = new Atlantik; + atlantik->setMinimumSize(640, 480); + atlantik->setCaption(i18n("The Atlantic Board Game")); + atlantik->show(); + } + + return kapplication.exec(); +} diff --git a/atlantik/client/main.h b/atlantik/client/main.h new file mode 100644 index 00000000..4c2f00c6 --- /dev/null +++ b/atlantik/client/main.h @@ -0,0 +1,29 @@ +// Copyright (c) 2002-2004 Rob Kaper <cap@capsi.com> +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// version 2 as published by the Free Software Foundation. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; see the file COPYING. If not, write to +// the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +// Boston, MA 02110-1301, USA. + +#ifndef ATLANTIK_MAIN_H +#define ATLANTIK_MAIN_H + +#define ATLANTIK_VERSION 075 +#define ATLANTIK_VERSION_STRING "0.7.5" + +#define ATLANTIK_VERSION_MAJOR 0 +#define ATLANTIK_VERSION_MINOR 7 +#define ATLANTIK_VERSION_RELEASE 5 + +int main(int, char *[]); + +#endif diff --git a/atlantik/client/monopigator.cpp b/atlantik/client/monopigator.cpp new file mode 100644 index 00000000..83ef0d42 --- /dev/null +++ b/atlantik/client/monopigator.cpp @@ -0,0 +1,164 @@ +// Copyright (c) 2002-2004 Rob Kaper <cap@capsi.com> +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// version 2 as published by the Free Software Foundation. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; see the file COPYING. If not, write to +// the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +// Boston, MA 02110-1301, USA. + +#include <qdom.h> +#include <qptrlist.h> +#include <qregexp.h> + +#include <kextendedsocket.h> + +#include "monopigator.moc" +#include "main.h" + +Monopigator::Monopigator() +{ + m_downloadData = 0; + m_job = 0; + m_timer = 0; +} + +Monopigator::~Monopigator() +{ + if (m_job) + m_job -> kill(); + delete m_downloadData; + m_downloadData=0L; +} + +void Monopigator::loadData(const KURL &url) +{ + delete m_downloadData; + m_downloadData = new QBuffer(); + m_downloadData->open(IO_WriteOnly); + m_downloadData->reset(); + + m_job = KIO::get(url, true, false); + m_job->addMetaData(QString::fromLatin1("UserAgent"), QString::fromLatin1("Atlantik/" ATLANTIK_VERSION_STRING)); + + if (!m_timer) + { + m_timer = new QTimer(this); + m_timer->start(10000, true); + } + + connect(m_job, SIGNAL(data(KIO::Job *, const QByteArray &)), SLOT(slotData(KIO::Job *, const QByteArray &))); + connect(m_job, SIGNAL(result(KIO::Job *)), SLOT(slotResult(KIO::Job *))); + connect(m_timer, SIGNAL(timeout()), SLOT(slotTimeout())); +} + +void Monopigator::slotData(KIO::Job *, const QByteArray &data) +{ + m_timer->stop(); + m_downloadData->writeBlock(data.data(), data.size()); +} + +void Monopigator::slotResult(KIO::Job *job) +{ + processData(m_downloadData->buffer(), !job->error()); + m_job = 0; +} + +void Monopigator::slotTimeout() +{ + if (m_job) + m_job -> kill(); + m_job = 0; + + emit timeout(); +} + +void Monopigator::processData(const QByteArray &data, bool okSoFar) +{ + if (okSoFar) + { + QString xmlData(data); + QDomDocument domDoc; + if (domDoc.setContent(xmlData)) + { + QDomElement eTop = domDoc.documentElement(); + if (eTop.tagName() != "monopigator") + return; + + QDomNode n = eTop.firstChild(); + while(!n.isNull()) + { + QDomElement e = n.toElement(); + if(!e.isNull()) + { + if (e.tagName() == "server") + emit monopigatorAdd(e.attributeNode(QString("ip")).value(), e.attributeNode(QString("host")).value(), e.attributeNode(QString("port")).value(), e.attributeNode(QString("version")).value(), e.attributeNode(QString("users")).value().toInt()); + } + n = n.nextSibling(); + } + emit finished(); + } + } +} + +MonopigatorEntry::MonopigatorEntry(QListView *parent, QString host, QString latency, QString version, QString users, QString port, QString ip) : QObject(), QListViewItem(parent, host, latency, version, users, port) +{ + m_isDev = ( version.find( QRegExp("(CVS|-dev)") ) != -1 ) ? true : false; + + setEnabled(false); + parent->sort(); + + if ( !ip.isEmpty() ) + host = ip; + m_latencySocket = new KExtendedSocket( host, port.toInt(), KExtendedSocket::inputBufferedSocket | KExtendedSocket::noResolve ); + connect(m_latencySocket, SIGNAL(lookupFinished(int)), this, SLOT(resolved())); + connect(m_latencySocket, SIGNAL(connectionSuccess()), this, SLOT(connected())); + m_latencySocket->startAsyncConnect(); +} + +void MonopigatorEntry::resolved() +{ + time.start(); +} + +void MonopigatorEntry::connected() +{ + setText( 1, QString::number(time.elapsed()) ); + setEnabled(true); + listView()->sort(); + delete m_latencySocket; +} + +int MonopigatorEntry::compare(QListViewItem *i, int col, bool ascending) const +{ + // Colums 1 and 3 are integers (latency and users) + if (col == 1 || col == 3) + { + int myVal = text(col).toInt(), iVal = i->text(col).toInt(); + if (myVal == iVal) + return 0; + else if (myVal > iVal) + return 1; + else + return -1; + } + return key( col, ascending ).compare( i->key( col, ascending) ); +} + +bool MonopigatorEntry::isDev() const +{ + return m_isDev; +} + +void MonopigatorEntry::showDevelopmentServers(bool show) +{ + if ( isVisible() != show ) + setVisible(show); +} diff --git a/atlantik/client/monopigator.h b/atlantik/client/monopigator.h new file mode 100644 index 00000000..1fd57b1b --- /dev/null +++ b/atlantik/client/monopigator.h @@ -0,0 +1,79 @@ +// Copyright (c) 2002-2004 Rob Kaper <cap@capsi.com> +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// version 2 as published by the Free Software Foundation. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; see the file COPYING. If not, write to +// the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +// Boston, MA 02110-1301, USA. + +#ifndef ATLANTIK_MONOPIGATOR_H +#define ATLANTIK_MONOPIGATOR_H + +#include <qobject.h> +#include <qbuffer.h> +#include <qlistview.h> +#include <qtimer.h> + +#include <kio/job.h> +#include <kurl.h> + +class KExtendedSocket; +class QTime; + +class Monopigator : public QObject +{ +Q_OBJECT + +public: + Monopigator(); + ~Monopigator(); + void loadData(const KURL &); + +signals: + void monopigatorAdd(QString ip, QString host, QString port, QString version, int users); + void finished(); + void timeout(); + +private slots: + void slotData(KIO::Job *, const QByteArray &); + void slotResult(KIO::Job *); + void slotTimeout(); + +private: + void processData(const QByteArray &, bool = true); + + QBuffer *m_downloadData; + QTimer *m_timer; + KIO::Job *m_job; +}; + +class MonopigatorEntry : public QObject, public QListViewItem +{ +Q_OBJECT + +public: + MonopigatorEntry(QListView *parent, QString host, QString latency, QString version, QString users, QString port, QString ip); + int compare(QListViewItem *i, int col, bool ascending) const; + bool isDev() const; + +private slots: + void resolved(); + void connected(); + void showDevelopmentServers(bool show); + +private: + KExtendedSocket *m_latencySocket; + QTime time; + QListView *m_parent; + bool m_isDev; +}; + +#endif diff --git a/atlantik/client/selectconfiguration_widget.cpp b/atlantik/client/selectconfiguration_widget.cpp new file mode 100644 index 00000000..0e7d5cdb --- /dev/null +++ b/atlantik/client/selectconfiguration_widget.cpp @@ -0,0 +1,189 @@ +// Copyright (c) 2002-2004 Rob Kaper <cap@capsi.com> +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// version 2 as published by the Free Software Foundation. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; see the file COPYING. If not, write to +// the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +// Boston, MA 02110-1301, USA. + +#include <iostream> + +#include <qcheckbox.h> +#include <qradiobutton.h> + +#include <kdebug.h> +#include <kdialog.h> +#include <klocale.h> +#include <kiconloader.h> +#include <kmessagebox.h> +#include <kstandarddirs.h> + +#include <atlantic_core.h> +#include <configoption.h> +#include <game.h> +#include <player.h> + +#include "selectconfiguration_widget.moc" + +SelectConfiguration::SelectConfiguration(AtlanticCore *atlanticCore, QWidget *parent, const char *name) : QWidget(parent, name) +{ + m_atlanticCore = atlanticCore; + m_game = 0; + + m_mainLayout = new QVBoxLayout(this, KDialog::marginHint()); + Q_CHECK_PTR(m_mainLayout); + + // Game configuration. + m_configBox = new QVGroupBox(i18n("Game Configuration"), this, "configBox"); + m_mainLayout->addWidget(m_configBox); + + // Player buttons. + QHBoxLayout *playerButtons = new QHBoxLayout(m_mainLayout, KDialog::spacingHint()); + playerButtons->setMargin(0); + + playerButtons->addItem(new QSpacerItem(20, 20, QSizePolicy::Expanding, QSizePolicy::Minimum)); + + // Vertical spacer. + m_mainLayout->addItem(new QSpacerItem(20, 20, QSizePolicy::Minimum, QSizePolicy::Expanding)); + + // Server buttons. + QHBoxLayout *serverButtons = new QHBoxLayout(m_mainLayout, KDialog::spacingHint()); + serverButtons->setMargin(0); + + m_backButton = new KPushButton(SmallIcon("back"), i18n("Leave Game"), this); + serverButtons->addWidget(m_backButton); + + connect(m_backButton, SIGNAL(clicked()), this, SIGNAL(leaveGame())); + + serverButtons->addItem(new QSpacerItem(20, 20, QSizePolicy::Expanding, QSizePolicy::Minimum)); + + m_startButton = new KPushButton(SmallIconSet("forward"), i18n("Start Game"), this); + serverButtons->addWidget(m_startButton); + m_startButton->setEnabled(false); + + connect(m_startButton, SIGNAL(clicked()), this, SIGNAL(startGame())); + + Player *playerSelf = m_atlanticCore->playerSelf(); + playerChanged(playerSelf); + connect(playerSelf, SIGNAL(changed(Player *)), this, SLOT(playerChanged(Player *))); + + emit statusMessage(i18n("Retrieving configuration list...")); +} + +void SelectConfiguration::initGame() +{ + emit statusMessage(i18n("Game started. Retrieving full game data...")); +} + +void SelectConfiguration::addConfigOption(ConfigOption *configOption) +{ + // FIXME: only bool types supported! + QCheckBox *checkBox = new QCheckBox(configOption->description(), m_configBox, "checkbox"); + m_configMap[(QObject *)checkBox] = configOption; + m_configBoxMap[configOption] = checkBox; + + checkBox->setChecked( configOption->value().toInt() ); + checkBox->setEnabled( configOption->edit() && m_atlanticCore->selfIsMaster() ); + checkBox->show(); + + connect(checkBox, SIGNAL(clicked()), this, SLOT(changeOption())); + connect(configOption, SIGNAL(changed(ConfigOption *)), this, SLOT(optionChanged(ConfigOption *))); +} + +void SelectConfiguration::gameOption(QString title, QString type, QString value, QString edit, QString command) +{ + // Find if option exists in GUI yet + if (QCheckBox *checkBox = dynamic_cast<QCheckBox *>(m_checkBoxMap[command])) + { + checkBox->setChecked(value.toInt()); + checkBox->setEnabled(edit.toInt()); + return; + } + + // Create option + if (type == "bool") + { + QCheckBox *checkBox = new QCheckBox(title, m_configBox, "checkbox"); + m_optionCommandMap[(QObject *)checkBox] = command; + m_checkBoxMap[command] = checkBox; + checkBox->setChecked(value.toInt()); + checkBox->setEnabled(edit.toInt()); + checkBox->show(); + + connect(checkBox, SIGNAL(clicked()), this, SLOT(optionChanged())); + } + // TODO: create options other than type=bool + + // TODO: Enable edit for master only +} + +void SelectConfiguration::changeOption() +{ + ConfigOption *configOption = m_configMap[(QObject *)QObject::sender()]; + if (configOption) + { + kdDebug() << "checked " << ((QCheckBox *)QObject::sender())->isChecked() << endl; + emit changeOption( configOption->id(), QString::number( ((QCheckBox *)QObject::sender())->isChecked() ) ); + } +} + +void SelectConfiguration::optionChanged(ConfigOption *configOption) +{ + QCheckBox *checkBox = m_configBoxMap[configOption]; + if (checkBox) + { + checkBox->setText( configOption->description() ); + checkBox->setChecked( configOption->value().toInt() ); + checkBox->setEnabled( configOption->edit() && m_atlanticCore->selfIsMaster() ); + } +} + +void SelectConfiguration::optionChanged() +{ + QString command = m_optionCommandMap[(QObject *)QObject::sender()]; + + if (QCheckBox *checkBox = m_checkBoxMap[command]) + { + command.append(QString::number(checkBox->isChecked())); + emit buttonCommand(command); + } +} + +void SelectConfiguration::slotEndUpdate() +{ + emit statusMessage(i18n("Retrieved configuration list.")); +} + +void SelectConfiguration::playerChanged(Player *player) +{ + kdDebug() << "playerChanged" << endl; + + if (player->game() != m_game) + { + kdDebug() << "playerChanged::change" << endl; + + if (m_game) + disconnect(m_game, SIGNAL(changed(Game *)), this, SLOT(gameChanged(Game *))); + + m_game = player->game(); + + if (m_game) + connect(m_game, SIGNAL(changed(Game *)), this, SLOT(gameChanged(Game *))); + } +} + +void SelectConfiguration::gameChanged(Game *game) +{ + m_startButton->setEnabled( game->master() == m_atlanticCore->playerSelf() ); + + for (QMapIterator<ConfigOption *, QCheckBox *> it = m_configBoxMap.begin() ; it != m_configBoxMap.end() ; ++it) + (*it)->setEnabled( it.key()->edit() && m_atlanticCore->selfIsMaster() ); +} diff --git a/atlantik/client/selectconfiguration_widget.h b/atlantik/client/selectconfiguration_widget.h new file mode 100644 index 00000000..033a0eb0 --- /dev/null +++ b/atlantik/client/selectconfiguration_widget.h @@ -0,0 +1,80 @@ +// Copyright (c) 2002-2004 Rob Kaper <cap@capsi.com> +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// version 2 as published by the Free Software Foundation. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; see the file COPYING. If not, write to +// the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +// Boston, MA 02110-1301, USA. + +#ifndef ATLANTIK_SELECTCONFIGURATION_WIDGET_H +#define ATLANTIK_SELECTCONFIGURATION_WIDGET_H + +#include <qwidget.h> +#include <qlayout.h> +#include <qvgroupbox.h> + +#include <klistview.h> +#include <kpushbutton.h> + +class QCheckBox; +class QListViewItem; + +class AtlanticCore; +class ConfigOption; +class Game; +class Player; + +class SelectConfiguration : public QWidget +{ +Q_OBJECT + +public: + SelectConfiguration(AtlanticCore *atlanticCore, QWidget *parent, const char *name=0); + + void setCanStart(const bool &canStart); + QString hostToConnect() const; + int portToConnect(); + +private slots: + void addConfigOption(ConfigOption *configOption); + void changeOption(); + void gameOption(QString title, QString type, QString value, QString edit, QString command); + void optionChanged(ConfigOption *configOption); + void optionChanged(); + void slotEndUpdate(); + void initGame(); + void playerChanged(Player *player); + void gameChanged(Game *game); + +signals: + void startGame(); + void leaveGame(); + void joinConfiguration(int configurationId); + void newConfiguration(); + void changeOption(int configId, const QString &value); + void buttonCommand(QString); + void iconSelected(const QString &); + void statusMessage(const QString &message); + +private: + QVBoxLayout *m_mainLayout; + QVGroupBox *m_configBox, *m_messageBox; + KPushButton *m_backButton, *m_startButton; + QMap <QObject *, QString> m_optionCommandMap; + QMap <QObject *, ConfigOption *> m_configMap; + QMap <ConfigOption *, QCheckBox *> m_configBoxMap; + QMap <QString, QCheckBox *> m_checkBoxMap; + QMap <Player *, QListViewItem *> m_items; + Game *m_game; + AtlanticCore *m_atlanticCore; +}; + +#endif diff --git a/atlantik/client/selectgame_widget.cpp b/atlantik/client/selectgame_widget.cpp new file mode 100644 index 00000000..85d4f886 --- /dev/null +++ b/atlantik/client/selectgame_widget.cpp @@ -0,0 +1,192 @@ +// Copyright (c) 2002-2003 Rob Kaper <cap@capsi.com> +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// version 2 as published by the Free Software Foundation. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; see the file COPYING. If not, write to +// the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +// Boston, MA 02110-1301, USA. + +#include <qvgroupbox.h> +#include <qradiobutton.h> + +#include <kdebug.h> +#include <kdialog.h> +#include <klocale.h> +#include <kiconloader.h> +#include <knotifyclient.h> + +#include <atlantic_core.h> +#include <game.h> +#include <player.h> + +#include "selectgame_widget.h" + +SelectGame::SelectGame(AtlanticCore *atlanticCore, QWidget *parent, const char *name) : QWidget(parent, name) +{ + m_atlanticCore = atlanticCore; + + connect(m_atlanticCore, SIGNAL(createGUI(Game *)), this, SLOT(addGame(Game *))); + connect(m_atlanticCore, SIGNAL(removeGUI(Game *)), this, SLOT(delGame(Game *))); + + m_mainLayout = new QVBoxLayout(this, KDialog::marginHint()); + Q_CHECK_PTR(m_mainLayout); + + QVGroupBox *groupBox; + groupBox = new QVGroupBox(i18n("Create or Select monopd Game"), this, "groupBox"); + m_mainLayout->addWidget(groupBox); + + // List of games + m_gameList = new KListView(groupBox, "m_gameList"); + m_gameList->addColumn(i18n("Game")); + m_gameList->addColumn(i18n("Description")); + m_gameList->addColumn(i18n("Id")); + m_gameList->addColumn(i18n("Players")); + m_gameList->setAllColumnsShowFocus(true); +// m_mainLayout->addWidget(m_gameList); + + connect(m_gameList, SIGNAL(clicked(QListViewItem *)), this, SLOT(validateConnectButton())); + connect(m_gameList, SIGNAL(doubleClicked(QListViewItem *)), this, SLOT(connectClicked())); + connect(m_gameList, SIGNAL(rightButtonClicked(QListViewItem *, const QPoint &, int)), this, SLOT(validateConnectButton())); + connect(m_gameList, SIGNAL(selectionChanged(QListViewItem *)), this, SLOT(validateConnectButton())); + + QHBoxLayout *buttonBox = new QHBoxLayout(m_mainLayout, KDialog::spacingHint()); + + KPushButton *backButton = new KPushButton(SmallIcon("back"), i18n("Server List"), this); + buttonBox->addWidget(backButton); + + connect(backButton, SIGNAL(clicked()), this, SIGNAL(leaveServer())); + + buttonBox->addItem(new QSpacerItem(20, 20, QSizePolicy::Expanding, QSizePolicy::Minimum)); + + m_connectButton = new KPushButton(SmallIconSet("forward"), i18n("Create Game"), this); + m_connectButton->setEnabled(false); + buttonBox->addWidget(m_connectButton); + + connect(m_connectButton, SIGNAL(clicked()), this, SLOT(connectClicked())); + +} + +void SelectGame::addGame(Game *game) +{ + connect(game, SIGNAL(changed(Game *)), this, SLOT(updateGame(Game *))); + + if (game->id() == -1) + { + QListViewItem *item = new QListViewItem( m_gameList, i18n("Create a new %1 Game").arg(game->name()), game->description(), QString::null, QString::null, game->type() ); + item->setPixmap(0, QPixmap(SmallIcon("filenew"))); + } + else + { + Player *master = game->master(); + QListViewItem *item = new QListViewItem( m_gameList, i18n("Join %1's %2 Game").arg( (master ? master->name() : QString::null), game->name() ), game->description(), QString::number(game->id()), QString::number(game->players()), game->type() ); + item->setPixmap( 0, QPixmap(SmallIcon("atlantik")) ); + item->setEnabled(game->canBeJoined()); + + KNotifyClient::event(winId(), "newgame"); + + connect(master, SIGNAL(changed(Player *)), this, SLOT(playerChanged(Player *))); + } + +// validateConnectButton(); +} + +void SelectGame::delGame(Game *game) +{ + QListViewItem *item = findItem(game); + if (!item) + return; + + delete item; + + validateConnectButton(); +} + +void SelectGame::updateGame(Game *game) +{ + QListViewItem *item = findItem(game); + if (!item) + return; + + item->setText( 1, game->description() ); + + if (game->id() == -1) + item->setText(0, i18n("Create a new %1 Game").arg(game->name())); + else + { + Player *master = game->master(); + item->setText( 0, i18n("Join %1's %2 Game").arg( (master ? master->name() : QString::null), game->name() ) ); + item->setText( 3, QString::number( game->players() ) ); + item->setEnabled( game->canBeJoined() ); + + connect(master, SIGNAL(changed(Player *)), this, SLOT(playerChanged(Player *))); + } + m_gameList->triggerUpdate(); + + validateConnectButton(); +} + +void SelectGame::playerChanged(Player *player) +{ + QListViewItem *item = m_gameList->firstChild(); + Game *game = 0; + + while (item) + { + game = m_atlanticCore->findGame( item->text(2).toInt() ); + if ( game && game->master() == player ) + { + item->setText( 0, i18n("Join %1's %2 Game").arg( player->name(), game->name() ) ); + return; + } + item = item->nextSibling(); + } +} + +QListViewItem *SelectGame::findItem(Game *game) +{ + QListViewItem *item = m_gameList->firstChild(); + while (item) + { + if ( (game->id() == -1 || item->text(2) == QString::number(game->id())) && item->text(4) == game->type() ) + return item; + + item = item->nextSibling(); + } + return 0; +} + +void SelectGame::validateConnectButton() +{ + if (QListViewItem *item = m_gameList->selectedItem()) + { + if (item->text(2).toInt() > 0) + m_connectButton->setText(i18n("Join Game")); + else + m_connectButton->setText(i18n("Create Game")); + + m_connectButton->setEnabled(true); + } + else + m_connectButton->setEnabled(false); +} + +void SelectGame::connectClicked() +{ + if (QListViewItem *item = m_gameList->selectedItem()) + { + if (int gameId = item->text(2).toInt()) + emit joinGame(gameId); + else + emit newGame(item->text(4)); + } +} + +#include "selectgame_widget.moc" diff --git a/atlantik/client/selectgame_widget.h b/atlantik/client/selectgame_widget.h new file mode 100644 index 00000000..d47e905e --- /dev/null +++ b/atlantik/client/selectgame_widget.h @@ -0,0 +1,65 @@ +// Copyright (c) 2002-2003 Rob Kaper <cap@capsi.com> +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// version 2 as published by the Free Software Foundation. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; see the file COPYING. If not, write to +// the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +// Boston, MA 02110-1301, USA. + +#ifndef ATLANTIK_SELECTGAME_WIDGET_H +#define ATLANTIK_SELECTGAME_WIDGET_H + +#include <qwidget.h> +#include <qlayout.h> + +#include <klistview.h> +#include <kpushbutton.h> + +class AtlanticCore; +class Game; +class Player; + +class SelectGame : public QWidget +{ +Q_OBJECT + +public: + SelectGame(AtlanticCore *atlanticCore, QWidget *parent, const char *name=0); + + void initPage(); + bool validateNext(); + QString hostToConnect() const; + int portToConnect(); + +private slots: + void connectClicked(); + void addGame(Game *game); + void delGame(Game *game); + void updateGame(Game *game); + void playerChanged(Player *player); + void validateConnectButton(); + +signals: + void joinGame(int gameId); + void newGame(const QString &gameType); + void leaveServer(); + void msgStatus(const QString &status); + +private: + QListViewItem *findItem(Game *game); + + AtlanticCore *m_atlanticCore; + QVBoxLayout *m_mainLayout; + KListView *m_gameList; + KPushButton *m_connectButton; +}; + +#endif diff --git a/atlantik/client/selectserver_widget.cpp b/atlantik/client/selectserver_widget.cpp new file mode 100644 index 00000000..39c07b50 --- /dev/null +++ b/atlantik/client/selectserver_widget.cpp @@ -0,0 +1,178 @@ +// Copyright (c) 2002-2004 Rob Kaper <cap@capsi.com> +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// version 2 as published by the Free Software Foundation. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; see the file COPYING. If not, write to +// the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +// Boston, MA 02110-1301, USA. + +#include <qlabel.h> +#include <qlayout.h> +#include <qradiobutton.h> +#include <qsizepolicy.h> +#include <qvbuttongroup.h> +#include <qhgroupbox.h> + +#include <kdialog.h> +#include <kextendedsocket.h> +#include <klocale.h> +#include <kiconloader.h> + +#include "selectserver_widget.moc" + +SelectServer::SelectServer(bool useMonopigatorOnStart, bool hideDevelopmentServers, QWidget *parent, const char *name) : QWidget(parent, name) +{ + m_hideDevelopmentServers = hideDevelopmentServers; + + m_mainLayout = new QVBoxLayout(this, KDialog::marginHint()); + Q_CHECK_PTR(m_mainLayout); + + // Custom server group + QHGroupBox *customGroup = new QHGroupBox(i18n("Enter Custom monopd Server"), this, "customGroup"); + m_mainLayout->addWidget(customGroup); + + QLabel *hostLabel = new QLabel(i18n("Hostname:"), customGroup); + + m_hostEdit = new KLineEdit(customGroup); + m_hostEdit->setSizePolicy(QSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Minimum)); + + QLabel *portLabel = new QLabel(i18n("Port:"), customGroup); + + m_portEdit = new KLineEdit(QString::number(1234), customGroup); + m_portEdit->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Minimum)); + + KPushButton *connectButton = new KPushButton( KGuiItem(i18n("Connect"), "network"), customGroup); + connect(connectButton, SIGNAL(clicked()), this, SLOT(customConnect())); + + // Server list group + QVButtonGroup *bgroup = new QVButtonGroup(i18n("Select monopd Server"), this, "bgroup"); + bgroup->setExclusive(true); + m_mainLayout->addWidget(bgroup); + + // List of servers + m_serverList = new KListView(bgroup, "m_serverList"); + m_serverList->addColumn(i18n("Host")); + m_serverList->addColumn(i18n("Latency")); + m_serverList->addColumn(i18n("Version")); + m_serverList->addColumn(i18n("Users")); + m_serverList->setAllColumnsShowFocus(true); + m_serverList->setSorting(1); +// m_mainLayout->addWidget(m_serverList); + + connect(m_serverList, SIGNAL(clicked(QListViewItem *)), this, SLOT(validateConnectButton())); + connect(m_serverList, SIGNAL(doubleClicked(QListViewItem *)), this, SLOT(slotConnect())); + connect(m_serverList, SIGNAL(rightButtonClicked(QListViewItem *, const QPoint &, int)), this, SLOT(validateConnectButton())); + connect(m_serverList, SIGNAL(selectionChanged(QListViewItem *)), this, SLOT(validateConnectButton())); + + QHBoxLayout *buttonBox = new QHBoxLayout(m_mainLayout, KDialog::spacingHint()); + buttonBox->addItem(new QSpacerItem(20, 20, QSizePolicy::Expanding, QSizePolicy::Minimum)); + + // Server List / Refresh + m_refreshButton = new KPushButton( KGuiItem(useMonopigatorOnStart ? i18n("Reload Server List") : i18n("Get Server List"), useMonopigatorOnStart ? "reload" : "network"), this); + buttonBox->addWidget(m_refreshButton); + + connect(m_refreshButton, SIGNAL(clicked()), this, SLOT(slotRefresh())); + + // Connect + m_connectButton = new KPushButton(BarIconSet("forward", KIcon::SizeSmall), i18n("Connect"), this); + m_connectButton->setEnabled(false); + buttonBox->addWidget(m_connectButton); + + connect(m_connectButton, SIGNAL(clicked()), this, SLOT(slotConnect())); + + // Monopigator + m_monopigator = new Monopigator(); + + connect(m_monopigator, SIGNAL(monopigatorAdd(QString, QString, QString, QString, int)), this, SLOT(slotMonopigatorAdd(QString, QString, QString, QString, int))); + connect(m_monopigator, SIGNAL(finished()), SLOT(monopigatorFinished())); + connect(m_monopigator, SIGNAL(timeout()), SLOT(monopigatorTimeout())); +} + +SelectServer::~SelectServer() +{ + delete m_monopigator; +} + +void SelectServer::setHideDevelopmentServers(bool hideDevelopmentServers) +{ + if ( m_hideDevelopmentServers != hideDevelopmentServers ) + { + m_hideDevelopmentServers = hideDevelopmentServers; + emit showDevelopmentServers( !m_hideDevelopmentServers ); + } +} + +void SelectServer::initMonopigator() +{ + // Hardcoded, but there aren't any other Monopigator root servers at the moment + emit msgStatus(i18n("Retrieving server list...")); + + m_refreshButton->setGuiItem(KGuiItem(i18n("Reload Server List"), "reload")); + m_monopigator->loadData(KURL( "http://monopd-gator.kde.org/")); +} + +void SelectServer::slotMonopigatorAdd(QString ip, QString host, QString port, QString version, int users) +{ + MonopigatorEntry *item = new MonopigatorEntry(m_serverList, host, QString::number(9999), version, (users == -1) ? i18n("unknown") : QString::number(users), port, ip); + item->setPixmap(0, BarIcon("atlantik", KIcon::SizeSmall)); + + if ( item->isDev() ) + { + item->setVisible( !m_hideDevelopmentServers ); + connect(this, SIGNAL(showDevelopmentServers(bool)), item, SLOT(showDevelopmentServers(bool))); + } + + validateConnectButton(); +} + +void SelectServer::monopigatorFinished() +{ + emit msgStatus(i18n("Retrieved server list.")); + m_refreshButton->setEnabled(true); +} + +void SelectServer::monopigatorTimeout() +{ + emit msgStatus(i18n("Error while retrieving the server list.")); + m_refreshButton->setEnabled(true); +} + +void SelectServer::validateConnectButton() +{ + if (m_serverList->selectedItem()) + m_connectButton->setEnabled(true); + else + m_connectButton->setEnabled(false); +} + +void SelectServer::slotRefresh(bool useMonopigator) +{ + m_serverList->clear(); + validateConnectButton(); + + if (useMonopigator) + { + m_refreshButton->setEnabled(false); + initMonopigator(); + } +} + +void SelectServer::slotConnect() +{ + if (QListViewItem *item = m_serverList->selectedItem()) + emit serverConnect(item->text(0), item->text(4).toInt()); +} + +void SelectServer::customConnect() +{ + if (!m_hostEdit->text().isEmpty() && !m_portEdit->text().isEmpty()) + emit serverConnect(m_hostEdit->text(), m_portEdit->text().toInt()); +} diff --git a/atlantik/client/selectserver_widget.h b/atlantik/client/selectserver_widget.h new file mode 100644 index 00000000..c5d1b586 --- /dev/null +++ b/atlantik/client/selectserver_widget.h @@ -0,0 +1,73 @@ +// Copyright (c) 2002-2004 Rob Kaper <cap@capsi.com> +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// version 2 as published by the Free Software Foundation. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; see the file COPYING. If not, write to +// the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +// Boston, MA 02110-1301, USA. + +#ifndef ATLANTIK_SELECTSERVER_WIDGET_H +#define ATLANTIK_SELECTSERVER_WIDGET_H + +#include <qwidget.h> +#include <qlayout.h> +#include <qradiobutton.h> + +#include <klineedit.h> +#include <klistview.h> +#include <kpushbutton.h> + +#include "monopigator.h" + +class KExtendedSocket; + +class SelectServer : public QWidget +{ +Q_OBJECT + +public: + SelectServer(bool useMonopigatorOnStart, bool hideDevelopmentServers, QWidget *parent, const char *name=0); + virtual ~SelectServer(); + + void initPage(); + void setHideDevelopmentServers(bool hideDevelopmentServers); + bool validateNext(); + QString hostToConnect() const; + int portToConnect(); + +public slots: + void validateConnectButton(); + void slotRefresh(bool useMonopigator = true); + void slotMonopigatorAdd(QString ip, QString host, QString port, QString version, int users); + +private slots: + void slotConnect(); + void customConnect(); + void monopigatorFinished(); + void monopigatorTimeout(); + +signals: + void serverConnect(const QString host, int port); + void msgStatus(const QString &message); + void showDevelopmentServers(bool show); + +private: + void initMonopigator(); + + QVBoxLayout *m_mainLayout; + KListView *m_serverList; + KLineEdit *m_hostEdit, *m_portEdit; + KPushButton *m_addServerButton, *m_refreshButton, *m_customConnect, *m_connectButton; + Monopigator *m_monopigator; + bool m_hideDevelopmentServers; +}; + +#endif |