Commit 423308f8 authored by Piotr Henryk Dabrowski's avatar Piotr Henryk Dabrowski Committed by Nate Graham
Browse files

[Klipper] Fix clipboard history management

Summary:
Fixed clearing the clipboard when clearing history
(bug #409366 caused by 3bd6ac34)

Properly synchronize clipboard content and history
(deleting last item in history didn't clear the clipboard).

Keep last image in history even if we are ignoring images, but without preview
(so that we can still clear history, and the tooltip says truth about clipboard content).

Fixed tray icon tooltip text.

Do not scale small images up in clipboard Plasmoid.

BUG: 409366

{F7168503}

Test Plan:
Spectacle -> [Copy to Clipboard]
Paste into Dolphin (clipboard content)

Deleting single items from clipboard

Clearing the entire history

Reviewers: #plasma, #plasma_workspaces, ngraham, davidedmundson

Reviewed By: #plasma, #plasma_workspaces, ngraham, davidedmundson

Subscribers: GB_2, davidre, plasma-devel

Tags: #plasma

Differential Revision: https://phabricator.kde.org/D22684
parent 6d2fa8e6
......@@ -82,7 +82,7 @@ ColumnLayout {
level: 3
opacity: 0.6
visible: clipboardMenu.model.count === 0 && filter.length === 0
text: i18n("Clipboard history is empty.")
text: i18n("Clipboard is empty")
}
RowLayout {
......
......@@ -24,7 +24,8 @@ import org.kde.kquickcontrolsaddons 2.0 as KQuickControlsAddons
KQuickControlsAddons.QPixmapItem {
id: previewPixmap
height: Math.round(width * (nativeHeight/nativeWidth) + units.smallSpacing * 2)
width: Math.min(nativeWidth, width)
height: Math.min(nativeHeight, Math.round(width * (nativeHeight/nativeWidth) + units.smallSpacing * 2))
pixmap: DecorationRole
fillMode: KQuickControlsAddons.QPixmapItem.PreserveAspectFit
}
......@@ -21,6 +21,7 @@ target_link_libraries(testHistory
Qt5::Test
Qt5::Widgets # QAction
KF5::CoreAddons # KUrlMimeData
KF5::I18n
)
add_test(NAME klipper-testHistory COMMAND testHistory)
ecm_mark_as_test(testHistory)
......@@ -43,6 +44,7 @@ target_link_libraries(testHistoryModel
Qt5::Test
Qt5::Widgets # QAction
KF5::CoreAddons # KUrlMimeData
KF5::I18n
)
add_test(NAME klipper-testHistoryModel COMMAND testHistoryModel)
ecm_mark_as_test(testHistoryModel)
......@@ -16,10 +16,16 @@
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include "historyimageitem.h"
#include <QMimeData>
#include "historymodel.h"
#include <QCryptographicHash>
#include <QIcon>
#include <QMimeData>
#include <KLocalizedString>
namespace {
QByteArray compute_uuid(const QPixmap& data) {
......@@ -38,14 +44,15 @@ HistoryImageItem::HistoryImageItem( const QPixmap& data )
}
QString HistoryImageItem::text() const {
if ( m_text.isNull() ) {
m_text = QStringLiteral( "%1x%2x%3 %4" )
.arg( m_data.width() )
.arg( m_data.height() )
.arg( m_data.depth() );
if (m_text.isNull()) {
m_text =
QStringLiteral("▨ ") +
i18n("%1x%2 %3bpp")
.arg(m_data.width())
.arg(m_data.height())
.arg(m_data.depth());
}
return m_text;
}
/* virtual */
......@@ -60,3 +67,12 @@ QMimeData* HistoryImageItem::mimeData() const
return data;
}
const QPixmap& HistoryImageItem::image() const {
if (m_model->displayImages()) {
return m_data;
}
static QPixmap imageIcon(
QIcon::fromTheme(QStringLiteral("view-preview")).pixmap(QSize(48, 48))
);
return imageIcon;
}
......@@ -37,7 +37,7 @@ public:
}
return false;
}
const QPixmap& image() const override { return m_data; }
const QPixmap& image() const override;
QMimeData* mimeData() const override;
void write( QDataStream& stream ) const override;
......
......@@ -30,8 +30,8 @@
#include "historymodel.h"
HistoryItem::HistoryItem(const QByteArray& uuid)
: m_uuid(uuid)
, m_model(nullptr)
: m_model(nullptr)
, m_uuid(uuid)
{
}
......
......@@ -100,9 +100,12 @@ public:
QByteArray next_uuid() const;
void setModel(HistoryModel *model);
protected:
HistoryModel *m_model;
private:
QByteArray m_uuid;
HistoryModel *m_model;
};
inline
......
......@@ -25,6 +25,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
HistoryModel::HistoryModel(QObject *parent)
: QAbstractListModel(parent)
, m_maxSize(0)
, m_displayImages(true)
, m_mutex(QMutex::Recursive)
{
}
......
......@@ -46,6 +46,9 @@ public:
int maxSize() const;
void setMaxSize(int size);
bool displayImages() const;
void setDisplayImages(bool show);
void clear();
void moveToTop(const QByteArray &uuid);
void moveTopToBack();
......@@ -64,6 +67,7 @@ private:
void moveToTop(int row);
QList<QSharedPointer<HistoryItem>> m_items;
int m_maxSize;
bool m_displayImages;
QMutex m_mutex;
};
......@@ -72,6 +76,14 @@ inline int HistoryModel::maxSize() const
return m_maxSize;
}
inline bool HistoryModel::displayImages() const {
return m_displayImages;
}
inline void HistoryModel::setDisplayImages(bool show) {
m_displayImages = show;
}
Q_DECLARE_METATYPE(HistoryItemType)
#endif
......@@ -116,6 +116,7 @@ Klipper::Klipper(QObject* parent, const KSharedConfigPtr& config, KlipperMode mo
m_history = new History( this );
m_popup = new KlipperPopup(m_history);
m_popup->setShowHelp(m_mode == KlipperMode::Standalone);
connect(m_history, &History::changed, this, &Klipper::slotHistoryChanged);
connect(m_history, &History::changed, m_popup, &KlipperPopup::slotHistoryChanged);
connect(m_history, &History::topIsUserSelectedSet, m_popup, &KlipperPopup::slotTopIsUserSelectedSet);
......@@ -288,7 +289,6 @@ void Klipper::clearClipboardContents()
void Klipper::clearClipboardHistory()
{
updateTimestamp();
slotClearClipboard();
history()->slotClear();
saveSession();
}
......@@ -330,6 +330,8 @@ void Klipper::loadSettings()
// this will cause it to loadSettings too
setURLGrabberEnabled(m_bURLGrabber);
history()->setMaxSize( KlipperSettings::maxClipItems() );
history()->model()->setDisplayImages(!m_bIgnoreImages);
// Convert 4.3 settings
if (KlipperSettings::synchronize() != 3) {
// 2 was the id of "Ignore selection" radiobutton
......@@ -604,23 +606,24 @@ HistoryItemPtr Klipper::applyClipChanges( const QMimeData* clipData )
return HistoryItemPtr();
}
Ignore lock( m_locklevel );
HistoryItemPtr item = HistoryItem::create( clipData );
bool saveHistory = true;
if (clipData->data(QStringLiteral("x-kde-passwordManagerHint")) == QByteArrayLiteral("secret")) {
saveHistory = false;
}
if (clipData->hasImage() && m_bIgnoreImages) {
saveHistory = false;
if (!(history()->empty())) {
if (m_bIgnoreImages && history()->first()->mimeData()->hasImage()) {
history()->remove(history()->first());
}
}
m_last = item;
HistoryItemPtr item = HistoryItem::create( clipData );
if (saveHistory) {
bool saveToHistory = true;
if (clipData->data(QStringLiteral("x-kde-passwordManagerHint")) == QByteArrayLiteral("secret")) {
saveToHistory = false;
}
if (saveToHistory) {
history()->insert( item );
}
return item;
return item;
}
void Klipper::newClipData( QClipboard::Mode mode )
......@@ -636,6 +639,13 @@ void Klipper::newClipData( QClipboard::Mode mode )
}
void Klipper::slotHistoryChanged()
{
if (history()->empty()) {
slotClearClipboard();
}
}
// Protection against too many clipboard data changes. Lyx responds to clipboard data
// requests with setting new clipboard data, so if Lyx takes over clipboard,
// Klipper notices, requests this data, this triggers "new" clipboard contents
......@@ -697,7 +707,7 @@ void Klipper::checkClipData( bool selectionMode )
// This won't quite work, but it's close enough for now.
// The trouble is that the top selection =! top clipboard
// but we don't track that yet. We will....
auto top = m_last;
auto top = history()->first();
if ( top ) {
setClipboard( *top, selectionMode ? Selection : Clipboard);
}
......@@ -721,7 +731,7 @@ void Klipper::checkClipData( bool selectionMode )
}
if ( changed && clipEmpty && m_bNoNullClipboard ) {
auto top = m_last;
auto top = history()->first();
if ( top ) {
// keep old clipboard after someone set it to null
qCDebug(KLIPPER_LOG) << "Resetting clipboard (Prevent empty clipboard)";
......@@ -992,7 +1002,6 @@ void Klipper::slotAskClearHistory()
KMessageBox::Dangerous);
if (clearHist == KMessageBox::Yes) {
history()->slotClear();
slotClearClipboard();
saveHistory();
}
......
......@@ -145,6 +145,8 @@ private Q_SLOTS:
void newClipData( QClipboard::Mode );
void slotClearClipboard();
void slotHistoryChanged();
void slotQuit();
void slotStartShowTimer();
......@@ -159,8 +161,6 @@ private:
QClipboard* m_clip;
QSharedPointer<HistoryItem> m_last;
QElapsedTimer m_showTimer;
History* m_history;
......
Markdown is supported
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