KDEGames

kgamedifficulty.cpp
1 /*
2 Copyright (c) 2007, 2008 Nicolas Roffet, <[email protected]>
3 Copyright (c) 2007, Pino Toscano, <[email protected]>
4 
5 This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
6 
7 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.
8 
9 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
10 */
11 
12 #include "kgamedifficulty.h"
13 
14 
15 
16 
17 
18 #include <KActionCollection>
19 #include <KComboBox>
20 #include <QIcon>
21 #include <KLocalizedString>
22 #include <KMessageBox>
23 #include <QStatusBar>
24 #include <KSelectAction>
25 #include <kxmlguiwindow.h>
26 
27 
28 
29 class KGameDifficultyPrivate : public QObject
30 {
31  Q_OBJECT
32 
33  public:
34  ~KGameDifficultyPrivate();
35 
36  void init(KXmlGuiWindow* window, const QObject* recvr, const char* slotStandard, const char* slotCustom);
37 
38  void rebuildActions();
39 
44 
45  void setLevel(KGameDifficulty::standardLevel level);
46  void setLevelCustom(int key);
47 
48 
52  int m_levelCustom;
53 
56  QMap<int, QString> m_customLevels;
57 
58  KSelectAction* m_menu;
59  KGameDifficulty::onChange m_restartOnChange;
60  bool m_running;
61  int m_oldSelection;
62  KComboBox* m_comboBox;
63 
64 
65  public Q_SLOTS:
72  void changeSelection(int newSelection);
73 
74  Q_SIGNALS:
81  void standardLevelChanged(KGameDifficulty::standardLevel level);
82 
89  void customLevelChanged(int key);
90 
91 
92  private:
93  void setSelection(int newSelection);
94 };
95 
96 
97 KGameDifficultyPrivate::~KGameDifficultyPrivate()
98 {
99  delete KGameDifficulty::self();
100 }
101 
102 
103 void KGameDifficultyPrivate::init(KXmlGuiWindow* window, const QObject* recvr, const char* slotStandard, const char* slotCustom = nullptr)
104 {
105  Q_ASSERT(recvr!=nullptr);
106 
107  m_oldSelection = -1; // No valid selection
108  m_level = KGameDifficulty::NoLevel;
109  m_running = false;
110 
111  QObject::connect(this, SIGNAL(standardLevelChanged(KGameDifficulty::standardLevel)), recvr, slotStandard);
112  if (slotCustom!=nullptr)
113  QObject::connect(this, SIGNAL(customLevelChanged(int)), recvr, slotCustom);
114 
115  m_menu = new KSelectAction(QIcon::fromTheme( QStringLiteral( "games-difficult") ), i18nc("Game difficulty level", "Difficulty" ), window);
116  m_menu->setToolTip(i18n("Set the difficulty level"));
117  m_menu->setWhatsThis(i18n("Set the difficulty level of the game."));
118  QObject::connect(m_menu, SIGNAL(triggered(int)), this, SLOT(changeSelection(int)));
119  m_menu->setObjectName( QStringLiteral("options_game_difficulty" ));
120  window->actionCollection()->addAction(m_menu->objectName(), m_menu);
121 
122  setParent(window);
123 
124  m_comboBox = new KComboBox(window);
125  m_comboBox->setToolTip(i18n("Difficulty"));
126  QObject::connect(m_comboBox, SIGNAL(activated(int)), this, SLOT(changeSelection(int)));
127  window->statusBar()->addPermanentWidget(m_comboBox);
128 
130 }
131 
132 
133 void KGameDifficultyPrivate::changeSelection(int newSelection)
134 {
135  if (newSelection!=m_oldSelection) {
136  bool mayChange = true;
137 
138  if (mayChange && (m_restartOnChange==KGameDifficulty::RestartOnChange) && m_running)
139  mayChange = ( KMessageBox::warningContinueCancel(nullptr, i18n("Changing the difficulty level will end the current game!"), QString(), KGuiItem(i18n("Change the difficulty level"))) == KMessageBox::Continue );
140 
141  if (mayChange) {
142  setSelection(newSelection);
143  } else {
144  // restore current level selection
145  setSelection(m_oldSelection);
146  }
147  }
148 }
149 
150 QPair<QByteArray, QString> KGameDifficultyPrivate::standardLevelString(KGameDifficulty::standardLevel level)
151 {
152  //The first entry in the pair is to be used as a key so don't change it. It doesn't have to match the string to be translated
153  switch (level) {
155  return qMakePair(QByteArray("Ridiculously Easy"), i18nc("Game difficulty level 1 out of 8", "Ridiculously Easy"));
157  return qMakePair(QByteArray("Very Easy"), i18nc("Game difficulty level 2 out of 8", "Very Easy"));
159  return qMakePair(QByteArray("Easy"), i18nc("Game difficulty level 3 out of 8", "Easy"));
161  return qMakePair(QByteArray("Medium"), i18nc("Game difficulty level 4 out of 8", "Medium"));
163  return qMakePair(QByteArray("Hard"), i18nc("Game difficulty level 5 out of 8", "Hard"));
165  return qMakePair(QByteArray("Very Hard"), i18nc("Game difficulty level 6 out of 8", "Very Hard"));
167  return qMakePair(QByteArray("Extremely Hard"), i18nc("Game difficulty level 7 out of 8", "Extremely Hard"));
169  return qMakePair(QByteArray("Impossible"), i18nc("Game difficulty level 8 out of 8", "Impossible"));
173  // Do nothing
174  break;
175  }
176  return qMakePair(QByteArray(), QString());
177 }
178 
179 void KGameDifficultyPrivate::rebuildActions()
180 {
181  m_menu->clear();
182  m_comboBox->clear();
183  std::sort(m_standardLevels.begin(), m_standardLevels.end());
184 
185  for (KGameDifficulty::standardLevel level : qAsConst(m_standardLevels)) {
186  if (level!=KGameDifficulty::Configurable) {
187  m_menu->addAction(standardLevelString(level).second);
188  m_comboBox->addItem(QIcon::fromTheme( QStringLiteral( "games-difficult" )), standardLevelString(level).second);
189  }
190  }
191 
192  if (!m_customLevels.isEmpty()) {
193  for (const QString &s : qAsConst(m_customLevels)) {
194  m_menu->addAction(s);
195  m_comboBox->addItem(QIcon::fromTheme( QStringLiteral( "games-difficult" )), s);
196  }
197  }
198 
199  if (m_standardLevels.contains(KGameDifficulty::Configurable)) {
200  QAction* separator = new QAction(m_menu);
201  separator->setSeparator(true);
202  m_menu->addAction(separator);
203 
204  QString s = i18nc("Name of the game difficulty level that is customized by the user by setting up different game parameters", "Custom");
205  m_menu->addAction(s);
206  m_comboBox->addItem(QIcon::fromTheme( QStringLiteral( "games-difficult" )), s);
207  }
208 
209  // reselect the previous selected item.
210  if (m_level==KGameDifficulty::Custom)
211  KGameDifficulty::setLevelCustom(m_levelCustom);
212  else if (m_standardLevels.contains(m_level))
213  KGameDifficulty::setLevel(m_level);
214 }
215 
216 void KGameDifficultyPrivate::setSelection(int newSelection)
217 {
218  int countWithoutConfigurable = m_standardLevels.count();
219  if (m_standardLevels.contains(KGameDifficulty::Configurable))
220  countWithoutConfigurable--;
221 
222  if ((m_standardLevels.contains(KGameDifficulty::Configurable)) && (newSelection>m_menu->actions().count()-3))
224  else if(newSelection<countWithoutConfigurable)
225  KGameDifficulty::setLevel(m_standardLevels[newSelection]);
226  else
227  KGameDifficulty::setLevelCustom((m_customLevels.keys()).value(newSelection - countWithoutConfigurable));
228 
229  m_oldSelection = newSelection;
230 }
231 
232 
233 void KGameDifficultyPrivate::setLevel(KGameDifficulty::standardLevel level)
234 {
235  if ((!m_standardLevels.contains(level)) && (level!=KGameDifficulty::Custom))
236  level = KGameDifficulty::NoLevel;
237 
238  if (level==KGameDifficulty::Configurable) {
239  m_menu->setCurrentItem(m_menu->actions().count()-1);
240  m_comboBox->setCurrentIndex(m_comboBox->count()-1);
241  } else if (level!=KGameDifficulty::Custom) {
242  int i = m_standardLevels.indexOf(level);
243  m_menu->setCurrentItem(i);
244  m_comboBox->setCurrentIndex(i);
245  }
246 
247  if (level != m_level) {
248  m_level = level;
249  Q_EMIT standardLevelChanged(level);
250  }
251 
252  m_oldSelection = m_menu->currentItem();
253 }
254 
255 
256 void KGameDifficultyPrivate::setLevelCustom(int key)
257 {
258  m_level = KGameDifficulty::Custom;
259 
260  int a = m_standardLevels.count();
261  if (m_standardLevels.contains(KGameDifficulty::Configurable))
262  a -= 1;
263 
264  int i = (m_customLevels.keys()).indexOf(key) + a;
265  m_menu->setCurrentItem(i);
266  m_comboBox->setCurrentIndex(i);
267 
268  if (key != m_levelCustom) {
269  m_levelCustom = key;
270  Q_EMIT customLevelChanged(key);
271  }
272 
273  m_oldSelection = m_menu->currentItem();
274 }
275 
276 
277 
278 //---//
279 
280 
281 
282 KGameDifficulty* KGameDifficulty::instance = nullptr;
283 
284 
286 {
287  // We do not need to delete d, because d deletes us.
288 }
289 
290 
291 void KGameDifficulty::init(KXmlGuiWindow* window, const QObject* recvr, const char* slotStandard, const char* slotCustom)
292 {
293  self()->d->init(window, recvr, slotStandard, slotCustom);
294 }
295 
296 
298 {
299  Q_ASSERT(self()->d);
300 
301  self()->d->m_restartOnChange = restart;
302  if (restart==RestartOnChange)
303  self()->d->m_comboBox->setWhatsThis(i18n("Select the <b>difficulty</b> of the game.<br />If you change the difficulty level while a game is running, you will have to cancel it and start a new one."));
304  else
305  self()->d->m_comboBox->setWhatsThis(i18n("Select the <b>difficulty</b> of the game.<br />You can change the difficulty level during a running game."));
306 
307 }
308 
309 
311 {
312  Q_ASSERT(self()->d);
313 
314  if ((level!=Custom) && (level!=NoLevel)) {
315  self()->d->m_standardLevels.append(level);
316  self()->d->rebuildActions();
317  }
318 }
319 
320 
322 {
323  Q_ASSERT(self()->d);
324 
325  self()->d->m_standardLevels.removeAll(level);
326  self()->d->rebuildActions();
327 }
328 
329 
330 void KGameDifficulty::addCustomLevel(int key, const QString& appellation)
331 {
332  Q_ASSERT(self()->d);
333 
334  self()->d->m_customLevels.insert(key, appellation);
335  self()->d->rebuildActions();
336 }
337 
338 
340 {
341  Q_ASSERT(self()->d);
342 
343  self()->d->m_customLevels.remove(key);
344  self()->d->rebuildActions();
345 }
346 
347 
348 void KGameDifficulty::setEnabled(bool enabled)
349 {
350  Q_ASSERT(self()->d->m_menu);
351 
352  // TODO: Doing this never disable the combobox in the toolbar (just in the menu). It seems to be a bug in the class KSelectAction of kdelibs/kdeui/actions. To check and solve...
353  self()->d->m_menu->setEnabled(enabled);
354  self()->d->m_comboBox->setEnabled(enabled);
355 }
356 
357 
359 {
360  Q_ASSERT(self()->d);
361 
362  self()->d->setLevel(level);
363 }
364 
365 
367 {
368  Q_ASSERT(self()->d);
369 
370  self()->d->setLevelCustom(key);
371 }
372 
373 
375 {
376  Q_ASSERT(self()->d);
377 
378  return self()->d->m_levelCustom;
379 }
380 
381 
383 {
384  Q_ASSERT(self()->d);
385 
386  return self()->d->m_level;
387 }
388 
389 
391 {
392  Q_ASSERT(self()->d);
393 
394  return self()->d->standardLevelString(self()->d->m_level).second;
395 }
396 
397 
399 {
400  Q_ASSERT(self()->d);
401 
402  return self()->d->standardLevelString(self()->d->m_level);
403 }
404 
405 
407 {
408  Q_ASSERT(self()->d);
409 
410  QMap<QByteArray, QString> levelStrings;
411 
412  levelStrings.insert(self()->d->standardLevelString(RidiculouslyEasy).first, self()->d->standardLevelString(RidiculouslyEasy).second);
413  levelStrings.insert(self()->d->standardLevelString(VeryEasy).first, self()->d->standardLevelString(VeryEasy).second);
414  levelStrings.insert(self()->d->standardLevelString(Easy).first, self()->d->standardLevelString(Easy).second);
415  levelStrings.insert(self()->d->standardLevelString(Medium).first, self()->d->standardLevelString(Medium).second);
416  levelStrings.insert(self()->d->standardLevelString(Hard).first, self()->d->standardLevelString(Hard).second);
417  levelStrings.insert(self()->d->standardLevelString(VeryHard).first, self()->d->standardLevelString(VeryHard).second);
418  levelStrings.insert(self()->d->standardLevelString(ExtremelyHard).first, self()->d->standardLevelString(ExtremelyHard).second);
419  levelStrings.insert(self()->d->standardLevelString(Impossible).first, self()->d->standardLevelString(Impossible).second);
420 
421  return levelStrings;
422 }
423 
425 {
426  Q_ASSERT(self()->d);
427 
428  QMap<int, QByteArray> weights;
429  weights.insert(RidiculouslyEasy, self()->d->standardLevelString(RidiculouslyEasy).first);
430  weights.insert(VeryEasy, self()->d->standardLevelString(VeryEasy).first);
431  weights.insert(Easy, self()->d->standardLevelString(Easy).first);
432  weights.insert(Medium, self()->d->standardLevelString(Medium).first);
433  weights.insert(Hard, self()->d->standardLevelString(Hard).first);
434  weights.insert(VeryHard, self()->d->standardLevelString(VeryHard).first);
435  weights.insert(ExtremelyHard, self()->d->standardLevelString(ExtremelyHard).first);
436  weights.insert(Impossible, self()->d->standardLevelString(Impossible).first);
437 
438  return weights;
439 }
440 
441 void KGameDifficulty::setRunning(bool running)
442 {
443  Q_ASSERT(self()->d);
444 
445  self()->d->m_running = running;
446 }
447 
448 
449 KGameDifficulty::KGameDifficulty() : d(new KGameDifficultyPrivate())
450 {
451 }
452 
453 
454 KGameDifficulty* KGameDifficulty::self()
455 {
456  if (instance==nullptr)
457  instance = new KGameDifficulty();
458  return instance;
459 }
460 
461 #include "kgamedifficulty.moc"
static void addCustomLevel(int key, const QString &appellation)
Add a custom difficulty level.
static void init(KXmlGuiWindow *window, const QObject *recvr, const char *slotStandard, const char *slotCustom=nullptr)
Initialize the difficulty class.
virtual KActionCollection * actionCollection() const
void setSeparator(bool b)
static QPair< QByteArray, QString > localizedLevelString()
Level "Very hard".
QStatusBar * statusBar() const const
Q_INVOKABLE QAction * addAction(const QString &name, QAction *action)
static int levelCustom()
Get the current custom difficulty level.
static QMap< QByteArray, QString > localizedLevelStrings()
Q_SIGNALSQ_SIGNALS
KGameDifficuty manages the game difficulty levels in a standard way.
static void removeStandardLevel(standardLevel level)
Remove a standard difficulty level.
Level "Very easy".
static standardLevel level()
Get the current standard difficulty level.
Level "Ridiculously easy".
Level "Extremely hard".
ButtonCode warningContinueCancel(QWidget *parent, const QString &text, const QString &caption=QString(), const KGuiItem &buttonContinue=KStandardGuiItem::cont(), const KGuiItem &buttonCancel=KStandardGuiItem::cancel(), const QString &dontAskAgainName=QString(), Options options=Notify)
Q_OBJECTQ_OBJECT
Level "Impossible".
QString i18nc(const char *context, const char *text, const TYPE &arg...)
static void setLevelCustom(int key)
Set the new current difficulty level as a custom one.
virtual ~KGameDifficulty()
Destructor.
onChange
Behavior on change.
void setParent(QObject *parent)
QCA_EXPORT void init()
static void setLevel(standardLevel level)
Set the new current difficulty level as a standard one.
QString i18n(const char *text, const TYPE &arg...)
if(recurs()&&!first)
void addPermanentWidget(QWidget *widget, int stretch)
static void removeCustomLevel(int key)
Remove a custom difficulty level.
static void setRunning(bool running)
Set the game state: Running or not.
static QString levelString()
standardLevel
Standard difficulty levels.
Any custom appellations for levels.
QIcon fromTheme(const QString &name)
QMap::iterator insert(const Key &key, const T &value)
static void setRestartOnChange(onChange restart)
Set if a new game has to be started by change.
Q_SLOTSQ_SLOTS
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
static void addStandardLevel(standardLevel level)
Add a standard difficulty level.
The current game has to be canceled and a new game will be started on change.
Q_EMITQ_EMIT
static QMap< int, QByteArray > levelWeights()
static void setEnabled(bool enabled)
Set if the difficulty level may be changed.
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Thu Nov 26 2020 22:36:17 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.