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
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
____________________________________________________

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

#36 Post by MochiMoppel »

Just for the record and everybody's amusement here is what I *thought* would be a solution to the "move onto item" problem.

It uses the deprecated table widget.
It nicely allows drag&drop only between items, eliminating the need for a work around. As a bonus it keeps the dragged item marked and does not fall into instant amnesia like tree.

Works perfectly here for at least 3 drops, but then...

Code: Select all

#!/bin/bash
echo '
<table column-header-active="false|false" reorderable="true"> 
	<label>No|Fruit</label> 
	<item>1|apple</item> 
	<item>2|banana</item> 
	<item>3|citron</item> 
	<item>4|durian</item> 
</table>' | gtkdialog -s

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

#37 Post by zigbert »

MochiMoppel wrote:Works perfectly here for at least 3 drops, but then...
:lol:

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

#38 Post by MochiMoppel »

Back to the thread topic and to the OP's question "Is it possible to create an input box in which an action starts immediately when the item is dropped into the box?"

My last attempt worked only for focus model "click", allowed drag only from external windows, required a tmp file and ...OK, let's forget it.

Gtkdialog has no "dropped" signal and so the main problem is to distinguish between manual entry and drag&drop. I'm now convinced that the concept to allow manual entry is bad. Not only does it require very complex code, it also is hardly useful.

Below demo tries to simulate yad's dnd ("drag-and-drop box") widget which accepts only drag&drop text and triggers an action.

The code uses an entry widget with disabled keyboard input (can-focus="false"). Like yad's dnd widget the entry widget remains neatly blank. Unlike yad it supports all of the following features:
- Accepts drag&drop from the active gtkdialog window, not just from external windows
- Accepts middle click paste (select source text, paste with middle click. Not exactly drag&drop, but IMO even better)
- Accepts paste from clipboard (via right-click dialog, Ctrl+V not possible as keyboard input is disabled)

This technique can produce mini windows very similar to desktop icons and may be particularly useful for touchscreens.

Code: Select all

#!/bin/bash
function drop_action {
	Xdialog -left -backtitle "You dropped:" -msg "${DROP_ZONE// \//\n/}" x &
}; export -f drop_action

echo '
<frame Drop files/folders> 
<entry can-focus="false" has-frame="false">
	<variable>DROP_ZONE</variable> 
	<width>110</width> 
	<height>100</height> 
	<action>[[ $DROP_ZONE ]] && drop_action</action>
	<action>clear:DROP_ZONE</action>
</entry> 
</frame>' | gtkdialog -s
Attachments
drag-and-drop.png
(53.7 KiB) Downloaded 738 times

User avatar
misko_2083
Posts: 114
Joined: Tue 08 Nov 2016, 13:42

#39 Post by misko_2083 »

GtkTreeView creates children when row is DND on another row.

one
^two
three

When you drop row "two" on row "one" this is what happens:
one
\
two
three

In Gtkdialog, the expander that is suppose to expand the children, is disabled. This is probably by design.

In the source ( widget_tree.c ):

Code: Select all

	/* Remove the default indentation in column 0 */
	gtk_tree_view_set_show_expanders(GTK_TREE_VIEW(tree_view), FALSE);
If this is enabled, it is possible to see the children and move them back:

Code: Select all

	/* Show the expander */
	gtk_tree_view_set_show_expanders(GTK_TREE_VIEW(tree_view), TRUE);
Image
This is not the solution, but now we know where the row goes when it is dropped on another row. :D

arivas_2005
Posts: 212
Joined: Sun 25 Feb 2007, 14:39

#40 Post by arivas_2005 »

Hi
in

Code: Select all

#!/bin/bash
function drop_action { 
    fils_sels=$(echo "$DROP_ZONE" | sed 's, /,\n/,g')
    # fil_sels,  is modification thanks to @MochiMoppel
   Xdialog -left -backtitle "You dropped:" -msg "$fils_sels" x &
}; export -f drop_action

echo '
<frame Drop files/folders>
<entry can-focus="false" has-frame="false">
   <variable>DROP_ZONE</variable>
   <width>110</width>
   <height>100</height>
   <action>[[ $DROP_ZONE ]] && drop_action</action>
   <action>clear:DROP_ZONE</action>
</entry>
</frame>' | gtkdialog -s
-How export $DROP_ZONE or $fils_sels ?
I want to use it outside the frame and the function,
in more procedures
Ex.
Xdialog -left -backtitle "You dropped:" -msgbox "${DROP_ZONE// \//\n/} " x or
Xdialog -left -backtitle "You dropped:" -msgbox "$fils_sels" x
outside of the function.
( export fils_sels2=$fils_sels not work!)
Thanks you!

Post Reply