File indexing completed on 2024-04-28 04:05:04
0001 /* 0002 This file is part of the KDE games library 0003 SPDX-FileCopyrightText: 2001 Andreas Beckermann <b_mann@gmx.de> 0004 SPDX-FileCopyrightText: 2007 Simon Hürlimann <simon.huerlimann@huerlisi.ch> 0005 0006 SPDX-License-Identifier: LGPL-2.0-only 0007 */ 0008 0009 #include "kgamestandardaction.h" 0010 0011 // KF 0012 #include <KActionCollection> 0013 #include <KLazyLocalizedString> 0014 #include <KLocalizedString> 0015 #include <KStandardShortcut> 0016 // Qt 0017 #include <QIcon> 0018 // Std 0019 #include <string> 0020 0021 // Helper class for storing raw data in static tables which can be used for QString instance 0022 // creation at runtime without copying/converting to new memalloc'ed memory, as well as avoiding 0023 // that way storing the strings directly as QStrings resulting in non-constexpr init code on 0024 // library loading 0025 struct RawStringData { 0026 template<std::size_t StringSize> 0027 constexpr inline RawStringData(const char16_t (&_data)[StringSize]) 0028 : data(_data) 0029 , size(std::char_traits<char16_t>::length(_data)) 0030 { 0031 } 0032 constexpr inline RawStringData(std::nullptr_t) 0033 { 0034 } 0035 constexpr inline RawStringData() = default; 0036 0037 inline QString toString() const 0038 { 0039 if (!data) { 0040 return QString(); 0041 } 0042 0043 return Qt::Literals::StringLiterals::operator""_s(data, size); 0044 } 0045 0046 private: 0047 const char16_t *const data = nullptr; 0048 const std::size_t size = 0; 0049 }; 0050 0051 struct KGameStandardActionInfo { 0052 KGameStandardAction::GameStandardAction id; 0053 KStandardShortcut::StandardShortcut globalAccel; // if we reuse a global accel 0054 int shortcut; // specific shortcut (NH: should be configurable) 0055 const RawStringData psName; 0056 const KLazyLocalizedString psLabel; 0057 const KLazyLocalizedString psWhatsThis; 0058 const RawStringData psIconName; 0059 const KLazyLocalizedString psToolTip; 0060 }; 0061 0062 #define CTRL(x) QKeyCombination(Qt::CTRL | Qt::Key_##x).toCombined() 0063 0064 const KGameStandardActionInfo g_rgActionInfo[] = { 0065 // clang-format off 0066 // "game" menu 0067 { KGameStandardAction::New, KStandardShortcut::New, 0, u"game_new", 0068 kli18nc("new game", "&New"), kli18n("Start a new game."), u"document-new", kli18n("Start a new game") }, 0069 { KGameStandardAction::Load, KStandardShortcut::Open, 0, u"game_load", 0070 kli18n("&Load..."), {}, u"document-open", kli18n("Open a saved game...") }, 0071 { KGameStandardAction::LoadRecent, KStandardShortcut::AccelNone, 0, u"game_load_recent", 0072 kli18n("Load &Recent"), {}, nullptr, kli18n("Open a recently saved game...") }, 0073 { KGameStandardAction::Restart, KStandardShortcut::Reload, 0, u"game_restart", 0074 kli18n("Restart &Game"), {}, u"view-refresh", kli18n("Restart the game") }, 0075 { KGameStandardAction::Save, KStandardShortcut::Save, 0, u"game_save", 0076 kli18n("&Save"), {}, u"document-save", kli18n("Save the current game") }, 0077 { KGameStandardAction::SaveAs, KStandardShortcut::AccelNone, 0, u"game_save_as", 0078 kli18n("Save &As..."), {}, u"document-save-as", kli18n("Save the current game to another file") }, 0079 { KGameStandardAction::End, KStandardShortcut::End, 0, u"game_end", 0080 kli18n("&End Game"), {}, u"window-close", kli18n("End the current game") }, 0081 { KGameStandardAction::Pause, KStandardShortcut::AccelNone, Qt::Key_P, u"game_pause", 0082 kli18n("Pa&use"), {}, u"media-playback-pause", kli18n("Pause the game") }, 0083 { KGameStandardAction::Highscores, KStandardShortcut::AccelNone, CTRL(H), u"game_highscores", 0084 kli18n("Show &High Scores"), {}, u"games-highscores", kli18n("Show high scores") }, 0085 { KGameStandardAction::ClearHighscores, KStandardShortcut::AccelNone, 0, u"game_clear_highscores", 0086 kli18n("&Clear High Scores"), {}, u"clear_highscore", kli18n("Clear high scores") }, 0087 { KGameStandardAction::Statistics, KStandardShortcut::AccelNone, 0, u"game_statistics", 0088 kli18n("Show Statistics"), {}, u"highscore", kli18n("Show statistics") }, 0089 { KGameStandardAction::ClearStatistics, KStandardShortcut::AccelNone, 0, u"game_clear_statistics", 0090 kli18n("&Clear Statistics"), {}, u"flag", kli18n("Delete all-time statistics.") }, 0091 { KGameStandardAction::Print, KStandardShortcut::Print, 0, u"game_print", 0092 kli18n("&Print..."), {}, u"document-print", {} }, 0093 { KGameStandardAction::Quit, KStandardShortcut::Quit, 0, u"game_quit", 0094 kli18n("&Quit"), {}, u"application-exit", kli18n("Quit the program") }, 0095 0096 // "move" menu 0097 { KGameStandardAction::Repeat, KStandardShortcut::AccelNone, 0, u"move_repeat", 0098 kli18n("Repeat"), {}, nullptr, kli18n("Repeat the last move") }, 0099 { KGameStandardAction::Undo, KStandardShortcut::Undo, 0, u"move_undo", 0100 kli18n("Und&o"), {}, u"edit-undo", kli18n("Undo the last move") }, 0101 { KGameStandardAction::Redo, KStandardShortcut::Redo, 0, u"move_redo", 0102 kli18n("Re&do"), {}, u"edit-redo", kli18n("Redo the latest move") }, 0103 { KGameStandardAction::Roll, KStandardShortcut::AccelNone, CTRL(R), u"move_roll", 0104 kli18n("&Roll Dice"), {}, u"roll", kli18n("Roll the dice") }, 0105 { KGameStandardAction::EndTurn, KStandardShortcut::AccelNone, 0, u"move_end_turn", 0106 kli18n("End Turn"), {}, u"games-endturn", {} }, 0107 { KGameStandardAction::Hint, KStandardShortcut::AccelNone, Qt::Key_H, u"move_hint", 0108 kli18n("&Hint"), {}, u"games-hint", kli18n("Give a hint") }, 0109 { KGameStandardAction::Demo, KStandardShortcut::AccelNone, Qt::Key_D, u"move_demo", 0110 kli18n("&Demo"), {}, u"media-playback-start", kli18n("Play a demo") }, 0111 { KGameStandardAction::Solve, KStandardShortcut::AccelNone, 0, u"move_solve", 0112 kli18n("&Solve"), {}, u"games-solve", kli18n("Solve the game") }, 0113 0114 // "settings" menu 0115 { KGameStandardAction::Carddecks, KStandardShortcut::AccelNone, 0, u"options_configure_carddecks", 0116 kli18n("Configure &Carddecks..."), {}, nullptr, {} }, 0117 { KGameStandardAction::ConfigureHighscores, KStandardShortcut::AccelNone, 0, u"options_configure_highscores", 0118 kli18n("Configure &High Scores..."), {}, nullptr, {} }, 0119 0120 { KGameStandardAction::ActionNone, KStandardShortcut::AccelNone, 0, nullptr, {}, {}, nullptr, {} } 0121 // clang-format on 0122 }; 0123 0124 static const KGameStandardActionInfo *infoPtr(KGameStandardAction::GameStandardAction id) 0125 { 0126 for (uint i = 0; g_rgActionInfo[i].id != KGameStandardAction::ActionNone; i++) { 0127 if (g_rgActionInfo[i].id == id) 0128 return &g_rgActionInfo[i]; 0129 } 0130 return nullptr; 0131 } 0132 0133 QAction *KGameStandardAction::_k_createInternal(KGameStandardAction::GameStandardAction id, QObject *parent) 0134 { 0135 QAction *pAction = nullptr; 0136 const KGameStandardActionInfo *pInfo = infoPtr(id); 0137 // qCDebug(GAMES_UI) << "KGameStandardAction::create( " << id << "=" << (pInfo ? pInfo->psName : (const char*)nullptr) << "," << parent << " )"; 0138 if (pInfo) { 0139 const QString sLabel = pInfo->psLabel.toString(); 0140 switch (id) { 0141 case LoadRecent: 0142 pAction = new KRecentFilesAction(sLabel, parent); 0143 break; 0144 case Pause: 0145 case Demo: 0146 pAction = new KToggleAction(QIcon::fromTheme(pInfo->psIconName.toString()), sLabel, parent); 0147 break; 0148 default: 0149 pAction = new QAction(QIcon::fromTheme(pInfo->psIconName.toString()), sLabel, parent); 0150 break; 0151 } 0152 0153 // clang-format off 0154 const QList<QKeySequence> cut = 0155 (pInfo->globalAccel != KStandardShortcut::AccelNone) ? KStandardShortcut::shortcut(pInfo->globalAccel) : 0156 (pInfo->shortcut != 0) ? QList<QKeySequence>{QKeySequence(pInfo->shortcut)} : 0157 /* else */ QList<QKeySequence>(); 0158 // clang-format on 0159 0160 if (!cut.isEmpty()) { 0161 pAction->setShortcuts(cut); 0162 pAction->setProperty("defaultShortcuts", QVariant::fromValue(cut)); 0163 } 0164 if (!pInfo->psToolTip.isEmpty()) 0165 pAction->setToolTip(pInfo->psToolTip.toString()); 0166 if (!pInfo->psWhatsThis.isEmpty()) 0167 pAction->setWhatsThis(pInfo->psWhatsThis.toString()); 0168 else if (!pInfo->psToolTip.isEmpty()) 0169 pAction->setWhatsThis(pInfo->psToolTip.toString()); 0170 0171 pAction->setObjectName(pInfo->psName.toString()); 0172 } 0173 0174 KActionCollection *collection = qobject_cast<KActionCollection *>(parent); 0175 if (collection && pAction) 0176 collection->addAction(pAction->objectName(), pAction); 0177 0178 return pAction; 0179 } 0180 0181 QAction *KGameStandardAction::create(GameStandardAction id, const QObject *recvr, const char *slot, QObject *parent) 0182 { 0183 QAction *pAction = _k_createInternal(id, parent); 0184 if (recvr && slot) { 0185 switch (id) { 0186 case LoadRecent: 0187 QObject::connect(pAction, SIGNAL(urlSelected(QUrl)), recvr, slot); 0188 break; 0189 default: 0190 QObject::connect(pAction, SIGNAL(triggered(bool)), recvr, slot); 0191 break; 0192 } 0193 } 0194 return pAction; 0195 } 0196 0197 QString KGameStandardAction::name(GameStandardAction id) 0198 { 0199 const KGameStandardActionInfo *pInfo = infoPtr(id); 0200 return (pInfo) ? pInfo->psName.toString() : QString(); 0201 } 0202 0203 QAction *KGameStandardAction::gameNew(const QObject *recvr, const char *slot, QObject *parent) 0204 { 0205 return KGameStandardAction::create(New, recvr, slot, parent); 0206 } 0207 QAction *KGameStandardAction::load(const QObject *recvr, const char *slot, QObject *parent) 0208 { 0209 return KGameStandardAction::create(Load, recvr, slot, parent); 0210 } 0211 KRecentFilesAction *KGameStandardAction::loadRecent(const QObject *recvr, const char *slot, QObject *parent) 0212 { 0213 return static_cast<KRecentFilesAction *>(KGameStandardAction::create(LoadRecent, recvr, slot, parent)); 0214 } 0215 QAction *KGameStandardAction::save(const QObject *recvr, const char *slot, QObject *parent) 0216 { 0217 return KGameStandardAction::create(Save, recvr, slot, parent); 0218 } 0219 QAction *KGameStandardAction::saveAs(const QObject *recvr, const char *slot, QObject *parent) 0220 { 0221 return KGameStandardAction::create(SaveAs, recvr, slot, parent); 0222 } 0223 QAction *KGameStandardAction::end(const QObject *recvr, const char *slot, QObject *parent) 0224 { 0225 return KGameStandardAction::create(End, recvr, slot, parent); 0226 } 0227 KToggleAction *KGameStandardAction::pause(const QObject *recvr, const char *slot, QObject *parent) 0228 { 0229 return static_cast<KToggleAction *>(KGameStandardAction::create(Pause, recvr, slot, parent)); 0230 } 0231 QAction *KGameStandardAction::highscores(const QObject *recvr, const char *slot, QObject *parent) 0232 { 0233 return KGameStandardAction::create(Highscores, recvr, slot, parent); 0234 } 0235 QAction *KGameStandardAction::statistics(const QObject *recvr, const char *slot, QObject *parent) 0236 { 0237 return KGameStandardAction::create(Highscores, recvr, slot, parent); 0238 } 0239 QAction *KGameStandardAction::clearStatistics(const QObject *recvr, const char *slot, QObject *parent) 0240 { 0241 return KGameStandardAction::create(ClearStatistics, recvr, slot, parent); 0242 } 0243 QAction *KGameStandardAction::print(const QObject *recvr, const char *slot, QObject *parent) 0244 { 0245 return KGameStandardAction::create(Print, recvr, slot, parent); 0246 } 0247 QAction *KGameStandardAction::quit(const QObject *recvr, const char *slot, QObject *parent) 0248 { 0249 return KGameStandardAction::create(Quit, recvr, slot, parent); 0250 } 0251 0252 QAction *KGameStandardAction::repeat(const QObject *recvr, const char *slot, QObject *parent) 0253 { 0254 return KGameStandardAction::create(Repeat, recvr, slot, parent); 0255 } 0256 QAction *KGameStandardAction::undo(const QObject *recvr, const char *slot, QObject *parent) 0257 { 0258 return KGameStandardAction::create(Undo, recvr, slot, parent); 0259 } 0260 0261 QAction *KGameStandardAction::redo(const QObject *recvr, const char *slot, QObject *parent) 0262 { 0263 return KGameStandardAction::create(Redo, recvr, slot, parent); 0264 } 0265 0266 QAction *KGameStandardAction::roll(const QObject *recvr, const char *slot, QObject *parent) 0267 { 0268 return KGameStandardAction::create(Roll, recvr, slot, parent); 0269 } 0270 QAction *KGameStandardAction::endTurn(const QObject *recvr, const char *slot, QObject *parent) 0271 { 0272 return KGameStandardAction::create(EndTurn, recvr, slot, parent); 0273 } 0274 0275 QAction *KGameStandardAction::carddecks(const QObject *recvr, const char *slot, QObject *parent) 0276 { 0277 return KGameStandardAction::create(Carddecks, recvr, slot, parent); 0278 } 0279 QAction *KGameStandardAction::configureHighscores(const QObject *recvr, const char *slot, QObject *parent) 0280 { 0281 return KGameStandardAction::create(ConfigureHighscores, recvr, slot, parent); 0282 } 0283 QAction *KGameStandardAction::hint(const QObject *recvr, const char *slot, QObject *parent) 0284 { 0285 return KGameStandardAction::create(Hint, recvr, slot, parent); 0286 } 0287 KToggleAction *KGameStandardAction::demo(const QObject *recvr, const char *slot, QObject *parent) 0288 { 0289 return static_cast<KToggleAction *>(KGameStandardAction::create(Demo, recvr, slot, parent)); 0290 } 0291 QAction *KGameStandardAction::solve(const QObject *recvr, const char *slot, QObject *parent) 0292 { 0293 return KGameStandardAction::create(Solve, recvr, slot, parent); 0294 } 0295 QAction *KGameStandardAction::restart(const QObject *recvr, const char *slot, QObject *parent) 0296 { 0297 return KGameStandardAction::create(Restart, recvr, slot, parent); 0298 }