Page 1 of 1

Listview Multiselect GetGadgetText()

Posted: Thu Dec 31, 2015 4:30 am
by mark5009
Hi and Happy New Year! [1]

I want to copy the text from multiple selected items within a Listview gadget to the clipboard.

My original expectation is that an event proc such as

Code: Select all

Procedure log_to_clipboard( EventType )
   Protected txt.s = "" ; holds our cut text
   txt = GetGadgetText( lv1 )
   ClearClipboard()
   SetClipboardText( txt )
   Debug "sent text to clipboard: " + txt
EndProcedure
Would do the trick. However, only the last line of the selected items is copied.
Am I missing something obvious?

Many thanks .. mark.

[1] standard western calendar implied

Re: Listview Multiselect GetGadgetText()

Posted: Thu Dec 31, 2015 6:04 am
by collectordave
Happy new year.

It appears only one item is returned by getgadgettext. You need to use getgadgettext on each seleted item in the list box.

A little code below

Code: Select all

          For i = 0 To 9
            If GetGadgetItemState(ListView_0, i) = 1
              Debug GetGadgetItemText(ListView_0, i)
            EndIf
          Next i
          
Try this in your code and it will send all selected items to the debug output. Once happy replace the debug line with your code for clipboard etc.

Hope this helps

Re: Listview Multiselect GetGadgetText()

Posted: Thu Dec 31, 2015 7:40 am
by mark5009
collectordave wrote: It appears only one item is returned by getgadgettext. You need to use getgadgettext on each seleted item in the list box.
...
Hope this helps
Many thanks, collectordave. I suspected this might be the case but was hoping it might not be. Still, given the speed and ease of PB, it is not really much of a problem, just a little unexpected.

Kind regards .. mark.

Re: Listview Multiselect GetGadgetText()

Posted: Thu Dec 31, 2015 2:34 pm
by Shardik
mark5009 wrote:I suspected this might be the case but was hoping it might not be.
Your hope can be satisfied. In Windows it's possible with an API function to obtain an array which contains all selected items:

Code: Select all

#ItemCount = 10

; ----- Create an array that will contain the indices of the selected items
Dim ItemIndex.L(#ItemCount - 1)

OpenWindow(0, 100, 100, 270, 195, "Detect multiselected items")
ListViewGadget(0, 10, 10, 250, 135, #PB_ListView_MultiSelect)
ButtonGadget(1, 70, 155, 120, 25, "List selected items")

For i = 1 To #ItemCount
  AddGadgetItem (0, -1, "Item " + Str(i))
Next

Repeat 
  Select WaitWindowEvent()
    Case #PB_Event_CloseWindow 
      Break
    Case #PB_Event_Gadget
      If EventGadget() = 1
        ; ----- Count the selected items
        SelectedItemsCount = SendMessage_(GadgetID(0), #LB_GETSELCOUNT, 0, 0)
        Debug "Number of selected items: " + SelectedItemsCount

        If SelectedItemsCount > 0
          ; ----- Get the selected items and let them pass into the array 
          SendMessage_(GadgetID(0), #LB_GETSELITEMS, SelectedItemsCount, @ItemIndex()) 

          For i = 0 To SelectedItemsCount - 1
            Debug ItemIndex(i) + 1
          Next i
        EndIf
      EndIf
  EndSelect
ForEver

Re: Listview Multiselect GetGadgetText()

Posted: Thu Dec 31, 2015 3:00 pm
by RASHAD
Using the ClipBoard()

Code: Select all

OpenWindow(0, 100, 100, 270, 195, "Detect multiselected items")
ListViewGadget(0, 10, 10, 250, 135, #PB_ListView_MultiSelect)
ButtonGadget(1, 70, 155, 120, 25, "List selected items")

For i = 1 To 10
  AddGadgetItem (0, -1, "Item " + Str(i))
Next

Repeat
  Select WaitWindowEvent()
    Case #PB_Event_CloseWindow
      Break
    Case #PB_Event_Gadget
        Text$ = ""
        For item = 0 To CountGadgetItems(0)
            If GetGadgetItemState(0,item) = 1
               Text$ = Text$ + GetGadgetItemText(0,item) + #CRLF$
            EndIf
        Next
        ClearClipboard()
        SetClipboardText(Text$)
        Debug GetClipboardText()
  EndSelect
ForEver


Re: Listview Multiselect GetGadgetText()

Posted: Fri Jan 01, 2016 12:17 am
by mark5009
Thanks, Rashad.

I am using OSX and there might be a way of doing the same locally, I'd rather not go platform specific if the payoff is minimal. So, I am using the clipboard code, almost identical to the one you posted.

.. mark.

Re: Listview Multiselect GetGadgetText()

Posted: Fri Jan 01, 2016 9:49 am
by Shardik
mark5009 wrote:I am using OSX
If you would have posted your OS in your signature, I would have posted the API code for OS X... :wink:

I have converted my example from above using Windows API functions to an example using the necessary MacOS API functions.

The native API functions should be much faster than anything you can currently do solely with PureBasic code. Of course this only matters when working with ListViewGadgets containg many items...

I have tested the following example successfully on these MacOS X versions with PB 5.41 x86 and x64:
- 10.6.8 (Snow Leopard)
- 10.11.2 (El Capitan)

Code: Select all

#ItemCount = 10

; ----- Create an array that will contain the indices of the selected items
Dim ItemIndex.I(#ItemCount - 1)

OpenWindow(0, 100, 100, 270, 250, "Detect multiselected items")
ListViewGadget(0, 10, 10, 250, 195, #PB_ListView_MultiSelect)
ButtonGadget(1, 60, 215, 140, 25, "List selected items")

For i = 1 To #ItemCount
  AddGadgetItem (0, -1, "Item " + Str(i))
Next

Repeat
  Select WaitWindowEvent()
    Case #PB_Event_CloseWindow
      Break
    Case #PB_Event_Gadget
      If EventGadget() = 1
        ; ----- Request an NSIndexSet of the indices of the selected items
        IndexSet = CocoaMessage(0, GadgetID(0), "selectedRowIndexes")
        ; ----- Copy the indices of the selected items into array ItemIndex()
        SelectedItemsCount = CocoaMessage(0, IndexSet,
          "getIndexes:", @ItemIndex(),
          "maxCount:", ArraySize(ItemIndex()) + 1,
          "inIndexRange:", 0)
        ; ----- Display number of selected items
        Debug "Number of selected items: " + SelectedItemsCount

        If SelectedItemsCount > 0
          ; ----- Display index of each selected item
          For i = 0 To SelectedItemsCount - 1
            Debug ItemIndex(i) + 1
          Next i
        EndIf
      EndIf
  EndSelect
ForEver

Re: Listview Multiselect GetGadgetText()

Posted: Fri Jan 01, 2016 1:23 pm
by Shardik
The code example below is true cross-platform while using the fast platform-specific API functions of Linux, MacOS X and Windows to get the indices of all selected rows in a ListViewGadget without having to iterate over each row when using solely PureBasic functions.

I have tested the example successfully on these operating systems:
- MacOS X 10.6.8 (Snow Leopard) with PB 5.41 x86 and x64
- Ubuntu 14.04 x64 with KDE and PB 5.41 x64
- Windows 7 SP1 with PB 5.41 x86 and x64

Code: Select all

EnableExplicit

#RowCount = 10

; ----- Create an array that will contain the indices of the selected items

CompilerIf #PB_Compiler_OS = #PB_OS_MacOS
  Dim RowIndex.I(#RowCount - 1) ; Has to be Long in x86 and Quad in x64!
CompilerElse
  Dim RowIndex.L(#RowCount - 1)
CompilerEndIf

Procedure.I GetSelectedRows(GadgetID.I)
  Protected SelectedRowsCount.I

  CompilerSelect #PB_Compiler_OS
    CompilerCase #PB_OS_Linux
      Shared RowIndex.L()

      Protected i.I
      Protected IndexList.I
      Protected Path.I
      Protected Selection.I

      Selection = gtk_tree_view_get_selection_(GadgetID(GadgetID))

      If Selection
        IndexList = gtk_tree_selection_get_selected_rows_(Selection, 0)

        If IndexList
          SelectedRowsCount = g_list_length_(IndexList)

          For i = 0 To SelectedRowsCount - 1
            Path = g_list_nth_data_(IndexList, i)
            RowIndex(i) = PeekI(gtk_tree_path_get_indices_(Path))
          Next i

          g_list_free_(IndexList)
        EndIf
      EndIf
    CompilerCase #PB_OS_MacOS
      Shared RowIndex.I()

      Protected IndexSet.I

      IndexSet = CocoaMessage(0, GadgetID(GadgetID), "selectedRowIndexes")
      SelectedRowsCount = CocoaMessage(0, IndexSet,
        "getIndexes:", @RowIndex(),
        "maxCount:", ArraySize(RowIndex()) + 1,
        "inIndexRange:", 0)
    CompilerCase #PB_OS_Windows
      Shared RowIndex.L()

      SelectedRowsCount = SendMessage_(GadgetID(0), #LB_GETSELCOUNT, 0, 0)

      If SelectedRowsCount > 0
        SendMessage_(GadgetID(GadgetID), #LB_GETSELITEMS, SelectedRowsCount,
          @RowIndex())
      EndIf
  CompilerEndSelect

  ProcedureReturn SelectedRowsCount
EndProcedure

Define i.I
Define SelectedRowsCount.I

OpenWindow(0, 100, 100, 270, 195, "Detect multiselected items")
ListViewGadget(0, 10, 10, 250, 135, #PB_ListView_MultiSelect)
ButtonGadget(1, 60, 155, 140, 25, "List selected items")

For i = 1 To #RowCount
  AddGadgetItem (0, -1, "Row " + Str(i))
Next

Repeat
  Select WaitWindowEvent()
    Case #PB_Event_CloseWindow
      Break
    Case #PB_Event_Gadget
      If EventGadget() = 1
        SelectedRowsCount = GetSelectedRows(0)
        Debug "Number of selected rows: " + SelectedRowsCount

        If SelectedRowsCount > 0
          For i = 0 To SelectedRowsCount - 1
            Debug RowIndex(i) + 1
          Next i
        EndIf
      EndIf
  EndSelect
ForEver

Re: Listview Multiselect GetGadgetText()

Posted: Mon Jan 04, 2016 2:43 am
by mark5009
Shardik wrote:
mark5009 wrote:I am using OSX
If you would have posted your OS in your signature, I would have posted the API code for OS X... :wink:

I have converted my example from above using Windows API functions to an example using the necessary MacOS API functions.
Wow! Many thanks, Shardik. Fantastic stuff.

.. mark.