Draft implementation of MultiProgress for progress bars

This commit is contained in:
Pranav Srinivas Kumar
2019-12-17 20:06:50 -06:00
parent 01966b8239
commit 92725d6cb2
7 changed files with 138 additions and 27 deletions

BIN
img/multi_progress.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 185 KiB

View File

@@ -231,6 +231,9 @@ private:
auto remaining = eta > elapsed ? (eta - elapsed) : (elapsed - eta); auto remaining = eta > elapsed ? (eta - elapsed) : (elapsed - eta);
_print_duration(std::cout, remaining); _print_duration(std::cout, remaining);
std::cout << "]"; std::cout << "]";
} else {
if (_show_elapsed_time)
std::cout << "]";
} }
if (_max_postfix_text_length == 0) if (_max_postfix_text_length == 0)

View File

@@ -26,51 +26,62 @@ SOFTWARE.
*/ */
#pragma once #pragma once
#define NOMINMAX #define NOMINMAX
#include <functional>
#include <indicators/progress_bar.hpp> #include <indicators/progress_bar.hpp>
#include <vector> #include <vector>
#include <functional>
namespace indicators { namespace indicators {
template <size_t count> template <size_t count> class MultiProgress {
class MultiProgress {
public: public:
void add_progress_bar(ProgressBar& bar) { void add_progress_bar(ProgressBar &bar) {
_bars.push_back(bar); _bars.push_back(bar);
bar._multi_progress_mode = true; bar._multi_progress_mode = true;
} }
template <size_t index> template <size_t index>
typename std::enable_if<(index < count), void>::type typename std::enable_if<(index < count), void>::type set_progress(float value) {
set_progress(float value) { if (!_bars[index].get().is_completed())
_bars[index].get().set_progress(value); _bars[index].get().set_progress(value);
_print_progress(); _print_progress();
} }
template <size_t index> template <size_t index> typename std::enable_if<(index < count), void>::type tick() {
typename std::enable_if<(index < count), void>::type if (!_bars[index].get().is_completed())
tick() { _bars[index].get().tick();
_bars[index].get().tick();
_print_progress(); _print_progress();
} }
template <size_t index> template <size_t index>
typename std::enable_if<(index < count), bool>::type typename std::enable_if<(index < count), bool>::type is_completed() const {
is_completed() const { return _bars[index].get().is_completed(); } return _bars[index].get().is_completed();
}
private: private:
std::atomic<bool> _started{false};
std::mutex _mutex;
std::vector<std::reference_wrapper<ProgressBar>> _bars; std::vector<std::reference_wrapper<ProgressBar>> _bars;
void _print_progress() { bool _all_completed() {
bool result{true};
for (size_t i = 0; i < count; ++i) for (size_t i = 0; i < count; ++i)
std::cout << "\x1b[A"; result &= _bars[i].get().is_completed();
for (auto& bar: _bars) { return result;
bar.get()._print_progress(); }
void _print_progress() {
std::unique_lock<std::mutex> lock{_mutex};
if (_started)
for (size_t i = 0; i < count; ++i)
std::cout << "\x1b[A";
for (auto &bar : _bars) {
bar.get()._print_progress(true);
std::cout << "\n"; std::cout << "\n";
} }
std::cout << termcolor::reset;
if (!_started)
_started = true;
} }
}; };
} } // namespace indicators

View File

@@ -36,7 +36,6 @@ SOFTWARE.
#include <mutex> #include <mutex>
#include <string> #include <string>
#include <thread> #include <thread>
#include <indicators/multi_progress.hpp>
namespace indicators { namespace indicators {
@@ -146,10 +145,9 @@ private:
std::atomic<bool> _saved_start_time{false}; std::atomic<bool> _saved_start_time{false};
std::chrono::time_point<std::chrono::high_resolution_clock> _start_time_point; std::chrono::time_point<std::chrono::high_resolution_clock> _start_time_point;
std::mutex _mutex; std::mutex _mutex;
Color _foreground_color; Color _foreground_color{indicators::Color::WHITE};
template <size_t count> template <size_t count> friend class MultiProgress;
friend class MultiProgress;
std::atomic<bool> _multi_progress_mode{false}; std::atomic<bool> _multi_progress_mode{false};
std::ostream &_print_duration(std::ostream &os, std::chrono::nanoseconds ns) { std::ostream &_print_duration(std::ostream &os, std::chrono::nanoseconds ns) {
@@ -181,7 +179,13 @@ private:
} }
} }
void _print_progress() { void _print_progress(bool force = false) {
if (_multi_progress_mode && !force) {
if (_progress > 100.0) {
_completed = true;
}
return;
}
std::unique_lock<std::mutex> lock{_mutex}; std::unique_lock<std::mutex> lock{_mutex};
auto now = std::chrono::high_resolution_clock::now(); auto now = std::chrono::high_resolution_clock::now();
auto elapsed = std::chrono::duration_cast<std::chrono::nanoseconds>(now - _start_time_point); auto elapsed = std::chrono::duration_cast<std::chrono::nanoseconds>(now - _start_time_point);
@@ -244,6 +248,9 @@ private:
auto remaining = eta > elapsed ? (eta - elapsed) : (elapsed - eta); auto remaining = eta > elapsed ? (eta - elapsed) : (elapsed - eta);
_print_duration(std::cout, remaining); _print_duration(std::cout, remaining);
std::cout << "]"; std::cout << "]";
} else {
if (_show_elapsed_time)
std::cout << "]";
} }
if (_max_postfix_text_length == 0) if (_max_postfix_text_length == 0)
@@ -253,7 +260,7 @@ private:
if (_progress > 100.0) { if (_progress > 100.0) {
_completed = true; _completed = true;
} }
if (_completed) if (_completed && !force)
std::cout << termcolor::reset << std::endl; std::cout << termcolor::reset << std::endl;
} }
}; };

View File

@@ -207,6 +207,9 @@ private:
auto remaining = eta > elapsed ? (eta - elapsed) : (elapsed - eta); auto remaining = eta > elapsed ? (eta - elapsed) : (elapsed - eta);
_print_duration(std::cout, remaining); _print_duration(std::cout, remaining);
std::cout << "]"; std::cout << "]";
} else {
if (_show_elapsed_time)
std::cout << "]";
} }
if (_max_postfix_text_length == 0) if (_max_postfix_text_length == 0)

View File

@@ -16,3 +16,6 @@ target_link_libraries(progress_spinner PRIVATE indica::indica)
add_executable(time_meter time_meter.cpp) add_executable(time_meter time_meter.cpp)
target_link_libraries(time_meter PRIVATE indica::indica) target_link_libraries(time_meter PRIVATE indica::indica)
add_executable(multi_progress multi_progress.cpp)
target_link_libraries(multi_progress PRIVATE indica::indica)

View File

@@ -0,0 +1,84 @@
#include <indicators/multi_progress.hpp>
int main() {
indicators::ProgressBar bar1;
bar1.set_bar_width(50);
bar1.start_bar_with("[");
bar1.fill_bar_progress_with("");
bar1.lead_bar_progress_with("");
bar1.fill_bar_remainder_with(" ");
bar1.end_bar_with(" ]");
bar1.set_foreground_color(indicators::Color::YELLOW);
bar1.show_elapsed_time();
bar1.show_remaining_time();
bar1.set_prefix_text("Progress Bar #1 ");
indicators::ProgressBar bar2;
bar2.set_bar_width(50);
bar2.start_bar_with("[");
bar2.fill_bar_progress_with("=");
bar2.lead_bar_progress_with(">");
bar2.fill_bar_remainder_with(" ");
bar2.end_bar_with(" ]");
bar2.set_foreground_color(indicators::Color::CYAN);
bar2.show_elapsed_time();
bar2.show_remaining_time();
bar2.set_prefix_text("Progress Bar #2 ");
indicators::ProgressBar bar3;
bar3.set_bar_width(50);
bar3.start_bar_with("[");
bar3.fill_bar_progress_with("#");
bar3.lead_bar_progress_with("#");
bar3.fill_bar_remainder_with(" ");
bar3.end_bar_with(" ]");
bar3.set_foreground_color(indicators::Color::RED);
bar3.show_elapsed_time();
bar3.show_remaining_time();
bar3.set_prefix_text("Progress Bar #3 ");
indicators::MultiProgress<3> bars;
bars.add_progress_bar(bar1);
bars.add_progress_bar(bar2);
bars.add_progress_bar(bar3);
std::cout << "Multiple Progress Bars:\n";
auto job1 = [&bars]() {
while (true) {
bars.tick<0>();
if (bars.is_completed<0>())
break;
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
};
auto job2 = [&bars]() {
while (true) {
bars.tick<1>();
if (bars.is_completed<1>())
break;
std::this_thread::sleep_for(std::chrono::milliseconds(200));
}
};
auto job3 = [&bars]() {
while (true) {
bars.tick<2>();
if (bars.is_completed<2>())
break;
std::this_thread::sleep_for(std::chrono::milliseconds(60));
}
};
std::thread first_job(job1);
std::thread second_job(job2);
std::thread third_job(job3);
first_job.join();
second_job.join();
third_job.join();
return 0;
}