diff options
Diffstat (limited to 'src/dialogs/ingredientparserdialog.cpp')
-rw-r--r-- | src/dialogs/ingredientparserdialog.cpp | 299 |
1 files changed, 299 insertions, 0 deletions
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" |