File indexing completed on 2024-04-28 04:03:30

0001 /*
0002     SPDX-FileCopyrightText: 2003 Russell Steffen <rsteffen@bayarea.net>
0003     SPDX-FileCopyrightText: 2003 Stephan Zehetner <s.zehetner@nevox.org>
0004     SPDX-FileCopyrightText: 2008-2009 Dmitry Suzdalev <dimsuz@gmail.com>
0005     SPDX-FileCopyrightText: 2006 Inge Wallin <inge@lysator.liu.se>
0006     SPDX-FileCopyrightText: 2006 Pierre Ducroquet <pinaraf@gmail.com>
0007     SPDX-FileCopyrightText: 2011 Jeffrey Kelling <overlordapophis@gmail.com>
0008 
0009     SPDX-License-Identifier: GPL-2.0-or-later
0010 */
0011 
0012 #include "mapitems.h"
0013 
0014 #include <QAbstractTextDocumentLayout>
0015 #include <QBrush>
0016 #include <QGraphicsScene>
0017 #include <QPainter>
0018 #include <QTimer>
0019 
0020 #include <KLocalizedString>
0021 #include <KColorScheme>
0022 
0023 #include "mapscene.h"
0024 #include "map.h"
0025 #include "../planet.h"
0026 
0027 /********************************
0028     PlanetItem
0029  *******************************/
0030 
0031 PlanetItem::PlanetItem (MapScene *scene, Sector *sector, Game *game)
0032     : QGraphicsObject(),
0033       m_scene(scene),
0034       m_sector(sector),
0035       m_game(game),
0036       m_hovered(false),
0037       m_selected(false),
0038       m_blinkState(false)
0039 {
0040     if (m_sector->planet() != nullptr) {
0041         m_lookName = QStringLiteral("planet_%1").arg(m_sector->planet()->planetLook() + 1);
0042     }
0043     setAcceptHoverEvents(true);
0044 
0045     m_blinkTimer = new QTimer(this);
0046     connect(m_blinkTimer, &QTimer::timeout, this, &PlanetItem::blinkPlanet);
0047     connect(m_sector, &Sector::update, this, &PlanetItem::updatePlanet);
0048 }
0049 
0050 
0051 void PlanetItem::updatePlanet()
0052 {
0053     Planet  *planet = m_sector->planet();
0054     if (planet != nullptr) {
0055         m_lookName = QStringLiteral("planet_%1").arg(planet->planetLook() + 1);
0056         update();
0057     }
0058 }
0059 
0060 
0061 QRectF PlanetItem::boundingRect() const
0062 {
0063     qreal size = m_scene->getSectorSize();
0064     return QRectF(m_sector->coord().y() * size + m_scene->itemsHorizontalOffset(),
0065                   m_sector->coord().x() * size + m_scene->itemsVerticalOffset(),
0066                   size,
0067                   size);
0068 }
0069 
0070 void PlanetItem::paint(QPainter *p, const QStyleOptionGraphicsItem * /*option*/,
0071                        QWidget * /*widget*/)
0072 {
0073     if(!m_sector->planet())
0074         return;
0075     // Display a frame around the planet
0076     if (!m_sector->planet()->player()->isNeutral()) {
0077         QBrush backBrush = p->brush();
0078 
0079         backBrush.setColor(m_sector->planet()->player()->color());
0080         backBrush.setStyle(Qt::SolidPattern);
0081 
0082         p->setOpacity(0.5);
0083         p->fillRect(boundingRect(), backBrush );
0084         p->setOpacity(1);
0085     }
0086 
0087     // Display the planet
0088     qreal sectorSize = m_scene->getSectorSize();
0089     QPointF sectorTopLeft(m_sector->coord().y() * sectorSize + m_scene->itemsHorizontalOffset(),
0090                           m_sector->coord().x() * sectorSize + m_scene->itemsVerticalOffset());
0091 
0092     QPixmap planetPix = renderPixmap(m_lookName, sectorSize, sectorSize);
0093     p->drawPixmap(sectorTopLeft, planetPix);
0094 
0095     if ( m_hovered || (m_selected && m_blinkState) ) {
0096         QBrush  backBrush = p->brush();
0097 
0098         backBrush.setColor(KColorScheme(QPalette::Active).background().color());
0099         backBrush.setStyle(Qt::SolidPattern);
0100 
0101         p->setOpacity(0.3);
0102         p->fillRect(boundingRect(), backBrush );
0103         p->setOpacity(1);
0104     }
0105 
0106     // Show the name of the planet (on top of bkgnd)
0107 
0108     QRectF TextRect(sectorTopLeft.x(), sectorTopLeft.y(), sectorSize, sectorSize);
0109 
0110     QPixmap nameBackgroundPix = renderPixmap(QStringLiteral("planet_name_background"), sectorSize, sectorSize);
0111     p->drawPixmap(TextRect.topLeft(), nameBackgroundPix);
0112     p->setFont(QFont(QStringLiteral("Times"), 16));
0113     p->drawText(TextRect, m_sector->planet()->name());
0114 
0115     // Show the number of ships on the planet.
0116     if((m_game->options().NeutralsShowShips || !m_sector->planet()->player()->isNeutral())
0117        && ((!m_game->options().BlindMap || m_game->currentPlayer() == m_sector->planet()->player())
0118            || (m_game->options().NeutralsShowShips && m_sector->planet()->player()->isNeutral())))
0119     {
0120         QString shipCount = QString::number(m_sector->planet()->ships());
0121 
0122         QPixmap shipsBackgroundPix = renderPixmap(QStringLiteral("planet_ship_count_background"),
0123                                                   sectorSize, sectorSize);
0124         p->drawPixmap(TextRect.topLeft(), shipsBackgroundPix);
0125         p->setFont(QFont(QStringLiteral("Times"), 16));
0126         p->drawText(TextRect, Qt::AlignRight | Qt::AlignBottom, shipCount);
0127     }
0128 }
0129 
0130 QPixmap PlanetItem::renderPixmap( const QString& svgId, int width, int height ) const
0131 {
0132     QPixmap pix;
0133     QString cacheKey = QStringLiteral("%1%2x%3").arg(svgId).arg(width).arg(height);
0134     if (!m_scene->imageCache()->findPixmap(cacheKey, &pix)) {
0135         pix = QPixmap(width, height);
0136         pix.fill(Qt::transparent);
0137         QPainter pixPainter(&pix);
0138         m_scene->renderer()->render(&pixPainter, svgId, QRect(0, 0, width, height));
0139         m_scene->imageCache()->insertPixmap(cacheKey, pix);
0140     }
0141 
0142     return pix;
0143 }
0144 
0145 
0146 void PlanetItem::hoverEnterEvent( QGraphicsSceneHoverEvent * /*event*/ )
0147 {
0148     m_hovered = true;
0149 
0150     Planet  *planet = m_sector->planet();
0151     m_scene->displayPlanetInfo(planet);
0152 
0153     update();
0154 }
0155 
0156 void PlanetItem::hoverLeaveEvent( QGraphicsSceneHoverEvent * /*event*/ )
0157 {
0158     m_hovered = false;
0159     m_scene->displayPlanetInfo(nullptr);
0160 
0161     update();
0162 }
0163 
0164 
0165 void PlanetItem::mousePressEvent( QGraphicsSceneMouseEvent * /*event*/ )
0166 {
0167     m_selected = true;
0168     m_blinkTimer->start(500);
0169     update();
0170 
0171     Q_EMIT planetItemSelected(this);
0172 }
0173 
0174 void PlanetItem::select(  )
0175 {
0176     m_selected = true;
0177     m_blinkTimer->start(500);
0178     update();
0179 }
0180 
0181 void PlanetItem::unselect() {
0182     m_blinkTimer->stop();
0183     m_blinkState = false;
0184     m_selected   = false;
0185 
0186     update();
0187 }
0188 
0189 void PlanetItem::blinkPlanet()
0190 {
0191     m_blinkState = !m_blinkState;
0192 
0193     update();
0194 }
0195 
0196 
0197 /********************************
0198     PlanetInfoItem
0199  *******************************/
0200 
0201 
0202 PlanetInfoItem::PlanetInfoItem (Game *game)
0203   : QGraphicsItem(),
0204     m_game(game),
0205     m_textDoc(),
0206     m_planet(nullptr)
0207 {
0208 }
0209 
0210 void PlanetInfoItem::setPlanet (Planet *planet)
0211 {
0212     m_planet = planet;
0213 
0214     QString  text = i18n("Planet name: %1", planet->name());
0215     if((m_game->options().NeutralsShowStats || !planet->player()->isNeutral())
0216        && ((!m_game->options().BlindMap || m_game->currentPlayer() == planet->player())
0217            || (m_game->options().NeutralsShowStats && planet->player()->isNeutral())))
0218     {
0219         text += QLatin1String("<br />") + i18n("Owner: %1", planet->player()->coloredName()
0220           + (m_game->options().NeutralsShowShips || !planet->player()->isNeutral() ?
0221              QLatin1String("<br />")
0222           + i18n("Ships: %1", planet->ships() ) :
0223              QString()));
0224         if( m_game->currentPlayer() == planet->player() )
0225         {
0226             int shipsNeeded = 0; // determine how many ships will be needed by standing orders
0227             for (AttackFleet* fleet : planet->player()->standingOrders()) {
0228                 if(fleet->source == planet)
0229                     shipsNeeded += fleet->shipCount();
0230             }
0231             if(shipsNeeded)
0232                 text += QLatin1String("<br />") + i18nc("regarding standing orders", "Ships due: %1", shipsNeeded);
0233         }
0234         text += QLatin1String("<br />")
0235           + i18n("Production: %1", planet->production())
0236           + QLatin1String("<br />")
0237           + i18n("Kill percent: %1", planet->killPercentage() );
0238     }
0239     m_textDoc.setHtml(text);
0240 }
0241 
0242 
0243 QRectF PlanetInfoItem::boundingRect() const
0244 {
0245     return QRectF(0, 0, m_textDoc.idealWidth(), m_textDoc.size().height());
0246 }
0247 
0248 void PlanetInfoItem::paint(QPainter *p,
0249                            const QStyleOptionGraphicsItem * /*option*/,
0250                            QWidget * /*widget*/)
0251 {
0252     QBrush  brush = p->brush();
0253 
0254     const KColorScheme colorScheme(QPalette::Active);
0255 
0256     brush.setColor(colorScheme.background().color());
0257     brush.setStyle(Qt::SolidPattern);
0258 
0259     p->setOpacity(0.7);
0260     p->fillRect(QRectF(0, 0,
0261                        m_textDoc.idealWidth() + 1,
0262                        m_textDoc.size().height() + 1),
0263                 brush);
0264     p->setOpacity(1.0);
0265 
0266     p->save();
0267     QAbstractTextDocumentLayout::PaintContext ctx;
0268     ctx.palette.setColor(QPalette::Text, colorScheme.foreground().color());
0269     m_textDoc.documentLayout()->draw(p, ctx);
0270     p->restore();
0271 }
0272 
0273 #include "moc_mapitems.cpp"