SaltyCrane: pyqthttps://www.saltycrane.com/blog/2008-01-29T17:33:00-08:00PyQt: How to pass arguments while emitting a signal
2008-01-29T17:33:00-08:00https://www.saltycrane.com/blog/2008/01/pyqt-how-to-pass-arguments-while/
<p>I often forget how to do this so I'm documenting it here for future reference.
If I want to emit a signal and also pass an argument with that signal, I
can use the form <code>self.emit(SIGNAL("<em>mySignalName</em>"), myarg)</code>.
I connect the signal to a method in the usual way.
To use the argument, I merely need to specify the argument in the method
definition. What often confuses me is that I don't need to specify arguments
in the <code>connect</code> statement. The example below emits a signal
<code><em>didSomething</em></code> and passes two arguments,
<code><em>"important"</em></code> and
<code><em>"information"</em></code> to the <code>update_label</code> method.
</p>
<pre class="python">import sys
import time
from PyQt4.QtCore import *
from PyQt4.QtGui import *
####################################################################
class MyWindow(QWidget):
def __init__(self, *args):
QWidget.__init__(self, *args)
self.label = QLabel(" ")
layout = QVBoxLayout()
layout.addWidget(self.label)
self.setLayout(layout)
self.connect(self, SIGNAL("didSomething"),
self.update_label)
self.do_something()
def do_something(self):
self.emit(SIGNAL("didSomething"), "important", "information")
def update_label(self, value1, value2):
self.label.setText(value1 + " " + value2)
####################################################################
if __name__ == "__main__":
app = QApplication(sys.argv)
w = MyWindow()
w.show()
sys.exit(app.exec_())
</pre>
PyQt4 QItemDelegate example with QListView and QAbstractListModel
2008-01-23T18:13:00-08:00https://www.saltycrane.com/blog/2008/01/pyqt4-qitemdelegate-example-with/
<p>I am currently working on a mini project which uses a QListView to
display items in a list box. I am happy with most of the default
behavior in the list view, however, I want to change how the highlighting
of selected items is displayed. Currently, in my Windows environment,
selecting
an item in the list highlights the item in dark blue. This is fine, however,
when the list box loses focus, the highlight color turns to a light gray,
which is hard for me to see. I would like the selection to have a red
highlight, whether the widget has focus or not.
</p>
<p>My solution is to add a custom delegate to my list view. Normally,
a standard view
uses a default delegate (QItemDelegate) to render and edit the model's
data. To customize the way the data is displayed in the view, I
subclass QItemDelegate and implement a custom <code>paint()</code>
method to set the background color to red for selected items. (Note,
it is possible to specify certain formatting (including background color)
using ItemDataRoles in the QAbstractListModel subclass, however, using
a custom delegate is more powerful, and I didn't want to mix
appearance-related code with my data model.)</p>
<p>In the example below, I started with the <a href="http://www.saltycrane.com/blog/2008/01/pyqt-43-simple-qabstractlistmodel/">
simple QListView / QAbstractListModel example</a>, and added MyDelegate, a
subclass of QItemDelegate. This class reimplements the <code>paint()</code>
method to highlight selected items in red.</p>
<p>See also: <a href="http://doc.trolltech.com/4.3/qitemdelegate.html#details">
Qt 4.3 QItemDelegate documentation</a></p>
<pre class="python">import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
####################################################################
def main():
app = QApplication(sys.argv)
w = MyWindow()
w.show()
sys.exit(app.exec_())
####################################################################
class MyWindow(QWidget):
def __init__(self, *args):
QWidget.__init__(self, *args)
# create objects
list_data = [1,2,3,4]
lm = MyListModel(list_data, self)
de = MyDelegate(self)
lv = QListView()
lv.setModel(lm)
lv.setItemDelegate(de)
# layout
layout = QVBoxLayout()
layout.addWidget(lv)
self.setLayout(layout)
####################################################################
class MyDelegate(QItemDelegate):
def __init__(self, parent=None, *args):
QItemDelegate.__init__(self, parent, *args)
def paint(self, painter, option, index):
painter.save()
# set background color
painter.setPen(QPen(Qt.NoPen))
if option.state & QStyle.State_Selected:
painter.setBrush(QBrush(Qt.red))
else:
painter.setBrush(QBrush(Qt.white))
painter.drawRect(option.rect)
# set text color
painter.setPen(QPen(Qt.black))
value = index.data(Qt.DisplayRole)
if value.isValid():
text = value.toString()
painter.drawText(option.rect, Qt.AlignLeft, text)
painter.restore()
####################################################################
class MyListModel(QAbstractListModel):
def __init__(self, datain, parent=None, *args):
""" datain: a list where each item is a row
"""
QAbstractTableModel.__init__(self, parent, *args)
self.listdata = datain
def rowCount(self, parent=QModelIndex()):
return len(self.listdata)
def data(self, index, role):
if index.isValid() and role == Qt.DisplayRole:
return QVariant(self.listdata[index.row()])
else:
return QVariant()
####################################################################
if __name__ == "__main__":
main()
</pre>
How to install pyqt4 on ubuntu linux
2008-01-15T12:41:00-08:00https://www.saltycrane.com/blog/2008/01/how-to-install-pyqt4-on-ubuntu-linux/<h5>Install and run "hello world" example</h5>
<ul>
<li><pre>apt-cache search pyqt</pre></li>
<li><pre>sudo apt-get install python-qt4</pre></li>
<li>Create a file <code>~/tmp/helloworld.py</code>
<pre class="python">import sys
from PyQt4.QtGui import *
app = QApplication(sys.argv)
button = QPushButton("Hello World", None)
button.show()
app.exec_()</pre>
</li>
<li>Run it:
<pre>python ~/tmp/helloworld.py</pre>
You should see a window with a single button pop up.
</li>
</ul>
<br>
<h5>Install additional examples</h5>
<ul>
<li>For more examples, install the <code>python-qt4-doc</code> package:
<pre>sudo apt-get install python-qt4-doc</pre>
</li>
<li>After installation, the examples are located at:
<pre>/usr/share/doc/python-qt4-doc/examples</pre>
</li>
</ul>
Python PyQt Tab Completion example
2008-01-04T12:18:00-08:00https://www.saltycrane.com/blog/2008/01/python-pyqt-tab-completion-example/
<p>Here is an example Python GUI that implements tab completion. It uses
the open source <a href="http://trolltech.com/products/qt">Qt
4.3 toolkit</a> and <a href="http://www.riverbankcomputing.co.uk/pyqt/">
PyQt 4.3</a> Python bindings.
</p>
<p>A list of words is presented in a list box. As the user types,
the list is shortened to show possible matches. If the user presses
<em>TAB</em>, the input text is "completed" to the longest possible
string match. This may be a whole word or a common substring of
multiple words.</p>
<p>This example consists of two basic elements:
<ul>
<li><code>MyLineEdit</code> is a subclass of the <a href="http://doc.trolltech.com/4.3/qlineedit.html">
<code>QLineEdit</code></a>
class. It is used as an input box to enter text. I needed to subclass
<code>QLineEdit</code> because I needed to capture the <em>TAB</em>
key press event for tab completion. (See <a href="http://www.saltycrane.com/blog/2008/01/how-to-capture-tab-key-press-event-with/">
this previous post</a>.)
</li>
<li><a href="http://doc.trolltech.com/4.3/qlistview.html">
<code>QListView</code></a> and <code>MyListModel</code> implement a
list with a simple model/view architechture. <code>MyListModel</code>
is a subclass of <a href="http://doc.trolltech.com/4.3/qabstractlistmodel.html">
<code>QAbstractListModel</code></a>. I implemented
the required <code>rowCount</code> and <code>data</code> methods
as well as a method called <code>setAllData</code> which replaces
the entire existing data with a new list of data.
</li>
</ul>
</p>
<p>This example makes use of two <code>SIGNAL</code>s:
<ul>
<li>The <code>textChanged</code> signal is emitted each time the user
types a letter inside the <code>QLineEdit</code> box.
It is connected to the
<code>text_changed</code> method which updates the list of words
in the <code>QListView</code>. <code>MyListModel</code>'s
<code>setAllData</code> method is used to update the data.
</li>
<li>The <code>tabPressed</code> signal is a custom signal I added to
my <code>QLineEdit</code> subclass. It is emitted each time the user
presses the <em>TAB</em> key. This signal is connected the <code>
tab_pressed</code> method which completes the input to the
longest matching substring of the available words.
</li>
</ul>
</p>
<pre class="python">import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
LIST_DATA = ['a', 'aardvark', 'aardvarks', 'aardwolf', 'aardwolves',
'abacus', 'babel', 'bach', 'cache',
'daggle', 'facet', 'kabob', 'kansas']
####################################################################
def main():
app = QApplication(sys.argv)
w = MyWindow()
w.show()
sys.exit(app.exec_())
####################################################################
class MyWindow(QWidget):
def __init__(self, *args):
QWidget.__init__(self, *args)
# create objects
self.la = QLabel("Start typing to match items in list:")
self.le = MyLineEdit()
self.lm = MyListModel(LIST_DATA, self)
self.lv = QListView()
self.lv.setModel(self.lm)
# layout
layout = QVBoxLayout()
layout.addWidget(self.la)
layout.addWidget(self.le)
layout.addWidget(self.lv)
self.setLayout(layout)
# connections
self.connect(self.le, SIGNAL("textChanged(QString)"),
self.text_changed)
self.connect(self.le, SIGNAL("tabPressed"),
self.tab_pressed)
def text_changed(self):
""" updates the list of possible completions each time a key is
pressed """
pattern = str(self.le.text())
self.new_list = [item for item in LIST_DATA if item.find(pattern) == 0]
self.lm.setAllData(self.new_list)
def tab_pressed(self):
""" completes the word to the longest matching string
when the tab key is pressed """
# only one item in the completion list
if len(self.new_list) == 1:
newtext = self.new_list[0] + " "
self.le.setText(newtext)
# more than one remaining matches
elif len(self.new_list) > 1:
match = self.new_list.pop(0)
for word in self.new_list:
match = string_intersect(word, match)
self.le.setText(match)
####################################################################
class MyLineEdit(QLineEdit):
def __init__(self, *args):
QLineEdit.__init__(self, *args)
def event(self, event):
if (event.type()==QEvent.KeyPress) and (event.key()==Qt.Key_Tab):
self.emit(SIGNAL("tabPressed"))
return True
return QLineEdit.event(self, event)
####################################################################
class MyListModel(QAbstractListModel):
def __init__(self, datain, parent=None, *args):
""" datain: a list where each item is a row
"""
QAbstractTableModel.__init__(self, parent, *args)
self.listdata = datain
def rowCount(self, parent=QModelIndex()):
return len(self.listdata)
def data(self, index, role):
if index.isValid() and role == Qt.DisplayRole:
return QVariant(self.listdata[index.row()])
else:
return QVariant()
def setAllData(self, newdata):
""" replace all data with new data """
self.listdata = newdata
self.reset()
####################################################################
def string_intersect(str1, str2):
newlist = []
for i,j in zip(str1, str2):
if i == j:
newlist.append(i)
else:
break
return ''.join(newlist)
####################################################################
if __name__ == "__main__":
main()
</pre>
How to capture the Tab key press event with PyQt 4.3
2008-01-03T15:26:00-08:00https://www.saltycrane.com/blog/2008/01/how-to-capture-tab-key-press-event-with/
<p>Normally, pressing the <em>TAB</em> key changes focus among widgets.
However, I would like to use the <em>TAB</em> key for other purposes
(e.g. tab completion).
To gain control of the <em>TAB</em> key press event, I need to subclass
my widget and reimplement the <code>QObject.event()</code> event handler.
I don't need to re-write the entire event handler. I only need to process
<em>TAB</em> key press events. I will pass all other events to the default
event handler. The example below subclasses the <code>QLineEdit</code>
widget and reimplements the <code>event()</code> method. Pressing the
<em>TAB</em> key inside this new widget prints out the text "tab pressed"
inside a second <code>QLineEdit</code> box.</p>
<p>The <a href="http://doc.trolltech.com/4.3/eventsandfilters.html#event-handlers">
Events and Event Filters</a> Trolltech QT documentation has a good
explanation of how this works. My example shows how to use Python and PyQt
instead of C++.</p>
<pre class="python">import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
####################################################################
def main():
app = QApplication(sys.argv)
w = MyWindow()
w.show()
sys.exit(app.exec_())
####################################################################
class MyWindow(QWidget):
def __init__(self, *args):
QWidget.__init__(self, *args)
# create objects
self.la = QLabel("Press tab in this box:")
self.le = MyLineEdit()
self.la2 = QLabel("\nLook here:")
self.le2 = QLineEdit()
# layout
layout = QVBoxLayout()
layout.addWidget(self.la)
layout.addWidget(self.le)
layout.addWidget(self.la2)
layout.addWidget(self.le2)
self.setLayout(layout)
# connections
self.connect(self.le, SIGNAL("tabPressed"),
self.update)
def update(self):
newtext = str(self.le2.text()) + "tab pressed "
self.le2.setText(newtext)
####################################################################
class MyLineEdit(QLineEdit):
def __init__(self, *args):
QLineEdit.__init__(self, *args)
def event(self, event):
if (event.type()==QEvent.KeyPress) and (event.key()==Qt.Key_Tab):
self.emit(SIGNAL("tabPressed"))
return True
return QLineEdit.event(self, event)
####################################################################
if __name__ == "__main__":
main()
</pre>
PyQt 4.3 Simple QAbstractListModel/ QlistView example
2008-01-03T12:50:00-08:00https://www.saltycrane.com/blog/2008/01/pyqt-43-simple-qabstractlistmodel/<pre class="python">import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
####################################################################
def main():
app = QApplication(sys.argv)
w = MyWindow()
w.show()
sys.exit(app.exec_())
####################################################################
class MyWindow(QWidget):
def __init__(self, *args):
QWidget.__init__(self, *args)
# create table
list_data = [1,2,3,4]
lm = MyListModel(list_data, self)
lv = QListView()
lv.setModel(lm)
# layout
layout = QVBoxLayout()
layout.addWidget(lv)
self.setLayout(layout)
####################################################################
class MyListModel(QAbstractListModel):
def __init__(self, datain, parent=None, *args):
""" datain: a list where each item is a row
"""
QAbstractListModel.__init__(self, parent, *args)
self.listdata = datain
def rowCount(self, parent=QModelIndex()):
return len(self.listdata)
def data(self, index, role):
if index.isValid() and role == Qt.DisplayRole:
return QVariant(self.listdata[index.row()])
else:
return QVariant()
####################################################################
if __name__ == "__main__":
main()
</pre>
PyQt 4.3 QTableView / QAbstractTableModel sorting example
2007-12-05T18:54:00-08:00https://www.saltycrane.com/blog/2007/12/pyqt-43-qtableview-qabstracttablemodel/
<p>It took me a while to figure out why <code>QTableView</code>'s
<code>setSortingEnabled</code> method wasn't working.
It turns out the <code>sort</code> method in <code>QAbstractItemModel</code>
is not implemented. So I had to implement it myself. Hence, my previous post,
<a href="http://www.saltycrane.com/blog/2007/12/how-to-sort-table-by-columns-in-python/">How
to sort a table by columns in Python</a>. I'm not sure if this is the best
way to implement the <code>sort</code> method, but I couldn't find anything
else out there, and this seems to work for me.</p>
<pre class="python">import re
import operator
import os
import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
def main():
app = QApplication(sys.argv)
w = MyWindow()
w.show()
sys.exit(app.exec_())
class MyWindow(QWidget):
def __init__(self, *args):
QWidget.__init__(self, *args)
# create table
self.get_table_data()
table = self.createTable()
# layout
layout = QVBoxLayout()
layout.addWidget(table)
self.setLayout(layout)
def get_table_data(self):
stdouterr = os.popen4("dir c:\\")[1].read()
lines = stdouterr.splitlines()
lines = lines[5:]
lines = lines[:-2]
self.tabledata = [re.split(r"\s+", line, 4)
for line in lines]
def createTable(self):
# create the view
tv = QTableView()
# set the table model
header = ['date', 'time', '', 'size', 'filename']
tm = MyTableModel(self.tabledata, header, self)
tv.setModel(tm)
# set the minimum size
tv.setMinimumSize(400, 300)
# hide grid
tv.setShowGrid(False)
# set the font
font = QFont("Courier New", 8)
tv.setFont(font)
# hide vertical header
vh = tv.verticalHeader()
vh.setVisible(False)
# set horizontal header properties
hh = tv.horizontalHeader()
hh.setStretchLastSection(True)
# set column width to fit contents
tv.resizeColumnsToContents()
# set row height
nrows = len(self.tabledata)
for row in xrange(nrows):
tv.setRowHeight(row, 18)
# enable sorting
tv.setSortingEnabled(True)
return tv
class MyTableModel(QAbstractTableModel):
def __init__(self, datain, headerdata, parent=None, *args):
""" datain: a list of lists
headerdata: a list of strings
"""
QAbstractTableModel.__init__(self, parent, *args)
self.arraydata = datain
self.headerdata = headerdata
def rowCount(self, parent):
return len(self.arraydata)
def columnCount(self, parent):
return len(self.arraydata[0])
def data(self, index, role):
if not index.isValid():
return QVariant()
elif role != Qt.DisplayRole:
return QVariant()
return QVariant(self.arraydata[index.row()][index.column()])
def headerData(self, col, orientation, role):
if orientation == Qt.Horizontal and role == Qt.DisplayRole:
return QVariant(self.headerdata[col])
return QVariant()
def sort(self, Ncol, order):
"""Sort table by given column number.
"""
self.emit(SIGNAL("layoutAboutToBeChanged()"))
self.arraydata = sorted(self.arraydata, key=operator.itemgetter(Ncol))
if order == Qt.DescendingOrder:
self.arraydata.reverse()
self.emit(SIGNAL("layoutChanged()"))
if __name__ == "__main__":
main()
</pre>
PyQt 4.3 QTableView / QAbstractTableModel formatting example
2007-12-04T18:06:00-08:00https://www.saltycrane.com/blog/2007/12/pyqt-43-qtableview-qabstracttable-model/
<p>This example displays the output of the "dir" command using QTableView and
QAbstractTableModel. It adds some more formatting to my
<a href="http://www.saltycrane.com/blog/2007/06/pyqt-42-qabstracttablemodelqtableview/">previous example</a>
such as specifying the font, a header, column width, row height, etc.</p>
<pre class="python">import re
import os
import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
def main():
app = QApplication(sys.argv)
w = MyWindow()
w.show()
sys.exit(app.exec_())
class MyWindow(QWidget):
def __init__(self, *args):
QWidget.__init__(self, *args)
# create table
self.get_table_data()
table = self.createTable()
# layout
layout = QVBoxLayout()
layout.addWidget(table)
self.setLayout(layout)
def get_table_data(self):
stdouterr = os.popen4("dir c:\\")[1].read()
lines = stdouterr.splitlines()
lines = lines[5:]
lines = lines[:-2]
self.tabledata = [re.split(r"\s+", line, 4)
for line in lines]
def createTable(self):
# create the view
tv = QTableView()
# set the table model
header = ['date', 'time', '', 'size', 'filename']
tm = MyTableModel(self.tabledata, header, self)
tv.setModel(tm)
# set the minimum size
self.setMinimumSize(400, 300)
# hide grid
tv.setShowGrid(False)
# set the font
font = QFont("Courier New", 8)
tv.setFont(font)
# hide vertical header
vh = tv.verticalHeader()
vh.setVisible(False)
# set horizontal header properties
hh = tv.horizontalHeader()
hh.setStretchLastSection(True)
# set column width to fit contents
tv.resizeColumnsToContents()
# set row height
nrows = len(self.tabledata)
for row in xrange(nrows):
tv.setRowHeight(row, 18)
# enable sorting
# this doesn't work
#tv.setSortingEnabled(True)
return tv
class MyTableModel(QAbstractTableModel):
def __init__(self, datain, headerdata, parent=None, *args):
QAbstractTableModel.__init__(self, parent, *args)
self.arraydata = datain
self.headerdata = headerdata
def rowCount(self, parent):
return len(self.arraydata)
def columnCount(self, parent):
return len(self.arraydata[0])
def data(self, index, role):
if not index.isValid():
return QVariant()
elif role != Qt.DisplayRole:
return QVariant()
return QVariant(self.arraydata[index.row()][index.column()])
def headerData(self, col, orientation, role):
if orientation == Qt.Horizontal and role == Qt.DisplayRole:
return QVariant(self.headerdata[col])
return QVariant()
if __name__ == "__main__":
main()</pre>
PyQt example: How to run a command and disply its stdout
2007-12-03T13:51:00-08:00https://www.saltycrane.com/blog/2007/12/pyqt-example-how-to-run-command-and/
<p>This widget consists of a <code>QLineEdit</code> class and a <code>QTextEdit</code>
class. The user enters a DOS command in the input box, hits RETURN, and the
stdout from the command is displayed in the text box.</p>
<pre class="python">import os
import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
def main():
app = QApplication(sys.argv)
w = MyWindow()
w.show()
sys.exit(app.exec_())
class MyWindow(QWidget):
def __init__(self, *args):
QWidget.__init__(self, *args)
# create objects
label = QLabel(self.tr("Enter command and press Return"))
self.le = QLineEdit()
self.te = QTextEdit()
# layout
layout = QVBoxLayout(self)
layout.addWidget(label)
layout.addWidget(self.le)
layout.addWidget(self.te)
self.setLayout(layout)
# create connection
self.connect(self.le, SIGNAL("returnPressed(void)"),
self.run_command)
def run_command(self):
cmd = str(self.le.text())
stdouterr = os.popen4(cmd)[1].read()
self.te.setText(stdouterr)
if __name__ == "__main__":
main()</pre>
How to display the stdout of a command with PyQt
2007-12-03T13:31:00-08:00https://www.saltycrane.com/blog/2007/12/how-to-display-stdout-of-command-with/
<p>This widget contains a <code>QPushButton</code> and a <code>QTextEdit</code>
box. When the button is pushed, the results of the <code>dir</code> is
displayed in the text box.</p>
<pre class="python">import os
import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
def main():
app = QApplication(sys.argv)
w = MyWindow()
w.show()
sys.exit(app.exec_())
class MyWindow(QWidget):
def __init__(self, *args):
QWidget.__init__(self, *args)
# create objects
self.pb = QPushButton(self.tr("Run command"))
self.te = QTextEdit()
# layout
layout = QVBoxLayout(self)
layout.addWidget(self.pb)
layout.addWidget(self.te)
self.setLayout(layout)
# create connection
self.connect(self.pb, SIGNAL("clicked(bool)"),
self.run_command)
def run_command(self):
stdouterr = os.popen4("dir")[1].read()
self.te.setText(stdouterr)
if __name__ == "__main__":
main()</pre>
More PyQt example code
2007-06-21T18:10:00-07:00https://www.saltycrane.com/blog/2007/06/more-pyqt-example-code/Here is some more PyQt example code.
<pre class="python">################################################################
def main():
app = QApplication(sys.argv)
mw = MainWindow()
sys.exit(app.exec_())
################################################################
class MainWindow(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
# create stuff
self.rw = ReportWidget()
self.setCentralWidget(self.rw)
self.sw = StartWindow()
self.createActions()
self.createMenus()
self.createStatusBar()
# create progress bar
self.pb = QProgressBar(self.statusBar())
self.statusBar().addPermanentWidget(self.pb)
# connections
self.connect(self.sw, SIGNAL("okClicked"),
self.rw.create)
self.connect(self.rw.table, SIGNAL("progressChanged"),
self.update_progress)
self.connect(self.rw.table, SIGNAL("displayFinished"),
self.hide_progress_bar)
# format the main window
self.setGeometry(100,100,750,550)
# show windows
self.show()
self.sw.show()
def update_progress(self, n, nrows):
self.pb.show()
self.pb.setRange(0, nrows)
self.pb.setValue(n)
self.statusBar().showMessage(self.tr("Parsing eventlog data..."))
def hide_progress_bar(self):
self.pb.hide()
self.statusBar().showMessage(self.tr("Finished"))
def about(self):
QMessageBox.about(self, self.tr("About AIS Audit Tool"),
self.tr("AIS Audit Tool\n\n"
"%s\n"
"%s\n"
"%s" % (__author__, __version__, __date__)))
def createActions(self):
self.exitAct = QAction(self.tr("E&xit;"), self)
self.exitAct.setShortcut(self.tr("Ctrl+Q"))
self.exitAct.setStatusTip(self.tr("Exit the application"))
self.connect(self.exitAct, SIGNAL("triggered()"), self, SLOT("close()"))
self.aboutAct = QAction(self.tr("&About;"), self)
self.aboutAct.setStatusTip(self.tr("Show the application's About box"))
self.connect(self.aboutAct, SIGNAL("triggered()"), self.about)
self.aboutQtAct = QAction(self.tr("About &Qt;"), self)
self.aboutQtAct.setStatusTip(self.tr("Show the Qt library's About box"))
self.connect(self.aboutQtAct, SIGNAL("triggered()"), qApp, SLOT("aboutQt()"))
def createMenus(self):
self.fileMenu = self.menuBar().addMenu(self.tr("&File;"))
self.fileMenu.addAction(self.exitAct)
self.helpMenu = self.menuBar().addMenu(self.tr("&Help;"))
self.helpMenu.addAction(self.aboutAct)
self.helpMenu.addAction(self.aboutQtAct)
def createStatusBar(self):
sb = QStatusBar()
sb.setFixedHeight(18)
self.setStatusBar(sb)
self.statusBar().showMessage(self.tr("Ready"))
################################################################
class StartWindow(QWidget):
def __init__(self, *args):
QWidget.__init__(self, *args)
# date box
self.label_date = QLabel()
self.label_date.setText("Set date of last audit:")
default = datetime.date.today() - datetime.timedelta(DEFAULT_DAYS_FROM_LAST_AUDIT)
self.datebox = QDateEdit(QDate(default.year, default.month, default.day))
# buttons
spacer = QSpacerItem(20,40,QSizePolicy.Minimum,QSizePolicy.Expanding)
self.button_ok = QPushButton()
self.button_ok.setText("OK")
self.button_ok.setDefault(True)
button_cancel = QPushButton()
button_cancel.setText("Cancel")
# layout
layout_right = QVBoxLayout(self)
layout_right.addWidget(self.label_date)
layout_right.addWidget(self.datebox)
layout_right.addItem(spacer)
layout_right.addWidget(self.button_ok)
layout_right.addWidget(button_cancel)
# connections
self.connect(button_cancel, SIGNAL("clicked(bool)"),
self.close)
self.connect(self.button_ok, SIGNAL("clicked(bool)"),
self.ok_clicked)
def ok_clicked(self):
self.close()
year = self.datebox.date().year()
month = self.datebox.date().month()
day = self.datebox.date().day()
dateobj = datetime.date(int(year),int(month),int(day))
self.emit(SIGNAL("okClicked"), dateobj)
################################################################
class ReportWidget(QWidget):
def __init__(self, *args):
QWidget.__init__(self, *args)
self.cbUsers = QCheckBox("Hide SYSTEM users")
self.cbSorting = QCheckBox("Sorting enabled")
self.table = MyTable()
self.textbrowser = QTextBrowser()
self.textbrowser.setFontFamily("Courier")
self.textbrowser.setFontPointSize(10)
hlayout = QHBoxLayout()
hlayout.addWidget(self.cbUsers)
hlayout.addWidget(self.cbSorting)
vlayout = QVBoxLayout()
vlayout.setMargin(2)
vlayout.addLayout(hlayout)
vlayout.addWidget(self.table)
self.setLayout(vlayout)
self.setGeometry(100,100,750,550)
# connections
self.connect(self.cbUsers, SIGNAL("stateChanged(int)"),
self.cbUsersChanged)
self.connect(self.cbSorting, SIGNAL("stateChanged(int)"),
self.cbSortingChanged)
def create(self, dateobj):
""" Parses the eventlog data, displays it in a table, and
displays the user login/logout also """
self.table.display_data(dateobj)
def cbUsersChanged(self):
state = self.cbUsers.checkState()
if state == 0:
self.table.show_system_users()
elif state == 2:
self.table.hide_system_users()
def cbSortingChanged(self):
state = self.cbSorting.checkState()
if state == 0:
self.table.setSortingEnabled(False)
elif state == 2:
self.table.setSortingEnabled(True)
################################################################
class MyTable(QTableWidget):
""" Creates a custom table widget """
def __init__(self, *args):
QTableWidget.__init__(self, *args)
self.setSelectionMode(self.ContiguousSelection)
self.setGeometry(0,0,700,400)
self.setShowGrid(False)
self.other_users_list = []
def hide_system_users(self):
for n in self.other_users_list:
self.setRowHidden(n, True)
def show_system_users(self):
for n in self.other_users_list:
self.setRowHidden(n, False)
def display_data(self, dateobj):
""" Reads in data as a 2D list and formats and displays it in
the table """
print "Fetching data..."
ep = EventlogParser()
data = ep.parse_log(dateobj)
print "Done."
if len(data)==0:
data = ["No data for this date range."]
nrows = len(data)
ncols = len(data[0])
self.setRowCount(nrows)
self.setColumnCount(ncols)
self.setHorizontalHeaderLabels(['No.', 'Date','Time','Type','Event','User','Computer'])
for i in xrange(len(data)):
# update progress dialog
if (i%20) == 0:
self.emit(SIGNAL("progressChanged"), i, nrows)
qApp.processEvents()
# set each cell to be a QTableWidgetItem from the _process_row method
items = self._process_row(data[i])
for j in range(len(items)):
self.setItem(i, j, items[j])
self.setRowHeight(i, 16)
# set column width first time through
if i == 0:
self.resizeColumnsToContents()
self.setColumnWidth(4, 250)
# format column width
self.resizeColumnsToContents()
self.setColumnWidth(4, 250)
# emit signal for finished processing
self.emit(SIGNAL("displayFinished"))
def _process_row(self, row):
""" Formats items in the row of the 2-D list data
Input: the row of data from the EventlogParser in a list
Returns a list of QTableWidgetItems to be one row in the table
"""
icon = []
for i in xrange(len(row)):
# general formatting for all cells (may be overwritten)
icon.append(QIcon())
computer = row[6]
# time processing
if i == 2:
try:
hour = int(re.split(r":", row[i])[0])
except:
raise
if hour <= EARLY_HOUR or hour >= LATE_HOUR:
backcolor_time = QColor(0,0,102)
else:
backcolor_time = QColor("white")
# success or failure processing
elif i == 3:
if row[i] == "8":
row[i] = "Success"
icon[i] = QIcon("success.png")
elif row[i] == "16":
row[i] = "Failure"
icon[i] = QIcon("failure.png")
else:
row[i] = "Unknown"
icon[i] = QIcon("unknown.png")
# event processing
elif i == 4:
backcolor = QColor("white")
if row[i] in RED_EVENTIDS:
backcolor = QColor("red")
elif row[i] in ORANGE_EVENTIDS:
backcolor = QColor("orange")
elif row[i] in YELLOW_EVENTIDS:
backcolor = QColor("yellow")
elif row[i] in GREEN_EVENTIDS:
pass
elif row[i] in OTHER_EVENTIDS:
backcolor = QColor("blue")
try:
row[i] = row[i] + ": " + EVENT_DESC[row[i]]
except:
pass
# user processing
elif i == 5:
if row[i] in (computer, "", "SYSTEM", "NETWORK SERVICE", "LOCAL SERVICE", "ANONYMOUS LOGON"):
font = QFont("Arial", 8)
font.setBold(False)
textcolor = QColor("gray")
user = 'other'
else:
font = QFont("Arial", 8)
font.setBold(True)
textcolor = QColor("black")
user = 'user'
# create table widget item
tableitem_list = []
for i in xrange(len(row)):
tableitem = QTableWidgetItem(row[i])
if i == 2:
tableitem.setBackgroundColor(backcolor_time)
else:
tableitem.setBackgroundColor(backcolor)
tableitem.setTextColor(textcolor)
tableitem.setFont(font)
tableitem.setTextAlignment(Qt.AlignTop)
tableitem.setToolTip(row[i])
tableitem.setIcon(icon[i])
tableitem_list.append(tableitem)
return tableitem_list
################################################################
if __name__ == "__main__":
main()
</pre>
How to get code completion for PyQt using Pydev
2007-06-14T12:50:00-07:00https://www.saltycrane.com/blog/2007/06/how-to-get-code-completion-for-pyqt/
<div><font face="Arial" color="#000080" size="2"><span class="574274119-14062007">Because PyQt doesn't come with the .py source files which Pydev needs for code completion, you need to add the PyQt modules as a "forced builtin lib". See the following FAQs at the pydev website: <a href="http://pydev.sourceforge.net/faq.html#ref_22">http://pydev.sourceforge.net/faq.html#ref_22</a> and <a href="http://pydev.sourceforge.net/faq.html#ref_15">http://pydev.sourceforge.net/faq.html#ref_15</a></span></font></div> <div><font face="Arial" color="#000080" size="2"><span class="574274119-14062007"></span></font> </div> <div><font face="Arial" color="#000080" size="2"><span class="574274119-14062007">Here are the steps:</span></font></div> <ol> <li><font face="Arial" color="#000080" size="2"><span class="574274119-14062007">Go to "Window" -> "Preferences..." -> "Pydev" -> "Interpreter - Python"</span></font></li> <li><font face="Arial" color="#000080" size="2"><span class="574274119-14062007">In the "Forced builtin libs" section, click "New..."</span></font></li> <li><font face="Arial" color="#000080" size="2"><span class="574274119-14062007">Type in "PyQt4" and click "OK".</span></font></li> <li><font face="Arial" color="#000080" size="2"><span class="574274119-14062007">Click "OK" to close the Preferences window.</span></font></li></ol> <div><font face="Arial" color="#000080" size="2"><span class="574274119-14062007">Note: If you installed PyQt after installing Pydev, you will probably have to update the PYTHONPATH with the path to the PyQt libraries. You can do this easily by "Remove"ing the python interpreter and then re-adding it in again. (For reference, I am using Eclipse 3.2.2, Pydev 1.3.4, Python 2.5.1, and PyQt 4.2.3)</span></font></div>
More example code for PyQt 4.2
2007-06-12T17:40:00-07:00https://www.saltycrane.com/blog/2007/06/more-example-code-for-pyqt-42/<p>Here is some more example code for PyQt 4.2.</p>
<pre class="python">################################################################
################################################################
def main():
app = QApplication(sys.argv)
app.setQuitOnLastWindowClosed(True)
form = StartForm()
form.show()
report = ReportWindow()
app.connect(form, SIGNAL("okClicked"),
report.create)
sys.exit(app.exec_())
################################################################
################################################################
class StartForm(QWidget):
def __init__(self, *args):
QWidget.__init__(self, *args)
# position the form on the screen
self.move(1500, 50)
# date box
self.label_date = QLabel()
self.label_date.setText("Set date of last audit:")
default = datetime.date.today() - datetime.timedelta(DEFAULT_DAYS_FROM_LAST_AUDIT)
self.datebox = QDateEdit(QDate(default.year, default.month, default.day))
# buttons
spacer = QSpacerItem(20,40,QSizePolicy.Minimum,QSizePolicy.Expanding)
self.button_ok = QPushButton()
self.button_ok.setText("OK")
self.button_ok.setDefault(True)
button_cancel = QPushButton()
button_cancel.setText("Cancel")
# layout
layout_right = QVBoxLayout(self)
layout_right.addWidget(self.label_date)
layout_right.addWidget(self.datebox)
layout_right.addItem(spacer)
layout_right.addWidget(self.button_ok)
layout_right.addWidget(button_cancel)
# connections
self.connect(button_cancel, SIGNAL("clicked(bool)"),
self.close)
self.connect(self.button_ok, SIGNAL("clicked(bool)"),
self.ok_clicked)
def ok_clicked(self):
self.label_date.setText("Getting eventlog data...")
year = self.datebox.date().year()
month = self.datebox.date().month()
day = self.datebox.date().day()
delta = datetime.date.today() - datetime.date(int(year),int(month),int(day))
self.emit(SIGNAL("okClicked"), delta.days)
self.close()
################################################################
################################################################
class ReportWindow(QWidget):
def __init__(self, *args):
QWidget.__init__(self, *args)
self.cbUsers = QCheckBox("Hide SYSTEM users")
self.cbSorting = QCheckBox("Sorting enabled")
self.tableview = EventlogTableView()
vlayout = QVBoxLayout()
vlayout.addWidget(self.cbUsers)
vlayout.addWidget(self.cbSorting)
vlayout.addWidget(self.tableview)
self.setLayout(vlayout)
self.setGeometry(100,100,750,550)
# connections
self.connect(self.cbUsers, SIGNAL("stateChanged(int)"),
self.cbUsersChanged)
self.connect(self.cbSorting, SIGNAL("stateChanged(int)"),
self.cbSortingChanged)
def create(self, ndays):
""" Run dumpel.exe, parse and show the results in a table """
ep = EventlogParser()
logdata = ep.parseLog(ndays)
model = EventlogTableModel(logdata, self)
self.tableview.setModel(model)
self.tableview.formatData()
self.show()
def cbUsersChanged(self):
state = self.cbUsers.checkState()
print "state= " + str(state)
if state == 0:
self.table.show_system_users()
elif state == 2:
self.table.hide_system_users()
def cbSortingChanged(self):
state = self.cbSorting.checkState()
if state == 0:
self.table.setSortingEnabled(False)
elif state == 2:
self.table.setSortingEnabled(True)
################################################################
################################################################
class EventlogTableView(QTableView):
def __init__(self, *args):
QTableView.__init__(self, *args)
def formatData(self):
""" Formats the data in the table view """
self.resizeColumnsToContents()
# format items
model = self.model()
self.nrows = model.rowCount(self)
self.ncols = model.columnCount(self)
for i in xrange(self.nrows):
for j in xrange(self.ncols):
index = model.index(i, j)
################################################################
################################################################
class EventlogTableModel(QAbstractTableModel):
def __init__(self, datain, parent=None):
QAbstractTableModel.__init__(self, parent)
self.logdata = datain
def rowCount(self, parent):
return len(self.logdata)
def columnCount(self, parent):
return len(self.logdata[0])
def data(self, index, role):
if not index.isValid():
return QVariant()
elif role != Qt.DisplayRole:
return QVariant()
return QVariant(self.logdata[index.row()][index.column()])
################################################################
################################################################
class EventlogParser:
def __init__(self):
pass
def parseLog(self, ndays):
""" Runs dumpel.exe and stores the results in a data structure
Example dumpel output:
3/14/2006 1:00:51 PM 8 1 515 Security NT AUTHORITY\SYSTEM ANC9PLT561 Win
Returns a 2-dimensional list
"""
os.system("dumpel -f dumpel_results.txt -l security -d %s" % ndays)
fin = open("dumpel_results.txt", "r")
data = []
for line in fin.readlines():
items = re.split(r'\t+', line, maxsplit=8)
# date processing
items[0] = format_datetime(items[0], items[1])
# success/failure processing
if items[2] == "8":
items[2] = "Success"
elif items[2] == "16":
items[2] = "Failure"
else:
items[2] = "Unknown"
# event processing
event = items[4]
try:
desc = event_desc[event]
except:
desc = 'need to look up this event id'
items[4] = event + ": " + desc
# user processing
(dom, user) = re.split(r"\\", items[6])
items[6] = user
# delete unused columns
items[7:8] = []
items[5:6] = []
items[3:4] = []
data.append(items)
print "Parse sucessful.\n"
return data </pre>
PyQt 4.2 QAbstractTableModel/QTableView Example
2007-06-11T09:39:00-07:00https://www.saltycrane.com/blog/2007/06/pyqt-42-qabstracttablemodelqtableview/<pre class="python">from PyQt4.QtCore import *
from PyQt4.QtGui import *
import sys
my_array = [['00','01','02'],
['10','11','12'],
['20','21','22']]
def main():
app = QApplication(sys.argv)
w = MyWindow()
w.show()
sys.exit(app.exec_())
class MyWindow(QWidget):
def __init__(self, *args):
QWidget.__init__(self, *args)
tablemodel = MyTableModel(my_array, self)
tableview = QTableView()
tableview.setModel(tablemodel)
layout = QVBoxLayout(self)
layout.addWidget(tableview)
self.setLayout(layout)
class MyTableModel(QAbstractTableModel):
def __init__(self, datain, parent=None, *args):
QAbstractTableModel.__init__(self, parent, *args)
self.arraydata = datain
def rowCount(self, parent):
return len(self.arraydata)
def columnCount(self, parent):
return len(self.arraydata[0])
def data(self, index, role):
if not index.isValid():
return QVariant()
elif role != Qt.DisplayRole:
return QVariant()
return QVariant(self.arraydata[index.row()][index.column()])
if __name__ == "__main__":
main()</pre>
PyQt4 Examples
2007-01-25T17:54:00-08:00https://www.saltycrane.com/blog/2007/01/python-gui-tutorials-for-pyqt-41-qt-42/<p>PyQt is the best GUI toolkit for Python. Here are some examples and notes I am in the process of collecting.</p>
<p>There is a good collection of tutorials and examples included with the PyQt 4 installation.
On Windows, go to "Start" -> "All Programs" -> "PyQt GPL v4.x.x" -> "Examples Source" for many tutorials and examples ported from C++/QT to Python/PyQt.</p>
<p><em>Update 2008-09-28</em>: For Ubuntu Linux, the examples are part of the
<code>python-qt4-doc</code> package. Execute <code>sudo apt-get install python-qt4-doc</code> then navigate to <code>/usr/share/doc/python-qt4-doc/examples</code>.
</p>
<ul>
<li><a href="http://www.saltycrane.com/blog/2007/01/how-to-install-pyqt-41-python-25-and-qt_8340/">
How to install PyQt4 on Windows</a></li>
<li><a href="http://www.saltycrane.com/blog/2008/01/how-to-install-pyqt4-on-ubuntu-linux/">
How to install PyQt4 on Ubuntu</a></li>
<li><a href="http://www.saltycrane.com/blog/2007/06/pyqt-42-qabstracttablemodelqtableview/">
PyQt4 QAbstractTableModel / QTableView simple example</a></li>
<li><a href="http://www.saltycrane.com/blog/2007/12/how-to-display-stdout-of-command-with/">
How to display the stdout of a command with PyQt4</a></li>
<li><a href="http://www.saltycrane.com/blog/2007/12/pyqt-example-how-to-run-command-and/">
How to run a command and display its stdout with PyQt4</a></li>
<li><a href="http://www.saltycrane.com/blog/2007/12/pyqt-43-qtableview-qabstracttable-model/">
PyQt4 QAbstractTableModel / QTableView example with formatting</a></li>
<li><a href="http://www.saltycrane.com/blog/2007/12/pyqt-43-qtableview-qabstracttablemodel/">
PyQt4 QAbstractTableModel / QTableView example with sorting</a></li>
<li><a href="http://www.saltycrane.com/blog/2008/01/pyqt-43-simple-qabstractlistmodel/">
PyQt4 QAbstractListModel / QListView simple example</a></li>
<li><a href="http://www.saltycrane.com/blog/2008/01/how-to-capture-tab-key-press-event-with/">
How to capture the Tab press key event in PyQt4</a></li>
<li><a href="http://www.saltycrane.com/blog/2008/01/python-pyqt-tab-completion-example/">
PyQt4 Tab Completion Example</a></li>
</ul>
How to install PyQt 4.3 and Python 2.5 on Windows
2007-01-25T10:35:00-08:00https://www.saltycrane.com/blog/2007/01/how-to-install-pyqt-41-python-25-and-qt_8340/
<p>Update 1/10/2008: PyQt has made the install process a lot simpler because
it has bundled everything you need in one installer including QT 4.3 open
source edition. Now all you need to do is install Python and the PyQt bundle.
Immediately following are the updated steps. Below that is the old instructions.
</p>
<p>Update 7/1/2008: Updated for PyQt 4.4.2</p>
<br /><h4>NEW INSTRUCTIONS</h4>
<p>Here are the steps to install and create a simple "Hello World" GUI
application using PyQt 4.4, and Python 2.5, on Windows.</p>
<br />Install Python 2.5<br />
<ol>
<li>Go to <a href="http://www.python.org/download/">http://www.python.org/download/</a>
and click on "Python 2.5.x Windows installer"</li>
<li>Save and run the Windows installer</li>
<li>Go through the steps and accept the defaults.</li>
</ol>
<br />Install the PyQt 4.4 bundle (including QT 4.4)<br />
<ol>
<li>Go to <a href="http://www.riverbankcomputing.co.uk/software/pyqt/download">
http://www.riverbankcomputing.co.uk/software/pyqt/download</a>
and select the "PyQt-Py2.5-gpl-4.4.2-1.exe" link.
</li>
<li>Save and run the file.</li>
<li>Go through the steps and accept the defaults.</li>
</ol>
<br />Run a "Hello World" application<br />
<ol>
<li>Go to "Start" -> "All Programs" -> "Python 2.5" -> "IDLE (Python GUI)"</li>
<li>Open a new window ("File" -> "New window")</li>
<li>Type the following code inside and save:
<pre>import sys
from PyQt4.QtGui import *
app = QApplication(sys.argv)
button = QPushButton("Hello World", None)
button.show()
app.exec_()</pre>
</li>
<li>Hit "F5" to run. A window with a single push button should pop up.</li>
</ol>
<p>For more examples, go to "Start" -> "All Programs" -> "PyQt GPL v4.4.2 for Python v2.5"
> "Examples" > "PyQt Examples Source" (For a default installation, this is also
located at <code>C:\Python25\PyQt4\examples</code>.) To start, look in the "tutorial"
directory.
</p>
<br /><h4>OLD INSTRUCTIONS</h4>
Here are the steps to install and create a simple "Hello World" GUI application using PyQt 4.1.1, Python 2.5, and QT 4.2.2 Open Source edition (GPL) on Windows XP with the MinGW compiler.<br /><br />Install Python 2.5<br /> <ol> <li>Go to <a href="http://www.python.org/download/">http://www.python.org/download/</a> and click on "Python 2.5 Windows installer"</li> <li>Save and run the Windows installer</li> <li>Go through the steps and accept the defaults.</li></ol><br />Install MinGW<br /> <ol> <li>Go to <a href="http://www.mingw.org/download.shtml">http://www.mingw.org/download.shtml</a></li> <li>Download the following "bin" files from the "Current" section: <ul> <li>gcc-core-3.4.2-20040916-1.tar.gz</li> <li>gcc-g++-3.4.2-20040916-1.tar.gz</li> <li>mingw-runtime-3.9.tar.gz</li> <li>w32api-3.6.tar.gz</li></ul></li> <li>Extract all the files to "c:\mingw"</li></ol><br />Install QT 4.2.2 Open Source edition<br /> <ol> <li>Go to the Open Source download page at <a href="http://www.trolltech.com/developer/downloads/qt/windows">http://www.trolltech.com/developer/downloads/qt/windows</a>. Note there is also an Evaluation version. This is *not* the one you want.</li> <li>Under the "Download" heading, select the "http://ftp.iasi.roedu.net/mirrors/ftp.trolltech.com/qt/source/qt-win-opensource-4.2.2-mingw.exe" link.</li> <li>Go through the steps and accept the defaults.</li> <li>When you get to the MinGW page, leave the "Download and install minimal MinGW installation" box unchecked and make sure the location of the MinGW installation is set to "c:\mingw". Click "Install".</li> <li>You will get an error message which says that the installer could not find a valid "w32api.h" file. You can install the 3.2 version from the mingw site, but the 3.6 version works. Click "Yes" to continue. Click "Finish" to finish the installation.</li></ol><br />Install PyQt 4.1.1<br /> <ol> <li>Go to <a href="http://www.riverbankcomputing.co.uk/pyqt/download.php">http://www.riverbankcomputing.co.uk/pyqt/download.php</a> and select the "PyQt-gpl-4.1.1-Py2.5-Qt4.2.2.exe" link.</li> <li>Save and run the file.</li> <li>Go through the steps and accept the defaults.</li></ol><br />Check your Environment Variables<br /> <ol> <li>Right-click on "My Computer" and select "Properties"</li> <li>Click the "Advanced" tab</li> <li>Click "Environment Variables"</li> <li>The following variables should be set: <ul> <li>user variable QTDIR - "c:\qt\4.2.2"</li> <li>user variable QMAKESPEC - "win32-g++"</li> <li>system variable PATH - include "C:\Qt\4.2.2\bin;C:\Python25\Scripts;C:\Python25;C:\Python25\DLLs;"</li></ul></li></ol><br />Run a "Hello World" application<br /> <ol> <li>Go to "Start" -> "All Programs" -> "Python 2.5" -> "IDLE (Python GUI)"</li> <li>Open a new window ("File" -> "New window")</li> <li>Type the following code inside and save: <pre>import sys<br />from PyQt4.QtGui import *<br />app = QApplication(sys.argv)<br />button = QPushButton("Hello World", None)<br />button.show()<br />app.exec_()</pre></li> <li>Hit "F5" to run.</li></ol><span style="font-family:arial; font-size:50%; color:black;">Technorati tags: <a href="http://technorati.com/tag/python" rel="tag">python</a>, <a href="http://technorati.com/tag/pyqt" rel="tag">pyqt</a></span>
Larger python qt pyqt example
2006-12-18T12:04:00-08:00https://www.saltycrane.com/blog/2006/12/larger-python-qt-pyqt-example/
This script is used to parse Windows Event Viewer logs. It uses
dumpel.exe. It colors significant events and presents results in a QT
GUI.
<pre>
"""windows_audit.py
"""
__author__ = "So Feng"
__version__ = "$Revision: 1.0 $"
__date__ = "$Date: 2006/10/17 $"
__license__ = "Python"
import re
import datetime
from datetime import date
import time
import glob
import os
import sys
from Qt import *
import StringIO
# constants
NCHARS_TO_WRAP = 30
EARLY_HOUR = 6
LATE_HOUR = 20
outfile = "audit_" + str(datetime.date.today()) + ".txt"
red_eventids = ["560","565","592","678"] orange_eventids = ["539","629","644","531","544","545","675","676"]
yellow_eventids = ["529","530","532","533","534","535","536","537","681",
"576","608","609","610","611","624","625","626","627",
"628","630","631","632","633","634","635","636","637",
"638","639","640","641","642","643","645","646","647",
"648","649","650","651","652","653","654","655","656",
"657","658","659","660","661","662","663","664","665",
"666","667","668","669","670","672"]
green_eventids = ["528", "538", "540", "680"] other_eventids = ["612", "617", "618", "619"] failure_list = ('529', '530', '531', '532', '533', '534', '535', '536', '537', '539', '544', '545', '546', '547', '616', '675', '676', '677', '679', '681', ) success_list = ('512', '513', '514', '515', '516', '517', '518', '528', '538', '540', '541', '542', '543', '560', '561', '562', '563', '564', '565', '566', '576', '577', '578', '592', '593', '594', '595', '608', '609', '610', '611', '612', '613', '614', '615', '617', '618', '619', '620', '624', '625', '626', '627', '628', '630', '631', '632', '633', '634', '635', '636', '637', '638', '639', '640', '641', '642', '643', '644', '645', '646', '647', '648', '649', '650', '651', '652', '653', '654', '655', '656', '657', '658', '659', '660', '661', '662', '663', '664', '665', '666', '667', '668', '669', '670', '672', '673', '674', '678', '680', '682', '683', ) event_desc = {
'512': 'Windows NT is starting up. ',
'513': 'Windows NT is shutting down.\n All logon sessions will be terminated by this shutdown. ',
'514': 'An authentication package has been loaded by the Local Security Authority.\n This authentication package will be used to authenticate logon attempts. ',
'515': 'A trusted logon process has registered with the Local Security Authority.\n This logon process will be trusted to submit logon requests. ',
'516': 'Internal resources allocated for the queuing of audit messages have been\n exhausted, leading to the loss of some audits. ',
'517': 'The audit log was cleared ',
'518': 'An notification package has been loaded by the Security Account Manager.\n This package will be notified of any account or password changes. ',
'528': 'Successful Logon: ',
'529': 'Logon Failure Unknown user name or bad password',
'530': 'Logon Failure Account logon time restriction violation',
'531': 'Logon Failure Account currently disabled',
'532': 'Logon Failure The specified user account has expired',
'533': 'Logon Failure User not allowed to logon at this computer',
'534': 'Logon Failure The user has not been granted the requested \n logon type at this machine',
'535': 'Logon Failure The specified account\'s password has expired',
'536': 'Logon Failure The NetLogon component is not active',
'537': 'Logon Failure An unexpected error occurred during logon',
'538': 'User Logoff ',
<span id="fullpost">
'539': 'Logon Failure Account locked out',
'540': 'Successful Network Logon ',
'541': 'IKE security association established. ',
'542': 'IKE security association ended. ',
'543': 'IKE security association ended. ',
'544': 'IKE security association establishment failed because peer could not\n authenticate. The certificate trust could not be established. ',
'545': 'IKE peer authentication failed. ',
'546': 'IKE security association establishment failed because peer\n sent invalid proposal. ',
'547': 'IKE security association negotiation failed. ',
'560': 'Object Open ',
'561': 'Handle Allocated ',
'562': 'Handle Closed ',
'563': 'Object Open for Delete ',
'564': 'Object Deleted ',
'565': 'Object Open ',
'566': 'Object Operation ',
'576': 'Special privileges assigned to new logon: ',
'577': 'Privileged Service Called ',
'578': 'Privileged object operation ',
'592': 'A new process has been created ',
'593': 'A process has exited ',
'594': 'A handle to an object has been duplicated ',
'595': 'Indirect access to an object has been obtained ',
'608': 'User Right Assigned ',
'609': 'User Right Removed ',
'610': 'New Trusted Domain ',
'611': 'Removing Trusted Domain ',
'612': 'Audit Policy Change ',
'613': 'IPSec policy agent started ',
'614': 'IPSec policy agent disabled ',
'615': 'IPSEC PolicyAgent Service: %1 ',
'616': 'IPSec policy agent encountered a potentially serious failure. ',
'617': 'Kerberos Policy Changed ',
'618': 'Encrypted Data Recovery Policy Changed ',
'619': 'Quality of Service Policy Changed ',
'620': 'Trusted Domain Information Modified: ',
'624': 'User Account Created ',
'625': 'User Account Type Change ',
'626': 'User Account Enabled ',
'627': 'Change Password Attempt ',
'628': 'User Account password set ',
'630': 'User Account Deleted: ',
'631': 'Security Enabled Global Group Created ',
'632': 'Security Enabled Global Group Member Added ',
'633': 'Security Enabled Global Group Member Removed ',
'634': 'Security Enabled Global Group Deleted ',
'635': 'Security Enabled Local Group Created ',
'636': 'Security Enabled Local Group Member Added ',
'637': 'Security Enabled Local Group Member Removed ',
'638': 'Security Enabled Local Group Deleted ',
'639': 'Security Enabled Local Group Changed ',
'640': 'General Account Database Change ',
'641': 'Security Enabled Global Group Changed ',
'642': 'User Account Changed ',
'643': 'Domain Policy Changed: %1 modified ',
'644': 'User Account Locked Out ',
'645': 'Computer Account Created ',
'646': 'Computer Account Changed ',
'647': 'Computer Account Deleted ',
'648': 'Security Disabled Local Group Created ',
'649': 'Security Disabled Local Group Changed ',
'650': 'Security Disabled Local Group Member Added ',
'651': 'Security Disabled Local Group Member Removed ',
'652': 'Security Disabled Local Group Deleted ',
'653': 'Security Disabled Global Group Created ',
'654': 'Security Disabled Global Group Changed ',
'655': 'Security Disabled Global Group Member Added ',
'656': 'Security Disabled Global Group Member Removed ',
'657': 'Security Disabled Global Group Deleted ',
'658': 'Security Enabled Universal Group Created ',
'659': 'Security Enabled Universal Group Changed ',
'660': 'Security Enabled Universal Group Member Added ',
'661': 'Security Enabled Universal Group Member Removed ',
'662': 'Security Enabled Universal Group Deleted ',
'663': 'Security Disabled Universal Group Created ',
'664': 'Security Disabled Universal Group Changed ',
'665': 'Security Disabled Universal Group Member Added ',
'666': 'Security Disabled Universal Group Member Removed ',
'667': 'Security Disabled Universal Group Deleted ',
'668': 'Group Type Changed ',
'669': 'Add SID History ',
'670': 'Add SID History ',
'672': 'Authentication Ticket Granted ',
'673': 'Service Ticket Granted ',
'674': 'Ticket Granted Renewed ',
'675': 'Pre-authentication failed ',
'676': 'Authentication Ticket Request Failed ',
'677': 'Authentication Ticket Request Failed ',
'678': 'Account Mapped for Logon by: %1 ',
'679': 'The name: %2 could not be mapped for logon by: %1 ',
'680': 'Account Used for Logon by: %1 ',
'681': 'The logon to account: %2 by: %1 from workstation: %3 failed. The error code was: %4 ',
'682': 'Session reconnected to winstation: ',
'683': 'Session disconnected from winstation: ',
}
#sys.stderr = StringIO.StringIO()
#sys.stdout = StringIO.StringIO()
################################################################
################################################################
def main():
app = QApplication(sys.argv)
app.setQuitOnLastWindowClosed(True)
form = StartForm()
form.show()
report = ReportWindow()
app.connect(form, SIGNAL("okClicked"),
report.create)
sys.exit(app.exec_())
################################################################
################################################################
class StartForm(QWidget):
def __init__(self, *args):
QWidget.__init__(self, *args)
# # directory tree
# label_file = QLabel()
# label_file.setText("Select file:")
# dirmodel = QDirModel()
# treeview = QTreeView(self)
# treeview.setModel(dirmodel)
# treeview.setRootIndex(dirmodel.index(QDir.currentPath()))
# treeview.hideColumn(1)
# treeview.hideColumn(2)
# treeview.hideColumn(3)
# treeview.header().hide()
# date box
self.label_date = QLabel()
self.label_date.setText("Set date of last audit:")
default = datetime.date.today() - datetime.timedelta(10)
self.datebox = QDateEdit(QDate(default.year, default.month, default.day))
# buttons
spacer = QSpacerItem(20,40,QSizePolicy.Minimum,QSizePolicy.Expanding)
self.button_ok = QPushButton()
self.button_ok.setText("OK")
self.button_ok.setDefault(True)
button_cancel = QPushButton()
button_cancel.setText("Cancel")
# layout
# layout_left = QVBoxLayout()
# layout_left.addWidget(label_file)
# layout_left.addWidget(treeview)
layout_right = QVBoxLayout(self)
layout_right.addWidget(self.label_date)
layout_right.addWidget(self.datebox)
layout_right.addItem(spacer)
layout_right.addWidget(self.button_ok)
layout_right.addWidget(button_cancel)
# layout = QHBoxLayout(self)
# layout.addLayout(layout_left)
# layout.addLayout(layout_right)
# connections
self.connect(button_cancel, SIGNAL("clicked()"),
self.close)
self.connect(self.button_ok, SIGNAL("clicked()"),
self.ok_clicked)
def ok_clicked(self):
self.label_date.setText("Getting eventlog data...")
year = self.datebox.date().year()
month = self.datebox.date().month()
day = self.datebox.date().day()
delta = datetime.date.today() - datetime.date(int(year),int(month),int(day))
self.emit(SIGNAL("okClicked"), delta.days)
self.close()
################################################################
################################################################
class ReportWindow(QMainWindow):
def __init__(self, *args):
QMainWindow.__init__(self, *args)
# self.cb = QCheckBox()
self.table = MyTable()
self.textbrowser = QTextBrowser()
self.textbrowser.setFontFamily("Courier")
self.textbrowser.setFontPointSize(10)
splitter = QSplitter(Qt.Vertical, self)
# splitter = QSplitter(Qt.Vertical)
splitter.addWidget(self.table)
splitter.addWidget(self.textbrowser)
# vlayout = QVBoxLayout(self)
# vlayout.addWidget(self.cb)
# vlayout.addWidget(splitter)
self.setGeometry(100,100,750,550)
self.setCentralWidget(splitter)
def create(self, date):
self.table.parse_event_log(date)
self.table.setdata()
fh = open(outfile, "r")
text = fh.read()
self.textbrowser.setPlainText(text)
self.show()
################################################################
################################################################
class MyTable(QTableWidget):
def __init__(self, *args):
QTableWidget.__init__(self, *args)
self.setSortingEnabled(True)
self.setSelectionMode(self.ContiguousSelection)
#self.setFixedWidth(750)
self.setGeometry(0,0,700,400)
self.data = []
def setdata(self):
if len(self.data) == 0:
self.setRowCount(1)
self.setColumnCount(1)
newitem = QTableWidgetItem("No data for this date range.")
self.setItem(0, 0, newitem)
self.resizeColumnsToContents()
else:
self.nrows = len(self.data)
self.ncols = len(self.data[0])
self.setRowCount(self.nrows)
self.setColumnCount(self.ncols)
self.setmydata_list()
self.resizeColumnsToContents()
self.setGridStyle(Qt.DotLine)
self.setShowGrid(False)
self.setColumnWidth(3, 250)
#self.resizeRowsToContents()
#self.setHorizontalHeaderLabels(['date','time','?','?','event','source','user','?','computer','data'])
self.setHorizontalHeaderLabels(['Date','Time','Type','Event','User','Computer','Data'])
def setmydata_list(self):
n = 0
date_prev = ''
for row in self.data:
# event processing
event = row[4]
try:
row[4] = event + ": " + event_desc[event]
except:
pass
color = QColor("white")
if event in red_eventids:
color = QColor("red")
elif event in orange_eventids:
color = QColor("orange")
elif event in yellow_eventids:
color = QColor("yellow")
elif event in green_eventids:
#color = QColor("green")
pass
elif event in other_eventids:
color = QColor("blue")
# success or failure processing
if row[2] == "8":
row[2] = "Success"
icon = QIcon("success.png")
elif row[2] == "16":
row[2] = "Failure"
icon = QIcon("failure.png")
else:
row[2] = "Unknown"
icon = QIcon("unknown.png")
# date processing
row[0] = format_datetime(row[0], row[1])
(date, thetime) = re.split(r"\n", row[0])
newday = False
if date != date_prev:
newday = True
date_prev = date
thetime = re.split(r":", thetime)
hour = int(thetime[0])
if hour <= EARLY_HOUR or hour >= LATE_HOUR:
colordate = QColor(0,0,102)
else:
colordate = QColor("white")
# user
(dom, user) = re.split(r"\\", row[6])
row[6] = user
if user in ("SYSTEM", "NETWORK SERVICE", "LOCAL SERVICE", "ANONYMOUS LOGON"):
textcolor = QColor("gray")
font = QFont("Arial", 8)
else:
textcolor = QColor("black")
font = QFont("Arial", 8)
font.setBold(True)
# insert line
if newday:
m = 0
for j in range(len(row)-3):
text = ""
if j == 0:
text = date
newitem = QTableWidgetItem(text)
newitem.setBackgroundColor(QColor("black"))
self.setItem(n, m, newitem)
m += 1
self.setRowHeight(n, 15)
n += 1
#for item in row:
m = 0
for j in range(len(row)):
# skip these columns
if j in (3,5,7):
continue
item = row[j]
if j == 1:
color2 = colordate
else:
color2 = color
newitem = QTableWidgetItem(item)
newitem.setBackgroundColor(color2)
newitem.setTextColor(textcolor)
newitem.setFont(font)
newitem.setTextAlignment(Qt.AlignTop)
newitem.setToolTip(item)
if j == 2:
newitem.setIcon(icon)
self.setItem(n, m, newitem)
m += 1
self.setRowHeight(n, 16)
n += 1
def parse_event_log(self, ndays):
"""Parses event log file.
Returns none.
"""
# run dumpel.exe
os.system("dumpel -f dumpel_results.txt -l security -d %s" % ndays)
fin = open("dumpel_results.txt")
lines = fin.readlines()
# open output files
#outfile = "audit_" + str(datetime.date.today()) + ".txt"
fout=open(outfile,'w')
# initialization
fout.write("LOGON/LOGOFFS:\n")
fout.write("--------------\n")
output = "%-13s %3s %11s %12s %12s\n" % ('user','day','date','logon','logoff')
fout.write(output)
event578_count = 0
user_logged_in = 0
red_events = []
orange_events = []
yellow_events = []
# loop on each line in the file
for line in lines:
items = re.split('\t', line)
self.data.append(items)
date = items[0]
time = items[1]
event = items[4]
(dom, user) = re.split(r"\\", items[6])
day = get_weekday(date)
if event in red_eventids:
red_events.append(line)
elif event in orange_eventids:
orange_events.append(line)
elif event in yellow_eventids:
yellow_events.append(line)
elif user != "SYSTEM":
#if (not user_logged_in) and (event == "528"):
if event == "528":
if user_logged_in:
output = "%-13s %3s %11s %12s %12s\n" % (user,day,logon_date,logon_time,'no logout')
fout.write(output)
logon_time = time
logon_user = user
logon_date = date
logout_backup = ""
user_logged_in = 1
elif user_logged_in and event == "578":
if user == logon_user:
if event578_count == 0:
event578_count = 1
elif event578_count == 1:
event578_count = 0
user_logged_in = 0
output = "%-13s %3s %11s %12s %12s\n" % (user,day,logon_date,logon_time,time)
fout.write(output)
# print red events
fout.write("\nRED EVENTS:\n")
fout.write("-----------\n")
if len(red_events) == 0:
fout.write("None.\n")
else:
for event in red_events:
fout.write(event)
# print orange events
fout.write("\nORANGE EVENTS:\n")
fout.write("--------------\n")
if len(orange_events) == 0:
fout.write("None.\n")
else:
for event in orange_events:
fout.write(event)
# print yellow events
fout.write("\nYELLOW EVENTS:\n")
fout.write("--------------\n")
if len(yellow_events) == 0:
fout.write("None.\n")
else:
for event in yellow_events:
fout.write(event)
# close files
fin.close()
fout.close()
# print message
print "Parse sucessful.\n"
return
################################################################
################################################################
def get_weekday(date):
(month,day,year) = re.split('/', date)
weekday = datetime.date(int(year),int(month),int(day)).weekday()
day_names = ['Mon','Tue','Wed','Thu','Fri','Sat','Sun']
return day_names[weekday]
################################################################
################################################################
def format_datetime(date, thetime):
(month,day,year) = re.split('/', date)
dateobj = datetime.date(int(year),int(month),int(day))
newdate = "%04d/%02d/%02d" % (dateobj.year, dateobj.month, dateobj.day)
timeobj = time.strptime(thetime, "%I:%M:%S %p")
newtime = time.strftime("%H:%M:%S", timeobj)
return newdate + "\n" + newtime
################################################################
################################################################
def get_dateobject(date):
(month,day,year) = re.split('/', date)
return datetime.date(int(year),int(month),int(day))
################################################################
################################################################
if __name__ == "__main__":
main()
</span></pre>
QTableWidget Example using Python 2.4, QT 4.1.4, and PyQt
2006-10-25T16:24:00-07:00https://www.saltycrane.com/blog/2006/10/qtablewidget-example-using-python-24/
QTableWidget Example using Python 2.4, QT 4.1.4, and PyQt
<pre class="python">
import sys
from Qt import *
lista = ['aa', 'ab', 'ac']
listb = ['ba', 'bb', 'bc']
listc = ['ca', 'cb', 'cc']
mystruct = {'A':lista, 'B':listb, 'C':listc}
class MyTable(QTableWidget):
def __init__(self, thestruct, *args):
QTableWidget.__init__(self, *args)
self.data = thestruct
self.setmydata()
def setmydata(self):
n = 0
for key in self.data:
m = 0
for item in self.data[key]:
newitem = QTableWidgetItem(item)
self.setItem(m, n, newitem)
m += 1
n += 1
def main(args):
app = QApplication(args)
table = MyTable(mystruct, 5, 3)
table.show()
sys.exit(app.exec_())
if __name__=="__main__":
main(sys.argv)
</pre>