diff options
Diffstat (limited to 'atlantik/libatlantikui')
20 files changed, 3369 insertions, 0 deletions
diff --git a/atlantik/libatlantikui/Makefile.am b/atlantik/libatlantikui/Makefile.am new file mode 100644 index 00000000..2e3bbbed --- /dev/null +++ b/atlantik/libatlantikui/Makefile.am @@ -0,0 +1,15 @@ +INCLUDES = -I$(top_srcdir)/atlantik/libatlantic $(all_includes) +lib_LTLIBRARIES = libatlantikui.la +libatlantikui_la_LDFLAGS = $(all_libraries) $(KDE_RPATH) -no-undefined -version-info 3:0:2 +libatlantikui_la_LIBADD = ../libatlantic/libatlantic.la $(LIB_KIO) + +libatlantikui_la_SOURCES = auction_widget.cpp board.cpp estatedetails.cpp \ + estateview.cpp kwrappedlistviewitem.cpp portfolioestate.cpp \ + portfolioview.cpp token.cpp trade_widget.cpp + +libatlantikuiincludedir = $(includedir)/atlantik/ui +libatlantikuiinclude_HEADERS = auction_widget.h board.h estatedetails.h \ + estateview.h kwrappedlistviewitem.h portfolioestate.h \ + portfolioview.h token.h trade_widget.h libatlantikui_export.h + +METASOURCES = AUTO diff --git a/atlantik/libatlantikui/auction_widget.cpp b/atlantik/libatlantikui/auction_widget.cpp new file mode 100644 index 00000000..e7dc7fd8 --- /dev/null +++ b/atlantik/libatlantikui/auction_widget.cpp @@ -0,0 +1,141 @@ +// Copyright (c) 2002 Rob Kaper <[email protected]> +// +// 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 <qvgroupbox.h> +#include <qhbox.h> +#include <qspinbox.h> +#include <qlabel.h> + +#include <kdebug.h> + +#include <kdialog.h> +#include <kiconloader.h> +#include <klocale.h> +#include <kpushbutton.h> + +#include <atlantic_core.h> +#include <player.h> +#include <estate.h> +#include <auction.h> + +#include "auction_widget.moc" + +AuctionWidget::AuctionWidget(AtlanticCore *atlanticCore, Auction *auction, QWidget *parent, const char *name) : QWidget(parent, name) +{ + m_atlanticCore = atlanticCore; + + m_auction = auction; + connect(m_auction, SIGNAL(changed()), this, SLOT(auctionChanged())); + connect(m_auction, SIGNAL(updateBid(Player *, int)), this, SLOT(updateBid(Player *, int))); + connect(this, SIGNAL(bid(Auction *, int)), m_auction, SIGNAL(bid(Auction *, int))); + + m_mainLayout = new QVBoxLayout(this, KDialog::marginHint()); + Q_CHECK_PTR(m_mainLayout); + + // Player list + Estate *estate = auction->estate(); + m_playerGroupBox = new QVGroupBox(estate ? i18n("Auction: %1").arg(estate->name()) : i18n("Auction"), this, "groupBox"); + m_mainLayout->addWidget(m_playerGroupBox); + + m_playerList = new KListView(m_playerGroupBox); + m_playerList->addColumn(i18n("Player")); + m_playerList->addColumn(i18n("Bid")); + m_playerList->setSorting(1, false); + + KListViewItem *item; + Player *player, *pSelf = m_atlanticCore->playerSelf(); + + QPtrList<Player> playerList = m_atlanticCore->players(); + for (QPtrListIterator<Player> it(playerList); *it; ++it) + { + if ( (player = *it) && player->game() == pSelf->game() ) + { + item = new KListViewItem(m_playerList, player->name(), QString("0")); + item->setPixmap(0, QPixmap(SmallIcon("personal"))); + m_playerItems[player] = item; + + connect(player, SIGNAL(changed(Player *)), this, SLOT(playerChanged(Player *))); + } + } + + // Bid spinbox and button + QHBox *bidBox = new QHBox(this); + m_mainLayout->addWidget(bidBox); + + m_bidSpinBox = new QSpinBox(1, 10000, 1, bidBox); + + KPushButton *bidButton = new KPushButton(i18n("Make Bid"), bidBox, "bidButton"); + connect(bidButton, SIGNAL(clicked()), this, SLOT(slotBidButtonClicked())); + + // Status label + m_statusLabel = new QLabel(this, "statusLabel"); + m_mainLayout->addWidget(m_statusLabel); +} + +void AuctionWidget::auctionChanged() +{ + QString status; + switch (m_auction->status()) + { + case 1: + status = i18n("Going once..."); + break; + + case 2: + status = i18n("Going twice..."); + break; + + case 3: + status = i18n("Sold!"); + break; + + default: + status = QString::null; + } + m_statusLabel->setText(status); +} + +void AuctionWidget::playerChanged(Player *player) +{ + if (!player) + return; + + QListViewItem *item; + if (!(item = m_playerItems[player])) + return; + + item->setText(0, player->name()); + m_playerList->triggerUpdate(); +} + +void AuctionWidget::updateBid(Player *player, int amount) +{ + if (!player) + return; + + QListViewItem *item; + if (!(item = m_playerItems[player])) + return; + + item->setText(1, QString::number(amount)); + m_bidSpinBox->setMinValue(amount+1); + m_playerList->triggerUpdate(); +} + +void AuctionWidget::slotBidButtonClicked() +{ + emit bid(m_auction, m_bidSpinBox->value()); +} diff --git a/atlantik/libatlantikui/auction_widget.h b/atlantik/libatlantikui/auction_widget.h new file mode 100644 index 00000000..a87b8fc4 --- /dev/null +++ b/atlantik/libatlantikui/auction_widget.h @@ -0,0 +1,65 @@ +// Copyright (c) 2002 Rob Kaper <[email protected]> +// +// 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_AUCTION_WIDGET_H +#define ATLANTIK_AUCTION_WIDGET_H + +#include <qwidget.h> +#include <qlayout.h> +#include <qmap.h> + +#include <klistview.h> + +class QVGroupBox; +class QSpinBox; +class QLabel; + +class KListViewItem; + +class AtlanticCore; +class Player; +class Auction; + +class AuctionWidget : public QWidget +{ +Q_OBJECT + +public: + AuctionWidget(AtlanticCore *atlanticCore, Auction *auction, QWidget *parent, const char *name=0); + +private slots: + void auctionChanged(); + void playerChanged(Player *player); + void updateBid(Player *player, int amount); + void slotBidButtonClicked(); + +signals: + void bid(Auction *auction, int amount); + +private: + QVBoxLayout *m_mainLayout; + QVGroupBox *m_playerGroupBox; + QSpinBox *m_bidSpinBox; + QMap<Player *, KListViewItem *> m_playerItems; + QLabel *m_statusLabel; + + KListView *m_playerList; + + AtlanticCore *m_atlanticCore; + Auction *m_auction; +}; + +#endif diff --git a/atlantik/libatlantikui/board.cpp b/atlantik/libatlantikui/board.cpp new file mode 100644 index 00000000..a4fdf3ce --- /dev/null +++ b/atlantik/libatlantikui/board.cpp @@ -0,0 +1,601 @@ +// Copyright (c) 2002-2004 Rob Kaper <[email protected]> +// +// 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 <qpainter.h> +#include <qstring.h> + +#include <kdebug.h> +#include <klocale.h> + +#include <atlantic_core.h> +#include <player.h> +#include <estate.h> +#include <auction.h> + +#include "auction_widget.h" +#include "estatedetails.h" +#include "estateview.h" +#include "token.h" + +#include "board.h" +#include "board.moc" + +AtlantikBoard::AtlantikBoard(AtlanticCore *atlanticCore, int maxEstates, DisplayMode mode, QWidget *parent, const char *name) : QWidget(parent, name) +{ + m_atlanticCore = atlanticCore; + m_maxEstates = maxEstates; + m_mode = mode; + m_animateTokens = false; + m_lastServerDisplay = 0; + + setMinimumSize(QSize(500, 500)); + + int sideLen = maxEstates/4; + + // Animated token movement + m_movingToken = 0; + m_timer = new QTimer(this); + connect(m_timer, SIGNAL(timeout()), this, SLOT(slotMoveToken())); + m_resumeTimer = false; + + m_gridLayout = new QGridLayout(this, sideLen+1, sideLen+1); + for(int i=0;i<=sideLen;i++) + { + if (i==0 || i==sideLen) + { + m_gridLayout->setRowStretch(i, 3); + m_gridLayout->setColStretch(i, 3); + } + else + { + m_gridLayout->setRowStretch(i, 2); + m_gridLayout->setColStretch(i, 2); + } + } + +// spacer = new QWidget(this); +// m_gridLayout->addWidget(spacer, sideLen, sideLen); // SE + + m_displayQueue.setAutoDelete(true); + m_estateViews.setAutoDelete(true); + m_tokens.setAutoDelete(true); + + displayDefault(); +} + +AtlantikBoard::~AtlantikBoard() +{ + reset(); +} + +void AtlantikBoard::reset() +{ + kdDebug() << "AtlantikBoard::reset" << endl; + + m_tokens.clear(); + m_estateViews.clear(); + m_displayQueue.clear(); + m_lastServerDisplay = 0; + m_movingToken = 0; +} + +void AtlantikBoard::setViewProperties(bool indicateUnowned, bool highliteUnowned, bool darkenMortgaged, bool quartzEffects, bool animateTokens) +{ + if (m_animateTokens != animateTokens) + m_animateTokens = animateTokens; + + // Update EstateViews + EstateView *estateView; + for (QPtrListIterator<EstateView> it(m_estateViews); *it; ++it) + if ((estateView = dynamic_cast<EstateView*>(*it))) + estateView->setViewProperties(indicateUnowned, highliteUnowned, darkenMortgaged, quartzEffects); +} + +int AtlantikBoard::heightForWidth(int width) +{ + return width; +} + +EstateView *AtlantikBoard::findEstateView(Estate *estate) +{ + EstateView *estateView; + for (QPtrListIterator<EstateView> i(m_estateViews); *i; ++i) + { + estateView = dynamic_cast<EstateView*>(*i); + if (estateView && estateView->estate() == estate) + return estateView; + } + return 0; +} + +void AtlantikBoard::addEstateView(Estate *estate, bool indicateUnowned, bool highliteUnowned, bool darkenMortgaged, bool quartzEffects) +{ + QString icon = QString(); + int estateId = estate->id(); + EstateOrientation orientation = North; + int sideLen = m_gridLayout->numRows() - 1; + + if (estateId < sideLen) + orientation = North; + else if (estateId < 2*sideLen) + orientation = East; + else if (estateId < 3*sideLen) + orientation = South; + else //if (estateId < 4*sideLen) + orientation = West; + + EstateView *estateView = new EstateView(estate, orientation, icon, indicateUnowned, highliteUnowned, darkenMortgaged, quartzEffects, this, "estateview"); + m_estateViews.append(estateView); + + connect(estate, SIGNAL(changed()), estateView, SLOT(estateChanged())); + connect(estateView, SIGNAL(estateToggleMortgage(Estate *)), estate, SIGNAL(estateToggleMortgage(Estate *))); + connect(estateView, SIGNAL(LMBClicked(Estate *)), estate, SIGNAL(LMBClicked(Estate *))); + connect(estateView, SIGNAL(estateHouseBuy(Estate *)), estate, SIGNAL(estateHouseBuy(Estate *))); + connect(estateView, SIGNAL(estateHouseSell(Estate *)), estate, SIGNAL(estateHouseSell(Estate *))); + connect(estateView, SIGNAL(newTrade(Player *)), estate, SIGNAL(newTrade(Player *))); + + // Designer has its own LMBClicked slot + if (m_mode == Play) + connect(estateView, SIGNAL(LMBClicked(Estate *)), this, SLOT(prependEstateDetails(Estate *))); + + if (estateId<sideLen) + m_gridLayout->addWidget(estateView, sideLen, sideLen-estateId); + else if (estateId<2*sideLen) + m_gridLayout->addWidget(estateView, 2*sideLen-estateId, 0); + else if (estateId<3*sideLen) + m_gridLayout->addWidget(estateView, 0, estateId-2*sideLen); + else + m_gridLayout->addWidget(estateView, estateId-3*sideLen, sideLen); + + estateView->show(); + + if (m_atlanticCore) + { + Player *player = 0; + QPtrList<Player> playerList = m_atlanticCore->players(); + for (QPtrListIterator<Player> it(playerList); (player = *it) ; ++it) + if (player->location() == estate) + addToken(player); + } +} + +void AtlantikBoard::addAuctionWidget(Auction *auction) +{ + AuctionWidget *auctionW = new AuctionWidget(m_atlanticCore, auction, this); + m_lastServerDisplay = auctionW; + m_displayQueue.prepend(auctionW); + updateCenter(); + + connect(auction, SIGNAL(completed()), this, SLOT(displayDefault())); +} + +Token *AtlantikBoard::findToken(Player *player) +{ + Token *token = 0; + for (QPtrListIterator<Token> it(m_tokens); (token = *it) ; ++it) + if (token->player() == player) + return token; + return 0; +} + +void AtlantikBoard::addToken(Player *player) +{ + if (!player->location()) + { + kdDebug() << "addToken ignored - estateView null" << endl; + return; + } + + Player *playerSelf = 0; + if (m_atlanticCore) + playerSelf = m_atlanticCore->playerSelf(); + + if (playerSelf && playerSelf->game() != player->game() ) + { + kdDebug() << "addToken ignored - not in same game as playerSelf" << endl; + return; + } + + kdDebug() << "addToken" << endl; + + Token *token = new Token(player, this, "token"); + m_tokens.append(token); + connect(player, SIGNAL(changed(Player *)), token, SLOT(playerChanged())); + + jumpToken(token); + + // Timer to reinit the gameboard _after_ event loop + QTimer::singleShot(100, this, SLOT(slotResizeAftermath())); +} + +void AtlantikBoard::playerChanged(Player *player) +{ + kdDebug() << "playerChanged: playerLoc " << (player->location() ? player->location()->name() : "none") << endl; + + Player *playerSelf = 0; + if (m_atlanticCore) + playerSelf = m_atlanticCore->playerSelf(); + + // Update token + Token *token = findToken(player); + if (token) + { + kdDebug() << "playerChanged: tokenLoc " << (token->location() ? token->location()->name() : "none") << endl; + if (player->isBankrupt() || (playerSelf && playerSelf->game() != player->game()) ) + token->hide(); + if (player->hasTurn()) + token->raise(); + + bool jump = false, move = false; + + if (token->inJail() != player->inJail()) + { + token->setInJail(player->inJail()); + + // If any status such as jail is ever allowed to + // change in the future, during movement, this needs + // to be addressed in moveToken and subsequent steps. + if (token != m_movingToken) + jump = true; + } + + if (token->location() != player->location()) + { + token->setLocation(player->location()); + jump = true; + } + + if (player->destination() && token->destination() != player->destination()) + { + if (m_animateTokens) + { + token->setDestination(player->destination()); + move = true; + } + else + { + token->setLocation(player->destination()); + jump = true; + } + } + + if (move) + moveToken(token); + else if (jump) + jumpToken(token); + } + else + addToken(player); +} + +void AtlantikBoard::removeToken(Player *player) +{ + Token *token = findToken(player); + if (!token) + return; + + if (token == m_movingToken) + { + m_timer->stop(); + m_movingToken = 0; + } + + m_tokens.remove(token); +} + +void AtlantikBoard::jumpToken(Token *token) +{ + if (!token || !token->location()) + return; + + kdDebug() << "jumpToken to " << token->location()->name() << endl; + + QPoint tGeom = calculateTokenDestination(token); + token->setGeometry(tGeom.x(), tGeom.y(), token->width(), token->height()); + + Player *player = token->player(); + if (player) + { + player->setLocation(token->location()); + player->setDestination(0); + + if (token->isHidden() && !player->isBankrupt()) + token->show(); + } + + if (token == m_movingToken) + { + m_timer->stop(); + + if (!m_resumeTimer) + m_movingToken = 0; + } + + emit tokenConfirmation(token->location()); +} + +void AtlantikBoard::moveToken(Token *token) +{ + kdDebug() << "moveToken to " << token->destination()->name() << endl; + + m_movingToken = token; + + // Start timer + m_timer->start(15); +} + +QPoint AtlantikBoard::calculateTokenDestination(Token *token, Estate *eDest) +{ + if (!eDest) + eDest = token->location(); + + EstateView *evDest = findEstateView(eDest); + if (!evDest) + return QPoint(0, 0); + + int x = 0, y = 0; + if (token->player()->inJail()) + { + x = evDest->geometry().right() - token->width() - 2; + y = evDest->geometry().top(); + } + else + { + x = evDest->geometry().center().x() - (token->width()/2); + y = evDest->geometry().center().y() - (token->height()/2); + +/* + // Re-center because of EstateView headers + switch(evDest->orientation()) + { + case North: + y += evDest->height()/8; break; + case East: + x -= evDest->width()/8; break; + case South: + y -= evDest->height()/8; break; + case West: + x += evDest->width()/8; break; + } +*/ + } + return QPoint(x, y); +} + +void AtlantikBoard::slotMoveToken() +{ + // Requires a core with estates to operate on + if (!m_atlanticCore) + { + kdDebug() << "slotMoveToken ignored - no atlanticCore" << endl; + return; + } + + // Do we actually have a token to move? + if (!m_movingToken) + { + m_timer->stop(); + return; + } + + // Where are we? + int xCurrent = m_movingToken->geometry().x(); + int yCurrent = m_movingToken->geometry().y(); + + // Where do we want to go today? + Estate *eDest = m_atlanticCore->estateAfter(m_movingToken->location()); + QPoint tGeom = calculateTokenDestination(m_movingToken, eDest); + + int xDest = tGeom.x(); + int yDest = tGeom.y(); + + if (xDest - xCurrent > 1) + xDest = xCurrent + 2; + else if (xCurrent - xDest > 1) + xDest = xCurrent - 2; + else + xDest = xCurrent; + + if (yDest - yCurrent > 1) + yDest = yCurrent + 2; + else if (yCurrent - yDest > 1) + yDest = yCurrent - 2; + else + yDest = yCurrent; + +// kdDebug() << "TOKEN: at " << xCurrent << "," << yCurrent << " and going to " << xDest << "," << yDest << endl; + + if (xCurrent != xDest || yCurrent != yDest) + { + m_movingToken->setGeometry(xDest, yDest, m_movingToken->width(), m_movingToken->height()); + return; + } + + // We have arrived at our destination! + m_movingToken->setLocation(eDest); + m_movingToken->player()->setLocation(eDest); + emit tokenConfirmation(eDest); + + // We have arrived at our _final_ destination! + if (eDest == m_movingToken->destination()) + { + m_movingToken->setDestination(0); + m_movingToken->player()->setDestination(0); + + m_timer->stop(); + m_movingToken = 0; + } +} + +void AtlantikBoard::resizeEvent(QResizeEvent *) +{ + // Stop moving tokens, slotResizeAftermath will re-enable this + if (m_timer!=0 && m_timer->isActive()) + { + m_timer->stop(); + m_resumeTimer=true; + } + +/* + // Adjust spacer to make sure board stays a square + int q = e->size().width() - e->size().height(); + if (q > 0) + { + QSize s(q, 0); + spacer->setFixedSize(s); + } + else + { + QSize s(0, -q); + spacer->setFixedSize(s); + } +*/ + // Timer to reinit the gameboard _after_ resizeEvent + QTimer::singleShot(0, this, SLOT(slotResizeAftermath())); +} + +void AtlantikBoard::slotResizeAftermath() +{ + kdDebug() << "AtlantikBoard::slotResizeAftermath" << endl; + // Move tokens back to their last known location (this has to be done + // _after_ resizeEvent has returned to make sure we have the correct + // adjusted estate geometries. + + Token *token = 0; + for (QPtrListIterator<Token> it(m_tokens); (token = *it) ; ++it) + jumpToken(token); + + // Restart the timer that was stopped in resizeEvent + if (m_resumeTimer && m_timer!=0 && !m_timer->isActive()) + { + m_timer->start(15); + m_resumeTimer=false; + } +} + +void AtlantikBoard::displayDefault() +{ + switch(m_displayQueue.count()) + { + case 0: + m_displayQueue.prepend(new QWidget(this)); + break; + case 1: + if (EstateDetails *display = dynamic_cast<EstateDetails*>(m_lastServerDisplay)) + display->setEstate(0); + break; + default: + if (m_displayQueue.getFirst() == m_lastServerDisplay) + m_lastServerDisplay = 0; + m_displayQueue.removeFirst(); + break; + } + updateCenter(); +} + +void AtlantikBoard::displayButton(QString command, QString caption, bool enabled) +{ + if (EstateDetails *display = dynamic_cast<EstateDetails*>(m_lastServerDisplay)) + display->addButton(command, caption, enabled); +} + +void AtlantikBoard::addCloseButton() +{ + EstateDetails *eDetails = 0; + if ((eDetails = dynamic_cast<EstateDetails*>(m_lastServerDisplay)) && eDetails != m_displayQueue.getLast()) + eDetails->addCloseButton(); +} + +void AtlantikBoard::insertDetails(QString text, bool clearText, bool clearButtons, Estate *estate) +{ + EstateDetails *eDetails = 0; + + if ((eDetails = dynamic_cast<EstateDetails*>(m_lastServerDisplay))) + { + if (clearText) + eDetails->setText(text); + else + eDetails->appendText(text); + + if (clearButtons) + eDetails->clearButtons(); + + eDetails->setEstate(estate); + return; + } + + if (m_displayQueue.getFirst() != m_lastServerDisplay) + m_displayQueue.removeFirst(); + + eDetails = new EstateDetails(estate, text, this); + m_lastServerDisplay = eDetails; + connect(eDetails, SIGNAL(buttonCommand(QString)), this, SIGNAL(buttonCommand(QString))); + connect(eDetails, SIGNAL(buttonClose()), this, SLOT(displayDefault())); + + m_displayQueue.insert(0, eDetails); + updateCenter(); +} + +void AtlantikBoard::prependEstateDetails(Estate *estate) +{ + if (!estate) + return; + + EstateDetails *eDetails = 0; + + if (m_displayQueue.getFirst() == m_lastServerDisplay) + { + eDetails = new EstateDetails(estate, QString::null, this); + m_displayQueue.prepend(eDetails); + + connect(eDetails, SIGNAL(buttonCommand(QString)), this, SIGNAL(buttonCommand(QString))); + connect(eDetails, SIGNAL(buttonClose()), this, SLOT(displayDefault())); + } + else + { + eDetails = dynamic_cast<EstateDetails*> ( m_displayQueue.getFirst() ); + if (eDetails) + { + eDetails->setEstate(estate); + eDetails->setText( QString::null ); + // eDetails->clearButtons(); + } + else + { + kdDebug() << "manual estatedetails with first in queue neither server nor details" << endl; + return; + } + } + + eDetails->addDetails(); + eDetails->addCloseButton(); + + updateCenter(); +} + +void AtlantikBoard::updateCenter() +{ + QWidget *center = m_displayQueue.getFirst(); + m_gridLayout->addMultiCellWidget(center, 1, m_gridLayout->numRows()-2, 1, m_gridLayout->numCols()-2); + center->show(); +} + +QWidget *AtlantikBoard::centerWidget() +{ + return m_displayQueue.getFirst(); +} diff --git a/atlantik/libatlantikui/board.h b/atlantik/libatlantikui/board.h new file mode 100644 index 00000000..deedb3d6 --- /dev/null +++ b/atlantik/libatlantikui/board.h @@ -0,0 +1,102 @@ +// Copyright (c) 2002-2003 Rob Kaper <[email protected]> +// +// 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_BOARD_H +#define ATLANTIK_BOARD_H + +#include <qwidget.h> +#include <qtimer.h> +#include <qlayout.h> +#include <qptrlist.h> +#include "libatlantikui_export.h" +class QPoint; + +class AtlanticCore; +class Auction; +class Estate; +class Player; +class Token; + +class EstateView; + +class LIBATLANTIKUI_EXPORT AtlantikBoard : public QWidget +{ +Q_OBJECT + +public: + enum DisplayMode { Play, Edit }; + + AtlantikBoard(AtlanticCore *atlanticCore, int maxEstates, DisplayMode mode, QWidget *parent, const char *name=0); + ~AtlantikBoard(); + void reset(); + + void setViewProperties(bool indicateUnowned, bool highliteUnowned, bool darkenMortgaged, bool quartzEffects, bool animateTokens); + int heightForWidth(int); + void addEstateView(Estate *estate, bool indicateUnowned = false, bool highliteUnowned = false, bool darkenMortgaged = false, bool quartzEffects = false); + void addAuctionWidget(Auction *auction); + + void addToken(Player *player); + void removeToken(Player *player); + + void indicateUnownedChanged(); + EstateView *findEstateView(Estate *estate); + QWidget *centerWidget(); + +public slots: + void slotMoveToken(); + void slotResizeAftermath(); + void displayDefault(); + +private slots: + void playerChanged(Player *player); + void displayButton(QString command, QString caption, bool enabled); + void prependEstateDetails(Estate *); + void insertDetails(QString text, bool clearText, bool clearButtons, Estate *estate = 0); + void addCloseButton(); + +signals: + void tokenConfirmation(Estate *estate); + void buttonCommand(QString command); + +protected: + void resizeEvent(QResizeEvent *); + +private: + Token *findToken(Player *player); + void jumpToken(Token *token); + void moveToken(Token *token); + QPoint calculateTokenDestination(Token *token, Estate *estate = 0); + + void updateCenter(); + + AtlanticCore *m_atlanticCore; + DisplayMode m_mode; + + QWidget *spacer, *m_lastServerDisplay; + QGridLayout *m_gridLayout; + Token *m_movingToken; + QTimer *m_timer; + bool m_resumeTimer; + + bool m_animateTokens; + int m_maxEstates; + + QPtrList<EstateView> m_estateViews; + QPtrList<Token> m_tokens; + QPtrList<QWidget> m_displayQueue; +}; + +#endif diff --git a/atlantik/libatlantikui/estatedetails.cpp b/atlantik/libatlantikui/estatedetails.cpp new file mode 100644 index 00000000..d143033c --- /dev/null +++ b/atlantik/libatlantikui/estatedetails.cpp @@ -0,0 +1,327 @@ +// Copyright (c) 2002-2004 Rob Kaper <[email protected]> +// +// 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 <qpainter.h> +#include <qpixmap.h> +#include <qlayout.h> +#include <qptrlist.h> +#include <qregexp.h> +#include <qvgroupbox.h> + +#include <kdialog.h> +#include <kglobalsettings.h> +#include <kiconloader.h> +#include <klistview.h> +#include <klocale.h> +#include <kpixmap.h> +#include <kpushbutton.h> +#include <kstdguiitem.h> + +#include <kdebug.h> + +#include <estate.h> +#include <estategroup.h> +#include <player.h> + +#include "estatedetails.h" +#include "kwrappedlistviewitem.h" + +EstateDetails::EstateDetails(Estate *estate, QString text, QWidget *parent, const char *name) : QWidget(parent, name) +{ + m_pixmap = 0; + m_quartzBlocks = 0; + b_recreate = true; + m_recreateQuartz = true; + + m_estate = 0; + + m_closeButton = 0; + m_buttons.setAutoDelete(true); + + m_mainLayout = new QVBoxLayout(this, KDialog::marginHint(), KDialog::spacingHint()); + Q_CHECK_PTR(m_mainLayout); + + m_mainLayout->addItem(new QSpacerItem(KDialog::spacingHint(), KDialog::spacingHint()+50, QSizePolicy::Fixed, QSizePolicy::Minimum)); + + m_infoListView = new KListView(this, "infoListView"); + m_infoListView->addColumn(m_estate ? m_estate->name() : QString("") ); + m_infoListView->setSorting(-1); + m_mainLayout->addWidget(m_infoListView); + + appendText(text); + + m_buttonBox = new QHBoxLayout(m_mainLayout, KDialog::spacingHint()); + m_buttonBox->setMargin(0); + + m_buttonBox->addItem(new QSpacerItem(20, 20, QSizePolicy::Expanding, QSizePolicy::Minimum)); + + setEstate(estate); +} + +EstateDetails::~EstateDetails() +{ + delete m_pixmap; + delete m_quartzBlocks; + delete m_infoListView; +} + +void EstateDetails::paintEvent(QPaintEvent *) +{ + if (m_recreateQuartz) + { +/* + if (m_quartzBlocks) + { + delete m_quartzBlocks; + m_quartzBlocks = 0; + } + + if (m_estate->color().isValid()) + { + m_quartzBlocks = new KPixmap(); + + if (m_orientation == North || m_orientation == South) + m_quartzBlocks->resize(25, m_titleHeight-2); + else + m_quartzBlocks->resize(25, m_titleWidth-2); + + drawQuartzBlocks(m_quartzBlocks, *m_quartzBlocks, m_estate->color().light(60), m_estate->color()); + m_quartzBlocks = rotatePixmap(m_quartzBlocks); + } +*/ + m_recreateQuartz = false; + b_recreate = true; + } + + if (b_recreate) + { + delete m_pixmap; + m_pixmap = new QPixmap(width(), height()); + + QColor greenHouse(0, 255, 0); + QColor redHotel(255, 51, 51); + QPainter painter; + painter.begin(m_pixmap, this); + + painter.setPen(Qt::black); + + painter.setBrush(m_estate ? m_estate->bgColor() : Qt::white); + painter.drawRect(rect()); + +/* + // Paint icon only when it exists and fits + if (icon!=0 && width() > icon->width() && height() > icon->height()) + painter.drawPixmap( (width() - icon->width())/2, (height() - icon->height())/2, *icon); +*/ + + if (m_estate) + { + int titleHeight = 50; + QColor titleColor = (m_estate->color().isValid() ? m_estate->color() : m_estate->bgColor().light(80)); + + KPixmap* quartzBuffer = new KPixmap; + quartzBuffer->resize(25, (height()/4)-2); + + QPainter quartzPainter; + quartzPainter.begin(quartzBuffer, this); + + painter.setBrush(titleColor); + painter.drawRect(0, 0, width(), titleHeight); + + if (m_quartzBlocks) + { + quartzPainter.drawPixmap(0, 0, *m_quartzBlocks); + painter.drawPixmap(1, 1, *quartzBuffer); + } + + if (m_estate->houses() > 0) + { + int titleWidth = width() / 5; + + if (m_estate->houses() == 5) + { + // Hotel + painter.setBrush(redHotel); + painter.drawRect(2, 2, titleWidth-4, titleHeight-4); + } + else + { + // Houses + painter.setBrush(greenHouse); + int h = titleHeight-4, w = titleWidth-4; + for ( unsigned int i=0 ; i < m_estate->houses() ; i++ ) + painter.drawRect(2+(i*(w+2)), 2, w, h); + } + } + + quartzPainter.end(); + delete quartzBuffer; + + // TODO: steal blur code from kicker/taskbar/taskcontainer.cpp + + // Estate name + painter.setPen(Qt::white); + int fontSize = KGlobalSettings::generalFont().pointSize(); + if (fontSize == -1) + fontSize = KGlobalSettings::generalFont().pixelSize(); + + painter.setFont(QFont(KGlobalSettings::generalFont().family(), fontSize * 2, QFont::Bold)); + painter.drawText(KDialog::marginHint(), KDialog::marginHint(), width()-KDialog::marginHint(), titleHeight, Qt::AlignJustify, m_estate->name()); + + painter.setPen(Qt::black); + + int xText = 0; + + // Estate group + if (m_estate->estateGroup()) + { + xText = titleHeight - fontSize - KDialog::marginHint(); + painter.setFont(QFont(KGlobalSettings::generalFont().family(), fontSize, QFont::Bold)); + painter.drawText(5, xText, width()-10, titleHeight, Qt::AlignRight, m_estate->estateGroup()->name().upper()); + } + + xText = titleHeight + fontSize + 5; + painter.setFont(QFont(KGlobalSettings::generalFont().family(), fontSize, QFont::Normal)); + } + b_recreate = false; + + } + bitBlt(this, 0, 0, m_pixmap); +} + +void EstateDetails::resizeEvent(QResizeEvent *) +{ + m_recreateQuartz = true; + b_recreate = true; +} + +void EstateDetails::addDetails() +{ + if (m_estate) + { + QListViewItem *infoText = 0; + + // Price + if (m_estate->price()) + { + infoText = new QListViewItem(m_infoListView, m_infoListView->lastItem(), i18n("Price: %1").arg(m_estate->price())); + infoText->setPixmap(0, QPixmap(SmallIcon("info"))); + } + + // Owner, houses, isMortgaged + if (m_estate && m_estate->canBeOwned()) + { + infoText = new QListViewItem(m_infoListView, m_infoListView->lastItem(), i18n("Owner: %1").arg(m_estate->owner() ? m_estate->owner()->name() : i18n("unowned"))); + infoText->setPixmap(0, QPixmap(SmallIcon("info"))); + + if (m_estate->isOwned()) + { + infoText = new QListViewItem(m_infoListView, m_infoListView->lastItem(), i18n("Houses: %1").arg(m_estate->houses())); + infoText->setPixmap(0, QPixmap(SmallIcon("info"))); + + infoText = new QListViewItem(m_infoListView, m_infoListView->lastItem(), i18n("Mortgaged: %1").arg(m_estate->isMortgaged() ? i18n("Yes") : i18n("No"))); + infoText->setPixmap(0, QPixmap(SmallIcon("info"))); + } + } + } +} + +void EstateDetails::addButton(QString command, QString caption, bool enabled) +{ + KPushButton *button = new KPushButton(caption, this); + m_buttons.append(button); + m_buttonCommandMap[(QObject *)button] = command; + m_buttonBox->addWidget(button); + + if (m_estate) + { + QColor bgColor, fgColor; + bgColor = m_estate->bgColor().light(110); + fgColor = ( bgColor.red() + bgColor.green() + bgColor.blue() < 255 ) ? Qt::white : Qt::black; + + button->setPaletteForegroundColor( fgColor ); + button->setPaletteBackgroundColor( bgColor ); + } + button->setEnabled(enabled); + button->show(); + + connect(button, SIGNAL(pressed()), this, SLOT(buttonPressed())); +} + +void EstateDetails::addCloseButton() +{ + if (!m_closeButton) + { + m_closeButton = new KPushButton(KStdGuiItem::close(), this); + m_buttonBox->addWidget(m_closeButton); + m_closeButton->show(); + connect(m_closeButton, SIGNAL(pressed()), this, SIGNAL(buttonClose())); + } +} + +void EstateDetails::setEstate(Estate *estate) +{ + if (m_estate != estate) + { + m_estate = estate; + + m_infoListView->setColumnText( 0, m_estate ? m_estate->name() : QString("") ); + + b_recreate = true; + update(); + } +} + +void EstateDetails::setText(QString text) +{ + m_infoListView->clear(); + appendText(text); +} + +void EstateDetails::appendText(QString text) +{ + if ( text.isEmpty() ) + return; + + KWrappedListViewItem *infoText = new KWrappedListViewItem(m_infoListView, m_infoListView->lastItem(), text); + + if ( text.find( QRegExp("rolls") ) != -1 ) + infoText->setPixmap(0, QPixmap(SmallIcon("roll"))); + else + infoText->setPixmap(0, QPixmap(SmallIcon("atlantik"))); + + m_infoListView->ensureItemVisible( infoText ); +} + +void EstateDetails::clearButtons() +{ + if (m_closeButton) + { + delete m_closeButton; + m_closeButton = 0; + } + + // Delete buttons + m_buttons.clear(); + m_buttonCommandMap.clear(); +} + +void EstateDetails::buttonPressed() +{ + emit buttonCommand(QString(m_buttonCommandMap[(QObject *)QObject::sender()])); +} + +#include "estatedetails.moc" diff --git a/atlantik/libatlantikui/estatedetails.h b/atlantik/libatlantikui/estatedetails.h new file mode 100644 index 00000000..b8264a51 --- /dev/null +++ b/atlantik/libatlantikui/estatedetails.h @@ -0,0 +1,77 @@ +// Copyright (c) 2002 Rob Kaper <[email protected]> +// +// 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_ESTATEDETAILS_H +#define ATLANTIK_ESTATEDETAILS_H + +#include <qwidget.h> + +class QPixmap; +class QString; +class QHBoxLayout; +class QVBoxLayout; +class QVGroupBox; + +class KListView; +class KPixmap; +class KPushButton; + +class Player; +class Estate; + +class EstateDetails : public QWidget +{ +Q_OBJECT + +public: + EstateDetails(Estate *estate, QString text, QWidget *parent, const char *name = 0); + ~EstateDetails(); + Estate *estate() { return m_estate; } + + void addDetails(); + void addButton(const QString command, const QString caption, bool enabled); + void addCloseButton(); + void setEstate(Estate *estate); + void setText(QString text); + void appendText(QString text); + void clearButtons(); + +protected: + void paintEvent(QPaintEvent *); + void resizeEvent(QResizeEvent *); + +private slots: + void buttonPressed(); + +signals: + void buttonCommand(QString); + void buttonClose(); + +private: + Estate *m_estate; + QPixmap *m_pixmap; + KPixmap *m_quartzBlocks; + KListView *m_infoListView; + KPushButton *m_closeButton; + bool b_recreate, m_recreateQuartz; + QVBoxLayout *m_mainLayout; + QHBoxLayout *m_buttonBox; + QVGroupBox *m_textGroupBox; + QMap <QObject *, QString> m_buttonCommandMap; + QPtrList<KPushButton> m_buttons; +}; + +#endif diff --git a/atlantik/libatlantikui/estateview.cpp b/atlantik/libatlantikui/estateview.cpp new file mode 100644 index 00000000..b8c3f38c --- /dev/null +++ b/atlantik/libatlantikui/estateview.cpp @@ -0,0 +1,558 @@ +// Copyright (c) 2002-2003 Rob Kaper <[email protected]> +// +// 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 <qtooltip.h> +#include <qpainter.h> +#include <qtimer.h> +#include <qwmatrix.h> +#include <qcursor.h> + +#include <kdebug.h> +#include <kdeversion.h> +#include <kdialogbase.h> +#include <kglobalsettings.h> +#include <klocale.h> +#include <kpixmapeffect.h> +#include <kpopupmenu.h> +#include <kstandarddirs.h> +#include <kstringhandler.h> + +#include <player.h> +#include <estate.h> + +#include "estateview.moc" +#include "config.h" + +EstateView::EstateView(Estate *estate, EstateOrientation orientation, const QString &_icon, bool indicateUnowned, bool highliteUnowned, bool darkenMortgaged, bool quartzEffects, QWidget *parent, const char *name) : QWidget(parent, name, WResizeNoErase) +{ + m_estate = estate; + m_orientation = orientation; + + m_indicateUnowned = indicateUnowned; + m_highliteUnowned = highliteUnowned; + m_darkenMortgaged = darkenMortgaged; + m_quartzEffects = quartzEffects; + + setBackgroundMode(NoBackground); // avoid flickering + + qpixmap = 0; + b_recreate = true; + + m_quartzBlocks = 0; + m_recreateQuartz = true; + + pe = 0; + updatePE(); + + icon = new QPixmap(locate("data", "atlantik/pics/" + _icon)); + icon = rotatePixmap(icon); + + updateToolTip(); +} + +void EstateView::updateToolTip() +{ + QToolTip::remove(this); + + if ( m_estate ) + { + QString toolTip = m_estate->name(); + if ( m_estate->isOwned() ) + { + toolTip.append( "\n" + i18n("Owner: %1").arg( m_estate->owner()->name() ) ); + if ( m_estate->isMortgaged() ) + toolTip.append( "\n" + i18n("Unmortgage Price: %1").arg( m_estate->unmortgagePrice() ) ); + else + toolTip.append( "\n" + i18n("Mortgage Value: %1").arg( m_estate->mortgagePrice() ) ); + if ( m_estate->canSellHouses() ) + toolTip.append( "\n" + i18n("House Value: %1").arg( m_estate->houseSellPrice() ) ); + if ( m_estate->canBuyHouses() ) + toolTip.append( "\n" + i18n("House Price: %1").arg( m_estate->housePrice() ) ); + } + else if ( m_estate->canBeOwned() ) + toolTip.append( "\n" + i18n("Price: %1").arg( m_estate->price() ) ); + else if ( m_estate->money() ) + toolTip.append( "\n" + i18n("Money: %1").arg( m_estate->money() ) ); + + QToolTip::add( this, toolTip ); + } +} + +void EstateView::setViewProperties(bool indicateUnowned, bool highliteUnowned, bool darkenMortgaged, bool quartzEffects) +{ + if (m_indicateUnowned != indicateUnowned) + { + m_indicateUnowned = indicateUnowned; + b_recreate = true; + updatePE(); + } + + if (m_highliteUnowned != highliteUnowned) + { + m_highliteUnowned = highliteUnowned; + b_recreate = true; + } + + if (m_darkenMortgaged != darkenMortgaged) + { + m_darkenMortgaged = darkenMortgaged; + b_recreate = true; + } + + if (m_quartzEffects != quartzEffects) + { + m_quartzEffects = quartzEffects; + b_recreate = true; +// m_recreateQuartz = true; + } + + if (b_recreate || m_recreateQuartz) + update(); +} + +QPixmap *EstateView::rotatePixmap(QPixmap *p) +{ + if (p==0 || p->isNull()) + return 0; + + QWMatrix m; + + switch(m_orientation) + { + case East: + m.rotate(90); + break; + case West: + m.rotate(-90); + break; + case South: + m.rotate(180); + break; + default:; + } + *p = p->xForm(m); + return p; +} + +KPixmap *EstateView::rotatePixmap(KPixmap *p) +{ + if (p==0 || p->isNull()) + return 0; + + QWMatrix m; + + switch(m_orientation) + { + case East: + m.rotate(90); + break; + case West: + m.rotate(-90); + break; + case South: + m.rotate(180); + break; + default:; + } + *p = p->xForm(m); + return p; +} + +void EstateView::updatePE() +{ + // Don't show a when a property is not unowned, cannot be owned at all + // or when the user has configured Atlantik not to show them. + if (m_estate->isOwned() || !m_estate->canBeOwned() || m_indicateUnowned==false) + { + delete pe; + pe = 0; + } + else + { + if (pe==0) + { + // Display a coloured portfolioestate to indicate property is + // for sale + pe = new PortfolioEstate(m_estate, 0, true, this, "board-portfolioestate"); + repositionPortfolioEstate(); + + pe->show(); + } + else if (!pe->isVisible()) + pe->show(); + } +} + +void EstateView::estateChanged() +{ + updateToolTip(); + + b_recreate = true; + m_recreateQuartz = true; + + update(); + updatePE(); +} + +void EstateView::repositionPortfolioEstate() +{ + if (pe!=0) + { + int x = (m_orientation == West ? (width()-2 - pe->width()) : 2); + int y = (m_orientation == North ? (height()-2 - pe->height()) : 2); + pe->setGeometry(x, y, pe->width(), pe->height()); + } +} + +void EstateView::paintEvent(QPaintEvent *) +{ + m_titleHeight = height()/4; + m_titleWidth = width()/4; + + if (m_recreateQuartz) + { + if (m_quartzBlocks) + { + delete m_quartzBlocks; + m_quartzBlocks = 0; + } + + if (m_estate->color().isValid()) + { + m_quartzBlocks = new KPixmap(); + + if (m_orientation == North || m_orientation == South) + m_quartzBlocks->resize(25, m_titleHeight-2); + else + m_quartzBlocks->resize(25, m_titleWidth-2); + + drawQuartzBlocks(m_quartzBlocks, *m_quartzBlocks, m_estate->color().light(60), m_estate->color()); + m_quartzBlocks = rotatePixmap(m_quartzBlocks); + } + + m_recreateQuartz = false; + b_recreate = true; + } + + if (b_recreate) + { + delete qpixmap; + qpixmap = new QPixmap(width(), height()); + + QColor greenHouse(0, 255, 0); + QColor redHotel(255, 51, 51); + QPainter painter; + painter.begin(qpixmap, this); + + painter.setPen(Qt::black); + + if (m_darkenMortgaged==true && m_estate->isMortgaged()) + painter.setBrush(m_estate->bgColor().light(10)); + else if (m_highliteUnowned==true && m_estate->canBeOwned() && !m_estate->isOwned()) + painter.setBrush(m_estate->bgColor().light(190)); + else + painter.setBrush(m_estate->bgColor()); + + painter.drawRect(rect()); + + // Paint icon only when it exists and fits + if (icon!=0 && width() > icon->width() && height() > icon->height()) + painter.drawPixmap( (width() - icon->width())/2, (height() - icon->height())/2, *icon); + + if (m_estate->color().isValid()) + { + KPixmap* quartzBuffer = new KPixmap; + if (m_orientation == North || m_orientation == South) + quartzBuffer->resize(25, m_titleHeight-2); + else + quartzBuffer->resize(m_titleWidth-2, 25); + + QPainter quartzPainter; + quartzPainter.begin(quartzBuffer, this); + + painter.setBrush(m_estate->color()); + switch(m_orientation) + { + case North: + painter.drawRect(0, 0, width(), m_titleHeight); + + if (m_quartzEffects && m_quartzBlocks) + { + quartzPainter.drawPixmap(0, 0, *m_quartzBlocks); + painter.drawPixmap(1, 1, *quartzBuffer); + } + + if (m_estate->houses() > 0) + { + if (m_estate->houses() == 5) + { + // Hotel + painter.setBrush(redHotel); + painter.drawRect(2, 2, (width()/2)-4, (m_titleHeight)-4); + } + else + { + // Houses + painter.setBrush(greenHouse); + int h = (m_titleHeight)-4, w = (m_titleWidth)-4; + for( unsigned int i=0 ; i < m_estate->houses() ; i++ ) + painter.drawRect(2+(i*(w+2)), 2, w, h); + } + } + break; + case South: + painter.drawRect(0, height()-(m_titleHeight), width(), m_titleHeight); + + if (m_quartzEffects && m_quartzBlocks) + { + quartzPainter.drawPixmap(0, 0, *m_quartzBlocks); + painter.drawPixmap(width()-quartzBuffer->width()-1, height()-m_titleHeight+1, *quartzBuffer); + } + + if (m_estate->houses() > 0) + { + if (m_estate->houses() == 5) + { + // Hotel + painter.setBrush(redHotel); + painter.drawRect(2, (3*(m_titleHeight))+2, (width()/2)-4, (m_titleHeight)-4); + } + else + { + // Houses + painter.setBrush(greenHouse); + int h = (m_titleHeight)-4, w = (m_titleWidth)-4; + for( unsigned int i=0 ; i < m_estate->houses() ; i++ ) + painter.drawRect(2+(i*(w+2)), (3*(m_titleHeight))+2, w, h); + } + } + break; + case West: + painter.drawRect(0, 0, m_titleWidth, height()); + + if (m_quartzEffects && m_quartzBlocks) + { + quartzPainter.drawPixmap(0, 0, *m_quartzBlocks); + painter.drawPixmap(1, height()-quartzBuffer->height()-1, *quartzBuffer); + } + + if (m_estate->houses() > 0) + { + if (m_estate->houses() == 5) + { + // Hotel + painter.setBrush(redHotel); + painter.drawRect(2, 2, (m_titleWidth)-4, (height()/2)-4); + } + else + { + // Houses + painter.setBrush(greenHouse); + int h = (m_titleHeight)-4, w = (m_titleWidth)-4; + for( unsigned int i=0 ; i < m_estate->houses() ; i++ ) + painter.drawRect(2, 2+(i*(h+2)), w, h); + } + } + break; + case East: + painter.drawRect(width()-(m_titleWidth), 0, m_titleWidth, height()); + + if (m_quartzEffects && m_quartzBlocks) + { + quartzPainter.drawPixmap(0, 0, *m_quartzBlocks); + painter.drawPixmap(width()-quartzBuffer->width()-1, 1, *quartzBuffer); + } + + if (m_estate->houses() > 0) + { + if (m_estate->houses() == 5) + { + // Hotel + painter.setBrush(redHotel); + painter.drawRect((3*(m_titleWidth))+2, 2, (m_titleWidth)-4, (height()/2)-4); + } + else + { + // Houses + painter.setBrush(greenHouse); + int h = (m_titleHeight)-4, w = (m_titleWidth)-4; + for( unsigned int i=0 ; i < m_estate->houses() ; i++ ) + painter.drawRect((3*(m_titleWidth))+2, 2+(i*(h+2)), w, h); + } + } + break; + } + + + quartzPainter.end(); + delete quartzBuffer; + } + + QFont font = QFont( KGlobalSettings::generalFont().family(), KGlobalSettings::generalFont().pointSize(), QFont::Normal ); + painter.setFont(font); + QString estateName = m_estate->name(); +#if defined(KDE_MAKE_VERSION) +#if KDE_VERSION >= KDE_MAKE_VERSION(3,2,0) + if ( m_estate->color().isValid() && ( m_orientation == West || m_orientation == East ) ) + estateName = KStringHandler::rPixelSqueeze( m_estate->name(), QFontMetrics( font ), 3*width()/4 ); + else + estateName = KStringHandler::rPixelSqueeze( m_estate->name(), QFontMetrics( font ), width() ); +#endif +#endif + if (m_estate->color().isValid() && m_orientation == West) + painter.drawText( width()/4 + 2, height()/2, estateName ); + else + painter.drawText(2, height()/2, estateName ); + + b_recreate = false; + } + bitBlt(this, 0, 0, qpixmap); +} + +void EstateView::resizeEvent(QResizeEvent *) +{ + m_recreateQuartz = true; + b_recreate = true; + + QTimer::singleShot(0, this, SLOT(slotResizeAftermath())); +} + +void EstateView::mousePressEvent(QMouseEvent *e) +{ + if (e->button()==RightButton && m_estate->isOwned()) + { + KPopupMenu *rmbMenu = new KPopupMenu(this); + rmbMenu->insertTitle(m_estate->name()); + + if (m_estate->isOwnedBySelf()) + { + Player *player = m_estate->owner(); + + // Mortgage toggle + if (m_estate->isMortgaged()) + { + rmbMenu->insertItem(i18n("Unmortgage"), 0); + if (!m_estate->canToggleMortgage() || player->hasDebt()) + rmbMenu->setItemEnabled(0, false); + } + else + { + rmbMenu->insertItem(i18n("Mortgage"), 0); + if (!m_estate->canToggleMortgage()) + rmbMenu->setItemEnabled(0, false); + } + + // Estate construction + if (m_estate->houses()>=4) + rmbMenu->insertItem(i18n("Build Hotel"), 1); + else + rmbMenu->insertItem(i18n("Build House"), 1); + + if (!m_estate->canBuyHouses() || player->hasDebt()) + rmbMenu->setItemEnabled(1, false); + + // Estate destruction + if (m_estate->houses()==5) + rmbMenu->insertItem(i18n("Sell Hotel"), 2); + else + rmbMenu->insertItem(i18n("Sell House"), 2); + + if (!(m_estate->canSellHouses())) + rmbMenu->setItemEnabled(2, false); + } + else + { + // Request trade + if (Player *player = m_estate->owner()) + rmbMenu->insertItem(i18n("Request Trade with %1").arg(player->name()), 3); + } + + KPopupMenu *pm = dynamic_cast<KPopupMenu *>(rmbMenu); + if (pm) { + connect(pm, SIGNAL(activated(int)), this, SLOT(slotMenuAction(int))); + } + QPoint g = QCursor::pos(); + rmbMenu->exec(g); + delete rmbMenu; + } + else if (e->button()==LeftButton) + emit LMBClicked(m_estate); +} + +void EstateView::slotResizeAftermath() +{ + repositionPortfolioEstate(); +} + +void EstateView::slotMenuAction(int item) +{ + switch (item) + { + case 0: + emit estateToggleMortgage(m_estate); + break; + + case 1: + emit estateHouseBuy(m_estate); + break; + + case 2: + emit estateHouseSell(m_estate); + break; + + case 3: + emit newTrade(m_estate->owner()); + break; + } +} + +// Kudos to Gallium <[email protected]> for writing the Quartz KWin style and +// letting me use the ultra slick algorithm! +void EstateView::drawQuartzBlocks(KPixmap *pi, KPixmap &p, const QColor &c1, const QColor &c2) +{ + QPainter px; + + if (pi==0 || pi->isNull()) + return; + + px.begin(pi); + + KPixmapEffect::gradient(p, c1, c2, KPixmapEffect::HorizontalGradient); + + px.fillRect( 2, 1, 3, 3, c1.light(120) ); + px.fillRect( 2, 5, 3, 3, c1 ); + px.fillRect( 2, 9, 3, 3, c1.light(110) ); + px.fillRect( 2, 13, 3, 3, c1 ); + + px.fillRect( 6, 1, 3, 3, c1.light(110) ); + px.fillRect( 6, 5, 3, 3, c2.light(110) ); + px.fillRect( 6, 9, 3, 3, c1.light(120) ); + px.fillRect( 6, 13, 3, 3, c2.light(130) ); + + px.fillRect( 10, 5, 3, 3, c1.light(110) ); + px.fillRect( 10, 9, 3, 3, c2.light(120) ); + px.fillRect( 10, 13, 3, 3, c2.light(150) ); + + px.fillRect( 14, 1, 3, 3, c1.dark(110) ); + px.fillRect( 14, 9, 3, 3, c2.light(120) ); + px.fillRect( 14, 13, 3, 3, c1.dark(120) ); + + px.fillRect( 18, 5, 3, 3, c1.light(110) ); + px.fillRect( 18, 13, 3, 3, c1.dark(110) ); + + px.fillRect( 22, 9, 3, 3, c2.light(120)); + px.fillRect( 22, 13, 3, 3, c2.light(110) ); +} diff --git a/atlantik/libatlantikui/estateview.h b/atlantik/libatlantikui/estateview.h new file mode 100644 index 00000000..864c8983 --- /dev/null +++ b/atlantik/libatlantikui/estateview.h @@ -0,0 +1,80 @@ +// Copyright (c) 2002-2003 Rob Kaper <[email protected]> +// +// 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_ESTATEVIEW_H +#define ATLANTIK_ESTATEVIEW_H + +#include <qwidget.h> +#include <qpixmap.h> + +#include <kpixmap.h> + +#include "portfolioestate.h" + +enum EstateOrientation { North=0, East=1, South=2, West=3 }; + +class Player; +class Estate; + +class EstateView : public QWidget +{ +Q_OBJECT + + public: + EstateView(Estate *estate, EstateOrientation orientation, const QString &, bool indicateUnowned, bool highliteUnowned, bool darkenMortgaged, bool quartzEffects, QWidget *parent, const char *name = 0); + void setViewProperties(bool indicateUnowned, bool highliteUnowned, bool darkenMortgaged, bool quartzEffects); + Estate *estate() { return m_estate; } + void updatePE(); + EstateOrientation orientation() { return m_orientation; } + + public slots: + void slotResizeAftermath(); + + signals: + void estateToggleMortgage(Estate *estate); + void estateHouseBuy(Estate *estate); + void estateHouseSell(Estate *estate); + void newTrade(Player *player); + void LMBClicked(Estate *estate); + + protected: + void paintEvent(QPaintEvent *); + void resizeEvent(QResizeEvent *); + void mousePressEvent(QMouseEvent *); + +private: + void updateToolTip(); + + QPixmap *rotatePixmap(QPixmap *); + KPixmap *rotatePixmap(KPixmap *); + void drawQuartzBlocks(KPixmap *pi, KPixmap &p, const QColor &c1, const QColor &c2); + void repositionPortfolioEstate(); + + Estate *m_estate; + QPixmap *qpixmap, *icon; + KPixmap *m_quartzBlocks; + bool m_indicateUnowned, m_highliteUnowned, m_darkenMortgaged, m_quartzEffects; + bool b_recreate, m_recreateQuartz; + int m_titleWidth, m_titleHeight; + EstateOrientation m_orientation; + PortfolioEstate *pe; + + private slots: + void slotMenuAction(int); + void estateChanged(); +}; + +#endif diff --git a/atlantik/libatlantikui/kwrappedlistviewitem.cpp b/atlantik/libatlantikui/kwrappedlistviewitem.cpp new file mode 100644 index 00000000..7bd9e2cf --- /dev/null +++ b/atlantik/libatlantikui/kwrappedlistviewitem.cpp @@ -0,0 +1,116 @@ +// Copyright (c) 2004 Rob Kaper <[email protected]>. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS `AS IS'' AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +// SUCH DAMAGE. + +#include <qheader.h> +#include <qstring.h> + +#include <kglobalsettings.h> +#include <klistview.h> +#include <kwordwrap.h> + +#include "kwrappedlistviewitem.h" + +KWrappedListViewItem::KWrappedListViewItem( QListView *parent, QString text, QString t2 ) +: QObject(), KListViewItem( parent ) +{ + init( parent, text, t2 ); +} + +KWrappedListViewItem::KWrappedListViewItem( QListView *parent, QListViewItem *after, QString text, QString t2 ) +: QObject(), KListViewItem( parent, after ) +{ + init( parent, text, t2 ); +} + +void KWrappedListViewItem::setup() +{ + widthChanged(); +} + +/* +int KWrappedListViewItem::width( const QFontMetrics&, const QListView*, int ) const +{ + return m_wrap->boundingRect().width(); +} +*/ + +void KWrappedListViewItem::wrapColumn( int c ) +{ + if ( c != m_wrapColumn ) + return; + + QListView *lv = listView(); + if ( !lv ) + return; + + QFont font = QFont( KGlobalSettings::generalFont().family(), KGlobalSettings::generalFont().pointSize(), QFont::Normal ); + QFontMetrics fm = QFontMetrics( font ); + + int wrapWidth = lv->width(); + for ( int i = 0 ; i < m_wrapColumn ; i++ ) + wrapWidth -= ( width(fm, lv, i) + lv->itemMargin() ); + + if ( pixmap(c) ) + wrapWidth -= ( pixmap( c )->width() + lv->itemMargin() ); + + QScrollBar *scrollBar = lv->verticalScrollBar(); + if ( !scrollBar->isHidden() ) + wrapWidth -= scrollBar->width(); + + QRect rect = QRect( 0, 0, wrapWidth - 20, -1 ); + + KWordWrap *wrap = KWordWrap::formatText( fm, rect, 0, m_origText ); + setText( c, wrap->wrappedString() ); + + int lc = text(c).contains( QChar( '\n' ) ) + 1; + setHeight( wrap->boundingRect().height() + lc*lv->itemMargin() ); + + widthChanged( c ); + + delete wrap; +} + +void KWrappedListViewItem::init( QListView *parent, QString text, QString t2 ) +{ + m_wrapColumn = 0; + setMultiLinesEnabled( true ); + parent->setResizeMode( QListView::LastColumn ); + + m_origText = text; + + if ( !t2.isNull() ) + { + setText( 0, text ); + m_origText = t2; + m_wrapColumn = 1; + } + else + m_origText = text; + + wrapColumn( m_wrapColumn ); + + connect( parent->header(), SIGNAL(sizeChange(int, int, int)), this, SLOT(wrapColumn(int))); +} + +#include "kwrappedlistviewitem.moc" diff --git a/atlantik/libatlantikui/kwrappedlistviewitem.h b/atlantik/libatlantikui/kwrappedlistviewitem.h new file mode 100644 index 00000000..056cef6d --- /dev/null +++ b/atlantik/libatlantikui/kwrappedlistviewitem.h @@ -0,0 +1,54 @@ +// Copyright (c) 2004 Rob Kaper <[email protected]>. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS `AS IS'' AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +// SUCH DAMAGE. + +#ifndef KWRAPPEDLISTVIEWITEM_H +#define KWRAPPEDLISTVIEWITEM_H + +#include <qobject.h> +#include <qstring.h> + +#include <klistview.h> + +class KWordWrap; + +class KWrappedListViewItem : public QObject, public KListViewItem +{ +Q_OBJECT + +public: + KWrappedListViewItem( QListView *parent, QString text, QString=QString::null ); + KWrappedListViewItem( QListView *parent, QListViewItem *after, QString text, QString=QString::null ); + void setup(); +// int width(const QFontMetrics& fm, const QListView* lv, int c) const; + +private slots: + void wrapColumn( int c ); + +private: + void init( QListView *parent, QString text, QString=QString::null ); + QString m_origText; + int m_wrapColumn; +}; + +#endif diff --git a/atlantik/libatlantikui/libatlantikui_export.h b/atlantik/libatlantikui/libatlantikui_export.h new file mode 100644 index 00000000..9ea1695f --- /dev/null +++ b/atlantik/libatlantikui/libatlantikui_export.h @@ -0,0 +1,25 @@ +// Copyright (c) 2004 Dirk Mueller <[email protected]> + +// +// 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 LIBATLANTIKUI_EXPORT_H +#define LIBATLANTIKUI_EXPORT_H + +#include <kdemacros.h> + +#define LIBATLANTIKUI_EXPORT KDE_EXPORT + +#endif diff --git a/atlantik/libatlantikui/portfolioestate.cpp b/atlantik/libatlantikui/portfolioestate.cpp new file mode 100644 index 00000000..625fb055 --- /dev/null +++ b/atlantik/libatlantikui/portfolioestate.cpp @@ -0,0 +1,94 @@ +// Copyright (c) 2002 Rob Kaper <[email protected]> +// +// 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 <qcolor.h> +#include <qpainter.h> +#include <qrect.h> + +#include "portfolioestate.moc" +#include "estate.h" + +PortfolioEstate::PortfolioEstate(Estate *estate, Player *player, bool alwaysOwned, QWidget *parent, const char *name) : QWidget(parent, name) +{ + m_estate = estate; + m_player = player; + m_alwaysOwned = alwaysOwned; + + QSize s(PE_WIDTH, PE_HEIGHT); + setFixedSize(s); + + b_recreate = true; +} + +void PortfolioEstate::estateChanged() +{ + b_recreate = true; + update(); +} + +QPixmap PortfolioEstate::drawPixmap(Estate *estate, Player *player, bool alwaysOwned) +{ + QColor lightGray(204, 204, 204), darkGray(153, 153, 153); + QPixmap qpixmap(PE_WIDTH, PE_HEIGHT); + QPainter painter; + painter.begin(&qpixmap); + + painter.setPen(lightGray); + painter.setBrush(white); + painter.drawRect(QRect(0, 0, PE_WIDTH, PE_HEIGHT)); + if (alwaysOwned || (estate && estate->isOwned() && player == estate->owner())) + { + painter.setPen(darkGray); + for (int y=5;y<=13;y+=2) + painter.drawLine(2, y, 10, y); + + painter.setPen(Qt::white); + painter.drawPoint(8, 5); + painter.drawPoint(8, 7); + painter.drawPoint(8, 9); + painter.drawPoint(5, 11); + painter.drawPoint(9, 11); + painter.drawPoint(3, 13); + painter.drawPoint(10, 13); + + painter.setPen(estate->color()); + painter.setBrush(estate->color()); + } + else + { + painter.setPen(lightGray); + painter.setBrush(lightGray); + } + painter.drawRect(0, 0, PE_WIDTH, 3); + + return qpixmap; +} + +void PortfolioEstate::paintEvent(QPaintEvent *) +{ + if (b_recreate) + { + m_pixmap = drawPixmap(m_estate, m_player, m_alwaysOwned); + b_recreate = false; + } + bitBlt(this, 0, 0, &m_pixmap); +} + +void PortfolioEstate::mousePressEvent(QMouseEvent *e) +{ + if (e->button()==LeftButton) + emit estateClicked(m_estate); +} diff --git a/atlantik/libatlantikui/portfolioestate.h b/atlantik/libatlantikui/portfolioestate.h new file mode 100644 index 00000000..65bd5db3 --- /dev/null +++ b/atlantik/libatlantikui/portfolioestate.h @@ -0,0 +1,55 @@ +// Copyright (c) 2002 Rob Kaper <[email protected]> +// +// 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_PORTFOLIOESTATE_H +#define ATLANTIK_PORTFOLIOESTATE_H + +#include <qpixmap.h> +#include <qwidget.h> + +#define PE_WIDTH 13 +#define PE_HEIGHT 16 + +class Estate; +class Player; + +class PortfolioEstate : public QWidget +{ +Q_OBJECT + +public: + PortfolioEstate(Estate *estate, Player *player, bool alwaysOwned, QWidget *parent, const char *name = 0); + Estate *estate() { return m_estate; } + static QPixmap drawPixmap(Estate *estate, Player *player = 0, bool alwaysOwned = true); + +protected: + void paintEvent(QPaintEvent *); + void mousePressEvent(QMouseEvent *); + +private slots: + void estateChanged(); + +signals: + void estateClicked(Estate *estate); + +private: + Estate *m_estate; + Player *m_player; + QPixmap m_pixmap; + bool b_recreate, m_alwaysOwned; +}; + +#endif diff --git a/atlantik/libatlantikui/portfolioview.cpp b/atlantik/libatlantikui/portfolioview.cpp new file mode 100644 index 00000000..c07d426b --- /dev/null +++ b/atlantik/libatlantikui/portfolioview.cpp @@ -0,0 +1,295 @@ +// Copyright (c) 2002-2003 Rob Kaper <[email protected]> +// +// 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 <qpainter.h> +#include <qcursor.h> + +#include <kdebug.h> +#include <kdialogbase.h> +#include <kiconeffect.h> +#include <kglobalsettings.h> +#include <klocale.h> +#include <kpopupmenu.h> +#include <kstandarddirs.h> + +#include <atlantic_core.h> +#include <config.h> +#include <player.h> +#include <estate.h> +#include <estategroup.h> + +#include "portfolioview.moc" + +#define PE_DISTW 4 +#define PE_DISTH 4 +#define PE_SPACE 2 +#define PE_MARGINW 5 +#define PE_MARGINH 2 +#define ICONSIZE 48 + +PortfolioView::PortfolioView(AtlanticCore *core, Player *player, QColor activeColor, QColor inactiveColor, QWidget *parent, const char *name) : QWidget(parent, name) +{ + m_atlanticCore = core; + m_player = player; + m_activeColor = activeColor; + m_inactiveColor = inactiveColor; + m_lastPE = 0; + + qpixmap = 0; + b_recreate = true; + + m_portfolioEstates.setAutoDelete(true); + setBackgroundColor(Qt::white); + setMinimumHeight(ICONSIZE); + + // Init icon + m_image = 0; + m_imageName = "hamburger.png"; + loadIcon(); +} + +PortfolioView::~PortfolioView() +{ + clearPortfolio(); + delete m_image; + delete qpixmap; +} + +Player *PortfolioView::player() +{ + return m_player; +} + +void PortfolioView::buildPortfolio() +{ + if ( m_portfolioEstates.count() ) + clearPortfolio(); + + // Loop through estate groups in order + QPtrList<EstateGroup> estateGroups = m_atlanticCore->estateGroups(); + PortfolioEstate *lastPE = 0, *firstPEprevGroup = 0; + + int x = 100, y = 25, marginHint = 5, bottom; + bottom = ICONSIZE - PE_HEIGHT - marginHint; + + EstateGroup *estateGroup; + for (QPtrListIterator<EstateGroup> it(estateGroups); *it; ++it) + { + if ((estateGroup = *it)) + { + // New group + lastPE = 0; + + // Loop through estates + QPtrList<Estate> estates = m_atlanticCore->estates(); + Estate *estate; + for (QPtrListIterator<Estate> it(estates); *it; ++it) + { + if ((estate = *it) && estate->estateGroup() == estateGroup) + { + // Create PE + PortfolioEstate *portfolioEstate = new PortfolioEstate(estate, m_player, false, this, "portfolioestate"); + m_portfolioEstates.append(portfolioEstate); + + connect(portfolioEstate, SIGNAL(estateClicked(Estate *)), this, SIGNAL(estateClicked(Estate *))); + if (lastPE) + { + x = lastPE->x() + 2; + y = lastPE->y() + 4; + if (y > bottom) + bottom = y; + } + else if (firstPEprevGroup) + { + x = firstPEprevGroup->x() + PE_WIDTH + 8; + y = 20 + marginHint; + firstPEprevGroup = portfolioEstate; + } + else + { + x = ICONSIZE + marginHint; + y = 20 + marginHint; + if (y > bottom) + bottom = y; + firstPEprevGroup = portfolioEstate; + } + + portfolioEstate->setGeometry(x, y, portfolioEstate->width(), portfolioEstate->height()); + portfolioEstate->show(); + + connect(estate, SIGNAL(changed()), portfolioEstate, SLOT(estateChanged())); + + lastPE = portfolioEstate; + } + } + } + } + setMinimumWidth(x + PE_WIDTH + marginHint); + int minHeight = bottom + PE_HEIGHT + marginHint; + if (minHeight > minimumHeight()) + setMinimumHeight(minHeight); +} + +void PortfolioView::clearPortfolio() +{ + m_portfolioEstates.clear(); +} + +void PortfolioView::loadIcon() +{ + if (m_imageName == m_player->image()) + return; + m_imageName = m_player->image(); + + delete m_image; + m_image = 0; + + if (!m_imageName.isEmpty()) + { + QString filename = locate("data", "atlantik/themes/default/tokens/" + m_imageName); + if (KStandardDirs::exists(filename)) + m_image = new QPixmap(filename); + } + + if (!m_image) + { + return; + +/* + m_imageName = "hamburger.png"; + + QString filename = locate("data", "atlantik/themes/default/tokens/" + m_imageName); + if (KStandardDirs::exists(filename)) + m_image = new QPixmap(filename); +*/ + } + else if (ICONSIZE > minimumHeight()) + setMinimumHeight(ICONSIZE); + + QWMatrix m; + m.scale(double(ICONSIZE) / m_image->width(), double(ICONSIZE) / m_image->height()); + QPixmap *scaledPixmap = new QPixmap(ICONSIZE, ICONSIZE); + *scaledPixmap = m_image->xForm(m); + + delete m_image; + m_image = scaledPixmap; +} + +void PortfolioView::paintEvent(QPaintEvent *) +{ + if (b_recreate) + { + delete qpixmap; + qpixmap = new QPixmap(width(), height()); + + QPainter painter; + painter.begin(qpixmap, this); + + painter.setPen(Qt::white); + painter.setBrush(Qt::white); + painter.drawRect(rect()); + + painter.setPen(m_player->hasTurn() ? m_activeColor : Qt::black); + painter.setBrush(m_player->hasTurn() ? m_activeColor : Qt::black); + painter.drawRect(0, 0, width(), 20); + + if (m_image) + { + painter.setPen(Qt::black); + painter.setBrush(Qt::white); + painter.drawRect(0, 0, ICONSIZE, ICONSIZE); + + painter.drawPixmap(0, 0, *m_image); + } + + painter.setPen(Qt::white); + painter.setFont(QFont(KGlobalSettings::generalFont().family(), KGlobalSettings::generalFont().pointSize(), QFont::Bold)); + painter.drawText(ICONSIZE + KDialog::marginHint(), 15, m_player->name()); + + if ( m_portfolioEstates.count() ) + painter.drawText(width() - 50, 15, QString::number(m_player->money())); + else + { + painter.setPen(Qt::black); + painter.setBrush(Qt::white); + + painter.setFont(QFont(KGlobalSettings::generalFont().family(), KGlobalSettings::generalFont().pointSize(), QFont::Normal)); + painter.drawText(ICONSIZE + KDialog::marginHint(), 30, m_player->host()); + } + + b_recreate = false; + } + bitBlt(this, 0, 0, qpixmap); +} + +void PortfolioView::resizeEvent(QResizeEvent *) +{ + b_recreate = true; +} + +void PortfolioView::playerChanged() +{ + loadIcon(); + + b_recreate = true; + update(); +} + +void PortfolioView::mousePressEvent(QMouseEvent *e) +{ + Player *playerSelf = m_atlanticCore->playerSelf(); + + if ( e->button()==RightButton && (m_player != playerSelf) ) + { + KPopupMenu *rmbMenu = new KPopupMenu(this); + rmbMenu->insertTitle(m_player->name()); + + if ( m_portfolioEstates.count() ) + { + // Start trade + rmbMenu->insertItem(i18n("Request Trade with %1").arg(m_player->name()), 0); + } + else + { + // Kick player + rmbMenu->insertItem(i18n("Boot Player %1 to Lounge").arg(m_player->name()), 0); + rmbMenu->setItemEnabled( 0, m_atlanticCore->selfIsMaster() ); + } + + connect(rmbMenu, SIGNAL(activated(int)), this, SLOT(slotMenuAction(int))); + QPoint g = QCursor::pos(); + rmbMenu->exec(g); + } +} + +void PortfolioView::slotMenuAction(int item) +{ + switch (item) + { + case 0: + if ( m_portfolioEstates.count() ) + emit newTrade(m_player); + else + emit kickPlayer(m_player); + break; + } +} +#undef PE_DISTW +#undef PE_DISTH +#undef PE_SPACE +#undef PE_MARGINW +#undef PE_MARGINH +#undef ICONSIZE diff --git a/atlantik/libatlantikui/portfolioview.h b/atlantik/libatlantikui/portfolioview.h new file mode 100644 index 00000000..26317e2b --- /dev/null +++ b/atlantik/libatlantikui/portfolioview.h @@ -0,0 +1,73 @@ +// Copyright (c) 2002-2003 Rob Kaper <[email protected]> +// +// 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_PORTFOLIOVIEW_H +#define ATLANTIK_PORTFOLIOVIEW_H + +#include <qwidget.h> +#include <qpixmap.h> +#include <qptrlist.h> + +#include "portfolioestate.h" +#include "libatlantikui_export.h" +class QColor; +class QString; + +class AtlanticCore; +class Player; +class Estate; + +class LIBATLANTIKUI_EXPORT PortfolioView : public QWidget +{ +Q_OBJECT + +public: + PortfolioView(AtlanticCore *core, Player *_player, QColor activeColor, QColor inactiveColor, QWidget *parent, const char *name = 0); + ~PortfolioView(); + + void buildPortfolio(); + void clearPortfolio(); + + Player *player(); + +protected: + void paintEvent(QPaintEvent *); + void resizeEvent(QResizeEvent *); + void mousePressEvent(QMouseEvent *); + +signals: + void newTrade(Player *player); + void kickPlayer(Player *player); + void estateClicked(Estate *); + +private slots: + void playerChanged(); + void slotMenuAction(int item); + +private: + void loadIcon(); + + AtlanticCore *m_atlanticCore; + Player *m_player; + PortfolioEstate *m_lastPE; + QColor m_activeColor, m_inactiveColor; + QPixmap *qpixmap, *m_image; + QString m_imageName; + bool b_recreate; + QPtrList<PortfolioEstate> m_portfolioEstates; +}; + +#endif diff --git a/atlantik/libatlantikui/token.cpp b/atlantik/libatlantikui/token.cpp new file mode 100644 index 00000000..6f13333f --- /dev/null +++ b/atlantik/libatlantikui/token.cpp @@ -0,0 +1,157 @@ +// Copyright (c) 2002-2003 Rob Kaper <[email protected]> +// +// 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 <qpainter.h> +#include <qpixmap.h> +#include <qfont.h> + +#include <kdebug.h> + +#include <kstandarddirs.h> +#include <kglobalsettings.h> + +#include "board.h" +#include "estate.h" +#include "player.h" + +#include "token.moc" + +#define TOKEN_ICONSIZE 32 + +Token::Token(Player *player, AtlantikBoard *parent, const char *name) : QWidget(parent, name) +{ + setBackgroundMode(NoBackground); // avoid flickering + + m_parentBoard = parent; + + m_player = player; + connect(m_player, SIGNAL(changed(Player *)), this, SLOT(playerChanged())); + + m_inJail = m_player->inJail(); + m_location = m_player->location(); + m_destination = 0; + + qpixmap = 0; + b_recreate = true; + + // Init icon + m_image = 0; + loadIcon(); + + setFixedSize(QSize(TOKEN_ICONSIZE, TOKEN_ICONSIZE + KGlobalSettings::generalFont().pointSize())); +} + +Token::~Token() +{ + delete m_image; +} + +Player *Token::player() +{ + return m_player; +} + +void Token::setLocation(Estate *location) +{ + if (m_location != location) + m_location = location; +} + +void Token::setDestination(Estate *estateView) +{ + if (m_destination != estateView) + m_destination = estateView; +} + +void Token::playerChanged() +{ + if (m_imageName != m_player->image()) + loadIcon(); + + b_recreate = true; + update(); +} + +void Token::loadIcon() +{ + m_imageName = m_player->image(); + + delete m_image; + m_image = 0; + + if (!m_imageName.isEmpty()) + { + QString filename = locate("data", "atlantik/themes/default/tokens/" + m_imageName); + if (KStandardDirs::exists(filename)) + m_image = new QPixmap(filename); + } + + if (!m_image) + { + m_imageName = "hamburger.png"; + + QString filename = locate("data", "atlantik/themes/default/tokens/" + m_imageName); + if (KStandardDirs::exists(filename)) + m_image = new QPixmap(filename); + } + + QWMatrix m; + m.scale(double(TOKEN_ICONSIZE) / m_image->width(), double(TOKEN_ICONSIZE) / m_image->height()); + QPixmap *scaledPixmap = new QPixmap(TOKEN_ICONSIZE, TOKEN_ICONSIZE); + *scaledPixmap = m_image->xForm(m); + + delete m_image; + m_image = scaledPixmap; +} + +void Token::paintEvent(QPaintEvent *) +{ + if (b_recreate) + { + delete qpixmap; + qpixmap = new QPixmap(width(), height()); + + QPainter painter; + painter.begin(qpixmap, this); + + if (m_image) + { + painter.setPen(Qt::black); + painter.setBrush(Qt::white); + painter.drawRect(0, 0, TOKEN_ICONSIZE, TOKEN_ICONSIZE); + + painter.drawPixmap(0, 0, *m_image); + } + + painter.setPen(Qt::black); + painter.setBrush(Qt::black); + painter.drawRect(0, TOKEN_ICONSIZE, width(), KGlobalSettings::generalFont().pointSize()); + + painter.setPen(Qt::white); + painter.setFont(QFont(KGlobalSettings::generalFont().family(), KGlobalSettings::generalFont().pointSize(), QFont::DemiBold)); + painter.drawText(1, height()-1, (m_player ? m_player->name() : QString::null)); + + b_recreate = false; + } + bitBlt(this, 0, 0, qpixmap); +} + +void Token::resizeEvent(QResizeEvent *) +{ + b_recreate = true; +} diff --git a/atlantik/libatlantikui/token.h b/atlantik/libatlantikui/token.h new file mode 100644 index 00000000..f0e52f2b --- /dev/null +++ b/atlantik/libatlantikui/token.h @@ -0,0 +1,62 @@ +// Copyright (c) 2002-2003 Rob Kaper <[email protected]> +// +// 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_TOKEN_H +#define ATLANTIK_TOKEN_H + +#include <qwidget.h> + +class QPixmap; + +class Player; +class Estate; +class AtlantikBoard; + +class Token : public QWidget +{ +Q_OBJECT + + public: + Token (Player *player, AtlantikBoard *parent, const char *name = 0); + ~Token(); + Player *player(); + void setLocation(Estate *estate); + Estate *location() { return m_location; } + void setDestination(Estate *estate); + Estate *destination() { return m_destination; } + void setInJail (bool inJail) { m_inJail = inJail; } + bool inJail() { return m_inJail; } + + private slots: + void playerChanged(); + + protected: + void paintEvent(QPaintEvent *); + void resizeEvent(QResizeEvent *); + +private: + void loadIcon(); + + Player *m_player; + Estate *m_location, *m_destination; + bool m_inJail; + AtlantikBoard *m_parentBoard; + bool b_recreate; + QPixmap *qpixmap, *m_image; + QString m_imageName; +}; + +#endif diff --git a/atlantik/libatlantikui/trade_widget.cpp b/atlantik/libatlantikui/trade_widget.cpp new file mode 100644 index 00000000..b2658abb --- /dev/null +++ b/atlantik/libatlantikui/trade_widget.cpp @@ -0,0 +1,374 @@ +// Copyright (c) 2002-2003 Rob Kaper <[email protected]> +// +// 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 <qlayout.h> +#include <qhgroupbox.h> +#include <qheader.h> +#include <qpopupmenu.h> +#include <qcursor.h> +#include <qvalidator.h> +#include <qmap.h> +#include <qlabel.h> +#include <qspinbox.h> + +#include <klocale.h> +#include <klistview.h> +#include <kdebug.h> +#include <kdialogbase.h> +#include <klineedit.h> +#include <kiconloader.h> +#include <kpushbutton.h> +#include <kcombobox.h> +#include <kpopupmenu.h> + +#include <atlantic_core.h> +#include <player.h> +#include <estate.h> +#include <trade.h> +#include <portfolioestate.h> + +#include "trade_widget.moc" + +TradeDisplay::TradeDisplay(Trade *trade, AtlanticCore *atlanticCore, QWidget *parent, const char *name) + : QWidget(parent, name, + WType_Dialog | WStyle_Customize | WStyle_DialogBorder | WStyle_Title | + WStyle_Minimize | WStyle_ContextHelp ) +{ + m_trade = trade; + m_atlanticCore = atlanticCore; + + setCaption(i18n("Trade %1").arg(trade->tradeId())); + + QVBoxLayout *listCompBox = new QVBoxLayout(this, KDialog::marginHint()); + + m_updateComponentBox = new QHGroupBox(i18n("Add Component"), this); + listCompBox->addWidget(m_updateComponentBox); + + m_editTypeCombo = new KComboBox(m_updateComponentBox); + m_editTypeCombo->insertItem(i18n("Estate")); + m_editTypeCombo->insertItem(i18n("Money")); + + connect(m_editTypeCombo, SIGNAL(activated(int)), this, SLOT(setTypeCombo(int))); + + m_estateCombo = new KComboBox(m_updateComponentBox); + QPtrList<Estate> estateList = m_atlanticCore->estates(); + Estate *estate; + for (QPtrListIterator<Estate> it(estateList); *it; ++it) + { + if ((estate = *it) && estate->isOwned()) + { + m_estateCombo->insertItem( PortfolioEstate::drawPixmap(estate), estate->name() ); + m_estateMap[m_estateCombo->count() - 1] = estate; + m_estateRevMap[estate] = m_estateCombo->count() - 1; + } + } + + connect(m_estateCombo, SIGNAL(activated(int)), this, SLOT(setEstateCombo(int))); + + m_moneyBox = new QSpinBox(0, 10000, 1, m_updateComponentBox); + + QPtrList<Player> playerList = m_atlanticCore->players(); + Player *player, *pSelf = m_atlanticCore->playerSelf(); + + m_fromLabel = new QLabel(m_updateComponentBox); + m_fromLabel->setText(i18n("From")); + m_playerFromCombo = new KComboBox(m_updateComponentBox); + + m_toLabel = new QLabel(m_updateComponentBox); + m_toLabel->setText(i18n("To")); + m_playerTargetCombo = new KComboBox(m_updateComponentBox); + + for (QPtrListIterator<Player> it(playerList); *it; ++it) + { + if ((player = *it) && player->game() == pSelf->game()) + { + m_playerFromCombo->insertItem(player->name()); + m_playerFromMap[m_playerFromCombo->count() - 1] = player; + m_playerFromRevMap[player] = m_playerFromCombo->count() - 1; + + m_playerTargetCombo->insertItem(player->name()); + m_playerTargetMap[m_playerTargetCombo->count() - 1] = player; + m_playerTargetRevMap[player] = m_playerTargetCombo->count() - 1; + + connect(player, SIGNAL(changed(Player *)), this, SLOT(playerChanged(Player *))); + } + } + + m_updateButton = new KPushButton(i18n("Update"), m_updateComponentBox); + m_updateButton->setEnabled(false); + + connect(m_updateButton, SIGNAL(clicked()), this, SLOT(updateComponent())); + + m_componentList = new KListView(this, "componentList"); + listCompBox->addWidget(m_componentList); + + m_componentList->addColumn(i18n("Player")); + m_componentList->addColumn(i18n("Gives")); + m_componentList->addColumn(i18n("Player")); + m_componentList->addColumn(i18n("Item")); + + connect(m_componentList, SIGNAL(contextMenu(KListView*, QListViewItem *, const QPoint&)), SLOT(contextMenu(KListView *, QListViewItem *, const QPoint&))); + connect(m_componentList, SIGNAL(clicked(QListViewItem *)), this, SLOT(setCombos(QListViewItem *))); + + QHBoxLayout *actionBox = new QHBoxLayout(this, 0, KDialog::spacingHint()); + listCompBox->addItem(actionBox); + + actionBox->addItem(new QSpacerItem(20, 20, QSizePolicy::Expanding, QSizePolicy::Minimum)); + + m_rejectButton = new KPushButton(BarIcon("cancel", KIcon::SizeSmall), i18n("Reject"), this); + actionBox->addWidget(m_rejectButton); + + connect(m_rejectButton, SIGNAL(clicked()), this, SLOT(reject())); + + m_acceptButton = new KPushButton(BarIcon("ok", KIcon::SizeSmall), i18n("Accept"), this); +// m_acceptButton->setEnabled(false); + actionBox->addWidget(m_acceptButton); + + connect(m_acceptButton, SIGNAL(clicked()), this, SLOT(accept())); + + m_status = new QLabel(this); + listCompBox->addWidget(m_status); + m_status->setText( i18n( "%1 out of %2 players accept current trade proposal." ).arg( m_trade->count( true ) ).arg( m_trade->count( false ) ) ); + +// mPlayerList->header()->hide(); +// mPlayerList->setRootIsDecorated(true); +// mPlayerList->setResizeMode(KListView::AllColumns); + + connect(m_trade, SIGNAL(itemAdded(TradeItem *)), this, SLOT(tradeItemAdded(TradeItem *))); + connect(m_trade, SIGNAL(itemRemoved(TradeItem *)), this, SLOT(tradeItemRemoved(TradeItem *))); + connect(m_trade, SIGNAL(changed(Trade *)), this, SLOT(tradeChanged())); + connect(m_trade, SIGNAL(rejected(Player *)), this, SLOT(tradeRejected(Player *))); + connect(this, SIGNAL(updateEstate(Trade *, Estate *, Player *)), m_trade, SIGNAL(updateEstate(Trade *, Estate *, Player *))); + connect(this, SIGNAL(updateMoney(Trade *, unsigned int, Player *, Player *)), m_trade, SIGNAL(updateMoney(Trade *, unsigned int, Player *, Player *))); + connect(this, SIGNAL(reject(Trade *)), m_trade, SIGNAL(reject(Trade *))); + connect(this, SIGNAL(accept(Trade *)), m_trade, SIGNAL(accept(Trade *))); + + setTypeCombo(m_editTypeCombo->currentItem()); + setEstateCombo(m_estateCombo->currentItem()); + + m_contextTradeItem = 0; +} + +void TradeDisplay::closeEvent(QCloseEvent *e) +{ + // Don't send network event when trade is already rejected + if (m_trade->isRejected()) + m_atlanticCore->removeTrade(m_trade); + else + emit reject(m_trade); + + e->accept(); +} + +void TradeDisplay::tradeItemAdded(TradeItem *tradeItem) +{ + KListViewItem *item = new KListViewItem(m_componentList, (tradeItem->from() ? tradeItem->from()->name() : QString("?")), i18n("gives is transitive ;)", "gives"), (tradeItem->to() ? tradeItem->to()->name() : QString("?")), tradeItem->text()); + connect(tradeItem, SIGNAL(changed(TradeItem *)), this, SLOT(tradeItemChanged(TradeItem *))); + + item->setPixmap(0, QPixmap(SmallIcon("personal"))); + item->setPixmap(2, QPixmap(SmallIcon("personal"))); + + if (TradeEstate *tradeEstate = dynamic_cast<TradeEstate*>(tradeItem)) + item->setPixmap(3, PortfolioEstate::drawPixmap(tradeEstate->estate())); +// else if (TradeMoney *tradeMoney = dynamic_cast<TradeMoney*>(tradeItem)) +// item->setPixmap(3, PortfolioEstate::pixMap(tradeEstate->estate())); + + m_componentMap[tradeItem] = item; + m_componentRevMap[item] = tradeItem; +} + +void TradeDisplay::tradeItemRemoved(TradeItem *t) +{ + KListViewItem *item = m_componentMap[t]; + delete item; + m_componentMap[t] = 0; +} + +void TradeDisplay::tradeItemChanged(TradeItem *t) +{ + KListViewItem *item = m_componentMap[t]; + if (item) + { + item->setText(0, t->from() ? t->from()->name() : QString("?")); + item->setPixmap(0, QPixmap(SmallIcon("personal"))); + item->setText(2, t->to() ? t->to()->name() : QString("?")); + item->setPixmap(2, QPixmap(SmallIcon("personal"))); + item->setText(3, t->text()); + } +} + +void TradeDisplay::tradeChanged() +{ + // TODO: add notification whether playerSelf has accepted or not and + // enable/disable accept button based on that + m_status->setText( i18n( "%1 out of %2 players accept current trade proposal." ).arg( m_trade->count( true ) ).arg( m_trade->count( false ) ) ); +} + +void TradeDisplay::playerChanged(Player *player) +{ + m_playerFromCombo->changeItem(player->name(), m_playerFromRevMap[player]); + m_playerTargetCombo->changeItem(player->name(), m_playerTargetRevMap[player]); + + TradeItem *item = 0; + for (QMap<KListViewItem *, TradeItem *>::Iterator it=m_componentRevMap.begin() ; it != m_componentRevMap.end() && (item = *it) ; ++it) + tradeItemChanged(item); +} + +void TradeDisplay::tradeRejected(Player *player) +{ + if (player) + m_status->setText(i18n("Trade proposal was rejected by %1.").arg(player->name())); + else + m_status->setText(i18n("Trade proposal was rejected.")); + + // Disable GUI elements + m_updateButton->setEnabled(false); + m_componentList->setEnabled(false); + m_rejectButton->setEnabled(false); + m_acceptButton->setEnabled(false); + + // TODO: add/enable close button +} + +void TradeDisplay::setTypeCombo(int index) +{ + switch (index) + { + case 0: + // Editing estate component + + m_estateCombo->show(); + m_estateCombo->setMaximumWidth(9999); + + m_moneyBox->hide(); + m_moneyBox->setMaximumWidth(0); + + setEstateCombo(m_estateCombo->currentItem()); // also updates playerfromCombo + m_playerFromCombo->setEnabled(false); + + m_updateButton->setEnabled( m_estateCombo->count() > 0 ); + + break; + + case 1: + // Editing money component + + m_estateCombo->hide(); + m_estateCombo->setMaximumWidth(0); + + m_moneyBox->show(); + m_moneyBox->setMaximumWidth(9999); + + m_playerFromCombo->setEnabled(true); + + m_updateButton->setEnabled(true); + + break; + } +} + +void TradeDisplay::setEstateCombo(int index) +{ + if (m_estateCombo->currentItem() != index) + m_estateCombo->setCurrentItem(index); + + if (Estate *estate = m_estateMap[index]) + m_playerFromCombo->setCurrentItem( m_playerFromRevMap[estate->owner()] ); +} + +void TradeDisplay::setCombos(QListViewItem *i) +{ + TradeItem *item = m_componentRevMap[(KListViewItem *)(i)]; + if (TradeEstate *tradeEstate = dynamic_cast<TradeEstate*>(item)) + { + setTypeCombo(0); + setEstateCombo( m_estateRevMap[tradeEstate->estate()] ); // also updates playerFromCombo + m_playerTargetCombo->setCurrentItem( m_playerTargetRevMap[tradeEstate->to()] ); + } + else if (TradeMoney *tradeMoney = dynamic_cast<TradeMoney*>(item)) + { + setTypeCombo(1); + m_moneyBox->setValue( tradeMoney->money() ); + m_playerFromCombo->setCurrentItem( m_playerFromRevMap[tradeMoney->from()] ); + m_playerTargetCombo->setCurrentItem( m_playerTargetRevMap[tradeMoney->to()] ); + } +} + +void TradeDisplay::updateComponent() +{ + Estate *estate; + Player *pFrom, *pTarget; + + switch (m_editTypeCombo->currentItem()) + { + case 0: + // Updating estate component + estate = m_estateMap[m_estateCombo->currentItem()]; + pTarget = m_playerTargetMap[m_playerTargetCombo->currentItem()]; + + if (estate && pTarget) + emit updateEstate(m_trade, estate, pTarget); + + break; + + case 1: + // Updating money component + pFrom = m_playerFromMap[m_playerFromCombo->currentItem()]; + pTarget = m_playerTargetMap[m_playerTargetCombo->currentItem()]; + + if (pFrom && pTarget) + emit updateMoney(m_trade, m_moneyBox->value(), pFrom, pTarget); + + break; + } +} + +void TradeDisplay::reject() +{ + emit reject(m_trade); +} + +void TradeDisplay::accept() +{ + emit accept(m_trade); +} + +void TradeDisplay::contextMenu(KListView *, QListViewItem *i, const QPoint& p) +{ + m_contextTradeItem = m_componentRevMap[(KListViewItem *)(i)]; + + KPopupMenu *rmbMenu = new KPopupMenu(this); +// rmbMenu->insertTitle( ... ); + rmbMenu->insertItem(i18n("Remove From Trade"), 0); + + connect(rmbMenu, SIGNAL(activated(int)), this, SLOT(contextMenuClicked(int))); + rmbMenu->exec(p); +} + +void TradeDisplay::contextMenuClicked(int) +{ + if (!m_contextTradeItem) + return; + + if (TradeEstate *tradeEstate = dynamic_cast<TradeEstate*>(m_contextTradeItem)) + emit updateEstate(m_trade, tradeEstate->estate(), 0); + else if (TradeMoney *tradeMoney = dynamic_cast<TradeMoney*>(m_contextTradeItem)) + emit updateMoney(m_trade, 0, tradeMoney->from(), tradeMoney->to()); + + m_contextTradeItem = 0; +} diff --git a/atlantik/libatlantikui/trade_widget.h b/atlantik/libatlantikui/trade_widget.h new file mode 100644 index 00000000..642cc919 --- /dev/null +++ b/atlantik/libatlantikui/trade_widget.h @@ -0,0 +1,98 @@ +// Copyright (c) 2002 Rob Kaper <[email protected]> +// +// 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 TRADEWIDGET_H +#define TRADEWIDGET_H + +#include <qwidget.h> +#include <qmap.h> +#include "libatlantikui_export.h" + +class QHGroupBox; +class QLabel; +class QListViewItem; +class QSpinBox; + +class KListView; +class KListViewItem; +class KComboBox; +class KPushButton; + +class AtlanticCore; +class Player; +class Trade; +class TradeItem; + +class LIBATLANTIKUI_EXPORT TradeDisplay : public QWidget +{ +Q_OBJECT + +public: + TradeDisplay(Trade *trade, AtlanticCore *atlanticCore, QWidget *parent=0, const char *name = 0); + + Trade *trade() { return mTrade; } + +protected: + void closeEvent(QCloseEvent *e); + +private slots: + void tradeItemAdded(TradeItem *); + void tradeItemRemoved(TradeItem *); + void tradeItemChanged(TradeItem *); + void tradeChanged(); + void playerChanged(Player *player); + void tradeRejected(Player *); + + void setTypeCombo(int); + void setEstateCombo(int); + void setCombos(QListViewItem *i); + + void updateComponent(); + void reject(); + void accept(); + + void contextMenu(KListView *l, QListViewItem *i, const QPoint& p); + void contextMenuClicked(int item); + +signals: + void updateEstate(Trade *trade, Estate *estate, Player *to); + void updateMoney(Trade *trade, unsigned int money, Player *from, Player *to); + void reject(Trade *trade); + void accept(Trade *trade); + +private: + QHGroupBox *m_updateComponentBox; + QLabel *m_status, *m_fromLabel, *m_toLabel; + QSpinBox *m_moneyBox; + + KComboBox *m_editTypeCombo, *m_playerFromCombo, *m_playerTargetCombo, *m_estateCombo; + KListView *m_componentList; + KPushButton *m_updateButton, *m_rejectButton, *m_acceptButton; + + AtlanticCore *m_atlanticCore; + Trade *mTrade, *m_trade; + TradeItem *m_contextTradeItem; + + // TODO: Wouldn't QPair make more sense here? + QMap<TradeItem *, KListViewItem *> m_componentMap; + QMap<KListViewItem *, TradeItem *> m_componentRevMap; + QMap<int, Estate *> m_estateMap; + QMap<Estate *, int> m_estateRevMap; + QMap<int, Player *> m_playerFromMap, m_playerTargetMap; + QMap<Player *, int> m_playerFromRevMap, m_playerTargetRevMap; +}; + +#endif |