how to display an accelerator for a Gio.MenuItem - python-2.7

I'm trying to display the shortcut key accelerator for a Gio.Menuitem
As you can see, the RandomAlbum menu item does not have an accelerator displayed - however, I have added added the accelerator and connected it to the Gio.MenuItem successfully because the menuitem responds to the keyboard shortcut Alt+Z
The snippet of code I'm using is as follows:
action = Gio.SimpleAction.new(action_name, None)
app = Gio.Application.get_default()
app.add_accelerator("<alt>Z", "app."+action_name, None)
item = Gio.MenuItem()
item.set_detailed_action('app.' + action_name)
item.set_label("RandomAlbum")
app.add_plugin_menu_item('tools', "unique name", item)
Any ideas why the accelerator does not display - but still responds to keyboard control?
The full source is here:
https://github.com/fossfreedom/Rhythmbox-Random-Album-Player

The missing piece of this jigsaw puzzle is realising that Gio.MenuItems themselves have attribute-values.
So in this case, before adding the menu-item to the GMenu the syntax required is:
item.set_attribute_value("accel", GLib.Variant("s", "<Alt>Z"))
To complete the answer, you can also set the label and action for the menu-item in this way:
item = Gio.MenuItem()
item.set_attribute_value("label", GLib.Variant("s", "RandomAlbum"))
item.set_attribute_value("action", GLib.Variant("s", "app."+action_name))
However the methods set_label and set_detailed_action perform the same role.

Related

Acumatica - How to change the page opened by the edit button (pencil)

I'm trying to customize a page so that the edit button (the pencil icon one) directs the user to a specific page. In my case, the edit button is linked to a BAccountID field :
By default, it opens the Business Account's page (page CR303000):
I would like it to open a different page that I created that has a similar BAccount view (page AR303001) :
Can this be done ? And how ? I can't seem to find the code behind this logic.
The target graph is declared in the PXPrimaryGraph attribute decorating the DAC.
BAccount DAC is a special case that uses a more complex attribute (CRCacheIndependentPrimaryGraphList) that inherits from PXPrimaryGraph.
[CRCacheIndependentPrimaryGraphList(new Type[]{
typeof(CR.BusinessAccountMaint),
typeof(EP.EmployeeMaint),
typeof(AP.VendorMaint),
typeof(AP.VendorMaint),
typeof(AR.CustomerMaint),
typeof(AR.CustomerMaint),
typeof(AP.VendorMaint),
typeof(AR.CustomerMaint),
typeof(CR.BusinessAccountMaint)},
new Type[]{
typeof(Select<CR.BAccount, Where<CR.BAccount.bAccountID, Equal<Current<BAccount.bAccountID>>,
And<Current<BAccount.viewInCrm>, Equal<True>>>>),
typeof(Select<EP.EPEmployee, Where<EP.EPEmployee.bAccountID, Equal<Current<BAccount.bAccountID>>>>),
typeof(Select<AP.VendorR, Where<AP.VendorR.bAccountID, Equal<Current<BAccount.bAccountID>>>>),
typeof(Select<AP.Vendor, Where<AP.Vendor.bAccountID, Equal<Current<BAccountR.bAccountID>>>>),
typeof(Select<AR.Customer, Where<AR.Customer.bAccountID, Equal<Current<BAccount.bAccountID>>>>),
typeof(Select<AR.Customer, Where<AR.Customer.bAccountID, Equal<Current<BAccountR.bAccountID>>>>),
typeof(Where<CR.BAccountR.bAccountID, Less<Zero>,
And<BAccountR.type, Equal<BAccountType.vendorType>>>),
typeof(Where<CR.BAccountR.bAccountID, Less<Zero>,
And<BAccountR.type, Equal<BAccountType.customerType>>>),
typeof(Select<CR.BAccount,
Where2<Where<
CR.BAccount.type, Equal<BAccountType.prospectType>,
Or<CR.BAccount.type, Equal<BAccountType.customerType>,
Or<CR.BAccount.type, Equal<BAccountType.vendorType>,
Or<CR.BAccount.type, Equal<BAccountType.combinedType>>>>>,
And<Where<CR.BAccount.bAccountID, Equal<Current<BAccount.bAccountID>>,
Or<Current<BAccount.bAccountID>, Less<Zero>>>>>>)
},
VerifyRightsBy = new [] { typeof(CR.BusinessAccountMaint) })]
There is no way to easily customize this attribute. To change it would you need to replace the BAccount DAC with another one. The preferred method for your use case is to avoid usage PXPrimaryGraph attribute by using a regular action button.
The action button can be configured to show the pencil icon:
Make PXButton appear as pencil icon
And it can be displayed beside the field using PXLayout Merge property or you can use LinkCommand to redirect:
https://stackoverflow.com/a/60446714/7376238

Behavioral discrepancy in Tkinter listbox, arrow keys vs. mouse click

My environment is Python 2.7, running on Windows 7.
I'm trying get a Tkinter Listbox to trigger a callback in response to the user changing the 'active' item (i.e. the item with focus). I'm using a binding to the <<ListboxSelect>> event to make this happen, and it's working -- sort of.
The callback itself is supposed to check what the new active item is, and carry out some processing accordingly. This logic operates the way I expect when I change the active item via the up/down arrow keys. But when I point & click on a new item instead, the code mistakenly identifies the prior active item as the current one.
Here's a stripped-down code sample that illustrates the behavior I'm getting:
import Tkinter as tk
#Root window
root = tk.Tk()
#Callback to show focus change
def updateDisplay(*args):
focusIndex = str(lb.index(tk.ACTIVE))
ctrlFI.set('Focus is at index '+focusIndex)
#Control variables
ctrlLB = tk.StringVar()
ctrlFI = tk.StringVar()
#Widgets
lb = tk.Listbox(root,
width=20, height=10,
relief=tk.FLAT,highlightthickness=0,
selectmode=tk.EXTENDED,
activestyle='dotbox',
listvariable=ctrlLB)
lbl = tk.Label(root,
justify=tk.LEFT, anchor=tk.W,
textvariable=ctrlFI)
lb.grid(row=0,column=0,sticky=tk.NW,padx=(5,0),pady=5)
lbl.grid(row=1,column=0,columnspan=2,sticky=tk.NW,padx=5,pady=5)
#Listbox binding to trigger callback
lb.bind('<<ListboxSelect>>',updateDisplay)
#Initializations to prep GUI
ctrlLB.set('Index0-entry Index1-entry Index2-entry Index3-entry Index4-entry')
ctrlFI.set('Ready')
#Begin app
tk.mainloop()
Here are the results when you use the arrow keys:
But here's what you get when you click with the mouse:
The information 'lags' one behind, showing the prior selection instead. (If you click the same item a second time, it 'catches up.')
So my questions are:
What is causing the discrepancy?
How do I fix it so the mouse click gives the right result?
The active item is not necessarily the same as the selected item. When you press the mouse down it changes the selected value but it does not change the active item. The active item only changes once you release the mouse button.
You should be able to see this by clicking and holding the mouse button over an item that is not currently selected. When you do, you'll see something like this:
In the above image, the active item is the one surrounded by a dotted outline. The selected item is in blue. When your code displays the 'focus', it's displaying the active element rather than the selected element.
If you want the selected item, you need to use curselection to get the index of the selected item. It returns a tuple, so in extended mode you need to get the first element that is returned (eg: lb.curselection()[0]). Be sure to handle the case where curselection returns an empty string.

[Python2.7 TKinter]How to gray out a option in optionmenu that has been selected by older instances?

Here's my code:
class DefaultServiceClassWidget(ServiceClassWidget):
def __init__(self, mpet_widget, sc_data, idx):
super(DefaultServiceClassWidget, self).__init__(mpet_widget, sc_data, idx, DefaultServiceClassRow.number)
delete_default_sc_button = Button(mpet_widget.listFrame,justify=LEFT,text="x",fg="red",command= lambda: mpet_widget.delete_sc(self.idx))
delete_default_sc_button.grid(column=4,row=DefaultServiceClassRow.number)
self.select_default_class_label = Label(mpet_widget.listFrame,anchor=W,justify=LEFT,text="Select a Class")
self.select_default_class_label.grid(column=0,row=DefaultServiceClassRow.number)
options = ["All","CS Registration","GPRS Attach","PDP Activation","SMS","Reset","USSD","LTE"]
self.menu_pick_a_class = OptionMenu(mpet_widget.listFrame, sc_data.get_name(), *options, command=lambda event: sc_data.set_id())
self.menu_pick_a_class.grid(column=1,row=DefaultServiceClassRow.number)
self.row = DefaultServiceClassRow.number
DefaultServiceClassRow.number = DefaultServiceClassRow.number+2
def delete(self):
DefaultServiceClassRow.number = DefaultServiceClassRow.number - 2
default_list = (list(self.mpet_widget.listFrame.grid_slaves(row=self.row)) +
list(self.mpet_widget.listFrame.grid_slaves(row=self.row+1)))
for l in default_list:
l.grid_remove()
What happens is that there's a button connected to this function, every time the button is clicked, this function gets called and created a new grid on the GUI. What I want is that if for example "SMS" in optionmenu is selected, the next time this function gets called, "SMS" option will be grayed out (i.e. each option can be only selected once in the program)
I've tried updating status of the selected option by using status = "disabled" but it only works for the same grid, once a new grid(instance) is created, everything gets reset and all the options became available again :(
Also, in the same grid, if I disabled an option by selecting it and then changed to something else, the original selection is still grayed and cannot be selected again - I know why this happens but how do I fix it?
Sorry for the long question but I can't seem to find a solution online :(
Thank you in advance!

WXPython: getting the initial value of a combo box

In a dialog box I have a combo box and a text field. I would like to make so that if one particular value in the combo box is selected, the text field would be disabled (or hidden), and if another value is selected, the text field would be enabled.
I have:
self.myCombo = wx.ComboBox(parent=self, choices=['value1', 'value2'], style = wx.CB_READONLY)
self.myCombo.Bind(wx.EVT_COMBOBOX, self.onChange)
# ...
def onChange(self, ev):
self.myTextField.Enable(False) if self.myCombo.GetValue() != "value1" else self.myTextField.Enable(True)
And this does work like a charm, the text field gets enabled and disabled.
However, I would like to have the text field enabled or disabled depending on the initial value of the combo box, meaning the value gotten from a config file and selected when the dialog box is open.
I've tried the same:
self.myTextField = wx.TextCtrl(parent=self)
self.myTextField.Enable(False) if self.myCombo.GetValue() != "value1" else self.myTextField.Enable(True)
but this doesn't work. I've tried GetSelection also, but when logging this, both GetValue and GetSelection return -1.
The combobox probably isn't fully initialized yet when you try to query it. If you want to disable it when it loads, you don't have to check its value. Just disable it. But for what you want to do, I would recommend using wxPython's wx.CallAfter() method.
Something like the following should suffice:
def __init__(self):
# initialize various variables
wx.CallAfter(self.check_combobox, args)
def check_combobox(self, args):
self.myTextField.Enable(False) if self.myCombo.GetValue() != "value1" else self.myTextField.Enable(True)

How to enable F5 for own view/explorer?

I have a view (ViewPart) based on my own objects (with an ITreeContentProvider). How can I enable the F5-key and the corresponding menu entry (File -> Refresh) for this view? Currently it's disabled.
The refresh action is a retargetable action with id IWorkbenchCommandConstants.FILE_REFRESH and usually implemented with org.eclipse.ui.actions.RefreshAction. So something like this in your ViewPart:
RefreshAction refreshResourcesAction = new RefreshAction(getViewSite());
refreshResourcesAction.setActionDefinitionId(IWorkbenchCommandConstants.FILE_REFRESH);
IActionBars bars = getViewSite().getActionBars();
bars.setGlobalActionHandler(ActionFactory.REFRESH.getId(), refreshResourcesAction);
RefreshAction expects the selection to be IResource based objects - if that is not the case in your view you will have to do more work.