I am trying to automate IE11 notification bar ( while downloading file) using Rautomation. Using MSUIA adapter I am able to catch the the save button. But I want to use Save As to supply the file location and name. But I cannot do that.
When seeing with UIspy I see that there is a splitbutton with name "Save". This splitbutton has another child splitbutton with name "" ( which is basically the down arrow) - I am not able to get to this control.
iemainwindow_local = RAutomation::Window.new(:class=>"IEFrame" , :adapter => :ms_uia )
ienotificationbar_frame = iemainwindow_local.child(:class=>"Frame Notification Bar")
ienotificationbar = ienotificationbar_frame.child(:class=>"DirectUIHWND")
if ienotificationbar.exists?
ienotificationbar.activate
sleep 1
mycontrol = ienotificationbar.control(:value =>"Save")
mycontrol2= mycontrol.control(:children_only => true)
mycontrol2.exist?
mycontrol.click
end
Getting error at this line mycontrol2= mycontrol.control(:children_only => true)
undefined method `control' for #<RAutomation::Adapter::MsUia::Control:0x4108e60>
Any idea how to get over this block?
I understand that there should be a menu and menuitems associated with the splitButton and when I click on down arrow besides Save, at UISpy I see that menu/ menu item is getting created directly under Desktop window ( though the processID is same ) - how to catch the menuitem Save as?
The Problem
Unfortunately, the :ms_uia adapter for RAutomation is not able to do this in its current form. I know this because I have written a lot of the UIA adapter for it :) The problem is that the current API doesn't allow you to really walk the tree like that (as you found out) because the Control class doesn't have a #control method. If the "Save" button had a native window handle, you'd be able to do this:
ieframe = RAutomation::Window.new(class: 'IEFrame')
save = RAutomation::Window.new(hwnd: ieframe.control(value: 'Save').hwnd)
save.control(index: 0)
Since it does not, unfortunately there isn't a reliable way to get down to it that I am aware of since it doesn't have any identifying properties about it (other than being a child of the "Save" button).
Alternative
I've written another gem called uia, which acts as a low-level wrapper around UI Automation and allows you to work more closely with UI Automation and interact with it how you see it within tools like UI Spy. Eventually, I will use this gem in RAutomation but have not had the time yet. To get down to the "Save As..." split button control in your circumstance, you can do this:
ieframe = UIA.find_element(title: /Thanks for downloading/)
save_as = ieframe.find(name: 'Save').find(control_type: :split_button)
save_as.as(:invoke).invoke
The save_as.as(:invoke) will treat the found "Save As" Element as something that implements the Invoke pattern, and then you can call the #invoke method to get the menu to pop.
Hope this helps!
Related
I am developing a WinUI3 app containing a NavigationView. The NV uses an observable collection to populate the NavigationViewItems.
The app must support expanding and collapsing NavigationViewItems programmatically. The only way I know of to do that is to set NavigationViewItem.IsExpanded = true. And the only way I know of to get the NavigationViewItem is through NavigationView.ContainerFromMenuItem().
The trouble is, ContainerFromMenuItem always returns null except when it is executed from a button event handler (such as a Click handler). The app must perform expand/collapse without user input.
For example, I have a button that launches a Click event with this code, which works just fine to toggle an NVItem:
Category selectedItem = (Category)navview.SelectedItem;
int idx1 = Categories.IndexOf(selectedItem);
var container = (NavigationViewItem)NavView.ContainerFromMenuItem(Categories[idx1]);
if (container != null)
{
container.IsExpanded = !container.IsExpanded;
}
However, that same code, when executed during app startup, such as in the MainWindow constructor after some test items are created, or in Attach(), always results in container being null.
So what am I doing wrong?
This question is somewhat similar to UWP: NavigationView.MenuItems results empty if populated programmatically but the answer to that one only deals with in-event use of ContainerFromMenuItem().
Thanks very much for any assistance on this.
I have a tree view for which some fields need to use a custom delegate for editing. The delegate presents a QListView for value selection. It seems like the QAbstractItemView.edit() method should be used to initiate the edit from the test but I can't figure out how to get access to the created editor (a QListView) so I can select the proper element for the test.
This is part of a test I had working with a QComboBox delegate before switching to the QListVew, but it seems too manual.
for index, enumerator in enumerate(group.children):
editor = delegate.createEditor(
parent=viewport,
option=None,
index=target_index,
)
editor.setCurrentIndex(index)
delegate.setModelData(editor, model, target_index)
assert enumerator.uuid == item.enumeration_uuid
https://github.com/altendky/st/commit/643c5c30f87fc3bfd8b422687e81f740ec36ef44#diff-06bc81dbbd9f7a12878169d5238e1572R846
Here is what I came up with.
https://github.com/altendky/st/blob/089432162b9e8ca67eafdfcc2a4ecc34e8f0e96e/epyqlib/tests/test_attrsmodel.py#L848
for row, enumerator in enumerate(group.children):
assert view.edit(
target_index,
PyQt5.QtWidgets.QAbstractItemView.AllEditTriggers,
None,
)
editor, = view.findChildren(PyQt5.QtWidgets.QListView)
index = editor.model().index(row, 0, editor.rootIndex())
editor.setCurrentIndex(index)
editor.clicked.emit(index)
# this is fun. if you get weird issues try doing this more times
for _ in range(3):
application.processEvents()
assert enumerator.uuid == item.enumeration_uuid
Do note that I connect the editor's clicked signal to post an enter-key event since the view's are hardcoded to catch an enter event and finish editing.
We got a Web Dynpro Application which was created with the Floorplan Manager.
By clicking a specific button I start a Business AddIn which check some conditions and then it should show a popup on the screen with a message for the user.
Is there a way I can accomplish that?
One way to get a PopUp (eg confirmation) window in Floorplan applications is to overwrite the NEEDS_CONFIRMATION method of the Interface IF_FPM_GUIBB_*_EXT inside your feeder-class.
Create a reference to cl_fpm_confirmation_request and put this one in the export-parameter EO_CONFIRMATION_REQUEST of the Method.
By Example:
METHOD if_fpm_guibb_list_ext~needs_confirmation.
DATA li_req TYPE REF TO cl_fpm_confirmation_request.
CASE io_event->mv_event_id.
WHEN 'YOUR_EVENT_ID'.
CREATE OBJECT li_req
EXPORTING
it_confirmation_text = 'Plaintext in Content of Popup'
iv_window_title = 'Title of the Popup'
iv_button_text_approve = 'Text Approve-Button'
iv_button_text_reject = 'Text Reject-Button'
.
eo_confirmation_request = li_confrequ.
ENDCASE.
ENDMETHOD.
The method will be called before the PROCESS_EVENT-Method an will override it when you cancel the popup.
Please be aware that every GUIBB-Implementation has it´s own extension interface, e.g. List, Tree, ...
For a deeper look inside popups in FPM or custom-popups have a look into https://blogs.sap.com/2013/11/26/popups-in-floorplan-manager/
I have an Eclipse product defined in a plugin - it does not define its own Application class (i.e. no custom implementation of IApplication). I am using some dynamic drop-down items in the main toolbar, defined in plugin.xml. I am building the Product using the Eclipse 4.3 (Kepler) platform.
At runtime, I would like the toolbar items to show which of the drop-down items are currently selected. For generic items, I use an icon, but for non-generic items I would like to show some identifying text. The identifying text is not always of the same length.
I am using an IElementUpdater to update the drop-down items and also the toolbar item. Everything works fine, except that the coolbar/toolbar/trimbar does not re-layout. If the new text is longer than the text it is replacing, or if I switch from icon to text or vice-versa, the toolbar appears empty - not even the drop-down arrow is showing. My test team reports that the Drop-down tool item "disappears", which is a pretty good description of the experience.
Is there any way to force the main toolbar/coolbar/trimbar complex re-layout?
I have done some research and it seems that I might be able to do this by defining my own IApplication implementation and capturing the Coolbar/Toolbar manager using an ActionBarAdvisor subclass for later calls to layout(). This is a pretty heavyweight solution - is there any other?
You can always retrieve toolbar manager from PartSite. There are also subclasses EditorSite and ViewSite:
IWorkbenchPartSite site = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getActivePart().getSite();
ToolBarManager mgr = null;
if (site instanceof IEditorSite) {
IEditorSite editorSite = (IEditorSite) site;
mgr = (ToolBarManager) editorSite.getActionBars().getToolBarManager();
} else if (site instanceof IViewSite) {
IViewSite viewSite = (IViewSite) site;
mgr = (ToolBarManager) viewSite.getActionBars().getToolBarManager();
}
Or if you know there is an active editor available:
PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getActiveEditor().getEditorSite().getActionBars().getToolBarManager();
Or inside of a view:
ToolBarManager mgr = getViewSite().getActionBars().getToolBarManager();
Then you will get a possibity to layout it:
mgr.getControl().layout(true);
I have an NSTokenField in my application and I implemented the tokenField:completionsForSubstring:indexOfToken:indexOfSelectedItem: method in which I specify the receiver’s tokenizing character set with the setTokenizingCharacterSet: method:
def tokenField(tokenField, completionsForSubstring:substring, indexOfToken:tokenIndex, indexOfSelectedItem:selectedIndex)
tokenField.setTokenizingCharacterSet(NSCharacterSet.whitespaceAndNewlineCharacterSet)
end
It works as expected when I click on the space bar or the enter button. I would also like to have the same behavior when I click on one of the item of the completion list with my mouse.
How is that possible?
Thanks for your help.
I don't know if it's possible to have this behaviour with a NSTokenField.
But you should take a look at MTTokenField which do what you want out of the box.
To do so, you will have to:
1.Create an Xcode Project as a Static Library(Do not enable ARC).
2.Save your project to vendor/MTTokenField
3.Drag and drop all the files of MTTokenField located in the subdirectory 'MTTokenField' to your new XCode project. Choose to copy the files.
4.Add this to your rakefile in order to compile and link the library with your Rubymotion project.
app.vendor_project("vendor/MTTokenField/", :xcode, :xcodeproj => "MTTokenField.xcodeproj", :target => "MTTokenField", :products => ["libMTTokenField.a"], :headers_dir => "MTTokenField")
5.In Interface Builder change the class of your NSTokenField to NSTextField and then set its custom class to MTTokenField, and also change the custom class of the cell: MTTokenFieldCell instead of NSTextFieldCell.
6.Then you have to set the delegate of your MTTokenField to a class which has to respond to :
def tokenField(tokenField, completionsForSubstring: substring )
# your have to return an array containing your results matching substring.
end
And that's it. It should work.
Hope it helps !
I found another solution using NSTokenField instead of MTTokenField.
In the delegate of my NSTokenField, I used the controlTextDidChange method of NSControl which is called anytime I write a character in my token field. In this method I check if there is a NSLeftMouseUp event which is triggered, and if it's the case, I simulate a click on Return. And that's it.
def controlTextDidChange(aNotification)
application = NSApplication.sharedApplication
event = application.currentEvent
if event.type == NSLeftMouseUp
e1 = CGEventCreateKeyboardEvent(nil, 0x24, true)
CGEventPost(KCGSessionEventTap, e1)
end
end
There is one more thing to do to make it properly work: the issue here is that if I have a completion list with 3 items for instance, one of them will be selected by default, let's say the first one. In this case, the solution will work as expected if I click the second or the third item but I will have to double click the first item to make it work.
To fix this, turn off the autocompletion and only display the suggestion box, i.e add this line to the tokenField:completionsForSubstring:indexOfToken:indexOfSelectedItem: method:
selectedIndex[0] = -1