You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
240 lines
6.2 KiB
240 lines
6.2 KiB
/* This file is part of the KDE project |
|
Copyright (C) 2004 Esben Mose Hansen <kde@mosehansen.dk> |
|
Copyright (C) by Andrew Stanley-Jones <asj@cban.com> |
|
Copyright (C) 2000 by Carsten Pfeiffer <pfeiffer@kde.org> |
|
Copyright (C) 2014 by Martin Gräßlin <mgraesslin@kde.org> |
|
|
|
This program is free software; you can redistribute it and/or |
|
modify it under the terms of the GNU General Public |
|
License as published by the Free Software Foundation; either |
|
version 2 of the License, or (at your option) any later version. |
|
|
|
This program is distributed in the hope that it will be useful, |
|
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
General Public License for more details. |
|
|
|
You should have received a copy of the GNU General Public License |
|
along with this program; see the file COPYING. If not, write to |
|
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
|
Boston, MA 02110-1301, USA. |
|
*/ |
|
#include "history.h" |
|
|
|
#include <QAction> |
|
|
|
#include "historyitem.h" |
|
#include "historystringitem.h" |
|
#include "historymodel.h" |
|
|
|
class CycleBlocker |
|
{ |
|
public: |
|
CycleBlocker(); |
|
~CycleBlocker(); |
|
|
|
static bool isBlocked(); |
|
private: |
|
static int s_blocker; |
|
}; |
|
|
|
int CycleBlocker::s_blocker = 0; |
|
CycleBlocker::CycleBlocker() |
|
{ |
|
s_blocker++; |
|
} |
|
|
|
CycleBlocker::~CycleBlocker() |
|
{ |
|
s_blocker--; |
|
} |
|
|
|
bool CycleBlocker::isBlocked() |
|
{ |
|
return s_blocker; |
|
} |
|
|
|
History::History( QObject* parent ) |
|
: QObject( parent ), |
|
m_topIsUserSelected( false ), |
|
m_model(new HistoryModel(this)) |
|
{ |
|
connect(m_model, &HistoryModel::rowsInserted, this, |
|
[this](const QModelIndex &parent, int start) { |
|
Q_UNUSED(parent) |
|
if (start == 0) { |
|
emit topChanged(); |
|
} |
|
emit changed(); |
|
} |
|
); |
|
connect(m_model, &HistoryModel::rowsMoved, this, |
|
[this](const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationRow) { |
|
Q_UNUSED(sourceParent) |
|
Q_UNUSED(sourceEnd) |
|
Q_UNUSED(destinationParent) |
|
if (sourceStart == 0 || destinationRow == 0) { |
|
emit topChanged(); |
|
} |
|
emit changed(); |
|
} |
|
); |
|
connect(m_model, &HistoryModel::rowsRemoved, this, |
|
[this](const QModelIndex &parent, int start) { |
|
Q_UNUSED(parent) |
|
if (start == 0) { |
|
emit topChanged(); |
|
} |
|
emit changed(); |
|
} |
|
); |
|
connect(m_model, &HistoryModel::modelReset, this, &History::changed); |
|
connect(m_model, &HistoryModel::modelReset, this, &History::topChanged); |
|
connect(this, &History::topChanged, |
|
[this]() { |
|
m_topIsUserSelected = false; |
|
if (!CycleBlocker::isBlocked()) { |
|
m_cycleStartUuid = QByteArray(); |
|
} |
|
} |
|
); |
|
} |
|
|
|
|
|
History::~History() { |
|
} |
|
|
|
void History::insert(HistoryItemPtr item) { |
|
if ( !item ) |
|
return; |
|
|
|
m_model->insert(item); |
|
|
|
} |
|
|
|
void History::forceInsert(HistoryItemPtr item) { |
|
if ( !item ) |
|
return; |
|
// TODO: do we need a force insert in HistoryModel |
|
m_model->insert(item); |
|
} |
|
|
|
void History::remove( const HistoryItemConstPtr &newItem ) { |
|
if ( !newItem ) |
|
return; |
|
|
|
m_model->remove(newItem->uuid()); |
|
} |
|
|
|
|
|
void History::slotClear() { |
|
m_model->clear(); |
|
} |
|
|
|
void History::slotMoveToTop(QAction* action) { |
|
QByteArray uuid = action->data().toByteArray(); |
|
if (uuid.isNull()) // not an action from popupproxy |
|
return; |
|
|
|
slotMoveToTop(uuid); |
|
} |
|
|
|
void History::slotMoveToTop(const QByteArray& uuid) { |
|
const QModelIndex item = m_model->indexOf(uuid); |
|
if (item.isValid() && item.row() == 0) { |
|
// The item is already at the top, but it still may be not be set as the actual clipboard |
|
// contents, normally this happens if the item is only in the X11 mouse selection but |
|
// not in the Ctrl+V clipboard. |
|
emit topChanged(); |
|
m_topIsUserSelected = true; |
|
emit topIsUserSelectedSet(); |
|
return; |
|
} |
|
m_model->moveToTop(uuid); |
|
m_topIsUserSelected = true; |
|
emit topIsUserSelectedSet(); |
|
} |
|
|
|
void History::setMaxSize( unsigned max_size ) { |
|
m_model->setMaxSize(max_size); |
|
} |
|
|
|
void History::cycleNext() { |
|
if (m_model->rowCount() < 2) { |
|
return; |
|
} |
|
|
|
if (m_cycleStartUuid.isEmpty()) { |
|
m_cycleStartUuid = m_model->index(0).data(Qt::UserRole+1).toByteArray(); |
|
} else if (m_cycleStartUuid == m_model->index(1).data(Qt::UserRole+1).toByteArray()) { |
|
// end of cycle |
|
return; |
|
} |
|
CycleBlocker blocker; |
|
m_model->moveTopToBack(); |
|
} |
|
|
|
void History::cyclePrev() { |
|
if (m_cycleStartUuid.isEmpty()) { |
|
return; |
|
} |
|
CycleBlocker blocker; |
|
m_model->moveBackToTop(); |
|
if (m_cycleStartUuid == m_model->index(0).data(Qt::UserRole+1).toByteArray()) { |
|
m_cycleStartUuid = QByteArray(); |
|
} |
|
} |
|
|
|
|
|
HistoryItemConstPtr History::nextInCycle() const |
|
{ |
|
if (m_model->hasIndex(1, 0)) { |
|
if (!m_cycleStartUuid.isEmpty()) { |
|
// check whether we are not at the end |
|
if (m_cycleStartUuid == m_model->index(1).data(Qt::UserRole+1).toByteArray()) { |
|
return HistoryItemConstPtr(); |
|
} |
|
} |
|
return m_model->index(1).data(Qt::UserRole).value<HistoryItemConstPtr>(); |
|
} |
|
return HistoryItemConstPtr(); |
|
|
|
} |
|
|
|
HistoryItemConstPtr History::prevInCycle() const |
|
{ |
|
if (m_cycleStartUuid.isEmpty()) { |
|
return HistoryItemConstPtr(); |
|
} |
|
return m_model->index(m_model->rowCount() - 1).data(Qt::UserRole).value<HistoryItemConstPtr>(); |
|
} |
|
|
|
HistoryItemConstPtr History::find(const QByteArray& uuid) const |
|
{ |
|
const QModelIndex index = m_model->indexOf(uuid); |
|
if (!index.isValid()) { |
|
return HistoryItemConstPtr(); |
|
} |
|
return index.data(Qt::UserRole).value<HistoryItemConstPtr>(); |
|
} |
|
|
|
bool History::empty() const |
|
{ |
|
return m_model->rowCount() == 0; |
|
} |
|
|
|
unsigned int History::maxSize() const |
|
{ |
|
return m_model->maxSize(); |
|
} |
|
|
|
HistoryItemConstPtr History::first() const |
|
{ |
|
const QModelIndex index = m_model->index(0); |
|
if (!index.isValid()) { |
|
return HistoryItemConstPtr(); |
|
} |
|
return index.data(Qt::UserRole).value<HistoryItemConstPtr>(); |
|
} |
|
|
|
|
|
|