]> sigrok.org Git - sigrok-meter.git/blob - mainwindow.py
Split the program up into multiple files.
[sigrok-meter.git] / mainwindow.py
1 ##
2 ## This file is part of the sigrok-meter project.
3 ##
4 ## Copyright (C) 2013 Uwe Hermann <uwe@hermann-uwe.de>
5 ## Copyright (C) 2014 Jens Steinhauser <jens.steinhauser@gmail.com>
6 ##
7 ## This program is free software; you can redistribute it and/or modify
8 ## it under the terms of the GNU General Public License as published by
9 ## the Free Software Foundation; either version 2 of the License, or
10 ## (at your option) any later version.
11 ##
12 ## This program is distributed in the hope that it will be useful,
13 ## but WITHOUT ANY WARRANTY; without even the implied warranty of
14 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 ## GNU General Public License for more details.
16 ##
17 ## You should have received a copy of the GNU General Public License
18 ## along with this program; if not, write to the Free Software
19 ## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
20 ##
21
22 import datamodel
23 import os.path
24 import qtcompat
25 import samplingthread
26 import textwrap
27
28 QtCore = qtcompat.QtCore
29 QtGui = qtcompat.QtGui
30
31 class EmptyMessageListView(QtGui.QListView):
32     '''List view that shows a message if the model im empty.'''
33
34     def __init__(self, message, parent=None):
35         super(self.__class__, self).__init__(parent)
36
37         self._message = message
38
39     def paintEvent(self, event):
40         m = self.model()
41         if m and m.rowCount():
42             super(self.__class__, self).paintEvent(event)
43             return
44
45         painter = QtGui.QPainter(self.viewport())
46         painter.drawText(self.rect(), QtCore.Qt.AlignCenter, self._message)
47
48 class MainWindow(QtGui.QMainWindow):
49     '''The main window of the application.'''
50
51     def __init__(self, context, drivers):
52         super(self.__class__, self).__init__()
53
54         self.context = context
55
56         self.delegate = datamodel.MultimeterDelegate(self, self.font())
57         self.model = datamodel.MeasurementDataModel(self)
58         self.model.rowsInserted.connect(self.modelRowsInserted)
59
60         self.setup_ui()
61
62         self.thread = samplingthread.SamplingThread(self.context, drivers)
63         self.thread.measured.connect(self.model.update)
64         self.thread.error.connect(self.error)
65         self.thread.start()
66
67     def setup_ui(self):
68         self.setWindowTitle('sigrok-meter')
69         # resizing the listView below will increase this again
70         self.resize(10, 10)
71
72         p = os.path.abspath(os.path.dirname(__file__))
73         p = os.path.join(p, 'sigrok-logo-notext.png')
74         self.setWindowIcon(QtGui.QIcon(p))
75
76         actionQuit = QtGui.QAction(self)
77         actionQuit.setText('&Quit')
78         actionQuit.setIcon(QtGui.QIcon.fromTheme('application-exit'))
79         actionQuit.setShortcut('Ctrl+Q')
80         actionQuit.triggered.connect(self.close)
81
82         actionAbout = QtGui.QAction(self)
83         actionAbout.setText('&About')
84         actionAbout.setIcon(QtGui.QIcon.fromTheme('help-about'))
85         actionAbout.triggered.connect(self.show_about)
86
87         menubar = self.menuBar()
88         menuFile = menubar.addMenu('&File')
89         menuFile.addAction(actionQuit)
90         menuHelp = menubar.addMenu('&Help')
91         menuHelp.addAction(actionAbout)
92
93         self.listView = EmptyMessageListView('waiting for data...')
94         self.listView.setFrameShape(QtGui.QFrame.NoFrame)
95         self.listView.viewport().setBackgroundRole(QtGui.QPalette.Window)
96         self.listView.viewport().setAutoFillBackground(True)
97         self.listView.setMinimumWidth(260)
98         self.listView.setSelectionMode(QtGui.QAbstractItemView.NoSelection)
99         self.listView.setEditTriggers(QtGui.QAbstractItemView.NoEditTriggers)
100         self.listView.setVerticalScrollMode(QtGui.QAbstractItemView.ScrollPerPixel)
101         self.listView.setItemDelegate(self.delegate)
102         self.listView.setModel(self.model)
103         self.listView.setUniformItemSizes(True)
104         self.listView.setMinimumSize(self.delegate.sizeHint())
105
106         self.setCentralWidget(self.listView)
107         self.centralWidget().setContentsMargins(0, 0, 0, 0)
108
109     def closeEvent(self, event):
110         self.thread.stop()
111         event.accept()
112
113     @QtCore.Slot()
114     def show_about(self):
115         text = textwrap.dedent('''\
116             <div align="center">
117                 <b>sigrok-meter</b><br/>
118                 0.1.0<br/>
119                 Using libsigrok {} (lib version {}).<br/>
120                 <a href='http://www.sigrok.org'>
121                          http://www.sigrok.org</a><br/>
122                 <br/>
123                 This program comes with ABSOLUTELY NO WARRANTY;<br/>
124                 for details visit
125                 <a href='http://www.gnu.org/licenses/gpl.html'>
126                          http://www.gnu.org/licenses/gpl.html</a>
127             </div>
128         '''.format(self.context.package_version, self.context.lib_version))
129
130         QtGui.QMessageBox.about(self, 'About sigrok-meter', text)
131
132     @QtCore.Slot(str)
133     def error(self, msg):
134         '''Error handler for the sampling thread.'''
135         QtGui.QMessageBox.critical(self, 'Error', msg)
136         self.close()
137
138     @QtCore.Slot(object, int, int)
139     def modelRowsInserted(self, parent, start, end):
140         '''Resizes the list view to the size of the content.'''
141
142         rows = self.model.rowCount()
143         dh = self.delegate.sizeHint().height()
144         self.listView.setMinimumHeight(dh * rows)