Interface cleanups for drag and drop support

This commit is contained in:
Peter Penz 2011-08-24 18:11:55 +02:00
parent 6e0d247d31
commit 8401080778
10 changed files with 96 additions and 77 deletions

View file

@ -27,6 +27,7 @@
#include <KStringHandler>
#include <KDebug>
#include <KIcon>
#include <QTextLine>
#include <QTimer>
@ -46,6 +47,8 @@ KFileItemListView::KFileItemListView(QGraphicsWidget* parent) :
m_updateIconSizeTimer(0),
m_minimumRolesWidths()
{
setAcceptDrops(true);
setScrollOrientation(Qt::Vertical);
setWidgetCreator(new KItemListWidgetCreator<KFileItemListWidget>());
setGroupHeaderCreator(new KItemListGroupHeaderCreator<KItemListGroupHeader>());
@ -204,6 +207,26 @@ QHash<QByteArray, QSizeF> KFileItemListView::visibleRoleSizes() const
return sizes;
}
QPixmap KFileItemListView::createDragPixmap(const QSet<int>& indexes) const
{
QPixmap pixmap;
if (model()) {
QSetIterator<int> it(indexes);
while (it.hasNext()) {
const int index = it.next();
// TODO: Only one item is considered currently
pixmap = model()->data(index).value("iconPixmap").value<QPixmap>();
if (pixmap.isNull()) {
KIcon icon(model()->data(index).value("iconName").toString());
pixmap = icon.pixmap(itemSize().toSize());
}
}
}
return pixmap;
}
void KFileItemListView::initializeItemListWidget(KItemListWidget* item)
{
KFileItemListWidget* fileItemListWidget = static_cast<KFileItemListWidget*>(item);

View file

@ -48,9 +48,15 @@ public:
void setItemLayout(Layout layout);
Layout itemLayout() const;
/** @reimp */
virtual QSizeF itemSizeHint(int index) const;
/** @reimp */
virtual QHash<QByteArray, QSizeF> visibleRoleSizes() const;
/** @reimp */
virtual QPixmap createDragPixmap(const QSet<int>& indexes) const;
protected:
virtual void initializeItemListWidget(KItemListWidget* item);
virtual void onModelChanged(KItemModelBase* current, KItemModelBase* previous);

View file

@ -24,6 +24,7 @@
#include <KStringHandler>
#include <KDebug>
#include <QMimeData>
#include <QTimer>
#define KFILEITEMMODEL_DEBUG
@ -132,6 +133,27 @@ bool KFileItemModel::supportsSorting() const
return true;
}
QMimeData* KFileItemModel::createMimeData(const QSet<int>& indexes) const
{
QMimeData* data = new QMimeData();
KUrl::List urls;
urls.reserve(indexes.count());
QSetIterator<int> it(indexes);
while (it.hasNext()) {
const int index = it.next();
const KUrl url = fileItem(index).url();
if (url.isValid() && !url.isEmpty()) {
urls.append(url);
}
}
urls.populateMimeData(data);
return data;
}
KFileItem KFileItemModel::fileItem(int index) const
{
if (index >= 0 && index < count()) {

View file

@ -66,6 +66,9 @@ public:
*/
virtual bool supportsSorting() const;
/** @reimp */
virtual QMimeData* createMimeData(const QSet<int>& indexes) const;
/**
* @return The file-item for the index \a index. If the index is in a valid
* range it is assured that the file-item is not null. The runtime

View file

@ -26,11 +26,6 @@
#include "kitemlistrubberband_p.h"
#include "kitemlistselectionmanager.h"
// TODO: Remove after moving mimeData() and createDropPixmap() into
// KFileItemModel/KFileItemListView
#include "kfileitemmodel.h"
#include <KIcon>
#include <QApplication>
#include <QDrag>
#include <QEvent>
@ -661,70 +656,26 @@ void KItemListController::slotRubberBandChanged()
m_selectionManager->setSelectedItems(selectedItems + m_oldSelection);
}
QPixmap KItemListController::createDragPixmap(const QSet<int>& indexes) const
{
if (!m_model || !m_view) {
return QPixmap();
}
// TODO: The current hack assumes a property "iconPixmap" in the model. The method
// will get an interface of KFileItemList later.
QSetIterator<int> it(indexes);
while (it.hasNext()) {
const int index = it.next();
// TODO: Only one item is considered currently
QPixmap pixmap = m_model->data(index).value("iconPixmap").value<QPixmap>();
if (pixmap.isNull()) {
KIcon icon(m_model->data(index).value("iconName").toString());
const QSizeF size = m_view->itemSize();
pixmap = icon.pixmap(size.toSize());
}
return pixmap;
}
return QPixmap();
}
QMimeData* KItemListController::createMimeData(const QSet<int>& indexes) const
{
if (!m_model) {
return 0;
}
QMimeData* data = new QMimeData();
// TODO: Check KDirModel::mimeData() for a good reference implementation
KUrl::List urls;
QSetIterator<int> it(indexes);
while (it.hasNext()) {
const int index = it.next();
// TODO: Big hack to use KFileItemModel here. Remove after moving mimeData()
// into KFileItemModel.
KFileItemModel* model = qobject_cast<KFileItemModel*>(m_model);
Q_ASSERT(model);
const KUrl url = model->fileItem(index).url();
urls.append(url);
}
urls.populateMimeData(data);
return data;
}
void KItemListController::startDragging()
{
if (!m_view || !m_model) {
return;
}
const QSet<int> selectedItems = m_selectionManager->selectedItems();
QMimeData* data = m_model->createMimeData(selectedItems);
if (!data) {
return;
}
// The created drag object will be owned and deleted
// by QApplication::activeWindow().
QDrag* drag = new QDrag(QApplication::activeWindow());
const QSet<int> selectedItems = m_selectionManager->selectedItems();
const QPixmap pixmap = createDragPixmap(selectedItems);
drag->setPixmap(pixmap);
QMimeData* data = createMimeData(selectedItems);
drag->setMimeData(data);
const QPixmap pixmap = m_view->createDragPixmap(selectedItems);
drag->setPixmap(pixmap);
drag->exec(Qt::MoveAction | Qt::CopyAction | Qt::LinkAction, Qt::IgnoreAction);
}

View file

@ -133,19 +133,6 @@ private slots:
void slotRubberBandChanged();
private:
/**
* @return Pixmap that is used for a drag operation based on the
* items given by \a indexes.
* TODO: Will be moved to KItemListView later
*/
QPixmap createDragPixmap(const QSet<int>& indexes) const;
/**
* @return MIME-data for the items given by \a indexes.
* TODO: Will be moved to KItemListView or KItemModelBase/KFileItemModel later.
*/
QMimeData* createMimeData(const QSet<int>& indexes) const;
/**
* Creates a QDrag object to start a drag-operation.
*/

View file

@ -66,7 +66,6 @@ KItemListView::KItemListView(QGraphicsWidget* parent) :
m_mousePos()
{
setAcceptHoverEvents(true);
setAcceptDrops(true);
m_sizeHintResolver = new KItemListSizeHintResolver(this);
@ -359,6 +358,12 @@ bool KItemListView::isTransactionActive() const
return m_activeTransactions > 0;
}
QPixmap KItemListView::createDragPixmap(const QSet<int>& indexes) const
{
Q_UNUSED(indexes);
return QPixmap();
}
void KItemListView::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget)
{
QGraphicsWidget::paint(painter, option, widget);

View file

@ -155,10 +155,17 @@ public:
void endTransaction();
bool isTransactionActive() const;
/**
* @return Pixmap that is used for a drag operation based on the
* items given by \a indexes. The default implementation returns
* a null-pixmap.
*/
virtual QPixmap createDragPixmap(const QSet<int>& indexes) const;
/**
* @reimp
*/
virtual void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget = 0);
virtual void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget = 0);
signals:
void offsetChanged(qreal current, qreal previous);

View file

@ -103,6 +103,12 @@ QString KItemModelBase::roleDescription(const QByteArray& role) const
return role;
}
QMimeData* KItemModelBase::createMimeData(const QSet<int>& indexes) const
{
Q_UNUSED(indexes);
return 0;
}
void KItemModelBase::onGroupRoleChanged(const QByteArray& current, const QByteArray& previous)
{
Q_UNUSED(current);

View file

@ -30,6 +30,8 @@
#include <QSet>
#include <QVariant>
class QMimeData;
struct KItemRange
{
KItemRange(int index, int count);
@ -107,6 +109,13 @@ public:
virtual QString roleDescription(const QByteArray& role) const;
/**
* @return MIME-data for the items given by \a indexes. The default implementation
* returns 0. The ownership of the returned instance is in the hand of the
* caller of this method.
*/
virtual QMimeData* createMimeData(const QSet<int>& indexes) const;
signals:
/**
* Is emitted if one or more items have been inserted. Each item-range consists