3
\$\begingroup\$

I have a function which writes a report based on technologies selected by the user via QCheckBoxes. Depending on the number of technologies chosen, the QProgressBar will go through set values until the function reaches completion.

For example:

1 tech: 0 -> 99 -> 100
2 tech: 0 -> 50 -> 99 -> 100
3 tech: 0 -> 33 -> 66 -> 99 -> 100
4 tech: 0 -> 25 -> 50 -> 75 -> 99 -> 100

Regardless of the number of technologies chosen, once the last one has been processed, the progressbar would be set to 99 to do some textual clean up before reaching 100.

At the moment, I have two such technologies (PV and wind turbine) where I manually set the progress values.

How could I achieve the above in a more systematic fashion?


My current code:

def report(self):
    # Define progress bar
    progressMessageBar = iface.messageBar().createMessage(str('Generating report...'))
    progress = QProgressBar()
    progress.setMaximum(100)
    progress.setAlignment(Qt.AlignLeft | Qt.AlignVCenter)
    progressMessageBar.layout().addWidget(progress)
    iface.messageBar().pushWidget(progressMessageBar, iface.messageBar().INFO)
    progress.setValue(0)
    sleep(5)

    # Define Report text browser
    display_report = self.report_dockwidget.report_textBrowser
    # Technology checkboxes
    pv_checkBox = self.pv_generation_dockwidget.returnResults_Checkbox
    wind_checkBox = self.wind_generation_dockwidget.returnResults_Checkbox

    # For PV
    if pv_checkBox.isChecked():
        # Do some processing
        progress.setValue(50)
        if not wind_checkBox.isChecked():
            progress.setValue(99)
        sleep(5)

    # For Wind
    if wind_checkBox.isChecked():
        # Do some processing
        if not pv_checkBox.isChecked():
            progress.setValue(50)
        else:
            progress.setValue(99)
        sleep(5)

    # Do some cleanup
    progressMessageBar.setText('Complete')
    progress.setValue(100)
    sleep(1)

    # Show report
    self.report_dockwidget.show()
\$\endgroup\$
2
\$\begingroup\$

One idea would be to gather all your techs in a queue and iterate over that, updating the progress as you go.

Since my Python is rather Rust-y (I'm sorry for that pun), here's some pseudocode:

# Setup progress bar et cetera
# Gather techs in a queue
techs = Queue()
if pv_checkBox.isChecked():
    techs.add(pv_task)
if wind_checkBox.isChecked():
    techs.add(wind_task)

# Do the work
total_tasks = techs.count()
done_tasks = 0
while not techs.isEmpty():
    task = techs.take()
    task.doWork()
    done_tasks += 1
    new_progress = max(done_tasks / total_tasks * 100, 99)
    progress.setValue(newProgress)

# Progress is now 99
doFinalStuff()
progress.setValue(100)

This will do all the tasks in a FIFO fashion and set the progress as you wanted with the last step always being 99.

Now, it would be a good idea to gather all checkboxes in a group or layout and, by getting and filtering all child elements, add the techs via loop as well.

\$\endgroup\$
  • \$\begingroup\$ Thanks for your answer! Interesting, never used Queue() before so will test this at some point and report back :) \$\endgroup\$ – Joseph Dec 5 '17 at 13:58
0
\$\begingroup\$

Thanks to @PhilKiener's answer, I translated his pseudocode with the relevant methods for Python 2.7 which works well:

# Setup progress bar et cetera
# Gather techs in a queue
techs = Queue.Queue()
if pv_checkBox.isChecked():
    techs.put(pv_task)
if wind_checkBox.isChecked():
    techs.put(wind_task)

# Do the work
total_tasks = len(techs.queue)
done_tasks = 0
while not techs.empty():
    task = techs.get()
    done_tasks += 1
    new_progress = int(ceil(float(done_tasks) / float(total_tasks) * 99))
    progress.setValue(new_progress)
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.