diff --git a/colorproxy_p.h b/colorproxy_p.h index c5d62688..6d32ef60 100644 --- a/colorproxy_p.h +++ b/colorproxy_p.h @@ -1,98 +1,98 @@ /*************************************************************************** * Copyright 2010 Stefan Majewsky * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library General Public License * * version 2 as published by the Free Software Foundation * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Library General Public License for more details. * * * * You should have received a copy of the GNU Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #ifndef LIBKDEGAMES_COLORPROXY_P_H #define LIBKDEGAMES_COLORPROXY_P_H #include #include #include class QPaintEngineColorProxy; #ifndef KDEGAMES_QCOLOR_QHASH # define KDEGAMES_QCOLOR_QHASH inline uint qHash(const QColor& color) { return color.rgba(); } #endif // KDEGAMES_QCOLOR_QHASH /** * This QPaintDevice forwards all painting operations performed on it to the * contained QPaintDevice. The only modification is that certain colors are * replaced by others in all painting operations (except for drawImage and * drawPixmap). * * @note Using this class results in a non-negligible performance penalty * (~10-20% longer runtime), so use it only if the set of color replacements is * non-empty. */ class QPaintDeviceColorProxy : public QPaintDevice { public: ///@warning Replacement loops (e.g. color1 -> color2 -> color3 -> color1) lead to infinite loops. ///@warning You should not interact with the @a proxiedDevice during the lifetime of this instance. QPaintDeviceColorProxy(QPaintDevice* proxiedDevice, const QHash& replacements); ~QPaintDeviceColorProxy(); QPaintDevice* proxiedDevice() const; - QPaintEngine* paintEngine() const Q_DECL_OVERRIDE; + QPaintEngine* paintEngine() const override; QBrush map(const QBrush& brush) const; inline QColor map(const QColor& color) const; QPen map(const QPen& pen) const; protected: - int metric(PaintDeviceMetric metric) const Q_DECL_OVERRIDE; + int metric(PaintDeviceMetric metric) const override; private: QPaintDevice* m_proxiedDevice; QPaintEngine* m_engine; QHash m_replacements; }; class QPaintEngineColorProxy : public QPaintEngine { public: QPaintEngineColorProxy(); ~QPaintEngineColorProxy(); - bool begin(QPaintDevice* device) Q_DECL_OVERRIDE; - bool end() Q_DECL_OVERRIDE; - void drawEllipse(const QRectF& rect) Q_DECL_OVERRIDE; - void drawEllipse(const QRect& rect) Q_DECL_OVERRIDE; - void drawImage(const QRectF& rectangle, const QImage& image, const QRectF& sr, Qt::ImageConversionFlags flags = Qt::AutoColor) Q_DECL_OVERRIDE; - void drawLines(const QLineF* lines, int lineCount) Q_DECL_OVERRIDE; - void drawLines(const QLine* lines, int lineCount) Q_DECL_OVERRIDE; - void drawPath(const QPainterPath& path) Q_DECL_OVERRIDE; - void drawPixmap(const QRectF& r, const QPixmap& pm, const QRectF& sr) Q_DECL_OVERRIDE; - void drawPoints(const QPointF* points, int pointCount) Q_DECL_OVERRIDE; - void drawPoints(const QPoint* points, int pointCount) Q_DECL_OVERRIDE; - void drawPolygon(const QPointF* points, int pointCount, PolygonDrawMode mode) Q_DECL_OVERRIDE; - void drawPolygon(const QPoint* points, int pointCount, PolygonDrawMode mode) Q_DECL_OVERRIDE; - void drawRects(const QRectF* rects, int rectCount) Q_DECL_OVERRIDE; - void drawRects(const QRect* rects, int rectCount) Q_DECL_OVERRIDE; - void drawTextItem(const QPointF& p, const QTextItem& textItem) Q_DECL_OVERRIDE; - void drawTiledPixmap(const QRectF& rect, const QPixmap& pixmap, const QPointF& p) Q_DECL_OVERRIDE; - Type type() const Q_DECL_OVERRIDE; - void updateState(const QPaintEngineState& state) Q_DECL_OVERRIDE; + bool begin(QPaintDevice* device) override; + bool end() override; + void drawEllipse(const QRectF& rect) override; + void drawEllipse(const QRect& rect) override; + void drawImage(const QRectF& rectangle, const QImage& image, const QRectF& sr, Qt::ImageConversionFlags flags = Qt::AutoColor) override; + void drawLines(const QLineF* lines, int lineCount) override; + void drawLines(const QLine* lines, int lineCount) override; + void drawPath(const QPainterPath& path) override; + void drawPixmap(const QRectF& r, const QPixmap& pm, const QRectF& sr) override; + void drawPoints(const QPointF* points, int pointCount) override; + void drawPoints(const QPoint* points, int pointCount) override; + void drawPolygon(const QPointF* points, int pointCount, PolygonDrawMode mode) override; + void drawPolygon(const QPoint* points, int pointCount, PolygonDrawMode mode) override; + void drawRects(const QRectF* rects, int rectCount) override; + void drawRects(const QRect* rects, int rectCount) override; + void drawTextItem(const QPointF& p, const QTextItem& textItem) override; + void drawTiledPixmap(const QRectF& rect, const QPixmap& pixmap, const QPointF& p) override; + Type type() const override; + void updateState(const QPaintEngineState& state) override; private: QPaintDeviceColorProxy* m_proxy; QPainter* m_painter; }; #endif // LIBKDEGAMES_COLORPROXY_P_H diff --git a/declarativeimports/corebindingsplugin.h b/declarativeimports/corebindingsplugin.h index 18f4feb6..06699fa3 100644 --- a/declarativeimports/corebindingsplugin.h +++ b/declarativeimports/corebindingsplugin.h @@ -1,33 +1,33 @@ /*************************************************************************** * Copyright 2012 Viranch Mehta * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library General Public License * * version 2 as published by the Free Software Foundation * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Library General Public License for more details. * * * * You should have received a copy of the GNU Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #ifndef COREBINDINGSPLUGIN_H #define COREBINDINGSPLUGIN_H #include class CoreBindingsPlugin : public QQmlExtensionPlugin { Q_OBJECT Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface") public: - void registerTypes(const char *uri) Q_DECL_OVERRIDE; + void registerTypes(const char *uri) override; }; #endif // COREBINDINGSPLUGIN_H diff --git a/highscore/kscoredialog.h b/highscore/kscoredialog.h index caef28e0..05ca1423 100644 --- a/highscore/kscoredialog.h +++ b/highscore/kscoredialog.h @@ -1,286 +1,286 @@ /**************************************************************** Copyright (c) 1998 Sandro Sigala Copyright (c) 2001 Waldo Bastian Copyright (c) 2007 Matt Williams All rights reserved. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that the copyright notice and this permission notice and warranty disclaimer appear in supporting documentation, and that the name of the author not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. The author disclaim all warranties with regard to this software, including all implied warranties of merchantability and fitness. In no event shall the author be liable for any special, indirect or consequential damages or any damages whatsoever resulting from loss of use, data or profits, whether in an action of contract, negligence or other tortious action, arising out of or in connection with the use or performance of this software. ****************************************************************/ #ifndef KSCOREDIALOG_H #define KSCOREDIALOG_H #include #include #include #include #include class KLocalizedString; class KgDifficulty; /** * \class KScoreDialog kscoredialog.h * * @short A simple high score implementation * * This class can be used both for displaying the current high scores * and also for adding new highscores. It is the recommended way of * implementing a simple highscore table. * * To display the current highscores it is simply a case of creating * a KScoreDialog object and calling exec(). This example code will * display the Name and Score (the score is always added automatically * unless hidden @ref hideField since it is used for sorting) of the * top 10 players: * \code * KScoreDialog ksdialog(this); * ksdialog.exec(); * \endcode * * To add a new highscore, e.g. at the end of a game you simply create an * object with the @ref Fields you want to write (i.e. KScoreDialog::Name | * KScoreDialog::Score), call addScore and then (optionally) display * the dialog. * This code will allow you to add a highscore with a Name and Score * field. If it's the first time a player has a score on the table, they * will be prompted for their name but subsequent times they will have * their name filled in automatically. * \code * KScoreDialog ksdialog(this); * ksdialog.addScore(playersScore); * ksdialog.exec(); * \endcode * * Or if you want to fill the name in from the code you can pass a default * name by doing * \code * KScoreDialog::FieldInfo scoreInfo; * scoreInfo[KScoreDialog::Name] = "Matt"; * scoreInfo[KScoreDialog::Score].setNum(playersScore); * ksdialog.addScore(scoreInfo); * \endcode * * If you want to add an extra field (e.g. the number of moves taken) then * do * \code * KScoreDialog::FieldInfo scoreInfo; * scoreInfo[KScoreDialog::Name] = "Matt"; * scoreInfo[KScoreDialog::Score].setNum(playersScore); * * ksdialog.addField(KScoreDialog::Custom1, "Num of Moves", "moves"); * scoreInfo[KScoreDialog::Custom1].setNum(42); * * ksdialog.addScore(scoreInfo); * \endcode * You can define up to 5 Custom fields. * @author Matt Williams */ class KDEGAMES_EXPORT KScoreDialog : public QDialog { Q_OBJECT public: ///Highscore fields enum Fields { Name = 1 << 0, Level = 1 << 1, Date = 1 << 2, Time = 1 << 3, Score = 1 << 4, Custom1 = 1 << 10, /// FieldInfo; /** * @param fields Bitwise OR of the @ref Fields that should be listed (Score is always present) * @param parent passed to parent QWidget constructor. */ explicit KScoreDialog(int fields=Name, QWidget *parent=nullptr); ~KScoreDialog(); /** * The group name must be passed though I18N_NOOP() in order for the * group name to be translated. i.e. * \code ksdialog.setConfigGroup(I18N_NOOP("Easy")); \endcode * If you set a group, it will be prefixed in the config file by * 'KHighscore_' otherwise the group will simply be 'KHighscore'. * * @param group to use for reading/writing highscores from/to. * @deprecated since 4.1 */ void KDE_DEPRECATED setConfigGroup(const QString& group = QString()); //void setConfigGroup(const QString& group, const QString& i18nName); /** * The group name must be passed though i18n() in order for the * group name to be translated. i.e. * \code ksdialog.setConfigGroup(qMakePair(QByteArray("Easy"), i18n("Easy"))); \endcode * If you set a group, it will be prefixed in the config file by * 'KHighscore_' otherwise the group will simply be 'KHighscore'. * * @param group to use for reading/writing highscores from/to. */ void setConfigGroup(const QPair& group); /** * You must add the translations of all group names to the dialog. This * is best done by passing the name through i18n(). * The group set through setConfigGroup(const QPair& group) * will be added automatically * * @param group the translated group name */ void addLocalizedConfigGroupName(const QPair& group); /** * You must add the translations of all group names to the dialog. This * is best done by passing the name through i18n(). * The group set through setConfigGroup(const QPair& group) * will be added automatically. * * This function can be used directly with KGameDifficulty::localizedLevelStrings(). * * @param groups the list of translated group names */ void addLocalizedConfigGroupNames(const QMap& groups); /** * Hide some config groups so that they are not shown on the dialog * (but are still stored in the configuration file). * \code * ksdialog.setHiddenConfigGroups(QList() << "Very Easy" << "Easy"); * \endcode * * @param hiddenGroups the list of group names you want to hide * * @since KDE 4.6 */ void setHiddenConfigGroups(const QList& hiddenGroups); /** * It is a good idea giving config group weights, otherwise tabs * get ordered by their tab name that is not probably what you want. * * This function can be used directly with KGameDifficulty::levelWeights(). * * @param weights the list of untranslated group weights * * @since KDE 4.2 */ void setConfigGroupWeights(const QMap& weights); /** * @param comment to add when showing high-scores. * The comment is only used once. */ void setComment(const QString& comment); /** * Define an extra FieldInfo entry. * @param field id of this field @ref Fields e.g. KScoreDialog::Custom1 * @param header text shown in the header in the dialog for this field. e.g. "Number of Moves" * @param key unique key used to store this field. e.g. "moves" */ void addField(int field, const QString& header, const QString& key); /** * Hide a field so that it is not shown on the table (but is still stored in the configuration file). * @param field id of this field @ref Fields e.g. KScoreDialog::Score */ void hideField(int field); /** * Adds a new score to the list. * * @param newInfo info about the score. * @param flags set whether the user should be prompted for their name and how the scores should be sorted * * @returns The highscore position if the score was good enough to * make it into the list (1 being topscore) or 0 otherwise. */ int addScore(const FieldInfo& newInfo = FieldInfo(), const AddScoreFlags& flags=0); /** * Convenience function for ease of use. * * @param newScore the score of the player. * @param flags set whether the user should be prompted for their name and how the scores should be sorted * * @returns The highscore position if the score was good enough to * make it into the list (1 being topscore) or 0 otherwise. */ int addScore(int newScore, const AddScoreFlags& flags=0); /** * @returns the current best score in the group */ int highScore(); /** * Assume that config groups (incl. current selection) are equal to * difficulty levels, and initialize them. This is usually equal to the * following code using KGameDifficulty: * @code * addLocalizedConfigGroupNames(KGameDifficulty::localizedLevelStrings()); * setConfigGroupWeights(KGameDifficulty::levelWeights()); * setConfigGroup(KGameDifficulty::localizedLevelString()); * @endcode */ void initFromDifficulty(const KgDifficulty* difficulty, bool setConfigGroup = true); ///Display the dialog as non-modal virtual void show(); ///Display the dialog as modal - int exec() Q_DECL_OVERRIDE; + int exec() override; private Q_SLOTS: void slotGotReturn(); void slotGotName(); void slotForgetScore(); private: - void keyPressEvent(QKeyEvent *ev) Q_DECL_OVERRIDE; + void keyPressEvent(QKeyEvent *ev) override; private: class KScoreDialogPrivate; KScoreDialogPrivate* const d; }; Q_DECLARE_OPERATORS_FOR_FLAGS(KScoreDialog::AddScoreFlags) #endif //KSCOREDIALOG_H diff --git a/kgamepopupitem.cpp b/kgamepopupitem.cpp index 6e0dbee6..69779bd4 100644 --- a/kgamepopupitem.cpp +++ b/kgamepopupitem.cpp @@ -1,538 +1,538 @@ /******************************************************************* Copyright 2007 Dmitry Suzdalev This library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ********************************************************************/ #include "kgamepopupitem.h" #include #include #include #include #include #include #include #include // margin on the sides of message box static const int MARGIN = 15; // offset of message from start of the scene static const int SHOW_OFFSET = 5; // space between pixmap and text static const int SOME_SPACE = 10; // width of the border in pixels static const qreal BORDER_PEN_WIDTH = 1.0; class TextItemWithOpacity : public QGraphicsTextItem { Q_OBJECT public: TextItemWithOpacity( QGraphicsItem* parent = nullptr ) :QGraphicsTextItem(parent), m_opacity(1.0) {} void setOpacity(qreal opa) { m_opacity = opa; } void setTextColor(const KStatefulBrush &brush) { m_brush = brush; } - void paint( QPainter* p, const QStyleOptionGraphicsItem *option, QWidget* widget ) Q_DECL_OVERRIDE; + void paint( QPainter* p, const QStyleOptionGraphicsItem *option, QWidget* widget ) override; Q_SIGNALS: void mouseClicked(); private: - void mouseReleaseEvent(QGraphicsSceneMouseEvent*) Q_DECL_OVERRIDE; + void mouseReleaseEvent(QGraphicsSceneMouseEvent*) override; private: qreal m_opacity; KStatefulBrush m_brush; }; void TextItemWithOpacity::paint( QPainter* p, const QStyleOptionGraphicsItem *option, QWidget* widget ) { // hope that it is ok to call this function here - i.e. I hope it won't be too expensive :) // we call it here (and not in setTextColor), because KstatefulBrush // absolutely needs QWidget parameter :) //NOTE from majewsky: For some weird reason, setDefaultTextColor does on some systems not check //whether the given color is equal to the one already set. Just calling setDefaultTextColor without //this check may result in an infinite loop of paintEvent -> setDefaultTextColor -> update -> paintEvent... const QColor textColor = m_brush.brush(widget).color(); if (textColor != defaultTextColor()) { setDefaultTextColor(textColor); } //render contents p->save(); p->setOpacity(m_opacity); QGraphicsTextItem::paint(p,option,widget); p->restore(); } void TextItemWithOpacity::mouseReleaseEvent(QGraphicsSceneMouseEvent* ev) { // NOTE: this item is QGraphicsTextItem which "eats" mouse events // because of interaction with links. Because of that let's make a // special signal to indicate mouse click emit mouseClicked(); QGraphicsTextItem::mouseReleaseEvent(ev); } class KGamePopupItemPrivate { private: KGamePopupItemPrivate(const KGamePopupItemPrivate&); const KGamePopupItemPrivate& operator=(const KGamePopupItemPrivate&); public: KGamePopupItemPrivate() : m_position( KGamePopupItem::BottomLeft ), m_timeout(2000), m_opacity(1.0), m_animOpacity(-1), m_hoveredByMouse(false), m_hideOnClick(true), m_textChildItem(0), m_sharpness(KGamePopupItem::Square), m_linkHovered(false) {} /** * Timeline for animations */ QTimeLine m_timeLine; /** * Timer used to start hiding */ QTimer m_timer; /** * Holds bounding rect of an item */ QRectF m_boundRect; /** * Position where item will appear */ KGamePopupItem::Position m_position; /** * Timeout to stay visible on screen */ int m_timeout; /** * Item opacity */ qreal m_opacity; /** * Opacity used while animating appearing in center */ qreal m_animOpacity; /** * Pixmap to display at the left of the text */ QPixmap m_iconPix; /** * Set to true when mouse hovers the message */ bool m_hoveredByMouse; /** * Set to true if this popup item hides on mouse click. */ bool m_hideOnClick; /** * Child of KGamePopupItem used to display text */ TextItemWithOpacity* m_textChildItem; /** * Part of the scene that is actually visible in QGraphicsView * This is needed for item to work correctly when scene is larger than * the View */ QRectF m_visibleSceneRect; /** * Background brush color */ KStatefulBrush m_brush; /** * popup angles sharpness */ KGamePopupItem::Sharpness m_sharpness; /** * painter path to draw a frame */ QPainterPath m_path; /** * Indicates if some link is hovered in text item */ bool m_linkHovered; }; KGamePopupItem::KGamePopupItem(QGraphicsItem * parent) : QGraphicsItem(parent), d(new KGamePopupItemPrivate) { hide(); d->m_textChildItem = new TextItemWithOpacity(this); d->m_textChildItem->setTextInteractionFlags( Qt::LinksAccessibleByMouse ); // above call said to enable ItemIsFocusable which we don't need. // So disabling it d->m_textChildItem->setFlag( QGraphicsItem::ItemIsFocusable, false ); connect(d->m_textChildItem, &TextItemWithOpacity::linkActivated, this, &KGamePopupItem::linkActivated); connect(d->m_textChildItem, &TextItemWithOpacity::linkHovered, this, &KGamePopupItem::onLinkHovered); connect(d->m_textChildItem, &TextItemWithOpacity::mouseClicked, this, &KGamePopupItem::onTextItemClicked); setZValue(100); // is 100 high enough??? d->m_textChildItem->setZValue(100); QIcon infoIcon = QIcon::fromTheme( QStringLiteral( "dialog-information" )); // default size is 32 setMessageIcon( infoIcon.pixmap(32, 32) ); d->m_timer.setSingleShot(true); setAcceptHoverEvents(true); // ignore scene transformations setFlag(QGraphicsItem::ItemIgnoresTransformations, true); // setup default colors d->m_brush = KStatefulBrush( KColorScheme::Tooltip, KColorScheme::NormalBackground ); d->m_textChildItem->setTextColor( KStatefulBrush(KColorScheme::Tooltip, KColorScheme::NormalText) ); connect(&d->m_timeLine, &QTimeLine::frameChanged, this, &KGamePopupItem::animationFrame); connect(&d->m_timeLine, &QTimeLine::finished, this, &KGamePopupItem::hideMe); connect(&d->m_timer, &QTimer::timeout, this, &KGamePopupItem::playHideAnimation); } void KGamePopupItem::paint( QPainter* p, const QStyleOptionGraphicsItem *option, QWidget* widget ) { Q_UNUSED(option); Q_UNUSED(widget); p->save(); QPen pen = p->pen(); pen.setWidthF( BORDER_PEN_WIDTH ); p->setPen(pen); if( d->m_animOpacity != -1) // playing Center animation { p->setOpacity(d->m_animOpacity); } else { p->setOpacity(d->m_opacity); } p->setBrush(d->m_brush.brush(widget)); p->drawPath(d->m_path); p->drawPixmap( MARGIN, static_cast(d->m_boundRect.height()/2) - d->m_iconPix.height()/2, d->m_iconPix ); p->restore(); } void KGamePopupItem::showMessage( const QString& text, Position pos, ReplaceMode mode ) { if(d->m_timeLine.state() == QTimeLine::Running || d->m_timer.isActive()) { if (mode == ReplacePrevious) { forceHide(InstantHide); } else { return;// we're already showing a message } } // NOTE: we blindly take first visible view we found. I.e. we don't support // multiple views. If no visible scene is found, we simply pick the first one. QGraphicsView *sceneView = 0; foreach (QGraphicsView *view, scene()->views()) { if (view->isVisible()) { sceneView = view; break; } } if (!sceneView) { sceneView = scene()->views().at(0); } QPolygonF poly = sceneView->mapToScene( sceneView->viewport()->contentsRect() ); d->m_visibleSceneRect = poly.boundingRect(); d->m_textChildItem->setHtml(text); d->m_position = pos; // do as QGS docs say: notify the scene about rect change prepareGeometryChange(); // recalculate bounding rect qreal w = d->m_textChildItem->boundingRect().width()+MARGIN*2+d->m_iconPix.width()+SOME_SPACE; qreal h = d->m_textChildItem->boundingRect().height()+MARGIN*2; if( d->m_iconPix.height() > h ) { h = d->m_iconPix.height() + MARGIN*2; } d->m_boundRect = QRectF(0, 0, w, h); // adjust to take into account the width of the pen // used to draw the border const qreal borderRadius = BORDER_PEN_WIDTH / 2.0; d->m_boundRect.adjust( -borderRadius , -borderRadius , borderRadius , borderRadius ); QPainterPath roundRectPath; roundRectPath.moveTo(w, d->m_sharpness); roundRectPath.arcTo(w-(2*d->m_sharpness), 0.0,(2*d->m_sharpness), (d->m_sharpness), 0.0, 90.0); roundRectPath.lineTo(d->m_sharpness, 0.0); roundRectPath.arcTo(0.0, 0.0, (2*d->m_sharpness), (2*d->m_sharpness), 90.0, 90.0); roundRectPath.lineTo(0.0, h-(d->m_sharpness)); roundRectPath.arcTo(0.0, h-(2*d->m_sharpness), 2*d->m_sharpness, 2*d->m_sharpness, 180.0, 90.0); roundRectPath.lineTo(w-(d->m_sharpness), h); roundRectPath.arcTo(w-(2*d->m_sharpness), h-(2*d->m_sharpness), (2*d->m_sharpness), (2*d->m_sharpness), 270.0, 90.0); roundRectPath.closeSubpath(); d->m_path = roundRectPath; // adjust y-pos of text item so it appears centered d->m_textChildItem->setPos( d->m_textChildItem->x(), d->m_boundRect.height()/2 - d->m_textChildItem->boundingRect().height()/2); // setup animation setupTimeline(); // move to the start position animationFrame(d->m_timeLine.startFrame()); show(); d->m_timeLine.start(); if(d->m_timeout != 0) { // 300 msec to animate showing message + d->m_timeout to stay visible => then hide d->m_timer.start( 300+d->m_timeout ); } } void KGamePopupItem::setupTimeline() { d->m_timeLine.setDirection( QTimeLine::Forward ); d->m_timeLine.setDuration(300); if( d->m_position == TopLeft || d->m_position == TopRight ) { int start = static_cast(d->m_visibleSceneRect.top() - d->m_boundRect.height() - SHOW_OFFSET); int end = static_cast(d->m_visibleSceneRect.top() + SHOW_OFFSET); d->m_timeLine.setFrameRange( start, end ); } else if( d->m_position == BottomLeft || d->m_position == BottomRight ) { int start = static_cast(d->m_visibleSceneRect.bottom()+SHOW_OFFSET); int end = static_cast(d->m_visibleSceneRect.bottom() - d->m_boundRect.height() - SHOW_OFFSET); d->m_timeLine.setFrameRange( start, end ); } else if( d->m_position == Center ) { d->m_timeLine.setFrameRange(0, d->m_timeLine.duration()); setPos( d->m_visibleSceneRect.left() + d->m_visibleSceneRect.width()/2 - d->m_boundRect.width()/2, d->m_visibleSceneRect.top() + d->m_visibleSceneRect.height()/2 - d->m_boundRect.height()/2); } } void KGamePopupItem::animationFrame(int frame) { if( d->m_position == TopLeft || d->m_position == BottomLeft ) { setPos( d->m_visibleSceneRect.left()+SHOW_OFFSET, frame ); } else if( d->m_position == TopRight || d->m_position == BottomRight ) { setPos( d->m_visibleSceneRect.right()-d->m_boundRect.width()-SHOW_OFFSET, frame ); } else if( d->m_position == Center ) { d->m_animOpacity = frame*d->m_opacity/d->m_timeLine.duration(); d->m_textChildItem->setOpacity( d->m_animOpacity ); update(); } } void KGamePopupItem::playHideAnimation() { if( d->m_hoveredByMouse ) { return; } // let's hide d->m_timeLine.setDirection( QTimeLine::Backward ); d->m_timeLine.start(); } void KGamePopupItem::setMessageTimeout( int msec ) { d->m_timeout = msec; } void KGamePopupItem::setHideOnMouseClick( bool hide ) { d->m_hideOnClick = hide; } bool KGamePopupItem::hidesOnMouseClick() const { return d->m_hideOnClick; } void KGamePopupItem::setMessageOpacity( qreal opacity ) { d->m_opacity = opacity; d->m_textChildItem->setOpacity(opacity); } QRectF KGamePopupItem::boundingRect() const { return d->m_boundRect; } KGamePopupItem::~KGamePopupItem() { delete d; } void KGamePopupItem::hideMe() { d->m_animOpacity = -1; // and restore child's opacity too d->m_textChildItem->setOpacity(d->m_opacity); // if we just got moved out of visibility, let's do more - let's hide :) if( d->m_timeLine.direction() == QTimeLine::Backward ) { hide(); emit hidden(); } } void KGamePopupItem::hoverEnterEvent( QGraphicsSceneHoverEvent* ) { d->m_hoveredByMouse = true; } void KGamePopupItem::hoverLeaveEvent( QGraphicsSceneHoverEvent* ) { d->m_hoveredByMouse = false; if( d->m_timeout != 0 && !d->m_timer.isActive() && d->m_timeLine.state() != QTimeLine::Running ) { playHideAnimation(); // let's hide } } void KGamePopupItem::setMessageIcon( const QPixmap& pix ) { d->m_iconPix = pix; d->m_textChildItem->setPos( MARGIN+pix.width()+SOME_SPACE, MARGIN ); // bounding rect is updated in showMessage() } int KGamePopupItem::messageTimeout() const { return d->m_timeout; } void KGamePopupItem::forceHide(HideType howToHide) { if(!isVisible()) { return; } if(howToHide == InstantHide) { d->m_timeLine.stop(); d->m_timer.stop(); hide(); emit hidden(); } else if(howToHide == AnimatedHide) { // forcefully unset it even if it is set // so we'll hide in any event d->m_hoveredByMouse = false; d->m_timer.stop(); playHideAnimation(); } } qreal KGamePopupItem::messageOpacity() const { return d->m_opacity; } void KGamePopupItem::setBackgroundBrush( const QBrush& brush ) { d->m_brush = KStatefulBrush(brush); } void KGamePopupItem::setTextColor( const QColor& color ) { KStatefulBrush brush(color, d->m_brush.brush(QPalette::Active)); d->m_textChildItem->setTextColor(brush); } void KGamePopupItem::onLinkHovered(const QString& link) { if(link.isEmpty()) { d->m_textChildItem->setCursor( Qt::ArrowCursor ); } else { d->m_textChildItem->setCursor( Qt::PointingHandCursor ); } d->m_linkHovered = !link.isEmpty(); emit linkHovered(link); } void KGamePopupItem::setSharpness( Sharpness sharpness ) { d->m_sharpness = sharpness; } KGamePopupItem::Sharpness KGamePopupItem::sharpness() const { return d->m_sharpness; } void KGamePopupItem::mousePressEvent( QGraphicsSceneMouseEvent* ) { // it is needed to reimplement this function to receive future // mouse release events } void KGamePopupItem::mouseReleaseEvent( QGraphicsSceneMouseEvent* ) { // NOTE: text child item is QGraphicsTextItem which "eats" mouse events // because of interaction with links. Because of that TextItemWithOpacity has // special signal to indicate mouse click which we catch in a onTextItemClicked() // slot if (d->m_hideOnClick) { forceHide(); } } void KGamePopupItem::onTextItemClicked() { // if link is hovered we don't hide as click should go to the link if (d->m_hideOnClick && !d->m_linkHovered) { forceHide(); } } #include "moc_kgamepopupitem.cpp" // For automocing KGamePopupItem #include "kgamepopupitem.moc" // For automocing TextItemWithOpacity diff --git a/kgamepopupitem.h b/kgamepopupitem.h index 13fe64b1..3bdc6039 100644 --- a/kgamepopupitem.h +++ b/kgamepopupitem.h @@ -1,192 +1,192 @@ /******************************************************************* Copyright 2007 Dmitry Suzdalev This library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ********************************************************************/ #ifndef K_GAME_POPUP_ITEM_H #define K_GAME_POPUP_ITEM_H #include #include #include class KGamePopupItemPrivate; /** * \class KGamePopupItem kgamepopupitem.h * * QGraphicsItem capable of showing short popup messages * which do not interrupt the gameplay. * Message can stay on screen for specified amount of time * and automatically hide after (unless user hovers it with mouse). * * Example of use: * \code * KGamePopupItem *messageItem = new KGamePopupItem(); * myGraphicsScene->addItem(messageItem); * ... * messageItem->setMessageTimeout( 3000 ); // 3 sec * messageItem->showMessage("Hello, I'm a game message! How do you do?", BottomLeft); * \endcode */ class KDEGAMES_EXPORT KGamePopupItem : public QObject, public QGraphicsItem { Q_OBJECT Q_INTERFACES(QGraphicsItem) public: /** * Possible values for message showing mode in respect to a previous * message */ enum ReplaceMode { LeavePrevious, ReplacePrevious }; /** * Possible values for the popup angles sharpness */ enum Sharpness { Square=0, Sharp=2, Soft=5, Softest=10 }; /** * The possible places in the scene where a message can be shown */ enum Position { TopLeft, TopRight, BottomLeft, BottomRight, Center }; /** * Constructs a message item. It is hidden by default. */ KGamePopupItem(QGraphicsItem * parent = nullptr); /** * Destructs a message item */ ~KGamePopupItem(); /** * Shows the message: item will appear at specified place * of the scene using simple animation * Item will be automatically hidden after timeout set in setMessageTimeOut() passes * If item is hovered with mouse it won't hide until user moves * the mouse away * * Note that if pos == Center, message animation will be of fade in/out type, * rather than slide in/out * * @param text holds the message to show * @param pos position on the scene where the message will appear * @param mode how to handle an already shown message by this item: either leave it and ignore the new one or replace it */ void showMessage( const QString& text, Position pos, ReplaceMode mode = LeavePrevious); /** * Sets the amount of time the item will stay visible on screen * before it goes away. * By default item is shown for 2000 msec * If item is hovered with mouse it will hide only after * user moves the mouse away * * @param msec amount of time in milliseconds. * if msec is 0, then message will stay visible until it * gets explicitly hidden by forceHide() */ void setMessageTimeout( int msec ); /** * @return timeout that is currently set */ int messageTimeout() const; /** * Sets the message opacity from 0 (fully transparent) to 1 (fully opaque) * For example 0.5 is half transparent * It defaults to 1.0 */ void setMessageOpacity( qreal opacity ); /** * @return current message opacity */ qreal messageOpacity() const; /** * Sets custom pixmap to show instead of default icon on the left */ void setMessageIcon( const QPixmap& pix ); /** * Sets whether to hide this popup item on mouse click. * By default a mouse click will cause an item to hide */ void setHideOnMouseClick( bool hide ); /** * @return whether this popup item hides on mouse click. */ bool hidesOnMouseClick() const; /** * Used to specify how to hide in forceHide() - instantly or animatedly */ enum HideType { InstantHide, AnimatedHide }; /** * Requests the item to be hidden immediately. */ void forceHide(HideType type=AnimatedHide); /** * Sets brush used to paint item background * By default system-default brush is used * @see KColorScheme */ void setBackgroundBrush( const QBrush& brush ); /** * Sets default color for unformatted text * By default system-default color is used * @see KColorScheme */ void setTextColor( const QColor& color ); /** * @return the bounding rect of this item. Reimplemented from QGraphicsItem */ - QRectF boundingRect() const Q_DECL_OVERRIDE; + QRectF boundingRect() const override; /** * Paints item. Reimplemented from QGraphicsItem */ - void paint( QPainter* p, const QStyleOptionGraphicsItem *option, QWidget* widget ) Q_DECL_OVERRIDE; + void paint( QPainter* p, const QStyleOptionGraphicsItem *option, QWidget* widget ) override; /** * Sets the popup angles sharpness */ void setSharpness( Sharpness sharpness ); /** * @return current popup angles sharpness */ Sharpness sharpness() const; Q_SIGNALS: /** * Emitted when user clicks on a link in item */ void linkActivated( const QString& link ); /** * Emitted when user hovers a link in item */ void linkHovered( const QString& link ); /** * Emitted when the popup finishes hiding. This includes hiding caused by * both timeouts and mouse clicks. */ void hidden(); private Q_SLOTS: void animationFrame(int); void hideMe(); void playHideAnimation(); void onLinkHovered(const QString&); void onTextItemClicked(); private: void setupTimeline(); - void mousePressEvent( QGraphicsSceneMouseEvent* ) Q_DECL_OVERRIDE; - void mouseReleaseEvent( QGraphicsSceneMouseEvent* ) Q_DECL_OVERRIDE; - void hoverEnterEvent( QGraphicsSceneHoverEvent* ) Q_DECL_OVERRIDE; - void hoverLeaveEvent( QGraphicsSceneHoverEvent* ) Q_DECL_OVERRIDE; + void mousePressEvent( QGraphicsSceneMouseEvent* ) override; + void mouseReleaseEvent( QGraphicsSceneMouseEvent* ) override; + void hoverEnterEvent( QGraphicsSceneHoverEvent* ) override; + void hoverLeaveEvent( QGraphicsSceneHoverEvent* ) override; KGamePopupItemPrivate * const d; }; #endif diff --git a/kgamerendereditem.h b/kgamerendereditem.h index 28800f02..4a951a77 100644 --- a/kgamerendereditem.h +++ b/kgamerendereditem.h @@ -1,53 +1,53 @@ /*************************************************************************** * Copyright 2010 Stefan Majewsky * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library General Public License * * version 2 as published by the Free Software Foundation * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Library General Public License for more details. * * * * You should have received a copy of the GNU Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #ifndef KGAMERENDEREDITEM_H #define KGAMERENDEREDITEM_H #include #include #include #include class KGameRenderedItemPrivate; /** * @class KGameRenderedItem kgamerendereditem.h * @since 4.6 * @short A QGraphicsPixmapItem which reacts to theme changes automatically. * * This class is a QGraphicsPixmapItem which retrieves its pixmap from a * KGameRenderer, and updates it automatically when the KGameRenderer changes * the theme. */ class KDEGAMES_EXPORT KGameRenderedItem : public QGraphicsPixmapItem, public KGameRendererClient { public: ///Creates a new KGameRenderedItem which renders the sprite with the ///given @a spriteKey as provided by the given @a renderer. KGameRenderedItem(KGameRenderer* renderer, const QString& spriteKey, QGraphicsItem* parent = nullptr); virtual ~KGameRenderedItem(); protected: - void receivePixmap(const QPixmap& pixmap) Q_DECL_OVERRIDE; + void receivePixmap(const QPixmap& pixmap) override; private: friend class KGameRenderedItemPrivate; KGameRenderedItemPrivate* const d; }; #endif // KGAMERENDEREDITEM_H diff --git a/kgamerenderedobjectitem.cpp b/kgamerenderedobjectitem.cpp index 446490e0..310f22c8 100644 --- a/kgamerenderedobjectitem.cpp +++ b/kgamerenderedobjectitem.cpp @@ -1,287 +1,287 @@ /*************************************************************************** * Copyright 2010 Stefan Majewsky * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library General Public License * * version 2 as published by the Free Software Foundation * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Library General Public License for more details. * * * * You should have received a copy of the GNU Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #include "kgamerenderedobjectitem.h" #include "kgamerenderer.h" #include #include class KGameRenderedObjectItemPrivate : public QGraphicsPixmapItem { public: KGameRenderedObjectItemPrivate(KGameRenderedObjectItem* parent); bool adjustRenderSize(); //returns whether an adjustment was made; WARNING: only call when m_primaryView != 0 void adjustTransform(); //QGraphicsItem reimplementations (see comment below for why we need all of this) - bool contains(const QPointF& point) const Q_DECL_OVERRIDE; - bool isObscuredBy(const QGraphicsItem* item) const Q_DECL_OVERRIDE; - QPainterPath opaqueArea() const Q_DECL_OVERRIDE; - void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget = 0) Q_DECL_OVERRIDE; - QPainterPath shape() const Q_DECL_OVERRIDE; + bool contains(const QPointF& point) const override; + bool isObscuredBy(const QGraphicsItem* item) const override; + QPainterPath opaqueArea() const override; + void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget = 0) override; + QPainterPath shape() const override; public: KGameRenderedObjectItem* m_parent; QGraphicsView* m_primaryView; QSize m_correctRenderSize; QSizeF m_fixedSize; }; KGameRenderedObjectItemPrivate::KGameRenderedObjectItemPrivate(KGameRenderedObjectItem* parent) : QGraphicsPixmapItem(parent) , m_parent(parent) , m_primaryView(0) , m_correctRenderSize(0, 0) , m_fixedSize(-1, -1) { } static inline int vectorLength(const QPointF& point) { return qSqrt(point.x() * point.x() + point.y() * point.y()); } bool KGameRenderedObjectItemPrivate::adjustRenderSize() { Q_ASSERT(m_primaryView); //create a polygon from the item's boundingRect const QRectF itemRect = m_parent->boundingRect(); QPolygonF itemPolygon(3); itemPolygon[0] = itemRect.topLeft(); itemPolygon[1] = itemRect.topRight(); itemPolygon[2] = itemRect.bottomLeft(); //determine correct render size const QPolygonF scenePolygon = m_parent->sceneTransform().map(itemPolygon); const QPolygon viewPolygon = m_primaryView->mapFromScene(scenePolygon); m_correctRenderSize.setWidth(qMax(vectorLength(viewPolygon[1] - viewPolygon[0]), 1)); m_correctRenderSize.setHeight(qMax(vectorLength(viewPolygon[2] - viewPolygon[0]), 1)); //ignore fluctuations in the render size which result from rounding errors const QSize diff = m_parent->renderSize() - m_correctRenderSize; if (qAbs(diff.width()) <= 1 && qAbs(diff.height()) <= 1) { return false; } m_parent->setRenderSize(m_correctRenderSize); adjustTransform(); return true; } void KGameRenderedObjectItemPrivate::adjustTransform() { //calculate new transform for this item QTransform t; t.scale(m_fixedSize.width() / m_correctRenderSize.width(), m_fixedSize.height() / m_correctRenderSize.height()); //render item m_parent->prepareGeometryChange(); setTransform(t); m_parent->update(); } KGameRenderedObjectItem::KGameRenderedObjectItem(KGameRenderer* renderer, const QString& spriteKey, QGraphicsItem* parent) : QGraphicsObject(parent) , KGameRendererClient(renderer, spriteKey) , d(new KGameRenderedObjectItemPrivate(this)) { setPrimaryView(renderer->defaultPrimaryView()); } KGameRenderedObjectItem::~KGameRenderedObjectItem() { delete d; } QPointF KGameRenderedObjectItem::offset() const { return d->pos(); } void KGameRenderedObjectItem::setOffset(const QPointF& offset) { if (d->pos() != offset) { prepareGeometryChange(); d->setPos(offset); update(); } } void KGameRenderedObjectItem::setOffset(qreal x, qreal y) { setOffset(QPointF(x, y)); } QSizeF KGameRenderedObjectItem::fixedSize() const { return d->m_fixedSize; } void KGameRenderedObjectItem::setFixedSize(const QSizeF& fixedSize) { if (d->m_primaryView) { d->m_fixedSize = fixedSize.expandedTo(QSize(1, 1)); d->adjustTransform(); } } QGraphicsView* KGameRenderedObjectItem::primaryView() const { return d->m_primaryView; } void KGameRenderedObjectItem::setPrimaryView(QGraphicsView* view) { if (d->m_primaryView != view) { d->m_primaryView = view; if (view) { if (!d->m_fixedSize.isValid()) { d->m_fixedSize = QSize(1, 1); } //determine render size and adjust coordinate system d->m_correctRenderSize = QSize(-10, -10); //force adjustment to be made d->adjustRenderSize(); } else { d->m_fixedSize = QSize(-1, -1); //reset transform to make coordinate systems of this item and the private item equal prepareGeometryChange(); d->setTransform(QTransform()); update(); } } } void KGameRenderedObjectItem::receivePixmap(const QPixmap& pixmap) { prepareGeometryChange(); d->setPixmap(pixmap); update(); } //We want to make sure that all interactional events are sent ot this item, and //not to the contained QGraphicsPixmapItem which provides the visual //representation (and the metrics calculations). //At the same time, we do not want the contained QGraphicsPixmapItem to slow //down operations like QGraphicsScene::collidingItems(). //So the strategy is to use the QGraphicsPixmapItem implementation from //KGameRenderedObjectItemPrivate for KGameRenderedObjectItem. //Then the relevant methods in KGameRenderedObjectItemPrivate are reimplemented empty //to effectively clear the item and hide it from any collision detection. This //strategy allows us to use the nifty QGraphicsPixmapItem logic without exposing //a QGraphicsPixmapItem subclass (which would conflict with QGraphicsObject). //BEGIN QGraphicsItem reimplementation of KGameRenderedObjectItem QRectF KGameRenderedObjectItem::boundingRect() const { return d->mapRectToParent(d->QGraphicsPixmapItem::boundingRect()); } bool KGameRenderedObjectItem::contains(const QPointF& point) const { return d->QGraphicsPixmapItem::contains(d->mapFromParent(point)); } bool KGameRenderedObjectItem::isObscuredBy(const QGraphicsItem* item) const { return d->QGraphicsPixmapItem::isObscuredBy(item); } QPainterPath KGameRenderedObjectItem::opaqueArea() const { return d->mapToParent(d->QGraphicsPixmapItem::opaqueArea()); } void KGameRenderedObjectItem::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) { Q_UNUSED(painter) Q_UNUSED(option) Q_UNUSED(widget) } QPainterPath KGameRenderedObjectItem::shape() const { return d->mapToParent(d->QGraphicsPixmapItem::shape()); } //END QGraphicsItem reimplementation of KGameRenderedObjectItem //BEGIN QGraphicsItem reimplementation of KGameRenderedObjectItemPrivate bool KGameRenderedObjectItemPrivate::contains(const QPointF& point) const { Q_UNUSED(point) return false; } bool KGameRenderedObjectItemPrivate::isObscuredBy(const QGraphicsItem* item) const { Q_UNUSED(item) return false; } QPainterPath KGameRenderedObjectItemPrivate::opaqueArea() const { return QPainterPath(); } void KGameRenderedObjectItemPrivate::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) { //Trivial stuff up to now. The fun stuff starts here. ;-) //There is no way to get informed when the viewport's coordinate system //(relative to this item's coordinate system) has changed, so we're checking //the renderSize in each paintEvent coming from the primary view. if (m_primaryView) { if (m_primaryView == widget || m_primaryView->isAncestorOf(widget)) { const bool isSimpleTransformation = !painter->transform().isRotating(); //If an adjustment was made, do not paint now, but wait for the next //painting. However, paint directly if the transformation is //complex, in order to avoid flicker. if (adjustRenderSize()) { if (isSimpleTransformation) { return; } } if (isSimpleTransformation) { //draw pixmap directly in physical coordinates const QPoint basePos = painter->transform().map(QPointF()).toPoint(); painter->save(); painter->setTransform(QTransform()); painter->drawPixmap(basePos, pixmap()); painter->restore(); return; } } } QGraphicsPixmapItem::paint(painter, option, widget); } QPainterPath KGameRenderedObjectItemPrivate::shape() const { return QPainterPath(); } //END QGraphicsItem reimplementation of KGameRenderedObjectItemPrivate diff --git a/kgamerenderedobjectitem.h b/kgamerenderedobjectitem.h index b30624b5..880c7278 100644 --- a/kgamerenderedobjectitem.h +++ b/kgamerenderedobjectitem.h @@ -1,112 +1,112 @@ /*************************************************************************** * Copyright 2010 Stefan Majewsky * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library General Public License * * version 2 as published by the Free Software Foundation * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Library General Public License for more details. * * * * You should have received a copy of the GNU Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #ifndef KGAMERENDEREDOBJECTITEM_H #define KGAMERENDEREDOBJECTITEM_H #include #include class QGraphicsView; #include #include class KGameRenderedObjectItemPrivate; /** * @class KGameRenderedObjectItem kgamerenderedobjectitem.h * @since 4.6 * @short A QGraphicsObject which displays pixmaps from a KGameRenderer. * * This item displays a pixmap which is retrieved from a KGameRenderer, and is * updated automatically when the KGameRenderer changes the theme. * * The item has built-in handling for animated sprites (i.e. those with multiple * frames). It is a QGraphicsObject and exposes a "frame" property, so you can * easily run the animation by plugging in a QPropertyAnimation. * * @section operationalmodes Modes of operation * * By default, this item behaves just like a QGraphicsPixmapItem. The size of * its bounding rect is equal to the size of the pixmap, i.e. the renderSize(). * * However, the KGameRenderedObjectItem has a second mode of operation, which is * enabled by setting a "primary view". (This can be done automatically via * KGameRenderer::setDefaultPrimaryView.) * * If such a primary view is set, the following happens: * \li The renderSize of the pixmap is automatically determined from the * painting requests received from the primary view (manual calls to * setRenderSize() are unnecessary and need to be avoided). * \li The size of the item's boundingRect() is independent of the renderSize(). * The default fixedSize() is 1x1, which means that the item's bounding rect * is the unit square (moved by the configured offset()). */ class KDEGAMES_EXPORT KGameRenderedObjectItem : public QGraphicsObject, public KGameRendererClient { Q_OBJECT Q_PROPERTY(int frame READ frame WRITE setFrame) public: ///Creates a new KGameRenderedObjectItem which renders the sprite with ///the given @a spriteKey as provided by the given @a renderer. KGameRenderedObjectItem(KGameRenderer* renderer, const QString& spriteKey, QGraphicsItem* parent = nullptr); virtual ~KGameRenderedObjectItem(); ///@return the item's offset, which defines the point of the top-left ///corner of the bounding rect, in local coordinates. QPointF offset() const; ///Sets the item's offset, which defines the point of the top-left ///corner of the bounding rect, in local coordinates. void setOffset(const QPointF& offset); ///@overload void setOffset(qreal x, qreal y); ///@return the fixed size of this item (or (-1, -1) if this item has no ///primary view) QSizeF fixedSize() const; ///Sets the fixed size of this item, i.e. the guaranteed size of the ///item. This works only when a primary view has been set. void setFixedSize(const QSizeF& size); ///Returns a pointer to the current primary view, or 0 if no primary ///view has been set (which is the default). ///@see setPrimaryView() QGraphicsView* primaryView() const; ///Sets the primary view of this item. (See class documentation for what ///the primary view does.) Pass a null pointer to just disconnect from ///the current primary view. The fixed size is then reset to (-1, -1). ///If a primary view is set, the fixed size is initialized to (1, 1). ///@warning While a primary view is set, avoid any manual calls to ///setRenderSize(). ///@see {Modes of operation} void setPrimaryView(QGraphicsView* view); //QGraphicsItem reimplementations (see comment in source file for why we need all of this) - QRectF boundingRect() const Q_DECL_OVERRIDE; - bool contains(const QPointF& point) const Q_DECL_OVERRIDE; - bool isObscuredBy(const QGraphicsItem* item) const Q_DECL_OVERRIDE; - QPainterPath opaqueArea() const Q_DECL_OVERRIDE; - void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget = 0) Q_DECL_OVERRIDE; - QPainterPath shape() const Q_DECL_OVERRIDE; + QRectF boundingRect() const override; + bool contains(const QPointF& point) const override; + bool isObscuredBy(const QGraphicsItem* item) const override; + QPainterPath opaqueArea() const override; + void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget = 0) override; + QPainterPath shape() const override; protected: - void receivePixmap(const QPixmap& pixmap) Q_DECL_OVERRIDE; + void receivePixmap(const QPixmap& pixmap) override; private: friend class KGameRenderedObjectItemPrivate; KGameRenderedObjectItemPrivate* const d; }; #endif // KGAMERENDEREDOBJECTITEM_H diff --git a/kgamerenderer_p.h b/kgamerenderer_p.h index e435dbed..72f2d993 100644 --- a/kgamerenderer_p.h +++ b/kgamerenderer_p.h @@ -1,177 +1,177 @@ /*************************************************************************** * Copyright 2010 Stefan Majewsky * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library General Public License * * version 2 as published by the Free Software Foundation * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Library General Public License for more details. * * * * You should have received a copy of the GNU Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #ifndef KGAMERENDERER_P_H #define KGAMERENDERER_P_H #include #include #include #include #include #include #include namespace KGRInternal { //Describes the state of a KGameRendererClient. struct ClientSpec { // The parentheses around QHash() avoid compile // errors on platforms with older gcc versions, e.g. OS X 10.6. inline ClientSpec(const QString& spriteKey = QString(), int frame = -1, const QSize& size = QSize(), const QHash& customColors = (QHash())); QString spriteKey; int frame; QSize size; QHash customColors; }; ClientSpec::ClientSpec(const QString& spriteKey_, int frame_, const QSize& size_, const QHash& customColors_) : spriteKey(spriteKey_) , frame(frame_) , size(size_) , customColors(customColors_) { } //Instantiates QSvgRenderer instances from one SVG file for multiple threads. class RendererPool { public: //The renderer pool needs the thread pool instance of //KGameRendererPrivate to terminate workers when a new SVG is loaded. //WARNING Call this only from the main thread. inline RendererPool(QThreadPool* threadPool); inline ~RendererPool(); //The second argument can be used to pass an instance which has been //used earlier to check the validity of the SVG file. inline void setPath(const QString& graphicsPath, QSvgRenderer* renderer = 0); //This can be used to determine whether a call to allocRenderer() //would need to create a new renderer instance. inline bool hasAvailableRenderers() const; //Returns a SVG renderer instance that can be used in the calling thread. inline QSvgRenderer* allocRenderer(); //Marks this renderer as available for allocation by other threads. inline void freeRenderer(QSvgRenderer* renderer); private: QString m_path; //path to SVG file enum Validity { Checked_Invalid, Checked_Valid, Unchecked }; Validity m_valid; //holds whether m_path points to a valid file mutable QMutex m_mutex; QThreadPool* m_threadPool; QHash m_hash; }; //Describes a rendering job which is delegated to a worker thread. struct Job { KGRInternal::RendererPool* rendererPool; ClientSpec spec; QString cacheKey, elementKey; QImage result; }; //Describes a worker thread. class Worker : public QRunnable { public: Worker(Job* job, bool isSynchronous, KGameRendererPrivate* parent); - void run() Q_DECL_OVERRIDE; + void run() override; private: Job* m_job; bool m_synchronous; KGameRendererPrivate* m_parent; }; } Q_DECLARE_METATYPE(KGRInternal::Job*) class KGameRendererPrivate : public QObject { Q_OBJECT public: KGameRendererPrivate(KgThemeProvider* provider, unsigned cacheSize, KGameRenderer* parent); void _k_setTheme(const KgTheme* theme); bool setTheme(const KgTheme* theme); inline QString spriteFrameKey(const QString& key, int frame, bool normalizeFrameNo = false) const; void requestPixmap(const KGRInternal::ClientSpec& spec, KGameRendererClient* client, QPixmap* synchronousResult = 0); private: inline void requestPixmap__propagateResult(const QPixmap& pixmap, KGameRendererClient* client, QPixmap* synchronousResult); public Q_SLOTS: void jobFinished(KGRInternal::Job* job, bool isSynchronous); //NOTE: This is invoked from KGRInternal::Worker::run. public: KGameRenderer* m_parent; KgThemeProvider* m_provider; const KgTheme* m_currentTheme; QString m_frameSuffix, m_sizePrefix, m_frameCountPrefix, m_boundsPrefix; unsigned m_cacheSize; KGameRenderer::Strategies m_strategies; int m_frameBaseIndex; QGraphicsView* m_defaultPrimaryView; QThreadPool m_workerPool; KGRInternal::RendererPool m_rendererPool; QHash m_clients; //maps client -> cache key of current pixmap QStringList m_pendingRequests; //cache keys of pixmaps which are currently being rendered KImageCache* m_imageCache; //In multi-threaded scenarios, there are two possible ways to use KIC's //pixmap cache. //1. The worker renders a QImage and stores it in the cache. The main // thread reads the QImage again and converts it into a QPixmap, // storing it in the pixmap cache for later re-use. //i.e. QImage -> diskcache -> QImage -> QPixmap -> pixmapcache -> serve //2. The worker renders a QImage and sends it directly to the main // thread, which converts it to a QPixmap. The QPixmap is stored in // KIC's pixmap cache, and converted to QImage to be written to the // shared data cache. //i.e. QImage -> QPixmap -> pixmapcache -> serve // \-> QImage -> diskcache //We choose a third way: //3. The worker renders a QImage which is converted to a QPixmap by the // main thread. The main thread caches the QPixmap itself, and stores // the QImage in the cache. //i.e. QImage -> QPixmap -> pixmapcache -> serve // \-> diskcache //As you see, implementing an own pixmap cache saves us one conversion. //We therefore disable KIC's pixmap cache because we do not need it. QHash m_pixmapCache; QHash m_frameCountCache; QHash m_boundsCache; }; class KGameRendererClientPrivate : public QObject { Q_OBJECT public: KGameRendererClientPrivate(KGameRenderer* renderer, const QString& spriteKey, KGameRendererClient* parent); public Q_SLOTS: void fetchPixmap(); public: KGameRendererClient* m_parent; KGameRenderer* m_renderer; KGRInternal::ClientSpec m_spec; }; #endif // KGAMERENDERER_P_H diff --git a/kgimageprovider_p.h b/kgimageprovider_p.h index d7aa7693..160ede1a 100644 --- a/kgimageprovider_p.h +++ b/kgimageprovider_p.h @@ -1,62 +1,62 @@ /*************************************************************************** * Copyright 2012 Viranch Mehta * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library General Public License * * version 2 as published by the Free Software Foundation * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Library General Public License for more details. * * * * You should have received a copy of the GNU Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #ifndef KGIMAGEPROVIDER_H #define KGIMAGEPROVIDER_H #include #include class KgThemeProvider; /** * @class KgImageProvider * @since 4.11 * @short A QDeclarativeImageProvider that renders requested sprites and * returns corresponding pixmap to the QML view. * * This class is a QDeclarativeImageProvider that takes a KgThemeProvider * in its constructor and uses it to get full path to SVGs. These theme * SVGs are read and requested sprite pixmap is extracted and given to * the QML image element that requests it. * * For porting KDE games to QML, there is a KgItem QML component provided * by KgCore QML plugin which is a small wrapper to request pixmaps from * this KgImageProvider. See KgItem's documentation for details. */ class KgImageProvider : public QQuickImageProvider { public: ///Construcs a new KgImageProvider with the supplied KgThemeProvider ///@param provider The KgThemeProvider used to discover the game's ///themes. KgImageProvider(KgThemeProvider* provider); ///Reimplemented method that is called when a sprite pixmap is requested - QImage requestImage(const QString& source, QSize *size, const QSize &requestedSize) Q_DECL_OVERRIDE; + QImage requestImage(const QString& source, QSize *size, const QSize &requestedSize) override; private: void reloadRenderer(); QString m_themeName; KgThemeProvider* m_provider; QSvgRenderer m_renderer; }; #endif //KGIMAGEPROVIDER_H diff --git a/kgthemeselector.cpp b/kgthemeselector.cpp index e3bb6bc7..3510c174 100644 --- a/kgthemeselector.cpp +++ b/kgthemeselector.cpp @@ -1,342 +1,342 @@ /*************************************************************************** * Copyright 2009-2012 Stefan Majewsky * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library General Public License * * version 2 as published by the Free Software Foundation * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Library General Public License for more details. * * * * You should have received a copy of the GNU Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #include "kgthemeselector.h" #include "kgthemeselector_p.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace Metrics { const int Padding = 6; const QSize ThumbnailBaseSize(64, 64); } //BEGIN KgThemeSelector class KgThemeSelector::Private { public: KgThemeSelector* q; KgThemeProvider* m_provider; Options m_options; QListWidget* m_list; QPushButton* m_knsButton; void fillList(); Private(KgThemeProvider* provider, Options options, KgThemeSelector* q) : q(q), m_provider(provider), m_options(options), m_knsButton(0) {} void _k_updateListSelection(const KgTheme* theme); void _k_updateProviderSelection(); void _k_showNewStuffDialog(); }; KgThemeSelector::KgThemeSelector(KgThemeProvider* provider, Options options, QWidget* parent) : QWidget(parent) , d(new Private(provider, options, this)) { d->m_list = new QListWidget(this); d->m_list->setSelectionMode(QAbstractItemView::SingleSelection); d->m_list->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel); //load themes from provider d->fillList(); //setup appearance of the theme list (min. size = 4 items) KgThemeDelegate* delegate = new KgThemeDelegate(d->m_list); const QSize itemSizeHint = delegate->sizeHint(QStyleOptionViewItem(), QModelIndex()); const QSize scrollBarSizeHint = d->m_list->verticalScrollBar()->sizeHint(); d->m_list->setMinimumSize(itemSizeHint.width() + 2 * scrollBarSizeHint.width(), 4.1 * itemSizeHint.height()); //monitor change selection in both directions connect(d->m_provider, SIGNAL(currentThemeChanged(const KgTheme*)), SLOT(_k_updateListSelection(const KgTheme*))); connect(d->m_list, SIGNAL(itemSelectionChanged()), SLOT(_k_updateProviderSelection())); //setup main layout QVBoxLayout* layout = new QVBoxLayout(this); layout->setContentsMargins(0, 0, 0, 0); layout->addWidget(d->m_list); //setup KNS button if (options & EnableNewStuffDownload) { d->m_knsButton = new QPushButton(QIcon::fromTheme(QStringLiteral("get-hot-new-stuff")), i18n("Get New Themes..."), this); layout->addWidget(d->m_knsButton); connect(d->m_knsButton, SIGNAL(clicked()), SLOT(_k_showNewStuffDialog())); } } KgThemeSelector::~KgThemeSelector() { delete d; } void KgThemeSelector::Private::fillList() { m_list->clear(); foreach (const KgTheme* theme, m_provider->themes()) { QListWidgetItem* item = new QListWidgetItem(theme->name(), m_list); item->setData(Qt::DecorationRole, m_provider->generatePreview(theme, Metrics::ThumbnailBaseSize)); item->setData(KgThemeDelegate::DescriptionRole, theme->description()); item->setData(KgThemeDelegate::AuthorRole, theme->author()); item->setData(KgThemeDelegate::AuthorEmailRole, theme->authorEmail()); item->setData(KgThemeDelegate::IdRole, theme->identifier()); } _k_updateListSelection(m_provider->currentTheme()); } void KgThemeSelector::Private::_k_updateListSelection(const KgTheme* theme) { for (int idx = 0; idx < m_list->count(); ++idx) { QListWidgetItem* item = m_list->item(idx); const QByteArray thisId = item->data(KgThemeDelegate::IdRole).toByteArray(); if (thisId == theme->identifier()) { m_list->setCurrentItem(item, QItemSelectionModel::ClearAndSelect); return; } } //make sure that something is selected if (m_list->count() > 0) { m_list->setCurrentRow(0, QItemSelectionModel::ClearAndSelect); } } void KgThemeSelector::Private::_k_updateProviderSelection() { const QListWidgetItem* selItem = m_list->selectedItems().value(0); if (!selItem) { return; } const QByteArray selId = selItem->data(KgThemeDelegate::IdRole).toByteArray(); //select the theme with this identifier foreach (const KgTheme* theme, m_provider->themes()) { if (theme->identifier() == selId) { m_provider->setCurrentTheme(theme); } } } void KgThemeSelector::Private::_k_showNewStuffDialog() { QPointer dialog(new KNS3::DownloadDialog(q)); dialog->exec(); if (dialog && !dialog->changedEntries().isEmpty()) { m_provider->rediscoverThemes(); fillList(); } //restore previous selection _k_updateListSelection(m_provider->currentTheme()); delete dialog; } class KgThemeSelector::Dialog : public QDialog { public: Dialog(KgThemeSelector* sel, const QString& caption) : mSelector(sel) { QVBoxLayout *mainLayout = new QVBoxLayout; setLayout(mainLayout); mainLayout->addWidget(sel); //replace QPushButton* btn = sel->d->m_knsButton; QDialogButtonBox *buttonBox = new QDialogButtonBox(this); if (btn) { btn->hide(); QPushButton *stuff = new QPushButton(QIcon::fromTheme(QStringLiteral("get-hot-new-stuff")), btn->text()); buttonBox->addButton(stuff, QDialogButtonBox::ActionRole); buttonBox->addButton(QDialogButtonBox::Close); connect(stuff, &QAbstractButton::clicked, btn, &QAbstractButton::clicked); connect(buttonBox, &QDialogButtonBox::rejected, this, &KgThemeSelector::Dialog::reject); } else { buttonBox->setStandardButtons(QDialogButtonBox::Close); connect(buttonBox, &QDialogButtonBox::rejected, this, &KgThemeSelector::Dialog::reject); } //window caption if (caption.isEmpty()) { setWindowTitle(i18nc("@title:window config dialog", "Select theme")); } else { setWindowTitle(caption); } mainLayout->addWidget(buttonBox); show(); } protected: - void closeEvent(QCloseEvent* event) Q_DECL_OVERRIDE + void closeEvent(QCloseEvent* event) override { event->accept(); //delete myself, but *not* the KgThemeSelector mSelector->setParent(0); deleteLater(); //restore the KNS button if (mSelector->d->m_knsButton) { mSelector->d->m_knsButton->show(); } } private: KgThemeSelector* mSelector; }; void KgThemeSelector::showAsDialog(const QString& caption) { if (!isVisible()) { new KgThemeSelector::Dialog(this, caption); } } //END KgThemeSelector //BEGIN KgThemeDelegate KgThemeDelegate::KgThemeDelegate(QObject* parent) : QStyledItemDelegate(parent) { QAbstractItemView* view = qobject_cast(parent); if (view) view->setItemDelegate(this); } QRect KgThemeDelegate::thumbnailRect(const QRect& baseRect) const { QRect thumbnailBaseRect(QPoint(Metrics::Padding + baseRect.left(), 0), Metrics::ThumbnailBaseSize); thumbnailBaseRect.moveCenter(QPoint(thumbnailBaseRect.center().x(), baseRect.center().y())); if (QApplication::isRightToLeft()) thumbnailBaseRect.moveRight(baseRect.right() - Metrics::Padding); return thumbnailBaseRect; } void KgThemeDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const { const bool rtl = option.direction == Qt::RightToLeft; QRect baseRect = option.rect; //draw background QApplication::style()->drawPrimitive(QStyle::PE_PanelItemViewItem, &option, painter, 0); //draw thumbnail QRect thumbnailBaseRect = this->thumbnailRect(baseRect); const QPixmap thumbnail = index.data(Qt::DecorationRole).value(); QApplication::style()->drawItemPixmap(painter, thumbnailBaseRect, Qt::AlignCenter, thumbnail); //find metrics: text QStringList texts; QList fonts; { QString name = index.data(Qt::DisplayRole).toString(); if (name.isEmpty()) name = i18n("[No name]"); texts << name; QFont theFont(painter->font()); theFont.setBold(true); fonts << theFont; }{ QString comment = index.data(DescriptionRole).toString(); if (!comment.isEmpty()) { texts << comment; fonts << painter->font(); } }{ QString author = index.data(AuthorRole).toString(); if (!author.isEmpty()) { const QString authorString = ki18nc("Author attribution, e.g. \"by Jack\"", "by %1").subs(author).toString(); texts << authorString; QFont theFont(painter->font()); theFont.setItalic(true); fonts << theFont; } } //TODO: display AuthorEmailRole QList textRects; int totalTextHeight = 0; for (int i = 0; i < texts.count(); ++i) { QFontMetrics fm(fonts[i]); textRects << fm.boundingRect(texts[i]); textRects[i].setHeight(qMax(textRects[i].height(), fm.lineSpacing())); totalTextHeight += textRects[i].height(); } QRect textBaseRect(baseRect); if (rtl) { textBaseRect.setRight(thumbnailBaseRect.left() - Metrics::Padding); textBaseRect.adjust(Metrics::Padding, Metrics::Padding, 0, -Metrics::Padding); } else { textBaseRect.setLeft(thumbnailBaseRect.right() + Metrics::Padding); textBaseRect.adjust(0, Metrics::Padding, -Metrics::Padding, -Metrics::Padding); } textBaseRect.setHeight(totalTextHeight); textBaseRect.moveTop(baseRect.top() + (baseRect.height() - textBaseRect.height()) / 2); //draw texts QRect currentTextRect(textBaseRect); painter->save(); for (int i = 0; i < texts.count(); ++i) { painter->setFont(fonts[i]); const QRect& textRect = textRects[i]; currentTextRect.setHeight(textRect.height()); const QFontMetrics fm(fonts[i]); const QString text = fm.elidedText(texts[i], Qt::ElideRight, currentTextRect.width()); painter->drawText(currentTextRect, Qt::AlignLeft | Qt::AlignVCenter, text); currentTextRect.moveTop(currentTextRect.bottom()); } painter->restore(); } QSize KgThemeDelegate::sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const { Q_UNUSED(option) Q_UNUSED(index) //TODO: take text size into account return QSize(400, Metrics::ThumbnailBaseSize.height() + 2 * Metrics::Padding); } //END KgThemeDelegate #include "moc_kgthemeselector.cpp" diff --git a/kgthemeselector_p.h b/kgthemeselector_p.h index c6607920..b37a00b3 100644 --- a/kgthemeselector_p.h +++ b/kgthemeselector_p.h @@ -1,44 +1,44 @@ /*************************************************************************** * Copyright 2009-2012 Stefan Majewsky * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library General Public License * * version 2 as published by the Free Software Foundation * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Library General Public License for more details. * * * * You should have received a copy of the GNU Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #ifndef KG_THEMESELECTOR_P_H #define KG_THEMESELECTOR_P_H #include #include class KgThemeDelegate : public QStyledItemDelegate { public: enum Roles { DescriptionRole = Qt::UserRole, AuthorRole, AuthorEmailRole, IdRole //not displayed, but used internally }; KgThemeDelegate(QObject* parent = nullptr); - void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const Q_DECL_OVERRIDE; + void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const override; ///@note The implementation is independent of @a option and @a index. - QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const Q_DECL_OVERRIDE; + QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const override; QRect thumbnailRect(const QRect& baseRect) const; }; #endif // KG_THEMESELECTOR_P_H diff --git a/libkdegamesprivate/kchatbaseitemdelegate.h b/libkdegamesprivate/kchatbaseitemdelegate.h index 6d243ac6..4126e1eb 100644 --- a/libkdegamesprivate/kchatbaseitemdelegate.h +++ b/libkdegamesprivate/kchatbaseitemdelegate.h @@ -1,80 +1,80 @@ /* This file is part of the KDE games library Copyright (C) 2007 Gael de Chalendar (aka Kleag) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 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 Library General Public License for more details. You should have received a copy of the GNU Library 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 __KCHATBASEITEMDELEGATE_H__ #define __KCHATBASEITEMDELEGATE_H__ #include #include "libkdegamesprivate_export.h" /** * \class KChatBaseItemDelegate kchatbaseitemdelegate.h * * A delegate (see the Qt Model/View module for details) to paint the lines of * the KChatBase list model (@ref KChatBaseModel). * * A KChatBaseItemDelegate paints two text items: first the player part then the * text part. This honors KChatBase::addMessage which also uses both. * * Colors and fonts for both parts are set in the corresponding model. **/ class KDEGAMESPRIVATE_EXPORT KChatBaseItemDelegate : public QAbstractItemDelegate { Q_OBJECT public: /** * Constructs a KChatBaseItemDelegate object **/ explicit KChatBaseItemDelegate(QObject *parent = nullptr); /** * Destruct a KChatBaseItemDelegate object. **/ virtual ~KChatBaseItemDelegate(); /** * Reimplementation of the default paint method. Draws the item at the * given index in the model with good fonts for player name and message. * * Should be reimplemented in inherited delegates */ void paint(QPainter *painter, const QStyleOptionViewItem &option, - const QModelIndex &index) const Q_DECL_OVERRIDE; + const QModelIndex &index) const override; void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index, const QString& sender, const QString& message) const; /** * Reimplementation of the default sizeHint. Computes the given item size * depending on the name and message sizes and on the fonts they use. * * Should be reimplemented in inherited delegates */ QSize sizeHint(const QStyleOptionViewItem &option, - const QModelIndex &index ) const Q_DECL_OVERRIDE; + const QModelIndex &index ) const override; virtual QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index, const QString& sender, const QString& message) const; }; #endif diff --git a/libkdegamesprivate/kchatbasemodel.h b/libkdegamesprivate/kchatbasemodel.h index e203bd68..76172a39 100644 --- a/libkdegamesprivate/kchatbasemodel.h +++ b/libkdegamesprivate/kchatbasemodel.h @@ -1,236 +1,236 @@ /* This file is part of the KDE games library Copyright (C) 2001 Andreas Beckermann (b_mann@gmx.de) Copyright (C) 2007 Gael de Chalendar (aka Kleag) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 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 Library General Public License for more details. You should have received a copy of the GNU Library 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 __KCHATBASEMODEL_H__ #define __KCHATBASEMODEL_H__ #include #include #include #include "libkdegamesprivate_export.h" Q_DECLARE_LOGGING_CATEGORY(GAMES_LIB) class KChatBaseModelPrivate; class KChatBaseMessagePrivate; class KConfig; /** * \class KChatBaseMessage kchatbasemodel.h * * @short The class of the elements stored in the chat list model * * It's a pair of strings where the first element is the sender name and the * second one is the actual message. It furthermore indicates the type of the * message: normal or system */ class KDEGAMESPRIVATE_EXPORT KChatBaseMessage : public QPair< QString, QString > { public: /** The different types of messages */ enum MessageType { Normal, System }; /** Default constructor. Necessary for Qt metatypes */ KChatBaseMessage(); /** Initializing constructor */ KChatBaseMessage(const QString& sender, const QString& message, MessageType type=Normal); /** Copy constructor. Necessary for Qt metatypes */ KChatBaseMessage(const KChatBaseMessage& m); /** Default destructor */ virtual ~KChatBaseMessage(); private: KChatBaseMessagePrivate* d; }; Q_DECLARE_METATYPE(KChatBaseMessage) /** * \class KChatBaseModel kchatbasemodel.h * * The model used to store messages displayed in the chat dialog messages * list. This is a list model and thus derived from @ref QAbstractListModel * and implementing its abstract API. */ class KDEGAMESPRIVATE_EXPORT KChatBaseModel : public QAbstractListModel { Q_OBJECT public: /** Default constructor */ explicit KChatBaseModel(QObject *parent = nullptr); /** Default destructor */ - ~KChatBaseModel() Q_DECL_OVERRIDE; + ~KChatBaseModel() override; /** * Reimplementation of the inherited method. * @return The current number of messages in the list */ - int rowCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE; + int rowCount(const QModelIndex &parent = QModelIndex()) const override; /** * Reimplementation of the inherited method. * @return The KChatBaseMessage at the given index as a QVariant */ - QVariant data(const QModelIndex &index, int role) const Q_DECL_OVERRIDE; + QVariant data(const QModelIndex &index, int role) const override; /** * Set the font that is used for the name part of a message. See also * nameFont and setBothFont **/ void setNameFont(const QFont& font); /** * Set the font that is used for the message part of a message. * @see messageFont, setBothFont **/ void setMessageFont(const QFont& font); /** * This sets both - nameFont and messageFont to font. You * probably want to use this if you don't wish to distinguish between * these parts of a message. * @param font A font used for both nameFont and messageFont **/ void setBothFont(const QFont& font); /** * Same as setNameFont but applies only to system messages. **/ void setSystemNameFont(const QFont& font); /** * Same as setMessageFont but applies only to system messages. **/ void setSystemMessageFont(const QFont& font); /** * Same as setBothFont but applies only to system messages. **/ void setSystemBothFont(const QFont& font); /** * This font should be used for the name (the "from: " part) of a * message. layoutMessage uses this to set the font using * KChatBaseItemDelegate::setNameFont but if you want to overwrite * layoutMessage you should do this yourself. * @return The font that is used for the name part of the message. **/ const QFont& nameFont() const; /** * This font should be used for a message. layoutMessage sets the * font of a message using KChatBaseItemDelegate::setMessageFont but if you * replace layoutMessage with your own function you should use * messageFont() yourself. * @return The font that is used for a message **/ const QFont& messageFont() const; /** * Same as systemNameFont but applies only to system messages. **/ const QFont& systemNameFont() const; /** * Same as systemMessageFont but applies only to system messages. **/ const QFont& systemMessageFont() const; /** * Save the configuration of the dialog to a KConfig object. If * the supplied KConfig pointer is NULL then KGlobal::config() is used * instead (and the group is changed to "KChatBase") butr the current * group is restored at the end. * @param conf A pointer to the KConfig object to save the config * to. If you use 0 then KGlobal::config() is used and the group is changed * to "KChatBase" (the current group is restored at the end). **/ virtual void saveConfig(KConfig* conf = 0); /** * Read the configuration from a KConfig object. If the pointer is * NULL KGlobal::config() is used and the group is changed to "KChatBase". * The current KConfig::group is restored after this call. **/ virtual void readConfig(KConfig* conf = 0); /** * Set the maximum number of items in the list. If the number of item * exceeds the maximum as many items are deleted (oldest first) as * necessary. The number of items will never exceed this value. * @param maxItems the maximum number of items. -1 (default) for * unlimited. **/ void setMaxItems(int maxItems); /** * Clear all messages in the list. **/ void clear(); /** * @return The maximum number of messages in the list. -1 is unlimited. See also * setMaxItems **/ int maxItems() const; public Q_SLOTS: /** * Add a text in the listbox. See also signalSendMessage() * * Maybe you want to replace this with a function that creates a nicer text * than "fromName: text" * * Update: the function layoutMessage is called by this now. This * means that you will get user defined outlook on the messages :-) * @param fromName The player who sent this message * @param text The text to be added **/ virtual void addMessage(const QString& fromName, const QString& text); /** * This works just like addMessage but adds a system message. System * messages will have a different look than player messages. * * You may wish to use this to display status information from your game. **/ virtual void addSystemMessage(const QString& fromName, const QString& text); /** * This clears all messages in the view. Note that only the messages are * cleared, not the sender names in the combo box! **/ void slotClear(); private: KChatBaseModelPrivate* d; }; #endif diff --git a/libkdegamesprivate/kgame/kgame.h b/libkdegamesprivate/kgame/kgame.h index f4acd658..05f9f9d6 100644 --- a/libkdegamesprivate/kgame/kgame.h +++ b/libkdegamesprivate/kgame/kgame.h @@ -1,933 +1,933 @@ /* This file is part of the KDE games library Copyright (C) 2001 Martin Heni (kde at heni-online.de) Copyright (C) 2001 Andreas Beckermann (b_mann@gmx.de) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 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 Library General Public License for more details. You should have received a copy of the GNU Library 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 __KGAME_H_ #define __KGAME_H_ #include #include #include #include #include "kgamenetwork.h" #include "libkdegamesprivate_export.h" Q_DECLARE_LOGGING_CATEGORY(GAMES_PRIVATE_KGAME) class KRandomSequence; class KPlayer; class KGamePropertyBase; class KGamePropertyHandler; class KGameSequence; class KGamePrivate; /** * \class KGame kgame.h * * @short The main KDE game object * * The KGame class is the central game object. A game basically * consists of following features: * - Player handling (add, remove,...) * - Game status (end,start,pause,...) * - load/save * - Move (and message) handling * - nextPlayer and gameOver() * - Network connection (for KGameNetwork) * * Example: * \code * KGame *game=new KGame; * \endcode * * */ class KDEGAMESPRIVATE_EXPORT KGame : public KGameNetwork { Q_OBJECT public: typedef QList KGamePlayerList; /** * The policy of the property. This can be PolicyClean (setVale uses * send), PolicyDirty (setValue uses changeValue) or * PolicyLocal (setValue uses setLocal). * * A "clean" policy means that the property is always the same on every * client. This is achieved by calling send which actually changes * the value only when the message from the MessageServer is received. * * A "dirty" policy means that as soon as setValue is called the * property is changed immediately. And additionally sent over network. * This can sometimes lead to bugs as the other clients do not * immediately have the same value. For more information see * changeValue. * * PolicyLocal means that a KGameProperty behaves like ever * "normal" variable. Whenever setValue is called (e.g. using "=") * the value of the property is changes immediately without sending it * over network. You might want to use this if you are sure that all * clients set the property at the same time. **/ enum GamePolicy { PolicyUndefined = 0, PolicyClean = 1, PolicyDirty = 2, PolicyLocal = 3 }; /** * Create a KGame object. The cookie is used to identify your * game in load/save and network operations. Change this between * games. */ explicit KGame(int cookie=42,QObject* parent=nullptr); /** * Destructs the game */ - ~KGame() Q_DECL_OVERRIDE; + ~KGame() override; /** * Gives debug output of the game status */ - void Debug() Q_DECL_OVERRIDE; + void Debug() override; /** * Game status - Use this to Control the game flow. * The KGame e.g. sets the status to Pause when you have * less player than the minimum amount */ enum GameStatus { Init = 0, Run = 1, Pause = 2, End = 3, Abort = 4, SystemPause = 5, Intro = 6, UserStatus = 7 }; // Properties /** * Returns a list of all active players * * @return the list of players */ KGamePlayerList *playerList(); /** * The same as @ref playerList but returns a const pointer. **/ const KGamePlayerList *playerList() const; /** * Returns a list of all inactive players * @return the list of players */ KGamePlayerList *inactivePlayerList(); /** * The same as @ref inactivePlayerList but returns a const pointer. **/ const KGamePlayerList *inactivePlayerList() const; /** * Returns a pointer to the game's KRandomSequence. This sequence is * identical for all network players! * @return KRandomSequence pointer */ KRandomSequence *random() const; /** * @return The KGameSequence object that is currently in use. * @see setGameSequence **/ KGameSequence *gameSequence() const; /** * Is the game running * @return true/false */ bool isRunning() const; // Player handling /** * Returns the player object for a given player id * @param id Player id * @return player object */ KPlayer *findPlayer(quint32 id) const; /** * Set a new @ref KGameSequence to control player management. By default * KGame uses a normal @ref KGameSequence object. You might want to subclass * that and provide your own object. * * The previous sequence will get deleted. * @param sequence The new game sequence object. KGame takes ownership and * will delete it on destruction! **/ void setGameSequence(KGameSequence* sequence); /** * Note that KPlayer::save must be implemented properly, as well as * KPlayer::rtti * This will only send a message to all clients. The player is _not_ added * directly! * See also playerInput which will be called as soon as the * player really has been added. * * Note that an added player will first get into a "queue" and won't be in * the game. It will be added to the game as soon as systemAddPlayer is * called what will happen as soon as IdAddPlayer is received. * * Note: you probably want to connect to signalPlayerJoinedGame for * further initialization! * @param newplayer The player you want to add. KGame will send a message to * all clients and add the player using systemAddPlayer **/ bool addPlayer(KPlayer* newplayer); /** * Sends a message over the network, msgid=IdRemovePlayer. * * As soon as this message is received by networkTransmission * systemRemovePlayer is called and the player is removed. **/ //AB: TODO: make sendMessage to return if the message will be able to be //sent, eg if a socket is connected, etc. If sendMessage returns false //remove the player directly using systemRemovePlayer bool removePlayer(KPlayer * player) { return removePlayer(player, 0); } /** * Called by the destructor of KPlayer to remove itself from the game * **/ void playerDeleted(KPlayer * player); /** * sends activate player: internal use only? */ bool activatePlayer(KPlayer *player); /** * sends inactivate player: internal use only? */ bool inactivatePlayer(KPlayer *player); /** * Set the maximal number of players. After this is * reached no more players can be added. You must be ADMIN to call this (@see * isAdmin). * @param maxnumber maximal number of players */ void setMaxPlayers(uint maxnumber); /** * What is the maximal number of players? * @return maximal number of players */ int maxPlayers() const; /** * Set the minimal number of players. A game can not be started * with less player resp. is paused when already running. You must be ADMIN * to call this (see @ref isAdmin)! * @param minnumber minimal number of players */ void setMinPlayers(uint minnumber); /** * What is the minimal number of players? * @return minimal number of players */ uint minPlayers() const; /** * Returns how many players are plugged into the game * @return number of players */ uint playerCount() const; /** * @deprecated * Use @ref KGameSequence::nextPlayer instead **/ virtual KPlayer * nextPlayer(KPlayer *last,bool exclusive=true); // Input events /** * Called by KPlayer to send a player input to the * KMessageServer. **/ virtual bool sendPlayerInput(QDataStream &msg,KPlayer *player,quint32 sender=0); /** * Called when a player input arrives from KMessageServer. * * Calls prepareNext (using QTimer::singleShot) if gameOver() * returns 0. This function should normally not be used outside KGame. * It could be made non-virtual,protected in a later version. At the * moment it is a virtual function to give you more control over KGame. * * For documentation see playerInput. **/ virtual bool systemPlayerInput(QDataStream &msg,KPlayer *player,quint32 sender=0); /** * This virtual function is called if the KGame needs to create a new player. * This happens only over a network and with load/save. Doing nothing * will create a default KPlayer. If you want to have your own player * you have to create one with the given rtti here. * Note: If your game uses a player class derived from KPlayer you MUST * override this function and create your player here. Otherwise the * game will crash. * Example: * \code * KPlayer *MyGame::createPlayer(int rtti,int io,bool isvirtual) * { * KPlayer *player=new MyPlayer; * if (!isvirtual) // network player ? * { * // Define something like this to add the IO modules * createIO(player,(KGameIO::IOMode)io); * } * return player; * } * \endcode * * @param rtti is the type of the player (0 means default KPlayer) * @param io is the 'or'ed rtti of the KGameIO's * @param isvirtual true if player is virtual */ virtual KPlayer *createPlayer(int rtti,int io,bool isvirtual); // load/save /** * Load a saved game, from file OR network. This function has * to be overwritten or you need to connect to the load signal * if you have game data other than KGameProperty. * For file load you should reset() the game before any load attempt * to make sure you load into an clear state. * * @param stream a data stream where you can stream the game from * @param reset - shall the game be reset before loading * * @return true? */ virtual bool load(QDataStream &stream,bool reset=true); /** * Same as above function but with different parameters * * @param filename - the filename of the file to be opened * @param reset - shall the game be reset before loading * * @return true? **/ virtual bool load(const QString& filename,bool reset=true); /** * Save a game to a file OR to network. Otherwise the same as * the load function * * @param stream a data stream to load the game from * @param saveplayers If true then all players wil be saved too * * @return true? */ virtual bool save(QDataStream &stream,bool saveplayers=true); /** * Same as above function but with different parameters * * @param filename the filename of the file to be saved * @param saveplayers If true then all players wil be saved too * * @return true? **/ virtual bool save(const QString& filename,bool saveplayers=true); /** * Resets the game, i.e. puts it into a state where everything * can be started from, e.g. a load game * Right now it does only need to delete all players * * @return true on success */ virtual bool reset(); // Game sequence /** * returns the game status, ie running,pause,ended,... * * @return game status */ int gameStatus() const; /** * sets the game status * * @param status the new status */ void setGameStatus(int status); /** * docu: see KPlayer **/ bool addProperty(KGamePropertyBase* data); /** * This is called by KPlayer::sendProperty only! Internal function! **/ bool sendPlayerProperty(int msgid, QDataStream& s, quint32 playerId); /** * This function allows to find the pointer to a player * property when you know its id */ KGamePropertyBase* findProperty(int id) const; /** * Changes the consistency policy of a property. The * GamePolicy is one of PolicyClean (default), PolicyDirty or PolicyLocal. * * It is up to you to decide how you want to work. **/ void setPolicy(GamePolicy p,bool recursive=true); /** * @return The default policy of the property **/ GamePolicy policy() const; /** * See KGameNetwork::sendMessage * * Send a network message msg with a given message ID msgid to all players of * a given group (see KPlayer::group) * @param msg the message which will be send. See messages.txt for contents * @param msgid an id for this message * @param sender the id of the sender * @param group the group of the receivers * @return true if worked */ bool sendGroupMessage(const QByteArray& msg, int msgid, quint32 sender, const QString& group); bool sendGroupMessage(const QDataStream &msg, int msgid, quint32 sender, const QString& group); bool sendGroupMessage(int msg, int msgid, quint32 sender, const QString& group); bool sendGroupMessage(const QString& msg, int msgid, quint32 sender, const QString& group); /** * This will either forward an incoming message to a specified player * (see KPlayer::networkTransmission) or * handle the message directly (e.g. if msgif==IdRemovePlayer it will remove * the (in the stream) specified player). If both is not possible (i.e. the * message is user specified data) the signal signalNetworkData is * emitted. * * This emits signalMessageUpdate before doing anything with * the message. You can use this signal when you want to be notified about * an update/change. * @param msgid Specifies the kind of the message. See messages.txt for * further information * @param stream The message that is being sent * @param receiver The is of the player this message is for. 0 For broadcast. * @param sender * @param clientID the client from which we received the transmission - hardly used **/ - void networkTransmission(QDataStream &stream, int msgid, quint32 receiver, quint32 sender, quint32 clientID) Q_DECL_OVERRIDE; + void networkTransmission(QDataStream &stream, int msgid, quint32 receiver, quint32 sender, quint32 clientID) override; /** * Returns a pointer to the KGame property handler **/ KGamePropertyHandler* dataHandler() const; protected Q_SLOTS: /** * Called by KGamePropertyHandler only! Internal function! **/ void sendProperty(int msgid, QDataStream& stream, bool* sent); /** * Called by KGamePropertyHandler only! Internal function! **/ void emitSignal(KGamePropertyBase *me); /** * @deprecated * Use KGameSequence::prepareNext() instead **/ virtual void prepareNext(); /** * Calls negotiateNetworkGame() * See KGameNetwork::signalClientConnected **/ void slotClientConnected(quint32 clientId); /** * This slot is called whenever the connection to a client is lost (ie the * signal KGameNetwork::signalClientDisconnected is emitted) and will remove * the players from that client. * @param clientId The client the connection has been lost to * @param broken (ignore this - not used) **/ void slotClientDisconnected(quint32 clientId,bool broken); /** * This slot is called whenever the connection to the server is lost (ie the * signal KGameNetwork::signalConnectionBroken is emitted) and will * switch to local game mode **/ void slotServerDisconnected(); Q_SIGNALS: /** * When a client disconnects from the game usually all players from that * client are removed. But if you use completely the KGame structure you * probably don't want this. You just want to replace the KGameIO of the * (human) player by a computer KGameIO. So this player continues game but * is from this point on controlled by the computer. * * You achieve this by connecting to this signal. It is emitted as soon as a * client disconnects on all other clients. Make sure to add a new * KGameIO only once! you might want to use @ref isAdmin for this. If you * added a new KGameIO set *remove=false otherwise the player is completely * removed. * @param player The player that is about to be removed. Add your new * KGameIO here - but only on one client! * @param remove Set this to FALSE if you don't want this player to be * removed completely. **/ void signalReplacePlayerIO(KPlayer* player, bool* remove); /** * The game will be loaded from the given stream. Load from here * the data which is NOT a game or player property. * It is not necessary to use this signal for a full property game. * * This signal is emitted before the players are loaded by * KGame. See also signalLoad * * You must load exactly the same data from the stream that you have saved * in signalSavePrePlayers. Otherwise player loading will not work * anymore. * * @param stream the load stream */ void signalLoadPrePlayers(QDataStream &stream); /** * The game will be loaded from the given stream. Load from here * the data which is NOT a game or player property. * It is not necessary to use this signal for a full property game. * * @param stream the load stream */ void signalLoad(QDataStream &stream); /** * The game will be saved to the given stream. Fill this with data * which is NOT a game or player property. * It is not necessary to use this signal for a full property game. * * This signal is emitted before the players are saved by * KGame. See also signalSave * * If you can choose between signalSavePrePlayers and signalSave then * better use signalSave * * @param stream the save stream **/ void signalSavePrePlayers(QDataStream &stream); /** * The game will be saved to the given stream. Fill this with data * which is NOT a game or player property. * It is not necessary to use this signal for a full property game. * * @param stream the save stream */ void signalSave(QDataStream &stream); /** * Is emitted if a game with a different version cookie is loaded. * Normally this should result in an error. But maybe you do support * loading of older game versions. Here would be a good place to do a * conversion. * * @param stream - the load stream * @param network - true if this is a network connect. False for load game * @param cookie - the saved cookie. It differs from KGame::cookie() * @param result - set this to true if you managed to load the game */ void signalLoadError(QDataStream &stream,bool network,int cookie, bool &result); /** * We got an user defined update message. This is usually done * by a sendData in a inherited KGame Object which defines its * own methods and has to synchronize them over the network. * Reaction to this is usually a call to a KGame function. */ void signalNetworkData(int msgid,const QByteArray& buffer, quint32 receiver, quint32 sender); /** * We got an network message. this can be used to notify us that something * changed. What changed can be seen in the message id. Whether this is * the best possible method to do this is unclear... */ void signalMessageUpdate(int msgid,quint32 receiver,quint32 sender); /** * a player left the game because of a broken connection or so! * * Note that when this signal is emitted the player is not part of @ref * playerList anymore but the pointer is still valid. You should do some * final cleanups here since the player is usually deleted after the signal * is emitted. * * @param player the player who left the game */ void signalPlayerLeftGame(KPlayer *player); /** * a player joined the game * * @param player the player who joined the game */ void signalPlayerJoinedGame(KPlayer *player); /** * This signal is emitted if a player property changes its value and * the property is set to notify this change */ void signalPropertyChanged(KGamePropertyBase *property, KGame *me); /** * Is emitted after a call to gameOver() returns a non zero * return code. This code is forwarded to this signal as 'status'. * * @param status the return code of gameOver() * @param current the player who did the last move * @param me a pointer to the KGame object */ void signalGameOver(int status, KPlayer *current, KGame *me); /** * Is emitted after a client is successfully connected to the game. * The client id is the id of the new game client. An easy way to * check whether that's us is * \code * if (clientid==gameid()) .. // we joined * else ... // someone joined the game * \endcode * @param clientid - The id of the new client * @param me - our game pointer */ void signalClientJoinedGame(quint32 clientid,KGame *me); /** * This signal is emitted after a network partner left the * game (either by a broken connection or voluntarily). * All changes to the network players have already be done. * If there are not enough players left, the game might have * been paused. To check this you get the old gamestatus * before the disconnection as argument here. The id of the * client who left the game allows to distinguish who left the * game. If it is 0, the server disconnected and you were a client * which has been switched back to local play. * You can use this signal to, e.g. set some menus back to local * player when they were network before. * * @param clientID - 0:server left, otherwise the client who left * @param oldgamestatus - the gamestatus before the loss * @param me - our game pointer **/ void signalClientLeftGame(int clientID,int oldgamestatus,KGame *me); protected: /** * A player input occurred. This is the most important function * as the given message will contain the current move made by * the given player. * Note that you HAVE to overwrite this function. Otherwise your * game makes no sense at all. * Generally you have to return TRUE in this function. Only then * the game sequence is proceeded by calling @ref playerInputFinished * which in turn will check for game over or the next player * However, if you have a delayed move, because you e.g. move a * card or a piece you want to return FALSE to pause the game sequence * and then manually call @ref playerInputFinished to resume it. * Example: * \code * bool MyClass::playerInput(QDataStream &msg,KPlayer *player) * { * qint32 move; * msg >> move; * qDebug() << " Player" << player->id() << "moved to" << move; * return true; * } * \endcode * * @param msg the move message * @param player the player who did the move * @return true - input ready, false: input manual */ virtual bool playerInput(QDataStream &msg,KPlayer *player)=0; /** * Called after the player input is processed by the game. Here the * checks for game over and nextPlayer (in the case of turn base games) * are processed. * Call this manually if you have a delayed move, i.e. your playerInput * function returns FALSE. If it returns true you need not do anything * here. * * @return the current player * **/ KPlayer *playerInputFinished(KPlayer *player); /** * This virtual function can be overwritten for your own player management. * It is called when a new game connects to an existing network game or * to the network master. In case you do not want all players of both games * to be present in the new network game, you can deactivate players here. * This is of particular importance if you have a game with fixed number of * player like e.g. chess. A network connect needs to disable one player of * each game to make sense. * * Not overwriting this function will activate a default behaviour which * will deactivate players until the @ref maxPlayers() number is reached * according to the KPlayer::networkPriority() value. Players with a low * value will be kicked out first. With equal priority players of the new * client will leave first. This means, not setting this value and not * overwriting this function will never allow a chess game to add client * players!!! * On the other hand setting one player of each game to a networkPriorty of * say 10, already does most of the work for you. * * The parameters of this function are the playerlist of the network game, * which is @ref playerList(). The second argument is the player list of * the new client who wants to join and the third argument serves as return * parameter. All player ID's which are written into this list * will be removed from the created game. You do this by an * \code * inactivate.append(player->id()); * \endcode * * @param oldplayer - the list of the network players * @param newplayer - the list of the client players * @param inactivate - the value list of ids to be deactivated * **/ virtual void newPlayersJoin(KGamePlayerList *oldplayer, KGamePlayerList *newplayer, QList &inactivate) { Q_UNUSED( oldplayer ); Q_UNUSED( newplayer ); Q_UNUSED( inactivate ); } /** * Save the player list to a stream. Used for network game and load/save. * Can be overwritten if you know what you are doing * * @param stream is the stream to save the player ot * @param list the optional list is the player list to be saved, default is playerList() * **/ void savePlayers(QDataStream &stream,KGamePlayerList *list=0); /** * Prepare a player for being added. Put all data about a player into the * stream so that it can be sent to the KGameCommunicationServer using * addPlayer (e.g.) * * This function ensures that the code for adding a player is the same in * addPlayer as well as in negotiateNetworkGame * @param stream is the stream to add the player * @param player The player to add **/ void savePlayer(QDataStream& stream,KPlayer* player); /** * Load the player list from a stream. Used for network game and load/save. * Can be overwritten if you know what you are doing * * @param stream is the stream to save the player to * @param isvirtual will set the virtual flag true/false * **/ KPlayer *loadPlayer(QDataStream& stream,bool isvirtual=false); /** * inactivates player. Use @ref inactivatePlayer instead! */ bool systemInactivatePlayer(KPlayer *player); /** * activates player. Use @ref activatePlayer instead! */ bool systemActivatePlayer(KPlayer *player); /** * Adds a player to the game * * Use @ref addPlayer to send @ref KGameMessage::IdAddPlayer. As soon as * this Id is received this function is called, where the player (see @ref * KPlayer::rtti) is added as well as its properties (see @ref KPlayer::save * and @ref KPlayer::load) * * This method calls the overloaded @ref systemAddPlayer with the created * player as argument. That method will really add the player. * If you need to do some changes to your newly added player just connect to * @ref signalPlayerJoinedGame */ /** * Finally adds a player to the game and therefore to the list. **/ bool systemAddPlayer(KPlayer* newplayer); /** * Removes a player from the game * * Use removePlayer to send KGameMessage::IdRemovePlayer. As soon * as this Id is received systemRemovePlayer is called and the player is * removed directly. **/ void systemRemovePlayer(KPlayer* player,bool deleteit); /** * This member function will transmit e.g. all players to that client, as well as * all properties of these players (at least if they have been added by * @ref KPlayer::addProperty) so that the client will finally have the same * status as the master. You want to overwrite this function if you expand * KGame by any properties which have to be known by all clients. * * Only the ADMIN is allowed to call this. * @param clientID The ID of the message client which has connected **/ virtual void negotiateNetworkGame(quint32 clientID); /** * synchronize the random numbers with all network clients * not used by KGame - if it should be kept then as public method */ void syncRandom(); void deletePlayers(); void deleteInactivePlayers(); /** * @deprecated * Use @ref KGameSequence instead. * * @param player the player who made the last move * @return anything else but 0 is considered as game over */ virtual int checkGameOver(KPlayer *player); /** * Load a saved game, from file OR network. Internal. * Warning: loadgame must not rely that all players all already * activated. Actually the network will activate a player AFTER * the loadgame only. This is not true anymore. But be careful * anyway. * * @param stream a data stream where you can stream the game from * @param network is it a network call -> make players virtual * @param reset shall the game be reset before loading * * @return true? */ virtual bool loadgame(QDataStream &stream, bool network, bool reset); /** * Save a game, to file OR network. Internal. * * @param stream a data stream where you can stream the game from * @param network is it a call from the network or from a file (unused but informative) * @param saveplayers shall the players be saved too (should be TRUE) * * @return true? */ virtual bool savegame(QDataStream &stream, bool network,bool saveplayers); private: //AB: this is to hide the "receiver" parameter from the user. It shouldn't be //used if possible (except for init). /** * This is an overloaded function. Id differs from the public one only in * its parameters: * * @param receiver The Client that will receive the message. You will hardly * ever need this. It it internally used to initialize a newly connected * client. **/ //void addPlayer(KPlayer* newplayer, quint32 receiver); /** * Just the same as the public one except receiver: * @param receiver 0 for broadcast, otherwise the receiver. Should only be * used in special circumstances and not outside KGame. **/ bool removePlayer(KPlayer * player, quint32 receiver); /** * Helping function - game negotiation **/ void setupGame(quint32 sender); /** * Helping function - game negotiation **/ void setupGameContinue(QDataStream& msg, quint32 sender); /** * Removes a player from all lists, removes the @ref KGame pointer from the * @ref KPlayer and deletes the player. Used by (e.g.) @ref * systemRemovePlayer * @return True if the player has been removed, false if the current is not * found **/ bool systemRemove(KPlayer* player,bool deleteit); private: KGamePrivate* const d; }; #endif diff --git a/libkdegamesprivate/kgame/kgamechat.h b/libkdegamesprivate/kgame/kgamechat.h index cf1cdad9..24f45989 100644 --- a/libkdegamesprivate/kgame/kgamechat.h +++ b/libkdegamesprivate/kgame/kgamechat.h @@ -1,221 +1,221 @@ /* This file is part of the KDE games library Copyright (C) 2001-2002 Andreas Beckermann (b_mann@gmx.de) Copyright (C) 2001 Martin Heni (kde at heni-online.de) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 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 Library General Public License for more details. You should have received a copy of the GNU Library 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 __KGAMECHAT_H__ #define __KGAMECHAT_H__ #include #include "../kchatbase.h" #include "libkdegamesprivate_export.h" class KPlayer; class KGame; class KGamePropertyBase; class KGameChatPrivate; /** * \class KGameChat kgamechat.h * * @short A Chat widget for KGame-based games * * Call @ref setFromPlayer() first - this will be used as the "from" part of * every message you will send. Otherwise it won't work! You can also use the * fromPlayer parameter in the constructor though... * * @author Andreas Beckermann **/ class KDEGAMESPRIVATE_EXPORT KGameChat : public KChatBase { Q_OBJECT public: /** * Construct a @ref KGame chat widget on @p game that used @p msgid for * the chat message. The @p fromPlayer is the local player (see @ref * setFromPlayer). **/ KGameChat(KGame* game, int msgid, KPlayer* fromPlayer, QWidget * parent, KChatBaseModel* model=0, KChatBaseItemDelegate* delegate=0); /** * @overload * To make use of this widget you need to call @ref setFromPlayer * manually. **/ KGameChat(KGame* game, int msgId, QWidget* parent, KChatBaseModel* model=0, KChatBaseItemDelegate* delegate=0); /** * @overload * This constructs a widget that is not usable. You must call at least * setGame, setFromPlayer and setMessageId manually. **/ explicit KGameChat(QWidget* parent); virtual ~KGameChat(); enum SendingIds { SendToGroup = 1 }; /** * This sets the fromPlayer to @p player. The fromPlayer is the * player that will appear as "from" when you send messages through this * widget. * @param player The player of this widget **/ void setFromPlayer(KPlayer* player); KPlayer* fromPlayer() const; /** * Set the @ref KGame object for this chat widget. All messages will be * sent through this object. You don't have to implement any send * functions, just call this function, call @ref setFromPlayer and be * done :-) * @param g The @ref KGame object the messages will be sent through **/ void setKGame(KGame* g); KGame* game() const; /** * @return The id of the messages produced by KGameChat. The id will be * used in @ref KGame as parameter msgid in the method @ref KGame::sendMessage **/ int messageId() const; /** * Change the message id of the chat widget. It is recommended that you * don't use this but prefer the constructor instead, but in certain * situations (such as using this widget in Qt designer) it may be * useful to change the message id. * * See also @ref messageId **/ void setMessageId(int msgid); /** * reimplemented from @ref KChatBase * @return @ref KPlayer::name() for the player set by @ref setFromPlayer **/ - QString fromName() const Q_DECL_OVERRIDE; + QString fromName() const override; public Q_SLOTS: - void addMessage(const QString& fromName, const QString& text) Q_DECL_OVERRIDE { KChatBase::addMessage(fromName, text);} + void addMessage(const QString& fromName, const QString& text) override { KChatBase::addMessage(fromName, text);} virtual void addMessage(int fromId, const QString& text); void slotReceiveMessage(int, const QByteArray&, quint32 receiver, quint32 sender); protected: /** * @param id The ID of the sending entry, as returned by @ref KChatBase sendingEntry * @return True if the entry "send to all" was selected, otherwise false **/ bool isSendToAllMessage(int id) const; /** * Used to indicate whether a message shall be sent to a group of * players. Note that this was not yet implemented when this doc was * written so this description might be wrong. (FIXME) * @param id The ID of the sending entry, as returned by @ref KChatBase sendingEntry * @return True if the message is meant to be sent to a group (see @ref KPlayer::group * ), e.g. if "send to my group" was selected. **/ bool isToGroupMessage(int id) const; /** * Used to indicate whether the message shall be sent to a single player * only. Note that you can also call @ref isSendToAllMessage and @ref * isToGroupMessage - if both return false it must be a player message. * This behaviour might be changed later - so don't depend on it. * * See also toPlayerId * @param id The ID of the sending entry, as returned by * @ref KChatBase sendingEntry * @return True if the message shall be sent to a special player, * otherwise false. **/ bool isToPlayerMessage(int id) const; /** * @param id The ID of the sending entry, as returned by * @ref KChatBase sendingEntry * @return The ID of the player (see KPlayer::id) the sending entry * belongs to. Note that the parameter id is an id as returned by * @ref KChatBase sendingEntry and the id this method returns is a * KPlayer ID. If @ref isToPlayerMessage returns false this method * returns -1 **/ int playerId(int id) const; /** * @param playerId The ID of the KPlayer object * @return The ID of the sending entry (see KChatBase) or -1 if * the player id was not found. **/ int sendingId(int playerId) const; /** * @return True if the player with this ID was added before (see * slotAddPlayer) **/ bool hasPlayer(int id) const; /** * @param name The name of the added player * @return A string that will be added as sending entry in @ref * KChatBase. By default this is "send to name" where name is the name * that you specify. See also KChatBase::addSendingEntry **/ virtual QString sendToPlayerEntry(const QString& name) const; protected Q_SLOTS: /** * Unsets a KGame object that has been set using setKGame * before. You don't have to call this - this is usually done * automatically. **/ void slotUnsetKGame(); void slotPropertyChanged(KGamePropertyBase*, KPlayer*); void slotAddPlayer(KPlayer*); void slotRemovePlayer(KPlayer*); /** * Called when KPlayer::signalNetworkData is emitted. The message * gets forwarded to slotReceiveMessage if @p me equals * fromPlayer. **/ void slotReceivePrivateMessage(int msgid, const QByteArray& buffer, quint32 sender, KPlayer* me); protected: - void returnPressed(const QString& text) Q_DECL_OVERRIDE; + void returnPressed(const QString& text) override; private: void init(KGame* g, int msgid); private: KGameChatPrivate* const d; }; #endif diff --git a/libkdegamesprivate/kgame/kgameio.h b/libkdegamesprivate/kgame/kgameio.h index 7919b982..98ac4736 100644 --- a/libkdegamesprivate/kgame/kgameio.h +++ b/libkdegamesprivate/kgame/kgameio.h @@ -1,601 +1,601 @@ /* This file is part of the KDE games library Copyright (C) 2001 Martin Heni (kde at heni-online.de) Copyright (C) 2001 Andreas Beckermann (b_mann@gmx.de) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 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 Library General Public License for more details. You should have received a copy of the GNU Library 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 __KGAMEIO_H__ #define __KGAMEIO_H__ #include #include #include "libkdegamesprivate_export.h" class QEvent; class QGraphicsScene; class QKeyEvent; class QMouseEvent; class KPlayer; class KGame; class KGameIOPrivate; class KGameKeyIOPrivate; class KGameMouseIOPrivate; class KGameProcessIOPrivate; class KGameComputerIOPrivate; /** * \class KGameIO kgameio.h * * \short Base class for IO devices for games * * This is the master class for * creating IO game devices. You cannot use it directly. * Either take one of the classes derived from it or * you have to create your own IO class derived from it (more probably). * * The idea behind this class is to provide a common interface * for input devices into your game. By programming a KGameIO * device you need not distinguish the actual IO in the game * anymore. All work is done by the IO's. This allows very * easy reuse in other games as well. * A further advantage of using the IO's is that you can exchange * the control of a player at runtime. E.g. you switch a player * to be controlled by the computer or vice versa. * * To achieve this you have to make all of your player inputs through a * KGameIO. You will usually call KGameIO::sendInput to do so. * * @author Martin Heni */ class KDEGAMESPRIVATE_EXPORT KGameIO : public QObject { Q_OBJECT public: /** * Constructs a KGameIO object */ KGameIO(); KGameIO(KPlayer*); virtual ~KGameIO(); /** * Gives debug output of the game status */ void Debug(); /** * Identifies the KGameIO via the rtti function */ enum IOMode {GenericIO=1,KeyIO=2,MouseIO=4,ProcessIO=8,ComputerIO=16}; /** * Run time identification. Predefined values are from IOMode * You MUST overwrite this in derived classes! * * @return rtti value */ virtual int rtti() const = 0; // Computer, network, local, ... /** * This function returns the player who owns this IO * * @return the player this IO device is plugged into */ KPlayer *player() const; /** * Equivalent to player()->game() * @return the @ref KGame object of this player **/ KGame* game() const; /** * Sets the player to which this IO belongs to. This * is done automatically when adding a device to a * player * * @param p the player */ void setPlayer(KPlayer *p); /** * Init this device by setting the player and e.g. sending an * init message to the device. This initialisation message is * very useful for computer players as you can transmit the * game status to them and only update this status in the setTurn * commands. * * Called by @ref KPlayer::addGameIO only! */ virtual void initIO(KPlayer *p); /** * Notifies the IO device that the player's setTurn had been called * Called by KPlayer * * This emits @ref signalPrepareTurn and sends the turn if the send * parameter is set to true. * * @param b turn is true/false */ virtual void notifyTurn(bool b); /** * Send an input message using @ref KPlayer::forwardInput **/ bool sendInput(QDataStream& stream, bool transmit = true, quint32 sender = 0); Q_SIGNALS: /** * Signal generated when @ref KPlayer::myTurn changes. This can either be * when you get the turn status or when you lose it. * * The datastream has to be filled with a move. If you set (or leave) the * send parameter to FALSE then nothing happens: the datastream will be * ignored. If you set it to TRUE @ref sendInput is used to * send the move. * * Often you want to ignore this signal (leave send=FALSE) and send the * message later. This is usually the case for a human player as he probably * doesn't react immediately. But you can still use this e.g. to notify the * player about the turn change. * * Example: * \code * void GameWindow::slotPrepareTurn(QDataStream &stream,bool b,KGameIO *input,bool * ) * { * KPlayer *player=input->player(); * if (!player->myTurn()) return ; * if (!b) return ; // only do something on setTurn(true) * stream << 1 << 2 << 3; // Some data for the process * } * \endcode * * @param io the KGameIO object itself * @param stream the stream into which the move will be written * @param turn the argument of setTurn * @param send set this to true to send the generated move using @ref * sendInput **/ void signalPrepareTurn(QDataStream & stream, bool turn, KGameIO *io, bool * send); private: friend class KGameIOPrivate; KGameIOPrivate *const d; Q_DISABLE_COPY(KGameIO) }; /** * \class KGameKeyIO kgameio.h * * The KGameKeyIO class. It is used to process keyboard input * from a widget and create moves for the player it belongs to. * @author Martin Heni */ class KDEGAMESPRIVATE_EXPORT KGameKeyIO : public KGameIO { Q_OBJECT public: /** * Create a keyboard input devices. All keyboards * inputs of the given widgets are passed through a signal * handler signalKeyEvent and can be used to generate * a valid move for the player. * Note the widget you pass to the constructor must be * the main window of your application, e.g. view->parentWidget() * as QT does not forward your keyevents otherwise. This means * that this might be a different widget compared to the one you * use for mouse inputs! * Example: * \code * KGameKeyIO *input; * input=new KGameKeyIO(myWidget); * connect(input,SIGNAL(signalKeyEvent(KGameIO *,QDataStream &,QKeyEvent *,bool *)), * this,SLOT(slotKeyInput(KGameIO *,QDataStream &,QKeyEvent *,bool *))); * \endcode * * @param parent The parents widget whose keyboard events * should be grabbed */ KGameKeyIO(QWidget *parent); virtual ~KGameKeyIO(); /** * The identification of the IO * * @return KeyIO */ - int rtti() const Q_DECL_OVERRIDE; + int rtti() const override; Q_SIGNALS: /** * Signal handler for keyboard events. This function is called * on every keyboard event. If appropriate it can generate a * move for the player the device belongs to. If this is done * and the event is eaten eatevent needs to be set to true. * What move you generate (i.e. what you write to the stream) * is totally up to you as it will not be evaluated but forwarded * to the player's/game's input move function * Example: * \code * KPlayer *player=input->player(); // Get the player * qint32 key=e->key(); * stream << key; * eatevent=true; * \endcode * * @param io the IO device we belong to * @param stream the stream where we write our move into * @param m The QKeyEvent we can evaluate * @param eatevent set this to true if we processed the event */ void signalKeyEvent(KGameIO *io,QDataStream &stream,QKeyEvent *m,bool *eatevent); protected: /** * Internal method to process the events */ - bool eventFilter( QObject *o, QEvent *e ) Q_DECL_OVERRIDE; + bool eventFilter( QObject *o, QEvent *e ) override; private: friend class KGameKeyIOPrivate; KGameKeyIOPrivate *const d; Q_DISABLE_COPY(KGameKeyIO) }; /** * \class KGameMouseIO kgameio.h * * The KGameMouseIO class. It is used to process mouse input * from a widget and create moves for the player it belongs to. * @author Martin Heni */ class KDEGAMESPRIVATE_EXPORT KGameMouseIO : public KGameIO { Q_OBJECT public: /** * Creates a mouse IO device. It captures all mouse * event of the given widget and forwards them to the * signal handler signalMouseEvent. * Example: * \code * KGameMouseIO *input; * input=new KGameMouseIO(mView); * connect(input,SIGNAL(signalMouseEvent(KGameIO *,QDataStream &,QMouseEvent *,bool *)), * this,SLOT(slotMouseInput(KGameIO *,QDataStream &,QMouseEvent *,bool *))); * \endcode * * @param parent The widget whose events should be captured * @param trackmouse enables mouse tracking (gives mouse move events) */ explicit KGameMouseIO(QWidget *parent,bool trackmouse=false); explicit KGameMouseIO(QGraphicsScene *parent,bool trackmouse=false); virtual ~KGameMouseIO(); /** * Manually activate or deactivate mouse tracking * * @param b true = tracking on */ void setMouseTracking(bool b); /** * The identification of the IO * * @return MouseIO */ - int rtti() const Q_DECL_OVERRIDE; + int rtti() const override; Q_SIGNALS: /** * Signal handler for mouse events. This function is called * on every mouse event. If appropriate it can generate a * move for the player the device belongs to. If this is done * and the event is eaten eatevent needs to be set to true. * @see signalKeyEvent * Example: * \code * KPlayer *player=input->player(); // Get the player * qint32 button=e->button(); * stream << button; * eatevent=true; * \endcode * * @param io the IO device we belong to * @param stream the stream where we write our move into * @param m The QMouseEvent we can evaluate * @param eatevent set this to true if we processed the event */ void signalMouseEvent(KGameIO *io,QDataStream &stream,QMouseEvent *m,bool *eatevent); protected: /** * Internal event filter */ - bool eventFilter( QObject *o, QEvent *e ) Q_DECL_OVERRIDE; + bool eventFilter( QObject *o, QEvent *e ) override; private: friend class KGameMouseIOPrivate; KGameMouseIOPrivate *const d; Q_DISABLE_COPY(KGameMouseIO) }; /** * \class KGameProcessIO kgameio.h * * The KGameProcessIO class. It is used to create a computer player * via a separate process and communicate transparently with it. * Its counterpart is the KGameProcess class which needs * to be used by the computer player. See its documentation * for the definition of the computer player. */ class KDEGAMESPRIVATE_EXPORT KGameProcessIO : public KGameIO { Q_OBJECT public: /** * Creates a computer player via a separate process. The process * name is given as fully qualified filename. * Example: * \code * KGameProcessIO *input; * input=new KGameProcessIO(executable_file); * connect(input,SIGNAL(signalPrepareTurn(QDataStream &,bool,KGameIO *,bool *)), * this,SLOT(slotPrepareTurn(QDataStream &,bool,KGameIO *,bool *))); * connect(input,SIGNAL(signalProcessQuery(QDataStream &,KGameProcessIO *)), * this,SLOT(slotProcessQuery(QDataStream &,KGameProcessIO *))); * \endcode * * @param name the filename of the process to start */ KGameProcessIO(const QString& name); /** * Deletes the process input devices */ virtual ~KGameProcessIO(); /** * The identification of the IO * * @return ProcessIO */ - int rtti() const Q_DECL_OVERRIDE; + int rtti() const override; /** * Send a message to the process. This is analogous to the sendMessage * commands of KGame. It will result in a signal of the computer player * on which you can react in the process player. * * @param stream - the actual data * @param msgid - the id of the message * @param receiver - not used * @param sender - who send the message */ void sendMessage(QDataStream &stream,int msgid, quint32 receiver, quint32 sender); /** * Send a system message to the process. This is analogous to the sendMessage * commands of KGame. It will result in a signal of the computer player * on which you can react in the process player. * * @param stream - the actual data * @param msgid - the id of the message * @param receiver - not used * @param sender - who send the message */ void sendSystemMessage(QDataStream &stream, int msgid, quint32 receiver, quint32 sender); /** * Init this device by setting the player and e.g. sending an * init message to the device. Calling this function will emit * the IOAdded signal on which you can react and initilise the * computer player. * This function is called automatically when adding the IO to * a player. */ - void initIO(KPlayer *p) Q_DECL_OVERRIDE; + void initIO(KPlayer *p) override; /** * Notifies the IO device that the player's setTurn had been called * Called by KPlayer. You can react on the @ref signalPrepareTurn to * prepare a message for the process, i.e. either update it on * the changes made to the game since the last turn or the initIO * has been called or transmit your gamestatus now. * * @param turn is true/false */ - void notifyTurn(bool turn) Q_DECL_OVERRIDE; + void notifyTurn(bool turn) override; protected: /** * Internal combined function for all message handling **/ void sendAllMessages(QDataStream &stream,int msgid, quint32 receiver, quint32 sender, bool usermsg); protected Q_SLOTS: /** * Internal message handler to receive data from the process */ void receivedMessage(const QByteArray& receiveBuffer); Q_SIGNALS: /** * A computer query message is received. This is a 'dummy' * message sent by the process if it needs to communicate * with us. It is not forwarded over the network. * Reacting to this message allows you to 'answer' questions * of the process, e.g. sending addition data which the process * needs to calculate a move. * * Example: * \code * void GameWindow::slotProcessQuery(QDataStream &stream,KGameProcessIO *reply) * { * int no; * stream >> no; // We assume the process sends us an integer question number * if (no==1) // but YOU have to do this in the process player * { * QByteArray buffer; * QDataStream out(buffer,QIODevice::WriteOnly); * reply->sendSystemMessage(out,4242,0,0); // lets reply something... * } * } * \endcode */ void signalProcessQuery(QDataStream &stream,KGameProcessIO *me); /** * Signal generated when the computer player is added. * You can use this to communicated with the process and * e.g. send initialisation information to the process. * * @param game the KGameIO object itself * @param stream the stream into which the move will be written * @param p the player itself * @param send set this to false if no move should be generated */ void signalIOAdded(KGameIO *game,QDataStream &stream,KPlayer *p,bool *send); /** Text is received by the process on STDERR. This is usually a debug string. * @param msg The text */ void signalReceivedStderr(const QString &msg); private: friend class KGameProcessIOPrivate; KGameProcessIOPrivate *const d; Q_DISABLE_COPY(KGameProcessIO) }; /** * \class KGameComputerIO kgameio.h * * \brief KGameIO variant for real-time games * * The KGameComputerIO class. It is used to create a LOCAL computer player * and communicate transparently with it. * Question: Is this needed or is it overwritten anyway for a real game? * * You most probably don't want to use this if you want to design a turn based * game/player. You'll rather use @ref KGameIO directly, i.e. subclass it * yourself. You just need to use @ref KGameIO::signalPrepareTurn and/or @ref * KGameIO::notifyTurn there. * * This is rather meant to be of use in real time games. * * @author */ class KDEGAMESPRIVATE_EXPORT KGameComputerIO : public KGameIO { Q_OBJECT public: /** * Creates a LOCAL computer player * */ KGameComputerIO(); KGameComputerIO(KPlayer* player); ~KGameComputerIO(); - int rtti() const Q_DECL_OVERRIDE; + int rtti() const override; /** * The number of advance calls until the player (or rather: the IO) * does something (default: 1). **/ void setReactionPeriod(int advanceCalls); int reactionPeriod() const; /** * Start a QTimer which calls advance every @p ms milli seconds. **/ void setAdvancePeriod(int ms); void stopAdvancePeriod(); /** * Ignore calls number of advance calls. if calls is -1 then all * following advance calls are ignored until unpause is called. * * This simply prevents the internal advance counter to be increased. * * You may want to use this to emulate a "thinking" computer player. Note * that this means if you increase the advance period (see * setAdvancePeriod), i.e. if you change the speed of your game, your * computer player thinks "faster". * @param calls Number of advance calls to be ignored **/ void pause(int calls = -1); /** * Equivalent to pause(0). Immediately continue to increase the internal * advance counter. **/ void unpause(); public Q_SLOTS: /** * Works kind of similar to QCanvas::advance. Increase the internal * advance counter. If @p reactionPeriod is reached the counter is set back to * 0 and @ref signalReaction is emitted. This is when the player is meant * to do something (move its units or so). * * This is very useful if you use QCanvas as you can use this in your * QCanvas::advance call. The advantage is that if you change the speed * of the game (i.e. change QCanvas::setAdvancePeriod) the computer * player gets slower as well. * * If you don't use QCanvas you can use setAdvancePeriod to get * the same result. Alternatively you can just use a QTimer. * **/ virtual void advance(); Q_SIGNALS: /** * This signal is emitted when your computer player is meant to do * something, or better is meant to be allowed to do something. **/ void signalReaction(); protected: /** * Default implementation simply emits signalReaction **/ virtual void reaction(); private: friend class KGameComputerIOPrivate; KGameComputerIOPrivate *const d; Q_DISABLE_COPY(KGameComputerIO) }; #endif diff --git a/libkdegamesprivate/kgame/kgameproperty.h b/libkdegamesprivate/kgame/kgameproperty.h index 2c0dadae..97ec9c6a 100644 --- a/libkdegamesprivate/kgame/kgameproperty.h +++ b/libkdegamesprivate/kgame/kgameproperty.h @@ -1,852 +1,852 @@ /* This file is part of the KDE games library Copyright (C) 2001 Andreas Beckermann (b_mann@gmx.de) Copyright (C) 2001 Martin Heni (kde at heni-online.de) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 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 Library General Public License for more details. You should have received a copy of the GNU Library 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 __KGAMEPROPERTY_H_ #define __KGAMEPROPERTY_H_ #include #include #include #include "libkdegamesprivate_export.h" class KGame; class KPlayer; class KGamePropertyHandler; using namespace std; /** * \class KGamePropertyBase kgameproperty.h * * @short Base class of KGameProperty * * The KGamePropertyBase class is the base class of KGameProperty. See * KGameProperty for further information. * * @author Andreas Beckermann **/ class KDEGAMESPRIVATE_EXPORT KGamePropertyBase { public: enum PropertyDataIds { // these belong to KPlayer/KGame! //KPlayer IdGroup=1, IdUserId=2, IdAsyncInput=3, IdTurn=4, IdName=5, //KGame IdGameStatus=6, IdMaxPlayer=7, IdMinPlayer=8, // Input Grabbing IdGrabInput=16, IdReleaseInput=17, IdCommand, // Reserved for internal use IdUser=256, IdAutomatic=0x7000 // Id's from here on are automatically given (16bit) }; /** * Commands for advanced properties (qint8) **/ enum PropertyCommandIds { // General CmdLock=1, // Array CmdAt=51, CmdResize=52, CmdFill=53, CmdSort=54, // List (could be the same id's actually) CmdInsert=61, CmdAppend=62, CmdRemove=63, CmdClear=64 }; /** * The policy of the property. This can be PolicyClean (setValue uses * send), PolicyDirty (setValue uses changeValue) or * PolicyLocal (setValue uses setLocal). * * A "clean" policy means that the property is always the same on every * client. This is achieved by calling send which actually changes * the value only when the message from the MessageServer is received. * * A "dirty" policy means that as soon as setValue is called the * property is changed immediately. And additionally sent over network. * This can sometimes lead to bugs as the other clients do not * immediately have the same value. For more information see * changeValue. * * PolicyLocal means that a KGameProperty behaves like ever * "normal" variable. Whenever setValue is called (e.g. using "=") * the value of the property is changes immediately without sending it * over network. You might want to use this if you are sure that all * clients set the property at the same time. **/ enum PropertyPolicy { PolicyUndefined = 0, PolicyClean = 1, PolicyDirty = 2, PolicyLocal = 3 }; /** * Constructs a KGamePropertyBase object and calls registerData. * @param id The id of this property. MUST be UNIQUE! Used to send and * receive changes in the property of the player automatically via * network. * @param owner The owner of the object. Must be a KGamePropertyHandler which manages * the changes made to this object, i.e. which will send the new data **/ KGamePropertyBase(int id, KGamePropertyHandler* owner); KGamePropertyBase(int id, KGame* parent); KGamePropertyBase(int id, KPlayer* parent); /** * Creates a KGamePropertyBase object without an owner. Remember to call * registerData! **/ KGamePropertyBase(); virtual ~KGamePropertyBase(); /** * Changes the consistency policy of a property. The * PropertyPolicy is one of PolicyClean (defaulz), PolicyDirty or PolicyLocal. * * It is up to you to decide how you want to work. **/ void setPolicy(PropertyPolicy p) { mFlags.bits.policy = p; } /** * @return The default policy of the property **/ PropertyPolicy policy() const { return (PropertyPolicy)mFlags.bits.policy; } /** * Sets this property to emit a signal on value changed. * As the properties do not inherit QObject for optimization * this signal is emitted via the KPlayer or KGame object **/ void setEmittingSignal(bool p) { mFlags.bits.emitsignal=p; } /** * See also setEmittingSignal * @return Whether this property emits a signal on value change **/ bool isEmittingSignal() const { return mFlags.bits.emitsignal; } /** * Sets this property to try to optimize signal and network handling * by not sending it out when the property value is not changed. **/ void setOptimized(bool p) { mFlags.bits.optimize = p ; } /** * See also setOptimize * @return Whether the property optimizes access (signals,network traffic) **/ bool isOptimized() const { return mFlags.bits.optimize; } /** * @return Whether this property is "dirty". See also setDirty **/ bool isDirty() const { return mFlags.bits.dirty; } /** * A locked property can only be changed by the player who has set the * lock. See also setLocked * @return Whether this property is currently locked. **/ bool isLocked() const { return mFlags.bits.locked; } /** * A locked property can only be changed by the player who has set the * lock. * * You can only call this if isLocked is false. A message is sent * over network so that the property is locked for all players except * you. * * @return returns false if the property can not be locked, i.e. it is already locked * **/ bool lock(); /** * A locked property can only be changed by the player who has set the * lock. * * You can only call this if isLocked is false. A message is sent * over network so that the property is locked for all players except * you. * * @return returns false if the property can not be locked, i.e. it is already locked * **/ bool unlock(bool force=false); /** * This will read the value of this property from the stream. You MUST * overwrite this method in order to use this class * @param s The stream to read from **/ virtual void load(QDataStream& s) = 0; /** * Write the value into a stream. MUST be overwritten **/ virtual void save(QDataStream& s) = 0; /** * send a command to advanced properties like arrays * @param stream The stream containing the data of the command * @param msgid The ID of the command - see PropertyCommandIds * @param isSender whether this client is also the sender of the command **/ virtual void command(QDataStream &stream, int msgid, bool isSender=false); /** * @return The id of this property **/ int id() const { return mId; } /** * @return a type_info of the data this property contains. **/ virtual const type_info* typeinfo() { return &typeid(this); } /** * You have to register a KGamePropertyBase before you can use it. * * You MUST call this before you can use KGamePropertyBase! * * @param id the id of this KGamePropertyBase object. The id MUST be * unique, i.e. you cannot have two properties with the same id for one * player, although (currently) nothing prevents you from doing so. But * you will get strange results! * * @param owner The owner of this data. This will send the data * using KPropertyHandler::sendProperty whenever you call send * * @param p If not 0 you can set the policy of the property here * * @param name if not 0 you can assign a name to this property * **/ int registerData(int id, KGamePropertyHandler* owner,PropertyPolicy p, const QString& name=QString()); /** * This is an overloaded member function, provided for convenience. * It differs from the above function only in what argument(s) it accepts. **/ int registerData(int id, KGamePropertyHandler* owner, const QString& name=QString()); /** * This is an overloaded member function, provided for convenience. * It differs from the above function only in what argument(s) it accepts. **/ int registerData(int id, KGame* owner, const QString& name=QString()); /** * This is an overloaded member function, provided for convenience. * It differs from the above function only in what argument(s) it accepts. **/ int registerData(int id, KPlayer* owner, const QString& name=QString()); /** * This is an overloaded member function, provided for convenience. * It differs from the above function only in what argument(s) it accepts. * In particular you can use this function to create properties which * will have an automatic id assigned. The new id is returned. **/ int registerData(KGamePropertyHandler* owner,PropertyPolicy p=PolicyUndefined, const QString& name=QString() ); void unregisterData(); protected: /** * A locked property can only be changed by the player who has set the * lock. * * You can only call this if isLocked is false. A message is sent * over network so that the property is locked for all players except * you. * Usually you use lock and unlock to access this property * **/ void setLock(bool l); /** * Sets the "dirty" flag of the property. If a property is "dirty" i.e. * KGameProperty::setLocal has been called there is no guarantee * that all clients share the same value. You have to ensure this * yourself e.g. by calling KGameProperty::setLocal on every * client. You can also ignore the dirty flag and continue working withe * the property depending on your situation. **/ void setDirty(bool d) { mFlags.bits.dirty = d ; } /** * Forward the data to the owner of this property which then sends it * over network. save is used to store the data into a stream so * you have to make sure that function is working properly if you * implement your own property! * * Note: this sends the current property! * * Might be obsolete - KGamePropertyArray still uses it. Is this a bug * or correct? **/ bool sendProperty(); /** * Forward the data to the owner of this property which then sends it * over network. save is used to store the data into a stream so * you have to make sure that function is working properly if you * implement your own property! * * This function is used by send to send the data over network. * This does not send the current value but the explicitly * given value. * * @return TRUE if the message could be sent successfully, otherwise * FALSE **/ bool sendProperty(const QByteArray& b); /** * Causes the parent object to emit a signal on value change **/ void emitSignal(); protected: KGamePropertyHandler* mOwner; // Having this as a union of the bitfield and the char // allows us to stream this quantity easily (if we need to) // At the moment it is not yet transmitted union Flags { char flag; struct { // unsigned char dosave : 1; // do save this property // unsigned char delaytransmit : 1; // do not send immediately on // change but a KPlayer:QTimer // sends it later on - fast // changing variables unsigned char emitsignal : 1; // KPlayer notifies on variable change (true) //unsigned char readonly : 1; // whether the property can be changed (false) unsigned char optimize : 1; // whether the property tries to optimize send/emit (false) unsigned char dirty: 1; // whether the property dirty (setLocal() was used) unsigned char policy : 2; // whether the property is always consistent (see PropertyPolicy) unsigned char locked: 1; // whether the property is locked (true) } bits; } mFlags; private: friend class KGamePropertyHandler; void init(); private: int mId; }; /** * \class KGameProperty kgameproperty.h * * @short A class for network transparent games * * Note: The entire API documentation is obsolete! * * The class KGameProperty can store any form of data and will transmit it via * network whenever you call send. This makes network transparent games * very easy. You first have to register the data to a KGamePropertyHandler * using KGamePropertyBase::registerData (which is called by the * constructor). For the KGamePropertyHandler you can use * KGame::dataHandler or KPlayer::dataHandler but you can also create your * own data handler. * * There are several concepts you can follow when writing network games. These * concepts differ completely from the way how data is transferred so you should * decide which one to use. You can also mix these concepts for a single * property but we do not recommend this. The concepts: *
    *
  • Always Consistent (clean) *
  • Not Always Consistent (dirty) *
  • A Mixture (very dirty) *
* I repeat: we do not recommend the third option ("a mixture"). Unless * you have a good reason for this you will probably introduce some hard to find * (and to fix) bugs. * * @section Always consistent (clean): * * This "policy" is default. Whenever you create a KGameProperty it is always * consistent. This means that consistency is the most important thing for the * property. This is achieved by using send to change the value of the * property. send needs a running KMessageServer and therefore * MUST be plugged into a KGamePropertyHandler using either * registerData or the constructor. The parent of the dataHandler must be able * to send messages (see above: the message server must be running). If you use * send to change the value of a property you won't see the effect * immediately: The new value is first transferred to the message server which * queues the message. As soon as all messages in the message server * which are before the changed property have been transferred the message * server delivers the new value of the KGameProperty to all clients. A * QTimer::singleShot is used to queue the messages inside the * KMessageServer. * * This means that if you do the following: * \code * KGamePropertyInt myProperty(id, dataHandler()); * myProperty.initData(0); * myProperty = 10; * int value = myProperty.value(); * \endcode * then "value" will be "0". initData is used to initialize the property * (e.g. when the KMessageServer is not yet running or can not yet be * reached). This is because "myProperty = 10" or "myProperty.send(10)" send a * message to the KMessageServer which uses QTimer::singleShot to * queue the message. The game first has to go back into the event loop where * the message is received. The KGamePropertyHandler receives the new value * sets the property. So if you need the new value you need to store it in a * different variable (see setLocal which creates one for you until the * message is received). The KGamePropertyHandler emits a signal (unless * you called setEmitSignal with false) when the new value is received: * KGamePropertyHandler::signalPropertyChanged. You can use this to react * to a changed property. * * This may look quite confusing but it has a big advantage: all * KGameProperty objects are ensured to have the same value on all clients in * the game at every time. This way you will save you a lot of trouble as * debugging can be very difficult if the value of a property changes * immediately on client A but only after one or two additional messages * (function calls, status changes, ...) on client B. * * The only disadvantage of this (clean) concept is that you cannot use a * changed variable immediately but have to wait for the KMessageServer to * change it. You probably want to use * KGamePropertyHandler::signalPropertyChanged for this. * * @section Not Always Consistent (dirty): * * There are a lot of people who don't want to use the (sometimes quite complex) * "clean" way. You can use setAlwaysConsistent to change the default * behaviour of the KGameProperty. If a property is not always consistent * it will use changeValue to send the property. changeValue also uses * send to send the new value over network but it also uses * setLocal to create a local copy of the property. This copy is created * dynamically and is deleted again as soon as the next message from the network * is received. To use the example above again: * \code * KGamePropertyInt myProperty(id, dataHandler()); * myProperty.setAlwaysConsistent(false); * myProperty.initData(0); * myProperty = 10; * int value = myProperty.value(); * \endcode * Now this example will "work" so value now is 10. Additionally the * KMessageServer receives a message from the local client (just as explained * above in "Always Consistent"). As soon as the message returns to the local * client again the local value is deleted, as the "network value" has the same * value as the local one. So you won't lose the ability to use the always * consistent "clean" value of the property if you use the "dirty" way. Just use * networkValue to access the value which is consistent among all clients. * * The advantage of this concept is clear: you can use a KGameProperty as * every other variable as the changes value takes immediate effect. * Additionally you can be sure that the value is transferred to all clients. * You will usually not experience serious bugs just because you use the "dirty" * way. Several events have to happen at once to get these "strange errors" * which result in inconsistent properties (like "game running" on client A but * "game ended/paused" on client B). But note that there is a very good reason * for the existence of these different concepts of KGameProperty. I have * myself experienced such a "strange error" and it took me several days to find * the reason until I could fix it. So I personally recommend the "clean" way. * On the other hand if you want to port a non-network game to a network game * you will probably start with "dirty" properties as it is you will not have to * change that much code... * * @section A Mixture (very dirty): * * You can also mix the concepts above. Note that we really don't recommend * this. With a mixture I mean something like this: * \code * KGamePropertyInt myProperty(id, dataHandler()); * myProperty.setAlwaysConsistent(false); * myProperty.initData(0); * myProperty = 10; * myProperty.setAlwaysConsistent(true); * myProperty = 20; * \endcode * (totally senseless example, btw) I.e. I am speaking of mixing both concepts * for a single property. Things like * \code * KGamePropertyInt myProperty1(id1, dataHandler()); * KGamePropertyInt myProperty2(id2, dataHandler()); * myProperty1.initData(0); * myProperty2.initData(0); * myProperty1.setAlwaysConsistent(false); * myProperty2.setAlwaysConsistent(true); * myProperty1 = 10; * myProperty2 = 20; * \endcode * are ok. But mixing the concepts for a single property will make it nearly * impossible to you to debug your game. * * So the right thing to do(tm) is to decide in the constructor whether you want * a "clean" or "dirty" property. * * Even if you have decided for one of the concepts you still can manually * follow another concept than the "policy" of your property. So if you use an * always consistent KGameProperty you still can manually call * changeValue as if it was not always consistent. Note that although this is * also kind of a "mixture" as described above this is very useful sometimes. In * contrast to the "mixture" above you don't have the problem that you don't * exactly know which concept you are currently following because you used the * function of the other concept only once. * * @section Custom classes: * * If you want to use a custum class with KGameProperty you have to implement the * operators << and >> for QDataStream: * \code * class Card * { * public: * int type; * int suite; * }; * QDataStream& operator<<(QDataStream& stream, Card& card) * { * qint16 type = card.type; * qint16 suite = card.suite; * s << type; * s << suite; * return s; * } * QDataStream& operator>>(QDataStream& stream, Card& card) * { * qint16 type; * qint16 suite; * s >> type; * s >> suite; * card.type = (int)type; * card.suite = (int)suite; * return s; * } * * class Player : KPlayer * { * [...] * KGameProperty mCards; * }; * \endcode * * Note: unlike most QT classes KGameProperty objects are *not* deleted * automatically! So if you create an object using e.g. KGameProperty* data = * new KGameProperty(id, dataHandler()) you have to put a delete data into your * destructor! * * @author Andreas Beckermann **/ template class KGameProperty : public KGamePropertyBase { public: /** * Constructs a KGameProperty object. A KGameProperty object will transmit * any changes to the KMessageServer and then to all clients in the * game (including the one that has sent the new value) * @param id The id of this property. MUST be UNIQUE! Used to send and * receive changes in the property of the playere automatically via * network. * @param owner The parent of the object. Must be a KGame which manages * the changes made to this object, i.e. which will send the new data. * Note that in contrast to most KDE/QT classes KGameProperty objects * are not deleted automatically! **/ // TODO: ID: Very ugly - better use something like parent()->propertyId() or so which assigns a free id automatically. KGameProperty(int id, KGamePropertyHandler* owner) : KGamePropertyBase(id, owner) { init(); } /** * This constructor does nothing. You have to call * KGamePropertyBase::registerData * yourself before using the KGameProperty object. **/ KGameProperty() : KGamePropertyBase() { init(); } virtual ~KGameProperty() {} /** * Set the value depending on the current policy (see * setConsistent). By default KGameProperty just uses send to set * the value of a property. This behaviour can be changed by using * setConsistent. * @param v The new value of the property **/ void setValue(type v) { switch (policy()) { case PolicyClean: send(v); break; case PolicyDirty: changeValue(v); break; case PolicyLocal: setLocal(v); break; default: // NEVER! qCritical() << "Undefined Policy in property" << id(); return; } } /** * This function sends a new value over network. * * Note that the value DOES NOT change when you call this function. This * function saves the value into a QDataStream and calls * sendProperty where it gets forwarded to the owner and finally the * value is sent over network. The KMessageServer now sends the * value to ALL clients - even the one who called this function. As soon * as the value from the message server is received load is called * and _then_ the value of the KGameProperty has been set. * * This ensures that a KGameProperty has _always_ the same value on * _every_ client in the network. Note that this means you can NOT do * something like * \code * myProperty.send(1); * doSomething(myProperty); * \endcode * as myProperty has not yet been set when doSomething is being called. * * You are informed about a value change by a signal from the parent of * the property which can be deactivated by setEmittingSignal because of * performance (you probably don't have to deactivate it - except you * want to write a real-time game like Command&Conquer with a lot of * activity). See emitSignal * * Note that if there is no KMessageServer accessible - before * the property has been registered to the KGamePropertyHandler (as * it is the case e.g. before a KPlayer has been plugged into the * KGame object) the property is *not* sent but set *locally* (see * setLocal)! * * @param v The new value of the property * @return whether the property could be sent successfully * @see setValue setLocal changeValue value **/ bool send(type v) { if (isOptimized() && mData == v) { return true; } if (isLocked()) { return false; } QByteArray b; QDataStream stream(&b, QIODevice::WriteOnly); stream << v; if (!sendProperty(b)) { setLocal(v); return false; } return true; } /** * This function sets the value of the property directly, i.e. it * doesn't send it to the network. * * Int contrast to @see you change _only_ the local value when using * this function. You do _not_ change the value of any other client. You * probably don't want to use this if you are using a dedicated server * (which is the only "client" which is allowed to change a value) but * rather want to use send(). * * But if you use your clients as servers (i.e. all clients receive a * players turn and then calculate the reaction of the game theirselves) * then you probably want to use setLocal as you can do things like * \code * myProperty.setLocal(1); * doSomething(myProperty); * \endcode * on every client. * * If you want to set the value locally AND send it over network you * want to call changeValue! * * You can also use setPolicy to set the default policy to * PolicyLocal. * * @see setValue send changeValue value **/ bool setLocal(type v) { if (isOptimized() && mData == v) { return false; } if (isLocked()) { return false; } mData = v; setDirty(true); if (isEmittingSignal()) { emitSignal(); } return true; } /** * This function does both, change the local value and change the * network value. The value is sent over network first, then changed * locally. * * This function is a convenience function and just calls send * followed by setLocal * * Note that emitSignal is also called twice: once after * setLocal and once when the value from send is received * * @see send setLocal setValue value **/ void changeValue(type v) { send(v); setLocal(v); } /** * Saves the object to a stream. * @param stream The stream to save to **/ - void save(QDataStream &stream) Q_DECL_OVERRIDE + void save(QDataStream &stream) override { stream << mData; } /** * @return The local value (see setLocal) if it is existing, * otherwise the network value which is always consistent on every * client. **/ const type& value() const { return mData; } /** * Reads from a stream and assigns the read value to this object. * * This function is called automatically when a new value is received * over network (i.e. it has been sent using send on this or any * other client) or when a game is loaded (and maybe on some other * events). * * Also calls emitSignal if isEmittingSignal is TRUE. * @param s The stream to read from **/ - void load(QDataStream& s) Q_DECL_OVERRIDE + void load(QDataStream& s) override { s >> mData; setDirty(false); if (isEmittingSignal()) { emitSignal(); } } /** * This calls setValue to change the value of the property. Note * that depending on the policy (see setAlwaysConsistent) the * returned value might be different from the assigned value!! * * So if you use setPolicy(PolicyClean): * \code * int a, b = 10; * myProperty = b; * a = myProperty.value(); * \endcode * Here a and b would differ! * The value is actually set as soon as it is received from the * KMessageServer which forwards it to ALL clients in the network. * * If you use a clean policy (see setPolicy) then * the returned value is the assigned value **/ const type& operator=(const type& t) { setValue(t); return value(); } /** * This copies the data of property to the KGameProperty object. * * Equivalent to setValue(property.value()); **/ const type& operator=(const KGameProperty& property) { setValue(property.value()); return value(); } /** * Yeah, you can do it! * \code * int a = myGamePropertyInt; * \endcode * If you don't see it: you don't have to use integerData.value() **/ operator type() const { return value(); } - const type_info* typeinfo() Q_DECL_OVERRIDE { return &typeid(type); } + const type_info* typeinfo() override { return &typeid(type); } private: void init() { } private: type mData; }; typedef KGameProperty KGamePropertyInt; typedef KGameProperty KGamePropertyUInt; typedef KGameProperty KGamePropertyQString; typedef KGameProperty KGamePropertyBool; #endif diff --git a/libkdegamesprivate/kgame/kmessageio.h b/libkdegamesprivate/kgame/kmessageio.h index 588309fc..35c6e3c4 100644 --- a/libkdegamesprivate/kgame/kmessageio.h +++ b/libkdegamesprivate/kgame/kmessageio.h @@ -1,393 +1,393 @@ /* This file is part of the KDE games library Copyright (C) 2001 Burkhard Lehner (Burkhard.Lehner@gmx.de) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 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 Library General Public License for more details. You should have received a copy of the GNU Library 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. */ /* KMessageIO class and subclasses KMessageSocket and KMessageDirect */ #ifndef _KMESSAGEIO_H_ #define _KMESSAGEIO_H_ #include #include #include #include #include #include "../libkdegamesprivate_export.h" /* This macro shouldn't be here ideally. Already declared in kgame.h, but throws error if not placed here. */ Q_DECLARE_LOGGING_CATEGORY(GAMES_PRIVATE_KGAME) class QTcpSocket; class KProcess; /** \class KMessageIO kmessageio.h This abstract base class represents one end of a message connections between two clients. Each client has one object of a subclass of KMessageIO. Calling /e send() on one object will emit the signal /e received() on the other object, and vice versa. For each type of connection (TCP/IP socket, COM port, direct connection within the same class) a subclass of KMessageIO must be defined that implements the pure virtual methods /e send() and /e isConnected(), and sends the signals. (See /e KMessageSocket for an example implementation.) Two subclasses are already included: /e KMessageSocket (connection using TCP/IP sockets) and /e KMessageDirect (connection using method calls, both sides must be within the same process). */ class KDEGAMESPRIVATE_EXPORT KMessageIO : public QObject { Q_OBJECT public: /** * The usual QObject constructor, does nothing else. **/ KMessageIO (QObject *parent = nullptr); /** * The usual destructor, does nothing special. **/ ~KMessageIO (); /** * The runtime identification */ virtual int rtti() const {return 0;} /** * @return Whether this KMessageIO is a network IO or not. **/ //virtual bool isNetwork () const = 0; virtual bool isNetwork () const { qCCritical(GAMES_PRIVATE_KGAME) << "Calling PURE virtual isNetwork...BAD"; return false; } /** This method returns the status of the object, whether it is already (or still) connected to another KMessageIO object or not. This is a pure virtual method, so it has to be implemented in a subclass of KMessageIO. */ //virtual bool isConnected () const = 0; virtual bool isConnected () const { qCCritical(GAMES_PRIVATE_KGAME) << "Calling PURE virtual isConnected...BAD"; return false; } /** Sets the ID number of this object. This number can for example be used to distinguish several objects in a server. NOTE: Sometimes it is useful to let two connected KMessageIO objects have the same ID number. You have to do so yourself, KMessageIO doesn't change this value on its own! */ void setId (quint32 id); /** Queries the ID of this object. */ quint32 id (); /** @return 0 in the default implementation. Reimplemented in @ref KMessageSocket. */ virtual quint16 peerPort () const { return 0; } /** @return "localhost" in the default implementation. Reimplemented in @ref KMessageSocket */ virtual QString peerName () const { return QStringLiteral("localhost"); } Q_SIGNALS: /** This signal is emitted when /e send() on the connected KMessageIO object is called. The parameter contains the same data array in /e msg as was used in /e send(). */ void received (const QByteArray &msg); /** This signal is emitted when the connection is closed. This can be caused by a hardware error (e.g. broken internet connection) or because the other object was killed. Note: Sometimes a broken connection can be undetected for a long time, or may never be detected at all. So don't rely on this signal! */ void connectionBroken (); public Q_SLOTS: /** This slot sends the data block in /e msg to the connected object, that will emit /e received(). For a concrete class, you have to subclass /e KMessageIO and overwrite this method. In the subclass, implement this method as an ordinary method, not as a slot! (Otherwise another slot would be defined. It would work, but uses more memory and time.) See /e KMessageSocket for an example implementation. */ virtual void send (const QByteArray &msg) = 0; protected: quint32 m_id; }; /** \class KMessageSocket kmessageio.h This class implements the message communication using a TCP/IP socket. The object can connect to a server socket, or can use an already connected socket. */ class KMessageSocket : public KMessageIO { Q_OBJECT public: /** Connects to a server socket on /e host with /e port. host can be an numerical (e.g. "192.168.0.212") or symbolic (e.g. "wave.peter.org") IP address. You can immediately use the /e sendSystem() and /e sendBroadcast() methods. The messages are stored and sent to the receiver after the connection is established. If the connection could not be established (e.g. unknown host or no server socket at this port), the signal /e connectionBroken is emitted. */ KMessageSocket (const QString& host, quint16 port, QObject *parent = nullptr ); /** Connects to a server socket on /e host with /e port. You can immediately use the /e sendSystem() and /e sendBroadcast() methods. The messages are stored and sent to the receiver after the connection is established. If the connection could not be established (e.g. unknown host or no server socket at this port), the signal /e connectionBroken is emitted. */ KMessageSocket (const QHostAddress &host, quint16 port, QObject *parent = nullptr); /** Uses /e socket to do the communication. The socket should already be connected, or at least be in /e connecting state. Note: The /e socket object is then owned by the /e KMessageSocket object. So don't use it otherwise any more and don't delete it. It is deleted together with this KMessageSocket object. (Use 0 as parent for the QSocket object t ensure it is not deleted.) */ explicit KMessageSocket (QTcpSocket *socket, QObject *parent = nullptr); /** Uses the socket specified by the socket descriptor socketFD to do the communication. The socket must already be connected. This constructor can be used with a QServerSocket within the (pure virtual) method /e newConnection. Note: The socket is then owned by the /e KMessageSocket object. So don't manipulate the socket afterwards, especially don't close it. The socket is automatically closed when KMessageSocket is deleted. */ explicit KMessageSocket (int socketFD, QObject *parent = nullptr); /** Destructor, closes the socket. */ ~KMessageSocket (); /** * The runtime identification */ - int rtti() const Q_DECL_OVERRIDE {return 1;} + int rtti() const override {return 1;} /** @return The port that this object is connected to. See QSocket::peerPort */ - quint16 peerPort () const Q_DECL_OVERRIDE; + quint16 peerPort () const override; /** @return The hostname this object is connected to. See QSocket::peerName. */ - QString peerName () const Q_DECL_OVERRIDE; + QString peerName () const override; /** @return TRUE as this is a network IO. */ - bool isNetwork() const Q_DECL_OVERRIDE { return true; } + bool isNetwork() const override { return true; } /** Returns true if the socket is in state /e connected. */ - bool isConnected () const Q_DECL_OVERRIDE; + bool isConnected () const override; /** Overwritten slot method from KMessageIO. Note: It is not declared as a slot method, since the slot is already defined in KMessageIO as a virtual method. */ - void send (const QByteArray &msg) Q_DECL_OVERRIDE; + void send (const QByteArray &msg) override; protected Q_SLOTS: virtual void processNewData (); protected: void initSocket (); QTcpSocket *mSocket; bool mAwaitingHeader; quint32 mNextBlockLength; bool isRecursive; // workaround for "bug" in QSocket, Qt 2.2.3 or older }; /** \class KMessageDirect kmessageio.h This class implements the message communication using function calls directly. It can only be used when both sides of the message pipe are within the same process. The communication is very fast. To establish a communication, you have to create two instances of KMessageDirect, the first one with no parameters in the constructor, the second one with the first as parameter: /code KMessageDirect *peer1, *peer2; peer1 = new KMessageDirect (); // unconnected peer2 = new KMessageDirect (peer1); // connect with peer1 /endcode The connection is only closed when one of the instances is deleted. */ class KMessageDirect : public KMessageIO { Q_OBJECT public: /** Creates an object and connects it to the object given in the first parameter. Use 0 as first parameter to create an unconnected object, that is later connected. If that object is already connected, the object remains unconnected. */ explicit KMessageDirect (KMessageDirect *partner = 0, QObject *parent = nullptr); /** Destructor, closes the connection. */ ~KMessageDirect (); /** * The runtime identification */ - int rtti() const Q_DECL_OVERRIDE {return 2;} + int rtti() const override {return 2;} /** @return FALSE as this is no network IO. */ - bool isNetwork() const Q_DECL_OVERRIDE { return false; } + bool isNetwork() const override { return false; } /** Returns true, if the object is connected to another instance. If you use the first constructor, the object is unconnected unless another object is created with this one as parameter. The connection can only be closed by deleting one of the objects. */ - bool isConnected () const Q_DECL_OVERRIDE; + bool isConnected () const override; /** Overwritten slot method from KMessageIO. Note: It is not declared as a slot method, since the slot is already defined in KMessageIO as a virtual method. */ - void send (const QByteArray &msg) Q_DECL_OVERRIDE; + void send (const QByteArray &msg) override; protected: KMessageDirect *mPartner; }; /** * \class KMessageProcess kmessageio.h */ class KMessageProcess : public KMessageIO { Q_OBJECT public: KMessageProcess(QObject *parent, const QString& file); ~KMessageProcess(); - bool isConnected() const Q_DECL_OVERRIDE; - void send (const QByteArray &msg) Q_DECL_OVERRIDE; + bool isConnected() const override; + void send (const QByteArray &msg) override; /** @return FALSE as this is no network IO. */ - bool isNetwork() const Q_DECL_OVERRIDE { return false; } + bool isNetwork() const override { return false; } /** * The runtime identification */ - int rtti() const Q_DECL_OVERRIDE {return 3;} + int rtti() const override {return 3;} public Q_SLOTS: void slotReceivedStdout(); void slotReceivedStderr(); void slotProcessExited(int, QProcess::ExitStatus); Q_SIGNALS: void signalReceivedStderr(const QString &msg); private: QString mProcessName; KProcess *mProcess; QByteArray* mSendBuffer; QByteArray mReceiveBuffer; int mReceiveCount; }; #endif diff --git a/libkdegamesprivate/kgamecanvas.h b/libkdegamesprivate/kgamecanvas.h index c4dabd05..f28d9e43 100644 --- a/libkdegamesprivate/kgamecanvas.h +++ b/libkdegamesprivate/kgamecanvas.h @@ -1,684 +1,684 @@ /* Originally created for KBoard Copyright 2006 Maurizio Monge BSD License 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 THE AUTHOR ``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 THE AUTHOR 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 __KGAMECANVAS_H__ #define __KGAMECANVAS_H__ /* * Author: Maurizio Monge */ #include #include #include #include #include #include #include #include #include "libkdegamesprivate_export.h" #include class KGameCanvasItem; /** \class KGameCanvasAbstract kgamecanvas.h \brief Container class. A KGameCanvasAbstract is a set of canvas items. \deprecated For new applications, use Qt's Graphics View framework or Qt Quick. */ class KDEGAMESPRIVATE_EXPORT KGameCanvasAbstract { protected: friend class KGameCanvasItem; QList m_items; QList m_animated_items; public: /** The constructor */ KGameCanvasAbstract(); virtual ~KGameCanvasAbstract(); /** Returns a const pointer to the list holding all the items in the canvas */ const QList* items() const { return &m_items; } /** Helper function to retrieve the topmost item at the given position */ KGameCanvasItem* itemAt(const QPoint &pos) const; /** Overload, same as above */ KGameCanvasItem* itemAt(int x, int y) const { return itemAt(QPoint(x,y)); } /** Helper function to retrieve all the items at the given position, starting from the topmost one. */ QList itemsAt(const QPoint &pos) const; /** Overload, same as above */ QList itemsAt(int x, int y) const { return itemsAt(QPoint(x,y)); } /** Virtual function to let know the canvas that it has animated items in it */ virtual void ensureAnimating() = 0; /** Virtual function to ensure an update is pending, called from children */ virtual void ensurePendingUpdate() = 0; /** Virtual function to update a rect */ virtual void invalidate(const QRect& r, bool translate = true) = 0; /** Virtual function to update a region */ virtual void invalidate(const QRegion& r, bool translate = true) = 0; /** Returns the toplevel non-group KGameCanvasWidget object */ virtual class KGameCanvasWidget* topLevelCanvas() = 0; /** @return Position of the abstract canvas relative to the toplevel canvas. */ virtual QPoint canvasPosition() const = 0; }; /** \class KGameCanvasItem kgamecanvas.h \brief An abstract item. A KGameCanvasItem is an abstract class to represent a generic item that can be put in a canvas. \deprecated For new applications, use Qt's Graphics View framework or Qt Quick. */ class KDEGAMESPRIVATE_EXPORT KGameCanvasItem { private: friend class KGameCanvasAbstract; friend class KGameCanvasWidget; friend class KGameCanvasGroup; friend class KGameCanvasAdapter; bool m_visible; bool m_animated; int m_opacity; QPoint m_pos; KGameCanvasAbstract *m_canvas; bool m_changed; QRect m_last_rect; static QPixmap* transparence_pixmap_cache; static QPixmap* getTransparenceCache(const QSize &s); virtual void paintInternal(QPainter* p, const QRect& prect, const QRegion& preg, const QPoint &delta, double cumulative_opacity); void updateAfterRestack(int from, int to); /* function to update pending changes, called from parent */ virtual void updateChanges(); public: /** Constructor, it allows you to specify the reference canvas or to create an orphan item that will be put into a canvas in a second moment. The item is always hidden after being created. Note that the restacking functions are quite intelligent and will only repaint if there is an actual need of doing it. So if you call raise on an item that is already (locally) on the top, no redraw will take place */ KGameCanvasItem(KGameCanvasAbstract* canvas = NULL); virtual ~KGameCanvasItem(); /** schedule an update if the item */ virtual void changed(); /** Returns true if the item is visible */ bool visible() const { return m_visible; } /** Set the item as visible or hidden */ void setVisible(bool v); /** Returns true if the item is animated */ bool animated() const { return m_animated; } /** Set the item as animated or not */ void setAnimated(bool a); /** Returns the opacity of the item */ int opacity() const { return m_opacity; } /** Set the item's opacity value (int the 0-255 range) */ void setOpacity(int o); /** Hides the item */ void hide(){ setVisible(false); } /** Shows the item */ void show(){ setVisible(true); } /** Restacks the item on the top of the canvas */ void raise(); /** Restacks the item on the bottom of the canvas */ void lower(); /** Restacks the item immediately over ref */ void stackOver(KGameCanvasItem* ref); /** Restacks the item immediately under ref */ void stackUnder(KGameCanvasItem* ref); /** Returns the canvas that is actually "owning" the item */ KGameCanvasAbstract *canvas() const { return m_canvas; } /** Returns the toplevel canvas widget, or NULL */ KGameCanvasWidget *topLevelCanvas() const { return m_canvas ? m_canvas->topLevelCanvas() : NULL; } /** Lets you specify the owning canvas. Call this function with canvas set to NULL to remove the item from the current canvas. */ void putInCanvas(KGameCanvasAbstract *canvas); /** Returns the position of the item */ QPoint pos() const { return m_pos; } /** @return Position of the item relative to the top level canvas. */ QPoint absolutePosition() const; /** Sets a new position. Note that an update will be posted to the parent canvas, and if you move an item twice in very little time, a region bigger than needed will be updated, causing a possible inefficiency */ void moveTo(const QPoint &newpos); /** Overload, same as above */ void moveTo(int x, int y) { moveTo( QPoint(x,y)); } /** Override this function to draw the item with the painter */ virtual void paint(QPainter* p) = 0; /** Override this function to return the rect the item will be drawn into */ virtual QRect rect() const = 0; /** Override this function to specify if the painting operations will paint over each other. If not, the item will be drawn more quickly when opacity is != 255, because it does not have to be painted onto a pixmap first. If you don't care about the item's opacity, don't care about this function as well. */ virtual bool layered() const; /** Override this function to handle animations, the default function does nothing. The argument is the number of milliseconds from the creation of the canvas, so that you use it to handle the animation. */ virtual void advance(int msecs); }; /** \class KGameCanvasDummy kgamecanvas.h \brief A dummy (empty) item. A KGameCanvasDummy is an empty, invisible item. You can use it as reference for stacking items in the canvas using the stackOver and stackUnder functions. \deprecated For new applications, use Qt's Graphics View framework or Qt Quick. */ class KDEGAMESPRIVATE_EXPORT KGameCanvasDummy : public KGameCanvasItem { public: /** Constructor */ KGameCanvasDummy(KGameCanvasAbstract* canvas = NULL); virtual ~KGameCanvasDummy(); /** This function does nothing (of course) */ - void paint(QPainter* p) Q_DECL_OVERRIDE; + void paint(QPainter* p) override; /** This returns an empty rectangle */ - QRect rect() const Q_DECL_OVERRIDE; + QRect rect() const override; }; /** \class KGameCanvasGroup kgamecanvas.h \brief An item containing other items. A KGameCanvasGroup is an KGameCanvasItem, but it is also a KGameCanvasAbstract, so you can add children items to it. Just an inner canvas, if you prefer. \deprecated For new applications, use Qt's Graphics View framework or Qt Quick. */ class KDEGAMESPRIVATE_EXPORT KGameCanvasGroup : public KGameCanvasItem, public KGameCanvasAbstract { private: mutable bool m_child_rect_changed; mutable QRect m_last_child_rect; void paintInternal(QPainter* p, const QRect& prect, const QRegion& preg, - const QPoint& delta, double cumulative_opacity) Q_DECL_OVERRIDE; + const QPoint& delta, double cumulative_opacity) override; - void ensureAnimating() Q_DECL_OVERRIDE; - void ensurePendingUpdate() Q_DECL_OVERRIDE; - void invalidate(const QRect& r, bool translate = true) Q_DECL_OVERRIDE; - void invalidate(const QRegion& r, bool translate = true) Q_DECL_OVERRIDE; - void updateChanges() Q_DECL_OVERRIDE; - void changed() Q_DECL_OVERRIDE; + void ensureAnimating() override; + void ensurePendingUpdate() override; + void invalidate(const QRect& r, bool translate = true) override; + void invalidate(const QRegion& r, bool translate = true) override; + void updateChanges() override; + void changed() override; public: /** Constructor */ KGameCanvasGroup(KGameCanvasAbstract* canvas = NULL); virtual ~KGameCanvasGroup(); /** This paints all the children */ - void paint(QPainter* p) Q_DECL_OVERRIDE; + void paint(QPainter* p) override; /** This returns the bouding rect of all children */ - QRect rect() const Q_DECL_OVERRIDE; + QRect rect() const override; /** Animations step, updates the animation for the children */ - void advance(int msecs) Q_DECL_OVERRIDE; + void advance(int msecs) override; /** returns the toplevel canvas (or null if it is in an orphan tree) */ - KGameCanvasWidget* topLevelCanvas() Q_DECL_OVERRIDE; + KGameCanvasWidget* topLevelCanvas() override; - QPoint canvasPosition() const Q_DECL_OVERRIDE; + QPoint canvasPosition() const override; }; /** \class KGameCanvasPicture kgamecanvas.h \brief A picture, ie a collection of paint operations. A KGameCanvasPicture is a picture that can be replayed on the canvas. \deprecated For new applications, use Qt's Graphics View framework or Qt Quick. */ class KDEGAMESPRIVATE_EXPORT KGameCanvasPicture : public KGameCanvasItem { private: QPicture m_picture; public: /** Constructor, specifying the picture to use */ KGameCanvasPicture(const QPicture& picture, KGameCanvasAbstract* canvas = NULL); /** Constructor, creating with an empty picture */ KGameCanvasPicture(KGameCanvasAbstract* canvas = NULL); virtual ~KGameCanvasPicture(); /** Returns the picture */ QPicture picture() const { return m_picture; } /** Sets the picture of the sprite */ void setPicture(const QPicture& picture); - void paint(QPainter* p) Q_DECL_OVERRIDE; - QRect rect() const Q_DECL_OVERRIDE; + void paint(QPainter* p) override; + QRect rect() const override; }; /** \class KGameCanvasPixmap kgamecanvas.h \brief A pixmap (sprite). A KGameCanvasPixmap is a pixmap that can be put in the canvas. \deprecated For new applications, use Qt's Graphics View framework or Qt Quick. */ class KDEGAMESPRIVATE_EXPORT KGameCanvasPixmap : public KGameCanvasItem { private: QPixmap m_pixmap; public: /** Constructor, specifying the pixmap to use */ KGameCanvasPixmap(const QPixmap& pixmap, KGameCanvasAbstract* canvas = NULL); /** Constructor, creating with an empty pixmap */ KGameCanvasPixmap(KGameCanvasAbstract* canvas = NULL); virtual ~KGameCanvasPixmap(); /** Returns the pixmap */ QPixmap pixmap() const { return m_pixmap; } /** Sets the pixmap of the sprite */ void setPixmap(const QPixmap& pixmap); - void paint(QPainter* p) Q_DECL_OVERRIDE; - QRect rect() const Q_DECL_OVERRIDE; - bool layered() const Q_DECL_OVERRIDE { return false; } + void paint(QPainter* p) override; + QRect rect() const override; + bool layered() const override { return false; } }; /** \class KGameCanvasRenderedPixmap kgamecanvas.h \brief A sprite pixmap from KGameRenderer. This canvas item behaves like KGameCanvasPixmap, but the pixmaps are served from a KGameRenderer. This class exists solely for the purpose of porting existing applications to KGameRenderer. \deprecated For new applications, use Qt's Graphics View framework or Qt Quick. */ class KDEGAMESPRIVATE_EXPORT KGameCanvasRenderedPixmap : public KGameCanvasPixmap, public KGameRendererClient { public: KGameCanvasRenderedPixmap(KGameRenderer* renderer, const QString& spriteKey, KGameCanvasAbstract* canvas = 0); protected: - void receivePixmap(const QPixmap& pixmap) Q_DECL_OVERRIDE; + void receivePixmap(const QPixmap& pixmap) override; }; /** \class KGameCanvasTiledPixmap kgamecanvas.h \brief A tiled pixmap (brush). A KGameCanvasTiledPixmap is a pixmap that can be put in the canvas. \deprecated For new applications, use Qt's Graphics View framework or Qt Quick. */ class KDEGAMESPRIVATE_EXPORT KGameCanvasTiledPixmap : public KGameCanvasItem { private: QPixmap m_pixmap; QSize m_size; QPoint m_origin; bool m_move_orig; public: /** Constructor, specifying the pixmap and the parameters to use */ KGameCanvasTiledPixmap(const QPixmap& pixmap, const QSize &size, const QPoint &origin, bool move_orig, KGameCanvasAbstract* canvas = NULL); /** Constructor, creating with an empty pixmap */ KGameCanvasTiledPixmap(KGameCanvasAbstract* canvas = NULL); virtual ~KGameCanvasTiledPixmap(); /** Returns the pixmap */ QPixmap pixmap() const { return m_pixmap; } /** Sets the pixmap of the tile */ void setPixmap(const QPixmap& pixmap); /** Sets the size */ void setSize(const QSize &size); /** The origin */ QPoint origin() const { return m_move_orig ? m_origin + pos() : m_origin; } /** Sets the origin of the tiles */ void setOrigin(const QPoint &size); /** If the origin is moved */ bool moveOrigin(){ return m_move_orig; } /** Sets if the origin of the brush will be moved with the pixmap */ void setMoveOrigin(bool move_orig); - void paint(QPainter* p) Q_DECL_OVERRIDE; - QRect rect() const Q_DECL_OVERRIDE; - bool layered() const Q_DECL_OVERRIDE { return false; } + void paint(QPainter* p) override; + QRect rect() const override; + bool layered() const override { return false; } }; /** \class KGameCanvasRectangle kgamecanvas.h \brief A solid rectangle. A KGameCanvasRectangle is a rectangle that can be put in the canvas. \deprecated For new applications, use Qt's Graphics View framework or Qt Quick. */ class KDEGAMESPRIVATE_EXPORT KGameCanvasRectangle : public KGameCanvasItem { private: QColor m_color; QSize m_size; public: /** Constructor, specifying the pixmap and the parameters to use */ KGameCanvasRectangle(const QColor& color, const QSize &size, KGameCanvasAbstract* canvas = NULL); /** Constructor, creating with an empty pixmap */ KGameCanvasRectangle(KGameCanvasAbstract* canvas = NULL); virtual ~KGameCanvasRectangle(); /** Returns the color */ QColor color() const { return m_color; } /** Sets the color */ void setColor(const QColor& color); /** Sets the size */ void setSize(const QSize &size); - void paint(QPainter* p) Q_DECL_OVERRIDE; - QRect rect() const Q_DECL_OVERRIDE; - bool layered() const Q_DECL_OVERRIDE { return false; } + void paint(QPainter* p) override; + QRect rect() const override; + bool layered() const override { return false; } }; /** \class KGameCanvasText kgamecanvas.h \brief KGameCanvasText. A KGameCanvasText is a text that can be put in the canvas. \deprecated For new applications, use Qt's Graphics View framework or Qt Quick. */ class KDEGAMESPRIVATE_EXPORT KGameCanvasText : public KGameCanvasItem { public: /** Specifies the meaning of the x coordinate of the item. It can refer to the start of the text, of the left, center, right of the bounding rectangle. */ enum HPos { HStart, HLeft, HRight, HCenter }; /** Specifies the meaning of the y coordinate of the item. It can refer to the baseline of the text, of the top, center, bottom of the bounding rectangle. */ enum VPos { VBaseline, VTop, VBottom, VCenter }; private: QString m_text; QColor m_color; QFont m_font; HPos m_hpos; VPos m_vpos; QRect m_bounding_rect; QPoint offsetToDrawPos() const; void calcBoundingRect(); public: /** Constructor, specifying the text and the parameters to use */ KGameCanvasText(const QString& text, const QColor& color, const QFont& font, HPos hp, VPos vp, KGameCanvasAbstract* canvas = NULL); /** Constructor, creating with an empty text */ KGameCanvasText(KGameCanvasAbstract* canvas = NULL); virtual ~KGameCanvasText(); /** Returns the text */ QString text() const { return m_text; } /** Sets the text */ void setText(const QString& text); /** Returns the color */ QColor color() const { return m_color; } /** Sets the color */ void setColor(const QColor& color); /** Returns the font */ QFont font() const { return m_font; } /** Sets the font */ void setFont(const QFont& font); /** Returns the horizontal positioning style */ HPos hPositioning() const { return m_hpos; } /** Returns the vertical positioning style */ VPos vPositioning() const { return m_vpos; } /** Sets the positioning style */ void setPositioning(HPos hp, VPos vp); - void paint(QPainter* p) Q_DECL_OVERRIDE; - QRect rect() const Q_DECL_OVERRIDE; - bool layered() const Q_DECL_OVERRIDE { return false; } + void paint(QPainter* p) override; + QRect rect() const override; + bool layered() const override { return false; } }; /** \class KGameCanvasWidget kgamecanvas.h \brief Container widget. A KGameCanvasWidget is a widget that can contain many KGameCanvasItem (images, rectangles, lines, etc). Portions of the widget are automatically redrawn to update the changes made to the items. \deprecated For new applications, use Qt's Graphics View framework or Qt Quick. */ class KDEGAMESPRIVATE_EXPORT KGameCanvasWidget : public QWidget, public KGameCanvasAbstract { Q_OBJECT private: friend class KGameCanvasItem; friend class AnimationNotifier; class KGameCanvasWidgetPrivate *priv; - void ensureAnimating() Q_DECL_OVERRIDE; - void ensurePendingUpdate() Q_DECL_OVERRIDE; - void invalidate(const QRect& r, bool translate = true) Q_DECL_OVERRIDE; - void invalidate(const QRegion& r, bool translate = true) Q_DECL_OVERRIDE; + void ensureAnimating() override; + void ensurePendingUpdate() override; + void invalidate(const QRect& r, bool translate = true) override; + void invalidate(const QRegion& r, bool translate = true) override; - void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE; + void paintEvent(QPaintEvent *event) override; private Q_SLOTS: void processAnimations(); void updateChanges(); public: /** The constructor */ KGameCanvasWidget(QWidget* parent = NULL); virtual ~KGameCanvasWidget(); /** Set the delay of the animation, in milliseconds */ void setAnimationDelay(int d); /** Return the number of milliseconds from the creation of the canvas (see also KGameCanvasItem::advance)*/ int mSecs(); /** returns 'this' */ - KGameCanvasWidget* topLevelCanvas() Q_DECL_OVERRIDE; + KGameCanvasWidget* topLevelCanvas() override; /** @return 0 */ - QPoint canvasPosition() const Q_DECL_OVERRIDE; + QPoint canvasPosition() const override; }; /** \class KGameCanvasAdapter kgamecanvas.h \brief A generic adapter for KGameCanvas KGameCanvasAdapter can be used to draw content managed by KGameCanvas inside systems which do not use KGameCanvas internally for their rendering. For example, suppose you have a widget CustomDisplay which paints itself with direct QPainter calls in its paintEvent, and you want to add a complex element to its rendering, which is best implemented via the KGameCanvas abstractions. What you can do is to create a KGameCanvasAdapter subclass, use it just like a KGameCanvasGroup, then call its render member function to have a QPainter object draw it. A KGameCanvas adapter notifies its parent using the pure virtual function updateParent, which is called when the adapter content is invalidated. \todo Support animations \deprecated For new applications, use Qt's Graphics View framework or Qt Quick. */ class KDEGAMESPRIVATE_EXPORT KGameCanvasAdapter : public KGameCanvasAbstract { QRect m_child_rect; bool m_child_rect_valid; QRect m_invalidated_rect; - void ensureAnimating() Q_DECL_OVERRIDE { } - void ensurePendingUpdate() Q_DECL_OVERRIDE; - void invalidate(const QRect& r, bool translate = true) Q_DECL_OVERRIDE; - void invalidate(const QRegion& r, bool translate = true) Q_DECL_OVERRIDE; + void ensureAnimating() override { } + void ensurePendingUpdate() override; + void invalidate(const QRect& r, bool translate = true) override; + void invalidate(const QRegion& r, bool translate = true) override; QRect childRect(); public: /** Constructor */ KGameCanvasAdapter(); /** * An adapter is not associated to any canvas, so this function * simply returns 0. */ - class KGameCanvasWidget* topLevelCanvas() Q_DECL_OVERRIDE { return 0; } + class KGameCanvasWidget* topLevelCanvas() override { return 0; } /** * The absolute position of the rendered content is not well * defined for KGameCanvasAdapter. We assume that the adapter * will be rendered at (0,0), and leave it to the user to perform * the necessary adjustments, which will depend on the chosen * rendering method. * * @return The point (0, 0). */ - QPoint canvasPosition() const Q_DECL_OVERRIDE { return QPoint(0, 0); } + QPoint canvasPosition() const override { return QPoint(0, 0); } /** * Draw the items of the adapter using the specified painter. * \param p The QPainter object to be used for rendering. */ virtual void render(QPainter* p); /** * Notify the parent that the adapter content inside \a rect needs * to be redrawn. * * \a rect The bounding rectangle of the region that needs repainting. */ virtual void updateParent(const QRect& rect) = 0; }; #endif //__KGRGAMECANVAS_H__