File indexing completed on 2024-04-21 15:08:02
0001 // Copyright (c) 2002-2003 Rob Kaper <cap@capsi.com> 0002 // 0003 // This library is free software; you can redistribute it and/or 0004 // modify it under the terms of the GNU Lesser General Public 0005 // License version 2.1 as published by the Free Software Foundation. 0006 // 0007 // This library is distributed in the hope that it will be useful, 0008 // but WITHOUT ANY WARRANTY; without even the implied warranty of 0009 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0010 // Lesser General Public License for more details. 0011 // 0012 // You should have received a copy of the GNU Lesser General Public License 0013 // along with this library; see the file COPYING.LIB. If not, write to 0014 // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0015 // Boston, MA 02110-1301, USA. 0016 0017 #include <qpainter.h> 0018 #include <QPixmap> 0019 #include <QMouseEvent> 0020 #include <QFile> 0021 #include <QMultiHash> 0022 #include <QMenu> 0023 #include <QApplication> 0024 #include <QStyle> 0025 #include <QFontDatabase> 0026 #include <QPaintEvent> 0027 0028 #include <klocalizedstring.h> 0029 0030 #include <atlantic_core.h> 0031 #include <player.h> 0032 #include <estate.h> 0033 #include <estategroup.h> 0034 #include <portfolioestate.h> 0035 0036 #include "portfolioview.h" 0037 0038 #include <algorithm> 0039 0040 #define PE_DISTW 4 0041 #define PE_DISTH 4 0042 #define PE_SPACE 2 0043 #define PE_MARGINW 5 0044 #define PE_MARGINH 2 0045 #define ICONSIZE 48 0046 0047 PortfolioView::PortfolioView(AtlanticCore *core, Player *player, QColor activeColor, QColor inactiveColor, QWidget *parent) 0048 : QWidget(parent) 0049 , m_atlanticCore(core) 0050 , m_player(player) 0051 , m_activeColor(activeColor) 0052 , m_inactiveColor(inactiveColor) 0053 , qpixmap(nullptr) 0054 , m_image(nullptr) 0055 , b_recreate(true) 0056 { 0057 QPalette pal = palette(); 0058 pal.setColor(backgroundRole(), Qt::white); 0059 setPalette(pal); 0060 setMinimumHeight(ICONSIZE); 0061 0062 // Init icon 0063 loadIcon(); 0064 } 0065 0066 PortfolioView::~PortfolioView() 0067 { 0068 clearPortfolio(); 0069 delete m_image; 0070 delete qpixmap; 0071 } 0072 0073 Player *PortfolioView::player() const 0074 { 0075 return m_player; 0076 } 0077 0078 void PortfolioView::buildPortfolio() 0079 { 0080 if ( m_portfolioEstates.count() ) 0081 clearPortfolio(); 0082 0083 // Loop through estate groups in order 0084 PortfolioEstate *lastPE = nullptr, *firstPEprevGroup = nullptr; 0085 0086 int x = 100, y = 25, marginHint = 5, bottom; 0087 bottom = ICONSIZE - PE_HEIGHT - marginHint; 0088 0089 QMultiHash<EstateGroup *, Estate *> groups; 0090 0091 foreach (Estate *estate, m_atlanticCore->estates()) 0092 groups.insert(estate->estateGroup(), estate); 0093 0094 if (!groups.isEmpty()) 0095 m_portfolioEstates.reserve(groups.count()); 0096 0097 foreach (EstateGroup *estateGroup, m_atlanticCore->estateGroups()) 0098 { 0099 { 0100 // New group 0101 lastPE = nullptr; 0102 0103 QList<Estate *> estates = groups.values(estateGroup); 0104 // QMultiHash/QHash tracks multiple values per key 0105 // in LIFO order 0106 std::reverse(estates.begin(), estates.end()); 0107 0108 // Loop through estates 0109 foreach (Estate *estate, estates) 0110 { 0111 { 0112 // Create PE 0113 PortfolioEstate *portfolioEstate = new PortfolioEstate(estate, m_player, false, this ); 0114 portfolioEstate->setObjectName(QStringLiteral("portfolioestate")); 0115 m_portfolioEstates.append(portfolioEstate); 0116 0117 connect(portfolioEstate, SIGNAL(estateClicked(Estate *)), this, SIGNAL(estateClicked(Estate *))); 0118 if (lastPE) 0119 { 0120 x = lastPE->x() + 2; 0121 y = lastPE->y() + 4; 0122 if (y > bottom) 0123 bottom = y; 0124 } 0125 else if (firstPEprevGroup) 0126 { 0127 x = firstPEprevGroup->x() + PE_WIDTH + 8; 0128 y = 20 + marginHint; 0129 firstPEprevGroup = portfolioEstate; 0130 } 0131 else 0132 { 0133 x = ICONSIZE + marginHint; 0134 y = 20 + marginHint; 0135 if (y > bottom) 0136 bottom = y; 0137 firstPEprevGroup = portfolioEstate; 0138 } 0139 0140 portfolioEstate->move(x, y); 0141 portfolioEstate->show(); 0142 0143 lastPE = portfolioEstate; 0144 } 0145 } 0146 } 0147 } 0148 setMinimumWidth(x + PE_WIDTH + marginHint); 0149 int minHeight = bottom + PE_HEIGHT + marginHint; 0150 if (minHeight > minimumHeight()) 0151 setMinimumHeight(minHeight); 0152 } 0153 0154 void PortfolioView::clearPortfolio() 0155 { 0156 qDeleteAll(m_portfolioEstates); 0157 m_portfolioEstates.clear(); 0158 } 0159 0160 void PortfolioView::setTokenTheme(const TokenTheme &theme) 0161 { 0162 m_tokenTheme = theme; 0163 loadIcon(true); 0164 b_recreate = true; 0165 update(); 0166 } 0167 0168 void PortfolioView::loadIcon(bool force) 0169 { 0170 if (m_imageName == m_player->image() && !force) 0171 return; 0172 m_imageName = m_player->image(); 0173 0174 delete m_image; 0175 m_image = nullptr; 0176 0177 if (!m_tokenTheme.isValid()) 0178 return; 0179 0180 QString imageFile; 0181 if (!m_imageName.isEmpty()) 0182 imageFile = m_tokenTheme.tokenPath(m_imageName); 0183 if (imageFile.isEmpty()) 0184 imageFile = m_tokenTheme.tokenPath(m_tokenTheme.fallbackIcon()); 0185 0186 const QPixmap pix(imageFile); 0187 if (pix.isNull()) 0188 return; 0189 0190 m_image = new QPixmap(pix.scaled(ICONSIZE, ICONSIZE, Qt::KeepAspectRatio)); 0191 } 0192 0193 void PortfolioView::paintEvent(QPaintEvent *e) 0194 { 0195 if (b_recreate) 0196 { 0197 const int spacingHint = QApplication::style()->pixelMetric(QStyle::PM_LayoutHorizontalSpacing); 0198 const QFont generalFont = QFontDatabase::systemFont(QFontDatabase::GeneralFont); 0199 if (!qpixmap || qpixmap->size() != size()) 0200 { 0201 delete qpixmap; 0202 qpixmap = new QPixmap(width(), height()); 0203 } 0204 0205 QPainter painter; 0206 painter.begin(qpixmap); 0207 0208 painter.setPen(Qt::white); 0209 painter.setBrush(Qt::white); 0210 painter.drawRect(rect()); 0211 0212 painter.setPen(m_player->hasTurn() ? m_activeColor : Qt::black); 0213 painter.setBrush(m_player->hasTurn() ? m_activeColor : Qt::black); 0214 painter.drawRect(0, 0, width() - 1, 20 - 1); 0215 0216 if (m_image) 0217 { 0218 painter.setPen(Qt::black); 0219 painter.setBrush(Qt::white); 0220 painter.drawRect(0, 0, ICONSIZE - 1, ICONSIZE - 1); 0221 0222 painter.drawPixmap((ICONSIZE - m_image->width()) / 2, (ICONSIZE - m_image->height()) / 2, *m_image); 0223 } 0224 0225 painter.setPen(Qt::white); 0226 painter.setFont(QFont(generalFont.family(), generalFont.pointSize(), QFont::Bold)); 0227 painter.drawText(ICONSIZE + spacingHint, 15, m_player->name()); 0228 0229 if ( m_portfolioEstates.count() ) 0230 painter.drawText(width() - 50, 15, QString::number(m_player->money())); 0231 else 0232 { 0233 painter.setPen(Qt::black); 0234 painter.setBrush(Qt::white); 0235 0236 painter.setFont(generalFont); 0237 painter.drawText(ICONSIZE + spacingHint, 30, m_player->host()); 0238 } 0239 0240 b_recreate = false; 0241 } 0242 QPainter painter(this); 0243 painter.drawPixmap(e->rect(), *qpixmap, e->rect()); 0244 } 0245 0246 void PortfolioView::resizeEvent(QResizeEvent *) 0247 { 0248 b_recreate = true; 0249 } 0250 0251 void PortfolioView::playerChanged() 0252 { 0253 loadIcon(); 0254 0255 b_recreate = true; 0256 if (m_player->isSpectator()) 0257 clearPortfolio(); 0258 else if (m_portfolioEstates.isEmpty()) 0259 buildPortfolio(); 0260 update(); 0261 } 0262 0263 void PortfolioView::contextMenuEvent(QContextMenuEvent *e) 0264 { 0265 Player *playerSelf = m_atlanticCore->playerSelf(); 0266 0267 if (m_player != playerSelf && !playerSelf->isSpectator()) 0268 { 0269 QMenu rmbMenu(this); 0270 rmbMenu.setTitle(m_player->name()); 0271 QAction *act; 0272 0273 if ( m_portfolioEstates.count() ) 0274 { 0275 // Start trade 0276 act = rmbMenu.addAction(i18n("Request Trade with %1", m_player->name())); 0277 connect(act, SIGNAL(triggered()), this, SLOT(slotMenuActionTrade())); 0278 } 0279 else 0280 { 0281 // Kick player 0282 act = rmbMenu.addAction(i18n("Boot Player %1 to Lounge", m_player->name())); 0283 act->setEnabled(m_atlanticCore->selfIsMaster()); 0284 connect(act, SIGNAL(triggered()), this, SLOT(slotMenuActionKick())); 0285 } 0286 0287 rmbMenu.exec(e->globalPos()); 0288 } 0289 } 0290 0291 void PortfolioView::slotMenuActionTrade() 0292 { 0293 Q_EMIT newTrade(m_player); 0294 } 0295 0296 void PortfolioView::slotMenuActionKick() 0297 { 0298 Q_EMIT kickPlayer(m_player); 0299 } 0300 0301 #include "moc_portfolioview.cpp"