Capturing Button Methods from a second Form using PyQT - qt

I am super new to PyQT ... I am using QT Designer for my forms. I am confused about where to put my event handling for the second form in my project.
I have the following .py files :
main.py
Ui_make_render_folders.py (generated from the Qt designer ui file)
Ui_prefs.py (generated from the Qt designer ui file)
Mainwindow.py (this is where all the even handling for the main form
lives)
icons_rc.py (resource file)
make_render_folders.py (where all my custom functions live)
Here is a picture of the script running :
click to see script running << CLICK HERE
My question is ... where does the even handling for my prefs window go ???? I cant figure out where to put my [b]on_btn_released() for the buttons on y 2nd form.[/b] Also I am not sure I am instantiating that dialog properly. Currently I am adding this code to the top of my MainWindow.py.
Finally what does #pyqSignature("") do ? And do I need it ?
"""
This is where all teh MainWindow logic sits
"""
import os
import os.path
from PyQt4.QtGui import QMainWindow, QFileDialog, QTreeWidgetItem, QDialog
from PyQt4.QtCore import pyqtSignature, QString
from make_folders import make_render_folders
from Ui_make_render_folders import Ui_MainWindow
from Ui_prefs import Ui_prefs
class Prefs(QDialog, Ui_prefs):
def __init__(self, parent = None):
QDialog.__init__(self, parent)
self.setupUi(self)
#pyqtSignature("")
def on_btn_get_ref_dir_released(self):
print '2nd form'
class MainWindow(QMainWindow, Ui_MainWindow):
def __init__(self, parent = None):
"""
Constructor
"""
QMainWindow.__init__(self, parent)
self.setupUi(self)
self.prefs = QDialog()
ui = Ui_prefs()
ui.setupUi(self.prefs)
#pyqtSignature("")
def on_btn_process_released(self):
print 'process'
no_of_shots = self.spn_no_of_shots.value()
#spot_path = self.le_proj_path.text()+'\\'+self.lst_spots.selectedItems()[0].text()
spot_path_string = 'self.le_proj_path.text())+os.sep,'
spot_path_string += str(self.lst_spots.selectedItems()[0].text())
os.path.join(spot_path_string)
save_position = self.lst_spots.selectedItems()[0]
if no_of_shots > 0:
if self.cmb_mode.currentText() == 'Create Shots':
print ('creating shots')
for x in range(1, no_of_shots+1):
make_render_folders.create_shot_folder(spot_path, x)
else:
print ('inserting shots')
if self.lst_shots.count() > 0:
t =self.lst_shots.selectedItems()[0].text()
cur_shot = t[2:]
cur_shot_val = int(cur_shot)
cur_index = self.lst_shots.currentRow()
print('sel_value :'+cur_shot)
print('sel_index :'+str(cur_index))
next_shot_index = int(cur_index)+1
print('nextshot_index ='+str(next_shot_index))
next_shot_text = self.lst_shots.item(next_shot_index).text()
next_shot_val = int(next_shot_text[2:])
print('nextshot value ='+str(next_shot_val))
insert_space = next_shot_val - cur_shot_val
print(str(insert_space))
if no_of_shots > (insert_space-1) :
print "not enough space - please reduce shots to insert"
else:
print('insert the shots')
for x in range(cur_shot_val,(cur_shot_val+no_of_shots) ):
print (str(x))
make_render_folders.insert_shot_folder(spot_path, x+1)
make_render_folders.populate_shot_list(self)
self.lst_shots.setCurrentRow(0)
#pyqtSignature("")
def on_btn_quit_released(self):
print 'quit'
self.close()
#pyqtSignature("")
def on_cmb_mode_currentIndexChanged(self, ret_text):
print ret_text
#pyqtSignature("")
def on_le_proj_path_editingFinished(self):
print "editingFinished le_proj_path"
def on_le_new_spot_name_textChanged(self):
if len(self.le_new_spot_name.text()) > 0 :
self.btn_add_spot.setEnabled(True)
else :
self.btn_add_spot.setEnabled(False)
#pyqtSignature("")
def on_btn_add_spot_released(self):
v_NewSpotFolder = self.le_new_spot_name.text()
v_rPath = self.le_proj_path.text()
x = make_render_folders.create_spot_folder(v_NewSpotFolder,v_rPath)
if x :
self.le_new_spot_name.clear()
make_render_folders.populate_spots_list(self)
#pyqtSignature("")
def on_actionLoad_Project_triggered(self):
print "actionLoad_Project"
self.lst_shots.clear()
self.lst_spots.clear()
proj_dir = str(QFileDialog.getExistingDirectory(self, 'Select Project'))
print proj_dir
if os.path.exists(proj_dir):
print 'the file is there'
elif os.access(os.path.dirname(proj_dir), os.W_OK):
print 'the file does not exists but write privileges are given'
else:
print 'can not write there'
p = os.path.join(proj_dir+os.sep,'renders')
self.le_proj_path.setText(p)
make_render_folders.populate_spots_list(self)
#pyqtSignature("")
def on_actionConfig_triggered(self):
print "config"
self.prefs.show()
#pyqtSignature("")
def on_actionQuit_triggered(self):
print "ActionQuit"
#pyqtSignature("")
def on_btn_get_folders_released(self):
make_render_folders.populate_spots_list(self)
def on_lst_spots_itemClicked (self):
print "got you"
self.lst_shots.clear()
make_render_folders.populate_shot_list(self)
Thanks !!!

Event handling for the Prefs window can go anywhere. Personally I always prefer to give each window its own file.
So the py files would look something like:
Mainwindow.py (Main form events etc)
Ui_make_render_folders.py (Qt Designer generated UI)
prefs.py (Prefs form events etc)
ui_prefs.py (Qt Designer generated UI)
your other files...
Initialisation: (MainWindow.py)
from PyQt4.QtGui import QMainWindow
from Ui_make_render_folders import Ui_MainWindow
#prefs here refers to the file: prefs.py. PrefWindow is the class within this file.
from prefs import PrefWindow
class MainWindow(QMainWindow):
def __init__(self, parent=None):
#Better way to initialise
super(MainWindow, self).__init__(parent)
self.main = Ui_MainWindow()
self.main.setupUi(self)
#initialise prefs to variable
self.prefs = PrefWindow(self)
# Rest of init...
Note: initialising of second form will be similar to above.
You should place all events for prefs form within its class.
From the function that calls Prefs:
#pyqtSlot()
def on_actionConfig_triggered(self):
print "config"
self.prefs.exec_() # Will block main window while its open.
# Use self.prefs.show() if you want user to be able to interact with main window
Finally: pyqtSignature
On http://pyqt.sourceforge.net/Docs/PyQt4/old_style_signals_slots.html it states that:
'The QtCore.pyqtSignature() serves the same purpose as the pyqtSlot() decorator but has a less Pythonic API.'
Better to use pyqtSlot()

Related

how to add data from ui (made using pyqt) to sqlite db?

i have made a simple pyqt gui with QLineEdit and QPushButton. i like to add showurl(in con.py given below) to sqlite db. the code :
ui.py
from PyQt4 import QtCore, QtGui
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
def _fromUtf8(s):
return s
try:
_encoding = QtGui.QApplication.UnicodeUTF8
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig)
class Ui_Form(object):
def setupUi(self, Form):
Form.setObjectName(_fromUtf8("Form"))
Form.resize(400, 300)
self.verticalLayout_2 = QtGui.QVBoxLayout(Form)
self.verticalLayout_2.setObjectName(_fromUtf8("verticalLayout_2"))
self.verticalLayout = QtGui.QVBoxLayout()
self.verticalLayout.setObjectName(_fromUtf8("verticalLayout"))
self.inserturl = QtGui.QLineEdit(Form)
self.inserturl.setObjectName(_fromUtf8("inserturl"))
self.verticalLayout.addWidget(self.inserturl)
spacerItem = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
self.verticalLayout.addItem(spacerItem)
self.insertdb_btn = QtGui.QPushButton(Form)
self.insertdb_btn.setObjectName(_fromUtf8("insertdb_btn"))
self.verticalLayout.addWidget(self.insertdb_btn)
self.verticalLayout_2.addLayout(self.verticalLayout)
self.retranslateUi(Form)
QtCore.QMetaObject.connectSlotsByName(Form)
def retranslateUi(self, Form):
Form.setWindowTitle(_translate("Form", "Form", None))
self.insertdb_btn.setText(_translate("Form", "ok", None))
con.py
import sys
from PyQt4 import QtCore, QtGui, QtSql
from insertdb2_ui import Ui_Form
def createConnection():
db = QtSql.QSqlDatabase.addDatabase('QSQLITE')
db.setDatabaseName('webscrap.db')
if db.open():
return True
else:
print db.lastError().text()
return False
class Test(QtGui.QWidget, Ui_Form):
def __init__(self):
super(Test, self).__init__()
self.setupUi(self)
self.insertdb_btn.clicked.connect(self.onClick)
def onClick(self):
showurl = self.inserturl.text()
print showurl
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
if not createConnection():
sys.exit(1)
window = Test()
window.show()
sys.exit(app.exec_())
i made the input data ie. showurl print on terminal. i want to add the showurl to sqlitedb webscrap.db which has fields id and url.
I am also confused about using model view(QSqlTableModel, QDataWidgetMapper).
You can use the QtSql.QSqlQuery() class to create query objects that interact with your database. To execute a query (in this case, an INSERT query), perform the following steps:
Instantiate a QSqlQuery() object.
Call the prepare() method on that object, passing to the prepare() method the SQL text that you want to execute.
Use the addBindValue() method to pass in variables to your query -- in this case, you want to pass in showurl.
Finally, call exec_() on the query object to execute
the query. If there is an error, you can retrieve it by calling on
the query object lastError().text().
So, in code, you would need to change your onClick() function to:
def onClick(self):
showurl = self.inserturl.text()
query_object = QtSql.QSqlQuery()
query_object.prepare("INSERT INTO table (url) VALUES (?)")
query_object.addBindValue(showurl)
if not query_object.exec_():
print query_object.lastError().text()
Please note that I did not specify a table name to insert into because you provided field names (id and url) but not a table name; therefore the query string uses a fake table name (table). You should replace this with a real table name. If you do not have a table in your database, you need to create one. Please reference https://www.sqlite.org/lang.html for documentation on SQLite commands (e.g. for creating tables). Please also refer to the PyQt4 documentation on QtSql.QSqlQuery(): http://pyqt.sourceforge.net/Docs/PyQt4/qsqlquery.html
For QSqlTableModel and QDataWidgetMapper, it is difficult to help without having a specific question to answer about them, but I highly recommend that you check out this excellent guide to both of those classes: http://doc.qt.digia.com/qq/qq21-datawidgetmapper.html. This guide does not use PyQt4 (instead it uses Qt alone, so the code is in C++), but the code is sparse and the concepts should resonate even if you are not familiar with C++.

pyqt4 - singleapplication - bring up the original window in an attempt to open the app for the second time

I want only one instance of my app to be running at each time. but when the user attempts to open it the second time, I want the first window to be brought to the front (it could be just minimized or minimized to the corner of the taskbar and the user doesn't know how to open it)
I have this code that does the detection job and it doesn't allow the second instance. I have trouble with the part that it has to open the original window. I have commented out some of my attempt.
import sys
from PyQt4 import QtGui, QtCore
import sys
class SingleApplication(QtGui.QApplication):
def __init__(self, argv, key):
QtGui.QApplication.__init__(self, argv)
self._activationWindow=None
self._memory = QtCore.QSharedMemory(self)
self._memory.setKey(key)
if self._memory.attach():
self._running = True
else:
self._running = False
if not self._memory.create(1):
raise RuntimeError(
self._memory.errorString().toLocal8Bit().data())
def isRunning(self):
return self._running
def activationWindow(self):
return self._activationWindow
def setActivationWindow(self, activationWindow):
self._activationWindow = activationWindow
def activateWindow(self):
if not self._activationWindow:
return
self._activationWindow.setWindowState(
self._activationWindow.windowState() & ~QtCore.Qt.WindowMinimized)
self._activationWindow.raise_()
self._activationWindow.activateWindow()
class Window(QtGui.QWidget):
def __init__(self):
QtGui.QWidget.__init__(self)
self.label = QtGui.QLabel(self)
self.label.setText("Hello")
layout = QtGui.QVBoxLayout(self)
layout.addWidget(self.label)
if __name__ == '__main__':
key = 'random _ text'
app = SingleApplication(sys.argv, key)
if app.isRunning():
#app.activateWindow()
sys.exit(1)
window = Window()
#app.setActivationWindow(window)
#print app.topLevelWidgets()[0].winId()
window.show()
sys.exit(app.exec_())
I've made this work on Windows using the win32 api (I'm not entirely sure, but there are probably equivalent calls on macos/unix).
Add the following import to your application,
import win32gui
set the window title to a fixed name (instead of doing this, you could store its whndl in the shared memory)
window = Window()
window.setWindowTitle('Single Application Example')
window.show()
and then change your activateWindow method to something like the following:
def activateWindow(self):
# needs to look for a named window ...
whndl = win32gui.FindWindowEx(0, 0, None, "Single Application Example")
if whndl is 0:
return #couldn't find the name window ...
#this requests the window to come to the foreground
win32gui.SetForegroundWindow(whndl)
You might be interested by the solutions proposed here
For instance, I would try:
app = SingleApplication(sys.argv, key)
if app.isRunning():
window = app.activationWindow()
window.showNormal()
window.raise()
app.activateWindow()
sys.exit(1)
window = Window()
app.setActivationWindow(window)
window.setWindowFlags(Popup)
window.show()

GTK TreeView with ListStore don't display anything. Python and SQLite3 used

I use GTK and Python for developing an application.
I want to load TreeView elements (1 column) from SQLite3 database.
But something go wrong (without any error)!
Here is a whole code:
#!/usr/bin/python
import sys
import sqlite3 as sqlite
from gi.repository import Gtk
from gi.repository import Notify
def notify(notifer, text, notificationtype=""):
Notify.init("Application")
notification = Notify.Notification.new (notifer, text, notificationtype)
notification.show ()
def get_object(gtkname):
builder = Gtk.Builder()
builder.add_from_file("main.ui")
return builder.get_object(gtkname)
def base_connect(basefile):
return sqlite.connect(basefile)
class Handler:
def main_destroy(self, *args):
Gtk.main_quit(*args)
def hardwaretool_clicked(self, widget):
baselist = get_object("subjectlist")
baselist.clear()
base = base_connect("subjectbase")
with base:
cur = base.cursor()
cur.execute("SELECT * FROM sub")
while True:
row = cur.fetchone()
if row == None:
break
iter = baselist.append()
print "row ", row[0]
baselist.set(iter, 0, row[0])
cur.close()
def gamestool_clicked(self, widget):
print("gamestool clicked!!!!! =)")
def appstool_clicked(self, widget):
print("appstool clicked!!!!! =)")
def fixtool_clicked(self, widget):
notify("Charmix","Fix Applied", "dialog-ok")
def brokenfixtool_clicked(self, widget):
notify("Charmix","Broken Fix Report Sended", "dialog-error")
def sendfixtool_clicked(self, widget):
notify("Charmix","Fix Sended", "dialog-information")
class CharmixMain:
def __init__(self):
builder = Gtk.Builder()
builder.add_from_file("main.ui")
self.window = builder.get_object("main")
self.subject = builder.get_object("subjectlist")
self.problem = builder.get_object("problemlist")
self.toolbar = builder.get_object("toolbar")
self.hardwaretool = builder.get_object("hardwaretool")
self.gamestool = builder.get_object("gamestool")
self.appstool = builder.get_object("appstool")
self.fixtool = builder.get_object("fixtool")
self.brokenfixtool = builder.get_object("brokenfixtool")
self.sendfixtool = builder.get_object("sendfixtool")
builder.connect_signals(Handler())
context = self.toolbar.get_style_context()
context.add_class(Gtk.STYLE_CLASS_PRIMARY_TOOLBAR)
if __name__ == "__main__":
Charmix = CharmixMain()
Charmix.window.show()
Gtk.main()
I'm interested in this part (not working normally):
def hardwaretool_clicked(self, widget):
baselist = get_object("subjectlist")
baselist.clear()
base = base_connect("subjectbase")
with base:
cur = base.cursor()
cur.execute("SELECT * FROM sub")
while True:
row = cur.fetchone()
if row == None:
break
iter = baselist.append()
print "row ", row[0]
baselist.set(iter, 0, row[0])
cur.close()
TreeView(subjecttree) don't display anything, but print "row ", row[0] works fine and display all the strings.
Please, help me.
Maybe i need to repaint TreeView or thomething like that?
Do you know, how can I get it?
The problem is in your get_object method.
When you do:
builder = Gtk.Builder()
builder.add_from_file("main.ui")
you're actually creating a new window; even if you are using the same ui file, you are creating a completely different widget.
One way to get around the problem of accesing the widgets you need to process with your handler is to pass them as parameter of the constructor:
class Handler(object):
def __init__(self, widget1, widget2):
self.widget1 = widget1
self.widget2 = widget2
...
You can use those widgets on the handler's method afterwards.
Another way of accesing the widgets in a more 'decoupled' way is to add the object you want to use as the last parameter of the connect method when you're connecting signals; the drawback is that you would have to do this manually (since Glade doesn't provide this posibility)
self.widget.connect('some-signal', handler.handler_method, object_to_use)

Overwriting the createWindow function in PyQt

I'm trying to handle the createWindow method in PyQt webkit. When you do this, PyQt gives the method a QWebPage.WebWindowType (or QWebPage::WebWindowType in c++). All I need is a URL to create a new window, so I'm not sure what to do with this class. The docs don't explain it very well either: http://doc.qt.digia.com/qt/qwebpage.html#WebWindowType-enum
I'm trying to intergrate this with my "Tab" class:
class Tab(QtGui.QWidget):
"""
Contains the variables and methods needed to open the Qt
based user interface and the event bus to allow interaction.
"""
def __init__(self, url, window):
"""
Set the up the following:
1) Initialise the Qt user interface.
2) Set margins.
3) Initialise the cookie jar.
4) Set the default URL.
5) Set the history buttons to disabled (there is not history yet).
5) Hide the tools menu.
6) Create the GUI event bus.
7) Set keyboard bindings.
"""
self.window = window
QtGui.QWidget.__init__(self)
self.ui = Ui_Browser()
self.ui.setupUi(self)
l = self.layout()
l.setMargin(0)
self.ui.horizontalLayout.setMargin(0)
try:
self.ui.webView.page().networkAccessManager().setCookieJar(self.window.cookies)
except:
pass
self.ui.webView.setUrl(url)
self.ui.url.setText(url.toString())
self.ui.back.setEnabled(False)
self.ui.forward.setEnabled(False)
self.ui.toolsBox.hide()
self.ui.tools.setChecked(False)
QtCore.QObject.connect(self.ui.back, QtCore.SIGNAL("clicked()"), self.back)
QtCore.QObject.connect(self.ui.forward, QtCore.SIGNAL("clicked()"), self.forward)
QtCore.QObject.connect(self.ui.refresh, QtCore.SIGNAL("clicked()"), self.refresh)
QtCore.QObject.connect(self.ui.url, QtCore.SIGNAL("returnPressed()"), self.url)
QtCore.QObject.connect(self.ui.webView, QtCore.SIGNAL("linkClicked (const QUrl&)"), self.navigate)
QtCore.QObject.connect(self.ui.webView, QtCore.SIGNAL("urlChanged (const QUrl&)"), self.navigate)
QtCore.QObject.connect(self.ui.webView, QtCore.SIGNAL("titleChanged(const QString&)"), self.title)
QtCore.QObject.connect(self.ui.webView, QtCore.SIGNAL("loadStarted()"), self.showProgressBar)
QtCore.QObject.connect(self.ui.webView, QtCore.SIGNAL("loadProgress(int)"), self.setProgressBar)
QtCore.QObject.connect(self.ui.webView, QtCore.SIGNAL("loadFinished(bool)"), self.hideProgressBar)
QtCore.QObject.connect(self.ui.toolPrint, QtCore.SIGNAL("clicked()"), self.printPage)
self.ui.webView.createWindow = self.createWindow
QtGui.QShortcut(QtGui.QKeySequence("Backspace"), self, self.back)
QtGui.QShortcut(QtGui.QKeySequence("F5"), self, self.refresh)
QtGui.QShortcut(QtGui.QKeySequence("Ctrl+p"), self, self.printPage)
def url(self):
"""
Go to URL entered.
"""
self.setHistory()
url = self.ui.url.text()
if not str(url).startswith("http://"):
url = "http://" + url
self.ui.webView.setUrl(QtCore.QUrl(url))
def navigate(self, url):
"""
Navigate to page requested.
"""
self.setHistory()
self.ui.url.setText(url.toString())
def refresh(self):
"""
Refresh the page.
"""
self.ui.webView.setUrl(QtCore.QUrl(self.ui.webView.url()))
def back(self):
"""
Enable the back button.
"""
page = self.ui.webView.page()
history = page.history()
history.back()
if history.canGoBack():
self.ui.back.setEnabled(True)
else:
self.ui.back.setEnabled(False)
def forward(self):
"""
Enable the forward button.
"""
page = self.ui.webView.page()
history = page.history()
history.forward()
if history.canGoForward():
self.ui.forward.setEnabled(True)
else:
self.ui.forward.setEnabled(False)
def title(self, title):
"""
Change the title of the window.
"""
self.window.tabs.setTabText(self.window.tabs.indexOf(self), title) or (self.window.setWindowTitle(title) if self.isThisFocused() else "New Tab")
def createWindow(self, WebWindowType):
"""
Overide the default behaviour.
"""
tab = Tab(QtCore.QUrl("about:blank"), self.window)
print(mode)
if mode == QtWebKit.QWebPage.WebModalDialog:
tab.ui.webView.setWindowModality(QtCore.Qt.ApplicationModal)
self.window.tabs.setCurrentIndex(self.window.tabs.addTab(tab, ""))
def isThisFocused(self):
"""
Return whether this tab is focused or not.
"""
if self.window.tabs.currentWidget() == self:
return True
return False
def setHistory(self):
"""
Check history and update buttons.
"""
page = self.ui.webView.page()
history = page.history()
if history.canGoBack():
self.ui.back.setEnabled(True)
else:
self.ui.back.setEnabled(False)
if history.canGoForward():
self.ui.forward.setEnabled(True)
else:
self.ui.forward.setEnabled(False)
def showProgressBar(self):
"""
We're loading a page, show the load progress bar.
"""
self.ui.progress.show()
def setProgressBar(self, percent):
"""
Set the percentage of the progress bar.
"""
self.ui.progress.setValue(percent)
def hideProgressBar(self, bool):
"""
We've finished loading the page, there is no need for the progress bar.
"""
self.ui.progress.hide()
def printPage(self):
"""
Use Qt's goodness to print the page.
"""
previewer = QtGui.QPrintPreviewDialog(paintRequested=self.ui.webView.print_)
previewer.exec_()
The createWindow function is used for handling requests to open a new window (e.g. a javascript window.open() call).
By default, createWindow does nothing, so it must be reimplemented it in a subclass.
Also, to work with javascript, it is necessary that the web-settings specify that javascript programs are allowed to open new windows.
Here's a demo script that illustrates how to use createWindow:
from PyQt4 import QtGui, QtCore, QtWebKit
class Browser(QtWebKit.QWebView):
_windows = set()
#classmethod
def _removeWindow(cls, window):
if window in cls._windows:
cls._windows.remove(window)
#classmethod
def newWindow(cls):
window = cls()
cls._windows.add(window)
return window
def __init__(self, parent=None):
QtWebKit.QWebView.__init__(self, parent)
self.setAttribute(QtCore.Qt.WA_DeleteOnClose, True)
self.settings().setAttribute(
QtWebKit.QWebSettings.JavascriptEnabled, True)
self.settings().setAttribute(
QtWebKit.QWebSettings.JavascriptCanOpenWindows, True)
def closeEvent(self, event):
self._removeWindow(self)
event.accept()
def createWindow(self, mode):
window = self.newWindow()
if mode == QtWebKit.QWebPage.WebModalDialog:
window.setWindowModality(QtCore.Qt.ApplicationModal)
window.show()
return window
html = """
<html>
<head>
<title>Test Page</title>
<script type="text/javascript"><!--
var url = 'https://www.google.com'
var count = 0
function newWindow() {
count += 1;
window.open(url, 'testwindow' + count, 'width=640,height=480');
}
--></script>
</head>
<body>
<input type="button" value="New Window" onclick="newWindow()" />
<p>Test Link</p>
</body>
</html>"""
if __name__ == '__main__':
import sys
app = QtGui.QApplication(sys.argv)
browser = Browser()
browser.setHtml(html)
browser.show()
sys.exit(app.exec_())
(NB: It is essential that a reference is kept to any newly created windows; failure to do so will almost certainly result in segmentation faults).
EDIT:
Just to clarify:
The createWindow function is intended to handle external requests to open a new browser window (e.g. a javascript window.open() call, as in the example above). And note that createWindow is a virtual function. This means that if it is overridden in a subclass of QWebView or QWebPage, the reimplemented function can be called internally by Qt. This is obviously vital if you need your own creatWindow function to be called from javascript code.
So if you want javascript programs on web-pages to be able to create and open an instance of your browser window class, then subclass QWebView and reimplement its createWindow function (as in the example above).
The createWindow function is not required at all for simply creating and showing a QWebView (e.g. adding a new tab). A QWebView is just a container for displaying web-pages, and is created and shown just like any other widget.

Connecting/disconnecting signals via eventFilter

I have an app with hundreds of custom buttons, each one needs multiple signal connections. The connect calls seem to be pretty slow, so I'm trying to connect/disconnect each button's signals via the main window's eventFilter using the enter and leave events.
However, sometimes those events seems to be called multiple times, causing RuntimeErrors (when trying to disconnect an event that is already gone).
Here is a snippet of code that shows a similar (and hopefully related) problem using default PushButtons.
To see the runtime error here, run the code, push one of the buttons, then close the window. That's when I see this:
RuntimeError: Fail to disconnect signal clicked().
Here is the code. Does anybody know if this is a PySide bug?
from PySide.QtGui import *
from PySide.QtCore import *
import sys
class TestWindow( QWidget ):
def __init__( self, parent=None ):
super( TestWindow, self ).__init__( parent )
self.setLayout( QGridLayout() )
def addWidget( self, w ):
self.layout().addWidget( w )
def testCB( self ):
print 'button connected'
def eventFilter( self, obj, event ):
'''Connect signals on mouse over'''
if event.type() == QEvent.Enter:
print 'enter',
obj.clicked.connect( self.testCB )
elif event.type() == QEvent.Leave:
print 'leave'
obj.clicked.disconnect( self.testCB )
return False
app = QApplication( sys.argv )
w = TestWindow()
for i in xrange(10):
btn = QPushButton( 'test %s' % i )
w.addWidget( btn )
btn.installEventFilter(w)
w.show()
sys.exit( app.exec_() )
In few cases, when I tested mouse events, showed better performance while events are attached to item class... so don't subclass. Rather :
class Button(QPushButton):
def __init__(self, label):
super(Button, self).__init__()
self.setText(label)
app = QApplication( sys.argv )
w = TestWindow()
for i in xrange(10):
btn = Button( 'test %s' % i )
w.addWidget( btn )
...then define mouse event for class.

Resources