summaryrefslogtreecommitdiffstats
path: root/src/dialogs
diff options
context:
space:
mode:
Diffstat (limited to 'src/dialogs')
-rw-r--r--src/dialogs/Makefile.am38
-rw-r--r--src/dialogs/advancedsearchdialog.cpp932
-rw-r--r--src/dialogs/advancedsearchdialog.h179
-rw-r--r--src/dialogs/authorsdialog.cpp66
-rw-r--r--src/dialogs/authorsdialog.h51
-rw-r--r--src/dialogs/borderdialog.cpp261
-rw-r--r--src/dialogs/borderdialog.h75
-rw-r--r--src/dialogs/categorieseditordialog.cpp67
-rw-r--r--src/dialogs/categorieseditordialog.h56
-rw-r--r--src/dialogs/conversiondialog.cpp166
-rw-r--r--src/dialogs/conversiondialog.h62
-rw-r--r--src/dialogs/createcategorydialog.cpp80
-rw-r--r--src/dialogs/createcategorydialog.h51
-rw-r--r--src/dialogs/createelementdialog.cpp48
-rw-r--r--src/dialogs/createelementdialog.h40
-rw-r--r--src/dialogs/createingredientweightdialog.cpp124
-rw-r--r--src/dialogs/createingredientweightdialog.h60
-rw-r--r--src/dialogs/createpropertydialog.cpp69
-rw-r--r--src/dialogs/createpropertydialog.h56
-rw-r--r--src/dialogs/createunitdialog.cpp116
-rw-r--r--src/dialogs/createunitdialog.h52
-rw-r--r--src/dialogs/dbimportdialog.cpp219
-rw-r--r--src/dialogs/dbimportdialog.h76
-rw-r--r--src/dialogs/dependanciesdialog.cpp100
-rw-r--r--src/dialogs/dependanciesdialog.h60
-rw-r--r--src/dialogs/dietviewdialog.cpp137
-rw-r--r--src/dialogs/dietviewdialog.h45
-rw-r--r--src/dialogs/dietwizarddialog.cpp748
-rw-r--r--src/dialogs/dietwizarddialog.h222
-rw-r--r--src/dialogs/editratingdialog.cpp243
-rw-r--r--src/dialogs/editratingdialog.h77
-rw-r--r--src/dialogs/ingredientgroupsdialog.cpp65
-rw-r--r--src/dialogs/ingredientgroupsdialog.h33
-rw-r--r--src/dialogs/ingredientmatcherdialog.cpp353
-rw-r--r--src/dialogs/ingredientmatcherdialog.h156
-rw-r--r--src/dialogs/ingredientparserdialog.cpp299
-rw-r--r--src/dialogs/ingredientparserdialog.h65
-rw-r--r--src/dialogs/ingredientsdialog.cpp702
-rw-r--r--src/dialogs/ingredientsdialog.h93
-rw-r--r--src/dialogs/pagesetupdialog.cpp310
-rw-r--r--src/dialogs/pagesetupdialog.h72
-rw-r--r--src/dialogs/prepmethodsdialog.cpp67
-rw-r--r--src/dialogs/prepmethodsdialog.h53
-rw-r--r--src/dialogs/propertiesdialog.cpp77
-rw-r--r--src/dialogs/propertiesdialog.h47
-rw-r--r--src/dialogs/recipeimportdialog.cpp185
-rw-r--r--src/dialogs/recipeimportdialog.h80
-rw-r--r--src/dialogs/recipeinputdialog.cpp1641
-rw-r--r--src/dialogs/recipeinputdialog.h228
-rw-r--r--src/dialogs/recipeprintpreview.cpp62
-rw-r--r--src/dialogs/recipeprintpreview.h41
-rw-r--r--src/dialogs/recipeviewdialog.cpp167
-rw-r--r--src/dialogs/recipeviewdialog.h77
-rw-r--r--src/dialogs/refineshoppinglistdialog.cpp206
-rw-r--r--src/dialogs/refineshoppinglistdialog.h66
-rw-r--r--src/dialogs/resizerecipedialog.cpp191
-rw-r--r--src/dialogs/resizerecipedialog.h69
-rw-r--r--src/dialogs/selectauthorsdialog.cpp181
-rw-r--r--src/dialogs/selectauthorsdialog.h66
-rw-r--r--src/dialogs/selectcategoriesdialog.cpp104
-rw-r--r--src/dialogs/selectcategoriesdialog.h57
-rw-r--r--src/dialogs/selectpropertydialog.cpp123
-rw-r--r--src/dialogs/selectpropertydialog.h60
-rw-r--r--src/dialogs/selectrecipedialog.cpp257
-rw-r--r--src/dialogs/selectrecipedialog.h99
-rw-r--r--src/dialogs/selectunitdialog.cpp77
-rw-r--r--src/dialogs/selectunitdialog.h51
-rw-r--r--src/dialogs/setupdisplay.cpp602
-rw-r--r--src/dialogs/setupdisplay.h148
-rw-r--r--src/dialogs/shoppinglistdialog.cpp267
-rw-r--r--src/dialogs/shoppinglistdialog.h76
-rw-r--r--src/dialogs/shoppinglistviewdialog.cpp102
-rw-r--r--src/dialogs/shoppinglistviewdialog.h46
-rw-r--r--src/dialogs/similarcategoriesdialog.cpp383
-rw-r--r--src/dialogs/similarcategoriesdialog.h84
-rw-r--r--src/dialogs/unitsdialog.cpp211
-rw-r--r--src/dialogs/unitsdialog.h65
-rw-r--r--src/dialogs/usdadatadialog.cpp200
-rw-r--r--src/dialogs/usdadatadialog.h47
79 files changed, 13287 insertions, 0 deletions
diff --git a/src/dialogs/Makefile.am b/src/dialogs/Makefile.am
new file mode 100644
index 0000000..23f80e1
--- /dev/null
+++ b/src/dialogs/Makefile.am
@@ -0,0 +1,38 @@
+## Makefile.am for krecipes
+
+# this is the program that gets installed. it's name is used for all
+# of the other Makefile.am variables
+
+# set the include path for X, tqt and TDE
+INCLUDES = -I$(srcdir)/.. $(all_includes)
+
+KDE_CXXFLAGS = $(USE_EXCEPTIONS)
+
+noinst_LTLIBRARIES=libkrecipesdialogs.la
+libkrecipesdialogs_la_SOURCES= \
+ advancedsearchdialog.cpp recipeimportdialog.cpp \
+ dietwizarddialog.cpp recipeinputdialog.cpp \
+ recipeviewdialog.cpp selectrecipedialog.cpp \
+ ingredientsdialog.cpp selectunitdialog.cpp \
+ createelementdialog.cpp propertiesdialog.cpp \
+ createpropertydialog.cpp selectpropertydialog.cpp \
+ unitsdialog.cpp dependanciesdialog.cpp \
+ shoppinglistdialog.cpp shoppinglistviewdialog.cpp \
+ selectcategoriesdialog.cpp categorieseditordialog.cpp \
+ authorsdialog.cpp selectauthorsdialog.cpp \
+ resizerecipedialog.cpp \
+ dietviewdialog.cpp ingredientmatcherdialog.cpp \
+ usdadatadialog.cpp prepmethodsdialog.cpp \
+ createcategorydialog.cpp borderdialog.cpp \
+ refineshoppinglistdialog.cpp pagesetupdialog.cpp \
+ dbimportdialog.cpp createunitdialog.cpp \
+ setupdisplay.cpp \
+ ingredientparserdialog.cpp ingredientgroupsdialog.cpp \
+ editratingdialog.cpp similarcategoriesdialog.cpp \
+ conversiondialog.cpp createingredientweightdialog.cpp \
+ recipeprintpreview.cpp
+
+libkrecipesdialogs_la_METASOURCES=AUTO
+
+#the library search path.
+libkrecipesdialogs_la_LDFLAGS = $(KDE_RPATH) $(all_libraries)
diff --git a/src/dialogs/advancedsearchdialog.cpp b/src/dialogs/advancedsearchdialog.cpp
new file mode 100644
index 0000000..9f4864d
--- /dev/null
+++ b/src/dialogs/advancedsearchdialog.cpp
@@ -0,0 +1,932 @@
+/***************************************************************************
+* Copyright (C) 2003-2004 by *
+* 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 "advancedsearchdialog.h"
+
+#include <tqvariant.h>
+#include <tqpushbutton.h>
+#include <tqtabwidget.h>
+#include <tqwidget.h>
+#include <tqcheckbox.h>
+#include <tqframe.h>
+#include <tqcombobox.h>
+#include <tqheader.h>
+#include <tqlistview.h>
+#include <tqgroupbox.h>
+#include <tqspinbox.h>
+#include <tqdatetimeedit.h>
+#include <kpushbutton.h>
+#include <tqlayout.h>
+#include <tqtooltip.h>
+#include <tqwhatsthis.h>
+#include <tqlabel.h>
+#include <tqlineedit.h>
+#include <tqscrollview.h>
+#include <tqhbox.h>
+#include <tqradiobutton.h>
+#include <tqbuttongroup.h>
+
+#include <tdeapplication.h>
+#include <kcursor.h>
+#include <kdebug.h>
+#include <kiconloader.h>
+#include <tdelistview.h>
+#include <tdelocale.h>
+#include <tdeconfig.h>
+#include <tdeglobal.h>
+#include <tdepopupmenu.h>
+
+#include "backends/recipedb.h"
+#include "backends/searchparameters.h"
+#include "recipeactionshandler.h"
+#include "widgets/recipelistview.h"
+#include "widgets/kdateedit.h"
+#include "widgets/ratingwidget.h"
+#include "widgets/fractioninput.h"
+#include "widgets/criteriacombobox.h"
+
+#include "profiling.h"
+
+AdvancedSearchDialog::AdvancedSearchDialog( TQWidget *parent, RecipeDB *db ) : TQWidget( parent ),
+ database( db )
+{
+ ///
+ ///BEGIN OF AUTOMATICALLY GENERATED GUI CODE///
+ ///
+ AdvancedSearchDialogLayout = new TQHBoxLayout( this, 5, 3, "AdvancedSearchDialogLayout");
+
+ layout7 = new TQVBoxLayout( 0, 0, 3, "layout7");
+
+ textLabel1_4 = new TQLabel( this, "textLabel1_4" );
+ layout7->addWidget( textLabel1_4 );
+
+ scrollView1 = new TQScrollView( this, "scrollView1" );
+ scrollView1->enableClipper(true);
+
+ parametersFrame = new TQFrame( scrollView1, "parametersFrame" );
+ parametersFrame->setSizePolicy( TQSizePolicy( (TQSizePolicy::SizeType)3, (TQSizePolicy::SizeType)3, 0, 0, parametersFrame->sizePolicy().hasHeightForWidth() ) );
+ parametersFrame->setFrameShape( TQFrame::NoFrame );
+ parametersFrame->setFrameShadow( TQFrame::Plain );
+ parametersFrame->setLineWidth( 0 );
+ parametersFrameLayout = new TQVBoxLayout( parametersFrame, 0, 0, "parametersFrameLayout");
+
+ titleButton = new TQPushButton( parametersFrame, "titleButton" );
+ titleButton->setToggleButton( TRUE );
+ parametersFrameLayout->addWidget( titleButton );
+
+ titleFrame = new TQFrame( parametersFrame, "titleFrame" );
+ titleFrame->setFrameShape( TQFrame::StyledPanel );
+ titleFrame->setFrameShadow( TQFrame::Raised );
+ titleFrameLayout = new TQVBoxLayout( titleFrame, 5, 3, "titleFrameLayout");
+
+ requireAllTitle = new TQCheckBox( i18n("Require All Words"), titleFrame );
+ titleFrameLayout->addWidget( requireAllTitle );
+
+ TQHBox *titleHBox = new TQHBox( titleFrame );
+ /*TQLabel *titleInfoLabel = */new TQLabel(i18n("Keywords:"),titleHBox);
+ titleEdit = new TQLineEdit( titleHBox, "titleEdit" );
+ titleFrameLayout->addWidget( titleHBox );
+
+ parametersFrameLayout->addWidget( titleFrame );
+ titleFrameSpacer = new TQSpacerItem( 0, 0, TQSizePolicy::Minimum, TQSizePolicy::Preferred );
+ parametersFrameLayout->addItem( titleFrameSpacer );
+
+
+ ingredientButton = new TQPushButton( parametersFrame, "ingredientButton" );
+ ingredientButton->setToggleButton( TRUE );
+ parametersFrameLayout->addWidget( ingredientButton );
+
+ ingredientFrame = new TQFrame( parametersFrame, "ingredientFrame" );
+ ingredientFrame->setFrameShape( TQFrame::StyledPanel );
+ ingredientFrame->setFrameShadow( TQFrame::Raised );
+ ingredientFrameLayout = new TQGridLayout( ingredientFrame, 1, 1, 3, 3, "ingredientFrameLayout");
+
+ TQLabel *ingredientInfoLabel = new TQLabel(i18n("Enter ingredients: (e.g. chicken pasta \"white wine\")"),ingredientFrame);
+ ingredientInfoLabel->setTextFormat( TQt::RichText );
+ ingredientFrameLayout->addMultiCellWidget( ingredientInfoLabel, 0, 0, 0, 1 );
+
+ ingredientsAllEdit = new TQLineEdit( ingredientFrame, "ingredientsAllEdit" );
+
+ ingredientFrameLayout->addWidget( ingredientsAllEdit, 1, 1 );
+
+ ingredientsAnyEdit = new TQLineEdit( ingredientFrame, "ingredientsAnyEdit" );
+
+ ingredientFrameLayout->addWidget( ingredientsAnyEdit, 2, 1 );
+
+ textLabel1_2 = new TQLabel( ingredientFrame, "textLabel1_2" );
+
+ ingredientFrameLayout->addWidget( textLabel1_2, 2, 0 );
+
+ textLabel1 = new TQLabel( ingredientFrame, "textLabel1" );
+
+ ingredientFrameLayout->addWidget( textLabel1, 1, 0 );
+
+ ingredientsWithoutEdit = new TQLineEdit( ingredientFrame, "ingredientsWithoutEdit" );
+
+ ingredientFrameLayout->addWidget( ingredientsWithoutEdit, 3, 1 );
+
+ textLabel1_3 = new TQLabel( ingredientFrame, "textLabel1_3" );
+
+ ingredientFrameLayout->addWidget( textLabel1_3, 3, 0 );
+ parametersFrameLayout->addWidget( ingredientFrame );
+ spacer3_2_3_2_2 = new TQSpacerItem( 0, 0, TQSizePolicy::Minimum, TQSizePolicy::Preferred );
+ parametersFrameLayout->addItem( spacer3_2_3_2_2 );
+
+
+ categoriesButton = new TQPushButton( parametersFrame, "categoriesButton" );
+ categoriesButton->setToggleButton( TRUE );
+ parametersFrameLayout->addWidget( categoriesButton );
+
+ categoryFrame = new TQFrame( parametersFrame, "categoryFrame" );
+ categoryFrame->setFrameShape( TQFrame::StyledPanel );
+ categoryFrame->setFrameShadow( TQFrame::Raised );
+ categoryFrameLayout = new TQGridLayout( categoryFrame, 1, 1, 3, 3, "categoryFrameLayout");
+
+ TQLabel *categoryInfoLabel = new TQLabel(i18n("Enter categories: (e.g. Desserts Pastas \"Main Dishes\")"),categoryFrame);
+ categoryInfoLabel->setTextFormat( TQt::RichText );
+ categoryFrameLayout->addMultiCellWidget( categoryInfoLabel, 0, 0, 0, 1 );
+
+ categoriesAllEdit = new TQLineEdit( categoryFrame, "categoriesAllEdit" );
+
+ categoryFrameLayout->addWidget( categoriesAllEdit, 1, 1 );
+
+ textLabel1_5 = new TQLabel( categoryFrame, "textLabel1_5" );
+
+ categoryFrameLayout->addWidget( textLabel1_5, 1, 0 );
+
+ textLabel1_3_3 = new TQLabel( categoryFrame, "textLabel1_3_3" );
+
+ categoryFrameLayout->addWidget( textLabel1_3_3, 3, 0 );
+
+ categoriesAnyEdit = new TQLineEdit( categoryFrame, "categoriesAnyEdit" );
+
+ categoryFrameLayout->addWidget( categoriesAnyEdit, 2, 1 );
+
+ textLabel1_2_3 = new TQLabel( categoryFrame, "textLabel1_2_3" );
+
+ categoryFrameLayout->addWidget( textLabel1_2_3, 2, 0 );
+
+ categoriesNotEdit = new TQLineEdit( categoryFrame, "categoriesNotEdit" );
+
+ categoryFrameLayout->addWidget( categoriesNotEdit, 3, 1 );
+ parametersFrameLayout->addWidget( categoryFrame );
+ spacer3_2_3_2 = new TQSpacerItem( 0, 0, TQSizePolicy::Minimum, TQSizePolicy::Preferred );
+ parametersFrameLayout->addItem( spacer3_2_3_2 );
+
+
+ authorsButton = new TQPushButton( parametersFrame, "authorsButton" );
+ authorsButton->setToggleButton( TRUE );
+ parametersFrameLayout->addWidget( authorsButton );
+
+ authorsFrame = new TQFrame( parametersFrame, "authorsFrame" );
+ authorsFrame->setFrameShape( TQFrame::StyledPanel );
+ authorsFrame->setFrameShadow( TQFrame::Raised );
+ authorsFrameLayout = new TQGridLayout( authorsFrame, 1, 1, 3, 3, "authorsFrameLayout");
+
+ TQLabel *authorsInfoLabel = new TQLabel(i18n("Enter author name (e.g. Smith or \"Jane Doe\")"),authorsFrame);
+ authorsInfoLabel->setTextFormat( TQt::RichText );
+ authorsFrameLayout->addMultiCellWidget( authorsInfoLabel, 0, 0, 0, 1 );
+
+ textLabel1_2_4 = new TQLabel( authorsFrame, "textLabel1_2_4" );
+
+ authorsFrameLayout->addWidget( textLabel1_2_4, 1, 0 );
+
+ textLabel1_6 = new TQLabel( authorsFrame, "textLabel1_6" );
+
+ authorsFrameLayout->addWidget( textLabel1_6, 2, 0 );
+
+ textLabel1_3_4 = new TQLabel( authorsFrame, "textLabel1_3_4" );
+
+ authorsFrameLayout->addWidget( textLabel1_3_4, 3, 0 );
+
+ authorsAnyEdit = new TQLineEdit( authorsFrame, "authorsAnyEdit" );
+
+ authorsFrameLayout->addWidget( authorsAnyEdit, 1, 1 );
+
+ authorsAllEdit = new TQLineEdit( authorsFrame, "authorsAllEdit" );
+
+ authorsFrameLayout->addWidget( authorsAllEdit, 2, 1 );
+
+ authorsWithoutEdit = new TQLineEdit( authorsFrame, "authorsWithoutEdit" );
+
+ authorsFrameLayout->addWidget( authorsWithoutEdit, 3, 1 );
+ parametersFrameLayout->addWidget( authorsFrame );
+ spacer3_2_3 = new TQSpacerItem( 0, 0, TQSizePolicy::Minimum, TQSizePolicy::Preferred );
+ parametersFrameLayout->addItem( spacer3_2_3 );
+
+
+ servingsButton = new TQPushButton( parametersFrame, "servingsButton" );
+ servingsButton->setToggleButton( TRUE );
+ parametersFrameLayout->addWidget( servingsButton );
+
+ servingsFrame = new TQFrame( parametersFrame, "servingsFrame" );
+ servingsFrame->setFrameShape( TQFrame::StyledPanel );
+ servingsFrame->setFrameShadow( TQFrame::Raised );
+ servingsFrameLayout = new TQVBoxLayout( servingsFrame, 3, 3, "servingsFrameLayout");
+
+ enableServingsCheckBox = new TQCheckBox( servingsFrame, "enableServingsCheckBox" );
+ servingsFrameLayout->addWidget( enableServingsCheckBox );
+
+ layout5 = new TQHBoxLayout( 0, 0, 3, "layout5");
+
+ servingsComboBox = new TQComboBox( FALSE, servingsFrame, "servingsComboBox" );
+ servingsComboBox->setEnabled( FALSE );
+ servingsComboBox->setSizePolicy( TQSizePolicy( (TQSizePolicy::SizeType)1, (TQSizePolicy::SizeType)0, 1, 0, servingsComboBox->sizePolicy().hasHeightForWidth() ) );
+ layout5->addWidget( servingsComboBox );
+
+ servingsSpinBox = new TQSpinBox( servingsFrame, "servingsSpinBox" );
+ servingsSpinBox->setEnabled( FALSE );
+ servingsSpinBox->setMinValue( 1 );
+ servingsSpinBox->setMaxValue( 9999 );
+ layout5->addWidget( servingsSpinBox );
+ servingsFrameLayout->addLayout( layout5 );
+ parametersFrameLayout->addWidget( servingsFrame );
+ spacer3_2_2 = new TQSpacerItem( 0, 0, TQSizePolicy::Minimum, TQSizePolicy::Preferred );
+ parametersFrameLayout->addItem( spacer3_2_2 );
+
+
+ prepTimeButton = new TQPushButton( parametersFrame, "prepTimeButton" );
+ prepTimeButton->setToggleButton( TRUE );
+ parametersFrameLayout->addWidget( prepTimeButton );
+
+ prepTimeFrame = new TQFrame( parametersFrame, "prepTimeFrame" );
+ prepTimeFrame->setFrameShape( TQFrame::StyledPanel );
+ prepTimeFrame->setFrameShadow( TQFrame::Raised );
+ prepTimeFrameLayout = new TQVBoxLayout( prepTimeFrame, 3, 3, "prepTimeFrameLayout");
+
+ enablePrepTimeCheckBox = new TQCheckBox( prepTimeFrame, "enablePrepTimeCheckBox" );
+ prepTimeFrameLayout->addWidget( enablePrepTimeCheckBox );
+
+ layout6 = new TQHBoxLayout( 0, 0, 3, "layout6");
+
+ prepTimeComboBox = new TQComboBox( FALSE, prepTimeFrame, "prepTimeComboBox" );
+ prepTimeComboBox->setEnabled( FALSE );
+ prepTimeComboBox->setSizePolicy( TQSizePolicy( (TQSizePolicy::SizeType)1, (TQSizePolicy::SizeType)0, 1, 0, prepTimeComboBox->sizePolicy().hasHeightForWidth() ) );
+ layout6->addWidget( prepTimeComboBox );
+
+ prepTimeEdit = new TQTimeEdit( prepTimeFrame, "prepTimeEdit" );
+ prepTimeEdit->setEnabled( FALSE );
+ prepTimeEdit->setDisplay( int( TQTimeEdit::Minutes | TQTimeEdit::Hours ) );
+ layout6->addWidget( prepTimeEdit );
+ prepTimeFrameLayout->addLayout( layout6 );
+ parametersFrameLayout->addWidget( prepTimeFrame );
+ spacer15 = new TQSpacerItem( 0, 0, TQSizePolicy::Minimum, TQSizePolicy::Preferred );
+ parametersFrameLayout->addItem( spacer15 );
+
+
+ instructionsButton = new TQPushButton( parametersFrame, "instructionsButton" );
+ instructionsButton->setToggleButton( TRUE );
+ parametersFrameLayout->addWidget( instructionsButton );
+
+ instructionsFrame = new TQFrame( parametersFrame, "instructionsFrame" );
+ instructionsFrame->setFrameShape( TQFrame::StyledPanel );
+ instructionsFrame->setFrameShadow( TQFrame::Raised );
+ instructionsFrameLayout = new TQVBoxLayout( instructionsFrame, 5, 3, "instructionsFrameLayout");
+
+ requireAllInstructions = new TQCheckBox( i18n("Require All Words"), instructionsFrame );
+ instructionsFrameLayout->addWidget( requireAllInstructions );
+
+ TQHBox *instructionsHBox = new TQHBox(instructionsFrame);
+ /*TQLabel *instructionsInfoLabel = */new TQLabel(i18n("Keywords:"),instructionsHBox);
+
+ instructionsEdit = new TQLineEdit( instructionsHBox, "instructionsEdit" );
+ instructionsFrameLayout->addWidget( instructionsHBox );
+
+ parametersFrameLayout->addWidget( instructionsFrame );
+ instructionsFrameSpacer = new TQSpacerItem( 0, 0, TQSizePolicy::Minimum, TQSizePolicy::Preferred );
+ parametersFrameLayout->addItem( instructionsFrameSpacer );
+
+
+ metaDataButton = new TQPushButton( parametersFrame, "metaDataButton" );
+ metaDataButton->setToggleButton( TRUE );
+ parametersFrameLayout->addWidget( metaDataButton );
+
+ metaDataFrame = new TQFrame( parametersFrame, "metaDataFrame" );
+ metaDataFrame->setFrameShape( TQFrame::StyledPanel );
+ metaDataFrame->setFrameShadow( TQFrame::Raised );
+ metaDataFrameLayout = new TQVBoxLayout( metaDataFrame, 5, 3, "metaDataFrameLayout");
+
+ TQLabel *createdLabel = new TQLabel( i18n("Created:"), metaDataFrame );
+ metaDataFrameLayout->addWidget( createdLabel );
+
+ TQHBox *createdHBox = new TQHBox(metaDataFrame);
+ createdStartDateEdit = new KDateEdit(createdHBox,"createdStartEdit");
+ createdStartDateEdit->setSizePolicy( TQSizePolicy::MinimumExpanding, TQSizePolicy::Preferred );
+ (void)new TQLabel(" - ",createdHBox);
+ createdEndDateEdit = new KDateEdit(createdHBox,"createdEndEdit");
+ createdEndDateEdit->setSizePolicy( TQSizePolicy::MinimumExpanding, TQSizePolicy::Preferred );
+ metaDataFrameLayout->addWidget( createdHBox );
+
+ TQLabel *modifiedLabel = new TQLabel( i18n("Modified:"), metaDataFrame );
+ metaDataFrameLayout->addWidget( modifiedLabel );
+
+ TQHBox *modifiedHBox = new TQHBox(metaDataFrame);
+ modifiedStartDateEdit = new KDateEdit(modifiedHBox,"modifiedStartEdit");
+ modifiedStartDateEdit->setSizePolicy( TQSizePolicy::MinimumExpanding, TQSizePolicy::Preferred );
+ (void)new TQLabel(" - ",modifiedHBox);
+ modifiedEndDateEdit = new KDateEdit(modifiedHBox,"modifiedEndEdit");
+ modifiedEndDateEdit->setSizePolicy( TQSizePolicy::MinimumExpanding, TQSizePolicy::Preferred );
+ metaDataFrameLayout->addWidget( modifiedHBox );
+
+ TQLabel *accessedLabel = new TQLabel( i18n("Last Accessed:"), metaDataFrame );
+ metaDataFrameLayout->addWidget( accessedLabel );
+
+ TQHBox *accessedHBox = new TQHBox(metaDataFrame);
+ accessedStartDateEdit = new KDateEdit(accessedHBox,"accessedStartEdit");
+ accessedStartDateEdit->setSizePolicy( TQSizePolicy::MinimumExpanding, TQSizePolicy::Preferred );
+ (void)new TQLabel(" - ",accessedHBox);
+ accessedEndDateEdit = new KDateEdit(accessedHBox,"accessedEndEdit");
+ accessedEndDateEdit->setSizePolicy( TQSizePolicy::MinimumExpanding, TQSizePolicy::Preferred );
+ metaDataFrameLayout->addWidget( accessedHBox );
+
+ parametersFrameLayout->addWidget( metaDataFrame );
+ metaDataFrameSpacer = new TQSpacerItem( 0, 0, TQSizePolicy::Minimum, TQSizePolicy::Preferred );
+ parametersFrameLayout->addItem( metaDataFrameSpacer );
+
+ //=============RATINGS FRAME===========//
+ ratingsButton = new TQPushButton( parametersFrame, "ratingsButton" );
+ ratingsButton->setToggleButton( TRUE );
+ parametersFrameLayout->addWidget( ratingsButton );
+
+ ratingButtonGroup = new TQButtonGroup( parametersFrame, "ratingButtonGroup" );
+ ratingButtonGroup->setLineWidth( 0 );
+ ratingButtonGroup->setColumnLayout(0, TQt::Vertical );
+ ratingButtonGroup->layout()->setSpacing( 5 );
+ ratingButtonGroup->layout()->setMargin( 3 );
+ ratingButtonGroupLayout = new TQVBoxLayout( ratingButtonGroup->layout() );
+ ratingButtonGroupLayout->setAlignment( TQt::AlignTop );
+
+ ratingAvgRadioButton = new TQRadioButton( ratingButtonGroup, "ratingAvgRadioButton" );
+ ratingAvgRadioButton->setChecked( TRUE );
+ ratingButtonGroupLayout->addWidget( ratingAvgRadioButton );
+
+ ratingAvgFrame = new TQFrame( ratingButtonGroup, "ratingAvgFrame" );
+ ratingAvgFrame->setLineWidth( 0 );
+ ratingAvgFrameLayout = new TQHBoxLayout( ratingAvgFrame, 2, 2, "ratingAvgFrameLayout");
+
+ avgStarsEdit = new FractionInput( ratingAvgFrame );
+ avgStarsEdit->setAllowRange(true);
+ ratingAvgFrameLayout->addWidget( avgStarsEdit );
+
+ avgStarsLabel = new TQLabel( ratingAvgFrame, "avgStarsLabel" );
+ ratingAvgFrameLayout->addWidget( avgStarsLabel );
+ ratingButtonGroupLayout->addWidget( ratingAvgFrame );
+
+ criterionRadioButton = new TQRadioButton( ratingButtonGroup, "criterionRadioButton" );
+ ratingButtonGroupLayout->addWidget( criterionRadioButton );
+
+ criterionFrame = new TQFrame( ratingButtonGroup, "criterionFrame" );
+ criterionFrame->setEnabled( FALSE );
+ criterionFrame->setLineWidth( 0 );
+ criterionFrameLayout = new TQVBoxLayout( criterionFrame, 2, 2, "criterionFrameLayout");
+
+ layout12 = new TQHBoxLayout( 0, 0, 6, "layout12");
+
+ criteriaComboBox = new CriteriaComboBox( FALSE, criterionFrame, database );
+ criteriaComboBox->setEditable( false );
+ criteriaComboBox->reload();
+ layout12->addWidget( criteriaComboBox );
+
+ starsWidget = new FractionInput( criterionFrame );
+ starsWidget->setAllowRange(true);
+ starsWidget->setSizePolicy( TQSizePolicy::Ignored, TQSizePolicy::Preferred );
+ layout12->addWidget( starsWidget );
+
+
+ addCriteriaButton = new TQPushButton( criterionFrame, "addCriteriaButton" );
+ addCriteriaButton->setSizePolicy( TQSizePolicy( (TQSizePolicy::SizeType)0, (TQSizePolicy::SizeType)0, 0, 0, addCriteriaButton->sizePolicy().hasHeightForWidth() ) );
+ addCriteriaButton->setMaximumSize( TQSize( 30, 30 ) );
+ layout12->addWidget( addCriteriaButton );
+#if 0
+ removeCriteriaButton = new TQPushButton( criterionFrame, "removeCriteriaButton" );
+ removeCriteriaButton->setSizePolicy( TQSizePolicy( (TQSizePolicy::SizeType)0, (TQSizePolicy::SizeType)0, 0, 0, removeCriteriaButton->sizePolicy().hasHeightForWidth() ) );
+ removeCriteriaButton->setMaximumSize( TQSize( 30, 30 ) );
+ layout12->addWidget( removeCriteriaButton );
+#endif
+ criterionFrameLayout->addLayout( layout12 );
+
+ criteriaListView = new TDEListView( criterionFrame, "criteriaListView" );
+ criteriaListView->setSizePolicy( TQSizePolicy::Preferred, TQSizePolicy::Minimum );
+ criteriaListView->addColumn( i18n( "Criterion" ) );
+ criteriaListView->addColumn( i18n( "Stars" ) );
+ criterionFrameLayout->addWidget( criteriaListView );
+ ratingButtonGroupLayout->addWidget( criterionFrame );
+
+ parametersFrameLayout->addWidget( ratingButtonGroup );
+ ratingsFrameSpacer = new TQSpacerItem( 0, 0, TQSizePolicy::Minimum, TQSizePolicy::Expanding );
+ parametersFrameLayout->addItem( ratingsFrameSpacer );
+
+
+ scrollView1->addChild( parametersFrame );
+ layout7->addWidget( scrollView1 );
+
+ layout9 = new TQHBoxLayout( 0, 0, 3, "layout9");
+
+ clearButton = new KPushButton( this, "clearButton" );
+ clearButton->setSizePolicy( TQSizePolicy( (TQSizePolicy::SizeType)1, (TQSizePolicy::SizeType)0, 0, 0, clearButton->sizePolicy().hasHeightForWidth() ) );
+ layout9->addWidget( clearButton );
+ spacer3 = new TQSpacerItem( 110, 0, TQSizePolicy::Expanding, TQSizePolicy::Minimum );
+ layout9->addItem( spacer3 );
+
+ findButton = new KPushButton( this, "findButton" );
+ findButton->setSizePolicy( TQSizePolicy( (TQSizePolicy::SizeType)1, (TQSizePolicy::SizeType)0, 0, 0, findButton->sizePolicy().hasHeightForWidth() ) );
+ layout9->addWidget( findButton );
+ layout7->addLayout( layout9 );
+ AdvancedSearchDialogLayout->addLayout( layout7 );
+
+ resultsListView = new TDEListView( this, "resultsListView" );
+ resultsListView->setSelectionMode( TQListView::Extended );
+ resultsListView->setSizePolicy( TQSizePolicy( (TQSizePolicy::SizeType)7, (TQSizePolicy::SizeType)7, 0, 1, resultsListView->sizePolicy().hasHeightForWidth() ) );
+ AdvancedSearchDialogLayout->addWidget( resultsListView );
+ languageChange();
+ clearWState( WState_Polished );
+ ///
+ ///END OF AUTOMATICALLY GENERATED GUI CODE///
+ ///
+
+ resultsListView->setSizePolicy( TQSizePolicy::MinimumExpanding, TQSizePolicy::Preferred );
+ scrollView1->setSizePolicy( TQSizePolicy::Preferred, TQSizePolicy::Ignored );
+
+ AdvancedSearchDialogLayout->setStretchFactor( resultsListView, 2 );
+
+ scrollView1->setHScrollBarMode( TQScrollView::AlwaysOff );
+ scrollView1->setResizePolicy( TQScrollView::AutoOneFit );
+
+ TDEConfig *config = TDEGlobal::config();
+ config->setGroup( "Advanced" );
+ bool show_id = config->readBoolEntry( "ShowID", false );
+ resultsListView->addColumn( i18n( "Title" ) );
+ resultsListView->addColumn( i18n( "Id" ), show_id ? -1 : 0 );
+
+ actionHandler = new RecipeActionsHandler( resultsListView, database, RecipeActionsHandler::Open | RecipeActionsHandler::Edit | RecipeActionsHandler::Export | RecipeActionsHandler::CopyToClipboard | RecipeActionsHandler::Remove );
+
+ connect( titleEdit, TQ_SIGNAL( returnPressed() ), TQ_SLOT( search() ) );
+ connect( ingredientsAllEdit, TQ_SIGNAL( returnPressed() ), TQ_SLOT( search() ) );
+ connect( ingredientsAnyEdit, TQ_SIGNAL( returnPressed() ), TQ_SLOT( search() ) );
+ connect( ingredientsWithoutEdit, TQ_SIGNAL( returnPressed() ), TQ_SLOT( search() ) );
+ connect( authorsAnyEdit, TQ_SIGNAL( returnPressed() ), TQ_SLOT( search() ) );
+ connect( authorsAllEdit, TQ_SIGNAL( returnPressed() ), TQ_SLOT( search() ) );
+ connect( authorsWithoutEdit, TQ_SIGNAL( returnPressed() ), TQ_SLOT( search() ) );
+ connect( categoriesNotEdit, TQ_SIGNAL( returnPressed() ), TQ_SLOT( search() ) );
+ connect( categoriesAnyEdit, TQ_SIGNAL( returnPressed() ), TQ_SLOT( search() ) );
+ connect( categoriesAllEdit, TQ_SIGNAL( returnPressed() ), TQ_SLOT( search() ) );
+ connect( ingredientsWithoutEdit, TQ_SIGNAL( returnPressed() ), TQ_SLOT( search() ) );
+ connect( instructionsEdit, TQ_SIGNAL( returnPressed() ), TQ_SLOT( search() ) );
+
+ connect( findButton, TQ_SIGNAL( clicked() ), TQ_SLOT( search() ) );
+ connect( clearButton, TQ_SIGNAL( clicked() ), TQ_SLOT( clear() ) );
+
+ connect( enableServingsCheckBox, TQ_SIGNAL( toggled( bool ) ), servingsSpinBox, TQ_SLOT( setEnabled( bool ) ) );
+ connect( enableServingsCheckBox, TQ_SIGNAL( toggled( bool ) ), servingsComboBox, TQ_SLOT( setEnabled( bool ) ) );
+ connect( enablePrepTimeCheckBox, TQ_SIGNAL( toggled( bool ) ), prepTimeEdit, TQ_SLOT( setEnabled( bool ) ) );
+ connect( enablePrepTimeCheckBox, TQ_SIGNAL( toggled( bool ) ), prepTimeComboBox, TQ_SLOT( setEnabled( bool ) ) );
+
+ connect( titleButton, TQ_SIGNAL( toggled( bool ) ), titleFrame, TQ_SLOT( setShown( bool ) ) );
+ connect( ingredientButton, TQ_SIGNAL( toggled( bool ) ), ingredientFrame, TQ_SLOT( setShown( bool ) ) );
+ connect( authorsButton, TQ_SIGNAL( toggled( bool ) ), authorsFrame, TQ_SLOT( setShown( bool ) ) );
+ connect( categoriesButton, TQ_SIGNAL( toggled( bool ) ), categoryFrame, TQ_SLOT( setShown( bool ) ) );
+ connect( servingsButton, TQ_SIGNAL( toggled( bool ) ), servingsFrame, TQ_SLOT( setShown( bool ) ) );
+ connect( prepTimeButton, TQ_SIGNAL( toggled( bool ) ), prepTimeFrame, TQ_SLOT( setShown( bool ) ) );
+ connect( instructionsButton, TQ_SIGNAL( toggled( bool ) ), instructionsFrame, TQ_SLOT( setShown( bool ) ) );
+ connect( metaDataButton, TQ_SIGNAL( toggled( bool ) ), metaDataFrame, TQ_SLOT( setShown( bool ) ) );
+ connect( ratingsButton, TQ_SIGNAL( toggled( bool ) ), ratingButtonGroup, TQ_SLOT( setShown( bool ) ) );
+
+ connect( titleButton, TQ_SIGNAL( toggled( bool ) ), TQ_SLOT( buttonSwitched() ) );
+ connect( ingredientButton, TQ_SIGNAL( toggled( bool ) ), TQ_SLOT( buttonSwitched() ) );
+ connect( authorsButton, TQ_SIGNAL( toggled( bool ) ), TQ_SLOT( buttonSwitched() ) );
+ connect( categoriesButton, TQ_SIGNAL( toggled( bool ) ), TQ_SLOT( buttonSwitched() ) );
+ connect( servingsButton, TQ_SIGNAL( toggled( bool ) ), TQ_SLOT( buttonSwitched() ) );
+ connect( prepTimeButton, TQ_SIGNAL( toggled( bool ) ), TQ_SLOT( buttonSwitched() ) );
+ connect( instructionsButton, TQ_SIGNAL( toggled( bool ) ), TQ_SLOT( buttonSwitched() ) );
+ connect( metaDataButton, TQ_SIGNAL( toggled( bool ) ), TQ_SLOT( buttonSwitched() ) );
+ connect( ratingsButton, TQ_SIGNAL( toggled( bool ) ), TQ_SLOT( buttonSwitched() ) );
+
+ connect( ratingButtonGroup, TQ_SIGNAL( clicked( int ) ), this, TQ_SLOT( activateRatingOption( int ) ) );
+
+ connect( addCriteriaButton, TQ_SIGNAL( clicked() ), this, TQ_SLOT( slotAddRatingCriteria() ) );
+
+ titleFrame->setShown(false);
+ ingredientFrame->setShown(false);
+ authorsFrame->setShown(false);
+ categoryFrame->setShown(false);
+ servingsFrame->setShown(false);
+ prepTimeFrame->setShown(false);
+ instructionsFrame->setShown(false);
+ metaDataFrame->setShown(false);
+ ratingButtonGroup->setShown(false);
+
+ connect( actionHandler, TQ_SIGNAL( recipeSelected( int, int ) ), TQ_SIGNAL( recipeSelected( int, int ) ) );
+ connect( actionHandler, TQ_SIGNAL( recipesSelected( const TQValueList<int> &, int ) ), TQ_SIGNAL( recipesSelected( const TQValueList<int> &, int ) ) );
+
+ connect( database, TQ_SIGNAL( recipeRemoved( int ) ), TQ_SLOT( removeRecipe( int ) ) );
+
+ clear();
+
+ TDEPopupMenu *kpop = new TDEPopupMenu( criteriaListView );
+ kpop->insertItem( i18n( "&Delete" ), this, TQ_SLOT( slotRemoveRatingCriteria() ), Key_Delete );
+}
+
+AdvancedSearchDialog::~AdvancedSearchDialog()
+{}
+
+void AdvancedSearchDialog::languageChange()
+{
+ titleButton->setText( TQString("%1 >>").arg(i18n("Title")) );
+ textLabel1_4->setText( i18n( "Search using the following criteria:" ) );
+ ingredientButton->setText( TQString("%1 >>").arg(i18n("Ingredients")) );
+ textLabel1_2->setText( i18n( "Uses any of:" ) );
+ textLabel1->setText( i18n( "Uses all:" ) );
+ textLabel1_3->setText( i18n( "Without:" ) );
+ categoriesButton->setText( i18n( "Categories >>" ) );
+ textLabel1_5->setText( i18n( "In all:" ) );
+ textLabel1_3_3->setText( i18n( "Not in:" ) );
+ textLabel1_2_3->setText( i18n( "In any of:" ) );
+ authorsButton->setText( TQString("%1 >>").arg(i18n("Authors")) );
+ textLabel1_2_4->setText( i18n( "By any of:" ) );
+ textLabel1_6->setText( i18n( "By all:" ) );
+ textLabel1_3_4->setText( i18n( "Not by:" ) );
+ servingsButton->setText( TQString("%1 >>").arg(i18n("Yield")) );
+ enableServingsCheckBox->setText( i18n( "Enabled" ) );
+ servingsComboBox->clear();
+ servingsComboBox->insertItem( i18n( "Yields at least:" ) );
+ servingsComboBox->insertItem( i18n( "Yields at most:" ) );
+ servingsComboBox->insertItem( i18n( "Yields about:" ) );
+ prepTimeButton->setText( TQString("%1 >>").arg(i18n("Preparation Time")) );
+ enablePrepTimeCheckBox->setText( i18n( "Enabled" ) );
+ prepTimeComboBox->clear();
+ prepTimeComboBox->insertItem( i18n( "Ready in at most:" ) );
+ prepTimeComboBox->insertItem( i18n( "Ready in about:" ) );
+ instructionsButton->setText( TQString("%1 >>").arg(i18n("Instructions")) );
+ metaDataButton->setText( TQString("%1 >>").arg(i18n("Meta Data")) );
+ clearButton->setText( i18n( "C&lear" ) );
+ findButton->setText( i18n( "&Search" ) );
+ ratingAvgRadioButton->setText( i18n( "By average:" ) );
+ avgStarsLabel->setText( i18n( "stars" ) );
+ criterionRadioButton->setText( i18n( "By criteria:" ) );
+ addCriteriaButton->setText( i18n( "+" ) );
+ //removeCriteriaButton->setText( i18n( "-" ) );
+ criteriaListView->header()->setLabel( 0, i18n( "Criteria" ) );
+ criteriaListView->header()->setLabel( 1, i18n( "Stars" ) );
+ ratingsButton->setText( TQString("%1 >>").arg(i18n("Ratings")) );
+}
+
+void AdvancedSearchDialog::removeRecipe( int id )
+{
+ TQListViewItemIterator iterator( resultsListView );
+ while ( iterator.current() ) {
+ if ( iterator.current()->rtti() == 1000 ) {
+ RecipeListItem * recipe_it = ( RecipeListItem* ) iterator.current();
+ if ( recipe_it->recipeID() == id )
+ delete recipe_it;
+ }
+ ++iterator;
+ }
+}
+
+void AdvancedSearchDialog::clear()
+{
+ resultsListView->clear();
+ authorsAllEdit->clear();
+ authorsWithoutEdit->clear();
+ authorsAnyEdit->clear();
+ categoriesAllEdit->clear();
+ categoriesNotEdit->clear();
+ categoriesAnyEdit->clear();
+ ingredientsAllEdit->clear();
+ ingredientsWithoutEdit->clear();
+ ingredientsAnyEdit->clear();
+ titleEdit->clear();
+ instructionsEdit->clear();
+
+ createdStartDateEdit->setDate( TQDate() );
+ createdEndDateEdit->setDate( TQDate() );
+ modifiedStartDateEdit->setDate( TQDate() );
+ modifiedEndDateEdit->setDate( TQDate() );
+ accessedStartDateEdit->setDate( TQDate() );
+ accessedEndDateEdit->setDate( TQDate() );
+
+ servingsSpinBox->setValue( 1 );
+ prepTimeEdit->setTime( TQTime(0,0) );
+
+ enablePrepTimeCheckBox->setChecked(false);
+ enableServingsCheckBox->setChecked(false);
+
+ requireAllTitle->setChecked(false);
+ requireAllInstructions->setChecked(false);
+
+ ratingAvgRadioButton->setChecked(true);
+ activateRatingOption(0);
+ avgStarsEdit->clear();
+ criteriaListView->clear();
+ starsWidget->clear();
+}
+
+void AdvancedSearchDialog::activateRatingOption( int button_id )
+{
+ switch ( button_id ) {
+ case 0:
+ criterionFrame->setEnabled( false );
+ ratingAvgFrame->setEnabled( true );
+ break;
+ case 1:
+ criterionFrame->setEnabled( true );
+ ratingAvgFrame->setEnabled( false );
+ break;
+ default:
+ break;
+ }
+}
+
+void AdvancedSearchDialog::buttonSwitched()
+{
+ const TQObject *sent = sender();
+
+ if ( sent->inherits("TQPushButton") ) {
+ TQPushButton *pushed = (TQPushButton*) sent;
+
+ TQString suffix = ( pushed->state() == TQButton::On ) ? " <<" : " >>";
+ pushed->setText( pushed->text().left( pushed->text().length() - 3 ) + suffix );
+ }
+}
+
+void AdvancedSearchDialog::search()
+{
+ TDEApplication::setOverrideCursor( KCursor::waitCursor() );
+
+ //we need to load more than just the title because we'll be doing further refining of the search
+ int load_items = RecipeDB::Title | RecipeDB::NamesOnly | RecipeDB::Noatime;
+ if ( !authorsAllEdit->text().isEmpty() || !authorsWithoutEdit->text().isEmpty() )
+ load_items |= RecipeDB::Authors;
+ if ( !ingredientsAllEdit->text().isEmpty() || !ingredientsWithoutEdit->text().isEmpty() )
+ load_items |= RecipeDB::Ingredients;
+ if ( !categoriesAllEdit->text().isEmpty() || !categoriesNotEdit->text().isEmpty() )
+ load_items |= RecipeDB::Categories;
+ if ( (ratingAvgRadioButton->isChecked() && !avgStarsEdit->isEmpty()) || (criterionRadioButton->isChecked() && criteriaListView->firstChild()) )
+ load_items |= RecipeDB::Ratings;
+
+ RecipeSearchParameters parameters;
+
+ parameters.titleKeywords = split(titleEdit->text(),true);
+ parameters.requireAllTitleWords = requireAllTitle->isChecked();
+
+ parameters.instructionsKeywords = split(instructionsEdit->text(),true);
+ parameters.requireAllInstructionsWords = requireAllInstructions->isChecked();
+
+ parameters.ingsOr = split(ingredientsAnyEdit->text(),true);
+ parameters.catsOr = split(categoriesAnyEdit->text(),true);
+ parameters.authorsOr = split(authorsAnyEdit->text(),true);
+
+ if ( enablePrepTimeCheckBox->isChecked() )
+ parameters.prep_time = prepTimeEdit->time();
+ parameters.prep_param = prepTimeComboBox->currentItem();
+
+ if ( enableServingsCheckBox->isChecked() )
+ parameters.servings = servingsSpinBox->value();
+ parameters.servings_param = servingsComboBox->currentItem();
+
+ parameters.createdDateBegin = createdStartDateEdit->date();
+ parameters.createdDateEnd = createdEndDateEdit->date();
+ if ( parameters.createdDateEnd.date().isValid() )
+ parameters.createdDateEnd = parameters.createdDateEnd.addDays(1); //we want to include the given day in the search
+
+ parameters.modifiedDateBegin = modifiedStartDateEdit->date();
+ parameters.modifiedDateEnd = modifiedEndDateEdit->date();
+ if ( parameters.modifiedDateEnd.date().isValid() )
+ parameters.modifiedDateEnd = parameters.modifiedDateEnd.addDays(1); //we want to include the given day in the search
+
+ parameters.accessedDateBegin = accessedStartDateEdit->date();
+ parameters.accessedDateEnd = accessedEndDateEdit->date();
+ if ( parameters.accessedDateEnd.date().isValid() )
+ parameters.accessedDateEnd = parameters.accessedDateEnd.addDays(1); //we want to include the given day in the search
+
+ START_TIMER("Doing database SQL search");
+ RecipeList allRecipes;
+ database->search( &allRecipes, load_items, parameters );
+ END_TIMER();
+
+ /*
+ * Ideally, would be done by the above SQL query, but I have no idea how to accomplish this.
+ */
+
+ START_TIMER("Further narrowing the search (no SQL)");
+ TQStringList items = split(authorsAllEdit->text());
+ for ( TQStringList::const_iterator author_it = items.begin(); author_it != items.end(); ++author_it ) {
+ for ( RecipeList::iterator it = allRecipes.begin(); it != allRecipes.end(); ++it ) {
+ if ( ( *it ).authorList.findByName( TQRegExp(*author_it,false, true) ).id == -1 ) {
+ it = allRecipes.remove( it );
+ it--;
+ }
+ }
+ }
+ items = split(authorsWithoutEdit->text());
+ for ( TQStringList::const_iterator author_it = items.begin(); author_it != items.end(); ++author_it ) {
+ for ( RecipeList::iterator it = allRecipes.begin(); it != allRecipes.end(); ++it ) {
+ if ( ( *it ).authorList.findByName( TQRegExp(*author_it,false,true) ).id != -1 ) {
+ it = allRecipes.remove( it );
+ it--;
+ }
+ }
+ }
+
+ //narrow down by categories
+ items = split(categoriesAllEdit->text());
+ for ( TQStringList::const_iterator cat_it = items.begin(); cat_it != items.end(); ++cat_it ) {
+ for ( RecipeList::iterator it = allRecipes.begin(); it != allRecipes.end(); ++it ) {
+ if ( ( *it ).categoryList.findByName( TQRegExp(*cat_it,false,true) ).id == -1 ) {
+ it = allRecipes.remove( it );
+ it--;
+ }
+ }
+ }
+ items = split(categoriesNotEdit->text());
+ for ( TQStringList::const_iterator cat_it = items.begin(); cat_it != items.end(); ++cat_it ) {
+ for ( RecipeList::iterator it = allRecipes.begin(); it != allRecipes.end(); ++it ) {
+ if ( ( *it ).categoryList.findByName( TQRegExp(*cat_it,false,true) ).id != -1 ) {
+ it = allRecipes.remove( it );
+ it--;
+ }
+ }
+ }
+
+ //narrow down by ingredients
+ items = split(ingredientsAllEdit->text());
+ for ( TQStringList::const_iterator ing_it = items.begin(); ing_it != items.end(); ++ing_it ) {
+ for ( RecipeList::iterator it = allRecipes.begin(); it != allRecipes.end(); ++it ) {
+ if ( ( *it ).ingList.findByName( TQRegExp(*ing_it,false,true) ).ingredientID == -1 ) {
+ it = allRecipes.remove( it );
+ it--;
+ }
+ }
+ }
+ items = split(ingredientsWithoutEdit->text());
+ for ( TQStringList::const_iterator ing_it = items.begin(); ing_it != items.end(); ++ing_it ) {
+ for ( RecipeList::iterator it = allRecipes.begin(); it != allRecipes.end(); ++it ) {
+ if ( ( *it ).ingList.findByName( TQRegExp(*ing_it,false,true) ).ingredientID != -1 ) {
+ it = allRecipes.remove( it );
+ it--;
+ }
+ }
+ }
+
+ if ( ratingAvgRadioButton->isChecked() && !avgStarsEdit->isEmpty() ) {
+ for ( RecipeList::iterator recipe_it = allRecipes.begin(); recipe_it != allRecipes.end(); ++recipe_it ) {
+ double sum = 0;
+ int count = 0;
+
+ for ( RatingList::iterator rating_it = (*recipe_it).ratingList.begin(); rating_it != (*recipe_it).ratingList.end(); ++rating_it ) {
+ sum += (*rating_it).average();
+ ++count;
+ }
+
+ if ( count != 0 ) {
+ double average = sum/count;
+
+ double stars;
+ double stars_offset;
+ avgStarsEdit->value(stars,stars_offset);
+ if ( stars_offset < 1e-10 ) { //if an exact amount is given, search for an amount within 0.5 of what is given
+ //we can get negatives here, but it really doesn't matter
+ stars = stars-0.5;
+ stars_offset = 1.0;
+ }
+
+
+ kdDebug()<<"average for "<<(*recipe_it).title<<" "<<average<<endl;
+ if ( average < stars || average > stars + stars_offset ) {
+ recipe_it = allRecipes.remove( recipe_it );
+ recipe_it--;
+ }
+ }
+ else {
+ recipe_it = allRecipes.remove( recipe_it );
+ recipe_it--;
+ }
+ }
+ }
+
+ //TODO: Clean this up and/or do it more efficiently
+ if ( criterionRadioButton->isChecked() && criteriaListView->firstChild() ) {
+ for ( RecipeList::iterator recipe_it = allRecipes.begin(); recipe_it != allRecipes.end(); ++recipe_it ) {
+ TQMap< int, double > idSumMap;
+ TQMap< int, int > idCountMap;
+
+ for ( RatingList::const_iterator rating_it = (*recipe_it).ratingList.begin(); rating_it != (*recipe_it).ratingList.end(); ++rating_it ) {
+ for ( RatingCriteriaList::const_iterator rc_it = (*rating_it).ratingCriteriaList.begin(); rc_it != (*rating_it).ratingCriteriaList.end(); ++rc_it ) {
+ TQMap< int, double >::iterator sum_it = idSumMap.find((*rc_it).id);
+ if ( sum_it == idSumMap.end() )
+ sum_it = idSumMap.insert((*rc_it).id,0);
+ (*sum_it) += (*rc_it).stars;
+
+ TQMap< int, int >::iterator count_it = idCountMap.find((*rc_it).id);
+ if ( count_it == idCountMap.end() )
+ count_it = idCountMap.insert((*rc_it).id,0);
+ (*count_it)++;
+ }
+ }
+
+ for ( TQListViewItem *item = criteriaListView->firstChild(); item; item = item->nextSibling() ) {
+ Ingredient i; i.setAmount( item->text(1) );
+ double stars = i.amount;
+ double stars_offset = i.amount_offset;
+
+ if ( stars_offset < 1e-10 ) { //if an exact amount is given, search for an amount within 0.5 of what is given
+ //we can get negatives here, but it really doesn't matter
+ stars = stars-0.5;
+ stars_offset = 1.0;
+ }
+
+ int id = item->text(2).toInt();
+
+ TQMap< int, double >::iterator sum_it = idSumMap.find(id);
+ if ( sum_it != idSumMap.end() ) {
+ TQMap< int, int >::iterator count_it = idCountMap.find(id);
+ double average = (*sum_it)/(*count_it);
+
+ if ( average < stars || average > stars + stars_offset ) {
+ recipe_it = allRecipes.remove( recipe_it );
+ recipe_it--;
+ break;
+ }
+ }
+ else {
+ recipe_it = allRecipes.remove( recipe_it );
+ recipe_it--;
+ break;
+ }
+ }
+ }
+ }
+ END_TIMER();
+
+
+ //now display the recipes left
+ resultsListView->clear();
+ for ( RecipeList::const_iterator it = allRecipes.begin(); it != allRecipes.end(); ++it ) {
+ ( void ) new RecipeListItem( resultsListView, *it );
+ }
+
+ if ( !resultsListView->firstChild() ) {
+ ( void ) new TQListViewItem( resultsListView, "--- "+i18n("No matching recipes found")+" ---");
+ }
+
+ TDEApplication::restoreOverrideCursor();
+}
+
+TQStringList AdvancedSearchDialog::split( const TQString &text, bool sql_wildcards ) const
+{
+ TQStringList result;
+
+ // To keep quoted words together, first split on quotes,
+ // and then split again on the even numbered items
+
+ TQStringList temp = TQStringList::split('"',text,true);
+ for ( uint i = 0; i < temp.count(); ++i ) {
+ if ( i & 1 ) //odd
+ result += temp[i].stripWhiteSpace();
+ else //even
+ result += TQStringList::split(' ',temp[i]);
+ }
+
+ if ( sql_wildcards ) {
+ for ( TQStringList::iterator it = result.begin(); it != result.end(); ++it ) {
+ (*it).replace("%","\\%");
+ (*it).replace("_","\\_");
+
+ (*it).replace("*","%");
+ (*it).replace("?","_");
+ }
+ }
+
+ return result;
+}
+
+void AdvancedSearchDialog::slotAddRatingCriteria()
+{
+ TQListViewItem * it = new TQListViewItem(criteriaListView,criteriaComboBox->currentText());
+
+ MixedNumber stars;
+ double stars_offset;
+ starsWidget->value(stars,stars_offset);
+ TQString stars_str = stars.toString();
+ if ( stars_offset > 0 )
+ stars_str += "-"+MixedNumber( stars + stars_offset ).toString();
+ else if ( stars.toDouble() <= 1e-10 )
+ stars_str = "";
+
+ it->setText(1,stars_str);
+ it->setText(2,TQString::number(criteriaComboBox->criteriaID(criteriaComboBox->currentItem())));
+}
+
+void AdvancedSearchDialog::slotRemoveRatingCriteria()
+{
+ delete criteriaListView->selectedItem();
+}
+
+#include "advancedsearchdialog.moc"
diff --git a/src/dialogs/advancedsearchdialog.h b/src/dialogs/advancedsearchdialog.h
new file mode 100644
index 0000000..65eb171
--- /dev/null
+++ b/src/dialogs/advancedsearchdialog.h
@@ -0,0 +1,179 @@
+/***************************************************************************
+* Copyright (C) 2003-2004 by *
+* 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. *
+***************************************************************************/
+
+#ifndef ADVANCEDSEARCHDIALOG_H
+#define ADVANCEDSEARCHDIALOG_H
+
+#include <tqwidget.h>
+
+class TQVBoxLayout;
+class TQHBoxLayout;
+class TQGridLayout;
+class TQSpacerItem;
+class TQScrollView;
+class TQPushButton;
+class TQFrame;
+class TQLineEdit;
+class TQLabel;
+class TQCheckBox;
+class TQComboBox;
+class TQSpinBox;
+class TQTimeEdit;
+class KPushButton;
+class TDEListView;
+class TQListViewItem;
+class TQRadioButton;
+class TQButtonGroup;
+
+class KDateEdit;
+class RecipeDB;
+class RecipeActionsHandler;
+class FractionInput;
+class CriteriaComboBox;
+
+
+class AdvancedSearchDialog : public TQWidget
+{
+ TQ_OBJECT
+
+public:
+ AdvancedSearchDialog( TQWidget *parent, RecipeDB * );
+ ~AdvancedSearchDialog();
+
+ virtual void languageChange();
+
+ RecipeActionsHandler *actionHandler;
+
+protected:
+ TQLabel* textLabel1_4;
+ TQScrollView* scrollView1;
+ TQFrame* parametersFrame;
+ TQLineEdit* titleEdit;
+ TQPushButton* titleButton;
+ TQFrame* titleFrame;
+ TQPushButton* ingredientButton;
+ TQFrame* ingredientFrame;
+ TQLineEdit* ingredientsAllEdit;
+ TQLineEdit* ingredientsAnyEdit;
+ TQLabel* textLabel1_2;
+ TQLabel* textLabel1;
+ TQLineEdit* ingredientsWithoutEdit;
+ TQLabel* textLabel1_3;
+ TQPushButton* categoriesButton;
+ TQFrame* categoryFrame;
+ TQLineEdit* categoriesAllEdit;
+ TQLabel* textLabel1_5;
+ TQLabel* textLabel1_3_3;
+ TQLineEdit* categoriesAnyEdit;
+ TQLabel* textLabel1_2_3;
+ TQLineEdit* categoriesNotEdit;
+ TQPushButton* authorsButton;
+ TQFrame* authorsFrame;
+ TQLabel* textLabel1_2_4;
+ TQLabel* textLabel1_6;
+ TQLabel* textLabel1_3_4;
+ TQLineEdit* authorsAnyEdit;
+ TQLineEdit* authorsAllEdit;
+ TQLineEdit* authorsWithoutEdit;
+ TQPushButton* servingsButton;
+ TQFrame* servingsFrame;
+ TQCheckBox* enableServingsCheckBox;
+ TQComboBox* servingsComboBox;
+ TQSpinBox* servingsSpinBox;
+ TQPushButton* prepTimeButton;
+ TQFrame* prepTimeFrame;
+ TQCheckBox* enablePrepTimeCheckBox;
+ TQComboBox* prepTimeComboBox;
+ TQTimeEdit* prepTimeEdit;
+ TQLineEdit* instructionsEdit;
+ TQPushButton* instructionsButton;
+ TQFrame* instructionsFrame;
+ KPushButton* clearButton;
+ KPushButton* findButton;
+ TDEListView* resultsListView;
+ TQCheckBox *requireAllTitle;
+ TQCheckBox *requireAllInstructions;
+ KDateEdit *createdStartDateEdit;
+ KDateEdit *createdEndDateEdit;
+ KDateEdit *modifiedStartDateEdit;
+ KDateEdit *modifiedEndDateEdit;
+ KDateEdit *accessedStartDateEdit;
+ KDateEdit *accessedEndDateEdit;
+ TQPushButton* metaDataButton;
+ TQFrame* metaDataFrame;
+ TQRadioButton* ratingAvgRadioButton;
+ FractionInput* avgStarsEdit;
+ TQLabel* avgStarsLabel;
+ TQRadioButton* criterionRadioButton;
+ CriteriaComboBox* criteriaComboBox;
+ FractionInput* starsWidget;
+ TQPushButton* addCriteriaButton;
+ TQPushButton* removeCriteriaButton;
+ TDEListView* criteriaListView;
+ TQPushButton* ratingsButton;
+ TQButtonGroup *ratingButtonGroup;
+ TQFrame *ratingAvgFrame;
+ TQFrame *criterionFrame;
+ TQVBoxLayout *criterionFrameLayout;
+ TQHBoxLayout *ratingAvgFrameLayout;
+ TQVBoxLayout *ratingButtonGroupLayout;
+
+ TQHBoxLayout* AdvancedSearchDialogLayout;
+ TQVBoxLayout* layout7;
+ TQHBoxLayout* scrollView1Layout;
+ TQVBoxLayout* parametersFrameLayout;
+ TQSpacerItem* spacer3_2_3_2_2;
+ TQSpacerItem* spacer3_2_3_2;
+ TQSpacerItem* spacer3_2_3;
+ TQSpacerItem* spacer3_2_2;
+ TQSpacerItem* titleFrameSpacer;
+ TQSpacerItem* instructionsFrameSpacer;
+ TQSpacerItem* metaDataFrameSpacer;
+ TQSpacerItem* spacer15;
+ TQVBoxLayout* titleFrameLayout;
+ TQGridLayout* ingredientFrameLayout;
+ TQGridLayout* categoryFrameLayout;
+ TQGridLayout* authorsFrameLayout;
+ TQVBoxLayout* servingsFrameLayout;
+ TQHBoxLayout* layout5;
+ TQVBoxLayout* prepTimeFrameLayout;
+ TQVBoxLayout* instructionsFrameLayout;
+ TQVBoxLayout* metaDataFrameLayout;
+ TQHBoxLayout* layout6;
+ TQHBoxLayout* layout9;
+ TQSpacerItem* spacer3;
+ TQVBoxLayout* ratingsFrameLayout;
+ TQHBoxLayout* layout11;
+ TQHBoxLayout* layout12;
+ TQSpacerItem* ratingsFrameSpacer;
+
+ RecipeDB *database;
+
+signals:
+ void recipeSelected( int, int );
+ void recipesSelected( const TQValueList<int> &, int );
+
+private slots:
+ void search();
+ void clear();
+ void buttonSwitched();
+ void activateRatingOption( int button_id );
+ void slotAddRatingCriteria();
+ void slotRemoveRatingCriteria();
+
+ //called by a signal from the database when a recipe is removed
+ void removeRecipe( int id );
+
+private:
+ TQStringList split( const TQString &text, bool sql_wildcards = false ) const;
+};
+
+#endif //ADVANCEDSEARCHDIALOG_H
+
diff --git a/src/dialogs/authorsdialog.cpp b/src/dialogs/authorsdialog.cpp
new file mode 100644
index 0000000..0a53899
--- /dev/null
+++ b/src/dialogs/authorsdialog.cpp
@@ -0,0 +1,66 @@
+/***************************************************************************
+* 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 "authorsdialog.h"
+#include "createelementdialog.h"
+#include "backends/recipedb.h"
+#include "widgets/authorlistview.h"
+
+#include <kdialog.h>
+#include <tdelocale.h>
+#include <tdemessagebox.h>
+
+AuthorsDialog::AuthorsDialog( TQWidget* parent, RecipeDB *db ) : TQWidget( parent )
+{
+
+ // Store pointer to database
+ database = db;
+
+ TQHBoxLayout* layout = new TQHBoxLayout( this, KDialog::marginHint(), KDialog::spacingHint() );
+
+ //Author List
+ authorListView = new StdAuthorListView( this, database, true );
+ layout->addWidget( authorListView );
+
+ //Buttons
+ TQVBoxLayout* vboxl = new TQVBoxLayout( KDialog::spacingHint() );
+
+ newAuthorButton = new TQPushButton( this );
+ newAuthorButton->setText( i18n( "Create ..." ) );
+ newAuthorButton->setFlat( true );
+ vboxl->addWidget( newAuthorButton );
+
+ removeAuthorButton = new TQPushButton( this );
+ removeAuthorButton->setText( i18n( "Delete" ) );
+ removeAuthorButton->setFlat( true );
+ vboxl->addWidget( removeAuthorButton );
+ vboxl->addStretch();
+
+ layout->addLayout( vboxl );
+
+ //Connect Signals & Slots
+
+ connect ( newAuthorButton, TQ_SIGNAL( clicked() ), authorListView, TQ_SLOT( createNew() ) );
+ connect ( removeAuthorButton, TQ_SIGNAL( clicked() ), authorListView, TQ_SLOT( remove
+ () ) );
+}
+
+AuthorsDialog::~AuthorsDialog()
+{}
+
+// (Re)loads the data from the database
+void AuthorsDialog::reload( ReloadFlags flag )
+{
+ authorListView->reload( flag );
+}
+
+#include "authorsdialog.moc"
diff --git a/src/dialogs/authorsdialog.h b/src/dialogs/authorsdialog.h
new file mode 100644
index 0000000..3678ae3
--- /dev/null
+++ b/src/dialogs/authorsdialog.h
@@ -0,0 +1,51 @@
+/***************************************************************************
+* 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. *
+***************************************************************************/
+
+#ifndef AUTHORSDIALOG_H
+#define AUTHORSDIALOG_H
+
+#include <tqwidget.h>
+#include <tqpushbutton.h>
+#include <tqhbox.h>
+#include <tqlayout.h>
+#include <kiconloader.h>
+#include <tdelistview.h>
+
+#include "widgets/dblistviewbase.h"
+
+class RecipeDB;
+class StdAuthorListView;
+
+/**
+@author Unai Garro
+*/
+
+class AuthorsDialog: public TQWidget
+{
+
+ TQ_OBJECT
+
+public:
+
+ AuthorsDialog( TQWidget* parent, RecipeDB *db );
+ ~AuthorsDialog();
+ void reload( ReloadFlags flag = Load );
+private:
+ // Internal data
+ RecipeDB *database;
+ //Widgets
+ StdAuthorListView *authorListView;
+ TQPushButton *newAuthorButton;
+ TQPushButton *removeAuthorButton;
+ TDEIconLoader *il;
+};
+#endif
diff --git a/src/dialogs/borderdialog.cpp b/src/dialogs/borderdialog.cpp
new file mode 100644
index 0000000..13a8459
--- /dev/null
+++ b/src/dialogs/borderdialog.cpp
@@ -0,0 +1,261 @@
+/***************************************************************************
+* Copyright (C) 2004 by *
+* 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 "borderdialog.h"
+
+#include <tqpushbutton.h>
+#include <tqgroupbox.h>
+#include <tqvbox.h>
+#include <tqlabel.h>
+#include <tqspinbox.h>
+#include <tqlayout.h>
+#include <tqtooltip.h>
+#include <tqwhatsthis.h>
+
+#include <kdebug.h>
+#include <tdehtml_part.h>
+#include <tdehtmlview.h>
+#include <tdelistbox.h>
+#include <tdelocale.h>
+
+#include "datablocks/kreborder.h"
+
+BorderDialog::BorderDialog( const KreBorder &border, TQWidget* parent, const char* name )
+ : KDialogBase( parent, name, true, TQString::null,
+ KDialogBase::Ok | KDialogBase::Cancel, KDialogBase::Ok )
+{
+ TQVBox *page = makeVBoxMainWidget();
+
+ borderGroupBox = new TQGroupBox( page, "borderGroupBox" );
+ borderGroupBox->setColumnLayout( 0, TQt::Vertical );
+ borderGroupBox->layout() ->setSpacing( 6 );
+ borderGroupBox->layout() ->setMargin( 11 );
+ borderGroupBoxLayout = new TQVBoxLayout( borderGroupBox->layout() );
+ borderGroupBoxLayout->setAlignment( TQt::AlignTop );
+
+ layout4 = new TQHBoxLayout( 0, 0, 6, "layout4" );
+
+ layout3 = new TQVBoxLayout( 0, 0, 6, "layout3" );
+
+ styleLabel = new TQLabel( borderGroupBox, "styleLabel" );
+ layout3->addWidget( styleLabel );
+
+ styleListBox = new TDEListBox( borderGroupBox, "styleListBox" );
+ layout3->addWidget( styleListBox );
+ layout4->addLayout( layout3 );
+
+ layout2 = new TQVBoxLayout( 0, 0, 6, "layout2" );
+
+ colorLabel = new TQLabel( borderGroupBox, "colorLabel" );
+ layout2->addWidget( colorLabel );
+
+ TQHBox *color_hbox = new TQHBox( borderGroupBox );
+ color_hbox->setSizePolicy( TQSizePolicy::MinimumExpanding, TQSizePolicy::MinimumExpanding );
+ hsSelector = new KHSSelector( color_hbox );
+ hsSelector->setMinimumSize( 140, 70 );
+ connect( hsSelector, TQ_SIGNAL( valueChanged( int, int ) ), TQ_SLOT( slotHSChanged( int, int ) ) );
+
+ valuePal = new KValueSelector( color_hbox );
+ valuePal->setMinimumSize( 26, 70 );
+ connect( valuePal, TQ_SIGNAL( valueChanged( int ) ), TQ_SLOT( slotVChanged( int ) ) );
+
+ layout2->addWidget( color_hbox );
+ layout4->addLayout( layout2 );
+
+ layout1 = new TQVBoxLayout( 0, 0, 6, "layout1" );
+
+ widthLabel = new TQLabel( borderGroupBox, "widthLabel" );
+ layout1->addWidget( widthLabel );
+
+ widthSpinBox = new TQSpinBox( borderGroupBox, "widthSpinBox" );
+ widthSpinBox->setMinValue( 1 );
+ layout1->addWidget( widthSpinBox );
+
+ widthListBox = new TDEListBox( borderGroupBox, "widthListBox" );
+ layout1->addWidget( widthListBox );
+ layout4->addLayout( layout1 );
+ borderGroupBoxLayout->addLayout( layout4 );
+
+ borderPreview = new TDEHTMLPart( borderGroupBox );
+ borderPreview->view() ->setSizePolicy( TQSizePolicy::Preferred, TQSizePolicy::Fixed );
+ borderGroupBoxLayout->addWidget( borderPreview->view() );
+
+ languageChange();
+
+ connect( widthSpinBox, TQ_SIGNAL( valueChanged( int ) ), TQ_SLOT( updatePreview() ) );
+ connect( widthListBox, TQ_SIGNAL( highlighted( int ) ), TQ_SLOT( updateSpinBox( int ) ) );
+ connect( styleListBox, TQ_SIGNAL( highlighted( int ) ), TQ_SLOT( updatePreview() ) );
+
+ initListBoxs();
+ loadBorder( border );
+
+ clearWState( WState_Polished );
+}
+
+BorderDialog::~BorderDialog()
+{}
+
+void BorderDialog::languageChange()
+{
+ borderGroupBox->setTitle( i18n( "Requested Border" ) );
+ styleLabel->setText( i18n( "Style:" ) );
+ colorLabel->setText( i18n( "Color:" ) );
+ widthLabel->setText( i18n( "Width:" ) );
+}
+
+KreBorder BorderDialog::border() const
+{
+ int width = widthSpinBox->value();
+
+ TQString style;
+ switch ( styleListBox->currentItem() ) {
+ case 0:
+ style = "none";
+ break;
+ case 1:
+ style = "dotted";
+ break;
+ case 2:
+ style = "dashed";
+ break;
+ case 3:
+ style = "solid";
+ break;
+ case 4:
+ style = "double";
+ break;
+ case 5:
+ style = "groove";
+ break;
+ case 6:
+ style = "ridge";
+ break;
+ case 7:
+ style = "inset";
+ break;
+ case 8:
+ style = "outset";
+ break;
+ }
+
+ return KreBorder( width, style, selColor );
+}
+
+void BorderDialog::loadBorder( const KreBorder &border )
+{
+ widthSpinBox->setValue( border.width );
+ widthListBox->setCurrentItem( border.width - 1 );
+
+ if ( border.style == "none" )
+ styleListBox->setCurrentItem( 0 );
+ else if ( border.style == "dotted" )
+ styleListBox->setCurrentItem( 1 );
+ else if ( border.style == "dashed" )
+ styleListBox->setCurrentItem( 2 );
+ else if ( border.style == "solid" )
+ styleListBox->setCurrentItem( 3 );
+ else if ( border.style == "double" )
+ styleListBox->setCurrentItem( 4 );
+ else if ( border.style == "groove" )
+ styleListBox->setCurrentItem( 5 );
+ else if ( border.style == "ridge" )
+ styleListBox->setCurrentItem( 6 );
+ else if ( border.style == "inset" )
+ styleListBox->setCurrentItem( 7 );
+ else if ( border.style == "outset" )
+ styleListBox->setCurrentItem( 8 );
+
+ setColor( border.color );
+
+ updatePreview();
+}
+
+void BorderDialog::initListBoxs()
+{
+ styleListBox->insertItem( i18n( "None" ) );
+ styleListBox->insertItem( i18n( "See http://krecipes.sourceforge.net/bordertypes.png for an example", "Dotted" ) );
+ styleListBox->insertItem( i18n( "See http://krecipes.sourceforge.net/bordertypes.png for an example", "Dashed" ) );
+ styleListBox->insertItem( i18n( "See http://krecipes.sourceforge.net/bordertypes.png for an example", "Solid" ) );
+ styleListBox->insertItem( i18n( "See http://krecipes.sourceforge.net/bordertypes.png for an example", "Double" ) );
+ styleListBox->insertItem( i18n( "See http://krecipes.sourceforge.net/bordertypes.png for an example", "Groove" ) );
+ styleListBox->insertItem( i18n( "See http://krecipes.sourceforge.net/bordertypes.png for an example", "Ridge" ) );
+ styleListBox->insertItem( i18n( "See http://krecipes.sourceforge.net/bordertypes.png for an example", "Inset" ) );
+ styleListBox->insertItem( i18n( "See http://krecipes.sourceforge.net/bordertypes.png for an example", "Outset" ) );
+
+ widthListBox->insertItem( "1" );
+ widthListBox->insertItem( "2" );
+ widthListBox->insertItem( "3" );
+ widthListBox->insertItem( "4" );
+ widthListBox->insertItem( "5" );
+ widthListBox->insertItem( "6" );
+ widthListBox->insertItem( "7" );
+}
+
+void BorderDialog::updatePreview()
+{
+ KreBorder b( border() );
+
+ TQString html_str = TQString( "<html><body><div style=\"vertical-align: middle; border: %1px %2 %3;\"><center><h1>%4</h1></center></div></body></html>" ).arg( b.width ).arg( b.style ).arg( b.color.name() ).arg( i18n( "Border Preview" ) );
+
+ borderPreview->begin();
+ borderPreview->write( html_str );
+ borderPreview->end();
+ borderPreview->show();
+}
+
+void BorderDialog::updateSpinBox( int index )
+{
+ widthSpinBox->setValue( index + 1 );
+}
+
+void BorderDialog::slotHSChanged( int h, int s )
+{
+ int _h, _s, v;
+ selColor.hsv( &_h, &_s, &v );
+ if ( v < 1 )
+ v = 1;
+
+ KColor col;
+ col.setHsv( h, s, v );
+
+ setColor( col );
+ updatePreview();
+}
+
+void BorderDialog::slotVChanged( int v )
+{
+ int h, s, _v;
+ selColor.hsv( &h, &s, &_v );
+
+ KColor col;
+ col.setHsv( h, s, v );
+
+ setColor( col );
+ updatePreview();
+}
+
+void BorderDialog::setColor( const KColor &color )
+{
+ if ( color == selColor )
+ return ;
+
+ selColor = color;
+
+ int h, s, v;
+ color.hsv( &h, &s, &v );
+ hsSelector->setValues( h, s );
+ valuePal->setHue( h );
+ valuePal->setSaturation( s );
+ valuePal->setValue( v );
+ valuePal->updateContents();
+ valuePal->repaint( FALSE );
+}
+
+#include "borderdialog.moc"
diff --git a/src/dialogs/borderdialog.h b/src/dialogs/borderdialog.h
new file mode 100644
index 0000000..07905ee
--- /dev/null
+++ b/src/dialogs/borderdialog.h
@@ -0,0 +1,75 @@
+/***************************************************************************
+* Copyright (C) 2004 by *
+* 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. *
+***************************************************************************/
+
+#ifndef BORDERDIALOG_H
+#define BORDERDIALOG_H
+
+#include <kdialogbase.h>
+#include <kcolordialog.h>
+
+class TQVBoxLayout;
+class TQHBoxLayout;
+class TQGridLayout;
+class TQSpacerItem;
+class TQGroupBox;
+class TQLabel;
+class TDEListBox;
+class TQListBoxItem;
+class TQSpinBox;
+class TDEHTMLPart;
+
+class KreBorder;
+
+class BorderDialog : public KDialogBase
+{
+ TQ_OBJECT
+
+public:
+ BorderDialog( const KreBorder &border, TQWidget* parent = 0, const char* name = 0 );
+ ~BorderDialog();
+
+ KreBorder border() const;
+
+ TQGroupBox* borderGroupBox;
+ TQLabel* styleLabel;
+ TDEListBox* styleListBox;
+ TQLabel* colorLabel;
+ KHSSelector* hsSelector;
+ KValueSelector* valuePal;
+ TQLabel* widthLabel;
+ TQSpinBox* widthSpinBox;
+ TDEListBox* widthListBox;
+ TDEHTMLPart* borderPreview;
+
+protected:
+ TQVBoxLayout* borderGroupBoxLayout;
+ TQHBoxLayout* layout4;
+ TQVBoxLayout* layout3;
+ TQVBoxLayout* layout2;
+ TQVBoxLayout* layout1;
+
+protected slots:
+ virtual void languageChange();
+ void updatePreview();
+ void updateSpinBox( int index );
+
+ void slotHSChanged( int h, int s );
+ void slotVChanged( int v );
+ void setColor( const KColor &color );
+
+private:
+ void loadBorder( const KreBorder &border );
+ void initListBoxs();
+
+ KColor selColor;
+
+};
+
+#endif // BORDERDIALOG_H
diff --git a/src/dialogs/categorieseditordialog.cpp b/src/dialogs/categorieseditordialog.cpp
new file mode 100644
index 0000000..d383fde
--- /dev/null
+++ b/src/dialogs/categorieseditordialog.cpp
@@ -0,0 +1,67 @@
+/***************************************************************************
+* 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 "categorieseditordialog.h"
+
+#include <kdebug.h>
+#include <kdialog.h>
+#include <tdelocale.h>
+#include <tdemessagebox.h>
+
+#include "widgets/categorylistview.h"
+#include "createcategorydialog.h"
+#include "backends/recipedb.h"
+
+CategoriesEditorDialog::CategoriesEditorDialog( TQWidget* parent, RecipeDB *db ) : TQWidget( parent )
+{
+
+ // Store pointer to database
+ database = db;
+
+ TQHBoxLayout* layout = new TQHBoxLayout( this, KDialog::marginHint(), KDialog::spacingHint() );
+
+ //Category List
+ categoryListView = new StdCategoryListView( this, database, true );
+ layout->addWidget( categoryListView );
+
+ //Buttons
+ TQVBoxLayout* vboxl = new TQVBoxLayout( KDialog::spacingHint() );
+
+ newCategoryButton = new TQPushButton( this );
+ newCategoryButton->setText( i18n( "Create ..." ) );
+ newCategoryButton->setFlat( true );
+ vboxl->addWidget( newCategoryButton );
+
+ removeCategoryButton = new TQPushButton( this );
+ removeCategoryButton->setText( i18n( "Delete" ) );
+ removeCategoryButton->setFlat( true );
+ vboxl->addWidget( removeCategoryButton );
+ vboxl->addStretch();
+
+ layout->addLayout( vboxl );
+
+ //Connect Signals & Slots
+
+ connect ( newCategoryButton, TQ_SIGNAL( clicked() ), categoryListView, TQ_SLOT( createNew() ) );
+ connect ( removeCategoryButton, TQ_SIGNAL( clicked() ), categoryListView, TQ_SLOT( remove
+ () ) );
+}
+
+CategoriesEditorDialog::~CategoriesEditorDialog()
+{}
+
+void CategoriesEditorDialog::reload( ReloadFlags flag )
+{
+ categoryListView->reload( flag );
+}
+
+#include "categorieseditordialog.moc"
diff --git a/src/dialogs/categorieseditordialog.h b/src/dialogs/categorieseditordialog.h
new file mode 100644
index 0000000..9b2e56d
--- /dev/null
+++ b/src/dialogs/categorieseditordialog.h
@@ -0,0 +1,56 @@
+/***************************************************************************
+* 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. *
+***************************************************************************/
+
+#ifndef CATEGORIESEDITORDIALOG_H
+#define CATEGORIESEDITORDIALOG_H
+
+#include <tqwidget.h>
+#include <tqpushbutton.h>
+#include <tqhbox.h>
+#include <tqlayout.h>
+#include <kiconloader.h>
+#include <tdelistview.h>
+
+#include "datablocks/categorytree.h"
+#include "widgets/dblistviewbase.h"
+
+class RecipeDB;
+class StdCategoryListView;
+
+/**
+@author Unai Garro
+*/
+class CategoriesEditorDialog: public TQWidget
+{
+
+ TQ_OBJECT
+
+public:
+
+ CategoriesEditorDialog( TQWidget* parent, RecipeDB *db );
+ ~CategoriesEditorDialog();
+
+ void reload( ReloadFlags flag = Load );
+
+private:
+ // Internal data
+ RecipeDB *database;
+ //Widgets
+ TQGridLayout *layout;
+ StdCategoryListView *categoryListView;
+ TQHBox *buttonBar;
+ TQPushButton *newCategoryButton;
+ TQPushButton *removeCategoryButton;
+ TDEIconLoader *il;
+};
+
+#endif
diff --git a/src/dialogs/conversiondialog.cpp b/src/dialogs/conversiondialog.cpp
new file mode 100644
index 0000000..c9e3f51
--- /dev/null
+++ b/src/dialogs/conversiondialog.cpp
@@ -0,0 +1,166 @@
+/***************************************************************************
+* Copyright (C) 2006 by *
+* 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 "conversiondialog.h"
+
+#include <tqvariant.h>
+#include <tqpushbutton.h>
+#include <kcombobox.h>
+#include <tqlabel.h>
+#include <klineedit.h>
+#include <tqlayout.h>
+#include <tqtooltip.h>
+#include <tqwhatsthis.h>
+#include <tqvbox.h>
+
+#include <kcombobox.h>
+#include <klineedit.h>
+#include <tdelocale.h>
+
+#include "backends/recipedb.h"
+#include "widgets/unitcombobox.h"
+#include "widgets/ingredientcombobox.h"
+#include "widgets/prepmethodcombobox.h"
+#include "widgets/fractioninput.h"
+
+ConversionDialog::ConversionDialog( TQWidget* parent, RecipeDB *db, const char* name )
+ : KDialogBase( parent, name, false, i18n( "Measurement Converter" ),
+ KDialogBase::Close | KDialogBase::User1 | KDialogBase::Help, KDialogBase::Close ),
+ m_database(db)
+{
+ setHelp("measure-converter");
+ setButtonText( KDialogBase::User1, i18n("Convert") );
+
+ setSizeGripEnabled( TRUE );
+
+ TQVBox *page = makeVBoxMainWidget();
+
+ TQHBox *vbox = new TQVBox(page);
+
+ TQHBox *fromTopBox = new TQHBox(vbox);
+ convertLabel = new TQLabel( fromTopBox, "convertLabel" );
+
+ amountEdit = new FractionInput( fromTopBox );
+
+ fromUnitBox = new UnitComboBox( fromTopBox, db );
+ fromUnitBox->reload();
+ fromTopBox->setStretchFactor( fromUnitBox, 2 );
+ fromTopBox->setSpacing(3);
+
+ TQHBox *fromBottomBox = new TQHBox(vbox);
+
+ ingredientBox = new IngredientComboBox( FALSE, fromBottomBox, db, i18n( "--Ingredient (optional)--" ) );
+ ingredientBox->reload();
+
+ prepMethodBox = new PrepMethodComboBox( false, fromBottomBox, db, i18n( "-No Preparation-" ) );
+ prepMethodBox->reload();
+ fromBottomBox->setSpacing(3);
+
+ TQHBox *toBox = new TQHBox(vbox);
+
+ toLabel = new TQLabel( toBox, "toLabel" );
+
+ toUnitBox = new UnitComboBox( toBox, db );
+ toUnitBox->reload();
+ toBox->setStretchFactor( toUnitBox, 2 );
+ toBox->setSpacing(8);
+
+ TQHBox *resultBox = new TQHBox(vbox);
+ resultLabel = new TQLabel( resultBox, "resultLabel" );
+ resultText = new TQLabel( resultBox, "resultText" );
+ resultBox->setStretchFactor( resultText, 2 );
+
+ languageChange();
+
+ setInitialSize( TQSize(300, 200).expandedTo(minimumSizeHint()) );
+
+ // signals and slots connections
+ connect ( this, TQ_SIGNAL( closeClicked() ), this, TQ_SLOT( accept() ) );
+}
+
+ConversionDialog::~ConversionDialog()
+{
+}
+
+void ConversionDialog::languageChange()
+{
+ convertLabel->setText( i18n( "Convert" ) );
+ toLabel->setText( i18n( "To" ) );
+ resultLabel->setText( i18n( "<b>Result:</b>" ) );
+ resultText->setText( TQString::null );
+}
+
+void ConversionDialog::show()
+{
+ reset();
+ KDialogBase::show();
+}
+
+void ConversionDialog::reset()
+{
+ resultText->setText( TQString::null );
+ ingredientBox->setCurrentItem( 0 );
+ prepMethodBox->setCurrentItem( 0 );
+ toUnitBox->setCurrentItem( 0 );
+ fromUnitBox->setCurrentItem( 0 );
+ amountEdit->clear();
+}
+
+void ConversionDialog::slotUser1()
+{
+ convert();
+}
+
+void ConversionDialog::convert()
+{
+ Ingredient result, ing;
+ Unit unit = m_database->unitName(toUnitBox->id(toUnitBox->currentItem()));
+
+ ing.amount = amountEdit->value().toDouble();
+ ing.ingredientID = ingredientBox->id(ingredientBox->currentItem());
+ ing.units = m_database->unitName(fromUnitBox->id(fromUnitBox->currentItem()));
+
+ int prepID = prepMethodBox->id(prepMethodBox->currentItem());
+ if ( prepID != -1 )
+ ing.prepMethodList.append(Element(TQString::null,prepID));
+
+ switch ( m_database->convertIngredientUnits( ing, unit, result ) ) {
+ case RecipeDB::Success:
+ resultLabel->setText( i18n( "<b>Result:</b>" ) );
+ resultText->setText(TQString::number(result.amount)+" "+((result.amount>1)?result.units.plural:result.units.name));
+ break;
+ case RecipeDB::MismatchedPrepMethodUsingApprox:
+ resultLabel->setText( i18n( "<b>Approximated result:</b>" ) );
+ resultText->setText(TQString::number(result.amount)+" "+((result.amount>1)?result.units.plural:result.units.name));
+ break;
+ case RecipeDB::MissingUnitConversion:
+ resultLabel->setText( i18n( "<b>Error:</b>" ) );
+ resultText->setText( i18n("Missing unit conversion") );
+ break;
+ case RecipeDB::MissingIngredientWeight:
+ resultLabel->setText( i18n( "<b>Error:</b>" ) );
+ resultText->setText( i18n("No ingredient weight available") );
+ break;
+ case RecipeDB::MismatchedPrepMethod:
+ resultLabel->setText( i18n( "<b>Error:</b>" ) );
+ resultText->setText( i18n("No ingredient weight available for this method of preparation") );
+ break;
+ case RecipeDB::MissingIngredient:
+ resultLabel->setText( i18n( "<b>Error:</b>" ) );
+ resultText->setText( i18n("Ingredient required for conversion") );
+ break;
+ case RecipeDB::InvalidTypes:
+ resultLabel->setText( i18n( "<b>Error:</b>" ) );
+ resultText->setText( i18n("Impossible unit conversion based on unit types") );
+ break;
+ }
+}
+
+#include "conversiondialog.moc"
diff --git a/src/dialogs/conversiondialog.h b/src/dialogs/conversiondialog.h
new file mode 100644
index 0000000..b467ce1
--- /dev/null
+++ b/src/dialogs/conversiondialog.h
@@ -0,0 +1,62 @@
+/***************************************************************************
+* Copyright (C) 2006 by *
+* 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. *
+***************************************************************************/
+
+#ifndef CONVERSIONDIALOG_H
+#define CONVERSIONDIALOG_H
+
+#include <kdialogbase.h>
+
+class TQVBoxLayout;
+class TQHBoxLayout;
+class TQGridLayout;
+class TQSpacerItem;
+class KComboBox;
+class TQLabel;
+class KLineEdit;
+class TQPushButton;
+
+class RecipeDB;
+class UnitComboBox;
+class IngredientComboBox;
+class PrepMethodComboBox;
+class FractionInput;
+
+class ConversionDialog : public KDialogBase
+{
+TQ_OBJECT
+
+public:
+ ConversionDialog( TQWidget* parent, RecipeDB *, const char* name = 0 );
+ ~ConversionDialog();
+
+ virtual void show();
+ void reset();
+
+protected:
+ IngredientComboBox* ingredientBox;
+ PrepMethodComboBox* prepMethodBox;
+ TQLabel* convertLabel;
+ UnitComboBox* toUnitBox;
+ UnitComboBox* fromUnitBox;
+ FractionInput* amountEdit;
+ TQLabel* toLabel;
+ TQLabel* resultLabel;
+ TQLabel* resultText;
+
+protected slots:
+ virtual void languageChange();
+ void slotUser1();
+ void convert();
+
+private:
+ RecipeDB *m_database;
+};
+
+#endif // CONVERSIONDIALOG_H
diff --git a/src/dialogs/createcategorydialog.cpp b/src/dialogs/createcategorydialog.cpp
new file mode 100644
index 0000000..f0cbc21
--- /dev/null
+++ b/src/dialogs/createcategorydialog.cpp
@@ -0,0 +1,80 @@
+/***************************************************************************
+* 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 "createcategorydialog.h"
+
+#include <tqpushbutton.h>
+#include <tqgroupbox.h>
+#include <tqlayout.h>
+#include <tqlabel.h>
+#include <tqvbox.h>
+
+#include <kcombobox.h>
+#include <klineedit.h>
+#include <tdelocale.h>
+
+CreateCategoryDialog::CreateCategoryDialog( TQWidget *parent, const ElementList& categories )
+ : KDialogBase( parent, "createCategoryDialog", true, i18n( "New Category" ),
+ KDialogBase::Ok | KDialogBase::Cancel, KDialogBase::Ok )
+{
+ TQVBox *page = makeVBoxMainWidget();
+
+ box = new TQGroupBox( page );
+ box->setColumnLayout( 0, TQt::Vertical );
+ box->layout() ->setSpacing( 6 );
+ box->layout() ->setMargin( 11 );
+ TQVBoxLayout *boxLayout = new TQVBoxLayout( box->layout() );
+ boxLayout->setAlignment( TQt::AlignTop );
+ box->setTitle( i18n( "New Category" ) );
+
+ elementEdit = new KLineEdit( box );
+ boxLayout->addWidget( elementEdit );
+
+ TQHBox *subcatHBox = new TQHBox( box );
+ ( void ) new TQLabel( i18n( "Subcategory of:" ), subcatHBox );
+ categoryComboBox = new KComboBox( subcatHBox );
+ boxLayout->addWidget( subcatHBox );
+ loadCategories( categories );
+
+ adjustSize();
+ setFixedSize( size() ); //we've got all the widgets put in, now let's keep it this size
+
+ elementEdit->setFocus();
+}
+
+
+CreateCategoryDialog::~CreateCategoryDialog()
+{}
+
+void CreateCategoryDialog::loadCategories( const ElementList& categories )
+{
+ categoryComboBox->insertItem( i18n( "**NONE**" ) );
+ for ( ElementList::const_iterator it = categories.begin(); it != categories.end(); ++it ) {
+ categoryComboBox->insertItem( ( *it ).name );
+ idMap.insert( ( *it ).name, ( *it ).id );
+ }
+}
+
+TQString CreateCategoryDialog::newCategoryName( void )
+{
+ return ( elementEdit->text() );
+}
+
+int CreateCategoryDialog::subcategory( void )
+{
+ if ( categoryComboBox->currentItem() == 0 ) {
+ return -1;
+ }
+ else {
+ return idMap[ categoryComboBox->currentText() ];
+ }
+}
diff --git a/src/dialogs/createcategorydialog.h b/src/dialogs/createcategorydialog.h
new file mode 100644
index 0000000..2211006
--- /dev/null
+++ b/src/dialogs/createcategorydialog.h
@@ -0,0 +1,51 @@
+/***************************************************************************
+* 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. *
+***************************************************************************/
+
+#ifndef CREATECATEGORYDIALOG_H
+#define CREATECATEGORYDIALOG_H
+
+#include <tqmap.h>
+
+#include <kdialogbase.h>
+
+#include "datablocks/elementlist.h"
+
+class KLineEdit;
+class TQPushButton;
+class TQVBoxLayout;
+class TQGroupBox;
+class TQVBox;
+class KComboBox;
+
+/**
+@author Jason Kivlighn
+*/
+class CreateCategoryDialog : public KDialogBase
+{
+public:
+ CreateCategoryDialog( TQWidget *parent, const ElementList &categories );
+ ~CreateCategoryDialog();
+ TQString newCategoryName( void );
+ int subcategory( void );
+
+private:
+ void loadCategories( const ElementList &categories );
+
+ //Widgets
+ TQGroupBox *box;
+ KLineEdit *elementEdit;
+ KComboBox* categoryComboBox;
+ TQMap<TQString, int> idMap;
+
+};
+
+#endif
diff --git a/src/dialogs/createelementdialog.cpp b/src/dialogs/createelementdialog.cpp
new file mode 100644
index 0000000..1f5b4a0
--- /dev/null
+++ b/src/dialogs/createelementdialog.cpp
@@ -0,0 +1,48 @@
+/***************************************************************************
+* 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 "createelementdialog.h"
+
+#include <tdelocale.h>
+
+CreateElementDialog::CreateElementDialog( TQWidget *parent, const TQString &text )
+ : KDialogBase( parent, "createElementDialog", true, text,
+ KDialogBase::Ok | KDialogBase::Cancel, KDialogBase::Ok )
+{
+ TQVBox *page = makeVBoxMainWidget();
+
+ box = new TQGroupBox( page );
+ box->setColumnLayout( 0, TQt::Vertical );
+ box->layout() ->setSpacing( 6 );
+ box->layout() ->setMargin( 11 );
+ TQVBoxLayout *boxLayout = new TQVBoxLayout( box->layout() );
+ boxLayout->setAlignment( TQt::AlignTop );
+ box->setTitle( text );
+
+ elementEdit = new KLineEdit( box );
+ boxLayout->addWidget( elementEdit );
+
+ adjustSize();
+ setFixedSize( size() ); //we've got all the widgets put in, now let's keep it this size
+
+ elementEdit->setFocus();
+}
+
+
+CreateElementDialog::~CreateElementDialog()
+{}
+
+TQString CreateElementDialog::newElementName( void )
+{
+ return ( elementEdit->text() );
+}
+
diff --git a/src/dialogs/createelementdialog.h b/src/dialogs/createelementdialog.h
new file mode 100644
index 0000000..775647a
--- /dev/null
+++ b/src/dialogs/createelementdialog.h
@@ -0,0 +1,40 @@
+/***************************************************************************
+* 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. *
+***************************************************************************/
+
+#ifndef CREATEELEMENTDIALOG_H
+#define CREATEELEMENTDIALOG_H
+
+#include <tqpushbutton.h>
+#include <tqgroupbox.h>
+#include <tqlayout.h>
+#include <tqvbox.h>
+
+#include <klineedit.h>
+#include <kdialogbase.h>
+
+/**
+@author Unai Garro
+*/
+class CreateElementDialog : public KDialogBase
+{
+public:
+ CreateElementDialog( TQWidget *parent, const TQString &text );
+ ~CreateElementDialog();
+ TQString newElementName( void );
+
+private:
+ //Widgets
+ TQGroupBox *box;
+ KLineEdit *elementEdit;
+};
+
+#endif
diff --git a/src/dialogs/createingredientweightdialog.cpp b/src/dialogs/createingredientweightdialog.cpp
new file mode 100644
index 0000000..45bf158
--- /dev/null
+++ b/src/dialogs/createingredientweightdialog.cpp
@@ -0,0 +1,124 @@
+/***************************************************************************
+* Copyright (C) 2006 by *
+* 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 "createingredientweightdialog.h"
+
+#include <tqgroupbox.h>
+#include <tqlabel.h>
+#include <tqpushbutton.h>
+#include <tqlayout.h>
+#include <tqtooltip.h>
+#include <tqwhatsthis.h>
+#include <tqvbox.h>
+
+#include <tdemessagebox.h>
+#include <tdelocale.h>
+
+#include "widgets/unitcombobox.h"
+#include "widgets/prepmethodcombobox.h"
+#include "widgets/fractioninput.h"
+#include "datablocks/weight.h"
+#include "backends/recipedb.h"
+
+CreateIngredientWeightDialog::CreateIngredientWeightDialog( TQWidget* parent, RecipeDB *db )
+ : KDialogBase( parent, "createIngWeightDialog", true, TQString::null,
+ KDialogBase::Ok | KDialogBase::Cancel, KDialogBase::Ok )
+{
+ TQVBox *page = makeVBoxMainWidget();
+
+ groupBox1 = new TQGroupBox( page );
+ groupBox1->setColumnLayout(0, TQt::Vertical );
+ groupBox1->layout()->setSpacing( 6 );
+ groupBox1->layout()->setMargin( 11 );
+ groupBox1Layout = new TQGridLayout( groupBox1->layout() );
+ groupBox1Layout->setAlignment( TQt::AlignTop );
+
+ perAmountEdit = new FractionInput( groupBox1 );
+
+ groupBox1Layout->addWidget( perAmountEdit, 1, 1 );
+
+ weightEdit = new FractionInput( groupBox1 );
+
+ groupBox1Layout->addWidget( weightEdit, 0, 1 );
+
+ weightUnitBox = new UnitComboBox( groupBox1, db, Unit::Mass );
+ weightUnitBox->reload();
+
+ groupBox1Layout->addMultiCellWidget( weightUnitBox, 0, 0, 2, 3 );
+
+ perAmountLabel = new TQLabel( groupBox1, "perAmountLabel" );
+
+ groupBox1Layout->addWidget( perAmountLabel, 1, 0 );
+
+ weightLabel = new TQLabel( groupBox1, "weightLabel" );
+
+ groupBox1Layout->addWidget( weightLabel, 0, 0 );
+
+ perAmountUnitBox = new UnitComboBox( groupBox1, db );
+ perAmountUnitBox->reload();
+
+ groupBox1Layout->addWidget( perAmountUnitBox, 1, 2 );
+
+ prepMethodBox = new PrepMethodComboBox( false, groupBox1, db, i18n("-No Preparation-") );
+ prepMethodBox->reload();
+ groupBox1Layout->addWidget( prepMethodBox, 1, 3 );
+
+ languageChange();
+ clearWState( WState_Polished );
+
+ weightEdit->setFocus();
+}
+
+CreateIngredientWeightDialog::~CreateIngredientWeightDialog()
+{
+ // no need to delete child widgets, TQt does it all for us
+}
+
+void CreateIngredientWeightDialog::languageChange()
+{
+ groupBox1->setTitle( i18n( "New Ingredient Weight" ) );
+ perAmountLabel->setText( i18n( "Per Amount:" ) );
+ weightLabel->setText( i18n( "Weight:" ) );
+}
+
+void CreateIngredientWeightDialog::slotOk()
+{
+ if ( !perAmountEdit->isInputValid() ) {
+ KMessageBox::error( this, i18n( "Amount field contains invalid input." ),
+ i18n( "Invalid input" ) );
+ perAmountEdit->setFocus();
+ perAmountEdit->selectAll();
+ return;
+ }
+ else if ( !weightEdit->isInputValid() ) {
+ KMessageBox::error( this, i18n( "Amount field contains invalid input." ),
+ i18n( "Invalid input" ) );
+ weightEdit->setFocus();
+ weightEdit->selectAll();
+ return;
+ }
+
+ accept();
+}
+
+Weight CreateIngredientWeightDialog::weight() const
+{
+ Weight w;
+ w.perAmount = perAmountEdit->value().toDouble();
+ w.perAmountUnitID = perAmountUnitBox->id( perAmountUnitBox->currentItem() );
+ w.weight = weightEdit->value().toDouble();
+ w.weightUnitID = weightUnitBox->id( weightUnitBox->currentItem() );
+ w.prepMethodID = prepMethodBox->id( prepMethodBox->currentItem() );
+ w.prepMethod = prepMethodBox->currentText();
+
+ return w;
+}
+
+#include "createingredientweightdialog.moc"
diff --git a/src/dialogs/createingredientweightdialog.h b/src/dialogs/createingredientweightdialog.h
new file mode 100644
index 0000000..cbc4d8f
--- /dev/null
+++ b/src/dialogs/createingredientweightdialog.h
@@ -0,0 +1,60 @@
+/***************************************************************************
+* Copyright (C) 2006 by *
+* 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. *
+***************************************************************************/
+
+#ifndef CREATEINGREDIENTWEIGHTDIALOG_H
+#define CREATEINGREDIENTWEIGHTDIALOG_H
+
+#include <kdialogbase.h>
+
+class TQVBoxLayout;
+class TQHBoxLayout;
+class TQGridLayout;
+class TQSpacerItem;
+class TQGroupBox;
+class KLineEdit;
+class KComboBox;
+class TQLabel;
+class TQPushButton;
+
+class FractionInput;
+class UnitComboBox;
+class PrepMethodComboBox;
+class RecipeDB;
+class Weight;
+
+class CreateIngredientWeightDialog : public KDialogBase
+{
+TQ_OBJECT
+
+public:
+ CreateIngredientWeightDialog( TQWidget* parent, RecipeDB* );
+ ~CreateIngredientWeightDialog();
+
+ Weight weight() const;
+
+protected:
+ TQGridLayout* groupBox1Layout;
+
+protected slots:
+ virtual void languageChange();
+ void slotOk();
+
+private:
+ TQGroupBox* groupBox1;
+ FractionInput* perAmountEdit;
+ FractionInput* weightEdit;
+ UnitComboBox* weightUnitBox;
+ TQLabel* perAmountLabel;
+ TQLabel* weightLabel;
+ UnitComboBox* perAmountUnitBox;
+ PrepMethodComboBox* prepMethodBox;
+};
+
+#endif // CREATEINGREDIENTWEIGHTDIALOG_H
diff --git a/src/dialogs/createpropertydialog.cpp b/src/dialogs/createpropertydialog.cpp
new file mode 100644
index 0000000..9f8f107
--- /dev/null
+++ b/src/dialogs/createpropertydialog.cpp
@@ -0,0 +1,69 @@
+/***************************************************************************
+* 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 "createpropertydialog.h"
+
+#include <tdelocale.h>
+
+CreatePropertyDialog::CreatePropertyDialog( TQWidget *parent, UnitList* list )
+ : KDialogBase( parent, "createPropertyDialog", true, i18n( "New Property" ),
+ KDialogBase::Ok | KDialogBase::Cancel, KDialogBase::Ok )
+{
+
+ // Initialize Internal Variables
+ unitList = list; // Store the pointer to the unitList;
+
+ // Initialize widgets
+ TQVBox *page = makeVBoxMainWidget();
+
+ box = new TQGroupBox( page );
+ box->setColumnLayout( 0, TQt::Vertical );
+ box->layout() ->setSpacing( 6 );
+ box->layout() ->setMargin( 11 );
+ TQGridLayout *gridLayout = new TQGridLayout( box->layout() );
+ gridLayout->setAlignment( TQt::AlignTop );
+ box->setTitle( i18n( "New Property" ) );
+
+ nameEditText = new TQLabel( i18n( "Property name:" ), box );
+ propertyNameEdit = new KLineEdit( box );
+ propertyNameEdit->setMinimumWidth( 150 );
+ gridLayout->addWidget( nameEditText, 0, 0 );
+ gridLayout->addWidget( propertyNameEdit, 0, 1 );
+
+ unitsText = new TQLabel( i18n( "Units:" ), box );
+ propertyUnits = new KLineEdit( box );
+ propertyUnits->setMinimumWidth( 150 );
+ gridLayout->addWidget( unitsText, 1, 0 );
+ gridLayout->addWidget( propertyUnits, 1, 1 );
+
+ adjustSize();
+ setFixedSize( size() );
+
+ propertyNameEdit->setFocus();
+}
+
+
+CreatePropertyDialog::~CreatePropertyDialog()
+{}
+
+
+TQString CreatePropertyDialog::newPropertyName( void )
+{
+ return ( propertyNameEdit->text() );
+}
+
+TQString CreatePropertyDialog::newUnitsName( void )
+{
+ return ( propertyUnits->text() );
+}
+
+
diff --git a/src/dialogs/createpropertydialog.h b/src/dialogs/createpropertydialog.h
new file mode 100644
index 0000000..1714e9e
--- /dev/null
+++ b/src/dialogs/createpropertydialog.h
@@ -0,0 +1,56 @@
+/***************************************************************************
+* 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. *
+***************************************************************************/
+
+/**
+@author Unai Garro
+*/
+
+#ifndef CREATEPROPERTYDIALOG_H
+#define CREATEPROPERTYDIALOG_H
+
+#include <tqcombobox.h>
+#include <tqlayout.h>
+#include <tqpushbutton.h>
+#include <tqgroupbox.h>
+#include <tqvbox.h>
+#include <tqlabel.h>
+
+#include <klineedit.h>
+#include <kdialogbase.h>
+
+#include "datablocks/unit.h"
+
+class CreatePropertyDialog : public KDialogBase
+{
+public:
+ CreatePropertyDialog( TQWidget *parent, UnitList *list );
+ ~CreatePropertyDialog();
+ TQString newPropertyName( void );
+ TQString newUnitsName( void );
+
+
+private:
+ //Widgets
+ TQGroupBox *box;
+ KLineEdit *propertyNameEdit;
+ KLineEdit *propertyUnits;
+ TQLabel *nameEditText;
+ TQLabel *unitsText;
+
+ //Internal variables
+ UnitList *unitList;
+
+ //Methods
+ void loadUnits();
+};
+
+#endif
diff --git a/src/dialogs/createunitdialog.cpp b/src/dialogs/createunitdialog.cpp
new file mode 100644
index 0000000..4929bb6
--- /dev/null
+++ b/src/dialogs/createunitdialog.cpp
@@ -0,0 +1,116 @@
+/***************************************************************************
+* Copyright (C) 2003-2004 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 "createunitdialog.h"
+
+#include <tqlabel.h>
+
+#include <tdelocale.h>
+#include <klineedit.h>
+#include <kcombobox.h>
+
+CreateUnitDialog::CreateUnitDialog( TQWidget *parent, const TQString &name, const TQString &plural, const TQString &name_abbrev, const TQString &plural_abbrev, bool newUnit )
+ : KDialogBase( parent, "createElementDialog", true, (newUnit)?i18n( "New Unit" ):i18n("Unit"),
+ KDialogBase::Ok | KDialogBase::Cancel, KDialogBase::Ok )
+{
+ TQVBox *page = makeVBoxMainWidget();
+
+ box = new TQGroupBox( page );
+ box->setColumnLayout( 0, TQt::Vertical );
+ box->layout() ->setSpacing( 6 );
+ box->layout() ->setMargin( 11 );
+ TQGridLayout *gridLayout = new TQGridLayout( box->layout() );
+ gridLayout->setAlignment( TQt::AlignTop );
+
+ box->setTitle( (newUnit)?i18n( "New Unit" ):i18n("Unit") );
+
+ TQLabel *nameLabel = new TQLabel( i18n( "Singular:" ), box );
+ nameEdit = new KLineEdit( name, box );
+
+ gridLayout->addWidget( nameLabel, 0, 0 );
+ gridLayout->addWidget( nameEdit, 0, 1 );
+
+ TQLabel *nameAbbrevLabel = new TQLabel( i18n( "Abbreviation:" ), box );
+ nameAbbrevEdit = new KLineEdit( name_abbrev, box );
+
+ gridLayout->addWidget( nameAbbrevLabel, 0, 2 );
+ gridLayout->addWidget( nameAbbrevEdit, 0, 3 );
+
+ TQLabel *pluralLabel = new TQLabel( i18n( "Plural:" ), box );
+ pluralEdit = new KLineEdit( plural, box );
+
+ gridLayout->addWidget( pluralLabel, 1, 0 );
+ gridLayout->addWidget( pluralEdit, 1, 1 );
+
+ TQLabel *pluralAbbrevLabel = new TQLabel( i18n( "Abbreviation:" ), box );
+ pluralAbbrevEdit = new KLineEdit( plural_abbrev, box );
+
+ gridLayout->addWidget( pluralAbbrevLabel, 1, 2 );
+ gridLayout->addWidget( pluralAbbrevEdit, 1, 3 );
+
+ TQLabel *typeLabel = new TQLabel( i18n( "Type:" ), box );
+ typeComboBox = new KComboBox( false, box );
+ typeComboBox->insertItem(i18n("Other"));
+ typeComboBox->insertItem(i18n("Mass"));
+ typeComboBox->insertItem(i18n("Volume"));
+
+ gridLayout->addWidget( typeLabel, 2, 0 );
+ gridLayout->addMultiCellWidget( typeComboBox, 2, 2, 1, 3 );
+
+ adjustSize();
+ setFixedSize( size() ); //we've got all the widgets put in, now let's keep it this size
+
+ connect( nameAbbrevEdit, TQ_SIGNAL(textChanged(const TQString&)), TQ_SLOT(nameAbbrevTextChanged(const TQString &)) );
+
+ if ( name.isEmpty() )
+ nameEdit->setFocus();
+ else if ( plural.isEmpty() )
+ pluralEdit->setFocus();
+}
+
+
+CreateUnitDialog::~CreateUnitDialog()
+{}
+
+Unit CreateUnitDialog::newUnit( void )
+{
+ TQString name = nameEdit->text();
+ TQString plural = pluralEdit->text();
+
+ if ( name.isEmpty() )
+ name = plural;
+ if ( plural.isEmpty() )
+ plural = name;
+
+ Unit new_unit = Unit( name, plural );
+ new_unit.name_abbrev = nameAbbrevEdit->text();
+ new_unit.plural_abbrev = pluralAbbrevEdit->text();
+
+ new_unit.type = (Unit::Type)typeComboBox->currentItem();
+
+ return new_unit;
+}
+
+void CreateUnitDialog::nameAbbrevTextChanged(const TQString &newText)
+{
+ //appending
+ if ( newText.left( newText.length()-1 ) == pluralAbbrevEdit->text() ) {
+ pluralAbbrevEdit->setText( newText );
+ }
+
+ //truncating
+ if ( newText.left( newText.length()-1 ) == pluralAbbrevEdit->text().left( newText.length()-1 ) ) {
+ pluralAbbrevEdit->setText( newText );
+ }
+}
+
+#include "createunitdialog.moc"
diff --git a/src/dialogs/createunitdialog.h b/src/dialogs/createunitdialog.h
new file mode 100644
index 0000000..a2e1777
--- /dev/null
+++ b/src/dialogs/createunitdialog.h
@@ -0,0 +1,52 @@
+/***************************************************************************
+* Copyright (C) 2003-2004 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. *
+***************************************************************************/
+
+#ifndef CREATEUNITDIALOG_H
+#define CREATEUNITDIALOG_H
+
+#include <kdialogbase.h>
+#include <tqpushbutton.h>
+#include <tqgroupbox.h>
+#include <tqlayout.h>
+#include <tqvbox.h>
+
+#include "datablocks/unit.h"
+
+class KComboBox;
+class KLineEdit;
+
+/**
+@author Unai Garro
+*/
+class CreateUnitDialog : public KDialogBase
+{
+TQ_OBJECT
+
+public:
+ CreateUnitDialog( TQWidget *parent, const TQString &name = TQString::null, const TQString &plural = TQString::null, const TQString &name_abbrev = TQString::null, const TQString &plural_abbrev = TQString::null, bool newUnit = true );
+ ~CreateUnitDialog();
+ Unit newUnit( void );
+
+protected slots:
+ void nameAbbrevTextChanged(const TQString &);
+
+private:
+ //Widgets
+ TQGroupBox *box;
+ KLineEdit *nameEdit;
+ KLineEdit *pluralEdit;
+ KLineEdit *nameAbbrevEdit;
+ KLineEdit *pluralAbbrevEdit;
+ KComboBox *typeComboBox;
+};
+
+#endif
diff --git a/src/dialogs/dbimportdialog.cpp b/src/dialogs/dbimportdialog.cpp
new file mode 100644
index 0000000..7d5d68b
--- /dev/null
+++ b/src/dialogs/dbimportdialog.cpp
@@ -0,0 +1,219 @@
+/***************************************************************************
+* Copyright (C) 2004 by *
+* 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 "dbimportdialog.h"
+
+#include <unistd.h> //for getuid()
+#include <pwd.h> //getpwuid()
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <tqpushbutton.h>
+#include <tqbuttongroup.h>
+#include <tqradiobutton.h>
+#include <tqwidgetstack.h>
+#include <tqwidget.h>
+#include <tqlineedit.h>
+#include <tqlabel.h>
+#include <tqlayout.h>
+#include <tqtooltip.h>
+#include <tqwhatsthis.h>
+#include <tqhbox.h>
+
+#include <tdeconfig.h>
+#include <kdebug.h>
+#include <tdelocale.h>
+#include <kurlrequester.h>
+#include <knuminput.h>
+
+DBImportDialog::DBImportDialog( TQWidget *parent, const char *name )
+ : KDialogBase( parent, name, true, i18n( "Database Import" ),
+ KDialogBase::Ok | KDialogBase::Cancel, KDialogBase::Ok )
+{
+ setButtonBoxOrientation( Vertical );
+
+ TQHBox *page = makeHBoxMainWidget();
+
+ dbButtonGroup = new TQButtonGroup( page, "dbButtonGroup" );
+ dbButtonGroup->setSizePolicy( TQSizePolicy( ( TQSizePolicy::SizeType ) 4, ( TQSizePolicy::SizeType ) 5, 0, 0, dbButtonGroup->sizePolicy().hasHeightForWidth() ) );
+ dbButtonGroup->setColumnLayout( 0, TQt::Vertical );
+ dbButtonGroup->layout() ->setSpacing( 6 );
+ dbButtonGroup->layout() ->setMargin( 11 );
+ dbButtonGroupLayout = new TQVBoxLayout( dbButtonGroup->layout() );
+ dbButtonGroupLayout->setAlignment( TQt::AlignTop );
+
+ liteRadioButton = new TQRadioButton( dbButtonGroup, "liteRadioButton" );
+ liteRadioButton->setChecked( TRUE );
+ dbButtonGroupLayout->addWidget( liteRadioButton );
+
+ mysqlRadioButton = new TQRadioButton( dbButtonGroup, "mysqlRadioButton" );
+ dbButtonGroupLayout->addWidget( mysqlRadioButton );
+
+ psqlRadioButton = new TQRadioButton( dbButtonGroup, "psqlRadioButton" );
+ dbButtonGroupLayout->addWidget( psqlRadioButton );
+
+ paramStack = new TQWidgetStack( page, "paramStack" );
+ paramStack->setSizePolicy( TQSizePolicy( ( TQSizePolicy::SizeType ) 7, ( TQSizePolicy::SizeType ) 5, 0, 0, paramStack->sizePolicy().hasHeightForWidth() ) );
+
+ sqlitePage = new TQWidget( paramStack, "sqlitePage" );
+ serverPageLayout_2 = new TQVBoxLayout( sqlitePage, 11, 6, "serverPageLayout_2" );
+
+ TQLabel *sqliteLabel = new TQLabel( i18n( "Database file:" ), sqlitePage );
+ serverPageLayout_2->addWidget( sqliteLabel );
+ sqliteDBRequester = new KURLRequester( sqlitePage, "sqliteDBRequester" );
+ sqliteDBRequester->setShowLocalProtocol( false );
+ serverPageLayout_2->addWidget( sqliteDBRequester );
+
+ TQSpacerItem *vSpacer = new TQSpacerItem( 20, 20, TQSizePolicy::Minimum, TQSizePolicy::Expanding );
+ serverPageLayout_2->addItem(vSpacer);
+
+ paramStack->addWidget( sqlitePage, 1 );
+
+ serverPage = new TQWidget( paramStack, "serverPage" );
+ serverPageLayout = new TQVBoxLayout( serverPage, 11, 6, "serverPageLayout" );
+
+ layout5 = new TQGridLayout( 0, 1, 1, 0, 6, "layout5" );
+
+ hostEdit = new TQLineEdit( serverPage, "hostEdit" );
+ layout5->addWidget( hostEdit, 0, 1 );
+ hostLabel = new TQLabel( serverPage, "hostLabel" );
+ layout5->addWidget( hostLabel, 0, 0 );
+
+ userEdit = new TQLineEdit( serverPage, "userEdit" );
+ layout5->addWidget( userEdit, 1, 1 );
+ userLabel = new TQLabel( serverPage, "userLabel" );
+ layout5->addWidget( userLabel, 1, 0 );
+
+ passwordEdit = new TQLineEdit( serverPage, "passwordEdit" );
+ passwordEdit->setEchoMode( TQLineEdit::Password );
+ layout5->addWidget( passwordEdit, 2, 1 );
+ passwordLabel = new TQLabel( serverPage, "passwordLabel" );
+ layout5->addWidget( passwordLabel, 2, 0 );
+
+ portEdit = new KIntNumInput( serverPage, "portEdit" );
+ portEdit->setMinValue(0);
+ portEdit->setValue(0);
+ layout5->addWidget( portEdit, 3, 1 );
+ portLabel = new TQLabel( serverPage, "portLabel" );
+ layout5->addWidget( portLabel, 3, 0 );
+
+ nameEdit = new TQLineEdit( serverPage, "nameEdit" );
+ layout5->addWidget( nameEdit, 4, 1 );
+ nameLabel = new TQLabel( serverPage, "nameLabel" );
+ layout5->addWidget( nameLabel, 4, 0 );
+
+ serverPageLayout->addLayout( layout5 );
+ paramStack->addWidget( serverPage, 0 );
+
+ languageChange();
+
+
+#if (!HAVE_MYSQL)
+
+ mysqlRadioButton->setEnabled( false );
+#endif
+
+#if (!HAVE_POSTGRESQL)
+
+ psqlRadioButton->setEnabled( false );
+#endif
+
+#if (!(HAVE_SQLITE || HAVE_SQLITE3))
+
+ liteRadioButton->setEnabled( false );
+#if (HAVE_MYSQL)
+
+ dbButtonGroup->setButton( 1 ); // Otherwise by default liteCheckBox is checked even if it's disabled
+ switchDBPage(1);
+#else
+ #if (HAVE_POSTGRESQL)
+
+ dbButtonGroup->setButton( 2 );
+ switchDBPage(2);
+#endif
+ #endif
+ #endif
+
+ // signals and slots connections
+ connect( dbButtonGroup, TQ_SIGNAL( clicked( int ) ), this, TQ_SLOT( switchDBPage( int ) ) );
+}
+
+void DBImportDialog::languageChange()
+{
+ dbButtonGroup->setTitle( i18n( "Database" ) );
+ liteRadioButton->setText( "SQLite" );
+ mysqlRadioButton->setText( "MySQL" );
+ psqlRadioButton->setText( "PostgreSQL" );
+ hostLabel->setText( i18n( "Server:" ) );
+ userLabel->setText( i18n( "Username:" ) );
+ passwordLabel->setText( i18n( "Password:" ) );
+ nameLabel->setText( i18n( "Database name:" ) );
+ portLabel->setText( i18n( "Port:" ) );
+ portEdit->setSpecialValueText( i18n("Default") );
+
+ //set defaults
+ hostEdit->setText( "localhost" );
+ nameEdit->setText( "Krecipes" );
+
+ // get username
+ uid_t userID;
+ struct passwd *user;
+ userID = getuid();
+ user = getpwuid ( userID );
+ TQString username(user->pw_name);
+
+ userEdit->setText( username );
+}
+
+void DBImportDialog::switchDBPage( int id )
+{
+ switch ( id ) {
+ case 0: //SQLite
+ paramStack->raiseWidget( sqlitePage );
+ break;
+ case 1: //MySQL
+ case 2: //PostgreSQL
+ paramStack->raiseWidget( serverPage );
+ break;
+ }
+}
+
+TQString DBImportDialog::dbType() const
+{
+ int id = dbButtonGroup->id( dbButtonGroup->selected() );
+ switch ( id ) {
+ case 0:
+ return "SQLite";
+ case 1:
+ return "MySQL";
+ case 2:
+ return "PostgreSQL";
+ default:
+ return TQString::null;
+ }
+}
+
+void DBImportDialog::serverParams( TQString &host, TQString &user, TQString &pass, int &port, TQString &table ) const
+{
+ host = hostEdit->text();
+ user = userEdit->text();
+ pass = passwordEdit->text();
+ table = nameEdit->text();
+ port = portEdit->value();
+}
+
+TQString DBImportDialog::dbFile() const
+{
+ return sqliteDBRequester->url();
+}
+
+#include "dbimportdialog.moc"
diff --git a/src/dialogs/dbimportdialog.h b/src/dialogs/dbimportdialog.h
new file mode 100644
index 0000000..eef49c5
--- /dev/null
+++ b/src/dialogs/dbimportdialog.h
@@ -0,0 +1,76 @@
+/***************************************************************************
+* Copyright (C) 2004 by *
+* 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. *
+***************************************************************************/
+#ifndef DBIMPORTDIALOG_H
+#define DBIMPORTDIALOG_H
+
+#include <kdialogbase.h>
+
+class TQVBoxLayout;
+class TQHBoxLayout;
+class TQGridLayout;
+class TQSpacerItem;
+class TQButtonGroup;
+class TQRadioButton;
+class TQWidgetStack;
+class TQWidget;
+class TQLineEdit;
+class TQLabel;
+class TQPushButton;
+
+class KURLRequester;
+class KIntNumInput;
+
+/**
+@author Jason Kivlighn
+*/
+
+class DBImportDialog: public KDialogBase
+{
+ TQ_OBJECT
+public:
+ DBImportDialog( TQWidget *parent = 0, const char *name = 0 );
+
+ TQString dbType() const;
+ void serverParams( TQString &host, TQString &user, TQString &pass, int &port, TQString &table ) const;
+ TQString dbFile() const;
+
+private:
+ // Widgets
+ TQButtonGroup* dbButtonGroup;
+ TQRadioButton* liteRadioButton;
+ TQRadioButton* mysqlRadioButton;
+ TQRadioButton* psqlRadioButton;
+ TQWidgetStack* paramStack;
+ TQWidget* serverPage;
+ TQLineEdit* nameEdit;
+ TQLabel* passwordLabel;
+ TQLineEdit* hostEdit;
+ TQLineEdit* passwordEdit;
+ TQLineEdit* userEdit;
+ TQLabel* userLabel;
+ TQLabel* hostLabel;
+ TQLabel* nameLabel;
+ TQLabel* portLabel;
+ KIntNumInput *portEdit;
+ TQWidget* sqlitePage;
+ KURLRequester* sqliteDBRequester;
+
+ TQVBoxLayout* dbButtonGroupLayout;
+ TQVBoxLayout* serverPageLayout;
+ TQGridLayout* layout5;
+ TQVBoxLayout* serverPageLayout_2;
+
+protected slots:
+ void languageChange();
+ void switchDBPage( int id );
+
+};
+
+#endif
diff --git a/src/dialogs/dependanciesdialog.cpp b/src/dialogs/dependanciesdialog.cpp
new file mode 100644
index 0000000..ac7d095
--- /dev/null
+++ b/src/dialogs/dependanciesdialog.cpp
@@ -0,0 +1,100 @@
+/***************************************************************************
+* Copyright (C) 2003 by *
+* Unai Garro (ugarro@users.sourceforge.net) *
+* Cyril Bosselut (bosselut@b1project.com) *
+* *
+* Copyright (C) 2003-2005 by *
+* 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 "dependanciesdialog.h"
+#include "datablocks/elementlist.h"
+
+#include <tqvbox.h>
+
+#include <tdelocale.h>
+#include <tdeglobal.h>
+#include <tdeconfig.h>
+#include <tdemessagebox.h>
+
+DependanciesDialog::DependanciesDialog( TQWidget *parent, const TQValueList<ListInfo> &lists, bool deps_are_deleted ) : KDialogBase( parent, "DependanciesDialog", true, TQString::null,
+ KDialogBase::Ok | KDialogBase::Cancel, KDialogBase::Cancel ),
+ m_depsAreDeleted(deps_are_deleted)
+{
+ init( lists );
+}
+
+DependanciesDialog::DependanciesDialog( TQWidget *parent, const ListInfo &list, bool deps_are_deleted ) : KDialogBase( parent, "DependanciesDialog", true, TQString::null,
+ KDialogBase::Ok | KDialogBase::Cancel, KDialogBase::Cancel ),
+ m_depsAreDeleted(deps_are_deleted)
+{
+ TQValueList<ListInfo> lists;
+ lists << list;
+ init( lists );
+}
+
+DependanciesDialog::~DependanciesDialog()
+{}
+
+void DependanciesDialog::init( const TQValueList<ListInfo> &lists )
+{
+ TQVBox *page = makeVBoxMainWidget();
+
+ // Design the dialog
+
+ instructionsLabel = new TQLabel( page );
+ instructionsLabel->setMinimumSize( TQSize( 100, 30 ) );
+ instructionsLabel->setMaximumSize( TQSize( 10000, 10000 ) );
+ instructionsLabel->setAlignment( int( TQLabel::WordBreak | TQLabel::AlignVCenter ) );
+
+ if ( m_depsAreDeleted ) {
+ instructionsLabel->setText( i18n( "<b>WARNING:</b> The following will have to be removed also, since currently they use the element you have chosen to be removed." ) );
+ }
+ else {
+ instructionsLabel->setText( i18n( "<b>WARNING:</b> The following currently use the element you have chosen to be removed." ) );
+ }
+
+ for ( TQValueList<ListInfo>::const_iterator list_it = lists.begin(); list_it != lists.end(); ++list_it ) {
+ if ( !((*list_it).list).isEmpty() ) {
+ TQGroupBox *groupBox = new TQGroupBox( 1, TQt::Vertical, (*list_it).name, page );
+ TDEListBox *listBox = new TDEListBox( groupBox );
+ loadList( listBox, (*list_it).list );
+ }
+ }
+
+ setSizeGripEnabled( true );
+}
+
+void DependanciesDialog::loadList( TDEListBox* listBox, const ElementList &list )
+{
+ TDEConfig * config = TDEGlobal::config();
+ config->setGroup( "Advanced" );
+ bool show_id = config->readBoolEntry( "ShowID", false );
+
+ for ( ElementList::const_iterator el_it = list.begin(); el_it != list.end(); ++el_it ) {
+ TQString name = ( *el_it ).name;
+ if ( show_id )
+ name += " (" + TQString::number(( *el_it ).id) + ")";
+ listBox->insertItem( name );
+ }
+}
+
+void DependanciesDialog::accept()
+{
+ if ( !m_msg.isEmpty() ) {
+ switch ( KMessageBox::warningYesNo(this,
+ TQString("<b>%1</b><br><br>%2").arg(m_msg).arg(i18n("Are you sure you wish to proceed?")),
+ TQString::null,KStdGuiItem::yes(),KStdGuiItem::no(),"doubleCheckDelete") )
+ {
+ case KMessageBox::Yes: TQDialog::accept(); break;
+ case KMessageBox::No: TQDialog::reject(); break;
+ }
+ }
+ else
+ TQDialog::accept();
+}
diff --git a/src/dialogs/dependanciesdialog.h b/src/dialogs/dependanciesdialog.h
new file mode 100644
index 0000000..076bd04
--- /dev/null
+++ b/src/dialogs/dependanciesdialog.h
@@ -0,0 +1,60 @@
+/***************************************************************************
+* Copyright (C) 2003 by *
+* Unai Garro (ugarro@users.sourceforge.net) *
+* Cyril Bosselut (bosselut@b1project.com) *
+* *
+* Copyright (C) 2003-2005 by *
+* 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. *
+***************************************************************************/
+
+#ifndef DEPENDANCIESDIALOG_H
+#define DEPENDANCIESDIALOG_H
+
+#include <tqgroupbox.h>
+#include <tqlabel.h>
+
+#include <tdelistview.h>
+#include <kdialogbase.h>
+
+#include "datablocks/elementlist.h"
+
+struct ListInfo {
+ ElementList list;
+ TQString name;
+};
+
+/**
+@author Unai Garro
+*/
+class DependanciesDialog: public KDialogBase
+{
+public:
+ //Methods
+ DependanciesDialog( TQWidget *parent, const TQValueList<ListInfo> &lists, bool deps_are_deleted = true );
+ DependanciesDialog( TQWidget *parent, const ListInfo &list, bool deps_are_deleted = true );
+
+ ~DependanciesDialog();
+
+ void setCustomWarning( const TQString &msg ){ m_msg = msg; }
+
+public slots:
+ void accept();
+
+private:
+ //Widgets
+ TQLabel *instructionsLabel;
+
+ bool m_depsAreDeleted;
+ TQString m_msg;
+
+ // Methods
+ void init( const TQValueList<ListInfo> &lists );
+ void loadList( TDEListBox*, const ElementList &list );
+};
+
+#endif
diff --git a/src/dialogs/dietviewdialog.cpp b/src/dialogs/dietviewdialog.cpp
new file mode 100644
index 0000000..5b51c27
--- /dev/null
+++ b/src/dialogs/dietviewdialog.cpp
@@ -0,0 +1,137 @@
+/***************************************************************************
+* Copyright (C) 2003-2005 *
+* Unai Garro (ugarro@users.sourceforge.net) *
+* 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 "dietviewdialog.h"
+
+#include <kiconloader.h>
+#include <tdelocale.h>
+#include <kstandarddirs.h>
+
+DietViewDialog::DietViewDialog( TQWidget *parent, const RecipeList &recipeList, int dayNumber, int mealNumber, const TQValueList <int> &dishNumbers )
+ : KDialogBase( parent, "dietViewDialog", true, TQString::null,
+ KDialogBase::User2 | KDialogBase::Close | KDialogBase::User1, KDialogBase::User2,
+ false, KStdGuiItem::print() )
+{
+ setButtonText( KDialogBase::User2, i18n( "Create &Shopping List" ) );
+
+ // Design the dialog
+ TQVBox *page = makeVBoxMainWidget();
+
+ // The html part
+ dietView = new TDEHTMLPart( page );
+
+ setInitialSize( TQSize(350, 450) );
+
+ setSizeGripEnabled( true );
+
+ connect ( this, TQ_SIGNAL( user2Clicked() ), this, TQ_SLOT( slotOk() ) );
+ connect ( this, TQ_SIGNAL( closeClicked() ), this, TQ_SLOT( close() ) );
+ connect ( this, TQ_SIGNAL( user1Clicked() ), this, TQ_SLOT( print() ) );
+
+ // Show the diet
+ showDiet( recipeList, dayNumber, mealNumber, dishNumbers );
+}
+
+DietViewDialog::~DietViewDialog()
+{}
+
+void DietViewDialog::showDiet( const RecipeList &recipeList, int dayNumber, int mealNumber, const TQValueList <int> &dishNumbers )
+{
+
+
+ // Header
+ TQString htmlCode = TQString( "<html><head><title>%1</title>" ).arg( i18n( "Diet" ) );
+
+ // CSS
+ htmlCode += "<STYLE type=\"text/css\">\n";
+ htmlCode += "#calendar{border: thin solid black}";
+ htmlCode += ".dayheader{ background-color: #D6D6D6; color: black; border:none;}";
+ htmlCode += ".day{ background-color: #E5E5E5; color: black; border:medium solid #D6D6D6;}";
+ htmlCode += ".meal{ background-color: #CDD4FF; color: black; border:thin solid #B4BEFF; text-align:center;}";
+ htmlCode += ".dish{font-size: smaller; overflow: hidden; height:2.5em;}";
+ htmlCode += "</STYLE>";
+
+
+ htmlCode += "</head><body>"; // /Header
+
+ // Calendar border
+ htmlCode += TQString( "<div id=\"calendar\">" );
+
+ // Title
+ htmlCode += TQString( "<center><div STYLE=\"width: 100%\">" );
+ htmlCode += TQString( "<h1>%1</h1></div></center>" ).arg( i18n( "Diet" ) );
+
+ // Diet table
+ htmlCode += TQString( "<center><div STYLE=\"width: 98%\">" );
+ htmlCode += TQString( "<table><tbody>" );
+
+
+ TQValueList <int>::ConstIterator it;
+ it = dishNumbers.begin();
+ RecipeList::ConstIterator rit;
+ rit = recipeList.begin();
+
+ for ( int row = 0, day = 0; row <= ( ( dayNumber - 1 ) / 7 ); row++ ) // New row (week)
+ {
+ htmlCode += TQString( "<tr>" );
+
+ for ( int col = 0; ( col < 7 ) && ( day < dayNumber ); col++, day++ ) // New column (day)
+ {
+ htmlCode += TQString( "<td><div class=\"day\">" );
+ htmlCode += TQString( "<div class=\"dayheader\"><center>" );
+ htmlCode += TQString( i18n( "Day %1" ) ).arg( day + 1 );
+ htmlCode += TQString( "</center></div>" );
+ for ( int meal = 0;meal < mealNumber;meal++ ) // Meals in each cell
+ {
+ int dishNumber = *it;
+ htmlCode += TQString( "<div class=\"meal\">" );
+ for ( int dish = 0; dish < dishNumber;dish++ ) // Dishes in each Meal
+ {
+ htmlCode += TQString( "<div class=\"dish\">" );
+ htmlCode += ( *rit ).title;
+ htmlCode += "<br>";
+ htmlCode += TQString( "</div>" );
+ rit++;
+ }
+ it++;
+ htmlCode += TQString( "</div>" );
+ }
+ it = dishNumbers.begin(); // meals have same dish number everyday
+ htmlCode += TQString( "</div></td>" );
+ }
+
+ htmlCode += TQString( "</tr>" );
+ }
+
+ htmlCode += TQString( "</tbody></table>" );
+ htmlCode += TQString( "</div></center>" );
+ htmlCode += TQString( "</div></body></html>" );
+
+ resize( TQSize( 600, 400 ) );
+
+ // Display it
+ dietView->begin( KURL( locateLocal( "tmp", "/" ) ) ); // Initialize to tmp dir, where photos and logos can be stored
+ dietView->write( htmlCode );
+ dietView->end();
+}
+
+void DietViewDialog::print( void )
+{
+ dietView->view()->print();
+}
+
+void DietViewDialog::slotOk( void )
+{
+ emit signalOk();
+ close();
+}
+
+#include "dietviewdialog.moc"
diff --git a/src/dialogs/dietviewdialog.h b/src/dialogs/dietviewdialog.h
new file mode 100644
index 0000000..aff4992
--- /dev/null
+++ b/src/dialogs/dietviewdialog.h
@@ -0,0 +1,45 @@
+/***************************************************************************
+* Copyright (C) 2003 by *
+* Unai Garro (ugarro@users.sourceforge.net) *
+* *
+* 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. *
+***************************************************************************/
+
+#ifndef DIETVIEWDIALOG_H
+#define DIETVIEWDIALOG_H
+
+#include <tqpushbutton.h>
+#include <tqlayout.h>
+#include <tqvbox.h>
+#include <tqwidget.h>
+
+#include <tdehtml_part.h>
+#include <tdehtmlview.h>
+#include <kdialogbase.h>
+
+#include "datablocks/recipelist.h"
+
+class DietViewDialog: public KDialogBase
+{
+ TQ_OBJECT
+
+public:
+ DietViewDialog( TQWidget *parent, const RecipeList &recipeList, int dayNumber, int mealNumber, const TQValueList <int> &dishNumbers );
+ ~DietViewDialog();
+private:
+ // Widgets
+ TDEHTMLPart *dietView;
+
+ // Private methods
+ void showDiet( const RecipeList &recipeList, int dayNumber, int mealNumber, const TQValueList <int> &dishNumbers );
+private slots:
+ void print( void );
+ void slotOk( void );
+signals:
+ void signalOk( void );
+};
+
+#endif
diff --git a/src/dialogs/dietwizarddialog.cpp b/src/dialogs/dietwizarddialog.cpp
new file mode 100644
index 0000000..30414cf
--- /dev/null
+++ b/src/dialogs/dietwizarddialog.cpp
@@ -0,0 +1,748 @@
+/***************************************************************************
+* 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 <tqbitmap.h>
+#include <tqheader.h>
+#include <tqlayout.h>
+#include <tqpainter.h>
+#include <tqwmatrix.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
+ 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();
+}
+
+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"
diff --git a/src/dialogs/dietwizarddialog.h b/src/dialogs/dietwizarddialog.h
new file mode 100644
index 0000000..c848664
--- /dev/null
+++ b/src/dialogs/dietwizarddialog.h
@@ -0,0 +1,222 @@
+/***************************************************************************
+* 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. *
+***************************************************************************/
+
+#ifndef DIETWIZARDDIALOG_H
+#define DIETWIZARDDIALOG_H
+
+#include <stdlib.h> // For RAND_MAX
+
+#include <tqcheckbox.h>
+#include <tqhbox.h>
+#include <tqhgroupbox.h>
+#include <tqlabel.h>
+#include <tqptrlist.h>
+#include <tqpushbutton.h>
+#include <tqslider.h>
+#include <tqspinbox.h>
+#include <tqtabwidget.h>
+#include <tqtoolbutton.h>
+#include <tqvaluelist.h>
+#include <tqvbox.h>
+#include <tqvgroupbox.h>
+#include <tqwidgetstack.h>
+
+#include <tdelistview.h>
+
+#include "datablocks/constraintlist.h"
+#include "datablocks/recipelist.h"
+#include "datablocks/elementlist.h"
+#include "datablocks/ingredientpropertylist.h"
+#include "datablocks/recipe.h"
+#include "datablocks/unitratiolist.h"
+
+#include "widgets/dblistviewbase.h"
+
+class KDoubleNumInput;
+
+class DishInput;
+class DishTitle;
+class MealInput;
+class RecipeDB;
+class RecipeList;
+class CategoryCheckListView;
+class PropertyConstraintListView;
+
+/**
+@author Unai Garro
+*/
+
+
+class DietWizardDialog: public TQVBox
+{
+
+ TQ_OBJECT
+
+public:
+
+ DietWizardDialog( TQWidget *parent, RecipeDB* db );
+ ~DietWizardDialog();
+
+private:
+ //Private variables
+ RecipeDB *database;
+
+ int dayNumber;
+ int mealNumber;
+
+ RecipeList *dietRList;
+
+ //Widgets
+ TQHBox *optionsBox;
+ TQVGroupBox *mealsSliderBox;
+ TQLabel *mealNumberLabel;
+ TQSlider *mealNumberSelector;
+ TQVGroupBox *daysSliderBox;
+ TQLabel *dayNumberLabel;
+ TQSlider *dayNumberSelector;
+ TQTabWidget *mealTabs;
+ MealInput *mealTab; // points to the current tab
+ TQPushButton *okButton;
+
+ //Methods
+ bool checkCategories( Recipe &rec, int meal, int dish );
+ bool checkConstraints( Recipe &rec, int meal, int dish );
+ bool checkLimits( IngredientPropertyList &properties, ConstraintList &constraints );
+ void loadConstraints( int meal, int dish, ConstraintList *constraints ) const;
+ void loadEnabledCategories( int meal, int dish, ElementList *categories );
+ void newTab( const TQString &name );
+ bool categoryFiltering( int meal, int dish ) const;
+ int getNecessaryFlags() const;
+
+public:
+ //Methods
+ void reload( ReloadFlags flags = Load );
+ RecipeList& dietList( void );
+
+private slots:
+ void changeDayNumber( int dn );
+ void changeMealNumber( int mn );
+ void createDiet( void );
+ void clear();
+ void createShoppingList( void );
+ void populateIteratorList( RecipeList &rl, TQValueList <RecipeList::Iterator> *il );
+signals:
+ void dietReady( void );
+};
+
+class MealInput: public TQWidget
+{
+ TQ_OBJECT
+
+public:
+ // Methods
+
+ MealInput( TQWidget *parent, RecipeDB *database );
+ ~MealInput();
+ void reload( ReloadFlags flag = Load );
+ int dishNo( void )
+ {
+ return dishNumber;
+ };
+ void setDishNo( int dn );
+ void showDish( int dn );
+
+ // Public widgets and variables
+ TQValueList <DishInput*> dishInputList; // The list of dishes
+
+private:
+ // Widgets
+ // Private Variables
+ int dishNumber;
+ RecipeDB *database;
+
+ // Settings section for the meal
+ TQHBox *mealOptions;
+
+ // Dish number setting
+ TQHBox *dishNumberBox;
+ TQLabel *dishNumberLabel;
+ TQSpinBox *dishNumberInput;
+
+ // Move <-> buttons
+ TQHGroupBox *toolBar;
+ TQToolButton *buttonNext;
+ TQToolButton *buttonPrev;
+
+ // Settings for the dish
+ TQWidgetStack *dishStack;
+
+public slots:
+ void nextDish( void );
+ void prevDish( void );
+
+private slots:
+ void changeDishNumber( int dn );
+
+};
+
+class DishInput: public TQWidget
+{
+ TQ_OBJECT
+
+public:
+ DishInput( TQWidget *parent, RecipeDB *database, const TQString &title );
+ ~DishInput();
+ // Methods
+ bool isCategoryFilteringEnabled( void ) const;
+ void loadConstraints( ConstraintList *constraints ) const;
+ void loadEnabledCategories( ElementList* categories );
+ void reload( ReloadFlags flag = Load );
+ void setDishTitle( const TQString & text );
+ void clear();
+
+
+private:
+ // Variables
+ bool categoryFiltering;
+ // Widgets
+ TQHGroupBox *listBox;
+ DishTitle *dishTitle;
+ TQVBox *categoriesBox;
+ TQCheckBox *categoriesEnabledBox;
+ CategoryCheckListView *categoriesView;
+ PropertyConstraintListView *constraintsView;
+ KDoubleNumInput *constraintsEditBox1;
+ KDoubleNumInput *constraintsEditBox2;
+ RecipeDB *database;
+
+private slots:
+ void enableCategories( bool enable );
+ void insertConstraintsEditBoxes( TQListViewItem* it );
+ void hideConstraintInputs();
+ void setMinValue( double minValue );
+ void setMaxValue( double maxValue );
+};
+
+class DishTitle: public TQWidget
+{
+
+ TQ_OBJECT
+
+public:
+ DishTitle( TQWidget *parent, const TQString &title );
+ ~DishTitle();
+ virtual TQSize sizeHint () const;
+ virtual TQSize minimumSizeHint() const;
+protected:
+ //Variables
+ TQString titleText;
+ //Methods
+ virtual void paintEvent( TQPaintEvent *p );
+};
+
+#endif
diff --git a/src/dialogs/editratingdialog.cpp b/src/dialogs/editratingdialog.cpp
new file mode 100644
index 0000000..bab6e1b
--- /dev/null
+++ b/src/dialogs/editratingdialog.cpp
@@ -0,0 +1,243 @@
+/***************************************************************************
+* Copyright (C) 2005 by 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 "editratingdialog.h"
+
+#include <tdelocale.h>
+
+#include <tqvariant.h>
+#include <tqpushbutton.h>
+#include <tqlabel.h>
+#include <tqcombobox.h>
+#include <knuminput.h>
+#include <tqheader.h>
+#include <tdelistview.h>
+#include <tqtextedit.h>
+#include <tqlineedit.h>
+#include <tqlayout.h>
+#include <tqtooltip.h>
+#include <tqwhatsthis.h>
+#include <tqpainter.h>
+#include <tqvbox.h>
+
+#include <tdepopupmenu.h>
+#include <tdelocale.h>
+#include <kiconloader.h>
+#include <kdebug.h>
+
+#include "datablocks/rating.h"
+#include "datablocks/elementlist.h"
+#include "datablocks/mixednumber.h"
+
+#include "widgets/ratingwidget.h"
+
+class RatingCriteriaListView : public TDEListView
+{
+public:
+ RatingCriteriaListView( TQWidget *parent = 0, const char *name = 0 ) : TDEListView(parent,name){}
+
+ void rename( TQListViewItem *it, int c )
+ {
+ if ( c == 1 )
+ it->setPixmap(c,TQPixmap());
+
+ TDEListView::rename(it,c);
+ }
+};
+
+
+EditRatingDialog::EditRatingDialog( const ElementList &criteriaList, const Rating &rating, TQWidget* parent, const char* name )
+ : KDialogBase( parent, name, true, i18n( "Rating" ),
+ KDialogBase::Ok | KDialogBase::Cancel, KDialogBase::Ok )
+{
+ init(criteriaList);
+ loadRating(rating);
+}
+
+/*
+ * Constructs a EditRatingDialog as a child of 'parent', with the
+ * name 'name' and widget flags set to 'f'.
+ */
+EditRatingDialog::EditRatingDialog( const ElementList &criteriaList, TQWidget* parent, const char* name )
+ : KDialogBase( parent, name, true, i18n( "Rating" ),
+ KDialogBase::Ok | KDialogBase::Cancel, KDialogBase::Ok )
+{
+ init(criteriaList);
+}
+
+void EditRatingDialog::init( const ElementList &criteriaList )
+{
+ TQVBox *page = makeVBoxMainWidget();
+
+ layout2 = new TQHBox( page );
+
+ raterLabel = new TQLabel( layout2, "raterLabel" );
+ raterEdit = new TQLineEdit( layout2, "raterEdit" );
+
+ layout8 = new TQHBox( page );
+
+ criteriaLabel = new TQLabel( layout8, "criteriaLabel" );
+
+ criteriaComboBox = new TQComboBox( FALSE, layout8, "criteriaComboBox" );
+ criteriaComboBox->setSizePolicy( TQSizePolicy( TQSizePolicy::MinimumExpanding, (TQSizePolicy::SizeType)0, 0, 0, criteriaComboBox->sizePolicy().hasHeightForWidth() ) );
+ criteriaComboBox->setEditable( TRUE );
+ criteriaComboBox->lineEdit()->disconnect( criteriaComboBox ); //so hitting enter doesn't enter the item into the box
+
+ starsLabel = new TQLabel( layout8, "starsLabel" );
+
+ starsWidget = new RatingWidget( 5, layout8, "starsWidget" );
+
+ addButton = new TQPushButton( layout8, "addButton" );
+
+ removeButton = new TQPushButton( layout8, "removeButton" );
+
+ criteriaListView = new RatingCriteriaListView( page, "criteriaListView" );
+ criteriaListView->addColumn( i18n( "Criteria" ) );
+ criteriaListView->addColumn( i18n( "Stars" ) );
+ criteriaListView->setSizePolicy( TQSizePolicy( (TQSizePolicy::SizeType)7, (TQSizePolicy::SizeType)7, 0, 0, criteriaListView->sizePolicy().hasHeightForWidth() ) );
+ criteriaListView->setSorting(-1);
+ criteriaListView->setItemsRenameable( true );
+ criteriaListView->setRenameable( 0, true );
+ criteriaListView->setRenameable( 1, true );
+
+ commentsLabel = new TQLabel( page, "commentsLabel" );
+
+ commentsEdit = new TQTextEdit( page, "commentsEdit" );
+
+ languageChange();
+ resize( TQSize(358, 331).expandedTo(minimumSizeHint()) );
+ clearWState( WState_Polished );
+
+ connect( criteriaListView, TQ_SIGNAL(itemRenamed(TQListViewItem*,const TQString &,int)), this, TQ_SLOT(itemRenamed(TQListViewItem*,const TQString &,int)) );
+ connect( addButton, TQ_SIGNAL(clicked()), this, TQ_SLOT(slotAddRatingCriteria()) );
+ connect( removeButton, TQ_SIGNAL(clicked()), this, TQ_SLOT(slotRemoveRatingCriteria()) );
+
+ TDEIconLoader il;
+ TDEPopupMenu *kpop = new TDEPopupMenu( criteriaListView );
+ kpop->insertItem( il.loadIcon( "editshred", TDEIcon::NoGroup, 16 ), i18n( "&Delete" ), this, TQ_SLOT( slotRemoveRatingCriteria() ), Key_Delete );
+
+ for ( ElementList::const_iterator criteria_it = criteriaList.begin(); criteria_it != criteriaList.end(); ++criteria_it ) {
+ criteriaComboBox->insertItem( ( *criteria_it ).name );
+ //criteriaComboBox->completionObject()->addItem( ( *criteria_it ).name );
+ }
+
+ ratingID = -1;
+}
+
+/*
+ * Destroys the object and frees any allocated resources
+ */
+EditRatingDialog::~EditRatingDialog()
+{
+ // no need to delete child widgets, TQt does it all for us
+}
+
+/*
+ * Sets the strings of the subwidgets using the current
+ * language.
+ */
+void EditRatingDialog::languageChange()
+{
+ criteriaLabel->setText( i18n( "Criteria:" ) );
+ starsLabel->setText( i18n( "Stars:" ) );
+ addButton->setText( i18n( "Add" ) );
+ removeButton->setText( i18n( "&Delete" ) );
+ criteriaListView->header()->setLabel( 0, i18n( "Criteria" ) );
+ criteriaListView->header()->setLabel( 1, i18n( "Stars" ) );
+ commentsLabel->setText( i18n( "Comments:" ) );
+ raterLabel->setText( i18n( "Rater:" ) );
+}
+
+void EditRatingDialog::itemRenamed(TQListViewItem* it, const TQString &, int c)
+{
+ if ( c == 1 ) {
+ bool ok = false;
+ MixedNumber stars_mn = MixedNumber::fromString(it->text(c),&ok);
+ if ( ok && !it->text(c).isEmpty() ) {
+ double stars = TQMAX(0,TQMIN(stars_mn.toDouble(),5)); //force to between 0 and 5
+ TQPixmap starsPic = Rating::starsPixmap( stars );
+ it->setPixmap(c,starsPic);
+ it->setText(2,TQString::number(stars));
+ }
+ else {
+ double stars = it->text(2).toDouble(); //col 2 holds the old value, which we'll set it back to
+ TQPixmap starsPic = Rating::starsPixmap( stars );
+ it->setPixmap(c,starsPic);
+ }
+
+ it->setText(c,TQString::null);
+ }
+}
+
+Rating EditRatingDialog::rating() const
+{
+ Rating r;
+
+ for ( TQListViewItem *it = criteriaListView->firstChild(); it; it = it->nextSibling() ) {
+ RatingCriteria rc;
+ rc.name = it->text(0);
+ rc.stars = it->text(2).toDouble();
+ r.append( rc );
+ }
+
+ r.comment = commentsEdit->text();
+ r.rater = raterEdit->text();
+
+ r.id = ratingID;
+
+ return r;
+}
+
+void EditRatingDialog::loadRating( const Rating &rating )
+{
+ for ( RatingCriteriaList::const_iterator rc_it = rating.ratingCriteriaList.begin(); rc_it != rating.ratingCriteriaList.end(); ++rc_it ) {
+ addRatingCriteria(*rc_it);
+ }
+
+ raterEdit->setText(rating.rater);
+ commentsEdit->setText(rating.comment);
+
+ ratingID = rating.id;
+}
+
+void EditRatingDialog::slotAddRatingCriteria()
+{
+ RatingCriteria r;
+ r.name = criteriaComboBox->lineEdit()->text().stripWhiteSpace();
+ if ( r.name.isEmpty() )
+ return;
+
+ r.stars = starsWidget->text().toDouble();
+
+ addRatingCriteria(r);
+
+ criteriaComboBox->lineEdit()->clear();
+ starsWidget->clear();
+
+ criteriaComboBox->lineEdit()->setFocus();
+}
+
+void EditRatingDialog::addRatingCriteria( const RatingCriteria &rc )
+{
+ TQListViewItem * it = new TQListViewItem(criteriaListView,rc.name);
+
+ TQPixmap stars = Rating::starsPixmap(rc.stars);
+ if ( !stars.isNull() ) //there aren't zero stars
+ it->setPixmap(1,stars);
+
+ it->setText(2,TQString::number(rc.stars));
+}
+
+void EditRatingDialog::slotRemoveRatingCriteria()
+{
+ delete criteriaListView->selectedItem();
+}
+
+#include "editratingdialog.moc"
diff --git a/src/dialogs/editratingdialog.h b/src/dialogs/editratingdialog.h
new file mode 100644
index 0000000..6996fb0
--- /dev/null
+++ b/src/dialogs/editratingdialog.h
@@ -0,0 +1,77 @@
+/***************************************************************************
+* Copyright (C) 2005 by 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. *
+***************************************************************************/
+
+#ifndef EDITRATINGDIALOG_H
+#define EDITRATINGDIALOG_H
+
+#include <kdialogbase.h>
+
+class TQVBoxLayout;
+class TQHBoxLayout;
+class TQGridLayout;
+class TQSpacerItem;
+class TQLabel;
+class TQComboBox;
+class KDoubleSpinBox;
+class TQPushButton;
+class TDEListView;
+class TQListViewItem;
+class TQTextEdit;
+class TQLineEdit;
+class RatingWidget;
+
+class Rating;
+class RatingCriteria;
+class ElementList;
+class RatingCriteriaListView;
+
+class EditRatingDialog : public KDialogBase
+{
+TQ_OBJECT
+
+public:
+ EditRatingDialog( const ElementList &criteriaList, const Rating &, TQWidget* parent = 0, const char* name = 0 );
+ EditRatingDialog( const ElementList &criteriaList, TQWidget* parent = 0, const char* name = 0 );
+ ~EditRatingDialog();
+
+ TQLabel* criteriaLabel;
+ TQComboBox* criteriaComboBox;
+ TQLabel* starsLabel;
+ RatingWidget *starsWidget;
+ TQPushButton* addButton;
+ TQPushButton* removeButton;
+ RatingCriteriaListView* criteriaListView;
+ TQLabel* commentsLabel;
+ TQTextEdit* commentsEdit;
+ TQLabel* raterLabel;
+ TQLineEdit* raterEdit;
+
+ Rating rating() const;
+
+protected:
+ TQHBox* layout8;
+ TQHBox* layout2;
+
+protected slots:
+ virtual void languageChange();
+ void slotAddRatingCriteria();
+ void slotRemoveRatingCriteria();
+ void itemRenamed(TQListViewItem* it, const TQString &, int c);
+
+private:
+ void init(const ElementList &criteriaList);
+
+ void loadRating( const Rating & );
+ void addRatingCriteria( const RatingCriteria &rc );
+
+ int ratingID;
+};
+
+#endif // EDITRATINGDIALOG_H
diff --git a/src/dialogs/ingredientgroupsdialog.cpp b/src/dialogs/ingredientgroupsdialog.cpp
new file mode 100644
index 0000000..dcfae3d
--- /dev/null
+++ b/src/dialogs/ingredientgroupsdialog.cpp
@@ -0,0 +1,65 @@
+/***************************************************************************
+* Copyright (C) 2005 by *
+* 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 "ingredientgroupsdialog.h"
+
+#include <tqpushbutton.h>
+#include <tqlayout.h>
+#include <tqvbox.h>
+
+#include <tdelocale.h>
+#include <kdialog.h>
+
+#include "widgets/krelistview.h"
+#include "widgets/headerlistview.h"
+
+IngredientGroupsDialog::IngredientGroupsDialog( RecipeDB *db, TQWidget *parent, const char *name ) : TQWidget(parent,name), database(db)
+{
+ TQHBoxLayout* layout = new TQHBoxLayout( this, KDialog::marginHint(), KDialog::spacingHint() );
+
+ headerListView = new KreListView ( this, i18n( "Header list" ), true, 0 );
+ StdHeaderListView *list_view = new StdHeaderListView( headerListView, database, true );
+ headerListView->setListView( list_view );
+ headerListView->setSizePolicy( TQSizePolicy( TQSizePolicy::Ignored, TQSizePolicy::MinimumExpanding ) );
+ layout->addWidget(headerListView);
+
+ TQVBoxLayout *buttonLayout = new TQVBoxLayout(NULL, 0, KDialog::spacingHint());
+ TQPushButton *addHeaderButton = new TQPushButton( this );
+ addHeaderButton->setText( "+" );
+ addHeaderButton->setMinimumSize( TQSize( 30, 30 ) );
+ addHeaderButton->setMaximumSize( TQSize( 30, 30 ) );
+ addHeaderButton->setSizePolicy( TQSizePolicy( TQSizePolicy::Fixed, TQSizePolicy::Fixed ) );
+ addHeaderButton->setFlat( true );
+ buttonLayout->addWidget(addHeaderButton);
+
+ TQSpacerItem* spacer_buttons = new TQSpacerItem( 10, 10, TQSizePolicy::Fixed, TQSizePolicy::Fixed );
+ buttonLayout->addItem( spacer_buttons );
+
+ TQPushButton *removeHeaderButton = new TQPushButton( this );
+ removeHeaderButton->setText( "-" );
+ removeHeaderButton->setMinimumSize( TQSize( 30, 30 ) );
+ removeHeaderButton->setMaximumSize( TQSize( 30, 30 ) );
+ removeHeaderButton->setSizePolicy( TQSizePolicy( TQSizePolicy::Fixed, TQSizePolicy::Fixed ) );
+ removeHeaderButton->setFlat( true );
+ buttonLayout->addWidget(removeHeaderButton);
+
+ TQSpacerItem* spacer_below_buttons = new TQSpacerItem( 10, 10, TQSizePolicy::Fixed, TQSizePolicy::MinimumExpanding );
+ buttonLayout->addItem( spacer_below_buttons );
+
+ layout->addLayout(buttonLayout);
+
+ connect( addHeaderButton, TQ_SIGNAL( clicked() ), list_view, TQ_SLOT( createNew() ) );
+ connect( removeHeaderButton, TQ_SIGNAL( clicked() ), list_view, TQ_SLOT( remove() ) );
+}
+
+void IngredientGroupsDialog::reload( ReloadFlags flag )
+{
+ ( ( StdHeaderListView* ) headerListView->listView() ) ->reload(flag);
+}
diff --git a/src/dialogs/ingredientgroupsdialog.h b/src/dialogs/ingredientgroupsdialog.h
new file mode 100644
index 0000000..2b8f585
--- /dev/null
+++ b/src/dialogs/ingredientgroupsdialog.h
@@ -0,0 +1,33 @@
+/***************************************************************************
+* Copyright (C) 2005 by *
+* 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. *
+***************************************************************************/
+
+#ifndef INGREDIENTGROUPSDIALOG_H
+#define INGREDIENTGROUPSDIALOG_H
+
+#include <tqwidget.h>
+
+#include "widgets/dblistviewbase.h"
+
+class KreListView;
+class RecipeDB;
+
+class IngredientGroupsDialog : public TQWidget
+{
+public:
+ IngredientGroupsDialog( RecipeDB *db, TQWidget *parent, const char *name );
+
+ void reload( ReloadFlags flag = Load );
+
+private:
+ KreListView *headerListView;
+ RecipeDB *database;
+};
+
+#endif
diff --git a/src/dialogs/ingredientmatcherdialog.cpp b/src/dialogs/ingredientmatcherdialog.cpp
new file mode 100644
index 0000000..b994ec8
--- /dev/null
+++ b/src/dialogs/ingredientmatcherdialog.cpp
@@ -0,0 +1,353 @@
+/***************************************************************************
+* Copyright (C) 2003 by *
+* Unai Garro (ugarro@users.sourceforge.net) *
+* *
+* 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 "ingredientmatcherdialog.h"
+
+#include "datablocks/recipelist.h"
+#include "widgets/ingredientlistview.h"
+#include "datablocks/elementlist.h"
+#include "backends/recipedb.h"
+#include "widgets/krelistview.h"
+#include "widgets/unitcombobox.h"
+#include "widgets/fractioninput.h"
+#include "widgets/amountunitinput.h"
+#include "datablocks/mixednumber.h"
+#include "recipeactionshandler.h"
+
+#include <tqheader.h>
+#include <tqpainter.h>
+#include <tqstringlist.h>
+#include <tqlayout.h>
+#include <tqgroupbox.h>
+
+#include <tdeapplication.h>
+#include <kcursor.h>
+#include <kiconloader.h>
+#include <tdelocale.h>
+#include <knuminput.h>
+#include <tdeconfig.h>
+#include <tdeglobal.h>
+#include <kdebug.h>
+#include <kdialogbase.h>
+
+#include "profiling.h"
+
+IngredientMatcherDialog::IngredientMatcherDialog( TQWidget *parent, RecipeDB *db ) : TQWidget( parent )
+{
+ // Initialize internal variables
+ database = db;
+
+ //Design the dialog
+
+ TQVBoxLayout *dialogLayout = new TQVBoxLayout( this, 11, 6 );
+
+ // Ingredient list
+ TQHBoxLayout *layout2 = new TQHBoxLayout( 0, 0, 6, "layout2" );
+
+ allIngListView = new KreListView( this, TQString::null, true, 0 );
+ StdIngredientListView *list_view = new StdIngredientListView(allIngListView,database);
+ list_view->setSelectionMode( TQListView::Multi );
+ allIngListView->setListView(list_view);
+ layout2->addWidget( allIngListView );
+
+ TQVBoxLayout *layout1 = new TQVBoxLayout( 0, 0, 6, "layout1" );
+
+ TDEIconLoader il;
+
+ addButton = new TQPushButton( this, "addButton" );
+ addButton->setIconSet( il.loadIconSet( "forward", TDEIcon::Small ) );
+ addButton->setFixedSize( TQSize( 32, 32 ) );
+ layout1->addWidget( addButton );
+
+ removeButton = new TQPushButton( this, "removeButton" );
+ removeButton->setIconSet( il.loadIconSet( "back", TDEIcon::Small ) );
+ removeButton->setFixedSize( TQSize( 32, 32 ) );
+ layout1->addWidget( removeButton );
+ TQSpacerItem *spacer1 = new TQSpacerItem( 51, 191, TQSizePolicy::Minimum, TQSizePolicy::Expanding );
+ layout1->addItem( spacer1 );
+ layout2->addLayout( layout1 );
+
+ ingListView = new KreListView( this, TQString::null, true );
+ ingListView->listView() ->addColumn( i18n( "Ingredient (required?)" ) );
+ ingListView->listView() ->addColumn( i18n( "Amount Available" ) );
+ layout2->addWidget( ingListView );
+ dialogLayout->addLayout( layout2 );
+
+ // Box to select allowed number of missing ingredients
+ missingBox = new TQHBox( this );
+ missingNumberLabel = new TQLabel( missingBox );
+ missingNumberLabel->setText( i18n( "Missing ingredients allowed:" ) );
+ missingNumberSpinBox = new KIntSpinBox( missingBox );
+ missingNumberSpinBox->setMinValue( -1 );
+ missingNumberSpinBox->setSpecialValueText( i18n( "Any" ) );
+ dialogLayout->addWidget(missingBox);
+
+ // Found recipe list
+ recipeListView = new KreListView( this, i18n( "Matching Recipes" ), false, 1, missingBox );
+ recipeListView->listView() ->setSizePolicy( TQSizePolicy::Ignored, TQSizePolicy::Ignored );
+ recipeListView->listView() ->setAllColumnsShowFocus( true );
+
+ recipeListView->listView() ->addColumn( i18n( "Title" ) );
+
+ TDEConfig *config = TDEGlobal::config();
+ config->setGroup( "Advanced" );
+ bool show_id = config->readBoolEntry( "ShowID", false );
+ recipeListView->listView() ->addColumn( i18n( "Id" ), show_id ? -1 : 0 );
+
+ recipeListView->listView() ->addColumn( i18n( "Missing Ingredients" ) );
+
+ recipeListView->listView() ->setSorting( -1 );
+ dialogLayout->addWidget(recipeListView);
+
+ RecipeActionsHandler *actionHandler = new RecipeActionsHandler( recipeListView->listView(), database, RecipeActionsHandler::Open | RecipeActionsHandler::Edit | RecipeActionsHandler::Export );
+
+ TQHBox *buttonBox = new TQHBox( this );
+
+ okButton = new TQPushButton( buttonBox );
+ okButton->setIconSet( il.loadIconSet( "button_ok", TDEIcon::Small ) );
+ okButton->setText( i18n( "Find matching recipes" ) );
+
+ //buttonBox->layout()->addItem( new TQSpacerItem( 10,10, TQSizePolicy::MinimumExpanding, TQSizePolicy::Fixed ) );
+
+ clearButton = new TQPushButton( buttonBox );
+ clearButton->setIconSet( il.loadIconSet( "edit-clear", TDEIcon::Small ) );
+ clearButton->setText( i18n( "Clear" ) );
+ dialogLayout->addWidget(buttonBox);
+
+ // Connect signals & slots
+ connect ( okButton, TQ_SIGNAL( clicked() ), this, TQ_SLOT( findRecipes() ) );
+ connect ( clearButton, TQ_SIGNAL( clicked() ), recipeListView->listView(), TQ_SLOT( clear() ) );
+ connect ( clearButton, TQ_SIGNAL( clicked() ), this, TQ_SLOT( unselectIngredients() ) );
+ connect ( actionHandler, TQ_SIGNAL( recipeSelected( int, int ) ), TQ_SIGNAL( recipeSelected( int, int ) ) );
+ connect( addButton, TQ_SIGNAL( clicked() ), this, TQ_SLOT( addIngredient() ) );
+ connect( removeButton, TQ_SIGNAL( clicked() ), this, TQ_SLOT( removeIngredient() ) );
+ connect( ingListView->listView(), TQ_SIGNAL( doubleClicked( TQListViewItem*, const TQPoint &, int ) ), TQ_SLOT( itemRenamed( TQListViewItem*, const TQPoint &, int ) ) );
+}
+
+IngredientMatcherDialog::~IngredientMatcherDialog()
+{
+}
+
+void IngredientMatcherDialog::itemRenamed( TQListViewItem* item, const TQPoint &, int col )
+{
+ if ( col == 1 ) {
+ KDialogBase amountEditDialog(this,"IngredientMatcherAmountEdit",
+ false, i18n("Enter amount"), KDialogBase::Cancel | KDialogBase::Ok, KDialogBase::Ok);
+
+ TQGroupBox *box = new TQGroupBox( 1, Horizontal, i18n("Amount"), &amountEditDialog );
+ AmountUnitInput *amountEdit = new AmountUnitInput( box, database );
+ // Set the values from the item
+ if ( !item->text(1).isEmpty() ) {
+ amountEdit->setAmount( MixedNumber::fromString(item->text(2)) );
+ Unit u;
+ u.id = item->text(3).toInt();
+ amountEdit->setUnit( u );
+ } else {
+ amountEdit->setAmount( -1 );
+ Unit u;
+ u.id = -1;
+ amountEdit->setUnit( u );
+ }
+
+ amountEditDialog.setMainWidget(box);
+
+ if ( amountEditDialog.exec() == TQDialog::Accepted ) {
+ MixedNumber amount = amountEdit->amount();
+ Unit unit = amountEdit->unit();
+
+ if ( amount.toDouble() <= 1e-5 ) {
+ amount = -1;
+ unit.id = -1;
+
+ item->setText(1,TQString::null);
+ } else {
+ item->setText(1,amount.toString()+" "+((amount.toDouble()>1)?unit.plural:unit.name));
+ }
+
+ item->setText(2,amount.toString());
+ item->setText(3,TQString::number(unit.id));
+
+ IngredientList::iterator ing_it = m_item_ing_map[item];
+ (*ing_it).amount = amount.toDouble();
+ (*ing_it).units = unit;
+ }
+ }
+}
+
+void IngredientMatcherDialog::addIngredient()
+{
+ TQPtrList<TQListViewItem> items = allIngListView->listView()->selectedItems();
+ if ( items.count() > 0 ) {
+ TQPtrListIterator<TQListViewItem> it(items);
+ TQListViewItem *item;
+ while ( (item = it.current()) != 0 ) {
+ bool dup = false;
+ for ( TQListViewItem *exists_it = ingListView->listView()->firstChild(); exists_it; exists_it = exists_it->nextSibling() ) {
+ if ( exists_it->text( 0 ) == item->text( 0 ) ) {
+ dup = true;
+ break;
+ }
+ }
+
+ if ( !dup ) {
+ TQListViewItem * new_item = new TQCheckListItem( ingListView->listView(), item->text( 0 ), TQCheckListItem::CheckBox );
+
+ ingListView->listView() ->setSelected( new_item, true );
+ ingListView->listView() ->ensureItemVisible( new_item );
+ allIngListView->listView() ->setSelected( item, false );
+
+ m_item_ing_map.insert( new_item, m_ingredientList.append( Ingredient( item->text( 0 ), 0, Unit(), -1, item->text( 1 ).toInt() ) ) );
+ }
+ ++it;
+ }
+ }
+}
+
+void IngredientMatcherDialog::removeIngredient()
+{
+ TQListViewItem * item = ingListView->listView() ->selectedItem();
+ if ( item ) {
+ for ( IngredientList::iterator it = m_ingredientList.begin(); it != m_ingredientList.end(); ++it ) {
+ if ( *m_item_ing_map.find( item ) == it ) {
+ m_ingredientList.remove( it );
+ m_item_ing_map.remove( item );
+ break;
+ }
+ }
+ delete item;
+ }
+}
+
+void IngredientMatcherDialog::unselectIngredients()
+{
+ ingListView->listView()->clear();
+ for ( TQListViewItem *it = allIngListView->listView()->firstChild(); it; it = it->nextSibling() )
+ allIngListView->listView()->setSelected(it,false);
+}
+
+void IngredientMatcherDialog::findRecipes( void )
+{
+ TDEApplication::setOverrideCursor( KCursor::waitCursor() );
+
+ START_TIMER("Ingredient Matcher: loading database data");
+
+ RecipeList rlist;
+ database->loadRecipes( &rlist, RecipeDB::Title | RecipeDB::NamesOnly | RecipeDB::Ingredients | RecipeDB::IngredientAmounts );
+
+ END_TIMER();
+ START_TIMER("Ingredient Matcher: analyzing data for matching recipes");
+
+ // Clear the list
+ recipeListView->listView() ->clear();
+
+ // Now show the recipes with ingredients that are contained in the previous set
+ // of ingredients
+ RecipeList incompleteRecipes;
+ TQValueList <int> missingNumbers;
+ TQValueList <IngredientList> missingIngredients;
+
+ RecipeList::Iterator it;
+ for ( it = rlist.begin();it != rlist.end();++it ) {
+ IngredientList il = ( *it ).ingList;
+ if ( il.isEmpty() )
+ continue;
+
+ IngredientList missing;
+ if ( m_ingredientList.containsSubSet( il, missing, true, database ) ) {
+ new CustomRecipeListItem( recipeListView->listView(), *it );
+ }
+ else {
+ incompleteRecipes.append( *it );
+ missingIngredients.append( missing );
+ missingNumbers.append( missing.count() );
+ }
+ }
+ END_TIMER();
+
+ //Check if the user wants to show missing ingredients
+
+ if ( missingNumberSpinBox->value() == 0 ) {
+ TDEApplication::restoreOverrideCursor();
+ return ;
+ } //"None"
+
+
+
+ START_TIMER("Ingredient Matcher: searching for and displaying partial matches");
+
+ IngredientList requiredIngredients;
+ for ( TQListViewItem *it = ingListView->listView()->firstChild(); it; it = it->nextSibling() ) {
+ if ( ((TQCheckListItem*)it)->isOn() )
+ requiredIngredients << *m_item_ing_map[it];
+ }
+
+ // Classify recipes with missing ingredients in different lists by ammount
+ TQValueList<int>::Iterator nit;
+ TQValueList<IngredientList>::Iterator ilit;
+ int missingNoAllowed = missingNumberSpinBox->value();
+
+ if ( missingNoAllowed == -1 ) // "Any"
+ {
+ for ( nit = missingNumbers.begin();nit != missingNumbers.end();++nit )
+ if ( ( *nit ) > missingNoAllowed )
+ missingNoAllowed = ( *nit );
+ }
+
+
+ for ( int missingNo = 1; missingNo <= missingNoAllowed; missingNo++ ) {
+ nit = missingNumbers.begin();
+ ilit = missingIngredients.begin();
+
+ bool titleShownYet = false;
+
+ for ( it = incompleteRecipes.begin();it != incompleteRecipes.end();++it, ++nit, ++ilit ) {
+ if ( !( *it ).ingList.containsAny( m_ingredientList ) )
+ continue;
+
+ if ( !( *it ).ingList.containsSubSet( requiredIngredients ) )
+ continue;
+
+ if ( ( *nit ) == missingNo ) {
+ if ( !titleShownYet ) {
+ new SectionItem( recipeListView->listView(), i18n( "You are missing 1 ingredient for:", "You are missing %n ingredients for:", missingNo ) );
+ titleShownYet = true;
+ }
+ new CustomRecipeListItem( recipeListView->listView(), *it, *ilit );
+ }
+ }
+ }
+ END_TIMER();
+
+ TDEApplication::restoreOverrideCursor();
+}
+
+void IngredientMatcherDialog::reload( ReloadFlags flag )
+{
+ ( ( StdIngredientListView* ) allIngListView->listView() ) ->reload(flag);
+}
+
+void SectionItem::paintCell ( TQPainter * p, const TQColorGroup & /*cg*/, int column, int width, int /*align*/ )
+{
+ // Draw the section's deco
+ p->setPen( TDEGlobalSettings::activeTitleColor() );
+ p->setBrush( TDEGlobalSettings::activeTitleColor() );
+ p->drawRect( 0, 0, width, height() );
+
+ // Draw the section's text
+ if ( column == 0 ) {
+ TQFont titleFont = TDEGlobalSettings::windowTitleFont ();
+ p->setFont( titleFont );
+
+ p->setPen( TDEGlobalSettings::activeTextColor() );
+ p->drawText( 0, 0, width, height(), TQt::AlignLeft | TQt::AlignVCenter, mText );
+ }
+}
+
+#include "ingredientmatcherdialog.moc"
diff --git a/src/dialogs/ingredientmatcherdialog.h b/src/dialogs/ingredientmatcherdialog.h
new file mode 100644
index 0000000..2bd54b3
--- /dev/null
+++ b/src/dialogs/ingredientmatcherdialog.h
@@ -0,0 +1,156 @@
+/***************************************************************************
+* Copyright (C) 2003 by *
+* Unai Garro (ugarro@users.sourceforge.net) *
+* *
+* Copyright (C) 2006 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. *
+***************************************************************************/
+
+#ifndef INGREDIENTMATCHERDIALOG_H
+#define INGREDIENTMATCHERDIALOG_H
+
+#include "datablocks/element.h"
+#include "datablocks/ingredientlist.h"
+#include "datablocks/recipe.h"
+#include "widgets/recipelistview.h"
+#include "widgets/dblistviewbase.h"
+
+#include <tqfontmetrics.h>
+#include <tqlabel.h>
+#include <tqlistview.h>
+#include <tqpushbutton.h>
+#include <tqhbox.h>
+#include <tqvbox.h>
+
+#include <kstringhandler.h>
+#include <tdelocale.h>
+
+class KreListView;
+class KIntSpinBox;
+class RecipeDB;
+class MixedNumber;
+
+/**
+@author Unai Garro
+*/
+
+class CustomRecipeListItem : public RecipeListItem
+{
+public:
+ CustomRecipeListItem( TQListView* qlv, const Recipe &r, const IngredientList &il ) : RecipeListItem( qlv, r )
+ {
+ ingredientListStored = new TQStringList();
+ IngredientList::ConstIterator ili;
+ for ( ili = il.begin();ili != il.end();++ili ) {
+ if ( (*ili).substitutes.count() > 0 ) {
+ TQStringList subs;
+ subs << ( *ili ).name;
+ for ( TQValueList<IngredientData>::const_iterator it = (*ili).substitutes.begin(); it != (*ili).substitutes.end(); ++it ) {
+ subs << (*it).name;
+ }
+ ingredientListStored->append( subs.join(TQString(" %1 ").arg(i18n("OR"))) );
+ }
+ else
+ ingredientListStored->append( ( *ili ).name );
+ }
+
+ moveItem( qlv->lastItem() );
+ }
+ CustomRecipeListItem( TQListView* qlv, const Recipe &r ) : RecipeListItem( qlv, r )
+ {
+ ingredientListStored = 0;
+
+ moveItem( qlv->lastItem() );
+ }
+
+ ~CustomRecipeListItem( void )
+ {
+ delete ingredientListStored;
+ }
+
+private:
+ TQStringList *ingredientListStored;
+
+public:
+ virtual TQString text( int column ) const
+ {
+ if ( column == 2 && ingredientListStored )
+ return ingredientListStored->join ( "," );
+ else
+ return ( RecipeListItem::text( column ) );
+ }
+};
+
+class SectionItem: public TQListViewItem
+{
+public:
+ SectionItem( TQListView* qlv, TQString sectionText ) : TQListViewItem( qlv, qlv->lastItem() )
+ {
+ mText = sectionText;
+ }
+
+ ~SectionItem( void )
+ {}
+ virtual void paintCell ( TQPainter * p, const TQColorGroup & cg, int column, int width, int align );
+
+private:
+ TQString mText;
+
+public:
+ virtual TQString text( int column ) const
+ {
+ if ( column == 0 )
+ return ( mText );
+ else
+ return ( TQString::null );
+ }
+};
+class IngredientMatcherDialog: public TQWidget
+{
+
+ TQ_OBJECT
+
+public:
+
+ IngredientMatcherDialog( TQWidget *parent, RecipeDB* db );
+ ~IngredientMatcherDialog();
+ void reload( ReloadFlags flag = Load );
+
+signals:
+ void recipeSelected( int, int );
+
+private:
+ //Private variables
+ RecipeDB *database;
+
+ //Widgets
+
+ KreListView *allIngListView;
+ KreListView *ingListView;
+
+ KreListView *recipeListView;
+ TQHBox *missingBox;
+ TQLabel *missingNumberLabel;
+ KIntSpinBox *missingNumberSpinBox;
+
+ TQPushButton *okButton;
+ TQPushButton *clearButton;
+ TQPushButton *addButton;
+ TQPushButton *removeButton;
+
+ IngredientList m_ingredientList;
+ TQMap<TQListViewItem*, IngredientList::iterator> m_item_ing_map;
+
+private slots:
+ void findRecipes( void );
+ void unselectIngredients();
+ void addIngredient();
+ void removeIngredient();
+ void itemRenamed( TQListViewItem*, const TQPoint &, int col );
+};
+
+#endif
diff --git a/src/dialogs/ingredientparserdialog.cpp b/src/dialogs/ingredientparserdialog.cpp
new file mode 100644
index 0000000..0081bcf
--- /dev/null
+++ b/src/dialogs/ingredientparserdialog.cpp
@@ -0,0 +1,299 @@
+/***************************************************************************
+* Copyright (C) 2005 by *
+* 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 "ingredientparserdialog.h"
+
+#include <tqpushbutton.h>
+#include <tqtextedit.h>
+#include <tqlabel.h>
+#include <tqlineedit.h>
+#include <tqlayout.h>
+#include <tqtooltip.h>
+#include <tqwhatsthis.h>
+#include <tqheader.h>
+#include <tqapplication.h>
+#include <tqclipboard.h>
+#include <tqvbox.h>
+
+#include <tdelocale.h>
+#include <kdebug.h>
+#include <tdelistview.h>
+#include <kpushbutton.h>
+#include <tdemessagebox.h>
+#include <tdeaction.h>
+#include <tdepopupmenu.h>
+
+#include "datablocks/mixednumber.h"
+#include "widgets/inglistviewitem.h"
+
+IngredientParserDialog::IngredientParserDialog( const UnitList &units, TQWidget* parent, const char* name )
+ : KDialogBase( parent, name, true, i18n( "Ingredient Parser" ),
+ KDialogBase::Ok | KDialogBase::Cancel, KDialogBase::Ok ),
+ m_unitList(units)
+{
+ setButtonBoxOrientation( Vertical );
+
+ TQVBox *page = makeVBoxMainWidget();
+
+ textLabel1 = new TQLabel( page, "textLabel1" );
+ textLabel1->setTextFormat( TQLabel::RichText );
+
+ ingredientTextEdit = new TQTextEdit( page, "ingredientTextEdit" );
+ ingredientTextEdit->setTextFormat( TQTextEdit::PlainText );
+
+ parseButton = new KPushButton( page, "parseButton" );
+
+ previewLabel = new TQLabel( page, "previewLabel" );
+ previewLabel->setTextFormat( TQLabel::RichText );
+
+ previewIngView = new TDEListView( page, "previewIngView" );
+ previewIngView->setSorting(-1);
+ previewIngView->addColumn( i18n( "Ingredient" ) );
+ previewIngView->addColumn( i18n( "Amount" ) );
+ previewIngView->addColumn( i18n( "Unit" ) );
+ previewIngView->addColumn( i18n( "Preparation Method" ) );
+
+ languageChange();
+ setInitialSize( TQSize(577, 371).expandedTo(minimumSizeHint()) );
+
+ previewIngView->setItemsRenameable( true );
+ previewIngView->setRenameable( 0, true );
+ previewIngView->setRenameable( 1, true );
+ previewIngView->setRenameable( 2, true );
+ previewIngView->setRenameable( 3, true );
+
+ previewIngView->setSelectionMode( TQListView::Extended );
+
+ ingredientTextEdit->setText( TQApplication::clipboard()->text() );
+ ingredientTextEdit->selectAll();
+
+ TQWidget *buttonWidget = new TQWidget( page );
+ TQHBoxLayout *buttonBox = new TQHBoxLayout(buttonWidget);
+ TQSpacerItem *horizontalSpacing = new TQSpacerItem( 20, 20, TQSizePolicy::Expanding, TQSizePolicy::Minimum );
+ buttonGroup = new TQPushButton( i18n("Set &Header"), buttonWidget );
+ TQWhatsThis::add( buttonGroup, i18n("If an ingredient header is detected as an ingredient, select it and click this button so that Krecipes will recognize it as a header. All the ingredients below the header will be included within that group.\n\nAlternatively, if you select multiple ingredients and click this button, those ingredients will be grouped together.") );
+ buttonBox->addWidget( buttonGroup );
+ buttonBox->addItem( horizontalSpacing );
+
+ TDEPopupMenu *kpop = new TDEPopupMenu( previewIngView );
+ kpop->insertItem( i18n( "&Delete" ), this, TQ_SLOT( removeIngredient() ), Key_Delete );
+ kpop->insertItem( i18n("Set &Header") , this, TQ_SLOT( convertToHeader() ) );
+
+ connect( parseButton, TQ_SIGNAL(clicked()), this, TQ_SLOT(parseText()) );
+ connect( buttonGroup, TQ_SIGNAL(clicked()), this, TQ_SLOT(convertToHeader()) );
+}
+
+IngredientParserDialog::~IngredientParserDialog()
+{
+ // no need to delete child widgets, TQt does it all for us
+}
+
+void IngredientParserDialog::languageChange()
+{
+ textLabel1->setText( i18n( "To use: Paste a list of ingredient below, click \"Parse Text\", and then you may correct any incorrectly parsed ingredients.<br><b>Caution: Fields will be truncated if longer than the database allows</b>" ) );
+ previewLabel->setText( i18n("Ingredients as understood by Krecipes:") );
+ parseButton->setText( i18n( "Parse Text" ) );
+ previewIngView->header()->setLabel( 0, i18n( "Ingredient" ) );
+ previewIngView->header()->setLabel( 1, i18n( "Amount" ) );
+ previewIngView->header()->setLabel( 2, i18n( "Unit" ) );
+ previewIngView->header()->setLabel( 3, i18n( "Preparation Method" ) );
+}
+
+void IngredientParserDialog::accept()
+{
+ for ( TQListViewItem *it = previewIngView->firstChild(); it; it = it->nextSibling() ) {
+ if ( it->rtti() == INGGRPLISTVIEWITEM_RTTI ) {
+ TQString group = ((IngGrpListViewItem*)it)->group();
+ for ( IngListViewItem *sub_it = (IngListViewItem*)it->firstChild(); sub_it; sub_it = (IngListViewItem*)sub_it->nextSibling() ) {
+ Ingredient ing = sub_it->ingredient();
+ ing.group = group;
+ m_ingList.append(ing);
+ }
+ }
+ else
+ m_ingList.append(((IngListViewItem*)it)->ingredient());
+ }
+
+ TQDialog::accept();
+}
+
+void IngredientParserDialog::removeIngredient()
+{
+ delete previewIngView->selectedItem();
+ if ( !previewIngView->firstChild() )
+ enableButtonOK( false );
+}
+
+void IngredientParserDialog::convertToHeader()
+{
+ TQPtrList<TQListViewItem> items = previewIngView->selectedItems();
+ if ( items.count() == 0 )
+ return;
+ else if ( items.count() > 1 )
+ convertToHeader(items);
+ else { //items.count = 1
+ TQListViewItem *item = items.first();
+ if ( item->rtti() == INGLISTVIEWITEM_RTTI ) {
+ TQListViewItem *new_item = new IngGrpListViewItem(previewIngView,
+ (item->parent())?item->parent():item,
+ ((IngListViewItem*)item)->ingredient().name, -1);
+
+ TQListViewItem *next_sibling;
+ TQListViewItem *last_item = 0;
+ for ( TQListViewItem * it = (item->parent())?item->nextSibling():new_item->nextSibling(); it; it = next_sibling ) {
+ if ( it->rtti() == INGGRPLISTVIEWITEM_RTTI )
+ break;
+
+ next_sibling = it->nextSibling(); //get the next sibling of this item before we move it
+
+ if ( it->parent() )
+ it->parent()->takeItem(it);
+ else
+ previewIngView->takeItem( it );
+
+ new_item->insertItem( it );
+
+ if ( last_item )
+ it->moveItem( last_item );
+ last_item = it;
+ }
+
+ new_item->setOpen(true);
+
+ delete item;
+ }
+ }
+}
+
+void IngredientParserDialog::convertToHeader( const TQPtrList<TQListViewItem> &items )
+{
+ if ( items.count() > 0 ) {
+ TQPtrListIterator<TQListViewItem> it(items);
+ TQListViewItem *item = it.current();
+
+ if ( item->rtti() != INGLISTVIEWITEM_RTTI )
+ return;
+
+ TQString group = ((IngListViewItem*)item)->ingredient().name;
+ TQListViewItem *ingGroupItem = new IngGrpListViewItem(previewIngView,
+ (item->parent())?item->parent():item, group, -1);
+ delete item; //delete the ingredient header which was detected as an ingredient
+ ++it;
+
+ TQListViewItem *last_item = 0;
+ while ( (item = it.current()) != 0 ) {
+ //ignore anything that isn't an ingredient (e.g. headers)
+ if ( item->rtti() == INGLISTVIEWITEM_RTTI ) {
+ if ( item->parent() )
+ item->parent()->takeItem(item);
+ else
+ previewIngView->takeItem( item );
+
+ ingGroupItem->insertItem( item );
+
+ if ( last_item )
+ item->moveItem( last_item );
+ last_item = item;
+ }
+
+ ++it;
+ }
+
+ ingGroupItem->setOpen(true);
+ previewIngView->clearSelection();
+ }
+}
+
+void IngredientParserDialog::parseText()
+{
+ previewIngView->clear();
+
+ TQListViewItem *last_item = 0;
+
+ int line_num = 0;
+ TQStringList ingredients = TQStringList::split("\n",ingredientTextEdit->text());
+ for ( TQStringList::const_iterator it = ingredients.begin(); it != ingredients.end(); ++it ) {
+ TQString line = (*it).simplifyWhiteSpace();
+
+ ++line_num;
+ int format_at = 0;
+ Ingredient ing;
+
+
+ //======amount======//
+ int first_space = line.find( " ", format_at+1 );
+ if ( first_space == -1 )
+ first_space = line.length();
+
+ int second_space = line.find( " ", first_space+1 );
+ if ( second_space == -1 )
+ second_space = line.length();
+
+ Ingredient i;
+ bool ok;
+ i.setAmount(line.mid(format_at,second_space-format_at),&ok);
+ if ( !ok ) {
+ i.setAmount(line.mid(format_at,first_space-format_at),&ok);
+ if ( ok ) format_at = first_space+1;
+ }
+ else
+ format_at = second_space+1;
+
+ if ( ok ) {
+ ing.amount = i.amount;
+ ing.amount_offset = i.amount_offset;
+ }
+ else
+ kdDebug()<<"no amount on line "<<line_num<<endl;
+
+
+ //======unit======//
+ first_space = line.find( " ", format_at+1 );
+ if ( first_space == -1 )
+ first_space = line.length();
+
+ bool isUnit = false;
+ TQString unitCheck = line.mid(format_at,first_space-format_at);
+
+ for ( UnitList::const_iterator unit_it = m_unitList.begin(); unit_it != m_unitList.end(); ++unit_it ) {
+ if ( (*unit_it).name == unitCheck || (*unit_it).plural == unitCheck || (*unit_it).name_abbrev == unitCheck || (*unit_it).plural_abbrev == unitCheck ) {
+ isUnit = true;
+ format_at = first_space+1;
+ break;
+ }
+ }
+
+ if ( isUnit ) {
+ ing.units.name = unitCheck;
+ ing.units.plural = unitCheck;
+ }
+ else
+ kdDebug()<<"no unit on line "<<line_num<<endl;
+
+
+ //======ingredient======//
+ int ing_end = line.find( TQRegExp("(,|;)"), format_at+1 );
+ if ( ing_end == -1 )
+ ing_end = line.length();
+
+ ing.name = line.mid(format_at,ing_end-format_at);
+ format_at = ing_end+2;
+
+
+ //======prep method======//
+ int end = line.length();
+ ing.prepMethodList = ElementList::split(",",line.mid(format_at,end-format_at));
+
+ last_item = new IngListViewItem(previewIngView,last_item,ing);
+ enableButtonOK( true );
+ }
+}
+
+#include "ingredientparserdialog.moc"
diff --git a/src/dialogs/ingredientparserdialog.h b/src/dialogs/ingredientparserdialog.h
new file mode 100644
index 0000000..f9a6dbb
--- /dev/null
+++ b/src/dialogs/ingredientparserdialog.h
@@ -0,0 +1,65 @@
+/***************************************************************************
+* Copyright (C) 2005 by *
+* 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. *
+***************************************************************************/
+
+#ifndef INGREDIENTPARSERDIALOG_H
+#define INGREDIENTPARSERDIALOG_H
+
+#include <kdialogbase.h>
+
+#include "datablocks/ingredientlist.h"
+#include "datablocks/unit.h"
+
+class TQVBoxLayout;
+class TQHBoxLayout;
+class TQGridLayout;
+class TQSpacerItem;
+class TQLabel;
+class TQTextEdit;
+class TQLineEdit;
+class KPushButton;
+class TDEListView;
+class TQListViewItem;
+class TQPushButton;
+
+class IngredientParserDialog : public KDialogBase
+{
+ TQ_OBJECT
+
+public:
+ IngredientParserDialog( const UnitList &units, TQWidget* parent = 0, const char* name = 0 );
+ ~IngredientParserDialog();
+
+ IngredientList ingredients() const { return m_ingList; }
+
+protected:
+ TQLabel* textLabel1;
+ TQLabel *previewLabel;
+ TQTextEdit* ingredientTextEdit;
+ KPushButton* parseButton;
+ TDEListView* previewIngView;
+ TQPushButton* buttonGroup;
+
+protected slots:
+ virtual void accept();
+ void parseText();
+ void removeIngredient();
+
+ //Set Header button slot
+ virtual void convertToHeader();
+ virtual void languageChange();
+
+private:
+ void convertToHeader( const TQPtrList<TQListViewItem> &items );
+
+ UnitList m_unitList;
+ IngredientList m_ingList;
+};
+
+#endif // INGREDIENTPARSERDIALOG_H
diff --git a/src/dialogs/ingredientsdialog.cpp b/src/dialogs/ingredientsdialog.cpp
new file mode 100644
index 0000000..358e01f
--- /dev/null
+++ b/src/dialogs/ingredientsdialog.cpp
@@ -0,0 +1,702 @@
+/***************************************************************************
+* 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 "ingredientsdialog.h"
+#include "backends/recipedb.h"
+#include "createelementdialog.h"
+#include "datablocks/ingredientpropertylist.h"
+#include "datablocks/mixednumber.h"
+#include "datablocks/weight.h"
+#include "unitsdialog.h"
+#include "usdadatadialog.h"
+#include "selectpropertydialog.h"
+#include "selectunitdialog.h"
+#include "dependanciesdialog.h"
+#include "widgets/ingredientlistview.h"
+#include "widgets/weightinput.h"
+#include "dialogs/ingredientgroupsdialog.h"
+#include "dialogs/createingredientweightdialog.h"
+
+#include <tdeapplication.h>
+#include <kcursor.h>
+#include <kdebug.h>
+#include <tdelocale.h>
+#include <tdemessagebox.h>
+#include <tdeglobal.h>
+#include <tdeconfig.h>
+
+#include <tqheader.h>
+#include <tqmessagebox.h>
+#include <tqtabwidget.h>
+
+class WeightListItem : public TQListViewItem
+{
+public:
+ WeightListItem( TQListView *listview, TQListViewItem *item, const Weight &w ) : TQListViewItem(listview,item), m_weight(w){}
+
+ void setWeight( const Weight &w ) { m_weight = w; }
+ Weight weight() const { return m_weight; }
+
+ void setAmountUnit( double amount, const Unit &unit, const Element &prepMethod )
+ {
+ m_weight.perAmount = amount;
+ m_weight.perAmountUnitID = unit.id;
+ m_weight.perAmountUnit = (m_weight.perAmount>1)?unit.plural:unit.name;
+ m_weight.prepMethodID = prepMethod.id;
+ m_weight.prepMethod = prepMethod.name;
+ }
+
+ void setWeightUnit( double weight, const Unit &unit )
+ {
+ m_weight.weight = weight;
+ m_weight.weightUnitID = unit.id;
+ m_weight.weightUnit = (m_weight.weight>1)?unit.plural:unit.name;
+ }
+
+ virtual TQString text( int c ) const
+ {
+ if ( c == 0 )
+ return TQString::number(m_weight.weight)+" "+m_weight.weightUnit;
+ else if ( c == 1 )
+ return TQString::number(m_weight.perAmount)+" "
+ +m_weight.perAmountUnit
+ +((m_weight.prepMethodID!=-1)?", "+m_weight.prepMethod:TQString::null);
+ else
+ return TQString::null;
+ }
+
+private:
+ Weight m_weight;
+};
+
+IngredientsDialog::IngredientsDialog( TQWidget* parent, RecipeDB *db ) : TQWidget( parent )
+{
+
+ // Store pointer to database
+ database = db;
+
+ // Initialize internal variables
+ propertiesList = new IngredientPropertyList;
+ perUnitListBack = new ElementList;
+
+ // Design dialog
+
+ TQHBoxLayout* page_layout = new TQHBoxLayout( this, KDialog::marginHint(), KDialog::spacingHint() );
+
+ TQTabWidget *tabWidget = new TQTabWidget( this );
+
+ TQWidget *ingredientTab = new TQWidget( tabWidget );
+
+ layout = new TQGridLayout( ingredientTab, 1, 1, 0, 0 );
+ TQSpacerItem* spacer_left = new TQSpacerItem( 10, 10, TQSizePolicy::Fixed, TQSizePolicy::Minimum );
+ layout->addItem( spacer_left, 1, 0 );
+ TQSpacerItem* spacer_top = new TQSpacerItem( 10, 10, TQSizePolicy::Minimum, TQSizePolicy::Fixed );
+ layout->addItem( spacer_top, 0, 1 );
+
+ ingredientListView = new KreListView ( ingredientTab, i18n( "Ingredient list" ), true, 0 );
+ StdIngredientListView *list_view = new StdIngredientListView( ingredientListView, database, true );
+ ingredientListView->setListView( list_view );
+ layout->addMultiCellWidget ( ingredientListView, 1, 5, 1, 1 );
+ ingredientListView->setSizePolicy( TQSizePolicy( TQSizePolicy::MinimumExpanding, TQSizePolicy::MinimumExpanding ) );
+
+ TQSpacerItem* spacer_rightIngredients = new TQSpacerItem( 10, 10, TQSizePolicy::Fixed, TQSizePolicy::Minimum );
+ layout->addItem( spacer_rightIngredients, 1, 2 );
+
+
+ addIngredientButton = new TQPushButton( ingredientTab );
+ addIngredientButton->setText( "+" );
+ layout->addWidget( addIngredientButton, 1, 3 );
+ addIngredientButton->setMinimumSize( TQSize( 30, 30 ) );
+ addIngredientButton->setMaximumSize( TQSize( 30, 30 ) );
+ addIngredientButton->setSizePolicy( TQSizePolicy( TQSizePolicy::Fixed, TQSizePolicy::Fixed ) );
+ addIngredientButton->setFlat( true );
+
+ removeIngredientButton = new TQPushButton( ingredientTab );
+ removeIngredientButton->setText( "-" );
+ layout->addWidget( removeIngredientButton, 3, 3 );
+ removeIngredientButton->setMinimumSize( TQSize( 30, 30 ) );
+ removeIngredientButton->setMaximumSize( TQSize( 30, 30 ) );
+ removeIngredientButton->setSizePolicy( TQSizePolicy( TQSizePolicy::Fixed, TQSizePolicy::Fixed ) );
+ removeIngredientButton->setFlat( true );
+
+ TQSpacerItem* spacer_Ing_Buttons = new TQSpacerItem( 10, 10, TQSizePolicy::Minimum, TQSizePolicy::Fixed );
+ layout->addItem( spacer_Ing_Buttons, 2, 3 );
+
+
+ TQSpacerItem* spacer_Ing_Units = new TQSpacerItem( 30, 5, TQSizePolicy::Fixed, TQSizePolicy::Minimum );
+ layout->addItem( spacer_Ing_Units, 1, 4 );
+
+
+ TDEConfig *config = TDEGlobal::config();
+ config->setGroup( "Advanced" );
+ bool show_id = config->readBoolEntry( "ShowID", false );
+
+ TQScrollView *scrollView1 = new TQScrollView( ingredientTab, "scrollView1" );
+ scrollView1->enableClipper(true);
+ TQWidget *rightWidget = new TQWidget(scrollView1);
+ TQGridLayout *rightLayout = new TQGridLayout( rightWidget, 1, 1, 0, 0 );
+
+ unitsListView = new KreListView ( rightWidget, i18n( "Unit list" ) );
+ unitsListView->listView() ->addColumn( i18n( "Units" ) );
+ unitsListView->listView() ->addColumn( i18n( "Id" ), show_id ? -1 : 0 );
+ unitsListView->listView() ->setSorting( 0 );
+ unitsListView->listView() ->setAllColumnsShowFocus( true );
+ rightLayout->addMultiCellWidget ( unitsListView, 1, 4, 0, 0 );
+ unitsListView->listView() ->setMinimumWidth( 150 );
+ unitsListView->setSizePolicy( TQSizePolicy( TQSizePolicy::MinimumExpanding, TQSizePolicy::MinimumExpanding ) );
+
+ TQSpacerItem* spacer_rightUnits = new TQSpacerItem( 5, 5, TQSizePolicy::Fixed, TQSizePolicy::Minimum );
+ rightLayout->addItem( spacer_rightUnits, 1, 1 );
+
+ addUnitButton = new TQPushButton( rightWidget );
+ addUnitButton->setText( "+" );
+ rightLayout->addWidget( addUnitButton, 1, 2 );
+ addUnitButton->resize( TQSize( 30, 30 ) );
+ addUnitButton->setMinimumSize( TQSize( 30, 30 ) );
+ addUnitButton->setMaximumSize( TQSize( 30, 30 ) );
+ addUnitButton->setSizePolicy( TQSizePolicy( TQSizePolicy::Fixed, TQSizePolicy::Fixed ) );
+ addUnitButton->setFlat( true );
+
+ removeUnitButton = new TQPushButton( rightWidget );
+ removeUnitButton->setText( "-" );
+ rightLayout->addWidget( removeUnitButton, 3, 2 );
+ removeUnitButton->resize( TQSize( 30, 30 ) );
+ removeUnitButton->setMinimumSize( TQSize( 30, 30 ) );
+ removeUnitButton->setMaximumSize( TQSize( 30, 30 ) );
+ removeUnitButton->setSizePolicy( TQSizePolicy( TQSizePolicy::Fixed, TQSizePolicy::Fixed ) );
+ removeUnitButton->setFlat( true );
+ TQSpacerItem* spacer_Units_Properties = new TQSpacerItem( 10, 10, TQSizePolicy::Minimum, TQSizePolicy::Fixed );
+ rightLayout->addItem( spacer_Units_Properties, 2, 2 );
+
+
+ propertiesListView = new KreListView ( rightWidget, i18n( "Ingredient Properties" ) );
+ rightLayout->addMultiCellWidget ( propertiesListView, 6, 9, 0, 0 );
+
+ propertiesListView->listView() ->addColumn( i18n( "Property" ) );
+ propertiesListView->listView() ->addColumn( i18n( "Amount" ) );
+ propertiesListView->listView() ->addColumn( i18n( "Units" ) );
+ propertiesListView->listView() ->addColumn( i18n( "Id" ), show_id ? -1 : 0 );
+ propertiesListView->listView() ->setAllColumnsShowFocus( true );
+ propertiesListView->listView() ->setSizePolicy( TQSizePolicy( TQSizePolicy::MinimumExpanding, TQSizePolicy::MinimumExpanding ) );
+ propertiesListView->listView() ->setSorting( -1 ); // Disable sorting. For the moment, the order is important to identify the per_units ID corresponding to this row. So the user shouldn't change this order.
+
+ addPropertyButton = new TQPushButton( rightWidget );
+ addPropertyButton->setText( "+" );
+ rightLayout->addWidget( addPropertyButton, 6, 2 );
+ addPropertyButton->resize( TQSize( 30, 30 ) );
+ addPropertyButton->setMinimumSize( TQSize( 30, 30 ) );
+ addPropertyButton->setMaximumSize( TQSize( 30, 30 ) );
+ addPropertyButton->setSizePolicy( TQSizePolicy( TQSizePolicy::Fixed, TQSizePolicy::Fixed ) );
+ addPropertyButton->setFlat( true );
+
+ removePropertyButton = new TQPushButton( rightWidget );
+ removePropertyButton->setText( "-" );
+ rightLayout->addWidget( removePropertyButton, 8, 2 );
+ removePropertyButton->resize( TQSize( 30, 30 ) );
+ removePropertyButton->setMinimumSize( TQSize( 30, 30 ) );
+ removePropertyButton->setMaximumSize( TQSize( 30, 30 ) );
+ removePropertyButton->setSizePolicy( TQSizePolicy( TQSizePolicy::Fixed, TQSizePolicy::Fixed ) );
+ removePropertyButton->setFlat( true );
+
+ TQSpacerItem* spacer_Prop_Buttons = new TQSpacerItem( 9, 10, TQSizePolicy::Minimum, TQSizePolicy::Fixed );
+ rightLayout->addItem( spacer_Prop_Buttons, 7, 2 );
+
+ weightsListView = new KreListView ( rightWidget, i18n( "Ingredient Weights" ) );
+ weightsListView->listView() ->addColumn( i18n( "Weight" ) );
+ weightsListView->listView() ->addColumn( i18n( "Per Amount" ) );
+ weightsListView->listView() ->setAllColumnsShowFocus( true );
+ rightLayout->addMultiCellWidget ( weightsListView, 10, 14, 0, 0 );
+ weightsListView->listView() ->setMinimumWidth( 150 );
+ weightsListView->setSizePolicy( TQSizePolicy( TQSizePolicy::MinimumExpanding, TQSizePolicy::MinimumExpanding ) );
+
+ //TQSpacerItem* spacer_rightWeights = new TQSpacerItem( 5, 5, TQSizePolicy::Fixed, TQSizePolicy::Minimum );
+ //layout->addItem( spacer_rightWeights, 1, 6 );
+
+ addWeightButton = new TQPushButton( rightWidget );
+ addWeightButton->setText( "+" );
+ rightLayout->addWidget( addWeightButton, 10, 2 );
+ addWeightButton->resize( TQSize( 30, 30 ) );
+ addWeightButton->setMinimumSize( TQSize( 30, 30 ) );
+ addWeightButton->setMaximumSize( TQSize( 30, 30 ) );
+ addWeightButton->setSizePolicy( TQSizePolicy( TQSizePolicy::Fixed, TQSizePolicy::Fixed ) );
+ addWeightButton->setFlat( true );
+
+ removeWeightButton = new TQPushButton( rightWidget );
+ removeWeightButton->setText( "-" );
+ rightLayout->addWidget( removeWeightButton, 12, 2 );
+ removeWeightButton->resize( TQSize( 30, 30 ) );
+ removeWeightButton->setMinimumSize( TQSize( 30, 30 ) );
+ removeWeightButton->setMaximumSize( TQSize( 30, 30 ) );
+ removeWeightButton->setSizePolicy( TQSizePolicy( TQSizePolicy::Fixed, TQSizePolicy::Fixed ) );
+ removeWeightButton->setFlat( true );
+
+ TQSpacerItem* spacer_Weight_Properties = new TQSpacerItem( 10, 10, TQSizePolicy::Minimum, TQSizePolicy::Fixed );
+ rightLayout->addItem( spacer_Weight_Properties, 11, 2 );
+
+ TQSpacerItem* spacerBottom = new TQSpacerItem( 10, 10, TQSizePolicy::Fixed, TQSizePolicy::Expanding );
+ rightLayout->addItem( spacerBottom, 13, 2 );
+
+ scrollView1->setResizePolicy( TQScrollView::AutoOneFit );
+ layout->addMultiCellWidget(scrollView1,1,4,5,5);
+
+ TQPushButton *loadUsdaButton = new TQPushButton( ingredientTab );
+ loadUsdaButton->setText( i18n( "Load USDA data" ) );
+ loadUsdaButton->setFlat( true );
+ layout->addWidget(loadUsdaButton,5,5);
+
+ scrollView1->addChild(rightWidget);
+ scrollView1->setSizePolicy( TQSizePolicy::MinimumExpanding, TQSizePolicy::Ignored );
+
+
+ inputBox = new KDoubleNumInput( propertiesListView->listView() ->viewport() );
+ propertiesListView->listView() ->addChild( inputBox );
+ inputBox->hide();
+
+ tabWidget->insertTab( ingredientTab, i18n( "Ingredients" ) );
+
+ groupsDialog = new IngredientGroupsDialog(database,tabWidget,"groupsDialog");
+ tabWidget->insertTab( groupsDialog, i18n( "Headers" ) );
+
+ page_layout->addWidget( tabWidget );
+
+ // Initialize
+ unitList = new UnitList;
+
+ // Signals & Slots
+ connect( ingredientListView->listView(), TQ_SIGNAL( selectionChanged() ), this, TQ_SLOT( updateLists() ) );
+ connect( addIngredientButton, TQ_SIGNAL( clicked() ), list_view, TQ_SLOT( createNew() ) );
+ connect( addUnitButton, TQ_SIGNAL( clicked() ), this, TQ_SLOT( addUnitToIngredient() ) );
+ connect( removeUnitButton, TQ_SIGNAL( clicked() ), this, TQ_SLOT( removeUnitFromIngredient() ) );
+ connect( addWeightButton, TQ_SIGNAL( clicked() ), this, TQ_SLOT( addWeight() ) );
+ connect( removeWeightButton, TQ_SIGNAL( clicked() ), this, TQ_SLOT( removeWeight() ) );
+ connect( removeIngredientButton, TQ_SIGNAL( clicked() ), list_view, TQ_SLOT( remove
+ () ) );
+ connect( addPropertyButton, TQ_SIGNAL( clicked() ), this, TQ_SLOT( addPropertyToIngredient() ) );
+ connect( removePropertyButton, TQ_SIGNAL( clicked() ), this, TQ_SLOT( removePropertyFromIngredient() ) );
+ connect( propertiesListView->listView(), TQ_SIGNAL( executed( TQListViewItem* ) ), this, TQ_SLOT( insertPropertyEditBox( TQListViewItem* ) ) );
+ connect( propertiesListView->listView(), TQ_SIGNAL( selectionChanged() ), inputBox, TQ_SLOT( hide() ) );
+ connect( inputBox, TQ_SIGNAL( valueChanged( double ) ), this, TQ_SLOT( setPropertyAmount( double ) ) );
+
+ connect( weightsListView->listView(), TQ_SIGNAL( doubleClicked( TQListViewItem*, const TQPoint &, int ) ), TQ_SLOT( itemRenamed( TQListViewItem*, const TQPoint &, int ) ) );
+
+ connect( loadUsdaButton, TQ_SIGNAL( clicked() ), this, TQ_SLOT( openUSDADialog() ) );
+}
+
+
+IngredientsDialog::~IngredientsDialog()
+{
+ delete unitList;
+ delete perUnitListBack;
+ delete propertiesList;
+}
+
+void IngredientsDialog::reloadIngredientList( ReloadFlags flag )
+{
+ ( ( StdIngredientListView* ) ingredientListView->listView() ) ->reload(flag);
+
+ // Reload Unit List
+ updateLists();
+
+}
+
+void IngredientsDialog::reloadUnitList()
+{
+
+ int ingredientID = -1;
+ // Find selected ingredient
+ TQListViewItem *it;
+ it = ingredientListView->listView() ->selectedItem();
+
+ if ( it ) { // Check if an ingredient is selected first
+ ingredientID = it->text( 1 ).toInt();
+ }
+
+
+ unitList->clear();
+ unitsListView->listView() ->clear();
+
+ if ( ingredientID >= 0 ) {
+ database->loadPossibleUnits( ingredientID, unitList );
+
+ //Populate this data into the TDEListView
+
+ for ( UnitList::const_iterator unit_it = unitList->begin(); unit_it != unitList->end(); ++unit_it ) {
+ if ( !( *unit_it ).name.isEmpty() ) {
+ ( void ) new TQListViewItem( unitsListView->listView(), ( *unit_it ).name, TQString::number( ( *unit_it ).id ) );
+ }
+ }
+
+ // Select the first unit
+ unitsListView->listView() ->setSelected( unitsListView->listView() ->firstChild(), true );
+
+ }
+}
+
+void IngredientsDialog::addWeight()
+{
+ TQListViewItem *it = ingredientListView->listView()->selectedItem();
+ if ( it ) {
+ CreateIngredientWeightDialog weightDialog( this, database );
+ if ( weightDialog.exec() == TQDialog::Accepted ) {
+ Weight w = weightDialog.weight();
+ w.ingredientID = it->text( 1 ).toInt();
+ database->addIngredientWeight( w );
+
+ TQListViewItem * lastElement = weightsListView->listView()->lastItem();
+
+ WeightListItem *weight_it = new WeightListItem( weightsListView->listView(), lastElement, w );
+ weight_it->setAmountUnit( w.perAmount, database->unitName(w.perAmountUnitID),
+ Element(w.prepMethod,w.prepMethodID)
+ );
+ weight_it->setWeightUnit( w.weight, database->unitName(w.weightUnitID) );
+ }
+ }
+}
+
+void IngredientsDialog::removeWeight()
+{
+ TQListViewItem *it = weightsListView->listView() ->selectedItem();
+ if ( it ) {
+ switch ( KMessageBox::warningContinueCancel(this, i18n("Recipes may require this information for nutrient analysis. Are you sure you want to delete this entry?"), TQString::null, KStdGuiItem::cont(), "DeleteIngredientWeight") ) {
+ case KMessageBox::Continue:
+ database->removeIngredientWeight( ((WeightListItem*)it)->weight().id );
+ delete it;
+ break;
+ default: break;
+ }
+ }
+}
+
+void IngredientsDialog::itemRenamed( TQListViewItem* item, const TQPoint &, int col )
+{
+ WeightListItem *weight_it = (WeightListItem*)item;
+ Weight w = weight_it->weight();
+
+ if ( col == 0 ) {
+ KDialogBase amountEditDialog(this,"WeightAmountEdit",
+ false, i18n("Enter amount"), KDialogBase::Cancel | KDialogBase::Ok, KDialogBase::Ok);
+
+ TQGroupBox *box = new TQGroupBox( 1, Horizontal, i18n("Amount"), &amountEditDialog );
+ AmountUnitInput *amountEdit = new AmountUnitInput( box, database, Unit::Mass, MixedNumber::DecimalFormat );
+
+ WeightListItem *it = (WeightListItem*)item;
+ Weight w = it->weight();
+
+ amountEdit->setAmount( w.weight );
+ amountEdit->setUnit( Unit(w.weightUnit,w.weightUnit,w.weightUnitID) );
+
+ amountEditDialog.setMainWidget(box);
+
+ if ( amountEditDialog.exec() == TQDialog::Accepted ) {
+ MixedNumber amount = amountEdit->amount();
+ Unit unit = amountEdit->unit();
+
+ it->setWeightUnit( amount.toDouble(), unit );
+ database->addIngredientWeight( it->weight() );
+ }
+ }
+ else if ( col == 1 ) {
+ KDialogBase amountEditDialog(this,"PerAmountEdit",
+ false, i18n("Enter amount"), KDialogBase::Cancel | KDialogBase::Ok, KDialogBase::Ok);
+
+ TQGroupBox *box = new TQGroupBox( 1, Horizontal, i18n("Amount"), &amountEditDialog );
+ WeightInput *amountEdit = new WeightInput( box, database, Unit::All, MixedNumber::DecimalFormat );
+
+ WeightListItem *it = (WeightListItem*)item;
+ Weight w = it->weight();
+
+ amountEdit->setAmount( w.perAmount );
+ amountEdit->setUnit( Unit(w.perAmountUnit,w.perAmountUnit,w.perAmountUnitID) );
+ amountEdit->setPrepMethod( Element(w.prepMethod,w.prepMethodID) );
+
+ amountEditDialog.setMainWidget(box);
+
+ if ( amountEditDialog.exec() == TQDialog::Accepted ) {
+ MixedNumber amount = amountEdit->amount();
+ Unit unit = amountEdit->unit();
+
+ it->setAmountUnit( amount.toDouble(), unit, amountEdit->prepMethod() );
+ database->addIngredientWeight( it->weight() );
+ }
+ }
+}
+
+void IngredientsDialog::addUnitToIngredient( void )
+{
+
+ // Find selected ingredient item
+ TQListViewItem * it;
+ int ingredientID = -1;
+ if ( ( it = ingredientListView->listView() ->selectedItem() ) ) {
+ ingredientID = it->text( 1 ).toInt();
+ }
+ if ( ingredientID >= 0 ) // an ingredient was selected previously
+ {
+ UnitList allUnits;
+ database->loadUnits( &allUnits );
+
+ SelectUnitDialog unitsDialog( this, allUnits, SelectUnitDialog::HideEmptyUnit );
+
+ if ( unitsDialog.exec() == TQDialog::Accepted )
+ {
+ int unitID = unitsDialog.unitID();
+
+ if ( !( database->ingredientContainsUnit( ingredientID, unitID ) ) )
+ database->addUnitToIngredient( ingredientID, unitID ); // Add chosen unit to ingredient in database
+ else {
+ TQMessageBox::information( this, i18n( "Unit Exists" ), i18n( "The ingredient contains already the unit that you have chosen." ) );
+ }
+ reloadUnitList(); // Reload the list from database
+ }
+ }
+}
+
+void IngredientsDialog::removeUnitFromIngredient( void )
+{
+
+ // Find selected ingredient/unit item combination
+ TQListViewItem * it;
+ int ingredientID = -1, unitID = -1;
+ if ( ( it = ingredientListView->listView() ->selectedItem() ) )
+ ingredientID = it->text( 1 ).toInt();
+ if ( ( it = unitsListView->listView() ->selectedItem() ) )
+ unitID = it->text( 1 ).toInt();
+
+ if ( ( ingredientID >= 0 ) && ( unitID >= 0 ) ) // an ingredient/unit combination was selected previously
+ {
+ ElementList dependingRecipes, dependingPropertiesInfo;
+
+ database->findIngredientUnitDependancies( ingredientID, unitID, &dependingRecipes, &dependingPropertiesInfo );
+
+ TQValueList<ListInfo> lists;
+ if ( !dependingRecipes.isEmpty() ) {
+ ListInfo info;
+ info.list = dependingRecipes;
+ info.name = i18n("Recipes");
+ lists << info;
+ }
+ if ( !dependingPropertiesInfo.isEmpty() ) {
+ ListInfo info;
+ info.list = dependingPropertiesInfo;
+ info.name = i18n("Properties");
+ lists << info;
+ }
+
+ if ( lists.isEmpty() )
+ database->removeUnitFromIngredient( ingredientID, unitID );
+ else
+ { // must warn!
+ DependanciesDialog warnDialog( this, lists );
+ if ( !dependingRecipes.isEmpty() )
+ warnDialog.setCustomWarning( i18n("You are about to permanantly delete recipes from your database.") );
+ if ( warnDialog.exec() == TQDialog::Accepted )
+ database->removeUnitFromIngredient( ingredientID, unitID );
+ }
+ reloadUnitList(); // Reload the list from database
+ reloadPropertyList(); // Properties could have been removed if a unit is removed, so we need to reload.
+ }
+}
+
+void IngredientsDialog:: reloadPropertyList( void )
+{
+ propertiesList->clear();
+ propertiesListView->listView() ->clear();
+ perUnitListBack->clear();
+
+ inputBox->hide();
+
+
+ //If none is selected, select first item
+ TQListViewItem *it;
+ it = ingredientListView->listView() ->selectedItem();
+
+ //Populate this data into the TDEListView
+ if ( it ) { // make sure that the ingredient list is not empty
+
+ database->loadProperties( propertiesList, it->text( 1 ).toInt() ); // load the list for this ingredient
+ for ( IngredientPropertyList::const_iterator prop_it = propertiesList->begin(); prop_it != propertiesList->end(); ++prop_it ) {
+ TQListViewItem * lastElement = propertiesListView->listView() ->lastItem();
+ //Insert property after the last one (it's important to keep the order in the case of the properties to be able to identify the per_units ID later on).
+ ( void ) new TQListViewItem( propertiesListView->listView(), lastElement, (*prop_it).name, TQString::number( (*prop_it).amount ), (*prop_it).units + TQString( "/" ) + (*prop_it).perUnit.name, TQString::number( (*prop_it).id ) );
+ // Store the perUnits with the ID for using later
+ Element perUnitEl;
+ perUnitEl.id = (*prop_it).perUnit.id;
+ perUnitEl.name = (*prop_it).perUnit.name;
+ perUnitListBack->append( perUnitEl );
+
+ }
+ }
+}
+
+void IngredientsDialog::reloadWeightList( void )
+{
+ weightsListView->listView() ->clear();
+
+ //If none is selected, select first item
+ TQListViewItem *it = ingredientListView->listView() ->selectedItem();
+
+ //Populate this data into the TDEListView
+ if ( it ) { // make sure that the ingredient list is not empty
+ WeightList list = database->ingredientWeightUnits( it->text( 1 ).toInt() ); // load the list for this ingredient
+ for ( WeightList::const_iterator weight_it = list.begin(); weight_it != list.end(); ++weight_it ) {
+ TQListViewItem * lastElement = weightsListView->listView() ->lastItem();
+
+ Weight w = *weight_it;
+ WeightListItem *weight_it1 = new WeightListItem( weightsListView->listView(), lastElement, w );
+ weight_it1->setAmountUnit( w.perAmount,
+ database->unitName(w.perAmountUnitID),
+ Element((w.prepMethodID==-1)?TQString::null:database->prepMethodName(w.prepMethodID),w.prepMethodID)
+ );
+ weight_it1->setWeightUnit( w.weight, database->unitName(w.weightUnitID) );
+ }
+ }
+}
+
+void IngredientsDialog:: updateLists( void )
+{
+ reloadUnitList();
+ reloadPropertyList();
+ reloadWeightList();
+}
+
+void IngredientsDialog::addPropertyToIngredient( void )
+{
+
+ // Find selected ingredient item
+ TQListViewItem * it;
+ int ingredientID = -1;
+ if ( ( it = ingredientListView->listView() ->selectedItem() ) ) {
+ ingredientID = it->text( 1 ).toInt();
+ }
+ if ( ingredientID >= 0 ) // an ingredient was selected previously
+ {
+ IngredientPropertyList allProperties;
+ database->loadProperties( &allProperties );
+ UnitList unitList;
+ database->loadPossibleUnits( ingredientID, &unitList );
+ SelectPropertyDialog propertyDialog( this, &allProperties, &unitList, SelectPropertyDialog::HideEmptyUnit );
+
+ if ( propertyDialog.exec() == TQDialog::Accepted )
+ {
+
+ int propertyID = propertyDialog.propertyID();
+ int perUnitsID = propertyDialog.perUnitsID();
+ if ( !( database->ingredientContainsProperty( ingredientID, propertyID, perUnitsID ) ) ) {
+ if ( ( propertyID >= 0 ) && ( perUnitsID >= 0 ) ) // check if the property is not -1 ... (not selected)
+ database->addPropertyToIngredient( ingredientID, propertyID, 0, perUnitsID ); // Add result chosen property to ingredient in database, with amount 0 by default
+ }
+ else {
+ TQMessageBox::information( this, i18n( "Property Exists" ), i18n( "The property you tried to add already exists in the ingredient with the same per units." ) );
+ }
+ reloadPropertyList(); // Reload the list from database
+ }
+ }
+}
+
+void IngredientsDialog::removePropertyFromIngredient( void )
+{
+
+ // Find selected ingredient/property item combination
+ TQListViewItem * it;
+ int ingredientID = -1, propertyID = -1;
+ int perUnitsID = -1;
+ if ( ( it = ingredientListView->listView() ->selectedItem() ) )
+ ingredientID = it->text( 1 ).toInt();
+ if ( ( it = propertiesListView->listView() ->selectedItem() ) )
+ propertyID = it->text( 3 ).toInt();
+ if ( propertyID >= 0 )
+ perUnitsID = perUnitListBack->getElement( findPropertyNo( it ) ).id ;
+
+ if ( ( ingredientID >= 0 ) && ( propertyID >= 0 ) && ( perUnitsID >= 0 ) ) // an ingredient/property combination was selected previously
+ {
+ ElementList results;
+ database->removePropertyFromIngredient( ingredientID, propertyID, perUnitsID );
+
+ reloadPropertyList(); // Reload the list from database
+
+ }
+}
+
+void IngredientsDialog::insertPropertyEditBox( TQListViewItem* it )
+{
+ TQRect r = propertiesListView->listView() ->header() ->sectionRect( 1 );
+
+ r.moveBy( 0, propertiesListView->listView() ->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->setValue( it->text( 1 ).toDouble() );
+ inputBox->show();
+}
+
+void IngredientsDialog::setPropertyAmount( double amount )
+{
+ TQListViewItem *ing_it = ingredientListView->listView() ->selectedItem(); // Find selected ingredient
+ TQListViewItem *prop_it = propertiesListView->listView() ->selectedItem();
+
+ if ( ing_it && prop_it ) // Appart from property, Check if an ingredient is selected first, just in case
+ {
+ prop_it->setText( 1, TQString::number( amount ) );
+ int propertyID = prop_it->text( 3 ).toInt();
+ int ingredientID = ing_it->text( 1 ).toInt();
+ int per_units = perUnitListBack->getElement( findPropertyNo( prop_it ) ).id ;
+ database->changePropertyAmountToIngredient( ingredientID, propertyID, amount, per_units );
+ }
+}
+
+int IngredientsDialog::findPropertyNo( TQListViewItem * /*it*/ )
+{
+ bool found = false;
+ int i = 0;
+ TQListViewItem* item = propertiesListView->listView() ->firstChild();
+ while ( i < propertiesListView->listView() ->childCount() && !found ) {
+ if ( item == propertiesListView->listView() ->currentItem() )
+ found = true;
+ else {
+ item = item->nextSibling();
+ ++i;
+ }
+ }
+ if ( found ) {
+ return ( i );
+ }
+ else {
+ return ( -1 );
+ }
+}
+
+void IngredientsDialog::reload( ReloadFlags flag )
+{
+ reloadIngredientList( flag );
+ groupsDialog->reload( flag );
+}
+
+void IngredientsDialog::openUSDADialog( void )
+{
+ TQListViewItem * ing_it = ingredientListView->listView() ->selectedItem(); // Find selected ingredient
+ if ( ing_it ) {
+ TDEApplication::setOverrideCursor( KCursor::waitCursor() );
+ USDADataDialog usda_dialog( Element( ing_it->text( 0 ), ing_it->text( 1 ).toInt() ), database, this );
+ TDEApplication::restoreOverrideCursor();
+
+ if ( usda_dialog.exec() == TQDialog::Accepted ) {
+ reloadPropertyList(); //update property list upon success
+ reloadWeightList();
+ }
+ }
+ else
+ TQMessageBox::information( this, TQString::null, i18n( "No ingredient selected." ) );
+}
+
+#include "ingredientsdialog.moc"
diff --git a/src/dialogs/ingredientsdialog.h b/src/dialogs/ingredientsdialog.h
new file mode 100644
index 0000000..32af993
--- /dev/null
+++ b/src/dialogs/ingredientsdialog.h
@@ -0,0 +1,93 @@
+/***************************************************************************
+* 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. *
+***************************************************************************/
+
+#ifndef INGREDIENTSDIALOG_H
+#define INGREDIENTSDIALOG_H
+
+#include <tqpushbutton.h>
+#include <tqvbox.h>
+#include <tqlayout.h>
+#include <tqwidget.h>
+#include <knuminput.h>
+
+#include "widgets/krelistview.h"
+#include "widgets/dblistviewbase.h"
+#include "datablocks/unit.h"
+
+class KDoubleNumInput;
+
+class RecipeDB;
+class ElementList;
+class SelectUnitDialog;
+class CreateElementDialog;
+class IngredientPropertyList;
+class SelectPropertyDialog;
+class UnitsDialog;
+class IngredientGroupsDialog;
+class MixedNumber;
+
+class IngredientsDialog: public TQWidget
+{
+TQ_OBJECT
+
+public:
+ IngredientsDialog( TQWidget* parent, RecipeDB *db );
+ ~IngredientsDialog();
+ void reload( ReloadFlags flag = Load );
+
+private:
+ // Widgets
+ TQGridLayout* layout;
+ TQPushButton* addIngredientButton;
+ TQPushButton* removeIngredientButton;
+ TQPushButton* addUnitButton;
+ TQPushButton* removeUnitButton;
+ TQPushButton* addPropertyButton;
+ TQPushButton* removePropertyButton;
+ TQPushButton* addWeightButton;
+ TQPushButton* removeWeightButton;
+ KreListView* ingredientListView;
+ KreListView* unitsListView;
+ KreListView* propertiesListView;
+ KreListView* weightsListView;
+ TQPushButton* pushButton5;
+ KDoubleNumInput* inputBox;
+ IngredientGroupsDialog *groupsDialog;
+
+ // Internal Methods
+ void reloadIngredientList( ReloadFlags flag = Load );
+ void reloadUnitList( void );
+ void reloadPropertyList( void );
+ void reloadWeightList( void );
+ int findPropertyNo( TQListViewItem *it );
+
+ // Internal Variables
+ RecipeDB *database;
+ UnitList *unitList;
+ IngredientPropertyList *propertiesList;
+ ElementList *perUnitListBack;
+
+private slots:
+ void addUnitToIngredient( void );
+ void removeUnitFromIngredient( void );
+ void addWeight();
+ void removeWeight();
+ void updateLists( void );
+ void addPropertyToIngredient( void );
+ void removePropertyFromIngredient( void );
+ void insertPropertyEditBox( TQListViewItem* it );
+ void setPropertyAmount( double amount );
+ void openUSDADialog( void );
+ void itemRenamed( TQListViewItem*, const TQPoint &, int col );
+};
+
+#endif
diff --git a/src/dialogs/pagesetupdialog.cpp b/src/dialogs/pagesetupdialog.cpp
new file mode 100644
index 0000000..08e3fda
--- /dev/null
+++ b/src/dialogs/pagesetupdialog.cpp
@@ -0,0 +1,310 @@
+/***************************************************************************
+* Copyright (C) 2003-2005 by 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 "pagesetupdialog.h"
+
+#include <tqdir.h>
+#include <tqlayout.h>
+#include <tqhbox.h>
+#include <tqfileinfo.h>
+#include <tqpushbutton.h>
+#include <tqpopupmenu.h>
+#include <tqtooltip.h>
+#include <tqtabwidget.h>
+#include <tqlabel.h>
+
+#include <tdehtmlview.h>
+#include <tdeapplication.h>
+#include <kdebug.h>
+#include <tdefiledialog.h>
+#include <tdelocale.h>
+#include <kiconloader.h>
+#include <tdemessagebox.h>
+#include <kstandarddirs.h>
+#include <tdeaction.h>
+#include <tdeconfig.h>
+#include <kstdaction.h>
+#include <tdetoolbar.h>
+#include <tdepopupmenu.h>
+
+#include "setupdisplay.h"
+
+PageSetupDialog::PageSetupDialog( TQWidget *parent, const Recipe &sample, const TQString &configEntry ) : KDialog( parent, 0, true ), m_configEntry(configEntry)
+{
+ TDEIconLoader il;
+
+ TQVBoxLayout * layout = new TQVBoxLayout( this );
+
+ TDEToolBar *toolbar = new TDEToolBar( this );
+ TDEActionCollection *actionCollection = new TDEActionCollection( this );
+
+ TDEAction *std_open = KStdAction::open( 0, 0, 0 ); //use this to create a custom open action
+ TDEToolBarPopupAction *custom_open = new TDEToolBarPopupAction( std_open->text(), std_open->icon(), std_open->shortcut(), this, TQ_SLOT( loadFile() ), actionCollection, "open_popup" );
+
+ TDEPopupMenu *open_popup = custom_open->popupMenu();
+
+ open_popup->insertTitle( i18n( "Styles" ) );
+ TQDir included_layouts( getIncludedLayoutDir(), "*.klo", TQDir::Name | TQDir::IgnoreCase, TQDir::Files );
+ for ( unsigned int i = 0; i < included_layouts.count(); i++ ) {
+ int id = open_popup->insertItem( included_layouts[ i ].left(included_layouts[ i ].find(".")), this, TQ_SLOT( loadLayout( int ) ) );
+ included_layouts_map.insert( id, included_layouts[ i ] );
+ }
+
+ open_popup->insertTitle( i18n( "Templates" ) );
+ TQDir included_templates( getIncludedLayoutDir(), "*.template", TQDir::Name | TQDir::IgnoreCase, TQDir::Files );
+ for ( unsigned int i = 0; i < included_templates.count(); i++ ) {
+ int id = open_popup->insertItem( included_templates[ i ].left(included_templates[ i ].find(".")).replace("_"," "), this, TQ_SLOT( loadTemplate( int ) ) );
+ included_layouts_map.insert( id, included_templates[ i ] );
+ }
+
+ custom_open->plug( toolbar );
+
+ KStdAction::save( this, TQ_SLOT( saveLayout() ), actionCollection ) ->plug( toolbar );
+ KStdAction::saveAs( this, TQ_SLOT( saveAsLayout() ), actionCollection ) ->plug( toolbar );
+ KStdAction::redisplay( this, TQ_SLOT( reloadLayout() ), actionCollection ) ->plug( toolbar );
+
+ TDEToolBarPopupAction *shown_items = new TDEToolBarPopupAction( i18n( "Items Shown" ), "frame_edit" );
+ shown_items->setDelayed( false );
+ shown_items_popup = shown_items->popupMenu();
+ shown_items_popup->insertTitle( i18n( "Show Items" ) );
+ shown_items->plug( toolbar );
+ layout->addWidget( toolbar );
+
+ TQLabel *help = new TQLabel(i18n("<i>Usage: Right-click any element to edit the look of that element.</i>"),this);
+ layout->addWidget( help );
+
+ m_htmlPart = new SetupDisplay(sample, this);
+ layout->addWidget( m_htmlPart->view() );
+
+ TQHBox *buttonsBox = new TQHBox( this );
+ TQPushButton *okButton = new TQPushButton( il.loadIconSet( "ok", TDEIcon::Small ), i18n( "Save and Close" ), buttonsBox );
+ TQPushButton *cancelButton = new TQPushButton( il.loadIconSet( "cancel", TDEIcon::Small ), i18n( "&Cancel" ), buttonsBox );
+ layout->addWidget( buttonsBox );
+
+ connect( m_htmlPart, TQ_SIGNAL(itemVisibilityChanged(KreDisplayItem*,bool)), this, TQ_SLOT(updateItemVisibility(KreDisplayItem*,bool)) );
+ connect( okButton, TQ_SIGNAL( clicked() ), TQ_SLOT( accept() ) );
+ connect( cancelButton, TQ_SIGNAL( clicked() ), TQ_SLOT( reject() ) );
+
+ TDEConfig *config = TDEGlobal::config();
+ config->setGroup( "Page Setup" );
+ TQSize defaultSize(300,400);
+ resize(config->readSizeEntry( "WindowSize", &defaultSize ));
+
+ //let's do everything we can to be sure at least some layout is loaded
+ TQString layoutFile = config->readEntry( m_configEntry+"Layout", locate( "appdata", "layouts/Default.klo" ) );
+ if ( layoutFile.isEmpty() || !TQFile::exists( layoutFile ) )
+ layoutFile = locate( "appdata", "layouts/Default.klo" );
+
+ TQString tmpl = config->readEntry( m_configEntry+"Template", locate( "appdata", "layouts/Default.template" ) );
+ if ( tmpl.isEmpty() || !TQFile::exists( tmpl ) )
+ tmpl = locate( "appdata", "layouts/Default.template" );
+ kdDebug()<<"tmpl: "<<tmpl<<endl;
+ active_template = tmpl;
+ loadLayout( layoutFile );
+
+ initShownItems();
+}
+
+void PageSetupDialog::accept()
+{
+ if ( m_htmlPart->hasChanges() )
+ saveLayout();
+
+ if ( !active_filename.isEmpty() ) {
+ TDEConfig * config = kapp->config();
+ config->setGroup( "Page Setup" );
+ config->writeEntry( m_configEntry+"Layout", active_filename );
+ }
+
+ if ( !active_template.isEmpty() ) {
+ TDEConfig * config = kapp->config();
+ config->setGroup( "Page Setup" );
+ config->writeEntry( m_configEntry+"Template", active_template );
+ }
+
+ TDEConfig *config = kapp->config();
+ config->setGroup( "Page Setup" );
+ config->writeEntry( "WindowSize", size() );
+
+ TQDialog::accept();
+}
+
+void PageSetupDialog::reject()
+{
+ if ( m_htmlPart->hasChanges() ) {
+ switch ( KMessageBox::questionYesNoCancel( this, i18n( "The recipe view layout has been modified.\nDo you want to save it?" ), i18n( "Save Layout?" ) ) ) {
+ case KMessageBox::Yes:
+ saveLayout();
+ break;
+ case KMessageBox::No:
+ break;
+ default:
+ return ;
+ }
+ }
+
+ TQDialog::reject();
+}
+
+void PageSetupDialog::updateItemVisibility( KreDisplayItem *item, bool visible )
+{
+ shown_items_popup->setItemChecked( widget_popup_map[ item ], visible );
+}
+
+void PageSetupDialog::initShownItems()
+{
+ shown_items_popup->clear();
+
+ PropertiesMap properties = m_htmlPart->properties();
+
+ TQValueList<TQString> nameList;
+ TQMap<TQString,KreDisplayItem*> nameMap;
+
+ for ( PropertiesMap::const_iterator it = properties.begin(); it != properties.end(); ++it ) {
+ nameList << it.key()->name;
+ nameMap.insert( it.key()->name, it.key() );
+ }
+ qHeapSort( nameList );
+
+ for ( TQValueList<TQString>::const_iterator it = nameList.begin(); it != nameList.end(); ++it ) {
+ KreDisplayItem *item = nameMap[*it];
+ if ( properties[item] & SetupDisplay::Visibility ) {
+ int new_id = shown_items_popup->insertItem ( *it );
+ shown_items_popup->setItemChecked( new_id, item->show );
+ shown_items_popup->connectItem( new_id, this, TQ_SLOT( setItemShown( int ) ) );
+
+ popup_widget_map.insert( new_id, item );
+ widget_popup_map.insert( item, new_id );
+ }
+ }
+}
+
+void PageSetupDialog::setItemShown( int id )
+{
+ shown_items_popup->setItemChecked( id, !shown_items_popup->isItemChecked( id ) );
+ m_htmlPart->setItemShown( popup_widget_map[ id ], shown_items_popup->isItemChecked( id ) );
+}
+
+void PageSetupDialog::loadFile()
+{
+ TQString file = KFileDialog::getOpenFileName( locateLocal( "appdata", "layouts/" ), TQString("*.klo *.template|%1").arg(i18n("Krecipes style or template file")), this, i18n( "Select Layout" ) );
+
+ if ( file.endsWith(".klo") )
+ loadLayout( file );
+ else {
+ active_template = file;
+ m_htmlPart->loadTemplate( file );
+ }
+}
+
+void PageSetupDialog::loadTemplate( int popup_param )
+{
+ active_template = getIncludedLayoutDir() + "/" + included_layouts_map[ popup_param ];
+ m_htmlPart->loadTemplate( active_template );
+}
+
+void PageSetupDialog::loadLayout( int popup_param )
+{
+ loadLayout( getIncludedLayoutDir() + "/" + included_layouts_map[ popup_param ] );
+}
+
+void PageSetupDialog::loadLayout( const TQString &filename )
+{
+ if ( m_htmlPart->hasChanges() ) {
+ switch ( KMessageBox::questionYesNoCancel( this, i18n( "This layout has been modified.\nDo you want to save it?" ), i18n( "Save Layout?" ) ) ) {
+ case KMessageBox::Yes:
+ saveLayout();
+ break;
+ case KMessageBox::No:
+ break;
+ default:
+ return ;
+ }
+ }
+
+ if ( !filename.isEmpty() ) {
+ m_htmlPart->loadLayout( filename );
+ setActiveFile( filename );
+ }
+}
+
+void PageSetupDialog::reloadLayout()
+{
+ m_htmlPart->reload();
+}
+
+void PageSetupDialog::saveLayout()
+{
+ if ( m_htmlPart->hasChanges() ) {
+ if ( have_write_perm )
+ m_htmlPart->saveLayout( active_filename );
+ else {
+ switch ( KMessageBox::warningYesNo( this, i18n( "Unable to save the layout because you do not have sufficient permissions to modify this file.\nWould you like to instead save the current layout to a new file?" ) ) ) {
+ case KMessageBox::Yes:
+ saveAsLayout();
+ break;
+ default:
+ break;
+ }
+ }
+ }
+}
+
+void PageSetupDialog::saveAsLayout()
+{
+ TQString filename = KFileDialog::getSaveFileName( TDEGlobal::instance() ->dirs() ->saveLocation( "appdata", "layouts/" ), "*.klo|Krecipes Layout (*.klo)", this, TQString::null );
+
+ if ( !filename.isEmpty() ) {
+ if ( haveWritePerm( filename ) ) {
+ m_htmlPart->saveLayout( filename );
+ setActiveFile(filename);
+ }
+ else {
+ switch ( KMessageBox::warningYesNo( this, i18n( "You have selected a file that you do not have the permissions to write to.\nWould you like to select another file?" ) ) ) {
+ case KMessageBox::Yes:
+ saveAsLayout();
+ break;
+ default:
+ break;
+ }
+ }
+ }
+}
+
+TQString PageSetupDialog::getIncludedLayoutDir() const
+{
+ TQFileInfo file_info( locate( "appdata", "layouts/Default.klo" ) );
+ return file_info.dirPath( true );
+}
+
+void PageSetupDialog::setActiveFile( const TQString &filename )
+{
+ active_filename = filename;
+ have_write_perm = haveWritePerm( filename );
+}
+
+bool PageSetupDialog::haveWritePerm( const TQString &filename )
+{
+ TQFileInfo info( filename );
+
+ if ( info.exists() ) //check that we can write to this particular file
+ {
+ TQFileInfo info( filename );
+ return info.isWritable();
+ }
+ else //check that we can write to the directory since the file doesn't exist
+ {
+ TQFileInfo dir_info( info.dirPath( true ) );
+ return dir_info.isWritable();
+ }
+}
+
+
+#include "pagesetupdialog.moc"
diff --git a/src/dialogs/pagesetupdialog.h b/src/dialogs/pagesetupdialog.h
new file mode 100644
index 0000000..70c2b4d
--- /dev/null
+++ b/src/dialogs/pagesetupdialog.h
@@ -0,0 +1,72 @@
+/***************************************************************************
+* Copyright (C) 2003-2005 by 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. *
+***************************************************************************/
+
+#ifndef PAGESETUPDIALOG_H
+#define PAGESETUPDIALOG_H
+
+#include <tqmap.h>
+
+#include <kdialog.h>
+
+#include "datablocks/recipe.h"
+
+class TDEPopupMenu;
+
+class SetupDisplay;
+class KreDisplayItem;
+
+/**
+ * @author Jason Kivlighn
+ */
+class PageSetupDialog : public KDialog
+{
+ TQ_OBJECT
+
+public:
+ PageSetupDialog( TQWidget *parent, const Recipe &sample, const TQString &configEntry = TQString::null );
+ ~PageSetupDialog()
+ {}
+
+protected:
+ virtual void accept();
+ virtual void reject();
+ void save();
+
+private slots:
+ void loadFile();
+ void loadLayout( int );
+ void loadLayout( const TQString &filename );
+ void loadTemplate( int );
+ void reloadLayout();
+ void saveLayout();
+ void saveAsLayout();
+ void updateItemVisibility( KreDisplayItem*, bool );
+ void setItemShown( int id );
+
+private:
+ TQString getIncludedLayoutDir() const;
+ void setActiveFile( const TQString &filename );
+ bool haveWritePerm( const TQString &filename );
+ void initShownItems();
+
+ SetupDisplay *m_htmlPart;
+
+ TQString active_filename;
+ TQString active_template;
+ bool have_write_perm;
+ TQString m_configEntry;
+
+ TQMap<int, KreDisplayItem*> popup_widget_map;
+ TQMap<KreDisplayItem*, int> widget_popup_map;
+ TQMap<int, TQString> included_layouts_map;
+ TDEPopupMenu *shown_items_popup;
+};
+
+#endif //PAGESETUPDIALOG_H
diff --git a/src/dialogs/prepmethodsdialog.cpp b/src/dialogs/prepmethodsdialog.cpp
new file mode 100644
index 0000000..066c09f
--- /dev/null
+++ b/src/dialogs/prepmethodsdialog.cpp
@@ -0,0 +1,67 @@
+/***************************************************************************
+* 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 "prepmethodsdialog.h"
+#include "createelementdialog.h"
+#include "dependanciesdialog.h"
+#include "backends/recipedb.h"
+#include "widgets/prepmethodlistview.h"
+
+#include <kdialog.h>
+#include <tdelocale.h>
+#include <tdemessagebox.h>
+
+PrepMethodsDialog::PrepMethodsDialog( TQWidget* parent, RecipeDB *db ) : TQWidget( parent )
+{
+
+ // Store pointer to database
+ database = db;
+
+ TQHBoxLayout* layout = new TQHBoxLayout( this, KDialog::marginHint(), KDialog::spacingHint() );
+
+ //PrepMethod List
+ prepMethodListView = new StdPrepMethodListView( this, database, true );
+ layout->addWidget( prepMethodListView );
+
+ //Buttons
+ TQVBoxLayout* vboxl = new TQVBoxLayout( KDialog::spacingHint() );
+
+ newPrepMethodButton = new TQPushButton( this );
+ newPrepMethodButton->setText( i18n( "Create ..." ) );
+ newPrepMethodButton->setFlat( true );
+ vboxl->addWidget( newPrepMethodButton );
+
+ removePrepMethodButton = new TQPushButton( this );
+ removePrepMethodButton->setText( i18n( "Delete" ) );
+ removePrepMethodButton->setFlat( true );
+ vboxl->addWidget( removePrepMethodButton );
+ vboxl->addStretch();
+
+ layout->addLayout( vboxl );
+
+ //Connect Signals & Slots
+
+ connect ( newPrepMethodButton, TQ_SIGNAL( clicked() ), prepMethodListView, TQ_SLOT( createNew() ) );
+ connect ( removePrepMethodButton, TQ_SIGNAL( clicked() ), prepMethodListView, TQ_SLOT( remove
+ () ) );
+}
+
+PrepMethodsDialog::~PrepMethodsDialog()
+{}
+
+// (Re)loads the data from the database
+void PrepMethodsDialog::reload( ReloadFlags flag )
+{
+ prepMethodListView->reload( flag );
+}
+
+#include "prepmethodsdialog.moc"
diff --git a/src/dialogs/prepmethodsdialog.h b/src/dialogs/prepmethodsdialog.h
new file mode 100644
index 0000000..5dbb01c
--- /dev/null
+++ b/src/dialogs/prepmethodsdialog.h
@@ -0,0 +1,53 @@
+/***************************************************************************
+* 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. *
+***************************************************************************/
+
+#ifndef PREPMETHODSDIALOG_H
+#define PREPMETHODSDIALOG_H
+
+#include <tqwidget.h>
+#include <tqpushbutton.h>
+#include <tqhbox.h>
+#include <tqlayout.h>
+#include <kiconloader.h>
+#include <tdelistview.h>
+
+#include "widgets/dblistviewbase.h"
+
+class RecipeDB;
+class StdPrepMethodListView;
+
+/**
+@author Unai Garro
+*/
+
+class PrepMethodsDialog: public TQWidget
+{
+
+ TQ_OBJECT
+
+public:
+
+ PrepMethodsDialog( TQWidget* parent, RecipeDB *db );
+ ~PrepMethodsDialog();
+ void reload( ReloadFlags flag = Load );
+private:
+ // Internal data
+ RecipeDB *database;
+ //Widgets
+ TQGridLayout *layout;
+ StdPrepMethodListView *prepMethodListView;
+ TQHBox *buttonBar;
+ TQPushButton *newPrepMethodButton;
+ TQPushButton *removePrepMethodButton;
+ TDEIconLoader *il;
+};
+#endif
diff --git a/src/dialogs/propertiesdialog.cpp b/src/dialogs/propertiesdialog.cpp
new file mode 100644
index 0000000..366eb63
--- /dev/null
+++ b/src/dialogs/propertiesdialog.cpp
@@ -0,0 +1,77 @@
+/***************************************************************************
+* 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 "propertiesdialog.h"
+#include <tdelocale.h>
+#include <kdialog.h>
+#include <tdemessagebox.h>
+#include <tdeconfig.h>
+
+#include "backends/recipedb.h"
+#include "createpropertydialog.h"
+#include "widgets/propertylistview.h"
+
+PropertiesDialog::PropertiesDialog( TQWidget *parent, RecipeDB *db ) : TQWidget( parent )
+{
+
+ // Store pointer to database
+ database = db;
+
+ // Design dialog
+
+ TQHBoxLayout* layout = new TQHBoxLayout( this, KDialog::marginHint(), KDialog::spacingHint() );
+
+ propertyListView = new CheckPropertyListView( this, database, true );
+ propertyListView->reload();
+
+ TDEConfig *config = TDEGlobal::config();
+ config->setGroup("Formatting");
+ TQStringList hiddenList = config->readListEntry("HiddenProperties");
+ for ( TQCheckListItem *item = (TQCheckListItem*)propertyListView->firstChild(); item; item = (TQCheckListItem*)item->nextSibling() ) {
+ if ( !hiddenList.contains(item->text(0)) )
+ item->setOn(true);
+ }
+
+ layout->addWidget ( propertyListView );
+
+ TQVBoxLayout* vboxl = new TQVBoxLayout( KDialog::spacingHint() );
+ addPropertyButton = new TQPushButton( this );
+ addPropertyButton->setText( i18n( "Create ..." ) );
+ addPropertyButton->setFlat( true );
+ vboxl->addWidget( addPropertyButton );
+ removePropertyButton = new TQPushButton( this );
+ removePropertyButton->setText( i18n( "Delete" ) );
+ removePropertyButton->setFlat( true );
+ vboxl->addWidget( removePropertyButton );
+ vboxl->addStretch();
+ layout->addLayout( vboxl );
+
+ // Connect signals & slots
+ connect( addPropertyButton, TQ_SIGNAL( clicked() ), propertyListView, TQ_SLOT( createNew() ) );
+ connect( removePropertyButton, TQ_SIGNAL( clicked() ), propertyListView, TQ_SLOT( remove
+ () ) );
+
+ //FIXME: We've got some sort of build issue... we get undefined references to CreatePropertyDialog without this dummy code here
+ UnitList list;
+ CreatePropertyDialog d( this, &list );
+}
+
+
+PropertiesDialog::~PropertiesDialog()
+{}
+
+void PropertiesDialog::reload( void )
+{
+ propertyListView->reload();
+}
+
+#include "propertiesdialog.moc"
diff --git a/src/dialogs/propertiesdialog.h b/src/dialogs/propertiesdialog.h
new file mode 100644
index 0000000..d6ae406
--- /dev/null
+++ b/src/dialogs/propertiesdialog.h
@@ -0,0 +1,47 @@
+/***************************************************************************
+* 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. *
+***************************************************************************/
+
+#ifndef PROPERTIESDIALOG_H
+#define PROPERTIESDIALOG_H
+
+#include <tqlayout.h>
+#include <tqpushbutton.h>
+#include <tqvbox.h>
+#include <tdelistview.h>
+
+class RecipeDB;
+class StdPropertyListView;
+
+/**
+@author Unai Garro
+*/
+class PropertiesDialog: public TQWidget
+{
+ TQ_OBJECT
+public:
+ PropertiesDialog( TQWidget *parent, RecipeDB *db );
+ ~PropertiesDialog();
+ void reload( void );
+
+private:
+ // Variables
+ RecipeDB *database;
+
+ // Widgets
+ TQGridLayout* layout;
+ TQPushButton* addPropertyButton;
+ TQPushButton* removePropertyButton;
+ StdPropertyListView* propertyListView;
+
+};
+
+#endif
diff --git a/src/dialogs/recipeimportdialog.cpp b/src/dialogs/recipeimportdialog.cpp
new file mode 100644
index 0000000..cbc3dcf
--- /dev/null
+++ b/src/dialogs/recipeimportdialog.cpp
@@ -0,0 +1,185 @@
+/***************************************************************************
+* 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 "recipeimportdialog.h"
+
+#include <tdelocale.h>
+#include <kpushbutton.h>
+#include <tdelistview.h>
+#include <kdebug.h>
+
+#include <tqvbox.h>
+#include <tqlayout.h>
+#include <tqheader.h>
+#include <tqvariant.h>
+#include <tqdict.h>
+
+#include "datablocks/recipe.h"
+
+RecipeImportDialog::RecipeImportDialog( const RecipeList &list, TQWidget *parent )
+ : KDialogBase( parent, "RecipeImportDialog", true, i18n( "Import Recipes" ),
+ KDialogBase::Ok | KDialogBase::Cancel, KDialogBase::Ok ),
+ list_copy( list )
+{
+ setButtonBoxOrientation( Vertical );
+
+ TQVBox *page = makeVBoxMainWidget();
+
+ kListView = new TDEListView( page );
+ kListView->addColumn( i18n( "Recipes" ) );
+ kListView->setProperty( "selectionMode", "NoSelection" );
+ kListView->setRootIsDecorated( true );
+ kListView->setAllColumnsShowFocus( true );
+
+ languageChange();
+
+ setInitialSize( TQSize( 600, 480 ).expandedTo( minimumSizeHint() ) );
+
+ loadListView();
+}
+
+RecipeImportDialog::~RecipeImportDialog()
+{
+ delete recipe_items;
+}
+
+void RecipeImportDialog::languageChange()
+{
+}
+
+void RecipeImportDialog::loadListView()
+{
+ CustomCheckListItem * head_item = new CustomCheckListItem( kListView, TQString( i18n( "All (%1)" ) ).arg( list_copy.count() ), TQCheckListItem::CheckBox );
+ head_item->setOpen( true );
+
+ //get all categories
+ TQStringList categoryList;
+
+ RecipeList::const_iterator recipe_it;
+ for ( recipe_it = list_copy.begin(); recipe_it != list_copy.end(); ++recipe_it ) {
+ for ( ElementList::const_iterator cat_it = ( *recipe_it ).categoryList.begin(); cat_it != ( *recipe_it ).categoryList.end(); ++cat_it ) {
+ if ( categoryList.contains( ( *cat_it ).name ) < 1 )
+ categoryList << ( *cat_it ).name;
+ }
+ }
+
+ //create all category check list items
+ TQDict<CustomCheckListItem> all_categories;
+
+ TQStringList::iterator it;
+ for ( it = categoryList.begin(); it != categoryList.end(); ++it ) {
+ CustomCheckListItem *category_item = new CustomCheckListItem( head_item, *it, TQCheckListItem::CheckBox );
+ //category_item->setOpen(true);
+
+ all_categories.insert( *it, category_item );
+ }
+
+ //add recipes to category check list items
+ recipe_items = new TQMap<CustomCheckListItem*, RecipeList::const_iterator>; //we won't be able to identify a recipe later if we just put a value in here. The iterator will be unique so we'll use it. This is safe since the list is constant (iterators won't become invlalid).
+
+ CustomCheckListItem *item = 0;
+ CustomCheckListItem *category_item = 0;
+
+ for ( recipe_it = list_copy.begin(); recipe_it != list_copy.end(); ++recipe_it ) {
+ if ( ( *recipe_it ).categoryList.count() == 0 ) {
+ if ( !category_item ) //don't create this until there are recipes to put in it
+ {
+ category_item = new CustomCheckListItem( head_item, i18n( "Uncategorized" ), TQCheckListItem::CheckBox );
+ all_categories.insert( i18n( "Uncategorized" ), category_item );
+ }
+ CustomCheckListItem *item = new CustomCheckListItem( category_item, ( *recipe_it ).title, TQCheckListItem::CheckBox );
+ recipe_items->insert( item, recipe_it );
+ }
+ else {
+ for ( ElementList::const_iterator cat_it = ( *recipe_it ).categoryList.begin(); cat_it != ( *recipe_it ).categoryList.end(); ++cat_it ) {
+
+ CustomCheckListItem *category_item = all_categories[ ( *cat_it ).name ];
+
+ item = new CustomCheckListItem( category_item, item, ( *recipe_it ).title, TQCheckListItem::CheckBox );
+ recipe_items->insert( item, recipe_it );
+ }
+ }
+ }
+
+ //append the number of recipes in each category to the check list item text
+ TQDictIterator<CustomCheckListItem> categories_it( all_categories );
+ for ( ; categories_it.current(); ++categories_it ) {
+ int count = 0;
+ for ( TQCheckListItem * it = static_cast<TQCheckListItem*>( categories_it.current() ->firstChild() ); it; it = static_cast<TQCheckListItem*>( it->nextSibling() ) ) {
+ count++;
+ }
+ categories_it.current() ->setText( 0, categories_it.current() ->text( 0 ) + TQString( " (%1)" ).arg( count ) );
+ }
+
+ head_item->setOn( true ); //this will check all recipes
+}
+
+RecipeList RecipeImportDialog::getSelectedRecipes()
+{
+ RecipeList selected_recipes;
+
+ TQValueList<RecipeList::const_iterator> already_included_recipes;
+
+ TQMap<CustomCheckListItem*, RecipeList::const_iterator>::const_iterator it;
+ for ( it = recipe_items->begin(); it != recipe_items->end(); ++it ) {
+ if ( static_cast<CustomCheckListItem*>( it.key() ) ->isOn() &&
+ ( already_included_recipes.contains( it.data() ) == 0 ) ) //make sure it isn't already in the list
+ {
+ already_included_recipes.prepend( it.data() );
+ selected_recipes.prepend( *it.data() );
+ }
+ }
+
+ return selected_recipes;
+}
+
+CustomCheckListItem::CustomCheckListItem( TQListView *parent, const TQString & s, Type t )
+ : TQCheckListItem( parent, s, t ), m_locked( false )
+{}
+
+CustomCheckListItem::CustomCheckListItem( CustomCheckListItem *parent, const TQString & s, Type t )
+ : TQCheckListItem( parent, s, t ), m_locked( false )
+{}
+
+CustomCheckListItem::CustomCheckListItem( TQCheckListItem *parent, TQCheckListItem *after, const TQString & s, Type t )
+ : TQCheckListItem( parent, after, s, t ), m_locked( false )
+{}
+
+void CustomCheckListItem::stateChange( bool on )
+{
+ if ( !m_locked ) {
+ for ( TQCheckListItem * it = static_cast<TQCheckListItem*>( firstChild() ); it; it = static_cast<TQCheckListItem*>( it->nextSibling() ) ) {
+ it->setOn( on );
+ }
+ }
+
+ if ( !on ) {
+ TQListViewItem * parent = this->parent();
+ if ( parent && ( parent->rtti() == 1 ) ) {
+ CustomCheckListItem * item = static_cast<CustomCheckListItem*>( parent );
+ item->setLocked( true );
+ item->setOn( on );
+ item->setLocked( false );
+ }
+ }
+
+ TQString thisText = text(0);
+ TQListViewItemIterator it( listView() );
+ while ( it.current() ) {
+ if ( it.current()->rtti() == 1 && it.current()->text(0) == thisText ) {
+ CustomCheckListItem * item = static_cast<CustomCheckListItem*>( it.current() );
+ item->setOn( on );
+ }
+ ++it;
+ }
+}
+
diff --git a/src/dialogs/recipeimportdialog.h b/src/dialogs/recipeimportdialog.h
new file mode 100644
index 0000000..5dfdf2c
--- /dev/null
+++ b/src/dialogs/recipeimportdialog.h
@@ -0,0 +1,80 @@
+/***************************************************************************
+* 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. *
+***************************************************************************/
+
+#ifndef RECIPEIMPORTDIALOG_H
+#define RECIPEIMPORTDIALOG_H
+
+#include <tqvaluelist.h>
+#include <tqmap.h>
+#include <tqlistview.h>
+
+#include <kdialogbase.h>
+
+#include "datablocks/recipelist.h"
+
+class TDEListView;
+
+class TQListViewItem;
+
+class Recipe;
+class CustomCheckListItem;
+
+/**
+ * @author Jason Kivlighn
+ */
+class RecipeImportDialog : public KDialogBase
+{
+public:
+ RecipeImportDialog( const RecipeList &all_recipes, TQWidget *parent = 0 );
+ ~RecipeImportDialog();
+
+ RecipeList getSelectedRecipes();
+
+protected slots:
+ virtual void languageChange();
+
+private:
+ void loadListView();
+
+ TDEListView* kListView;
+
+ TQMap<CustomCheckListItem*, RecipeList::const_iterator> *recipe_items;
+ const RecipeList list_copy;
+};
+
+/** A specialized TQCheckListItem that sets the state of its children to its
+ * current state.
+ * @author Jason Kivlighn
+ */
+class CustomCheckListItem : public TQCheckListItem
+{
+public:
+ CustomCheckListItem( TQListView *parent, const TQString &, Type );
+ CustomCheckListItem( CustomCheckListItem *parent, const TQString &, Type );
+ CustomCheckListItem( TQCheckListItem *parent, TQCheckListItem *after, const TQString &, Type );
+
+protected:
+ virtual void stateChange( bool );
+ bool locked() const
+ {
+ return m_locked;
+ }
+ void setLocked( bool b )
+ {
+ m_locked = b;
+ }
+
+private:
+ bool m_locked;
+};
+
+#endif //RECIPEIMPORTDIALOG_H
diff --git a/src/dialogs/recipeinputdialog.cpp b/src/dialogs/recipeinputdialog.cpp
new file mode 100644
index 0000000..31ee38e
--- /dev/null
+++ b/src/dialogs/recipeinputdialog.cpp
@@ -0,0 +1,1641 @@
+/***************************************************************************
+* Copyright (C) 2003-2005 by *
+* Unai Garro (ugarro@users.sourceforge.net) *
+* Cyril Bosselut (bosselut@b1project.com) *
+* Jason Kivlighn (jkivlighn@gmail.com) *
+* *
+* Copyright (C) 2006 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 "recipeinputdialog.h"
+
+#include <tqstring.h>
+#include <tqlayout.h>
+#include <tqhbox.h>
+#include <tqvbox.h>
+#include <tqimage.h>
+#include <tqmessagebox.h>
+#include <tqtooltip.h>
+#include <tqdatetimeedit.h>
+#include <tqdragobject.h>
+#include <tqbuttongroup.h>
+#include <tqradiobutton.h>
+#include <tqwidgetstack.h>
+#include <tqpainter.h>
+
+#include <tdeapplication.h>
+#include <tdecompletionbox.h>
+#include <tdespell.h>
+#include <kurl.h>
+#include <tdefiledialog.h>
+#include <tdelocale.h>
+#include <tdemessagebox.h>
+#include <kdebug.h>
+#include <kled.h>
+#include <kdialogbase.h>
+
+#include "selectauthorsdialog.h"
+#include "resizerecipedialog.h"
+#include "ingredientparserdialog.h"
+#include "editratingdialog.h"
+#include "createunitdialog.h"
+#include "datablocks/recipe.h"
+#include "datablocks/categorytree.h"
+#include "datablocks/unit.h"
+#include "datablocks/weight.h"
+#include "backends/recipedb.h"
+#include "selectcategoriesdialog.h"
+#include "widgets/fractioninput.h"
+#include "widgets/kretextedit.h"
+#include "widgets/inglistviewitem.h"
+#include "../widgets/ratingdisplaywidget.h"
+#include "widgets/kwidgetlistbox.h"
+#include "widgets/ingredientinputwidget.h"
+#include "image.h" //Initializes default photo
+
+#include "profiling.h"
+
+enum ColorStatus { GreenStatus, RedStatus, YellowStatus };
+
+ClickableLed::ClickableLed( TQWidget *parent ) : KLed(parent)
+{
+}
+
+void ClickableLed::mouseReleaseEvent( TQMouseEvent* )
+{
+ emit clicked();
+}
+
+ImageDropLabel::ImageDropLabel( TQWidget *parent, TQPixmap &_sourcePhoto ) : TQLabel( parent ),
+ sourcePhoto( _sourcePhoto )
+{
+ setAcceptDrops( TRUE );
+}
+
+void ImageDropLabel::dragEnterEvent( TQDragEnterEvent* event )
+{
+ event->accept( TQImageDrag::canDecode( event ) );
+}
+
+void ImageDropLabel::dropEvent( TQDropEvent* event )
+{
+ TQImage image;
+
+ if ( TQImageDrag::decode( event, image ) ) {
+ if ( ( image.width() > width() || image.height() > height() ) || ( image.width() < width() && image.height() < height() ) ) {
+ TQPixmap pm_scaled;
+ pm_scaled.convertFromImage( image.smoothScale( width(), height(), TQImage::ScaleMin ) );
+ setPixmap( pm_scaled );
+
+ sourcePhoto = pm_scaled; // to save scaled later on
+ }
+ else {
+ setPixmap( image );
+ sourcePhoto = image;
+ }
+
+ emit changed();
+ }
+}
+
+
+RecipeInputDialog::RecipeInputDialog( TQWidget* parent, RecipeDB *db ) : TQVBox( parent )
+{
+
+ // Adjust internal parameters
+ loadedRecipe = new Recipe();
+ loadedRecipe->recipeID = -1; // No loaded recipe initially
+ loadedRecipe->title = TQString::null;
+ loadedRecipe->instructions = TQString::null;
+ database = db;
+
+ TDEIconLoader *il = new TDEIconLoader;
+
+ // Tabs
+ tabWidget = new TQTabWidget( this, "tabWidget" );
+ tabWidget->setSizePolicy( TQSizePolicy( TQSizePolicy::MinimumExpanding, TQSizePolicy::MinimumExpanding ) );
+
+
+ //------- Recipe Tab -----------------
+ // Recipe Photo
+
+ recipeTab = new TQGroupBox( tabWidget );
+ recipeTab->setFrameStyle( TQFrame::NoFrame );
+ recipeTab->setSizePolicy( TQSizePolicy( TQSizePolicy::MinimumExpanding, TQSizePolicy::MinimumExpanding ) );
+
+
+ // Design the Dialog
+ TQGridLayout* recipeLayout = new TQGridLayout( recipeTab, 1, 1, 0, 0 );
+
+ // Border
+ TQSpacerItem* spacer_left = new TQSpacerItem( 10, 10, TQSizePolicy::Fixed, TQSizePolicy::Minimum );
+ recipeLayout->addItem( spacer_left, 1, 0 );
+ TQSpacerItem* spacer_right = new TQSpacerItem( 10, 10, TQSizePolicy::Fixed, TQSizePolicy::Minimum );
+ recipeLayout->addItem( spacer_right, 1, 8 );
+ TQSpacerItem* spacer_top = new TQSpacerItem( 10, 10, TQSizePolicy::Minimum , TQSizePolicy::Fixed );
+ recipeLayout->addItem( spacer_top, 0, 1 );
+ TQSpacerItem* spacer_bottom = new TQSpacerItem( 10, 10, TQSizePolicy::Minimum , TQSizePolicy::MinimumExpanding );
+ recipeLayout->addItem( spacer_bottom, 8, 1 );
+
+
+ TQPixmap image1( defaultPhoto );
+
+ photoLabel = new ImageDropLabel( recipeTab, sourcePhoto );
+ photoLabel->setPixmap( image1 );
+ photoLabel->setFixedSize( TQSize( 221, 166 ) );
+ photoLabel->setSizePolicy( TQSizePolicy( TQSizePolicy::Fixed, TQSizePolicy::Fixed ) );
+ photoLabel->setAlignment( TQt::AlignHCenter | TQt::AlignVCenter );
+ recipeLayout->addMultiCellWidget( photoLabel, 3, 7, 1, 1 );
+
+ TQVBox *photoButtonsBox = new TQVBox( recipeTab );
+
+ changePhotoButton = new TQPushButton( photoButtonsBox );
+ changePhotoButton->setSizePolicy( TQSizePolicy( TQSizePolicy::Preferred, TQSizePolicy::Ignored ) );
+ changePhotoButton->setText( "..." );
+ TQToolTip::add
+ ( changePhotoButton, i18n( "Select photo" ) );
+
+ TQPushButton *clearPhotoButton = new TQPushButton( photoButtonsBox );
+ clearPhotoButton->setPixmap( il->loadIcon( "clear_left", TDEIcon::NoGroup, 16 ) );
+ TQToolTip::add
+ ( clearPhotoButton, i18n( "Clear photo" ) );
+
+ recipeLayout->addMultiCellWidget( photoButtonsBox, 3, 7, 2, 2 );
+
+
+ //Title->photo spacer
+ TQSpacerItem* title_photo = new TQSpacerItem( 10, 10, TQSizePolicy::Minimum, TQSizePolicy::Fixed );
+ recipeLayout->addItem( title_photo, 2, 3 );
+
+
+ // Title
+ TQVBox *titleBox = new TQVBox( recipeTab );
+ titleBox->setSpacing( 5 );
+ titleLabel = new TQLabel( i18n( "Recipe Name" ), titleBox );
+ titleEdit = new KLineEdit( titleBox );
+ titleEdit->setMinimumSize( TQSize( 360, 30 ) );
+ titleEdit->setMaximumSize( TQSize( 10000, 30 ) );
+ titleEdit->setSizePolicy( TQSizePolicy( TQSizePolicy::MinimumExpanding, TQSizePolicy::Fixed ) );
+ recipeLayout->addMultiCellWidget( titleBox, 1, 1, 1, 7 );
+
+
+ // Photo ->author spacer
+ TQSpacerItem* title_spacer = new TQSpacerItem( 10, 10, TQSizePolicy::Fixed, TQSizePolicy::Minimum );
+ recipeLayout->addItem( title_spacer, 2, 1 );
+
+ // Author(s) & Categories
+ TQVBox *authorBox = new TQVBox( recipeTab ); // contains label and authorInput (input widgets)
+ authorBox->setSpacing( 5 );
+ recipeLayout->addWidget( authorBox, 3, 4 );
+ authorLabel = new TQLabel( i18n( "Authors" ), authorBox );
+ TQHBox *authorInput = new TQHBox( authorBox ); // Contains input + button
+
+
+ authorShow = new KLineEdit( authorInput );
+ authorShow->setReadOnly( true );
+ authorShow->setMinimumSize( TQSize( 100, 20 ) );
+ authorShow->setMaximumSize( TQSize( 10000, 20 ) );
+ authorShow->setSizePolicy( TQSizePolicy( TQSizePolicy::MinimumExpanding, TQSizePolicy::Fixed ) );
+
+
+ addAuthorButton = new TQPushButton( authorInput );
+ addAuthorButton->setText( "+" );
+ addAuthorButton->setFixedSize( TQSize( 20, 20 ) );
+ addAuthorButton->setFlat( true );
+
+
+ TQSpacerItem* author_category = new TQSpacerItem( 10, 10, TQSizePolicy::Fixed, TQSizePolicy::Minimum );
+ recipeLayout->addItem( author_category, 3, 5 );
+
+ TQVBox *categoryBox = new TQVBox( recipeTab ); // Contains the label and categoryInput (input widgets)
+ categoryBox->setSpacing( 5 );
+ categoryLabel = new TQLabel( i18n( "Categories" ), categoryBox );
+ TQHBox *categoryInput = new TQHBox( categoryBox ); // Contains the input widgets
+
+ categoryShow = new KLineEdit( categoryInput );
+ categoryShow->setReadOnly( true );
+ categoryShow->setMinimumSize( TQSize( 100, 20 ) );
+ categoryShow->setMaximumSize( TQSize( 10000, 20 ) );
+ categoryShow->setSizePolicy( TQSizePolicy( TQSizePolicy::MinimumExpanding, TQSizePolicy::Fixed ) );
+ recipeLayout->addWidget( categoryBox, 4, 4 );
+
+ addCategoryButton = new TQPushButton( categoryInput );
+ addCategoryButton->setText( "+" );
+ addCategoryButton->setFixedSize( TQSize( 20, 20 ) );
+ addCategoryButton->setFlat( true );
+
+ //Category ->Servings spacer
+ TQSpacerItem* category_yield = new TQSpacerItem( 10, 10, TQSizePolicy::Minimum, TQSizePolicy::Fixed );
+ recipeLayout->addItem( category_yield, 5, 4 );
+
+ TQHBox *serv_prep_box = new TQHBox( recipeTab );
+ serv_prep_box->setSpacing( 5 );
+
+ // Backup options
+ TQGroupBox *yieldGBox = new TQGroupBox( serv_prep_box, "yieldGBox" );
+ yieldGBox->setTitle( i18n( "Yield" ) );
+ yieldGBox->setColumns( 2 );
+
+ yieldLabel = new TQLabel( i18n( "Amount" ), yieldGBox );
+ /*TQLabel *yieldTypeLabel = */new TQLabel( i18n( "Type" ), yieldGBox );
+ yieldNumInput = new FractionInput( yieldGBox );
+ yieldNumInput->setAllowRange(true);
+ yieldTypeEdit = new KLineEdit( yieldGBox );
+
+ TQVBox *prepTimeBox = new TQVBox( serv_prep_box );
+ prepTimeBox->setSizePolicy( TQSizePolicy( TQSizePolicy::Minimum, TQSizePolicy::Fixed ) );
+ prepTimeBox->setSpacing( 5 );
+
+ ( void ) new TQLabel( i18n( "Preparation Time" ), prepTimeBox );
+ prepTimeEdit = new TQTimeEdit( prepTimeBox );
+ prepTimeEdit->setMinValue( TQTime( 0, 0 ) );
+ prepTimeEdit->setDisplay( TQTimeEdit::Hours | TQTimeEdit::Minutes );
+
+ recipeLayout->addWidget( serv_prep_box, 6, 4 );
+
+ //------- END OF Recipe Tab ---------------
+
+ //------- Ingredients Tab -----------------
+
+ ingredientGBox = new TQGroupBox( recipeTab );
+ ingredientGBox->setFrameStyle( TQFrame::NoFrame );
+ ingredientGBox->setSizePolicy( TQSizePolicy( TQSizePolicy::MinimumExpanding, TQSizePolicy::MinimumExpanding ) );
+ TQGridLayout* ingredientsLayout = new TQGridLayout( ingredientGBox );
+
+ // Border
+ TQSpacerItem* spacerBoxLeft = new TQSpacerItem( 10, 10, TQSizePolicy::Fixed, TQSizePolicy::Minimum );
+ ingredientsLayout->addItem( spacerBoxLeft, 1, 0 );
+ TQSpacerItem* spacerBoxTop = new TQSpacerItem( 10, 20, TQSizePolicy::Minimum, TQSizePolicy::Fixed );
+ ingredientsLayout->addItem( spacerBoxTop, 0, 1 );
+
+ //Input Widgets
+ ingInput = new IngredientInputWidget( database, ingredientGBox );
+ ingredientsLayout->addMultiCellWidget( ingInput, 1, 1, 1, 5 );
+
+ // Spacers to list and buttons
+ TQSpacerItem* spacerToList = new TQSpacerItem( 10, 10, TQSizePolicy::Minimum, TQSizePolicy::Fixed );
+ ingredientsLayout->addItem( spacerToList, 2, 1 );
+ TQSpacerItem* spacerToButtons = new TQSpacerItem( 10, 10, TQSizePolicy::Fixed, TQSizePolicy::Minimum );
+ ingredientsLayout->addItem( spacerToButtons, 3, 4 );
+
+ // Add, Up,down,... buttons
+
+ addButton = new KPushButton( ingredientGBox );
+ addButton->setFixedSize( TQSize( 31, 31 ) );
+ addButton->setFlat( true );
+ TQPixmap pm = il->loadIcon( "new", TDEIcon::NoGroup, 16 );
+ addButton->setPixmap( pm );
+ addButton->setSizePolicy( TQSizePolicy( TQSizePolicy::Fixed, TQSizePolicy::Fixed ) );
+ ingredientsLayout->addWidget( addButton, 3, 5 );
+
+ // Spacer to the rest of buttons
+ TQSpacerItem* spacerToOtherButtons = new TQSpacerItem( 10, 10, TQSizePolicy::Minimum, TQSizePolicy::Fixed );
+ ingredientsLayout->addItem( spacerToOtherButtons, 4, 5 );
+
+ upButton = new KPushButton( ingredientGBox );
+ upButton->setFixedSize( TQSize( 31, 31 ) );
+ upButton->setFlat( true );
+ pm = il->loadIcon( "go-up", TDEIcon::NoGroup, 16 );
+ upButton->setPixmap( pm );
+ upButton->setSizePolicy( TQSizePolicy( TQSizePolicy::Fixed, TQSizePolicy::Fixed ) );
+ ingredientsLayout->addWidget( upButton, 5, 5 );
+
+ downButton = new KPushButton( ingredientGBox );
+ downButton->setFixedSize( TQSize( 31, 31 ) );
+ downButton->setFlat( true );
+ pm = il->loadIcon( "go-down", TDEIcon::NoGroup, 16 );
+ downButton->setPixmap( pm );
+ downButton->setSizePolicy( TQSizePolicy( TQSizePolicy::Fixed, TQSizePolicy::Fixed ) );
+ ingredientsLayout->addWidget( downButton, 6, 5 );
+
+ removeButton = new KPushButton( ingredientGBox );
+ removeButton->setFixedSize( TQSize( 31, 31 ) );
+ removeButton->setFlat( true );
+ pm = il->loadIcon( "remove", TDEIcon::NoGroup, 16 );
+ removeButton->setPixmap( pm );
+ removeButton->setSizePolicy( TQSizePolicy( TQSizePolicy::Fixed, TQSizePolicy::Fixed ) );
+ ingredientsLayout->addWidget( removeButton, 7, 5 );
+
+ ingParserButton = new KPushButton( ingredientGBox );
+ ingParserButton->setFixedSize( TQSize( 31, 31 ) );
+ ingParserButton->setFlat( true );
+ pm = il->loadIcon( "edit-paste", TDEIcon::NoGroup, 16 );
+ ingParserButton->setPixmap( pm );
+ ingParserButton->setSizePolicy( TQSizePolicy( TQSizePolicy::Fixed, TQSizePolicy::Fixed ) );
+ ingredientsLayout->addWidget( ingParserButton, 8, 5 );
+
+ TQToolTip::add
+ ( addButton, i18n( "Add ingredient" ) );
+ TQToolTip::add
+ ( upButton, i18n( "Move ingredient up" ) );
+ TQToolTip::add
+ ( downButton, i18n( "Move ingredient down" ) );
+ TQToolTip::add
+ ( removeButton, i18n( "Remove ingredient" ) );
+ TQToolTip::add
+ ( ingParserButton, i18n( "Paste Ingredients" ) );
+
+ // Ingredient List
+ ingredientList = new TDEListView( ingredientGBox, "ingredientList" );
+ ingredientList->addColumn( i18n( "Ingredient" ) );
+ ingredientList->addColumn( i18n( "Amount" ) );
+ ingredientList->setColumnAlignment( 1, TQt::AlignHCenter );
+ ingredientList->addColumn( i18n( "Units" ) );
+ ingredientList->addColumn( i18n( "Preparation Method" ) );
+ ingredientList->setSorting( -1 ); // Do not sort
+ ingredientList->setSizePolicy( TQSizePolicy( TQSizePolicy::Expanding, TQSizePolicy::MinimumExpanding ) );
+ ingredientList->setItemsRenameable( true );
+ ingredientList->setRenameable( 0, false ); //name
+ ingredientList->setRenameable( 1, true ); //amount
+ ingredientList->setRenameable( 2, true ); //units
+ ingredientList->setRenameable( 3, true ); //prep method
+ ingredientList->setDefaultRenameAction( TQListView::Reject );
+ ingredientsLayout->addMultiCellWidget( ingredientList, 3, 9, 1, 3 );
+
+ TQHBoxLayout *propertyStatusLayout = new TQHBoxLayout( NULL, 0, 5 );
+ TQLabel *propertyLabel = new TQLabel( i18n("Property Status:"), ingredientGBox );
+ propertyStatusLabel = new TQLabel( ingredientGBox );
+ propertyStatusLed = new ClickableLed( ingredientGBox );
+ propertyStatusLed->setFixedSize( TQSize(16,16) );
+ propertyStatusButton = new TQPushButton( i18n("Details..."), ingredientGBox );
+ //TQPushButton *propertyUpdateButton = new TQPushButton( i18n("Update"), ingredientGBox );
+ propertyStatusLayout->addWidget( propertyLabel );
+ propertyStatusLayout->addWidget( propertyStatusLabel );
+ propertyStatusLayout->addWidget( propertyStatusLed );
+ propertyStatusLayout->addWidget( propertyStatusButton );
+ //propertyStatusLayout->addWidget( propertyUpdateButton );
+ TQSpacerItem* propertySpacerRight = new TQSpacerItem( 10, 10, TQSizePolicy::MinimumExpanding, TQSizePolicy::Minimum );
+ propertyStatusLayout->addItem( propertySpacerRight );
+
+ KGuiItem updateGuiItem;
+ updateGuiItem.setText( i18n("Update") );
+ updateGuiItem.setIconSet( il->loadIconSet( "reload", TDEIcon::NoGroup ) );
+ propertyStatusDialog = new KDialogBase( KDialogBase::Swallow, i18n("Property details"),
+ KDialogBase::Close | KDialogBase::User1 | KDialogBase::Help,
+ KDialogBase::Close, this, "propertyStatusDialog", false, false,
+ updateGuiItem
+ );
+ propertyStatusDialog->setHelp("property-status");
+ statusTextView = new TQTextEdit(0);
+ statusTextView->setTextFormat( TQt::RichText );
+ statusTextView->setReadOnly(true);
+ propertyStatusDialog->setMainWidget( statusTextView );
+ propertyStatusDialog->resize( 400, 300 );
+
+ ingredientsLayout->addMultiCellLayout( propertyStatusLayout, 10, 10, 1, 4 );
+
+ // ------- Recipe Instructions Tab -----------
+
+ instructionsTab = new TQGroupBox( recipeTab );
+ instructionsTab->setFrameStyle( TQFrame::NoFrame );
+ instructionsTab->setSizePolicy( TQSizePolicy( TQSizePolicy::MinimumExpanding, TQSizePolicy::MinimumExpanding ) );
+
+ TQVBoxLayout *instructionsLayout = new TQVBoxLayout( instructionsTab );
+
+ instructionsEdit = new KreTextEdit( instructionsTab );
+ instructionsEdit->setSizePolicy( TQSizePolicy( TQSizePolicy::MinimumExpanding, TQSizePolicy::MinimumExpanding ) );
+ instructionsEdit->setTabChangesFocus ( true );
+ instructionsLayout->addWidget( instructionsEdit );
+
+ spellCheckButton = new TQToolButton( instructionsTab );
+ spellCheckButton->setIconSet( il->loadIconSet( "tools-check-spelling", TDEIcon::Small ) );
+ TQToolTip::add
+ ( spellCheckButton, i18n( "Check spelling" ) );
+ instructionsLayout->addWidget( spellCheckButton );
+
+ // ------- END OF Recipe Instructions Tab -----------
+
+
+ // ------- Recipe Ratings Tab -----------
+
+ TQVBox *ratingsTab = new TQVBox(recipeTab);
+ ratingListDisplayWidget = new KWidgetListbox(ratingsTab);
+ TQPushButton *addRatingButton = new TQPushButton(i18n("Add Rating..."),ratingsTab);
+
+ connect( addRatingButton, TQ_SIGNAL(clicked()), this, TQ_SLOT(slotAddRating()) );
+
+ // ------- END OF Recipe Ratings Tab -----------
+
+
+ tabWidget->insertTab( recipeTab, i18n( "Recipe" ) );
+ tabWidget->insertTab( ingredientGBox, i18n( "Ingredients" ) );
+ tabWidget->insertTab( instructionsTab, i18n( "Instructions" ) );
+ tabWidget->insertTab( ratingsTab, i18n( "Ratings" ) );
+
+
+ // Functions Box
+ TQHBox* functionsLayout = new TQHBox( this );
+
+ functionsBox = new TQGroupBox( 1, TQt::Vertical, functionsLayout );
+ functionsBox->setFrameStyle( TQFrame::NoFrame );
+
+ saveButton = new TQToolButton( functionsBox );
+ saveButton->setIconSet( il->loadIconSet( "document-save", TDEIcon::Small ) );
+ saveButton->setEnabled( false );
+ showButton = new TQToolButton( functionsBox );
+ showButton->setIconSet( il->loadIconSet( "viewmag", TDEIcon::Small ) );
+ closeButton = new TQToolButton( functionsBox );
+ closeButton->setIconSet( il->loadIconSet( "window-close", TDEIcon::Small ) );
+ resizeButton = new TQToolButton( functionsBox );
+ resizeButton->setIconSet( il->loadIconSet( "2uparrow", TDEIcon::Small ) ); //TODO: give me an icon :)
+
+ saveButton->setTextLabel( i18n( "Save recipe" ), true );
+ saveButton->setUsesTextLabel( true );
+ showButton->setTextLabel( i18n( "Show recipe" ), true );
+ showButton->setUsesTextLabel( true );
+ closeButton->setTextLabel( i18n( "Close" ), true );
+ closeButton->setUsesTextLabel( true );
+ resizeButton->setTextLabel( i18n( "Resize recipe" ), true );
+ resizeButton->setUsesTextLabel( true );
+
+ functionsLayout->layout() ->addItem( new TQSpacerItem( 10, 10, TQSizePolicy::MinimumExpanding, TQSizePolicy::Fixed ) );
+
+ // Dialog design
+ tabWidget->resize( size().expandedTo( minimumSizeHint() ) );
+ clearWState( WState_Polished );
+
+ // Initialize internal data
+ unsavedChanges = false; // Indicates if there's something not saved yet.
+ enableChangedSignal(); // Enables the signal "changed()"
+
+ // Connect signals & Slots
+ connect( changePhotoButton, TQ_SIGNAL( clicked() ), this, TQ_SLOT( changePhoto() ) );
+ connect( clearPhotoButton, TQ_SIGNAL( clicked() ), TQ_SLOT( clearPhoto() ) );
+ connect( upButton, TQ_SIGNAL( clicked() ), this, TQ_SLOT( moveIngredientUp() ) );
+ connect( downButton, TQ_SIGNAL( clicked() ), this, TQ_SLOT( moveIngredientDown() ) );
+ connect( removeButton, TQ_SIGNAL( clicked() ), this, TQ_SLOT( removeIngredient() ) );
+ connect( addButton, TQ_SIGNAL( clicked() ), ingInput, TQ_SLOT( addIngredient() ) );
+ connect( ingParserButton, TQ_SIGNAL( clicked() ), this, TQ_SLOT( slotIngredientParser() ) );
+ connect( photoLabel, TQ_SIGNAL( changed() ), this, TQ_SIGNAL( changed() ) );
+ connect( this, TQ_SIGNAL( changed() ), this, TQ_SLOT( recipeChanged() ) );
+ connect( yieldNumInput, TQ_SIGNAL( textChanged( const TQString & ) ), this, TQ_SLOT( recipeChanged() ) );
+ connect( yieldTypeEdit, TQ_SIGNAL( textChanged( const TQString & ) ), this, TQ_SLOT( recipeChanged() ) );
+ connect( prepTimeEdit, TQ_SIGNAL( valueChanged( const TQTime & ) ), TQ_SLOT( recipeChanged() ) );
+ connect( titleEdit, TQ_SIGNAL( textChanged( const TQString& ) ), this, TQ_SLOT( recipeChanged( const TQString& ) ) );
+ connect( instructionsEdit, TQ_SIGNAL( textChanged() ), this, TQ_SLOT( recipeChanged() ) );
+ connect( addCategoryButton, TQ_SIGNAL( clicked() ), this, TQ_SLOT( addCategory() ) );
+ connect( addAuthorButton, TQ_SIGNAL( clicked() ), this, TQ_SLOT( addAuthor() ) );
+ connect( titleEdit, TQ_SIGNAL( textChanged( const TQString& ) ), this, TQ_SLOT( prepTitleChanged( const TQString& ) ) );
+ connect( ingredientList, TQ_SIGNAL( itemRenamed( TQListViewItem*, const TQString &, int ) ), TQ_SLOT( syncListView( TQListViewItem*, const TQString &, int ) ) );
+
+ connect ( ingInput, TQ_SIGNAL( ingredientEntered(const Ingredient&) ), this, TQ_SLOT( addIngredient(const Ingredient&) ) );
+ connect ( ingInput, TQ_SIGNAL( headerEntered(const Element&) ), this, TQ_SLOT( addIngredientHeader(const Element&) ) );
+
+ connect( propertyStatusLed, TQ_SIGNAL(clicked()), TQ_SLOT(updatePropertyStatus()) );
+ connect( propertyStatusDialog, TQ_SIGNAL(user1Clicked()), TQ_SLOT(updatePropertyStatus()) );
+ connect( propertyStatusButton, TQ_SIGNAL(clicked()), propertyStatusDialog, TQ_SLOT(show()) );
+
+ // Function buttons
+ connect ( saveButton, TQ_SIGNAL( clicked() ), this, TQ_SLOT( save() ) );
+ connect ( closeButton, TQ_SIGNAL( clicked() ), this, TQ_SLOT( closeOptions() ) );
+ connect ( showButton, TQ_SIGNAL( clicked() ), this, TQ_SLOT( showRecipe() ) );
+ connect ( resizeButton, TQ_SIGNAL( clicked() ), this, TQ_SLOT( resizeRecipe() ) );
+ connect ( spellCheckButton, TQ_SIGNAL( clicked() ), this, TQ_SLOT( spellCheck() ) );
+ connect ( this, TQ_SIGNAL( enableSaveOption( bool ) ), this, TQ_SLOT( enableSaveButton( bool ) ) );
+
+ connect ( database, TQ_SIGNAL( recipeRemoved(int) ), this, TQ_SLOT( recipeRemoved(int) ) );
+
+ delete il;
+
+ //FIXME: We've got some sort of build issue... we get undefined references to CreateUnitDialog without this dummy code here
+ CreateUnitDialog d( this, "" );
+}
+
+
+RecipeInputDialog::~RecipeInputDialog()
+{
+ delete loadedRecipe;
+}
+
+void RecipeInputDialog::recipeRemoved( int id )
+{
+ if ( loadedRecipe->recipeID == id ) {
+ loadedRecipe->recipeID = -1;
+ recipeChanged();
+ }
+}
+
+void RecipeInputDialog::prepTitleChanged( const TQString &title )
+{
+ //we don't want the menu to grow due to a long title
+ //### KStringHandler::rsqueeze does this but I can't remember when it was added (compatibility issue...)
+ TQString short_title = title.left( 20 );
+ if ( title.length() > 20 )
+ short_title.append( "..." );
+
+ emit titleChanged( short_title );
+}
+
+int RecipeInputDialog::loadedRecipeID() const
+{
+ return loadedRecipe->recipeID;
+}
+
+void RecipeInputDialog::loadRecipe( int recipeID )
+{
+ emit enableSaveOption( false );
+ unsavedChanges = false;
+
+ //Disable changed() signals
+ enableChangedSignal( false );
+
+ //Empty current recipe
+ loadedRecipe->empty();
+
+ //Set back to the first page
+ tabWidget->setCurrentPage( 0 );
+
+ // Load specified Recipe ID
+ database->loadRecipe( loadedRecipe, RecipeDB::All ^ RecipeDB::Meta ^ RecipeDB::Properties, recipeID );
+
+ reload();
+
+ propertyStatusDialog->hide();
+ updatePropertyStatus();
+
+ //Enable changed() signals
+ enableChangedSignal();
+
+}
+
+void RecipeInputDialog::reload( void )
+{
+ yieldNumInput->setValue( 1, 0 );
+ yieldTypeEdit->setText("");
+ ingredientList->clear();
+ ratingListDisplayWidget->clear();
+ ingInput->clear();
+
+ //Load Values in Interface
+ titleEdit->setText( loadedRecipe->title );
+ instructionsEdit->setText( loadedRecipe->instructions );
+ yieldNumInput->setValue( loadedRecipe->yield.amount, loadedRecipe->yield.amount_offset );
+ yieldTypeEdit->setText( loadedRecipe->yield.type );
+ prepTimeEdit->setTime( loadedRecipe->prepTime );
+
+ //show ingredient list
+ IngredientList list_copy = loadedRecipe->ingList;
+ for ( IngredientList group_list = list_copy.firstGroup(); group_list.count() != 0; group_list = list_copy.nextGroup() ) {
+ TQListViewItem * lastElement = ingredientList->lastItem();
+ TQListViewItem *ing_header = 0;
+
+ TQString group = group_list[ 0 ].group;
+ if ( !group.isEmpty() ) {
+ if ( lastElement && lastElement->parent() )
+ lastElement = lastElement->parent();
+
+ ing_header = new IngGrpListViewItem( ingredientList, lastElement, group_list[ 0 ].group, group_list[ 0 ].groupID );
+ ing_header->setOpen( true );
+ lastElement = ing_header;
+ }
+
+ for ( IngredientList::const_iterator ing_it = group_list.begin(); ing_it != group_list.end(); ++ing_it ) {
+ //Insert ingredient after last one
+ if ( ing_header ) {
+ lastElement = new IngListViewItem ( ing_header, lastElement, *ing_it );
+ }
+ else {
+ if ( lastElement && lastElement->parent() )
+ lastElement = lastElement->parent();
+ lastElement = new IngListViewItem ( ingredientList, lastElement, *ing_it );
+ }
+
+ for ( TQValueList<IngredientData>::const_iterator sub_it = (*ing_it).substitutes.begin(); sub_it != (*ing_it).substitutes.end(); ++sub_it ) {
+ new IngSubListViewItem ( lastElement, *sub_it );
+ lastElement->setOpen(true);
+ }
+
+ //update completion
+ instructionsEdit->addCompletionItem( ( *ing_it ).name );
+ }
+ }
+ //
+ //show photo
+ if ( !loadedRecipe->photo.isNull() ) {
+
+ // //get the photo
+ sourcePhoto = loadedRecipe->photo;
+
+ if ( ( sourcePhoto.width() > photoLabel->width() || sourcePhoto.height() > photoLabel->height() ) || ( sourcePhoto.width() < photoLabel->width() && sourcePhoto.height() < photoLabel->height() ) ) {
+ TQImage pm = sourcePhoto.convertToImage();
+ TQPixmap pm_scaled;
+ pm_scaled.convertFromImage( pm.smoothScale( photoLabel->width(), photoLabel->height(), TQImage::ScaleMin ) );
+ photoLabel->setPixmap( pm_scaled );
+
+ sourcePhoto = pm_scaled; // to save scaled later on
+ }
+ else {
+ photoLabel->setPixmap( sourcePhoto );
+ }
+ }
+ else {
+ TQPixmap photo = TQPixmap( defaultPhoto );
+ photoLabel->setPixmap( photo );
+ sourcePhoto = TQPixmap();
+ }
+
+
+ // Show categories
+ showCategories();
+
+ // Show authors
+ showAuthors();
+
+ // Show ratings
+ for ( RatingList::iterator rating_it = loadedRecipe->ratingList.begin(); rating_it != loadedRecipe->ratingList.end(); ++rating_it ) {
+ RatingDisplayWidget *item = new RatingDisplayWidget;
+ item->rating_it = rating_it;
+ addRating(*rating_it,item);
+ ratingListDisplayWidget->insertItem(item);
+ }
+ ratingListDisplayWidget->ensureCellVisible(0,0);
+
+ // Update yield type auto completion
+ TDECompletion *completion = yieldTypeEdit->completionObject();
+ completion->clear();
+ ElementList yieldList;
+ database->loadYieldTypes( &yieldList );
+ for ( ElementList::const_iterator it = yieldList.begin(); it != yieldList.end(); ++it ) {
+ completion->addItem( (*it).name );
+ }
+}
+
+void RecipeInputDialog::changePhoto( void )
+{
+ // standard filedialog
+ KURL filename = KFileDialog::getOpenURL( TQString::null, TQString( "*.png *.jpg *.jpeg *.xpm *.gif|%1 (*.png *.jpg *.jpeg *.xpm *.gif)" ).arg( i18n( "Images" ) ), this );
+ TQPixmap pixmap ( filename.path() );
+ if ( !( pixmap.isNull() ) ) {
+ // If photo is bigger than the label, or smaller in width, than photoLabel, scale it
+ sourcePhoto = pixmap;
+ if ( ( sourcePhoto.width() > photoLabel->width() || sourcePhoto.height() > photoLabel->height() ) || ( sourcePhoto.width() < photoLabel->width() && sourcePhoto.height() < photoLabel->height() ) ) {
+ TQImage pm = sourcePhoto.convertToImage();
+ TQPixmap pm_scaled;
+ pm_scaled.convertFromImage( pm.smoothScale( photoLabel->width(), photoLabel->height(), TQImage::ScaleMin ) );
+ photoLabel->setPixmap( pm_scaled );
+
+ sourcePhoto = pm_scaled; // to save scaled later on
+ photoLabel->setPixmap( pm_scaled );
+ }
+ else {
+ photoLabel->setPixmap( sourcePhoto );
+ }
+ emit changed();
+ }
+}
+
+void RecipeInputDialog::clearPhoto( void )
+{
+ sourcePhoto = TQPixmap();
+ photoLabel->setPixmap( TQPixmap( defaultPhoto ) );
+
+ emit changed();
+}
+
+void RecipeInputDialog::moveIngredientUp( void )
+{
+ TQListViewItem * it = ingredientList->selectedItem();
+ if ( !it || it->rtti() == INGSUBLISTVIEWITEM_RTTI )
+ return ;
+
+ TQListViewItem *iabove = it->itemAbove();
+ while ( iabove && iabove->rtti() == INGSUBLISTVIEWITEM_RTTI )
+ iabove = iabove->itemAbove();
+
+ if ( iabove ) {
+ if ( it->rtti() == INGGRPLISTVIEWITEM_RTTI ) {
+ if ( iabove->parent() )
+ iabove = iabove->parent();
+
+ int it_index = ingItemIndex( ingredientList, it );
+ int iabove_index = ingItemIndex( ingredientList, iabove );
+
+ iabove->moveItem( it ); //Move the Item
+
+ loadedRecipe->ingList.move( iabove_index, ( iabove->rtti() == INGGRPLISTVIEWITEM_RTTI ) ? iabove->childCount() : 1, it_index + it->childCount() - 1 );
+ }
+ else {
+ int it_index = ingItemIndex( ingredientList, it );
+ int iabove_index = ingItemIndex( ingredientList, iabove );
+ IngredientList::iterator ing = loadedRecipe->ingList.at( it_index );
+
+ if ( iabove->parent() != it->parent() ) {
+ if ( iabove->rtti() == INGGRPLISTVIEWITEM_RTTI && it->parent() ) { //move the item out of the group
+ it->parent() ->takeItem( it );
+ ingredientList->insertItem( it );
+ it->moveItem( ( iabove->itemAbove() ->parent() ) ? iabove->itemAbove() ->parent() : iabove->itemAbove() ); //Move the Item
+ }
+ else { //move the item into the group
+ ingredientList->takeItem( it );
+ iabove->parent() ->insertItem( it );
+ it->moveItem( iabove ); //Move the Item
+ }
+
+ ingredientList->setCurrentItem( it ); //Keep selected
+ }
+ else {
+ iabove->moveItem( it ); //Move the Item
+ loadedRecipe->ingList.move( it_index, iabove_index );
+ }
+
+ if ( it->parent() )
+ ( *ing ).groupID = ( ( IngGrpListViewItem* ) it->parent() ) ->id();
+ else
+ ( *ing ).groupID = -1;
+ }
+
+ emit changed();
+ }
+}
+
+void RecipeInputDialog::moveIngredientDown( void )
+{
+ TQListViewItem * it = ingredientList->selectedItem();
+ if ( !it || it->rtti() == INGSUBLISTVIEWITEM_RTTI )
+ return ;
+
+ TQListViewItem *ibelow = it->itemBelow();
+ while ( ibelow && ibelow->rtti() == INGSUBLISTVIEWITEM_RTTI )
+ ibelow = ibelow->itemBelow();
+
+ if ( ibelow ) {
+ if ( it->rtti() == INGGRPLISTVIEWITEM_RTTI ) {
+ TQListViewItem * next_sibling = it->nextSibling();
+
+ if ( next_sibling ) {
+ int it_index = ingItemIndex( ingredientList, it );
+ int ibelow_index = ingItemIndex( ingredientList, next_sibling );
+
+ it->moveItem( next_sibling ); //Move the Item
+
+ int skip = 0;
+ if ( next_sibling->childCount() > 0 )
+ skip = next_sibling->childCount() - 1;
+
+ loadedRecipe->ingList.move( it_index, it->childCount(), ibelow_index + skip );
+ }
+ }
+ else {
+ int it_index = ingItemIndex( ingredientList, it );
+ int ibelow_index = ingItemIndex( ingredientList, ibelow );
+ IngredientList::iterator ing = loadedRecipe->ingList.at( it_index );
+
+ if ( ibelow->rtti() == INGGRPLISTVIEWITEM_RTTI || ( ibelow->parent() != it->parent() ) ) {
+ if ( ibelow->rtti() == INGGRPLISTVIEWITEM_RTTI && !it->parent() ) { //move the item into the group
+ if ( !it->parent() )
+ ingredientList->takeItem( it );
+ else
+ it->parent() ->takeItem( it );
+
+ ibelow->insertItem( it );
+ }
+ else { //move the item out of the group
+ TQListViewItem *parent = it->parent(); //store this because we can't get it after we do it->takeItem()
+ parent->takeItem( it );
+ ingredientList->insertItem( it );
+ it->moveItem( parent ); //Move the Item
+ }
+
+ ingredientList->setCurrentItem( it ); //Keep selected
+ }
+ else {
+ it->moveItem( ibelow ); //Move the Item
+ loadedRecipe->ingList.move( it_index, ibelow_index );
+ }
+
+ if ( it->parent() )
+ ( *ing ).groupID = ( ( IngGrpListViewItem* ) it->parent() ) ->id();
+ else
+ ( *ing ).groupID = -1;
+ }
+
+ emit changed();
+ }
+ else if ( it->parent() ) {
+ it->parent() ->takeItem( it );
+ ingredientList->insertItem( it );
+ it->moveItem( ( ingredientList->lastItem() ->parent() ) ? ingredientList->lastItem() ->parent() : ingredientList->lastItem() ); //Move the Item
+ ingredientList->setCurrentItem( it ); //Keep selected
+
+ int it_index = ingItemIndex( ingredientList, it );
+ IngredientList::iterator ing = loadedRecipe->ingList.at( it_index );
+ ( *ing ).groupID = -1;
+
+ emit changed();
+ }
+}
+
+void RecipeInputDialog::removeIngredient( void )
+{
+ TQListViewItem * it = ingredientList->selectedItem();
+ if ( it && (it->rtti() == INGLISTVIEWITEM_RTTI || it->rtti() == INGSUBLISTVIEWITEM_RTTI) ) {
+ TQListViewItem *iselect = it->itemBelow();
+ while ( iselect && iselect->rtti() == INGSUBLISTVIEWITEM_RTTI )
+ iselect = iselect->itemBelow();
+
+ if ( !iselect ) {
+ iselect = it->itemAbove();
+ while ( iselect && iselect->rtti() == INGSUBLISTVIEWITEM_RTTI )
+ iselect = iselect->itemAbove();
+ }
+
+ IngListViewItem *ing_item = (IngListViewItem*)it; //we can cast IngSubListViewItem to this too, it's a subclass
+
+ IngredientData &ing = loadedRecipe->ingList.findSubstitute( ing_item->ingredient() );
+
+ //Remove it from the instruction's completion
+ instructionsEdit->removeCompletionItem( ing.name );
+
+ loadedRecipe->ingList.removeSubstitute( ing );
+
+ int ingID = ing_item->ingredient().ingredientID;
+ TQMap<int,TQString>::iterator map_it;
+ if ( (map_it = propertyStatusMapRed.find(ingID)) != propertyStatusMapRed.end() )
+ propertyStatusMapRed.remove( map_it );
+ else if ( (map_it = propertyStatusMapYellow.find(ingID)) != propertyStatusMapYellow.end() )
+ propertyStatusMapYellow.remove( map_it );
+ showStatusIndicator();
+
+ //Now remove the ingredient
+ it->setSelected( false );
+ delete it;
+ if ( iselect )
+ ingredientList->setSelected( iselect, true ); // be careful iselect->setSelected doesn't work this way.
+
+ emit changed();
+ }
+ else if ( it && it->rtti() == INGGRPLISTVIEWITEM_RTTI ) {
+ IngGrpListViewItem * header = ( IngGrpListViewItem* ) it;
+
+ for ( IngListViewItem * sub_item = (IngListViewItem*)header->firstChild(); sub_item; sub_item = (IngListViewItem*)sub_item->nextSibling() ) {
+ IngredientData &ing = loadedRecipe->ingList.findSubstitute( sub_item->ingredient() );
+
+ //Remove it from the instruction's completion
+ instructionsEdit->removeCompletionItem( ing.name );
+
+ loadedRecipe->ingList.removeSubstitute( ing );
+
+ int ingID = sub_item->ingredient().ingredientID;
+ TQMap<int,TQString>::iterator map_it;
+ if ( (map_it = propertyStatusMapRed.find(ingID)) != propertyStatusMapRed.end() )
+ propertyStatusMapRed.remove( map_it );
+ else if ( (map_it = propertyStatusMapYellow.find(ingID)) != propertyStatusMapYellow.end() )
+ propertyStatusMapYellow.remove( map_it );
+ showStatusIndicator();
+ }
+
+ delete header;
+
+ emit changed();
+ }
+
+}
+
+int RecipeInputDialog::createNewYieldIfNecessary( const TQString &yield )
+{
+ if ( yield.stripWhiteSpace().isEmpty() ) //no yield
+ return -1;
+ else
+ {
+ int id = database->findExistingYieldTypeByName( yield );
+ if ( id == -1 ) //creating new
+ {
+ database->createNewYieldType( yield );
+ id = database->lastInsertID();
+ }
+
+ return id;
+ }
+}
+
+void RecipeInputDialog::syncListView( TQListViewItem* it, const TQString &new_text, int col )
+{
+ if ( it->rtti() != INGLISTVIEWITEM_RTTI )
+ return ;
+
+ IngListViewItem *ing_item = ( IngListViewItem* ) it;
+
+ IngredientData &new_ing = loadedRecipe->ingList.findSubstitute( ing_item->ingredient() );
+
+ switch ( col ) {
+ case 1: //amount
+ {
+ bool ok;
+
+ Ingredient new_ing_amount;
+ new_ing_amount.setAmount(new_text,&ok);
+
+ if ( ok )
+ {
+ if ( new_ing.amount != new_ing_amount.amount ||
+ new_ing.amount_offset != new_ing_amount.amount_offset ) {
+ new_ing.amount = new_ing_amount.amount;
+ new_ing.amount_offset = new_ing_amount.amount_offset;
+ if ( !new_text.isEmpty() )
+ ing_item->setAmount( new_ing_amount.amount, new_ing_amount.amount_offset );
+
+ new_ing.amount = new_ing_amount.amount;
+ new_ing.amount_offset = new_ing_amount.amount_offset;
+ emit changed();
+ }
+ }
+ else
+ {
+ if ( !new_text.isEmpty() )
+ ing_item->setAmount( new_ing.amount, new_ing.amount_offset );
+ }
+
+ break;
+ }
+ case 2: //unit
+ {
+ Unit old_unit = new_ing.units;
+
+ if ( new_text.length() > uint(database->maxUnitNameLength()) )
+ {
+ KMessageBox::error( this, TQString( i18n( "Unit name cannot be longer than %1 characters." ) ).arg( database->maxUnitNameLength() ) );
+ ing_item->setUnit( old_unit );
+ break;
+ }
+
+ TQString approp_unit = new_ing.amount > 1 ? new_ing.units.plural : new_ing.units.name;
+ if ( approp_unit != new_text.stripWhiteSpace() )
+ {
+ Unit new_unit;
+ int new_id = IngredientInputWidget::createNewUnitIfNecessary( new_text.stripWhiteSpace(), new_ing.amount > 1, ing_item->ingredient().ingredientID, new_unit, database );
+
+ if ( new_id != -1 ) {
+ new_ing.units = new_unit;
+ new_ing.units.id = new_id;
+
+ ing_item->setUnit( new_ing.units );
+
+ updatePropertyStatus();
+ emit changed();
+ }
+ else {
+ ing_item->setUnit( old_unit );
+ }
+ }
+ break;
+ }
+ case 3: //prep method
+ {
+ TQString old_text = new_ing.prepMethodList.join(",");
+
+ TQStringList prepMethodList = TQStringList::split(",",new_text.stripWhiteSpace());
+
+ for ( TQStringList::const_iterator it = prepMethodList.begin(); it != prepMethodList.end(); ++it ) {
+ if ( (*it).stripWhiteSpace().length() > uint(database->maxPrepMethodNameLength()) )
+ {
+ KMessageBox::error( this, TQString( i18n( "Preparation method cannot be longer than %1 characters." ) ).arg( database->maxPrepMethodNameLength() ) );
+ ing_item->setPrepMethod( old_text );
+ break;
+ }
+ }
+
+ if ( old_text != new_text.stripWhiteSpace() )
+ {
+ new_ing.prepMethodList = ElementList::split(",",new_text.stripWhiteSpace());
+ TQValueList<int> new_ids = IngredientInputWidget::createNewPrepIfNecessary( new_ing.prepMethodList, database );
+
+ TQValueList<int>::const_iterator id_it = new_ids.begin();
+ for ( ElementList::iterator it = new_ing.prepMethodList.begin(); it != new_ing.prepMethodList.end(); ++it, ++id_it ) {
+ (*it).id = *id_it;
+ }
+
+ updatePropertyStatus();
+ emit changed();
+ }
+ break;
+ }
+ }
+}
+
+void RecipeInputDialog::recipeChanged( void )
+{
+ if ( changedSignalEnabled ) {
+ // Enable Save Button
+ emit enableSaveOption( true );
+ emit createButton( this, titleEdit->text() );
+ unsavedChanges = true;
+
+ }
+
+}
+
+void RecipeInputDialog::recipeChanged( const TQString & /*t*/ )
+{
+ recipeChanged(); // jumps to the real slot function
+}
+
+void RecipeInputDialog::enableChangedSignal( bool en )
+{
+ changedSignalEnabled = en;
+}
+
+bool RecipeInputDialog::save ( void )
+{
+ //check bounds first
+ if ( titleEdit->text().length() > uint(database->maxRecipeTitleLength()) ) {
+ KMessageBox::error( this, TQString( i18n( "Recipe title cannot be longer than %1 characters." ) ).arg( database->maxRecipeTitleLength() ), i18n( "Unable to save recipe" ) );
+ return false;
+ }
+
+ emit enableSaveOption( false );
+ saveRecipe();
+ unsavedChanges = false;
+
+ return true;
+}
+
+void RecipeInputDialog::saveRecipe( void )
+{
+ // Nothing except for the ingredient list (loadedRecipe->ingList)
+ // was stored before for performance. (recipeID is already there)
+
+ loadedRecipe->photo = sourcePhoto;
+ loadedRecipe->instructions = instructionsEdit->text();
+ loadedRecipe->title = titleEdit->text();
+ yieldNumInput->value(loadedRecipe->yield.amount,loadedRecipe->yield.amount_offset);
+ loadedRecipe->yield.type_id = createNewYieldIfNecessary(yieldTypeEdit->text());
+ loadedRecipe->prepTime = prepTimeEdit->time();
+
+ // Now save()
+ kdDebug() << "Saving..." << endl;
+ database->saveRecipe( loadedRecipe );
+
+
+}
+
+void RecipeInputDialog::newRecipe( void )
+{
+ loadedRecipe->empty();
+ TQPixmap image( defaultPhoto );
+ photoLabel->setPixmap( image );
+ sourcePhoto = TQPixmap();
+
+ instructionsEdit->setText( i18n( "Write the recipe instructions here" ) );
+ instructionsEdit->clearCompletionItems();
+ titleEdit->setText( i18n( "Write the recipe title here" ) );
+ ingredientList->clear();
+ authorShow->clear();
+ categoryShow->clear();
+ yieldNumInput->setValue( 1, 0 );
+ yieldTypeEdit->setText("");
+ prepTimeEdit->setTime( TQTime( 0, 0 ) );
+
+ instructionsEdit->selectAll();
+
+ //Set back to the first page
+ tabWidget->setCurrentPage( 0 );
+
+ ingInput->clear();
+
+ //Set focus to the title
+ titleEdit->setFocus();
+ titleEdit->selectAll();
+
+ //clear status info
+ propertyStatusMapRed.clear();
+ propertyStatusMapYellow.clear();
+ showStatusIndicator();
+}
+
+bool RecipeInputDialog::everythingSaved()
+{
+ return ( !( unsavedChanges ) );
+}
+
+void RecipeInputDialog::addCategory( void )
+{
+ SelectCategoriesDialog *editCategoriesDialog = new SelectCategoriesDialog( this, loadedRecipe->categoryList, database );
+
+ if ( editCategoriesDialog->exec() == TQDialog::Accepted ) { // user presses Ok
+ loadedRecipe->categoryList.clear();
+ editCategoriesDialog->getSelectedCategories( &( loadedRecipe->categoryList ) ); // get the category list chosen
+ emit( recipeChanged() ); //Indicate that the recipe changed
+
+ }
+
+ delete editCategoriesDialog;
+
+ // show category list
+ showCategories();
+
+
+}
+
+void RecipeInputDialog::showCategories( void )
+{
+ TQString categories;
+ for ( ElementList::const_iterator cat_it = loadedRecipe->categoryList.begin(); cat_it != loadedRecipe->categoryList.end(); ++cat_it ) {
+ if ( !categories.isEmpty() )
+ categories += ",";
+ categories += ( *cat_it ).name;
+ }
+ categoryShow->setText( categories );
+}
+
+void RecipeInputDialog::addAuthor( void )
+{
+ SelectAuthorsDialog * editAuthorsDialog = new SelectAuthorsDialog( this, loadedRecipe->authorList, database );
+
+
+ if ( editAuthorsDialog->exec() == TQDialog::Accepted ) { // user presses Ok
+ loadedRecipe->authorList.clear();
+ editAuthorsDialog->getSelectedAuthors( &( loadedRecipe->authorList ) ); // get the category list chosen
+ emit( recipeChanged() ); //Indicate that the recipe changed
+ }
+
+ delete editAuthorsDialog;
+
+ // show authors list
+ showAuthors();
+}
+
+void RecipeInputDialog::showAuthors( void )
+{
+ TQString authors;
+ for ( ElementList::const_iterator author_it = loadedRecipe->authorList.begin(); author_it != loadedRecipe->authorList.end(); ++author_it ) {
+ if ( !authors.isEmpty() )
+ authors += ",";
+ authors += ( *author_it ).name;
+ }
+ authorShow->setText( authors );
+}
+
+void RecipeInputDialog::enableSaveButton( bool enabled )
+{
+ saveButton->setEnabled( enabled );
+}
+
+void RecipeInputDialog::closeOptions( void )
+{
+
+ // First check if there's anything unsaved in the recipe
+ if ( unsavedChanges ) {
+
+ switch ( KMessageBox::questionYesNoCancel( this, i18n( "This recipe contains unsaved changes.\n" "Would you like to save it before closing?" ), i18n( "Unsaved changes" ) ) ) {
+ case KMessageBox::Yes:
+ save();
+ break;
+ case KMessageBox::No:
+ break;
+ case KMessageBox::Cancel:
+ return ;
+ }
+
+ }
+
+ emit enableSaveOption( false );
+ unsavedChanges = false;
+
+ // Now close really
+ emit closeRecipe();
+
+
+}
+
+void RecipeInputDialog::showRecipe( void )
+{
+ // First check if there's anything unsaved in the recipe
+
+ if ( loadedRecipe->recipeID == -1 ) {
+ switch ( KMessageBox::questionYesNo( this, i18n( "You need to save the recipe before displaying it. Would you like to save it now?" ), i18n( "Unsaved changes" ) ) ) {
+ case KMessageBox::Yes:
+ save();
+ break;
+ case KMessageBox::No:
+ return ;
+ }
+ }
+ else if ( unsavedChanges ) {
+
+ switch ( KMessageBox::questionYesNoCancel( this, i18n( "This recipe has changes that will not be displayed unless the recipe is saved. Would you like to save it now?" ), i18n( "Unsaved changes" ) ) ) {
+ case KMessageBox::Yes:
+ save();
+ break;
+ case KMessageBox::No:
+ break;
+ case KMessageBox::Cancel:
+ return ;
+ }
+
+ }
+
+ // Now open it really
+ emit showRecipe( loadedRecipe->recipeID );
+}
+
+void RecipeInputDialog::spellCheck( void )
+{
+ TQString text = instructionsEdit->text();
+ KSpellConfig default_cfg( this );
+ KSpell::modalCheck( text, &default_cfg );
+ KMessageBox::information( this, i18n( "Spell check complete." ) );
+
+ if ( text != instructionsEdit->text() ) //check if there were changes
+ instructionsEdit->setText( text );
+}
+
+void RecipeInputDialog::resizeRecipe( void )
+{
+ yieldNumInput->value( loadedRecipe->yield.amount, loadedRecipe->yield.amount_offset );
+ ResizeRecipeDialog dlg( this, loadedRecipe );
+
+ if ( dlg.exec() == TQDialog::Accepted )
+ reload();
+}
+
+int RecipeInputDialog::ingItemIndex( TQListView *listview, const TQListViewItem *item ) const
+{
+ if ( !item )
+ return -1;
+
+ if ( item == listview->firstChild() )
+ return 0;
+ else {
+ TQListViewItemIterator it( listview->firstChild() );
+ uint j = 0;
+ for ( ; it.current() && it.current() != item; ++it ) {
+ if ( it.current() ->rtti() == INGLISTVIEWITEM_RTTI ) {
+ if ( !it.current()->parent() || it.current()->parent()->rtti() == INGGRPLISTVIEWITEM_RTTI )
+ j++;
+ }
+ }
+
+ if ( !it.current() )
+ return -1;
+
+ return j;
+ }
+}
+
+void RecipeInputDialog::slotIngredientParser()
+{
+ UnitList units;
+ database->loadUnits(&units);
+ IngredientParserDialog dlg(units,this);
+ if ( dlg.exec() == TQDialog::Accepted ) {
+ IngredientList ings = dlg.ingredients();
+ TQStringList usedGroups;
+ bool haveHeader = false;
+ for ( IngredientList::iterator it = ings.begin(); it != ings.end(); ++it ) {
+ if ( !(*it).group.isEmpty() && usedGroups.find((*it).group) == usedGroups.end() ) {
+ int id = IngredientInputWidget::createNewGroupIfNecessary((*it).group,database);
+ addIngredientHeader( Element((*it).group, id) );
+ haveHeader = true;
+ usedGroups << (*it).group;
+ }
+ (*it).ingredientID = IngredientInputWidget::createNewIngredientIfNecessary((*it).name,database);
+ (*it).units.id = IngredientInputWidget::createNewUnitIfNecessary((*it).units.name,false,(*it).ingredientID,(*it).units,database);
+
+ TQValueList<int> prepIDs = IngredientInputWidget::createNewPrepIfNecessary((*it).prepMethodList,database);
+ TQValueList<int>::const_iterator prep_id_it = prepIDs.begin();
+ for ( ElementList::iterator prep_it = (*it).prepMethodList.begin(); prep_it != (*it).prepMethodList.end(); ++prep_it, ++prep_id_it ) {
+ (*prep_it).id = *prep_id_it;
+ }
+
+ addIngredient( *it, !haveHeader );
+
+ if ( usedGroups.count() > 0 && (*it).group.isEmpty() ) {
+ TQListViewItem *last_item = ingredientList->lastItem();
+ if ( last_item->parent() ) {
+ last_item->parent()->takeItem( last_item );
+ ingredientList->insertItem( last_item );
+ last_item->moveItem( ingredientList->lastItem()->parent() );
+ }
+ }
+ }
+ }
+}
+
+void RecipeInputDialog::slotAddRating()
+{
+ ElementList criteriaList;
+ database->loadRatingCriterion(&criteriaList);
+
+ EditRatingDialog ratingDlg(criteriaList,this);
+ if ( ratingDlg.exec() == TQDialog::Accepted ) {
+ Rating r = ratingDlg.rating();
+
+ for ( RatingCriteriaList::iterator rc_it = r.ratingCriteriaList.begin(); rc_it != r.ratingCriteriaList.end(); ++rc_it ) {
+ int criteria_id = database->findExistingRatingByName((*rc_it).name);
+ if ( criteria_id == -1 ) {
+ database->createNewRating((*rc_it).name);
+ criteria_id = database->lastInsertID();
+ }
+ (*rc_it).id = criteria_id;
+ }
+
+ RatingDisplayWidget *item = new RatingDisplayWidget;
+ item->rating_it = loadedRecipe->ratingList.append(r);
+ addRating(r,item);
+ ratingListDisplayWidget->insertItem(item,0);
+ emit( recipeChanged() ); //Indicate that the recipe changed
+ }
+}
+
+void RecipeInputDialog::addRating( const Rating &rating, RatingDisplayWidget *item )
+{
+ int average = tqRound(rating.average());
+ if ( average >= 0 )
+ item->icon->setPixmap( UserIcon(TQString("rating%1").arg(average) ) );
+ else //no rating criteria, therefore no average (we don't want to automatically assume a zero average)
+ item->icon->clear();
+
+ item->raterName->setText(rating.rater);
+ item->comment->setText(rating.comment);
+
+ item->criteriaListView->clear();
+ for ( RatingCriteriaList::const_iterator rc_it = rating.ratingCriteriaList.begin(); rc_it != rating.ratingCriteriaList.end(); ++rc_it ) {
+ TQListViewItem * it = new TQListViewItem(item->criteriaListView,(*rc_it).name);
+
+ int stars = int((*rc_it).stars * 2); //multiply by two to make it easier to work with half-stars
+
+ TQPixmap star = UserIcon(TQString::fromLatin1("star_on"));
+ int pixmapWidth = 18*(stars/2)+((stars%2==1)?9:0);
+ TQPixmap generatedPixmap(pixmapWidth,18);
+
+ if ( !generatedPixmap.isNull() ) { //there aren't zero stars
+ generatedPixmap.fill();
+ TQPainter painter( &generatedPixmap );
+ painter.drawTiledPixmap(0,0,pixmapWidth,18,star);
+ it->setPixmap(1,generatedPixmap);
+ }
+ }
+
+ item->buttonEdit->disconnect();
+ item->buttonRemove->disconnect();
+ connect(item->buttonEdit, TQ_SIGNAL(clicked()),
+ this, TQ_SLOT(slotEditRating()));
+ connect(item->buttonRemove, TQ_SIGNAL(clicked()),
+ this, TQ_SLOT(slotRemoveRating()));
+}
+
+void RecipeInputDialog::slotEditRating()
+{
+ RatingDisplayWidget *sender = (RatingDisplayWidget*)(TQObject::sender()->parent());
+
+ ElementList criteriaList;
+ database->loadRatingCriterion(&criteriaList);
+
+ EditRatingDialog ratingDlg(criteriaList,*sender->rating_it,this);
+ if ( ratingDlg.exec() == TQDialog::Accepted ) {
+ Rating r = ratingDlg.rating();
+
+ for ( RatingCriteriaList::iterator rc_it = r.ratingCriteriaList.begin(); rc_it != r.ratingCriteriaList.end(); ++rc_it ) {
+ int criteria_id = database->findExistingRatingByName((*rc_it).name);
+ if ( criteria_id == -1 ) {
+ database->createNewRating((*rc_it).name);
+ criteria_id = database->lastInsertID();
+ }
+ (*rc_it).id = criteria_id;
+ }
+
+ (*sender->rating_it) = r;
+ addRating(r,sender);
+ emit recipeChanged(); //Indicate that the recipe changed
+ }
+}
+
+void RecipeInputDialog::slotRemoveRating()
+{
+ RatingDisplayWidget *sender = (RatingDisplayWidget*)(TQObject::sender()->parent());
+ loadedRecipe->ratingList.remove(sender->rating_it);
+
+ //FIXME: sender is removed but never deleted (sender->deleteLater() doesn't work)
+ ratingListDisplayWidget->removeItem(sender);
+
+ emit recipeChanged(); //Indicate that the recipe changed
+}
+
+void RecipeInputDialog::addIngredient( const Ingredient &ing, bool noHeader )
+{
+ Ingredient ingCopy = ing;
+
+ //Append to the ListView
+ TQListViewItem* lastElement = ingredientList->lastItem();
+ while ( lastElement && lastElement->rtti() == INGSUBLISTVIEWITEM_RTTI )
+ lastElement = lastElement->itemAbove();
+
+ if ( noHeader && lastElement )
+ lastElement = (lastElement->parent())?lastElement->parent():lastElement;
+
+ if ( !noHeader && lastElement &&
+ ( lastElement->rtti() == INGGRPLISTVIEWITEM_RTTI || ( lastElement->parent() && lastElement->parent() ->rtti() == INGGRPLISTVIEWITEM_RTTI ) ) )
+ {
+ IngGrpListViewItem * header = ( lastElement->parent() ) ? ( IngGrpListViewItem* ) lastElement->parent() : ( IngGrpListViewItem* ) lastElement;
+
+ ingCopy.groupID = header->id();
+
+ lastElement = new IngListViewItem( header, lastElement, ingCopy );
+ for ( TQValueList<IngredientData>::const_iterator it = ingCopy.substitutes.begin(); it != ingCopy.substitutes.end(); ++it ) {
+ new IngSubListViewItem( lastElement, *it );
+ }
+ lastElement->setOpen(true);
+ }
+ else {
+ lastElement = new IngListViewItem( ingredientList, lastElement, ingCopy );
+ for ( TQValueList<IngredientData>::const_iterator it = ing.substitutes.begin(); it != ing.substitutes.end(); ++it ) {
+ new IngSubListViewItem( lastElement, *it );
+ }
+ lastElement->setOpen(true);
+ }
+
+ //append to recipe
+ loadedRecipe->ingList.append( ingCopy );
+
+ //update the completion in the instructions edit
+ instructionsEdit->addCompletionItem( ingCopy.name );
+
+ updatePropertyStatus( ingCopy, true );
+
+ emit changed();
+}
+
+void RecipeInputDialog::addIngredientHeader( const Element &header )
+{
+ TQListViewItem *last_item = ingredientList->lastItem();
+ if ( last_item && last_item->parent() )
+ last_item = last_item->parent();
+
+ IngGrpListViewItem *ing_header = new IngGrpListViewItem( ingredientList, last_item, header.name, header.id );
+ ing_header->setOpen( true );
+}
+
+void RecipeInputDialog::updatePropertyStatus()
+{
+ propertyStatusMapRed.clear();
+ propertyStatusMapYellow.clear();
+
+ for ( IngredientList::const_iterator ing_it = loadedRecipe->ingList.begin(); ing_it != loadedRecipe->ingList.end(); ++ing_it ) {
+ updatePropertyStatus( *ing_it, false );
+ }
+
+ showStatusIndicator();
+}
+
+void RecipeInputDialog::updatePropertyStatus( const Ingredient &ing, bool updateIndicator )
+{
+ IngredientPropertyList ingPropertyList;
+ database->loadProperties( &ingPropertyList, ing.ingredientID );
+
+ if ( ingPropertyList.count() == 0 ) {
+ propertyStatusMapRed.insert(ing.ingredientID,TQString(i18n("<b>%1:</b> No nutrient information available")).arg(ing.name));
+ }
+
+ TQMap<int,bool> ratioCache; //unit->conversion possible
+ IngredientPropertyList::const_iterator prop_it;
+ for ( prop_it = ingPropertyList.begin(); prop_it != ingPropertyList.end(); ++prop_it ) {
+ Ingredient result;
+
+ TQMap<int,bool>::const_iterator cache_it = ratioCache.find((*prop_it).perUnit.id);
+ if ( cache_it == ratioCache.end() ) {
+ RecipeDB::ConversionStatus status = database->convertIngredientUnits( ing, (*prop_it).perUnit, result );
+ ratioCache.insert((*prop_it).perUnit.id,status==RecipeDB::Success||status==RecipeDB::MismatchedPrepMethod);
+
+ switch ( status ) {
+ case RecipeDB::Success: break;
+ case RecipeDB::MissingUnitConversion: {
+ if ( ing.units.type != Unit::Other && ing.units.type == (*prop_it).perUnit.type ) {
+ propertyStatusMapRed.insert(ing.ingredientID,TQString(i18n("<b>%3:</b> Unit conversion missing for conversion from '%1' to '%2'"))
+ .arg(ing.units.name.isEmpty()?i18n("-No unit-"):ing.units.name)
+ .arg((*prop_it).perUnit.name)
+ .arg(ing.name));
+ } else {
+ WeightList weights = database->ingredientWeightUnits( ing.ingredientID );
+ TQValueList< TQPair<int,int> > usedIds;
+ TQStringList missingConversions;
+ for ( WeightList::const_iterator weight_it = weights.begin(); weight_it != weights.end(); ++weight_it ) {
+ //skip entries that only differ in how it's prepared
+ TQPair<int,int> usedPair((*weight_it).perAmountUnitID,(*weight_it).weightUnitID);
+ if ( usedIds.find(usedPair) != usedIds.end() )
+ continue;
+
+ TQString toUnit = database->unitName((*weight_it).perAmountUnitID).name;
+ if ( toUnit.isEmpty() ) toUnit = i18n("-No unit-");
+
+ TQString fromUnit = database->unitName((*weight_it).weightUnitID).name;
+ if ( fromUnit.isEmpty() ) fromUnit = i18n("-No unit-");
+
+ TQString ingUnit = ing.units.name;
+ if ( ingUnit.isEmpty() ) ingUnit = i18n("-No unit-");
+
+ TQString propUnit = (*prop_it).perUnit.name;
+ if ( propUnit.isEmpty() ) propUnit = i18n("-No unit-");
+
+ missingConversions << conversionPath( ingUnit, toUnit, fromUnit, propUnit);
+
+ usedIds << usedPair;
+ }
+ propertyStatusMapRed.insert(ing.ingredientID,TQString(i18n("<b>%1:</b> Either an appropriate ingredient weight entry is needed, or Krecipes needs conversion information to perform one of the following conversions: %2"))
+ .arg(ing.name)
+ .arg("<ul><li>"+missingConversions.join("</li><li>")+"</li></ul>")
+ );
+ }
+ break;
+ }
+ case RecipeDB::MissingIngredientWeight:
+ propertyStatusMapRed.insert(ing.ingredientID,TQString(i18n("<b>%1:</b> No ingredient weight entries")).arg(ing.name));
+ break;
+ case RecipeDB::MismatchedPrepMethod:
+ if ( ing.prepMethodList.count() == 0 )
+ propertyStatusMapRed.insert(ing.ingredientID,TQString(i18n("<b>%1:</b> There is no ingredient weight entry for when no preparation method is specified")).arg(ing.name));
+ else
+ propertyStatusMapRed.insert(ing.ingredientID,TQString(i18n("<b>%1:</b> There is no ingredient weight entry for when prepared in any of the following manners: %2")).arg(ing.name).arg("<ul><li>"+ing.prepMethodList.join("</li><li>")+"</li></ul>"));
+ break;
+ case RecipeDB::MismatchedPrepMethodUsingApprox:
+ propertyStatusMapYellow.insert(ing.ingredientID,TQString(i18n("<b>%1:</b> There is no ingredient weight entry for when prepared in any of the following manners (defaulting to a weight entry without a preparation method specified): %2")).arg(ing.name).arg("<ul><li>"+ing.prepMethodList.join("</li><li>")+"</li></ul>"));
+ break;
+ default: kdDebug()<<"Code error: Unhandled conversion status code "<<status<<endl; break;
+ }
+ }
+ }
+
+ if ( updateIndicator )
+ showStatusIndicator();
+}
+
+void RecipeInputDialog::showStatusIndicator()
+{
+ if ( propertyStatusMapRed.count() == 0 ) {
+ if ( propertyStatusMapYellow.count() == 0 ) {
+ propertyStatusLed->setColor( TQt::green );
+ propertyStatusLabel->setText( i18n("Complete") );
+ propertyStatusButton->setEnabled(false);
+ }
+ else {
+ propertyStatusLed->setColor( TQt::yellow );
+ propertyStatusLabel->setText( i18n("Complete, but approximations made") );
+ propertyStatusButton->setEnabled(true);
+ }
+ }
+ else {
+ propertyStatusLed->setColor( TQt::red );
+ propertyStatusLabel->setText( i18n("Incomplete") );
+ propertyStatusButton->setEnabled(true);
+ }
+
+ if ( propertyStatusMapRed.count() == 0 && propertyStatusMapYellow.count() == 0 )
+ propertyStatusDialog->hide();
+ else
+ statusTextView->setText(statusMessage());
+}
+
+TQString RecipeInputDialog::statusMessage() const
+{
+ TQString statusMessage;
+
+ if ( propertyStatusMapRed.count() > 0 ) {
+ statusMessage.append( i18n("The nutrient information for this recipe is incomplete because the following information is missing:") );
+ statusMessage.append("<ul>");
+ for ( TQMap<int,TQString>::const_iterator it = propertyStatusMapRed.begin(); it != propertyStatusMapRed.end(); ++it ) {
+ statusMessage.append("<li>");
+ statusMessage.append(it.data());
+ statusMessage.append("</li>");
+ }
+ statusMessage.append("</ul>");
+ }
+
+ if ( propertyStatusMapYellow.count() > 0 ) {
+ statusMessage.append( i18n("The following approximations will be made when determining nutrient information:") );
+ statusMessage.append("<ul>");
+ for ( TQMap<int,TQString>::const_iterator it = propertyStatusMapYellow.begin(); it != propertyStatusMapYellow.end(); ++it ) {
+ statusMessage.append("<li>");
+ statusMessage.append(it.data());
+ statusMessage.append("</li>");
+ }
+ statusMessage.append("</ul>");
+ }
+
+ return statusMessage;
+}
+
+TQString RecipeInputDialog::conversionPath( const TQString &ingUnit, const TQString &toUnit, const TQString &fromUnit, const TQString &propUnit ) const
+{
+ TQString path = "'"+ingUnit+"'";
+
+ TQString lastUnit = ingUnit;
+ if ( lastUnit != toUnit ) {
+ path.append(" =&gt; '"+toUnit+"'");
+ lastUnit = toUnit;
+ }
+ if ( lastUnit != fromUnit ) {
+ path.append(" =&gt; '"+fromUnit+"'");
+ lastUnit = fromUnit;
+ }
+ if ( lastUnit != propUnit ) {
+ path.append(" =&gt; '"+propUnit+"'");
+ lastUnit = propUnit;
+ }
+ return path;
+}
+
+#include "recipeinputdialog.moc"
diff --git a/src/dialogs/recipeinputdialog.h b/src/dialogs/recipeinputdialog.h
new file mode 100644
index 0000000..dd9a623
--- /dev/null
+++ b/src/dialogs/recipeinputdialog.h
@@ -0,0 +1,228 @@
+/***************************************************************************
+* Copyright (C) 2003-2005 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. *
+***************************************************************************/
+
+#ifndef RECIPEINPUTDIALOG_H
+#define RECIPEINPUTDIALOG_H
+
+#include <kdialog.h>
+#include <ktextedit.h>
+#include <klineedit.h>
+#include <kcombobox.h>
+#include <tdelistview.h>
+#include <knuminput.h>
+#include <kpushbutton.h>
+#include <kiconloader.h>
+#include <kled.h>
+
+#include <tqlabel.h>
+#include <tqgroupbox.h>
+#include <tqmap.h>
+#include <tqobject.h>
+#include <tqtabwidget.h>
+#include <tqtoolbutton.h>
+#include <tqvbox.h>
+
+#include "datablocks/elementlist.h"
+
+class TQTabWidget;
+class TQTimeEdit;
+class TQDragEvent;
+class TQButtonGroup;
+class TQWidgetStack;
+class TQTextEdit;
+
+class KreTextEdit;
+class KWidgetListbox;
+class KDialogBase;
+
+class ImageDropLabel;
+class Recipe;
+class ElementList;
+class RecipeDB;
+class FractionInput;
+class Ingredient;
+class Rating;
+class RatingDisplayWidget;
+class IngredientInputWidget;
+class ClickableLed;
+
+/**
+@author Unai Garro
+*/
+class RecipeInputDialog: public TQVBox
+{
+ TQ_OBJECT
+
+public:
+
+ RecipeInputDialog( TQWidget* parent, RecipeDB* db );
+ void loadRecipe( int recipeID );
+ ~RecipeInputDialog();
+ void newRecipe( void );
+ bool everythingSaved();
+ void reload( void );
+ int loadedRecipeID() const;
+
+private:
+
+ // Internal Data
+ Recipe *loadedRecipe; //Loaded Recipe
+ RecipeDB *database;
+ bool changedSignalEnabled;
+ bool unsavedChanges;
+
+ // Widgets
+ TQTabWidget* tabWidget;
+ TQGroupBox* recipeTab;
+ TQGroupBox* instructionsTab;
+
+ //Recipe Photo
+ ImageDropLabel *photoLabel;
+ TQPixmap sourcePhoto;
+ TQPushButton *changePhotoButton;
+
+ //Recipe Body
+ KreTextEdit* instructionsEdit;
+ TQLabel* titleLabel;
+ KLineEdit* titleEdit;
+
+ //Additional recipe data
+ TQLabel* yieldLabel;
+ FractionInput* yieldNumInput;
+ KLineEdit* yieldTypeEdit;
+ TQTimeEdit *prepTimeEdit;
+ TQLabel* authorLabel;
+ KLineEdit* authorShow;
+ TQPushButton* addAuthorButton;
+ TQLabel* categoryLabel;
+ KLineEdit* categoryShow;
+ TQPushButton* addCategoryButton;
+
+ //Ingredient inputs
+ TDEListView* ingredientList;
+ TQGroupBox *ingredientGBox;
+ IngredientInputWidget *ingInput;
+ ClickableLed *propertyStatusLed;
+ TQLabel *propertyStatusLabel;
+ TQPushButton *propertyStatusButton;
+ TQTextEdit *statusTextView;
+ KDialogBase *propertyStatusDialog;
+
+ // Buttons to move ingredients up & down...
+ KPushButton* upButton;
+ KPushButton* downButton;
+ KPushButton* removeButton;
+ KPushButton* addButton;
+ KPushButton* ingParserButton;
+
+ //Function buttons
+ TQGroupBox* functionsBox;
+ TQToolButton* saveButton;
+ TQToolButton* closeButton;
+ TQToolButton* showButton;
+ TQToolButton* resizeButton;
+
+ TQToolButton* spellCheckButton;
+
+ KWidgetListbox *ratingListDisplayWidget;
+
+ TQMap<int,TQString> propertyStatusMapRed;
+ TQMap<int,TQString> propertyStatusMapYellow;
+
+ // Internal functions
+ int createNewYieldIfNecessary( const TQString &yield );
+ void saveRecipe( void );
+ void showCategories( void );
+ void showAuthors( void );
+ int ingItemIndex( TQListView *listview, const TQListViewItem *item ) const;
+ void addRating( const Rating &rating, RatingDisplayWidget *item );
+ TQString statusMessage() const;
+ TQString conversionPath( const TQString &ingUnit, const TQString &toUnit, const TQString &fromUnit, const TQString &propUnit ) const;
+
+ // Signals & Slots
+
+private slots:
+ void changePhoto( void );
+ void clearPhoto( void );
+ void moveIngredientUp( void );
+ void moveIngredientDown( void );
+ void removeIngredient( void );
+ void syncListView( TQListViewItem* it, const TQString &new_text, int col );
+ void recipeChanged( void );
+ void recipeChanged( const TQString &t );
+ void enableChangedSignal( bool en = true );
+ void addCategory( void );
+ void addAuthor( void );
+ void enableSaveButton( bool enabled );
+ void closeOptions( void );
+ void showRecipe( void );
+ void prepTitleChanged( const TQString &title );
+ void recipeRemoved( int id );
+ void slotIngredientParser();
+ void slotAddRating();
+ void slotEditRating();
+ void slotRemoveRating();
+ void addIngredient( const Ingredient &ing, bool noHeader = false );
+ void addIngredientHeader( const Element &header );
+ void updatePropertyStatus();
+ void updatePropertyStatus( const Ingredient &ing, bool updateIndicator );
+ void showStatusIndicator();
+
+public slots:
+ bool save ( void ); // Activated when krecipes.cpp sends signal save()
+ void spellCheck( void );
+ void resizeRecipe( void );
+
+signals:
+ void changed( void );
+ void closeRecipe( void );
+ void createButton( TQWidget* w, const TQString &title );
+ void enableSaveOption( bool en = true );
+ void showRecipe( int recipeID ); //Indicates krecipesview to show it
+ void titleChanged( const TQString &title );
+
+
+};
+
+class ClickableLed : public KLed
+{
+TQ_OBJECT
+
+public:
+ ClickableLed( TQWidget *parent );
+
+protected:
+ virtual void mouseReleaseEvent( TQMouseEvent* );
+
+signals:
+ void clicked();
+};
+
+class ImageDropLabel : public TQLabel
+{
+ TQ_OBJECT
+
+public:
+ ImageDropLabel( TQWidget *parent, TQPixmap &_sourcePhoto );
+
+signals:
+ void changed();
+
+protected:
+ void dragEnterEvent( TQDragEnterEvent* event );
+ void dropEvent( TQDropEvent* event );
+
+private:
+ TQPixmap &sourcePhoto;
+};
+
+#endif
diff --git a/src/dialogs/recipeprintpreview.cpp b/src/dialogs/recipeprintpreview.cpp
new file mode 100644
index 0000000..7350d11
--- /dev/null
+++ b/src/dialogs/recipeprintpreview.cpp
@@ -0,0 +1,62 @@
+/***************************************************************************
+* Copyright (C) 2006 by *
+* 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 "recipeprintpreview.h"
+
+#include <tqvbox.h>
+
+#include <kdebug.h>
+#include <tdelocale.h>
+
+#include "recipeviewdialog.h"
+#include "pagesetupdialog.h"
+
+RecipePrintPreview::RecipePrintPreview( TQWidget *parent, RecipeDB *db, const TQValueList<int> &ids )
+ : KDialogBase( parent, "RecipePrintPreview", true, i18n("Print Preview"),
+ KDialogBase::Ok | KDialogBase::Cancel | KDialogBase::User1 | KDialogBase::Help, KDialogBase::Ok )
+{
+ setHelp("print-recipe");
+ setButtonText( KDialogBase::User1, i18n("&Edit") );
+ setButtonText( KDialogBase::Ok, i18n("&Print") );
+
+ setSizeGripEnabled( true );
+
+ // Initialize UI Elements
+ TQVBox *page = makeVBoxMainWidget();
+
+ recipeView = new RecipeViewDialog( page, db );
+ recipeView->loadRecipes( ids, "Print" );
+
+ setInitialSize( TQSize(450,500), false );
+}
+
+RecipePrintPreview::~RecipePrintPreview()
+{
+}
+
+void RecipePrintPreview::slotOk()
+{
+ recipeView->printNoPreview();
+ accept();
+}
+
+void RecipePrintPreview::slotUser1( void )
+{
+ PageSetupDialog pageSetup( this, Recipe(), "Print" );
+ if ( pageSetup.exec() == TQDialog::Accepted )
+ reload();
+}
+
+void RecipePrintPreview::reload()
+{
+ recipeView->reload( "Print" );
+}
+
+#include "recipeprintpreview.moc"
diff --git a/src/dialogs/recipeprintpreview.h b/src/dialogs/recipeprintpreview.h
new file mode 100644
index 0000000..f4c7b65
--- /dev/null
+++ b/src/dialogs/recipeprintpreview.h
@@ -0,0 +1,41 @@
+/***************************************************************************
+* Copyright (C) 2006 by *
+* 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. *
+***************************************************************************/
+
+#ifndef RECIPEPRINTPREVIEW_H
+#define RECIPEPRINTPREVIEW_H
+
+#include <tqstring.h>
+#include <tqvaluelist.h>
+
+#include <kdialogbase.h>
+
+class RecipeDB;
+class RecipeViewDialog;
+
+class RecipePrintPreview : public KDialogBase
+{
+TQ_OBJECT
+
+public:
+ RecipePrintPreview( TQWidget *parent, RecipeDB *db, const TQValueList<int> &ids );
+ ~RecipePrintPreview();
+
+ void reload();
+
+public slots:
+ void slotOk();
+ void slotUser1( void );
+
+private:
+ // Internal Variables
+ RecipeViewDialog *recipeView;
+};
+
+#endif
diff --git a/src/dialogs/recipeviewdialog.cpp b/src/dialogs/recipeviewdialog.cpp
new file mode 100644
index 0000000..133aece
--- /dev/null
+++ b/src/dialogs/recipeviewdialog.cpp
@@ -0,0 +1,167 @@
+/***************************************************************************
+* 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 "recipeviewdialog.h"
+
+#include <tqlayout.h>
+#include <tqstyle.h>
+#include <tqfile.h>
+
+#include <tdeapplication.h>
+#include <kcursor.h>
+#include <kdebug.h>
+#include <tdehtmlview.h>
+#include <tdehtml_part.h>
+#include <tdelocale.h>
+#include <tdemainwindow.h>
+#include <kprogress.h>
+#include <kstandarddirs.h>
+#include <kstatusbar.h>
+#include <tdeconfig.h>
+#include <tdeglobal.h>
+
+#include "datablocks/mixednumber.h"
+#include "backends/recipedb.h"
+#include "exporters/htmlexporter.h"
+#include "recipeprintpreview.h"
+
+RecipeViewDialog::RecipeViewDialog( TQWidget *parent, RecipeDB *db, int recipeID ) : TQVBox( parent ),
+ database(db)
+{
+ // Initialize UI Elements
+ recipeView = new TDEHTMLPart( this );
+
+ connect( database, TQ_SIGNAL(recipeRemoved(int)), TQ_SLOT(recipeRemoved(int)) );
+
+ tmp_filename = locateLocal( "tmp", "krecipes_recipe_view" );
+
+ //----------Load the recipe --------
+ if ( recipeID != -1 )
+ loadRecipe( recipeID );
+}
+
+RecipeViewDialog::~RecipeViewDialog()
+{
+ if ( recipe_loaded )
+ removeOldFiles();
+}
+
+bool RecipeViewDialog::loadRecipe( int recipeID )
+{
+ TQValueList<int> ids;
+ ids.append( recipeID );
+ return loadRecipes( ids );
+}
+
+bool RecipeViewDialog::loadRecipes( const TQValueList<int> &ids, const TQString &layoutConfig )
+{
+ TDEApplication::setOverrideCursor( KCursor::waitCursor() );
+
+ // Remove any files created by the last recipe loaded
+ removeOldFiles();
+
+ ids_loaded = ids; //need to save these ids in order to delete the html files later...make sure this comes after the call to removeOldFiles()
+ recipe_loaded = ( ids.count() > 0 && ids[ 0 ] >= 0 );
+
+ bool success = showRecipes( ids, layoutConfig );
+
+ TDEApplication::restoreOverrideCursor();
+ return success;
+}
+
+bool RecipeViewDialog::showRecipes( const TQValueList<int> &ids, const TQString &layoutConfig )
+{
+ KProgressDialog * progress_dialog = 0;
+
+ if ( ids.count() > 1 ) //we don't want a progress bar coming up when there is only one recipe... it may show up during the splash screen
+ {
+ progress_dialog = new KProgressDialog( this, "open_progress_dialog", TQString::null, i18n( "Opening recipes, please wait..." ), true );
+ progress_dialog->resize( 240, 80 );
+ }
+
+ HTMLExporter html_generator( tmp_filename + ".html", "html" );
+ if ( layoutConfig != TQString::null ) {
+ TDEConfig *config = TDEGlobal::config();
+ config->setGroup( "Page Setup" );
+ TQString styleFile = config->readEntry( layoutConfig+"Layout", locate( "appdata", "layouts/Default.klo" ) );
+ if ( !styleFile.isEmpty() && TQFile::exists( styleFile ) )
+ html_generator.setStyle( styleFile );
+
+ TQString templateFile = config->readEntry( layoutConfig+"Template", locate( "appdata", "layouts/Default.template" ) );
+ if ( !templateFile.isEmpty() && TQFile::exists( templateFile ) )
+ html_generator.setTemplate( templateFile );
+ }
+
+ html_generator.exporter( ids, database, progress_dialog ); //writes the generated HTML to 'tmp_filename+".html"'
+ if ( progress_dialog && progress_dialog->wasCancelled() ) {
+ delete progress_dialog;
+ return false;
+ }
+
+ delete recipeView; // Temporary workaround
+ recipeView = new TDEHTMLPart( this ); // to avoid the problem of caching images of TDEHTMLPart
+
+ KURL url;
+ url.setPath( tmp_filename + ".html" );
+ recipeView->openURL( url );
+ recipeView->show();
+ kdDebug() << "Opening URL: " << url.htmlURL() << endl;
+
+ delete progress_dialog;
+ return true;
+}
+
+void RecipeViewDialog::print()
+{
+ if ( recipe_loaded ) {
+ RecipePrintPreview preview( this, database, ids_loaded );
+ preview.exec();
+ }
+}
+
+void RecipeViewDialog::printNoPreview( void )
+{
+ if ( recipe_loaded ) {
+ recipeView->view() ->print();
+ }
+}
+
+void RecipeViewDialog::reload( const TQString &layoutConfig )
+{
+ loadRecipes( ids_loaded, layoutConfig );
+}
+
+void RecipeViewDialog::removeOldFiles()
+{
+ if ( ids_loaded.count() > 0 ) {
+ RecipeList recipe_list;
+ database->loadRecipes( &recipe_list, RecipeDB::Title, ids_loaded );
+
+ TQValueList<int> recipe_ids;
+ for ( RecipeList::const_iterator it = recipe_list.begin(); it != recipe_list.end(); ++it )
+ recipe_ids << ( *it ).recipeID;
+
+ HTMLExporter::removeHTMLFiles( tmp_filename, recipe_ids );
+ }
+}
+
+void RecipeViewDialog::recipeRemoved( int id )
+{
+ //if the deleted recipe is loaded, clean the view up
+ if ( ids_loaded.find(id) != ids_loaded.end() ) {
+ Recipe recipe; database->loadRecipe( &recipe, RecipeDB::Title, id );
+ HTMLExporter::removeHTMLFiles( tmp_filename, recipe.recipeID );
+ ids_loaded.remove(id);
+ }
+}
+
+#include "recipeviewdialog.moc"
diff --git a/src/dialogs/recipeviewdialog.h b/src/dialogs/recipeviewdialog.h
new file mode 100644
index 0000000..2b7c884
--- /dev/null
+++ b/src/dialogs/recipeviewdialog.h
@@ -0,0 +1,77 @@
+/***************************************************************************
+* 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. *
+***************************************************************************/
+
+#ifndef RECIPEVIEWDIALOG_H
+#define RECIPEVIEWDIALOG_H
+
+#include <tqvbox.h>
+#include <tqstring.h>
+
+class RecipeDB;
+class Recipe;
+class TDEHTMLPart;
+class TQPushButton;
+
+/**
+@author Unai Garro
+*/
+
+class RecipeViewDialog : public TQVBox
+{
+ TQ_OBJECT
+
+public:
+ RecipeViewDialog( TQWidget *parent, RecipeDB *db, int recipeID = -1 );
+
+ ~RecipeViewDialog();
+
+ /** @return Boolean indicating whether or not the recipe was successfully loaded */
+ bool loadRecipe( int recipeID );
+
+ /** @return Boolean indicating whether or not the recipes were successfully loaded */
+ bool loadRecipes( const TQValueList<int> &ids, const TQString &layoutConfig = TQString::null );
+
+ int recipesLoaded() const
+ {
+ return ids_loaded.count();
+ }
+ const TQValueList<int> currentRecipes() const
+ {
+ return ids_loaded;
+ }
+
+ void reload( const TQString &layoutConfig = TQString::null );
+
+public slots:
+ void printNoPreview( void );
+ void print( void );
+
+private:
+
+ // Internal Variables
+ TDEHTMLPart *recipeView;
+ RecipeDB *database;
+ bool recipe_loaded;
+ TQValueList<int> ids_loaded;
+ TQString tmp_filename;
+
+ // Internal Methods
+ bool showRecipes( const TQValueList<int> &ids, const TQString &layoutConfig );
+ void removeOldFiles();
+
+private slots:
+ void recipeRemoved(int);
+
+};
+
+
+#endif
diff --git a/src/dialogs/refineshoppinglistdialog.cpp b/src/dialogs/refineshoppinglistdialog.cpp
new file mode 100644
index 0000000..adbe5bb
--- /dev/null
+++ b/src/dialogs/refineshoppinglistdialog.cpp
@@ -0,0 +1,206 @@
+/***************************************************************************
+* Copyright (C) 2004 by 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 "refineshoppinglistdialog.h"
+
+#include <tqvariant.h>
+#include <tqpushbutton.h>
+#include <tqlabel.h>
+#include <tqheader.h>
+#include <tqlayout.h>
+#include <tqtooltip.h>
+#include <tqwhatsthis.h>
+
+#include <tdelocale.h>
+#include <kiconloader.h>
+#include <tdeapplication.h>
+#include <kcursor.h>
+#include <tdeconfig.h>
+
+#include "backends/recipedb.h"
+#include "widgets/krelistview.h"
+#include "widgets/ingredientlistview.h"
+#include "shoppinglistviewdialog.h"
+#include "shoppingcalculator.h"
+#include "datablocks/mixednumber.h"
+
+RefineShoppingListDialog::RefineShoppingListDialog( TQWidget* parent, RecipeDB *db, const ElementList &recipeList )
+ : KDialogBase( parent, "refinedialog", true, TQString::null,
+ KDialogBase::Ok, KDialogBase::Ok ),
+ database( db )
+{
+ setButtonText( KDialogBase::Ok, i18n( "&Done" ) );
+
+ TQVBox *page = makeVBoxMainWidget();
+
+ helpLabel = new TQLabel( page, "helpLabel" );
+ helpLabel->setTextFormat( TQLabel::RichText );
+
+ TQWidget *layout2Widget = new TQWidget(page);
+
+ TQHBoxLayout *layout2 = new TQHBoxLayout( layout2Widget, 0, 6, "layout2" );
+
+ allIngListView = new KreListView( layout2Widget, TQString::null, true, 0 );
+ StdIngredientListView *list_view = new StdIngredientListView(allIngListView,database);
+ list_view->reload();
+ allIngListView->setListView(list_view);
+ layout2->addWidget( allIngListView );
+
+ layout1 = new TQVBoxLayout( 0, 0, 6, "layout1" );
+
+ TDEIconLoader il;
+
+ addButton = new TQPushButton( layout2Widget, "addButton" );
+ addButton->setIconSet( il.loadIconSet( "forward", TDEIcon::Small ) );
+ addButton->setFixedSize( TQSize( 32, 32 ) );
+ layout1->addWidget( addButton );
+
+ removeButton = new TQPushButton( layout2Widget, "removeButton" );
+ removeButton->setIconSet( il.loadIconSet( "back", TDEIcon::Small ) );
+ removeButton->setFixedSize( TQSize( 32, 32 ) );
+ layout1->addWidget( removeButton );
+ spacer1 = new TQSpacerItem( 51, 191, TQSizePolicy::Minimum, TQSizePolicy::Expanding );
+ layout1->addItem( spacer1 );
+ layout2->addLayout( layout1 );
+
+ ingListView = new KreListView( layout2Widget, TQString::null, true );
+ ingListView->listView() ->addColumn( i18n( "Ingredients in Shopping List" ) );
+ ingListView->listView() ->addColumn( i18n( "Amount" ) );
+ ingListView->listView() ->addColumn( i18n( "Unit" ) );
+ ingListView->listView() ->setItemsRenameable( true );
+ ingListView->listView() ->setRenameable( 0, false );
+ ingListView->listView() ->setRenameable( 1, true );
+ ingListView->listView() ->setRenameable( 2, true );
+ layout2->addWidget( ingListView );
+
+ languageChange();
+
+ clearWState( WState_Polished );
+
+ connect( addButton, TQ_SIGNAL( clicked() ), this, TQ_SLOT( addIngredient() ) );
+ connect( removeButton, TQ_SIGNAL( clicked() ), this, TQ_SLOT( removeIngredient() ) );
+ connect( ingListView->listView(), TQ_SIGNAL( itemRenamed( TQListViewItem*, const TQString &, int ) ), TQ_SLOT( itemRenamed( TQListViewItem*, const TQString &, int ) ) );
+
+ TDEApplication::setOverrideCursor( KCursor::waitCursor() );
+ calculateShopping( recipeList, &ingredientList, database );
+ TDEApplication::restoreOverrideCursor();
+
+ loadData();
+}
+
+RefineShoppingListDialog::~RefineShoppingListDialog()
+{}
+
+void RefineShoppingListDialog::languageChange()
+{
+ helpLabel->setText( i18n( "On the right are the ingredients needed for the recipes you selected. You may now add additional ingredients, remove ingredients you do not need, or modify the amounts of existing ingredients." ) );
+ allIngListView->listView() ->header() ->setLabel( 0, i18n( "Ingredients" ) );
+ ingListView->listView() ->header() ->setLabel( 0, i18n( "Ingredients in Shopping List" ) );
+ ingListView->listView() ->header() ->setLabel( 1, i18n( "Amount" ) );
+ ingListView->listView() ->header() ->setLabel( 2, i18n( "Unit" ) );
+}
+
+void RefineShoppingListDialog::accept()
+{
+ hide();
+
+ ShoppingListViewDialog view( this, ingredientList );
+ view.exec();
+
+ TQDialog::accept();
+}
+
+void RefineShoppingListDialog::loadData()
+{
+ for ( IngredientList::iterator it = ingredientList.begin(); it != ingredientList.end(); ++it ) {
+ //from here on, the shopping list will work with the upper value of the range (if exists)
+ (*it).amount = (*it).amount+(*it).amount_offset;
+ (*it).amount_offset = 0;
+
+ TQString amount_str;
+ if ( ( *it ).amount > 0 ) {
+ TDEConfig * config = kapp->config();
+ config->setGroup( "Formatting" );
+
+ if ( config->readBoolEntry( "Fraction" ) )
+ amount_str = MixedNumber( ( *it ).amount ).toString();
+ else
+ amount_str = beautify( TDEGlobal::locale() ->formatNumber( ( *it ).amount, 5 ) );
+ }
+
+ TQListViewItem *new_item = new TQListViewItem( ingListView->listView(), ( *it ).name, amount_str, ( *it ).amount > 1 ? ( *it ).units.plural : ( *it ).units.name );
+ item_ing_map.insert( new_item, it );
+ }
+}
+
+void RefineShoppingListDialog::addIngredient()
+{
+ TQListViewItem * item = allIngListView->listView() ->selectedItem();
+ if ( item ) {
+ TQListViewItem * new_item = new TQListViewItem( ingListView->listView(), item->text( 0 ) );
+ ingListView->listView() ->setSelected( new_item, true );
+ ingListView->listView() ->ensureItemVisible( new_item );
+ allIngListView->listView() ->setSelected( item, false );
+
+ item_ing_map.insert( new_item, ingredientList.append( Ingredient( item->text( 0 ), 0, Unit() ) ) );
+ }
+}
+
+void RefineShoppingListDialog::removeIngredient()
+{
+ TQListViewItem * item = ingListView->listView() ->selectedItem();
+ if ( item ) {
+ for ( IngredientList::iterator it = ingredientList.begin(); it != ingredientList.end(); ++it ) {
+ if ( *item_ing_map.find( item ) == it ) {
+ ingredientList.remove( it );
+ item_ing_map.remove( item );
+ break;
+ }
+ }
+ delete item;
+ }
+}
+
+void RefineShoppingListDialog::itemRenamed( TQListViewItem* item, const TQString &new_text, int col )
+{
+ if ( col == 1 ) {
+ IngredientList::iterator found_it = *item_ing_map.find( item );
+
+ bool ok;
+ MixedNumber amount = MixedNumber::fromString( new_text, &ok );
+ if ( ok ) {
+ ( *found_it ).amount = amount.toDouble();
+ }
+ else { //revert back to the valid amount string
+ TQString amount_str;
+ if ( ( *found_it ).amount > 0 ) {
+ TDEConfig * config = kapp->config();
+ config->setGroup( "Formatting" );
+
+ if ( config->readBoolEntry( "Fraction" ) )
+ amount_str = MixedNumber( ( *found_it ).amount ).toString();
+ else
+ amount_str = beautify( TDEGlobal::locale() ->formatNumber( ( *found_it ).amount, 5 ) );
+ }
+
+ item->setText( 1, amount_str );
+ }
+ }
+ else if ( col == 2 ) {
+ IngredientList::iterator found_it = *item_ing_map.find( item );
+
+ if ( ( *found_it ).amount > 1 )
+ ( *found_it ).units.plural = new_text;
+ else
+ ( *found_it ).units.name = new_text;
+ }
+}
+
+#include "refineshoppinglistdialog.moc"
diff --git a/src/dialogs/refineshoppinglistdialog.h b/src/dialogs/refineshoppinglistdialog.h
new file mode 100644
index 0000000..5952a9b
--- /dev/null
+++ b/src/dialogs/refineshoppinglistdialog.h
@@ -0,0 +1,66 @@
+/***************************************************************************
+* Copyright (C) 2004 by 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. *
+***************************************************************************/
+
+#ifndef REFINESHOPPINGLISTDIALOG_H
+#define REFINESHOPPINGLISTDIALOG_H
+
+#include <tqvariant.h>
+#include <tqmap.h>
+
+#include <kdialogbase.h>
+
+#include "datablocks/ingredientlist.h"
+
+class TQVBoxLayout;
+class TQHBoxLayout;
+class TQGridLayout;
+class TQSpacerItem;
+class TQLabel;
+class TQListViewItem;
+class TQPushButton;
+
+class RecipeDB;
+class ElementList;
+class KreListView;
+
+class RefineShoppingListDialog : public KDialogBase
+{
+ TQ_OBJECT
+
+public:
+ RefineShoppingListDialog( TQWidget* parent, RecipeDB *db, const ElementList &recipeList );
+ ~RefineShoppingListDialog();
+
+ TQLabel* helpLabel;
+ KreListView* allIngListView;
+ TQPushButton* addButton;
+ TQPushButton* removeButton;
+ KreListView* ingListView;
+
+protected:
+ TQVBoxLayout* layout1;
+ TQSpacerItem* spacer1;
+
+protected slots:
+ virtual void languageChange();
+ virtual void accept();
+ void addIngredient();
+ void removeIngredient();
+ void itemRenamed( TQListViewItem*, const TQString &, int );
+
+private:
+ void loadData();
+
+ RecipeDB *database;
+ IngredientList ingredientList;
+ TQMap<TQListViewItem*, IngredientList::iterator> item_ing_map;
+};
+
+#endif // REFINESHOPPINGLISTDIALOG_H
diff --git a/src/dialogs/resizerecipedialog.cpp b/src/dialogs/resizerecipedialog.cpp
new file mode 100644
index 0000000..958fadb
--- /dev/null
+++ b/src/dialogs/resizerecipedialog.cpp
@@ -0,0 +1,191 @@
+/***************************************************************************
+* 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 "resizerecipedialog.h"
+
+#include <cmath>
+
+#include <tqvbox.h>
+#include <tqvariant.h>
+#include <tqbuttongroup.h>
+#include <tqframe.h>
+#include <tqlabel.h>
+#include <knuminput.h>
+#include <klineedit.h>
+#include <tqradiobutton.h>
+#include <tqlayout.h>
+#include <tqtooltip.h>
+#include <tqwhatsthis.h>
+#include <tqimage.h>
+#include <tqpixmap.h>
+
+#include <tdelocale.h>
+#include <tdemessagebox.h>
+#include <kdebug.h>
+
+#include "datablocks/recipe.h"
+#include "widgets/fractioninput.h"
+
+#define FACTOR_RADIO_BUTTON 0
+#define SERVINGS_RADIO_BUTTON 1
+
+ResizeRecipeDialog::ResizeRecipeDialog( TQWidget *parent, Recipe *recipe )
+ : KDialogBase( parent, "ResizeRecipeDialog", true, i18n( "Resize Recipe" ),
+ KDialogBase::Ok | KDialogBase::Cancel, KDialogBase::Ok ),
+ m_recipe( recipe )
+{
+ TQVBox *page = makeVBoxMainWidget();
+
+ buttonGroup = new TQButtonGroup( page );
+ buttonGroup->setSizePolicy( TQSizePolicy( ( TQSizePolicy::SizeType ) 5, ( TQSizePolicy::SizeType ) 7, 0, 1, buttonGroup->sizePolicy().hasHeightForWidth() ) );
+ buttonGroup->setLineWidth( 0 );
+ buttonGroup->setColumnLayout( 0, TQt::Vertical );
+ buttonGroup->layout() ->setSpacing( 6 );
+ buttonGroup->layout() ->setMargin( 11 );
+ buttonGroupLayout = new TQVBoxLayout( buttonGroup->layout() );
+ buttonGroupLayout->setAlignment( TQt::AlignTop );
+
+ yieldRadioButton = new TQRadioButton( buttonGroup );
+ buttonGroup->insert( yieldRadioButton, SERVINGS_RADIO_BUTTON );
+ buttonGroupLayout->addWidget( yieldRadioButton );
+
+ yieldFrame = new TQFrame( buttonGroup );
+ yieldFrame->setFrameShape( TQFrame::Box );
+ yieldFrame->setFrameShadow( TQFrame::Sunken );
+ yieldFrame->setLineWidth( 1 );
+ yieldFrameLayout = new TQGridLayout( yieldFrame, 1, 1, 11, 6 );
+
+ currentYieldLabel = new TQLabel( yieldFrame );
+
+ yieldFrameLayout->addWidget( currentYieldLabel, 0, 0 );
+
+ newYieldLabel = new TQLabel( yieldFrame );
+
+ yieldFrameLayout->addMultiCellWidget( newYieldLabel, 1, 1, 0, 1 );
+
+ currentYieldInput = new KLineEdit( yieldFrame );
+ currentYieldInput->setReadOnly( TRUE );
+ currentYieldInput->setAlignment( TQt::AlignRight );
+ yieldFrameLayout->addMultiCellWidget( currentYieldInput, 0, 0, 1, 2 );
+
+ newYieldInput = new FractionInput( yieldFrame );
+ yieldFrameLayout->addWidget( newYieldInput, 1, 2 );
+
+ buttonGroupLayout->addWidget( yieldFrame );
+
+ factorRadioButton = new TQRadioButton( buttonGroup );
+ buttonGroup->insert( factorRadioButton, FACTOR_RADIO_BUTTON );
+ buttonGroupLayout->addWidget( factorRadioButton );
+
+ factorFrame = new TQFrame( buttonGroup );
+ factorFrame->setSizePolicy( TQSizePolicy( ( TQSizePolicy::SizeType ) 7, ( TQSizePolicy::SizeType ) 5, 1, 0, factorFrame->sizePolicy().hasHeightForWidth() ) );
+ factorFrame->setFrameShape( TQFrame::Box );
+ factorFrame->setFrameShadow( TQFrame::Sunken );
+ factorFrame->setLineWidth( 1 );
+ factorFrameLayout = new TQHBoxLayout( factorFrame, 11, 6 );
+
+ factorLabel = new TQLabel( factorFrame );
+ factorFrameLayout->addWidget( factorLabel );
+
+ factorInput = new FractionInput( factorFrame );
+ factorInput->setSizePolicy( TQSizePolicy( ( TQSizePolicy::SizeType ) 7, ( TQSizePolicy::SizeType ) 5, 0, 0, factorInput->sizePolicy().hasHeightForWidth() ) );
+ factorFrameLayout->addWidget( factorInput );
+ buttonGroupLayout->addWidget( factorFrame );
+
+ languageChange();
+
+
+ newYieldInput->setValue( m_recipe->yield.amount, 0 ); //Ignore the range info, it doesn't work in this context
+ currentYieldInput->setText( m_recipe->yield.toString() );
+
+ if ( recipe->yield.amount_offset > 0 ) {
+ yieldRadioButton->setEnabled(false);
+ buttonGroup->setButton( FACTOR_RADIO_BUTTON );
+ activateCurrentOption( FACTOR_RADIO_BUTTON );
+ }
+ else {
+ buttonGroup->setButton( SERVINGS_RADIO_BUTTON );
+ activateCurrentOption( SERVINGS_RADIO_BUTTON );
+ }
+
+ // signals and slots connections
+ connect( buttonGroup, TQ_SIGNAL( clicked( int ) ), this, TQ_SLOT( activateCurrentOption( int ) ) );
+}
+
+void ResizeRecipeDialog::languageChange()
+{
+ buttonGroup->setTitle( TQString::null );
+ yieldRadioButton->setText( i18n( "Scale by yield" ) );
+ newYieldLabel->setText( i18n( "New yield:" ) );
+ currentYieldLabel->setText( i18n( "Current yield:" ) );
+ factorRadioButton->setText( i18n( "Scale by factor" ) );
+ factorLabel->setText( i18n( "Factor (i.e. 1/2 to half, 3 to triple):" ) );
+}
+
+void ResizeRecipeDialog::activateCurrentOption( int button_id )
+{
+ switch ( button_id ) {
+ case SERVINGS_RADIO_BUTTON:
+ factorFrame->setEnabled( false );
+ yieldFrame->setEnabled( true );
+ break;
+ case FACTOR_RADIO_BUTTON:
+ factorFrame->setEnabled( true );
+ yieldFrame->setEnabled( false );
+ break;
+ default:
+ break;
+ }
+}
+
+void ResizeRecipeDialog::accept()
+{
+ if ( currentYieldInput->text().toInt() == 0 )
+ KMessageBox::error( this, i18n( "Unable to scale a recipe with zero yield" ) );
+ else if ( buttonGroup->selected() == yieldRadioButton ) {
+ if ( newYieldInput->isInputValid() ) {
+ double new_yield = newYieldInput->value().toDouble();
+ double current_yield = MixedNumber::fromString(currentYieldInput->text()).toDouble();
+
+ resizeRecipe( new_yield / current_yield );
+ }
+ else {
+ KMessageBox::error( this, i18n( "Invalid input" ) );
+ newYieldInput->selectAll();
+ return;
+ }
+ }
+ else {
+ if ( factorInput->isInputValid() && factorInput->value() > 0 )
+ resizeRecipe( factorInput->value().toDouble() );
+ else {
+ KMessageBox::error( this, i18n( "Invalid input" ) );
+ factorInput->selectAll();
+ return ;
+ }
+ }
+
+ TQDialog::accept();
+}
+
+//TODO YIELD: handle ranges
+void ResizeRecipeDialog::resizeRecipe( double factor )
+{
+ m_recipe->yield.amount = MixedNumber::fromString(currentYieldInput->text()).toDouble() * factor;
+
+ for ( IngredientList::iterator ing_it = m_recipe->ingList.begin(); ing_it != m_recipe->ingList.end(); ++ing_it ) {
+ ( *ing_it ).amount = ( *ing_it ).amount * factor;
+ ( *ing_it ).amount_offset = ( *ing_it ).amount_offset * factor;
+ }
+}
+
+#include "resizerecipedialog.moc"
diff --git a/src/dialogs/resizerecipedialog.h b/src/dialogs/resizerecipedialog.h
new file mode 100644
index 0000000..725ecdb
--- /dev/null
+++ b/src/dialogs/resizerecipedialog.h
@@ -0,0 +1,69 @@
+/***************************************************************************
+* 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. *
+***************************************************************************/
+
+#ifndef RESIZERECIPEDIALOG_H
+#define RESIZERECIPEDIALOG_H
+
+#include <kdialogbase.h>
+
+class Recipe;
+
+class TQVBoxLayout;
+class TQHBoxLayout;
+class TQGridLayout;
+class FractionInput;
+class TQButtonGroup;
+class TQFrame;
+class TQLabel;
+class KIntNumInput;
+class KLineEdit;
+class TQRadioButton;
+class TQPushButton;
+
+/**
+ *@author Jason Kivlighn
+ */
+class ResizeRecipeDialog : public KDialogBase
+{
+ TQ_OBJECT
+
+public:
+ ResizeRecipeDialog( TQWidget *parent, Recipe* );
+
+protected slots:
+ void accept();
+ void activateCurrentOption( int );
+ virtual void languageChange();
+
+private:
+ void resizeRecipe( double factor );
+
+ Recipe *m_recipe;
+
+ TQButtonGroup* buttonGroup;
+ TQRadioButton* yieldRadioButton;
+ TQFrame* yieldFrame;
+ TQLabel* currentYieldLabel;
+ TQLabel* newYieldLabel;
+ KLineEdit* currentYieldInput;
+ FractionInput* newYieldInput;
+ TQRadioButton* factorRadioButton;
+ TQFrame* factorFrame;
+ TQLabel* factorLabel;
+ FractionInput* factorInput;
+
+ TQVBoxLayout* buttonGroupLayout;
+ TQGridLayout* yieldFrameLayout;
+ TQHBoxLayout* factorFrameLayout;
+};
+
+#endif //RESIZERECIPEDIALOG_H
diff --git a/src/dialogs/selectauthorsdialog.cpp b/src/dialogs/selectauthorsdialog.cpp
new file mode 100644
index 0000000..d7583d3
--- /dev/null
+++ b/src/dialogs/selectauthorsdialog.cpp
@@ -0,0 +1,181 @@
+/***************************************************************************
+* 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 "selectauthorsdialog.h"
+
+#include <tqmessagebox.h>
+#include <tqvbox.h>
+
+#include <tdeconfig.h>
+#include <kdialog.h>
+#include <tdelocale.h>
+#include <tdemessagebox.h>
+#include <tdeglobal.h>
+
+#include "backends/recipedb.h"
+
+SelectAuthorsDialog::SelectAuthorsDialog( TQWidget *parent, const ElementList &currentAuthors, RecipeDB *db )
+ : KDialogBase( parent, "SelectAuthorsDialog", true, i18n("Authors"),
+ KDialogBase::Ok | KDialogBase::Cancel, KDialogBase::Ok ),
+ database(db)
+{
+ TQVBox *page = makeVBoxMainWidget();
+
+ //Design UI
+
+ // Combo to Pick authors
+ TQHBox *topBox = new TQHBox(page);
+ topBox->setSpacing(6);
+
+ authorsCombo = new KComboBox( true, topBox );
+ authorsCombo->setSizePolicy( TQSizePolicy( TQSizePolicy::MinimumExpanding, TQSizePolicy::MinimumExpanding ) );
+ authorsCombo->completionObject() ->setCompletionMode( TDEGlobalSettings::CompletionPopupAuto );
+ authorsCombo->lineEdit() ->disconnect( authorsCombo ); //so hitting enter doesn't enter the item into the box
+
+ // Add/Remove buttons
+
+ il = new TDEIconLoader;
+ addAuthorButton = new TQPushButton( topBox );
+ TQPixmap pm = il->loadIcon( "go-down", TDEIcon::NoGroup, 16 );
+ addAuthorButton->setIconSet( pm );
+
+ removeAuthorButton = new TQPushButton( topBox );
+ pm = il->loadIcon( "go-up", TDEIcon::NoGroup, 16 );
+ removeAuthorButton->setIconSet( pm );
+
+ // Author List
+
+ authorListView = new TDEListView( page );
+ authorListView->setSizePolicy( TQSizePolicy( TQSizePolicy::MinimumExpanding, TQSizePolicy::MinimumExpanding ) );
+
+ TDEConfig * config = TDEGlobal::config();
+ config->setGroup( "Advanced" );
+ bool show_id = config->readBoolEntry( "ShowID", false );
+ authorListView->addColumn( i18n( "Id" ), show_id ? -1 : 0 );
+ authorListView->addColumn( i18n( "Author" ) );
+ authorListView->setAllColumnsShowFocus( true );
+
+ // Load the list
+ loadAuthors( currentAuthors );
+
+ adjustSize();
+ resize(450, height());
+
+ // Connect signals & Slots
+ connect ( addAuthorButton, TQ_SIGNAL( clicked() ), this, TQ_SLOT( addAuthor() ) );
+ connect ( removeAuthorButton, TQ_SIGNAL( clicked() ), this, TQ_SLOT( removeAuthor() ) );
+
+ authorsCombo->setEditText(TQString::null);
+ authorsCombo->lineEdit()->setFocus();
+}
+
+SelectAuthorsDialog::~SelectAuthorsDialog()
+{}
+
+void SelectAuthorsDialog::getSelectedAuthors( ElementList *newAuthors )
+{
+
+ for ( TQListViewItem * it = authorListView->firstChild();it; it = it->nextSibling() ) {
+ Element author;
+ author.id = it->text( 0 ).toInt();
+ author.name = it->text( 1 );
+ newAuthors->append( author );
+ }
+
+}
+
+void SelectAuthorsDialog::loadAuthors( const ElementList &currentAuthors )
+{
+
+ // Load the combo
+ reloadAuthorsCombo();
+
+ // Load the ListView with the authors of this recipe
+ authorListView->clear();
+ for ( ElementList::const_iterator author_it = currentAuthors.begin(); author_it != currentAuthors.end(); ++author_it ) {
+ ( void ) new TQListViewItem( authorListView, TQString::number( ( *author_it ).id ), ( *author_it ).name );
+ }
+
+}
+
+void SelectAuthorsDialog::addAuthor( void )
+{
+ //check bounds first
+ if ( authorsCombo->currentText().length() > uint(database->maxAuthorNameLength()) ) {
+ KMessageBox::error( this, TQString( i18n( "Author name cannot be longer than %1 characters." ) ).arg( database->maxAuthorNameLength() ) );
+ authorsCombo->lineEdit() ->selectAll();
+ return ;
+ }
+
+ if ( authorsCombo->lineEdit()->text().isEmpty() )
+ return;
+
+ if ( authorsCombo->contains( authorsCombo->currentText() ) )
+ authorsCombo->setCurrentItem( authorsCombo->currentText() );
+
+ createNewAuthorIfNecessary();
+
+ int currentItem = authorsCombo->currentItem();
+ Element currentElement = authorList.getElement( currentItem );
+
+ ( void ) new TQListViewItem( authorListView, TQString::number( currentElement.id ), currentElement.name );
+
+}
+
+void SelectAuthorsDialog::removeAuthor( void )
+{
+ // Find the selected item first
+ TQListViewItem * it;
+ it = authorListView->selectedItem();
+
+ if ( it ) { // Check if an author is selected first
+ delete it;
+ }
+
+}
+
+void SelectAuthorsDialog::createNewAuthorIfNecessary( void )
+{
+
+ if ( !authorsCombo->contains( authorsCombo->currentText() ) &&
+ !( authorsCombo->currentText().stripWhiteSpace() ).isEmpty() ) // author is not in the list and is not empty
+ { // Create new author
+ TQString newAuthorName = authorsCombo->currentText();
+ database->createNewAuthor( newAuthorName );
+ //List again the authors
+ reloadAuthorsCombo();
+
+ // Select the newly created author
+ authorsCombo->setCurrentItem( newAuthorName );
+ }
+}
+
+
+void SelectAuthorsDialog::reloadAuthorsCombo( void )
+{
+
+ //Load the author list
+ database->loadAuthors( &authorList );
+
+ // Load combo with all the authors
+ authorsCombo->clear();
+ authorsCombo->completionObject() ->clear();
+
+ for ( ElementList::const_iterator author_it = authorList.begin(); author_it != authorList.end(); ++author_it ) {
+ authorsCombo->insertItem( ( *author_it ).name );
+ authorsCombo->completionObject() ->addItem( ( *author_it ).name );
+ }
+
+}
+
+
+#include "selectauthorsdialog.moc"
diff --git a/src/dialogs/selectauthorsdialog.h b/src/dialogs/selectauthorsdialog.h
new file mode 100644
index 0000000..6304e08
--- /dev/null
+++ b/src/dialogs/selectauthorsdialog.h
@@ -0,0 +1,66 @@
+/***************************************************************************
+* 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. *
+***************************************************************************/
+
+#ifndef SELECTAUTHORSDIALOG_H
+#define SELECTAUTHORSDIALOG_H
+
+#include <tqlayout.h>
+#include <tqpushbutton.h>
+
+#include <kdialogbase.h>
+#include <kiconloader.h>
+#include <tdelistview.h>
+#include <kcombobox.h>
+
+#include "datablocks/elementlist.h"
+
+class RecipeDB;
+
+/**
+@author Unai Garro
+*/
+class SelectAuthorsDialog: public KDialogBase
+{
+
+ TQ_OBJECT
+
+public:
+
+ SelectAuthorsDialog( TQWidget *parent, const ElementList &currentAuthors, RecipeDB *db );
+ ~SelectAuthorsDialog();
+ void getSelectedAuthors( ElementList *newAuthors );
+
+private:
+
+ //Widgets
+ KComboBox *authorsCombo;
+ TDEListView *authorListView;
+ TQPushButton *okButton;
+ TQPushButton *cancelButton;
+ TQPushButton *addAuthorButton;
+ TQPushButton *removeAuthorButton;
+ TDEIconLoader *il;
+
+ //Variables
+ ElementList authorList;
+ RecipeDB *database;
+
+ //Private methods
+ void loadAuthors( const ElementList &authorList );
+ void createNewAuthorIfNecessary( void );
+ void reloadAuthorsCombo( void );
+private slots:
+ void addAuthor( void );
+ void removeAuthor( void );
+};
+
+#endif
diff --git a/src/dialogs/selectcategoriesdialog.cpp b/src/dialogs/selectcategoriesdialog.cpp
new file mode 100644
index 0000000..fe75bd3
--- /dev/null
+++ b/src/dialogs/selectcategoriesdialog.cpp
@@ -0,0 +1,104 @@
+/***************************************************************************
+* 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 "selectcategoriesdialog.h"
+#include "createcategorydialog.h"
+
+#include <tqvbox.h>
+
+#include <tdelocale.h>
+#include <kdebug.h>
+#include <kdialog.h>
+#include <tdemessagebox.h>
+
+#include "datablocks/categorytree.h"
+#include "backends/recipedb.h"
+#include "widgets/categorylistview.h"
+
+SelectCategoriesDialog::SelectCategoriesDialog( TQWidget *parent, const ElementList &items_on, RecipeDB *db )
+ : KDialogBase( parent, "SelectCategoriesDialog", true, i18n("Categories"),
+ KDialogBase::Ok | KDialogBase::Cancel, KDialogBase::Ok ),
+ database(db)
+{
+ TQVBox *page = makeVBoxMainWidget();
+
+ //Design UI
+
+ //Category List
+ categoryListView = new CategoryCheckListView( page, db, true, items_on );
+ categoryListView->reload();
+
+ //New category button
+ TQPushButton *newCatButton = new TQPushButton( page );
+ newCatButton->setText( i18n( "&New Category..." ) );
+ newCatButton->setFlat( true );
+
+ // Load the list
+ loadCategories( items_on );
+
+ setSizeGripEnabled( true );
+
+ // Connect signals & Slots
+ connect ( newCatButton, TQ_SIGNAL( clicked() ), TQ_SLOT( createNewCategory() ) );
+}
+
+SelectCategoriesDialog::~SelectCategoriesDialog()
+{}
+
+void SelectCategoriesDialog::getSelectedCategories( ElementList *newSelected )
+{
+ *newSelected = categoryListView->selections();
+}
+
+void SelectCategoriesDialog::loadCategories( const ElementList &items_on )
+{
+ categoryListView->populateAll();
+
+ ElementList::const_iterator it;
+ for ( it = items_on.begin(); it != items_on.end(); ++it ) {
+ CategoryCheckListItem *new_item = (CategoryCheckListItem*)categoryListView->findItem(TQString::number((*it).id),1);
+ if ( new_item ) {
+ new_item->setOn(true);
+ }
+ }
+}
+
+void SelectCategoriesDialog::createNewCategory( void )
+{
+ ElementList categories;
+ database->loadCategories( &categories );
+ CreateCategoryDialog* categoryDialog = new CreateCategoryDialog( this, categories );
+
+ if ( categoryDialog->exec() == TQDialog::Accepted ) {
+ TQString result = categoryDialog->newCategoryName();
+ int subcategory = categoryDialog->subcategory();
+
+ //check bounds first
+ if ( result.length() > uint(database->maxCategoryNameLength()) ) {
+ KMessageBox::error( this, TQString( i18n( "Category name cannot be longer than %1 characters." ) ).arg( database->maxCategoryNameLength() ) );
+ return ;
+ }
+
+ database->createNewCategory( result, subcategory ); // Create the new category in the database
+
+ //a listview item will automatically be created, but we need to turn it on
+ Element new_cat( result, database->lastInsertID() );
+ TQCheckListItem *new_item = ((TQCheckListItem*)categoryListView->findItem( TQString::number(new_cat.id), 1 ));
+ if ( new_item )
+ new_item->setOn(true);
+ }
+
+ delete categoryDialog;
+}
+
+
+#include "selectcategoriesdialog.moc"
diff --git a/src/dialogs/selectcategoriesdialog.h b/src/dialogs/selectcategoriesdialog.h
new file mode 100644
index 0000000..d73bb2b
--- /dev/null
+++ b/src/dialogs/selectcategoriesdialog.h
@@ -0,0 +1,57 @@
+/***************************************************************************
+* 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. *
+***************************************************************************/
+
+#ifndef SELECTCATEGORIESDIALOG_H
+#define SELECTCATEGORIESDIALOG_H
+
+#include <tqlayout.h>
+#include <tqpushbutton.h>
+
+#include <tdelistview.h>
+#include <kdialogbase.h>
+
+#include "datablocks/elementlist.h"
+
+class CategoryTree;
+class CategoryCheckListItem;
+class CategoryCheckListView;
+class RecipeDB;
+
+/**
+@author Unai Garro
+*/
+class SelectCategoriesDialog: public KDialogBase
+{
+
+ TQ_OBJECT
+
+public:
+
+ SelectCategoriesDialog( TQWidget *parent, const ElementList &items_on, RecipeDB* db );
+ ~SelectCategoriesDialog();
+ void getSelectedCategories( ElementList *selected );
+private:
+
+ //Widgets
+ CategoryCheckListView *categoryListView;
+
+ //Variables
+ RecipeDB *database;
+
+ //Private methods
+ void loadCategories( const ElementList &items_on );
+
+private slots:
+ void createNewCategory( void );
+};
+
+#endif
diff --git a/src/dialogs/selectpropertydialog.cpp b/src/dialogs/selectpropertydialog.cpp
new file mode 100644
index 0000000..1ce1887
--- /dev/null
+++ b/src/dialogs/selectpropertydialog.cpp
@@ -0,0 +1,123 @@
+/***************************************************************************
+* 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 "selectpropertydialog.h"
+
+#include <tdeconfig.h>
+#include <tdeglobal.h>
+#include <tdelocale.h>
+
+#include "datablocks/ingredientpropertylist.h"
+
+SelectPropertyDialog::SelectPropertyDialog( TQWidget* parent, IngredientPropertyList *propertyList, UnitList *unitList, OptionFlag showEmpty )
+ : KDialogBase( parent, "SelectPropertyDialog", true, i18n( "Choose Property" ),
+ KDialogBase::Ok | KDialogBase::Cancel, KDialogBase::Ok ), m_showEmpty(showEmpty)
+{
+
+ // Initialize internal variables
+ unitListBack = new UnitList;
+
+ // Initialize Widgets
+ TQVBox *page = makeVBoxMainWidget();
+
+ box = new TQGroupBox( page );
+ box->setTitle( i18n( "Choose Property" ) );
+ box->setColumnLayout( 0, TQt::Vertical );
+ box->layout() ->setSpacing( 6 );
+ box->layout() ->setMargin( 11 );
+ TQVBoxLayout *boxLayout = new TQVBoxLayout( box->layout() );
+ boxLayout->setAlignment( TQt::AlignTop );
+
+ propertyChooseView = new TDEListView( box, "propertyChooseView" );
+
+ TDEConfig *config = TDEGlobal::config();
+ config->setGroup( "Advanced" );
+ bool show_id = config->readBoolEntry( "ShowID", false );
+ propertyChooseView->addColumn( i18n( "Id" ), show_id ? -1 : 0 );
+
+ propertyChooseView->addColumn( i18n( "Property" ) );
+ propertyChooseView->setAllColumnsShowFocus( true );
+ boxLayout->addWidget( propertyChooseView );
+
+ TQHBoxLayout *layout2 = new TQHBoxLayout;
+
+ perUnitsLabel = new TQLabel( box );
+ perUnitsLabel->setGeometry( TQRect( 5, 285, 100, 30 ) );
+ perUnitsLabel->setText( i18n( "Per units:" ) );
+ layout2->addWidget( perUnitsLabel );
+
+ perUnitsBox = new KComboBox( FALSE, box );
+ layout2->addWidget( perUnitsBox );
+ boxLayout->addLayout( layout2 );
+
+ resize( TQSize( 200, 380 ).expandedTo( minimumSizeHint() ) );
+ clearWState( WState_Polished );
+
+ // Load data
+ loadProperties( propertyList );
+ loadUnits( unitList );
+}
+
+
+SelectPropertyDialog::~SelectPropertyDialog()
+{}
+
+
+int SelectPropertyDialog::propertyID( void )
+{
+
+ TQListViewItem * it;
+ if ( ( it = propertyChooseView->selectedItem() ) ) {
+ return ( it->text( 0 ).toInt() );
+ }
+ else
+ return ( -1 );
+}
+
+int SelectPropertyDialog::perUnitsID()
+{
+
+ int comboCount = perUnitsBox->count();
+ if ( comboCount > 0 ) { // If not, the list may be empty (no list defined) and crashes while reading as seen before. So check just in case.
+ int comboID = perUnitsBox->currentItem();
+ return ( *unitListBack->at( comboID ) ).id;
+ }
+ else
+ return ( -1 );
+}
+
+void SelectPropertyDialog::loadProperties( IngredientPropertyList *propertyList )
+{
+ for ( IngredientPropertyList::const_iterator prop_it = propertyList->begin(); prop_it != propertyList->end(); ++prop_it ) {
+ ( void ) new TQListViewItem( propertyChooseView, TQString::number( (*prop_it).id ), (*prop_it).name );
+ }
+}
+void SelectPropertyDialog::loadUnits( UnitList *unitList )
+{
+ for ( UnitList::const_iterator unit_it = unitList->begin(); unit_it != unitList->end(); ++unit_it ) {
+ TQString unitName = ( *unit_it ).name;
+ if ( unitName.isEmpty() ) {
+ if ( m_showEmpty == ShowEmptyUnit )
+ unitName = " "+i18n("-No unit-");
+ else
+ continue;
+ }
+
+ // Insert in the combobox
+ perUnitsBox->insertItem( unitName );
+
+ // Store with index for using later
+ Unit newUnit( *unit_it );
+ newUnit.name = unitName;
+ unitListBack->append( newUnit );
+ }
+}
diff --git a/src/dialogs/selectpropertydialog.h b/src/dialogs/selectpropertydialog.h
new file mode 100644
index 0000000..94d7c3b
--- /dev/null
+++ b/src/dialogs/selectpropertydialog.h
@@ -0,0 +1,60 @@
+/***************************************************************************
+* 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. *
+***************************************************************************/
+
+#ifndef SELECTPROPERTYDIALOG_H
+#define SELECTPROPERTYDIALOG_H
+
+#include <tqwidget.h>
+#include <tqlayout.h>
+#include <tqgroupbox.h>
+#include <tqlabel.h>
+#include <tqpushbutton.h>
+#include <tqvbox.h>
+
+#include <tdelistview.h>
+#include <kcombobox.h>
+#include <kdialogbase.h>
+
+#include "datablocks/unit.h"
+
+class IngredientPropertyList;
+
+/**
+@author Unai Garro
+*/
+class SelectPropertyDialog: public KDialogBase
+{
+public:
+ enum OptionFlag { ShowEmptyUnit, HideEmptyUnit } ;
+
+ // Methods
+ SelectPropertyDialog( TQWidget* parent, IngredientPropertyList *propertyList, UnitList *unitList, OptionFlag showEmpty = ShowEmptyUnit );
+ ~SelectPropertyDialog();
+ int propertyID( void );
+ int perUnitsID( void );
+private:
+ //Widgets
+ TQGroupBox *box;
+ TDEListView *propertyChooseView;
+ TQLabel *perUnitsLabel;
+ KComboBox *perUnitsBox;
+ OptionFlag m_showEmpty;
+
+ void loadProperties( IngredientPropertyList *propertyList );
+ void loadUnits( UnitList *unitList );
+
+ //Internal variables
+ UnitList *unitListBack; // To store unit list with ID's for later use
+
+};
+
+#endif
diff --git a/src/dialogs/selectrecipedialog.cpp b/src/dialogs/selectrecipedialog.cpp
new file mode 100644
index 0000000..a8a6ca6
--- /dev/null
+++ b/src/dialogs/selectrecipedialog.cpp
@@ -0,0 +1,257 @@
+/***************************************************************************
+* 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 "selectrecipedialog.h"
+
+#include <tqsignalmapper.h>
+#include <tqtabwidget.h>
+#include <tqtooltip.h>
+
+#include <tdelocale.h>
+#include <kdebug.h>
+#include <tdeapplication.h>
+#include <kprogress.h>
+#include <tdemessagebox.h>
+#include <tdeglobal.h>
+#include <tdeconfig.h>
+#include <kcursor.h>
+#include <kiconloader.h>
+
+#include "advancedsearchdialog.h"
+#include "datablocks/categorytree.h"
+#include "backends/recipedb.h"
+#include "datablocks/recipe.h"
+#include "selectunitdialog.h"
+#include "createelementdialog.h"
+#include "recipefilter.h"
+#include "widgets/recipelistview.h"
+#include "widgets/categorylistview.h"
+#include "widgets/categorycombobox.h"
+
+SelectRecipeDialog::SelectRecipeDialog( TQWidget *parent, RecipeDB* db )
+ : TQWidget( parent )
+{
+ //Store pointer to Recipe Database
+ database = db;
+
+ TQVBoxLayout *tabLayout = new TQVBoxLayout( this );
+ tabWidget = new TQTabWidget( this );
+ tabWidget->setSizePolicy( TQSizePolicy( TQSizePolicy::MinimumExpanding, TQSizePolicy::MinimumExpanding ) );
+ tabLayout->addWidget( tabWidget );
+
+ basicSearchTab = new TQGroupBox( this );
+ basicSearchTab->setFrameStyle( TQFrame::NoFrame );
+ basicSearchTab->setSizePolicy( TQSizePolicy( TQSizePolicy::MinimumExpanding, TQSizePolicy::MinimumExpanding ) );
+
+ //Design dialog
+
+ layout = new TQGridLayout( basicSearchTab, 1, 1, 0, 0 );
+
+ // Border Spacers
+ TQSpacerItem* spacer_left = new TQSpacerItem( 10, 10, TQSizePolicy::Fixed, TQSizePolicy::Minimum );
+ layout->addMultiCell( spacer_left, 1, 4, 0, 0 );
+ TQSpacerItem* spacer_top = new TQSpacerItem( 10, 10, TQSizePolicy::Minimum, TQSizePolicy::Fixed );
+ layout->addMultiCell( spacer_top, 0, 0, 1, 4 );
+
+ searchBar = new TQHBox( basicSearchTab );
+ searchBar->setSpacing( 7 );
+ layout->addWidget( searchBar, 1, 1 );
+
+ TDEIconLoader *il = new TDEIconLoader;
+ TQPushButton *clearSearchButton = new TQPushButton( searchBar );
+ clearSearchButton->setPixmap( il->loadIcon( "locationbar_erase", TDEIcon::NoGroup, 16 ) );
+
+ searchLabel = new TQLabel( searchBar );
+ searchLabel->setText( i18n( "Search:" ) );
+ searchLabel->setFixedWidth( searchLabel->fontMetrics().width( i18n( "Search:" ) ) + 5 );
+ searchBox = new KLineEdit( searchBar );
+
+ TQSpacerItem* searchSpacer = new TQSpacerItem( 10, 10, TQSizePolicy::Fixed, TQSizePolicy::Minimum );
+ layout->addItem( searchSpacer, 1, 2 );
+
+ #ifdef ENABLE_SLOW
+ categoryBox = new CategoryComboBox( basicSearchTab, database );
+ layout->addWidget( categoryBox, 1, 3 );
+ #endif
+
+ TQSpacerItem* spacerFromSearchBar = new TQSpacerItem( 10, 10, TQSizePolicy::Minimum, TQSizePolicy::Fixed );
+ layout->addItem( spacerFromSearchBar, 2, 1 );
+
+ recipeListView = new RecipeListView( basicSearchTab, database );
+ recipeListView->reload();
+ recipeListView->setSizePolicy( TQSizePolicy::Ignored, TQSizePolicy::Expanding );
+ layout->addMultiCellWidget( recipeListView, 3, 3, 1, 3 );
+
+ buttonBar = new TQHBox( basicSearchTab );
+ layout->addMultiCellWidget( buttonBar, 4, 4, 1, 3 );
+
+ openButton = new TQPushButton( buttonBar );
+ openButton->setText( i18n( "Open Recipe(s)" ) );
+ openButton->setDisabled( true );
+ TQPixmap pm = il->loadIcon( "ok", TDEIcon::NoGroup, 16 );
+ openButton->setIconSet( pm );
+ editButton = new TQPushButton( buttonBar );
+ editButton->setText( i18n( "Edit Recipe" ) );
+ editButton->setDisabled( true );
+ pm = il->loadIcon( "edit", TDEIcon::NoGroup, 16 );
+ editButton->setIconSet( pm );
+ removeButton = new TQPushButton( buttonBar );
+ removeButton->setText( i18n( "Delete" ) );
+ removeButton->setDisabled( true );
+ removeButton->setMaximumWidth( 100 );
+ pm = il->loadIcon( "editshred", TDEIcon::NoGroup, 16 );
+ removeButton->setIconSet( pm );
+
+ tabWidget->insertTab( basicSearchTab, i18n( "Basic" ) );
+
+ advancedSearch = new AdvancedSearchDialog( this, database );
+ tabWidget->insertTab( advancedSearch, i18n( "Advanced" ) );
+
+ TQToolTip::add( clearSearchButton, i18n( "Clear search" ) );
+
+ //Takes care of all recipe actions and provides a popup menu to 'recipeListView'
+ actionHandler = new RecipeActionsHandler( recipeListView, database );
+
+ recipeFilter = new RecipeFilter( recipeListView );
+
+ // Signals & Slots
+
+ connect( openButton, TQ_SIGNAL( clicked() ), actionHandler, TQ_SLOT( open() ) );
+ connect( this, TQ_SIGNAL( recipeSelected( bool ) ), openButton, TQ_SLOT( setEnabled( bool ) ) );
+ connect( editButton, TQ_SIGNAL( clicked() ), actionHandler, TQ_SLOT( edit() ) );
+ connect( this, TQ_SIGNAL( recipeSelected( bool ) ), editButton, TQ_SLOT( setEnabled( bool ) ) );
+ connect( removeButton, TQ_SIGNAL( clicked() ), actionHandler, TQ_SLOT( remove() ) );
+ connect( this, TQ_SIGNAL( recipeSelected( bool ) ), removeButton, TQ_SLOT( setEnabled( bool ) ) );
+
+ connect( clearSearchButton, TQ_SIGNAL( clicked() ), this, TQ_SLOT( clearSearch() ) );
+
+ TDEConfig * config = kapp->config();
+ config->setGroup( "Performance" );
+ if ( config->readBoolEntry("SearchAsYouType",true) ) {
+ connect( searchBox, TQ_SIGNAL( returnPressed( const TQString& ) ), recipeFilter, TQ_SLOT( filter( const TQString& ) ) );
+ connect( searchBox, TQ_SIGNAL( textChanged( const TQString& ) ), this, TQ_SLOT( ensurePopulated() ) );
+ connect( searchBox, TQ_SIGNAL( textChanged( const TQString& ) ), recipeFilter, TQ_SLOT( filter( const TQString& ) ) );
+ }
+ else {
+ connect( searchBox, TQ_SIGNAL( returnPressed( const TQString& ) ), this, TQ_SLOT( ensurePopulated() ) );
+ connect( searchBox, TQ_SIGNAL( returnPressed( const TQString& ) ), recipeFilter, TQ_SLOT( filter( const TQString& ) ) );
+ }
+
+ connect( recipeListView, TQ_SIGNAL( selectionChanged() ), this, TQ_SLOT( haveSelectedItems() ) );
+ #ifdef ENABLE_SLOW
+ connect( recipeListView, TQ_SIGNAL( nextGroupLoaded() ), categoryBox, TQ_SLOT( loadNextGroup() ) );
+ connect( recipeListView, TQ_SIGNAL( prevGroupLoaded() ), categoryBox, TQ_SLOT( loadPrevGroup() ) );
+ connect( categoryBox, TQ_SIGNAL( activated( int ) ), this, TQ_SLOT( filterComboCategory( int ) ) );
+ #endif
+ connect( recipeListView, TQ_SIGNAL( nextGroupLoaded() ), TQ_SLOT( refilter() ) );
+ connect( recipeListView, TQ_SIGNAL( prevGroupLoaded() ), TQ_SLOT( refilter() ) );
+
+ connect( advancedSearch, TQ_SIGNAL( recipeSelected( int, int ) ), TQ_SIGNAL( recipeSelected( int, int ) ) );
+ connect( advancedSearch, TQ_SIGNAL( recipesSelected( const TQValueList<int> &, int ) ), TQ_SIGNAL( recipesSelected( const TQValueList<int> &, int ) ) );
+
+ connect( actionHandler, TQ_SIGNAL( recipeSelected( int, int ) ), TQ_SIGNAL( recipeSelected( int, int ) ) );
+ connect( actionHandler, TQ_SIGNAL( recipesSelected( const TQValueList<int> &, int ) ), TQ_SIGNAL( recipesSelected( const TQValueList<int> &, int ) ) );
+
+ delete il;
+}
+
+SelectRecipeDialog::~SelectRecipeDialog()
+{
+ delete recipeFilter;
+}
+
+void SelectRecipeDialog::clearSearch()
+{
+ searchBox->setText( TQString::null );
+ recipeFilter->filter( TQString::null );
+}
+
+void SelectRecipeDialog::reload( ReloadFlags flag )
+{
+ recipeListView->reload(flag);
+
+ #ifdef ENABLE_SLOW
+ categoryBox->reload();
+ filterComboCategory( categoryBox->currentItem() );
+ #endif
+}
+
+void SelectRecipeDialog::refilter()
+{
+ if ( !searchBox->text().isEmpty() ) {
+ ensurePopulated();
+ recipeFilter->filter(searchBox->text());
+ }
+}
+
+void SelectRecipeDialog::ensurePopulated()
+{
+ recipeListView->populateAll();
+}
+
+void SelectRecipeDialog::haveSelectedItems()
+{
+ if ( recipeListView->selectedItems().count() > 0 )
+ emit recipeSelected( true );
+ else
+ emit recipeSelected( false );
+}
+
+void SelectRecipeDialog::getCurrentRecipe( Recipe *recipe )
+{
+ TQPtrList<TQListViewItem> items = recipeListView->selectedItems();
+ if ( items.count() == 1 && items.at(0)->rtti() == 1000 ) {
+ RecipeListItem * recipe_it = ( RecipeListItem* )items.at(0);
+ database->loadRecipe( recipe, RecipeDB::All, recipe_it->recipeID() );
+ }
+}
+
+void SelectRecipeDialog::filterComboCategory( int row )
+{
+ recipeListView->populateAll(); //TODO: this would be faster if we didn't need to load everything first
+
+ kdDebug() << "I got row " << row << "\n";
+
+ //First get the category ID corresponding to this combo row
+ int categoryID = categoryBox->id( row );
+
+ //Now filter
+ recipeFilter->filterCategory( categoryID ); // if categoryID==-1 doesn't filter
+ recipeFilter->filter( searchBox->text() );
+
+ if ( categoryID != -1 ) {
+ TQListViewItemIterator it( recipeListView );
+ while ( it.current() ) {
+ TQListViewItem *item = it.current();
+ if ( item->isVisible() ) {
+ item->setOpen( true ); //will only open if already populated
+ //(could be the selected category's parent
+ if ( !item->firstChild() ) {
+ recipeListView->open( item ); //populates and opens the selected category
+ break;
+ }
+ }
+ ++it;
+ }
+
+ }
+}
+
+RecipeActionsHandler* SelectRecipeDialog::getActionsHandler() const
+{
+ if ( tabWidget->currentPage() == basicSearchTab )
+ return actionHandler;
+ else
+ return advancedSearch->actionHandler;
+}
+
+#include "selectrecipedialog.moc"
diff --git a/src/dialogs/selectrecipedialog.h b/src/dialogs/selectrecipedialog.h
new file mode 100644
index 0000000..d296259
--- /dev/null
+++ b/src/dialogs/selectrecipedialog.h
@@ -0,0 +1,99 @@
+/**************************************************************************
+* 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. *
+***************************************************************************/
+
+#ifndef SELECTRECIPEDIALOG_H
+#define SELECTRECIPEDIALOG_H
+
+
+#include <tqwidget.h>
+#include <tqpushbutton.h>
+#include <tqlabel.h>
+#include <tqlayout.h>
+#include <tqcursor.h>
+#include <tqintdict.h>
+
+#include <kcombobox.h>
+#include <klineedit.h>
+#include <tdelistview.h>
+#include <kdialog.h>
+#include <tdefiledialog.h>
+#include <tdepopupmenu.h>
+
+#include "recipeactionshandler.h"
+#include "widgets/dblistviewbase.h"
+
+class TQHBox;
+class TQGroupBox;
+
+class RecipeDB;
+class ElementList;
+class Recipe;
+class AdvancedSearchDialog;
+class CategoryTree;
+class RecipeFilter;
+class RecipeListView;
+class CategoryComboBox;
+
+/**
+@author Unai Garro
+*/
+class SelectRecipeDialog : public TQWidget
+{
+ TQ_OBJECT
+public:
+ SelectRecipeDialog( TQWidget *parent, RecipeDB *db );
+ ~SelectRecipeDialog();
+
+
+ //Public Methods
+ void getCurrentRecipe( Recipe *recipe );
+
+ RecipeActionsHandler * getActionsHandler() const;
+
+private:
+
+ // Widgets
+ TQGridLayout *layout;
+ TQTabWidget *tabWidget;
+ TQGroupBox *basicSearchTab;
+ TQHBox *searchBar;
+ RecipeListView* recipeListView;
+ TQHBox *buttonBar;
+ TQPushButton *openButton;
+ TQPushButton *removeButton;
+ TQPushButton *editButton;
+ TQLabel *searchLabel;
+ KLineEdit *searchBox;
+ CategoryComboBox *categoryBox;
+ AdvancedSearchDialog *advancedSearch;
+ // Internal Data
+ RecipeDB *database;
+ RecipeActionsHandler *actionHandler;
+ RecipeFilter *recipeFilter;
+
+signals:
+ void recipeSelected( int id, int action );
+ void recipesSelected( const TQValueList<int> &ids, int action );
+ void recipeSelected( bool );
+
+private slots:
+ void filterComboCategory( int row );
+ void refilter();
+ void ensurePopulated();
+
+public slots:
+ void haveSelectedItems();
+ void reload( ReloadFlags flag = Load );
+ void clearSearch();
+};
+
+#endif
diff --git a/src/dialogs/selectunitdialog.cpp b/src/dialogs/selectunitdialog.cpp
new file mode 100644
index 0000000..d9500a6
--- /dev/null
+++ b/src/dialogs/selectunitdialog.cpp
@@ -0,0 +1,77 @@
+/***************************************************************************
+* 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 "selectunitdialog.h"
+
+#include <tdeconfig.h>
+#include <tdeglobal.h>
+#include <tdelocale.h>
+
+SelectUnitDialog::SelectUnitDialog( TQWidget* parent, const UnitList &unitList, OptionFlag showEmpty )
+ : KDialogBase( parent, "SelectUnitDialog", true, i18n( "Choose Unit" ),
+ KDialogBase::Ok | KDialogBase::Cancel, KDialogBase::Ok ), m_showEmpty(showEmpty)
+{
+ TQVBox *page = makeVBoxMainWidget();
+
+ box = new TQGroupBox( page );
+ box->setTitle( i18n( "Choose Unit" ) );
+ box->setColumnLayout( 0, TQt::Vertical );
+ TQVBoxLayout *boxLayout = new TQVBoxLayout( box->layout() );
+
+ unitChooseView = new TDEListView( box );
+
+ TDEConfig *config = TDEGlobal::config();
+ config->setGroup( "Advanced" );
+ bool show_id = config->readBoolEntry( "ShowID", false );
+ unitChooseView->addColumn( i18n( "Id" ), show_id ? -1 : 0 );
+
+ unitChooseView->addColumn( i18n( "Unit" ) );
+ unitChooseView->setSorting(1);
+ unitChooseView->setGeometry( TQRect( 5, 30, 180, 250 ) );
+ unitChooseView->setAllColumnsShowFocus( true );
+ boxLayout->addWidget( unitChooseView );
+
+ resize( TQSize( 200, 350 ) );
+
+ loadUnits( unitList );
+}
+
+
+SelectUnitDialog::~SelectUnitDialog()
+{}
+
+int SelectUnitDialog::unitID( void )
+{
+
+ TQListViewItem * it;
+ if ( ( it = unitChooseView->selectedItem() ) ) {
+ return ( it->text( 0 ).toInt() );
+ }
+ else
+ return ( -1 );
+}
+
+void SelectUnitDialog::loadUnits( const UnitList &unitList )
+{
+ for ( UnitList::const_iterator unit_it = unitList.begin(); unit_it != unitList.end(); ++unit_it ) {
+ TQString unitName = ( *unit_it ).name;
+ if ( unitName.isEmpty() ) {
+ if ( m_showEmpty == ShowEmptyUnit )
+ unitName = " "+i18n("-No unit-");
+ else
+ continue;
+ }
+
+ ( void ) new TQListViewItem( unitChooseView, TQString::number( ( *unit_it ).id ), unitName );
+ }
+}
+
diff --git a/src/dialogs/selectunitdialog.h b/src/dialogs/selectunitdialog.h
new file mode 100644
index 0000000..f2d8af0
--- /dev/null
+++ b/src/dialogs/selectunitdialog.h
@@ -0,0 +1,51 @@
+/***************************************************************************
+* 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. *
+***************************************************************************/
+
+#ifndef SELECTUNITDIALOG_H
+#define SELECTUNITDIALOG_H
+
+#include <tqwidget.h>
+#include <tqlayout.h>
+#include <tqpushbutton.h>
+#include <tqgroupbox.h>
+#include <tqvbox.h>
+
+#include <tdelistview.h>
+#include <kdialogbase.h>
+
+#include "datablocks/unit.h"
+
+/**
+@author Unai Garro
+*/
+class SelectUnitDialog : public KDialogBase
+{
+public:
+ enum OptionFlag { ShowEmptyUnit, HideEmptyUnit } ;
+
+ SelectUnitDialog( TQWidget* parent, const UnitList &unitList, OptionFlag = ShowEmptyUnit );
+
+ ~SelectUnitDialog();
+
+ int unitID( void );
+
+private:
+ //Widgets
+ TQGroupBox *box;
+ TDEListView *unitChooseView;
+ OptionFlag m_showEmpty;
+
+ void loadUnits( const UnitList &unitList );
+
+};
+
+#endif
diff --git a/src/dialogs/setupdisplay.cpp b/src/dialogs/setupdisplay.cpp
new file mode 100644
index 0000000..6efa42f
--- /dev/null
+++ b/src/dialogs/setupdisplay.cpp
@@ -0,0 +1,602 @@
+/***************************************************************************
+* Copyright (C) 2003-2005 *
+* 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 "setupdisplay.h"
+
+#include <tdeapplication.h>
+#include <tdeconfig.h>
+#include <kdebug.h>
+#include <tdefontdialog.h>
+#include <kcolordialog.h>
+#include <tdelocale.h>
+#include <tdepopupmenu.h>
+#include <kiconloader.h>
+#include <kstandarddirs.h>
+#include <tdetempfile.h>
+
+#include <tdehtmlview.h>
+#include <dom/dom_doc.h>
+#include <dom/css_rule.h>
+
+#include <tqinputdialog.h>
+#include <tqaction.h>
+#include <tqlabel.h>
+#include <tqfile.h>
+#include <tqregexp.h>
+#include <tqtextedit.h>
+#include <tqtooltip.h>
+#include <tqobjectlist.h>
+#include <tqvaluelist.h>
+#include <tqlayout.h>
+
+#include "datablocks/mixednumber.h"
+#include "dialogs/borderdialog.h"
+#include "exporters/htmlexporter.h"
+
+#include <cmath>
+
+KreDisplayItem::KreDisplayItem( const TQString &n, const TQString &_name ) : nodeId(n), name(_name)
+{
+ clear();
+}
+
+void KreDisplayItem::clear()
+{
+ alignment = TQt::AlignHCenter;
+ show = true;
+ backgroundColor = TQColor(255,255,255);
+ textColor = TQColor(0,0,0);
+ columns = 1;
+}
+
+SetupDisplay::SetupDisplay( const Recipe &sample, TQWidget *parent ) : TDEHTMLPart(parent),
+ box_properties( new PropertiesMap ),
+ node_item_map( new TQMap<TQString, KreDisplayItem*> ),
+ has_changes( false ),
+ popup(0)
+{
+ connect( this, TQ_SIGNAL( popupMenu(const TQString &,const TQPoint &) ), TQ_SLOT( nodeClicked(const TQString &,const TQPoint &) ) );
+
+ if ( sample.recipeID != -1 )
+ m_sample = sample;
+ else {
+ m_sample.title = i18n("Recipe Title");
+ m_sample.yield.amount = 0;
+ m_sample.categoryList.append( Element(i18n( "Category 1, Category 2, ..." ) ) );
+ m_sample.instructions = i18n("Instructions");
+ m_sample.prepTime = TQTime(0,0);
+
+ m_sample.authorList.append( Element(i18n( "Author 1, Author 2, ..." )) );
+
+ Ingredient ing;
+ ing.name = i18n("Ingredient 1");
+ m_sample.ingList.append( ing );
+
+ ing.name = i18n("Ingredient 2");
+ m_sample.ingList.append( ing );
+
+ ing.name = "...";
+ m_sample.ingList.append( ing );
+
+ RatingCriteria rc;
+ Rating rating1;
+ rating1.rater = i18n("Rater");
+ rating1.comment = i18n("Comment");
+
+ rc.name = i18n("Criteria 1");
+ rc.stars = 5.0;
+ rating1.append(rc);
+
+ rc.name = i18n("Criteria 2");
+ rc.stars = 2.5;
+ rating1.append(rc);
+
+ IngredientProperty prop;
+ prop.name = i18n("Property 1");
+ m_sample.properties.append(prop);
+ prop.name = i18n("Property 2");
+ m_sample.properties.append(prop);
+ prop.name = "...";
+ m_sample.properties.append(prop);
+
+ m_sample.ratingList.append(rating1);
+ }
+
+ kdDebug()<<"first load"<<endl;
+ loadHTMLView();
+ show();
+
+ createItem( "background", i18n("Background"), BackgroundColor );
+ createItem( "title", i18n("Title"), Font | BackgroundColor | TextColor | Visibility | Alignment | Border );
+ createItem( "instructions", i18n("Instructions"), Font | BackgroundColor | TextColor | Visibility | Alignment | Border );
+ createItem( "prep_time", i18n("Preparation Time"), Font | BackgroundColor | TextColor | Visibility | Alignment | Border );
+ createItem( "photo", i18n("Photo"), Visibility | Border );
+ createItem( "authors", i18n("Authors"), Font | BackgroundColor | TextColor | Visibility | Alignment | Border );
+ createItem( "categories", i18n("Categories"), Font | BackgroundColor | TextColor | Visibility | Alignment | Border );
+ createItem( "ingredients", i18n("Ingredients"), Font | BackgroundColor | TextColor | Visibility | Alignment | Border | Columns );
+ createItem( "properties", i18n("Properties"), Font | BackgroundColor | TextColor | Visibility | Alignment | Border | Columns );
+ createItem( "ratings", i18n("Ratings"), Font | BackgroundColor | TextColor | Visibility | Alignment | Border );
+ createItem( "yield", i18n("Yield"), Font | BackgroundColor | TextColor | Visibility | Alignment | Border );
+}
+
+SetupDisplay::~SetupDisplay()
+{
+ delete box_properties;
+ delete node_item_map;
+}
+
+void SetupDisplay::loadHTMLView( const TQString &templateFile, const TQString &styleFile )
+{
+ kdDebug()<<"loading template: "<<templateFile<<" style: "<<styleFile<<endl;
+ TQString tmp_filename = locateLocal( "tmp", "krecipes_recipe_view" );
+ HTMLExporter exporter( tmp_filename + ".html", "html" );
+ if ( templateFile != TQString::null )
+ exporter.setTemplate( templateFile );
+ if ( styleFile != TQString::null )
+ exporter.setStyle( styleFile );
+
+ RecipeList recipeList;
+ recipeList.append(m_sample);
+
+ TQFile file(tmp_filename + ".html");
+ if ( file.open( IO_WriteOnly ) ) {
+ TQTextStream stream(&file);
+ exporter.writeStream(stream,recipeList);
+ }
+ else {
+ kdDebug()<<"Unable to open file for writing"<<endl;
+ }
+ file.close();
+
+ KURL url;
+ url.setPath( tmp_filename + ".html" );
+ openURL( url );
+ kdDebug() << "Opening URL: " << url.htmlURL() << endl;
+}
+
+void SetupDisplay::reload()
+{
+ loadHTMLView( m_activeTemplate, m_activeStyle );
+}
+
+void SetupDisplay::loadTemplate( const TQString &filename )
+{
+ bool storeChangedState = has_changes;
+ KTempFile tmpFile;
+ saveLayout(tmpFile.name());
+ has_changes = storeChangedState; //saveLayout() sets changes to false
+
+ loadHTMLView( filename, tmpFile.name() );
+
+ m_activeTemplate = filename;
+}
+
+void SetupDisplay::createItem( const TQString &node, const TQString &name, unsigned int properties )
+{
+ KreDisplayItem * item = new KreDisplayItem( node, name );
+ box_properties->insert( item, properties );
+ node_item_map->insert( node, item );
+}
+
+void SetupDisplay::loadLayout( const TQString &filename )
+{
+ TQFile input( filename );
+ if ( input.open( IO_ReadOnly ) ) {
+ TQDomDocument doc;
+ TQString error;
+ int line;
+ int column;
+ if ( !doc.setContent( &input, &error, &line, &column ) ) {
+ kdDebug() << TQString( i18n( "\"%1\" at line %2, column %3. This may not be a Krecipes layout file." ) ).arg( error ).arg( line ).arg( column ) << endl;
+ return ;
+ }
+
+ m_styleSheet = DOM::CSSStyleSheet();
+
+ TQMap<TQString,KreDisplayItem*>::iterator it;
+ for ( it = node_item_map->begin(); it != node_item_map->end(); ++it ) {
+ it.data()->clear();
+ }
+ processDocument( doc );
+
+ loadHTMLView(m_activeTemplate, filename);
+ m_activeStyle = filename;
+
+ has_changes = false;
+ }
+ else
+ kdDebug() << "Unable to open file: " << filename << endl;
+}
+
+void SetupDisplay::beginObject( const TQString &object )
+{
+ TQMap<TQString, KreDisplayItem*>::iterator map_it = node_item_map->find( object );
+ if ( map_it != node_item_map->end() )
+ m_currentItem = map_it.data();
+ else
+ m_currentItem = 0;
+}
+
+void SetupDisplay::endObject()
+{
+ m_currentItem = 0;
+}
+
+void SetupDisplay::loadBackgroundColor( const TQString &object, const TQColor &color )
+{
+ if ( m_currentItem ) {
+ m_currentItem->backgroundColor = color;
+ m_styleSheet.insertRule("."+object+" { "+bgColorAsCSS(color)+" }",m_styleSheet.cssRules().length());
+ }
+}
+
+void SetupDisplay::loadFont( const TQString &object, const TQFont &font )
+{
+ if ( m_currentItem ) {
+ m_currentItem->font = font;
+ m_styleSheet.insertRule("."+object+" { "+fontAsCSS(font)+" }",m_styleSheet.cssRules().length());
+ }
+}
+
+void SetupDisplay::loadTextColor( const TQString &object, const TQColor &color )
+{
+ if ( m_currentItem ) {
+ m_currentItem->textColor = color;
+ m_styleSheet.insertRule("."+object+" { "+textColorAsCSS(color)+" }",m_styleSheet.cssRules().length());
+ }
+}
+
+void SetupDisplay::loadVisibility( const TQString &object, bool visible )
+{
+ if ( m_currentItem ) {
+ m_currentItem->show = visible;
+ emit itemVisibilityChanged( m_currentItem, visible );
+
+ m_styleSheet.insertRule("."+object+" { "+visibilityAsCSS(visible)+" }",m_styleSheet.cssRules().length());
+ }
+}
+
+void SetupDisplay::loadAlignment( const TQString &object, int alignment )
+{
+ if ( m_currentItem ) {
+ m_currentItem->alignment = alignment;
+ m_styleSheet.insertRule("."+object+" { "+alignmentAsCSS(alignment)+" }",m_styleSheet.cssRules().length());
+ }
+}
+
+void SetupDisplay::loadBorder( const TQString &object, const KreBorder& border )
+{
+ if ( m_currentItem ) {
+ m_currentItem->border = border;
+ m_styleSheet.insertRule("."+object+" { "+borderAsCSS(border)+" }",m_styleSheet.cssRules().length());
+ }
+}
+
+void SetupDisplay::loadColumns( const TQString &/*object*/, int cols )
+{
+ if ( m_currentItem ) {
+ m_currentItem->columns = cols;
+ }
+}
+
+void SetupDisplay::saveLayout( const TQString &filename )
+{
+ TQDomImplementation dom_imp;
+ TQDomDocument doc = dom_imp.createDocument( TQString::null, "krecipes-layout", dom_imp.createDocumentType( "krecipes-layout", TQString::null, TQString::null ) );
+
+ TQDomElement layout_tag = doc.documentElement();
+ layout_tag.setAttribute( "version", 0.4 );
+ //layout_tag.setAttribute( "generator", TQString("Krecipes v%1").arg(krecipes_version()) );
+ doc.appendChild( layout_tag );
+
+ for ( TQMap<TQString, KreDisplayItem*>::const_iterator it = node_item_map->begin(); it != node_item_map->end(); ++it ) {
+ TQDomElement base_tag = doc.createElement( it.key() );
+ layout_tag.appendChild( base_tag );
+
+ int properties = (*box_properties)[it.data()];
+ if ( properties & BackgroundColor ) {
+ TQDomElement backgroundcolor_tag = doc.createElement( "background-color" );
+ backgroundcolor_tag.appendChild( doc.createTextNode( it.data()->backgroundColor.name() ) );
+ base_tag.appendChild( backgroundcolor_tag );
+ }
+
+ if ( properties & TextColor ) {
+ TQDomElement textcolor_tag = doc.createElement( "text-color" );
+ textcolor_tag.appendChild( doc.createTextNode( it.data()->textColor.name() ) );
+ base_tag.appendChild( textcolor_tag );
+ }
+
+ if ( properties & Font ) {
+ TQDomElement font_tag = doc.createElement( "font" );
+ font_tag.appendChild( doc.createTextNode( it.data()->font.toString() ) );
+ base_tag.appendChild( font_tag );
+ }
+
+ if ( properties & Visibility ) {
+ TQDomElement visibility_tag = doc.createElement( "visible" );
+ visibility_tag.appendChild( doc.createTextNode( (it.data()->show) ? "true" : "false" ) );
+ base_tag.appendChild( visibility_tag );
+ }
+
+ if ( properties & Alignment ) {
+ TQDomElement alignment_tag = doc.createElement( "alignment" );
+ alignment_tag.appendChild( doc.createTextNode( TQString::number( it.data()->alignment ) ) );
+ base_tag.appendChild( alignment_tag );
+ }
+
+ if ( properties & Border ) {
+ TQDomElement border_tag = doc.createElement( "border" );
+ border_tag.setAttribute( "width", it.data()->border.width );
+ border_tag.setAttribute( "style", it.data()->border.style );
+ border_tag.setAttribute( "color", it.data()->border.color.name() );
+ base_tag.appendChild( border_tag );
+ }
+
+ if ( properties & Columns ) {
+ TQDomElement columns_tag = doc.createElement( "columns" );
+ columns_tag.appendChild( doc.createTextNode( TQString::number( it.data()->columns ) ) );
+ base_tag.appendChild( columns_tag );
+ }
+ }
+
+ TQFile out_file( filename );
+ if ( out_file.open( IO_WriteOnly ) ) {
+ has_changes = false;
+
+ TQTextStream stream( &out_file );
+ stream << "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n" << doc.toString();
+ }
+ else
+ kdDebug() << "Error: Unable to write to file " << filename << endl;
+}
+
+void SetupDisplay::begin(const KURL &url, int xOffset, int yOffset)
+{
+ kdDebug()<<"begin"<<endl;
+ TDEHTMLPart::begin(url,xOffset,yOffset);
+ kdDebug()<<"end"<<endl;
+
+ DOM::Document doc = document();
+ DOM::DOMImplementation impl = doc.implementation();
+ kdDebug() << "(1) document: " << document().handle() << endl;
+ #if 0
+ if ( !impl.isNull() ) {
+ //m_styleSheet = impl.createCSSStyleSheet("-krecipes","screen");
+ //m_styleSheet = DOM::CSSStyleSheet();
+ //doc.addStyleSheet(m_styleSheet);
+ //applyStylesheet();
+ }
+ #endif
+}
+
+void SetupDisplay::nodeClicked(const TQString &/*url*/,const TQPoint &point)
+{
+ DOM::Node node = nodeUnderMouse();
+ DOM::Element element;
+ if ( node.nodeType() != DOM::Node::ELEMENT_NODE ) {
+ kdDebug()<<"not an element"<<endl;
+ element = (DOM::Element)node.parentNode();
+ }
+ else
+ element = (DOM::Element)node;
+
+ while ( !element.parentNode().isNull() ) {
+ if ( element.hasAttribute("class") ) {
+ TQString id = element.getAttribute("class").string();
+ if ( node_item_map->keys().contains(id) )
+ break;
+ }
+
+ element = (DOM::Element)element.parentNode();
+ }
+
+ m_currNodeId = element.getAttribute("class").string();
+ if ( m_currNodeId.isEmpty() ) {
+ kdDebug()<<"Code error: unable to determine class of selected element"<<endl;
+ return;
+ }
+
+ KreDisplayItem *item = *node_item_map->find( m_currNodeId );
+
+ delete popup;
+ popup = new TDEPopupMenu( view() );
+ popup->insertTitle( item->name );
+
+ unsigned int properties = 0;
+ for ( PropertiesMap::const_iterator it = box_properties->begin(); it != box_properties->end(); ++it ) {
+ if ( it.key()->nodeId == m_currNodeId ) {
+ properties = it.data();
+ break;
+ }
+ }
+
+ TDEIconLoader il;
+
+ if ( properties & BackgroundColor )
+ popup->insertItem( i18n( "Background Color..." ), this, TQ_SLOT( setBackgroundColor() ) );
+
+ if ( properties & TextColor )
+ popup->insertItem( i18n( "Text Color..." ), this, TQ_SLOT( setTextColor() ) );
+
+ if ( properties & Font )
+ popup->insertItem( il.loadIconSet( "text", TDEIcon::Small, 16 ), i18n( "Font..." ), this, TQ_SLOT( setFont() ) );
+
+ if ( properties & Visibility ) {
+ int id = popup->insertItem( i18n( "Show" ), this, TQ_SLOT( setShown( int ) ) );
+ popup->setItemChecked( id, item->show );
+ }
+
+ if ( properties & Alignment ) {
+ TQPopupMenu * sub_popup = new TQPopupMenu( popup );
+
+ TQActionGroup *alignment_actions = new TQActionGroup( this );
+ alignment_actions->setExclusive( true );
+
+ TQAction *c_action = new TQAction( i18n( "Center" ), i18n( "Center" ), 0, alignment_actions, 0, true );
+ TQAction *l_action = new TQAction( i18n( "Left" ), i18n( "Left" ), 0, alignment_actions, 0, true );
+ TQAction *r_action = new TQAction( i18n( "Right" ), i18n( "Right" ), 0, alignment_actions, 0, true );
+
+ int align = item->alignment;
+ if ( align & TQt::AlignHCenter )
+ c_action->setOn(true);
+ if ( align & TQt::AlignLeft )
+ l_action->setOn(true);
+ if ( align & TQt::AlignRight )
+ r_action->setOn(true);
+
+ connect( alignment_actions, TQ_SIGNAL( selected( TQAction* ) ), TQ_SLOT( setAlignment( TQAction* ) ) );
+
+ popup->insertItem( i18n( "Alignment" ), sub_popup );
+
+ alignment_actions->addTo( sub_popup );
+ }
+
+ if ( properties & Border )
+ popup->insertItem( i18n( "Border..." ), this, TQ_SLOT( setBorder() ) );
+
+ if ( properties & Columns )
+ popup->insertItem( i18n( "Columns..." ), this, TQ_SLOT( setColumns() ) );
+
+ popup->popup( point );
+}
+
+void SetupDisplay::applyStylesheet()
+{
+ loadTemplate( m_activeTemplate );
+ if ( !document().isNull() && !m_styleSheet.isNull() ) {
+ //document().removeStyleSheet(m_styleSheet);
+ //document().addStyleSheet(m_styleSheet);
+ }
+}
+
+void SetupDisplay::setBackgroundColor()
+{
+ KreDisplayItem *item = *node_item_map->find( m_currNodeId );
+ if ( KColorDialog::getColor( item->backgroundColor, view() ) == TQDialog::Accepted ) {
+ m_currentItem = item;
+ loadBackgroundColor(m_currNodeId,item->backgroundColor);
+ m_currentItem = 0;
+
+ applyStylesheet();
+ has_changes = true;
+ }
+}
+
+void SetupDisplay::setBorder()
+{
+ KreDisplayItem *item = *node_item_map->find( m_currNodeId );
+ BorderDialog borderDialog( item->border, view() );
+ if ( borderDialog.exec() == TQDialog::Accepted ) {
+ m_currentItem = item;
+ loadBorder( m_currNodeId, borderDialog.border() );
+ m_currentItem = 0;
+
+ applyStylesheet();
+ has_changes = true;
+ }
+}
+
+void SetupDisplay::setColumns()
+{
+ KreDisplayItem *item = *node_item_map->find( m_currNodeId );
+ int cols = TQInputDialog::getInteger( TQString::null, i18n("Select the number of columns to use:"), item->columns, 1, 100, 1, 0, view() );
+ if ( cols > 0 ) {
+ m_currentItem = item;
+ loadColumns( m_currNodeId, cols );
+ m_currentItem = 0;
+
+ loadTemplate( m_activeTemplate );
+ has_changes = true;
+ }
+}
+
+void SetupDisplay::setTextColor()
+{
+ KreDisplayItem *item = *node_item_map->find( m_currNodeId );
+ if ( KColorDialog::getColor( item->textColor, view() ) == TQDialog::Accepted ) {
+ m_currentItem = item;
+ loadTextColor(m_currNodeId,item->textColor);
+ m_currentItem = 0;
+
+ applyStylesheet();
+ has_changes = true;
+ }
+}
+
+void SetupDisplay::setShown( int id )
+{
+ KreDisplayItem *item = *node_item_map->find( m_currNodeId );
+ emit itemVisibilityChanged( item, !popup->isItemChecked( id ) );
+
+ m_currentItem = item;
+ loadVisibility(m_currNodeId,!popup->isItemChecked( id ));
+ m_currentItem = 0;
+
+ applyStylesheet();
+ has_changes = true;
+}
+
+void SetupDisplay::setFont()
+{
+ KreDisplayItem *item = *node_item_map->find( m_currNodeId );
+ if ( TDEFontDialog::getFont( item->font, false, view() ) == TQDialog::Accepted ) {
+ m_currentItem = item;
+ loadFont(m_currNodeId,item->font);
+ m_currentItem = 0;
+
+ applyStylesheet();
+ has_changes = true;
+ }
+}
+
+void SetupDisplay::setAlignment( TQAction *action )
+{
+ KreDisplayItem *item = *node_item_map->find( m_currNodeId );
+
+ //TODO: isn't there a simpler way to do this...
+ //preserve non-horizontal alignment flags
+ if ( item->alignment & TQt::AlignRight )
+ item->alignment ^= TQt::AlignRight;
+ if ( item->alignment & TQt::AlignHCenter )
+ item->alignment ^= TQt::AlignHCenter;
+ if ( item->alignment & TQt::AlignLeft )
+ item->alignment ^= TQt::AlignLeft;
+
+ if ( action->text() == i18n( "Center" ) )
+ item->alignment |= TQt::AlignHCenter;
+ else if ( action->text() == i18n( "Left" ) )
+ item->alignment |= TQt::AlignLeft;
+ else if ( action->text() == i18n( "Right" ) )
+ item->alignment |= TQt::AlignRight;
+
+ m_currentItem = item;
+ loadAlignment(m_currNodeId,item->alignment);
+ m_currentItem = 0;
+
+ applyStylesheet();
+ has_changes = true;
+}
+
+void SetupDisplay::setItemShown( KreDisplayItem *item, bool visible )
+{
+ item->show = visible;
+
+ m_styleSheet.insertRule("."+item->nodeId+" { visibility:"+(item->show?"visible":"hidden")+" }",m_styleSheet.cssRules().length());
+ applyStylesheet();
+
+ has_changes = true;
+}
+
+void SetupDisplay::changeMade( void )
+{
+ has_changes = true;
+}
+
+#include "setupdisplay.moc"
diff --git a/src/dialogs/setupdisplay.h b/src/dialogs/setupdisplay.h
new file mode 100644
index 0000000..3edd092
--- /dev/null
+++ b/src/dialogs/setupdisplay.h
@@ -0,0 +1,148 @@
+/***************************************************************************
+* Copyright (C) 2003 by 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. *
+***************************************************************************/
+
+#ifndef SETUPDISPLAY_H
+#define SETUPDISPLAY_H
+
+#include <tdehtml_part.h>
+#include <dom/html_element.h>
+#include <dom/css_stylesheet.h>
+
+#include <tqdom.h>
+#include <tqwidget.h>
+#include <tqmap.h>
+
+#include "datablocks/recipe.h"
+#include "datablocks/kreborder.h"
+#include "klomanager.h"
+
+#include <math.h>
+
+class TDEPopupMenu;
+
+class TQAction;
+class TQLabel;
+class TQWidget;
+
+class StyleSheet;
+
+class KreDisplayItem
+{
+public:
+ KreDisplayItem( const TQString &id, const TQString &name );
+
+ void clear();
+
+ TQString nodeId;
+ TQString name;
+ KreBorder border;
+ int alignment;
+ int columns;
+ bool show;
+ TQColor backgroundColor;
+ TQColor textColor;
+ TQFont font;
+};
+
+typedef TQMap< KreDisplayItem*, unsigned int > PropertiesMap;
+
+/** @brief A TDEHTMLPart for editing specific CSS properties
+ *
+ * Set up the items of a recipe for display.
+ *
+ * @author Jason Kivlighn
+ */
+class SetupDisplay : public TDEHTMLPart, protected KLOManager
+{
+ TQ_OBJECT
+
+public:
+ SetupDisplay( const Recipe &, TQWidget *parent );
+ ~SetupDisplay();
+
+ enum Properties { None = 0, BackgroundColor = 1, TextColor = 2, Font = 4, Visibility = 8, Alignment = 32, Columns = 64, Border = 128 };
+
+ void saveLayout( const TQString & );
+ void loadLayout( const TQString & );
+ void loadTemplate( const TQString &filename );
+
+ bool hasChanges() const
+ {
+ return has_changes;
+ }
+
+ void setItemShown( KreDisplayItem *item, bool visible );
+
+ const PropertiesMap properties() const
+ {
+ return * box_properties;
+ }
+
+ void reload();
+
+signals:
+ void itemVisibilityChanged( KreDisplayItem *, bool );
+
+protected:
+ virtual void begin (const KURL &url=KURL(), int xOffset=0, int yOffset=0);
+
+ virtual void loadBackgroundColor( const TQString &obj, const TQColor& );
+ virtual void loadFont( const TQString &obj, const TQFont& );
+ virtual void loadTextColor( const TQString &obj, const TQColor& );
+ virtual void loadVisibility( const TQString &obj, bool );
+ virtual void loadAlignment( const TQString &obj, int );
+ virtual void loadBorder( const TQString &obj, const KreBorder& );
+ virtual void loadColumns( const TQString &obj, int );
+
+ virtual void beginObject( const TQString &obj );
+ virtual void endObject();
+
+protected slots:
+ void nodeClicked(const TQString &url,const TQPoint &point);
+ void changeMade();
+
+ //slots to set properties of item boxes
+ void setBackgroundColor();
+ void setBorder();
+ void setColumns();
+ void setTextColor();
+ void setFont();
+ void setShown( int id );
+ void setAlignment( TQAction * );
+
+private:
+ PropertiesMap *box_properties;
+ TQMap<TQString, KreDisplayItem*> *node_item_map;
+
+ bool has_changes;
+
+ // Methods
+ void applyStylesheet();
+ void loadPageLayout( const TQDomElement &tag );
+ void loadHTMLView( const TQString &templateFile = TQString::null, const TQString &styleFile = TQString::null );
+
+ void createItem( const TQString &id, const TQString &name, unsigned int properties );
+
+ //the name of the element under the mouse on a right-click
+ TQString m_currNodeId;
+
+ //the item corresponding to the current point of processing the KLO
+ KreDisplayItem *m_currentItem;
+
+ TDEPopupMenu *popup;
+ DOM::CSSStyleSheet m_styleSheet;
+ Recipe m_sample;
+
+ TQString m_activeTemplate;
+ TQString m_activeStyle;
+};
+
+#endif //SETUPDISPLAY_H
+
diff --git a/src/dialogs/shoppinglistdialog.cpp b/src/dialogs/shoppinglistdialog.cpp
new file mode 100644
index 0000000..a0ac00f
--- /dev/null
+++ b/src/dialogs/shoppinglistdialog.cpp
@@ -0,0 +1,267 @@
+/***************************************************************************
+* 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 "shoppinglistdialog.h"
+
+#include <tdelocale.h>
+#include <tdeconfig.h>
+#include <kcursor.h>
+#include <kdialog.h>
+#include <tdeglobal.h>
+#include <tdeapplication.h>
+
+#include "backends/recipedb.h"
+#include "refineshoppinglistdialog.h"
+#include "datablocks/recipelist.h"
+#include "widgets/recipelistview.h"
+#include "recipefilter.h"
+#include "recipeactionshandler.h"
+
+/** A simple listview to accept dropping a RecipeItemDrag */
+class ShoppingListView : public TDEListView
+{
+public:
+ ShoppingListView( TQWidget *parent ) : TDEListView( parent )
+ {}
+
+protected:
+ bool acceptDrag( TQDropEvent *event ) const
+ {
+ return RecipeItemDrag::canDecode( event );
+ }
+
+ TQDragObject *dragObject()
+ {
+ RecipeListItem * item = dynamic_cast<RecipeListItem*>( selectedItem() );
+ if ( item != 0 ) {
+
+ RecipeItemDrag * obj = new RecipeItemDrag( item, this, "Recipe drag item" );
+ /*const TQPixmap *pm = item->pixmap(0);
+ if( pm )
+ obj->setPixmap( *pm );*/
+ return obj;
+ }
+ return 0;
+ }
+};
+
+
+ShoppingListDialog::ShoppingListDialog( TQWidget *parent, RecipeDB *db ) : TQWidget( parent )
+{
+ // Store pointer to database
+ database = db;
+
+ // Design dialog
+ layout = new TQGridLayout( this, 2, 2, KDialog::marginHint(), KDialog::spacingHint() );
+
+ recipeListView = new KreListView ( this, i18n( "Full recipe list" ), true, 1 );
+ layout->addWidget( recipeListView, 0, 0 );
+ listview = new RecipeListView( recipeListView, database );
+ listview->setSizePolicy( TQSizePolicy::Ignored, TQSizePolicy::MinimumExpanding );
+ listview->setDragEnabled( true );
+ listview->setAcceptDrops( true );
+ listview->setDropVisualizer( false );
+ connect( recipeListView, TQ_SIGNAL( textChanged(const TQString&) ), TQ_SLOT( ensurePopulated() ) );
+ connect( listview, TQ_SIGNAL( dropped( TDEListView*, TQDropEvent*, TQListViewItem* ) ),
+ this, TQ_SLOT( slotDropped( TDEListView*, TQDropEvent*, TQListViewItem* ) ) );
+ recipeListView->setListView( listview );
+ recipeListView->setCustomFilter( new RecipeFilter( recipeListView->listView() ), TQ_SLOT( filter( const TQString & ) ) );
+ recipeListView->setSizePolicy( TQSizePolicy::Minimum, TQSizePolicy::MinimumExpanding );
+
+ TQBoxLayout* vboxl = new TQVBoxLayout( KDialog::spacingHint() );
+ TDEIconLoader il;
+ addRecipeButton = new TQPushButton( this );
+ addRecipeButton->setIconSet( il.loadIconSet( "forward", TDEIcon::Small ) );
+ addRecipeButton->setFixedSize( TQSize( 32, 32 ) );
+ addRecipeButton->setFlat( true );
+ vboxl->addWidget( addRecipeButton );
+
+ removeRecipeButton = new TQPushButton( this );
+ removeRecipeButton->setIconSet( il.loadIconSet( "back", TDEIcon::Small ) );
+ removeRecipeButton->setFixedSize( TQSize( 32, 32 ) );
+ removeRecipeButton->setFlat( true );
+ vboxl->addWidget( removeRecipeButton );
+ vboxl->addStretch();
+
+ layout->addItem( vboxl, 0, 1 );
+
+ shopRecipeListView = new KreListView ( this, i18n("Shopping List") );
+ ShoppingListView *slistview = new ShoppingListView( shopRecipeListView );
+ slistview->setSizePolicy( TQSizePolicy::Ignored, TQSizePolicy::MinimumExpanding );
+ slistview->setDragEnabled( true );
+ slistview->setAcceptDrops( true );
+ slistview->setDropVisualizer( false );
+ connect( slistview, TQ_SIGNAL( dropped( TDEListView*, TQDropEvent*, TQListViewItem* ) ),
+ this, TQ_SLOT( slotDropped( TDEListView*, TQDropEvent*, TQListViewItem* ) ) );
+ shopRecipeListView->setListView( slistview );
+ layout->addWidget( shopRecipeListView, 0, 2 );
+
+ shopRecipeListView->listView() ->addColumn( i18n( "Recipe Title" ) );
+
+ TDEConfig *config = TDEGlobal::config();
+ config->setGroup( "Advanced" );
+ bool show_id = config->readBoolEntry( "ShowID", false );
+ shopRecipeListView->listView() ->addColumn( i18n( "Id" ), show_id ? -1 : 0 );
+
+ shopRecipeListView->listView() ->setSorting( -1 );
+ shopRecipeListView->setSizePolicy( TQSizePolicy::Minimum, TQSizePolicy::MinimumExpanding );
+ shopRecipeListView->listView() ->setAllColumnsShowFocus( true );
+
+ buttonBar = new TQHBox( this, "buttonBar" );
+ layout->addMultiCellWidget( buttonBar, 1, 1, 0, 2 );
+
+ layout->setColStretch( 0, 1 );
+ layout->setColStretch( 1, 0 );
+ layout->setColStretch( 2, 1 );
+
+ okButton = new TQPushButton( buttonBar, "okButton" );
+ okButton->setText( i18n( "&OK" ) );
+ TQPixmap pm = il.loadIcon( "ok", TDEIcon::NoGroup, 16 );
+ okButton->setIconSet( pm );
+
+ //buttonBar->layout()->addItem( new TQSpacerItem( 10,10, TQSizePolicy::MinimumExpanding, TQSizePolicy::Fixed ) );
+
+ clearButton = new TQPushButton( buttonBar, "clearButton" );
+ clearButton->setText( i18n( "Clear" ) );
+ pm = il.loadIcon( "edit-clear", TDEIcon::NoGroup, 16 );
+ clearButton->setIconSet( pm );
+
+ //Takes care of all recipe actions and provides a popup menu to 'recipeListView'
+ actionHandler = new RecipeActionsHandler( recipeListView->listView(), database, RecipeActionsHandler::ExpandAll | RecipeActionsHandler::CollapseAll );
+
+ // Connect signals & slots
+ connect( addRecipeButton, TQ_SIGNAL( clicked() ), this, TQ_SLOT( addRecipe() ) );
+ connect( removeRecipeButton, TQ_SIGNAL( clicked() ), this, TQ_SLOT( removeRecipe() ) );
+ connect( okButton, TQ_SIGNAL( clicked() ), this, TQ_SLOT( showShoppingList() ) );
+ connect( clearButton, TQ_SIGNAL( clicked() ), this, TQ_SLOT( clear() ) );
+}
+
+ShoppingListDialog::~ShoppingListDialog()
+{}
+
+void ShoppingListDialog::ensurePopulated()
+{
+ listview->populateAll();
+}
+
+void ShoppingListDialog::createShopping( const RecipeList &rlist )
+{
+ clear();
+ RecipeList::const_iterator it;
+ for ( it = rlist.begin(); it != rlist.end(); ++it ) {
+ new RecipeListItem( shopRecipeListView->listView(), shopRecipeListView->listView() ->lastItem(), *it );
+ }
+}
+
+void ShoppingListDialog::reloadRecipeList( ReloadFlags flag )
+{
+ ( ( RecipeListView* ) recipeListView->listView() ) ->reload( flag );
+}
+
+void ShoppingListDialog::reload( ReloadFlags flag )
+{
+ reloadRecipeList ( flag ); // Missing: check if there's non-existing recipes in the list now, and if so, delete.
+}
+
+void ShoppingListDialog::addRecipe( void )
+{
+ TQPtrList<TQListViewItem> items = recipeListView->listView()->selectedItems();
+
+ TQPtrListIterator<TQListViewItem> it(items);
+ TQListViewItem *item;
+ while ( (item = it.current()) != 0 ) {
+ addRecipe( item );
+ ++it;
+ }
+}
+
+void ShoppingListDialog::addRecipe( TQListViewItem *item )
+{
+ if ( item ) {
+ if ( item->rtti() == 1000 ) {
+ RecipeListItem * recipe_it = ( RecipeListItem* ) item;
+
+ Recipe r;
+ r.title = recipe_it->title();
+ r.recipeID = recipe_it->recipeID();
+ ( void ) new RecipeListItem( shopRecipeListView->listView(), r );
+ }
+ }
+}
+
+void ShoppingListDialog::removeRecipe( void )
+{
+ TQListViewItem * it;
+ it = shopRecipeListView->listView() ->selectedItem();
+ if ( it )
+ delete it;
+}
+
+void ShoppingListDialog::showShoppingList( void )
+{
+ // Store the recipe list in ElementList object first
+ ElementList recipeList;
+ RecipeListItem *it;
+ for ( it = ( RecipeListItem* ) shopRecipeListView->listView() ->firstChild();it;it = ( RecipeListItem* ) it->nextSibling() ) {
+ Element newEl;
+ newEl.id = it->recipeID();
+ newEl.name = it->title(); // Storing the title is not necessary, but do it just in case it's used later on
+ recipeList.append( newEl );
+ }
+
+ RefineShoppingListDialog refineDialog( this, database, recipeList );
+ refineDialog.exec();
+}
+
+void ShoppingListDialog::addRecipeToShoppingList( int recipeID )
+{
+ Recipe r;
+ r.title = database->recipeTitle( recipeID );
+ r.recipeID = recipeID;
+
+ new RecipeListItem( shopRecipeListView->listView(), r );
+}
+
+void ShoppingListDialog::clear()
+{
+ shopRecipeListView->listView() ->clear();
+}
+
+void ShoppingListDialog::slotDropped( TDEListView *list, TQDropEvent *e, TQListViewItem * /*after*/ )
+{
+ Recipe r;
+ RecipeListItem *item = new RecipeListItem( recipeListView->listView(), r ); // needs parent, use this temporarily
+ if ( !RecipeItemDrag::decode( e, *item ) ) {
+ delete item;
+ return ;
+ }
+
+ if ( list == shopRecipeListView->listView() ) {
+ addRecipe( item );
+ }
+ //find and delete the item if we just dropped onto the recipe list from the shopping list
+ else if ( list == recipeListView->listView() && e->source() == shopRecipeListView->listView() ) {
+ TQListViewItemIterator list_it = TQListViewItemIterator( shopRecipeListView->listView() );
+ while ( list_it.current() ) {
+ if ( ( ( RecipeListItem* ) list_it.current() ) ->recipeID() == item->recipeID() ) {
+ delete list_it.current();
+ break;
+ }
+ list_it++;
+ }
+ }
+
+ delete item;
+ item = 0; // not needed anymore
+}
+
+#include "shoppinglistdialog.moc"
diff --git a/src/dialogs/shoppinglistdialog.h b/src/dialogs/shoppinglistdialog.h
new file mode 100644
index 0000000..cc8dc43
--- /dev/null
+++ b/src/dialogs/shoppinglistdialog.h
@@ -0,0 +1,76 @@
+/***************************************************************************
+* 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. *
+***************************************************************************/
+
+#ifndef SHOPPINGLISTDIALOG_H
+#define SHOPPINGLISTDIALOG_H
+
+#include <tqhbox.h>
+#include <tqlayout.h>
+#include <kpushbutton.h>
+#include <kiconloader.h>
+
+#include "widgets/krelistview.h"
+#include "widgets/dblistviewbase.h"
+
+class RecipeDB;
+class RecipeList;
+class ShoppingListViewDialog;
+class RecipeActionsHandler;
+class RecipeListView;
+
+/**
+@author Unai Garro
+*/
+
+class ShoppingListDialog: public TQWidget
+{
+ TQ_OBJECT
+public:
+
+ ShoppingListDialog( TQWidget *parent, RecipeDB *db );
+ ~ShoppingListDialog();
+ void reload( ReloadFlags flag = Load );
+ void createShopping( const RecipeList &rlist );
+
+private:
+
+ // Internal variables
+ RecipeDB *database;
+ // Internal Methods
+ void reloadRecipeList( ReloadFlags flag = Load );
+ void addRecipe( TQListViewItem *item );
+ // Widgets
+ TQGridLayout* layout;
+ TQPushButton* addRecipeButton;
+ TQPushButton* removeRecipeButton;
+ KreListView* recipeListView;
+ KreListView* shopRecipeListView;
+ TQHBox *buttonBar;
+ TQPushButton* okButton;
+ TQPushButton* clearButton;
+ ShoppingListViewDialog *shoppingListDisplay;
+ RecipeActionsHandler *actionHandler;
+ RecipeListView *listview;
+
+public slots:
+ void addRecipeToShoppingList( int recipeID ); // Called from inputdialog-> through krecipesview
+
+private slots:
+ void addRecipe( void );
+ void removeRecipe( void );
+ void showShoppingList( void );
+ void clear( void );
+ void slotDropped( TDEListView *list, TQDropEvent *e, TQListViewItem *after );
+ void ensurePopulated();
+};
+
+#endif
diff --git a/src/dialogs/shoppinglistviewdialog.cpp b/src/dialogs/shoppinglistviewdialog.cpp
new file mode 100644
index 0000000..9099aa1
--- /dev/null
+++ b/src/dialogs/shoppinglistviewdialog.cpp
@@ -0,0 +1,102 @@
+/***************************************************************************
+* 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 "shoppinglistviewdialog.h"
+#include "datablocks/ingredientlist.h"
+#include "datablocks/mixednumber.h"
+
+#include <tqpushbutton.h>
+
+#include <tdelocale.h>
+#include <tdeapplication.h>
+#include <tdeconfig.h>
+#include <kiconloader.h>
+
+ShoppingListViewDialog::ShoppingListViewDialog( TQWidget *parent, const IngredientList &ingredientList )
+ : KDialogBase( parent, "shoppingviewdialog", true, TQString::null,
+ KDialogBase::Close | KDialogBase::User1, KDialogBase::Close,
+ false, KStdGuiItem::print() )
+{
+ // Design dialog
+ TQVBox *page = makeVBoxMainWidget();
+
+ shoppingListView = new TDEHTMLPart( page );
+
+ setInitialSize( TQSize(350, 450) );
+
+ connect ( this, TQ_SIGNAL( user1Clicked() ), this, TQ_SLOT( print() ) );
+ connect ( this, TQ_SIGNAL( closeClicked() ), this, TQ_SLOT( accept() ) );
+
+ //---------- Sort the list --------
+ IngredientList list_copy = ingredientList;
+ qHeapSort( list_copy );
+
+ //---------- Load the list --------
+ display( list_copy );
+}
+
+
+ShoppingListViewDialog::~ShoppingListViewDialog()
+{}
+
+void ShoppingListViewDialog::display( const IngredientList &ingredientList )
+{
+ TQString recipeHTML;
+
+ // Create HTML Code
+
+ // Headers
+ recipeHTML = TQString( "<html><head><title>%1</title></head><body>" ).arg( i18n( "Shopping List" ) );
+ recipeHTML += "<center><div STYLE=\"width: 95%\">";
+ recipeHTML += TQString( "<center><h1>%1</h1></center>" ).arg( i18n( "Shopping List" ) );
+
+ // Ingredient List
+
+ recipeHTML += "<div STYLE=\"border:medium solid blue; width:95%\"><table cellspacing=0px width=100%><tbody>";
+ bool counter = true;
+
+ TDEConfig *config = TDEGlobal::config();
+ config->setGroup( "Formatting" );
+
+ bool useAbbreviations = config->readBoolEntry("AbbreviateUnits");
+ bool useFraction = config->readBoolEntry( "Fraction" );
+
+ for ( IngredientList::const_iterator ing_it = ingredientList.begin(); ing_it != ingredientList.end(); ++ing_it ) {
+ TQString color = ( counter ) ? "#CBCEFF" : "#BFC2F0";
+ counter = !counter;
+
+ MixedNumber::Format number_format = ( useFraction ) ? MixedNumber::MixedNumberFormat : MixedNumber::DecimalFormat;
+ TQString amount_str = MixedNumber( ( *ing_it ).amount ).toString( number_format );
+
+ TQString unit = ( *ing_it ).units.determineName( ( *ing_it ).amount + ( *ing_it ).amount_offset, useAbbreviations );
+
+ recipeHTML += TQString( "<tr bgcolor=\"%1\"><td>- %2:</td><td>%3 %4</td></tr>" ).arg( color ).arg( ( *ing_it ).name ).arg( amount_str ).arg( unit );
+ }
+ recipeHTML += "</tbody></table></div>";
+ // Close
+ recipeHTML += "</div></center></body></html>";
+
+
+ // Display
+ shoppingListView->begin( KURL( "file:/tmp/" ) ); // Initialize to /tmp, where photos and logos are stored
+ shoppingListView->write( recipeHTML );
+ shoppingListView->end();
+
+
+}
+
+void ShoppingListViewDialog::print()
+{
+ shoppingListView->view() ->print();
+}
+
+#include "shoppinglistviewdialog.moc"
diff --git a/src/dialogs/shoppinglistviewdialog.h b/src/dialogs/shoppinglistviewdialog.h
new file mode 100644
index 0000000..e080808
--- /dev/null
+++ b/src/dialogs/shoppinglistviewdialog.h
@@ -0,0 +1,46 @@
+/***************************************************************************
+* 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. *
+***************************************************************************/
+
+#ifndef SHOPPINGLISTVIEWDIALOG_H
+#define SHOPPINGLISTVIEWDIALOG_H
+
+#include <tqlayout.h>
+#include <tqvbox.h>
+#include <tqwidget.h>
+
+#include <tdehtml_part.h>
+#include <tdehtmlview.h>
+#include <kdialogbase.h>
+
+class IngredientList;
+
+class ShoppingListViewDialog: public KDialogBase
+{
+ TQ_OBJECT
+
+public:
+ ShoppingListViewDialog( TQWidget *parent, const IngredientList &ingredientList );
+ ~ShoppingListViewDialog();
+
+public slots:
+ void print();
+
+private:
+
+ // Widgets
+ TDEHTMLPart *shoppingListView;
+
+ // Internal Methods
+ void display( const IngredientList &ingredientList );
+};
+
+#endif
diff --git a/src/dialogs/similarcategoriesdialog.cpp b/src/dialogs/similarcategoriesdialog.cpp
new file mode 100644
index 0000000..75d9721
--- /dev/null
+++ b/src/dialogs/similarcategoriesdialog.cpp
@@ -0,0 +1,383 @@
+/***************************************************************************
+* Copyright (C) 2003-2006 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 "similarcategoriesdialog.h"
+
+#include <tqvariant.h>
+#include <tqpushbutton.h>
+#include <tqcombobox.h>
+#include <tqslider.h>
+#include <tqlabel.h>
+#include <tqheader.h>
+#include <tqlayout.h>
+#include <tqtooltip.h>
+#include <tqwhatsthis.h>
+
+#include <tdelistview.h>
+#include <tdelocale.h>
+#include <tdemessagebox.h>
+#include <klineedit.h>
+
+#include "widgets/categorycombobox.h"
+#include "backends/recipedb.h"
+
+SimilarCategoriesDialog::SimilarCategoriesDialog( ElementList &list, TQWidget* parent )
+ : TQDialog( parent, "SimilarCategoriesDialog", true ),
+ m_elementList(list)
+{
+ SimilarCategoriesDialogLayout = new TQVBoxLayout( this, 11, 6, "SimilarCategoriesDialogLayout");
+
+ layout6 = new TQHBoxLayout( 0, 0, 6, "layout6");
+
+ layout4 = new TQGridLayout( 0, 1, 1, 0, 6, "layout4");
+
+ categoriesBox = new KLineEdit( this );
+
+ layout4->addWidget( categoriesBox, 0, 1 );
+
+ thresholdSlider = new TQSlider( this, "thresholdSlider" );
+ thresholdSlider->setValue( 40 );
+ thresholdSlider->setOrientation( TQSlider::Horizontal );
+
+ layout4->addWidget( thresholdSlider, 1, 1 );
+
+ thresholdLabel = new TQLabel( this, "thresholdLabel" );
+
+ layout4->addWidget( thresholdLabel, 1, 0 );
+
+ categoryLabel = new TQLabel( this, "categoryLabel" );
+
+ layout4->addWidget( categoryLabel, 0, 0 );
+ layout6->addLayout( layout4 );
+
+ layout5 = new TQVBoxLayout( 0, 0, 6, "layout5");
+
+ searchButton = new TQPushButton( this, "searchButton" );
+ layout5->addWidget( searchButton );
+ spacer4 = new TQSpacerItem( 20, 51, TQSizePolicy::Minimum, TQSizePolicy::Expanding );
+ layout5->addItem( spacer4 );
+ layout6->addLayout( layout5 );
+ SimilarCategoriesDialogLayout->addLayout( layout6 );
+
+ layout9 = new TQHBoxLayout( 0, 0, 6, "layout9");
+
+ layout8 = new TQVBoxLayout( 0, 0, 6, "layout8");
+
+ allLabel = new TQLabel( this, "allLabel" );
+ layout8->addWidget( allLabel );
+
+ allListView = new TDEListView( this, "allListView" );
+ allListView->setSizePolicy( TQSizePolicy( (TQSizePolicy::SizeType)7, (TQSizePolicy::SizeType)7, 0, 1, allListView->sizePolicy().hasHeightForWidth() ) );
+ layout8->addWidget( allListView );
+ layout9->addLayout( layout8 );
+
+ layout1 = new TQVBoxLayout( 0, 0, 6, "layout1");
+
+ removeButton = new TQPushButton( this, "removeButton" );
+ layout1->addWidget( removeButton );
+
+ addButton = new TQPushButton( this, "addButton" );
+ layout1->addWidget( addButton );
+ spacer1 = new TQSpacerItem( 20, 61, TQSizePolicy::Minimum, TQSizePolicy::Expanding );
+ layout1->addItem( spacer1 );
+ layout9->addLayout( layout1 );
+
+ layout7 = new TQVBoxLayout( 0, 0, 6, "layout7");
+
+ toMergeLabel = new TQLabel( this, "toMergeLabel" );
+ layout7->addWidget( toMergeLabel );
+
+ toMergeListView = new TDEListView( this, "toMergeListView" );
+ toMergeListView->setSizePolicy( TQSizePolicy( (TQSizePolicy::SizeType)7, (TQSizePolicy::SizeType)7, 0, 1, toMergeListView->sizePolicy().hasHeightForWidth() ) );
+ layout7->addWidget( toMergeListView );
+ layout9->addLayout( layout7 );
+ SimilarCategoriesDialogLayout->addLayout( layout9 );
+
+ layout10 = new TQHBoxLayout( 0, 0, 6, "layout10");
+ spacer2 = new TQSpacerItem( 310, 20, TQSizePolicy::Expanding, TQSizePolicy::Minimum );
+ layout10->addItem( spacer2 );
+
+ mergeButton = new TQPushButton( this, "mergeButton" );
+ layout10->addWidget( mergeButton );
+
+ cancelButton = new TQPushButton( this, "cancelButton" );
+ layout10->addWidget( cancelButton );
+ SimilarCategoriesDialogLayout->addLayout( layout10 );
+ languageChange();
+ resize( TQSize(573, 429).expandedTo(minimumSizeHint()) );
+ clearWState( WState_Polished );
+
+ connect( searchButton, TQ_SIGNAL(clicked()), this, TQ_SLOT(findMatches()) );
+ connect( mergeButton, TQ_SIGNAL(clicked()), this, TQ_SLOT(mergeMatches()) );
+ connect( cancelButton, TQ_SIGNAL(clicked()), this, TQ_SLOT(reject()) );
+ connect( addButton, TQ_SIGNAL(clicked()), this, TQ_SLOT(addCategory()) );
+ connect( removeButton, TQ_SIGNAL(clicked()), this, TQ_SLOT(removeCategory()) );
+}
+
+/*
+ * Destroys the object and frees any allocated resources
+ */
+SimilarCategoriesDialog::~SimilarCategoriesDialog()
+{
+ // no need to delete child widgets, TQt does it all for us
+}
+
+/*
+ * Sets the strings of the subwidgets using the current
+ * language.
+ */
+void SimilarCategoriesDialog::languageChange()
+{
+ setCaption( i18n( "Similar Categories" ) );
+ thresholdLabel->setText( i18n( "Threshold:" ) );
+ categoryLabel->setText( i18n( "Category:" ) );
+ searchButton->setText( i18n( "Search" ) );
+ allLabel->setText( i18n( "Similar Categories:" ) );
+ removeButton->setText( i18n( "<<" ) );
+ addButton->setText( i18n( ">>" ) );
+ toMergeLabel->setText( i18n( "Categories to Merge:" ) );
+ mergeButton->setText( i18n( "Merge" ) );
+ cancelButton->setText( i18n( "Cancel" ) );
+
+ allListView->addColumn( i18n( "Category" ) );
+ //allListView->addColumn( i18n( "Id" ) );
+ toMergeListView->addColumn( i18n( "Category" ) );
+ //toMergeListView->addColumn( i18n( "Id" ) );
+}
+
+/*****************************************************/
+/*Function prototypes and libraries needed to compile*/
+/*****************************************************/
+
+#include <stdlib.h>
+#include <malloc.h>
+#include <string.h>
+int levenshtein_distance(const char *s,const char*t);
+int minimum(int a,int b,int c);
+
+/****************************************/
+/*Implementation of Levenshtein distance*/
+/****************************************/
+
+int levenshtein_distance(const char *s,const char*t)
+/*Compute levenshtein distance between s and t*/
+{
+ //Step 1
+ int k,i,j,n,m,cost,*d,distance;
+ n=strlen(s);
+ m=strlen(t);
+ if(n!=0&&m!=0)
+ {
+ d=(int*)malloc((sizeof(int))*(m+1)*(n+1));
+ m++;
+ n++;
+ //Step 2
+ for(k=0;k<n;k++)
+ d[k]=k;
+ for(k=0;k<m;k++)
+ d[k*n]=k;
+ //Step 3 and 4
+ for(i=1;i<n;i++)
+ for(j=1;j<m;j++)
+ {
+ //Step 5
+ if(s[i-1]==t[j-1])
+ cost=0;
+ else
+ cost=1;
+ //Step 6
+ d[j*n+i]=minimum(d[(j-1)*n+i]+1,d[j*n+i-1]+1,d[(j-1)*n+i-1]+cost);
+ }
+ distance=d[n*m-1];
+ free(d);
+ return distance;
+ }
+ else
+ return -1; //a negative return value means that one or both strings are empty.
+}
+
+int minimum(int a,int b,int c)
+/*Gets the minimum of three values*/
+{
+ int min=a;
+ if(b<min)
+ min=b;
+ if(c<min)
+ min=c;
+ return min;
+}
+
+/** @return an array of adjacent letter pairs contained in the input string */
+TQStringList letterPairs(const TQString& str) {
+ int numPairs = str.length()-1;
+ TQStringList pairs;
+ for (int i=0; i<numPairs; i++) {
+ pairs << str.mid(i,2);
+ }
+ return pairs;
+}
+
+/** @return an ArrayList of 2-character Strings. */
+TQValueList<TQStringList> wordLetterPairs(const TQString &str) {
+ TQValueList<TQStringList> allPairs;
+ // Tokenize the string and put the tokens/words into an array
+ TQStringList words = TQStringList::split("\\s",str);
+ // For each word
+ for (uint w=0; w < words.count(); w++) {
+ // Find the pairs of characters
+ TQStringList pairsInWord = letterPairs(words[w]);
+ for (uint p=0; p < pairsInWord.count(); p++) {
+ allPairs.append(pairsInWord[p]);
+ }
+ }
+ return allPairs;
+}
+
+/** @return lexical similarity value in the range [0,1] */
+double compareStrings(const TQString &str1, const TQString &str2) {
+ TQValueList<TQStringList> pairs1 = wordLetterPairs(str1.upper());
+ TQValueList<TQStringList> pairs2 = wordLetterPairs(str2.upper());
+ int intersection = 0;
+ int size_union = pairs1.count() + pairs2.count();
+ for (uint i=0; i<pairs1.count(); i++) {
+ TQStringList pair1=pairs1[i];
+ for(uint j=0; j<pairs2.count(); j++) {
+ TQStringList pair2=pairs2[j];
+ if (pair1 == pair2) {
+ intersection++;
+ pairs2.remove( pairs2.at(j) );
+ break;
+ }
+ }
+ }
+ return (2.0*intersection)/size_union;
+}
+
+
+
+#include <kdebug.h>
+
+#if 0
+void RecipeActionsHandler::mergeSimilar()
+{
+ TQPtrList<TQListViewItem> items = parentListView->selectedItems();
+ if ( items.count() > 1 )
+ KMessageBox::sorry( kapp->mainWidget(), i18n("Please select only one category."), TQString::null );
+ else if ( items.count() == 1 && items.at(0)->rtti() == 1001 ) {
+ CategoryListItem * cat_it = ( CategoryListItem* ) items.at(0);
+ TQString name = cat_it->categoryName();
+ const double max_allowed_distance = 0.60;
+ const int length = name.length();
+ ElementList categories;
+ database->loadCategories( &categories );
+
+ ElementList matches;
+ for ( ElementList::const_iterator it = categories.begin(); it != categories.end(); ++it ) {
+ #if 0
+ if ( levenshtein_distance(name.latin1(),(*it).name.latin1())/double(TQMAX(length,(*it).name.length())) >= max_allowed_distance ) {
+ #else
+ if ( compareStrings(name,(*it).name) >= max_allowed_distance ) {
+ #endif
+ kdDebug()<<(*it).name<<" matches"<<endl;
+ if ( cat_it->categoryId() != (*it).id )
+ matches.append(*it);
+ }
+ }
+
+
+ for ( ElementList::const_iterator it = categories.begin(); it != categories.end(); ++it ) {
+ database->mergeCategories(cat_it->categoryId(),(*it).id);
+ }
+
+ }
+ else //either nothing was selected or a recipe was selected
+ KMessageBox::sorry( kapp->mainWidget(), i18n("No recipes selected."), i18n("Edit Recipe") );
+}
+#endif
+
+void SimilarCategoriesDialog::findMatches()
+{
+ allListView->clear();
+ toMergeListView->clear();
+
+ const double threshold = (100 - thresholdSlider->value())/100.0;
+ const TQString name = categoriesBox->text();
+
+ for ( ElementList::const_iterator it = m_elementList.begin(); it != m_elementList.end(); ++it ) {
+ //kdDebug()<<(*it).name<<" (result/threshold): "<<compareStrings(name,(*it).name)<<"/"<<threshold<<endl;
+ #if 0
+ if ( levenshtein_distance(name.latin1(),(*it).name.latin1())/double(TQMAX(length,(*it).name.length())) >= max_allowed_distance ) {
+ #else
+ if ( compareStrings(name,(*it).name) >= threshold ) {
+ #endif
+ kdDebug()<<(*it).name<<" matches"<<endl;
+ //if ( id != (*it).id ) {
+ (void) new TQListViewItem(allListView,(*it).name,TQString::number((*it).id));
+ (void) new TQListViewItem(toMergeListView,(*it).name,TQString::number((*it).id));
+ //}
+ }
+ }
+}
+
+void SimilarCategoriesDialog::mergeMatches()
+{
+ if ( !toMergeListView->firstChild() ) {
+ KMessageBox::sorry( this, i18n("No categories selected to merge."), TQString::null );
+ return;
+ }
+
+ //const int id = categoriesBox->id(categoriesBox->currentItem());
+ //for ( TQListViewItem *item = toMergeListView->firstChild(); item; item = item->nextSibling() ) {
+ // m_database->mergeCategories(id,item->text(1).toInt());
+ //}
+
+ allListView->clear();
+ //toMergeListView->clear();
+
+ TQDialog::accept();
+}
+
+TQValueList<int> SimilarCategoriesDialog::matches() const
+{
+ TQValueList<int> ids;
+ for ( TQListViewItem *item = toMergeListView->firstChild(); item; item = item->nextSibling() ) {
+ ids << item->text(1).toInt();
+ }
+
+ return ids;
+}
+
+TQString SimilarCategoriesDialog::element() const
+{
+ return categoriesBox->text();
+}
+
+void SimilarCategoriesDialog::addCategory()
+{
+ TQListViewItem *item = allListView->selectedItem();
+ if ( item )
+ {
+ //make sure it isn't already in the list
+ for ( TQListViewItem *search_it = toMergeListView->firstChild(); search_it; search_it = search_it->nextSibling() ) {
+ if ( search_it->text(0) == item->text(0) )
+ return;
+ }
+
+ (void) new TQListViewItem(toMergeListView,item->text(0),item->text(1));
+ }
+}
+
+void SimilarCategoriesDialog::removeCategory()
+{
+ TQListViewItem *item = toMergeListView->selectedItem();
+ if ( item )
+ delete item;
+}
+
+#include "similarcategoriesdialog.moc"
diff --git a/src/dialogs/similarcategoriesdialog.h b/src/dialogs/similarcategoriesdialog.h
new file mode 100644
index 0000000..67d6d03
--- /dev/null
+++ b/src/dialogs/similarcategoriesdialog.h
@@ -0,0 +1,84 @@
+/***************************************************************************
+* Copyright (C) 2003-2006 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. *
+***************************************************************************/
+
+#ifndef SIMILARCATEGORIESDIALOG_H
+#define SIMILARCATEGORIESDIALOG_H
+
+#include <tqvariant.h>
+#include <tqdialog.h>
+#include <tqvaluevector.h>
+
+#include "datablocks/elementlist.h"
+
+class TQVBoxLayout;
+class TQHBoxLayout;
+class TQGridLayout;
+class TQSpacerItem;
+class TQSlider;
+class TQLabel;
+class TQPushButton;
+class TQListViewItem;
+
+class TDEListView;
+class KLineEdit;
+
+class RecipeDB;
+
+class SimilarCategoriesDialog : public TQDialog
+{
+TQ_OBJECT
+
+public:
+ SimilarCategoriesDialog( ElementList &, TQWidget* parent = 0 );
+ ~SimilarCategoriesDialog();
+
+ TQValueList<int> matches() const;
+ TQString element() const;
+
+ KLineEdit* categoriesBox;
+ TQSlider* thresholdSlider;
+ TQLabel* thresholdLabel;
+ TQLabel* categoryLabel;
+ TQPushButton* searchButton;
+ TQLabel* allLabel;
+ TDEListView* allListView;
+ TQPushButton* removeButton;
+ TQPushButton* addButton;
+ TQLabel* toMergeLabel;
+ TDEListView* toMergeListView;
+ TQPushButton* mergeButton;
+ TQPushButton* cancelButton;
+
+protected:
+ TQVBoxLayout* SimilarCategoriesDialogLayout;
+ TQHBoxLayout* layout6;
+ TQGridLayout* layout4;
+ TQVBoxLayout* layout5;
+ TQSpacerItem* spacer4;
+ TQHBoxLayout* layout9;
+ TQVBoxLayout* layout8;
+ TQVBoxLayout* layout1;
+ TQSpacerItem* spacer1;
+ TQVBoxLayout* layout7;
+ TQHBoxLayout* layout10;
+ TQSpacerItem* spacer2;
+
+protected slots:
+ virtual void languageChange();
+ void findMatches();
+ void mergeMatches();
+ void addCategory();
+ void removeCategory();
+
+private:
+ ElementList m_elementList;
+
+};
+
+#endif // SIMILARCATEGORIESDIALOG_H
diff --git a/src/dialogs/unitsdialog.cpp b/src/dialogs/unitsdialog.cpp
new file mode 100644
index 0000000..d52328a
--- /dev/null
+++ b/src/dialogs/unitsdialog.cpp
@@ -0,0 +1,211 @@
+/***************************************************************************
+* Copyright (C) 2003-2004 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 <tqlayout.h>
+#include <tqtabwidget.h>
+
+#include "unitsdialog.h"
+#include "createelementdialog.h"
+#include "dependanciesdialog.h"
+#include "backends/recipedb.h"
+#include "widgets/conversiontable.h"
+#include "widgets/unitlistview.h"
+
+#include <tdeapplication.h>
+#include <kdebug.h>
+#include <kdialog.h>
+#include <tdelocale.h>
+#include <tdemessagebox.h>
+#include <kprogress.h>
+
+UnitsDialog::UnitsDialog( TQWidget *parent, RecipeDB *db ) : TQWidget( parent )
+{
+
+ // Store pointer to database
+ database = db;
+
+ // Design dialog
+ TQHBoxLayout* page_layout = new TQHBoxLayout( this, KDialog::marginHint(), KDialog::spacingHint() );
+
+ TQTabWidget *tabWidget = new TQTabWidget( this );
+
+ TQWidget *unitTab = new TQWidget( tabWidget );
+ TQHBoxLayout* layout = new TQHBoxLayout( unitTab, KDialog::marginHint(), KDialog::spacingHint() );
+
+ unitListView = new StdUnitListView( unitTab, database, true );
+ layout->addWidget( unitListView );
+
+ TQVBoxLayout* vboxl = new TQVBoxLayout( KDialog::spacingHint() );
+ newUnitButton = new TQPushButton( unitTab );
+ newUnitButton->setText( i18n( "Create ..." ) );
+ newUnitButton->setFlat( true );
+ vboxl->addWidget( newUnitButton );
+
+ removeUnitButton = new TQPushButton( unitTab );
+ removeUnitButton->setText( i18n( "Delete" ) );
+ removeUnitButton->setFlat( true );
+ vboxl->addWidget( removeUnitButton );
+ vboxl->addStretch();
+ layout->addLayout( vboxl );
+
+ tabWidget->insertTab( unitTab, i18n( "Units" ) );
+
+ massConversionTable = new ConversionTable( tabWidget, 1, 1 );
+ tabWidget->insertTab( massConversionTable, i18n( "Mass Conversions" ) );
+
+ volumeConversionTable = new ConversionTable( tabWidget, 1, 1 );
+ tabWidget->insertTab( volumeConversionTable, i18n( "Volume Conversions" ) );
+
+ page_layout->addWidget( tabWidget );
+
+ // Connect signals & slots
+ connect( newUnitButton, TQ_SIGNAL( clicked() ), unitListView, TQ_SLOT( createNew() ) );
+ connect( removeUnitButton, TQ_SIGNAL( clicked() ), unitListView, TQ_SLOT( remove() ) );
+ connect( massConversionTable, TQ_SIGNAL( ratioChanged( int, int, double ) ), this, TQ_SLOT( saveRatio( int, int, double ) ) );
+ connect( massConversionTable, TQ_SIGNAL( ratioRemoved( int, int ) ), this, TQ_SLOT( removeRatio( int, int ) ) );
+ connect( volumeConversionTable, TQ_SIGNAL( ratioChanged( int, int, double ) ), this, TQ_SLOT( saveRatio( int, int, double ) ) );
+ connect( volumeConversionTable, TQ_SIGNAL( ratioRemoved( int, int ) ), this, TQ_SLOT( removeRatio( int, int ) ) );
+
+ //TODO: I'm too lazy right now, so do a complete reload to keep in sync with db
+ connect( database, TQ_SIGNAL( unitCreated( const Unit& ) ), this, TQ_SLOT( loadConversionTables() ) );
+ connect( database, TQ_SIGNAL( unitRemoved( int ) ), this, TQ_SLOT( loadConversionTables() ) );
+
+ //this is for the above TODO, but it still has some bugs to be worked out
+ //connect(database,TQ_SIGNAL(unitCreated(const Element&)),conversionTable,TQ_SLOT(unitCreated(const Element&)));
+ //connect(database,TQ_SIGNAL(unitRemoved(int)),conversionTable,TQ_SLOT(unitRemoved(int)));
+
+ //Populate data into the table
+ loadConversionTables();
+
+ //FIXME: We've got some sort of build issue... we get undefined references to CreateElementDialog without this dummy code here
+ CreateElementDialog d( this, "" );
+}
+
+UnitsDialog::~UnitsDialog()
+{}
+
+void UnitsDialog::reload( ReloadFlags flag )
+{
+ unitListView->reload( flag );
+ loadConversionTables();
+}
+
+void UnitsDialog::loadConversionTables( void )
+{
+ loadConversionTable( massConversionTable, Unit::Mass );
+ loadConversionTable( volumeConversionTable, Unit::Volume );
+}
+
+void UnitsDialog::loadConversionTable( ConversionTable *table, Unit::Type type )
+{
+ UnitList unitList;
+ database->loadUnits( &unitList, type );
+
+ TQStringList unitNames;
+ IDList unitIDs; // We need to store these in the table, so rows and cols are identified by unitID, not name.
+ table->clear();
+ for ( UnitList::const_iterator unit_it = unitList.begin(); unit_it != unitList.end(); ++unit_it ) {
+ unitNames.append( ( *unit_it ).name );
+ unitIDs.append( ( *unit_it ).id ); // append the element
+ }
+
+ // Resize the table
+ table->resize( unitNames.count(), unitNames.count() );
+
+ // Set the table labels, and id's
+ table->setRowLabels( unitNames );
+ table->setColumnLabels( unitNames );
+ table->setUnitIDs( unitIDs );
+
+
+ // Load and Populate the data into the table
+ UnitRatioList ratioList;
+ database->loadUnitRatios( &ratioList, type );
+ for ( UnitRatioList::const_iterator ratio_it = ratioList.begin(); ratio_it != ratioList.end(); ++ratio_it ) {
+ table->setRatio( ( *ratio_it ).uID1, ( *ratio_it ).uID2, ( *ratio_it ).ratio );
+ }
+}
+
+void UnitsDialog::saveRatio( int r, int c, double value )
+{
+ ConversionTable *conversionTable = (ConversionTable*)sender();
+ UnitRatio ratio;
+
+ ratio.uID1 = conversionTable->getUnitID( r );
+ ratio.uID2 = conversionTable->getUnitID( c );
+ ratio.ratio = value;
+ database->saveUnitRatio( &ratio );
+
+ UnitRatio reverse_ratio;
+ reverse_ratio.uID1 = ratio.uID2;
+ reverse_ratio.uID2 = ratio.uID1;
+ reverse_ratio.ratio = 1.0 / ratio.ratio;
+ database->saveUnitRatio( &reverse_ratio );
+ conversionTable->setRatio( reverse_ratio );
+
+#if 0
+ UnitRatioList ratioList;
+ database->loadUnitRatios( &ratioList, Unit::Mass );
+
+ saveAllRatios( ratioList );
+#endif
+}
+
+void UnitsDialog::removeRatio( int r, int c )
+{
+ ConversionTable *conversionTable = (ConversionTable*)sender();
+ database->removeUnitRatio( conversionTable->getUnitID( r ), conversionTable->getUnitID( c ) );
+}
+
+void UnitsDialog::saveAllRatios( UnitRatioList &ratioList )
+{
+#if 0
+ ConversionTable *conversionTable = massConversionTable;
+
+ KProgressDialog progress_dialog( this, "progress_dialog", i18n( "Finding Unit Ratios" ), TQString::null, true );
+ progress_dialog.progressBar() ->setTotalSteps( ratioList.count() * ratioList.count() );
+
+ for ( UnitRatioList::const_iterator current_it = ratioList.begin(); current_it != ratioList.end(); ++current_it ) {
+ UnitRatio current_ratio = *current_it;
+ for ( UnitRatioList::const_iterator ratio_it = ratioList.begin(); ratio_it != ratioList.end(); ++ratio_it ) {
+ if ( progress_dialog.wasCancelled() )
+ return ;
+
+ progress_dialog.progressBar() ->advance( 1 );
+ kapp->processEvents();
+
+ UnitRatio new_ratio;
+ new_ratio.uID1 = current_ratio.uID1;
+ new_ratio.uID2 = ( *ratio_it ).uID2;
+ new_ratio.ratio = ( *ratio_it ).ratio * current_ratio.ratio;
+
+ if ( ratioList.contains( new_ratio ) )
+ continue;
+
+ if ( ( ( *ratio_it ).uID1 == current_ratio.uID2 ) && ( ( *ratio_it ).uID2 != current_ratio.uID1 ) ) {
+ UnitRatio reverse_ratio;
+ reverse_ratio.uID1 = new_ratio.uID2;
+ reverse_ratio.uID2 = new_ratio.uID1;
+ reverse_ratio.ratio = 1.0 / new_ratio.ratio;
+
+ database->saveUnitRatio( &new_ratio );
+ database->saveUnitRatio( &reverse_ratio );
+ conversionTable->setRatio( new_ratio );
+ conversionTable->setRatio( reverse_ratio );
+ //ratioList.append(new_ratio); ratioList.append(reverse_ratio);
+ }
+ }
+ }
+#endif
+}
+
+#include "unitsdialog.moc"
diff --git a/src/dialogs/unitsdialog.h b/src/dialogs/unitsdialog.h
new file mode 100644
index 0000000..0810656
--- /dev/null
+++ b/src/dialogs/unitsdialog.h
@@ -0,0 +1,65 @@
+/***************************************************************************
+* Copyright (C) 2003-2004 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. *
+***************************************************************************/
+
+#ifndef UNITSDIALOG_H
+#define UNITSDIALOG_H
+#include <tqwidget.h>
+#include <tdelistview.h>
+#include <tqpushbutton.h>
+
+#include "datablocks/unitratiolist.h"
+#include "datablocks/unit.h"
+#include "widgets/dblistviewbase.h"
+
+class RecipeDB;
+class ConversionTable;
+class StdUnitListView;
+
+/**
+@author Unai Garro
+*/
+class UnitsDialog: public TQWidget
+{
+ TQ_OBJECT
+public:
+ UnitsDialog( TQWidget *parent, RecipeDB *db );
+ ~UnitsDialog();
+ virtual TQSize sizeHint () const
+ {
+ return TQSize( 300, 200 );
+ }
+
+public slots:
+ void reload( ReloadFlags flag = Load );
+
+private:
+ // Widgets
+ StdUnitListView *unitListView;
+ ConversionTable *massConversionTable;
+ ConversionTable *volumeConversionTable;
+ TQPushButton *newUnitButton;
+ TQPushButton *removeUnitButton;
+
+ // Internal methods
+ void saveAllRatios( UnitRatioList &ratioList );
+ bool checkBounds( const TQString &name );
+
+ // Internal Variables
+ RecipeDB *database;
+private slots:
+ void loadConversionTables();
+ void loadConversionTable( ConversionTable*, Unit::Type );
+ void saveRatio( int r, int c, double value );
+ void removeRatio( int r, int c );
+};
+
+#endif
diff --git a/src/dialogs/usdadatadialog.cpp b/src/dialogs/usdadatadialog.cpp
new file mode 100644
index 0000000..fd771c6
--- /dev/null
+++ b/src/dialogs/usdadatadialog.cpp
@@ -0,0 +1,200 @@
+/***************************************************************************
+* Copyright (C) 2003 by *
+* 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 "usdadatadialog.h"
+
+#include <kdebug.h>
+#include <kstandarddirs.h>
+#include <klineedit.h>
+#include <tdelistview.h>
+#include <tdelocale.h>
+#include <tdemessagebox.h>
+
+#include <tqfile.h>
+#include <tqlabel.h>
+#include <tqlayout.h>
+#include <tqpushbutton.h>
+#include <tqtextstream.h>
+#include <tqvbox.h>
+
+#include "backends/recipedb.h"
+#include "backends/usda_property_data.h"
+#include "backends/usda_unit_data.h"
+#include "widgets/krelistview.h"
+#include "datablocks/weight.h"
+
+USDADataDialog::USDADataDialog( const Element &ing, RecipeDB *db, TQWidget *parent )
+ : KDialogBase( parent, "usdaDataDialog", true, TQString::null,
+ KDialogBase::Ok | KDialogBase::Cancel, KDialogBase::Ok ),
+ ingredient( ing ),
+ database( db )
+{
+ setCaption( TQString( i18n( "Load ingredient properties for: \"%1\"" ) ).arg( ingredient.name ) );
+
+ TQVBox *page = makeVBoxMainWidget();
+
+ setButtonText( KDialogBase::Ok, i18n( "&Load" ) );
+
+ KreListView *krelistview = new KreListView( page, TQString::null, true, 0 );
+
+ listView = krelistview->listView();
+ listView->addColumn( i18n( "USDA Ingredient" ) );
+ listView->addColumn( i18n( "Id" ) );
+ listView->setAllColumnsShowFocus( true );
+
+ loadDataFromFile();
+
+ connect( listView, TQ_SIGNAL( doubleClicked( TQListViewItem*, const TQPoint &, int ) ), this, TQ_SLOT( slotOk() ) );
+}
+
+USDADataDialog::~USDADataDialog()
+{}
+
+void USDADataDialog::loadDataFromFile()
+{
+ TQString abbrev_file = locate( "appdata", "data/abbrev.txt" );
+ if ( abbrev_file.isEmpty() ) {
+ kdDebug() << "Unable to find abbrev.txt data file." << endl;
+ return ;
+ }
+
+ TQFile file( abbrev_file );
+ if ( !file.open( IO_ReadOnly ) ) {
+ kdDebug() << "Unable to open data file: " << abbrev_file << endl;
+ return ;
+ }
+
+ int index = 0;
+ TQTextStream stream( &file );
+ while ( !stream.atEnd() ) {
+ TQString line = stream.readLine();
+ if ( line.isEmpty() ) {
+ continue;
+ }
+
+ TQStringList fields = TQStringList::split( "^", line, true );
+ loaded_data << fields;
+
+ TQString ing_id = fields[ 0 ].mid( 1, fields[ 1 ].length() - 2 );
+ TQString ing_name = fields[ 1 ].mid( 1, fields[ 1 ].length() - 2 );
+ ( void ) new TQListViewItem( listView, ing_name, TQString::number( index ) ); //using an index instead of the actual id will help find the data later
+
+ index++;
+ }
+}
+
+void USDADataDialog::slotOk()
+{
+ TQListViewItem * item = listView->selectedItem();
+ if ( item ) {
+ int index = item->text( 1 ).toInt();
+ TQStringList data = loaded_data[ index ];
+
+ int grams_id = database->findExistingUnitByName( "g" ); //get this id because all data is given per gram
+ if ( grams_id == -1 ) {
+ //FIXME: take advantage of abbreviations
+ Unit unit("g","g");
+ unit.type = Unit::Mass;
+ database->createNewUnit( unit );
+ grams_id = database->lastInsertID();
+ }
+ else {
+ Unit unit = database->unitName(grams_id);
+ if ( unit.type != Unit::Mass ) {
+ unit.type = Unit::Mass;
+ database->modUnit( unit );
+ }
+ }
+
+ IngredientPropertyList property_list;
+ database->loadProperties( &property_list );
+ IngredientPropertyList existing_ing_props;
+ database->loadProperties( &existing_ing_props, ingredient.id );
+
+ int i = 0;
+ for ( TQStringList::const_iterator it = data.at( 2 ); !property_data_list[ i ].name.isEmpty(); ++it, ++i ) {
+ int property_id = property_list.findByName( property_data_list[ i ].name );
+ if ( property_id == -1 ) {
+ database->addProperty( property_data_list[ i ].name, property_data_list[ i ].unit );
+ property_id = database->lastInsertID();
+ }
+
+ double amount = ( *it ).toDouble() / 100.0; //data givin per 100g so divide by 100 to get the amount in 1 gram
+
+ if ( existing_ing_props.find( property_id ) != existing_ing_props.end() ) //property already added to ingredient, so just update
+ database->changePropertyAmountToIngredient( ingredient.id, property_id, amount, grams_id );
+ else
+ database->addPropertyToIngredient( ingredient.id, property_id, amount, grams_id );
+ }
+
+ i+=2;
+
+ int i_initial = i;
+ WeightList weights = database->ingredientWeightUnits( ingredient.id );
+ for ( ; i < i_initial+3; ++i ) {
+ Weight w;
+ w.weight = data[i].toDouble();
+
+ i++;
+
+ TQString amountAndWeight = data[i].mid( 1, data[i].length() - 2 );
+ if ( !amountAndWeight.isEmpty() ) {
+ int spaceIndex = amountAndWeight.find(" ");
+ w.perAmount = amountAndWeight.left(spaceIndex).toDouble();
+
+ TQString perAmountUnit = amountAndWeight.right(amountAndWeight.length()-spaceIndex-1);
+ if ( !parseUSDAUnitAndPrep( perAmountUnit, w.perAmountUnit, w.prepMethod ) )
+ continue;
+
+ int unitID = database->findExistingUnitByName( w.perAmountUnit );
+ if ( unitID == -1 ) {
+ for ( int i = 0; unit_data_list[ i ].name; ++i ) {
+ if ( w.perAmountUnit == unit_data_list[ i ].name || w.perAmountUnit == unit_data_list[ i ].plural ) {
+ database->createNewUnit( Unit(unit_data_list[ i ].name,unit_data_list[ i ].plural) );
+ }
+ }
+
+ unitID = database->lastInsertID();
+ }
+ w.perAmountUnitID = unitID;
+
+ if ( !w.prepMethod.isEmpty() ) {
+ int prepID = database->findExistingPrepByName( w.prepMethod );
+ if ( prepID == -1 ) {
+ database->createNewPrepMethod( w.prepMethod );
+ prepID = database->lastInsertID();
+ }
+ w.prepMethodID = prepID;
+ }
+
+ bool exists = false;
+ for ( WeightList::const_iterator it = weights.begin(); it != weights.end(); ++it ) {
+ if ( (*it).perAmountUnitID == w.perAmountUnitID && (*it).prepMethodID == w.prepMethodID ) {
+ exists = true;
+ break;
+ }
+ }
+ if ( exists )
+ continue;
+
+ w.weightUnitID = grams_id;
+ w.ingredientID = ingredient.id;
+ database->addIngredientWeight( w );
+ }
+ }
+
+ accept();
+ }
+ else
+ reject();
+}
+
+
+#include "usdadatadialog.moc"
diff --git a/src/dialogs/usdadatadialog.h b/src/dialogs/usdadatadialog.h
new file mode 100644
index 0000000..b96d9de
--- /dev/null
+++ b/src/dialogs/usdadatadialog.h
@@ -0,0 +1,47 @@
+/***************************************************************************
+* Copyright (C) 2003 by *
+* 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. *
+***************************************************************************/
+
+#ifndef USDADATADIALOG_H
+#define USDADATADIALOG_H
+
+#include <kdialogbase.h>
+
+#include <tqstringlist.h>
+#include <tqvaluelist.h>
+
+#include "datablocks/element.h"
+
+class RecipeDB;
+
+class TDEListView;
+
+class USDADataDialog : public KDialogBase
+{
+ TQ_OBJECT
+
+public:
+ USDADataDialog( const Element &, RecipeDB *database, TQWidget *parent = 0 );
+ ~USDADataDialog();
+
+private:
+ void loadDataFromFile();
+
+ TDEListView *listView;
+
+ Element ingredient;
+ RecipeDB *database;
+
+ TQValueList<TQStringList> loaded_data;
+
+private slots:
+ void slotOk();
+};
+
+#endif //USDADATADIALOG_H