2016-03-28 43 views
1

私はドラッグリスト項目(プレーン/テキスト)を別のQListViewにドラッグ&を実装しようとしています。ドラッグがうまく始まります(テキストドロップを受け付ける別のアプリケーションにアイテムをドロップすることさえできます)が、私の2番目のQListViewは何らかの理由でドロップを受け入れません。ここ は、リストビューで構成された方法です。このリストビューのためのQListViewの外部ドロップが機能しません

ui->lessonsListView->setAcceptDrops(true); 
ui->lessonsListView->setDropIndicatorShown(true); 
ui->lessonsListView->setDragDropMode(QAbstractItemView::DropOnly); 
ui->lessonsListView->setDragDropOverwriteMode(true); 

プロキシモデルは、次のメソッドを実装します。私はsupportedDropActions()flags()と呼ばれていることがわかりアプリケーションの出力から

Qt::ItemFlags LessonsProxyModel::flags(const QModelIndex &index) const 
{ 
    qDebug() << __FUNCTION__; 
    return Qt::ItemIsDropEnabled | QSortFilterProxyModel::flags(index); 
} 

Qt::DropActions LessonsProxyModel::supportedDropActions() const 
{ 
    qDebug() << __FUNCTION__; 
    return Qt::MoveAction; 
} 

bool LessonsProxyModel::canDropMimeData(const QMimeData *data, 
    Qt::DropAction action, int row, int column, const QModelIndex &parent) 
{ 
    qDebug() << __FUNCTION__; 
    Q_UNUSED(action); 
    Q_UNUSED(row); 
    Q_UNUSED(column); 

    if (!data->hasFormat("text/plain") || !parent.isValid()) 
     return false; 

    return true; 
} 

bool LessonsProxyModel::dropMimeData(const QMimeData *data, 
    Qt::DropAction action, int row, int column, const QModelIndex &parent) 
{ 
    qDebug() << __FUNCTION__; 
    if (!canDropMimeData(data, action, row, column, parent)) 
     return false; 

    emit dataDropped(data, parent); 

    return true; 
} 

canDropMimeData()でもdropMimeData()もこれまでに呼ばれていません。私は間違って何をしていますか? ヒントをいただければ幸いです。

ありがとうございました!

EDITED:

念のため: リストビューセットアップ:

ui->abonsListView->setDragEnabled(true); 

proxyModelコード:

Qt::ItemFlags AbonsProxyModel::flags(const QModelIndex &index) const 
{ 
    return Qt::ItemIsDragEnabled | QSortFilterProxyModel::flags(index); 
} 

Qt::DropActions AbonsProxyModel::supportedDragActions() const 
{ 
    qDebug() << __FUNCTION__; 
    return Qt::MoveAction; 
} 

QStringList AbonsProxyModel::mimeTypes() const 
{ 
    qDebug() << __FUNCTION__; 
    QStringList types; 
    types << "text/plain"; 
    return types; 
} 

QMimeData *AbonsProxyModel::mimeData(const QModelIndexList &indexes) const 
{ 
    qDebug() << __FUNCTION__; 
    QMimeData *mimeData = new QMimeData(); 

    foreach (const QModelIndex &index, indexes) 
     if (index.isValid()) 
     { 
      mimeData->setText(data(index, AbonsModel::Id).toString()); 
      qDebug() << __FUNCTION__; 
      return mimeData; 
     } 

    return mimeData; 
} 
+0

私はあなたが 'dragEnterEvent'、' dragMoveEvent'と 'QListView'サブクラスの' dropEvent'をオーバーライドする必要があり、信じています。 [documentation](http://doc.qt.io/qt-5/dnd.html)と[examples](http://doc.qt.io/qt-5/examples-draganddrop)をご覧ください。 html) – Marcus

+0

ありがとう!試してみます。しかし、上記のドキュメントでは、「このドキュメントでは、基本的なドラッグ&ドロップのメカニズムについて説明し、カスタムコントロールでそれを有効にするためのアプローチについて概説しています」と、「アイテムビューでドラッグ&ドロップを使用する」リンクの手順をたどりました。また、サブクラス化せずに別のリストビューに最適な作業をドラッグすると、アイテムビューにドラッグ&ドロップがすでにサポートされています。 –

+0

はいドラッグが完全に実装されています。ただし、ドロップが期待通りに機能しません。 QFileSystemModelとファイルブラウザ(イルカ)を組み合わせた 'QListView'を使って簡単なドラッグアンドドロップ実験を試みました。 'QListView'からイルカへのドラッグはすごく効果的ですが、それ以外の方法は受け入れられません。だから私は、ドロップを実行しようとしているウィジェットの 'dragEnterEvent'、' dragMoveEvent'と 'dropEvent'を設定しなければならないと思います。 – Marcus

答えて

1

を呼び出すことができるように

ですから、上記の持っているコードに加えて、あなたはMUSTはdragEnterEventdragMoveEventと受信ViewdropEventを上書き私は最終的に見つけました回答!私はこのコードを書き始めたとき、私はQtのドキュメントUsing Drag and Drop with Item Viewsからいくつかの作品をcopypasted、この記事では、彼らはただcanDropMimeData()の再実装のためのconst指定子を逃しました。したがって、canDropMimeData()の私のバージョンは非仮想になり、QListViewはちょうど基底クラスQAbstractProxyModelからメソッドを呼び出しました。私はconstを追加しました - そして、すべてはサブクラス化なしで魅力的に働いています。

0
以下に開始され、それらのドラッグからリストビューとモデルのソースコードはあります

私はプロキシモデルに関する多くの経験がありません。ドキュメントを見て、私はこれらの2つの機能が何であるかについて大まかに考えていると思います。これらの関数は自動的に呼び出されません。あなたはあなたの視点からそれらを「呼び出す」必要があります。

まず、正しいデータがあるかどうかを確認することはモデルの作業です。したがって、これらは、作業を簡単にするためのモデルの2つの便利な機能です。これらはモデル固有の関数であり、汎用関数ではないため、抽象モデルでは決して定義されません。

このシナリオを検討してください。どこかからQMimeDataオブジェクトがビューにドロップされます。このデータが正しいタイプであるかどうかをどのように知っていますか?データが正しいタイプであるかどうかは誰が決定するのですか?

Model-Viewフレームワークでは、Viewは塗装のみを行います。 Modelまでは、どのようにデータを処理するか、何を表示するか、受け入れ可能かどうかなどを決める必要があります。したがって、データがViewにドロップされた場合は、Modelに送信して、ドロップされたデータがModelの要件を満たしているかどうかを確認する必要があります。この仕事をするフックはbool Model::canDropMimeData(...)です。

許容できる場合、データの処理もModelによって実行する必要があります。再度、Modelにデータを送信する必要があります。このフックはbool Model::dropMimeData(...)です。

データが正常に処理されたかどうかをどのように知っていますか?戻り値をチェック!データが正常に処理された場合は、おそらくViewを更新する必要があります。あなたはcanDropMimeData(...)dropMimeData(...)

/* You need to allow the drag to enter the widget/view. */ 
/* This is a must. */ 
void TargetView::dragEnterEvent(QDragEnterEvent *deEvent) { 

    deEvent->acceptProposedAction(); 
}; 

/* This is optional. Use this to check if the data can be */ 
/* dropped at the current mouse position. Example: In a */ 
/* FileSystem View, it makes no sense to drop a bunch of */ 
/* files on top of a file, but makes sense it you drop it */ 
/* in an empty space or on a folder */ 
void TargetView::dragMoveEvent(QDragMoveEvent *dmEvent) { 
    /* You can do something like this */ 
    if (indexAt(dmEvent->pos()).isValid()) { 
     /* You cannot drop it on an existing index */ 
     /* If you ignore it, the cursor changes to */ 
     /* 'don't drop' image */ 
     dmEvent->ignore(); 
    } 

    else { 
     /* Empty space. Tell the user to feel free */ 
     /* to perform the drop. We accept the event */ 
     /* Cursor shows the drag+drop icon */ 
     dmEvent->accept(); 
    } 
}; 

void TargetView::dropEvent(QDropEvent *dpEvent) { 
    /* Here is where you call canDropMimeData and dropMimeData */ 
    QMimeData *mData = dpEvent->mimeData(); 
    if (model->canDropMimeData(mData, ..., ..., ..., ...)) { 
     /* Add the data to the model */ 
     bool updated = model->dropMimeData(mData, ..., ..., ..., ...); 
     if (updated) { 
      /* Intimate the view to update itself */ 
      update(); 
     } 
    } 
}; 
関連する問題