2011-08-04 8 views
3

QTreeViewから継承したカスタムモデルがあります。私はドラッグアンドドロップを有効にして、現在ツリーにアイテムをドロップすることができます。ただし、現在、既存のアイテムまたはアイテム間にドロップできます。私はあなたが既存のアイテムにしかドロップできないようにこれを制限したいと思います。Qt QTreeView:既存のアイテムのみドロップ可能

DragDropOverwriteModeをtrueに設定しました(実際はこれがQTreeViewのデフォルトです)。しかし、これはアイテム間のドロップを止めるものではありません。既存のアイテムにドロップすることができます。

私は、行と列が有効であるかどうかをチェックすることでdropMimeData(私が再実装している)の「挿入」ドロップを無視できることを知っています(既存の項目へのドロップは行と列を-1に設定し、現在の項目)と私はこれをやっている。しかし、私はこれらのドロップを取得しないことをお勧めします。つまり私はあなたが常に上の項目または下の項目のいずれかを落として、項目間に決していないようにしたいと思います。

アイデア?あなたは「」任意のアドバイスを

おかげで、 ジャイルズ

+0

答えが見つかりました。 Mattの答えに対するコメントを参照してください。 – giles123

答えて

3

はドラッグがカスタムビューにdragEnterEvent方法を再実装することで、イベントを入力してキャッチする必要があります。 Qtのドキュメントからの例は次のとおりです。あなたの場合は

void Window::dragEnterEvent(QDragEnterEvent *event) 
{ 
    if (event->mimeData()->hasFormat("text/plain")) 
     event->acceptProposedAction(); 
} 

、おそらく最も近い項目または類似した何かのxとyの位置でイベントで、xとyの位置を比較し、拒否または受諾する必要がありますその情報に基づいて提案された行動。

QAbstractItemModel::dropMimeDataドキュメントから:

これは、データを挿入する場所に適した場所を提供するために、図の責任です。

これは、あなたのような基になるモデルによってサポートされているものではない場合、ビューがドロップを拒否するように解釈されています。 trueDragDropOverwriteModeを設定するのQt 5.4(と私はこれもQtの4.8に本当だったと仮定)のよう

+1

返信と有益な情報をありがとう。 dragEnterEventは、最初にウィジェットをドラッグしたときにのみ呼び出されるため、マウスがウィジェット上を移動するときには繰り返し呼び出されないため、適切ではありません。しかし、dragMoveEventメソッドは繰り返し呼び出されるので、私はそれを使うことができると思います。 – giles123

+0

moveEventの矩形とツリー内のすべてのアイテムの矩形を比較するのは非常に複雑です。アイテム間ではなくアイテム上にあるかどうかを判断する簡単な方法はありますか?私はそれが正しいことを行う必要があるように聞こえるdropIndicatorPositionを見てきました。しかし、それは私が項目上であるか項目間で常に0を返します。任意の提案をいただければ幸いです。 – giles123

+2

私はこれまでよりはるかに簡単な方法を見つけました。渡されたインデックスが有効な場合にのみ、Qt :: ItemIsDropEnabledを返すように、基になるモデルのflagsメソッドを再実装します。アイテム間にある場合、無効なインデックスでflags()が呼び出されるので、ドロップを受け入れないようにすることができます。 – giles123

2

は、正しくドラッグだけで、既存のアイテムのドロップ可能にさせると、「上記/項目下の」ドロップターゲットを防ぎます出現から。

また、どのような質問の主張とは異なり、DragDropOverwriteModeは(私は多分それは新しいQtのバージョンだ、チェックしませんでした)QTreeViewにデフォルトでfalseに設定するので、手動でtrueに設定する必要があります。

ただし、アイテムをドロップできる位置を計算できることは、依然として有効です。何かが無効な赤の領域にドロップされた場合

QTreeView invalid drop areas

dropMimeDataがで呼び出されます:QTreeViewの例では、1は、下記の赤い部分、つまり、項目の左余白にドラッグしたものを削除することはできませんparent引数はNULLに設定されています。だから、 dragMoveEventにはのユーザーに「ここにはドロップできません」というカーソルが表示され、そこでドロップできないことがわかっているので、ignoreに役立ちます。(Qtの5.4のように)ドラッグ中Qtは、無効な領域にマウスカーソルを変更し実装していないが、我々はこのようにそれを行うことができます。

bool SubclassedTreeView::dropResultsInValidIndex(const QPoint& pos) 
{ 
    QTreeWidgetItem* item = itemAt(pos); 
    if (item == NULL || !indexFromItem(item).isValid()) 
     return false; 
    return visualRect(indexFromItem(item)).adjusted(-1, -1, 1, 1).contains(pos, false); 
} 

virtual void SubclassedTreeView::dragMoveEvent(QDragMoveEvent* event) 
{ 
    QTreeWidget::dragMoveEvent(event); 
    if (!event->isAccepted()) 
     return; 

    if (dropResultsInValidIndex(event->pos())) 
     event->accept(); 
    else 
     event->ignore(); //Show 'forbidden' cursor. 
} 

virtual bool SubclassedTreeView::dropMimeData(QTreeWidgetItem* parent, int index, const QMimeData* data, Qt::DropAction action) 
{ 
    Q_UNUSED(index); 
    //Modify the following action and data format checks to suit your needs: 
    if (parent == NULL || action != Qt::CopyAction || !data->hasFormat("my/preferred-type")) 
     return false; 

    QModelIndex modelIndex = indexFromItem(parent); 
    //modelIndex is where the data is dropped onto. Implement your custom drop action here... 

    return true; 
} 

上記のコードはQAbstractItemViewPrivate::position源から盗まれた小さな部分visualRect….adjusted(-1, -1, 1, 1)が含まれています。実際には、QAbstractItemViewPrivate::positionfalseの場合、この関数のソースを使用して項目の上書き/挿入/無効領域を計算することができます。

関連する問題