Drag, drop and go

For discussions about programming, programming questions/advice, and projects that don't really have anything to do with Puppy.
Message
Author
User avatar
MochiMoppel
Posts: 2084
Joined: Wed 26 Jan 2011, 09:06
Location: Japan

#16 Post by MochiMoppel »

LazY Puppy wrote:So, function move should look like code below:
This will delete most items when release event happens outside of the tree items (=no item is highlighted anymore) but still insided the tree widget area (e.g. an empty area below the items)

My attempt:

Code: Select all

move(){ 
    PRESS_EVENT=$(cat /tmp/PRESS_EVENT)
    [[ $PRESS_EVENT && $TREE ]] || exit                          # exit if at least one of the 2 values is empty
    [[ $PRESS_EVENT == $TREE ]] && exit                          # exit if both are equal (=single or double click)
    sed -i "/$PRESS_EVENT/d; /$TREE/ i\\$PRESS_EVENT" /tmp/list  # remove PRESS_EVENT, then insert item PRESS_EVENT before item $TREE
}
export -f move
Overall I'm not happy with this poor man's drag'n'drop substitute. Too many restrictions and pitfalls, but may still be useful in some cases.

User avatar
LazY Puppy
Posts: 1934
Joined: Fri 21 Nov 2014, 18:14
Location: Germany

#17 Post by LazY Puppy »

MochiMoppel wrote:
LazY Puppy wrote:So, function move should look like code below:
This will delete most items when release event happens outside of the tree items (=no item is highlighted anymore) but still insided the tree widget area (e.g. an empty area below the items)

My attempt:

Code: Select all

move(){ 
    PRESS_EVENT=$(cat /tmp/PRESS_EVENT)
    [[ $PRESS_EVENT && $TREE ]] || exit                          # exit if at least one of the 2 values is empty
    [[ $PRESS_EVENT == $TREE ]] && exit                          # exit if both are equal (=single or double click)
    sed -i "/$PRESS_EVENT/d; /$TREE/ i\\$PRESS_EVENT" /tmp/list  # remove PRESS_EVENT, then insert item PRESS_EVENT before item $TREE
}
export -f move
Overall I'm not happy with this poor man's drag'n'drop substitute. Too many restrictions and pitfalls, but may still be useful in some cases.
Thanks.

Just another situation that did not come to mind and therefor wasn't tested.

Checked right now. Out of a list of 69 wallpapers only two items remains in the tree item list. :shock: :lol:

How would example code look like, to move content of tree items between two gtkdialog tree widgets (where I can see many more use of compared to the one discussed) ?
RSH

"you only wanted to work your Puppies in German", "you are a separatist in that you want Germany to secede from Europe" (musher0) :lol:

No, but I gave my old drum kit away for free to a music store collecting instruments for refugees! :wink:

User avatar
MochiMoppel
Posts: 2084
Joined: Wed 26 Jan 2011, 09:06
Location: Japan

#18 Post by MochiMoppel »

LazY Puppy wrote:How would example code look like, to move content of tree items between two gtkdialog tree widgets
I dare to say that this is not possible, but then we have zigbert's statement:
zigbert wrote:This example shows only one list, but it is of course possible to drag between 2 lists.
So my question would be the same as LazY's: How?

some1
Posts: 117
Joined: Thu 17 Jan 2013, 11:07

#19 Post by some1 »

MochiMoppel:

2 parallel trees ATREE and BTREE

ATREE:

Code: Select all

<action signal=\"button-release-event\">echo \"ATREE - button-release-event\" \$ATREE >> ./SHOWME_EVENT</action>
<action signal=\"leave-notify-event\">echo \"ATREE - leave-notify-event\" \$ATREE>> ./SHOWME_EVENT</action>
<action signal=\"leave-notify-event\"> grabfocus BTREE>> ./SHOWME_EVENT</action
Ofcourse - 2 events to get the value of ATREE is not needed - just examples - 1 is sufficient.A matter of policy -when to fixate the ATREE-choice.

grabfocus BTREE will allow you to choose a position in BTREE

We can not have a "real" DnD - but have to move the mouse horizontally from ATREE to BTREE,press mousebutton when i BTREE - and do a release on BTREE-item-position.

BTREE:

Code: Select all

<action signal=\"button-release-event\">echo \"BTREE - button-release-event\" \$BTREE >> ./SHOWME_EVENT</action>

User avatar
MochiMoppel
Posts: 2084
Joined: Wed 26 Jan 2011, 09:06
Location: Japan

#20 Post by MochiMoppel »

I don't understand how this could work. A demo would be nice.
some1 wrote:grabfocus BTREE will allow you to choose a position in BTREE
How? I doubt that you can use the gtkdialog grabfocus function the way you do. What should the action grabfocus BTREE>> ./SHOWME_EVENT do? For me it produces an error message. Even if you use grabfocus:BTREE to activate BTREE, with a preceding button-press-event in ATREE item selection does not shift to BTREE.
We can not have a "real" DnD - but have to move the mouse horizontally from ATREE to BTREE,press mousebutton when i BTREE - and do a release on BTREE-item-position.
??? If we want do drag from ATREE to BTREE we need to press mousebutton in ATREE first. We can't possibly also press in BTREE. Or are you suggesting something like click'n'click instead of drag'n'drop?

User avatar
zigbert
Posts: 6621
Joined: Wed 29 Mar 2006, 18:13
Location: Valåmoen, Norway
Contact:

#21 Post by zigbert »

This is getting interesting :D
My original statement is many years old, and I don't remember what lead to it... MochiMoppel has a valid point in the fact that:
When pressing in treeA, it locks the focus, so release in treeB won't get the signal.

But hey, why so pessimistic :lol:
I have more than once got impressed of what you guys are able to do to push the limits...

mos
Posts: 6
Joined: Sat 01 Oct 2016, 12:15

#22 Post by mos »

Trying to make this drag'n drop widget to work like this :

Code: Select all

<entry width-request="300">
<variable>X</variable>
 <default>Drag an exe</default>
<action>echo $X > /tmp/txt &</action>

<action>'$HERE'/sedscript &</action>
 <action signal="changed"> some action on X </action>
</entry>
And the sedscript is:

Code: Select all

#!/bin/bash

sed -i 's/.*\///' /tmp/txt 
sed -i 's/ *$//' /tmp/txt

fsg=$( cat /tmp/txt )

echo "#!/bin/bash

env WINEPREFIX=\"/home/lns/.wine\" /opt/wine-staging/bin/wine Z:\\\\\\\\media\\\\\\\\SDA\\\\\\\\VST\\\\\\\\VSTi\\\\\\\\$fsg &" > /media/SDA/VST/VSTi/sfile

./media/SDA/VST/VSTi/sfile
What I want with these is to "drag'n drop" an windows .exe file over the empty field of this widget ,drop it there and make wine start it.sed is copying it as win.exe(without path) and wine should start it through sfile script. Everything works untill starting /media/SDA/VST/VSTi/sfile.Somehow ,in this file "env WINEPREFIX=\"/home/lns/.wine\" /opt/wine-staging/bin/wine Z:\\\\\\\\media\\\\\\\\SDA\\\\\\\\VST\\\\\\\\VSTi\\\\\\\\win.exe" is corectly copied on one line but without "&" on it's trail ,that's copied on the next line resulting something like this:

Code: Select all

#!/bin/bash

env WINEPREFIX="/home/lns/.wine" /opt/wine-staging/bin/wine Z:\\\\media\\\\SDA\\\\VST\\\\VSTi\\\\win.exe

 &
Wine can't start win.exe without "&" on it's trail ,so everything stops there.How to put "&" on it's place?I tried almost everything with sed but the result is the same with "&" thrown on the wrong place ,on the next line, not on the same line with win.exe and after win.exe.

User avatar
MochiMoppel
Posts: 2084
Joined: Wed 26 Jan 2011, 09:06
Location: Japan

#23 Post by MochiMoppel »

zigbert wrote:why so pessimistic
I was optimistic when I read your "of course". After reading your disclaimer and no word from some1 I lost my optimism. Let's call this realism, not pessimism. You can't always get what you want ♩ ♪♫ :wink:

Back to the thread topic. The solution to use a gtkdialog entry widget still has a flaw: While dropping works, editing the text in the entry field does not work anymore. Any attempt to edit the text will trigger a "changed" signal and therefore fire the associated action.

The following version lets the user edit text manually as usual. The action is triggered only after hitting the Enter key. Dropped text triggers the action immediately.

Here is the catch: This version of Drag&Drop&Go works only with window focus model "click". With focus model "sloppy" drag&drop works normally, but triggers action only after hitting the Enter key - just like manual entry.

Code: Select all

#!/bin/sh
export FOCUS_FLAG=/tmp/hasfocus
trap "rm $FOCUS_FLAG" EXIT

function some_action {
  [ -f $FOCUS_FLAG ] && METHOD=typed || METHOD=dropped
  Xdialog -msg "You $METHOD \n$vENTRY" x    
}
export -f some_action 

echo '
<window>
  <entry>
    <variable>vENTRY</variable>
    <default>D&D or type&ENTER</default>
    <action signal="changed"            condition="command_is_true([ -f $FOCUS_FLAG ] || echo true )">some_action &</action>
    <action signal="enter-notify-event" condition="command_is_true([ -f $FOCUS_FLAG ] || echo true )">grabfocus:vENTRY</action>
    <action signal="key-release-event"  condition="command_is_true([ $KEY_SYM = Return ] && echo true )">some_action &</action>
  </entry>
  <action signal="focus-in-event">touch $FOCUS_FLAG</action>
  <action signal="focus-out-event">rm   $FOCUS_FLAG</action>
</window>'| gtkdialog -cs

User avatar
zigbert
Posts: 6621
Joined: Wed 29 Mar 2006, 18:13
Location: Valåmoen, Norway
Contact:

#24 Post by zigbert »

I have updated the Tips and trick post with MochiMoppel's 'move' function.
Thank you

Depending on the focus model "sloppy" is somewhat strict :). A creative soluiton, but I have not included the example.

User avatar
MochiMoppel
Posts: 2084
Joined: Wed 26 Jan 2011, 09:06
Location: Japan

#25 Post by MochiMoppel »

@zigbert: Now, 9 months later, I regret my 'move' :lol:

This is what tips&tricks suggests now:
But this is not all....The next script shows how to move items in list by drag'n drop. Code:

Code: Select all

#!/bin/sh 

 move (){ 
    PRESS_EVENT=$(cat /tmp/PRESS_EVENT) 
    [[ $PRESS_EVENT && $TREE ]] || exit #exit if at least one of the 2 values is empty 
    [[ $PRESS_EVENT == $TREE ]] && exit #exit if both are equal (=single or double click) 
    sed -i "/$PRESS_EVENT/d; /$TREE/ i\\$PRESS_EVENT" /tmp/list #remove PRESS_EVENT, then insert item PRESS_EVENT before item $TREE 
 } 

 export -f move 
 ls -1 /usr/share/backgrounds > /tmp/list 

 export test=" 
 <tree rules_hint=\"true\" hover-selection=\"true\" tooltip-text=\"Drag'n drop items to move them in list\"> 
  <label>Backgrounds</label> 
  <input>cat /tmp/list</input> 
  <variable>TREE</variable> 
  <height>300</height><width>200</width> 
  <action signal=\"button-press-event\">echo \$TREE > /tmp/PRESS_EVENT</action> 
  <action signal=\"button-release-event\">move</action> 
  <action signal=\"button-release-event\">refresh:TREE</action> 
 </tree>" 
 gtkdialog -p test
...and this is how IMO moving items could be achieved much easier:

Code: Select all

#!/bin/sh
export test=' 
<tree headers-clickable="false" reorderable="true" rules_hint="true" Xhover-selection="true" tooltip-text="Drag'\''n drop items to move them in list"> 
<label>Backgrounds</label> 
<input>ls -1 /usr/share/backgrounds</input> 
<variable>TREE</variable> 
<height>300</height><width>200</width>
</tree>'
gtkdialog -p test
The reorderable tag attribute is not mentioned in the gtkdialog documentation, but it's included in the main Gtk documentation, used by GtkFileChooserDialog for shuffling bookmarks in the left bookmarks pane and you use it in Pmusic for sorting playlists, so it should have a place somewhere in tips&tricks.

User avatar
zigbert
Posts: 6621
Joined: Wed 29 Mar 2006, 18:13
Location: Valåmoen, Norway
Contact:

#26 Post by zigbert »

:D
Like it

Tried to make it more usable with a output file, but the release-event saves the list to <output file> 1 step behind my move. - I have to move twice to update the output file with the first move.

Code: Select all

#!/bin/sh 
export test=' 
<tree headers-clickable="false" reorderable="true" rules_hint="true" Xhover-selection="true" tooltip-text="Drag'\''n drop items to move them in list"> 
<label>Backgrounds</label> 
<input>ls -1 /usr/share/backgrounds</input> 
<output file>/tmp/test</output> 
<variable>TREE</variable> 
<height>300</height><width>200</width>
<action signal="button-release-event">save:TREE</action>
</tree>' 
gtkdialog -p test
Another issue is that moving an item onto another item deletes it. You have to ensure that the marker is between 2 items to make it work.

Any thoughts?

User avatar
MochiMoppel
Posts: 2084
Joined: Wed 26 Jan 2011, 09:06
Location: Japan

#27 Post by MochiMoppel »

zigbert wrote:Tried to make it more usable with a output file, but the release-event saves the list to <output file> 1 step behind my move.
Yeah, nice, isn't it? A great feature. Saves the status just after you released the button and before gtkdialog shuffles the sort order, updates the display and whatever else has to be done to process the signal. Gives you a last chance to backup your current sort order before you mess up your list with an accidental drop.

It's the same with other signals, e.g. selection-changed. Whatever action you define, user defined actions have precedence and are processed before the built-in actions.

If you want to save the reordered list you can either use the changed signal (which I find too heavy since it fires often) or you can "outsource" the save action. An (invisible) button is fine for that:

Code: Select all

<action signal="button-release-event">activate:BTN_SAVE</action>
.
.
<button visible="false">
	<variable>BTN_SAVE</variable>
	<action>save:TREE</action>
</button> 
Another issue is that moving an item onto another item deletes it.
...and hovering another item over the item that just ate your deleted item causes the culprit to spit it out again. You can have much fun with this feature ...or is it a bug? Anyway, if you combine your "1 step behind" save and my "outsourced" save, you have all ingredients for a bullet-proof reorder function.

The following code works for me. It takes a snapshot of the list before and after the reordering. Then it compares the output of the wc command, which should be the same for both files - unless a line is missing (deleted). In this case the tree is refreshed with the first snapshot, which effectively recreates the former sort order.

Code: Select all

#!/bin/sh
ls -1 /usr/share/backgrounds > /tmp/test
export test='
<vbox>
<tree headers-clickable="false" reorderable="true"> 
	<label>Backgrounds</label> 
	<input>cat /tmp/test</input> 
	<output file>/tmp/test</output> 
	<variable>TREE</variable> 
	<height>300</height><width>200</width> 
	<action signal="button-release-event">save:TREE</action> 
	<action signal="button-release-event">activate:BTN_SAVE</action> 
</tree>
<button visible="false">
	<variable>BTN_SAVE</variable>
	<action>cp /tmp/test /tmp/testbackup</action>
	<action>save:TREE</action>
	<action condition="command_is_true([[ $(wc </tmp/test) != $(wc </tmp/testbackup) ]] && sed "s/^|*//" /tmp/testbackup > /tmp/test && echo true )">refresh:TREE</action>
</button>
</vbox>' 
gtkdialog -p test

User avatar
MochiMoppel
Posts: 2084
Joined: Wed 26 Jan 2011, 09:06
Location: Japan

#28 Post by MochiMoppel »

zigbert wrote:Any thoughts?
:?: Did my thoughts solve your problems?

Just in case you are still waiting for more: There might be a chance to avoid the "move onto item" problem, but I'll still have to run some tests - when I find time.

User avatar
zigbert
Posts: 6621
Joined: Wed 29 Mar 2006, 18:13
Location: Valåmoen, Norway
Contact:

#29 Post by zigbert »

Wow, you're really into something :D

Will do more testing when time comes my way...
Would be nice to see if I could get it work properly in pMusic.

Thank you
Sigmund

User avatar
zigbert
Posts: 6621
Joined: Wed 29 Mar 2006, 18:13
Location: Valåmoen, Norway
Contact:

#30 Post by zigbert »

In the work of getting this exiting code work in actual usage, I've managed to implement the reorderable feature in the the pMusic playqueue. 2 of the 3 others functions that pMusic use in the queue are ok, but I struggle with the last one...

- The right-click menu is ok.
- The hot-key for removing items in queue by pressing mouse middle-button is ok.
- But activating (play) an item in the list by left-clicking on it seems to be troublesome. Well, it is sure doable with the release-event, but then I play every track I move by the reorderable function. I have tried to instead use doubleclick, but it doesn't seem to work in this combination. And the signal "row-activated" doesn't listen...

So, at this stage, the workaround is a bit hard. It reorders the list gently, but without any option to run actions on a left-click, we miss the last brick in the wall.

Any thoughts?
Sigmund

User avatar
MochiMoppel
Posts: 2084
Joined: Wed 26 Jan 2011, 09:06
Location: Japan

#31 Post by MochiMoppel »

Something like this?

Code: Select all

#!/bin/bash 
ls -1 /usr/share/backgrounds > /tmp/test 
do_something () { [[ $TREE ]] && viewnior "/usr/share/backgrounds/$TREE" ;} ; export -f do_something
export test=' 
<vbox> 
	<tree headers-clickable="false" reorderable="true"> 
		<label>Backgrounds</label> 
		<input>cat /tmp/test</input> 
		<output file>/tmp/test</output> 
		<variable>TREE</variable> 
		<height>300</height><width>200</width> 
		<action signal="button-release-event">save:TREE</action> 
		<action signal="button-release-event">activate:BTN_SAVE</action> 
	</tree> 
	<button visible="false"> 
		<variable>BTN_SAVE</variable> 
		<action>cp /tmp/test /tmp/testbackup</action> 
		<action>save:TREE</action> 
		<action>"[[ $(</tmp/test) == $(</tmp/testbackup) ]] && do_something &"</action> 
		<action condition="command_is_true([[ $(wc </tmp/test) != $(wc </tmp/testbackup) ]] && sed \"s/^|*//\" /tmp/testbackup > /tmp/test && echo true )">refresh:TREE</action> 
	</button> 
</vbox>' 
gtkdialog -p test
Item is activated upon button-release-event, but not after reordering.
If the list hasn't been reordered, the very last action condition doesn't need be tested and you can add a bit of sophistication and break the action chain before it reaches this nonsense test:

Code: Select all

<action condition="command_is_true([[ $(</tmp/test) == $(</tmp/testbackup) ]] && { do_something & echo true ;} || echo false )">break:</action> 
Better performance, worse readability :lol:

User avatar
zigbert
Posts: 6621
Joined: Wed 29 Mar 2006, 18:13
Location: Valåmoen, Norway
Contact:

#32 Post by zigbert »

Yeahhh!

Your code works, but it looses the handling of the $BUTTON value for release-event. I made a simple flag to store $BUTTON on press-event for later usage.

The code is too dirty (and complex) atm to show, but I will come back to it with a fresh brain and clean up. I had some other minor issues, so I had to change the approach a bit. I will come back with more feedback.

In the end we need to complete a simple, yet complete, example how to use and understand your code.

Keep it coming :D
Thanks a lot
Sigmund

User avatar
MochiMoppel
Posts: 2084
Joined: Wed 26 Jan 2011, 09:06
Location: Japan

#33 Post by MochiMoppel »

zigbert wrote:Keep it coming :D
OK, here we go:

First let's get rid of [[ $TREE ]] test in the function. The reason for that was a possibly empty $TREE, which occurs when the user drags the item just below itself.

And now the beauty part: Avoid all this (double) saving and copying stuff.
In my previous code all these actions fired with every release event, and of course double with a doubleclick. Made me nervous to think what might happen with speed when the list becomes bigger. Not elegant at all.

Below I attach an improved version that triggers only the main action and nothing else when the user clicks an item. It triggers the saving routine when the user moves an item. Find out why it works :wink:

Code: Select all

#!/bin/bash
ls -1 /usr/share/backgrounds > /tmp/test 
do_something () { Xdialog -info  "Do something with\n$TREE" x 2000 ;} ; export -f do_something
echo ' 
<vbox> 
	<tree headers-clickable="false" reorderable="true"> 
		<label>Backgrounds</label> 
		<input>cat /tmp/test</input> 
		<output file>/tmp/test</output> 
		<variable>TREE</variable> 
		<height>300</height><width>200</width>
		<action signal="button-release-event" condition="command_is_true( ((PTR_Y)) && { do_something & echo true ;})">break:</action>  
		<action signal="button-release-event">save:TREE</action> 
		<action signal="button-release-event">activate:BTN_SAVE</action>
	</tree>
	<button visible="false"> 
		<variable>BTN_SAVE</variable> 
		<action>cp /tmp/test /tmp/testbackup</action> 
		<action>save:TREE</action> 
		<action condition="command_is_true([[ $(wc </tmp/test) != $(wc </tmp/testbackup) ]] && sed "s/^|*//" /tmp/testbackup > /tmp/test && echo true )">refresh:TREE</action> 
	</button> 
</vbox>' | gtkdialog -s
zigbert wrote:I have tried to instead use doubleclick, but it doesn't seem to work in this combination. And the signal "row-activated" doesn't listen...
Well, "row-activated" , the default action, was listening. At least it listened to the Enter or Space key. It didn't pick up a doubleclick because a simple <action> (= "row-activated") , no matter where it is placed in the code, is always processed after the "button-release-event". With activating BTN_SAVE the action chain of the tree widget comes to an end and actions of the Button widget are processed. The process never returns to the tree widget to continue with the still "pending" row-activated event.

Good news: with above code the default action will now work. Personally I would prefer to use the default action so that the user can use either keyboard (Enter or Space) or mouse (doubleclick).

In above code try to change

Code: Select all

<action signal="button-release-event" condition="command_is_true( ((PTR_Y)) && { do_something & echo true ;})">break:</action> 
with

Code: Select all

<action>do_something &</action>
<action signal="button-release-event" condition="command_is_true( echo $PTR_Y )">break:</action>
I think there is no need to specify the mouse button. Dragging works only with the left button, and so does doubleclick. Middle or right mouse button clicks are not affected by the code.

User avatar
zigbert
Posts: 6621
Joined: Wed 29 Mar 2006, 18:13
Location: Valåmoen, Norway
Contact:

#34 Post by zigbert »

I think this is a wonderful workaround...
...But I really wonder what made you notice that $PTR_Y became 0 when moving an item - That is luck :lol:

I will wait a couple of days before updating the tips and tricks thread... It could be more.

Code: Select all

#!/bin/bash 
#Code below line 15 (break:) is activated when user move item in list

ls -1 /usr/share/backgrounds > /tmp/test 
do_something () { Xdialog -info  "Do something with\n$TREE" x 2000 ;} ; export -f do_something 
echo ' 
<vbox> 
   <tree headers-clickable="false" reorderable="true"> 
      <label>Backgrounds</label> 
      <input>cat /tmp/test</input> 
      <output file>/tmp/test</output> 
      <variable>TREE</variable> 
      <height>300</height><width>200</width> 
      <action>do_something &</action> 
      <action signal="button-release-event" condition="command_is_true( echo $PTR_Y )">break:</action>
      <action signal="button-release-event">save:TREE</action> 
      <action signal="button-release-event">activate:BTN_SAVE</action> 
   </tree> 
   <button visible="false"> 
      <variable>BTN_SAVE</variable> 
      <action>cp /tmp/test /tmp/testbackup</action> 
      <action>save:TREE</action> 
      <action condition="command_is_true([[ $(wc </tmp/test) != $(wc </tmp/testbackup) ]] && sed \"s/^|*//\" /tmp/testbackup > /tmp/test && echo true )">refresh:TREE</action> 
   </button> 
</vbox>' | gtkdialog -s

User avatar
don570
Posts: 5528
Joined: Wed 10 Mar 2010, 19:58
Location: Ontario

#35 Post by don570 »

sorting a list alphabetically can sometimes be helpful if test file is
created haphazardly

Code: Select all

# sort alphabetically
LIST=$(sort -f /tmp/test)
echo "$LIST" > /tmp/test 
I used script in puppy help system

http://murga-linux.com/puppy/viewtopic. ... 003#964003
____________________________________________________

Post Reply