When I use QWebInspector (python, PyQT4), it always opens with default activated "Elements" tab.
Is there a way programmatically switch tab to Network?
Now it looks as:
What I want to see:
Script source:
import sys, PyQt4.QtCore, PyQt4.QtGui, PyQt4.QtWebKit
if __name__ == '__main__':
app = PyQt4.QtGui.QApplication(sys.argv)
webview = PyQt4.QtWebKit.QWebView()
inspector = PyQt4.QtWebKit.QWebInspector()
webview.page().settings().setAttribute(
PyQt4.QtWebKit.QWebSettings.DeveloperExtrasEnabled, True
)
inspector.setPage(webview.page())
inspector.showMaximized()
webview.load(PyQt4.QtCore.QUrl('http://yahoo.com'))
app.exec_()
Surely, appropriate ะก++/QT method is also suitable!
Thanks!
WebInspector is based on web. You will need to get first and only child of inspector, it will be QWebView.
Like that:
QList<QWidget*> list = inspector.findChildren<QWidget *>();
QWebView* wv =(QWebView*) list.at(0);
Then connect to javaScriptWindowObjectCleared signal of this view, and in the connected slot execute javascript. You will need object to handle this. I called it someObject, for example
QObject::connect(
wv->page()->mainFrame(),
SIGNAL(javaScriptWindowObjectCleared()),
someObject,
SLOT(openNetworkTab())
);
add slot to someObject's class:
void openNetworkTab(){
wv->page()->mainFrame()->evaluateJavaScript("document.addEventListener('DOMContentLoaded',function(){setTimeout(function(){document.querySelector('.toolbar-item.network').click()},200);});");
}
Delay 200 just to wait for all event bindings initialization before make click
Here list of all inspector tab classes, just in case: .elements, .resources, .network, .scripts, .timeline, .profiles, .audits, .console
Related
I have a browser code built in python using PyQt5 and I want to implement a functionality which is whenever the browser receives an API call from a website to some other service it should open that in the default browser.
For example, whenever we want to login to a website using google and we click on the google option, we get a new window to select our google account. That's the same functionality I want to implement.
Find the complete code here: https://pastebin.com/41n9eghQ
class WebPage(QWebEnginePage):
linkClicked = Signal(QUrl)
def acceptNavigationRequest(self, url, navigation_type, isMainFrame):
if navigation_type == QWebEnginePage.NavigationTypeLinkClicked:
self.linkClicked.emit(url)
return False
return super(WebPage, self).acceptNavigationRequest(
url, navigation_type, isMainFrame)
The above class inside the code accepts and processes the in-browser navigation requests.
def createWindow(self, webwindowtype):
import webbrowser
try:
webbrowser.open(to_text_string(self.url().toString()))
except ValueError:
pass
The above function opens the window in default browser whenever an API call gets triggered, the only problem here is right now I am passing the url of the current website i.e. self.url() and not the url of the API and I don't understand how to do so.
Is there a way to capture the API request and pass that url to the webbrowser.open() function.
Any help would be appreciated, thanks for your attention!
I've been trying to get this working for a long time now and i always get stuck at detecting button presses. I made a toast notification that looks like this:
Here's my code :
import winrt.windows.ui.notifications as notifications
import winrt.windows.data.xml.dom as dom
app = '{1AC14E77-02E7-4E5D-B744-2EB1AE5198B7}\\WindowsPowerShell\\v1.0\\powershell.exe'
#create notifier
nManager = notifications.ToastNotificationManager
notifier = nManager.create_toast_notifier(app)
#define your notification as string
tString = """
<toast>
<visual>
<binding template='ToastGeneric'>
<text>New notifications</text>
<text>Text</text>
<text>Second text</text>
</binding>
</visual>
<actions>
<action
content="test1"
arguments="test1"
activationType="backround"/>
<action
content="test2"
arguments="test2"
activationType="backround"/>
</actions>
</toast>
"""
print(type(notifier.update))
#convert notification to an XmlDocument
xDoc = dom.XmlDocument()
xDoc.load_xml(tString)
#display notification
notifier.show(notifications.ToastNotification(xDoc))
I don't know how to detect button presses
the only thing i figured out is that if i change the argument of the buttons to a link like this:
arguments="https://google.com"
then it will open it
Is there any way i could implement this? or is there documentation for this XML format these toast notifications use. That explains how arguments work?
Alright so I know It's been a while, but I was trying to figure out the same thing and I couldn't find a good, conclusive answer anywhere. I've finally gotten something to work with WinRT in Python 3.9 so I wanted there to be an answer somewhere that people could find!
So to start, I'm not intimately familiar with how the 'arguments' attribute works, but it doesn't seem to be important for at least simple use cases. Most of what I know came from the Windows Toast docs. Here's some code that should produce a notification and open your Documents folder when you click the button. I got a headstart from an answer in this thread but it was missing some very important steps.
import os,sys,time
import subprocess
import threading
import winrt.windows.ui.notifications as notifications
import winrt.windows.data.xml.dom as dom
# this is not called on the main thread!
def handle_activated(sender, _):
path = os.path.expanduser("~\Documents")
subprocess.Popen('explorer "{}"'.format(path))
def test_notification():
#define your notification as
tString = """
<toast duration="short">
<visual>
<binding template='ToastGeneric'>
<text>New notifications</text>
<text>Text</text>
<text>Second text</text>
</binding>
</visual>
<actions>
<action
content="Test Button!"
arguments=""
activationType="foreground"/>
</actions>
</toast>
"""
#convert notification to an XmlDocument
xDoc = dom.XmlDocument()
xDoc.load_xml(tString)
notification = notifications.ToastNotification(xDoc)
# add the activation token.
notification.add_activated(handle_activated)
#create notifier
nManager = notifications.ToastNotificationManager
#link it to your Python executable (or whatever you want I guess?)
notifier = nManager.create_toast_notifier(sys.executable)
#display notification
notifier.show(notification)
duration = 7 # "short" duration for Toast notifications
# We have to wait for the results from the notification
# If we don't, the program will just continue and maybe even end before a button is clicked
thread = threading.Thread(target=lambda: time.sleep(duration))
thread.start()
print("We can still do things while the notification is displayed")
if __name__=="__main__":
test_notification()
The key thing to note here is that you need to find a way to wait for the response to the notification, since the notification is handled by a different thread than the program that produces it. This is why your "www.google.com" example worked while others didn't, because it didn't have anything to do with the Python program.
There's likely a more elegant solution, but a quick and easy way is to just create a Python thread and wait there for a duration. This way it doesn't interfere with the rest of your program in case you need to be doing something else. If you want your program to wait for a response, use time.sleep(duration) without all the threading code to pause the whole program.
I'm not sure how it works exactly, but it seems like the add_activated function just assigns a callback handler to the next available block in the XML. So if you wanted to add another button, my guess is that you can just do add_activated with another callback handler in the same order as you've listed your buttons.
Edit: I played around with it some and it turns out this lets you click anywhere, not just on the button. Not sure where to go from there but it's worth a heads up.
I am trying to make a simple program that opens the web browser when you go to a specific URL in flask.
I am using nginx with uwsgi, to work with flask, running on ubuntu desktop 18.04.
from flask import Flask
import webbrowser
app = Flask(__name__)
#app.route("/test")
def test():
#this is where a new webbrowser should be opened:
webbrowser.open_new_tab("https://google.com")
return "test!"
if __name__ == "__main__":
app.run(host='0.0.0.0')
I expect a new tab of the webbrowser to be opened on the server machine but nothing happens
Do you have a default browser set? You need a default set.
From webbrowser:
If the environment variable BROWSER exists, it is interpreted as the os.pathsep-separated list of browsers to try ahead of the platform defaults.
Another example from the same Python reference page demonstrates you need a window open to use open_new_tab() function:
Here are some simple examples:
url = 'http://docs.python.org/'
# Open URL in a new tab, if a browser window is already open.
webbrowser.open_new_tab(url)
# Open URL in new window, raising the window if possible.
webbrowser.open_new(url)
Ideally, You create a controller object specifying your browser of choice from the table in that link, such as "mozilla", "chrome", "safari" etc., then use the open_new_tab() function on that controller.
https://docs.python.org/3.5/library/webbrowser.html#browser-controller-objects
UPDATE:
So I tried this
import webbrowser
def main():
# this is where a new webbrowser should be opened:
webbrowser.open_new_tab("https://google.com")
return "test!"
if __name__ == "__main__":
main()
And I can open a new tab irrespective if a window is open.
So it works for a simple python script.
Are you saying that when you run you flask app, and try to do a GET request at http://yourip-or-domain-name/test your browser doesn't open?
(Assumption here is port 80 as you don't bind an explicit port in your app.run() call.
I am trying to be able to manage multiple instances of Selenium at the same time, but haven't had much luck. I'm not 100% sure if it's possible. I have an application with a GUI built with PyQT that retrieves our client's information from our SQL database. It's a fairly simple app that lets our users easily log in and out of our clients' accounts. They click the client's name, press "Login", it launches an instance of Firefox, logs into the account, and stays open so the user can do whatever they need to do. When they are done, they click the "Logout" button, and it logs out of the account and quits the webdriver instance.
What I'm trying to provide is a way for them to log into multiple accounts at once, while still maintaining the ability to click one of the client's names that they are logged into, process the logout on that account, and close that browser instance.
One thing I was hoping is to be able to control the webdriver by either a process ID, or unique ID, in which I can store in a dictionary linking it to that client, so when they click the client's name in the app, and press logout, it uses something in PyQT like "client_name = self.list_item.currentItem().text()" to get the name of the client they have selected (which I'm already using for other things, too), finds the unique ID or process ID, and sends the logout command to that instance, and then closes that instance.
This may not be the best way to go about doing it, but it's the only thing I could think of.
EDIT: I also know that you can retrieve the Selenium session_id with driver.session_id (considering your webdriver instance is assigned as 'driver'), but i have seen nothing so far on being able to control a webdriver instance by this session_id.
EDIT2: Here is an incredibly stripped down version of what I have:
from selenium import webdriver
from PyQt4 import QtGui, QtCore
class ClientAccountManager(QtGui.QMainWindow):
def __init__(self):
super(ClientAccountManager, self).__init__()
grid = QtGui.QGridLayout()
# Creates the list box
self.client_list = QtGui.QListWidget(self)
# Populates the list box with owner data
for name in client_names.itervalues():
item = QtGui.QListWidgetItem(name)
self.client_list.addItem(item)
# Creates the login button
login_btn = QtGui.QPushButton("Login", self)
login_btn.connect(login_btn, QtCore.SIGNAL('clicked()'), self.login)
# Creates the logout button
logout_btn = QtGui.QPushButton("Logout", self)
logout_btn.connect(logout_btn, QtCore.SIGNAL('clicked()'), self.logout)
def login(self):
# Finds the owner info based on who is selected
client_name = self.client_list.currentItem().text()
client_username, client_password = get_credentials(client_name)
# Creates browser instance
driver = webdriver.Firefox()
# Logs in
driver.get('https://www.....com/login.php')
driver.find_element_by_id('userNameId').send_keys(client_username)
driver.find_element_by_id('passwordId').send_keys(client_password)
driver.find_element_by_css_selector('input[type=submit]').click()
def logout(self):
# Finds the owner info based on who is selected
client_name = self.client_list.currentItem().text()
# Logs out
driver.get('https://www....com/logout.php')
# Closes the browser instance
driver.quit()
def main():
app = QtGui.QApplication(sys.argv)
cpm = ClientAccountManager()
cpm.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
You can have multiple drivers. Just call webdriver.Firefox() multiple times and keep references to each driver. Some people report oddball behavior, but it basically works.
driver.close() will close the browser and does not take an id.
I'm currently writing a piece of code to test windows app based on pyautowin.
When of the test is to check if we can minimized the window.
Below is the code:
MyApp.Start_(bittorrentApp)
time.sleep(2)
w_handle = pywinauto.findwindows.find_windows(title=u'Bittorrent Automation Task', class_name='WindowsForms10.Window.8.app.0.2bf8098_r15_ad1')[0]
window = MyApp.window_(handle=w_handle)
window.Click()
window.ClickInput(coords = (300,10))
time.sleep(1)
lStyles = win32api.GetWindowLong(GWL_STYLE);
if( lStyles & WS_MINIMIZE ):
print "minimized"
else:
print "not minimized"
I have imported win32api and I can minimized the window.
By the way
lStyles = win32api.GetWindowLong(GWL_STYLE);
return an error, saying GWL_STYLE is not defined
Any idea ?
pywinauto already has all such functionality.
if window.HasStyle(pywinauto.win32defines.WS_MINIMIZE):
window.Minimize()
That's all in HwndWrapper class. You can see all its attributes when typing window.WrapperObject(). in popup hint. WrapperObject() call is usually hidden for readability, but it's called implicitly anyway.
BTW, GetWindowLong(handle, style) has 2 parameters.