Blob Blame History Raw
/*
    Copyright (c) 2017, Lukas Holecek <hluk@email.cz>

    This file is part of CopyQ.

    CopyQ 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 3 of the License, or
    (at your option) any later version.

    CopyQ 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 CopyQ.  If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef CLIPBOARDMODEL_H
#define CLIPBOARDMODEL_H

#include "item/clipboarditem.h"

#include <QAbstractListModel>
#include <QList>

/**
 * Container with clipboard items.
 *
 * Item prepending is optimized.
 */
class ClipboardItemList {
public:
    ClipboardItem &operator [](int i)
    {
        return m_items[i];
    }

    const ClipboardItem &operator [](int i) const
    {
        return m_items[i];
    }

    void insert(int row, const ClipboardItem &item)
    {
        m_items.insert(row, item);
    }

    void remove(int row, int count)
    {
        const QList<ClipboardItem>::iterator from = m_items.begin() + row;
        const QList<ClipboardItem>::iterator to = from + count;
        m_items.erase(from, to);
    }

    int size() const
    {
        return m_items.size();
    }

    void move(int from, int to)
    {
        const ClipboardItem item = m_items[from];
        m_items.removeAt(from);
        m_items.insert(to, item);
    }

    void move(int from, int count, int to);

    void reserve(int maxItems)
    {
        m_items.reserve(maxItems);
    }

    void resize(int size)
    {
        if (size < this->size())
            remove(size, this->size());

        while (size > this->size())
            m_items.append(ClipboardItem());
    }

private:
    QList<ClipboardItem> m_items;
};

/**
 * Model containing ClipboardItem objects.
 *
 * Class implements QAbstractListModel interface.
 *
 * Clipboard item in model can be serialized and deserialized using
 * operators << and >> (see @ref clipboard_model_serialization_operators).
 */
class ClipboardModel : public QAbstractListModel
{
    Q_OBJECT

public:
    /** Return true if @a lhs is less than @a rhs. */
    using CompareItems = bool (const QModelIndex &, const QModelIndex &);

    explicit ClipboardModel(QObject *parent = nullptr);

    /** Return number of items in model. */
    int rowCount(const QModelIndex &parent = QModelIndex()) const override;

    /** Return data for given @a index. */
    QVariant data(const QModelIndex &index, int role) const override;

    /** Return flags for given @a index. */
    Qt::ItemFlags flags(const QModelIndex &index) const override;

    bool setData(const QModelIndex &index, const QVariant &value,
                 int role = Qt::EditRole) override;
    bool insertRows(int position, int rows,
                    const QModelIndex &index = QModelIndex()) override;
    bool removeRows(int position, int rows,
                    const QModelIndex &index = QModelIndex()) override;
    bool moveRows(const QModelIndex &sourceParent, int sourceRow, int rows,
            const QModelIndex &destinationParent, int destinationRow)
#if QT_VERSION < 0x050000
        ;
#else
        override;
#endif

    /** insert new item to model. */
    void insertItem(const QVariantMap &data, int row);

    /**
     * Move an item.
     * @return True only if item was successfully moved.
     */
    bool move(
            int pos, //!< Source row number.
            int newpos //!< Destination row number.
            );
    /**
     * Move items.
     * @return True only if all items was successfully moved.
     */
    bool moveItemsWithKeyboard(
            const QModelIndexList &indexList, //!< Indexed of items to move.
            int key,
            /*!< Key representing direction for movement (can be one of
             *   Qt::Key_Down, Qt::Key_Up, Qt::Key_End, Qt::Key_Home).
             */
            int count = 1
            );

    /**
     * Sort items in ascending order.
     */
    void sortItems(const QModelIndexList &indexList, CompareItems *compare);

    /**
     * Find item with given @a hash.
     * @return Row number with found item or -1 if no item was found.
     */
    int findItem(uint itemHash) const;

    /**
     * Return row index for given @a row.
     * @return Value of @a row if such index is in model.
     * @return -1 if model is empty.
     * @return 0 if @a cycle is true and @a row is bigger than last row index.
     * @return 0 if @a cycle is false and @a row is negative.
     * @return Last row index if @a cycle is false and @a row is bigger than last row index.
     * @return Last row index if @a cycle is true and @a row is negative.
     */
    int getRowNumber(int row, bool cycle = false) const;

public slots:
#if QT_VERSION < 0x050000
    void moveRow(int from, int to) { moveRows(QModelIndex(), from, 1, QModelIndex(), to); }
#endif

private:
    ClipboardItemList m_clipboardList;
};

#endif // CLIPBOARDMODEL_H