You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
800 lines
24 KiB
800 lines
24 KiB
/***************************************************************************
|
|
* Copyright (C) 2003 by *
|
|
* Unai Garro (ugarro@users.sourceforge.net) *
|
|
* Cyril Bosselut (bosselut@b1project.com) *
|
|
* Jason Kivlighn (jkivlighn@gmail.com) *
|
|
* *
|
|
* 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 "dietwizarddialog.h"
|
|
#include "backends/recipedb.h"
|
|
#include "dietviewdialog.h"
|
|
|
|
#include <ntqbitmap.h>
|
|
#include <ntqheader.h>
|
|
#include <ntqlayout.h>
|
|
#include <ntqpainter.h>
|
|
#include <ntqwmatrix.h>
|
|
|
|
#include <tdeapplication.h>
|
|
#include <kcursor.h>
|
|
#include <tdeglobalsettings.h>
|
|
#include <kiconloader.h>
|
|
#include <tdelocale.h>
|
|
#include <tdemessagebox.h>
|
|
#include <knuminput.h>
|
|
#include <kdebug.h>
|
|
|
|
#include "propertycalculator.h"
|
|
#include "widgets/propertylistview.h"
|
|
#include "widgets/categorylistview.h"
|
|
|
|
#include "profiling.h"
|
|
|
|
DietWizardDialog::DietWizardDialog( TQWidget *parent, RecipeDB *db ) : TQVBox( parent )
|
|
{
|
|
// Initialize internal variables
|
|
database = db;
|
|
mealNumber = 1;
|
|
dayNumber = 1;
|
|
dietRList = new RecipeList();
|
|
|
|
//Design the dialog
|
|
setSpacing( 5 );
|
|
// Options Box
|
|
optionsBox = new TQHBox( this );
|
|
|
|
daysSliderBox = new TQVGroupBox( i18n( "Number of Days" ), optionsBox );
|
|
dayNumberLabel = new TQLabel( daysSliderBox );
|
|
dayNumberLabel->setText( "- 1 -" );
|
|
dayNumberLabel->setAlignment( TQt::AlignHCenter );
|
|
dayNumberSelector = new TQSlider( daysSliderBox );
|
|
|
|
dayNumberSelector->setOrientation( TQt::Horizontal );
|
|
dayNumberSelector->setRange( 1, 10 );
|
|
dayNumberSelector->setSteps( 1, 1 );
|
|
dayNumberSelector->setTickmarks( TQSlider::Below );
|
|
dayNumberSelector->setFixedWidth( 100 );
|
|
|
|
mealsSliderBox = new TQVGroupBox( i18n( "Meals per Day" ), optionsBox );
|
|
mealNumberLabel = new TQLabel( mealsSliderBox );
|
|
mealNumberLabel->setText( "- 1 -" );
|
|
mealNumberLabel->setAlignment( TQt::AlignHCenter );
|
|
mealNumberSelector = new TQSlider( mealsSliderBox );
|
|
|
|
mealNumberSelector->setOrientation( TQt::Horizontal );
|
|
mealNumberSelector->setRange( 1, 10 );
|
|
mealNumberSelector->setSteps( 1, 1 );
|
|
mealNumberSelector->setTickmarks( TQSlider::Below );
|
|
mealNumberSelector->setFixedWidth( 100 );
|
|
|
|
// Tabs
|
|
mealTabs = new TQTabWidget( this );
|
|
mealTabs->setMargin( 5 );
|
|
|
|
// Button bar
|
|
TDEIconLoader il;
|
|
|
|
TQHBox *bottom_layout = new TQHBox( this );
|
|
//bottom_layout->layout()->addItem( new TQSpacerItem( 10,10, TQSizePolicy::MinimumExpanding, TQSizePolicy::Fixed ) );
|
|
|
|
okButton = new TQPushButton( bottom_layout );
|
|
okButton->setIconSet( il.loadIconSet( "button_ok", TDEIcon::Small ) );
|
|
okButton->setText( i18n( "Create the diet" ) );
|
|
|
|
TQPushButton *clearButton = new TQPushButton( bottom_layout );
|
|
clearButton->setIconSet( il.loadIconSet( "edit-clear", TDEIcon::Small ) );
|
|
clearButton->setText( i18n( "Clear" ) );
|
|
|
|
// Create Tabs
|
|
//don't use newTab, it'll load data and we don't want it to do that at startup
|
|
mealTab = new MealInput( mealTabs, database );
|
|
mealTabs->addTab( mealTab,i18n( "Meal 1" ) );
|
|
mealTabs->setCurrentPage( mealTabs->indexOf( mealTab ) );
|
|
|
|
// Signals & Slots
|
|
connect( mealNumberSelector, TQ_SIGNAL( valueChanged( int ) ), this, TQ_SLOT( changeMealNumber( int ) ) );
|
|
connect( dayNumberSelector, TQ_SIGNAL( valueChanged( int ) ), this, TQ_SLOT( changeDayNumber( int ) ) );
|
|
connect( okButton, TQ_SIGNAL( clicked() ), this, TQ_SLOT( createDiet() ) );
|
|
connect( clearButton, TQ_SIGNAL( clicked() ), this, TQ_SLOT( clear() ) );
|
|
}
|
|
|
|
|
|
DietWizardDialog::~DietWizardDialog()
|
|
{
|
|
delete dietRList;
|
|
}
|
|
|
|
void DietWizardDialog::clear()
|
|
{
|
|
mealNumberSelector->setValue( 1 );
|
|
dayNumberSelector->setValue( 1 );
|
|
|
|
MealInput* mealTab = ( MealInput* ) ( mealTabs->page( 0 ) ); // Get the meal
|
|
mealTab->setDishNo( 3 );
|
|
mealTab->showDish( 0 );
|
|
|
|
for ( uint i = 0; i < mealTab->dishInputList.count(); ++i ) {
|
|
DishInput* dishInput = mealTab->dishInputList[ i ]; // Get the dish input
|
|
dishInput->clear();
|
|
}
|
|
}
|
|
|
|
void DietWizardDialog::reload( ReloadFlags flag )
|
|
{
|
|
for ( int i = 0; i < mealTabs->count(); ++i ) {
|
|
MealInput *mealTab = (MealInput*)mealTabs->page(i);
|
|
mealTab->reload(flag);
|
|
}
|
|
}
|
|
|
|
void DietWizardDialog::newTab( const TQString &name )
|
|
{
|
|
mealTab = new MealInput( mealTabs, database );
|
|
mealTab->reload();
|
|
mealTabs->addTab( mealTab, name );
|
|
mealTabs->setCurrentPage( mealTabs->indexOf( mealTab ) );
|
|
}
|
|
|
|
void DietWizardDialog::changeMealNumber( int mn )
|
|
{
|
|
mealNumberLabel->setText( TQString( i18n( "- %1 -" ) ).arg( mn ) );
|
|
if ( mn > mealNumber ) {
|
|
|
|
while ( mealNumber != mn ) {
|
|
mealNumber++;
|
|
newTab( i18n( "Meal %1" ).arg( mealNumber ) );
|
|
|
|
}
|
|
}
|
|
else if ( mn < mealNumber ) {
|
|
|
|
while ( mealNumber != mn ) {
|
|
mealNumber--;
|
|
delete mealTabs->page( mealTabs->count() - 1 );
|
|
}
|
|
}
|
|
}
|
|
|
|
void DietWizardDialog::changeDayNumber( int dn )
|
|
{
|
|
|
|
if ( dn < 7 ) {
|
|
dayNumber = dn;
|
|
dayNumberLabel->setText( TQString( i18n( "- %1 -" ) ).arg( dn ) );
|
|
}
|
|
else if ( dn == 7 ) {
|
|
dayNumber = 7;
|
|
dayNumberLabel->setText( TQString( i18n( "- 1 week -" ) ) );
|
|
}
|
|
else {
|
|
dayNumber = ( dn - 6 ) * 7;
|
|
dayNumberLabel->setText( TQString( i18n( "- %1 weeks -" ) ).arg( dn - 6 ) );
|
|
}
|
|
}
|
|
|
|
void DietWizardDialog::createDiet( void )
|
|
{
|
|
TDEApplication::setOverrideCursor( KCursor::waitCursor() );
|
|
|
|
START_TIMER("Creating the diet");
|
|
|
|
RecipeList rlist;
|
|
dietRList->clear();
|
|
|
|
// Get the whole list of recipes, detailed
|
|
int flags = RecipeDB::Title | getNecessaryFlags();
|
|
database->loadRecipes( &rlist, flags );
|
|
|
|
// temporal iterator list so elements can be removed without reloading them again from the DB
|
|
// this list prevents the same meal from showing up in the same day twice
|
|
TQValueList <RecipeList::Iterator> tempRList;
|
|
|
|
bool alert = false;
|
|
|
|
for ( int day = 0;day < dayNumber;day++ ) // Create the diet for the number of days defined by the user
|
|
{
|
|
populateIteratorList( rlist, &tempRList ); // temporal iterator list so elements can be removed without reloading them again from the DB
|
|
for ( int meal = 0;meal < mealNumber;meal++ )
|
|
{
|
|
int dishNo = ( ( MealInput* ) ( mealTabs->page( meal ) ) ) ->dishNo();
|
|
|
|
for ( int dish = 0;dish < dishNo;dish++ ) {
|
|
bool found = false;
|
|
TQValueList <RecipeList::Iterator> tempDishRList = tempRList;
|
|
while ( ( !found ) && !tempDishRList.empty() ) {
|
|
int random_index = ( int ) ( ( float ) ( kapp->random() ) / ( float ) RAND_MAX * tempDishRList.count() );
|
|
TQValueList<RecipeList::Iterator>::Iterator iit = tempDishRList.at( random_index ); // note that at() retrieves an iterator to the iterator list, so we need to use * in order to get the RecipeList::Iterator
|
|
|
|
RecipeList::Iterator rit = *iit;
|
|
if ( found = ( ( ( !categoryFiltering( meal, dish ) ) || checkCategories( *rit, meal, dish ) ) && checkConstraints( *rit, meal, dish ) ) ) // Check that the recipe is inside the constraint limits and in the categories specified
|
|
{
|
|
dietRList->append( *rit ); // Add recipe to the diet list
|
|
tempRList.remove( tempRList.find(*iit) ); //can't just remove()... the iterator isn't from this list (its an iterator from tempDishRList)
|
|
}
|
|
else {
|
|
tempDishRList.remove( iit ); // Remove this analized recipe from teh list
|
|
}
|
|
}
|
|
if ( !found )
|
|
alert = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( alert ) {
|
|
TDEApplication::restoreOverrideCursor();
|
|
KMessageBox::sorry( this, i18n( "I could not create a full diet list given the constraints. Either the recipe list is too short or the constraints are too demanding. " ) );
|
|
}
|
|
|
|
else // show the resulting diet
|
|
{
|
|
|
|
// make a list of dishnumbers
|
|
TQValueList<int> dishNumbers;
|
|
|
|
for ( int meal = 0;meal < mealNumber;meal++ ) {
|
|
int dishNo = ( ( MealInput* ) ( mealTabs->page( meal ) ) ) ->dishNo();
|
|
dishNumbers << dishNo;
|
|
}
|
|
|
|
TDEApplication::restoreOverrideCursor();
|
|
|
|
// display the list
|
|
DietViewDialog dietDisplay( this, *dietRList, dayNumber, mealNumber, dishNumbers );
|
|
connect( &dietDisplay, TQ_SIGNAL( signalOk() ), this, TQ_SLOT( createShoppingList() ) );
|
|
dietDisplay.exec();
|
|
}
|
|
|
|
END_TIMER();
|
|
}
|
|
|
|
|
|
void DietWizardDialog::populateIteratorList( RecipeList &rl, TQValueList <RecipeList::Iterator> *il )
|
|
{
|
|
il->clear();
|
|
RecipeList::Iterator it;
|
|
for ( it = rl.begin();it != rl.end(); ++it )
|
|
il->append( it );
|
|
|
|
}
|
|
|
|
int DietWizardDialog::getNecessaryFlags() const
|
|
{
|
|
bool need_ingredients = false;
|
|
bool need_categories = false;
|
|
for ( int meal = 0;meal < mealNumber;meal++ ) {
|
|
int dishNo = ( ( MealInput* ) ( mealTabs->page( meal ) ) ) ->dishNo();
|
|
for ( int dish = 0;dish < dishNo;dish++ ) {
|
|
if ( !need_categories ) {
|
|
if ( categoryFiltering( meal, dish ) ) {
|
|
need_categories = true;
|
|
}
|
|
}
|
|
|
|
if ( !need_ingredients ) {
|
|
ConstraintList constraints;
|
|
loadConstraints( meal, dish, &constraints );
|
|
for ( ConstraintList::const_iterator ct_it = constraints.begin(); ct_it != constraints.end(); ++ct_it ) {
|
|
if ( (*ct_it).enabled ) {
|
|
need_ingredients = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( need_ingredients && need_categories )
|
|
break;
|
|
}
|
|
|
|
if ( need_ingredients && need_categories )
|
|
break;
|
|
}
|
|
|
|
kdDebug()<<"Do we need to load ingredients: "<<need_ingredients<<endl;
|
|
kdDebug()<<"Do we need to load categories: "<<need_categories<<endl;
|
|
|
|
int flags = 0;
|
|
if ( need_ingredients ) flags |= RecipeDB::Ingredients;
|
|
if ( need_categories ) flags |= RecipeDB::Categories;
|
|
|
|
return flags;
|
|
}
|
|
|
|
|
|
MealInput::MealInput( TQWidget *parent, RecipeDB *db ) : TQWidget( parent ),
|
|
database( db )
|
|
{
|
|
// Design the dialog
|
|
TQVBoxLayout *layout = new TQVBoxLayout( this );
|
|
layout->setSpacing( 10 );
|
|
|
|
// Options box
|
|
|
|
mealOptions = new TQHBox( this );
|
|
mealOptions->setSpacing( 10 );
|
|
layout->addWidget( mealOptions );
|
|
|
|
// Number of dishes input
|
|
dishNumberBox = new TQHBox( mealOptions );
|
|
dishNumberBox->setSpacing( 10 );
|
|
dishNumberLabel = new TQLabel( i18n( "No. of dishes: " ), dishNumberBox );
|
|
dishNumberInput = new TQSpinBox( dishNumberBox );
|
|
dishNumberInput->setMinValue( 1 );
|
|
dishNumberInput->setMaxValue( 10 );
|
|
dishNumberBox->setSizePolicy( TQSizePolicy( TQSizePolicy::Minimum, TQSizePolicy::Minimum ) );
|
|
|
|
// Toolbar
|
|
|
|
toolBar = new TQHGroupBox( mealOptions );
|
|
toolBar->setFrameStyle ( TQFrame::Panel | TQFrame::Sunken );
|
|
toolBar->setSizePolicy( TQSizePolicy( TQSizePolicy::MinimumExpanding, TQSizePolicy::Minimum ) );
|
|
|
|
// Next dish/ Previous dish buttons
|
|
TDEIconLoader il;
|
|
buttonPrev = new TQToolButton( toolBar );
|
|
buttonPrev->setUsesTextLabel( true );
|
|
buttonPrev->setTextLabel( i18n( "Previous Dish" ) );
|
|
buttonPrev->setIconSet( il.loadIconSet( "back", TDEIcon::Small ) );
|
|
buttonPrev->setTextPosition( TQToolButton::Under );
|
|
buttonNext = new TQToolButton( toolBar );
|
|
buttonNext->setUsesTextLabel( true );
|
|
buttonNext->setTextLabel( i18n( "Next Dish" ) );
|
|
buttonNext->setIconSet( il.loadIconSet( "forward", TDEIcon::Small ) );
|
|
buttonNext->setTextPosition( TQToolButton::Under );
|
|
|
|
|
|
// Dish widgets
|
|
dishStack = new TQWidgetStack( this );
|
|
layout->addWidget( dishStack );
|
|
dishStack->setSizePolicy( TQSizePolicy( TQSizePolicy::MinimumExpanding, TQSizePolicy::MinimumExpanding ) );
|
|
// Add default dishes
|
|
DishInput *newDish = new DishInput( this, database, i18n( "1st Course" ) );
|
|
dishStack->addWidget( newDish );
|
|
dishInputList.append( newDish );
|
|
newDish = new DishInput( this, database, i18n( "2nd Course" ) );
|
|
dishStack->addWidget( newDish );
|
|
dishInputList.append( newDish );
|
|
newDish = new DishInput( this, database, i18n( "Dessert" ) );
|
|
dishStack->addWidget( newDish );
|
|
dishInputList.append( newDish );
|
|
dishNumber = 3;
|
|
dishNumberInput->setValue( dishNumber );
|
|
|
|
// Signals & Slots
|
|
connect( dishNumberInput, TQ_SIGNAL( valueChanged( int ) ), this, TQ_SLOT( changeDishNumber( int ) ) );
|
|
connect( buttonPrev, TQ_SIGNAL( clicked() ), this, TQ_SLOT( prevDish() ) );
|
|
connect( buttonNext, TQ_SIGNAL( clicked() ), this, TQ_SLOT( nextDish() ) );
|
|
|
|
}
|
|
|
|
MealInput::~MealInput()
|
|
{}
|
|
|
|
void MealInput::reload( ReloadFlags flag )
|
|
{
|
|
TQValueList<DishInput*>::iterator it;
|
|
for ( it = dishInputList.begin(); it != dishInputList.end(); ++it ) {
|
|
DishInput *di = ( *it );
|
|
di->reload(flag);
|
|
}
|
|
}
|
|
|
|
void MealInput::setDishNo( int dn )
|
|
{
|
|
dishNumberInput->setValue( dn );
|
|
}
|
|
|
|
void MealInput::changeDishNumber( int dn )
|
|
{
|
|
if ( dn > dishNumber ) {
|
|
while ( dishNumber != dn ) {
|
|
DishInput * newDish = new DishInput( this, database, TQString( i18n( "Dish %1" ) ).arg( dishNumber + 1 ) );
|
|
newDish->reload();
|
|
dishStack->addWidget( newDish );
|
|
dishInputList.append( newDish );
|
|
dishStack->raiseWidget( newDish );
|
|
dishNumber++;
|
|
}
|
|
}
|
|
else if ( dn < dishNumber ) {
|
|
TQValueList <DishInput*>::Iterator it;
|
|
while ( dishNumber != dn ) {
|
|
it = dishInputList.fromLast();
|
|
DishInput *lastDish = ( *it );
|
|
dishInputList.remove( it );
|
|
|
|
if ( ( *it ) == ( DishInput* ) dishStack->visibleWidget() ) {
|
|
it--;
|
|
dishStack->raiseWidget( *it );
|
|
}
|
|
delete lastDish;
|
|
dishNumber--;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void MealInput::nextDish( void )
|
|
{
|
|
// First get the place of the current dish input in the list
|
|
TQValueList <DishInput*>::iterator it = dishInputList.find( ( DishInput* ) ( dishStack->visibleWidget() ) );
|
|
|
|
//Show the next dish if it exists
|
|
it++;
|
|
if ( it != dishInputList.end() ) {
|
|
dishStack->raiseWidget( *it );
|
|
}
|
|
|
|
}
|
|
|
|
void MealInput::prevDish( void )
|
|
{
|
|
// First get the place of the current dish input in the list
|
|
TQValueList <DishInput*>::iterator it = dishInputList.find( ( DishInput* ) ( dishStack->visibleWidget() ) );
|
|
|
|
//Show the previous dish if it exists
|
|
it--;
|
|
if ( it != dishInputList.end() ) {
|
|
dishStack->raiseWidget( *it );
|
|
}
|
|
}
|
|
|
|
void MealInput::showDish( int dn )
|
|
{
|
|
TQValueList <DishInput*>::iterator it = dishInputList.at( dn );
|
|
if ( it != dishInputList.end() )
|
|
dishStack->raiseWidget( *it );
|
|
}
|
|
|
|
DishInput::DishInput( TQWidget* parent, RecipeDB *db, const TQString &title ) : TQWidget( parent ),
|
|
database(db)
|
|
{
|
|
|
|
// Initialize internal variables
|
|
categoryFiltering = false;
|
|
|
|
// Design the widget
|
|
|
|
TQVBoxLayout *layout = new TQVBoxLayout( this );
|
|
layout->setSpacing( 10 );
|
|
|
|
//Horizontal Box to hold the TDEListView's
|
|
listBox = new TQHGroupBox( i18n( "Dish Characteristics" ), this );
|
|
layout->addWidget( listBox );
|
|
|
|
// Dish id
|
|
dishTitle = new DishTitle( listBox, title );
|
|
|
|
//Categories list
|
|
categoriesBox = new TQVBox( listBox );
|
|
categoriesEnabledBox = new TQCheckBox( categoriesBox );
|
|
categoriesEnabledBox->setText( i18n( "Enable Category Filtering" ) );
|
|
|
|
categoriesView = new CategoryCheckListView( categoriesBox, database, false );
|
|
categoriesView->setSizePolicy( TQSizePolicy::Ignored, TQSizePolicy::Ignored );
|
|
categoriesView->setEnabled( false ); // Disable it by default
|
|
|
|
//Constraints list
|
|
constraintsView = new PropertyConstraintListView( listBox, database );
|
|
constraintsView->setSizePolicy( TQSizePolicy::Ignored, TQSizePolicy::Ignored );
|
|
constraintsView->reload();
|
|
|
|
// KDoubleInput based edit boxes
|
|
constraintsEditBox1 = new KDoubleNumInput( constraintsView->viewport() );
|
|
constraintsView->addChild( constraintsEditBox1 );
|
|
constraintsEditBox1->hide();
|
|
constraintsEditBox2 = new KDoubleNumInput( constraintsView->viewport() );
|
|
constraintsView->addChild( constraintsEditBox2 );
|
|
constraintsEditBox2->hide();
|
|
|
|
|
|
// Connect Signals & Slots
|
|
connect( constraintsView, TQ_SIGNAL( executed( TQListViewItem* ) ), this, TQ_SLOT( insertConstraintsEditBoxes( TQListViewItem* ) ) );
|
|
connect( constraintsView, TQ_SIGNAL( selectionChanged() ), this, TQ_SLOT( hideConstraintInputs() ) );
|
|
connect( constraintsEditBox1, TQ_SIGNAL( valueChanged( double ) ), this, TQ_SLOT( setMinValue( double ) ) );
|
|
connect( constraintsEditBox2, TQ_SIGNAL( valueChanged( double ) ), this, TQ_SLOT( setMaxValue( double ) ) );
|
|
connect( categoriesEnabledBox, TQ_SIGNAL( toggled( bool ) ), this, TQ_SLOT( enableCategories( bool ) ) );
|
|
}
|
|
|
|
DishInput::~DishInput()
|
|
{}
|
|
|
|
void DishInput::clear()
|
|
{
|
|
TQListViewItemIterator it( categoriesView );
|
|
while ( it.current() ) {
|
|
TQCheckListItem * item = ( TQCheckListItem* ) it.current();
|
|
item->setOn( false );
|
|
++it;
|
|
}
|
|
|
|
constraintsView->reload();
|
|
categoriesEnabledBox->setChecked( false );
|
|
}
|
|
|
|
void DishInput::enableCategories( bool enable )
|
|
{
|
|
categoriesView->setEnabled( enable );
|
|
categoryFiltering = enable;
|
|
}
|
|
|
|
bool DishInput::isCategoryFilteringEnabled( void ) const
|
|
{
|
|
return categoryFiltering;
|
|
}
|
|
|
|
void DishInput::reload( ReloadFlags flag )
|
|
{
|
|
constraintsView->reload();
|
|
categoriesView->reload(flag);
|
|
}
|
|
|
|
void DishInput::insertConstraintsEditBoxes( TQListViewItem* it )
|
|
{
|
|
TQRect r;
|
|
|
|
// Constraints Box1
|
|
r = constraintsView->header() ->sectionRect( 2 ); //start at the section 2 header
|
|
r.moveBy( 0, constraintsView->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
|
|
r.setWidth( constraintsView->header() ->sectionRect( 2 ).width() ); // and width
|
|
constraintsEditBox1->setGeometry( r );
|
|
|
|
|
|
//Constraints Box2
|
|
r = constraintsView->header() ->sectionRect( 3 ); //start at the section 3 header
|
|
r.moveBy( 0, constraintsView->itemRect( it ).y() ); //Move down to the item
|
|
|
|
r.setHeight( it->height() ); // Set the item's height
|
|
r.setWidth( constraintsView->header() ->sectionRect( 3 ).width() ); // and width
|
|
constraintsEditBox2->setGeometry( r );
|
|
|
|
// Set the values from the item
|
|
constraintsEditBox1->setValue( ( ( ConstraintsListItem* ) it ) ->minVal() );
|
|
constraintsEditBox2->setValue( ( ( ConstraintsListItem* ) it ) ->maxVal() );
|
|
|
|
// Show Boxes
|
|
constraintsEditBox1->show();
|
|
constraintsEditBox2->show();
|
|
}
|
|
|
|
void DishInput::hideConstraintInputs()
|
|
{
|
|
constraintsEditBox1->hide();
|
|
constraintsEditBox2->hide();
|
|
}
|
|
|
|
void DishInput::loadConstraints( ConstraintList *constraints ) const
|
|
{
|
|
constraints->clear();
|
|
Constraint constraint;
|
|
for ( ConstraintsListItem * it = ( ConstraintsListItem* ) ( constraintsView->firstChild() );it;it = ( ConstraintsListItem* ) ( it->nextSibling() ) ) {
|
|
constraint.id = it->propertyId();
|
|
constraint.min = it->minVal();
|
|
constraint.max = it->maxVal();
|
|
constraint.enabled = it->isOn();
|
|
constraints->append( constraint );
|
|
}
|
|
}
|
|
|
|
void DishInput::loadEnabledCategories( ElementList* categories )
|
|
{
|
|
categories->clear();
|
|
|
|
// Only load those that are checked, unless filtering is disabled
|
|
if ( !categoriesView->isEnabled() ) {
|
|
database->loadCategories(categories);
|
|
}
|
|
else {
|
|
*categories = categoriesView->selections();
|
|
}
|
|
}
|
|
|
|
void DishInput::setMinValue( double minValue )
|
|
{
|
|
ConstraintsListItem *it = ( ConstraintsListItem* ) ( constraintsView->selectedItem() ); // Find selected property
|
|
|
|
if ( it )
|
|
it->setMin( minValue );
|
|
}
|
|
|
|
void DishInput::setMaxValue( double maxValue )
|
|
{
|
|
ConstraintsListItem *it = ( ConstraintsListItem* ) ( constraintsView->selectedItem() ); // Find selected property
|
|
|
|
if ( it )
|
|
it->setMax( maxValue );
|
|
}
|
|
|
|
DishTitle::DishTitle( TQWidget *parent, const TQString &title ) : TQWidget( parent )
|
|
{
|
|
titleText = title;
|
|
}
|
|
|
|
|
|
DishTitle::~DishTitle()
|
|
{}
|
|
|
|
void DishTitle::paintEvent( TQPaintEvent * )
|
|
{
|
|
|
|
|
|
|
|
// Now draw the text
|
|
|
|
if ( TQT_VERSION >= 0x030200 ) {
|
|
// Case 1: TQt 3.2+
|
|
|
|
TQPainter painter( this );
|
|
|
|
// First draw the decoration
|
|
painter.setPen( TDEGlobalSettings::activeTitleColor() );
|
|
painter.setBrush( TQBrush( TDEGlobalSettings::activeTitleColor() ) );
|
|
painter.drawRoundRect( 0, 20, 30, height() - 40, 50, ( int ) ( 50.0 / ( height() - 40 ) * 35.0 ) );
|
|
|
|
// Now draw the text
|
|
|
|
TQFont titleFont = TDEGlobalSettings::windowTitleFont ();
|
|
titleFont.setPointSize( 15 );
|
|
painter.setFont( titleFont );
|
|
painter.rotate( -90 );
|
|
painter.setPen( TQColor( 0x00, 0x00, 0x00 ) );
|
|
painter.drawText( 0, 0, -height(), 30, AlignCenter, titleText );
|
|
painter.setPen( TQColor( 0xFF, 0xFF, 0xFF ) );
|
|
painter.drawText( -1, -1, -height() - 1, 29, AlignCenter, titleText );
|
|
painter.end();
|
|
}
|
|
else {
|
|
// Case 2: TQt 3.1
|
|
|
|
// Use a pixmap
|
|
|
|
TQSize pmSize( height(), width() ); //inverted size so we can rotate later
|
|
TQPixmap pm( pmSize );
|
|
pm.fill( TQColor( 0xFF, 0xFF, 0xFF ) );
|
|
TQPainter painter( &pm );
|
|
|
|
// First draw the decoration
|
|
painter.setPen( TDEGlobalSettings::activeTitleColor() );
|
|
painter.setBrush( TQBrush( TDEGlobalSettings::activeTitleColor() ) );
|
|
painter.drawRoundRect( 20, 0, height() - 40, 30, ( int ) ( 50.0 / ( height() - 40 ) * 35.0 ), 50 );
|
|
|
|
// Now draw the text
|
|
TQFont titleFont = TDEGlobalSettings::windowTitleFont ();
|
|
titleFont.setPointSize( 15 );
|
|
painter.setFont( titleFont );
|
|
painter.setPen( TQColor( 0x00, 0x00, 0x00 ) );
|
|
painter.drawText( 0, 0, height(), 30, AlignCenter, titleText );
|
|
painter.setPen( TQColor( 0xFF, 0xFF, 0xFF ) );
|
|
painter.drawText( -1, -1, height() - 1, 29, AlignCenter, titleText );
|
|
painter.end();
|
|
|
|
//Set the border transparent using a mask
|
|
TQBitmap mask( pm.size() );
|
|
mask.fill( TQt::color0 );
|
|
painter.begin( &mask );
|
|
painter.setPen( TQt::color1 );
|
|
painter.setBrush( TQt::color1 );
|
|
painter.drawRoundRect( 20, 0, height() - 40, 30, ( int ) ( 50.0 / ( height() - 40 ) * 35.0 ), 50 );
|
|
|
|
painter.end();
|
|
pm.setMask( mask );
|
|
|
|
//And Rotate
|
|
TQWMatrix m ;
|
|
m.rotate( -90 );
|
|
pm = pm.xForm( m );
|
|
|
|
bitBlt( this, 0, 0, &pm );
|
|
}
|
|
|
|
}
|
|
TQSize DishTitle::sizeHint () const
|
|
{
|
|
return ( TQSize( 40, 200 ) );
|
|
}
|
|
|
|
TQSize DishTitle::minimumSizeHint() const
|
|
{
|
|
return ( TQSize( 40, 200 ) );
|
|
}
|
|
|
|
bool DietWizardDialog::checkCategories( Recipe &rec, int meal, int dish )
|
|
{
|
|
|
|
// Check if the recipe is among the categories chosen
|
|
ElementList categoryList;
|
|
loadEnabledCategories( meal, dish, &categoryList );
|
|
|
|
|
|
for ( ElementList::const_iterator cat_it = rec.categoryList.begin(); cat_it != rec.categoryList.end(); ++cat_it ) {
|
|
if ( categoryList.containsId( ( *cat_it ).id ) )
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
** Calculate the recipe Properties and check if they're within the constraints
|
|
*/
|
|
|
|
bool DietWizardDialog::checkConstraints( Recipe &rec, int meal, int dish )
|
|
{
|
|
// Check if the properties are within the constraints
|
|
ConstraintList constraints;
|
|
loadConstraints( meal, dish, &constraints ); //load the constraints
|
|
|
|
bool any_enabled = false;
|
|
for ( ConstraintList::const_iterator ct_it = constraints.begin(); ct_it != constraints.end(); ++ct_it ) {
|
|
if ( (*ct_it).enabled ) {
|
|
any_enabled = true;
|
|
break;
|
|
}
|
|
}
|
|
if ( !any_enabled )
|
|
return true;
|
|
|
|
// Calculate properties of the recipe
|
|
calculateProperties( rec, database );
|
|
|
|
bool withinLimits = checkLimits( rec.properties, constraints );
|
|
|
|
return ( withinLimits );
|
|
}
|
|
|
|
void DietWizardDialog::loadConstraints( int meal, int dish, ConstraintList *constraints ) const
|
|
{
|
|
MealInput * mealTab = ( MealInput* ) ( mealTabs->page( meal ) ); // Get the meal
|
|
DishInput* dishInput = mealTab->dishInputList[ dish ]; // Get the dish input
|
|
dishInput->loadConstraints( constraints ); //Load the constraints form the TDEListView
|
|
}
|
|
|
|
void DietWizardDialog::loadEnabledCategories( int meal, int dish, ElementList *categories )
|
|
{
|
|
MealInput * mealTab = ( MealInput* ) ( mealTabs->page( meal ) ); // Get the meal
|
|
DishInput* dishInput = mealTab->dishInputList[ dish ]; // Get the dish input
|
|
dishInput->loadEnabledCategories( categories ); //Load the categories that have been checked in the TDEListView
|
|
}
|
|
|
|
bool DietWizardDialog::categoryFiltering( int meal, int dish ) const
|
|
{
|
|
MealInput * mealTab = ( MealInput* ) ( mealTabs->page( meal ) ); // Get the meal
|
|
DishInput* dishInput = mealTab->dishInputList[ dish ]; // Get the dish input
|
|
return ( dishInput->isCategoryFilteringEnabled() ); //Load the categories that have been checked in the TDEListView
|
|
}
|
|
|
|
bool DietWizardDialog::checkLimits( IngredientPropertyList &properties, ConstraintList &constraints )
|
|
{
|
|
for ( ConstraintList::const_iterator ct_it = constraints.begin(); ct_it != constraints.end(); ++ct_it ) {
|
|
if ( (*ct_it).enabled ) {
|
|
IngredientPropertyList::const_iterator ip_it = properties.find( (*ct_it).id );
|
|
if ( ip_it != properties.end() ) {
|
|
if ( ( (*ip_it).amount > (*ct_it).max ) || ( (*ip_it).amount < (*ct_it).min ) )
|
|
return false;
|
|
}
|
|
else
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void DietWizardDialog::createShoppingList( void )
|
|
{
|
|
emit dietReady();
|
|
}
|
|
|
|
RecipeList& DietWizardDialog::dietList( void )
|
|
{
|
|
return *dietRList;
|
|
}
|
|
|
|
#include "dietwizarddialog.moc"
|