You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
krecipes/krecipes/src/dialogs/ingredientparserdialog.cpp

300 lines
9.5 KiB

/***************************************************************************
* 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 <ntqpushbutton.h>
#include <ntqtextedit.h>
#include <ntqlabel.h>
#include <ntqlineedit.h>
#include <ntqlayout.h>
#include <ntqtooltip.h>
#include <ntqwhatsthis.h>
#include <ntqheader.h>
#include <ntqapplication.h>
#include <ntqclipboard.h>
#include <ntqvbox.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"