Example #1
0
def make_progress(msg,total_steps):
    progress = QProgressDialog(msg, None, 0, total_steps, None)
    progress.setWindowTitle("Horse")
    progress.setMinimumDuration(0)
    progress.setWindowModality(Qt.WindowModal)
    progress.setValue( progress.value() + 1)
    progress.show()
    return progress
Example #2
0
 def doit(self):
     """Creates the report."""
     d = QProgressDialog(
             self.tr("Generating Diagrams..."), self.tr("Cancel"),
             0, len(self._connections) * len(self._diagramnames))
     d.setWindowModality(Qt.WindowModal)
     d.show()
     aborted = False
     for c in self._connections:
         aborted = self._createDiagrams(c, d)
     d.hide()
     if not aborted:
         self._collectInterpretations()
         self._generateReport()
def notifyRun(vcfPath, vcfAttributes, xAttribute, yAttribute, softFilters, forcedCategoricals, featurePaths):
    global canceled, splash, window
    splash = QProgressDialog("Loading %s" % os.path.split(vcfPath)[1], "Cancel", 0, 1000, parent=None)
    splash.setWindowModality(Qt.WindowModal)
    splash.setAutoReset(False)
    splash.setAutoClose(False)
    splash.show()
    canceled = False
    
    vData = variantData(vcfPath, vcfAttributes, forcedCategoricals)
    vParams = variantLoadingParameters(passFunction=vData.addVariant,
                                     rejectFunction=None,
                                     callbackArgs={},
                                     tickFunction=tick,
                                     tickInterval=0.1,
                                     individualsToInclude=[],
                                     individualAppendString="",
                                     lociToInclude=None,
                                     mask=None,
                                     invertMask=False,
                                     attributesToInclude=None,
                                     attributeAppendString="",
                                     skipGenotypeAttributes=True,
                                     returnFileObject=False,
                                     alleleMatching=allele.STRICT,
                                     attemptRepairsWhenComparing=True)
    try:
        variantFile.parseVcfFile(vcfPath, vParams)
    except cancelButtonException:
        splash.close()
        window.window.show()
        return
    
    if softFilters == None:
        softFilters = {}
        for k in vData.axisLookups.iterkeys():
            if k == xAttribute or k == yAttribute:
                if vData.axisLookups[k].hasNumeric:
                    fivePercent = 0.05*(vData.axisLookups[k].maximum-vData.axisLookups[k].minimum)
                    ranges = [(vData.axisLookups[k].maximum-fivePercent,vData.axisLookups[k].maximum)]
                else:
                    ranges = None
                values = []
            else:
                ranges = None
                values = None
            softFilters[k] = valueFilter(values=values,
                                         ranges=ranges,
                                         includeNone=True,
                                         includeBlank=True,
                                         includeInf=True,
                                         includeNaN=True,
                                         includeMissing=True,
                                         includeAlleleMasked=True,
                                         listMode=valueFilter.LIST_INCLUSIVE)
    intMan = interactionManager(vData,softFilters)
    
    # TODO
    fData = featureData(featurePaths)
    if canceled:
        splash.close()
        window.window.show()
        return

    splash.close()
    appWindow = appWidget(vData,fData,intMan,xAttribute,yAttribute)
    intMan.setApp(appWindow)
Example #4
0
class RunnerDialog(QDialog):

    options_added = Signal(Options)
    options_running = Signal(Options)
    options_simulated = Signal(Options)
    options_error = Signal(Options, Exception)
    results_saved = Signal(Results, str)
    results_error = Signal(Results, Exception)

    def __init__(self, parent=None):
        QDialog.__init__(self, parent)
        self.setWindowTitle('Runner')
        self.setMinimumWidth(750)

        # Runner
        self._runner = None

        self._running_timer = QTimer()
        self._running_timer.setInterval(500)

        # Widgets
        self._dlg_progress = QProgressDialog()
        self._dlg_progress.setRange(0, 100)
        self._dlg_progress.setModal(True)
        self._dlg_progress.hide()

        lbl_outputdir = QLabel("Output directory")
        self._txt_outputdir = DirBrowseWidget()

        max_workers = cpu_count() #@UndefinedVariable
        lbl_workers = QLabel('Number of workers')
        self._spn_workers = QSpinBox()
        self._spn_workers.setRange(1, max_workers)
        self._spn_workers.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        lbl_max_workers = QLabel('(max: %i)' % max_workers)

        self._chk_overwrite = QCheckBox("Overwrite existing results in output directory")
        self._chk_overwrite.setChecked(True)

        self._lbl_available = QLabel('Available')
        self._lst_available = QListView()
        self._lst_available.setModel(_AvailableOptionsListModel())
        self._lst_available.setSelectionMode(QListView.SelectionMode.MultiSelection)

        tlb_available = QToolBar()
        spacer = QWidget()
        spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        tlb_available.addWidget(spacer)
        act_open = tlb_available.addAction(getIcon("document-open"), "Open")
        act_open.setShortcut(QKeySequence.Open)
        tlb_available.addSeparator()
        act_remove = tlb_available.addAction(getIcon("list-remove"), "Remove")
        act_clear = tlb_available.addAction(getIcon("edit-clear"), "Clear")

        self._btn_addtoqueue = QPushButton(getIcon("go-next"), "")
        self._btn_addtoqueue.setToolTip("Add to queue")
        self._btn_addtoqueue.setEnabled(False)

        self._btn_addalltoqueue = QPushButton(getIcon("go-last"), "")
        self._btn_addalltoqueue.setToolTip("Add all to queue")
        self._btn_addalltoqueue.setEnabled(False)

        self._lbl_options = QLabel('Queued/Running/Completed')
        self._tbl_options = QTableView()
        self._tbl_options.setModel(_StateOptionsTableModel())
        self._tbl_options.setItemDelegate(_StateOptionsItemDelegate())
        self._tbl_options.setSelectionMode(QListView.SelectionMode.NoSelection)
        self._tbl_options.setColumnWidth(1, 60)
        self._tbl_options.setColumnWidth(2, 80)
        header = self._tbl_options.horizontalHeader()
        header.setResizeMode(0, QHeaderView.Interactive)
        header.setResizeMode(1, QHeaderView.Fixed)
        header.setResizeMode(2, QHeaderView.Fixed)
        header.setResizeMode(3, QHeaderView.Stretch)

        self._btn_start = QPushButton(getIcon("media-playback-start"), "Start")

        self._btn_cancel = QPushButton("Cancel")
        self._btn_cancel.setEnabled(False)

        self._btn_close = QPushButton("Close")

        self._btn_import = QPushButton("Import")
        self._btn_import.setEnabled(False)

        # Layouts
        layout = QVBoxLayout()

        sublayout = QGridLayout()
        sublayout.addWidget(lbl_outputdir, 0, 0)
        sublayout.addWidget(self._txt_outputdir, 0, 1)
        sublayout.addWidget(lbl_workers, 1, 0)

        subsublayout = QHBoxLayout()
        subsublayout.addWidget(self._spn_workers)
        subsublayout.addWidget(lbl_max_workers)
        sublayout.addLayout(subsublayout, 1, 1)
        layout.addLayout(sublayout)

        sublayout.addWidget(self._chk_overwrite, 2, 0, 1, 3)

        sublayout = QGridLayout()
        sublayout.setColumnStretch(0, 1)
        sublayout.setColumnStretch(2, 3)
        sublayout.addWidget(self._lbl_available, 0, 0)
        sublayout.addWidget(self._lst_available, 1, 0)
        sublayout.addWidget(tlb_available, 2, 0)

        subsublayout = QVBoxLayout()
        subsublayout.addStretch()
        subsublayout.addWidget(self._btn_addtoqueue)
        subsublayout.addWidget(self._btn_addalltoqueue)
        subsublayout.addStretch()
        sublayout.addLayout(subsublayout, 1, 1)

        sublayout.addWidget(self._lbl_options, 0, 2)
        sublayout.addWidget(self._tbl_options, 1, 2)
        layout.addLayout(sublayout)

        sublayout = QHBoxLayout()
        sublayout.addStretch()
        sublayout.addWidget(self._btn_import)
        sublayout.addWidget(self._btn_start)
        sublayout.addWidget(self._btn_cancel)
        sublayout.addWidget(self._btn_close)
        layout.addLayout(sublayout)

        self.setLayout(layout)

        # Signal
        self._running_timer.timeout.connect(self._onRunningTimer)

        act_open.triggered.connect(self._onOpen)
        act_remove.triggered.connect(self._onRemove)
        act_clear.triggered.connect(self._onClear)

        self._btn_addtoqueue.released.connect(self._onAddToQueue)
        self._btn_addalltoqueue.released.connect(self._onAddAllToQueue)
        self._btn_start.released.connect(self._onStart)
        self._btn_cancel.released.connect(self._onCancel)
        self._btn_close.released.connect(self._onClose)
        self._btn_import.released.connect(self._onImport)

        self.options_added.connect(self._onOptionsAdded)
        self.options_running.connect(self._onOptionsRunning)
        self.options_simulated.connect(self._onOptionsSimulated)
        self.options_error.connect(self._onOptionsError)
        self.results_error.connect(self._onResultsError)

        # Defaults
        settings = get_settings()
        section = settings.add_section('gui')
        if hasattr(section, 'outputdir'):
            self._txt_outputdir.setPath(section.outputdir)
        if hasattr(section, 'maxworkers'):
            self._spn_workers.setValue(int(section.maxworkers))
        if hasattr(section, 'overwrite'):
            state = True if section.overwrite.lower() == 'true' else False
            self._chk_overwrite.setChecked(state)

    def _onDialogProgressProgress(self, progress, status):
        self._dlg_progress.setValue(progress * 100)
        self._dlg_progress.setLabelText(status)

    def _onDialogProgressCancel(self):
        self._dlg_progress.hide()
        if self._options_reader_thread is None:
            return
        self._options_reader_thread.cancel()
        self._options_reader_thread.quit()
        self._options_reader_thread.wait()

    def _onDialogProgressException(self, ex):
        self._dlg_progress.hide()
        self._options_reader_thread.quit()
        self._options_reader_thread.wait()
        messagebox.exception(self, ex)

    def _onRunningTimer(self):
        self._tbl_options.model().reset()

    def _onOpen(self):
        settings = get_settings()
        curdir = getattr(settings.gui, 'opendir', os.getcwd())

        filepath, namefilter = \
            QFileDialog.getOpenFileName(self, "Open", curdir,
                                        'Options [*.xml] (*.xml)')

        if not filepath or not namefilter:
            return
        settings.gui.opendir = os.path.dirname(filepath)

        if not filepath.endswith('.xml'):
            filepath += '.xml'

        self._options_reader_thread = _OptionsReaderWrapperThread(filepath)
        self._dlg_progress.canceled.connect(self._onDialogProgressCancel)
        self._options_reader_thread.resultReady.connect(self._onOpened)
        self._options_reader_thread.progressUpdated.connect(self._onDialogProgressProgress)
        self._options_reader_thread.exceptionRaised.connect(self._onDialogProgressException)
        self._options_reader_thread.start()

        self._dlg_progress.reset()
        self._dlg_progress.show()

    def _onOpened(self, options):
        self._dlg_progress.hide()
        self._options_reader_thread.quit()
        self._options_reader_thread.wait()
        self._options_reader_thread = None

        try:
            self._lst_available.model().addOptions(options)
        except Exception as ex:
            messagebox.exception(self, ex)

    def _onRemove(self):
        selection = self._lst_available.selectionModel().selection().indexes()
        if len(selection) == 0:
            QMessageBox.warning(self, "Queue", "Select an options")
            return

        model = self._lst_available.model()
        for row in sorted(map(methodcaller('row'), selection), reverse=True):
            model.popOptions(row)

    def _onClear(self):
        self._lst_available.model().clearOptions()

    def _onAddToQueue(self):
        selection = self._lst_available.selectionModel().selection().indexes()
        if len(selection) == 0:
            QMessageBox.warning(self, "Queue", "Select an options")
            return

        model = self._lst_available.model()
        for row in sorted(map(methodcaller('row'), selection), reverse=True):
            options = model.options(row)
            try:
                self._runner.put(options)
            except Exception as ex:
                messagebox.exception(self, ex)
                return

    def _onAddAllToQueue(self):
        model = self._lst_available.model()
        for row in reversed(range(0, model.rowCount())):
            options = model.options(row)
            try:
                self._runner.put(options)
            except Exception as ex:
                messagebox.exception(self, ex)
                return

    def _onStart(self):
        outputdir = self._txt_outputdir.path()
        if not outputdir:
            QMessageBox.critical(self, 'Start', 'Missing output directory')
            return
        max_workers = self._spn_workers.value()
        overwrite = self._chk_overwrite.isChecked()
        self.start(outputdir, overwrite, max_workers)

    def _onCancel(self):
        self.cancel()

    def _onClose(self):
        if self._runner is not None:
            self._runner.close()
        self._running_timer.stop()
        self.close()

    def _onImport(self):
        list_options = self._lst_available.model().listOptions()
        if not list_options:
            return

        # Select options
        dialog = _OptionsSelector(list_options)
        if not dialog.exec_():
            return
        options = dialog.options()

        # Start importer
        outputdir = self._runner.outputdir
        max_workers = self._runner.max_workers
        importer = LocalImporter(outputdir, max_workers)

        importer.start()
        importer.put(options)

        self._dlg_progress.show()
        try:
            while importer.is_alive():
                if self._dlg_progress.wasCanceled():
                    importer.cancel()
                    break
                self._dlg_progress.setValue(importer.progress * 100)
        finally:
            self._dlg_progress.hide()

    def _onOptionsAdded(self, options):
        logging.debug('runner: optionsAdded')
        self._tbl_options.model().addOptions(options)

    def _onOptionsRunning(self, options):
        logging.debug('runner: optionsRunning')
        self._tbl_options.model().resetOptions(options)

    def _onOptionsSimulated(self, options):
        logging.debug('runner: optionsSimulated')
        self._tbl_options.model().resetOptions(options)

    def _onOptionsError(self, options, ex):
        logging.debug('runner: optionsError')
        self._tbl_options.model().resetOptions(options)

    def _onResultsError(self, results, ex):
        logging.debug('runner: resultsError')
        self._tbl_options.model().reset()

    def closeEvent(self, event):
        if self.is_running():
            message = 'Runner is running. Do you want to continue?'
            answer = QMessageBox.question(self, 'Runner', message,
                                          QMessageBox.Yes | QMessageBox.No)
            if answer == QMessageBox.No:
                event.ignore()
                return

        self.cancel()
        self._dlg_progress.close()

        settings = get_settings()
        section = settings.add_section('gui')

        path = self._txt_outputdir.path()
        if path:
            section.outputdir = path
        section.maxworkers = str(self._spn_workers.value())
        section.overwrite = str(self._chk_overwrite.isChecked())

        settings.write()

        event.accept()

    def addAvailableOptions(self, options):
        self._lst_available.model().addOptions(options)

    def removeAvailableOptions(self, options):
        self._lst_available.model().removeOptions(options)

    def clearAvailableOptions(self):
        self._lbl_available.model().clearOptions()

    def start(self, outputdir, overwrite, max_workers):
        self._runner = LocalRunner(outputdir=outputdir,
                                   overwrite=overwrite,
                                   max_workers=max_workers)

        self._tbl_options.setModel(_StateOptionsTableModel(self._runner))

        self._spn_workers.setEnabled(False)
        self._txt_outputdir.setEnabled(False)
        self._chk_overwrite.setEnabled(False)
        self._btn_addtoqueue.setEnabled(True)
        self._btn_addalltoqueue.setEnabled(True)
        self._btn_start.setEnabled(False)
        self._btn_cancel.setEnabled(True)
        self._btn_close.setEnabled(False)
        self._btn_import.setEnabled(True)

        self._runner.options_added.connect(self.options_added.emit)
        self._runner.options_running.connect(self.options_running.emit)
        self._runner.options_simulated.connect(self.options_simulated.emit)
        self._runner.options_error.connect(self.options_error.emit)
        self._runner.results_saved.connect(self.results_saved.emit)
        self._runner.results_error.connect(self.results_error.emit)

        self._running_timer.start()
        self._runner.start()

    def cancel(self):
        if self._runner is None:
            return
        self._runner.cancel()
        self._running_timer.stop()

        self._runner.options_added.disconnect(self.options_added.emit)
        self._runner.options_running.disconnect(self.options_running.emit)
        self._runner.options_simulated.disconnect(self.options_simulated.emit)
        self._runner.options_error.disconnect(self.options_error.emit)
        self._runner.results_saved.disconnect(self.results_saved.emit)
        self._runner.results_error.disconnect(self.results_error.emit)

        self._runner = None

        self._spn_workers.setEnabled(True)
        self._txt_outputdir.setEnabled(True)
        self._chk_overwrite.setEnabled(True)
        self._btn_addtoqueue.setEnabled(False)
        self._btn_addalltoqueue.setEnabled(False)
        self._btn_start.setEnabled(True)
        self._btn_cancel.setEnabled(False)
        self._btn_close.setEnabled(True)
        self._btn_import.setEnabled(False)

    def is_running(self):
        return self._runner is not None and self._runner.is_alive()
class setupApp:
    def __init__(self, params):
        loader = QUiLoader()
        infile = QFile("gui/ui/Setup.ui")
        infile.open(QFile.ReadOnly)
        self.window = loader.load(infile, None)
        
        self.loadPrefs()
        
        self.window.quitButton.clicked.connect(self.closeApp)
        self.window.saveButton.clicked.connect(self.savePrefs)
        self.window.runButton.clicked.connect(self.runSV)
        
        self.splash = QProgressDialog("Loading", "Cancel", 0, 100, parent=None)
        self.splash.setWindowModality(Qt.WindowModal)
        self.splash.setAutoReset(False)
        self.splash.setAutoClose(False)
        self.splash.hide()
        self.canceled = False
        
        self.window.show()
        self.runningApp = None
    
    def loadPrefs(self):
        infile = open(PREFS_FILE,'r')
        self.window.textEdit.setPlainText(infile.read())
        infile.close()
    
    def savePrefs(self):
        outfile=open(PREFS_FILE,'w')
        outfile.write(self.window.textEdit.toPlainText())
        outfile.close()
    
    def showProgressWidget(self, estimate=100, message="Loading..."):
        self.splash.setLabelText(message)
        self.splash.setMaximum(estimate)
        self.splash.setValue(0)
        self.splash.show()
    
    def tickProgressWidget(self, numTicks=1, message=None):
        if self.canceled:
            return
        if message != None:
            self.splash.setLabelText(message)
        newValue = min(self.splash.maximum(),numTicks+self.splash.value())
        self.splash.setValue(newValue)
        self.canceled = self.splash.wasCanceled()
        return self.canceled
    
    def runSV(self, params=PREFS_FILE):
        self.savePrefs()
        self.window.hide()
        
        appPrefs = prefs.generateFromText(self.window.textEdit.toPlainText())
        
        self.showProgressWidget(appPrefs.maxTicks, "Loading files...")
        
        self.canceled = False
        vData = appPrefs.loadDataObjects(callback=self.tickProgressWidget)
        if self.canceled:
            self.splash.hide()
            self.window.show()
            return
        
        self.showProgressWidget(vData.estimateTicks(), "Writing files...")
        
        success = vData.dumpVcfFile(path='/Users/Home/Desktop/chr3-seq_parsed.vcf',callback=self.tickProgressWidget)
        if not success:
            self.splash.hide()
            self.window.show()
            return
        
        sys.exit(0)
        # TODO write to file
    
    def closeApp(self):
        self.window.reject()
 def go(self):
     global visWindow
     for k in Pedigree.REQUIRED_KEYS.keys():
         t = self.overrides[k].currentText()
         if t == '':
             self.displayError("%s header is required." % k)
             return
         elif not t in self.header:
             self.displayError("%s doesn't exist in the input file." % t)
             return
         Pedigree.REQUIRED_KEYS[k] = t
     for k in Pedigree.RESERVED_KEYS.keys():
         t = self.overrides[k].currentText()
         if self.window.programBox.currentText() == 'vis':
             if t == '':
                 self.displayError("%s header is required." % k)
                 return
             elif not t in self.header:
                 self.displayError("%s doesn't exist in the input file." % t)
                 return
         else:
             if t == '':
                 t = k
         Pedigree.RESERVED_KEYS[k] = t
     
     try:
         if self.window.programBox.currentText() == 'vis':
             fileName = self.window.inputField.text()
             if fileName.lower().endswith('.gexf') or fileName.lower().endswith('.json'):
                 raise Exception('.gexf and .json formats are not supported for the vis program. Use calculateD to create a .dat file.')
             ped = Pedigree(fileName, countAndCalculate=False, zeroMissing=self.window.zeroMissingBox.isChecked())
             from resources.main_app import App
             self.window.hide()
             visWindow = App(ped)
             self.window.close()
         else:
             progress = QProgressDialog(u"Running...", u"Cancel", 0, NUM_TICKS, parent=None)
             progress.setWindowModality(Qt.WindowModal)
             progress.show()
             
             def tick(newMessage=None, increment=1):
                 if progress.wasCanceled():
                     raise cancelException('Cancel clicked.')
                 newValue = min(progress.maximum(),progress.value()+increment)
                 progress.setValue(newValue)
                 if newMessage != None:
                     progress.setLabelText(newMessage)
                 return True
             
             ped = Pedigree(self.window.inputField.text(), countAndCalculate=True, zeroMissing=self.window.zeroMissingBox.isChecked(), tickFunction=tick, numTicks=NUM_TICKS)
             
             progress.setLabelText('Writing File...')
             extension = os.path.splitext(self.window.outputField.text())[1].lower()
             if extension == '.gexf':
                 edgeTypes = Pedigree.defaultEdgeTypes()
                 nodeAttributeTypes = Pedigree.defaultNodeAttributeTypes()
                 nodeAttributeTypes['is_root'] = gexf_node_attribute_mapper('is_root', attrType=gexf_node_attribute_mapper.BOOLEAN, defaultValue=False, validValues=[False,True])
                 ped.write_gexf(self.window.outputField.text(), edgeTypes, nodeAttributeTypes)
             elif extension == '.json':
                 ped.write_json(self.window.outputField.text())
             else:
                 ped.write_egopama(self.window.outputField.text())
             
             progress.close()
             
             self.window.inputField.setText(self.window.outputField.text())
             self.window.outputField.setText("")
             self.window.programBox.setCurrentIndex(1)
     except Exception, e:
         if not isinstance(e, cancelException):
             self.displayError("An unexpected error occurred.",traceback.format_exc())
Example #7
0
    def reload(self, order_overview_widget, all_ops, all_operations, sort=1):

        # mainlog.debug("reload...")
        progress = QProgressDialog(_("Collecting data..."), None, 0,
                                   len(all_ops) + 3, order_overview_widget)
        progress.setWindowTitle("Horse")
        progress.setMinimumDuration(0)
        progress.setWindowModality(Qt.WindowModal)
        progress.setValue(progress.value() + 1)
        progress.show()

        for i in self.items():
            self.removeItem(i)

        self.posts_offsets = dict()
        self.drawn_operations_data = dict()

        self.cursor = QGraphicsRectItem(0, 0, 50, 300)
        self.cursor.setBrush(QBrush(QColor(208, 208, 255, 255)))
        self.cursor.setPen(QPen(Qt.transparent))
        self.addItem(self.cursor)

        bar_width = 8
        bar_height = int(bar_width * 60.0 / 8.0)

        ascent = QFontMetrics(self.base_font).ascent()
        ascent_big = QFontMetrics(self.base_font_big).ascent()

        post_ops = {}

        # mainlog.debug("reload...2")

        # z = 0
        # for op,order_part,parts in all_operations:
        #     z = op.planned_hours
        #     z = order_part.deadline
        #     z = order_part.qty
        #     z = order_part.human_identifier

        # all_operations = map(lambda i:i[0],all_operations)

        y = 0
        for opdef in all_ops:
            progress.setValue(progress.value() + 1)

            operations = filter(
                lambda op: op.operation_definition_id == opdef.
                operation_definition_id, all_operations)

            # We're only interested in the effort/time that remains
            # to be put on an operation. We're only interested in
            # the future.

            # We want the oeprations that are either
            # - ongoing
            # - ready to start.
            # In all cases we're only interested in operations
            # that are "active"

            if sort == 1:
                operations = sorted(
                    operations, key=lambda op: op.deadline or date(3000, 1, 1))
            elif sort == 2:
                operations = sorted(
                    operations,
                    key=lambda op: op.planned_hours * op.qty - op.done_hours)
            else:
                # Don't sort
                pass

            maximum = 16.0  #float !
            small_hours = 0
            op_ndx = 0
            current_x = 50
            bar_drawn = False

            total_done_hours = total_estimated = 0

            # --------------------------------------------------------------
            # Started operations

            bars_line = BarsLine(16, bar_width, bar_height, current_x, y, self,
                                 order_overview_widget)
            total_hours_to_do = 0

            for op in filter(lambda op: op.done_hours > 0, operations):
                hours_to_do = max(
                    0, op.planned_hours * op.qty -
                    op.done_hours)  # max protects against reporting errors
                total_hours_to_do += hours_to_do

                total_estimated += op.planned_hours * op.qty
                total_done_hours += op.done_hours

                bars_line.add_bar(hours_to_do, QBrush(Qt.green),
                                  self._operation_hoover_description(op),
                                  False,
                                  None)  # op.production_file.order_part)

            # --------------------------------------------------------------
            bars_line_unstarted_operations = BarsLine(16, bar_width,
                                                      bar_height,
                                                      current_x + 30, y, self,
                                                      order_overview_widget)
            total_hours_to_do_on_unstarted_operations = 0
            for op in filter(lambda op: op.done_hours == 0, operations):

                hours_to_do = op.planned_hours * op.qty
                total_hours_to_do_on_unstarted_operations += hours_to_do

                total_estimated += hours_to_do

                bars_line_unstarted_operations.add_bar(
                    hours_to_do, QBrush(Qt.yellow),
                    self._operation_hoover_description(op), False,
                    None)  #op.production_file.order_part)

            y_start = y

            total = total_hours_to_do + total_hours_to_do_on_unstarted_operations

            if total > 0:

                self.drawn_operations_data[
                    opdef.operation_definition_id] = "{}h".format(
                        int(round(total_estimated)))

                gi = QGraphicsSimpleTextItem(
                    _("{} - Estimated to do : {}h; done : {}h").format(
                        opdef.description, int(round(total)),
                        int(round(total_done_hours))))
                gi.setFont(self.base_font_big)
                gi.setPos(0, y - gi.boundingRect().height())
                self.addItem(gi)

                th = gi.boundingRect().height()

                gi = QGraphicsLineItem(-ascent_big, y, 1024 + 2 * ascent_big,
                                       y)
                gi.setPen(QPen(Qt.black))
                self.addItem(gi)

                y += th
            else:
                continue

            y_bars = y

            if total_hours_to_do > 0:
                # There's something to draw

                head = QGraphicsSimpleTextItem(_("Started"))
                head.setFont(self.base_font)
                head.setPos(current_x, y)
                self.addItem(head)
                y += head.boundingRect().height()

                y += bar_height
                bars_line.set_start_pos(current_x, y)
                bars_line.finish_bar()

                foot = QGraphicsSimpleTextItem(
                    _("{}h").format(int(total_hours_to_do + 0.5)))
                foot.setFont(self.base_font)
                foot.setPos(current_x, y)
                self.addItem(foot)
                y += foot.boundingRect().height()

                current_x = max(current_x + bars_line.estimate_width(),
                                head.boundingRect().right(),
                                foot.boundingRect().right())

                bar_drawn = True

            if total_hours_to_do_on_unstarted_operations > 0:

                if bars_line_unstarted_operations.estimate_width(
                ) + current_x > 1200:
                    x = 50
                    y += ascent_big
                else:
                    y = y_bars
                    x = current_x + 50

                head = QGraphicsSimpleTextItem(_("Not started yet"))
                head.setFont(self.base_font)
                head.setPos(x, y)
                self.addItem(head)
                y += head.boundingRect().height()

                y += bar_height
                bars_line_unstarted_operations.set_start_pos(x, y)
                bars_line_unstarted_operations.finish_bar()

                foot = QGraphicsSimpleTextItem(
                    _("{}h").format(
                        int(total_hours_to_do_on_unstarted_operations + 0.5)))
                foot.setFont(self.base_font)
                foot.setPos(x, y)
                self.addItem(foot)
                y += foot.boundingRect().height()

                bar_drawn = True

            y += 3 * ascent_big

            r = self.sceneRect()
            self.posts_offsets[opdef.operation_definition_id] =  \
                QRectF(r.x() - 2*ascent_big, y_start - 1.5*ascent_big,
                       r.width() + 4*ascent_big, (y - ascent_big) - (y_start - 1.5*ascent_big) )
            y += ascent_big

        # mainlog.debug("reload...3")
        import functools
        max_width = functools.reduce(lambda acc, po: max(acc, po.width()),
                                     self.posts_offsets.values(), 0)
        map(lambda po: po.setWidth(max_width), self.posts_offsets.values())

        # for r in self.posts_offsets.values():
        #     gi = QGraphicsLineItem(r.x(),r.y(),r.x()+r.width(),r.y())
        #     gi.setPen(QPen(Qt.lightGray))
        #     self.addItem(gi)

        progress.close()