// -*- c-basic-offset: 4 -*- /** @file ProgressDisplayOld.h * * @author Pablo d'Angelo * * $Id$ * * This is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this software; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include "ProgressDisplayOld.h" #ifdef WIN32 #define snprintf _snprintf #endif namespace AppBase { ProgressTask::ProgressTask(std::string shortMessage, std::string message, double subStepProgress, double progress) : shortMessage(shortMessage), message(message), subStepProgress(subStepProgress), progress(progress), measureProgress(true), last_displayed_progress(-1) { } ProgressTask::ProgressTask(std::string shortMessage, std::string message) : shortMessage(shortMessage), message(message), subStepProgress(0), progress(0), measureProgress(false), last_displayed_progress(-1) { } MultiProgressDisplay::MultiProgressDisplay(double minPrintStep) : m_minProgressStep(minPrintStep) { } void MultiProgressDisplay::pushTask(const ProgressTask & task) { tasks.push_back(task); taskAdded(); updateProgressDisplay(); } /** remove a task from the progress display */ void MultiProgressDisplay::popTask() { taskRemove(); if (!tasks.back().measureProgress && tasks.size()>1) { tasks[tasks.size()-2].progress += tasks[tasks.size()-2].subStepProgress; } tasks.pop_back(); updateProgressDisplay(); } /** change the message text of the current task */ void MultiProgressDisplay::setShortMessage(const std::string & msg) { tasks.back().shortMessage = msg; updateProgressDisplay(); } /** change the message text of the current task */ void MultiProgressDisplay::setMessage(const std::string & msg) { tasks.back().message = msg; updateProgressDisplay(); } /** set progress (affects this task and all tasks above it) */ void MultiProgressDisplay::setProgress(double progress) { propagateProgress(progress); double displayStep = tasks.back().progress - tasks.back().last_displayed_progress; if (displayStep > m_minProgressStep) { updateProgressDisplay(); tasks.back().last_displayed_progress = tasks.back().progress; } } /** increase progress by a substep. */ void MultiProgressDisplay::increase() { // substep progress. setProgress(tasks.back().progress + tasks.back().subStepProgress); } void MultiProgressDisplay::propagateProgress(double progress) { std::vector::reverse_iterator it = tasks.rbegin(); double diff = progress - it->progress; it->progress = progress; it++; while (it != tasks.rend()) { // scale previous change diff *= it->subStepProgress; // propagate to next level it->progress += diff; ++it; } } /// MultiProgressDisplayAdaptor::MultiProgressDisplayAdaptor(ProgressDisplay& myProgressDisplay) : MultiProgressDisplay(0.0), o_progressDisplay(myProgressDisplay) {}; /// MultiProgressDisplay* MultiProgressDisplayAdaptor::newMultiProgressDisplay(ProgressDisplay* myProgressDisplay) { if(myProgressDisplay != NULL) return new MultiProgressDisplayAdaptor(*myProgressDisplay); else return new DummyMultiProgressDisplay(); } /// void MultiProgressDisplayAdaptor::taskAdded() { assert(tasks.size() > 0); if (tasks.size() > 1) { o_progressDisplay.setParentProgressOfNewSubtasks(( ++(tasks.rbegin()) )->subStepProgress, true); } o_progressDisplay.startSubtask(tasks.back().getMessage(), 1.0); }; /// void MultiProgressDisplayAdaptor::taskRemove() { o_progressDisplay.finishSubtask(); }; /// void MultiProgressDisplayAdaptor::updateProgressDisplay() { if(tasks.empty()) { DEBUG_INFO("There are no tasks."); return; } if(tasks.back().getMessage().length() == 0) o_progressDisplay.setSubtaskMessage(tasks.back().getShortMessage()); else if(tasks.back().getShortMessage().length() == 0) o_progressDisplay.setSubtaskMessage(tasks.back().getMessage()); else o_progressDisplay.setSubtaskMessage(tasks.back().getShortMessage() + " ("+tasks.back().getMessage()+")"); o_progressDisplay.updateSubtaskProgress(tasks.back().getProgress()); } StreamMultiProgressDisplay::StreamMultiProgressDisplay(std::ostream& o, double minPrintStep) : MultiProgressDisplay(minPrintStep), m_stream(o), m_printedLines(0), m_whizz("-\\|/"), m_whizzCount(0) { } void StreamMultiProgressDisplay::updateProgressDisplay() { int lines = m_printedLines; // step back the line printed before. if (lines !=0) { m_stream << "\033[" << m_printedLines << "A" << "\r"; } m_printedLines = 0; // build the message: for (std::vector::iterator it = tasks.begin(); it != tasks.end(); ++it) { m_printedLines++; char tmp[81]; tmp[80]=0; if (it->measureProgress) { snprintf(tmp,80,"%20s: %-50s : %3.0f %%", it->getShortMessage().c_str(), it->getMessage().c_str(), 100 * it->getProgress()); } else if (! it->measureProgress && it+1 == tasks.end()) { m_whizzCount = (++m_whizzCount) % (int)m_whizz.size(); snprintf(tmp,80,"%20s: %-50s : %c ", it->getShortMessage().c_str(), it->getMessage().c_str(), m_whizz[m_whizzCount]); } else { snprintf(tmp,80,"%20s: %-50s : - ", it->getShortMessage().c_str(), it->getMessage().c_str()); } m_stream << tmp << std::endl; } // print empty lines.. while (m_printedLines < lines) { m_stream << " " << std::endl; m_printedLines++; } } } //namespace