Advance Wayland and KDE package bring-up

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
2026-04-14 10:51:06 +01:00
parent 51f3c21121
commit cf12defd28
15214 changed files with 20594243 additions and 269 deletions
@@ -0,0 +1,84 @@
add_library(KF6ConfigGui)
add_library(KF6::ConfigGui ALIAS KF6ConfigGui)
qt_extract_metatypes(KF6ConfigGui)
set_target_properties(KF6ConfigGui PROPERTIES
VERSION ${KCONFIG_VERSION}
SOVERSION ${KCONFIG_SOVERSION}
EXPORT_NAME ConfigGui
)
ecm_create_qm_loader(KF6ConfigGui kconfig6_qt)
target_sources(KF6ConfigGui PRIVATE
kconfiggui.cpp
kconfiggroupgui.cpp
kconfigloader.cpp
kconfigskeleton.cpp
kstandardshortcut.cpp
kstandardshortcutwatcher.cpp
kwindowconfig.cpp
kwindowstatesaver.cpp
kstandardactions.cpp
)
ecm_qt_declare_logging_category(KF6ConfigGui
HEADER kconfig_gui_log_settings.h
IDENTIFIER KCONFIG_GUI_LOG
CATEGORY_NAME kf.config.gui
DESCRIPTION "KConfig Gui"
EXPORT KCONFIG
)
ecm_generate_export_header(KF6ConfigGui
BASE_NAME KConfigGui
GROUP_BASE_NAME KF
VERSION ${KF_VERSION}
USE_VERSION_HEADER
VERSION_BASE_NAME KConfig
DEPRECATED_BASE_VERSION 0
DEPRECATION_VERSIONS
EXCLUDE_DEPRECATED_BEFORE_AND_AT ${EXCLUDE_DEPRECATED_BEFORE_AND_AT}
)
target_include_directories(KF6ConfigGui
INTERFACE "$<INSTALL_INTERFACE:${KDE_INSTALL_INCLUDEDIR_KF}/KConfig;${KDE_INSTALL_INCLUDEDIR_KF}/KConfigGui>")
target_link_libraries(KF6ConfigGui PUBLIC Qt6::Gui KF6::ConfigCore)
ecm_generate_headers(KConfigGui_HEADERS
HEADER_NAMES
KConfigGui
KConfigLoader
KConfigSkeleton
KStandardShortcut
KStandardShortcutWatcher
KWindowConfig
KWindowStateSaver
KStandardActions
REQUIRED_HEADERS KConfigGui_HEADERS
)
if(NOT BUILD_SHARED_LIBS)
target_sources(KF6ConfigGui PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/kconfigguistaticinitializer.cpp>
$<INSTALL_INTERFACE:${KDE_INSTALL_INCLUDEDIR_KF}/KConfigGui/kconfigguistaticinitializer.cpp>
)
endif()
install(TARGETS KF6ConfigGui EXPORT KF6ConfigTargets ${KF_INSTALL_TARGETS_DEFAULT_ARGS})
install(FILES
${CMAKE_CURRENT_BINARY_DIR}/kconfiggui_export.h
kstandardactions_p.h
${KConfigGui_HEADERS}
kconfigguistaticinitializer.cpp
DESTINATION ${KDE_INSTALL_INCLUDEDIR_KF}/KConfigGui COMPONENT Devel
)
# make available to ecm_add_qch in parent folder
set(KConfigGui_APIDOX_SRCS ${KConfigGui_HEADERS} PARENT_SCOPE)
set(KConfigGui_APIDOX_INCLUDE_DIRS ${CMAKE_CURRENT_BINARY_DIR} PARENT_SCOPE)
@@ -0,0 +1,207 @@
/*
This file is part of the KDE libraries
SPDX-FileCopyrightText: 2007 Thiago Macieira <thiago@kde.org>
SPDX-License-Identifier: LGPL-2.0-or-later
*/
#include "kconfiggui_export.h"
#include <kconfiggroup.h>
#include <QColor>
#include <QDebug>
#include <QFont>
#include <kconfiggroup_p.h>
/**
* Try to read a GUI type from config group @p cg at key @p key.
* @p input is the default value and also indicates the type to be read.
* @p output is to be set with the value that has been read.
*
* @returns true if something was handled (even if output was set to clear or default)
* or false if nothing was handled (e.g., Core type)
*/
static bool readEntryGui(const QByteArray &data, const char *key, const QVariant &input, QVariant &output)
{
const auto errString = [&]() {
return QStringLiteral("\"%1\" - conversion from \"%3\" to %2 failed")
.arg(QLatin1String(key), QLatin1String(input.typeName()), QLatin1String(data.constData()));
};
// set in case of failure
output = input;
switch (static_cast<QMetaType::Type>(input.userType())) {
case QMetaType::QColor: {
if (data.isEmpty() || data == "invalid") {
output = QColor(); // return what was stored
return true;
} else if (data.at(0) == '#') {
QColor col = QColor::fromString(QUtf8StringView(data.constData(), data.length()));
if (!col.isValid()) {
qCritical() << qPrintable(errString());
}
output = col;
return true;
} else if (!data.contains(',')) {
QColor col = QColor::fromString(QUtf8StringView(data.constData(), data.length()));
if (!col.isValid()) {
qCritical() << qPrintable(errString());
}
output = col;
return true;
} else {
const QList<QByteArray> list = data.split(',');
const int count = list.count();
if (count != 3 && count != 4) {
qCritical() //
<< qPrintable(errString()) //
<< qPrintable(QStringLiteral(" (wrong format: expected '%1' items, read '%2')").arg(QStringLiteral("3' or '4")).arg(count));
return true; // return default
}
int temp[4];
// bounds check components
for (int i = 0; i < count; i++) {
bool ok;
const int j = temp[i] = list.at(i).toInt(&ok);
if (!ok) { // failed to convert to int
qCritical() << qPrintable(errString()) << " (integer conversion failed)";
return true; // return default
}
if (j < 0 || j > 255) {
static const char *const components[] = {"red", "green", "blue", "alpha"};
qCritical() << qPrintable(errString())
<< qPrintable(QStringLiteral(" (bounds error: %1 component %2)")
.arg(QLatin1String(components[i]), //
j < 0 ? QStringLiteral("< 0") : QStringLiteral("> 255")));
return true; // return default
}
}
QColor aColor(temp[0], temp[1], temp[2]);
if (count == 4) {
aColor.setAlpha(temp[3]);
}
if (aColor.isValid()) {
output = aColor;
} else {
qCritical() << qPrintable(errString());
}
return true;
}
}
case QMetaType::QFont: {
QVariant tmp = QString::fromUtf8(data.constData(), data.length());
if (tmp.canConvert<QFont>()) {
output = tmp;
} else {
qCritical() << qPrintable(errString());
}
return true;
}
case QMetaType::QPixmap:
case QMetaType::QImage:
case QMetaType::QBrush:
case QMetaType::QPalette:
case QMetaType::QIcon:
case QMetaType::QRegion:
case QMetaType::QBitmap:
case QMetaType::QCursor:
case QMetaType::QSizePolicy:
case QMetaType::QPen:
// we may want to handle these in the future
default:
break;
}
return false; // not handled
}
/**
* Try to write a GUI type @p prop to config group @p cg at key @p key.
*
* @returns true if something was handled (even if an empty value was written)
* or false if nothing was handled (e.g., Core type)
*/
static bool writeEntryGui(KConfigGroup *cg, const char *key, const QVariant &prop, KConfigGroup::WriteConfigFlags pFlags)
{
switch (static_cast<QMetaType::Type>(prop.userType())) {
case QMetaType::QColor: {
const QColor rColor = prop.value<QColor>();
if (!rColor.isValid()) {
cg->writeEntry(key, "invalid", pFlags);
return true;
}
QList<int> list;
list.insert(0, rColor.red());
list.insert(1, rColor.green());
list.insert(2, rColor.blue());
if (rColor.alpha() != 255) {
list.insert(3, rColor.alpha());
}
cg->writeEntry(key, list, pFlags);
return true;
}
case QMetaType::QFont: {
QFont f = prop.value<QFont>();
// If the styleName property is set for a QFont, using setBold(true) would
// lead to Qt using an "emboldended"/synthetic font style instead of using
// the bold style provided by the font itself; the latter looks much better
// than the former. For more details see:
// https://bugreports.qt.io/browse/QTBUG-63792
// https://bugs.kde.org/show_bug.cgi?id=378523
/* clang-format off */
if (f.weight() == QFont::Normal
&& (f.styleName() == QLatin1String("Regular")
|| f.styleName() == QLatin1String("Normal")
|| f.styleName() == QLatin1String("Book")
|| f.styleName() == QLatin1String("Roman"))) { /* clang-format on */
f.setStyleName(QString());
}
cg->writeEntry(key, f.toString().toUtf8(), pFlags);
return true;
}
case QMetaType::QPixmap:
case QMetaType::QImage:
case QMetaType::QBrush:
case QMetaType::QPalette:
case QMetaType::QIcon:
case QMetaType::QRegion:
case QMetaType::QBitmap:
case QMetaType::QCursor:
case QMetaType::QSizePolicy:
case QMetaType::QPen:
// we may want to handle one of these in the future
break;
default:
break;
}
return false;
}
// Not static, because for static builds we use it in the kconfigguistaticinitializer.cpp file
// Exported as we need this to force linking in consumers that read GUI types from KConfig, but
// which are otherwise not using this library (and thus linking with --as-needed or MSVC would
// break things)
KCONFIGGUI_EXPORT int initKConfigGroupGui()
{
_kde_internal_KConfigGroupGui.readEntryGui = readEntryGui;
_kde_internal_KConfigGroupGui.writeEntryGui = writeEntryGui;
return 42; // because 42 is nicer than 1 or 0
}
#ifdef Q_CONSTRUCTOR_FUNCTION
Q_CONSTRUCTOR_FUNCTION(initKConfigGroupGui)
#else
static int dummyKConfigGroupGui = initKConfigGroupGui();
#endif
@@ -0,0 +1,51 @@
/*
This file is part of the KDE libraries
SPDX-FileCopyrightText: 1999 Matthias Ettrich <ettrich@kde.org>
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
*/
#include "kconfiggui.h"
#include "kconfig_gui_log_settings.h"
#include <QGuiApplication>
#include <kconfig.h>
static QString configName(const QString &id, const QString &key)
{
return QLatin1String("session/%1_%2_%3").arg(QGuiApplication::applicationName(), id, key);
}
static KConfig *s_sessionConfig = nullptr;
KConfig *KConfigGui::sessionConfig()
{
#ifdef QT_NO_SESSIONMANAGER
qCWarning(KCONFIG_GUI_LOG) << "Qt is built without session manager support";
#else
if (!hasSessionConfig() && qApp->isSessionRestored()) {
// create the default instance specific config object
// from applications' -session command line parameter
s_sessionConfig = new KConfig(configName(qApp->sessionId(), qApp->sessionKey()), KConfig::SimpleConfig);
}
#endif
return s_sessionConfig;
}
void KConfigGui::setSessionConfig(const QString &id, const QString &key)
{
if (hasSessionConfig()) {
delete s_sessionConfig;
s_sessionConfig = nullptr;
}
// create a new instance specific config object from supplied id & key
s_sessionConfig = new KConfig(configName(id, key), KConfig::SimpleConfig);
}
bool KConfigGui::hasSessionConfig()
{
return s_sessionConfig != nullptr;
}
@@ -0,0 +1,55 @@
/*
This file is part of the KDE libraries
SPDX-FileCopyrightText: 1999 Matthias Ettrich <ettrich@kde.org>
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
*/
#ifndef KCONFIGGUI_H
#define KCONFIGGUI_H
#include <kconfiggui_export.h>
#include <QString>
class KConfig;
/**
* Interface-related functions.
*/
namespace KConfigGui
{
/**
* Returns the current application session config object.
*
* @note If Qt is built without session manager support, i.e.
* QT_NO_SESSIONMANAGER is defined, this by default will return
* nullptr, unless a custom config has been set via
* @c setSessionConfig.
*
* @return A pointer to the application's instance specific
* KConfig object.
* @see KConfig
*/
KCONFIGGUI_EXPORT KConfig *sessionConfig();
/**
* Replaces the current application session config object.
*
* @param id new session id
* @param key new session key
*
* @since 5.11
*/
KCONFIGGUI_EXPORT void setSessionConfig(const QString &id, const QString &key);
/**
* Indicates if a session config has been created for that application
* (i.e.\ if sessionConfig() got called at least once)
*
* @return @c true if a sessionConfig object was created, @c false otherwise
*/
KCONFIGGUI_EXPORT bool hasSessionConfig();
}
#endif // KCONFIGGUI_H
@@ -0,0 +1,6 @@
// SPDX-FileCopyrightText: 2022 Alexander Lohnau <alexander.lohnau@gmx.de>
// SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
extern int initKConfigGroupGui();
static int myInit = initKConfigGroupGui();
@@ -0,0 +1,430 @@
/*
SPDX-FileCopyrightText: 2007 Aaron Seigo <aseigo@kde.org>
SPDX-License-Identifier: LGPL-2.0-or-later
*/
#include "kconfigloader.h"
#include "kconfigloader_p.h"
#include "kconfigloaderhandler_p.h"
#include <QColor>
#include <QFont>
#include <QHash>
#include <QUrl>
#include <QDebug>
void ConfigLoaderPrivate::parse(KConfigLoader *loader, QIODevice *xml)
{
clearData();
loader->clearItems();
if (xml) {
ConfigLoaderHandler handler(loader, this);
handler.parse(xml);
}
}
ConfigLoaderHandler::ConfigLoaderHandler(KConfigLoader *config, ConfigLoaderPrivate *d)
: m_config(config)
, d(d)
{
resetState();
}
bool ConfigLoaderHandler::parse(QIODevice *input)
{
if (!input->open(QIODevice::ReadOnly)) {
qWarning() << "Impossible to open device";
return false;
}
QXmlStreamReader reader(input);
while (!reader.atEnd()) {
reader.readNext();
if (reader.hasError()) {
return false;
}
switch (reader.tokenType()) {
case QXmlStreamReader::StartElement:
startElement(reader.name(), reader.attributes());
break;
case QXmlStreamReader::EndElement:
endElement(reader.name());
break;
case QXmlStreamReader::Characters:
if (!reader.isWhitespace() && !reader.text().trimmed().isEmpty()) {
m_cdata.append(reader.text());
}
break;
default:
break;
}
}
if (!reader.isEndDocument()) {
return false;
}
return true;
}
static bool caseInsensitiveCompare(const QStringView a, const QLatin1String b)
{
return a.compare(b, Qt::CaseInsensitive) == 0;
}
void ConfigLoaderHandler::startElement(const QStringView localName, const QXmlStreamAttributes &attrs)
{
// qDebug() << "ConfigLoaderHandler::startElement(" << localName << qName;
if (caseInsensitiveCompare(localName, QLatin1String("group"))) {
QString group;
for (const auto &attr : attrs) {
const auto attrName = attr.name();
if (caseInsensitiveCompare(attrName, QLatin1String("name"))) {
// qDebug() << "set group to" << attrs.value(i);
group = attr.value().toString();
}
}
if (group.isEmpty()) {
group = d->baseGroup;
} else {
d->groups.append(group);
if (!d->baseGroup.isEmpty()) {
group = d->baseGroup + QLatin1Char('\x1d') + group;
}
}
if (m_config) {
m_config->setCurrentGroup(group);
}
} else if (caseInsensitiveCompare(localName, QLatin1String("entry"))) {
for (const auto &attr : attrs) {
const auto attrName = attr.name();
if (caseInsensitiveCompare(attrName, QLatin1String("name"))) {
m_name = attr.value().trimmed().toString();
} else if (caseInsensitiveCompare(attrName, QLatin1String("type"))) {
m_type = attr.value().toString().toLower();
} else if (caseInsensitiveCompare(attrName, QLatin1String("key"))) {
m_key = attr.value().trimmed().toString();
}
}
} else if (caseInsensitiveCompare(localName, QLatin1String("choice"))) {
m_choice.name.clear();
m_choice.label.clear();
m_choice.whatsThis.clear();
for (const auto &attr : attrs) {
const auto attrName = attr.name();
if (caseInsensitiveCompare(attrName, QLatin1String("name"))) {
m_choice.name = attr.value().toString();
}
}
m_inChoice = true;
}
}
void ConfigLoaderHandler::endElement(const QStringView localName)
{
// qDebug() << "ConfigLoaderHandler::endElement(" << localName << qName;
if (caseInsensitiveCompare(localName, QLatin1String("entry"))) {
addItem();
resetState();
} else if (caseInsensitiveCompare(localName, QLatin1String("label"))) {
if (m_inChoice) {
m_choice.label = std::move(m_cdata).trimmed();
} else {
m_label = std::move(m_cdata).trimmed();
}
} else if (caseInsensitiveCompare(localName, QLatin1String("whatsthis"))) {
if (m_inChoice) {
m_choice.whatsThis = std::move(m_cdata).trimmed();
} else {
m_whatsThis = std::move(m_cdata).trimmed();
}
} else if (caseInsensitiveCompare(localName, QLatin1String("default"))) {
m_default = std::move(m_cdata).trimmed();
} else if (caseInsensitiveCompare(localName, QLatin1String("min"))) {
m_min = m_cdata.toInt(&m_haveMin);
} else if (caseInsensitiveCompare(localName, QLatin1String("max"))) {
m_max = m_cdata.toInt(&m_haveMax);
} else if (caseInsensitiveCompare(localName, QLatin1String("choice"))) {
m_enumChoices.append(m_choice);
m_inChoice = false;
}
m_cdata.clear();
}
void ConfigLoaderHandler::addItem()
{
if (m_name.isEmpty()) {
if (m_key.isEmpty()) {
return;
}
m_name = m_key;
}
m_name.remove(QLatin1Char(' '));
KConfigSkeletonItem *item = nullptr;
if (m_type == QLatin1String("bool")) {
const bool defaultValue = caseInsensitiveCompare(m_default, QLatin1String("true"));
item = m_config->addItemBool(m_name, *d->newBool(), defaultValue, m_key);
} else if (m_type == QLatin1String("color")) {
item = m_config->addItemColor(m_name, *d->newColor(), QColor(m_default), m_key);
} else if (m_type == QLatin1String("datetime")) {
item = m_config->addItemDateTime(m_name, *d->newDateTime(), QDateTime::fromString(m_default), m_key);
} else if (m_type == QLatin1String("enum")) {
m_key = (m_key.isEmpty()) ? m_name : m_key;
bool ok = false;
int defaultValue = m_default.toInt(&ok);
if (!ok) {
for (int i = 0; i < m_enumChoices.size(); i++) {
if (m_default == m_enumChoices[i].name) {
defaultValue = i;
break;
}
}
}
KConfigSkeleton::ItemEnum *enumItem = new KConfigSkeleton::ItemEnum(m_config->currentGroup(), m_key, *d->newInt(), m_enumChoices, defaultValue);
m_config->addItem(enumItem, m_name);
item = enumItem;
} else if (m_type == QLatin1String("font")) {
item = m_config->addItemFont(m_name, *d->newFont(), QFont(m_default), m_key);
} else if (m_type == QLatin1String("int")) {
KConfigSkeleton::ItemInt *intItem = m_config->addItemInt(m_name, *d->newInt(), m_default.toInt(), m_key);
if (m_haveMin) {
intItem->setMinValue(m_min);
}
if (m_haveMax) {
intItem->setMaxValue(m_max);
}
item = intItem;
} else if (m_type == QLatin1String("password")) {
item = m_config->addItemPassword(m_name, *d->newString(), m_default, m_key);
} else if (m_type == QLatin1String("path")) {
item = m_config->addItemPath(m_name, *d->newString(), m_default, m_key);
} else if (m_type == QLatin1String("string")) {
item = m_config->addItemString(m_name, *d->newString(), m_default, m_key);
} else if (m_type == QLatin1String("stringlist")) {
// FIXME: the split() is naive and will break on lists with ,'s in them
// empty parts are not wanted in this case
item = m_config->addItemStringList(m_name, *d->newStringList(), m_default.split(QLatin1Char(','), Qt::SkipEmptyParts), m_key);
} else if (m_type == QLatin1String("uint")) {
KConfigSkeleton::ItemUInt *uintItem = m_config->addItemUInt(m_name, *d->newUint(), m_default.toUInt(), m_key);
if (m_haveMin) {
uintItem->setMinValue(m_min);
}
if (m_haveMax) {
uintItem->setMaxValue(m_max);
}
item = uintItem;
} else if (m_type == QLatin1String("url")) {
m_key = (m_key.isEmpty()) ? m_name : m_key;
KConfigSkeleton::ItemUrl *urlItem = new KConfigSkeleton::ItemUrl(m_config->currentGroup(), m_key, *d->newUrl(), QUrl::fromUserInput(m_default));
m_config->addItem(urlItem, m_name);
item = urlItem;
} else if (m_type == QLatin1String("double")) {
KConfigSkeleton::ItemDouble *doubleItem = m_config->addItemDouble(m_name, *d->newDouble(), m_default.toDouble(), m_key);
if (m_haveMin) {
doubleItem->setMinValue(m_min);
}
if (m_haveMax) {
doubleItem->setMaxValue(m_max);
}
item = doubleItem;
} else if (m_type == QLatin1String("intlist")) {
QList<int> defaultList;
const QList<QStringView> tmpList = QStringView(m_default).split(QLatin1Char(','), Qt::SkipEmptyParts);
for (const QStringView tmp : tmpList) {
defaultList.append(tmp.toInt());
}
item = m_config->addItemIntList(m_name, *d->newIntList(), defaultList, m_key);
} else if (m_type == QLatin1String("longlong")) {
KConfigSkeleton::ItemLongLong *longlongItem = m_config->addItemLongLong(m_name, *d->newLongLong(), m_default.toLongLong(), m_key);
if (m_haveMin) {
longlongItem->setMinValue(m_min);
}
if (m_haveMax) {
longlongItem->setMaxValue(m_max);
}
item = longlongItem;
/* No addItemPathList in KConfigSkeleton ?
} else if (m_type == "PathList") {
//FIXME: the split() is naive and will break on lists with ,'s in them
item = m_config->addItemPathList(m_name, *d->newStringList(), m_default.split(","), m_key);
*/
} else if (m_type == QLatin1String("point")) {
QPoint defaultPoint;
const QList<QStringView> tmpList = QStringView(m_default).split(QLatin1Char(','));
if (tmpList.size() >= 2) {
defaultPoint.setX(tmpList[0].toInt());
defaultPoint.setY(tmpList[1].toInt());
}
item = m_config->addItemPoint(m_name, *d->newPoint(), defaultPoint, m_key);
} else if (m_type == QLatin1String("pointf")) {
QPointF defaultPointF;
const auto tmpList = QStringView(m_default).split(u',');
if (tmpList.size() >= 2) {
defaultPointF.setX(tmpList[0].toDouble());
defaultPointF.setY(tmpList[1].toDouble());
}
item = m_config->addItemPointF(m_name, *d->newPointF(), defaultPointF, m_key);
} else if (m_type == QLatin1String("rect")) {
QRect defaultRect;
const QList<QStringView> tmpList = QStringView(m_default).split(QLatin1Char(','));
if (tmpList.size() >= 4) {
defaultRect.setCoords(tmpList[0].toInt(), tmpList[1].toInt(), tmpList[2].toInt(), tmpList[3].toInt());
}
item = m_config->addItemRect(m_name, *d->newRect(), defaultRect, m_key);
} else if (m_type == QLatin1String("rectf")) {
QRectF defaultRectF;
const auto tmpList = QStringView(m_default).split(u',');
if (tmpList.size() >= 4) {
defaultRectF.setCoords(tmpList[0].toDouble(), tmpList[1].toDouble(), tmpList[2].toDouble(), tmpList[3].toDouble());
}
item = m_config->addItemRectF(m_name, *d->newRectF(), defaultRectF, m_key);
} else if (m_type == QLatin1String("size")) {
QSize defaultSize;
const QList<QStringView> tmpList = QStringView(m_default).split(QLatin1Char(','));
if (tmpList.size() >= 2) {
defaultSize.setWidth(tmpList[0].toInt());
defaultSize.setHeight(tmpList[1].toInt());
}
item = m_config->addItemSize(m_name, *d->newSize(), defaultSize, m_key);
} else if (m_type == QLatin1String("sizef")) {
QSizeF defaultSizeF;
const auto tmpList = QStringView(m_default).split(u',');
if (tmpList.size() >= 2) {
defaultSizeF.setWidth(tmpList[0].toDouble());
defaultSizeF.setHeight(tmpList[1].toDouble());
}
item = m_config->addItemSizeF(m_name, *d->newSizeF(), defaultSizeF, m_key);
} else if (m_type == QLatin1String("ulonglong")) {
KConfigSkeleton::ItemULongLong *ulonglongItem = m_config->addItemULongLong(m_name, *d->newULongLong(), m_default.toULongLong(), m_key);
if (m_haveMin) {
ulonglongItem->setMinValue(m_min);
}
if (m_haveMax) {
ulonglongItem->setMaxValue(m_max);
}
item = ulonglongItem;
/* No addItemUrlList in KConfigSkeleton ?
} else if (m_type == "urllist") {
//FIXME: the split() is naive and will break on lists with ,'s in them
QStringList tmpList = m_default.split(",");
QList<QUrl> defaultList;
foreach (const QString& tmp, tmpList) {
defaultList.append(QUrl(tmp));
}
item = m_config->addItemUrlList(m_name, *d->newUrlList(), defaultList, m_key);*/
}
if (item) {
item->setLabel(m_label);
item->setWhatsThis(m_whatsThis);
d->keysToNames.insert(item->group() + item->key(), item->name());
}
}
void ConfigLoaderHandler::resetState()
{
m_haveMin = false;
m_min = 0;
m_haveMax = false;
m_max = 0;
m_name.clear();
m_type.clear();
m_label.clear();
m_default.clear();
m_key.clear();
m_whatsThis.clear();
m_enumChoices.clear();
m_inChoice = false;
}
KConfigLoader::KConfigLoader(const QString &configFile, QIODevice *xml, QObject *parent)
: KConfigSkeleton(configFile, parent)
, d(new ConfigLoaderPrivate)
{
d->parse(this, xml);
}
KConfigLoader::KConfigLoader(KSharedConfigPtr config, QIODevice *xml, QObject *parent)
: KConfigSkeleton(std::move(config), parent)
, d(new ConfigLoaderPrivate)
{
d->parse(this, xml);
}
// FIXME: obviously this is broken and should be using the group as the root,
// but KConfigSkeleton does not currently support this. it will eventually though,
// at which point this can be addressed properly
KConfigLoader::KConfigLoader(const KConfigGroup &config, QIODevice *xml, QObject *parent)
: KConfigSkeleton(KSharedConfig::openConfig(config.config()->name(), config.config()->openFlags(), config.config()->locationType()), parent)
, d(new ConfigLoaderPrivate)
{
KConfigGroup group = config.parent();
d->baseGroup = config.name();
while (group.isValid() && group.name() != QLatin1String("<default>")) {
d->baseGroup = group.name() + QLatin1Char('\x1d') + d->baseGroup;
group = group.parent();
}
d->parse(this, xml);
}
KConfigLoader::~KConfigLoader()
{
delete d;
}
KConfigSkeletonItem *KConfigLoader::findItem(const QString &group, const QString &key) const
{
return KConfigSkeleton::findItem(d->keysToNames[group + key]);
}
KConfigSkeletonItem *KConfigLoader::findItemByName(const QString &name) const
{
return KConfigSkeleton::findItem(name);
}
QVariant KConfigLoader::property(const QString &name) const
{
KConfigSkeletonItem *item = KConfigSkeleton::findItem(name);
if (item) {
return item->property();
}
return QVariant();
}
bool KConfigLoader::hasGroup(const QString &group) const
{
return d->groups.contains(group);
}
QStringList KConfigLoader::groupList() const
{
return d->groups;
}
bool KConfigLoader::usrSave()
{
if (d->saveDefaults) {
const auto listItems = items();
for (const auto &item : listItems) {
config()->group(item->group()).writeEntry(item->key(), "");
}
}
return true;
}
@@ -0,0 +1,165 @@
/*
SPDX-FileCopyrightText: 2007 Aaron Seigo <aseigo@kde.org>
SPDX-License-Identifier: LGPL-2.0-or-later
*/
#ifndef KCONFIGLOADER_H
#define KCONFIGLOADER_H
#include <QIODevice>
#include <kconfiggroup.h>
#include <kconfigskeleton.h>
#include <ksharedconfig.h>
#include <kconfiggui_export.h>
class ConfigLoaderPrivate;
/**
* @class KConfigLoader kconfigloader.h <KConfigLoader>
*
* @short A KConfigSkeleton that populates itself based on KConfigXT XML
*
* This class allows one to ship an XML file and reconstitute it into a
* KConfigSkeleton object at runtime. Common usage might look like this:
*
* \code
* QFile file(xmlFilePath);
* KConfigLoader appletConfig(configFilePath, &file);
* \endcode
*
* Alternatively, any QIODevice may be used in place of QFile in the
* example above.
*
* KConfigLoader is useful if it is not possible to use compiled code
* and by that the kconfig compiler cannot be used. Common examples are
* scripted plugins which want to provide a configuration interface.
* With the help of KConfigLoader a dynamically loaded ui file can be
* populated with the stored values and also stored back to the config
* file.
*
* An example for populating a QDialog with a dynamically populated UI
* with the help of a KConfigDialogManager:
* \code
* QDialog *dialog = new QDialog();
* QFile xmlFile("path/to/kconfigxt.xml");
* KConfigGroup cg = KSharedConfig::openConfig()->group(QString());
* KConfigLoader *configLoader = new KConfigLoader(cg, &xmlFile, this);
*
* // load the ui file
* QUiLoader *loader = new QUiLoader(this);
* QFile uiFile("path/to/userinterface.ui");
* uiFile.open(QFile::ReadOnly);
* QWidget *customConfigForm = loader->load(&uiFile, dialog);
* uiFile.close();
*
* KConfigDialogManager *manager = new KConfigDialogManager(customConfigForm, configLoader);
* if (dialog->exec() == QDialog::Accepted) {
* manager->updateSettings();
* }
* \endcode
*
* Currently the following data types are supported:
*
* @li bools
* @li colors
* @li datetimes
* @li enumerations
* @li fonts
* @li ints
* @li passwords
* @li paths
* @li strings
* @li stringlists
* @li uints
* @li urls
* @li doubles
* @li int lists
* @li longlongs
* @li path lists
* @li points
* @li pointfs
* @li rects
* @li rectfs
* @li sizes
* @li sizefs
* @li ulonglongs
* @li url lists
**/
class KCONFIGGUI_EXPORT KConfigLoader : public KConfigSkeleton
{
public:
/**
* Creates a KConfigSkeleton populated using the definition found in
* the XML data passed in.
*
* @param configFile path to the configuration file to use
* @param xml the xml data; must be valid KConfigXT data
* @param parent optional QObject parent
**/
KConfigLoader(const QString &configFile, QIODevice *xml, QObject *parent = nullptr);
/**
* Creates a KConfigSkeleton populated using the definition found in
* the XML data passed in.
*
* @param config the configuration object to use
* @param xml the xml data; must be valid KConfigXT data
* @param parent optional QObject parent
**/
KConfigLoader(KSharedConfigPtr config, QIODevice *xml, QObject *parent = nullptr);
/**
* Creates a KConfigSkeleton populated using the definition found in
* the XML data passed in.
*
* @param config the group to use as the root for configuration items
* @param xml the xml data; must be valid KConfigXT data
* @param parent optional QObject parent
**/
KConfigLoader(const KConfigGroup &config, QIODevice *xml, QObject *parent = nullptr);
~KConfigLoader() override;
/**
* Finds the item for the given group and key.
*
* @param group the group in the config file to look in
* @param key the configuration key to find
* @return the associated KConfigSkeletonItem, or @c nullptr if none
*/
KConfigSkeletonItem *findItem(const QString &group, const QString &key) const;
/**
* Finds an item by its name
*/
KConfigSkeletonItem *findItemByName(const QString &name) const;
/**
* Returns the property (variantized value) of the named item
*/
QVariant property(const QString &name) const;
/**
* Check to see if a group exists
*
* @param group the name of the group to check for
* @return true if the group exists, or false if it does not
*/
bool hasGroup(const QString &group) const;
/**
* @return the list of groups defined by the XML
*/
QStringList groupList() const;
protected:
bool usrSave() override;
private:
ConfigLoaderPrivate *const d;
};
#endif // multiple inclusion guard
@@ -0,0 +1,235 @@
/*
SPDX-FileCopyrightText: 2007-2008 Aaron Seigo <aseigo@kde.org>
SPDX-License-Identifier: LGPL-2.0-or-later
*/
#ifndef KCONFIGLOADER_P_H
#define KCONFIGLOADER_P_H
#include <QUrl>
class ConfigLoaderPrivate
{
public:
ConfigLoaderPrivate()
: saveDefaults(false)
{
}
~ConfigLoaderPrivate()
{
clearData();
}
void clearData()
{
qDeleteAll(bools);
qDeleteAll(strings);
qDeleteAll(stringlists);
qDeleteAll(colors);
qDeleteAll(fonts);
qDeleteAll(ints);
qDeleteAll(uints);
qDeleteAll(urls);
qDeleteAll(dateTimes);
qDeleteAll(doubles);
qDeleteAll(intlists);
qDeleteAll(longlongs);
qDeleteAll(points);
qDeleteAll(pointfs);
qDeleteAll(rects);
qDeleteAll(rectfs);
qDeleteAll(sizes);
qDeleteAll(sizefs);
qDeleteAll(ulonglongs);
qDeleteAll(urllists);
}
bool *newBool()
{
bool *v = new bool;
bools.append(v);
return v;
}
QString *newString()
{
QString *v = new QString;
strings.append(v);
return v;
}
QStringList *newStringList()
{
QStringList *v = new QStringList;
stringlists.append(v);
return v;
}
QColor *newColor()
{
QColor *v = new QColor;
colors.append(v);
return v;
}
QFont *newFont()
{
QFont *v = new QFont;
fonts.append(v);
return v;
}
qint32 *newInt()
{
qint32 *v = new qint32;
ints.append(v);
return v;
}
quint32 *newUint()
{
quint32 *v = new quint32;
uints.append(v);
return v;
}
QUrl *newUrl()
{
QUrl *v = new QUrl;
urls.append(v);
return v;
}
QDateTime *newDateTime()
{
QDateTime *v = new QDateTime;
dateTimes.append(v);
return v;
}
double *newDouble()
{
double *v = new double;
doubles.append(v);
return v;
}
QList<qint32> *newIntList()
{
QList<qint32> *v = new QList<qint32>;
intlists.append(v);
return v;
}
qint64 *newLongLong()
{
qint64 *v = new qint64;
longlongs.append(v);
return v;
}
QPoint *newPoint()
{
QPoint *v = new QPoint;
points.append(v);
return v;
}
QPointF *newPointF()
{
QPointF *v = new QPointF;
pointfs.append(v);
return v;
}
QRect *newRect()
{
QRect *v = new QRect;
rects.append(v);
return v;
}
QRectF *newRectF()
{
QRectF *v = new QRectF;
rectfs.append(v);
return v;
}
QSize *newSize()
{
QSize *v = new QSize;
sizes.append(v);
return v;
}
QSizeF *newSizeF()
{
QSizeF *v = new QSizeF;
sizefs.append(v);
return v;
}
quint64 *newULongLong()
{
quint64 *v = new quint64;
ulonglongs.append(v);
return v;
}
QList<QUrl> *newUrlList()
{
QList<QUrl> *v = new QList<QUrl>();
urllists.append(v);
return v;
}
void parse(KConfigLoader *loader, QIODevice *xml);
/**
* Whether or not to write out default values.
*
* @param writeDefaults true if defaults should be written out
*/
void setWriteDefaults(bool writeDefaults)
{
saveDefaults = writeDefaults;
}
/**
* @return true if default values will also be written out
*/
bool writeDefaults() const
{
return saveDefaults;
}
QList<bool *> bools;
QList<QString *> strings;
QList<QStringList *> stringlists;
QList<QColor *> colors;
QList<QFont *> fonts;
QList<qint32 *> ints;
QList<quint32 *> uints;
QList<QUrl *> urls;
QList<QDateTime *> dateTimes;
QList<double *> doubles;
QList<QList<qint32> *> intlists;
QList<qint64 *> longlongs;
QList<QPoint *> points;
QList<QPointF *> pointfs;
QList<QRect *> rects;
QList<QRectF *> rectfs;
QList<QSize *> sizes;
QList<QSizeF *> sizefs;
QList<quint64 *> ulonglongs;
QList<QList<QUrl> *> urllists;
QString baseGroup;
QStringList groups;
QHash<QString, QString> keysToNames;
bool saveDefaults;
};
#endif
@@ -0,0 +1,45 @@
/*
SPDX-FileCopyrightText: 2007-2008 Aaron Seigo <aseigo@kde.org>
SPDX-FileCopyrightText: 2013 Marco Martin <mart@kde.org>
SPDX-License-Identifier: LGPL-2.0-or-later
*/
#ifndef KCONFIGLOADERHANDLER_P_H
#define KCONFIGLOADERHANDLER_P_H
#include <QXmlStreamAttributes>
class ConfigLoaderHandler
{
public:
ConfigLoaderHandler(KConfigLoader *config, ConfigLoaderPrivate *d);
bool parse(QIODevice *input);
void startElement(const QStringView localName, const QXmlStreamAttributes &attrs);
void endElement(const QStringView localName);
private:
void addItem();
void resetState();
KConfigLoader *m_config;
ConfigLoaderPrivate *d;
int m_min;
int m_max;
QString m_name;
QString m_key;
QString m_type;
QString m_label;
QString m_default;
QString m_cdata;
QString m_whatsThis;
KConfigSkeleton::ItemEnum::Choice m_choice;
QList<KConfigSkeleton::ItemEnum::Choice> m_enumChoices;
bool m_haveMin;
bool m_haveMax;
bool m_inChoice;
};
#endif
@@ -0,0 +1,99 @@
/*
This file is part of KOrganizer.
SPDX-FileCopyrightText: 2000, 2001 Cornelius Schumacher <schumacher@kde.org>
SPDX-FileCopyrightText: 2003 Waldo Bastian <bastian@kde.org>
SPDX-License-Identifier: LGPL-2.0-or-later
*/
#include "kconfigskeleton.h"
#include <kcoreconfigskeleton_p.h>
KConfigSkeleton::KConfigSkeleton(const QString &configname, QObject *parent)
: KCoreConfigSkeleton(configname, parent)
{
}
KConfigSkeleton::KConfigSkeleton(KSharedConfig::Ptr pConfig, QObject *parent)
: KCoreConfigSkeleton(std::move(pConfig), parent)
{
}
KConfigSkeleton::ItemColor::ItemColor(const QString &_group, const QString &_key, QColor &reference, const QColor &defaultValue)
: KConfigSkeletonGenericItem<QColor>(_group, _key, reference, defaultValue)
{
}
void KConfigSkeleton::ItemColor::readConfig(KConfig *config)
{
KConfigGroup cg = configGroup(config);
mReference = cg.readEntry(mKey, mDefault);
mLoadedValue = mReference;
readImmutability(cg);
}
void KConfigSkeleton::ItemColor::setProperty(const QVariant &p)
{
mReference = qvariant_cast<QColor>(p);
}
bool KConfigSkeleton::ItemColor::isEqual(const QVariant &v) const
{
return mReference == qvariant_cast<QColor>(v);
}
QVariant KConfigSkeleton::ItemColor::property() const
{
return QVariant(mReference);
}
KConfigSkeleton::ItemFont::ItemFont(const QString &_group, const QString &_key, QFont &reference, const QFont &defaultValue)
: KConfigSkeletonGenericItem<QFont>(_group, _key, reference, defaultValue)
{
}
void KConfigSkeleton::ItemFont::readConfig(KConfig *config)
{
KConfigGroup cg = configGroup(config);
mReference = cg.readEntry(mKey, mDefault);
mLoadedValue = mReference;
readImmutability(cg);
}
void KConfigSkeleton::ItemFont::setProperty(const QVariant &p)
{
mReference = qvariant_cast<QFont>(p);
}
bool KConfigSkeleton::ItemFont::isEqual(const QVariant &v) const
{
return mReference == qvariant_cast<QFont>(v);
}
QVariant KConfigSkeleton::ItemFont::property() const
{
return QVariant(mReference);
}
KConfigSkeleton::ItemColor *KConfigSkeleton::addItemColor(const QString &name, QColor &reference, const QColor &defaultValue, const QString &key)
{
KConfigSkeleton::ItemColor *item;
item = new KConfigSkeleton::ItemColor(d->mCurrentGroup, key.isNull() ? name : key, reference, defaultValue);
addItem(item, name);
return item;
}
KConfigSkeleton::ItemFont *KConfigSkeleton::addItemFont(const QString &name, QFont &reference, const QFont &defaultValue, const QString &key)
{
KConfigSkeleton::ItemFont *item;
item = new KConfigSkeleton::ItemFont(d->mCurrentGroup, key.isNull() ? name : key, reference, defaultValue);
addItem(item, name);
return item;
}
#include "moc_kconfigskeleton.cpp"
@@ -0,0 +1,118 @@
/*
This file is part of KDE.
SPDX-FileCopyrightText: 2001, 2002, 2003 Cornelius Schumacher <schumacher@kde.org>
SPDX-FileCopyrightText: 2003 Waldo Bastian <bastian@kde.org>
SPDX-License-Identifier: LGPL-2.0-or-later
*/
#ifndef KCONFIGSKELETON_H
#define KCONFIGSKELETON_H
#include <kconfiggui_export.h>
#include <kcoreconfigskeleton.h>
#include <QColor>
#include <QFont>
/**
* @class KConfigSkeleton kconfigskeleton.h <KConfigSkeleton>
*
* @short Class for handling preferences settings for an application.
* @author Cornelius Schumacher
*
* This class extends KCoreConfigSkeleton by support for GUI types.
*/
class KCONFIGGUI_EXPORT KConfigSkeleton : public KCoreConfigSkeleton
{
Q_OBJECT
public:
/**
* Class for handling a color preferences item.
*/
class KCONFIGGUI_EXPORT ItemColor : public KConfigSkeletonGenericItem<QColor>
{
public:
/** @copydoc KConfigSkeletonGenericItem::KConfigSkeletonGenericItem */
ItemColor(const QString &_group, const QString &_key, QColor &reference, const QColor &defaultValue = QColor(128, 128, 128));
/** @copydoc KConfigSkeletonItem::readConfig(KConfig*) */
void readConfig(KConfig *config) override;
/** @copydoc KConfigSkeletonItem::setProperty(const QVariant&) */
void setProperty(const QVariant &p) override;
/** @copydoc KConfigSkeletonItem::isEqual(const QVariant &) */
bool isEqual(const QVariant &p) const override;
/** @copydoc KConfigSkeletonItem::property() */
QVariant property() const override;
};
/**
* Class for handling a font preferences item.
*/
class KCONFIGGUI_EXPORT ItemFont : public KConfigSkeletonGenericItem<QFont>
{
public:
/** @copydoc KConfigSkeletonGenericItem::KConfigSkeletonGenericItem */
ItemFont(const QString &_group, const QString &_key, QFont &reference, const QFont &defaultValue = QFont());
/** @copydoc KConfigSkeletonItem::readConfig(KConfig*) */
void readConfig(KConfig *config) override;
/** @copydoc KConfigSkeletonItem::setProperty(const QVariant&) */
void setProperty(const QVariant &p) override;
/** @copydoc KConfigSkeletonItem::isEqual(const QVariant &) */
bool isEqual(const QVariant &p) const override;
/** @copydoc KConfigSkeletonItem::property() */
QVariant property() const override;
};
public:
/**
* Constructor.
*
* @param configname name of config file. If no name is given, the default
* config file as returned by KSharedConfig::openConfig() is used.
*/
explicit KConfigSkeleton(const QString &configname = QString(), QObject *parent = nullptr);
/**
* Constructor.
*
* @param config configuration object to use.
*/
explicit KConfigSkeleton(KSharedConfig::Ptr config, QObject *parent = nullptr);
/**
* Register an item of type QColor.
*
* @param name Name used to identify this setting. Names must be unique.
* @param reference Pointer to the variable, which is set by read()
* calls and read by save() calls.
* @param defaultValue Default value, which is used when the config file
* does not yet contain the key of this item.
* @param key Key used in config file. If @p key is a null string, @p name is used as key.
* @return The created item
*/
ItemColor *addItemColor(const QString &name, QColor &reference, const QColor &defaultValue = QColor(128, 128, 128), const QString &key = QString());
/**
* Register an item of type QFont.
*
* @param name Name used to identify this setting. Names must be unique.
* @param reference Pointer to the variable, which is set by read()
* calls and read by save() calls.
* @param defaultValue Default value, which is used when the config file
* does not yet contain the key of this item.
* @param key Key used in config file. If @p key is a null string, @p name is used as key.
* @return The created item
*/
ItemFont *addItemFont(const QString &name, QFont &reference, const QFont &defaultValue = QFont(), const QString &key = QString());
};
#endif
@@ -0,0 +1,175 @@
/*
This file is part of the KDE libraries
SPDX-FileCopyrightText: 1999, 2000 Kurt Granroth <granroth@kde.org>
SPDX-License-Identifier: LGPL-2.0-only
*/
#include "kstandardactions.h"
#include "kstandardactions_p.h"
#include "moc_kstandardactions_p.cpp"
#include <KStandardShortcutWatcher>
#include <QGuiApplication>
namespace KStandardActions
{
QList<StandardAction> actionIds()
{
QList<StandardAction> result;
for (uint i = 0; g_rgActionInfo[i].id != ActionNone; i++) {
result.append(g_rgActionInfo[i].id);
}
return result;
}
KStandardShortcut::StandardShortcut shortcutForActionId(StandardAction id)
{
const KStandardActionsInfo *pInfo = infoPtr(id);
return (pInfo) ? pInfo->idAccel : KStandardShortcut::AccelNone;
}
QAction *_kgui_createInternal(StandardAction id, QObject *parent)
{
QAction *pAction = new QAction(parent);
const KStandardActionsInfo *pInfo = infoPtr(id);
// qCDebug(KCONFIG_WIDGETS_LOG) << "KStandardActions::create( " << id << "=" << (pInfo ? pInfo->psName : (const char*)0) << ", " << parent << " )"; //
// ellis
if (pInfo) {
QString sLabel;
QString iconName = pInfo->psIconName.toString();
switch (id) {
case Back:
sLabel = QCoreApplication::translate("go back", "&Back");
if (QGuiApplication::isRightToLeft()) {
iconName = QStringLiteral("go-next");
}
break;
case Forward:
sLabel = QCoreApplication::translate("go forward", "&Forward");
if (QGuiApplication::isRightToLeft()) {
iconName = QStringLiteral("go-previous");
}
break;
case Home:
sLabel = QCoreApplication::translate("home page", "&Home");
break;
case Preferences:
case AboutApp:
case HelpContents: {
QString appDisplayName = QGuiApplication::applicationDisplayName();
if (appDisplayName.isEmpty()) {
appDisplayName = QCoreApplication::applicationName();
}
sLabel = QCoreApplication::translate("KStandardActions", pInfo->psLabel).arg(appDisplayName);
} break;
default:
sLabel = QCoreApplication::translate("KStandardActions", pInfo->psLabel);
}
if (QGuiApplication::isRightToLeft()) {
switch (id) {
case Prior:
iconName = QStringLiteral("go-next-view-page");
break;
case Next:
iconName = QStringLiteral("go-previous-view-page");
break;
case FirstPage:
iconName = QStringLiteral("go-last-view-page");
break;
case LastPage:
iconName = QStringLiteral("go-first-view-page");
break;
case DocumentBack:
iconName = QStringLiteral("go-next");
break;
case DocumentForward:
iconName = QStringLiteral("go-previous");
break;
default:
break;
}
}
if (id == Donate) {
const QString currencyCode = QLocale().currencySymbol(QLocale::CurrencyIsoCode).toLower();
if (!currencyCode.isEmpty()) {
iconName = QStringLiteral("help-donate-%1").arg(currencyCode);
}
}
QIcon icon = iconName.isEmpty() ? QIcon() : QIcon::fromTheme(iconName);
if (id == AboutApp) {
icon = qGuiApp->windowIcon();
}
// Set the text before setting the MenuRole, as on OS X setText will do some heuristic role guessing.
// This ensures user menu items get the intended role out of the list below.
pAction->setText(sLabel);
switch (id) {
case Quit:
pAction->setMenuRole(QAction::QuitRole);
break;
case Preferences:
pAction->setMenuRole(QAction::PreferencesRole);
break;
case AboutApp:
pAction->setMenuRole(QAction::AboutRole);
break;
default:
pAction->setMenuRole(QAction::NoRole);
break;
}
if (!QCoreApplication::translate("KStandardActions", pInfo->psToolTip).isEmpty()) {
pAction->setToolTip(QCoreApplication::translate("KStandardActions", pInfo->psToolTip));
}
pAction->setIcon(icon);
QList<QKeySequence> cut = KStandardShortcut::shortcut(pInfo->idAccel);
if (!cut.isEmpty()) {
// emulate KActionCollection::setDefaultShortcuts to allow the use of "configure shortcuts"
pAction->setShortcuts(cut);
pAction->setProperty("defaultShortcuts", QVariant::fromValue(cut));
}
pAction->connect(KStandardShortcut::shortcutWatcher(),
&KStandardShortcut::StandardShortcutWatcher::shortcutChanged,
pAction,
[pAction, shortcut = pInfo->idAccel](KStandardShortcut::StandardShortcut id, const QList<QKeySequence> &newShortcut) {
if (id != shortcut) {
return;
}
pAction->setShortcuts(newShortcut);
pAction->setProperty("defaultShortcuts", QVariant::fromValue(newShortcut));
});
pAction->setObjectName(pInfo->psName.toString());
}
if (pAction && parent && parent->inherits("KActionCollection")) {
QMetaObject::invokeMethod(parent, "addAction", Q_ARG(QString, pAction->objectName()), Q_ARG(QAction *, pAction));
}
return pAction;
}
QString name(StandardAction id)
{
const KStandardActionsInfo *pInfo = infoPtr(id);
return (pInfo) ? pInfo->psName.toString() : QString();
}
}
@@ -0,0 +1,535 @@
/*
This file is part of the KDE libraries
SPDX-FileCopyrightText: 1999, 2000 Kurt Granroth <granroth@kde.org>
SPDX-FileCopyrightText: 2001, 2002 Ellis Whitehead <ellis@kde.org>
SPDX-License-Identifier: LGPL-2.0-only
*/
#ifndef KGUISTANDARDACTION_H
#define KGUISTANDARDACTION_H
#include <QAction>
#include <QList>
#include <QStringList>
#include <KStandardShortcut>
#include <kconfiggui_export.h>
#include <optional>
#include <type_traits>
class QObject;
class QAction;
/**
* Convenience methods to access all standard KDE actions.
*
* These actions should be used instead of hardcoding menubar and
* toolbar items. Using these actions helps your application easily
* conform to the <a href="https://develop.kde.org/hig/">KDE Human Interface Guidelines</a>.
*
* All of the documentation for QAction holds for KStandardActions
* also. When in doubt on how things work, check the QAction
* documentation first.
* Please note that calling any of these methods automatically adds the action
* to the actionCollection() of the QObject given by the 'parent' parameter.
*
* <b>Simple Example:</b>\n
*
* In general, using standard actions should be a drop in replacement
* for regular actions. For example, if you previously had:
* @code
* QAction *newAct = new QAction(QIcon::fromTheme("document-new"),
* i18n("&New"),
* this);
* newAct->setShortcut(KStandardShortcut::shortcut(KStandardShortcut::New).constFirst());
* connect(newAct, &QAction::triggered, this, &ClassFoo::fileNew);
* @endcode
*
* You can replace it with:
* @code
* QAction *newAct = KStandardActions::openNew(this, &ClassFoo::fileNew, this);
* @endcode
*
* Alternatively you can instantiate the action using the StandardAction enums
* provided. This author can't think of a reason why you would want to, but, hey,
* if you do, here's how:
*
* \code
* QAction *newAct = KStandardActions::create(KStandardActions::New, this, &ClassFoo::fileNew, this);
* \endcode
*
* <b>Relationship with KActionCollection from KXMLGui</b>\n
*
* If a KActionCollection is passed as the parent then the action will be
* automatically added to that collection:
* \code
* QAction *cut = KStandardActions::cut(this, &ClassFoo::editCut, actionCollection());
* \endcode
*
* Each action has a unique internal name which can be queried using the
* name method. For example KStandardActions::name(KStandardActions::Cut)
* would return 'edit_cut'. This name can be used as a unique identifier
* for the actions. So if you wanted to add an existing standard action
* to an action collection you can do so like this:
* \code
* QAction *cut = KStandardActions::cut(this, &ClassFoo::editCut, this);
* actionCollection()->addAction(KStandardActions::name(KStandardActions::Cut), cut);
* \endcode
*
* You can then get a pointer to the action using
* \code
* QAction *cutPtr = actionCollection()->action(KStandardActions::name(KStandardActions::Cut));
* \endcode
*
* @author Kurt Granroth <granroth@kde.org>
* @since 6.3
*/
namespace KStandardActions
{
/**
* The standard menubar and toolbar actions.
*/
enum StandardAction {
ActionNone,
// File Menu
New, ///< Create a new document or window.
Open, ///< Open an existing file.
OpenRecent, ///< Open a recently used document.
Save, ///< Save the current document.
SaveAs, ///< Save the current document under a different name.
Revert, ///< Revert the current document to the last saved version.
Close, ///< Close the current document.
Print, ///< Print the current document.
PrintPreview, ///< Show a print preview of the current document.
Mail, ///< Send the current document by mail.
Quit, ///< Quit the program.
// Edit Menu
Undo, ///< Undo the last operation.
Redo, ///< Redo the last operation.
Cut, ///< Cut selected area and store it in the clipboard.
Copy, ///< Copy selected area and store it in the clipboard.
Paste, ///< Paste the contents of clipboard at the current mouse or cursor.
SelectAll, ///< Select all elements in the current document.
Deselect, ///< Deselect any selected elements in the current document.
Find, ///< Initiate a 'find' request in the current document.
FindNext, ///< Find the next instance of a stored 'find'
FindPrev, ///< Find a previous instance of a stored 'find'.
Replace, ///< Find and replace matches.
// View Menu
ActualSize, ///< View the document at its actual size.
FitToPage, ///< Fit the document view to the size of the current window.
FitToWidth, ///< Fit the document view to the width of the current window.
FitToHeight, ///< Fit the document view to the height of the current window.
ZoomIn, ///< Zoom in the current document.
ZoomOut, ///< Zoom out the current document.
Zoom, ///< Select the current zoom level.
Redisplay, ///< Redisplay or redraw the document.
// Go Menu
Up, ///< Move up (web style menu).
Back, ///< Move back (web style menu).
Forward, ///< Move forward (web style menu).
Home, ///< Go to the "Home" position or document.
Prior, ///< Scroll up one page.
Next, ///< Scroll down one page.
Goto, ///< Jump to some specific location in the document.
GotoPage, ///< Go to a specific page.
GotoLine, ///< Go to a specific line.
FirstPage, ///< Jump to the first page.
LastPage, ///< Jump to the last page.
DocumentBack, ///< Move back (document style menu).
DocumentForward, ///< Move forward (document style menu).
// Bookmarks Menu
AddBookmark, ///< Add the current page to the bookmarks tree.
EditBookmarks, ///< Edit the application bookmarks.
// Tools Menu
Spelling, ///< Pop up the spell checker.
// Settings Menu
ShowMenubar, ///< Show/Hide the menubar.
ShowToolbar, ///< Show/Hide the toolbar.
ShowStatusbar, ///< Show/Hide the statusbar.
KeyBindings, ///< Display the configure key bindings dialog.
Preferences, ///< Display the preferences/options dialog.
ConfigureToolbars, ///< Display the toolbar configuration dialog.
// Help Menu
HelpContents, ///< Display the handbook of the application.
WhatsThis, ///< Trigger the What's This cursor.
ReportBug, ///< Open up the Report Bug dialog.
AboutApp, ///< Display the application's About box.
AboutKDE, ///< Display the About KDE dialog.
// Other standard actions
ConfigureNotifications, ///< Display the notifications configuration dialog.
FullScreen, ///< Switch to/from full screen mode.
Clear, ///< Clear the content of the focus widget.
SwitchApplicationLanguage, ///< Display the Switch Application Language dialog.
DeleteFile, ///< Permanently deletes files or folders.
RenameFile, ///< Renames files or folders.
MoveToTrash, ///< Moves files or folders to the trash.
Donate, ///< Open donation page on kde.org.
HamburgerMenu ///< Opens a menu that substitutes the menubar.
// To keep in sync with KConfigWidgets::KStandardAction
};
/**
* @internal
*/
KCONFIGGUI_EXPORT QAction *_kgui_createInternal(StandardAction id, QObject *parent);
/**
* Creates an action corresponding to one of the
* KStandardActions::StandardAction actions, which is connected to the given
* object and @p slot, and is owned by @p parent.
*
* If not explicitly specified, @p connectionType will be AutoConnection for all actions
* except for ConfigureToolbars it will be QueuedConnection.
*
* @see create(StandardAction, const QObject *, const char *, QObject *)
*/
template<class Receiver, class Func>
inline QAction *create(StandardAction id, const Receiver *recvr, Func slot, QObject *parent, std::optional<Qt::ConnectionType> connectionType = std::nullopt)
{
QAction *action = _kgui_createInternal(id, parent);
// ConfigureToolbars is special because of bug #200815
const Qt::ConnectionType defaultConnectionType = (id == ConfigureToolbars) ? Qt::QueuedConnection : Qt::AutoConnection;
QObject::connect(action, &QAction::triggered, recvr, slot, connectionType.value_or(defaultConnectionType));
return action;
}
/**
* This will return the internal name of a given standard action.
*/
KCONFIGGUI_EXPORT QString name(StandardAction id);
/**
* Returns a list of all actionIds.
*/
KCONFIGGUI_EXPORT QList<StandardAction> actionIds();
/**
* Returns the standardshortcut associated with @a actionId.
*
* @param id The identifier whose associated shortcut is wanted.
*/
KCONFIGGUI_EXPORT KStandardShortcut::StandardShortcut shortcutForActionId(StandardAction id);
// clang-format off
#define KGUISTANDARDACTION_WITH_NEW_STYLE_CONNECT(name, enumValue) \
template<class Receiver, class Func> \
inline QAction *name(const Receiver *recvr, Func slot, QObject *parent) \
{ return create(enumValue, recvr, slot, parent); }
// clang-format on
/**
* Create a new document or window.
*/
KGUISTANDARDACTION_WITH_NEW_STYLE_CONNECT(openNew, New)
/**
* Open an existing file.
*/
KGUISTANDARDACTION_WITH_NEW_STYLE_CONNECT(open, Open)
/**
* Save the current document.
*/
KGUISTANDARDACTION_WITH_NEW_STYLE_CONNECT(save, Save)
/**
* Save the current document under a different name.
*/
KGUISTANDARDACTION_WITH_NEW_STYLE_CONNECT(saveAs, SaveAs)
/**
* Revert the current document to the last saved version
* (essentially will undo all changes).
*/
KGUISTANDARDACTION_WITH_NEW_STYLE_CONNECT(revert, Revert)
/**
* Close the current document.
*/
KGUISTANDARDACTION_WITH_NEW_STYLE_CONNECT(close, Close)
/**
* Print the current document.
*/
KGUISTANDARDACTION_WITH_NEW_STYLE_CONNECT(print, Print)
/**
* Show a print preview of the current document.
*/
KGUISTANDARDACTION_WITH_NEW_STYLE_CONNECT(printPreview, PrintPreview)
/**
* Mail this document.
*/
KGUISTANDARDACTION_WITH_NEW_STYLE_CONNECT(mail, Mail)
/**
* Quit the program.
*
* Note that you probably want to connect this action to either QWidget::close()
* or QApplication::closeAllWindows(), but not QApplication::quit(), so that
* KMainWindow::queryClose() is called on any open window (to warn the user
* about unsaved changes for example).
*/
KGUISTANDARDACTION_WITH_NEW_STYLE_CONNECT(quit, Quit)
/**
* Undo the last operation.
*/
KGUISTANDARDACTION_WITH_NEW_STYLE_CONNECT(undo, Undo)
/**
* Redo the last operation.
*/
KGUISTANDARDACTION_WITH_NEW_STYLE_CONNECT(redo, Redo)
/**
* Cut selected area and store it in the clipboard.
*/
KGUISTANDARDACTION_WITH_NEW_STYLE_CONNECT(cut, Cut)
/**
* Copy the selected area into the clipboard.
*/
KGUISTANDARDACTION_WITH_NEW_STYLE_CONNECT(copy, Copy)
/**
* Paste the contents of clipboard at the current mouse or cursor
* position.
*/
KGUISTANDARDACTION_WITH_NEW_STYLE_CONNECT(paste, Paste)
/**
* Clear the content of the focus widget
*/
KGUISTANDARDACTION_WITH_NEW_STYLE_CONNECT(clear, Clear)
/**
* Select all elements in the current document.
*/
KGUISTANDARDACTION_WITH_NEW_STYLE_CONNECT(selectAll, SelectAll)
/**
* Deselect any selected elements in the current document.
*/
KGUISTANDARDACTION_WITH_NEW_STYLE_CONNECT(deselect, Deselect)
/**
* Initiate a 'find' request in the current document.
*/
KGUISTANDARDACTION_WITH_NEW_STYLE_CONNECT(find, Find)
/**
* Find the next instance of a stored 'find'.
*/
KGUISTANDARDACTION_WITH_NEW_STYLE_CONNECT(findNext, FindNext)
/**
* Find a previous instance of a stored 'find'.
*/
KGUISTANDARDACTION_WITH_NEW_STYLE_CONNECT(findPrev, FindPrev)
/**
* Find and replace matches.
*/
KGUISTANDARDACTION_WITH_NEW_STYLE_CONNECT(replace, Replace)
/**
* View the document at its actual size.
*/
KGUISTANDARDACTION_WITH_NEW_STYLE_CONNECT(actualSize, ActualSize)
/**
* Fit the document view to the size of the current window.
*/
KGUISTANDARDACTION_WITH_NEW_STYLE_CONNECT(fitToPage, FitToPage)
/**
* Fit the document view to the width of the current window.
*/
KGUISTANDARDACTION_WITH_NEW_STYLE_CONNECT(fitToWidth, FitToWidth)
/**
* Fit the document view to the height of the current window.
*/
KGUISTANDARDACTION_WITH_NEW_STYLE_CONNECT(fitToHeight, FitToHeight)
/**
* Zoom in the current document view.
*/
KGUISTANDARDACTION_WITH_NEW_STYLE_CONNECT(zoomIn, ZoomIn)
/**
* Zoom out the current document view.
*/
KGUISTANDARDACTION_WITH_NEW_STYLE_CONNECT(zoomOut, ZoomOut)
/**
* Select the current zoom level.
*/
KGUISTANDARDACTION_WITH_NEW_STYLE_CONNECT(zoom, Zoom)
/**
* Redisplay or redraw the document.
*/
KGUISTANDARDACTION_WITH_NEW_STYLE_CONNECT(redisplay, Redisplay)
/**
* Move up (web style menu).
*/
KGUISTANDARDACTION_WITH_NEW_STYLE_CONNECT(up, Up)
/**
* Move back (web style menu).
*/
KGUISTANDARDACTION_WITH_NEW_STYLE_CONNECT(back, Back)
/**
* Move forward (web style menu).
*/
KGUISTANDARDACTION_WITH_NEW_STYLE_CONNECT(forward, Forward)
/**
* Go to the "Home" position or document.
*/
KGUISTANDARDACTION_WITH_NEW_STYLE_CONNECT(home, Home)
/**
* Scroll up one page.
*/
KGUISTANDARDACTION_WITH_NEW_STYLE_CONNECT(prior, Prior)
/**
* Scroll down one page.
*/
KGUISTANDARDACTION_WITH_NEW_STYLE_CONNECT(next, Next)
/**
* Jump to some specific location in the document.
*/
KGUISTANDARDACTION_WITH_NEW_STYLE_CONNECT(goTo, Goto)
/**
* Go to a specific page.
*/
KGUISTANDARDACTION_WITH_NEW_STYLE_CONNECT(gotoPage, GotoPage)
/**
* Go to a specific line.
*/
KGUISTANDARDACTION_WITH_NEW_STYLE_CONNECT(gotoLine, GotoLine)
/**
* Jump to the first page.
*/
KGUISTANDARDACTION_WITH_NEW_STYLE_CONNECT(firstPage, FirstPage)
/**
* Jump to the last page.
*/
KGUISTANDARDACTION_WITH_NEW_STYLE_CONNECT(lastPage, LastPage)
/**
* Move back (document style menu).
*/
KGUISTANDARDACTION_WITH_NEW_STYLE_CONNECT(documentBack, DocumentBack)
/**
* Move forward (document style menu).
*/
KGUISTANDARDACTION_WITH_NEW_STYLE_CONNECT(documentForward, DocumentForward)
/**
* Add the current page to the bookmarks tree.
*/
KGUISTANDARDACTION_WITH_NEW_STYLE_CONNECT(addBookmark, AddBookmark)
/**
* Edit the application bookmarks.
*/
KGUISTANDARDACTION_WITH_NEW_STYLE_CONNECT(editBookmarks, EditBookmarks)
/**
* Pop up the spell checker.
*/
KGUISTANDARDACTION_WITH_NEW_STYLE_CONNECT(spelling, Spelling)
/**
* Display the configure key bindings dialog.
*
* Note that you might be able to use the pre-built KXMLGUIFactory's function:
* @code
* KStandardActions::keyBindings(guiFactory(), &KXMLGUIFactory::showConfigureShortcutsDialog, actionCollection());
* @endcode
*/
KGUISTANDARDACTION_WITH_NEW_STYLE_CONNECT(keyBindings, KeyBindings)
/**
* Display the preferences/options dialog.
*/
KGUISTANDARDACTION_WITH_NEW_STYLE_CONNECT(preferences, Preferences)
/**
* Display the toolbar configuration dialog.
*/
KGUISTANDARDACTION_WITH_NEW_STYLE_CONNECT(configureToolbars, ConfigureToolbars)
/**
* Display the notifications configuration dialog.
*/
KGUISTANDARDACTION_WITH_NEW_STYLE_CONNECT(configureNotifications, ConfigureNotifications)
/**
* Display the Switch Application Language dialog.
*/
KGUISTANDARDACTION_WITH_NEW_STYLE_CONNECT(switchApplicationLanguage, SwitchApplicationLanguage)
/**
* Display the handbook of the application.
*/
KGUISTANDARDACTION_WITH_NEW_STYLE_CONNECT(helpContents, HelpContents)
/**
* Trigger the What's This cursor.
*/
KGUISTANDARDACTION_WITH_NEW_STYLE_CONNECT(whatsThis, WhatsThis)
/**
* Open up the Report Bug dialog.
*/
KGUISTANDARDACTION_WITH_NEW_STYLE_CONNECT(reportBug, ReportBug)
/**
* Display the application's About box.
*/
KGUISTANDARDACTION_WITH_NEW_STYLE_CONNECT(aboutApp, AboutApp)
/**
* Display the About KDE dialog.
*/
KGUISTANDARDACTION_WITH_NEW_STYLE_CONNECT(aboutKDE, AboutKDE)
/**
* Permanently deletes files or folders.
*/
KGUISTANDARDACTION_WITH_NEW_STYLE_CONNECT(deleteFile, DeleteFile)
/**
* Renames files or folders.
*/
KGUISTANDARDACTION_WITH_NEW_STYLE_CONNECT(renameFile, RenameFile)
/**
* Moves files or folders to the trash.
*/
KGUISTANDARDACTION_WITH_NEW_STYLE_CONNECT(moveToTrash, MoveToTrash)
/**
* Open donation page on kde.org.
*/
KGUISTANDARDACTION_WITH_NEW_STYLE_CONNECT(donate, Donate)
}
#endif // KSTDACTION_H
@@ -0,0 +1,181 @@
/*
This file is part of the KDE libraries
SPDX-FileCopyrightText: 1999, 2000 Kurt Granroth <granroth@kde.org>
SPDX-License-Identifier: LGPL-2.0-only
*/
#pragma once
#include <QAction>
#include <QGuiApplication>
#include <KStandardActions>
#include <KStandardShortcut>
#include <string>
namespace KStandardActions
{
/**
* Helper class for storing raw data in static tables which can be used for QString instance
* creation at runtime without copying/converting to new memalloc'ed memory, as well as avoiding
* that way storing the strings directly as QStrings resulting in non-constexpr init code on
* library loading
* @internal
*/
struct RawStringData {
template<std::size_t StringSize>
constexpr inline RawStringData(const char16_t (&_data)[StringSize])
: data(_data)
, size(std::char_traits<char16_t>::length(_data))
{
}
constexpr inline RawStringData(std::nullptr_t)
{
}
constexpr inline RawStringData() = default;
inline QString toString() const
{
if (!data) {
return QString();
}
return Qt::Literals::StringLiterals::operator""_s(data, size);
}
private:
const char16_t *const data = nullptr;
const std::size_t size = 0;
};
/**
* @internal
*/
struct KStandardActionsInfo {
KStandardActions::StandardAction id;
KStandardShortcut::StandardShortcut idAccel;
const RawStringData psName;
const char *psLabel;
const char *psToolTip;
const RawStringData psIconName;
};
// clang-format off
static constexpr KStandardActionsInfo g_rgActionInfo[] = {
{ New, KStandardShortcut::New, u"file_new", QT_TRANSLATE_NOOP("KStandardActions", "&New"), QT_TRANSLATE_NOOP("KStandardActions", "Create new document"), u"document-new" },
{ Open, KStandardShortcut::Open, u"file_open", QT_TRANSLATE_NOOP("KStandardActions", "&Open…"), QT_TRANSLATE_NOOP("KStandardActions", "Open an existing document"), u"document-open" },
{ OpenRecent, KStandardShortcut::AccelNone, u"file_open_recent", QT_TRANSLATE_NOOP("KStandardActions", "Open &Recent"), QT_TRANSLATE_NOOP("KStandardActions", "Open a document which was recently opened"), u"document-open-recent" },
{ Save, KStandardShortcut::Save, u"file_save", QT_TRANSLATE_NOOP("KStandardActions", "&Save"), QT_TRANSLATE_NOOP("KStandardActions", "Save document"), u"document-save" },
{ SaveAs, KStandardShortcut::SaveAs, u"file_save_as", QT_TRANSLATE_NOOP("KStandardActions", "Save &As…"), QT_TRANSLATE_NOOP("KStandardActions", "Save document under a new name"), u"document-save-as" },
{ Revert, KStandardShortcut::Revert, u"file_revert", QT_TRANSLATE_NOOP("KStandardActions", "Re&vert"), QT_TRANSLATE_NOOP("KStandardActions", "Revert unsaved changes made to document"), u"document-revert" },
{ Close, KStandardShortcut::Close, u"file_close", QT_TRANSLATE_NOOP("KStandardActions", "&Close"), QT_TRANSLATE_NOOP("KStandardActions", "Close document"), u"document-close" },
{ Print, KStandardShortcut::Print, u"file_print", QT_TRANSLATE_NOOP("KStandardActions", "&Print…"), QT_TRANSLATE_NOOP("KStandardActions", "Print document"), u"document-print" },
{ PrintPreview, KStandardShortcut::PrintPreview, u"file_print_preview", QT_TRANSLATE_NOOP("KStandardActions", "Print Previe&w"), QT_TRANSLATE_NOOP("KStandardActions", "Show a print preview of document"), u"document-print-preview" },
{ Mail, KStandardShortcut::Mail, u"file_mail", QT_TRANSLATE_NOOP("KStandardActions", "&Mail…"), QT_TRANSLATE_NOOP("KStandardActions", "Send document by mail"), u"mail-send" },
{ Quit, KStandardShortcut::Quit, u"file_quit", QT_TRANSLATE_NOOP("KStandardActions", "&Quit"), QT_TRANSLATE_NOOP("KStandardActions", "Quit application"), u"application-exit" },
{ Undo, KStandardShortcut::Undo, u"edit_undo", QT_TRANSLATE_NOOP("KStandardActions", "&Undo"), QT_TRANSLATE_NOOP("KStandardActions", "Undo last action"), u"edit-undo" },
{ Redo, KStandardShortcut::Redo, u"edit_redo", QT_TRANSLATE_NOOP("KStandardActions", "Re&do"), QT_TRANSLATE_NOOP("KStandardActions", "Redo last undone action"), u"edit-redo" },
{ Cut, KStandardShortcut::Cut, u"edit_cut", QT_TRANSLATE_NOOP("KStandardActions", "Cu&t"), QT_TRANSLATE_NOOP("KStandardActions", "Cut selection to clipboard"), u"edit-cut" },
{ Copy, KStandardShortcut::Copy, u"edit_copy", QT_TRANSLATE_NOOP("KStandardActions", "&Copy"), QT_TRANSLATE_NOOP("KStandardActions", "Copy selection to clipboard"), u"edit-copy" },
{ Paste, KStandardShortcut::Paste, u"edit_paste", QT_TRANSLATE_NOOP("KStandardActions", "&Paste"), QT_TRANSLATE_NOOP("KStandardActions", "Paste clipboard content"), u"edit-paste" },
{ Clear, KStandardShortcut::Clear, u"edit_clear", QT_TRANSLATE_NOOP("KStandardActions", "C&lear"), {}, u"edit-clear" },
{ SelectAll, KStandardShortcut::SelectAll, u"edit_select_all", QT_TRANSLATE_NOOP("KStandardActions", "Select &All"), {}, u"edit-select-all" },
{ Deselect, KStandardShortcut::Deselect, u"edit_deselect", QT_TRANSLATE_NOOP("KStandardActions", "Dese&lect"), {}, u"edit-select-none" },
{ Find, KStandardShortcut::Find, u"edit_find", QT_TRANSLATE_NOOP("KStandardActions", "&Find…"), {}, u"edit-find" },
{ FindNext, KStandardShortcut::FindNext, u"edit_find_next", QT_TRANSLATE_NOOP("KStandardActions", "Find &Next"), {}, u"go-down-search" },
{ FindPrev, KStandardShortcut::FindPrev, u"edit_find_prev", QT_TRANSLATE_NOOP("KStandardActions", "Find Pre&vious"), {}, u"go-up-search" },
{ Replace, KStandardShortcut::Replace, u"edit_replace", QT_TRANSLATE_NOOP("KStandardActions", "&Replace…"), {}, u"edit-find-replace" },
{ ActualSize, KStandardShortcut::ActualSize, u"view_actual_size", QT_TRANSLATE_NOOP("KStandardActions", "Zoom to &Actual Size"), QT_TRANSLATE_NOOP("KStandardActions", "View document at its actual size"), u"zoom-original" },
{ FitToPage, KStandardShortcut::FitToPage, u"view_fit_to_page", QT_TRANSLATE_NOOP("KStandardActions", "&Fit to Page"), QT_TRANSLATE_NOOP("KStandardActions", "Zoom to fit page in window"), u"zoom-fit-page" },
{ FitToWidth, KStandardShortcut::FitToWidth, u"view_fit_to_width", QT_TRANSLATE_NOOP("KStandardActions", "Fit to Page &Width"), QT_TRANSLATE_NOOP("KStandardActions", "Zoom to fit page width in window"), u"zoom-fit-width" },
{ FitToHeight, KStandardShortcut::FitToHeight, u"view_fit_to_height", QT_TRANSLATE_NOOP("KStandardActions", "Fit to Page &Height"), QT_TRANSLATE_NOOP("KStandardActions", "Zoom to fit page height in window"), u"zoom-fit-height" },
{ ZoomIn, KStandardShortcut::ZoomIn, u"view_zoom_in", QT_TRANSLATE_NOOP("KStandardActions", "Zoom &In"), {}, u"zoom-in" },
{ ZoomOut, KStandardShortcut::ZoomOut, u"view_zoom_out", QT_TRANSLATE_NOOP("KStandardActions", "Zoom &Out"), {}, u"zoom-out" },
{ Zoom, KStandardShortcut::Zoom, u"view_zoom", QT_TRANSLATE_NOOP("KStandardActions", "&Zoom…"), QT_TRANSLATE_NOOP("KStandardActions", "Select zoom level"), u"zoom" },
{ Redisplay, KStandardShortcut::Reload, u"view_redisplay", QT_TRANSLATE_NOOP("KStandardActions", "&Refresh"), QT_TRANSLATE_NOOP("KStandardActions", "Refresh document"), u"view-refresh" },
{ Up, KStandardShortcut::Up, u"go_up", QT_TRANSLATE_NOOP("KStandardActions", "&Up"), QT_TRANSLATE_NOOP("KStandardActions", "Go up"), u"go-up" },
// The following three have special i18n() needs for sLabel
{ Back, KStandardShortcut::Back, u"go_back", {}, {}, u"go-previous" },
{ Forward, KStandardShortcut::Forward, u"go_forward", {}, {}, u"go-next" },
{ Home, KStandardShortcut::Home, u"go_home", {}, {}, u"go-home" },
{ Prior, KStandardShortcut::Prior, u"go_previous", QT_TRANSLATE_NOOP("KStandardActions", "&Previous Page"), QT_TRANSLATE_NOOP("KStandardActions", "Go to previous page"), u"go-previous-view-page" },
{ Next, KStandardShortcut::Next, u"go_next", QT_TRANSLATE_NOOP("KStandardActions", "&Next Page"), QT_TRANSLATE_NOOP("KStandardActions", "Go to next page"), u"go-next-view-page" },
{ Goto, KStandardShortcut::Goto, u"go_goto", QT_TRANSLATE_NOOP("KStandardActions", "&Go To…"), {}, {} },
{ GotoPage, KStandardShortcut::GotoPage, u"go_goto_page", QT_TRANSLATE_NOOP("KStandardActions", "&Go to Page…"), {}, u"go-jump" },
{ GotoLine, KStandardShortcut::GotoLine, u"go_goto_line", QT_TRANSLATE_NOOP("KStandardActions", "&Go to Line…"), {}, {} },
{ FirstPage, KStandardShortcut::Begin, u"go_first", QT_TRANSLATE_NOOP("KStandardActions", "&First Page"), QT_TRANSLATE_NOOP("KStandardActions", "Go to first page"), u"go-first-view-page" },
{ LastPage, KStandardShortcut::End, u"go_last", QT_TRANSLATE_NOOP("KStandardActions", "&Last Page"), QT_TRANSLATE_NOOP("KStandardActions", "Go to last page"), u"go-last-view-page" },
{ DocumentBack, KStandardShortcut::DocumentBack, u"go_document_back", QT_TRANSLATE_NOOP("KStandardActions", "&Back"), QT_TRANSLATE_NOOP("KStandardActions", "Go back in document"), u"go-previous" },
{ DocumentForward, KStandardShortcut::DocumentForward, u"go_document_forward", QT_TRANSLATE_NOOP("KStandardActions", "&Forward"), QT_TRANSLATE_NOOP("KStandardActions", "Go forward in document"), u"go-next" },
{ AddBookmark, KStandardShortcut::AddBookmark, u"bookmark_add", QT_TRANSLATE_NOOP("KStandardActions", "&Add Bookmark"), {}, u"bookmark-new" },
{ EditBookmarks, KStandardShortcut::EditBookmarks, u"bookmark_edit", QT_TRANSLATE_NOOP("KStandardActions", "&Edit Bookmarks…"), {}, u"bookmarks-organize" },
{ Spelling, KStandardShortcut::Spelling, u"tools_spelling", QT_TRANSLATE_NOOP("KStandardActions", "&Spelling…"), QT_TRANSLATE_NOOP("KStandardActions", "Check spelling in document"), u"tools-check-spelling" },
{ ShowMenubar, KStandardShortcut::ShowMenubar, u"options_show_menubar", QT_TRANSLATE_NOOP("KStandardActions", "Show &Menubar"), QT_TRANSLATE_NOOP("KStandardActions", "Show or hide menubar"), u"show-menu" },
{ ShowToolbar, KStandardShortcut::ShowToolbar, u"options_show_toolbar", QT_TRANSLATE_NOOP("KStandardActions", "Show &Toolbar"), QT_TRANSLATE_NOOP("KStandardActions", "Show or hide toolbar"), {} },
{ ShowStatusbar, KStandardShortcut::ShowStatusbar, u"options_show_statusbar", QT_TRANSLATE_NOOP("KStandardActions", "Show St&atusbar"), QT_TRANSLATE_NOOP("KStandardActions", "Show or hide statusbar"), {} },
{ FullScreen, KStandardShortcut::FullScreen, u"fullscreen", QT_TRANSLATE_NOOP("KStandardActions", "F&ull Screen Mode"), {}, u"view-fullscreen" },
{ KeyBindings, KStandardShortcut::KeyBindings, u"options_configure_keybinding", QT_TRANSLATE_NOOP("KStandardActions", "Configure Keyboard S&hortcuts…"), {}, u"configure-shortcuts" },
{ Preferences, KStandardShortcut::Preferences, u"options_configure", QT_TRANSLATE_NOOP("KStandardActions", "&Configure %1…"), {}, u"configure" },
{ ConfigureToolbars, KStandardShortcut::ConfigureToolbars, u"options_configure_toolbars", QT_TRANSLATE_NOOP("KStandardActions", "Configure Tool&bars…"), {}, u"configure-toolbars" },
{ ConfigureNotifications, KStandardShortcut::ConfigureNotifications, u"options_configure_notifications", QT_TRANSLATE_NOOP("KStandardActions", "Configure &Notifications…"), {}, u"preferences-desktop-notification" },
// the idea here is that Contents is used in menus, and Help in dialogs, so both share the same
// shortcut
{ HelpContents, KStandardShortcut::Help, u"help_contents", QT_TRANSLATE_NOOP("KStandardActions", "%1 &Handbook"), {}, u"help-contents" },
{ WhatsThis, KStandardShortcut::WhatsThis, u"help_whats_this", QT_TRANSLATE_NOOP("KStandardActions", "What's &This?"), {}, u"help-contextual" },
{ ReportBug, KStandardShortcut::ReportBug, u"help_report_bug", QT_TRANSLATE_NOOP("KStandardActions", "&Report Bug…"), {}, u"tools-report-bug" },
{ SwitchApplicationLanguage, KStandardShortcut::SwitchApplicationLanguage, u"switch_application_language", QT_TRANSLATE_NOOP("KStandardActions", "Configure &Language…"), {}, u"preferences-desktop-locale" },
{ AboutApp, KStandardShortcut::AccelNone, u"help_about_app", QT_TRANSLATE_NOOP("KStandardActions", "&About %1"), {}, nullptr },
{ AboutKDE, KStandardShortcut::AccelNone, u"help_about_kde", QT_TRANSLATE_NOOP("KStandardActions", "About &KDE"), {}, u"kde" },
{ DeleteFile, KStandardShortcut::DeleteFile, u"deletefile", QT_TRANSLATE_NOOP("KStandardActions", "&Delete"), {}, u"edit-delete" },
{ RenameFile, KStandardShortcut::RenameFile, u"renamefile", QT_TRANSLATE_NOOP("KStandardActions", "&Rename…"), {}, u"edit-rename" },
{ MoveToTrash, KStandardShortcut::MoveToTrash, u"movetotrash", QT_TRANSLATE_NOOP("KStandardActions", "&Move to Trash"), {}, u"trash-empty" },
{ Donate, KStandardShortcut::Donate, u"help_donate", QT_TRANSLATE_NOOP("KStandardActions", "&Donate"), {}, u"help-donate"},
{ HamburgerMenu, KStandardShortcut::OpenMainMenu, u"hamburger_menu", QT_TRANSLATE_NOOP("KStandardActions", "Open &Menu"), {}, u"application-menu" },
};
// clang-format on
/**
* @internal
*/
inline const KStandardActionsInfo *infoPtr(StandardAction id)
{
for (const auto &action : g_rgActionInfo) {
if (action.id == id) {
return &action;
}
}
return nullptr;
}
/**
* @internal
*/
static inline QStringList internal_stdNames()
{
QStringList result;
for (const auto &action : g_rgActionInfo) {
if (!QCoreApplication::translate("KStandardActions", action.psLabel).isEmpty()) {
if (QByteArrayView(action.psLabel).contains("%1"))
// Prevents KLocalizedString::toString() from complaining about unsubstituted placeholder.
{
result.append(QCoreApplication::translate("KStandardActions", action.psLabel).arg(QString()));
} else {
result.append(QCoreApplication::translate("KStandardActions", action.psLabel));
}
}
}
return result;
}
}
@@ -0,0 +1,877 @@
/*
This file is part of the KDE libraries
SPDX-FileCopyrightText: 1997 Stefan Taferner <taferner@alpin.or.at>
SPDX-FileCopyrightText: 2000 Nicolas Hadacek <haadcek@kde.org>
SPDX-FileCopyrightText: 2001, 2002 Ellis Whitehead <ellis@kde.org>
SPDX-License-Identifier: LGPL-2.0-or-later
*/
#include "kstandardshortcut.h"
#include "kstandardshortcutwatcher.h"
#include "kconfig.h"
#include "kconfigwatcher.h"
#include "ksharedconfig.h"
#include <kconfiggroup.h>
#include <QCoreApplication>
#include <QDebug>
#include <QKeySequence>
namespace KStandardShortcut
{
struct KStandardShortcutInfo {
//! The standard shortcut id. @see StandardShortcut
StandardShortcut id;
/**
* Unique name for the given accel. The name is used to save the user
* settings. It's not representable. Use description for that.
* @warning NEVER EVER CHANGE IT OR TRANSLATE IT!
*/
const char *name;
//! Localized label for user-visible display, including translation context.
struct {
const char *text;
const char *context;
} description;
//! The keys for this shortcut
int cutDefault, cutDefault2;
//! A shortcut that is created with @a cutDefault and @cutDefault2
QList<QKeySequence> cut;
//! If this struct is initialized. If not initialized @cut is not valid
bool isInitialized;
// Category of this Shortcut
Category category;
};
#define CTRL(x) QKeyCombination(Qt::CTRL | Qt::Key_##x).toCombined()
#define SHIFT(x) QKeyCombination(Qt::SHIFT | Qt::Key_##x).toCombined()
#define CTRLALT(x) QKeyCombination(Qt::CTRL | Qt::ALT | Qt::Key_##x).toCombined()
#define CTRLSHIFT(x) QKeyCombination(Qt::CTRL | Qt::SHIFT | Qt::Key_##x).toCombined()
#define ALT(x) QKeyCombination(Qt::ALT | Qt::Key_##x).toCombined()
#define ALTSHIFT(x) QKeyCombination(Qt::ALT | Qt::SHIFT | Qt::Key_##x).toCombined()
#define CTRLMETA(x) QKeyCombination(Qt::CTRL | Qt::META | Qt::Key_##x).toCombined()
/** Array of predefined KStandardShortcutInfo objects, which cover all
the "standard" accelerators. Each enum value from StandardShortcut
should appear in this table.
*/
// STUFF WILL BREAK IF YOU DON'T READ THIS!!!
// Read the comments of the big enum in kstandardshortcut.h before you change anything!
static KStandardShortcutInfo g_infoStandardShortcut[] = {
// Group File,
{AccelNone, nullptr, {nullptr, nullptr}, 0, 0, QList<QKeySequence>(), false, Category::InvalidCategory},
{Open, "Open", QT_TRANSLATE_NOOP3("KStandardShortcut", "Open", "@action"), CTRL(O), 0, QList<QKeySequence>(), false, Category::File},
{New, "New", QT_TRANSLATE_NOOP3("KStandardShortcut", "New", "@action"), CTRL(N), 0, QList<QKeySequence>(), false, Category::File},
{Close, "Close", QT_TRANSLATE_NOOP3("KStandardShortcut", "Close", "@action"), CTRL(W), CTRL(Escape), QList<QKeySequence>(), false, Category::File},
{Save, "Save", QT_TRANSLATE_NOOP3("KStandardShortcut", "Save", "@action"), CTRL(S), 0, QList<QKeySequence>(), false, Category::File},
{Print, "Print", QT_TRANSLATE_NOOP3("KStandardShortcut", "Print", "@action"), CTRL(P), 0, QList<QKeySequence>(), false, Category::File},
{Quit, "Quit", QT_TRANSLATE_NOOP3("KStandardShortcut", "Quit", "@action"), CTRL(Q), 0, QList<QKeySequence>(), false, Category::Navigation},
// Group Edit
{Undo, "Undo", QT_TRANSLATE_NOOP3("KStandardShortcut", "Undo", "@action"), CTRL(Z), 0, QList<QKeySequence>(), false, Category::Edit},
{Redo, "Redo", QT_TRANSLATE_NOOP3("KStandardShortcut", "Redo", "@action"), CTRLSHIFT(Z), 0, QList<QKeySequence>(), false, Category::Edit},
// Both "Cut" and "Delete" use Shift+Delete, but this is okay; see
// https://commits.kde.org/kxmlgui/8eabbf6725386e716b7536c71a9181dfe5d959f0
{Cut, "Cut", QT_TRANSLATE_NOOP3("KStandardShortcut", "Cut", "@action"), CTRL(X), SHIFT(Delete), QList<QKeySequence>(), false, Category::Edit},
{Copy, "Copy", QT_TRANSLATE_NOOP3("KStandardShortcut", "Copy", "@action"), CTRL(C), CTRL(Insert), QList<QKeySequence>(), false, Category::Edit},
{Paste, "Paste", QT_TRANSLATE_NOOP3("KStandardShortcut", "Paste", "@action"), CTRL(V), SHIFT(Insert), QList<QKeySequence>(), false, Category::Edit},
{PasteSelection,
"Paste Selection",
QT_TRANSLATE_NOOP3("KStandardShortcut", "Paste Selection", "@action"),
CTRLSHIFT(Insert),
0,
QList<QKeySequence>(),
false,
Category::Edit},
{SelectAll, "SelectAll", QT_TRANSLATE_NOOP3("KStandardShortcut", "Select All", "@action"), CTRL(A), 0, QList<QKeySequence>(), false, Category::Edit},
{Deselect, "Deselect", QT_TRANSLATE_NOOP3("KStandardShortcut", "Deselect", "@action"), CTRLSHIFT(A), 0, QList<QKeySequence>(), false, Category::Edit},
{DeleteWordBack,
"DeleteWordBack",
QT_TRANSLATE_NOOP3("KStandardShortcut", "Delete Word Backwards", "@action"),
#if defined(Q_OS_MACOS)
ALT(Backspace),
#else
CTRL(Backspace),
#endif
0,
QList<QKeySequence>(),
false,
Category::Edit},
{DeleteWordForward,
"DeleteWordForward",
QT_TRANSLATE_NOOP3("KStandardShortcut", "Delete Word Forward", "@action"),
#if defined(Q_OS_MACOS)
ALT(Delete),
#else
CTRL(Delete),
#endif
0,
QList<QKeySequence>(),
false,
Category::Edit},
{Find, "Find", QT_TRANSLATE_NOOP3("KStandardShortcut", "Find", "@action"), CTRL(F), 0, QList<QKeySequence>(), false, Category::Edit},
{FindNext, "FindNext", QT_TRANSLATE_NOOP3("KStandardShortcut", "Find Next", "@action"), Qt::Key_F3, 0, QList<QKeySequence>(), false, Category::Edit},
{FindPrev, "FindPrev", QT_TRANSLATE_NOOP3("KStandardShortcut", "Find Prev", "@action"), SHIFT(F3), 0, QList<QKeySequence>(), false, Category::Edit},
{Replace, "Replace", QT_TRANSLATE_NOOP3("KStandardShortcut", "Replace", "@action"), CTRL(R), 0, QList<QKeySequence>(), false, Category::Edit},
// Group Navigation
{Home,
"Home",
QT_TRANSLATE_NOOP3("KStandardShortcut", "Home", "@action Go to main page"),
ALT(Home),
Qt::Key_HomePage,
QList<QKeySequence>(),
false,
Category::Navigation},
{Begin,
"Begin",
QT_TRANSLATE_NOOP3("KStandardShortcut", "Begin", "@action Beginning of document"),
#if defined(Q_OS_MACOS)
CTRL(Up),
#else
CTRL(Home),
#endif
0,
QList<QKeySequence>(),
false,
Category::Navigation},
{End,
"End",
QT_TRANSLATE_NOOP3("KStandardShortcut", "End", "@action End of document"),
#if defined(Q_OS_MACOS)
CTRL(Down),
#else
CTRL(End),
#endif
0,
QList<QKeySequence>(),
false,
Category::Navigation},
{Prior, "Prior", QT_TRANSLATE_NOOP3("KStandardShortcut", "Prior", "@action"), Qt::Key_PageUp, 0, QList<QKeySequence>(), false, Category::Navigation},
{Next,
"Next",
QT_TRANSLATE_NOOP3("KStandardShortcut", "Next", "@action Opposite to Prior"),
Qt::Key_PageDown,
0,
QList<QKeySequence>(),
false,
Category::Navigation},
{Up, "Up", QT_TRANSLATE_NOOP3("KStandardShortcut", "Up", "@action"), ALT(Up), 0, QList<QKeySequence>(), false, Category::Navigation},
{Back, "Back", QT_TRANSLATE_NOOP3("KStandardShortcut", "Back", "@action"), ALT(Left), Qt::Key_Back, QList<QKeySequence>(), false, Category::Navigation},
{Forward,
"Forward",
QT_TRANSLATE_NOOP3("KStandardShortcut", "Forward", "@action"),
ALT(Right),
Qt::Key_Forward,
QList<QKeySequence>(),
false,
Category::Navigation},
{Reload,
"Reload",
QT_TRANSLATE_NOOP3("KStandardShortcut", "Reload", "@action"),
Qt::Key_F5,
Qt::Key_Refresh,
QList<QKeySequence>(),
false,
Category::Navigation},
{BeginningOfLine,
"BeginningOfLine",
QT_TRANSLATE_NOOP3("KStandardShortcut", "Beginning of Line", "@action"),
#if defined(Q_OS_MACOS)
CTRL(Left),
#else
Qt::Key_Home,
#endif
0,
QList<QKeySequence>(),
false,
Category::Navigation},
{EndOfLine,
"EndOfLine",
QT_TRANSLATE_NOOP3("KStandardShortcut", "End of Line", "@action"),
#if defined(Q_OS_MACOS)
CTRL(Right),
#else
Qt::Key_End,
#endif
0,
QList<QKeySequence>(),
false,
Category::Navigation},
{GotoLine, "GotoLine", QT_TRANSLATE_NOOP3("KStandardShortcut", "Go to Line", "@action"), CTRL(G), 0, QList<QKeySequence>(), false, Category::Navigation},
{BackwardWord,
"BackwardWord",
QT_TRANSLATE_NOOP3("KStandardShortcut", "Backward Word", "@action"),
#if defined(Q_OS_MACOS)
ALT(Left),
#else
CTRL(Left),
#endif
0,
QList<QKeySequence>(),
false,
Category::Navigation},
{ForwardWord,
"ForwardWord",
QT_TRANSLATE_NOOP3("KStandardShortcut", "Forward Word", "@action"),
#if defined(Q_OS_MACOS)
ALT(Right),
#else
CTRL(Right),
#endif
0,
QList<QKeySequence>(),
false,
Category::Navigation},
{AddBookmark,
"AddBookmark",
QT_TRANSLATE_NOOP3("KStandardShortcut", "Add Bookmark", "@action"),
CTRL(B),
0,
QList<QKeySequence>(),
false,
Category::Navigation},
{ZoomIn, "ZoomIn", QT_TRANSLATE_NOOP3("KStandardShortcut", "Zoom In", "@action"), CTRL(Plus), CTRL(Equal), QList<QKeySequence>(), false, Category::View},
{ZoomOut, "ZoomOut", QT_TRANSLATE_NOOP3("KStandardShortcut", "Zoom Out", "@action"), CTRL(Minus), 0, QList<QKeySequence>(), false, Category::View},
{FullScreen,
"FullScreen",
QT_TRANSLATE_NOOP3("KStandardShortcut", "Full Screen Mode", "@action"),
#if defined(Q_OS_MACOS)
CTRLMETA(F),
#else
CTRLSHIFT(F),
#endif
0,
QList<QKeySequence>(),
false,
Category::View},
{ShowMenubar, "ShowMenubar", QT_TRANSLATE_NOOP3("KStandardShortcut", "Show Menu Bar", "@action"), CTRL(M), 0, QList<QKeySequence>(), false, Category::View},
{TabNext,
"Activate Next Tab",
QT_TRANSLATE_NOOP3("KStandardShortcut", "Activate Next Tab", "@action"),
CTRL(PageDown),
CTRL(BracketRight),
QList<QKeySequence>(),
false,
Category::Navigation},
{TabPrev,
"Activate Previous Tab",
QT_TRANSLATE_NOOP3("KStandardShortcut", "Activate Previous Tab", "@action"),
CTRL(PageUp),
CTRL(BracketLeft),
QList<QKeySequence>(),
false,
Category::Navigation},
// Group Help
{Help, "Help", QT_TRANSLATE_NOOP3("KStandardShortcut", "Help", "@action"), Qt::Key_F1, 0, QList<QKeySequence>(), false, Category::Help},
{WhatsThis, "WhatsThis", QT_TRANSLATE_NOOP3("KStandardShortcut", "What's This", "@action"), SHIFT(F1), 0, QList<QKeySequence>(), false, Category::Help},
// Group TextCompletion
{TextCompletion,
"TextCompletion",
QT_TRANSLATE_NOOP3("KStandardShortcut", "Text Completion", "@action"),
CTRL(E),
0,
QList<QKeySequence>(),
false,
Category::Edit},
{PrevCompletion,
"PrevCompletion",
QT_TRANSLATE_NOOP3("KStandardShortcut", "Previous Completion Match", "@action"),
CTRL(Up),
0,
QList<QKeySequence>(),
false,
Category::Edit},
{NextCompletion,
"NextCompletion",
QT_TRANSLATE_NOOP3("KStandardShortcut", "Next Completion Match", "@action"),
CTRL(Down),
0,
QList<QKeySequence>(),
false,
Category::Edit},
{SubstringCompletion,
"SubstringCompletion",
QT_TRANSLATE_NOOP3("KStandardShortcut", "Substring Completion", "@action"),
CTRL(T),
0,
QList<QKeySequence>(),
false,
Category::Edit},
{RotateUp,
"RotateUp",
QT_TRANSLATE_NOOP3("KStandardShortcut", "Previous Item in List", "@action"),
Qt::Key_Up,
0,
QList<QKeySequence>(),
false,
Category::Navigation},
{RotateDown,
"RotateDown",
QT_TRANSLATE_NOOP3("KStandardShortcut", "Next Item in List", "@action"),
Qt::Key_Down,
0,
QList<QKeySequence>(),
false,
Category::Navigation},
{OpenRecent, "OpenRecent", QT_TRANSLATE_NOOP3("KStandardShortcut", "Open Recent", "@action"), 0, 0, QList<QKeySequence>(), false, Category::File},
{SaveAs, "SaveAs", QT_TRANSLATE_NOOP3("KStandardShortcut", "Save As", "@action"), CTRLSHIFT(S), 0, QList<QKeySequence>(), false, Category::File},
{Revert, "Revert", QT_TRANSLATE_NOOP3("KStandardShortcut", "Revert", "@action"), 0, 0, QList<QKeySequence>(), false, Category::Edit},
{PrintPreview, "PrintPreview", QT_TRANSLATE_NOOP3("KStandardShortcut", "Print Preview", "@action"), 0, 0, QList<QKeySequence>(), false, Category::File},
{Mail, "Mail", QT_TRANSLATE_NOOP3("KStandardShortcut", "Mail", "@action"), 0, 0, QList<QKeySequence>(), false, Category::Help},
{Clear, "Clear", QT_TRANSLATE_NOOP3("KStandardShortcut", "Clear", "@action"), 0, 0, QList<QKeySequence>(), false, Category::Edit},
{ActualSize,
"ActualSize",
QT_TRANSLATE_NOOP3("KStandardShortcut", "Zoom to Actual Size", "@action"),
CTRL(0),
0,
QList<QKeySequence>(),
false,
Category::View},
{FitToPage, "FitToPage", QT_TRANSLATE_NOOP3("KStandardShortcut", "Fit To Page", "@action"), 0, 0, QList<QKeySequence>(), false, Category::View},
{FitToWidth, "FitToWidth", QT_TRANSLATE_NOOP3("KStandardShortcut", "Fit To Width", "@action"), 0, 0, QList<QKeySequence>(), false, Category::View},
{FitToHeight, "FitToHeight", QT_TRANSLATE_NOOP3("KStandardShortcut", "Fit To Height", "@action"), 0, 0, QList<QKeySequence>(), false, Category::View},
{Zoom, "Zoom", QT_TRANSLATE_NOOP3("KStandardShortcut", "Zoom", "@action"), 0, 0, QList<QKeySequence>(), false, Category::View},
{Goto, "Goto", QT_TRANSLATE_NOOP3("KStandardShortcut", "Goto", "@action"), 0, 0, QList<QKeySequence>(), false, Category::Navigation},
{GotoPage, "GotoPage", QT_TRANSLATE_NOOP3("KStandardShortcut", "Goto Page", "@action"), 0, 0, QList<QKeySequence>(), false, Category::Navigation},
{DocumentBack,
"DocumentBack",
QT_TRANSLATE_NOOP3("KStandardShortcut", "Document Back", "@action"),
ALTSHIFT(Left),
0,
QList<QKeySequence>(),
false,
Category::Navigation},
{DocumentForward,
"DocumentForward",
QT_TRANSLATE_NOOP3("KStandardShortcut", "Document Forward", "@action"),
ALTSHIFT(Right),
0,
QList<QKeySequence>(),
false,
Category::Navigation},
{EditBookmarks,
"EditBookmarks",
QT_TRANSLATE_NOOP3("KStandardShortcut", "Edit Bookmarks", "@action"),
0,
0,
QList<QKeySequence>(),
false,
Category::Navigation},
{Spelling, "Spelling", QT_TRANSLATE_NOOP3("KStandardShortcut", "Spelling", "@action"), 0, 0, QList<QKeySequence>(), false, Category::Edit},
{ShowToolbar, "ShowToolbar", QT_TRANSLATE_NOOP3("KStandardShortcut", "Show Toolbar", "@action"), 0, 0, QList<QKeySequence>(), false, Category::View},
{ShowStatusbar, "ShowStatusbar", QT_TRANSLATE_NOOP3("KStandardShortcut", "Show Statusbar", "@action"), 0, 0, QList<QKeySequence>(), false, Category::View},
{KeyBindings,
"KeyBindings",
QT_TRANSLATE_NOOP3("KStandardShortcut", "Key Bindings", "@action"),
CTRLALT(Comma),
0,
QList<QKeySequence>(),
false,
Category::Settings},
{Preferences,
"Preferences",
QT_TRANSLATE_NOOP3("KStandardShortcut", "Configure Application", "@action"),
CTRLSHIFT(Comma),
0,
QList<QKeySequence>(),
false,
Category::Settings},
{ConfigureToolbars,
"ConfigureToolbars",
QT_TRANSLATE_NOOP3("KStandardShortcut", "Configure Toolbars", "@action"),
0,
0,
QList<QKeySequence>(),
false,
Category::Settings},
{ConfigureNotifications,
"ConfigureNotifications",
QT_TRANSLATE_NOOP3("KStandardShortcut", "Configure Notifications", "@action"),
0,
0,
QList<QKeySequence>(),
false,
Category::Settings},
{ReportBug, "ReportBug", QT_TRANSLATE_NOOP3("KStandardShortcut", "Report Bug", "@action"), 0, 0, QList<QKeySequence>(), false, Category::Help},
{SwitchApplicationLanguage,
"SwitchApplicationLanguage",
QT_TRANSLATE_NOOP3("KStandardShortcut", "Configure Language…", "@action"),
0,
0,
QList<QKeySequence>(),
false,
Category::Settings},
{AboutApp, "AboutApp", QT_TRANSLATE_NOOP3("KStandardShortcut", "About Application", "@action"), 0, 0, QList<QKeySequence>(), false, Category::Help},
{AboutKDE, "AboutKDE", QT_TRANSLATE_NOOP3("KStandardShortcut", "About KDE", "@action"), 0, 0, QList<QKeySequence>(), false, Category::Help},
// Both "Cut" and "Delete" use Shift+Delete, but this is okay; see
// https://commits.kde.org/kxmlgui/8eabbf6725386e716b7536c71a9181dfe5d959f0
{DeleteFile, "DeleteFile", QT_TRANSLATE_NOOP3("KStandardShortcut", "Delete", "@action"), SHIFT(Delete), 0, QList<QKeySequence>(), false, Category::File},
{RenameFile, "RenameFile", QT_TRANSLATE_NOOP3("KStandardShortcut", "Rename", "@action"), Qt::Key_F2, 0, QList<QKeySequence>(), false, Category::File},
{MoveToTrash,
"MoveToTrash",
QT_TRANSLATE_NOOP3("KStandardShortcut", "Move to Trash", "@action"),
Qt::Key_Delete,
0,
QList<QKeySequence>(),
false,
Category::File},
{Donate, "Donate", QT_TRANSLATE_NOOP3("KStandardShortcut", "Donate", "@action"), 0, 0, QList<QKeySequence>(), false, Category::Help},
{ShowHideHiddenFiles,
"ShowHideHiddenFiles",
QT_TRANSLATE_NOOP3("KStandardShortcut", "Show/Hide Hidden Files", "@action"),
CTRL(H),
ALT(Period),
QList<QKeySequence>(),
false,
Category::View},
{CreateFolder,
"CreateFolder",
QT_TRANSLATE_NOOP3("KStandardShortcut", "Create Folder", "@action"),
CTRLSHIFT(N),
0,
QList<QKeySequence>(),
false,
Category::File},
{OpenMainMenu,
"OpenMainMenu",
QT_TRANSLATE_NOOP3("KStandardShortcut", "Open Main Menu", "@action referring to the menu bar or a hamburger menu"),
Qt::Key_F10,
0,
QList<QKeySequence>(),
false,
Category::View},
{OpenContextMenu,
"OpenContextMenu",
QT_TRANSLATE_NOOP3("KStandardShortcut", "Open Context Menu", "@action"),
Qt::Key_Menu,
SHIFT(F10),
QList<QKeySequence>(),
false,
Category::View},
// dummy entry to catch simple off-by-one errors. Insert new entries before this line.
{AccelNone, nullptr, {nullptr, nullptr}, 0, 0, QList<QKeySequence>(), false, Category::InvalidCategory}};
/** Search for the KStandardShortcutInfo object associated with the given @p id.
Return a dummy entry with no name and an empty shortcut if @p id is invalid.
*/
static KStandardShortcutInfo *guardedStandardShortcutInfo(StandardShortcut id)
{
if (id >= static_cast<int>(sizeof(g_infoStandardShortcut) / sizeof(KStandardShortcutInfo)) || id < 0) {
qWarning() << "KStandardShortcut: id not found!";
return &g_infoStandardShortcut[AccelNone];
} else {
return &g_infoStandardShortcut[id];
}
}
// Sanitize the list for duplicates. For some reason some
// people have kdeglobals entries like
// Close=Ctrl+W; Ctrl+Esc; Ctrl+W; Ctrl+Esc;
// having the same shortcut more than once in the shortcut
// declaration is clearly bogus so fix it
static void sanitizeShortcutList(QList<QKeySequence> *list)
{
for (int i = 0; i < list->size(); ++i) {
const QKeySequence &ks = list->at(i);
int other = list->indexOf(ks, i + 1);
while (other != -1) {
list->removeAt(other);
other = list->indexOf(ks, other);
}
}
}
/** Initialize the accelerator @p id by checking if it is overridden
in the configuration file (and if it isn't, use the default).
On X11, if QApplication was initialized with GUI disabled,
the default will always be used.
*/
void initialize(StandardShortcut id)
{
KStandardShortcutInfo *info = guardedStandardShortcutInfo(id);
// All three are needed.
if (info->id != AccelNone) {
Q_ASSERT(info->description.text);
Q_ASSERT(info->description.context);
Q_ASSERT(info->name);
}
KConfigGroup cg(KSharedConfig::openConfig(), QStringLiteral("Shortcuts"));
if (cg.hasKey(info->name)) {
QString s = cg.readEntry(info->name);
if (s != QLatin1String("none")) {
info->cut = QKeySequence::listFromString(s);
sanitizeShortcutList(&info->cut);
} else {
info->cut = QList<QKeySequence>();
}
} else {
info->cut = hardcodedDefaultShortcut(id);
}
info->isInitialized = true;
}
void saveShortcut(StandardShortcut id, const QList<QKeySequence> &newShortcut)
{
KStandardShortcutInfo *info = guardedStandardShortcutInfo(id);
// If the action has no standard shortcut associated there is nothing to
// save
if (info->id == AccelNone) {
return;
}
KConfigGroup cg(KSharedConfig::openConfig(), QStringLiteral("Shortcuts"));
info->cut = newShortcut;
bool sameAsDefault = (newShortcut == hardcodedDefaultShortcut(id));
if (sameAsDefault) {
// If the shortcut is the equal to the hardcoded one we remove it from
// kdeglobal if necessary and return.
if (cg.hasKey(info->name)) {
cg.deleteEntry(info->name, KConfig::Global | KConfig::Persistent | KConfig::Notify);
cg.sync();
}
return;
}
// Write the changed shortcut to kdeglobals
sanitizeShortcutList(&info->cut);
cg.writeEntry(info->name, QKeySequence::listToString(info->cut), KConfig::Global | KConfig::Persistent | KConfig::Notify);
cg.sync();
}
QString name(StandardShortcut id)
{
return QString::fromLatin1(guardedStandardShortcutInfo(id)->name);
}
QString label(StandardShortcut id)
{
KStandardShortcutInfo *info = guardedStandardShortcutInfo(id);
return QCoreApplication::translate("KStandardShortcut", info->description.text, info->description.context);
}
// TODO: Add psWhatsThis entry to KStandardShortcutInfo
QString whatsThis(StandardShortcut /*id*/)
{
// KStandardShortcutInfo* info = guardedStandardShortcutInfo( id );
// if( info && info->whatsThis )
// return i18n(info->whatsThis);
// else
return QString();
}
const QList<QKeySequence> &shortcut(StandardShortcut id)
{
KStandardShortcutInfo *info = guardedStandardShortcutInfo(id);
if (!info->isInitialized) {
initialize(id);
}
return info->cut;
}
StandardShortcut find(const QKeySequence &seq)
{
if (!seq.isEmpty()) {
for (const KStandardShortcutInfo &shortcutInfo : g_infoStandardShortcut) {
const StandardShortcut id = shortcutInfo.id;
if (id != AccelNone) {
if (!shortcutInfo.isInitialized) {
initialize(id);
}
if (shortcutInfo.cut.contains(seq)) {
return id;
}
}
}
}
return AccelNone;
}
StandardShortcut findByName(const QString &name)
{
for (const KStandardShortcutInfo &shortcutInfo : g_infoStandardShortcut) {
if (QLatin1StringView(shortcutInfo.name) == name) {
return shortcutInfo.id;
}
}
return AccelNone;
}
QList<QKeySequence> hardcodedDefaultShortcut(StandardShortcut id)
{
QList<QKeySequence> cut;
KStandardShortcutInfo *info = guardedStandardShortcutInfo(id);
if (info->cutDefault != 0) {
cut << info->cutDefault;
}
if (info->cutDefault2 != 0) {
if (cut.isEmpty()) {
cut << QKeySequence();
}
cut << info->cutDefault2;
}
return cut;
}
Category category(StandardShortcut id)
{
return guardedStandardShortcutInfo(id)->category;
}
const QList<QKeySequence> &open()
{
return shortcut(Open);
}
const QList<QKeySequence> &openNew()
{
return shortcut(New);
}
const QList<QKeySequence> &close()
{
return shortcut(Close);
}
const QList<QKeySequence> &save()
{
return shortcut(Save);
}
const QList<QKeySequence> &print()
{
return shortcut(Print);
}
const QList<QKeySequence> &quit()
{
return shortcut(Quit);
}
const QList<QKeySequence> &cut()
{
return shortcut(Cut);
}
const QList<QKeySequence> &copy()
{
return shortcut(Copy);
}
const QList<QKeySequence> &paste()
{
return shortcut(Paste);
}
const QList<QKeySequence> &pasteSelection()
{
return shortcut(PasteSelection);
}
const QList<QKeySequence> &deleteWordBack()
{
return shortcut(DeleteWordBack);
}
const QList<QKeySequence> &deleteWordForward()
{
return shortcut(DeleteWordForward);
}
const QList<QKeySequence> &undo()
{
return shortcut(Undo);
}
const QList<QKeySequence> &redo()
{
return shortcut(Redo);
}
const QList<QKeySequence> &find()
{
return shortcut(Find);
}
const QList<QKeySequence> &findNext()
{
return shortcut(FindNext);
}
const QList<QKeySequence> &findPrev()
{
return shortcut(FindPrev);
}
const QList<QKeySequence> &replace()
{
return shortcut(Replace);
}
const QList<QKeySequence> &home()
{
return shortcut(Home);
}
const QList<QKeySequence> &begin()
{
return shortcut(Begin);
}
const QList<QKeySequence> &end()
{
return shortcut(End);
}
const QList<QKeySequence> &beginningOfLine()
{
return shortcut(BeginningOfLine);
}
const QList<QKeySequence> &endOfLine()
{
return shortcut(EndOfLine);
}
const QList<QKeySequence> &prior()
{
return shortcut(Prior);
}
const QList<QKeySequence> &next()
{
return shortcut(Next);
}
const QList<QKeySequence> &backwardWord()
{
return shortcut(BackwardWord);
}
const QList<QKeySequence> &forwardWord()
{
return shortcut(ForwardWord);
}
const QList<QKeySequence> &gotoLine()
{
return shortcut(GotoLine);
}
const QList<QKeySequence> &addBookmark()
{
return shortcut(AddBookmark);
}
const QList<QKeySequence> &tabNext()
{
return shortcut(TabNext);
}
const QList<QKeySequence> &tabPrev()
{
return shortcut(TabPrev);
}
const QList<QKeySequence> &fullScreen()
{
return shortcut(FullScreen);
}
const QList<QKeySequence> &zoomIn()
{
return shortcut(ZoomIn);
}
const QList<QKeySequence> &zoomOut()
{
return shortcut(ZoomOut);
}
const QList<QKeySequence> &help()
{
return shortcut(Help);
}
const QList<QKeySequence> &completion()
{
return shortcut(TextCompletion);
}
const QList<QKeySequence> &prevCompletion()
{
return shortcut(PrevCompletion);
}
const QList<QKeySequence> &nextCompletion()
{
return shortcut(NextCompletion);
}
const QList<QKeySequence> &rotateUp()
{
return shortcut(RotateUp);
}
const QList<QKeySequence> &rotateDown()
{
return shortcut(RotateDown);
}
const QList<QKeySequence> &substringCompletion()
{
return shortcut(SubstringCompletion);
}
const QList<QKeySequence> &whatsThis()
{
return shortcut(WhatsThis);
}
const QList<QKeySequence> &reload()
{
return shortcut(Reload);
}
const QList<QKeySequence> &selectAll()
{
return shortcut(SelectAll);
}
const QList<QKeySequence> &up()
{
return shortcut(Up);
}
const QList<QKeySequence> &back()
{
return shortcut(Back);
}
const QList<QKeySequence> &forward()
{
return shortcut(Forward);
}
const QList<QKeySequence> &showMenubar()
{
return shortcut(ShowMenubar);
}
const QList<QKeySequence> &deleteFile()
{
return shortcut(DeleteFile);
}
const QList<QKeySequence> &renameFile()
{
return shortcut(RenameFile);
}
const QList<QKeySequence> &createFolder()
{
return shortcut(CreateFolder);
}
const QList<QKeySequence> &moveToTrash()
{
return shortcut(MoveToTrash);
}
const QList<QKeySequence> &preferences()
{
return shortcut(Preferences);
}
const QList<QKeySequence> &showHideHiddenFiles()
{
return shortcut(ShowHideHiddenFiles);
}
const QList<QKeySequence> &openMainMenu()
{
return shortcut(OpenMainMenu);
}
const QList<QKeySequence> &openContextMenu()
{
return shortcut(OpenContextMenu);
}
}
@@ -0,0 +1,578 @@
/*
This file is part of the KDE libraries
SPDX-FileCopyrightText: 1997 Stefan Taferner <taferner@kde.org>
SPDX-FileCopyrightText: 2000 Nicolas Hadacek <hadacek@kde.org>
SPDX-FileCopyrightText: 2001, 2002 Ellis Whitehead <ellis@kde.org>
SPDX-License-Identifier: LGPL-2.0-or-later
*/
#ifndef KSTANDARDSHORTCUT_H
#define KSTANDARDSHORTCUT_H
#include <QKeySequence>
#include <QString>
#include <kconfiggui_export.h>
/**
* \namespace KStandardShortcut
* Convenient methods for access to the common accelerator keys in
* the key configuration. These are the standard keybindings that should
* be used in all KDE applications. They will be configurable,
* so do not hardcode the default behavior.
*/
namespace KStandardShortcut
{
// STUFF WILL BREAK IF YOU DON'T READ THIS!!!
/*
*Always add new std-accels to the end of this enum, never in the middle!
*Don't forget to add the corresponding entries in g_infoStandardShortcut[] in kstandardshortcut.cpp, too.
*Values of elements here and positions of the corresponding entries in
*the big array g_infoStandardShortcut[] ABSOLUTELY MUST BE THE SAME.
* !!! !!!! !!!!! !!!!
* !!!! !!! !!!! !!!!
*
* Other Rules:
*
* - Never change the name of an existing shortcut
* - Never translate the name of a shortcut
*/
/**
* Defines the identifier of all standard accelerators.
*/
enum StandardShortcut {
// C++ requires that the value of an enum symbol be one more than the previous one.
// This means that everything will be well-ordered from here on.
AccelNone = 0,
// File menu
Open, ///< Open file.
New, ///< Create a new document.
Close, ///< Close current document.
Save, ///< Save current document.
// The Print item
Print, ///< Print current document.
Quit, ///< Quit the program.
// Edit menu
Undo, ///< Undo last operation.
Redo, ///< Redo last operation.
Cut, ///< Cut selected area and store it in the clipboard.
Copy, ///< Copy selected area into the clipboard.
Paste, ///< Paste contents of clipboard at mouse/cursor position.
PasteSelection, ///< Paste the selection at mouse/cursor position.
SelectAll, ///< Select all.
Deselect, ///< Deselect any selected elements.
DeleteWordBack, ///< Delete a word back from mouse/cursor position.
DeleteWordForward, ///< Delete a word forward from mouse/cursor position.
Find, ///< Initiate a 'find' request in the current document.
FindNext, ///< Find the next instance of a stored 'find'.
FindPrev, ///< Find a previous instance of a stored 'find'.
Replace, ///< Find and replace matches.
// Navigation
Home, ///< Go to home page.
Begin, ///< Go to beginning of the document.
End, ///< Go to end of the document.
Prior, ///< Scroll up one page.
Next, ///< Scroll down one page.
Up, ///< Up.
Back, ///< Back.
Forward, ///< Forward.
Reload, ///< Reload.
// Text Navigation
BeginningOfLine, ///< Go to beginning of current line.
EndOfLine, ///< Go to end of current line.
GotoLine, ///< Go to line.
BackwardWord, ///< BackwardWord.
ForwardWord, ///< ForwardWord.
// View parameters
AddBookmark, ///< Add current page to bookmarks.
ZoomIn, ///< Zoom in.
ZoomOut, ///< Zoom out.
FullScreen, ///< Full Screen mode.
ShowMenubar, ///< Show Menu Bar.
// Tabular navigation
TabNext, ///< Next Tab.
TabPrev, ///< Previous Tab.
// Help menu
Help, ///< Help the user in the current situation.
WhatsThis, ///< What's This button.
// Text completion
TextCompletion, ///< Complete text in input widgets.
PrevCompletion, ///< Iterate through a list when completion returns multiple items.
NextCompletion, ///< Iterate through a list when completion returns multiple items.
SubstringCompletion, ///< Find a string within another string or list of strings.
RotateUp, ///< Help users iterate through a list of entries.
RotateDown, ///< Help users iterate through a list of entries.
OpenRecent, ///< Open a recently used document.
SaveAs, ///< Save the current document under a different name.
Revert, ///< Revert the current document to the last saved version.
PrintPreview, ///< Show a print preview of the current document.
Mail, ///< Send the current document by mail.
Clear, ///< Clear the content of the focus widget.
ActualSize, ///< View the document at its actual size.
FitToPage, ///< Fit the document view to the size of the current window.
FitToWidth, ///< Fit the document view to the width of the current window.
FitToHeight, ///< Fit the document view to the height of the current window.
Zoom, ///< Select the current zoom level.
Goto, ///< Jump to some specific location in the document.
GotoPage, ///< Go to a specific page.
DocumentBack, ///< Move back (document style menu).
DocumentForward, ///< Move forward (document style menu).
EditBookmarks, ///< Edit the application bookmarks.
Spelling, ///< Pop up the spell checker.
ShowToolbar, ///< Show/Hide the toolbar.
ShowStatusbar, ///< Show/Hide the statusbar.
KeyBindings, ///< Display the configure key bindings dialog.
Preferences, ///< Display the preferences/options dialog.
ConfigureToolbars, ///< Display the toolbar configuration dialog.
ConfigureNotifications, ///< Display the notifications configuration dialog.
ReportBug, ///< Display the Report Bug dialog.
SwitchApplicationLanguage, ///< Display the Switch Application Language dialog.
AboutApp, ///< Display the application's About dialog.
AboutKDE, ///< Display the About KDE dialog.
DeleteFile, ///< Permanently delete files or folders. @since 5.25
RenameFile, ///< Rename files or folders. @since 5.25
MoveToTrash, ///< Move files or folders to the trash. @since 5.25
Donate, ///< Open donation page on kde.org. @since 5.26
ShowHideHiddenFiles, ///< Toggle showing or hiding hidden files @since 5.70
CreateFolder, ///< Create a folder. @since 5.74
OpenMainMenu, ///< Open a main menu like the menu bar or a hamburger menu. Necessary for accessibility. @since 6.0
OpenContextMenu, ///< Open a context menu for the object with keyboard focus. Necessary for accessibility. @since 6.0
// Insert new items here!
StandardShortcutCount, // number of standard shortcuts
};
/**
* Categories in which the standard shortcuts can be classified
* @since 5.74
*/
enum class Category {
InvalidCategory = -1,
File,
Edit,
Navigation,
View,
Settings,
Help,
};
/**
* Returns the keybinding for @p accel.
* On X11, if QApplication was initialized with GUI disabled, the
* default keybinding will always be returned.
* @param id the id of the accelerator
*/
KCONFIGGUI_EXPORT const QList<QKeySequence> &shortcut(StandardShortcut id);
/**
* Returns a unique name for the given accel.
* @param id the id of the accelerator
* @return the unique name of the accelerator
*/
KCONFIGGUI_EXPORT QString name(StandardShortcut id);
/**
* Returns a localized label for user-visible display.
* @param id the id of the accelerator
* @return a localized label for the accelerator
*/
KCONFIGGUI_EXPORT QString label(StandardShortcut id);
/**
* Returns an extended WhatsThis description for the given accelerator.
* @param id the id of the accelerator
* @return a localized description of the accelerator
*/
KCONFIGGUI_EXPORT QString whatsThis(StandardShortcut id);
/**
* Return the StandardShortcut id of the standard accel action which
* uses this key sequence, or AccelNone if none of them do.
* This is used by class KKeyChooser.
* @param keySeq the key sequence to search
* @return the id of the standard accelerator, or AccelNone if there
* is none
*/
KCONFIGGUI_EXPORT StandardShortcut find(const QKeySequence &keySeq);
/**
* Return the StandardShortcut id of the standard accelerator action which
* has \p name as its name, or AccelNone if none of them do.
* @param name the name as returned by name(StandardShortcut id)
* @return the id of the standard accelerator with the given name or AccelNone
* if there is no such accelerator
* @since 5.71
*/
KCONFIGGUI_EXPORT StandardShortcut findByName(const QString &name);
/**
* Returns the hardcoded default shortcut for @p id.
* This does not take into account the user's configuration.
* @param id the id of the accelerator
* @return the default shortcut of the accelerator
*/
KCONFIGGUI_EXPORT QList<QKeySequence> hardcodedDefaultShortcut(StandardShortcut id);
/**
* Saves the new shortcut \a cut for standard accel \a id.
*/
KCONFIGGUI_EXPORT void saveShortcut(StandardShortcut id, const QList<QKeySequence> &newShortcut);
/**
* Returns the appropriate category for the given StandardShortcut \p id.
* @since 5.73
*/
KCONFIGGUI_EXPORT Category category(StandardShortcut id);
/**
* Open file. Default: Ctrl-o
* @return the shortcut of the standard accelerator
*/
KCONFIGGUI_EXPORT const QList<QKeySequence> &open();
/**
* Create a new document (or whatever). Default: Ctrl-n
* @return the shortcut of the standard accelerator
*/
KCONFIGGUI_EXPORT const QList<QKeySequence> &openNew();
/**
* Close current document. Default: Ctrl-w
* @return the shortcut of the standard accelerator
*/
KCONFIGGUI_EXPORT const QList<QKeySequence> &close();
/**
* Save current document. Default: Ctrl-s
* @return the shortcut of the standard accelerator
*/
KCONFIGGUI_EXPORT const QList<QKeySequence> &save();
/**
* Print current document. Default: Ctrl-p
* @return the shortcut of the standard accelerator
*/
KCONFIGGUI_EXPORT const QList<QKeySequence> &print();
/**
* Quit the program. Default: Ctrl-q
* @return the shortcut of the standard accelerator
*/
KCONFIGGUI_EXPORT const QList<QKeySequence> &quit();
/**
* Undo last operation. Default: Ctrl-z
* @return the shortcut of the standard accelerator
*/
KCONFIGGUI_EXPORT const QList<QKeySequence> &undo();
/**
* Redo last operation. Default: Shift-Ctrl-z
* @return the shortcut of the standard accelerator
*/
KCONFIGGUI_EXPORT const QList<QKeySequence> &redo();
/**
* Cut selected area and store it in the clipboard. Default: Ctrl-x
* @return the shortcut of the standard accelerator
*/
KCONFIGGUI_EXPORT const QList<QKeySequence> &cut();
/**
* Copy selected area into the clipboard. Default: Ctrl-c
* @return the shortcut of the standard accelerator
*/
KCONFIGGUI_EXPORT const QList<QKeySequence> &copy();
/**
* Paste contents of clipboard at mouse/cursor position. Default: Ctrl-v
* @return the shortcut of the standard accelerator
*/
KCONFIGGUI_EXPORT const QList<QKeySequence> &paste();
/**
* Paste the selection at mouse/cursor position. Default: Ctrl-Shift-Insert
* @return the shortcut of the standard accelerator
*/
KCONFIGGUI_EXPORT const QList<QKeySequence> &pasteSelection();
/**
* Select all. Default: Ctrl-A
* @return the shortcut of the standard accelerator
**/
KCONFIGGUI_EXPORT const QList<QKeySequence> &selectAll();
/**
* Delete a word back from mouse/cursor position. Default: Ctrl-Backspace
* @return the shortcut of the standard accelerator
*/
KCONFIGGUI_EXPORT const QList<QKeySequence> &deleteWordBack();
/**
* Delete a word forward from mouse/cursor position. Default: Ctrl-Delete
* @return the shortcut of the standard accelerator
*/
KCONFIGGUI_EXPORT const QList<QKeySequence> &deleteWordForward();
/**
* Initiate a 'find' request in the current document. Default: Ctrl-f
* @return the shortcut of the standard accelerator
*/
KCONFIGGUI_EXPORT const QList<QKeySequence> &find();
/**
* Find the next instance of a stored 'find' Default: F3
* @return the shortcut of the standard accelerator
*/
KCONFIGGUI_EXPORT const QList<QKeySequence> &findNext();
/**
* Find a previous instance of a stored 'find'. Default: Shift-F3
* @return the shortcut of the standard accelerator
*/
KCONFIGGUI_EXPORT const QList<QKeySequence> &findPrev();
/**
* Find and replace matches. Default: Ctrl-r
* @return the shortcut of the standard accelerator
*/
KCONFIGGUI_EXPORT const QList<QKeySequence> &replace();
/**
* Zoom in. Default: Ctrl-Plus
* @return the shortcut of the standard accelerator
*/
KCONFIGGUI_EXPORT const QList<QKeySequence> &zoomIn();
/**
* Zoom out. Default: Ctrl-Minus
* @return the shortcut of the standard accelerator
*/
KCONFIGGUI_EXPORT const QList<QKeySequence> &zoomOut();
/**
* Go to home page. Default: Alt-Home
* @return the shortcut of the standard accelerator
*/
KCONFIGGUI_EXPORT const QList<QKeySequence> &home();
/**
* Go to beginning of the document. Default: Ctrl-Home
* @return the shortcut of the standard accelerator
*/
KCONFIGGUI_EXPORT const QList<QKeySequence> &begin();
/**
* Go to end of the document. Default: Ctrl-End
* @return the shortcut of the standard accelerator
*/
KCONFIGGUI_EXPORT const QList<QKeySequence> &end();
/**
* Go to beginning of current line. Default: Home
* @return the shortcut of the standard accelerator
*/
KCONFIGGUI_EXPORT const QList<QKeySequence> &beginningOfLine();
/**
* Go to end of current line. Default: End
* @return the shortcut of the standard accelerator
*/
KCONFIGGUI_EXPORT const QList<QKeySequence> &endOfLine();
/**
* Scroll up one page. Default: Prior
* @return the shortcut of the standard accelerator
*/
KCONFIGGUI_EXPORT const QList<QKeySequence> &prior();
/**
* Scroll down one page. Default: Next
* @return the shortcut of the standard accelerator
*/
KCONFIGGUI_EXPORT const QList<QKeySequence> &next();
/**
* Go to line. Default: Ctrl+G
* @return the shortcut of the standard accelerator
*/
KCONFIGGUI_EXPORT const QList<QKeySequence> &gotoLine();
/**
* Add current page to bookmarks. Default: Ctrl+B
* @return the shortcut of the standard accelerator
*/
KCONFIGGUI_EXPORT const QList<QKeySequence> &addBookmark();
/**
* Next Tab. Default: Ctrl-<
* @return the shortcut of the standard accelerator
*/
KCONFIGGUI_EXPORT const QList<QKeySequence> &tabNext();
/**
* Previous Tab. Default: Ctrl->
* @return the shortcut of the standard accelerator
*/
KCONFIGGUI_EXPORT const QList<QKeySequence> &tabPrev();
/**
* Full Screen Mode. Default: Ctrl+Shift+F
* @return the shortcut of the standard accelerator
*/
KCONFIGGUI_EXPORT const QList<QKeySequence> &fullScreen();
/**
* Help the user in the current situation. Default: F1
* @return the shortcut of the standard accelerator
*/
KCONFIGGUI_EXPORT const QList<QKeySequence> &help();
/**
* Complete text in input widgets. Default Ctrl+E
* @return the shortcut of the standard accelerator
**/
KCONFIGGUI_EXPORT const QList<QKeySequence> &completion();
/**
* Iterate through a list when completion returns
* multiple items. Default: Ctrl+Up
* @return the shortcut of the standard accelerator
*/
KCONFIGGUI_EXPORT const QList<QKeySequence> &prevCompletion();
/**
* Iterate through a list when completion returns
* multiple items. Default: Ctrl+Down
* @return the shortcut of the standard accelerator
*/
KCONFIGGUI_EXPORT const QList<QKeySequence> &nextCompletion();
/**
* Find a string within another string or list of strings.
* Default: Ctrl-T
* @return the shortcut of the standard accelerator
*/
KCONFIGGUI_EXPORT const QList<QKeySequence> &substringCompletion();
/**
* Help users iterate through a list of entries. Default: Up
* @return the shortcut of the standard accelerator
*/
KCONFIGGUI_EXPORT const QList<QKeySequence> &rotateUp();
/**
* Help users iterate through a list of entries. Default: Down
* @return the shortcut of the standard accelerator
*/
KCONFIGGUI_EXPORT const QList<QKeySequence> &rotateDown();
/**
* What's This button. Default: Shift+F1
* @return the shortcut of the standard accelerator
*/
KCONFIGGUI_EXPORT const QList<QKeySequence> &whatsThis();
/**
* Reload. Default: F5
* @return the shortcut of the standard accelerator
*/
KCONFIGGUI_EXPORT const QList<QKeySequence> &reload();
/**
* Up. Default: Alt+Up
* @return the shortcut of the standard accelerator
*/
KCONFIGGUI_EXPORT const QList<QKeySequence> &up();
/**
* Back. Default: Alt+Left
* @return the shortcut of the standard accelerator
*/
KCONFIGGUI_EXPORT const QList<QKeySequence> &back();
/**
* Forward. Default: ALT+Right
* @return the shortcut of the standard accelerator
*/
KCONFIGGUI_EXPORT const QList<QKeySequence> &forward();
/**
* BackwardWord. Default: Ctrl+Left
* @return the shortcut of the standard accelerator
*/
KCONFIGGUI_EXPORT const QList<QKeySequence> &backwardWord();
/**
* ForwardWord. Default: Ctrl+Right
* @return the shortcut of the standard accelerator
*/
KCONFIGGUI_EXPORT const QList<QKeySequence> &forwardWord();
/**
* Show Menu Bar. Default: Ctrl-M
* @return the shortcut of the standard accelerator
*/
KCONFIGGUI_EXPORT const QList<QKeySequence> &showMenubar();
/**
* Permanently delete files or folders. Default: Shift+Delete
* @return the shortcut of the standard accelerator
* @since 5.25
*/
KCONFIGGUI_EXPORT const QList<QKeySequence> &deleteFile();
/**
* Rename files or folders. Default: F2
* @return the shortcut of the standard accelerator
* @since 5.25
*/
KCONFIGGUI_EXPORT const QList<QKeySequence> &renameFile();
/**
* Create a folder. Default: Ctrl+Shift+N
* @return the shortcut of the standard accelerator
* @since 5.74
*/
KCONFIGGUI_EXPORT const QList<QKeySequence> &createFolder();
/**
* Moves files or folders to the trash. Default: Delete
* @return the shortcut of the standard accelerator
* @since 5.25
*/
KCONFIGGUI_EXPORT const QList<QKeySequence> &moveToTrash();
/**
* Opens the app's settings window. Default: Ctrl+Shift+Comma
* @return the shortcut of the standard accelerator
* @since 5.64
*/
KCONFIGGUI_EXPORT const QList<QKeySequence> &preferences();
/**
* Shows or hides hidden files. Defaults: Ctrl+H, Alt+.
* @return the shortcut of the standard accelerator
* @since 5.70
*/
KCONFIGGUI_EXPORT const QList<QKeySequence> &showHideHiddenFiles();
/**
* Open a main menu like the menu bar or a hamburger menu.
* Necessary for accessibility. Default: F10
* @return the shortcut of the standard accelerator
* @since 6.0
*/
KCONFIGGUI_EXPORT const QList<QKeySequence> &openMainMenu();
/**
* Open a context menu for the object with keyboard focus.
* Necessary for accessibility. Default: Menu, Shift+F10
* @return the shortcut of the standard accelerator
* @since 6.0
*/
KCONFIGGUI_EXPORT const QList<QKeySequence> &openContextMenu();
}
#endif // KSTANDARDSHORTCUT_H
@@ -0,0 +1,20 @@
/*
This file is part of the KDE libraries
SPDX-FileCopyrightText: 1997 Stefan Taferner <taferner@alpin.or.at>
SPDX-FileCopyrightText: 2000 Nicolas Hadacek <haadcek@kde.org>
SPDX-FileCopyrightText: 2001, 2002 Ellis Whitehead <ellis@kde.org>
SPDX-License-Identifier: LGPL-2.0-or-later
*/
#ifndef KSTANDARDSHORTCUT_P_H
#define KSTANDARDSHORTCUT_P_H
#include "kstandardshortcut.h"
namespace KStandardShortcut
{
void initialize(StandardShortcut id);
}
#endif
@@ -0,0 +1,48 @@
/*
SPDX-FileCopyrightText: 2022 David Redondo <kde@david-redondo.de>
SPDX-License-Identifier: LGPL-2.0-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
*/
#include "kstandardshortcutwatcher.h"
#include "kconfigwatcher.h"
#include "kstandardshortcut_p.h"
namespace KStandardShortcut
{
class StandardShortcutWatcherPrivate
{
public:
KConfigWatcher::Ptr watcher = KConfigWatcher::create(KSharedConfig::openConfig());
};
StandardShortcutWatcher::StandardShortcutWatcher(QObject *parent)
: QObject(parent)
, d(std::make_unique<StandardShortcutWatcherPrivate>())
{
connect(d->watcher.get(), &KConfigWatcher::configChanged, this, [this](const KConfigGroup &group, const QByteArrayList &keys) {
if (group.name() != QStringLiteral("Shortcuts")) {
return;
}
for (const auto &key : keys) {
const StandardShortcut shortcut = KStandardShortcut::findByName(QString::fromUtf8(key));
if (shortcut != KStandardShortcut::AccelNone) {
initialize(shortcut);
Q_EMIT shortcutChanged(shortcut, KStandardShortcut::shortcut(shortcut));
}
}
});
}
StandardShortcutWatcher::~StandardShortcutWatcher() = default;
StandardShortcutWatcher *shortcutWatcher()
{
static StandardShortcutWatcher watcher;
return &watcher;
}
}
#include "moc_kstandardshortcutwatcher.cpp"
@@ -0,0 +1,55 @@
/*
SPDX-FileCopyrightText: 2022 David Redondo <kde@david-redondo.de>
SPDX-License-Identifier: LGPL-2.0-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
*/
#ifndef KSTANDARDSHORTCUTWATCHER_H
#define KSTANDARDSHORTCUTWATCHER_H
#include "kstandardshortcut.h"
#include <QObject>
#include <memory>
#include <kconfiggui_export.h>
namespace KStandardShortcut
{
class StandardShortcutWatcherPrivate;
/**
* Watches for changes made to standard shortcuts and notifies about those changes.
* @see KStandardShortcut::shortcutWatcher
* @since 5.91
*/
class KCONFIGGUI_EXPORT StandardShortcutWatcher : public QObject
{
Q_OBJECT
public:
~StandardShortcutWatcher();
Q_SIGNALS:
/**
* The standardshortcut @p id was changed to @p shortcut
*/
void shortcutChanged(KStandardShortcut::StandardShortcut id, const QList<QKeySequence> &shortcut);
private:
KCONFIGGUI_NO_EXPORT explicit StandardShortcutWatcher(QObject *parent = nullptr);
friend KCONFIGGUI_EXPORT StandardShortcutWatcher *shortcutWatcher();
std::unique_ptr<StandardShortcutWatcherPrivate> d;
};
/**
* Returns the global KStandardShortcutWatcher instance of this program.
* In addition to the notifying about changes it also keeps the information returned by the
* functions in @p KStandardShortcut up to date.
* The object is created by the first call to this function.
* @since 5.91
*/
KCONFIGGUI_EXPORT StandardShortcutWatcher *shortcutWatcher();
}
#endif
@@ -0,0 +1,242 @@
/*
This file is part of the KDE libraries
SPDX-FileCopyrightText: 2012 Benjamin Port <benjamin.port@ben2367.fr>
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
*/
#include "kwindowconfig.h"
#include "ksharedconfig.h"
#include <QGuiApplication>
#include <QScreen>
#include <QWindow>
static const char s_initialSizePropertyName[] = "_kconfig_initial_size";
static const char s_initialScreenSizePropertyName[] = "_kconfig_initial_screen_size";
// Convenience function to get a space-separated list of all connected screens
static QString allConnectedScreens()
{
QStringList names;
const auto screens = QGuiApplication::screens();
names.reserve(screens.length());
for (auto screen : screens) {
names << screen->name();
}
// A string including the connector names is used in the config file key for
// storing per-screen-arrangement size and position data, which means we
// need this string to be consistent for the same screen arrangement. But
// connector order is non-deterministic. We need to sort the list to keep a
// consistent order and avoid losing multi-screen size and position data.
names.sort();
return names.join(QLatin1Char(' '));
}
// Convenience function to return screen by its name from window screen siblings
// returns current window screen if not found
static QScreen *findScreenByName(const QWindow *window, const QString screenName)
{
if (screenName == window->screen()->name()) {
return window->screen();
}
for (QScreen *s : window->screen()->virtualSiblings()) {
if (s->name() == screenName) {
return s;
}
}
return window->screen();
}
// Convenience function to get an appropriate config file key under which to
// save window size, position, or maximization information.
static QString configFileString(const QString &key)
{
QString returnString;
const int numberOfScreens = QGuiApplication::screens().length();
if (numberOfScreens == 1) {
// For single-screen setups, we save data on a per-resolution basis.
const QRect screenGeometry = QGuiApplication::primaryScreen()->geometry();
returnString = QStringLiteral("%1x%2 screen: %3").arg(QString::number(screenGeometry.width()), QString::number(screenGeometry.height()), key);
} else {
// For multi-screen setups, we save data based on the number of screens.
// Distinguishing individual screens based on their names is unreliable
// due to name strings being inherently volatile.
returnString = QStringLiteral("%1 screens: %2").arg(QString::number(numberOfScreens), key);
}
return returnString;
}
// Convenience function for "window is maximized" string
static QString screenMaximizedString()
{
return configFileString(QStringLiteral("Window-Maximized"));
}
// Convenience function for window width string
static QString windowWidthString()
{
return configFileString(QStringLiteral("Width"));
}
// Convenience function for window height string
static QString windowHeightString()
{
return configFileString(QStringLiteral("Height"));
}
// Convenience function for window X position string
static QString windowXPositionString()
{
return configFileString(QStringLiteral("XPosition"));
}
// Convenience function for window Y position string
static QString windowYPositionString()
{
return configFileString(QStringLiteral("YPosition"));
}
static QString windowScreenPositionString()
{
return QStringLiteral("%1").arg(allConnectedScreens());
}
void KWindowConfig::saveWindowSize(const QWindow *window, KConfigGroup &config, KConfigGroup::WriteConfigFlags options)
{
// QWindow::screen() shouldn't return null, but it sometimes does due to bugs.
if (!window || !window->screen()) {
return;
}
const QScreen *screen = window->screen();
const QSize sizeToSave = window->size();
const bool isMaximized = window->windowState() & Qt::WindowMaximized;
// Save size only if window is not maximized
if (!isMaximized) {
const QSize defaultSize(window->property(s_initialSizePropertyName).toSize());
const QSize defaultScreenSize(window->property(s_initialScreenSizePropertyName).toSize());
const bool sizeValid = defaultSize.isValid() && defaultScreenSize.isValid();
if (!sizeValid || (defaultSize != sizeToSave || defaultScreenSize != screen->geometry().size())) {
config.writeEntry(windowWidthString(), sizeToSave.width(), options);
config.writeEntry(windowHeightString(), sizeToSave.height(), options);
// Don't keep the maximized string in the file since the window is
// no longer maximized at this point
config.deleteEntry(screenMaximizedString());
}
// Revert width and height to default if they are same as defaults
else {
config.revertToDefault(windowWidthString());
config.revertToDefault(windowHeightString());
}
}
if ((isMaximized == false) && !config.hasDefault(screenMaximizedString())) {
config.revertToDefault(screenMaximizedString());
} else {
config.writeEntry(screenMaximizedString(), isMaximized, options);
}
}
bool KWindowConfig::hasSavedWindowSize(KConfigGroup &config)
{
return config.hasKey(windowWidthString()) || config.hasKey(windowHeightString()) || config.hasKey(screenMaximizedString());
}
void KWindowConfig::restoreWindowSize(QWindow *window, const KConfigGroup &config)
{
if (!window) {
return;
}
const QString screenName = config.readEntry(windowScreenPositionString(), window->screen()->name());
const int width = config.readEntry(windowWidthString(), -1);
const int height = config.readEntry(windowHeightString(), -1);
const bool isMaximized = config.readEntry(configFileString(QStringLiteral("Window-Maximized")), false);
// Check default size
const QSize defaultSize(window->property(s_initialSizePropertyName).toSize());
const QSize defaultScreenSize(window->property(s_initialScreenSizePropertyName).toSize());
if (!defaultSize.isValid() || !defaultScreenSize.isValid()) {
const QScreen *screen = findScreenByName(window, screenName);
window->setProperty(s_initialSizePropertyName, window->size());
window->setProperty(s_initialScreenSizePropertyName, screen->geometry().size());
}
if (width > 0 && height > 0) {
window->resize(width, height);
}
if (isMaximized) {
window->setWindowState(Qt::WindowMaximized);
}
}
void KWindowConfig::saveWindowPosition(const QWindow *window, KConfigGroup &config, KConfigGroup::WriteConfigFlags options)
{
// On Wayland, the compositor is solely responsible for window positioning,
// So this needs to be a no-op
if (!window || QGuiApplication::platformName() == QLatin1String{"wayland"}) {
return;
}
// If the window is maximized, saving the position will only serve to mis-position
// it once de-maximized, so let's not do that
if (window->windowState() & Qt::WindowMaximized) {
return;
}
config.writeEntry(windowXPositionString(), window->x(), options);
config.writeEntry(windowYPositionString(), window->y(), options);
config.writeEntry(windowScreenPositionString(), window->screen()->name(), options);
}
bool KWindowConfig::hasSavedWindowPosition(KConfigGroup &config)
{
// Window position save/restore features outside of the compositor are not
// supported on Wayland
if (QGuiApplication::platformName() == QLatin1String{"wayland"}) {
return false;
}
return config.hasKey(windowXPositionString()) || config.hasKey(windowYPositionString()) || config.hasKey(windowScreenPositionString());
}
void KWindowConfig::restoreWindowPosition(QWindow *window, const KConfigGroup &config)
{
// On Wayland, the compositor is solely responsible for window positioning,
// So this needs to be a no-op
if (!window || QGuiApplication::platformName() == QLatin1String{"wayland"}) {
return;
}
const bool isMaximized = config.readEntry(configFileString(QStringLiteral("Window-Maximized")), false);
// Don't need to restore position if the window was maximized
if (isMaximized) {
window->setWindowState(Qt::WindowMaximized);
return;
}
// Move window to proper screen
const QScreen *screen = window->screen();
const QString screenName = config.readEntry(windowScreenPositionString(), screen->name());
if (screenName != screen->name()) {
QScreen *screenConf = findScreenByName(window, screenName);
window->setScreen(screenConf);
restoreWindowScreenPosition(window, screenConf, config);
return;
}
restoreWindowScreenPosition(window, screen, config);
}
void KWindowConfig::restoreWindowScreenPosition(QWindow *window, const QScreen *screen, const KConfigGroup &config)
{
Q_UNUSED(screen);
const int xPos = config.readEntry(windowXPositionString(), -1);
const int yPos = config.readEntry(windowYPositionString(), -1);
if (xPos == -1 || yPos == -1) {
return;
}
window->setX(xPos);
window->setY(yPos);
}
@@ -0,0 +1,119 @@
/*
This file is part of the KDE libraries
SPDX-FileCopyrightText: 2012 Benjamin Port <benjamin.port@ben2367.fr>
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
*/
#ifndef KWINDOWCONFIG_H
#define KWINDOWCONFIG_H
#include <kconfiggroup.h>
#include <kconfiggui_export.h>
class QWindow;
class QScreen;
/**
* Save and load window sizes into a config
*/
namespace KWindowConfig
{
/**
* Saves the window's size dependent on the screen dimension either to the
* global or application config file.
*
* @note the group must be set before calling
*
* @param window The window to save size.
* @param config The config group to read from.
* @param options passed to KConfigGroup::writeEntry()
* @since 5.0
*/
KCONFIGGUI_EXPORT void saveWindowSize(const QWindow *window, KConfigGroup &config, KConfigGroup::WriteConfigFlags options = KConfigGroup::Normal);
/**
* Returns whether a given KConfig group has any saved window size data.
*
* @param config The config group to read from.
* @since 6.0
*/
KCONFIGGUI_EXPORT bool hasSavedWindowSize(KConfigGroup &config);
/**
* Restores the dialog's size from the configuration according to
* the screen size.
*
* If you're calling this from a constructor (for a mainwindow or dialog, for instance)
* you should first call winId() so that a QWindow is created, then you can call windowHandle()
* to pass to this method.
*
* Example code:
* @code
* create(); // ensure there's a window created
* const QSize availableSize = windowHandle()->screen()->availableSize();
* windowHandle()->resize(availableSize.width() * 0.7, availableSize.height() * 0.5); // default size
* KWindowConfig::restoreWindowSize(windowHandle(), KSharedConfig::openConfig()->group("MyDialog"));
* resize(windowHandle()->size()); // workaround for QTBUG-40584
* @endcode
*
* @note the group must be set before calling
*
* @param window The window to restore size.
* @param config The config group to read from.
* @since 5.0.
*/
KCONFIGGUI_EXPORT void restoreWindowSize(QWindow *window, const KConfigGroup &config);
/**
* Saves the window's position either to the global or application config file.
* This function has no effect on Wayland, where the compositor is responsible
* for window positioning.
*
* @note the group must be set before calling
*
* @param window The window whose position to save.
* @param config The config group to read from.
* @param options passed to KConfigGroup::writeEntry()
* @since 5.74
*/
KCONFIGGUI_EXPORT void saveWindowPosition(const QWindow *window, KConfigGroup &config, KConfigGroup::WriteConfigFlags options = KConfigGroup::Normal);
/**
* Returns whether a given KConfig group has any saved window position data.
*
* @note: always returns false on Wayland where saving and restoring window
* position data is not supported.
*
* @param config The config group to read from.
* @since 6.0
*/
KCONFIGGUI_EXPORT bool hasSavedWindowPosition(KConfigGroup &config);
/**
* Restores the window's screen position from the configuration and calls restoreWindowScreenPosition.
* This function has no effect on Wayland, where the compositor is responsible
* for window positioning.
*
* @note the group must be set before calling
*
* @param window The window whose position to restore.
* @param config The config group to read from.
* @since 5.74
*/
KCONFIGGUI_EXPORT void restoreWindowPosition(QWindow *window, const KConfigGroup &config);
/**
* Restores the window's position on provided screen from the configuration.
* This function has no effect on Wayland, where the compositor is responsible
* for window positioning.
*
* @note the group must be set before calling
*
* @param window The window whose position to restore.
* @param screen Screen on which window should be placed.
* @param config The config group to read from.
* @since 5.99
*/
KCONFIGGUI_EXPORT void restoreWindowScreenPosition(QWindow *window, const QScreen *screen, const KConfigGroup &config);
}
#endif // KWINDOWCONFIG_H
@@ -0,0 +1,127 @@
/*
SPDX-FileCopyrightText: 2022 Volker Krause <vkrause@kde.org>
SPDX-License-Identifier: LGPL-2.0-or-later
*/
#include "kwindowstatesaver.h"
#include "ksharedconfig.h"
#include "kwindowconfig.h"
#include <QWindow>
class KWindowStateSaverPrivate
{
public:
QWindow *window = nullptr;
KConfigGroup configGroup;
std::function<QWindow *()> windowHandleCallback;
int timerId = 0;
void init(KWindowStateSaver *q);
void initWidget(QObject *widget, KWindowStateSaver *q);
};
void KWindowStateSaverPrivate::init(KWindowStateSaver *q)
{
if (!window) {
return;
}
KWindowConfig::restoreWindowSize(window, configGroup);
KWindowConfig::restoreWindowPosition(window, configGroup);
const auto saveSize = [q, this]() {
KWindowConfig::saveWindowSize(window, configGroup);
if (!timerId) {
timerId = q->startTimer(std::chrono::seconds(30));
}
};
const auto savePosition = [q, this]() {
KWindowConfig::saveWindowPosition(window, configGroup);
if (!timerId) {
timerId = q->startTimer(std::chrono::seconds(30));
}
};
QObject::connect(window, &QWindow::widthChanged, q, saveSize);
QObject::connect(window, &QWindow::heightChanged, q, saveSize);
QObject::connect(window, &QWindow::xChanged, q, savePosition);
QObject::connect(window, &QWindow::yChanged, q, savePosition);
}
void KWindowStateSaverPrivate::initWidget(QObject *widget, KWindowStateSaver *q)
{
if (!window && windowHandleCallback) {
window = windowHandleCallback();
}
if (window) {
init(q);
} else {
widget->installEventFilter(q);
}
}
KWindowStateSaver::KWindowStateSaver(QWindow *window, const KConfigGroup &configGroup)
: QObject(window)
, d(new KWindowStateSaverPrivate)
{
Q_ASSERT(window);
d->window = window;
d->configGroup = configGroup;
d->init(this);
}
KWindowStateSaver::KWindowStateSaver(QWindow *window, const QString &configGroupName)
: QObject(window)
, d(new KWindowStateSaverPrivate)
{
Q_ASSERT(window);
d->window = window;
d->configGroup = KConfigGroup(KSharedConfig::openStateConfig(), configGroupName);
d->init(this);
}
KWindowStateSaver::~KWindowStateSaver()
{
delete d;
}
void KWindowStateSaver::timerEvent(QTimerEvent *event)
{
killTimer(event->timerId());
d->configGroup.sync();
d->timerId = 0;
}
bool KWindowStateSaver::eventFilter(QObject *watched, QEvent *event)
{
// QEvent::PlatformSurface would give us a valid window, but if there are
// intial resizings (explicitly or via layout constraints) those would then
// already overwrite our restored values. So wait until all that is done
// and only restore afterwards.
if (event->type() == QEvent::ShowToParent && !d->window) {
watched->removeEventFilter(this);
d->window = d->windowHandleCallback();
d->init(this);
}
return QObject::eventFilter(watched, event);
}
void KWindowStateSaver::initWidget(QObject *widget, const std::function<QWindow *()> &windowHandleCallback, const KConfigGroup &configGroup)
{
d = new KWindowStateSaverPrivate;
d->windowHandleCallback = windowHandleCallback;
d->configGroup = configGroup;
d->initWidget(widget, this);
}
void KWindowStateSaver::initWidget(QObject *widget, const std::function<QWindow *()> &windowHandleCallback, const QString &configGroupName)
{
d = new KWindowStateSaverPrivate;
d->windowHandleCallback = windowHandleCallback;
d->configGroup = KConfigGroup(KSharedConfig::openStateConfig(), configGroupName);
d->initWidget(widget, this);
}
#include "moc_kwindowstatesaver.cpp"
@@ -0,0 +1,117 @@
/*
SPDX-FileCopyrightText: 2022 Volker Krause <vkrause@kde.org>
SPDX-License-Identifier: LGPL-2.0-or-later
*/
#ifndef KWINDOWSTATESAVER_H
#define KWINDOWSTATESAVER_H
#include <kconfiggroup.h>
#include <kconfiggui_export.h>
#include <QObject>
class QWindow;
class KWindowStateSaverPrivate;
/**
* Saves and restores a window size and (when possible) position.
*
* This is useful for retrofitting persisting window geometry on existing windows or dialogs,
* without having to modify those classes themselves, or having to inherit from them.
* For this, create a new instance of KWindowStateSaver for every window that should have it's
* state persisted, and pass it the window or widget as well as the config group the state
* should be stored in. The KWindowStateSaver will restore an existing state and then monitor
* the window for subsequent changes to persist. It will delete itself once the window is
* deleted.
*
* @code
* QPrintPreviewDialog dlg = ...
* new KWindowStateSaver(&dlg, "printPreviewDialogState");
* ...
* dlg.exec();
* @endcode
*
* Note that freshly created top-level QWidgets (such as the dialog in the above example)
* do not have an associated QWindow yet (ie. windowHandle() return @c nullptr). KWindowStateSaver
* supports this with its QWidget constructors which will monitor the widget for having
* its associated QWindow created before continuing with that.
*
* When implementing your own windows/dialogs, using KWindowConfig directly can be an
* alternative.
*
* @see KWindowConfig
* @since 5.92
*/
class KCONFIGGUI_EXPORT KWindowStateSaver : public QObject
{
Q_OBJECT
public:
/**
* Create a new window state saver for @p window.
* @param configGroup A KConfigGroup that holds the window state.
*/
explicit KWindowStateSaver(QWindow *window, const KConfigGroup &configGroup);
/**
* Create a new window state saver for @p window.
* @param configGroupName The name of a KConfigGroup in the default state
* configuration (see KSharedConfig::openStateConfig) that holds the window state.
*/
explicit KWindowStateSaver(QWindow *window, const QString &configGroupName);
/**
* Create a new window state saver for @p widget.
* Use this for widgets that aren't shown yet and would still return @c nullptr from windowHandle().
* @param configGroup A KConfigGroup that holds the window state.
*/
template<typename Widget>
explicit inline KWindowStateSaver(Widget *widget, const KConfigGroup &configGroup);
/**
* Create a new window state saver for @p widget.
* Use this for widgets that aren't shown yet and would still return @c nullptr from windowHandle().
* @param configGroupName The name of a KConfigGroup in the default state
* configuration (see KSharedConfig::openStateConfig) that holds the window state.
*/
template<typename Widget>
explicit inline KWindowStateSaver(Widget *widget, const QString &configGroupName);
~KWindowStateSaver();
private:
void timerEvent(QTimerEvent *event) override;
bool eventFilter(QObject *watched, QEvent *event) override;
// API used by template code, so technically part of the ABI
void initWidget(QObject *widget, const std::function<QWindow *()> &windowHandleCallback, const KConfigGroup &configGroup);
void initWidget(QObject *widget, const std::function<QWindow *()> &windowHandleCallback, const QString &configGroupName);
// cannot use std::unique_ptr due to the template ctors
// not seeing the full private class
KWindowStateSaverPrivate *d = nullptr;
};
template<typename Widget>
KWindowStateSaver::KWindowStateSaver(Widget *widget, const KConfigGroup &configGroup)
: QObject(widget)
{
initWidget(
widget,
[widget]() {
return widget->windowHandle();
},
configGroup);
}
template<typename Widget>
KWindowStateSaver::KWindowStateSaver(Widget *widget, const QString &configGroupName)
: QObject(widget)
{
initWidget(
widget,
[widget]() {
return widget->windowHandle();
},
configGroupName);
}
#endif // KWINDOWSTATESAVER_H