Scripting qBittorrent

Hi folks.

Just wondering if anybody has some insight into qBittorrent. I’m trying to speed up searches.

  • open or focus the app
  • go to search tab
  • enter search term
  • hit enter

The dictionary has nothing specific, but this seems like it has some scriptable aspects to it. Choosing tabs and entering strings into form fields sounds like standard stuff. But then again, what do I know.

Any advice/insight appreciated.

Cheers

This application is not very scriptable, since it has only a standard set of commands. For example, a window has no tab property.

Using GUI scripting, your task can be accomplished something like this:


try
	tell application "qbittorrent" to activate
on error
	-- request to allow incoming connections recieved
	tell application "System Events"
		repeat until (window 1 of application process "UserNotificationCenter") exists
			delay 0.02
		end repeat
		click UI element "Allow" of window application process "UserNotificationCenter"
	end tell
end try

tell application "System Events" to tell application process "qbittorrent"
	set frontmost to true
	repeat until window "qBittorrent v4.2.3" exists
		delay 0.02
	end repeat
	tell window "qBittorrent v4.2.3"
		set searchField to first text field whose description is "Filter torrent names..."
		tell searchField
			set focused to true
			set value to "myTorrentName" -- filter the torrents keyword
		end tell
	end tell
end tell

So how did you know the field name? Properties would be the place I’d look for that. What I found:

{document:missing value,
	 closeable:true,
	 zoomed:false,
	 class:window,
	 index:1,
	 visible:true,
	 name:"[D: 30.4 KiB/s,
	 U: 0 B/s] qBittorrent v4.1.6",
	 modal:false,
	 miniaturizable:true,
	 titled:true,
	 id:2085,
	 miniaturized:false,
	 floating:false,
	 resizable:true,
	 bounds:{39,
	 23,
	 1605,
	 1440},
	 zoomable:true}

Trips up here:


	tell window "qBittorrent v4.1.6"
		-- set searchField to first text field whose description is "Search"
		set searchField to first text field           -- Index bad here, but DOES take focus
		tell searchField
			set focused to true
			set value to "myTorrentName" -- filter the torrents keyword
		end tell
	end tell

What you see, is commands for window class from Standard Suite for each Cocoa application. You can get them:

tell application "qbittorrent" to tell window "qBittorrent v4.2.3" to get properties

Without using GUI scripting you have access only to this properties above. To be able to control other properties, the developer should provide this additional properties. The qBittorent.app doesn’t provide additional properties, so we should use GUI scripting to access all properties of all objects of this Cocoa application. We call System Events.app to help us to access all objects and properties of given Cocoa application. Because System Events.app has access to all of them when the window became frontmost, so only it can help us with non scriptable application:


tell application "System Events" to tell application process "qbittorrent"
	set frontmost to true
	class of UI elements -- {window, menu bar, UI element}
	name of window 1 -- "qBittorrent v4.2.3"
	tell window "qBittorrent v4.2.3"
		class of UI elements -- {group,button,button,...,text field, static text}
		set textFields to every text field -- text field 1
		tell text field 1
			--return name -- returns missing value
			return description -- returns "Filter torrent names..."
			--return it -- returns all properties and classes of this text field
		end tell
	end tell
end tell
-- RESULT: We should tell to 1st text field whose description is "Filter torrent names..."

UI Elements of window “qBittorrent v4.2.3”:

button “Open”
button “Delete”
button “Resume”
button “Pause”
button “Preferences”
button “Lock”
text field 1 – what you needed here
static text 1 – the whole bottom line of window you see (“DHT:…”)
button 8 – close window
button 9 – make window full screen
button 10 – minimize window (to Dock)
static text “qBittorrent v4.2.3”

OK, good to know.

I’m on 4.1.6 on El Capitan:

{window, menu bar} – Transfers tab

then

{group, group, button, button, button, button, button, button, button, button, button, button, button, text field, static text, button, button, button, static text} – Search tab

This app, when it opens, defaults to the Transfers tab. Then it inserts the Search tab. Is there a way to navigate to the Search tab given there are no said objects in the first UI elements?

Basically:

Activate
sleep 3
Move to Searches tab
Enter search into field
perform search


try
	tell application "qbittorrent" to activate
on error
	-- request to allow incoming connections recieved
	tell application "System Events"
		repeat until (window 1 of application process "UserNotificationCenter") exists
			delay 0.02
		end repeat
		click UI element "Allow" of window application process "UserNotificationCenter"
	end tell
end try

tell application "System Events" to tell application process "qbittorrent"
	set frontmost to true
	repeat until window "qBittorrent v4.2.3" exists
		delay 0.02
	end repeat
	tell window "qBittorrent v4.2.3"
		try
			set transfersGroup to 1st group whose name begins with "Transfers"
			tell transfersGroup to click radio button "Search"
		end try
		set value of text field 1 of group 1 to "thisTorrentName" -- edit for your keywords
		click button "Search" of group 1
	end tell
end tell

That worked. Thank you. Question though:

You created a pointer to this first group named “Transfers”. It’s a group? Not clear on that.

Second, you told that pointer/group to click its own radio button, which is not a radio button. Not the radio button I am used to at least.

This application has 2 radio buttons (“Transfers…” and “Search”}. Both of them is child objects of group named “Transfers…”. To click some button we should first tell to its parent object.

If you don’t feel like (or don’t have time) to explore the entire object model of a certain application, than exist the easiest way to determine the full reference to any object (for example, to a button) of the user interface (GUI) - Use the Record functionality of the Automator application and read the script of the action that it wrote.

  1. Open qBittorent
  2. Open Automator, choose creating new Workflow.
  3. Click Record button of Automator
  4. click some object(s) of qBittorent’s window
  5. stop recording of Automator. Now your click action(s) is written in the Automator’s window
  6. drag each written action to empty area under the written actions area (that is, to scripts area)
  7. copy or read founded reference

My screen while Automator recording is ON:

Now, I clicked both radio buttons “Transfer” and “Search” of qBittorent window, then stopped recording by Automator. The screen of Automator with already written actions (that is, 2 my clicks):

Now, I dragged one o 2 written actions (it is Click the “Search” radio button) to the scripts area:

As you see, the full reference to radio button “Search” is:

radio button “Search” of group “Transfers (2)” of window “qBittorrent v4.2.3” of application process “qbittorrent”

NOTE: I removed escaping symbols ("") as you see

And, here is other method to get full references of all objects of qBittorrent’s window. Using the following script in the Apple’s Script Editor. Or, in another script editor (I like Script Debugger, because it lists the result as objects, and you can play with them directly from Results area). The result is very big list, so I don’t provide it here. See and search in it yourself:


tell application "System Events" to tell application process "qbittorrent"
	set frontmost to true
	repeat until window "qBittorrent v4.2.3" exists
		delay 0.02
	end repeat
	tell window "qBittorrent v4.2.3" to return entire contents
end tell

Your first reply is what I accomplished. But this one has more insight for syntax. Both are excellent tools.

Cheers