<commit_before>/***************************************************************************
 *   Copyright (C) 2003 by Unai Garro                                      *
 *   uga@ee.ed.ac.uk                                                       *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 ***************************************************************************/
#include "ingredientsdialog.h"
#include <qheader.h>

IngredientsDialog::IngredientsDialog(QWidget* parent, RecipeDB *db):QWidget(parent)
{

    // Store pointer to database
    database=db;

    // Initialize internal variables
    propertiesList= new IngredientPropertyList;
    perUnitListBack= new ElementList;

    // Design dialog

    layout = new QGridLayout( this, 1, 1, 0, 0);
    QSpacerItem* spacer_left = new QSpacerItem( 10,10, QSizePolicy::Fixed, QSizePolicy::Minimum );
    layout->addItem( spacer_left, 1,0 );
    QSpacerItem* spacer_top = new QSpacerItem( 10,10, QSizePolicy::Minimum, QSizePolicy::Fixed );
    layout->addItem(spacer_top,0,1);

    ingredientListView=new KListView (this);
    layout->addMultiCellWidget (ingredientListView,1,4,1,1);
    ingredientListView->addColumn("Id");
    ingredientListView->addColumn("Ingredient");
    ingredientListView->setSizePolicy(QSizePolicy(QSizePolicy::Fixed,QSizePolicy::MinimumExpanding));

    QSpacerItem* spacer_rightIngredients = new QSpacerItem( 5,5, QSizePolicy::Fixed, QSizePolicy::Minimum );
    layout->addItem(spacer_rightIngredients,1,2);

    addIngredientButton = new QPushButton( this);
    addIngredientButton->setText("+");
    layout->addWidget( addIngredientButton, 1, 3 );
    addIngredientButton->setMinimumSize(QSize(30,30));
    addIngredientButton->setMaximumSize(QSize(30,30));
    addIngredientButton->setSizePolicy(QSizePolicy(QSizePolicy::Fixed,QSizePolicy::Fixed));
    addIngredientButton->setFlat(true);

    removeIngredientButton = new QPushButton( this);
    removeIngredientButton->setText("-");
    layout->addWidget( removeIngredientButton, 3, 3 );
    removeIngredientButton->setMinimumSize(QSize(30,30));
    removeIngredientButton->setMaximumSize(QSize(30,30));
    removeIngredientButton->setSizePolicy(QSizePolicy(QSizePolicy::Fixed,QSizePolicy::Fixed));
    removeIngredientButton->setFlat(true);

    QSpacerItem* spacer_Ing_Buttons = new QSpacerItem( 5,5, QSizePolicy::Minimum, QSizePolicy::Fixed );
    layout->addItem(spacer_Ing_Buttons,2,3);

    QSpacerItem* spacer_Ing_Units = new QSpacerItem( 30,5, QSizePolicy::Fixed, QSizePolicy::Minimum );
    layout->addItem(spacer_Ing_Units,1,4);

    unitsListView=new KListView (this);
    unitsListView->addColumn("i.");
    unitsListView->addColumn("Units");
    layout->addMultiCellWidget (unitsListView,1,4,5,5);
    unitsListView->setSizePolicy(QSizePolicy(QSizePolicy::Fixed,QSizePolicy::MinimumExpanding));

    QSpacerItem* spacer_rightUnits = new QSpacerItem( 5,5, QSizePolicy::Fixed, QSizePolicy::Minimum );
    layout->addItem(spacer_rightUnits,1,6);

    addUnitButton = new QPushButton( this);
    addUnitButton->setText("+");
    layout->addWidget( addUnitButton, 1, 7 );
    addUnitButton->resize(QSize(30,30));
    addUnitButton->setMinimumSize(QSize(30,30));
    addUnitButton->setMaximumSize(QSize(30,30));
    addUnitButton->setSizePolicy(QSizePolicy(QSizePolicy::Fixed,QSizePolicy::Fixed));
    addUnitButton->setFlat(true);

    removeUnitButton = new QPushButton( this);
    removeUnitButton->setText("-");
    layout->addWidget( removeUnitButton, 3, 7 );
    removeUnitButton->resize(QSize(30,30));
    removeUnitButton->setMinimumSize(QSize(30,30));
    removeUnitButton->setMaximumSize(QSize(30,30));
    removeUnitButton->setSizePolicy(QSizePolicy(QSizePolicy::Fixed,QSizePolicy::Fixed));
    removeUnitButton->setFlat(true);
    QSpacerItem* spacer_Units_Properties = new QSpacerItem( 30,5, QSizePolicy::Fixed, QSizePolicy::Minimum );
    layout->addItem(spacer_Units_Properties,1,8);

    propertiesListView=new KListView (this);
    layout->addMultiCellWidget (propertiesListView,1,4,9,9);
    propertiesListView->addColumn("Id");
    propertiesListView->addColumn("Property");
    propertiesListView->addColumn("Amount");
    propertiesListView->addColumn("units");
    propertiesListView->setAllColumnsShowFocus(true);
    propertiesListView->setSizePolicy(QSizePolicy(QSizePolicy::MinimumExpanding,QSizePolicy::MinimumExpanding));

    QSpacerItem* spacer_rightProperties= new QSpacerItem(5,5,QSizePolicy::Fixed,QSizePolicy::Minimum);
    layout->addItem(spacer_rightProperties,1,10);

    addPropertyButton= new QPushButton(this);
    addPropertyButton->setText("+");
    layout->addWidget( addPropertyButton, 1, 11 );
    addPropertyButton->resize(QSize(30,30));
    addPropertyButton->setMinimumSize(QSize(30,30));
    addPropertyButton->setMaximumSize(QSize(30,30));
    addPropertyButton->setSizePolicy(QSizePolicy(QSizePolicy::Fixed,QSizePolicy::Fixed));
    addPropertyButton->setFlat(true);

    removePropertyButton=new QPushButton(this);
    removePropertyButton->setText("-");
    layout->addWidget( removePropertyButton, 3, 11 );
    removePropertyButton->resize(QSize(30,30));
    removePropertyButton->setMinimumSize(QSize(30,30));
    removePropertyButton->setMaximumSize(QSize(30,30));
    removePropertyButton->setSizePolicy(QSizePolicy(QSizePolicy::Fixed,QSizePolicy::Fixed));
    removePropertyButton->setFlat(true);

    inputBox=new EditBox(this);
    inputBox->hide();

    // Initialize
    ingredientList =new ElementList;
    unitList=new ElementList;
    reloadIngredientList();

    // Signals & Slots
    connect(this->ingredientListView,SIGNAL(selectionChanged()),this, SLOT(updateLists()));
    connect(this->addIngredientButton,SIGNAL(clicked()),this,SLOT(addIngredient()));
    connect(this->addUnitButton,SIGNAL(clicked()),this,SLOT(addUnitToIngredient()));
    connect(this->removeUnitButton,SIGNAL(clicked()),this,SLOT(removeUnitFromIngredient()));
    connect(this->removeIngredientButton,SIGNAL(clicked()),this,SLOT(removeIngredient()));
    connect(this->addPropertyButton,SIGNAL(clicked()),this,SLOT(addPropertyToIngredient()));
    connect(this->removePropertyButton,SIGNAL(clicked()),this,SLOT(removePropertyFromIngredient()));
    connect(this->propertiesListView,SIGNAL(executed(QListViewItem*)),this,SLOT(insertPropertyEditBox(QListViewItem*)));
    connect(this->inputBox,SIGNAL(valueChanged(double)),this,SLOT(setPropertyAmount(double)));
}

IngredientsDialog::~IngredientsDialog()
{

}

void IngredientsDialog::reloadIngredientList(void)
{
ingredientListView->clear();
ingredientList->clear();
database->loadIngredients(ingredientList);

//Populate this data into the KListView

	for ( Element *ing =ingredientList->getFirst(); ing; ing =ingredientList->getNext() )
	{
	QListViewItem *it= new QListViewItem(ingredientListView,QString::number(ing->id),ing->name);
	}

// Reload Unit List
updateLists();

}

void IngredientsDialog::reloadUnitList()
{

int ingredientID=-1;
// Find selected ingredient
QListViewItem *it; it=ingredientListView->selectedItem();

if (it){  // Check if an ingredient is selected first
ingredientID=it->text(0).toInt();
}

unitList->clear();
unitsListView->clear();

if (ingredientID>=0)
{
database->loadPossibleUnits(ingredientID,unitList);

//Populate this data into the KListView

	for ( Element *unit =unitList->getFirst(); unit; unit =unitList->getNext() )
	{
	QListViewItem *uit= new QListViewItem(unitsListView,QString::number(unit->id),unit->name);
	}

// Select the first unit
unitsListView->setSelected(unitsListView->firstChild(),true);

}
}

void IngredientsDialog::addIngredient(void)
{
CreateElementDialog* elementDialog=new CreateElementDialog(QString("New Ingredient"));

if ( elementDialog->exec() == QDialog::Accepted ) {
   QString result = elementDialog->newElementName();
   database->createNewIngredient(result); // Create the new ingredient in database
   reloadIngredientList(); // Reload the list from database
}
delete elementDialog;
}

void IngredientsDialog::addUnitToIngredient(void)
{

// Find selected ingredient item
QListViewItem *it;
int ingredientID=-1;
if (it=ingredientListView->selectedItem())
  {
  ingredientID=it->text(0).toInt();
  }
if (ingredientID>=0) // an ingredient was selected previously
{
  ElementList allUnits;
  database->loadUnits(&allUnits);

  SelectUnitDialog* unitsDialog=new SelectUnitDialog(0,&allUnits);

  if ( unitsDialog->exec() == QDialog::Accepted ) {
    int result = unitsDialog->unitID();
    database->AddUnitToIngredient(ingredientID,result); // Add result chosen unit to ingredient in database
    reloadUnitList(); // Reload the list from database
}
}
}

void IngredientsDialog::removeUnitFromIngredient(void)
{

// Find selected ingredient/unit item combination
QListViewItem *it;
int ingredientID=-1, unitID=-1;
if (it=ingredientListView->selectedItem()) ingredientID=it->text(0).toInt();
if (it=unitsListView->selectedItem()) unitID=it->text(0).toInt();

if ((ingredientID>=0)&&(unitID>=0)) // an ingredient/unit combination was selected previously
{
  ElementList results;
  database->findUseOf_Ing_Unit_InRecipes(&results,ingredientID,unitID); // Find if this ingredient-unit combination is being used
  if (results.isEmpty()) database->removeUnitFromIngredient(ingredientID,unitID);
  else database->removeUnitFromIngredient(ingredientID,unitID); //must warn!

reloadUnitList(); // Reload the list from database

}
}

void IngredientsDialog::removeIngredient(void)
{
// Find selected ingredient item
QListViewItem *it;
int ingredientID=-1;
if (it=ingredientListView->selectedItem()) ingredientID=it->text(0).toInt();

if (ingredientID>=0) // an ingredient/unit combination was selected previously
{
ElementList results;
database->findUseOfIngInRecipes(&results,ingredientID);
if (results.isEmpty()) database->removeIngredient(ingredientID);
else database->removeIngredient(ingredientID);

reloadIngredientList();// Reload the list from database

}

}

void IngredientsDialog:: reloadPropertyList(void)
{
propertiesList->clear();
propertiesListView->clear();
perUnitListBack->clear();

//If none is selected, select first item
QListViewItem *it;
it=ingredientListView->selectedItem();

//Populate this data into the KListView
if (it){// make sure that the ingredient list is not empty

	database->loadProperties(propertiesList,it->text(0).toInt()); // load the list for this ingredient
	for ( IngredientProperty *prop =propertiesList->getFirst(); prop; prop =propertiesList->getNext() )
	{
	  QListViewItem *it= new QListViewItem(propertiesListView,QString::number(prop->id),prop->name,QString::number(prop->amount),prop->units+QString("/")+prop->perUnit.name);
	  // Store the perUnits with the ID for using later
	  Element perUnitEl;
	  perUnitEl.id=prop->perUnit.id;
	  perUnitEl.name=prop->perUnit.name;
	  perUnitListBack->add(perUnitEl);

	}
	}
}

void IngredientsDialog:: updateLists(void)
{

//If no ingredient is selected, select first item

QListViewItem *it;
if (!(it=ingredientListView->selectedItem()))
{
it=ingredientListView->firstChild();
}

reloadUnitList();
reloadPropertyList();
}

void IngredientsDialog::addPropertyToIngredient(void)
{

// Find selected ingredient item
QListViewItem *it;
int ingredientID=-1;
if (it=ingredientListView->selectedItem())
  {
  ingredientID=it->text(0).toInt();
  }
if (ingredientID>=0) // an ingredient was selected previously
{
 IngredientPropertyList allProperties; database->loadProperties(&allProperties);
 ElementList unitList; database->loadPossibleUnits(ingredientID,&unitList);
 SelectPropertyDialog* propertyDialog=new SelectPropertyDialog(0,&allProperties,&unitList);

 if ( propertyDialog->exec() == QDialog::Accepted ) {
    int propertyID = propertyDialog->propertyID();
    int perUnitsID = propertyDialog->perUnitsID();
    database->addPropertyToIngredient(ingredientID,propertyID,0,perUnitsID); // Add result chosen property to ingredient in database, with amount 0 by default
    reloadPropertyList(); // Reload the list from database
}
}
}

void IngredientsDialog::removePropertyFromIngredient(void)
{

// Find selected ingredient/property item combination
QListViewItem *it;
int ingredientID=-1, propertyID=-1;
if (it=ingredientListView->selectedItem()) ingredientID=it->text(0).toInt();
if (it=propertiesListView->selectedItem()) propertyID=it->text(0).toInt();

if ((ingredientID>=0)&&(propertyID>=0)) // an ingredient/property combination was selected previously
{
  ElementList results;
  database->removePropertyFromIngredient(ingredientID,propertyID);

reloadPropertyList(); // Reload the list from database

}
}

void IngredientsDialog::insertPropertyEditBox(QListViewItem* it)
{

QRect r;

r=propertiesListView->header()->sectionRect(2); //Set in position reference to qlistview, and with the column size();

r.moveBy(propertiesListView->pos().x(),propertiesListView->pos().y()); // Move to the position of qlistview
r.moveBy(0,r.height()+propertiesListView->itemRect(it).y()); //Move down to the item, note that its height is same as header's right now.

r.setHeight(it->height()); // Set the item's height

inputBox->setGeometry(r);
inputBox->show();
}

void IngredientsDialog::setPropertyAmount(double amount)
{

inputBox->hide();

QListViewItem *ing_it=ingredientListView->selectedItem(); // Find selected ingredient
QListViewItem *prop_it=propertiesListView->selectedItem();

if (ing_it && prop_it)// Appart from property, Check if an ingredient is selected first, just in case
{
prop_it->setText(2,QString::number(amount));
int propertyID=prop_it->text(0).toInt();
int ingredientID=ing_it->text(0).toInt();
int per_units=perUnitListBack->getElement(findPropertyNo(prop_it))->id ;
database->changePropertyAmountToIngredient(ingredientID,propertyID,amount,per_units);
}

reloadPropertyList();

}

int IngredientsDialog::findPropertyNo(QListViewItem *it)
{
bool found=false;
int i = 0;
QListViewItem* item = propertiesListView->firstChild();
while (i < propertiesListView->childCount() && !found) {
  if (item == propertiesListView->currentItem())
    found = true;
  else {
    item = item->nextSibling();
    ++i;
  }
}
if (found)
  {
  return (i);
  }
else
  {
  return (-1);
  }
}<commit_msg>Actually remove the properties using ingredient+unit combination, if a unit is ddisabled (removed) from that ingredient. The query execution was missing.<commit_after>/***************************************************************************
 *   Copyright (C) 2003 by Unai Garro                                      *
 *   uga@ee.ed.ac.uk                                                       *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 ***************************************************************************/
#include "ingredientsdialog.h"
#include <qheader.h>

IngredientsDialog::IngredientsDialog(QWidget* parent, RecipeDB *db):QWidget(parent)
{

    // Store pointer to database
    database=db;

    // Initialize internal variables
    propertiesList= new IngredientPropertyList;
    perUnitListBack= new ElementList;

    // Design dialog

    layout = new QGridLayout( this, 1, 1, 0, 0);
    QSpacerItem* spacer_left = new QSpacerItem( 10,10, QSizePolicy::Fixed, QSizePolicy::Minimum );
    layout->addItem( spacer_left, 1,0 );
    QSpacerItem* spacer_top = new QSpacerItem( 10,10, QSizePolicy::Minimum, QSizePolicy::Fixed );
    layout->addItem(spacer_top,0,1);

    ingredientListView=new KListView (this);
    layout->addMultiCellWidget (ingredientListView,1,4,1,1);
    ingredientListView->addColumn("Id");
    ingredientListView->addColumn("Ingredient");
    ingredientListView->setSizePolicy(QSizePolicy(QSizePolicy::Fixed,QSizePolicy::MinimumExpanding));

    QSpacerItem* spacer_rightIngredients = new QSpacerItem( 5,5, QSizePolicy::Fixed, QSizePolicy::Minimum );
    layout->addItem(spacer_rightIngredients,1,2);

    addIngredientButton = new QPushButton( this);
    addIngredientButton->setText("+");
    layout->addWidget( addIngredientButton, 1, 3 );
    addIngredientButton->setMinimumSize(QSize(30,30));
    addIngredientButton->setMaximumSize(QSize(30,30));
    addIngredientButton->setSizePolicy(QSizePolicy(QSizePolicy::Fixed,QSizePolicy::Fixed));
    addIngredientButton->setFlat(true);

    removeIngredientButton = new QPushButton( this);
    removeIngredientButton->setText("-");
    layout->addWidget( removeIngredientButton, 3, 3 );
    removeIngredientButton->setMinimumSize(QSize(30,30));
    removeIngredientButton->setMaximumSize(QSize(30,30));
    removeIngredientButton->setSizePolicy(QSizePolicy(QSizePolicy::Fixed,QSizePolicy::Fixed));
    removeIngredientButton->setFlat(true);

    QSpacerItem* spacer_Ing_Buttons = new QSpacerItem( 5,5, QSizePolicy::Minimum, QSizePolicy::Fixed );
    layout->addItem(spacer_Ing_Buttons,2,3);

    QSpacerItem* spacer_Ing_Units = new QSpacerItem( 30,5, QSizePolicy::Fixed, QSizePolicy::Minimum );
    layout->addItem(spacer_Ing_Units,1,4);

    unitsListView=new KListView (this);
    unitsListView->addColumn("i.");
    unitsListView->addColumn("Units");
    layout->addMultiCellWidget (unitsListView,1,4,5,5);
    unitsListView->setSizePolicy(QSizePolicy(QSizePolicy::Fixed,QSizePolicy::MinimumExpanding));

    QSpacerItem* spacer_rightUnits = new QSpacerItem( 5,5, QSizePolicy::Fixed, QSizePolicy::Minimum );
    layout->addItem(spacer_rightUnits,1,6);

    addUnitButton = new QPushButton( this);
    addUnitButton->setText("+");
    layout->addWidget( addUnitButton, 1, 7 );
    addUnitButton->resize(QSize(30,30));
    addUnitButton->setMinimumSize(QSize(30,30));
    addUnitButton->setMaximumSize(QSize(30,30));
    addUnitButton->setSizePolicy(QSizePolicy(QSizePolicy::Fixed,QSizePolicy::Fixed));
    addUnitButton->setFlat(true);

    removeUnitButton = new QPushButton( this);
    removeUnitButton->setText("-");
    layout->addWidget( removeUnitButton, 3, 7 );
    removeUnitButton->resize(QSize(30,30));
    removeUnitButton->setMinimumSize(QSize(30,30));
    removeUnitButton->setMaximumSize(QSize(30,30));
    removeUnitButton->setSizePolicy(QSizePolicy(QSizePolicy::Fixed,QSizePolicy::Fixed));
    removeUnitButton->setFlat(true);
    QSpacerItem* spacer_Units_Properties = new QSpacerItem( 30,5, QSizePolicy::Fixed, QSizePolicy::Minimum );
    layout->addItem(spacer_Units_Properties,1,8);

    propertiesListView=new KListView (this);
    layout->addMultiCellWidget (propertiesListView,1,4,9,9);
    propertiesListView->addColumn("Id");
    propertiesListView->addColumn("Property");
    propertiesListView->addColumn("Amount");
    propertiesListView->addColumn("units");
    propertiesListView->setAllColumnsShowFocus(true);
    propertiesListView->setSizePolicy(QSizePolicy(QSizePolicy::MinimumExpanding,QSizePolicy::MinimumExpanding));

    QSpacerItem* spacer_rightProperties= new QSpacerItem(5,5,QSizePolicy::Fixed,QSizePolicy::Minimum);
    layout->addItem(spacer_rightProperties,1,10);

    addPropertyButton= new QPushButton(this);
    addPropertyButton->setText("+");
    layout->addWidget( addPropertyButton, 1, 11 );
    addPropertyButton->resize(QSize(30,30));
    addPropertyButton->setMinimumSize(QSize(30,30));
    addPropertyButton->setMaximumSize(QSize(30,30));
    addPropertyButton->setSizePolicy(QSizePolicy(QSizePolicy::Fixed,QSizePolicy::Fixed));
    addPropertyButton->setFlat(true);

    removePropertyButton=new QPushButton(this);
    removePropertyButton->setText("-");
    layout->addWidget( removePropertyButton, 3, 11 );
    removePropertyButton->resize(QSize(30,30));
    removePropertyButton->setMinimumSize(QSize(30,30));
    removePropertyButton->setMaximumSize(QSize(30,30));
    removePropertyButton->setSizePolicy(QSizePolicy(QSizePolicy::Fixed,QSizePolicy::Fixed));
    removePropertyButton->setFlat(true);

    inputBox=new EditBox(this);
    inputBox->hide();

    // Initialize
    ingredientList =new ElementList;
    unitList=new ElementList;
    reloadIngredientList();

    // Signals & Slots
    connect(this->ingredientListView,SIGNAL(selectionChanged()),this, SLOT(updateLists()));
    connect(this->addIngredientButton,SIGNAL(clicked()),this,SLOT(addIngredient()));
    connect(this->addUnitButton,SIGNAL(clicked()),this,SLOT(addUnitToIngredient()));
    connect(this->removeUnitButton,SIGNAL(clicked()),this,SLOT(removeUnitFromIngredient()));
    connect(this->removeIngredientButton,SIGNAL(clicked()),this,SLOT(removeIngredient()));
    connect(this->addPropertyButton,SIGNAL(clicked()),this,SLOT(addPropertyToIngredient()));
    connect(this->removePropertyButton,SIGNAL(clicked()),this,SLOT(removePropertyFromIngredient()));
    connect(this->propertiesListView,SIGNAL(executed(QListViewItem*)),this,SLOT(insertPropertyEditBox(QListViewItem*)));
    connect(this->inputBox,SIGNAL(valueChanged(double)),this,SLOT(setPropertyAmount(double)));
}

IngredientsDialog::~IngredientsDialog()
{

}

void IngredientsDialog::reloadIngredientList(void)
{
ingredientListView->clear();
ingredientList->clear();
database->loadIngredients(ingredientList);

//Populate this data into the KListView

	for ( Element *ing =ingredientList->getFirst(); ing; ing =ingredientList->getNext() )
	{
	QListViewItem *it= new QListViewItem(ingredientListView,QString::number(ing->id),ing->name);
	}

// Reload Unit List
updateLists();

}

void IngredientsDialog::reloadUnitList()
{

int ingredientID=-1;
// Find selected ingredient
QListViewItem *it; it=ingredientListView->selectedItem();

if (it){  // Check if an ingredient is selected first
ingredientID=it->text(0).toInt();
}

unitList->clear();
unitsListView->clear();

if (ingredientID>=0)
{
database->loadPossibleUnits(ingredientID,unitList);

//Populate this data into the KListView

	for ( Element *unit =unitList->getFirst(); unit; unit =unitList->getNext() )
	{
	QListViewItem *uit= new QListViewItem(unitsListView,QString::number(unit->id),unit->name);
	}

// Select the first unit
unitsListView->setSelected(unitsListView->firstChild(),true);

}
}

void IngredientsDialog::addIngredient(void)
{
CreateElementDialog* elementDialog=new CreateElementDialog(QString("New Ingredient"));

if ( elementDialog->exec() == QDialog::Accepted ) {
   QString result = elementDialog->newElementName();
   database->createNewIngredient(result); // Create the new ingredient in database
   reloadIngredientList(); // Reload the list from database
}
delete elementDialog;
}

void IngredientsDialog::addUnitToIngredient(void)
{

// Find selected ingredient item
QListViewItem *it;
int ingredientID=-1;
if (it=ingredientListView->selectedItem())
  {
  ingredientID=it->text(0).toInt();
  }
if (ingredientID>=0) // an ingredient was selected previously
{
  ElementList allUnits;
  database->loadUnits(&allUnits);

  SelectUnitDialog* unitsDialog=new SelectUnitDialog(0,&allUnits);

  if ( unitsDialog->exec() == QDialog::Accepted ) {
    int result = unitsDialog->unitID();
    database->AddUnitToIngredient(ingredientID,result); // Add result chosen unit to ingredient in database
    reloadUnitList(); // Reload the list from database
}
}
}

void IngredientsDialog::removeUnitFromIngredient(void)
{

// Find selected ingredient/unit item combination
QListViewItem *it;
int ingredientID=-1, unitID=-1;
if (it=ingredientListView->selectedItem()) ingredientID=it->text(0).toInt();
if (it=unitsListView->selectedItem()) unitID=it->text(0).toInt();

if ((ingredientID>=0)&&(unitID>=0)) // an ingredient/unit combination was selected previously
{
  ElementList results;
  database->findUseOf_Ing_Unit_InRecipes(&results,ingredientID,unitID); // Find if this ingredient-unit combination is being used
  if (results.isEmpty()) database->removeUnitFromIngredient(ingredientID,unitID);
  else database->removeUnitFromIngredient(ingredientID,unitID); //must warn!

reloadUnitList(); // Reload the list from database
reloadPropertyList(); // Properties could have been removed if a unit is removed, so we need to reload.
}
}

void IngredientsDialog::removeIngredient(void)
{
// Find selected ingredient item
QListViewItem *it;
int ingredientID=-1;
if (it=ingredientListView->selectedItem()) ingredientID=it->text(0).toInt();

if (ingredientID>=0) // an ingredient/unit combination was selected previously
{
ElementList results;
database->findUseOfIngInRecipes(&results,ingredientID);
if (results.isEmpty()) database->removeIngredient(ingredientID);
else database->removeIngredient(ingredientID);

reloadIngredientList();// Reload the list from database

}

}

void IngredientsDialog:: reloadPropertyList(void)
{
propertiesList->clear();
propertiesListView->clear();
perUnitListBack->clear();

//If none is selected, select first item
QListViewItem *it;
it=ingredientListView->selectedItem();

//Populate this data into the KListView
if (it){// make sure that the ingredient list is not empty

	database->loadProperties(propertiesList,it->text(0).toInt()); // load the list for this ingredient
	for ( IngredientProperty *prop =propertiesList->getFirst(); prop; prop =propertiesList->getNext() )
	{
	  QListViewItem *it= new QListViewItem(propertiesListView,QString::number(prop->id),prop->name,QString::number(prop->amount),prop->units+QString("/")+prop->perUnit.name);
	  // Store the perUnits with the ID for using later
	  Element perUnitEl;
	  perUnitEl.id=prop->perUnit.id;
	  perUnitEl.name=prop->perUnit.name;
	  perUnitListBack->add(perUnitEl);

	}
	}
}

void IngredientsDialog:: updateLists(void)
{

//If no ingredient is selected, select first item

QListViewItem *it;
if (!(it=ingredientListView->selectedItem()))
{
it=ingredientListView->firstChild();
}

reloadUnitList();
reloadPropertyList();
}

void IngredientsDialog::addPropertyToIngredient(void)
{

// Find selected ingredient item
QListViewItem *it;
int ingredientID=-1;
if (it=ingredientListView->selectedItem())
  {
  ingredientID=it->text(0).toInt();
  }
if (ingredientID>=0) // an ingredient was selected previously
{
 IngredientPropertyList allProperties; database->loadProperties(&allProperties);
 ElementList unitList; database->loadPossibleUnits(ingredientID,&unitList);
 SelectPropertyDialog* propertyDialog=new SelectPropertyDialog(0,&allProperties,&unitList);

 if ( propertyDialog->exec() == QDialog::Accepted ) {
    int propertyID = propertyDialog->propertyID();
    int perUnitsID = propertyDialog->perUnitsID();
    database->addPropertyToIngredient(ingredientID,propertyID,0,perUnitsID); // Add result chosen property to ingredient in database, with amount 0 by default
    reloadPropertyList(); // Reload the list from database
}
}
}

void IngredientsDialog::removePropertyFromIngredient(void)
{

// Find selected ingredient/property item combination
QListViewItem *it;
int ingredientID=-1, propertyID=-1;
if (it=ingredientListView->selectedItem()) ingredientID=it->text(0).toInt();
if (it=propertiesListView->selectedItem()) propertyID=it->text(0).toInt();

if ((ingredientID>=0)&&(propertyID>=0)) // an ingredient/property combination was selected previously
{
  ElementList results;
  database->removePropertyFromIngredient(ingredientID,propertyID);

reloadPropertyList(); // Reload the list from database

}
}

void IngredientsDialog::insertPropertyEditBox(QListViewItem* it)
{

QRect r;

r=propertiesListView->header()->sectionRect(2); //Set in position reference to qlistview, and with the column size();

r.moveBy(propertiesListView->pos().x(),propertiesListView->pos().y()); // Move to the position of qlistview
r.moveBy(0,r.height()+propertiesListView->itemRect(it).y()); //Move down to the item, note that its height is same as header's right now.

r.setHeight(it->height()); // Set the item's height

inputBox->setGeometry(r);
inputBox->show();
}

void IngredientsDialog::setPropertyAmount(double amount)
{

inputBox->hide();

QListViewItem *ing_it=ingredientListView->selectedItem(); // Find selected ingredient
QListViewItem *prop_it=propertiesListView->selectedItem();

if (ing_it && prop_it)// Appart from property, Check if an ingredient is selected first, just in case
{
prop_it->setText(2,QString::number(amount));
int propertyID=prop_it->text(0).toInt();
int ingredientID=ing_it->text(0).toInt();
int per_units=perUnitListBack->getElement(findPropertyNo(prop_it))->id ;
database->changePropertyAmountToIngredient(ingredientID,propertyID,amount,per_units);
}

reloadPropertyList();

}

int IngredientsDialog::findPropertyNo(QListViewItem *it)
{
bool found=false;
int i = 0;
QListViewItem* item = propertiesListView->firstChild();
while (i < propertiesListView->childCount() && !found) {
  if (item == propertiesListView->currentItem())
    found = true;
  else {
    item = item->nextSibling();
    ++i;
  }
}
if (found)
  {
  return (i);
  }
else
  {
  return (-1);
  }
}<|endoftext|>


<commit_before>/*
 * Copyright 2007-2020 CM4all GmbH
 * All rights reserved.
 *
 * author: Max Kellermann <mk@cm4all.com>
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * - Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the
 * distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
 * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "Server.hxx"
#include "net/SocketConfig.hxx"
#include "net/SocketAddress.hxx"
#include "net/SendMessage.hxx"
#include "util/ByteOrder.hxx"
#include "util/ConstBuffer.hxx"
#include "util/RuntimeError.hxx"
#include "util/WritableBuffer.hxx"

#include <stdexcept>

#include <assert.h>
#include <string.h>
#include <alloca.h>

ControlServer::ControlServer(EventLoop &event_loop, UniqueSocketDescriptor s,
			     ControlHandler &_handler) noexcept
	:handler(_handler), socket(event_loop, std::move(s), *this)
{
}

ControlServer::ControlServer(EventLoop &event_loop, ControlHandler &_handler,
			     const SocketConfig &config)
	:ControlServer(event_loop, config.Create(SOCK_DGRAM), _handler)
{
}

static void
control_server_decode(ControlServer &control_server,
		      const void *data, size_t length,
		      WritableBuffer<UniqueFileDescriptor> fds,
		      SocketAddress address, int uid,
		      ControlHandler &handler)
{
	/* verify the magic number */

	const uint32_t *magic = (const uint32_t *)data;

	if (length < sizeof(*magic) || FromBE32(*magic) != BengProxy::control_magic) {
		handler.OnControlError(std::make_exception_ptr(std::runtime_error("wrong magic")));
		return;
	}

	data = magic + 1;
	length -= sizeof(*magic);

	if (length % 4 != 0) {
		handler.OnControlError(std::make_exception_ptr(FormatRuntimeError("odd control packet (length=%zu)", length)));
		return;
	}

	/* now decode all commands */

	while (length > 0) {
		const auto *header = (const BengProxy::ControlHeader *)data;
		if (length < sizeof(*header)) {
			handler.OnControlError(std::make_exception_ptr(FormatRuntimeError("partial header (length=%zu)",
											  length)));
			return;
		}

		size_t payload_length = FromBE16(header->length);
		const auto command = (BengProxy::ControlCommand)
			FromBE16(header->command);

		data = header + 1;
		length -= sizeof(*header);

		const char *payload = (const char *)data;
		if (length < payload_length) {
			handler.OnControlError(std::make_exception_ptr(FormatRuntimeError("partial payload (length=%zu, expected=%zu)",
											  length, payload_length)));
			return;
		}

		/* this command is ok, pass it to the callback */

		handler.OnControlPacket(control_server, command,
					{payload_length > 0 ? payload : nullptr, payload_length},
					fds,
					address, uid);

		payload_length = ((payload_length + 3) | 3) - 3; /* apply padding */

		data = payload + payload_length;
		length -= payload_length;
	}
}

bool
ControlServer::OnUdpDatagram(ConstBuffer<void> payload,
			     WritableBuffer<UniqueFileDescriptor> fds,
			     SocketAddress address, int uid)
{
	if (!handler.OnControlRaw(payload, address, uid))
		/* discard datagram if raw() returns false */
		return true;

	control_server_decode(*this, payload.data, payload.size,
			      fds, address, uid, handler);
	return true;
}

void
ControlServer::OnUdpError(std::exception_ptr ep) noexcept
{
	handler.OnControlError(ep);
}

void
ControlServer::Reply(SocketAddress address,
		     BengProxy::ControlCommand command,
		     const void *payload, size_t payload_length)
{
	const struct BengProxy::ControlHeader header{ToBE16(payload_length), ToBE16(uint16_t(command))};

	struct iovec v[] = {
		{ const_cast<BengProxy::ControlHeader *>(&header), sizeof(header) },
		{ const_cast<void *>(payload), payload_length },
	};

	SendMessage(socket.GetSocket(),
		    MessageHeader(ConstBuffer<struct iovec>(v, std::size(v)))
		    .SetAddress(address),
		    MSG_DONTWAIT|MSG_NOSIGNAL);
}
<commit_msg>control/Server: throw instead of invoking OnControlError()<commit_after>/*
 * Copyright 2007-2020 CM4all GmbH
 * All rights reserved.
 *
 * author: Max Kellermann <mk@cm4all.com>
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * - Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the
 * distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
 * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "Server.hxx"
#include "net/SocketConfig.hxx"
#include "net/SocketAddress.hxx"
#include "net/SendMessage.hxx"
#include "util/ByteOrder.hxx"
#include "util/ConstBuffer.hxx"
#include "util/RuntimeError.hxx"
#include "util/WritableBuffer.hxx"

#include <stdexcept>

#include <assert.h>
#include <string.h>
#include <alloca.h>

ControlServer::ControlServer(EventLoop &event_loop, UniqueSocketDescriptor s,
			     ControlHandler &_handler) noexcept
	:handler(_handler), socket(event_loop, std::move(s), *this)
{
}

ControlServer::ControlServer(EventLoop &event_loop, ControlHandler &_handler,
			     const SocketConfig &config)
	:ControlServer(event_loop, config.Create(SOCK_DGRAM), _handler)
{
}

static void
control_server_decode(ControlServer &control_server,
		      const void *data, size_t length,
		      WritableBuffer<UniqueFileDescriptor> fds,
		      SocketAddress address, int uid,
		      ControlHandler &handler)
{
	/* verify the magic number */

	const uint32_t *magic = (const uint32_t *)data;

	if (length < sizeof(*magic) || FromBE32(*magic) != BengProxy::control_magic)
		throw std::runtime_error("wrong magic");

	data = magic + 1;
	length -= sizeof(*magic);

	if (length % 4 != 0)
		throw FormatRuntimeError("odd control packet (length=%zu)", length);

	/* now decode all commands */

	while (length > 0) {
		const auto *header = (const BengProxy::ControlHeader *)data;
		if (length < sizeof(*header))
			throw FormatRuntimeError("partial header (length=%zu)",
						 length);

		size_t payload_length = FromBE16(header->length);
		const auto command = (BengProxy::ControlCommand)
			FromBE16(header->command);

		data = header + 1;
		length -= sizeof(*header);

		const char *payload = (const char *)data;
		if (length < payload_length)
			throw FormatRuntimeError("partial payload (length=%zu, expected=%zu)",
						 length, payload_length);

		/* this command is ok, pass it to the callback */

		handler.OnControlPacket(control_server, command,
					{payload_length > 0 ? payload : nullptr, payload_length},
					fds,
					address, uid);

		payload_length = ((payload_length + 3) | 3) - 3; /* apply padding */

		data = payload + payload_length;
		length -= payload_length;
	}
}

bool
ControlServer::OnUdpDatagram(ConstBuffer<void> payload,
			     WritableBuffer<UniqueFileDescriptor> fds,
			     SocketAddress address, int uid)
{
	if (!handler.OnControlRaw(payload, address, uid))
		/* discard datagram if raw() returns false */
		return true;

	control_server_decode(*this, payload.data, payload.size,
			      fds, address, uid, handler);
	return true;
}

void
ControlServer::OnUdpError(std::exception_ptr ep) noexcept
{
	handler.OnControlError(ep);
}

void
ControlServer::Reply(SocketAddress address,
		     BengProxy::ControlCommand command,
		     const void *payload, size_t payload_length)
{
	const struct BengProxy::ControlHeader header{ToBE16(payload_length), ToBE16(uint16_t(command))};

	struct iovec v[] = {
		{ const_cast<BengProxy::ControlHeader *>(&header), sizeof(header) },
		{ const_cast<void *>(payload), payload_length },
	};

	SendMessage(socket.GetSocket(),
		    MessageHeader(ConstBuffer<struct iovec>(v, std::size(v)))
		    .SetAddress(address),
		    MSG_DONTWAIT|MSG_NOSIGNAL);
}
<|endoftext|>


<commit_before>#ifndef _C4_TYPES_HPP_
#define _C4_TYPES_HPP_

#include <stdint.h>
#include <stddef.h>
#include <type_traits>

/** @file types.hpp basic types, and utility macros and traits for types.
 * @ingroup basic_headers */

C4_BEGIN_NAMESPACE(c4)

using i8 = int8_t;
using u8 = uint8_t;
using i16 = int16_t;
using u16 = uint16_t;
using i32 = int32_t;
using u32 = uint32_t;
using i64 = int64_t;
using u64 = uint64_t;

using f32 = float;
using f64 = double;

using ssize_t = std::make_signed< size_t >::type;

//--------------------------------------------------

// some tag types

/** a tag type for initializing the containers with variadic arguments a la
 * initializer_list, minus the initializer_list overload problems.
 * @see */
struct aggregate_t {};
/** @see aggregate_t */
constexpr const aggregate_t aggregate{};

/** a tag type for specifying the initial capacity of allocatable contiguous storage */
struct with_capacity_t {};
/** @see with_capacity_t */
constexpr const with_capacity_t with_capacity{};

//--------------------------------------------------

/** whether a value should be used in place of a const-reference in argument passing. */
template< class T >
struct cref_uses_val
{
    enum { value = (
    std::is_scalar< T >::value
    ||
    (std::is_pod< T >::value && sizeof(T) <= sizeof(size_t))) };
};
/** utility macro to override the default behaviour for c4::fastcref<T>
 @see fastcref */
#define C4_CREF_USES_VAL(T) \
template<>                  \
struct cref_uses_val< T >   \
{                           \
    enum { value = true };  \
};

/** Whether to use pass-by-value or pass-by-const-reference in a function argument
 * or return type. */
template< class T >
using fastcref = typename std::conditional< c4::cref_uses_val< T >::value, T, T const& >::type;

//--------------------------------------------------
/** a tag type which can be used to disambiguate in variadic template overloads */
struct varargs_t {};
/** a tag variable which can be used to disambiguate in variadic template overloads */
constexpr const varargs_t varargs{};

/** Just what its name says. Useful sometimes as a default empty policy class. */
struct EmptyStruct
{
    template< class... T > EmptyStruct(T && ...){}
};

/** Just what its name says. Useful sometimes as a default policy class to
 * be inherited from. */
struct EmptyStructVirtual
{
    virtual ~EmptyStructVirtual() = default;
    template< class... T > EmptyStructVirtual(T && ...){}
};

/** */
template< class T >
struct inheritfrom : public T {};

//--------------------------------------------------
// Utilities to make a class obey size restrictions (eg, min size or size multiple of).
// DirectX usually makes this restriction with uniform buffers.
// This is also useful for padding to prevent false-sharing.

/** how many bytes must be added to size such that the result is at least minsize? */
C4_ALWAYS_INLINE constexpr size_t min_remainder(size_t size, size_t minsize)
{
    return size < minsize ? minsize-size : 0;
}

/** how many bytes must be added to size such that the result is a multiple of multipleof?  */
C4_ALWAYS_INLINE constexpr size_t mult_remainder(size_t size, size_t multipleof)
{
    return (((size % multipleof) != 0) ? (multipleof-(size % multipleof)) : 0);
}

/** force the following class to be tightly packed.
 * @see http://stackoverflow.com/questions/21092415/force-c-structure-to-pack-tightly */
#pragma pack(push, 1)
/** pad a class with more bytes at the end. */
template< class T, size_t BytesToPadAtEnd >
struct Padded : public T
{
    using T::T;
public:
    char ___c4padspace___[BytesToPadAtEnd];
};
#pragma pack(pop)
/** When the padding argument is 0, we cannot declare the char[] array. */
template< class T >
struct Padded< T, 0 > : public T
{
    using T::T;
};

/** make T have a size which is at least Min bytes */
template< class T, size_t Min >
using MinSized = Padded< T, min_remainder(sizeof(T), Min) >;

/** make T have a size which is a multiple of Mult bytes */
template< class T, size_t Mult >
using MultSized = Padded< T, mult_remainder(sizeof(T), Mult) >;

/** make T have a size which is simultaneously:
 *  -bigger or equal than Min
 *  -a multiple of Mult */
template< class T, size_t Min, size_t Mult >
using MinMultSized = MultSized< MinSized< T, Min >, Mult >;

/** make T be suitable for use as a uniform buffer. (at least with DirectX). */
template< class T >
using UbufSized = MinMultSized< T, 64, 16 >;

//-----------------------------------------------------------------------------

/** SFINAE. use this macro to enable a template function overload
based on a compile-time condition.
@code
// define an overload for a non-pod type
template< class T, C4_REQUIRE_T(std::is_pod< T >::value) >
void foo() { std::cout << "pod type\n"; }

// define an overload for a non-pod type
template< class T, C4_REQUIRE_T(!std::is_pod< T >::value) >
void foo() { std::cout << "nonpod type\n"; }

struct non_pod
{
    non_pod() : name("asdfkjhasdkjh") {}
    const char *name;
};

int main()
{
    foo< float >(); // prints "pod type"
    foo< non_pod >(); // prints "nonpod type"
}
@endcode */
#define C4_REQUIRE_T(cond) typename std::enable_if< cond, bool >::type* = nullptr

/** enable_if for a return type
 * @see C4_REQUIRE_T */
#define C4_REQUIRE_R(cond, type_) typename std::enable_if< cond, type_ >::type

//-----------------------------------------------------------------------------
/** declare a traits class telling whether a type provides a member typedef */
#define C4_DEFINE_HAS_TYPEDEF(member_typedef)                   \
template< typename T >                                          \
struct has_##stype                                              \
{                                                               \
private:                                                        \
                                                                \
    typedef char                      yes;                      \
    typedef struct { char array[2]; } no;                       \
                                                                \
    template< typename C >                                      \
    static yes _test(typename C::member_typedef*);              \
                                                                \
    template< typename C >                                      \
    static no  _test(...);                                      \
                                                                \
public:                                                         \
                                                                \
    enum { value = (sizeof(_test< T >(0)) == sizeof(yes)) };    \
                                                                \
}

//-----------------------------------------------------------------------------
/** declare a traits class telling whether a type provides a method */
#define C4_DEFINE_HAS_METHOD(ret_type, method_name, const_qualifier, ...) \
template< typename T >                                                  \
struct has_##method_name##_method                                       \
{                                                                       \
private:                                                                \
                                                                        \
    typedef char                      &yes;                             \
    typedef struct { char array[2]; } &no;                              \
                                                                        \
    template< typename C >                                              \
    static yes _test                                                    \
    (                                                                   \
        C const_qualifier* v,                                           \
        typename std::enable_if                                         \
        <                                                               \
            std::is_same< decltype(v->method_name(__VA_ARGS__)), ret_type >::value \
            ,                                                           \
            void /* this is defined only if the bool above is true. */  \
                 /* so when it fails, SFINAE is triggered */            \
        >                                                               \
        ::type*                                                         \
    );                                                                  \
                                                                        \
    template< typename C >                                              \
    static no _test(...);                                               \
                                                                        \
public:                                                                 \
                                                                        \
    enum { value = (sizeof(_test< T >((typename std::remove_reference< T >::type*)0, 0)) == sizeof(yes)) }; \
                                                                        \
};

//-----------------------------------------------------------------------------
#define _c4_DEFINE_ARRAY_TYPES_WITHOUT_ITERATOR(T, I)       \
                                                            \
    using value_type = T;                                   \
    using size_type = I;                                    \
    using ssize_type = typename std::make_signed<I>::type;  \
                                                            \
    using pointer = T*;                                     \
    using const_pointer = T const*;                         \
                                                            \
    using reference = T&;                                   \
    using const_reference = T const&;                       \
                                                            \
    using difference_type = ptrdiff_t;

#define _c4_DEFINE_ARRAY_TYPES(T, I)                                    \
                                                                        \
    _c4_DEFINE_ARRAY_TYPES_WITHOUT_ITERATOR(T, I);                      \
                                                                        \
    using iterator = T*;                                                \
    using const_iterator = T const*;                                    \
                                                                        \
    using reverse_iterator = std::reverse_iterator< T* >;               \
    using const_reverse_iterator = std::reverse_iterator< T const* >;

//-----------------------------------------------------------------------------
// http://stackoverflow.com/questions/10821380/is-t-an-instance-of-a-template-in-c
template< template < typename... > class X, typename    T > struct is_instance_of_tpl             : std::false_type {};
template< template < typename... > class X, typename... Y > struct is_instance_of_tpl<X, X<Y...>> : std::true_type {};

//-----------------------------------------------------------------------------
// A template parameter pack is mass-forwardable if
// all of its types are mass-forwardable...
template< class T, class ...Args >
struct is_mass_forwardable : public std::conditional<
    is_mass_forwardable< T >::value && is_mass_forwardable< Args... >::value,
    std::true_type, std::false_type
    >::type
{};
// ... and a type is mass-forwardable if:
template< class T >
struct is_mass_forwardable<T> : public std::conditional<
    (
        !std::is_rvalue_reference<T>::value ||
        (
            std::is_trivially_move_constructible<typename std::remove_reference<T>::type>::value &&
            std::is_trivially_move_assignable<typename std::remove_reference<T>::type>::value
        )
    ),
    std::true_type,
    std::false_type
    >::type
{};

C4_END_NAMESPACE(c4)

#endif /* _C4_TYPES_HPP_ */
<commit_msg>types: join tag types<commit_after>#ifndef _C4_TYPES_HPP_
#define _C4_TYPES_HPP_

#include <stdint.h>
#include <stddef.h>
#include <type_traits>

/** @file types.hpp basic types, and utility macros and traits for types.
 * @ingroup basic_headers */

C4_BEGIN_NAMESPACE(c4)

using i8 = int8_t;
using u8 = uint8_t;
using i16 = int16_t;
using u16 = uint16_t;
using i32 = int32_t;
using u32 = uint32_t;
using i64 = int64_t;
using u64 = uint64_t;

using f32 = float;
using f64 = double;

using ssize_t = std::make_signed< size_t >::type;

//--------------------------------------------------

// some tag types

/** a tag type for initializing the containers with variadic arguments a la
 * initializer_list, minus the initializer_list overload problems.
 * @see */
struct aggregate_t {};
/** @see aggregate_t */
constexpr const aggregate_t aggregate{};

/** a tag type for specifying the initial capacity of allocatable contiguous storage */
struct with_capacity_t {};
/** @see with_capacity_t */
constexpr const with_capacity_t with_capacity{};

/** a tag type which can be used to disambiguate in variadic template overloads */
struct varargs_t {};
/** a tag variable which can be used to disambiguate in variadic template overloads */
constexpr const varargs_t varargs{};

//--------------------------------------------------

/** whether a value should be used in place of a const-reference in argument passing. */
template< class T >
struct cref_uses_val
{
    enum { value = (
    std::is_scalar< T >::value
    ||
    (std::is_pod< T >::value && sizeof(T) <= sizeof(size_t))) };
};
/** utility macro to override the default behaviour for c4::fastcref<T>
 @see fastcref */
#define C4_CREF_USES_VAL(T) \
template<>                  \
struct cref_uses_val< T >   \
{                           \
    enum { value = true };  \
};

/** Whether to use pass-by-value or pass-by-const-reference in a function argument
 * or return type. */
template< class T >
using fastcref = typename std::conditional< c4::cref_uses_val< T >::value, T, T const& >::type;

//--------------------------------------------------

/** Just what its name says. Useful sometimes as a default empty policy class. */
struct EmptyStruct
{
    template< class... T > EmptyStruct(T && ...){}
};

/** Just what its name says. Useful sometimes as a default policy class to
 * be inherited from. */
struct EmptyStructVirtual
{
    virtual ~EmptyStructVirtual() = default;
    template< class... T > EmptyStructVirtual(T && ...){}
};

/** */
template< class T >
struct inheritfrom : public T {};

//--------------------------------------------------
// Utilities to make a class obey size restrictions (eg, min size or size multiple of).
// DirectX usually makes this restriction with uniform buffers.
// This is also useful for padding to prevent false-sharing.

/** how many bytes must be added to size such that the result is at least minsize? */
C4_ALWAYS_INLINE constexpr size_t min_remainder(size_t size, size_t minsize)
{
    return size < minsize ? minsize-size : 0;
}

/** how many bytes must be added to size such that the result is a multiple of multipleof?  */
C4_ALWAYS_INLINE constexpr size_t mult_remainder(size_t size, size_t multipleof)
{
    return (((size % multipleof) != 0) ? (multipleof-(size % multipleof)) : 0);
}

/** force the following class to be tightly packed.
 * @see http://stackoverflow.com/questions/21092415/force-c-structure-to-pack-tightly */
#pragma pack(push, 1)
/** pad a class with more bytes at the end. */
template< class T, size_t BytesToPadAtEnd >
struct Padded : public T
{
    using T::T;
public:
    char ___c4padspace___[BytesToPadAtEnd];
};
#pragma pack(pop)
/** When the padding argument is 0, we cannot declare the char[] array. */
template< class T >
struct Padded< T, 0 > : public T
{
    using T::T;
};

/** make T have a size which is at least Min bytes */
template< class T, size_t Min >
using MinSized = Padded< T, min_remainder(sizeof(T), Min) >;

/** make T have a size which is a multiple of Mult bytes */
template< class T, size_t Mult >
using MultSized = Padded< T, mult_remainder(sizeof(T), Mult) >;

/** make T have a size which is simultaneously:
 *  -bigger or equal than Min
 *  -a multiple of Mult */
template< class T, size_t Min, size_t Mult >
using MinMultSized = MultSized< MinSized< T, Min >, Mult >;

/** make T be suitable for use as a uniform buffer. (at least with DirectX). */
template< class T >
using UbufSized = MinMultSized< T, 64, 16 >;

//-----------------------------------------------------------------------------

/** SFINAE. use this macro to enable a template function overload
based on a compile-time condition.
@code
// define an overload for a non-pod type
template< class T, C4_REQUIRE_T(std::is_pod< T >::value) >
void foo() { std::cout << "pod type\n"; }

// define an overload for a non-pod type
template< class T, C4_REQUIRE_T(!std::is_pod< T >::value) >
void foo() { std::cout << "nonpod type\n"; }

struct non_pod
{
    non_pod() : name("asdfkjhasdkjh") {}
    const char *name;
};

int main()
{
    foo< float >(); // prints "pod type"
    foo< non_pod >(); // prints "nonpod type"
}
@endcode */
#define C4_REQUIRE_T(cond) typename std::enable_if< cond, bool >::type* = nullptr

/** enable_if for a return type
 * @see C4_REQUIRE_T */
#define C4_REQUIRE_R(cond, type_) typename std::enable_if< cond, type_ >::type

//-----------------------------------------------------------------------------
/** declare a traits class telling whether a type provides a member typedef */
#define C4_DEFINE_HAS_TYPEDEF(member_typedef)                   \
template< typename T >                                          \
struct has_##stype                                              \
{                                                               \
private:                                                        \
                                                                \
    typedef char                      yes;                      \
    typedef struct { char array[2]; } no;                       \
                                                                \
    template< typename C >                                      \
    static yes _test(typename C::member_typedef*);              \
                                                                \
    template< typename C >                                      \
    static no  _test(...);                                      \
                                                                \
public:                                                         \
                                                                \
    enum { value = (sizeof(_test< T >(0)) == sizeof(yes)) };    \
                                                                \
}

//-----------------------------------------------------------------------------
/** declare a traits class telling whether a type provides a method */
#define C4_DEFINE_HAS_METHOD(ret_type, method_name, const_qualifier, ...) \
template< typename T >                                                  \
struct has_##method_name##_method                                       \
{                                                                       \
private:                                                                \
                                                                        \
    typedef char                      &yes;                             \
    typedef struct { char array[2]; } &no;                              \
                                                                        \
    template< typename C >                                              \
    static yes _test                                                    \
    (                                                                   \
        C const_qualifier* v,                                           \
        typename std::enable_if                                         \
        <                                                               \
            std::is_same< decltype(v->method_name(__VA_ARGS__)), ret_type >::value \
            ,                                                           \
            void /* this is defined only if the bool above is true. */  \
                 /* so when it fails, SFINAE is triggered */            \
        >                                                               \
        ::type*                                                         \
    );                                                                  \
                                                                        \
    template< typename C >                                              \
    static no _test(...);                                               \
                                                                        \
public:                                                                 \
                                                                        \
    enum { value = (sizeof(_test< T >((typename std::remove_reference< T >::type*)0, 0)) == sizeof(yes)) }; \
                                                                        \
};

//-----------------------------------------------------------------------------
#define _c4_DEFINE_ARRAY_TYPES_WITHOUT_ITERATOR(T, I)       \
                                                            \
    using value_type = T;                                   \
    using size_type = I;                                    \
    using ssize_type = typename std::make_signed<I>::type;  \
                                                            \
    using pointer = T*;                                     \
    using const_pointer = T const*;                         \
                                                            \
    using reference = T&;                                   \
    using const_reference = T const&;                       \
                                                            \
    using difference_type = ptrdiff_t;

#define _c4_DEFINE_ARRAY_TYPES(T, I)                                    \
                                                                        \
    _c4_DEFINE_ARRAY_TYPES_WITHOUT_ITERATOR(T, I);                      \
                                                                        \
    using iterator = T*;                                                \
    using const_iterator = T const*;                                    \
                                                                        \
    using reverse_iterator = std::reverse_iterator< T* >;               \
    using const_reverse_iterator = std::reverse_iterator< T const* >;

//-----------------------------------------------------------------------------
// http://stackoverflow.com/questions/10821380/is-t-an-instance-of-a-template-in-c
template< template < typename... > class X, typename    T > struct is_instance_of_tpl             : std::false_type {};
template< template < typename... > class X, typename... Y > struct is_instance_of_tpl<X, X<Y...>> : std::true_type {};

//-----------------------------------------------------------------------------
// A template parameter pack is mass-forwardable if
// all of its types are mass-forwardable...
template< class T, class ...Args >
struct is_mass_forwardable : public std::conditional<
    is_mass_forwardable< T >::value && is_mass_forwardable< Args... >::value,
    std::true_type, std::false_type
    >::type
{};
// ... and a type is mass-forwardable if:
template< class T >
struct is_mass_forwardable<T> : public std::conditional<
    (
        !std::is_rvalue_reference<T>::value ||
        (
            std::is_trivially_move_constructible<typename std::remove_reference<T>::type>::value &&
            std::is_trivially_move_assignable<typename std::remove_reference<T>::type>::value
        )
    ),
    std::true_type,
    std::false_type
    >::type
{};

C4_END_NAMESPACE(c4)

#endif /* _C4_TYPES_HPP_ */
<|endoftext|>


<commit_before>#include <Poco/Net/HTTPClientSession.h>
#include <Poco/Net/HTTPRequest.h>
#include <Poco/Net/HTTPResponse.h>
#include <Poco/StreamCopier.h>
#include <Poco/Path.h>
#include <Poco/URI.h>
#include <Poco/Exception.h>
#include <iostream>
#include <string>

using namespace Poco::Net;
using namespace Poco;
using namespace std;

int main(int argc, char **argv) {
	if (argc != 2) {
		cout << "Usage: " << argv[0] << " <url>" << endl;
		cout << "			 fetch the <url> resource and output the result" << endl;
		return -1;
	}

	try {
		URI uri(argv[1]);
		HTTPClientSession session(uri.getHost(), uri.getPort());

		string path(uri.getPathAndQuery());
		if (path.empty()) path = "/";

		HTTPRequest req(HTTPRequest::HTTP_GET, path, HTTPMessage::HTTP_1_1);
		session.sendRequest(req);

		HTTPResponse res;
		cout << res.getStatus() << " " << res.getReason() << endl;

		istream &is = session.receiveResponse(res);
		StreamCopier::copyStream64(is, cout);
	} catch (Poco::Exception &ex) {
		cerr << ex.displayText() << endl;
		return -1;
	}

	return 0;
}

<commit_msg>comments for what to do to get POST working in POCO<commit_after>#include <Poco/Net/HTTPClientSession.h>
#include <Poco/Net/HTTPRequest.h>
#include <Poco/Net/HTTPResponse.h>
#include <Poco/StreamCopier.h>
#include <Poco/Path.h>
#include <Poco/URI.h>
#include <Poco/Exception.h>
#include <iostream>
#include <string>

using namespace Poco::Net;
using namespace Poco;
using namespace std;

int main(int argc, char **argv) {
	if (argc != 2) {
		cout << "Usage: " << argv[0] << " <url>" << endl;
		cout << "			 fetch the <url> resource and output the result" << endl;
		return -1;
	}

	try {
		URI uri(argv[1]);
		HTTPClientSession session(uri.getHost(), uri.getPort());

		// http://bsecure/api/v0/session
		string path(uri.getPathAndQuery());
		if (path.empty()) path = "/";

		// USE POST
		// {"email":"x@src.bz","code":"591acbb20a20d8115f7cfd39b218948e"}
		HTTPRequest req(HTTPRequest::HTTP_GET, path, HTTPMessage::HTTP_1_1);
		session.sendRequest(req);

		// expect 200 response
		HTTPResponse res;
		cout << res.getStatus() << " " << res.getReason() << endl;

		istream &is = session.receiveResponse(res);
		StreamCopier::copyStream64(is, cout);
	} catch (Poco::Exception &ex) {
		cerr << ex.displayText() << endl;
		return -1;
	}

	return 0;
}

<|endoftext|>


<commit_before>#include "widget.h"
#include <QDebug>
#include <QPainter>
#include <QFontMetrics>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
	resize(402, 322);
}

Widget::~Widget()
{

}

void Widget::paintEvent(QPaintEvent *event)
{
	QPainter painter(this);

	/*!
	 * Draw the border
	 */
	QRect rect = this->geometry();
	rect.moveTopLeft(QPoint(0, 0));
	rect.adjust(10, 10, -11, -11); /**< set aside for edge. */
	painter.setPen(Qt::NoPen);
	painter.setBrush(QBrush(Qt::white));
	painter.drawRoundRect(rect, 10, 10);

	/*!
	 * Draw the Title
	 */
	painter.setPen(Qt::SolidLine);
	painter.setFont(QFont("Microsoft YaHei UI", 12)); /**< Use YaHei Font */
	painter.drawText(QRect(rect.left(), rect.top(), rect.width(), 50), Qt::AlignCenter, "Simple barchart example");

	/*!
	 * Set data for test
	 */
	QStringList monthList;
	monthList << "Jan" << "Feb" << "Mar" << "Apr" << "May" << "Jun";

	QStringList valueList;
	valueList << "0.0" << "3.2" << "6.5" << "9.8" << "13.0";

	/*!
	 * Calculate the Font's pixel.
	 */
	QFontMetrics metrics = painter.fontMetrics();

	int leftBearing = metrics.width("100.0") + 35; /**< 5 is the scale width. */
	const int topBearing = 15;
	int coordWidth	= rect.width() - 2*leftBearing;
	int coordHeight = rect.height() - topBearing - 4*metrics.height();

	painter.translate(leftBearing, rect.bottom() - 2*metrics.height()); /**< move center to left bottom */
	float deltaX = static_cast<float>(coordWidth)/monthList.size();
	float deltaY = static_cast<float>(coordHeight)/(valueList.size()-1);

	/*!
	 * Draw the coordinate
	 */
	painter.drawLine(0, 0, coordWidth, 0);
	for (int i = 0; i != monthList.size(); ++i)
	{
		int strLen = metrics.width(monthList.at(i));
		// scale
		painter.drawLine(deltaX*(i+1), 0, deltaX*(i+1), 4);
		// text
		painter.drawText(deltaX*i + (deltaX-strLen)/2 ,metrics.height(), monthList.at(i));
	}

	painter.drawLine(0, 0, 0, -coordHeight);
	for (int i = 0; i != valueList.size(); ++i)
	{
		int deviation = metrics.height()/2 - metrics.descent();
		painter.drawLine(-4, -deltaY*i, 0, -deltaY*i);
		painter.drawText(-metrics.width(valueList.at(i))-4, -deltaY*i+deviation, valueList.at(i));
	}
}
<commit_msg>remove warning<commit_after>#include "widget.h"
#include <QDebug>
#include <QPainter>
#include <QFontMetrics>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
	resize(402, 322);
}

Widget::~Widget()
{

}

void Widget::paintEvent(QPaintEvent *)
{
	QPainter painter(this);

	/*!
	 * Draw the border
	 */
	QRect rect = this->geometry();
	rect.moveTopLeft(QPoint(0, 0));
	rect.adjust(10, 10, -11, -11); /**< set aside for edge. */
	painter.setPen(Qt::NoPen);
	painter.setBrush(QBrush(Qt::white));
	painter.drawRoundRect(rect, 10, 10);

	/*!
	 * Draw the Title
	 */
	painter.setPen(Qt::SolidLine);
	painter.setFont(QFont("Microsoft YaHei UI", 12)); /**< Use YaHei Font */
	painter.drawText(QRect(rect.left(), rect.top(), rect.width(), 50), Qt::AlignCenter, "Simple barchart example");

	/*!
	 * Set data for test
	 */
	QStringList monthList;
	monthList << "Jan" << "Feb" << "Mar" << "Apr" << "May" << "Jun";

	QStringList valueList;
	valueList << "0.0" << "3.2" << "6.5" << "9.8" << "13.0";

	/*!
	 * Calculate the Font's pixel.
	 */
	QFontMetrics metrics = painter.fontMetrics();

	int leftBearing = metrics.width("100.0") + 35; /**< 5 is the scale width. */
	const int topBearing = 15;
	int coordWidth	= rect.width() - 2*leftBearing;
	int coordHeight = rect.height() - topBearing - 4*metrics.height();

	painter.translate(leftBearing, rect.bottom() - 2*metrics.height()); /**< move center to left bottom */
	float deltaX = static_cast<float>(coordWidth)/monthList.size();
	float deltaY = static_cast<float>(coordHeight)/(valueList.size()-1);

	/*!
	 * Draw the coordinate
	 */
	painter.drawLine(0, 0, coordWidth, 0);
	for (int i = 0; i != monthList.size(); ++i)
	{
		int strLen = metrics.width(monthList.at(i));
		// scale
		painter.drawLine(deltaX*(i+1), 0, deltaX*(i+1), 4);
		// text
		painter.drawText(deltaX*i + (deltaX-strLen)/2 ,metrics.height(), monthList.at(i));
	}

	painter.drawLine(0, 0, 0, -coordHeight);
	for (int i = 0; i != valueList.size(); ++i)
	{
		int deviation = metrics.height()/2 - metrics.descent();
		painter.drawLine(-4, -deltaY*i, 0, -deltaY*i);
		painter.drawText(-metrics.width(valueList.at(i))-4, -deltaY*i+deviation, valueList.at(i));
	}
}
<|endoftext|>


<commit_before>/*
 * dialer - MeeGo Voice Call Manager
 * Copyright (c) 2009, 2010, Intel Corporation.
 *
 * This program is licensed under the terms and conditions of the
 * Apache License, version 2.0.  The full text of the Apache License is at
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 */

#include "common.h"
#include "callitem.h"
#include "callitemmodel.h"
#include "dialerapplication.h"
#include "seasidesyncmodel.h"
#include <QGraphicsItem>
#include <QGraphicsWidget>
#include <QDebug>
#include <MTheme>

#include <MWidgetCreator>

#define DEFAULT_RINGTONE "ring-1.wav"

M_REGISTER_WIDGET(CallItem)

CallItem::CallItem(const QString path, MWidget *parent)
    : MWidgetController(new CallItemModel, parent),
      m_path(path),
      m_peopleItem(NULL),
      m_ringtone(new QMediaPlayer()),
      m_rtKey(new MGConfItem("/apps/dialer/defaultRingtone")),
      m_isconnected(FALSE),
      m_ringtonefile("")
{
    TRACE

    m_ringtonefile = QString("%1/%2/stereo/%3")
                                     .arg(SOUNDS_DIR)
                                     .arg(MTheme::instance()->currentTheme())
                                     .arg(DEFAULT_RINGTONE);
    m_ringtone->setMedia(QMediaContent(QUrl::fromLocalFile(
                m_rtKey->value(QVariant(m_ringtonefile)).toString())));
    m_ringtone->setVolume(100);

    if (isValid())
        init();
}

CallItem::~CallItem()
{
    TRACE
    if (m_ringtone) {
        disconnect(m_ringtone, SIGNAL(positionChanged(qint64)));
        m_ringtone->stop();
        delete m_ringtone;
        m_ringtone = 0;
    }

    if (m_rtKey)
        delete m_rtKey;
    m_rtKey = 0;

    if (m_peopleItem)
        delete m_peopleItem;
    m_peopleItem = 0;

    // delete the callproxy object
    if (callProxy())
        delete callProxy();
}

void CallItem::init()
{
    TRACE
    if (!m_path.isEmpty()) {
        CallProxy *call = new CallProxy(m_path);

        if (call->isValid()) {
            model()->setCall(call);
            connect(call,SIGNAL(stateChanged()),this,SLOT(callStateChanged()));
            connect(call,SIGNAL(dataChanged()),this,SLOT(callDataChanged()));
        } else
            qCritical("Invalid CallProxy instance!");
    } else
        qCritical("Empty call path.  Can not create CallProxy!");

    populatePeopleItem();

    if (state() == CallItemModel::STATE_INCOMING ||
        state() == CallItemModel::STATE_WAITING)
    {
        // Start ringing
        if (!m_isconnected && m_ringtone) {
           connect(m_ringtone, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)),
                               SLOT(ringtoneStatusChanged(QMediaPlayer::MediaStatus)));
           m_isconnected = TRUE;
           m_ringtone->play();
        }
    }
}

bool CallItem::isValid()
{
    TRACE
    return (!path().isEmpty());
}

bool CallItem::isValid() const
{
    TRACE
    return (!path().isEmpty());
}

QString CallItem::path() const
{
    TRACE
    return m_path;
}

bool CallItem::setPath(QString path)
{
    TRACE
    if (!m_path.isEmpty()) {
        qCritical("Path already set and can not be changed once it is set");
        return false;
    } else if (path.isEmpty()) {
        qCritical("It makes no sense to set Path to an empty string!?!?");
        return false;
    }

    m_path = path;

    init();

    return true;
}

void CallItem::setDirection(CallItemModel::CallDirection direction)
{
    TRACE
    model()->setDirection(direction);
}

QString CallItem::lineID() const
{
    TRACE
    return (isValid())?model()->lineID():QString();
}

QString CallItem::name() const
{
    TRACE
    return (isValid())?model()->name():QString();
}

CallItemModel::CallState CallItem::state() const
{
    TRACE
    return model()->stateType();
}

CallItemModel::CallDirection CallItem::direction() const
{
    TRACE
    return model()->direction();
}

CallItemModel::CallDisconnectReason CallItem::reason() const
{
    TRACE
    return model()->reasonType();
}

int CallItem::duration() const
{
    TRACE
    return model()->duration();
}

QDateTime CallItem::startTime() const
{
    TRACE
    return model()->startTime();
}

PeopleItem * CallItem::peopleItem() const
{
    TRACE
    return m_peopleItem;
}

CallProxy* CallItem::callProxy() const
{
    TRACE
    return model()->call();
}

void CallItem::setPeopleItem(PeopleItem *person)
{
    TRACE
    if (m_peopleItem)
        delete m_peopleItem;
    m_peopleItem = person;
}

void CallItem::click()
{
    TRACE

    emit clicked();
}

void CallItem::callStateChanged()
{
    TRACE
    if (state() == CallItemModel::STATE_INCOMING ||
        state() == CallItemModel::STATE_WAITING)
    {
        // Start ringing
        if (!m_isconnected && m_ringtone) {
            connect(m_ringtone, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)),
                                SLOT(ringtoneStatusChanged(QMediaPlayer::MediaStatus)));
            m_isconnected = TRUE;
            m_ringtone->play();
        }
    } else {
        // Stop ringing
        if (m_ringtone) {
            disconnect(m_ringtone, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)));
            m_isconnected = FALSE;
            m_ringtone->stop();
        }
    }
    emit stateChanged();
}

void CallItem::callDataChanged()
{
    // For now we only handle lineid because
    // a) that's the only case where the signal is emitted
    // b) I haven't read anything about callerid name changing in-call
    populatePeopleItem();
}

void CallItem::callDisconnected(const QString &reason)
{
    TRACE
    Q_UNUSED(reason);
}

QVariant CallItem::itemChange(GraphicsItemChange change, const QVariant &val)
{
    TRACE
    if (change == QGraphicsItem::ItemSelectedHasChanged)
        model()->setSelected(val.toBool());

    return QGraphicsItem::itemChange(change, val);
}

void CallItem::populatePeopleItem()
{
    TRACE

    QModelIndexList matches;
    matches.clear();
    int role = Seaside::SearchRole;
    int hits = -1;

    //% "Unknown Caller"
    QString pi_name   = qtTrId("xx_unknown_caller");
    QString pi_photo  = "icon-m-content-avatar-placeholder";
    //% "Private"
    QString pi_lineid = qtTrId("xx_private");

    if (!lineID().isEmpty()) {
        pi_lineid = stripLineID(lineID());
        SeasideSyncModel *contacts = DA_SEASIDEMODEL;
        QModelIndex first = contacts->index(0,Seaside::ColumnPhoneNumbers);
        matches = contacts->match(first, role, QVariant(pi_lineid), hits);

        QString firstName = QString();
        QString lastName = QString();

        if (!matches.isEmpty()) {
            QModelIndex person = matches.at(0); //First match is all we look at
            SEASIDE_SHORTCUTS
            SEASIDE_SET_MODEL_AND_ROW(person.model(), person.row());

            firstName = SEASIDE_FIELD(FirstName, String);
            lastName = SEASIDE_FIELD(LastName, String);
            pi_photo = SEASIDE_FIELD(Avatar, String);
        } else if (!name().isEmpty()) {
            // We don't have a contact, but we have a callerid name, let's use it
            firstName = name();
        }

        if (lastName.isEmpty() && !firstName.isEmpty())
            // Contacts first (common) name
            //% "%1"
            pi_name = qtTrId("xx_first_name").arg(firstName);
        else if (firstName.isEmpty() && !lastName.isEmpty())
            // BMC# 8079 - NW
            // Contacts last (sur) name
            //% "%1"
            pi_name = qtTrId("xx_last_name").arg(lastName);
        else if (!firstName.isEmpty() && !lastName.isEmpty())
            // Contacts full, sortable name, is "Firstname Lastname"
            //% "%1 %2"
            pi_name = qtTrId("xx_first_last_name").arg(firstName)
                .arg(lastName);

    } else {
        //% "Unavailable"
        pi_lineid = qtTrId("xx_unavailable");
    }

    if (m_peopleItem != NULL)
        delete m_peopleItem;
    m_peopleItem = new PeopleItem();

    m_peopleItem->setName(pi_name);
    m_peopleItem->setPhoto(pi_photo);
    m_peopleItem->setPhone(pi_lineid);
}

void CallItem::ringtoneStatusChanged(QMediaPlayer::MediaStatus status)
{
    TRACE
    if (status == QMediaPlayer::EndOfMedia)
    {
      m_ringtone->setMedia(QMediaContent(QUrl::fromLocalFile(m_ringtonefile)));
      m_ringtone->play();
    }
}
<commit_msg>Fixed:   For FEA#4419, remove wrong comment and whitespace cleanup<commit_after>/*
 * dialer - MeeGo Voice Call Manager
 * Copyright (c) 2009, 2010, Intel Corporation.
 *
 * This program is licensed under the terms and conditions of the
 * Apache License, version 2.0.  The full text of the Apache License is at
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 */

#include "common.h"
#include "callitem.h"
#include "callitemmodel.h"
#include "dialerapplication.h"
#include "seasidesyncmodel.h"
#include <QGraphicsItem>
#include <QGraphicsWidget>
#include <QDebug>
#include <MTheme>

#include <MWidgetCreator>

#define DEFAULT_RINGTONE "ring-1.wav"

M_REGISTER_WIDGET(CallItem)

CallItem::CallItem(const QString path, MWidget *parent)
    : MWidgetController(new CallItemModel, parent),
      m_path(path),
      m_peopleItem(NULL),
      m_ringtone(new QMediaPlayer()),
      m_rtKey(new MGConfItem("/apps/dialer/defaultRingtone")),
      m_isconnected(FALSE),
      m_ringtonefile("")
{
    TRACE

    m_ringtonefile = QString("%1/%2/stereo/%3")
                                     .arg(SOUNDS_DIR)
                                     .arg(MTheme::instance()->currentTheme())
                                     .arg(DEFAULT_RINGTONE);
    m_ringtone->setMedia(QMediaContent(QUrl::fromLocalFile(
                m_rtKey->value(QVariant(m_ringtonefile)).toString())));
    m_ringtone->setVolume(100);

    if (isValid())
        init();
}

CallItem::~CallItem()
{
    TRACE
    if (m_ringtone) {
        disconnect(m_ringtone, SIGNAL(positionChanged(qint64)));
        m_ringtone->stop();
        delete m_ringtone;
        m_ringtone = 0;
    }

    if (m_rtKey)
        delete m_rtKey;
    m_rtKey = 0;

    if (m_peopleItem)
        delete m_peopleItem;
    m_peopleItem = 0;

    // delete the callproxy object
    if (callProxy())
        delete callProxy();
}

void CallItem::init()
{
    TRACE
    if (!m_path.isEmpty()) {
        CallProxy *call = new CallProxy(m_path);

        if (call->isValid()) {
            model()->setCall(call);
            connect(call,SIGNAL(stateChanged()),this,SLOT(callStateChanged()));
            connect(call,SIGNAL(dataChanged()),this,SLOT(callDataChanged()));
        } else
            qCritical("Invalid CallProxy instance!");
    } else
        qCritical("Empty call path.  Can not create CallProxy!");

    populatePeopleItem();

    if (state() == CallItemModel::STATE_INCOMING ||
        state() == CallItemModel::STATE_WAITING)
    {
        // Start ringing
        if (!m_isconnected && m_ringtone) {
           connect(m_ringtone, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)),
                               SLOT(ringtoneStatusChanged(QMediaPlayer::MediaStatus)));
           m_isconnected = TRUE;
           m_ringtone->play();
        }
    }
}

bool CallItem::isValid()
{
    TRACE
    return (!path().isEmpty());
}

bool CallItem::isValid() const
{
    TRACE
    return (!path().isEmpty());
}

QString CallItem::path() const
{
    TRACE
    return m_path;
}

bool CallItem::setPath(QString path)
{
    TRACE
    if (!m_path.isEmpty()) {
        qCritical("Path already set and can not be changed once it is set");
        return false;
    } else if (path.isEmpty()) {
        qCritical("It makes no sense to set Path to an empty string!?!?");
        return false;
    }

    m_path = path;

    init();

    return true;
}

void CallItem::setDirection(CallItemModel::CallDirection direction)
{
    TRACE
    model()->setDirection(direction);
}

QString CallItem::lineID() const
{
    TRACE
    return (isValid())?model()->lineID():QString();
}

QString CallItem::name() const
{
    TRACE
    return (isValid())?model()->name():QString();
}

CallItemModel::CallState CallItem::state() const
{
    TRACE
    return model()->stateType();
}

CallItemModel::CallDirection CallItem::direction() const
{
    TRACE
    return model()->direction();
}

CallItemModel::CallDisconnectReason CallItem::reason() const
{
    TRACE
    return model()->reasonType();
}

int CallItem::duration() const
{
    TRACE
    return model()->duration();
}

QDateTime CallItem::startTime() const
{
    TRACE
    return model()->startTime();
}

PeopleItem * CallItem::peopleItem() const
{
    TRACE
    return m_peopleItem;
}

CallProxy* CallItem::callProxy() const
{
    TRACE
    return model()->call();
}

void CallItem::setPeopleItem(PeopleItem *person)
{
    TRACE
    if (m_peopleItem)
        delete m_peopleItem;
    m_peopleItem = person;
}

void CallItem::click()
{
    TRACE

    emit clicked();
}

void CallItem::callStateChanged()
{
    TRACE
    if (state() == CallItemModel::STATE_INCOMING ||
        state() == CallItemModel::STATE_WAITING)
    {
        // Start ringing
        if (!m_isconnected && m_ringtone) {
            connect(m_ringtone, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)),
                                SLOT(ringtoneStatusChanged(QMediaPlayer::MediaStatus)));
            m_isconnected = TRUE;
            m_ringtone->play();
        }
    } else {
        // Stop ringing
        if (m_ringtone) {
            disconnect(m_ringtone, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)));
            m_isconnected = FALSE;
            m_ringtone->stop();
        }
    }
    emit stateChanged();
}

void CallItem::callDataChanged()
{
    populatePeopleItem();
}

void CallItem::callDisconnected(const QString &reason)
{
    TRACE
    Q_UNUSED(reason);
}

QVariant CallItem::itemChange(GraphicsItemChange change, const QVariant &val)
{
    TRACE
    if (change == QGraphicsItem::ItemSelectedHasChanged)
        model()->setSelected(val.toBool());

    return QGraphicsItem::itemChange(change, val);
}

void CallItem::populatePeopleItem()
{
    TRACE

    QModelIndexList matches;
    matches.clear();
    int role = Seaside::SearchRole;
    int hits = -1;

    //% "Unknown Caller"
    QString pi_name   = qtTrId("xx_unknown_caller");
    QString pi_photo  = "icon-m-content-avatar-placeholder";
    //% "Private"
    QString pi_lineid = qtTrId("xx_private");

    if (!lineID().isEmpty()) {
        pi_lineid = stripLineID(lineID());
        SeasideSyncModel *contacts = DA_SEASIDEMODEL;
        QModelIndex first = contacts->index(0,Seaside::ColumnPhoneNumbers);
        matches = contacts->match(first, role, QVariant(pi_lineid), hits);

        QString firstName = QString();
        QString lastName = QString();

        if (!matches.isEmpty()) {
            QModelIndex person = matches.at(0); //First match is all we look at
            SEASIDE_SHORTCUTS
            SEASIDE_SET_MODEL_AND_ROW(person.model(), person.row());

            firstName = SEASIDE_FIELD(FirstName, String);
            lastName = SEASIDE_FIELD(LastName, String);
            pi_photo = SEASIDE_FIELD(Avatar, String);
        } else if (!name().isEmpty()) {
            // We don't have a contact, but we have a callerid name, let's use it
            firstName = name();
        }

        if (lastName.isEmpty() && !firstName.isEmpty())
            // Contacts first (common) name
            //% "%1"
            pi_name = qtTrId("xx_first_name").arg(firstName);
        else if (firstName.isEmpty() && !lastName.isEmpty())
            // BMC# 8079 - NW
            // Contacts last (sur) name
            //% "%1"
            pi_name = qtTrId("xx_last_name").arg(lastName);
        else if (!firstName.isEmpty() && !lastName.isEmpty())
            // Contacts full, sortable name, is "Firstname Lastname"
            //% "%1 %2"
            pi_name = qtTrId("xx_first_last_name").arg(firstName)
                .arg(lastName);

    } else {
        //% "Unavailable"
        pi_lineid = qtTrId("xx_unavailable");
    }

    if (m_peopleItem != NULL)
        delete m_peopleItem;
    m_peopleItem = new PeopleItem();

    m_peopleItem->setName(pi_name);
    m_peopleItem->setPhoto(pi_photo);
    m_peopleItem->setPhone(pi_lineid);
}

void CallItem::ringtoneStatusChanged(QMediaPlayer::MediaStatus status)
{
    TRACE
    if (status == QMediaPlayer::EndOfMedia)
    {
      m_ringtone->setMedia(QMediaContent(QUrl::fromLocalFile(m_ringtonefile)));
      m_ringtone->play();
    }
}
<|endoftext|>


<commit_before>// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab
/*
 * Ceph - scalable distributed file system
 *
 * Copyright (C) 2004-2009 Sage Weil <sage@newdream.net>
 *
 * This 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.  See file COPYING.
 *
 */

using namespace std;

#include "config.h"

#include "common/ConfUtils.h"
#include "common/common_init.h"
#include "auth/Crypto.h"
#include "auth/Auth.h"
#include "auth/KeyRing.h"

void usage()
{
  cout << " usage: [--create-keyring] [--gen-key] [--name=<name>] [--set-uid=uid] [--caps=<filename>] [--list] [--print-key] <filename>" << std::endl;
  exit(1);
}

int main(int argc, const char **argv)
{
  vector<const char*> args;
  argv_to_vec(argc, argv, args);
  env_to_vec(args);
  DEFINE_CONF_VARS(usage);
  common_init(args, "osdmaptool", false, false);

  const char *me = argv[0];

  const char *fn = 0;
  bool gen_key = false;
  const char *add_key = 0;
  bool list = false;
  bool print_key = false;
  bool create_keyring = false;
  const char *caps_fn = NULL;
  const char *import_keyring = NULL;
  bool set_auid = false;
  __u64 auid = CEPH_AUTH_UID_DEFAULT;
  const char *name = g_conf.name;

  FOR_EACH_ARG(args) {
    if (CONF_ARG_EQ("gen-key", 'g')) {
      CONF_SAFE_SET_ARG_VAL(&gen_key, OPT_BOOL);
    } else if (CONF_ARG_EQ("add-key", 'a')) {
      CONF_SAFE_SET_ARG_VAL(&add_key, OPT_STR);
    } else if (CONF_ARG_EQ("list", 'l')) {
      CONF_SAFE_SET_ARG_VAL(&list, OPT_BOOL);
    } else if (CONF_ARG_EQ("caps", '\0')) {
      CONF_SAFE_SET_ARG_VAL(&caps_fn, OPT_STR);
    } else if (CONF_ARG_EQ("print-key", 'p')) {
      CONF_SAFE_SET_ARG_VAL(&print_key, OPT_BOOL);
    } else if (CONF_ARG_EQ("create-keyring", 'c')) {
      CONF_SAFE_SET_ARG_VAL(&create_keyring, OPT_BOOL);
    } else if (CONF_ARG_EQ("import-keyring", '\0')) {
      CONF_SAFE_SET_ARG_VAL(&import_keyring, OPT_STR);
    } else if (CONF_ARG_EQ("set-uid", 'u')) {
      CONF_SAFE_SET_ARG_VAL(&auid, OPT_LONGLONG);
      set_auid = true;
    } else if (!fn) {
      fn = args[i];
    } else
      usage();
  }
  if (!fn) {
    cerr << me << ": must specify filename" << std::endl;
    usage();
  }
  if (!(gen_key ||
	add_key ||
	list ||
	caps_fn ||
	set_auid ||
	print_key ||
	create_keyring ||
	import_keyring)) {
    cerr << "no command specified" << std::endl;
    usage();
  }
  if (gen_key && add_key) {
    cerr << "can't both gen_key and add_key" << std::endl;
    usage();
  }
  if (caps_fn || add_key || gen_key || print_key || set_auid) {
    if (!name || !(*name)) {
      cerr << "must specify entity name" << std::endl;
      usage();
    }
  }

  // keyring --------
  bool modified = false;
  KeyRing keyring;
  string s = name;
  EntityName ename;
  if (name[0] && !ename.from_str(s)) {
    cerr << "'" << s << "' is not a valid entity name" << std::endl;
    exit(1);
  }

  bufferlist bl;
  int r = 0;
  if (create_keyring) {
    cout << "creating " << fn << std::endl;
    modified = true;
  } else {
    r = bl.read_file(fn, true);
    if (r >= 0) {
      try {
	bufferlist::iterator iter = bl.begin();
	::decode(keyring, iter);
      } catch (buffer::error *err) {
	cerr << "error reading file " << fn << std::endl;
	exit(1);
      }
    } else {
      cerr << "can't open " << fn << ": " << strerror(-r) << std::endl;
      exit(1);
    }
  }

  // write commands
  if (import_keyring) {
    KeyRing other;
    bufferlist obl;
    int r = obl.read_file(import_keyring);
    if (r >= 0) {
      try {
	bufferlist::iterator iter = obl.begin();
	::decode(other, iter);
      } catch (buffer::error *err) {
	cerr << "error reading file " << import_keyring << std::endl;
	exit(1);
      }

      cout << "importing contents of " << import_keyring << " into " << fn << std::endl;
      //other.print(cout);
      keyring.import(other);
      modified = true;
    } else {
      cerr << "can't open " << import_keyring << ": " << strerror(-r) << std::endl;
      exit(1);
    }
  }
  if (gen_key) {
    EntityAuth eauth;
    eauth.key.create(CEPH_CRYPTO_AES);
    keyring.add(ename, eauth);
    modified = true;
  }
  if (add_key) {
    if (!name) {
      cerr << "must specify a name to add a key" << std::endl;
      exit(1);
    }
    EntityAuth eauth;
    string ekey(add_key);
    try {
      eauth.key.decode_base64(ekey);
    } catch (buffer::error *err) {
      cerr << "can't decode key '" << add_key << "'" << std::endl;
      exit(1);
    }
    keyring.add(ename, eauth);
    modified = true;
    cout << "added entity " << ename << " auth " << eauth << std::endl;
  }
  if (caps_fn) {
    ConfFile *cf = new ConfFile(caps_fn);
    if (!cf->parse()) {
      cerr << "could not parse caps file " << caps_fn << std::endl;
      exit(1);
    }
    map<string, bufferlist> caps;
    const char *key_names[] = { "mon", "osd", "mds", NULL };
    for (int i=0; key_names[i]; i++) {
      char *val;
      cf->read("global", key_names[i], &val, NULL);
      if (val) {
        bufferlist bl;
        ::encode(val, bl);
        string s(key_names[i]);
        caps[s] = bl;
        free(val);
      }
    }
    keyring.set_caps(ename, caps);
    modified = true;
  }
  if (set_auid) {
    if (!name) {
      cerr << "must specify a name to set a uid" << std::endl;
      exit(1);
    }
    keyring.set_uid(ename, auid);
    modified = true;
  }

  // read commands
  if (list) {
    keyring.print(cout);
  }
  if (print_key) {
    CryptoKey key;
    if (keyring.get_secret(ename, key)) {
      string a;
      key.encode_base64(a);
      cout << a << std::endl;
    } else {
      cerr << "entity " << ename << " not found" << std::endl;
    }
  }

  // write result?
  if (modified) {
    bufferlist bl;
    ::encode(keyring, bl);
    r = bl.write_file(fn, 0600);
    if (r < 0) {
      cerr << "could not write " << fn << std::endl;
    }
    //cout << "wrote " << bl.length() << " bytes to " << fn << std::endl;
  }

  return 0;
}
<commit_msg>auth: cauthtool now identifies itself properly to common_init<commit_after>// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab
/*
 * Ceph - scalable distributed file system
 *
 * Copyright (C) 2004-2009 Sage Weil <sage@newdream.net>
 *
 * This 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.  See file COPYING.
 *
 */

using namespace std;

#include "config.h"

#include "common/ConfUtils.h"
#include "common/common_init.h"
#include "auth/Crypto.h"
#include "auth/Auth.h"
#include "auth/KeyRing.h"

void usage()
{
  cout << " usage: [--create-keyring] [--gen-key] [--name=<name>] [--set-uid=uid] [--caps=<filename>] [--list] [--print-key] <filename>" << std::endl;
  exit(1);
}

int main(int argc, const char **argv)
{
  vector<const char*> args;
  argv_to_vec(argc, argv, args);
  env_to_vec(args);
  DEFINE_CONF_VARS(usage);
  common_init(args, "cauthtool", false, false);

  const char *me = argv[0];

  const char *fn = 0;
  bool gen_key = false;
  const char *add_key = 0;
  bool list = false;
  bool print_key = false;
  bool create_keyring = false;
  const char *caps_fn = NULL;
  const char *import_keyring = NULL;
  bool set_auid = false;
  __u64 auid = CEPH_AUTH_UID_DEFAULT;
  const char *name = g_conf.name;

  FOR_EACH_ARG(args) {
    if (CONF_ARG_EQ("gen-key", 'g')) {
      CONF_SAFE_SET_ARG_VAL(&gen_key, OPT_BOOL);
    } else if (CONF_ARG_EQ("add-key", 'a')) {
      CONF_SAFE_SET_ARG_VAL(&add_key, OPT_STR);
    } else if (CONF_ARG_EQ("list", 'l')) {
      CONF_SAFE_SET_ARG_VAL(&list, OPT_BOOL);
    } else if (CONF_ARG_EQ("caps", '\0')) {
      CONF_SAFE_SET_ARG_VAL(&caps_fn, OPT_STR);
    } else if (CONF_ARG_EQ("print-key", 'p')) {
      CONF_SAFE_SET_ARG_VAL(&print_key, OPT_BOOL);
    } else if (CONF_ARG_EQ("create-keyring", 'c')) {
      CONF_SAFE_SET_ARG_VAL(&create_keyring, OPT_BOOL);
    } else if (CONF_ARG_EQ("import-keyring", '\0')) {
      CONF_SAFE_SET_ARG_VAL(&import_keyring, OPT_STR);
    } else if (CONF_ARG_EQ("set-uid", 'u')) {
      CONF_SAFE_SET_ARG_VAL(&auid, OPT_LONGLONG);
      set_auid = true;
    } else if (!fn) {
      fn = args[i];
    } else
      usage();
  }
  if (!fn) {
    cerr << me << ": must specify filename" << std::endl;
    usage();
  }
  if (!(gen_key ||
	add_key ||
	list ||
	caps_fn ||
	set_auid ||
	print_key ||
	create_keyring ||
	import_keyring)) {
    cerr << "no command specified" << std::endl;
    usage();
  }
  if (gen_key && add_key) {
    cerr << "can't both gen_key and add_key" << std::endl;
    usage();
  }
  if (caps_fn || add_key || gen_key || print_key || set_auid) {
    if (!name || !(*name)) {
      cerr << "must specify entity name" << std::endl;
      usage();
    }
  }

  // keyring --------
  bool modified = false;
  KeyRing keyring;
  string s = name;
  EntityName ename;
  if (name[0] && !ename.from_str(s)) {
    cerr << "'" << s << "' is not a valid entity name" << std::endl;
    exit(1);
  }

  bufferlist bl;
  int r = 0;
  if (create_keyring) {
    cout << "creating " << fn << std::endl;
    modified = true;
  } else {
    r = bl.read_file(fn, true);
    if (r >= 0) {
      try {
	bufferlist::iterator iter = bl.begin();
	::decode(keyring, iter);
      } catch (buffer::error *err) {
	cerr << "error reading file " << fn << std::endl;
	exit(1);
      }
    } else {
      cerr << "can't open " << fn << ": " << strerror(-r) << std::endl;
      exit(1);
    }
  }

  // write commands
  if (import_keyring) {
    KeyRing other;
    bufferlist obl;
    int r = obl.read_file(import_keyring);
    if (r >= 0) {
      try {
	bufferlist::iterator iter = obl.begin();
	::decode(other, iter);
      } catch (buffer::error *err) {
	cerr << "error reading file " << import_keyring << std::endl;
	exit(1);
      }

      cout << "importing contents of " << import_keyring << " into " << fn << std::endl;
      //other.print(cout);
      keyring.import(other);
      modified = true;
    } else {
      cerr << "can't open " << import_keyring << ": " << strerror(-r) << std::endl;
      exit(1);
    }
  }
  if (gen_key) {
    EntityAuth eauth;
    eauth.key.create(CEPH_CRYPTO_AES);
    keyring.add(ename, eauth);
    modified = true;
  }
  if (add_key) {
    if (!name) {
      cerr << "must specify a name to add a key" << std::endl;
      exit(1);
    }
    EntityAuth eauth;
    string ekey(add_key);
    try {
      eauth.key.decode_base64(ekey);
    } catch (buffer::error *err) {
      cerr << "can't decode key '" << add_key << "'" << std::endl;
      exit(1);
    }
    keyring.add(ename, eauth);
    modified = true;
    cout << "added entity " << ename << " auth " << eauth << std::endl;
  }
  if (caps_fn) {
    ConfFile *cf = new ConfFile(caps_fn);
    if (!cf->parse()) {
      cerr << "could not parse caps file " << caps_fn << std::endl;
      exit(1);
    }
    map<string, bufferlist> caps;
    const char *key_names[] = { "mon", "osd", "mds", NULL };
    for (int i=0; key_names[i]; i++) {
      char *val;
      cf->read("global", key_names[i], &val, NULL);
      if (val) {
        bufferlist bl;
        ::encode(val, bl);
        string s(key_names[i]);
        caps[s] = bl;
        free(val);
      }
    }
    keyring.set_caps(ename, caps);
    modified = true;
  }
  if (set_auid) {
    if (!name) {
      cerr << "must specify a name to set a uid" << std::endl;
      exit(1);
    }
    keyring.set_uid(ename, auid);
    modified = true;
  }

  // read commands
  if (list) {
    keyring.print(cout);
  }
  if (print_key) {
    CryptoKey key;
    if (keyring.get_secret(ename, key)) {
      string a;
      key.encode_base64(a);
      cout << a << std::endl;
    } else {
      cerr << "entity " << ename << " not found" << std::endl;
    }
  }

  // write result?
  if (modified) {
    bufferlist bl;
    ::encode(keyring, bl);
    r = bl.write_file(fn, 0600);
    if (r < 0) {
      cerr << "could not write " << fn << std::endl;
    }
    //cout << "wrote " << bl.length() << " bytes to " << fn << std::endl;
  }

  return 0;
}
<|endoftext|>