Results 1 to 13 of 13

Thread: QtTreeWidget: issue with indicator display

  1. #1
    Join Date
    Jun 2010
    Posts
    8
    Qt products
    Qt4
    Platforms
    Windows

    Question QtTreeWidget: issue with indicator display

    Hi,

    It seems part of this question has already been asked a few time, but I haven't been able to find any matching answer until now, so I decided to create a new post.

    I have a tree containing my scene graph, using a custom derived QtTreeWidget class directly (no model/view):

    qt.png

    Now, I have two issues, which are linked together I guess, related to moving items within the tree:


    1. first of all, no drop indicator is being shown, although I think I have called the right code:
      Qt Code:
      1. setAcceptDrops(imTRUE);
      2. setDragEnabled(true);
      3. setDragDropMode(DragDrop);
      4. setDragDropOverwriteMode(imFALSE);
      5. setDropIndicatorShown(imTRUE);
      6.  
      7. setSelectionMode(QAbstractItemView::SingleSelection);
      8. setSelectionBehavior(QAbstractItemView::SelectRows);
      To copy to clipboard, switch view to plain text mode 
      I have tried to derive my own style and experiment with QStyle::PE_IndicatorItemViewItemDrop, but without any success.
      I have also tried to draw a custom line by myself, but I can't figure out where it should be drawn exactly (see point 2 below).

    2. it is very hard to precisely define where the node will be dropped. More precisely, I can't figure out why the node gets sometimes added as child of the target, and sometimes it gets added before or after the target item. I know the position of the cursor defines this behaviour, however, without any visual indicator, this is really hard to use.


    Any help would be appreciated, I have had this issue for month now
    Thanks guys !

  2. #2
    Join Date
    Sep 2011
    Location
    Manchester
    Posts
    538
    Thanks
    3
    Thanked 106 Times in 103 Posts
    Qt products
    Qt4 Qt/Embedded
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: QtTreeWidget: issue with indicator display

    IMHO you should drop point 2 and fix point 1 (which solves both issues).

    As to why it happens, can't tell.
    Would be easier if your example be compilable
    Only thing that comes to my mind is that you turn off the indicator somewhere.

    Do you reimplement paint event of that widget?

  3. #3
    Join Date
    Jun 2011
    Posts
    56
    Thanks
    7
    Qt products
    Qt4

    Default Re: QtTreeWidget: issue with indicator display

    I'd take a look at your:

    Qt::ItemFlags QTreeWidgetItem::flags () const

    and check if you return Qt::ItemIsDragEnabled, but this might just as well not be the case, as you can drag&drop, but don't see the indicator. Can you try on some other OS, such as linux? I'd install arch linux in a virtual machine (it always has the latest Qt) and see how things go in there?

  4. #4
    Join Date
    Jun 2010
    Posts
    8
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: QtTreeWidget: issue with indicator display

    Thanks guys for your answer, I really appreciate.

    @Spitfire: you are right, that's basically what I am trying to achieve. I have checked my code, I don't disable the indicator anywhere. Unfortunately it's not easy to make a compilable example, some work is involved, but I will do it if I can't find any solution soon.
    I have overriden the paint event, however currently all it does is calling the base class (QtTreeWidget) paint method. So that's not the problem.

    @ugluk: the flags seems to be fine, I added the piece of code below for each created item, the flag returned by flags() is 61 (decimal) and its value is not modified by the line just below:

    Qt Code:
    1. Qt::ItemFlags flag = pItem->flags();
    2. flag |= Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled;
    3. pItem->setFlags(flag);
    To copy to clipboard, switch view to plain text mode 

    Below the full relevant code of my class:

    Qt Code:
    1. //////////////////////////////////////////////////////////////////////////
    2.  
    3. class imQMimeData : public QMimeData
    4. {
    5. public :
    6.  
    7. imQMimeData () : QMimeData ()
    8. {
    9. m_eDropAction = Qt::MoveAction;
    10. }
    11.  
    12. virtual ~imQMimeData () {}
    13.  
    14. imNode* GetNode(void) const { return m_pNode; }
    15. void SetNode(imNode* _pNode) { m_pNode = _pNode; }
    16.  
    17. QTreeWidgetItem* GetItem(void) const { return m_pItem; }
    18. void SetItem(QTreeWidgetItem* _pItem) { m_pItem = _pItem; }
    19.  
    20. imU32 GetOldIndex() const { return m_nOldIndex; }
    21. void SetOldIndex(imU32 _nIndex) { m_nOldIndex = _nIndex; }
    22.  
    23. public :
    24.  
    25. imNode* m_pNode;
    26. QTreeWidgetItem* m_pItem;
    27. imU32 m_nOldIndex;
    28. Qt::DropAction m_eDropAction;
    29. };
    30.  
    31. //////////////////////////////////////////////////////////////////////////
    32.  
    33. imGuiSceneExplorer::imGuiSceneExplorer(QWidget * parent) : QTreeWidget(parent), imIStreamingCallback()
    34. {
    35. m_pScene = imNULL;
    36. m_bBuildingTree = imFALSE;
    37. m_pUI = imNULL;
    38. }
    39.  
    40.  
    41. //////////////////////////////////////////////////////////////////////////
    42.  
    43. imGuiSceneExplorer::~imGuiSceneExplorer()
    44. {
    45. clear();
    46. }
    47.  
    48. //////////////////////////////////////////////////////////////////////////
    49.  
    50. void imGuiSceneExplorer::SetUI(Ui::imGuiMainWindowClass* _pUI)
    51. {
    52. m_pUI = _pUI;
    53.  
    54. setColumnCount(2);
    55.  
    56. headerItem()->setText(0, tr("Name"));
    57. headerItem()->setText(1, tr("Type"));
    58.  
    59. header()->setResizeMode(0, QHeaderView::ResizeToContents);
    60. header()->setResizeMode(1, QHeaderView::ResizeToContents);
    61.  
    62. // drag & drop
    63. setAcceptDrops(imTRUE);
    64. setDragEnabled(true);
    65. setDragDropMode(DragDrop);
    66. setDragDropOverwriteMode(imFALSE);
    67. setDropIndicatorShown(imTRUE);
    68.  
    69. setSelectionMode(QAbstractItemView::SingleSelection);
    70. setSelectionBehavior(QAbstractItemView::SelectRows);
    71.  
    72. // context menu
    73. setContextMenuPolicy(Qt::CustomContextMenu);
    74. connect(this, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(ShowTreeContextMenu(const QPoint&)));
    75. }
    76.  
    77. //////////////////////////////////////////////////////////////////////////
    78.  
    79. QSize imGuiSceneExplorer::sizeHint() const
    80. {
    81. QSize theSize(256, 768);
    82. return theSize;
    83. }
    84.  
    85. //////////////////////////////////////////////////////////////////////////
    86.  
    87. void imGuiSceneExplorer::SelectNode(imNode* _pNode)
    88. {
    89. while (*it)
    90. {
    91. imNode* pNode = GetNodeFromItem(*it);
    92. if (pNode == _pNode)
    93. {
    94. setCurrentItem(*it);
    95.  
    96. if (m_pScene)
    97. m_pScene->SetSelectedNode(_pNode);
    98.  
    99. return;
    100. }
    101. ++it;
    102. }
    103. }
    104.  
    105. //////////////////////////////////////////////////////////////////////////
    106.  
    107. imNode* imGuiSceneExplorer::GetNodeFromItem(QTreeWidgetItem* _pItem)
    108. {
    109. if (!_pItem)
    110. return imNULL;
    111. return *(imNode**)_pItem->data(0, Qt::UserRole).toByteArray().constData();
    112. }
    113.  
    114. //////////////////////////////////////////////////////////////////////////
    115.  
    116. void imGuiSceneExplorer::BuildContent( imScene* _pScene )
    117. {
    118. clear();
    119.  
    120. m_pScene = _pScene;
    121. if (!_pScene)
    122. return;
    123.  
    124. // create top level item
    125. m_bBuildingTree = imTRUE;
    126. imNode* pRoot = _pScene->GetRootNode();
    127. AddNodeItem(pRoot, imNULL, -1);
    128. m_bBuildingTree = imFALSE;
    129. }
    130.  
    131. //////////////////////////////////////////////////////////////////////////
    132.  
    133. QTreeWidgetItem* imGuiSceneExplorer::CreateItemFromNode(imNode* _pNode)
    134. {
    135. imAssert(_pNode);
    136. if (_pNode)
    137. {
    138. QTreeWidgetItem* pItem = imNew QTreeWidgetItem();
    139. Qt::ItemFlags flag = pItem->flags();
    140. flag |= Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled;
    141. pItem->setFlags(flag);
    142.  
    143. // node name
    144. imStringBase sName(_pNode->GetName().GetLength() ? _pNode->GetName() : _pNode->RTTIGetClass()->getName());
    145. QString sQName = QString::fromWCharArray((const wchar_t*)sName);
    146. pItem->setText(0, sQName);
    147.  
    148. // node type
    149. imStringBase sType(_pNode->RTTIGetClass()->getName());
    150. QString sQType = QString::fromWCharArray((const wchar_t*)sType);
    151. pItem->setText(1, sQType);
    152.  
    153. // set data
    154. QByteArray data((const char *)&_pNode, sizeof(_pNode));
    155. QVariant oVariant(data);
    156. pItem->setData( 0, Qt::UserRole, oVariant);
    157.  
    158. return pItem;
    159. }
    160. return imNULL;
    161. }
    162.  
    163. //////////////////////////////////////////////////////////////////////////
    164.  
    165. void imGuiSceneExplorer::rowsInserted ( const QModelIndex & parent, int start, int end )
    166. {
    167. if (!m_bBuildingTree)
    168. {
    169. QTreeWidgetItem* pItemParent = itemFromIndex(parent);
    170. if (pItemParent)
    171. {
    172. imNode* pParent = GetNodeFromItem(pItemParent);
    173. if (pParent)
    174. {
    175. for (imInt i = start; i <= end; ++i)
    176. {
    177. QTreeWidgetItem* pItemChild = pItemParent->child(i);
    178. imNode* pChild = GetNodeFromItem(pItemChild);
    179. pParent->InsertChild(pChild, i);
    180. }
    181. }
    182. }
    183. }
    184.  
    185. QTreeWidget::rowsInserted(parent,start,end);
    186. }
    187.  
    188. //////////////////////////////////////////////////////////////////////////
    189.  
    190. void imGuiSceneExplorer::rowsAboutToBeRemoved ( const QModelIndex & parent, int start, int end )
    191. {
    192. if (!m_bBuildingTree)
    193. {
    194. QTreeWidgetItem* pItemParent = itemFromIndex(parent);
    195. imNode* pParent = GetNodeFromItem(pItemParent);
    196.  
    197. for (imInt i = start; i <= end; ++i)
    198. {
    199. QTreeWidgetItem* pItemChild = pItemParent->child(i);
    200. imNode* pChild = GetNodeFromItem(pItemChild);
    201. pParent->RemoveChild(i, imFALSE);
    202. }
    203. }
    204.  
    205. QTreeWidget::rowsAboutToBeRemoved(parent,start,end);
    206. }
    207.  
    208. //////////////////////////////////////////////////////////////////////////
    209.  
    210. QMimeData *imGuiSceneExplorer::mimeData(const QList<QTreeWidgetItem *> items) const
    211. {
    212. imAssert(items.size());
    213. if (items.size())
    214. {
    215. imQMimeData *mimeData = imNew imQMimeData();
    216. imNode* pNode = *(imNode**)items[0]->data(0, Qt::UserRole).toByteArray().constData();
    217. mimeData->SetNode(pNode);
    218. mimeData->SetItem(items[0]);
    219. mimeData->SetOldIndex(items[0]->parent() ? items[0]->parent()->indexOfChild(items[0]) : 0);
    220.  
    221. return mimeData;
    222. }
    223. return imNULL;
    224. }
    225.  
    226. //////////////////////////////////////////////////////////////////////////
    227.  
    228. bool imGuiSceneExplorer::dropMimeData(QTreeWidgetItem *parent, int index, const QMimeData *data, Qt::DropAction action)
    229. {
    230. if (action == Qt::IgnoreAction)
    231. return true;
    232.  
    233. if (parent)
    234. {
    235. const imQMimeData* myData = static_cast<const imQMimeData *>(data);
    236. if (myData && parent != myData->GetItem())
    237. {
    238. imNode* pNode = myData->GetNode();
    239. AddNodeItem(pNode, parent, index);
    240. }
    241. }
    242. return true;
    243. }
    244.  
    245. //////////////////////////////////////////////////////////////////////////
    246.  
    247. void imGuiSceneExplorer::dragEnterEvent ( QDragEnterEvent * event )
    248. {
    249. QTreeWidget::dragEnterEvent(event);
    250.  
    251. event->accept();
    252. }
    253.  
    254. //////////////////////////////////////////////////////////////////////////
    255.  
    256. void imGuiSceneExplorer::dragMoveEvent ( QDragMoveEvent * event )
    257. {
    258. QTreeWidget::dragMoveEvent(event);
    259.  
    260. event->accept();
    261. }
    262.  
    263. //////////////////////////////////////////////////////////////////////////
    264.  
    265. void imGuiSceneExplorer::paintEvent( QPaintEvent* event )
    266. {
    267. QTreeWidget::paintEvent (event);
    268. }
    269.  
    270. //////////////////////////////////////////////////////////////////////////
    271.  
    272. void imGuiSceneExplorer::OnItemSelected()
    273. {
    274. // do something
    275. }
    276.  
    277. //////////////////////////////////////////////////////////////////////////
    To copy to clipboard, switch view to plain text mode 

  5. #5
    Join Date
    Sep 2011
    Location
    Manchester
    Posts
    538
    Thanks
    3
    Thanked 106 Times in 103 Posts
    Qt products
    Qt4 Qt/Embedded
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: QtTreeWidget: issue with indicator display

    Ok, now it's obvious

    Your imGuiSceneExplorer::mimeData() doesn't do its job.
    It should "Return an object that contains a serialized description of the specified items" but in your case it returns basically empty QMimeData object.

    As a test, call base implementation of mimeData() and return whatever you get from there, you'll see your problem fixed.
    Now you just need to figure out how to copy data from that object or serialize everything yourself.

  6. #6
    Join Date
    Jun 2010
    Posts
    8
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: QtTreeWidget: issue with indicator display

    @Spitfire: that was it !! Many many thanks for that ! a shame i can't pay you a beer for that

    thanks once again, this issue has been here for a while. Happy day

  7. #7
    Join Date
    Sep 2011
    Location
    Manchester
    Posts
    538
    Thanks
    3
    Thanked 106 Times in 103 Posts
    Qt products
    Qt4 Qt/Embedded
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: QtTreeWidget: issue with indicator display

    I'm glad I could help.
    And if you ever visit Manchester, I'm happy to go for a beer

  8. #8
    Join Date
    Jun 2010
    Posts
    8
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: QtTreeWidget: issue with indicator display

    not very likely, but I will do

    I have it now all working.

    As I am currently fixing all the annoying stuff I have for ages (I am really not a Qt specialist), may I ask you one additional question ?

    Basically, when using the DragDrop mode
    Qt Code:
    1. setDragDropMode(DragDrop);
    To copy to clipboard, switch view to plain text mode 
    the default behaviour is a copy operation. One has to press "shift" to swtich to a move operation.

    Now, I want to have a move operation by default, and press "Ctrl" to switch to copy operation.

    I know I can use
    Qt Code:
    1. setDragDropMode(InternalMove);
    To copy to clipboard, switch view to plain text mode 
    , but in that case, pressing Ctrl shows a "+" indicator, however, when mouse is being release, dropMimeData() doesn't get called.

    Is there a way to solve this easily ?

  9. #9
    Join Date
    Sep 2011
    Location
    Manchester
    Posts
    538
    Thanks
    3
    Thanked 106 Times in 103 Posts
    Qt products
    Qt4 Qt/Embedded
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: QtTreeWidget: issue with indicator display

    Qt Code:
    1. QTreeWidget* tree = new QTreeWidget( this );
    2. tree->setDragEnabled( true );
    3. tree->setAcceptDrops( true );
    4. tree->setDropIndicatorShown( true );
    5. tree->setDefaultDropAction( Qt::MoveAction ); // that's what you need
    To copy to clipboard, switch view to plain text mode 
    This should do it. No need to set setDragDropMode() as setDragEnabled() and setAcceptDrops() do it for you.

  10. #10
    Join Date
    Jun 2010
    Posts
    8
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: QtTreeWidget: issue with indicator display

    Hi, thanks for your answer.

    The problem is that calling
    Qt Code:
    1. setDefaultDropAction( Qt::MoveAction );
    To copy to clipboard, switch view to plain text mode 
    leads to the following behaviour: I can't insert my items between two existing nodes anymore (indicator=line), all I can do is to move the item as a child (indicator=rectangle). Does that make sense ?

    Moving/copying by inserting the item between two existing items was possible before.

    Any idea ?

  11. #11
    Join Date
    Sep 2011
    Location
    Manchester
    Posts
    538
    Thanks
    3
    Thanked 106 Times in 103 Posts
    Qt products
    Qt4 Qt/Embedded
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: QtTreeWidget: issue with indicator display

    What you mean you can't insert the items?
    Does the line indicator appear but nothing happens?

    This works fine for me:
    Qt Code:
    1. MainWindow::MainWindow( QWidget* p )
    2. :
    3. {
    4. QTreeWidget* tree = new QTreeWidget( this );
    5. tree->setDragEnabled( true );
    6. tree->setAcceptDrops( true );
    7. tree->setDropIndicatorShown( true );
    8. tree->setDefaultDropAction( Qt::MoveAction );
    9.  
    10. for( int i = 0; i < 5; i++ )
    11. {
    12. QTreeWidgetItem* root = new QTreeWidgetItem( tree->invisibleRootItem() );
    13. root->setText( 0, "root" + QString::number( i ) );
    14.  
    15. for( int j = 0; j < 5; ++j )
    16. {
    17. QTreeWidgetItem* leaf = new QTreeWidgetItem( root );
    18. leaf->setText( 0, "Leaf " + QString::number( j ) );
    19. }
    20. }
    21.  
    22. this->setCentralWidget( tree );
    23. }
    To copy to clipboard, switch view to plain text mode 
    See if this example has the same issue you're experiencing.
    You may need to upgrade it to use mime types, if you do and are able to replicate the issue - post the code here.

  12. #12
    Join Date
    Jun 2010
    Posts
    8
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: QtTreeWidget: issue with indicator display

    OK, your example worked for me.
    I have managed to fix my issue: actually the widget was being defined using Qt Designer, where some properties were set for that widget.
    So, basically, to avoid confusion I've cleared all the properties defined in Qt Designer, and this seems to work now.

    I think I now rather owe you a barrel of beer

    Thanks a lot for your help, that was really appreciated.

  13. #13
    Join Date
    Sep 2011
    Location
    Manchester
    Posts
    538
    Thanks
    3
    Thanked 106 Times in 103 Posts
    Qt products
    Qt4 Qt/Embedded
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: QtTreeWidget: issue with indicator display

    I'm glad I could help.

    Take care!

Similar Threads

  1. QRadiButton and QCheckBox Indicator Box Sizing Issue.
    By savaliya_ambani in forum Qt for Embedded and Mobile
    Replies: 4
    Last Post: 27th August 2011, 00:56
  2. checkbox implementation in QTableWidget display issue
    By prajesh in forum Qt Programming
    Replies: 11
    Last Post: 26th February 2010, 09:35
  3. Replies: 8
    Last Post: 27th April 2009, 19:19
  4. Tray context menu display issue
    By r2hubert in forum Qt Programming
    Replies: 1
    Last Post: 7th July 2008, 20:15
  5. Drop Indicator
    By guilugi in forum Qt Programming
    Replies: 2
    Last Post: 18th January 2006, 10:49

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.