Commit 99d0f172 authored by Jonathan Marten's avatar Jonathan Marten
Browse files

Klipper: Make the "General" configuration options clearer

Combine the "Text selection only", "Ignore selection" and "Ignore images"
options into separate sets of radio buttons for text and images, to make
their functions explicit.

Remove the "Prevent empty clipboard" option (but leave it as a hidden
config file setting), it was difficult to explain and it is unclear if it
ever had a use case.

Convert the page to a QFormLayout, and add explanatory text to existing
controls where appropriate.

GUI:
I18N:
parent 358292af
Pipeline #130093 passed with stage
in 4 minutes and 51 seconds
......@@ -24,7 +24,7 @@ ecm_qt_declare_logging_category(libklipper_common_SRCS HEADER klipper_debug.h ID
configure_file(config-klipper.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-klipper.h )
ki18n_wrap_ui(libklipper_common_SRCS generalconfig.ui actionsconfig.ui editactiondialog.ui)
ki18n_wrap_ui(libklipper_common_SRCS actionsconfig.ui editactiondialog.ui)
kconfig_add_kcfg_files(libklipper_common_SRCS klippersettings.kcfgc)
add_library(libklipper_common_static STATIC ${libklipper_common_SRCS})
......
......@@ -7,34 +7,223 @@
#include "configdialog.h"
#include <qbuttongroup.h>
#include <qfontdatabase.h>
#include <qformlayout.h>
#include <qgroupbox.h>
#include <qradiobutton.h>
#include <qtooltip.h>
#include <qwindow.h>
#include <KConfigSkeleton>
#include <KEditListWidget>
#include <KShortcutsEditor>
#include <kwindowconfig.h>
#include <kconfigskeleton.h>
#include <kpluralhandlingspinbox.h>
#include "klipper_debug.h"
#include "editactiondialog.h"
#include "klipper.h"
#include "klippersettings.h"
static QLabel *createHintLabel(const QString &text, QWidget *parent)
{
QLabel *hintLabel = new QLabel(text, parent);
hintLabel->setFont(QFontDatabase::systemFont(QFontDatabase::SmallestReadableFont));
hintLabel->setWordWrap(true);
hintLabel->setAlignment(Qt::AlignLeft|Qt::AlignTop);
// The minimum width needs to be set so that QLabel will wrap the text
// to fill that width. Otherwise, it will try to adjust the text wrapping
// width so that the text is laid out in a pleasing looking rectangle,
// which unfortunately leaves a lot of white space below the actual text.
// See the "tryWidth" block in QLabelPrivate::sizeForWidth().
hintLabel->setMinimumWidth(400);
return (hintLabel);
}
static QLabel *createHintLabel(const KConfigSkeletonItem *item, QWidget *parent)
{
return (createHintLabel(item->whatsThis(), parent));
}
GeneralWidget::GeneralWidget(QWidget *parent)
: QWidget(parent)
{
m_ui.setupUi(this);
m_ui.kcfg_TimeoutForActionPopups->setSuffix(ki18np(" second", " seconds"));
m_ui.kcfg_MaxClipItems->setSuffix(ki18np(" entry", " entries"));
QFormLayout *layout = new QFormLayout(this);
// Retain clipboard history
const KConfigSkeletonItem *item = KlipperSettings::self()->keepClipboardContentsItem();
m_enableHistoryCb = new QCheckBox(item->label(), this);
m_enableHistoryCb->setChecked(KlipperSettings::keepClipboardContents());
m_enableHistoryCb->setToolTip(item->toolTip());
layout->addRow(QString(), m_enableHistoryCb);
layout->addRow(QString(), new QLabel(this));
// Synchronise selection and clipboard
item = KlipperSettings::self()->syncClipboardsItem();
m_syncClipboardsCb = new QCheckBox(item->label(), this);
m_syncClipboardsCb->setChecked(KlipperSettings::syncClipboards());
layout->addRow(i18n("Selection and Clipboard:"), m_syncClipboardsCb);
QLabel *hint = createHintLabel(item, this);
layout->addRow(QString(), hint);
connect(hint, &QLabel::linkActivated, this, [this, hint]() {
QToolTip::showText(QCursor::pos(),
xi18nc("@info:tooltip",
"When text or an area of the screen is highlighted with the mouse or keyboard, \
this is the <emphasis>selection</emphasis>. It can be pasted using the middle mouse button.\
<nl/>\
<nl/>\
If the selection is explicitly copied using a <interface>Copy</interface> or <interface>Cut</interface> action, \
it is saved to the <emphasis>clipboard</emphasis>. It can be pasted using a <interface>Paste</interface> action. \
<nl/>\
<nl/>\
When turned on this option keeps the selection and the clipboard the same, so that any selection is immediately available to paste by any means. \
If it is turned off, the selection may still be saved in the clipboard history (subject to the options below), but it can only be pasted using the middle mouse button."),
hint);
});
layout->addRow(QString(), new QLabel(this));
// Radio button group: Storing text selections in history
//
// These two options correspond to the 'ignoreSelection' internal
// Klipper setting.
//
// The 'Always' option is not available if selection/clipboard synchronisation
// is turned off - in this case the selection is never automatically saved
// in the clipboard history.
QButtonGroup *bg = new QButtonGroup(this);
m_alwaysTextRb = new QRadioButton(i18n("Always save in history"), this);
m_alwaysTextRb->setChecked(!KlipperSettings::ignoreSelection());
bg->addButton(m_alwaysTextRb);
layout->addRow(i18n("Text selection:"), m_alwaysTextRb);
m_copiedTextRb = new QRadioButton(i18n("Only when explicitly copied"), this);
m_copiedTextRb->setChecked(KlipperSettings::ignoreSelection());
bg->addButton(m_copiedTextRb);
layout->addRow(QString(), m_copiedTextRb);
layout->addRow(QString(), createHintLabel(i18n("Whether text selections are saved in the clipboard history."), this));
// Radio button group: Storing non-text selections in history
//
// The truth table for the 4 possible combinations of internal Klipper
// settings (of which two are equivalent, making 3 user-visible options)
// controlling what is stored in the clipboard history is:
//
// selectionTextOnly ignoreImages Selected Selected Copied Copied Option
// text image/other text image/other
//
// false false yes yes yes yes 1
// true false yes no yes yes 2
// false true yes no yes no 3
// true true yes no yes no 3
//
// Option 1: Always store images in history
// 2: Only when explicitly copied
// 3: Never store images in history
//
// The 'Always' option is not available if selection/clipboard synchronisation
// is turned off.
bg = new QButtonGroup(this);
m_alwaysImageRb = new QRadioButton(i18n("Always save in history"), this);
m_alwaysImageRb->setChecked(!KlipperSettings::ignoreImages() && !KlipperSettings::selectionTextOnly());
bg->addButton(m_alwaysImageRb);
layout->addRow(i18n("Non-text selection:"), m_alwaysImageRb);
m_copiedImageRb = new QRadioButton(i18n("Only when explicitly copied"), this);
m_copiedImageRb->setChecked(!KlipperSettings::ignoreImages() && KlipperSettings::selectionTextOnly());
bg->addButton(m_copiedImageRb);
layout->addRow(QString(), m_copiedImageRb);
m_neverImageRb = new QRadioButton(i18n("Never save in history"), this);
m_neverImageRb->setChecked(KlipperSettings::ignoreImages());
bg->addButton(m_neverImageRb);
layout->addRow(QString(), m_neverImageRb);
layout->addRow(QString(), createHintLabel(i18n("Whether non-text selections (such as images) are saved in the clipboard history."), this));
layout->addRow(QString(), new QLabel(this));
// Action popup time
item = KlipperSettings::self()->timeoutForActionPopupsItem();
m_actionTimeoutSb = new KPluralHandlingSpinBox(this);
m_actionTimeoutSb->setRange(item->minValue().toInt(), item->maxValue().toInt());
m_actionTimeoutSb->setValue(KlipperSettings::timeoutForActionPopups());
m_actionTimeoutSb->setSuffix(ki18ncp("Unit of time", " second", " seconds"));
m_actionTimeoutSb->setSpecialValueText(i18nc("No timeout", "None"));
m_actionTimeoutSb->setToolTip(item->toolTip());
layout->addRow(item->label(), m_actionTimeoutSb);
// Clipboard history size
item = KlipperSettings::self()->maxClipItemsItem();
m_historySizeSb = new KPluralHandlingSpinBox(this);
m_historySizeSb->setRange(item->minValue().toInt(), item->maxValue().toInt());
m_historySizeSb->setValue(KlipperSettings::maxClipItems());
m_historySizeSb->setSuffix(ki18ncp("NUmber of entries", " entry", " entries"));
m_historySizeSb->setToolTip(item->toolTip());
layout->addRow(item->label(), m_historySizeSb);
m_settingsSaved = false;
connect(m_syncClipboardsCb, &QAbstractButton::clicked, this, &GeneralWidget::updateWidgets);
layout->addItem(new QSpacerItem(QSizePolicy::Fixed, QSizePolicy::Expanding));
}
void GeneralWidget::updateWidgets()
{
if (m_ui.kcfg_IgnoreSelection->isChecked()) {
m_ui.kcfg_SyncClipboards->setEnabled(false);
m_ui.kcfg_SelectionTextOnly->setEnabled(false);
} else if (m_ui.kcfg_SyncClipboards->isChecked()) {
m_ui.kcfg_IgnoreSelection->setEnabled(false);
if (m_syncClipboardsCb->isChecked()) {
m_alwaysImageRb->setEnabled(true);
m_alwaysTextRb->setEnabled(true);
if (m_settingsSaved) {
m_alwaysTextRb->setChecked(m_prevAlwaysText);
m_alwaysImageRb->setChecked(m_prevAlwaysImage);
m_settingsSaved = false;
}
} else {
m_prevAlwaysText = m_alwaysTextRb->isChecked();
m_prevAlwaysImage = m_alwaysImageRb->isChecked();
m_settingsSaved = true;
if (m_alwaysImageRb->isChecked()) {
m_copiedImageRb->setChecked(true);
}
if (m_alwaysTextRb->isChecked()) {
m_copiedTextRb->setChecked(true);
}
m_alwaysImageRb->setEnabled(false);
m_alwaysTextRb->setEnabled(false);
}
}
void GeneralWidget::save()
{
KlipperSettings::setKeepClipboardContents(m_enableHistoryCb->isChecked());
KlipperSettings::setSyncClipboards(m_syncClipboardsCb->isChecked());
KlipperSettings::setIgnoreSelection(m_copiedTextRb->isChecked());
KlipperSettings::setIgnoreImages(m_neverImageRb->isChecked());
KlipperSettings::setSelectionTextOnly(m_copiedImageRb->isChecked());
KlipperSettings::setTimeoutForActionPopups(m_actionTimeoutSb->value());
KlipperSettings::setMaxClipItems(m_historySizeSb->value());
}
ActionsWidget::ActionsWidget(QWidget *parent)
: QWidget(parent)
, m_editActDlg(nullptr)
......@@ -262,8 +451,13 @@ ConfigDialog::ConfigDialog(QWidget *parent, KConfigSkeleton *skeleton, const Kli
m_shortcutsWidget = new KShortcutsEditor(collection, this, KShortcutsEditor::GlobalAction);
addPage(m_shortcutsWidget, i18nc("Shortcuts Config", "Shortcuts"), QStringLiteral("preferences-desktop-keyboard"), i18n("Shortcuts Configuration"));
connect(m_generalPage, &GeneralWidget::settingChanged, this, &ConfigDialog::settingsChangedSlot);
// from KWindowConfig::restoreWindowSize() API documentation
(void) winId();
const KConfigGroup grp = KSharedConfig::openConfig()->group("ConfigDialog");
KWindowConfig::restoreWindowSize(windowHandle(), grp);
resize(windowHandle()->size());
}
ConfigDialog::~ConfigDialog()
......@@ -280,6 +474,7 @@ void ConfigDialog::updateSettings()
}
m_shortcutsWidget->save();
m_generalPage->save();
m_actionsPage->resetModifiedState();
......@@ -287,6 +482,8 @@ void ConfigDialog::updateSettings()
m_klipper->urlGrabber()->setExcludedWMClasses(m_actionsPage->excludedWMClasses());
m_klipper->saveSettings();
KlipperSettings::self()->save();
KConfigGroup grp = KSharedConfig::openConfig()->group("ConfigDialog");
KWindowConfig::saveWindowSize(windowHandle(), grp);
}
......
......@@ -11,24 +11,46 @@
#include "urlgrabber.h"
#include "ui_actionsconfig.h"
#include "ui_generalconfig.h"
class KConfigSkeleton;
class KShortcutsEditor;
class Klipper;
class KEditListWidget;
class KActionCollection;
class KPluralHandlingSpinBox;
class EditActionDialog;
class QCheckBox;
class QRadioButton;
class GeneralWidget : public QWidget
{
Q_OBJECT
public:
explicit GeneralWidget(QWidget *parent);
void updateWidgets();
void save();
signals:
void settingChanged();
private:
Ui::GeneralWidget m_ui;
QCheckBox *m_enableHistoryCb;
QCheckBox *m_syncClipboardsCb;
QRadioButton *m_alwaysTextRb;
QRadioButton *m_copiedTextRb;
QRadioButton *m_alwaysImageRb;
QRadioButton *m_copiedImageRb;
QRadioButton *m_neverImageRb;
KPluralHandlingSpinBox *m_actionTimeoutSb;
KPluralHandlingSpinBox *m_historySizeSb;
bool m_settingsSaved;
bool m_prevAlwaysImage;
bool m_prevAlwaysText;
};
class ActionsWidget : public QWidget
......@@ -91,7 +113,7 @@ public:
ConfigDialog(QWidget *parent, KConfigSkeleton *config, const Klipper *klipper, KActionCollection *collection);
~ConfigDialog() override;
private:
protected slots:
// reimp
void updateWidgets() override;
// reimp
......
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>GeneralWidget</class>
<widget class="QWidget" name="GeneralWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>463</width>
<height>417</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QCheckBox" name="kcfg_KeepClipboardContents">
<property name="text">
<string>Save clipboard contents on exit</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="kcfg_PreventEmptyClipboard">
<property name="text">
<string>Prevent empty clipboard</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="kcfg_IgnoreImages">
<property name="text">
<string>Ignore images</string>
</property>
</widget>
</item>
<item>
<widget class="QGroupBox" name="selection_group">
<property name="title">
<string>Selection and Clipboard</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QCheckBox" name="kcfg_IgnoreSelection">
<property name="text">
<string>Ignore selection</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="kcfg_SelectionTextOnly">
<property name="text">
<string>Text selection only</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="kcfg_SyncClipboards">
<property name="text">
<string>Synchronize contents of the clipboard and the selection</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QLabel" name="timeout_label">
<property name="text">
<string>Timeout for action popups:</string>
</property>
</widget>
</item>
<item>
<widget class="KPluralHandlingSpinBox" name="kcfg_TimeoutForActionPopups">
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="history_size_label">
<property name="text">
<string>Clipboard history size:</string>
</property>
</widget>
</item>
<item>
<widget class="KPluralHandlingSpinBox" name="kcfg_MaxClipItems">
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>KPluralHandlingSpinBox</class>
<extends>QSpinBox</extends>
<header>kpluralhandlingspinbox.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections>
<connection>
<sender>kcfg_IgnoreSelection</sender>
<signal>clicked(bool)</signal>
<receiver>kcfg_SelectionTextOnly</receiver>
<slot>setDisabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>78</x>
<y>213</y>
</hint>
<hint type="destinationlabel">
<x>80</x>
<y>231</y>
</hint>
</hints>
</connection>
<connection>
<sender>kcfg_IgnoreSelection</sender>
<signal>clicked(bool)</signal>
<receiver>kcfg_SyncClipboards</receiver>
<slot>setDisabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>209</x>
<y>214</y>
</hint>
<hint type="destinationlabel">
<x>207</x>
<y>265</y>
</hint>
</hints>
</connection>
<connection>
<sender>kcfg_SyncClipboards</sender>
<signal>clicked(bool)</signal>
<receiver>kcfg_IgnoreSelection</receiver>
<slot>setDisabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>300</x>
<y>261</y>
</hint>
<hint type="destinationlabel">
<x>301</x>
<y>210</y>
</hint>
</hints>
</connection>
</connections>
</ui>
......@@ -9,36 +9,38 @@
<label>Klipper version</label>
</entry>
<entry name="KeepClipboardContents" type="Bool">
<label>Keep clipboard contents</label>
<label>Save the clipboard history across desktop sessions</label>
<default>true</default>
<tooltip>Retain the clipboard history, so it will be available the next time you log in.</tooltip>
</entry>
<entry name="PreventEmptyClipboard" type="Bool">
<label>Prevent empty clipboard</label>
<entry name="PreventEmptyClipboard" key="NoEmptyClipboard" type="Bool">
<label>Prevent the clipboard from being cleared</label>
<default>true</default>
<whatsthis>Selecting this option has the effect, that the clipboard can never be emptied. E.g. when an application exits, the clipboard would usually be emptied.</whatsthis>
</entry>
<entry name="IgnoreImages" type="Bool">
<label>Ignore images</label>
<default>true</default>
</entry>
<entry name="IgnoreSelection" type="Bool">
<label>Ignore Selection</label>
<default>true</default>
<whatsthis>When an area of the screen is selected with mouse or keyboard, this is called "the selection".&lt;br/&gt;If this option is set, the selection is not entered into the clipboard history, though it is still available for pasting using the middle mouse button.</whatsthis>
<whatsthis>Do not allow the clipboard to be cleared, for example when an application exits.</whatsthis>
</entry>
<entry name="Synchronize" type="Int">
<label comment="KDE::DoNotExtract">Backwards compatibility, don't touch.</label>
<default>3</default>
</entry>
<entry name="SyncClipboards" type="Bool">
<label>Synchronize clipboard and selection</label>
<label>Keep the selection and clipboard the same</label>
<default>false</default>
<whatsthis>When an area of the screen is selected with mouse or keyboard, this is called "the selection".&lt;br/&gt;If this option is selected, the selection and the clipboard is kept the same, so that anything in the selection is immediately available for pasting elsewhere using any method, including the traditional middle mouse button. Otherwise, the selection is recorded in the clipboard history, but the selection can only be pasted using the middle mouse button. Also see the 'Ignore Selection' option.</whatsthis>
<whatsthis>Content selected with the cursor is automatically copied to the clipboard so that it can be pasted with either a Paste action or a middle-click.&lt;br/&gt;&lt;a href="1"&gt;More about the selection and clipboard&lt;/a&gt;.</whatsthis>
</entry>
<entry name="IgnoreSelection" type="Bool">
<label>Ignore the selection</label>
<default>true</default>
<whatsthis>Content selected with the cursor but not explicitly copied to the clipboard is not automatically stored in the clipboard history, and can only be pasted using a middle-click.</whatsthis>
</entry>
<entry name="SelectionTextOnly" type="Bool">
<label>Selection text only</label>
<label>Text selection only</label>
<default>true</default>
<whatsthis>Only store text selections in the clipboard history, not images or any other type of data.</whatsthis>
</entry>
<entry name="IgnoreImages" type="Bool">
<label>Always ignore images</label>
<default>true</default>
<whatsthis>When an area of the screen is selected with mouse or keyboard, this is called "the selection".&lt;br/&gt;If this option is selected, only text selections are stored in the history, while images and other selections are not.</whatsthis>
<whatsthis>Do not store images in the clipboard history, even if explicitly copied.</whatsthis>
</entry>
<entry name="UseGUIRegExpEditor" type="Bool">
<label>Use graphical regexp editor</label>
......@@ -53,17 +55,18 @@
<label>No actions for WM_CLASS</label>
</entry>
<entry name="TimeoutForActionPopups" type="Int">
<label>Timeout for action popups (seconds)</label>
<label>Automatic action popup time:</label>
<default>8</default>
<min>0</min>
<max>200</max>
<tooltip>A value of 0 disables the timeout</tooltip>
<tooltip>Display the automatic action popup for this time.</tooltip>
</entry>
<entry name="MaxClipItems" type="Int">
<label>Clipboard history size</label>
<label>Clipboard history size:</label>
<default>20</default>
<min>1</min>
<max>2048</max>
<tooltip>The clipboard history will store up to this many items.</tooltip>
</entry>
<entry key="ActionListChanged" name="ActionList" type="Int">
<label>Dummy entry for indicating changes in an action's tree widget</label>
......@@ -74,15 +77,17 @@
<entry name="StripWhiteSpace" type="Bool">
<label>Strip whitespace when executing an action</label>
<default>true</default>
<whatsthis>Sometimes, the selected text has some whitespace at the end, which, if loaded as URL in a browser would cause an error. Enabling this option removes any whitespace at the beginning or end of the selected string (the original clipboard contents will not be modified).</whatsthis>
<tooltip>Remove white space from the start and end of clipboard text before performing an action. For example, this ensures that the URL pasted in a browser is interpreted as expected.&lt;br/&gt;&lt;br/&gt;The text saved on the clipboard is not affected.</tooltip>
</entry>
<entry name="ReplayActionInHistory" type="Bool">
<label>Replay action in history</label>
<default>false</default>
<tooltip>When a clipboard item is selected from the history popup, automatically perform the configured actions on it.</tooltip>
</entry>
<entry name="EnableMagicMimeActions" type="Bool">
<label>Enable MIME-based actions</label>
<default>true</default>
<tooltip>If this option is set, and a file name or URL is selected, include applications that can handle its MIME type in the actions popup.</tooltip>
</entry>
</group>
</kcfg>
......@@ -4,5 +4,6 @@ ClassName=KlipperSettings
Singleton=true
CustomAdditions=false
SetUserTexts=true
Mutators=URLGrabberEnabled,NoActionsForWM_CLASS,Version
Mutators=true
TranslationSystem=kde
ItemAccessors=true
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment