namespace APT {
namespace Progress {
+PackageManager::PackageManager() : d(NULL), percentage(0.0), last_reported_progress(-1) {};
+PackageManager::~PackageManager() {};
/* Return a APT::Progress::PackageManager based on the global
* apt configuration (i.e. APT::Status-Fd and APT::Status-deb822-Fd)
(*I)->HandleSIGWINCH(signum);
}
-int PackageManagerFancy::GetNumberTerminalRows()
+PackageManagerFancy::TermSize
+PackageManagerFancy::GetTerminalSize()
{
struct winsize win;
+ PackageManagerFancy::TermSize s = { 0, 0 };
+
// FIXME: get from "child_pty" instead?
if(ioctl(STDOUT_FILENO, TIOCGWINSZ, (char *)&win) != 0)
- return -1;
+ return s;
if(_config->FindB("Debug::InstallProgress::Fancy", false) == true)
- std::cerr << "GetNumberTerminalRows: " << win.ws_row << std::endl;
-
- return win.ws_row;
+ std::cerr << "GetTerminalSize: " << win.ws_row << " x " << win.ws_col << std::endl;
+
+ s.rows = win.ws_row;
+ s.columns = win.ws_col;
+ return s;
}
void PackageManagerFancy::SetupTerminalScrollArea(int nr_rows)
if(_config->FindB("Debug::InstallProgress::Fancy", false) == true)
std::cerr << "SetupTerminalScrollArea: " << nr_rows << std::endl;
+ if (unlikely(nr_rows <= 1))
+ return;
+
// scroll down a bit to avoid visual glitch when the screen
// area shrinks by one row
std::cout << "\n";
// setup tty size to ensure xterm/linux console are working properly too
// see bug #731738
struct winsize win;
- ioctl(child_pty, TIOCGWINSZ, (char *)&win);
- win.ws_row = nr_rows - 1;
- ioctl(child_pty, TIOCSWINSZ, (char *)&win);
+ if (ioctl(child_pty, TIOCGWINSZ, (char *)&win) != -1)
+ {
+ win.ws_row = nr_rows - 1;
+ ioctl(child_pty, TIOCSWINSZ, (char *)&win);
+ }
}
void PackageManagerFancy::HandleSIGWINCH(int)
{
- int nr_terminal_rows = GetNumberTerminalRows();
+ int const nr_terminal_rows = GetTerminalSize().rows;
SetupTerminalScrollArea(nr_terminal_rows);
+ DrawStatusLine();
}
void PackageManagerFancy::Start(int a_child_pty)
{
child_pty = a_child_pty;
- int nr_terminal_rows = GetNumberTerminalRows();
- if (nr_terminal_rows > 0)
- SetupTerminalScrollArea(nr_terminal_rows);
+ int const nr_terminal_rows = GetTerminalSize().rows;
+ SetupTerminalScrollArea(nr_terminal_rows);
}
void PackageManagerFancy::Stop()
{
- int nr_terminal_rows = GetNumberTerminalRows();
+ int const nr_terminal_rows = GetTerminalSize().rows;
if (nr_terminal_rows > 0)
{
SetupTerminalScrollArea(nr_terminal_rows + 1);
child_pty = -1;
}
+std::string
+PackageManagerFancy::GetTextProgressStr(float Percent, int OutputSize)
+{
+ std::string output;
+ int i;
+
+ // should we raise a exception here instead?
+ if (Percent < 0.0 || Percent > 1.0 || OutputSize < 3)
+ return output;
+
+ int BarSize = OutputSize - 2; // bar without the leading "[" and trailing "]"
+ output += "[";
+ for(i=0; i < BarSize*Percent; i++)
+ output += "#";
+ for (/*nothing*/; i < BarSize; i++)
+ output += ".";
+ output += "]";
+ return output;
+}
+
bool PackageManagerFancy::StatusChanged(std::string PackageName,
unsigned int StepsDone,
unsigned int TotalSteps,
HumanReadableAction))
return false;
- int row = GetNumberTerminalRows();
+ return DrawStatusLine();
+}
+bool PackageManagerFancy::DrawStatusLine()
+{
+ PackageManagerFancy::TermSize const size = GetTerminalSize();
+ if (unlikely(size.rows < 1 || size.columns < 1))
+ return false;
static std::string save_cursor = "\033[s";
static std::string restore_cursor = "\033[u";
std::cout << save_cursor
// move cursor position to last row
- << "\033[" << row << ";0f"
+ << "\033[" << size.rows << ";0f"
<< set_bg_color
<< set_fg_color
<< progress_str
- << restore_cursor
<< restore_bg
<< restore_fg;
std::flush(std::cout);
+
+ // draw text progress bar
+ if (_config->FindB("Dpkg::Progress-Fancy::Progress-Bar", true))
+ {
+ int padding = 4;
+ float progressbar_size = size.columns - padding - progress_str.size();
+ float current_percent = percentage / 100.0;
+ std::cout << " "
+ << GetTextProgressStr(current_percent, progressbar_size)
+ << " ";
+ std::flush(std::cout);
+ }
+
+ // restore
+ std::cout << restore_cursor;
+ std::flush(std::cout);
+
last_reported_progress = percentage;
return true;