diff --git a/gui/mozregression-gui.py b/gui/mozregression-gui.py
index 3323550f..5b3bde65 100644
--- a/gui/mozregression-gui.py
+++ b/gui/mozregression-gui.py
@@ -9,6 +9,7 @@ from mozlog.structured.structuredlog import StructuredLogger
from mozregui.ui.mainwindow import Ui_MainWindow
from mozregui.wizard import BisectionWizard
from mozregui.bisection import BisectRunner
+from mozregui.report import ReportModel
class MainWindow(QMainWindow):
@@ -18,6 +19,12 @@ class MainWindow(QMainWindow):
self.ui.setupUi(self)
self.bisect_runner = BisectRunner(self)
+ self.report_model = ReportModel()
+ self.ui.report_view.setModel(self.report_model)
+
+ self.bisect_runner.bisector_created.connect(
+ self.report_model.attach_bisector)
+
@Slot()
def start_bisection_wizard(self):
wizard = BisectionWizard(self)
diff --git a/gui/mozregui/bisection.py b/gui/mozregui/bisection.py
index a5ebd255..c54df2f0 100644
--- a/gui/mozregui/bisection.py
+++ b/gui/mozregui/bisection.py
@@ -66,7 +66,11 @@ class GuiTestRunner(QObject, TestRunner):
class GuiBisector(QObject, Bisector):
- finished = Signal(int)
+ started = Signal(object)
+ finished = Signal(object, int)
+ step_started = Signal(object, int)
+ step_build_found = Signal(object, int, object)
+ step_finished = Signal(object, int, str)
def __init__(self, fetch_config, persist=None):
QObject.__init__(self)
@@ -75,6 +79,7 @@ class GuiBisector(QObject, Bisector):
self.bisection = None
self.mid = None
self.build_infos = None
+ self._step_num = 0
self.download_manager.download_finished.connect(self._build_dl_finished)
self.test_runner.evaluate_finished.connect(self._evaluate_finished)
@@ -85,19 +90,25 @@ class GuiBisector(QObject, Bisector):
self.test_runner,
self.fetch_config,
dl_in_background=False)
+ self._step_num = 0
+ self.started.emit(self.bisection)
self._bisect_next()
@Slot()
def _bisect_next(self):
+ self._step_num += 1
+ self.step_started.emit(self.bisection, self._step_num)
# todo: make this non blocking
self.mid = mid = self.bisection.search_mid_point()
result = self.bisection.init_handler(mid)
if result != Bisection.RUNNING:
- self.finished.emit(result)
+ self.finished.emit(self.bisection, result)
else:
self.build_infos = \
self.bisection.handler.build_infos(mid, self.fetch_config)
self.download_manager.focus_download(self.build_infos)
+ self.step_build_found.emit(self.bisection, self._step_num,
+ self.build_infos)
@Slot(object)
def _build_dl_finished(self, dl):
@@ -111,14 +122,18 @@ class GuiBisector(QObject, Bisector):
@Slot()
def _evaluate_finished(self):
self.bisection.update_build_info(self.mid, self.test_runner.app_info)
+ self.step_finished.emit(self.bisection, self._step_num,
+ self.test_runner.verdict)
result = self.bisection.handle_verdict(self.mid, self.test_runner.verdict)
if result != Bisection.RUNNING:
- self.finished.emit(result)
+ self.finished.emit(self.bisection, result)
else:
self._bisect_next()
class BisectRunner(QObject):
+ bisector_created = Signal(object)
+
def __init__(self, mainwindow):
QObject.__init__(self)
self.mainwindow = mainwindow
@@ -129,6 +144,7 @@ class BisectRunner(QObject):
fetch_config = create_config(options['application'],
mozinfo.os, mozinfo.bits)
self.bisector = GuiBisector(fetch_config)
+ self.bisector.started.connect(self.on_bisection_started)
self.bisector.download_manager.download_progress.connect(
self.show_dl_progress)
self.bisector.test_runner.evaluate_started.connect(
@@ -166,8 +182,8 @@ class BisectRunner(QObject):
verdict = "b"
self.bisector.test_runner.finish(verdict)
- @Slot(int)
- def bisection_finished(self, resultcode):
+ @Slot(object, int)
+ def bisection_finished(self, bisection, resultcode):
if resultcode == Bisection.NO_DATA:
msg = "Unable to find enough data to bisect."
dialog = QMessageBox.warning
@@ -175,3 +191,7 @@ class BisectRunner(QObject):
msg = "The bisection is done."
dialog = QMessageBox.information
dialog(self.mainwindow, "End of the bisection", msg)
+
+ @Slot()
+ def on_bisection_started(self):
+ self.bisector_created.emit(self.bisector)
diff --git a/gui/mozregui/report.py b/gui/mozregui/report.py
new file mode 100644
index 00000000..c1dd5366
--- /dev/null
+++ b/gui/mozregui/report.py
@@ -0,0 +1,72 @@
+from PySide.QtCore import QAbstractTableModel, QModelIndex, Qt, \
+ Slot
+
+class StepReport(object):
+ def __init__(self):
+ self.build_infos = None
+ self.verdict = None
+
+ def status_text(self):
+ if self.build_infos is None:
+ return "Looking for build data..."
+ if self.build_infos['build_type'] == 'nightly':
+ msg = "Found nightly build: %s" % self.build_infos['build_date']
+ else:
+ msg = "Found inbound build: %s" % self.build_infos['changeset']
+ if self.verdict is not None:
+ msg += ' (verdict: %s)' % self.verdict
+ return msg
+
+class ReportModel(QAbstractTableModel):
+ def __init__(self):
+ QAbstractTableModel.__init__(self)
+ self.step_reports = []
+
+ @Slot(object)
+ def attach_bisector(self, bisector):
+ bisector.step_started.connect(self.step_started)
+ bisector.step_build_found.connect(self.step_build_found)
+ bisector.step_finished.connect(self.step_finished)
+ bisector.finished.connect(self.finished)
+
+ def rowCount(self, parent=QModelIndex()):
+ return len(self.step_reports)
+
+ def columnCount(self, parent=QModelIndex()):
+ return 1
+
+ def data(self, index, role=Qt.DisplayRole):
+ if role == Qt.DisplayRole:
+ step_report = self.step_reports[index.row()]
+ return step_report.status_text()
+ return None
+
+ def update_step_report(self, step_report):
+ index = self.createIndex(self.step_reports.index(step_report), 0)
+ self.dataChanged.emit(index, index)
+
+ @Slot(object, int)
+ def step_started(self, bisection, step_num):
+ self.beginInsertRows(QModelIndex(), step_num-1, step_num-1)
+ self.step_reports.append(StepReport())
+ self.endInsertRows()
+
+ @Slot(object, int, object)
+ def step_build_found(self, bisection, step_num, build_infos):
+ step_report = self.step_reports[step_num-1]
+ step_report.build_infos = build_infos
+ self.update_step_report(step_report)
+
+ @Slot(object, int, str)
+ def step_finished(self, bisection, step_num, verdict):
+ step_report = self.step_reports[step_num-1]
+ step_report.verdict = verdict
+ self.update_step_report(step_report)
+
+ @Slot(object, int)
+ def finished(self, bisection, result):
+ # remove the last insterted step
+ index = len(self.step_reports) -1
+ self.beginRemoveRows(QModelIndex(), index, index)
+ self.step_reports.pop(index)
+ self.endRemoveRows()
diff --git a/gui/mozregui/ui/mainwindow.ui b/gui/mozregui/ui/mainwindow.ui
index 41bcc366..4136dd89 100644
--- a/gui/mozregui/ui/mainwindow.ui
+++ b/gui/mozregui/ui/mainwindow.ui
@@ -13,7 +13,23 @@
Mozregression-gui
-
+
+
+ -
+
+
+ false
+
+
+ true
+
+
+ false
+
+
+
+
+