<<MenuSelect>> in Tcl/Tk 8.6.11 and on - menu

I have a problem with MenuSelect event in Tcl/Tk 8.6.11 (tried in Linux, Debian 10.7).
In fact, it doesn't fire at all for the main and tearoff-ed menus. Though working fine in Tcl/Tk 8.6.9, and even in 8.6.11 - only while menus are not tearoff-ed.
A test code:
package require Tk
proc ::somehandler {w wt} {
puts "Step [incr ::step]: $w / $wt, index=[$wt index active]"
}
set w [menu .m -tearoff 1]
$w add command -label {Item 1}
$w add command -label {Item 2}
bind $w <<MenuSelect>> [list ::somehandler $w %W]
pack [button .b -text "Click me" \
-command {tk_popup .m [winfo pointerx .] [winfo pointery .]}]
I tried the following (idiotic though) replacement:
event delete <<MenuSelect>>
event add <<MenuSelect>> <Motion>
bind $w <<MenuSelect>> [list ::somehandler $w %W]
... with the same results.
Seemingly, it's related to menu pathes dealt in Tk somewhat tricky, as seen in the above example.
I'm too lazy to change a standard code at switching from 8.6.9 to 8.6.11/12, 8.7 etc.
TIA for any hints.

This is probably related to the fact that menus use clones for tearoffs and the menubar. From the documentation:
When a menu is set as a menubar for a toplevel window, or when a menu
is torn off, a clone of the menu is made. This clone is a menu widget
in its own right, but it is a child of the original. Changes in the
configuration of the original are reflected in the clone. Additionally,
any cascades that are pointed to are also cloned so that menu traversal
will work right. Clones are destroyed when either the tearoff or
menubar goes away, or when the original menu is destroyed.
I can't remember how exactly clones are really named, but you don't normally interact with them directly; it's only with event handling that you ever really see them. (I've only ever had to deal with them when doing tooltips for menus.)
Normally, it's considered best to avoid using <<MenuSelect>> and instead just set a -command on the entries that can be selected (or to just set the model variables right for checkbutton and radiobutton entries). And avoid tearoffs entirely; they're a style of menu interaction that went out of fashion over 25 years ago.

For Tk 8.6.11+, bind Menu should be used instead of bind $w (for individual menu items). It adds some acrobatics to an event handler that should calculate what's a menu item to be dealt with.
I.e. we have something like:
bind Menu <<MenuSelect>> [list ::somehandler %W]
The %W wildcard is passed to ::somehandler as a "cloned" name, if the menu item is in a cloned menu.
And ::somehandler should calculate who is the %W in reality.
Csaba Nemethi advises to use a procedure like clonename (from utils.tcl of BWidget package). This procedure gets a clone name from a "normal" menu item's path.
Here is a bit modified version of it:
proc clonename {mnu} {
# Gets a clone name of a menu.
# mnu - the menu's path
# This procedure is borrowed from BWidget's utils.tcl.
set path [set menupath {}]
set found 0
foreach widget [lrange [split $mnu .] 1 end] {
if {$found || [winfo class "$path.$widget"] eq {Menu}} {
set found 1
append menupath # $widget
append path . $menupath
} else {
append menupath # $widget
append path . $widget
}
}
return $path
}
As an example of use, see test.tcl of:
http://chiselapp.com/user/aplsimple/repository/baltip/zip/trunk/baltip.zip
Thank you Donal and Csaba for your hints.

Related

Determine Nemo context menu actions ordering

I am having the following problem / question
and I am seeking for help / answers here. :)
I am using Debian 9 with Cinnamon UI and it works fine so far.
I recently started to get myself familiar with the nemo
actions, in order to extend the context menu with my entries.
While this works, I could not figure out how to determine
in which order the menu points are shown.
I tried the common method of using two-digit starts for the .nemo_action files (like for udev rules etc), changing zhe action names, ....
However, I could not figure out what algorithm is behind this
Can anyone shed some light on this?
I can even live with an answer like: “you need to modify the code here...”
The only thing I found on the internet so far:
https://forums.linuxmint.com/viewtopic.php?t=178757
Thanks in advance.
O.K., found it...nemo_action_manager.c, set_up_actions():
file_list = nemo_directory_get_file_list (directory);
// AlexG: List seems to be retrieved unsorted, so let's sort it.
// Then the order of menu items is == alphabetical order of nemo action file names
file_list = g_list_sort(file_list, _cbSortFileList);
[...]
I obtained a small bash script mints nemo github that allow sorting of Nemo Actions based on name; on demand. The default order is by modification date.
Below you find the script to sort actions and to set the order i named them alphabetically.
#!/bin/bash
if ! zenity --question --no-wrap --icon-name="folder" --title="Sort Nemo Actions?" --no-wrap --text="Sorting actions will close down all existing nemo instances.\n\nWould you like to proceed?"; then
exit 1
fi
mkdir -p /tmp/actions/
mv "$HOME"/.local/share/nemo/actions/*.nemo_action /tmp/actions/
ACTIONS=$(find /tmp/actions -iname '*.nemo_action' | sort -n)
for i in $ACTIONS; do
touch "$i"
done
mv /tmp/actions/*.nemo_action "$HOME"/.local/share/nemo/actions/
nemo -q
nemo-desktop -q
nemo-desktop & disown

bash: Create a ncurses dialog radiolist from a dynamic file and output selection to variable

I am working on building a ncurses/dialog driven interactive shell script to Clonezilla to simplify the creation and restoration of images passed with very specific settings that we use each time. Part of the script asks the user to select an image for restoration and I have hit a wall.
I want to use a dialog radiolist for this part so that they can only select a single image file from a list of available images. I create the list of images on the fly and store it in a file called .clone_images_list
I am almost all the way there, I have everything working except that when the user selects a filename, it outputs the line number instead of the filename. I have tried everything that I can think of with no success.
Here is what I have so far:
.
#! /bin/bash
COUNT=1
IMAGELIST=""
while read i; do
IMAGELIST="$IMAGELIST $COUNT $i off"
let COUNT=COUNT+1
done < .clone_images_list
dialog --backtitle "Available Image List" \
--radiolist "Select Image To Restore" 0 0 $COUNT \
$IMAGELIST 2> .tempfile
IMAGEFILE=`cat .tempfile`
echo $IMAGEFILE
Here is what my .clone_images_list looks like:
channel1.170822104015.img
channel2.170822181523.img
channel3.170822180559.img
host.170822160320.img
host.170822174917.img
This list can be longer or shorter and updates anytime a new image has been created.
For my script to work, I need to get the actual filename into a variable that I can use later in my script.
Looking for some ideas....
The radiolist widget returns the selected tag (which is the first column).
In this line
IMAGELIST="$IMAGELIST $COUNT $i off"
you are setting the tag field to a number. If you changed that to
IMAGELIST="$IMAGELIST $i $i off"
then the tag would be a filename.
If you do that, the --no-tags option would be helpful, since otherwise the widget would display the filename twice.

how to add a menuitem in ModelPanel in Maya via mel scripting?

how to add a menuitem in ModelPanel ?
yes! interesingly I couldnot find a proper way to add my menu in ModelPanel. (each of four top,front,persp,side)
eg. I wantto add my menu after "Look at Selection MenuItem"
is it possible ?
I found that
$modelPanelShowMenus
is a string array which is Menu of "Show" for all four viewPorts. but cant dive deeper.
Yes it is possible. You will need to override the function global proc postModelEditorViewMenuCmd which lives in file createModelPanelMenu.mel. Copy the entire procedure to a mel file to your user scripts folder. Do not change the original mel file!
Then add your menu item definitions on the line that come after following line:
$itemName = `menuItem -label (uiRes("m_createModelPanelMenu.kLookAtSelection"))
-command ("{ string $camera = `modelEditor -q -camera "+$editor+"`;"+
"viewLookAt $camera;}")`;
Then in your userSetup.mel call the mel file inside a eval deferred call to override the default behavior. And your set to go.
Alternatively override the menu handler name in the panel itself. This allows you to chain the calls later.

Change default naming conventions by windows explorer using AHK

currently, what happens in windows explorer when highlighting and batch renaming files/folders is as such:
test(1).jpg
test(2).jpg
test(3).jpg
how do i code a script such that highlighting the files/folders and hitting the same hotkey (f2) allows me to change the naming convention?
Variable {space} ###.jpg
where Variable is the name for user input and ### is the running sequence starting from 001?
in addition, i need the script to IGNORE warnings when there's already another file with the previous same name. one possible way to overcome this is to temporarily rename the offending file to a temp name first, so that the renamer can continue with its correct sequence.
Yes, i do know there are many capable applications that can already do the simple job above - but i prefer NOT to have a GUI (since it's v simple).
appreciate everyone's help!
consider this example :
#Include Explorer.ahk ;get it from : https://github.com/denolfe/AutoHotkey/blob/master/lib/Explorer.ahk
F2::
InputBox, Variable, Rename files, Enter your filename prefix.,, 250, 150,,,,,DefaultPrefix
path := Explorer_GetPath()
sel := Explorer_GetSelected()
MsgBox % sel
if ( StrLen(sel) && FileExist(path) )
{
Loop, Parse, sel, `n
{
SetWorkingDir, %path%
MsgBox %A_loopfield%
FileMove, %A_loopfield%, %Variable%_%A_index%.*, 1 ; the '1' means Overwrite
}
}
return

ImageMagick API for command-line GUI application interface to `display` [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
We don’t allow questions seeking recommendations for books, tools, software libraries, and more. You can edit the question so it can be answered with facts and citations.
Closed 4 years ago.
Improve this question
I'd like to, basically, have a quick way to select a box (region of interest) in an image, and get geometry output in ImageMagick's format. I cannot see an easy way to do it with the default ImageMagick display viewer, so I'm looking for some API (and hopefully examples) to allow me to code my own viewer.
A bit of background: In ImageMagick • View topic - selecting a region of interest from command line (2008) it is said you cannot do it, however, there is display: ImageMagick - Region of Interest (2003?) which explains how to do it (but apparently it refers to an older version).
Anyways, this is how things look is you call display -size 300x500 pattern:checkerboard (pattern:checkerboard is built-in pattern image in imagemagick):
Once the "ImageMagick" display window is up, click on it; then Command menu shows - from it, choose /"Image Edit"/"Region of Interest..."; then can click and drag on the viewer display window. And you also get the geometry in upper left corner - but you cannot copy/paste it as text (so I've had to retype).
Also, display in command line mode takes up the terminal (linux - Make imagemagick's display exit at terminal, preserving the window (single instance mode) - Super User) - and I cannot see a way to force it to run in "single instance mode", such that I could issue filenames on the command line, and display would load them in the one and the same currently running instance.
Now, I've found Casting spells with ImageMagick - Image manipulation for programmers (2012), which mentions a MagickWand API; after some searching, I found on the imagemagick site:
ImageMagick: MagickWand, C API for ImageMagick
ImageMagick: MagickCore, Low-level C API for ImageMagick
ImageMagick: PerlMagick, Perl API for ImageMagick
ImageMagick: Magick++, C++ API for ImageMagick
So, my first thought was a script in Python - but apparently there is only a Perl API, which is fine.
However, what I need to code is basically a command line interface, which will start a display -like window process as a "single instance", and exit the terminal while passing parameters such as file name, -density etc to the window; the window would then react on mouse clicks, allowing selection of a crop geometry box (region of interest) - and finally, render the geometry string in a text box, so you can copy it. But as far as I can see, all the APIs are oriented toward performing the functions of the command-line convert.
So my question is - can any of these API's be used to program a display-like GUI; and do there exist any examples of a similar nature (preferably in a scripting language, but I'll live with C/C++) which can be pointed out?
Many thanks in advance for any answers,
Cheers!
Well, this turned out to be a bit of a pain, but I managed to put together a Perl-Tk script with ImageMagick API, that behaves like what I wanted: imgckdis.pl (code also below). Here is a screenshot:
Note that it can pretty much just display an image in hardcoded 400x400 px (although it may extend for bigger images) - there is no menus, no mouse interaction (scrollwheel zoom) - pretty much nothing :) The script only accepts one command-line argument - a file to be opened; but it can also understand ImageMagick specials like "xc:white" (the ImageMagick portion will even automatically render SVG files, as shown on screenshot).
But one thing it is capable of, is working in single instance mode: the first instance started becomes a "master", and draws the Tk window, and locks the respective terminal. Subsequent instances of the script, realizing the master instance is already started, will simply issue a command to the master to load a new image.
This "issuing a command to 'master'" turned out to be not so easy, as the collection of links below shows (as well as the revision notes in the online vesrion). I thought at first, that using interprocess-communication shared variables would allow me to store a "pointer by reference" to the master; and then allow the subsequent instances to call functions on it. Well, it seems that cannot be done - for one, Perl may discourage that - but even if you hop over all those checks, in the end you get a memory address which is not seen as in shared space, and so one cannot retrieve anything from it. Furthermore, the IPC::Shareable Perl package is possibly "guaranteed" only for integers and strings ?!
Nevertheless, the approach that finally worked is, as hinted, to have the "master" poll for changes in changed variables; and non-master instances to simply change this variable when they are called - and this approach seems to work... However, for a "real" application, one would then have to think of organizing quite a few of these shared variables..
Well, maybe one cannot still zoom and reposition the image, and draw a geometry rectangle - but, at least it's an example that can be demonstrated to be working (at least on Ubuntu) :)...
Hope this helps someone,
Cheers!
The code:
#!/usr/bin/perl
# imgckdis.pl
# http://sdaaubckp.svn.sf.net/viewvc/sdaaubckp/single-scripts/imgckdis.pl
use warnings;
use strict;
use Image::Magick; # sudo apt-get install perlmagick # debian/ubuntu
use Tk;
use MIME::Base64;
use Carp;
use Fcntl ':flock';
use Data::Printer;
use Class::Inspector;
use IPC::Shareable;
my $amMaster = 1;
my $file_read;
open my $self, '<', $0 or die "Couldn't open self: $!";
flock $self, LOCK_EX | LOCK_NB or $amMaster = 0;
if ($amMaster == 1) {
print "We are master single instance as per flock\n";
IPC::Shareable->clean_up_all;
}
if (!$ARGV[0]) {
$file_read = "xc:white";
} else {
$file_read = $ARGV[0];
}
chomp $file_read;
my %options = (
create => 1,
exclusive => 0,
mode => 0644,
destroy => 0,
);
my $glue1 = 'dat1';
my $glue2 = 'dat2';
my $refcount;
my $reffname;
my $lastreffname;
my $refcount_handle = tie $refcount, 'IPC::Shareable', $glue1 , \%options ;
if ($amMaster == 1) {
$refcount = undef;
}
my $reffname_handle = tie $reffname, 'IPC::Shareable', $glue2 , \%options ;
if ($amMaster == 1) {
$reffname = undef;
}
my ($image, $blob, $content, $tkimage, $mw);
if ($amMaster == 1) { # if (not(defined($refcount))) {
# initialize the assigns
$lastreffname = "";
$reffname_handle->shlock(LOCK_SH|LOCK_NB);
$reffname = $file_read; #
$reffname_handle->shunlock();
$refcount_handle->shlock(LOCK_SH|LOCK_NB);
$refcount = 1; #
$refcount_handle->shunlock();
}
# mainly from http://objectmix.com/perl/771215-how-display-image-magick-image-tk-canvas.html
sub generateImageContent() {
#fake a PGM then convert it to gif
$image = Image::Magick->new(
size => "400x400",
);
$image->Read($file_read); #("xc:white");
$image->Draw(
primitive => 'line',
points => "300,100 300,500",
stroke => '#600',
);
# set it as PGM
$image->Set(magick=>'pgm');
#your pgm is loaded here, now change it to gif or whatever
$image->Set(magick=>'gif');
$blob = $image->ImageToBlob();
# Tk wants base64encoded images
$content = encode_base64( $blob ) or die $!;
}
sub loadImageContent() {
#fake a PGM then convert it to gif
$image = Image::Magick->new(
size => "400x400",
);
$image->Read($lastreffname); #("xc:red") for test
# set it as PGM
$image->Set(magick=>'pgm');
#your pgm is loaded here, now change it to gif or whatever
$image->Set(magick=>'gif');
$blob = $image->ImageToBlob();
# Tk wants base64encoded images
$content = encode_base64( $blob ) or die $!;
#~ $tkimage->read($content); # expects filename
$tkimage->put($content); # works!
}
sub CleanupExit() {
# only one remove() passes - the second fails: "Couldn't remove shared memory segment/semaphore set"
(tied $refcount)->remove();
IPC::Shareable->clean_up;
$mw->destroy();
print "Exiting appliction!\n";
exit;
}
sub updateVars() {
if ( not($reffname eq $lastreffname) ) {
print "Change: ", $lastreffname, " -> ", $reffname, "\n";
$lastreffname = $reffname;
loadImageContent();
}
}
if ( not($amMaster == 1) ) {
# simply set the shared variable to cmdarg variable
# (master's updateVars should take care of update)
$reffname_handle->shlock(LOCK_SH|LOCK_NB);
$reffname = $file_read;
$reffname_handle->shunlock();
# and exit now - we don't want a second instance
print "Main instance of this script is already running\n";
croak "Loading new file: $file_read";
}
$mw = MainWindow->new();
$mw->protocol(WM_DELETE_WINDOW => sub { CleanupExit(); } );
generateImageContent();
$tkimage = $mw->Photo(-data => $content);
$mw->Label(-image => $tkimage)->pack(-expand => 1, -fill => 'both');
$mw->Button(-text => 'Quit', -command => sub { CleanupExit(); } )->pack;
# polling function for sharable - 100 ms
$mw->repeat(100, \&updateVars);
MainLoop;
__END__
Relevant links:
How to display an Image::Magick image in a Tk::Canvas?
Installing the Perl Image::Magick module on CentOS 5.2 (Fourmilog: None Dare Call It Reason)
perl - How do I install Image::Magick on Debian etch? - Stack Overflow
[magick-users] PerlMagick 6.0.0 Composite -opacity doesn't work
Ensuring only one copy of a perl script is running at a time
Re: Limiting a program to a single running instance - nntp.perl.org
Sys::RunAlone - search.cpan.org
What's the best way to make sure only one instance of a Perl program is running? - Stack Overflow
reinstall PERL - PERL Beginners (Do you need to predeclare croak?)
Image in Perl TK?
Perl Tk::Photo help
introspection - How do I list available methods on a given object or package in Perl? - Stack Overflow
Can't install IPC:Shareable
Share variables between Child processes in perl without IPC::Shareable - Stack Overflow
IPC::Shareable - search.cpan.org
perl - Checking IPC Shareable lock - Stack Overflow
Storing complex data structures using Storable
using tie on two arrays on IPC::Shareable makes array1 and array2 both same even though array2 is not updated.
Dereferencing in perl
Shared Memory using IPC::Shareable - Can't use an undefined value as an ARRAY reference
Re: Handling child process and close window exits in Perl/Tk
How can I convert the stringified version of array reference to actual array reference in Perl? - Stack Overflow
Re: IPC::Shareable Problem with multidimentional hash
perl - IPC::Shareable variables, "Can't use string ... as a SCALAR ref.." and memory address - Stack Overflow
Perl/Tk App and Interprocess Communication
Re: Antw: Re: Perl/Tk + Thread - nntp.perl.org

Resources