diff --git a/CMakeLists.txt b/CMakeLists.txt index f97b23f9..0d460756 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,275 +1,280 @@ enable_testing() project(libkdegames) cmake_minimum_required (VERSION 3.5 FATAL_ERROR) set (QT_MIN_VERSION "5.9.0") set (KF5_MIN_VERSION "5.46.0") find_package(ECM ${KF5_MIN_VERSION} REQUIRED NO_MODULE) set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules ${ECM_MODULE_PATH} ${ECM_KDE_MODULE_DIR}) find_package(Qt5 ${QT_MIN_VERSION} REQUIRED NO_MODULE COMPONENTS Widgets Qml Quick QuickWidgets Svg Test) find_package(KF5 ${KF5_MIN_VERSION} REQUIRED COMPONENTS CoreAddons Config WidgetsAddons Codecs Archive DBusAddons DNSSD Declarative I18n GuiAddons Service ConfigWidgets ItemViews IconThemes Completion JobWidgets TextWidgets GlobalAccel XmlGui Crash Bookmarks NewStuff Completion) include(FeatureSummary) include(GenerateExportHeader) include(ECMPackageConfigHelpers) include(ECMSetupVersion) include(ECMGenerateHeaders) include(ECMMarkNonGuiExecutable) include(KDEInstallDirs) include(KDECompilerSettings NO_POLICY_SCOPE) include(KDECMakeSettings) add_definitions(${QT_DEFINITIONS}) add_definitions(-DQT_USE_FAST_CONCATENATION -DQT_USE_FAST_OPERATOR_PLUS) add_definitions(-DMAKE_KDEGAMESPRIVATE_LIB) add_definitions(-DTRANSLATION_DOMAIN="libkdegames5") include_directories(${CMAKE_SOURCE_DIR}/includes) find_package(OpenAL REQUIRED) set_package_properties(OPENAL PROPERTIES URL "http://connect.creativelabs.com/openal" ) find_package(SndFile REQUIRED) set_package_properties(SndFile PROPERTIES URL "http://www.mega-nerd.com/libsndfile/" ) set(HIGHSCORE_DIRECTORY "" CACHE STRING "Where to install system-wide highscores e.g. /var/games") configure_file(highscore/config-highscore.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/highscore/config-highscore.h ) add_subdirectory( carddecks ) add_subdirectory( declarativeimports ) add_subdirectory( highscore ) add_subdirectory( includes ) add_subdirectory( libkdegamesprivate ) add_subdirectory( tests ) include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/highscore ${CMAKE_CURRENT_BINARY_DIR}/highscore # the following only for libkdegamesprivate, but there aren't # target-specific include directories ${CMAKE_CURRENT_SOURCE_DIR}/libkdegamesprivate/kgame ${CMAKE_CURRENT_SOURCE_DIR}/libkdegamesprivate/.. ) option (USE_OPENAL_SNDFILE "use OpenAL and libsndfile in libkdegames" ON) if (SNDFILE_FOUND AND USE_OPENAL_SNDFILE) message(STATUS "Checking libsndfile capabilities") try_compile(SNDFILE_WORKS ${CMAKE_CURRENT_BINARY_DIR}/audio/check-libsndfile-capabilities ${CMAKE_CURRENT_SOURCE_DIR}/audio/check-libsndfile-capabilities.cpp CMAKE_FLAGS -DINCLUDE_DIRECTORIES=${SNDFILE_INCLUDE_DIR}) if (NOT SNDFILE_WORKS) message(FATAL_ERROR "Your version of libsndfile (found in " ${SNDFILE_LIBRARIES} ") is too old. At least version 0.21 is needed. To skip the optional OpenAL/libsndfile dependency in libkdegames (not recommended), re-run cmake with -DUSE_OPENAL_SNDFILE=OFF.") endif (NOT SNDFILE_WORKS) endif (SNDFILE_FOUND AND USE_OPENAL_SNDFILE) message (STATUS "INCLUDES FOR SOUND: " ${OPENAL_INCLUDE_DIR} " " ${SNDFILE_INCLUDE_DIR}) message (STATUS "LIBRARIES FOR SOUND: " ${OPENAL_LIBRARY} " " ${SNDFILE_LIBRARIES}) include_directories(${OPENAL_INCLUDE_DIR} ${SNDFILE_INCLUDE_DIR}) set(KGAUDIO_LINKLIBS ${OPENAL_LIBRARY} ${SNDFILE_LIBRARIES}) set(KGAUDIO_BACKEND openal) set(KGAUDIO_BACKEND_OPENAL TRUE) # for configure_file() below configure_file(libkdegames_capabilities.h.in ${CMAKE_CURRENT_BINARY_DIR}/libkdegames_capabilities.h) ########### next target ############### +#add_definitions( -DQT_DISABLE_DEPRECATED_BEFORE=0x060000 ) +#if (${KF5Config_VERSION} STRGREATER "5.56.0") +# add_definitions(-DQT_NO_FOREACH) +# MESSAGE(STATUS "compile without foreach") +#endif() set(kdegames_LIB_SRCS audio/kgaudioscene-${KGAUDIO_BACKEND}.cpp audio/kgsound-${KGAUDIO_BACKEND}.cpp colorproxy_p.cpp # highscore/kconfigrawbackend.cpp highscore/khighscore.cpp highscore/kscoredialog.cpp kgameclock.cpp kgamepopupitem.cpp kgamerendereditem.cpp kgamerenderedobjectitem.cpp kgamerendererclient.cpp kgamerenderer.cpp kgdeclarativeview.cpp kgimageprovider.cpp kgdifficulty.cpp kgtheme.cpp kgthemeprovider.cpp kgthemeselector.cpp kstandardgameaction.cpp ) add_library(KF5KDEGames SHARED ${kdegames_LIB_SRCS}) generate_export_header(KF5KDEGames BASE_NAME libkdegames EXPORT_MACRO_NAME KDEGAMES_EXPORT DEPRECATED_MACRO_NAME KDE_DEPRECATED) target_link_libraries(KF5KDEGames PRIVATE ${KGAUDIO_LINKLIBS} Qt5::Xml Qt5::Svg Qt5::Quick KF5::Declarative KF5::NewStuff KF5::IconThemes KF5::GuiAddons KF5::Completion PUBLIC Qt5::Widgets Qt5::QuickWidgets Qt5::Qml KF5::ConfigCore KF5::I18n KF5::WidgetsAddons KF5::ConfigWidgets ) target_include_directories(KF5KDEGames INTERFACE "$") set(KDEGAMES_VERSION 7.0.0) set(KDEGAMES_SOVERSION 7) set_target_properties(KF5KDEGames PROPERTIES VERSION ${KDEGAMES_VERSION} SOVERSION ${KDEGAMES_SOVERSION} EXPORT_NAME KF5KDEGames ) ecm_setup_version(${KDEGAMES_VERSION} VARIABLE_PREFIX KDEGAMES VERSION_HEADER "${CMAKE_CURRENT_BINARY_DIR}/kdegames_version.h" PACKAGE_VERSION_FILE "${CMAKE_CURRENT_BINARY_DIR}/KF5KDEGamesConfigVersion.cmake" SOVERSION ${KDEGAMES_SOVERSION}) set_target_properties(KF5KDEGames PROPERTIES VERSION ${KDEGAMES_VERSION} SOVERSION ${KDEGAMES_SOVERSION} ) install(TARGETS KF5KDEGames EXPORT KF5KDEGamesLibraryDepends ${KF5_INSTALL_TARGETS_DEFAULT_ARGS}) ########### next target ############### # NOTE: The libkdegamesprivate target is compiled in this directory, because # CMake can't cope with exported libraries in two different directories. set(kdegamesprivate_LIB_SRCS libkdegamesprivate/kchatbase.cpp libkdegamesprivate/kchatbaseitemdelegate.cpp libkdegamesprivate/kchatbasemodel.cpp libkdegamesprivate/kgame/kgamechat.cpp libkdegamesprivate/kgame/kgame.cpp libkdegamesprivate/kgame/kgameerror.cpp libkdegamesprivate/kgame/kgameio.cpp libkdegamesprivate/kgame/kgamemessage.cpp libkdegamesprivate/kgame/kgamenetwork.cpp libkdegamesprivate/kgame/kgameproperty.cpp libkdegamesprivate/kgame/kgamepropertyhandler.cpp libkdegamesprivate/kgame/kgamesequence.cpp libkdegamesprivate/kgame/kmessageclient.cpp libkdegamesprivate/kgame/kmessageio.cpp libkdegamesprivate/kgame/kmessageserver.cpp libkdegamesprivate/kgame/kplayer.cpp libkdegamesprivate/kgamecanvas.cpp libkdegamesprivate/kgamedifficulty.cpp libkdegamesprivate/kgamesvgdocument.cpp libkdegamesprivate/kgametheme.cpp libkdegamesprivate/kgamethemeselector.cpp ) ki18n_wrap_ui(kdegamesprivate_LIB_SRCS libkdegamesprivate/kgamethemeselector.ui ) add_library(KF5KDEGamesPrivate SHARED ${kdegamesprivate_LIB_SRCS}) generate_export_header(KF5KDEGamesPrivate BASE_NAME libkdegamesprivate EXPORT_MACRO_NAME KDEGAMESPRIVATE_EXPORT DEPRECATED_MACRO_NAME KDE_DEPRECATED) target_link_libraries(KF5KDEGamesPrivate PRIVATE KF5::DNSSD KF5::NewStuff KF5::Archive PUBLIC Qt5::Xml Qt5::Network KF5::Completion KF5KDEGames ) target_include_directories(KF5KDEGamesPrivate INTERFACE "$" ) set_target_properties(KF5KDEGamesPrivate PROPERTIES VERSION 1.0.0 SOVERSION 1 ) install(TARGETS KF5KDEGamesPrivate EXPORT KF5KDEGamesLibraryDepends ${KF5_INSTALL_TARGETS_DEFAULT_ARGS}) ########### install files ############### install(FILES kgthemeprovider-migration.upd DESTINATION ${DATA_INSTALL_DIR}/kconf_update) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libkdegames_export.h ${CMAKE_CURRENT_BINARY_DIR}/libkdegames_capabilities.h audio/kgaudioscene.h audio/kgsound.h kgameclock.h kgamepopupitem.h kgamerendereditem.h kgamerenderedobjectitem.h kgamerendererclient.h kgamerenderer.h kgdeclarativeview.h kgdifficulty.h kgtheme.h kgthemeprovider.h kgthemeselector.h kstandardgameaction.h DESTINATION ${KF5_INCLUDE_INSTALL_DIR}/KF5KDEGames COMPONENT Devel) ########### generate exports ############### # add libraries to the build-tree export set export(TARGETS KF5KDEGames KF5KDEGamesPrivate FILE "${PROJECT_BINARY_DIR}/KF5KDEGamesLibraryDepends.cmake") # define the installation directory for the CMake files set(CMAKECONFIG_INSTALL_DIR "${CMAKECONFIG_INSTALL_PREFIX}/KF5KDEGames") # create the Config.cmake and ConfigVersion.cmake files ecm_configure_package_config_file("${CMAKE_CURRENT_SOURCE_DIR}/KDEGamesConfig.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/KF5KDEGamesConfig.cmake" INSTALL_DESTINATION ${CMAKECONFIG_INSTALL_DIR} ) install(FILES "${CMAKE_CURRENT_BINARY_DIR}/KF5KDEGamesConfig.cmake" "${CMAKE_CURRENT_BINARY_DIR}/KF5KDEGamesConfigVersion.cmake" DESTINATION "${CMAKECONFIG_INSTALL_DIR}" COMPONENT Devel ) # install the export set for use with the install-tree install(EXPORT KF5KDEGamesLibraryDepends DESTINATION ${CMAKECONFIG_INSTALL_DIR} COMPONENT Devel) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/kdegames_version.h DESTINATION ${KF5_INCLUDE_INSTALL_DIR}/KF5KDEGames COMPONENT Devel) install( FILES libkdegames.categories DESTINATION ${KDE_INSTALL_CONFDIR} ) feature_summary(WHAT ALL INCLUDE_QUIET_PACKAGES FATAL_ON_MISSING_REQUIRED_PACKAGES) diff --git a/highscore/kscoredialog.cpp b/highscore/kscoredialog.cpp index 346da78c..5b9f97fc 100644 --- a/highscore/kscoredialog.cpp +++ b/highscore/kscoredialog.cpp @@ -1,696 +1,696 @@ /**************************************************************** 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. ****************************************************************/ #include "kscoredialog.h" #include "khighscore.h" #include "../kgdifficulty.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define DEFAULT_GROUP_NAME I18N_NOOP("High Scores") typedef QList GroupScores; /// scores; QMap scores; /// hiddenGroups; /// Groups that should not be shown in the dialog QMap configGroupWeights; /// Weights of the groups, defines ordering QTabWidget *tabWidget; //QWidget *page; //QGridLayout *layout; KLineEdit *edit; /// > stack; QMap > labels; /// newName; //index of the new name to add (groupKey, position) QPair latest; //index of the latest addition (groupKey, position) int nrCols; bool loaded; QByteArray configGroup; KHighscore* highscoreObject; QMap translatedGroupNames; /// tabs; QMap col; QMap header; ///
key; ///highscoreObject = new KHighscore(); d->edit = 0; fields |= Score; //Make 'Score' field automatic (it can be hidden if necessary) d->fields = fields; d->hiddenFields = 0; d->newName = QPair(QByteArray(),-1); d->latest = QPair("Null",-1); d->loaded = false; d->nrCols = 0; d->configGroup=QByteArray(); //Set up the default table headers d->header[Name] = i18n("Name"); d->key[Name] = QStringLiteral( "Name" ); d->header[Date] = i18n("Date"); d->key[Date] = QStringLiteral( "Date" ); d->header[Level] = i18n("Level"); d->key[Level] = QStringLiteral( "Level" ); d->header[Score] = i18n("Score"); d->key[Score] = QStringLiteral( "Score" ); d->header[Time] = i18n("Time"); d->key[Time] = QStringLiteral( "Time" ); //d->page = new QWidget(this); d->tabWidget = new QTabWidget(this); d->tabWidget->setTabPosition(QTabWidget::West); QVBoxLayout *mainLayout = new QVBoxLayout; setLayout(mainLayout); mainLayout->addWidget(d->tabWidget); d->buttonBox = new QDialogButtonBox(this); d->buttonBox->setStandardButtons(QDialogButtonBox::Close); connect(d->buttonBox, &QDialogButtonBox::rejected, this, &KScoreDialog::reject); mainLayout->addWidget(d->buttonBox); } KScoreDialog::~KScoreDialog() { delete d->highscoreObject; delete d; } void KScoreDialog::setConfigGroup(const QString &group) //DEPRECATED! { d->configGroup = group.toUtf8(); d->loaded = false; } void KScoreDialog::setConfigGroup(const QPair& group) { d->configGroup = group.first; //untranslated string addLocalizedConfigGroupName(group); //add the translation to the list d->loaded = false; } void KScoreDialog::addLocalizedConfigGroupName(const QPair& group) { if (!d->translatedGroupNames.contains(group.first)) { d->translatedGroupNames.insert(group.first, group.second); qCDebug(GAMES_HIGHSCORE) << "adding" << group.first << "->" << group.second; } } void KScoreDialog::addLocalizedConfigGroupNames(const QMap& groups) { QMap::const_iterator it = groups.begin(); for (; it != groups.end(); ++it) { addLocalizedConfigGroupName(qMakePair(it.key(), it.value())); } } void KScoreDialog::initFromDifficulty(const KgDifficulty* diff, bool doSetConfigGroup) { QMap localizedLevelStrings; QMap levelWeights; foreach (const KgDifficultyLevel* level, diff->levels()) { localizedLevelStrings.insert(level->key(), level->title()); levelWeights.insert(level->hardness(), level->key()); } addLocalizedConfigGroupNames(localizedLevelStrings); setConfigGroupWeights(levelWeights); if (doSetConfigGroup) { const KgDifficultyLevel* curLvl = diff->currentLevel(); setConfigGroup(qMakePair(curLvl->key(), curLvl->title())); } } void KScoreDialog::setHiddenConfigGroups(const QList& hiddenGroups) { d->hiddenGroups = hiddenGroups; } void KScoreDialog::setConfigGroupWeights(const QMap& weights) { d->configGroupWeights = weights; } QString KScoreDialog::KScoreDialogPrivate::findTranslatedGroupName(const QByteArray& name) { const QString lookupResult = translatedGroupNames.value(name); //If it wasn't found then just try i18n( to see if it happens to be in the database return lookupResult.isEmpty() ? i18n(name) : lookupResult; //FIXME? } void KScoreDialog::setComment(const QString &comment) { d->comment = comment; } void KScoreDialog::addField(int field, const QString &header, const QString &key) { d->fields |= field; d->header[field] = header; d->key[field] = key; } void KScoreDialog::hideField(int field) { d->hiddenFields |= field; } /* Create the widgets and layouts etc. for the dialog */ void KScoreDialog::KScoreDialogPrivate::setupDialog() { nrCols = 1; for(int field = 1; field < fields; field = field * 2) { if ( (fields & field) && !(hiddenFields & field ) ) col[field] = nrCols++; } tabWidget->clear(); QList keysToConfigure = scores.keys(); - foreach(const QByteArray &groupName, configGroupWeights) + for(const QByteArray &groupName : qAsConst(configGroupWeights)) { int index = keysToConfigure.indexOf(groupName); if (index != -1) { setupGroup(groupName); keysToConfigure.removeAt(index); } } foreach(const QByteArray &groupName, keysToConfigure) { setupGroup(groupName); } } void KScoreDialog::KScoreDialogPrivate::setupGroup(const QByteArray& groupKey) { if (hiddenGroups.contains(groupKey)) return; QWidget* widget = new QWidget(q); tabs[groupKey] = widget; QString tabName = groupKey.isEmpty() ? i18n(DEFAULT_GROUP_NAME) : findTranslatedGroupName(groupKey); tabWidget->addTab(widget, tabName); QGridLayout* layout = new QGridLayout(widget); //layout->setObjectName( QLatin1String("ScoreTab-" )+groupName); //layout->setMargin(QApplication::style()->pixelMetric(QStyle::PM_DefaultChildMargin)+20); //layout->setSpacing(QApplication::style()->pixelMetric(QStyle::PM_DefaultLayoutSpacing)); layout->addItem(new QSpacerItem(0, 15), 4, 0); commentLabel = new QLabel(tabWidget); commentLabel->setAlignment(Qt::AlignVCenter | Qt::AlignHCenter); QFont bold = q->font(); bold.setBold(true); QLabel *label; layout->addItem(new QSpacerItem(50, 0), 0, 0); label = new QLabel(i18n("Rank"), widget); layout->addWidget(label, 3, 0); label->setFont(bold); for(int field = 1; field < fields; field = field * 2) { if ( (fields & field) && !(hiddenFields & field ) ) //If it's used and not hidden { layout->addItem( new QSpacerItem( 50, 0 ), 0, col[field] ); label = new QLabel(header[field], widget); layout->addWidget(label, 3, col[field], field <= Name ? Qt::AlignLeft : Qt::AlignRight); label->setFont(bold); } } KSeparator *sep = new KSeparator(Qt::Horizontal, tabWidget->widget(tabWidget->currentIndex())); layout->addWidget(sep, 4, 0, 1, nrCols); QString num; for (int i = 1; i <= 10; ++i) { QLabel *label; num.setNum(i); label = new QLabel(i18nc("Enumeration (#1, #2 ...) of the highscore entries", "#%1", num), widget); labels[groupKey].insert((i-1)*nrCols + 0, label); //Fill up column zero layout->addWidget(label, i+4, 0); if (fields & Name) //If we have a Name field { QStackedWidget *localStack = new QStackedWidget(widget); stack[groupKey].insert(i-1, localStack); layout->addWidget(localStack, i+4, col[Name]); label = new QLabel(localStack); labels[groupKey].insert((i-1)*nrCols + col[Name], label); localStack->addWidget(label); localStack->setCurrentWidget(label); } for(int field = Name * 2; field < fields; field = field * 2) { if ( (fields & field) && !(hiddenFields & field ) ) //Maybe disable for Name? { label = new QLabel(widget); labels[groupKey].insert((i-1)*nrCols + col[field], label); layout->addWidget(label, i+4, col[field], Qt::AlignRight); } } } } /* Fill the dialog with the correct data */ void KScoreDialog::KScoreDialogPrivate::aboutToShow() { if (!loaded) loadScores(); if (!nrCols) setupDialog(); int tabIndex=0; //Index of the current tab QMap::const_iterator it = scores.constBegin(); for (; it != scores.constEnd(); ++it) { const QByteArray &groupKey = it.key(); if (hiddenGroups.contains(groupKey)) continue; qCDebug(GAMES_HIGHSCORE) << latest.first << tabWidget->tabText(tabIndex); //Only display the comment on the page with the new score (or) this one if there's only one tab if(latest.first == groupKey || ( latest.first.isEmpty() && groupKey == DEFAULT_GROUP_NAME ) ) { QWidget* widget = tabs.value(groupKey); QGridLayout* layout = qobject_cast(widget->layout()); commentLabel->setText(comment); if (comment.isEmpty()) { commentLabel->setMinimumSize(QSize(1,1)); commentLabel->hide(); layout->addItem( new QSpacerItem( 0, -15 ), 0, 0 ); layout->addItem( new QSpacerItem( 0, -15 ), 2, 0 ); } else { layout->addWidget(commentLabel, 1, 0, 1, nrCols); commentLabel->setMinimumSize(commentLabel->sizeHint()); commentLabel->show(); layout->addItem( new QSpacerItem( 0, -10 ), 0, 0 ); layout->addItem( new QSpacerItem( 0, 10 ), 2, 0 ); } comment.clear(); tabWidget->setCurrentWidget(widget); } QFont normal = q->font(); QFont bold = normal; bold.setBold(true); QString num; for (int i = 1; i <= 10; ++i) { QLabel *label; num.setNum(i); //qCDebug(GAMES_HIGHSCORE) << "groupName:" << groupName << "id:" << i-1; FieldInfo score = scores[groupKey].at(i-1); label = labels[groupKey].at((i-1)*nrCols + 0); //crash! FIXME if ( (i == latest.second) && (groupKey == latest.first) ) label->setFont(bold); else label->setFont(normal); if (fields & Name) { if ( (newName.second == i) && (groupKey == newName.first) ) { QStackedWidget *localStack = stack[groupKey].at(i-1); edit = new KLineEdit(player, localStack); edit->setMinimumWidth(40); localStack->addWidget(edit); localStack->setCurrentWidget(edit); edit->setFocus(); connect(edit, &KLineEdit::returnPressed, q, &KScoreDialog::slotGotReturn); } else { label = labels[groupKey].at((i-1)*nrCols + col[Name]); if ( (i == latest.second) && (groupKey == latest.first) ) label->setFont(bold); else label->setFont(normal); label->setText(score[Name]); } } for(int field = Name * 2; field < fields; field = field * 2) { if ( (fields & field) && !(hiddenFields & field ) ) { label = labels[groupKey].at((i-1)*nrCols + col[field]); if ( (i == latest.second) && (groupKey == latest.first) ) label->setFont(bold); else label->setFont(normal); label->setText(score[field]); } } } tabIndex++; } int configGroupIndex = tabWidget->indexOf(tabs.value(configGroup)); if(!hiddenGroups.contains(configGroup) && configGroupIndex > -1) { tabWidget->setCurrentIndex(configGroupIndex); } latest = QPair(QByteArray(),-1); q->setFixedSize(q->minimumSizeHint()); //NOTE Remove this line to make dialog resizable } void KScoreDialog::KScoreDialogPrivate::loadScores() { scores.clear(); QList groupKeyList; //This will be a list of all the groups in the config file foreach( const QString & groupString, highscoreObject->groupList()) { groupKeyList << groupString.toUtf8(); //Convert all the QStrings to QByteArrays } QByteArray tempCurrentGroup = configGroup; //temp to store the user-set group name if (!groupKeyList.contains( configGroup) ) //If the current group doesn't have any entries, add it to the list to process { qCDebug(GAMES_HIGHSCORE) << "The current high score group " << configGroup << " isn't in the list, adding it"; groupKeyList << configGroup; setupGroup(configGroup); } - foreach(const QByteArray &groupKey, groupKeyList) + for (const QByteArray &groupKey : qAsConst(groupKeyList)) { highscoreObject->setHighscoreGroup(QLatin1String( groupKey )); player = highscoreObject->readEntry(0, QStringLiteral( "LastPlayer" )); //FIXME for (int i = 1; i <= 10; ++i) { FieldInfo score; for(int field = 1; field < fields; field = field * 2) { if (fields & field) { score[field] = highscoreObject->readEntry(i, key[field], QStringLiteral("-")); } } scores[groupKey].append(score); } } highscoreObject->setHighscoreGroup(QLatin1String( tempCurrentGroup )); //reset to the user-set group name foreach(const QByteArray &groupKey, scores.keys()) { if( (scores[groupKey][0].value(Score)==QLatin1String( "-" )) && (scores.size() > 1) && (latest.first != groupKey) ) { qCDebug(GAMES_HIGHSCORE) << "Removing group " << groupKey << " since it's unused."; scores.remove(groupKey); } } loaded = true; } void KScoreDialog::KScoreDialogPrivate::saveScores() { highscoreObject->setHighscoreGroup(QLatin1String( configGroup )); highscoreObject->writeEntry(0,QStringLiteral( "LastPlayer" ), player); for (int i = 1; i <= 10; ++i) { FieldInfo score = scores[configGroup].at(i-1); for(int field = 1; field < fields; field = field * 2) { if (fields & field) { highscoreObject->writeEntry(i, key[field], score[field]); } } } highscoreObject->writeAndUnlock(); } int KScoreDialog::addScore(const FieldInfo& newInfo, const AddScoreFlags& flags) { qCDebug(GAMES_HIGHSCORE) << "adding new score"; bool askName=false, lessIsMore=false; if(flags.testFlag(KScoreDialog::AskName)) askName = true; if(flags.testFlag(KScoreDialog::LessIsMore)) lessIsMore = true; d->latest.first = d->configGroup; //Temporarily set this so loadScores() knows not to delete this group if (!d->loaded) d->loadScores(); d->latest.first = "Null"; //and reset it. for(int i=0; iscores[d->configGroup].size(); i++) { FieldInfo score = d->scores[d->configGroup].at(i); //First look at the score in the config file bool ok; //will be false if there isn't any score yet in position i int num_score = score[Score].toLong(&ok); //test if the stored score is a number score = FieldInfo(newInfo); //now look at the submitted score int newScore = score[Score].toInt(); qCDebug(GAMES_HIGHSCORE) << "num_score =" << num_score << " - newScore =" << newScore; if (((newScore > num_score) && !lessIsMore) || ((newScore < num_score) && lessIsMore) || !ok) { d->latest = QPair(d->configGroup,i+1); d->scores[d->configGroup].insert(i, score); // Save the position to delete in case of Forget d->lastHighPosition = i; if(score[Name].isEmpty()) //If we don't have a name, prompt the player. { if(!d->player.isEmpty()) //d->player should be filled out by d->loadScores() { score[Name] = d->player; } else { KUser user; score[Name] = user.property(KUser::FullName).toString(); if (score[Name].isEmpty()) { score[Name] = user.loginName(); } } askName = true; } if (askName) { d->player=score[Name]; d->newName = QPair(d->configGroup,i+1); d->buttonBox->setStandardButtons(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); d->buttonBox->button(QDialogButtonBox::Ok)->setText(i18n("&Remember")); d->buttonBox->button(QDialogButtonBox::Cancel)->setText(i18n("&Forget")); d->buttonBox->button(QDialogButtonBox::Ok)->setToolTip(i18n("Remember this high score")); d->buttonBox->button(QDialogButtonBox::Cancel)->setToolTip(i18n("Forget this high score")); connect(d->buttonBox, &QDialogButtonBox::accepted, this, &KScoreDialog::slotGotName); connect(d->buttonBox, &QDialogButtonBox::rejected, this, &KScoreDialog::slotForgetScore); } else d->saveScores(); if (i == 0) d->comment = i18n("Excellent!\nYou have a new high score!"); else d->comment = i18n("Well done!\nYou made it to the high score list!"); return i+1; } } d->latest = qMakePair(d->configGroup, 0); return 0; } int KScoreDialog::addScore(int newScore, const AddScoreFlags& flags) { FieldInfo scoreInfo; scoreInfo[Score]=QString::number(newScore); return addScore(scoreInfo, AskName | flags); } void KScoreDialog::show() { d->aboutToShow(); QDialog::show(); } int KScoreDialog::exec() { d->aboutToShow(); return QDialog::exec(); } void KScoreDialog::slotGotReturn() { QTimer::singleShot(0, this, &KScoreDialog::slotGotName); // TODO: Is it better to hide the window, as if any button where pressed? } void KScoreDialog::slotGotName() { if (d->newName.second == -1) return; d->player = d->edit->text(); d->scores[d->newName.first][d->newName.second-1][Name] = d->player; d->saveScores(); QFont bold = font(); bold.setBold(true); QLabel *label = d->labels[d->newName.first].at((d->newName.second-1)*d->nrCols + d->col[Name]); label->setFont(bold); label->setText(d->player); d->stack[d->newName.first].at((d->newName.second-1))->setCurrentWidget(label); d->stack[d->newName.first].at((d->newName.second-1))->removeWidget(d->edit); delete d->edit; d->edit = 0; d->newName = QPair(QByteArray(),-1); d->scores[d->configGroup].removeAt(10); d->comment.clear(); // hide the congratulations d->commentLabel->hide(); d->buttonBox->setStandardButtons(QDialogButtonBox::Close); connect(d->buttonBox, &QDialogButtonBox::rejected, this, &KScoreDialog::reject); } void KScoreDialog::slotForgetScore() { if (d->newName.second == -1) return; // remove the editor from the stack d->stack[d->newName.first].at((d->newName.second-1))->removeWidget(d->edit); // delete the editor delete d->edit; d->edit = 0; // avoid to recreate the KTextEdit widget d->newName = QPair(QByteArray(),-1); // delete the highscore to forget d->scores[d->configGroup].removeAt(d->lastHighPosition); d->comment.clear(); d->commentLabel->hide(); d->buttonBox->setStandardButtons(QDialogButtonBox::Close); connect(d->buttonBox, &QDialogButtonBox::rejected, this, &KScoreDialog::reject); } int KScoreDialog::highScore() { if (!d->loaded) d->loadScores(); if (!d->scores[d->configGroup].isEmpty()) return d->scores[d->configGroup].first()[Score].toInt(); else return 0; } void KScoreDialog::keyPressEvent(QKeyEvent *ev) { if ((d->newName.second != -1) && (ev->key() == Qt::Key_Return)) { ev->ignore(); return; } QDialog::keyPressEvent(ev); } diff --git a/kgthemeprovider.cpp b/kgthemeprovider.cpp index 87e95869..efceb99c 100644 --- a/kgthemeprovider.cpp +++ b/kgthemeprovider.cpp @@ -1,298 +1,299 @@ /*************************************************************************** * Copyright 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 "kgthemeprovider.h" #include "kgimageprovider_p.h" #include #include #include #include #include #include class KgThemeProvider::Private { public: KgThemeProvider *q; QString m_name; QList m_themes; const QByteArray m_configKey; const KgTheme* m_currentTheme; const KgTheme* m_defaultTheme; //this stores the arguments which were passed to discoverThemes() QByteArray m_dtResource; QString m_dtDirectory; QString m_dtDefaultThemeName; const QMetaObject* m_dtThemeClass; //this remembers which themes were already discovered QStringList m_discoveredThemes; //this disables the addTheme() lock during rediscoverThemes() bool m_inRediscover; Private(KgThemeProvider *parent, const QByteArray& key) : q(parent), m_configKey(key), m_currentTheme(0), m_defaultTheme(0), m_inRediscover(false) {} void updateThemeName() { emit q->currentThemeNameChanged(q->currentThemeName()); } }; KgThemeProvider::KgThemeProvider(const QByteArray& configKey, QObject* parent) : QObject(parent) , d(new Private(this, configKey)) { qRegisterMetaType(); qRegisterMetaType(); connect(this, SIGNAL(currentThemeChanged(const KgTheme*)), this, SLOT(updateThemeName())); } KgThemeProvider::~KgThemeProvider() { if (!d->m_themes.isEmpty()) { //save current theme in config file (no sync() call here; this will most //likely be called at application shutdown when others are also writing to //KGlobal::config(); also KConfig's dtor will sync automatically) //but do not save if there is no choice; this is esp. helpful for the //KGameRenderer constructor overload that uses a single KgTheme instance if (d->m_themes.size() > 1 && !d->m_configKey.isEmpty()) { KConfigGroup cg(KSharedConfig::openConfig(), "KgTheme"); cg.writeEntry(d->m_configKey.data(), currentTheme()->identifier()); } //cleanup while (!d->m_themes.isEmpty()) { delete const_cast(d->m_themes.takeFirst()); } delete d; } } QString KgThemeProvider::name() const { return d->m_name; } QList KgThemeProvider::themes() const { return d->m_themes; } void KgThemeProvider::addTheme(KgTheme* theme) { //The intended use is to create the KgThemeProvider object, add themes, //*then* start to work with the currentLevel(). The first call to //currentTheme() will load the previous selection from the config, and the //level list will be considered immutable from this point. Q_ASSERT_X(d->m_currentTheme == 0 || d->m_inRediscover, "KgThemeProvider::addTheme", "Only allowed before currentTheme() is called." ); //add theme d->m_themes.append(theme); theme->setParent(this); } const KgTheme* KgThemeProvider::defaultTheme() const { return d->m_defaultTheme; } void KgThemeProvider::setDefaultTheme(const KgTheme* theme) { if (d->m_currentTheme) { qCDebug(GAMES_LIB) << "You're calling setDefaultTheme after the current " "theme has already been determined. That's not gonna work."; return; } Q_ASSERT(d->m_themes.contains(theme)); d->m_defaultTheme = theme; } const KgTheme* KgThemeProvider::currentTheme() const { if (d->m_currentTheme) { return d->m_currentTheme; } Q_ASSERT(!d->m_themes.isEmpty()); //check configuration file for saved theme if (!d->m_configKey.isEmpty()) { KConfigGroup cg(KSharedConfig::openConfig(), "KgTheme"); const QByteArray id = cg.readEntry(d->m_configKey.data(), QByteArray()); //look for a theme with this id foreach (const KgTheme* theme, d->m_themes) { if (theme->identifier() == id) { return d->m_currentTheme = theme; } } } //fall back to default theme (or first theme if no default specified) return d->m_currentTheme = (d->m_defaultTheme ? d->m_defaultTheme : d->m_themes.first()); } void KgThemeProvider::setCurrentTheme(const KgTheme* theme) { Q_ASSERT(d->m_themes.contains(theme)); if (d->m_currentTheme != theme) { d->m_currentTheme = theme; emit currentThemeChanged(theme); } } QString KgThemeProvider::currentThemeName() const { return currentTheme()->name(); } void KgThemeProvider::discoverThemes(const QByteArray& resource, const QString& directory, const QString& defaultThemeName, const QMetaObject* themeClass) { d->m_dtResource = resource; d->m_dtDirectory = directory; d->m_dtDefaultThemeName = defaultThemeName; d->m_dtThemeClass = themeClass; rediscoverThemes(); } // Function to replace KStandardDirs::relativeLocation() static QString relativeToApplications(const QString& file) { const QString canonical = QFileInfo(file).canonicalFilePath(); - Q_FOREACH(const QString& base, QStandardPaths::standardLocations(QStandardPaths::AppDataLocation)) { + const QStringList dirs = QStandardPaths::standardLocations(QStandardPaths::AppDataLocation); + for (const QString& base : dirs) { if (canonical.startsWith(base)) return canonical.mid(base.length()+1); } return file; } void KgThemeProvider::rediscoverThemes() { if (d->m_dtResource.isEmpty()) { return; //discoverThemes() was never called } KgTheme* defaultTheme = NULL; d->m_inRediscover = true; const QString defaultFileName = d->m_dtDefaultThemeName + QLatin1String(".desktop"); QStringList themePaths; - QStringList dirs = QStandardPaths::locateAll(QStandardPaths::AppDataLocation, d->m_dtDirectory, QStandardPaths::LocateDirectory); - Q_FOREACH (const QString &dir, dirs) { + const QStringList dirs = QStandardPaths::locateAll(QStandardPaths::AppDataLocation, d->m_dtDirectory, QStandardPaths::LocateDirectory); + for (const QString &dir : dirs) { const QStringList fileNames = QDir(dir).entryList(QStringList() << QStringLiteral("*.desktop")); - Q_FOREACH (const QString &file, fileNames) { + for (const QString &file : fileNames) { if (!themePaths.contains(file)) { themePaths.append(dir + '/' + file); } } } //create themes from result, order default theme at the front (that's not //needed by KgThemeProvider, but nice for the theme selector) QList themes; foreach (const QString& themePath, themePaths) { const QFileInfo fi(themePath); if (d->m_discoveredThemes.contains(fi.fileName())) { continue; } d->m_discoveredThemes << fi.fileName(); //the identifier is constructed such that it is compatible with //KGameTheme (e.g. "themes/default.desktop") const QByteArray id = relativeToApplications(themePath).toUtf8(); //create theme KgTheme* theme; if (d->m_dtThemeClass) { theme = qobject_cast(d->m_dtThemeClass->newInstance( Q_ARG(QByteArray, id), Q_ARG(QObject*, this) )); Q_ASSERT_X(theme, "KgThemeProvider::discoverThemes", "Could not create theme instance. Is your constructor Q_INVOKABLE?" ); } else { theme = new KgTheme(id, this); } //silently discard invalid theme files if (!theme->readFromDesktopFile(themePath)) { delete theme; continue; } //order default theme at the front (that's not necessarily needed by //KgThemeProvider, but nice for the theme selector) if (fi.fileName() == defaultFileName) { themes.prepend(theme); defaultTheme = theme; } else { themes.append(theme); } } //add themes in the determined order - foreach (KgTheme* theme, themes) + for (KgTheme* theme : qAsConst(themes)) { addTheme(theme); } if(defaultTheme != NULL) { setDefaultTheme(defaultTheme); } else if(d->m_defaultTheme == NULL && themes.count() != 0) { setDefaultTheme(themes.value(0)); } d->m_inRediscover = false; } QPixmap KgThemeProvider::generatePreview(const KgTheme* theme, const QSize& size) { const qreal dpr = qApp->testAttribute(Qt::AA_UseHighDpiPixmaps) ? qApp->devicePixelRatio() : 1; QPixmap pixmap = QPixmap(theme->previewPath()).scaled(size * dpr, Qt::KeepAspectRatio); pixmap.setDevicePixelRatio(dpr); return pixmap; } void KgThemeProvider::setDeclarativeEngine(const QString& name, QQmlEngine* engine) { if (d->m_name != name) { // prevent multiple declarations d->m_name = name; engine->addImageProvider(name, new KgImageProvider(this)); engine->rootContext()->setContextProperty(name, this); } } #include "moc_kgthemeprovider.cpp" diff --git a/libkdegamesprivate/kchatbaseitemdelegate.cpp b/libkdegamesprivate/kchatbaseitemdelegate.cpp index 87cc39ff..6ac7674e 100644 --- a/libkdegamesprivate/kchatbaseitemdelegate.cpp +++ b/libkdegamesprivate/kchatbaseitemdelegate.cpp @@ -1,92 +1,92 @@ /* 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. */ #include "kchatbaseitemdelegate.h" #include "kchatbasemodel.h" #include #include #include KChatBaseItemDelegate::KChatBaseItemDelegate(QObject *parent) : QAbstractItemDelegate(parent) { } KChatBaseItemDelegate::~KChatBaseItemDelegate() { } void KChatBaseItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { // qDebug() << "KChatBaseItemDelegate::paint"; KChatBaseMessage m = index.model()->data(index, Qt::DisplayRole).value(); paint(painter, option, index,m.first, m.second); } void KChatBaseItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index, const QString& sender, const QString& message) const { // qDebug() << "KChatBaseItemDelegate::paint"; QFontMetrics fm = painter->fontMetrics(); painter->setFont(((KChatBaseModel*)index.model())->nameFont()); painter->drawText(option.rect.x(), QFontMetrics(option.font).height()+option.rect.y(), i18n("%1: ",sender)); painter->setFont(((KChatBaseModel*)index.model())->messageFont()); - painter->drawText(option.rect.x() + 3 + QFontMetrics(((KChatBaseModel*)index.model())->nameFont()).width(i18n("%1: ",sender)), + painter->drawText(option.rect.x() + 3 + QFontMetrics(((KChatBaseModel*)index.model())->nameFont()).boundingRect(i18n("%1: ",sender)).width(), QFontMetrics(option.font).height()+option.rect.y(), message); } QSize KChatBaseItemDelegate::sizeHint(const QStyleOptionViewItem & option , const QModelIndex & index ) const { // qDebug() << "KChatBaseItemDelegate::sizeHint"; KChatBaseMessage m = index.model()->data(index, Qt::DisplayRole).value(); return sizeHint(option, index, m.first, m.second); } QSize KChatBaseItemDelegate::sizeHint(const QStyleOptionViewItem & option , const QModelIndex & index, const QString& sender, const QString& message ) const { // qDebug() << "KChatBaseItemDelegate::sizeHint"; int w = 0; w += 6; - w += QFontMetrics(option.font).width(sender+i18n("%1: ",sender)); - w += QFontMetrics(option.font).width(message); + w += QFontMetrics(option.font).boundingRect(sender+i18n("%1: ",sender)).width(); + w += QFontMetrics(option.font).boundingRect(message).width(); int h = 0; h += 2; if (QFontMetrics(((KChatBaseModel*)index.model())->nameFont()).lineSpacing() > QFontMetrics(((KChatBaseModel*)index.model())->messageFont()).lineSpacing()) { h += QFontMetrics(((KChatBaseModel*)index.model())->nameFont()).lineSpacing(); } else { h += QFontMetrics(((KChatBaseModel*)index.model())->messageFont()).lineSpacing(); } return QSize(w,h); } diff --git a/libkdegamesprivate/kgamedifficulty.cpp b/libkdegamesprivate/kgamedifficulty.cpp index 700c7332..f63fd560 100644 --- a/libkdegamesprivate/kgamedifficulty.cpp +++ b/libkdegamesprivate/kgamedifficulty.cpp @@ -1,462 +1,462 @@ /* Copyright (c) 2007, 2008 Nicolas Roffet, Copyright (c) 2007, Pino Toscano, 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. 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 program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ #include "kgamedifficulty.h" #include #include #include #include #include #include #include #include #include class KGameDifficultyPrivate : public QObject { Q_OBJECT public: ~KGameDifficultyPrivate(); void init(KXmlGuiWindow* window, const QObject* recvr, const char* slotStandard, const char* slotCustom); void rebuildActions(); /** * @return standard string for standard level */ QPair standardLevelString(KGameDifficulty::standardLevel level); void setLevel(KGameDifficulty::standardLevel level); void setLevelCustom(int key); /** * @brief Current custom difficulty level */ int m_levelCustom; KGameDifficulty::standardLevel m_level; QList m_standardLevels; QMap m_customLevels; KSelectAction* m_menu; KGameDifficulty::onChange m_restartOnChange; bool m_running; int m_oldSelection; KComboBox* m_comboBox; public Q_SLOTS: /** * @brief Player wants to change the difficulty level to a standard level * * The difference with the method "setSelection" is that the player may have to confirm that he agrees to end the current game (if needed). * @param newSelection Selected item. */ void changeSelection(int newSelection); Q_SIGNALS: /** * @brief Current difficulty level changed to a standard level * * The game catches this signal and restarts a game with the new standard difficulty level. * @param level New standard level. */ void standardLevelChanged(KGameDifficulty::standardLevel level); /** * @brief Current difficulty level changed to a custom level * * The game catches this signal and restarts a game with the new standard difficulty level. * @param key Custom level identifier. */ void customLevelChanged(int key); private: void setSelection(int newSelection); }; KGameDifficultyPrivate::~KGameDifficultyPrivate() { delete KGameDifficulty::self(); } void KGameDifficultyPrivate::init(KXmlGuiWindow* window, const QObject* recvr, const char* slotStandard, const char* slotCustom = 0) { Q_ASSERT(recvr!=0); m_oldSelection = -1; // No valid selection m_level = KGameDifficulty::NoLevel; m_running = false; QObject::connect(this, SIGNAL(standardLevelChanged(KGameDifficulty::standardLevel)), recvr, slotStandard); if (slotCustom!=0) QObject::connect(this, SIGNAL(customLevelChanged(int)), recvr, slotCustom); m_menu = new KSelectAction(QIcon::fromTheme( QStringLiteral( "games-difficult") ), i18nc("Game difficulty level", "Difficulty" ), window); m_menu->setToolTip(i18n("Set the difficulty level")); m_menu->setWhatsThis(i18n("Set the difficulty level of the game.")); QObject::connect(m_menu, SIGNAL(triggered(int)), this, SLOT(changeSelection(int))); m_menu->setObjectName( QStringLiteral("options_game_difficulty" )); window->actionCollection()->addAction(m_menu->objectName(), m_menu); setParent(window); m_comboBox = new KComboBox(window); m_comboBox->setToolTip(i18n("Difficulty")); QObject::connect(m_comboBox, SIGNAL(activated(int)), this, SLOT(changeSelection(int))); window->statusBar()->addPermanentWidget(m_comboBox); KGameDifficulty::setRestartOnChange(KGameDifficulty::RestartOnChange); } void KGameDifficultyPrivate::changeSelection(int newSelection) { if (newSelection!=m_oldSelection) { bool mayChange = true; if (mayChange && (m_restartOnChange==KGameDifficulty::RestartOnChange) && m_running) mayChange = ( KMessageBox::warningContinueCancel(0, i18n("Changing the difficulty level will end the current game!"), QString(), KGuiItem(i18n("Change the difficulty level"))) == KMessageBox::Continue ); if (mayChange) { setSelection(newSelection); } else { // restore current level selection setSelection(m_oldSelection); } } } QPair KGameDifficultyPrivate::standardLevelString(KGameDifficulty::standardLevel level) { //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 switch (level) { case KGameDifficulty::RidiculouslyEasy: return qMakePair(QByteArray("Ridiculously Easy"), i18nc("Game difficulty level 1 out of 8", "Ridiculously Easy")); case KGameDifficulty::VeryEasy: return qMakePair(QByteArray("Very Easy"), i18nc("Game difficulty level 2 out of 8", "Very Easy")); case KGameDifficulty::Easy: return qMakePair(QByteArray("Easy"), i18nc("Game difficulty level 3 out of 8", "Easy")); case KGameDifficulty::Medium: return qMakePair(QByteArray("Medium"), i18nc("Game difficulty level 4 out of 8", "Medium")); case KGameDifficulty::Hard: return qMakePair(QByteArray("Hard"), i18nc("Game difficulty level 5 out of 8", "Hard")); case KGameDifficulty::VeryHard: return qMakePair(QByteArray("Very Hard"), i18nc("Game difficulty level 6 out of 8", "Very Hard")); case KGameDifficulty::ExtremelyHard: return qMakePair(QByteArray("Extremely Hard"), i18nc("Game difficulty level 7 out of 8", "Extremely Hard")); case KGameDifficulty::Impossible: return qMakePair(QByteArray("Impossible"), i18nc("Game difficulty level 8 out of 8", "Impossible")); case KGameDifficulty::Custom: case KGameDifficulty::Configurable: case KGameDifficulty::NoLevel: // Do nothing break; } return qMakePair(QByteArray(), QString()); } void KGameDifficultyPrivate::rebuildActions() { m_menu->clear(); m_comboBox->clear(); - qSort(m_standardLevels.begin(), m_standardLevels.end()); + std::sort(m_standardLevels.begin(), m_standardLevels.end()); foreach(KGameDifficulty::standardLevel level, m_standardLevels) { if (level!=KGameDifficulty::Configurable) { m_menu->addAction(standardLevelString(level).second); m_comboBox->addItem(QIcon::fromTheme( QStringLiteral( "games-difficult" )), standardLevelString(level).second); } } if (!m_customLevels.isEmpty()) { foreach(const QString &s, m_customLevels) { m_menu->addAction(s); m_comboBox->addItem(QIcon::fromTheme( QStringLiteral( "games-difficult" )), s); } } if (m_standardLevels.contains(KGameDifficulty::Configurable)) { QAction* separator = new QAction(m_menu); separator->setSeparator(true); m_menu->addAction(separator); QString s = i18nc("Name of the game difficulty level that is customized by the user by setting up different game parameters", "Custom"); m_menu->addAction(s); m_comboBox->addItem(QIcon::fromTheme( QStringLiteral( "games-difficult" )), s); } // reselect the previous selected item. if (m_level==KGameDifficulty::Custom) KGameDifficulty::setLevelCustom(m_levelCustom); else if (m_standardLevels.contains(m_level)) KGameDifficulty::setLevel(m_level); } void KGameDifficultyPrivate::setSelection(int newSelection) { int countWithoutConfigurable = m_standardLevels.count(); if (m_standardLevels.contains(KGameDifficulty::Configurable)) countWithoutConfigurable--; if ((m_standardLevels.contains(KGameDifficulty::Configurable)) && (newSelection>m_menu->actions().count()-3)) KGameDifficulty::setLevel(KGameDifficulty::Configurable); else if(newSelectionsetCurrentItem(m_menu->actions().count()-1); m_comboBox->setCurrentIndex(m_comboBox->count()-1); } else if (level!=KGameDifficulty::Custom) { int i = m_standardLevels.indexOf(level); m_menu->setCurrentItem(i); m_comboBox->setCurrentIndex(i); } if (level != m_level) { m_level = level; emit standardLevelChanged(level); } m_oldSelection = m_menu->currentItem(); } void KGameDifficultyPrivate::setLevelCustom(int key) { m_level = KGameDifficulty::Custom; int a = m_standardLevels.count(); if (m_standardLevels.contains(KGameDifficulty::Configurable)) a -= 1; int i = (m_customLevels.uniqueKeys()).indexOf(key) + a; m_menu->setCurrentItem(i); m_comboBox->setCurrentIndex(i); if (key != m_levelCustom) { m_levelCustom = key; emit customLevelChanged(key); } m_oldSelection = m_menu->currentItem(); } //---// KGameDifficulty* KGameDifficulty::instance = 0; KGameDifficulty::~KGameDifficulty() { // We do not need to delete d, because d deletes us. } void KGameDifficulty::init(KXmlGuiWindow* window, const QObject* recvr, const char* slotStandard, const char* slotCustom) { self()->d->init(window, recvr, slotStandard, slotCustom); } void KGameDifficulty::setRestartOnChange(onChange restart) { Q_ASSERT(self()->d); self()->d->m_restartOnChange = restart; if (restart==RestartOnChange) self()->d->m_comboBox->setWhatsThis(i18n("Select the difficulty of the game.
If you change the difficulty level while a game is running, you will have to cancel it and start a new one.")); else self()->d->m_comboBox->setWhatsThis(i18n("Select the difficulty of the game.
You can change the difficulty level during a running game.")); } void KGameDifficulty::addStandardLevel(standardLevel level) { Q_ASSERT(self()->d); if ((level!=Custom) && (level!=NoLevel)) { self()->d->m_standardLevels.append(level); self()->d->rebuildActions(); } } void KGameDifficulty::removeStandardLevel(standardLevel level) { Q_ASSERT(self()->d); self()->d->m_standardLevels.removeAll(level); self()->d->rebuildActions(); } void KGameDifficulty::addCustomLevel(int key, const QString& appellation) { Q_ASSERT(self()->d); self()->d->m_customLevels.insert(key, appellation); self()->d->rebuildActions(); } void KGameDifficulty::removeCustomLevel(int key) { Q_ASSERT(self()->d); self()->d->m_customLevels.remove(key); self()->d->rebuildActions(); } void KGameDifficulty::setEnabled(bool enabled) { Q_ASSERT(self()->d->m_menu); // 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... self()->d->m_menu->setEnabled(enabled); self()->d->m_comboBox->setEnabled(enabled); } void KGameDifficulty::setLevel(standardLevel level) { Q_ASSERT(self()->d); self()->d->setLevel(level); } void KGameDifficulty::setLevelCustom(int key) { Q_ASSERT(self()->d); self()->d->setLevelCustom(key); } int KGameDifficulty::levelCustom() { Q_ASSERT(self()->d); return self()->d->m_levelCustom; } KGameDifficulty::standardLevel KGameDifficulty::level() { Q_ASSERT(self()->d); return self()->d->m_level; } QString KGameDifficulty::levelString() { Q_ASSERT(self()->d); return self()->d->standardLevelString(self()->d->m_level).second; } QPair KGameDifficulty::localizedLevelString() { Q_ASSERT(self()->d); return self()->d->standardLevelString(self()->d->m_level); } QMap KGameDifficulty::localizedLevelStrings() { Q_ASSERT(self()->d); QMap levelStrings; levelStrings.insert(self()->d->standardLevelString(RidiculouslyEasy).first, self()->d->standardLevelString(RidiculouslyEasy).second); levelStrings.insert(self()->d->standardLevelString(VeryEasy).first, self()->d->standardLevelString(VeryEasy).second); levelStrings.insert(self()->d->standardLevelString(Easy).first, self()->d->standardLevelString(Easy).second); levelStrings.insert(self()->d->standardLevelString(Medium).first, self()->d->standardLevelString(Medium).second); levelStrings.insert(self()->d->standardLevelString(Hard).first, self()->d->standardLevelString(Hard).second); levelStrings.insert(self()->d->standardLevelString(VeryHard).first, self()->d->standardLevelString(VeryHard).second); levelStrings.insert(self()->d->standardLevelString(ExtremelyHard).first, self()->d->standardLevelString(ExtremelyHard).second); levelStrings.insert(self()->d->standardLevelString(Impossible).first, self()->d->standardLevelString(Impossible).second); return levelStrings; } QMap KGameDifficulty::levelWeights() { Q_ASSERT(self()->d); QMap weights; weights.insert(RidiculouslyEasy, self()->d->standardLevelString(RidiculouslyEasy).first); weights.insert(VeryEasy, self()->d->standardLevelString(VeryEasy).first); weights.insert(Easy, self()->d->standardLevelString(Easy).first); weights.insert(Medium, self()->d->standardLevelString(Medium).first); weights.insert(Hard, self()->d->standardLevelString(Hard).first); weights.insert(VeryHard, self()->d->standardLevelString(VeryHard).first); weights.insert(ExtremelyHard, self()->d->standardLevelString(ExtremelyHard).first); weights.insert(Impossible, self()->d->standardLevelString(Impossible).first); return weights; } void KGameDifficulty::setRunning(bool running) { Q_ASSERT(self()->d); self()->d->m_running = running; } KGameDifficulty::KGameDifficulty() : d(new KGameDifficultyPrivate()) { } KGameDifficulty* KGameDifficulty::self() { if (instance==0) instance = new KGameDifficulty(); return instance; } #include "kgamedifficulty.moc" diff --git a/libkdegamesprivate/kgamethemeselector.cpp b/libkdegamesprivate/kgamethemeselector.cpp index e10e799c..43133719 100644 --- a/libkdegamesprivate/kgamethemeselector.cpp +++ b/libkdegamesprivate/kgamethemeselector.cpp @@ -1,218 +1,218 @@ /* Copyright (C) 2007 Mauricio Piacentini Copyright (C) 2007 Matt Williams 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 "kgamethemeselector.h" #include #include #include #include #include #include #include #include "ui_kgamethemeselector.h" #include "kgametheme.h" class KGameThemeSelector::KGameThemeSelectorPrivate { public: KGameThemeSelectorPrivate(KGameThemeSelector* parent) : q(parent) {} ~KGameThemeSelectorPrivate() { qDeleteAll(themeMap); } KGameThemeSelector* q; QMap themeMap; Ui::KGameThemeSelectorBase ui; QString lookupDirectory; QString groupName; void setupData(KConfigSkeleton* config, KGameThemeSelector::NewStuffState knsflags); void findThemes(const QString &initialSelection); // private slots void _k_updatePreview(); void _k_updateThemeList(const QString& strTheme); void _k_openKNewStuffDialog(); }; KGameThemeSelector::KGameThemeSelector(QWidget* parent, KConfigSkeleton * aconfig, KGameThemeSelector::NewStuffState knsflags, const QString &groupName, const QString &directory) : QWidget(parent), d(new KGameThemeSelectorPrivate(this)) { d->lookupDirectory = directory; d->groupName = groupName; d->setupData(aconfig, knsflags); } KGameThemeSelector::~KGameThemeSelector() { delete d; } void KGameThemeSelector::KGameThemeSelectorPrivate::setupData(KConfigSkeleton * aconfig, KGameThemeSelector::NewStuffState knsflags) { ui.setupUi(q); ui.getNewButton->setIcon(QIcon::fromTheme( QStringLiteral( "get-hot-new-stuff" ))); //The lineEdit widget holds our theme path for automatic connection via KConfigXT. //But the user should not manipulate it directly, so we hide it. ui.kcfg_Theme->hide(); connect(ui.kcfg_Theme, SIGNAL(textChanged(QString)), q, SLOT(_k_updateThemeList(QString))); //Disable KNS button? if (knsflags==KGameThemeSelector::NewStuffDisableDownload) { ui.getNewButton->hide(); } //Get the last used theme path from the KConfigSkeleton KConfigSkeletonItem * configItem = aconfig->findItem(QStringLiteral( "Theme" )); QString lastUsedTheme = configItem->property().toString(); //Now get our themes into the list widget findThemes(lastUsedTheme); connect(ui.getNewButton, SIGNAL(clicked()), q, SLOT(_k_openKNewStuffDialog())); } void KGameThemeSelector::KGameThemeSelectorPrivate::findThemes(const QString &initialSelection) { qDeleteAll(themeMap.values()); themeMap.clear(); //Disconnect the themeList as we are going to clear it and do not want previews generated ui.themeList->disconnect(); ui.themeList->clear(); ui.themeList->setSortingEnabled(true); QStringList themesAvailable; const QStringList dirs = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QCoreApplication::applicationName() + QLatin1Char( '/' ) + lookupDirectory, QStandardPaths::LocateDirectory); //Added subdirectory for finding gamethemeselector resources - Q_FOREACH(const QString& dir, dirs) { + for (const QString& dir : dirs) { QDirIterator it(dir, QStringList() << QStringLiteral("*.desktop"), QDir::NoFilter, QDirIterator::Subdirectories); while (it.hasNext()) { QFileInfo fileInfo(it.next()); const QString filePath = QDir(dir).relativeFilePath(fileInfo.filePath()); themesAvailable.append(filePath); } } bool initialFound = false; - foreach (const QString &file, themesAvailable) + for (const QString &file : qAsConst(themesAvailable)) { const QString themePath = lookupDirectory + QLatin1Char( '/' ) + file; KGameTheme* atheme = new KGameTheme(groupName); if (atheme->load(themePath)) { QString themeName = atheme->themeProperty(QStringLiteral( "Name" )); //Add underscores to avoid duplicate names. while (themeMap.contains(themeName)) themeName += QLatin1Char( '_' ); themeMap.insert(themeName, atheme); QListWidgetItem * item = new QListWidgetItem(themeName, ui.themeList); //Find if this is our currently configured theme if (themePath==initialSelection) { initialFound = true; ui.themeList->setCurrentItem(item); _k_updatePreview(); } } else { delete atheme; } } if (!initialFound) { // TODO change this if we ever change KGameTheme::loadDefault QString defaultPath = QStringLiteral( "themes/default.desktop" ); foreach(KGameTheme* theme, themeMap) { if (theme->path().endsWith(defaultPath)) { const QList itemList = ui.themeList->findItems(theme->themeProperty(QStringLiteral( "Name" )), Qt::MatchExactly); // never can be != 1 but better safe than sorry if (itemList.count() == 1) { ui.themeList->setCurrentItem(itemList.first()); _k_updatePreview(); } } } } //Reconnect the themeList connect(ui.themeList, SIGNAL(currentItemChanged(QListWidgetItem*,QListWidgetItem*)), q, SLOT(_k_updatePreview())); } void KGameThemeSelector::KGameThemeSelectorPrivate::_k_updatePreview() { KGameTheme * seltheme = themeMap.value(ui.themeList->currentItem()->text()); //Sanity checkings. Should not happen. if (!seltheme) return; if (seltheme->path() == ui.kcfg_Theme->text()) { return; } ui.kcfg_Theme->setText(seltheme->fileName()); QString authstr(QStringLiteral( "Author" )); QString contactstr(QStringLiteral( "AuthorEmail" )); QString descstr(QStringLiteral( "Description" )); QString emailstr; if (!seltheme->themeProperty(contactstr).isEmpty() ) { emailstr = QString::fromLatin1( "%1").arg(seltheme->themeProperty(contactstr)); } ui.themeAuthor->setText(seltheme->themeProperty(authstr)); ui.themeContact->setText(emailstr); ui.themeDescription->setText(seltheme->themeProperty(descstr)); //Draw the preview QPixmap pix(seltheme->preview()); ui.themePreview->setPixmap(pix.scaled(ui.themePreview->size(),Qt::KeepAspectRatio,Qt::SmoothTransformation)); } void KGameThemeSelector::KGameThemeSelectorPrivate::_k_updateThemeList(const QString& strTheme) { //find theme and set selection to the current theme; happens when pressing "Default" QListWidgetItem * currentItem = ui.themeList->currentItem(); if(!currentItem || themeMap.value(currentItem->text())->fileName() != strTheme) { for(int i = 0; i < ui.themeList->count(); i++) { if(themeMap.value(ui.themeList->item(i)->text())->fileName() == strTheme) { ui.themeList->setCurrentItem(ui.themeList->item(i)); break; } } } } void KGameThemeSelector::KGameThemeSelectorPrivate::_k_openKNewStuffDialog() { QPointer dialog(new KNS3::DownloadDialog( q )); dialog->exec(); if ( dialog && !dialog->changedEntries().isEmpty() ) findThemes( ui.kcfg_Theme->text() ); delete dialog; } #include "moc_kgamethemeselector.cpp"