<commit_before>#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "order.h"
#include "Item.h"
#include <vector>
#include <sstream>
#include <string>

using namespace std;

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    ui->scroll_layout->setAlignment(Qt::AlignTop);
    new_order = new Order();
    connect(new_order, SIGNAL(itemsChanged()), this, SLOT(update_list()));
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_hamburger_button_clicked()
{
    // Add the hamburger item to the scroll box.
    Item *hamburger_item = new Item();
    hamburger_item->setId(new_order->getItemCount() + 1);
    hamburger_item->setItemsLeft(99);
    hamburger_item->setPrice(3.90);
    hamburger_item->setName(string("Hamburger"));

    new_order->addItem(hamburger_item);

    // Create the topping buttons.
    button_factory("Bacon", 1);
    button_factory("Cheese",2);
    button_factory("Lettuce",3);
    button_factory("Tomatoes",4);
    button_factory("Pickles",5);
    button_factory("Onions",6);
    button_factory("Ketchup",7);
    button_factory("Mustard",8);
    button_factory("Barbeque",9);
    button_factory("Mayo",10);
    button_factory("Small",11);
    button_factory("Medium",12);
    button_factory("Large",13);

    /*How are we going to handle different sizes and extras? For example,
      each size has a different price, and some of the toppings should add
      to the price as well (bacon, cheese, etc.)
      */

    // This is what changes "pages".
    ui->stackedWidget->setCurrentIndex(2);
}

void MainWindow::on_hotdog_button_clicked()
{

    // Add the hotdog item to the scroll box.
    Item *hotdog_item = new Item();
    hotdog_item->setId(new_order->getItemCount() + 1);
    hotdog_item->setItemsLeft(99);
    hotdog_item->setPrice(3.90);
    hotdog_item->setName(string("Hotdog"));

    new_order->addItem(hotdog_item);

    // Create the topping buttons.
    button_factory("Chili", 1);
    button_factory("Cheese",2);
    button_factory("Onions",3);
    button_factory("Sauerkraut",4);
    button_factory("Relish",5);;
    button_factory("Ketchup",6);
    button_factory("Mustard",7);
    button_factory("Small",8);
    button_factory("Medium",9);
    button_factory("Large",10);

    /*How are we going to handle different sizes and extras? For example,
      each size has a different price, and some of the toppings should add
      to the price as well (bacon, cheese, etc.)
      */

    ui->stackedWidget->setCurrentIndex(2);
}

void MainWindow::on_chick_sand_button_clicked()
{
    // Add the chicken sandwich item to the scroll box.
    Item *chick_sand_item = new Item();
    chick_sand_item->setId(new_order->getItemCount() + 1);
    chick_sand_item->setItemsLeft(99);
    chick_sand_item->setPrice(2.25);
    chick_sand_item->setName(string("Chicken Sandwich"));

    new_order->addItem(chick_sand_item);

    // Create the topping buttons.
    button_factory("Bacon", 1);
    button_factory("Cheese",2);
    button_factory("Lettuce",3);
    button_factory("Tomatoes",4);
    button_factory("Pickles",5);;
    button_factory("Mayo",6);
    button_factory("Barbeque",7);
    button_factory("Small",8);
    button_factory("Medium",9);
    button_factory("Large",10);

    /*How are we going to handle different sizes and extras? For example,
      each size has a different price, and some of the toppings should add
      to the price as well (bacon, cheese, etc.)
      */

    ui->stackedWidget->setCurrentIndex(2);
}

void MainWindow::on_chick_nug_button_clicked()
{

    // Add the chicken nugget item to the scroll box.
    Item *chick_nug_item = new Item();
    chick_nug_item->setId(new_order->getItemCount() + 1);
    chick_nug_item->setItemsLeft(99);
    chick_nug_item->setPrice(1.99);
    chick_nug_item->setName(string("Chicken Nuggets"));

    new_order->addItem(chick_nug_item);

    // Create the topping buttons.
    button_factory("Sweet & Sour Sauce", 1);
    button_factory("Honey Mustard",2);
    button_factory("Onions",3);
    button_factory("Ketchup",4);
    button_factory("Mustard",5);
    button_factory("Small",6);
    button_factory("Medium",7);
    button_factory("Large",8);

    ui->stackedWidget->setCurrentIndex(2);
}

void MainWindow::on_salad_button_clicked()
{
    /// Add the salad item to the scroll box.
    Item *salad_item = new Item();
    salad_item->setId(new_order->getItemCount() + 1);
    salad_item->setItemsLeft(99);
    salad_item->setPrice(3.99);
    salad_item->setName(string("Salad"));

    new_order->addItem(salad_item);

    // Create the topping buttons.
    button_factory("Tomatoes", 1);
    button_factory("Croutons",2);
    button_factory("Almonds",3);
    button_factory("Walnuts",4);
    button_factory("Bacon",5);
    button_factory("Cheese", 6);
    button_factory("Onions",7);
    button_factory("Cucumbers",8);
    button_factory("Ranch",9);
    button_factory("Italian",10);
    button_factory("Caesar", 11);
    button_factory("Honey Mustard",12);
    button_factory("Vinaigrette",13);
    button_factory("Olive Oil",14);
    button_factory("Small",15);
    button_factory("Medium",16);
    button_factory("Large",17);

    ui->stackedWidget->setCurrentIndex(2);
}

void MainWindow::on_fries_button_clicked()
{
    // Add the fries item to the scroll box.
    Item *fries_item = new Item();
    fries_item->setId(new_order->getItemCount() + 1);
    fries_item->setItemsLeft(99);
    fries_item->setPrice(1.99);
    fries_item->setName(string("Fries"));

    new_order->addItem(fries_item);

    // Create the topping buttons.
    button_factory("Chili", 1);
    button_factory("Cheese",2);
    button_factory("Bacon",3);
    button_factory("Ketchup",4);
    button_factory("Mustard",5);
    button_factory("Small",6);
    button_factory("Medium",7);
    button_factory("Large",8);

    ui->stackedWidget->setCurrentIndex(2);
}

void MainWindow::on_soda_button_clicked()
{
    // Add the soda item to the scroll box.
    Item *soda_item = new Item();
    soda_item->setId(new_order->getItemCount() + 1);
    soda_item->setItemsLeft(99);
    soda_item->setPrice(1.25);
    soda_item->setName(string("Soda"));

    new_order->addItem(soda_item);

    // Create the topping buttons.
    button_factory("Cherry Soda", 1);
    button_factory("Cola",2);
    button_factory("Orange Soda",3);
    button_factory("Lemon-Lime Soda",4);
    button_factory("Grape",5);
    button_factory("Root Beer",6);
    button_factory("Ginger Ale",7);
    button_factory("Small",8);
    button_factory("Medium",9);
    button_factory("Large",10);

    ui->stackedWidget->setCurrentIndex(2);
}

void MainWindow::on_tea_button_clicked()
{
    // Add the tea item to the scroll box.
    Item *tea_item = new Item();
    tea_item->setId(new_order->getItemCount() + 1);
    tea_item->setItemsLeft(99);
    tea_item->setPrice(1.00);
    tea_item->setName(string("Tea"));

    new_order->addItem(tea_item);

    // Create the topping buttons.
    button_factory("Green Tea", 1);
    button_factory("Peach Iced Tea",2);
    button_factory("Strawberry Iced Tea",3);
    button_factory("Sweet Tea",4);
    button_factory("Unsweet Tea",5);
    button_factory("Lemon Tea",6);
    button_factory("Small",7);
    button_factory("Medium",8);
    button_factory("Large",9);

    ui->stackedWidget->setCurrentIndex(2);
}

void MainWindow::on_milk_shake_button_clicked()
{
    // Add the milkshake item to the scroll box.
    Item *milkshake_item = new Item();
    milkshake_item->setId(new_order->getItemCount() + 1);
    milkshake_item->setItemsLeft(99);
    milkshake_item->setPrice(3.99);
    milkshake_item->setName(string("Milkshake"));

    new_order->addItem(milkshake_item);

    // Create the topping buttons.
    button_factory("Chocolate", 1);
    button_factory("Vanilla",2);
    button_factory("Strawberry",3);
    button_factory("Cherry",4);
    button_factory("Whipped Cream",5);
    button_factory("Sprinkles",6);
    button_factory("Small",7);
    button_factory("Medium",8);
    button_factory("Large",9);
    ui->stackedWidget->setCurrentIndex(2);
}

void MainWindow::on_admin_button_clicked()
{
    ui->stackedWidget->setCurrentIndex(1);
}

void MainWindow::on_checkout_button_clicked()
{
    // This is where we will add the confirmation page.
    // Then print out the receipt.
}

void MainWindow::on_admin_button_2_clicked()
{
    ui->stackedWidget->setCurrentIndex(0);
}

void MainWindow::on_done_button_clicked()
{
    ui->stackedWidget->setCurrentIndex(0);

    clear_items(ui->gridLayout);
    clear_items(ui->gridLayout2);
    clear_items(ui->gridLayout3);
    clear_items(ui->gridLayout4);
    clear_items(ui->gridLayout5);
    clear_items(ui->gridLayout6);
    clear_items(ui->gridLayout7);
    clear_items(ui->gridLayout8);
    clear_items(ui->gridLayout9);
    clear_items(ui->gridLayout10);
    clear_items(ui->gridLayout11);
    clear_items(ui->gridLayout12);
    clear_items(ui->gridLayout13);
    clear_items(ui->gridLayout14);
    clear_items(ui->gridLayout15);
}

void MainWindow::clear_items(QLayout *layout)
{
    QLayoutItem *item;
    while((item = layout->takeAt(0)))
    {
        if (item->widget())
        {
            delete item->widget();
        }
    }
}

void MainWindow::set_button_style(QPushButton *button)
{
    button->setStyleSheet(
       "background-color: rgb(87, 137, 183);"
        "max-width: 150px;"
        "height: 150px;"
        "selection-color: rgb(255, 170, 127);"
        "font: 16pt 'MS Shell Dlg 2';"
        "color: rgb(255, 255, 255);"
        "selection-background-color: rgb(66, 111, 153);"
    );
    button->setCheckable(true);
}

void MainWindow::button_factory(string name, int position) {
    QString topping_name = QString::fromStdString(name);
    QPushButton *topping_button = new QPushButton(topping_name);
    set_button_style(topping_button);

    switch(position) {
    case 1:
        ui->gridLayout->addWidget(topping_button);
        break;
    case 2:
        ui->gridLayout2->addWidget(topping_button);
        break;
    case 3:
        ui->gridLayout3->addWidget(topping_button);
        break;
    case 4:
        ui->gridLayout4->addWidget(topping_button);
        break;
    case 5:
        ui->gridLayout5->addWidget(topping_button);
        break;
    case 6:
        ui->gridLayout6->addWidget(topping_button);
        break;
    case 7:
        ui->gridLayout7->addWidget(topping_button);
        break;
    case 8:
        ui->gridLayout8->addWidget(topping_button);
        break;
    case 9:
        ui->gridLayout9->addWidget(topping_button);
        break;
    case 10:
        ui->gridLayout10->addWidget(topping_button);
        break;
    case 11:
        ui->gridLayout11->addWidget(topping_button);
        break;
    case 12:
        ui->gridLayout12->addWidget(topping_button);
        break;
    case 13:
        ui->gridLayout13->addWidget(topping_button);
        break;
    case 14:
        ui->gridLayout14->addWidget(topping_button);
        break;
    case 15:
        ui->gridLayout15->addWidget(topping_button);
        break;
    }
}

void MainWindow::update_list() {
    clear_items(ui->scroll_layout);

    vector<Item*> *items = new_order->itemArray;
    vector<Item*>::iterator it;
    int i = 0;
    for (it = items->begin(); it != items->end(); it++, i++) {
        std::ostringstream strs;
        strs << (*it)->getPrice();
        string str_price = strs.str();

        if (str_price.length() == 3)
            str_price += "0";
        else if (str_price.length() == 2)
            str_price = "0" + str_price;
        str_price = "$" + str_price;

        QPushButton *remove_button = new QPushButton("X");
        remove_button->setStyleSheet("color:white;background-color:red;max-width: 20px");
        QLabel *item = new QLabel(QString::fromStdString((*it)->getName()));
        QLabel *price = new QLabel(QString::fromStdString(str_price));
        QHBoxLayout *item_line = new QHBoxLayout();
        item_line->addWidget(remove_button);
        item_line->addWidget(item);
        item_line->addWidget(price);
        ui->scroll_layout->addLayout(item_line);

        // Working on remove button.
        //int id = (*it)->getId();
        //connect(remove_button, SIGNAL(clicked(bool)), new_order, SLOT(removeItem(int));
    }
}
<commit_msg>Fixed soda and tea buttons<commit_after>#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "order.h"
#include "Item.h"
#include <vector>
#include <sstream>
#include <string>

using namespace std;

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    ui->scroll_layout->setAlignment(Qt::AlignTop);
    new_order = new Order();
    connect(new_order, SIGNAL(itemsChanged()), this, SLOT(update_list()));
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_hamburger_button_clicked()
{
    // Add the hamburger item to the scroll box.
    Item *hamburger_item = new Item();
    hamburger_item->setId(new_order->getItemCount() + 1);
    hamburger_item->setItemsLeft(99);
    hamburger_item->setPrice(3.90);
    hamburger_item->setName(string("Hamburger"));

    new_order->addItem(hamburger_item);

    // Create the topping buttons.
    button_factory("Bacon", 1);
    button_factory("Cheese",2);
    button_factory("Lettuce",3);
    button_factory("Tomatoes",4);
    button_factory("Pickles",5);
    button_factory("Onions",6);
    button_factory("Ketchup",7);
    button_factory("Mustard",8);
    button_factory("Barbeque",9);
    button_factory("Mayo",10);
    button_factory("Small",11);
    button_factory("Medium",12);
    button_factory("Large",13);

    /*How are we going to handle different sizes and extras? For example,
      each size has a different price, and some of the toppings should add
      to the price as well (bacon, cheese, etc.)
      */

    // This is what changes "pages".
    ui->stackedWidget->setCurrentIndex(2);
}

void MainWindow::on_hotdog_button_clicked()
{

    // Add the hotdog item to the scroll box.
    Item *hotdog_item = new Item();
    hotdog_item->setId(new_order->getItemCount() + 1);
    hotdog_item->setItemsLeft(99);
    hotdog_item->setPrice(3.90);
    hotdog_item->setName(string("Hotdog"));

    new_order->addItem(hotdog_item);

    // Create the topping buttons.
    button_factory("Chili", 1);
    button_factory("Cheese",2);
    button_factory("Onions",3);
    button_factory("Sauerkraut",4);
    button_factory("Relish",5);;
    button_factory("Ketchup",6);
    button_factory("Mustard",7);
    button_factory("Small",8);
    button_factory("Medium",9);
    button_factory("Large",10);

    /*How are we going to handle different sizes and extras? For example,
      each size has a different price, and some of the toppings should add
      to the price as well (bacon, cheese, etc.)
      */

    ui->stackedWidget->setCurrentIndex(2);
}

void MainWindow::on_chick_sand_button_clicked()
{
    // Add the chicken sandwich item to the scroll box.
    Item *chick_sand_item = new Item();
    chick_sand_item->setId(new_order->getItemCount() + 1);
    chick_sand_item->setItemsLeft(99);
    chick_sand_item->setPrice(2.25);
    chick_sand_item->setName(string("Chicken Sandwich"));

    new_order->addItem(chick_sand_item);

    // Create the topping buttons.
    button_factory("Bacon", 1);
    button_factory("Cheese",2);
    button_factory("Lettuce",3);
    button_factory("Tomatoes",4);
    button_factory("Pickles",5);;
    button_factory("Mayo",6);
    button_factory("Barbeque",7);
    button_factory("Small",8);
    button_factory("Medium",9);
    button_factory("Large",10);

    /*How are we going to handle different sizes and extras? For example,
      each size has a different price, and some of the toppings should add
      to the price as well (bacon, cheese, etc.)
      */

    ui->stackedWidget->setCurrentIndex(2);
}

void MainWindow::on_chick_nug_button_clicked()
{

    // Add the chicken nugget item to the scroll box.
    Item *chick_nug_item = new Item();
    chick_nug_item->setId(new_order->getItemCount() + 1);
    chick_nug_item->setItemsLeft(99);
    chick_nug_item->setPrice(1.99);
    chick_nug_item->setName(string("Chicken Nuggets"));

    new_order->addItem(chick_nug_item);

    // Create the topping buttons.
    button_factory("Sweet & Sour Sauce", 1);
    button_factory("Honey Mustard",2);
    button_factory("Onions",3);
    button_factory("Ketchup",4);
    button_factory("Mustard",5);
    button_factory("Small",6);
    button_factory("Medium",7);
    button_factory("Large",8);

    ui->stackedWidget->setCurrentIndex(2);
}

void MainWindow::on_salad_button_clicked()
{
    /// Add the salad item to the scroll box.
    Item *salad_item = new Item();
    salad_item->setId(new_order->getItemCount() + 1);
    salad_item->setItemsLeft(99);
    salad_item->setPrice(3.99);
    salad_item->setName(string("Salad"));

    new_order->addItem(salad_item);

    // Create the topping buttons.
    button_factory("Tomatoes", 1);
    button_factory("Croutons",2);
    button_factory("Almonds",3);
    button_factory("Walnuts",4);
    button_factory("Bacon",5);
    button_factory("Cheese", 6);
    button_factory("Onions",7);
    button_factory("Cucumbers",8);
    button_factory("Ranch",9);
    button_factory("Italian",10);
    button_factory("Caesar", 11);
    button_factory("Honey Mustard",12);
    button_factory("Vinaigrette",13);
    button_factory("Olive Oil",14);
    button_factory("Small",15);
    button_factory("Medium",16);
    button_factory("Large",17);

    ui->stackedWidget->setCurrentIndex(2);
}

void MainWindow::on_fries_button_clicked()
{
    // Add the fries item to the scroll box.
    Item *fries_item = new Item();
    fries_item->setId(new_order->getItemCount() + 1);
    fries_item->setItemsLeft(99);
    fries_item->setPrice(1.99);
    fries_item->setName(string("Fries"));

    new_order->addItem(fries_item);

    // Create the topping buttons.
    button_factory("Chili", 1);
    button_factory("Cheese",2);
    button_factory("Bacon",3);
    button_factory("Ketchup",4);
    button_factory("Mustard",5);
    button_factory("Small",6);
    button_factory("Medium",7);
    button_factory("Large",8);

    ui->stackedWidget->setCurrentIndex(2);
}

void MainWindow::on_soda_button_clicked()
{
    // Add the soda item to the scroll box.
    Item *soda_item = new Item();
    soda_item->setId(new_order->getItemCount() + 1);
    soda_item->setItemsLeft(99);
    soda_item->setPrice(1.25);
    soda_item->setName(string("Soda"));

    new_order->addItem(soda_item);

    // Create the topping buttons.
    button_factory("Cherry Soda", 1);
    button_factory("Cola",2);
    button_factory("Orange Soda",3);
    button_factory("Lemon-Lime",4);
    button_factory("Grape",5);
    button_factory("Root Beer",6);
    button_factory("Ginger Ale",7);
    button_factory("Small",8);
    button_factory("Medium",9);
    button_factory("Large",10);

    ui->stackedWidget->setCurrentIndex(2);
}

void MainWindow::on_tea_button_clicked()
{
    // Add the tea item to the scroll box.
    Item *tea_item = new Item();
    tea_item->setId(new_order->getItemCount() + 1);
    tea_item->setItemsLeft(99);
    tea_item->setPrice(1.00);
    tea_item->setName(string("Tea"));

    new_order->addItem(tea_item);

    // Create the topping buttons.
    button_factory("Green Tea", 1);
    button_factory("Peach Tea",2);
    button_factory("Strawberry",3);
    button_factory("Sweet Tea",4);
    button_factory("Unsweet Tea",5);
    button_factory("Lemon Tea",6);
    button_factory("Small",7);
    button_factory("Medium",8);
    button_factory("Large",9);

    ui->stackedWidget->setCurrentIndex(2);
}

void MainWindow::on_milk_shake_button_clicked()
{
    // Add the milkshake item to the scroll box.
    Item *milkshake_item = new Item();
    milkshake_item->setId(new_order->getItemCount() + 1);
    milkshake_item->setItemsLeft(99);
    milkshake_item->setPrice(3.99);
    milkshake_item->setName(string("Milkshake"));

    new_order->addItem(milkshake_item);

    // Create the topping buttons.
    button_factory("Chocolate", 1);
    button_factory("Vanilla",2);
    button_factory("Strawberry",3);
    button_factory("Cherry",4);
    button_factory("Whipped Cream",5);
    button_factory("Sprinkles",6);
    button_factory("Small",7);
    button_factory("Medium",8);
    button_factory("Large",9);
    ui->stackedWidget->setCurrentIndex(2);
}

void MainWindow::on_admin_button_clicked()
{
    ui->stackedWidget->setCurrentIndex(1);
}

void MainWindow::on_checkout_button_clicked()
{
    // This is where we will add the confirmation page.
    // Then print out the receipt.
}

void MainWindow::on_admin_button_2_clicked()
{
    ui->stackedWidget->setCurrentIndex(0);
}

void MainWindow::on_done_button_clicked()
{
    ui->stackedWidget->setCurrentIndex(0);

    clear_items(ui->gridLayout);
    clear_items(ui->gridLayout2);
    clear_items(ui->gridLayout3);
    clear_items(ui->gridLayout4);
    clear_items(ui->gridLayout5);
    clear_items(ui->gridLayout6);
    clear_items(ui->gridLayout7);
    clear_items(ui->gridLayout8);
    clear_items(ui->gridLayout9);
    clear_items(ui->gridLayout10);
    clear_items(ui->gridLayout11);
    clear_items(ui->gridLayout12);
    clear_items(ui->gridLayout13);
    clear_items(ui->gridLayout14);
    clear_items(ui->gridLayout15);
}

void MainWindow::clear_items(QLayout *layout)
{
    QLayoutItem *item;
    while((item = layout->takeAt(0)))
    {
        if (item->widget())
        {
            delete item->widget();
        }
    }
}

void MainWindow::set_button_style(QPushButton *button)
{
    button->setStyleSheet(
       "background-color: rgb(87, 137, 183);"
        "max-width: 150px;"
        "height: 150px;"
        "selection-color: rgb(255, 170, 127);"
        "font: 16pt 'MS Shell Dlg 2';"
        "color: rgb(255, 255, 255);"
        "selection-background-color: rgb(66, 111, 153);"
    );
    button->setCheckable(true);
}

void MainWindow::button_factory(string name, int position) {
    QString topping_name = QString::fromStdString(name);
    QPushButton *topping_button = new QPushButton(topping_name);
    set_button_style(topping_button);

    switch(position) {
    case 1:
        ui->gridLayout->addWidget(topping_button);
        break;
    case 2:
        ui->gridLayout2->addWidget(topping_button);
        break;
    case 3:
        ui->gridLayout3->addWidget(topping_button);
        break;
    case 4:
        ui->gridLayout4->addWidget(topping_button);
        break;
    case 5:
        ui->gridLayout5->addWidget(topping_button);
        break;
    case 6:
        ui->gridLayout6->addWidget(topping_button);
        break;
    case 7:
        ui->gridLayout7->addWidget(topping_button);
        break;
    case 8:
        ui->gridLayout8->addWidget(topping_button);
        break;
    case 9:
        ui->gridLayout9->addWidget(topping_button);
        break;
    case 10:
        ui->gridLayout10->addWidget(topping_button);
        break;
    case 11:
        ui->gridLayout11->addWidget(topping_button);
        break;
    case 12:
        ui->gridLayout12->addWidget(topping_button);
        break;
    case 13:
        ui->gridLayout13->addWidget(topping_button);
        break;
    case 14:
        ui->gridLayout14->addWidget(topping_button);
        break;
    case 15:
        ui->gridLayout15->addWidget(topping_button);
        break;
    }
}

void MainWindow::update_list() {
    clear_items(ui->scroll_layout);

    vector<Item*> *items = new_order->itemArray;
    vector<Item*>::iterator it;
    int i = 0;
    for (it = items->begin(); it != items->end(); it++, i++) {
        std::ostringstream strs;
        strs << (*it)->getPrice();
        string str_price = strs.str();

        if (str_price.length() == 3)
            str_price += "0";
        else if (str_price.length() == 2)
            str_price = "0" + str_price;
        str_price = "$" + str_price;

        QPushButton *remove_button = new QPushButton("X");
        remove_button->setStyleSheet("color:white;background-color:red;max-width: 20px");
        QLabel *item = new QLabel(QString::fromStdString((*it)->getName()));
        QLabel *price = new QLabel(QString::fromStdString(str_price));
        QHBoxLayout *item_line = new QHBoxLayout();
        item_line->addWidget(remove_button);
        item_line->addWidget(item);
        item_line->addWidget(price);
        ui->scroll_layout->addLayout(item_line);

        // Working on remove button.
        //int id = (*it)->getId();
        //connect(remove_button, SIGNAL(clicked(bool)), new_order, SLOT(removeItem(int));
    }
}
<|endoftext|>


<commit_before>#include <QStyledItemDelegate>
#include <QSortFilterProxyModel>
#include <QLineEdit>

#include <QDebug>

#include "mainwindow.h"
#include "ui_mainwindow.h"

#include "icontheme.h"

#include <sys/resource.h>
#include <sys/time.h>
#include <iostream>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow),
    settings(new QSettings(this))
{
    if (QIcon::themeName().isNull())
        QIcon::setThemeName("built-in-theme");
    ui->setupUi(this);

    default_theme_paths = QIcon::themeSearchPaths();
    IconTheme::add_themes_dirs(settings->value("additional-theme-dirs").toStringList());

    model = new ThemeIconsModel(this);
    QSortFilterProxyModel * proxy_model = new QSortFilterProxyModel(this);
    proxy_model->setSortCaseSensitivity(Qt::CaseInsensitive);
    proxy_model->setSourceModel(model);
    proxy_model->sort(0);
    proxy_model->setFilterCaseSensitivity(Qt::CaseInsensitive);
    ui->listView->setModel(proxy_model);
    view_delegate = new IconDelegate(ui->listView);
    view_delegate->set_size_hint({160, 128});
    ui->listView->setItemDelegate(view_delegate);

    QWidget * expander = new QWidget(this);
    expander->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Ignored);
    ui->mainToolBar->addWidget(expander);

    QLineEdit * filter_edit = new QLineEdit(this);
    filter_edit->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
    filter_edit->setClearButtonEnabled(true);
    filter_edit->addAction(QIcon::fromTheme("view-filter-symbolic"),
                           QLineEdit::LeadingPosition);
    connect(filter_edit, &QLineEdit::textChanged,
            proxy_model, &QSortFilterProxyModel::setFilterFixedString);
    ui->mainToolBar->addWidget(filter_edit);
    themes_combo = new QComboBox(this);
    connect(themes_combo, &QComboBox::currentTextChanged,
            model, &ThemeIconsModel::set_current_theme);
    ui->mainToolBar->addWidget(themes_combo);

    // following call changes current icon theme
    struct rusage before, after;
    getrusage(RUSAGE_SELF, &before);
    load_themes(QIcon::themeName());
    for (int i = 0, len = model->rowCount(); i < len; i++)
        model->data(model->index(i), Qt::DecorationRole);
    getrusage(RUSAGE_SELF, &after);
    double start_time = before.ru_utime.tv_sec + before.ru_utime.tv_usec * 1e-6;
    double end_time = after.ru_utime.tv_sec + after.ru_utime.tv_usec * 1e-6;
    std::cout << "time: " << end_time - start_time << std::endl;
    std::cout << "Memory:" << (after.ru_maxrss - before.ru_maxrss) << std::endl;
//    QMenu * view_type_menu = new QMenu(this);
//    view_type_menu
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::show_settings()
{
    if (settings_dialog == nullptr)
        settings_dialog = new SettingsDialog(this);
    if (settings_dialog->exec() != QDialog::Accepted)
        return;
    IconTheme::set_themes_dirs(default_theme_paths);
    IconTheme::add_themes_dirs(settings->value("additional-theme-dirs").toStringList());
    load_themes(QIcon::themeName());
}

void MainWindow::load_themes(QString current_theme)
{
    QHash<QString, IconTheme> themes;
    QStringList theme_list = IconTheme::themes();
    theme_list.sort(Qt::CaseInsensitive);
    for (const QString& theme: theme_list) {
        qDebug() << "Loading: " << theme;
        themes.insert(theme, IconTheme(theme));
    }
    if (current_theme.isNull() || !theme_list.contains(current_theme)) {
        current_theme = theme_list.value(0);
    }
    model->set_themes(themes, current_theme);
    themes_combo->clear();
    themes_combo->addItems(theme_list);
    themes_combo->setCurrentText(current_theme);
}
<commit_msg>Revert "Added resource usage estimation"<commit_after>#include <QStyledItemDelegate>
#include <QSortFilterProxyModel>
#include <QLineEdit>

#include <QDebug>

#include "mainwindow.h"
#include "ui_mainwindow.h"

#include "icontheme.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow),
    settings(new QSettings(this))
{
    if (QIcon::themeName().isNull())
        QIcon::setThemeName("built-in-theme");
    ui->setupUi(this);

    default_theme_paths = QIcon::themeSearchPaths();
    IconTheme::add_themes_dirs(settings->value("additional-theme-dirs").toStringList());

    model = new ThemeIconsModel(this);
    QSortFilterProxyModel * proxy_model = new QSortFilterProxyModel(this);
    proxy_model->setSortCaseSensitivity(Qt::CaseInsensitive);
    proxy_model->setSourceModel(model);
    proxy_model->sort(0);
    proxy_model->setFilterCaseSensitivity(Qt::CaseInsensitive);
    ui->listView->setModel(proxy_model);
    view_delegate = new IconDelegate(ui->listView);
    view_delegate->set_size_hint({160, 128});
    ui->listView->setItemDelegate(view_delegate);

    QWidget * expander = new QWidget(this);
    expander->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Ignored);
    ui->mainToolBar->addWidget(expander);

    QLineEdit * filter_edit = new QLineEdit(this);
    filter_edit->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
    filter_edit->setClearButtonEnabled(true);
    filter_edit->addAction(QIcon::fromTheme("view-filter-symbolic"),
                           QLineEdit::LeadingPosition);
    connect(filter_edit, &QLineEdit::textChanged,
            proxy_model, &QSortFilterProxyModel::setFilterFixedString);
    ui->mainToolBar->addWidget(filter_edit);
    themes_combo = new QComboBox(this);
    connect(themes_combo, &QComboBox::currentTextChanged,
            model, &ThemeIconsModel::set_current_theme);
    ui->mainToolBar->addWidget(themes_combo);

    // following call changes current icon theme
    load_themes(QIcon::themeName());
//    QMenu * view_type_menu = new QMenu(this);
//    view_type_menu
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::show_settings()
{
    if (settings_dialog == nullptr)
        settings_dialog = new SettingsDialog(this);
    if (settings_dialog->exec() != QDialog::Accepted)
        return;
    IconTheme::set_themes_dirs(default_theme_paths);
    IconTheme::add_themes_dirs(settings->value("additional-theme-dirs").toStringList());
    load_themes(QIcon::themeName());
}

void MainWindow::load_themes(QString current_theme)
{
    QHash<QString, IconTheme> themes;
    QStringList theme_list = IconTheme::themes();
    theme_list.sort(Qt::CaseInsensitive);
    for (const QString& theme: theme_list) {
        qDebug() << "Loading: " << theme;
        themes.insert(theme, IconTheme(theme));
    }
    if (current_theme.isNull() || !theme_list.contains(current_theme)) {
        current_theme = theme_list.value(0);
    }
    model->set_themes(themes, current_theme);
    themes_combo->clear();
    themes_combo->addItems(theme_list);
    themes_combo->setCurrentText(current_theme);
}
<|endoftext|>


<commit_before>#include "mainwindow.h"
#include "ui_mainwindow.h"

#include "cvtiff.h"

#include <QFileDialog>

using namespace std;
using namespace cv;

void MainWindow::saveAsClicked()
{
    QString fname = QFileDialog::getSaveFileName(this, "Save a 8-bit image", ".",
        "JPEG files (*.jpg);;PNG files (*.png);;All files (*.*)"
    );
    if (fname.isNull())
        return;

    QImage img(ldr.data, ldr.cols, ldr.rows, 3*ldr.cols, QImage::Format_RGB888);
    img.save(fname);
}

void MainWindow::openClicked()
{
    QString fname = QFileDialog::getOpenFileName(this, "Open a 16-bit TIFF file", ".",
        "TIFF files (*.tif *.tiff);;All files (*.*)"
    );
    if (fname.isNull())
        return;

    hdr = cvtiffLoad16(fname.toStdString());
    cropChanged();
}

void MainWindow::tonemapChanged()
{
    ldr = ui->toneMap->tonemap(hdr_pp);
    QImage img(ldr.data, ldr.cols, ldr.rows, 3*ldr.cols, QImage::Format_RGB888);
    ui->picture->setPixmap(QPixmap::fromImage(img));
}

void MainWindow::cropChanged()
{
    int l = ui->scaleHLo->value() * hdr.cols / 100;
    int r = ui->scaleHHi->value() * hdr.cols / 100;
    int t = ui->scaleVLo->value() * hdr.rows / 100;
    int b = ui->scaleVHi->value() * hdr.rows / 100;

    if (t >= b)
    {
        if (b > 0)
            t = b - 1;
        else
            b = t + 1;
    }

    if (l >= r)
    {
        if (r > 0)
            l = r - 1;
        else
            r = l + 1;
    }

    hdr_pp = Mat(hdr, cvRect(l, t, r-l, b-t));

    tonemapChanged();
}

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    connect(ui->toneMap, SIGNAL(changed()), SLOT(tonemapChanged()));
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::changeEvent(QEvent *e)
{
    QMainWindow::changeEvent(e);
    switch (e->type()) {
    case QEvent::LanguageChange:
        ui->retranslateUi(this);
        break;
    default:
        break;
    }
}
<commit_msg>Some sanity checks.<commit_after>#include "mainwindow.h"
#include "ui_mainwindow.h"

#include "cvtiff.h"

#include <QFileDialog>

using namespace std;
using namespace cv;

void MainWindow::saveAsClicked()
{
    QString fname = QFileDialog::getSaveFileName(this, "Save a 8-bit image", ".",
        "JPEG files (*.jpg);;PNG files (*.png);;All files (*.*)"
    );
    if (fname.isNull())
        return;

    QImage img(ldr.data, ldr.cols, ldr.rows, 3*ldr.cols, QImage::Format_RGB888);
    img.save(fname);
}

void MainWindow::openClicked()
{
    QString fname = QFileDialog::getOpenFileName(this, "Open a 16-bit TIFF file", ".",
        "TIFF files (*.tif *.tiff);;All files (*.*)"
    );
    if (fname.isNull())
        return;

    hdr = cvtiffLoad16(fname.toStdString());
    cropChanged();
}

void MainWindow::tonemapChanged()
{
    if (hdr_pp.empty())
        return;

    ldr = ui->toneMap->tonemap(hdr_pp);
    QImage img(ldr.data, ldr.cols, ldr.rows, 3*ldr.cols, QImage::Format_RGB888);
    ui->picture->setPixmap(QPixmap::fromImage(img));
}

void MainWindow::cropChanged()
{
    if (hdr.empty())
        return;

    int l = ui->scaleHLo->value() * hdr.cols / 100;
    int r = ui->scaleHHi->value() * hdr.cols / 100;
    int t = ui->scaleVLo->value() * hdr.rows / 100;
    int b = ui->scaleVHi->value() * hdr.rows / 100;

    if (t >= b)
    {
        if (b > 0)
            t = b - 1;
        else
            b = t + 1;
    }

    if (l >= r)
    {
        if (r > 0)
            l = r - 1;
        else
            r = l + 1;
    }

    hdr_pp = Mat(hdr, cvRect(l, t, r-l, b-t));

    tonemapChanged();
}

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    connect(ui->toneMap, SIGNAL(changed()), SLOT(tonemapChanged()));
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::changeEvent(QEvent *e)
{
    QMainWindow::changeEvent(e);
    switch (e->type()) {
    case QEvent::LanguageChange:
        ui->retranslateUi(this);
        break;
    default:
        break;
    }
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: mmdocselectpage.hxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: obo $ $Date: 2006-03-29 08:07:35 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library 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 Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/
#ifndef _MAILMERGEDOCSELECTPAGE_HXX
#define _MAILMERGEDOCSELECTPAGE_HXX

#ifndef _SVTOOLS_WIZARDMACHINE_HXX_
#include <svtools/wizardmachine.hxx>
#endif
#ifndef _MAILMERGEHELPER_HXX
#include <mailmergehelper.hxx>
#endif
#ifndef _SV_LSTBOX_HXX
#include <vcl/lstbox.hxx>
#endif
#ifndef _SV_BUTTON_HXX
#include <vcl/button.hxx>
#endif
#ifndef _STDCTRL_HXX
#include <svtools/stdctrl.hxx>
#endif
class SwMailMergeWizard;
/*-- 02.04.2004 09:21:06---------------------------------------------------

  -----------------------------------------------------------------------*/
class SwMailMergeDocSelectPage : public svt::OWizardPage
{
    SwBoldFixedInfo     m_aHeaderFI;
    FixedInfo           m_aHowToFT;
    RadioButton         m_aCurrentDocRB;
    RadioButton         m_aNewDocRB;
    RadioButton         m_aLoadDocRB;
    RadioButton         m_aLoadTemplateRB;
    RadioButton         m_aRecentDocRB;

    PushButton          m_aBrowseDocPB;
    PushButton          m_aBrowseTemplatePB;

    ListBox             m_aRecentDocLB;

    String              m_sLoadFileName;
    String              m_sLoadTemplateName;

    SwMailMergeWizard*  m_pWizard;

    DECL_LINK(DocSelectHdl, RadioButton*);
    DECL_LINK(FileSelectHdl, PushButton*);

    virtual sal_Bool    commitPage(COMMIT_REASON _eReason);

public:
        SwMailMergeDocSelectPage( SwMailMergeWizard* _pParent);
        ~SwMailMergeDocSelectPage();

};

#endif

<commit_msg>INTEGRATION: CWS odbmacros2 (1.4.840); FILE MERGED 2008/02/11 11:13:29 fs 1.4.840.1: IWizardPage is COMMIT_REASON is deprecated - replace usages with CommitPageReason, while I have an svtools-incompatible CWS<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: mmdocselectpage.hxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: kz $ $Date: 2008-03-06 19:05:21 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library 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 Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/
#ifndef _MAILMERGEDOCSELECTPAGE_HXX
#define _MAILMERGEDOCSELECTPAGE_HXX

#ifndef _SVTOOLS_WIZARDMACHINE_HXX_
#include <svtools/wizardmachine.hxx>
#endif
#ifndef _MAILMERGEHELPER_HXX
#include <mailmergehelper.hxx>
#endif
#ifndef _SV_LSTBOX_HXX
#include <vcl/lstbox.hxx>
#endif
#ifndef _SV_BUTTON_HXX
#include <vcl/button.hxx>
#endif
#ifndef _STDCTRL_HXX
#include <svtools/stdctrl.hxx>
#endif
class SwMailMergeWizard;
/*-- 02.04.2004 09:21:06---------------------------------------------------

  -----------------------------------------------------------------------*/
class SwMailMergeDocSelectPage : public svt::OWizardPage
{
    SwBoldFixedInfo     m_aHeaderFI;
    FixedInfo           m_aHowToFT;
    RadioButton         m_aCurrentDocRB;
    RadioButton         m_aNewDocRB;
    RadioButton         m_aLoadDocRB;
    RadioButton         m_aLoadTemplateRB;
    RadioButton         m_aRecentDocRB;

    PushButton          m_aBrowseDocPB;
    PushButton          m_aBrowseTemplatePB;

    ListBox             m_aRecentDocLB;

    String              m_sLoadFileName;
    String              m_sLoadTemplateName;

    SwMailMergeWizard*  m_pWizard;

    DECL_LINK(DocSelectHdl, RadioButton*);
    DECL_LINK(FileSelectHdl, PushButton*);

    virtual sal_Bool    commitPage( CommitPageReason _eReason );

public:
        SwMailMergeDocSelectPage( SwMailMergeWizard* _pParent);
        ~SwMailMergeDocSelectPage();

};

#endif

<|endoftext|>


<commit_before>#include <list>

#ifdef DEBUG
#include <iostream>
#endif

#ifndef CPX_INFBOUND
#include <climits>
#define INFBOUND INT_MAX
#else
#define INFBOUND CPX_INFBOUND
#endif

#include "cluster.h"
#include "sense.h"
#include "thread.h"
#include "lockingvars.h"
#include "symgroup.h" // S[n].size()

Cluster::Cluster(int nThreads, int nObj, Sense sense, bool spread_threads,
    int nObjLeft, int * ordering, int ** share_to_, int ** share_from_,
    int ** share_bounds_, int ** share_limit_, std::list<Thread*> & threads,
    Locking_Vars ** locks) {
  if (nThreads == 1) {
    // Build perm
    int * perm = new int[nObj];
    int i;
    for(i = 0; i < nObj; ++i) {
      perm[i] = ordering[i];
    }
#ifdef DEBUG
    std::cout << "Thread " << threads.size() << " using permutation ";
    std::cout << perm[0];
    for(int d = 1; d < nObj; ++d) {
      std::cout << "," << perm[d];
    }
    std::cout << std::endl;
#endif
    // If there is only one objective left to add, then at the previous stage
    // we must've had 2 objectives left, and 2 threads to use (else the Thread
    // object would be constructed there), so this thread would have a partner.
    bool has_partner = (nObjLeft == 1);
    // Build thread
    Thread *t = new Thread(threads.size(), nObj, perm, share_to_, share_from_,
        share_bounds_, share_limit_, locks, has_partner);
    threads.push_back(t);
//    threads.push_back( new Thread(threads.size(), nObj, perm, shared_limits));
  } else {
    int *my_ordering = new int[nObj];
#ifdef DEBUG
    std::cout << "Working with permutation ";
    std::cout << ordering[0];
    for(int d = 1; d < nObj; ++d) {
      std::cout << "," << ordering[d];
    }
    std::cout << " and " << nObjLeft << " objectives left.";
    std::cout << std::endl;
#endif
    for(int i = 0; i < nObj; ++i) {
      my_ordering[i] = ordering[i];
    }
    int ** share_to = new int*[nObj];
    int ** share_from = new int*[nObj];
    int ** share_limit = new int*[nObj];
    int ** share_bounds = new int*[nObj];
    for(int j = 0; j < nObj; ++j) {
      share_to[j] = share_to_[j];
      share_bounds[j] = share_bounds_[j];
      share_from[j] = share_from_[j];
      share_limit[j] = share_limit_[j];
    }
    // Work out how many different objectives will occur
    // in position "nObjLeft - 1"
    int ind = nObjLeft;
    int ** new_shares = new int*[nObj] {nullptr};
    int ** new_bounds = new int*[nObj] {nullptr};
    int ** new_limit = new int*[nObj] {nullptr};
    int num_sub_clusters = (ind < nThreads) ? ind : nThreads;
    for(int j = 0; j < num_sub_clusters; ++j) {
      int pos = my_ordering[nObjLeft - j - 1];
      new_shares[pos] = new int;
      new_bounds[pos] = new int;
      new_limit[pos] = new int;
      if (sense == MIN) {
        *new_shares[pos] = INFBOUND;
        *new_bounds[pos] = -INFBOUND;
        *new_limit[pos] = INFBOUND;
      } else {
        *new_shares[pos] = -INFBOUND;
        *new_bounds[pos] = INFBOUND;
        *new_limit[pos] = -INFBOUND;
      }
    }

    if (spread_threads) {
      // Split up threads
      int perCluster = nThreads / nObjLeft;
      int withExtra = nThreads % nObjLeft;
      int i;
      for(i = 0; i < withExtra ; ++i) {
        int pos = my_ordering[nObjLeft-1];
        locks[pos] = new Locking_Vars(perCluster + 1);
        int * old_share_to = share_to[pos];
        int * old_share_bounds = share_bounds[pos];
        int * old_share_limit = share_limit[pos];
        int ** old_from = new int*[nObj];
        for(int j = 0; j < nObjLeft; ++j) {
          int obj = my_ordering[j];
          old_from[obj] = share_from[obj];
        }
        for(int j = 0; j < nObjLeft; ++j) {
          int obj = my_ordering[j];
          if (obj == pos) {
            share_to[obj] = new_shares[obj];
            share_bounds[obj] = new_bounds[obj];
            share_limit[obj] = new_limit[obj];
          } else {
            share_from[obj] = new_shares[obj];
          }
        }
        Cluster(perCluster + 1, nObj, sense, spread_threads, nObjLeft - 1,
            my_ordering, share_to, share_from, share_bounds, share_limit, threads, locks);
        share_to[pos] = old_share_to;
        share_bounds[pos] = old_share_bounds;
        share_limit[pos] = old_share_limit;
        for(int j = 0; j < nObjLeft; ++j) {
          int obj = my_ordering[j];
          share_from[obj] = old_from[obj];
        }
        // Rotate ordering
        int first = my_ordering[0];
        for (int c = 0; c < nObjLeft-1; ++c) {
          my_ordering[c] = my_ordering[c+1];
        }
        my_ordering[nObjLeft - 1] = first;

      }
      if (perCluster > 0) {
        for( ; i < nObjLeft ; ++i) {
          int pos = my_ordering[nObjLeft-1];
          int * old_share_to = share_to[pos];
          int * old_share_bounds = share_bounds[pos];
          int * old_share_limit = share_limit[pos];
          locks[pos] = new Locking_Vars(perCluster);
          int ** old_from = new int*[nObj];
          for(int j = 0; j < nObjLeft; ++j) {
            int obj = my_ordering[j];
            old_from[obj] = share_from[obj];
          }
          for(int j = 0; j < nObjLeft; ++j) {
            int obj = my_ordering[j];
            if (obj == pos) {
              share_to[obj] = new_shares[obj];
              share_bounds[obj] = new_bounds[obj];
              share_limit[obj] = new_limit[obj];
            } else {
              share_from[obj] = new_shares[obj];
            }
          }
          Cluster(perCluster, nObj, sense, spread_threads, nObjLeft - 1,
              my_ordering, share_to, share_from, share_bounds, share_limit, threads, locks);
          share_to[pos] = old_share_to;
          share_bounds[pos] = old_share_bounds;
          share_limit[pos] = old_share_limit;
          for(int j = 0; j < nObjLeft; ++j) {
            int obj = my_ordering[j];
            share_from[obj] = old_from[obj];
          }
          // Rotate ordering
          int first = my_ordering[0];
          for (int c = 0; c < nObjLeft-1; ++c) {
            my_ordering[c] = my_ordering[c+1];
          }
          my_ordering[nObjLeft - 1] = first;
          }
      }
    } else { // grouping threads "near" each other
      int threads_remaining = nThreads;
      while (threads_remaining > 0) {
        int threads_to_use = (S[nObjLeft-1].size() > threads_remaining) ? threads_remaining : S[nObjLeft-1].size();
        int pos = my_ordering[nObjLeft-1];
        locks[pos] = new Locking_Vars(threads_to_use);
        int * old_share_to = share_to[pos];
        int * old_share_bounds = share_bounds[pos];
        int * old_share_limit = share_limit[pos];
        int ** old_from = new int*[nObj];
        for(int j = 0; j < nObjLeft; ++j) {
          int obj = my_ordering[j];
          old_from[obj] = share_from[obj];
        }
        for(int j = 0; j < nObjLeft; ++j) {
          int obj = my_ordering[j];
          if (obj == pos) {
            share_to[obj] = new_shares[obj];
            share_bounds[pos] = new_bounds[obj];
            share_limit[obj] = new_limit[obj];
          } else {
            share_from[obj] = new_shares[obj];
          }
        }
        Cluster(threads_to_use, nObj, sense, spread_threads, nObjLeft - 1,
            my_ordering, share_to, share_from, share_bounds, share_limit, threads, locks);
        threads_remaining -= threads_to_use;
        share_to[pos] = old_share_to;
        share_bounds[pos] = old_share_bounds;
        share_limit[pos] = old_share_limit;
        for(int j = 0; j < nObjLeft; ++j) {
          int obj = my_ordering[j];
          share_from[obj] = old_from[obj];
        }
        // Rotate ordering
        int first = my_ordering[0];
        for (int c = 0; c < nObjLeft-1; ++c) {
          my_ordering[c] = my_ordering[c+1];
        }
        my_ordering[nObjLeft - 1] = first;
      }
    }
    delete[] my_ordering;
    delete[] new_shares;
    delete[] new_limit;
    delete[] share_to;
    delete[] share_from;
    delete[] share_limit;
    delete[] share_bounds;
  }
}
<commit_msg>Allocate locks to threads correctly<commit_after>#include <list>

#ifdef DEBUG
#include <iostream>
#endif

#ifndef CPX_INFBOUND
#include <climits>
#define INFBOUND INT_MAX
#else
#define INFBOUND CPX_INFBOUND
#endif

#include "cluster.h"
#include "sense.h"
#include "thread.h"
#include "lockingvars.h"
#include "symgroup.h" // S[n].size()

Cluster::Cluster(int nThreads, int nObj, Sense sense, bool spread_threads,
    int nObjLeft, int * ordering, int ** share_to_, int ** share_from_,
    int ** share_bounds_, int ** share_limit_, std::list<Thread*> & threads,
    Locking_Vars ** locks) {
  if (nThreads == 1) {
    // Build perm
    int * perm = new int[nObj];
    int i;
    for(i = 0; i < nObj; ++i) {
      perm[i] = ordering[i];
    }
#ifdef DEBUG
    std::cout << "Thread " << threads.size() << " using permutation ";
    std::cout << perm[0];
    for(int d = 1; d < nObj; ++d) {
      std::cout << "," << perm[d];
    }
    std::cout << std::endl;
#endif
    // If there is only one objective left to add, then at the previous stage
    // we must've had 2 objectives left, and 2 threads to use (else the Thread
    // object would be constructed there), so this thread would have a partner.
    bool has_partner = (nObjLeft == 1);
    // Build thread
    Thread *t = new Thread(threads.size(), nObj, perm, share_to_, share_from_,
        share_bounds_, share_limit_, locks, has_partner);
    threads.push_back(t);
//    threads.push_back( new Thread(threads.size(), nObj, perm, shared_limits));
  } else {
    int *my_ordering = new int[nObj];
#ifdef DEBUG
    std::cout << "Working with permutation ";
    std::cout << ordering[0];
    for(int d = 1; d < nObj; ++d) {
      std::cout << "," << ordering[d];
    }
    std::cout << " and " << nObjLeft << " objectives left.";
    std::cout << std::endl;
#endif
    for(int i = 0; i < nObj; ++i) {
      my_ordering[i] = ordering[i];
    }
    int ** share_to = new int*[nObj];
    int ** share_from = new int*[nObj];
    int ** share_limit = new int*[nObj];
    int ** share_bounds = new int*[nObj];
    for(int j = 0; j < nObj; ++j) {
      share_to[j] = share_to_[j];
      share_bounds[j] = share_bounds_[j];
      share_from[j] = share_from_[j];
      share_limit[j] = share_limit_[j];
    }
    // Work out how many different objectives will occur
    // in position "nObjLeft - 1"
    int ind = nObjLeft;
    int ** new_shares = new int*[nObj] {nullptr};
    int ** new_bounds = new int*[nObj] {nullptr};
    int ** new_limit = new int*[nObj] {nullptr};
    int num_sub_clusters = (ind < nThreads) ? ind : nThreads;
    for(int j = 0; j < num_sub_clusters; ++j) {
      int pos = my_ordering[nObjLeft - j - 1];
      new_shares[pos] = new int;
      new_bounds[pos] = new int;
      new_limit[pos] = new int;
      if (sense == MIN) {
        *new_shares[pos] = INFBOUND;
        *new_bounds[pos] = -INFBOUND;
        *new_limit[pos] = INFBOUND;
      } else {
        *new_shares[pos] = -INFBOUND;
        *new_bounds[pos] = INFBOUND;
        *new_limit[pos] = -INFBOUND;
      }
    }

    if (spread_threads) {
      // Split up threads
      int perCluster = nThreads / nObjLeft;
      int withExtra = nThreads % nObjLeft;
      int i;
      for(i = 0; i < withExtra ; ++i) {
        int pos = my_ordering[nObjLeft-1];
        locks[pos] = new Locking_Vars(perCluster + 1);
        int * old_share_to = share_to[pos];
        int * old_share_bounds = share_bounds[pos];
        int * old_share_limit = share_limit[pos];
        int ** old_from = new int*[nObj];
        for(int j = 0; j < nObjLeft; ++j) {
          int obj = my_ordering[j];
          old_from[obj] = share_from[obj];
        }
        for(int j = 0; j < nObjLeft; ++j) {
          int obj = my_ordering[j];
          if (obj == pos) {
            share_to[obj] = new_shares[obj];
            share_bounds[obj] = new_bounds[obj];
            share_limit[obj] = new_limit[obj];
          } else {
            share_from[obj] = new_shares[obj];
          }
        }
        Cluster(perCluster + 1, nObj, sense, spread_threads, nObjLeft - 1,
            my_ordering, share_to, share_from, share_bounds, share_limit, threads, locks);
        share_to[pos] = old_share_to;
        share_bounds[pos] = old_share_bounds;
        share_limit[pos] = old_share_limit;
        for(int j = 0; j < nObjLeft; ++j) {
          int obj = my_ordering[j];
          share_from[obj] = old_from[obj];
        }
        // Rotate ordering
        int first = my_ordering[0];
        for (int c = 0; c < nObjLeft-1; ++c) {
          my_ordering[c] = my_ordering[c+1];
        }
        my_ordering[nObjLeft - 1] = first;
        locks[pos] = nullptr;
      }
      if (perCluster > 0) {
        for( ; i < nObjLeft ; ++i) {
          int pos = my_ordering[nObjLeft-1];
          int * old_share_to = share_to[pos];
          int * old_share_bounds = share_bounds[pos];
          int * old_share_limit = share_limit[pos];
          locks[pos] = new Locking_Vars(perCluster);
          int ** old_from = new int*[nObj];
          for(int j = 0; j < nObjLeft; ++j) {
            int obj = my_ordering[j];
            old_from[obj] = share_from[obj];
          }
          for(int j = 0; j < nObjLeft; ++j) {
            int obj = my_ordering[j];
            if (obj == pos) {
              share_to[obj] = new_shares[obj];
              share_bounds[obj] = new_bounds[obj];
              share_limit[obj] = new_limit[obj];
            } else {
              share_from[obj] = new_shares[obj];
            }
          }
          Cluster(perCluster, nObj, sense, spread_threads, nObjLeft - 1,
              my_ordering, share_to, share_from, share_bounds, share_limit, threads, locks);
          share_to[pos] = old_share_to;
          share_bounds[pos] = old_share_bounds;
          share_limit[pos] = old_share_limit;
          for(int j = 0; j < nObjLeft; ++j) {
            int obj = my_ordering[j];
            share_from[obj] = old_from[obj];
          }
          // Rotate ordering
          int first = my_ordering[0];
          for (int c = 0; c < nObjLeft-1; ++c) {
            my_ordering[c] = my_ordering[c+1];
          }
          my_ordering[nObjLeft - 1] = first;
          locks[pos] = nullptr;
        }
      }
    } else { // grouping threads "near" each other
      int threads_remaining = nThreads;
      while (threads_remaining > 0) {
        int threads_to_use = (S[nObjLeft-1].size() > threads_remaining) ? threads_remaining : S[nObjLeft-1].size();
        int pos = my_ordering[nObjLeft-1];
        locks[pos] = new Locking_Vars(threads_to_use);
        int * old_share_to = share_to[pos];
        int * old_share_bounds = share_bounds[pos];
        int * old_share_limit = share_limit[pos];
        int ** old_from = new int*[nObj];
        for(int j = 0; j < nObjLeft; ++j) {
          int obj = my_ordering[j];
          old_from[obj] = share_from[obj];
        }
        for(int j = 0; j < nObjLeft; ++j) {
          int obj = my_ordering[j];
          if (obj == pos) {
            share_to[obj] = new_shares[obj];
            share_bounds[pos] = new_bounds[obj];
            share_limit[obj] = new_limit[obj];
          } else {
            share_from[obj] = new_shares[obj];
          }
        }
        Cluster(threads_to_use, nObj, sense, spread_threads, nObjLeft - 1,
            my_ordering, share_to, share_from, share_bounds, share_limit, threads, locks);
        threads_remaining -= threads_to_use;
        share_to[pos] = old_share_to;
        share_bounds[pos] = old_share_bounds;
        share_limit[pos] = old_share_limit;
        for(int j = 0; j < nObjLeft; ++j) {
          int obj = my_ordering[j];
          share_from[obj] = old_from[obj];
        }
        // Rotate ordering
        int first = my_ordering[0];
        for (int c = 0; c < nObjLeft-1; ++c) {
          my_ordering[c] = my_ordering[c+1];
        }
        my_ordering[nObjLeft - 1] = first;
        locks[pos] = nullptr;
      }
    }
    delete[] my_ordering;
    delete[] new_shares;
    delete[] new_limit;
    delete[] share_to;
    delete[] share_from;
    delete[] share_limit;
    delete[] share_bounds;
  }
}
<|endoftext|>


<commit_before>/*
 *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "webrtc/system_wrappers/source/event_posix.h"

#include <errno.h>
#include <pthread.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <sys/time.h>
#include <unistd.h>

#include "webrtc/base/checks.h"

namespace webrtc {

const long int E6 = 1000000;
const long int E9 = 1000 * E6;

EventWrapper* EventPosix::Create() {
  EventPosix* ptr = new EventPosix;
  if (!ptr) {
    return NULL;
  }

  const int error = ptr->Construct();
  if (error) {
    delete ptr;
    return NULL;
  }
  return ptr;
}

EventPosix::EventPosix()
    : timer_thread_(0),
      timer_event_(0),
      periodic_(false),
      time_(0),
      count_(0),
      state_(kDown) {
}

int EventPosix::Construct() {
  // Set start time to zero
  memset(&created_at_, 0, sizeof(created_at_));

  pthread_mutexattr_t attr;
  pthread_mutexattr_init(&attr);
  pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
  int result = pthread_mutex_init(&mutex_, &attr);
  if (result != 0) {
    return -1;
  }
#ifdef WEBRTC_CLOCK_TYPE_REALTIME
  result = pthread_cond_init(&cond_, 0);
  if (result != 0) {
    return -1;
  }
#else
  pthread_condattr_t cond_attr;
  result = pthread_condattr_init(&cond_attr);
  if (result != 0) {
    return -1;
  }
  result = pthread_condattr_setclock(&cond_attr, CLOCK_MONOTONIC);
  if (result != 0) {
    return -1;
  }
  result = pthread_cond_init(&cond_, &cond_attr);
  if (result != 0) {
    return -1;
  }
  result = pthread_condattr_destroy(&cond_attr);
  if (result != 0) {
    return -1;
  }
#endif
  return 0;
}

EventPosix::~EventPosix() {
  StopTimer();
  pthread_cond_destroy(&cond_);
  pthread_mutex_destroy(&mutex_);
}

bool EventPosix::Reset() {
  if (0 != pthread_mutex_lock(&mutex_)) {
    return false;
  }
  state_ = kDown;
  pthread_mutex_unlock(&mutex_);
  return true;
}

bool EventPosix::Set() {
  if (0 != pthread_mutex_lock(&mutex_)) {
    return false;
  }
  state_ = kUp;
  // Release all waiting threads
  pthread_cond_broadcast(&cond_);
  pthread_mutex_unlock(&mutex_);
  return true;
}

EventTypeWrapper EventPosix::Wait(unsigned long timeout) {
  int ret_val = 0;
  if (0 != pthread_mutex_lock(&mutex_)) {
    return kEventError;
  }

  if (kDown == state_) {
    if (WEBRTC_EVENT_INFINITE != timeout) {
      timespec end_at;
#ifndef WEBRTC_MAC
#ifdef WEBRTC_CLOCK_TYPE_REALTIME
      clock_gettime(CLOCK_REALTIME, &end_at);
#else
      clock_gettime(CLOCK_MONOTONIC, &end_at);
#endif
#else
      timeval value;
      struct timezone time_zone;
      time_zone.tz_minuteswest = 0;
      time_zone.tz_dsttime = 0;
      gettimeofday(&value, &time_zone);
      TIMEVAL_TO_TIMESPEC(&value, &end_at);
#endif
      end_at.tv_sec  += timeout / 1000;
      end_at.tv_nsec += (timeout - (timeout / 1000) * 1000) * E6;

      if (end_at.tv_nsec >= E9) {
        end_at.tv_sec++;
        end_at.tv_nsec -= E9;
      }
      ret_val = pthread_cond_timedwait(&cond_, &mutex_, &end_at);
    } else {
      ret_val = pthread_cond_wait(&cond_, &mutex_);
    }
  }

  // Be careful to only change the state if we're about to report that the
  // event was signaled.
  if (ret_val == 0) {
    DCHECK(state_ == kUp);
    state_ = kDown;
  }

  pthread_mutex_unlock(&mutex_);

  switch (ret_val) {
    case 0:
      return kEventSignaled;
    case ETIMEDOUT:
      return kEventTimeout;
    default:
      return kEventError;
  }
}

EventTypeWrapper EventPosix::Wait(timespec& wake_at) {
  int ret_val = 0;
  if (0 != pthread_mutex_lock(&mutex_)) {
    return kEventError;
  }

  if (kUp != state_) {
    ret_val = pthread_cond_timedwait(&cond_, &mutex_, &wake_at);
  }
  state_ = kDown;

  pthread_mutex_unlock(&mutex_);

  switch (ret_val) {
    case 0:
      return kEventSignaled;
    case ETIMEDOUT:
      return kEventTimeout;
    default:
      return kEventError;
  }
}

bool EventPosix::StartTimer(bool periodic, unsigned long time) {
  pthread_mutex_lock(&mutex_);
  if (timer_thread_) {
    if (periodic_) {
      // Timer already started.
      pthread_mutex_unlock(&mutex_);
      return false;
    } else  {
      // New one shot timer
      time_ = time;
      created_at_.tv_sec = 0;
      timer_event_->Set();
      pthread_mutex_unlock(&mutex_);
      return true;
    }
  }

  // Start the timer thread
  timer_event_ = static_cast<EventPosix*>(EventWrapper::Create());
  const char* thread_name = "WebRtc_event_timer_thread";
  timer_thread_ = ThreadWrapper::CreateThread(Run, this, kRealtimePriority,
                                              thread_name);
  periodic_ = periodic;
  time_ = time;
  unsigned int id = 0;
  bool started = timer_thread_->Start(id);
  pthread_mutex_unlock(&mutex_);

  return started;
}

bool EventPosix::Run(ThreadObj obj) {
  return static_cast<EventPosix*>(obj)->Process();
}

bool EventPosix::Process() {
  pthread_mutex_lock(&mutex_);
  if (created_at_.tv_sec == 0) {
#ifndef WEBRTC_MAC
#ifdef WEBRTC_CLOCK_TYPE_REALTIME
    clock_gettime(CLOCK_REALTIME, &created_at_);
#else
    clock_gettime(CLOCK_MONOTONIC, &created_at_);
#endif
#else
    timeval value;
    struct timezone time_zone;
    time_zone.tz_minuteswest = 0;
    time_zone.tz_dsttime = 0;
    gettimeofday(&value, &time_zone);
    TIMEVAL_TO_TIMESPEC(&value, &created_at_);
#endif
    count_ = 0;
  }

  timespec end_at;
  unsigned long long time = time_ * ++count_;
  end_at.tv_sec  = created_at_.tv_sec + time / 1000;
  end_at.tv_nsec = created_at_.tv_nsec + (time - (time / 1000) * 1000) * E6;

  if (end_at.tv_nsec >= E9) {
    end_at.tv_sec++;
    end_at.tv_nsec -= E9;
  }

  pthread_mutex_unlock(&mutex_);
  switch (timer_event_->Wait(end_at)) {
    case kEventSignaled:
      return true;
    case kEventError:
      return false;
    case kEventTimeout:
      break;
  }

  pthread_mutex_lock(&mutex_);
  if (periodic_ || count_ == 1)
    Set();
  pthread_mutex_unlock(&mutex_);

  return true;
}

bool EventPosix::StopTimer() {
  if (timer_event_) {
    timer_event_->Set();
  }
  if (timer_thread_) {
    if (!timer_thread_->Stop()) {
      return false;
    }

    delete timer_thread_;
    timer_thread_ = 0;
  }
  if (timer_event_) {
    delete timer_event_;
    timer_event_ = 0;
  }

  // Set time to zero to force new reference time for the timer.
  memset(&created_at_, 0, sizeof(created_at_));
  count_ = 0;
  return true;
}

}  // namespace webrtc
<commit_msg>Fix false positive DHECK in event_posix.cc<commit_after>/*
 *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "webrtc/system_wrappers/source/event_posix.h"

#include <errno.h>
#include <pthread.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <sys/time.h>
#include <unistd.h>

#include "webrtc/base/checks.h"

namespace webrtc {

const long int E6 = 1000000;
const long int E9 = 1000 * E6;

EventWrapper* EventPosix::Create() {
  EventPosix* ptr = new EventPosix;
  if (!ptr) {
    return NULL;
  }

  const int error = ptr->Construct();
  if (error) {
    delete ptr;
    return NULL;
  }
  return ptr;
}

EventPosix::EventPosix()
    : timer_thread_(0),
      timer_event_(0),
      periodic_(false),
      time_(0),
      count_(0),
      state_(kDown) {
}

int EventPosix::Construct() {
  // Set start time to zero
  memset(&created_at_, 0, sizeof(created_at_));

  pthread_mutexattr_t attr;
  pthread_mutexattr_init(&attr);
  pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
  int result = pthread_mutex_init(&mutex_, &attr);
  if (result != 0) {
    return -1;
  }
#ifdef WEBRTC_CLOCK_TYPE_REALTIME
  result = pthread_cond_init(&cond_, 0);
  if (result != 0) {
    return -1;
  }
#else
  pthread_condattr_t cond_attr;
  result = pthread_condattr_init(&cond_attr);
  if (result != 0) {
    return -1;
  }
  result = pthread_condattr_setclock(&cond_attr, CLOCK_MONOTONIC);
  if (result != 0) {
    return -1;
  }
  result = pthread_cond_init(&cond_, &cond_attr);
  if (result != 0) {
    return -1;
  }
  result = pthread_condattr_destroy(&cond_attr);
  if (result != 0) {
    return -1;
  }
#endif
  return 0;
}

EventPosix::~EventPosix() {
  StopTimer();
  pthread_cond_destroy(&cond_);
  pthread_mutex_destroy(&mutex_);
}

bool EventPosix::Reset() {
  if (0 != pthread_mutex_lock(&mutex_)) {
    return false;
  }
  state_ = kDown;
  pthread_mutex_unlock(&mutex_);
  return true;
}

bool EventPosix::Set() {
  if (0 != pthread_mutex_lock(&mutex_)) {
    return false;
  }
  state_ = kUp;
  // Release all waiting threads
  pthread_cond_broadcast(&cond_);
  pthread_mutex_unlock(&mutex_);
  return true;
}

EventTypeWrapper EventPosix::Wait(unsigned long timeout) {
  int ret_val = 0;
  if (0 != pthread_mutex_lock(&mutex_)) {
    return kEventError;
  }

  if (kDown == state_) {
    if (WEBRTC_EVENT_INFINITE != timeout) {
      timespec end_at;
#ifndef WEBRTC_MAC
#ifdef WEBRTC_CLOCK_TYPE_REALTIME
      clock_gettime(CLOCK_REALTIME, &end_at);
#else
      clock_gettime(CLOCK_MONOTONIC, &end_at);
#endif
#else
      timeval value;
      struct timezone time_zone;
      time_zone.tz_minuteswest = 0;
      time_zone.tz_dsttime = 0;
      gettimeofday(&value, &time_zone);
      TIMEVAL_TO_TIMESPEC(&value, &end_at);
#endif
      end_at.tv_sec  += timeout / 1000;
      end_at.tv_nsec += (timeout - (timeout / 1000) * 1000) * E6;

      if (end_at.tv_nsec >= E9) {
        end_at.tv_sec++;
        end_at.tv_nsec -= E9;
      }
      ret_val = pthread_cond_timedwait(&cond_, &mutex_, &end_at);
    } else {
      ret_val = pthread_cond_wait(&cond_, &mutex_);
    }
  }

  // Be careful to only change the state if we're about to report that the
  // event was signaled.
  if (ret_val == 0) {
    // state_ might already be kDown, in case of multiple waiters. That's OK.
    state_ = kDown;
  }

  pthread_mutex_unlock(&mutex_);

  switch (ret_val) {
    case 0:
      return kEventSignaled;
    case ETIMEDOUT:
      return kEventTimeout;
    default:
      return kEventError;
  }
}

EventTypeWrapper EventPosix::Wait(timespec& wake_at) {
  int ret_val = 0;
  if (0 != pthread_mutex_lock(&mutex_)) {
    return kEventError;
  }

  if (kUp != state_) {
    ret_val = pthread_cond_timedwait(&cond_, &mutex_, &wake_at);
  }
  state_ = kDown;

  pthread_mutex_unlock(&mutex_);

  switch (ret_val) {
    case 0:
      return kEventSignaled;
    case ETIMEDOUT:
      return kEventTimeout;
    default:
      return kEventError;
  }
}

bool EventPosix::StartTimer(bool periodic, unsigned long time) {
  pthread_mutex_lock(&mutex_);
  if (timer_thread_) {
    if (periodic_) {
      // Timer already started.
      pthread_mutex_unlock(&mutex_);
      return false;
    } else  {
      // New one shot timer
      time_ = time;
      created_at_.tv_sec = 0;
      timer_event_->Set();
      pthread_mutex_unlock(&mutex_);
      return true;
    }
  }

  // Start the timer thread
  timer_event_ = static_cast<EventPosix*>(EventWrapper::Create());
  const char* thread_name = "WebRtc_event_timer_thread";
  timer_thread_ = ThreadWrapper::CreateThread(Run, this, kRealtimePriority,
                                              thread_name);
  periodic_ = periodic;
  time_ = time;
  unsigned int id = 0;
  bool started = timer_thread_->Start(id);
  pthread_mutex_unlock(&mutex_);

  return started;
}

bool EventPosix::Run(ThreadObj obj) {
  return static_cast<EventPosix*>(obj)->Process();
}

bool EventPosix::Process() {
  pthread_mutex_lock(&mutex_);
  if (created_at_.tv_sec == 0) {
#ifndef WEBRTC_MAC
#ifdef WEBRTC_CLOCK_TYPE_REALTIME
    clock_gettime(CLOCK_REALTIME, &created_at_);
#else
    clock_gettime(CLOCK_MONOTONIC, &created_at_);
#endif
#else
    timeval value;
    struct timezone time_zone;
    time_zone.tz_minuteswest = 0;
    time_zone.tz_dsttime = 0;
    gettimeofday(&value, &time_zone);
    TIMEVAL_TO_TIMESPEC(&value, &created_at_);
#endif
    count_ = 0;
  }

  timespec end_at;
  unsigned long long time = time_ * ++count_;
  end_at.tv_sec  = created_at_.tv_sec + time / 1000;
  end_at.tv_nsec = created_at_.tv_nsec + (time - (time / 1000) * 1000) * E6;

  if (end_at.tv_nsec >= E9) {
    end_at.tv_sec++;
    end_at.tv_nsec -= E9;
  }

  pthread_mutex_unlock(&mutex_);
  switch (timer_event_->Wait(end_at)) {
    case kEventSignaled:
      return true;
    case kEventError:
      return false;
    case kEventTimeout:
      break;
  }

  pthread_mutex_lock(&mutex_);
  if (periodic_ || count_ == 1)
    Set();
  pthread_mutex_unlock(&mutex_);

  return true;
}

bool EventPosix::StopTimer() {
  if (timer_event_) {
    timer_event_->Set();
  }
  if (timer_thread_) {
    if (!timer_thread_->Stop()) {
      return false;
    }

    delete timer_thread_;
    timer_thread_ = 0;
  }
  if (timer_event_) {
    delete timer_event_;
    timer_event_ = 0;
  }

  // Set time to zero to force new reference time for the timer.
  memset(&created_at_, 0, sizeof(created_at_));
  count_ = 0;
  return true;
}

}  // namespace webrtc
<|endoftext|>


<commit_before>#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MAIN

#include<iostream>
#include<boost/test/unit_test.hpp>
#include<string>
#include<vector>

#include"ring_buffer.h"
#include"GlbContainer.h"
#include"IPRecord.h"

using namespace boost;
using namespace std;

const string TEST_STR(string(" THIS    IS      A  TEST\n"));

BOOST_AUTO_TEST_CASE(ring_buffer_shouldent_strip_line_feed) {
    vector<string> strVector;
    ring_buffer::stringToVector(TEST_STR, strVector, ' ', false);
    BOOST_CHECK(strVector.size() == 4);
    BOOST_CHECK(strVector[0].compare("THIS") == 0);
    BOOST_CHECK(strVector[1].compare("IS") == 0);
    BOOST_CHECK(strVector[2].compare("A") == 0);
    BOOST_CHECK(strVector[3].compare("TEST\n") == 0);
}

BOOST_AUTO_TEST_CASE(ring_buffer_should_strip_line_feed) {
    vector<string> strVector;
    ring_buffer::stringToVector(TEST_STR, strVector, ' ', true);
    BOOST_CHECK(strVector.size() == 4);
    BOOST_CHECK(strVector[0].compare("THIS") == 0);
    BOOST_CHECK(strVector[1].compare("IS") == 0);
    BOOST_CHECK(strVector[2].compare("A") == 0);
    BOOST_CHECK(strVector[3].compare("TEST") == 0);
}

BOOST_AUTO_TEST_CASE(ring_buffer_should_strip_all_line_feeds_too) {
    string lineFeededString("this\n\n is \na test \nblah\nblah\n");
    vector<string> strVector;
    ring_buffer::stringToVector(lineFeededString, strVector, ' ', true);
    BOOST_CHECK(strVector.size() == 6);
    BOOST_CHECK(strVector[0].compare("this") == 0);
    BOOST_CHECK(strVector[1].compare("is") == 0);
    BOOST_CHECK(strVector[2].compare("a") == 0);
    BOOST_CHECK(strVector[3].compare("test") == 0);
    BOOST_CHECK(strVector[4].compare("blah") == 0);
    BOOST_CHECK(strVector[5].compare("blah") == 0);
}

BOOST_AUTO_TEST_CASE(test_str_maps) {
    BOOST_CHECK(strToIpType("IPv4") == IPRecordType::IPv4);
    BOOST_CHECK(strToIpType("IPv6") == IPRecordType::IPv6);
    BOOST_CHECK(strToIpType("NONE") == IPRecordType::NONE);
    BOOST_CHECK(ipTypeToStr(IPRecordType::IPv4).compare("IPv4") == 0);
    BOOST_CHECK(ipTypeToStr(IPRecordType::IPv6).compare("IPv6") == 0);
    BOOST_CHECK(ipTypeToStr(IPRecordType::NONE).compare("NONE") == 0);

    BOOST_CHECK(strToGlbType("NONE") == GlbType::NONE);
    BOOST_CHECK(strToGlbType("RANDOM") == GlbType::RANDOM);
    BOOST_CHECK(strToGlbType("GEOIP") == GlbType::GEOIP);
    BOOST_CHECK(strToGlbType("WEIGHTED") == GlbType::WEIGHTED);
    BOOST_CHECK(glbTypeToStr(GlbType::NONE).compare("NONE") == 0);
    BOOST_CHECK(glbTypeToStr(GlbType::RANDOM).compare("RANDOM") == 0);
    BOOST_CHECK(glbTypeToStr(GlbType::GEOIP).compare("GEOIP") == 0);
    BOOST_CHECK(glbTypeToStr(GlbType::WEIGHTED).compare("WEIGHTED") == 0);
}

BOOST_AUTO_TEST_CASE(test_IP_to_string) {
    std::string expIPRStr("{ ipType=IPv4, ip=127.0.0.1, ttl=30}");
    IPRecord ipr(IPRecordType::IPv4, "127.0.0.1", 30);

    BOOST_CHECK(expIPRStr.compare(ipr.to_string()) == 0);

    std::string expGlbStr("{ cname=testglb.rackexp.org, nsLookups=10, glbType=RANDOM, nIPv4=2, nIPv6=3}");
    std::vector<IPRecord> ipVec;
    // Add 2 records
    ipVec.push_back(IPRecord(IPRecordType::IPv4, "127.0.0.1", 30));
    ipVec.push_back(IPRecord(IPRecordType::IPv4, "192.168.3.0", 30));
    ipVec.push_back(IPRecord(IPRecordType::IPv4, "10.0.0.0", 30));
    ipVec.push_back(IPRecord(IPRecordType::IPv6, "::", 30));
    ipVec.push_back(IPRecord(IPRecordType::IPv6, "ffee::", 30));
    GlbContainer glb("testglb.rackexp.org", GlbType::RANDOM);
    glb.setRandomAlgoIPVectors(ipVec);
    for (int i = 0; i < 16; i++) {
        glb.incNLookups();
    }
    std::cout << glb.to_string(true) << std::endl;
}

BOOST_AUTO_TEST_CASE(show_size_of_Glb) {
    std::cout << "sizeof(GlbContainer):: " << sizeof (GlbContainer) << std::endl;
    std::cout << "sizeof(IPRecord):      " << sizeof (IPRecord) << std::endl;
}<commit_msg>Adding to_string test for GlbContainer<commit_after>#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MAIN

#include<iostream>
#include<boost/test/unit_test.hpp>
#include<string>
#include<vector>

#include"ring_buffer.h"
#include"GlbContainer.h"
#include"IPRecord.h"

using namespace boost;
using namespace std;

const string TEST_STR(string(" THIS    IS      A  TEST\n"));

BOOST_AUTO_TEST_CASE(ring_buffer_shouldent_strip_line_feed) {
    vector<string> strVector;
    ring_buffer::stringToVector(TEST_STR, strVector, ' ', false);
    BOOST_CHECK(strVector.size() == 4);
    BOOST_CHECK(strVector[0].compare("THIS") == 0);
    BOOST_CHECK(strVector[1].compare("IS") == 0);
    BOOST_CHECK(strVector[2].compare("A") == 0);
    BOOST_CHECK(strVector[3].compare("TEST\n") == 0);
}

BOOST_AUTO_TEST_CASE(ring_buffer_should_strip_line_feed) {
    vector<string> strVector;
    ring_buffer::stringToVector(TEST_STR, strVector, ' ', true);
    BOOST_CHECK(strVector.size() == 4);
    BOOST_CHECK(strVector[0].compare("THIS") == 0);
    BOOST_CHECK(strVector[1].compare("IS") == 0);
    BOOST_CHECK(strVector[2].compare("A") == 0);
    BOOST_CHECK(strVector[3].compare("TEST") == 0);
}

BOOST_AUTO_TEST_CASE(ring_buffer_should_strip_all_line_feeds_too) {
    string lineFeededString("this\n\n is \na test \nblah\nblah\n");
    vector<string> strVector;
    ring_buffer::stringToVector(lineFeededString, strVector, ' ', true);
    BOOST_CHECK(strVector.size() == 6);
    BOOST_CHECK(strVector[0].compare("this") == 0);
    BOOST_CHECK(strVector[1].compare("is") == 0);
    BOOST_CHECK(strVector[2].compare("a") == 0);
    BOOST_CHECK(strVector[3].compare("test") == 0);
    BOOST_CHECK(strVector[4].compare("blah") == 0);
    BOOST_CHECK(strVector[5].compare("blah") == 0);
}

BOOST_AUTO_TEST_CASE(test_str_maps) {
    BOOST_CHECK(strToIpType("IPv4") == IPRecordType::IPv4);
    BOOST_CHECK(strToIpType("IPv6") == IPRecordType::IPv6);
    BOOST_CHECK(strToIpType("NONE") == IPRecordType::NONE);
    BOOST_CHECK(ipTypeToStr(IPRecordType::IPv4).compare("IPv4") == 0);
    BOOST_CHECK(ipTypeToStr(IPRecordType::IPv6).compare("IPv6") == 0);
    BOOST_CHECK(ipTypeToStr(IPRecordType::NONE).compare("NONE") == 0);

    BOOST_CHECK(strToGlbType("NONE") == GlbType::NONE);
    BOOST_CHECK(strToGlbType("RANDOM") == GlbType::RANDOM);
    BOOST_CHECK(strToGlbType("GEOIP") == GlbType::GEOIP);
    BOOST_CHECK(strToGlbType("WEIGHTED") == GlbType::WEIGHTED);
    BOOST_CHECK(glbTypeToStr(GlbType::NONE).compare("NONE") == 0);
    BOOST_CHECK(glbTypeToStr(GlbType::RANDOM).compare("RANDOM") == 0);
    BOOST_CHECK(glbTypeToStr(GlbType::GEOIP).compare("GEOIP") == 0);
    BOOST_CHECK(glbTypeToStr(GlbType::WEIGHTED).compare("WEIGHTED") == 0);
}

BOOST_AUTO_TEST_CASE(test_IP_to_string) {
    std::string expIPRStr("{ ipType=IPv4, ip=127.0.0.1, ttl=30}");
    IPRecord ipr(IPRecordType::IPv4, "127.0.0.1", 30);

    BOOST_CHECK(expIPRStr.compare(ipr.to_string()) == 0);

    std::string expGlbStr("{ cname=testglb.rackexp.org, nsLookups=16, glbType=RANDOM, nIPv4=3, nIPv6=2}");
    std::vector<IPRecord> ipVec;
    // Add 2 records
    ipVec.push_back(IPRecord(IPRecordType::IPv4, "127.0.0.1", 30));
    ipVec.push_back(IPRecord(IPRecordType::IPv4, "192.168.3.0", 30));
    ipVec.push_back(IPRecord(IPRecordType::IPv4, "10.0.0.0", 30));
    ipVec.push_back(IPRecord(IPRecordType::IPv6, "::", 30));
    ipVec.push_back(IPRecord(IPRecordType::IPv6, "ffee::", 30));
    GlbContainer glb("testglb.rackexp.org", GlbType::RANDOM);
    glb.setRandomAlgoIPVectors(ipVec);
    for (int i = 0; i < 16; i++) {
        glb.incNLookups();
    }
    BOOST_CHECK(glb.to_string().compare(expGlbStr) == 0);
}

BOOST_AUTO_TEST_CASE(show_size_of_Glb) {
    std::cout << "sizeof(GlbContainer):: " << sizeof (GlbContainer) << std::endl;
    std::cout << "sizeof(IPRecord):      " << sizeof (IPRecord) << std::endl;
}<|endoftext|>


<commit_before>//=======================================================================
// Copyright Baptiste Wicht 2013.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include <sstream>

#include <boost/algorithm/string.hpp>

#include "console.hpp"

std::string budget::format_code(int attr, int fg, int bg){
    std::stringstream stream;
    stream << "" << '\033' << "[" << attr << ";" << (fg + 30) << (bg + 40) << "m";
    return stream.str();
}

void budget::display_table(std::vector<std::string> columns, std::vector<std::vector<std::string>> contents, std::size_t groups){
    assert(groups > 0);

    for(auto& row : contents){
        for(auto& cell : row){
            boost::algorithm::trim(cell);
        }
    }

    std::vector<std::size_t> widths;
    std::vector<std::size_t> header_widths;

    if(!contents.size()){
        for(auto& column : columns){
            widths.push_back(column.length());
        }
    } else {
        auto& first = contents[0];

        for(auto& value : first){
            widths.push_back(0);
        }

        for(auto& row : contents){
            for(std::size_t i = 0; i < widths.size(); ++i){
                widths[i] = std::max(widths[i], row[i].length() + (i < row.size() - 1 ? 1 : 0));
            }
        }
    }

    assert(widths.size() == groups * columns.size());

    for(std::size_t i = 0; i < columns.size(); ++i){
        auto& column = columns[i];

        std::size_t width = 0;
        for(std::size_t j = i * groups; j < (i + 1) * groups; ++j){
            width += widths[j];
        }

        width = std::max(width, column.length());
        header_widths.push_back(width + (i < columns.size() - 1 && column.length() >= width ? 1 : 0));

        --width;

        std::cout << format_code(4, 0, 7) << column << (width > column.length() ? std::string(width - column.length(), ' ') : "") << format_code(0, 0, 7);

        if(i < columns.size() - 1){
            std::cout << " ";
        }
    }

    std::cout << std::endl;

    for(std::size_t i = 0; i < contents.size(); ++i){
        auto& row = contents[i];

        if(i % 2 == 0){
            std::cout << format_code(7, 0, 7);
        } else {
            std::cout << format_code(0, 0, 7);
        }

        std::size_t acc_width = 0;
        for(std::size_t j = 0; j < row.size(); ++j){
            auto width = widths[j];
            acc_width += width;

            if(groups == 1){
                width = std::max(width, header_widths[j]);
            } else if((j+1) % groups == 0 && header_widths[(j-(groups-1)) / groups] > acc_width){
                width = std::max(width, header_widths[(j-(groups-1)) / groups] - acc_width);
            }

            std::cout << row[j] << std::string(width - row[j].length(), ' ');
        }

        std::cout << format_code(0, 0, 7) << std::endl;
    }
}
<commit_msg>Some more spaces bug<commit_after>//=======================================================================
// Copyright Baptiste Wicht 2013.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include <sstream>

#include <boost/algorithm/string.hpp>

#include "console.hpp"

std::string budget::format_code(int attr, int fg, int bg){
    std::stringstream stream;
    stream << "" << '\033' << "[" << attr << ";" << (fg + 30) << (bg + 40) << "m";
    return stream.str();
}

void budget::display_table(std::vector<std::string> columns, std::vector<std::vector<std::string>> contents, std::size_t groups){
    assert(groups > 0);

    for(auto& row : contents){
        for(auto& cell : row){
            boost::algorithm::trim(cell);
        }
    }

    std::vector<std::size_t> widths;
    std::vector<std::size_t> header_widths;

    if(!contents.size()){
        for(auto& column : columns){
            widths.push_back(column.length());
        }
    } else {
        auto& first = contents[0];

        for(auto& value : first){
            widths.push_back(0);
        }

        for(auto& row : contents){
            for(std::size_t i = 0; i < row.size(); ++i){
                widths[i] = std::max(widths[i], row[i].length() + 1);
            }
        }
    }

    assert(widths.size() == groups * columns.size());

    for(std::size_t i = 0; i < columns.size(); ++i){
        auto& column = columns[i];

        std::size_t width = 0;
        for(std::size_t j = i * groups; j < (i + 1) * groups; ++j){
            width += widths[j];
        }

        width = std::max(width, column.length());
        header_widths.push_back(width + (i < columns.size() - 1 && column.length() >= width ? 1 : 0));

 //           std::cout << "i=" << i << std::endl;
  //          std::cout << "width=" << width << std::endl;
   //         std::cout << "column.length()=" << column.length() << std::endl;

        --width;

        std::cout << format_code(4, 0, 7) << column << (width > column.length() ? std::string(width - column.length(), ' ') : "") << format_code(0, 0, 7);

        if(i < columns.size() - 1){
            std::cout << " ";
        }
    }

    std::cout << std::endl;

    for(std::size_t i = 0; i < contents.size(); ++i){
        auto& row = contents[i];

        if(i % 2 == 0){
            std::cout << format_code(7, 0, 7);
        } else {
            std::cout << format_code(0, 0, 7);
        }

        std::size_t acc_width = 0;
        for(std::size_t j = 0; j < row.size(); ++j){
            auto width = widths[j];
            acc_width += width;

            if(groups == 1){
                width = std::max(width, header_widths[j]);
            } else if((j+1) % groups == 0 && header_widths[(j-(groups-1)) / groups] + 1 > acc_width){
                width = std::max(width, header_widths[(j-(groups-1)) / groups] + 1 - acc_width);
                acc_width = 0;
            }

            std::cout << row[j] << std::string(width - row[j].length(), ' ');
        }

        std::cout << format_code(0, 0, 7) << std::endl;
    }
}
<|endoftext|>


<commit_before>#ifndef HEADER_GUARD_CLASS_CONTENTS_H
#define HEADER_GUARD_CLASS_CONTENTS_H

#include <vector>
#include <string>
#include <memory>

#include "change.hh"
#include "mode.hh"

/*!
 * \file contents.hh
 *
 * \brief Defines the class contents, which contains all the
 * information about the buffer.
 */

/*!
 * \brief Define move_t so that code can be more descriptive and can change it
 * from one place.
 */
using move_t = unsigned long;

/*!
 * \brief Define move_ts to be a signed version of move_t
 *
 * \see move_t
 */
using move_ts = long;

/*!
 * \class contents contents.hh "../../../src/contents.hh"
 *
 * \brief Defines all the information about the buffer.
 */
class contents {
  private:
    const mode* m;
    std::vector<std::shared_ptr<change> > _changes;
    size_t _changes_i = 0;
    friend boost::optional<std::shared_ptr<change> >
    undo_change(contents&, boost::optional<int>);
    friend boost::optional<std::shared_ptr<change> >
    redo_change(contents&, boost::optional<int>);
    friend boost::optional<std::shared_ptr<change> >
    reapply_change(contents&, boost::optional<int>);

  public:
    /*!
     * \brief The literal contents of the buffer
     */
    std::vector<std::string> cont;
    /*!
     * \brief The linear list of changes to the buffer
     */
    const std::vector<std::shared_ptr<change> >& changes = _changes;
    const size_t& changes_i = _changes_i;
    move_t
    y = 0 /*!< \brief The y (vertical) position in the buffer. */,
    x = 0 /*!< \brief The x (horizontal) position in the buffer. */,
    desired_x = 0 /*!< \brief This will be set to the x value we
                       * want when you move to a different line but
                       * the line you move to is too short
                       *
                       * \see waiting_for_desired */,
    y_offset = 0 /*!< \brief The number of lines that are not
                      * displayed (off the top) */,
    max_y /*!< \brief The vertical height the buffer has been allocated */,
    max_x /*!< \brief The horizontal width the buffer has been allocated */;
    bool waiting_for_desired = false /*!< \brief Controls if the x
                                      * value will try to adjust to
                                      * desired_x
                                      *
                                      * \see desired_x */,
         refresh = true /*!< \brief Controls if the screen should
                         * refresh everytime something happens */,
         delete_mode = false /*!< \brief Controls if the private mode
                              * pointer variable will be deleted in the
                              * destructor */,
         is_inserting = false /*!< \brief Will be true if the user is
                               * currently inserting text into the
                               * buffer.  This will cause the
                               * print_contents method to not have
                               * undefined behavior if x is too
                               * large. */;

    /*!
     * Construcs a contents object
     */
    contents(std::vector<std::string> cont = std::vector<std::string>(),
             mode* m = &mode::fundamental);
    /*!
     * Constructs a contents object
     */
    contents(mode* m);
    /*!
     * Constructs a contents object
     */
    contents(move_t y, unsigned long x, mode* m = &mode::fundamental);

    /*!
     * \brief Calls operator() on the private mode pointer member.
     *
     * \see mode
     */
    bool operator()(char) const;

    /*!
     * \brief If delete_mode is true, then it will delete the private
     * mode pointer member.
     *
     * \see delete_mode
     */
    ~contents();
    /*!
     * \brief Constructs this contents object as a copy of the other
     * contents object.
     *
     * This forces the private mode member to make a deep copy.
     */
    contents(const contents&);
    /*!
     * \brief Constructs this contents object as a copy of the other
     * contents object.
     */
    contents(contents&&);
    /*!
     * \brief Constructs this contents object as a copy of the other
     * contents object.
     *
     * This forces the private mode member to make a deep copy.
     */
    contents& operator=(const contents&);
    /*!
     * \brief Constructs this contents object as a copy of the other
     * contents object.
     */
    contents& operator=(contents&&);

    /*!
     * \brief Updates the values of ``max_y`` and ``max_x``
     *
     * \see max_y
     * \see max_x
     */
    void refreshmaxyx();

    /*!
     * \brief Calls ``cont.push_back(str)``
     *
     * \see cont
     *
     * \param str The string to be put at the end of the vector of strings, cont
     */
    void push_back(const std::string& str);

    /*!
     * \brief Adds the change given to the private vector, possibly
     * deleting some changes
     *
     * ----------
     * | change |
     * | ------ |
     * ----------
     *
     * \see changes _changes
     *
     * \param change The string to be put at the end of the vector of
     * changes, ``_changes`` (public interface ``changes``)
     */
    void push_back(std::shared_ptr<change> change);
};

#endif
<commit_msg>Put some ``\c``s in documentation (code blocks)<commit_after>#ifndef HEADER_GUARD_CLASS_CONTENTS_H
#define HEADER_GUARD_CLASS_CONTENTS_H

#include <vector>
#include <string>
#include <memory>

#include "change.hh"
#include "mode.hh"

/*!
 * \file contents.hh
 *
 * \brief Defines the class contents, which contains all the
 * information about the buffer.
 */

/*!
 * \brief Define \c move_t so that code can be more descriptive and can change it
 * from one place.
 */
using move_t = unsigned long;

/*!
 * \brief Define \c move_ts to be a signed version of \c move_t
 *
 * \see move_t
 */
using move_ts = long;

/*!
 * \class contents contents.hh "../../../src/contents.hh"
 *
 * \brief Defines all the information about the buffer.
 */
class contents {
  private:
    const mode* m;
    std::vector<std::shared_ptr<change> > _changes;
    size_t _changes_i = 0;
    friend boost::optional<std::shared_ptr<change> >
    undo_change(contents&, boost::optional<int>);
    friend boost::optional<std::shared_ptr<change> >
    redo_change(contents&, boost::optional<int>);
    friend boost::optional<std::shared_ptr<change> >
    reapply_change(contents&, boost::optional<int>);

  public:
    /*!
     * \brief The literal contents of the buffer
     */
    std::vector<std::string> cont;
    /*!
     * \brief The linear list of changes to the buffer
     */
    const std::vector<std::shared_ptr<change> >& changes = _changes;
    const size_t& changes_i = _changes_i;
    move_t
    y = 0 /*!< \brief The y (vertical) position in the buffer. */,
    x = 0 /*!< \brief The x (horizontal) position in the buffer. */,
    desired_x = 0 /*!< \brief This will be set to the x value we
                       * want when you move to a different line but
                       * the line you move to is too short
                       *
                       * \see waiting_for_desired */,
    y_offset = 0 /*!< \brief The number of lines that are not
                      * displayed (off the top) */,
    max_y /*!< \brief The vertical height the buffer has been allocated */,
    max_x /*!< \brief The horizontal width the buffer has been allocated */;
    bool waiting_for_desired = false /*!< \brief Controls if the x
                                      * value will try to adjust to
                                      * desired_x
                                      *
                                      * \see desired_x */,
         refresh = true /*!< \brief Controls if the screen should
                         * refresh everytime something happens */,
         delete_mode = false /*!< \brief Controls if the private mode
                              * pointer variable will be deleted in the
                              * destructor */,
         is_inserting = false /*!< \brief Will be true if the user is
                               * currently inserting text into the
                               * buffer.  This will cause the
                               * print_contents method to not have
                               * undefined behavior if x is too
                               * large. */;

    /*!
     * Construcs a contents object
     */
    contents(std::vector<std::string> cont = std::vector<std::string>(),
             mode* m = &mode::fundamental);
    /*!
     * Constructs a contents object
     */
    contents(mode* m);
    /*!
     * Constructs a contents object
     */
    contents(move_t y, unsigned long x, mode* m = &mode::fundamental);

    /*!
     * \brief Calls operator() on the private mode pointer member.
     *
     * \see mode
     */
    bool operator()(char) const;

    /*!
     * \brief If delete_mode is true, then it will delete the private
     * mode pointer member.
     *
     * \see delete_mode
     */
    ~contents();
    /*!
     * \brief Constructs this contents object as a copy of the other
     * contents object.
     *
     * This forces the private mode member to make a deep copy.
     */
    contents(const contents&);
    /*!
     * \brief Constructs this contents object as a copy of the other
     * contents object.
     */
    contents(contents&&);
    /*!
     * \brief Constructs this contents object as a copy of the other
     * contents object.
     *
     * This forces the private mode member to make a deep copy.
     */
    contents& operator=(const contents&);
    /*!
     * \brief Constructs this contents object as a copy of the other
     * contents object.
     */
    contents& operator=(contents&&);

    /*!
     * \brief Updates the values of ``max_y`` and ``max_x``
     *
     * \see max_y
     * \see max_x
     */
    void refreshmaxyx();

    /*!
     * \brief Calls ``cont.push_back(str)``
     *
     * \see cont
     *
     * \param str The string to be put at the end of the vector of strings, cont
     */
    void push_back(const std::string& str);

    /*!
     * \brief Adds the change given to the private vector, possibly
     * deleting some changes
     *
     * ----------
     * | change |
     * | ------ |
     * ----------
     *
     * \see changes _changes
     *
     * \param change The string to be put at the end of the vector of
     * changes, ``_changes`` (public interface ``changes``)
     */
    void push_back(std::shared_ptr<change> change);
};

#endif
<|endoftext|>