wxDataViewTreeCtrl - How to check if a container has child items? Topic is solved

If you are using the main C++ distribution of wxWidgets, Feel free to ask any question related to wxWidgets development here. This means questions regarding to C++ and wxWidgets, not compile problems.
apoorv569
Super wx Problem Solver
Super wx Problem Solver
Posts: 426
Joined: Tue Oct 20, 2020 3:35 pm

wxDataViewTreeCtrl - How to check if a container has child items?

Post by apoorv569 »

I see there is a method in wxDataViewTreeCtrl class to check if a item is a container, I'm wondering if there is a way/method to check if a container has child items in it or not? as I could not find anything.
User avatar
doublemax
Moderator
Moderator
Posts: 19163
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: wxDataViewTreeCtrl - How to check if a container has child items?

Post by doublemax »

wxDataViewTreeCtrl::GetChildCount() ?
Use the source, Luke!
apoorv569
Super wx Problem Solver
Super wx Problem Solver
Posts: 426
Joined: Tue Oct 20, 2020 3:35 pm

Re: wxDataViewTreeCtrl - How to check if a container has child items?

Post by apoorv569 »

doublemax wrote: Fri May 28, 2021 9:15 pm wxDataViewTreeCtrl::GetChildCount() ?
Ah! Yes, don't know how I missed this.

I also want to know if it is possible to get wxDataViewItem from wxDropFilesEvent, as I want to drag and drop files from wxDataViewListCtrl to wxDataViewTreeCtrl, and the AppendItem() needs a wxDataViewItem& parent. I have enabled DragAcceptFIles(true) on the wxDataViewTreeCtrl.
Image

Code: Select all

void MainFrame::OnDragAndDropToCollectionView(wxDropFilesEvent& event)
{
    if (event.GetNumberOfFiles() > 0)
    {
        wxString* dropped = event.GetFiles();
        wxASSERT(dropped);

        wxString filepath;
        wxArrayString filepath_array;

        for (int i = 0; i < event.GetNumberOfFiles(); i++)
        {
            filepath = dropped[i];

            if (wxFileExists(filepath))
            {
                filepath_array.push_back(filepath);
            }
            // else if (wxDirExists(filepath))
            // {
            //     wxDir::GetAllFiles(filepath, &filepath_array);
            // }
        }

	wxDataViewItem selected = m_CollectionView->GetSelection();

	for(int i = 0; i < event.GetNumberOfFiles(); i++)
	  m_CollectionView->AppendItem(selected, filepath_array[i].AfterLast('/'));
    }
}
But this m_CollectionView->GetSelection() always just drops it on outside of any container.
AmadeusK525
Experienced Solver
Experienced Solver
Posts: 61
Joined: Wed Aug 19, 2020 12:04 am

Re: wxDataViewTreeCtrl - How to check if a container has child items?

Post by AmadeusK525 »

Hello,
AFAIK wxDataViewListCtrls and wxDataViewTreeCtrls handle their wxDataViewItems differently: the former uses wxDataViewListStore and the latter uses wxDataViewTreeStore, so I suspect that, even if you manage to get the wxDataViewItem (which is just a memory address, what handles the data is the wxDataViewModel), trying to add it to a different kind of wxDataViewCtrl may have unexpected behavior. Well, even so, if you handle the wxDataViewCtrl drag and drop events (wxEVT_DATAVIEW_ITEM_BEGIN_DRAG, wxEVT_DATAVIEW_ITEM_DROP_POSSIBLE and wxEVT_DATAVIEW_ITEM_DROP), this may be possible using wxDataViewEvent::GetProposedIndex() and then wxDataViewListCtrl::RowToItem(). Using these events is demonstrated in the wxDataViewCtrl sample, although it's limited to the same wxDataViewCtrl, so I'm not sure if they'll be fired when trying to send a wxDataViewItem from one control to another.
apoorv569
Super wx Problem Solver
Super wx Problem Solver
Posts: 426
Joined: Tue Oct 20, 2020 3:35 pm

Re: wxDataViewTreeCtrl - How to check if a container has child items?

Post by apoorv569 »

AmadeusK525 wrote: Sun May 30, 2021 2:18 am Hello,
AFAIK wxDataViewListCtrls and wxDataViewTreeCtrls handle their wxDataViewItems differently: the former uses wxDataViewListStore and the latter uses wxDataViewTreeStore, so I suspect that, even if you manage to get the wxDataViewItem (which is just a memory address, what handles the data is the wxDataViewModel), trying to add it to a different kind of wxDataViewCtrl may have unexpected behavior. Well, even so, if you handle the wxDataViewCtrl drag and drop events (wxEVT_DATAVIEW_ITEM_BEGIN_DRAG, wxEVT_DATAVIEW_ITEM_DROP_POSSIBLE and wxEVT_DATAVIEW_ITEM_DROP), this may be possible using wxDataViewEvent::GetProposedIndex() and then wxDataViewListCtrl::RowToItem(). Using these events is demonstrated in the wxDataViewCtrl sample, although it's limited to the same wxDataViewCtrl, so I'm not sure if they'll be fired when trying to send a wxDataViewItem from one control to another.
Thanks for the response, I don't want to get the wxDataViewListCtrl item to wxDataViewTreeCtrl, what I mean by how to get the wxDataViewItem is, as in when the user drag a file from wxDataViewListCtrl, and tries to drop it on wxDataViewTreeCtrl, I want to get the wxDataViewItem on which container the user drops the file on, so I can add the file(filename) to that container. I'm not trying transfer memory address. I basically get the info of the item that is being dragged from wxDataViewListCtrl, from the Sqlite database, such as filename, sample rate, path and all and I want to insert the filename to whatever container the file drops on. I'm using wxDataViewTreeCtrl as sort of a folder-file directory thing, container as folder, files as child items.
User avatar
doublemax
Moderator
Moderator
Posts: 19163
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: wxDataViewTreeCtrl - How to check if a container has child items?

Post by doublemax »

Get the position from the event, then wxDataViewCtrl::HitTest() to find the item at that position.
Use the source, Luke!
AmadeusK525
Experienced Solver
Experienced Solver
Posts: 61
Joined: Wed Aug 19, 2020 12:04 am

Re: wxDataViewTreeCtrl - How to check if a container has child items?

Post by AmadeusK525 »

apoorv569 wrote: Sun May 30, 2021 2:31 pm I basically get the info of the item that is being dragged from wxDataViewListCtrl, from the Sqlite database, such as filename, sample rate, path and all and I want to insert the filename to whatever container the file drops on.
Oh okay, sorry for the mix-up!
apoorv569
Super wx Problem Solver
Super wx Problem Solver
Posts: 426
Joined: Tue Oct 20, 2020 3:35 pm

Re: wxDataViewTreeCtrl - How to check if a container has child items?

Post by apoorv569 »

doublemax wrote: Sun May 30, 2021 2:45 pm Get the position from the event, then wxDataViewCtrl::HitTest() to find the item at that position.
The HitTest() take wxPoint& point, wxDataViewItem& item and wxDataViewColumn*& column. The wxPoint& point will take event.GetPosition(), but what do I put in place of wxDataViewItem& item and wxDataViewColumn*& column?
apoorv569
Super wx Problem Solver
Super wx Problem Solver
Posts: 426
Joined: Tue Oct 20, 2020 3:35 pm

Re: wxDataViewTreeCtrl - How to check if a container has child items?

Post by apoorv569 »

doublemax wrote: Sun May 30, 2021 2:45 pm Get the position from the event, then wxDataViewCtrl::HitTest() to find the item at that position.
Okay, I found this post here -viewtopic.php?t=37775

I tried this and it works now. Thank you for the help.

Here is the code might help someone else in future.

Code: Select all

void MainFrame::OnDragAndDropToCollectionView(wxDropFilesEvent& event)
{
    if (event.GetNumberOfFiles() > 0)
    {
        wxString* dropped = event.GetFiles();
        wxASSERT(dropped);

        // wxBusyCursor busy_cursor;
        // wxWindowDisabler window_disabler;

        wxString filepath;
        wxArrayString filepath_array;

        for (int i = 0; i < event.GetNumberOfFiles(); i++)
        {
            filepath = dropped[i];

            if (wxFileExists(filepath))
            {
                filepath_array.push_back(filepath);
            }
            // else if (wxDirExists(filepath))
            // {
            //     wxDir::GetAllFiles(filepath, &filepath_array);
            // }
        }

	wxDataViewItem selected;
	wxDataViewColumn* column;
	wxPoint position = event.GetPosition();
	
	m_CollectionView->HitTest(position, selected, column);

	for(int i = 0; i < event.GetNumberOfFiles(); i++)
	{
	  wxLogDebug("Dropping %s on folder: %s", filepath_array[i].AfterLast('/'), m_CollectionView->GetItemText(selected));
	  m_CollectionView->AppendItem(selected, filepath_array[i].AfterLast('/'));
	}
    }
}
apoorv569
Super wx Problem Solver
Super wx Problem Solver
Posts: 426
Joined: Tue Oct 20, 2020 3:35 pm

Re: wxDataViewTreeCtrl - How to check if a container has child items?

Post by apoorv569 »

doublemax wrote: Sun May 30, 2021 2:45 pm Get the position from the event, then wxDataViewCtrl::HitTest() to find the item at that position.
This works, but I'm only able to drag and drop one item at a time, if I select multiple items from wxDataViewListCtrl and try to drop them on wxDataViewTreeCtrl only the item I clicked on to drag gets added and it ignores the rest, event.GetNumberOfFiles() also returns 1. Is there a way to drag and drop multiple items at once.
User avatar
doublemax
Moderator
Moderator
Posts: 19163
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: wxDataViewTreeCtrl - How to check if a container has child items?

Post by doublemax »

apoorv569 wrote: Mon May 31, 2021 5:36 am
doublemax wrote: Sun May 30, 2021 2:45 pm Get the position from the event, then wxDataViewCtrl::HitTest() to find the item at that position.
This works, but I'm only able to drag and drop one item at a time, if I select multiple items from wxDataViewListCtrl and try to drop them on wxDataViewTreeCtrl only the item I clicked on to drag gets added and it ignores the rest, event.GetNumberOfFiles() also returns 1. Is there a way to drag and drop multiple items at once.
This is something you must handle when the drag operation starts. You must iterate over all selected items and add all filenames to the wxFileDataObject
Use the source, Luke!
apoorv569
Super wx Problem Solver
Super wx Problem Solver
Posts: 426
Joined: Tue Oct 20, 2020 3:35 pm

Re: wxDataViewTreeCtrl - How to check if a container has child items?

Post by apoorv569 »

doublemax wrote:This is something you must handle when the drag operation starts. You must iterate over all selected items and add all filenames to the wxFileDataObject
Okay I changed the code, it is working, but it only detects that I'm dragging multiple files if I hold CTRL and then drag the selected items, but clicking CTRL first time deselects the file I start dragging on, so I have to reselect the file while holding CTRL, only then it takes all files. Is this behavior expected or something is wrong?
Image

Here is the code,

Code: Select all

void MainFrame::OnDragAndDropToCollectionView(wxDropFilesEvent& event)
{
    if (event.GetNumberOfFiles() > 0)
    {
        wxFileDataObject file_data;
        wxArrayString files;

	wxDataViewItemArray items;
	int rows = m_SampleListView->GetSelections(items);

        wxDataViewItem selected;
        wxDataViewColumn* column;
        wxPoint position = event.GetPosition();
        m_CollectionView->HitTest(position, selected, column);

	for(int i = 0; i < rows; i++)
	{
	    int row = m_SampleListView->ItemToRow(items[i]);
	    wxString name = m_SampleListView->GetTextValue(row, 1);

	    file_data.AddFile(name);

            files = file_data.GetFilenames();

            wxLogDebug("Dropping %d files.", rows);
	    wxLogDebug("Dropping %s on folder: %s", files[i], m_CollectionView->GetItemText(selected));

	    m_CollectionView->AppendItem(selected, files[i]);
	}
    }
}
User avatar
doublemax
Moderator
Moderator
Posts: 19163
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: wxDataViewTreeCtrl - How to check if a container has child items?

Post by doublemax »

I guess you have some other event handlers on the wxDVC that disturb the selection behavior. When you have multiple files selected, click any of them and keep the button pressed. The selection should not change until you release the mouse. If it behaves differently, check your other event handlers and what they do.
Use the source, Luke!
apoorv569
Super wx Problem Solver
Super wx Problem Solver
Posts: 426
Joined: Tue Oct 20, 2020 3:35 pm

Re: wxDataViewTreeCtrl - How to check if a container has child items?

Post by apoorv569 »

doublemax wrote: Mon May 31, 2021 10:27 pm I guess you have some other event handlers on the wxDVC that disturb the selection behavior. When you have multiple files selected, click any of them and keep the button pressed. The selection should not change until you release the mouse. If it behaves differently, check your other event handlers and what they do.
Yes actually, I also have this event handler for wxDataViewListCtrl, that handles dragging and dropping a file outside of the application, to like a audio player or file manager or something. Here is the code

Code: Select all

void MainFrame::OnDragFromSampleView(wxDataViewEvent& event)
{
    int selected_row = m_SampleListView->ItemToRow(event.GetItem());

    if (selected_row < 0) return;

    wxString selection = m_SampleListView->GetTextValue(selected_row, 1);

    wxString sample_path = GetFileNamePathAndExtension(selection).Path;

    wxFileDataObject* fileData = new wxFileDataObject();

    fileData->AddFile(sample_path);
    event.SetDataObject(fileData);

    wxLogDebug("Started dragging '%s'.", sample_path);
}
And when do I try to drag and drop on wxDataViewTreeCtrl, it does print this debug statement, "Started dragging ...", could this be doing something wrong?
User avatar
doublemax
Moderator
Moderator
Posts: 19163
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: wxDataViewTreeCtrl - How to check if a container has child items?

Post by doublemax »

If this is a wxEVT_DATAVIEW_ITEM_BEGIN_DRAG handler, it should be fine.
Use the source, Luke!