/* -*- indent-tabs-mode: nil; -*-
 *
 * This file is part of the Mango recipe management distribution.
 * Copyright (c) 2000-2003, Roland Jesse
 * All rights reserved.
 *
 * For license and copyright information see the file COPYRIGHT or 
 * <http://www.opensource.org/licenses/bsd-license.html>.
 *
 * $Id: RecipeListDialog.cpp,v 1.23 2003/02/22 20:24:14 rjesse Exp $
 */

#include "RecipeListDialog.h"
#include "Recipe.h"
#include "RecipeModel.h"
#include "Repository.h"
#include "CreateRecipeWindow.h"
#include "ExportDialog.h"
#include "PrintPreviewForm.h"
#include "Mango.h"
#include "TodoDialog.h"

#include <qfiledialog.h>
#include <qlabel.h>
#include <qlistbox.h>
#include <qmessagebox.h>
#include <qstringlist.h>
#include <qworkspace.h>

RecipeListDialog::RecipeListDialog(
   RecipeModel* model, QWidget* parent, const char* name)
   : RecipeListForm(parent, name),
     m_model( model)
{
   connect( m_model, SIGNAL( notify()), SLOT( update()));
   QString cap( caption());
   cap.append( m_model->getName());
   setMDICaption( cap);
   initContextMenu();
   populateListBox();
   listBoxRecipes->setCurrentItem( 0);
} // Constructor.

RecipeListDialog::~RecipeListDialog()
{
}

void
RecipeListDialog::initContextMenu()
{
   m_contextMenu = new QPopupMenu( this);
   m_contextMenu->insertItem( tr( "&Remove", "Item in the context menu"),
                              this, SLOT( slotRemoveSelected()),
                              tr( "Ctrl+R", "Context menu|Remove"));
   m_contextMenu->insertItem( tr( "&Edit", "Item in the context menu"),
                              this, SLOT( slotEdit()),
                              tr( "Ctrl+E", "Context menu|Edit"));
   m_contextMenu->insertItem( tr( "&View", "Item in the context menu"),
                              this, SLOT( slotView()),
                              tr( "Ctrl+V", "Context menu|View"));
   m_contextMenu->insertItem( tr( "E&xport", "Item in the context menu"),
                              this, SLOT( slotExportSelected()),
                              tr( "Ctrl+x", "Context menu|Export"));
   connect( listBoxRecipes, SIGNAL( contextMenuRequested( QListBoxItem*, const QPoint&)),
            this, SLOT( slotContextMenu( QListBoxItem*, const QPoint&)));
} // initContextMenu()

void
RecipeListDialog::slotContextMenu( QListBoxItem*, const QPoint& pos)
{
   m_contextMenu->exec( pos);
} // slotContextMenu()

void
RecipeListDialog::slotExportSelected()  // protected
{
   int numSelected = 0;

   for (uint a = 0; a < listBoxRecipes->count(); a++)
      if (listBoxRecipes->isSelected( a)) numSelected++;

   if (numSelected == 0)
      QMessageBox::information( this,
                               tr( "Export recipe(s)"),
                               tr( "Please make a selection first."));
   else if (numSelected == 1)
      exportSingleRecipe();
   else                         // more than one recipe selected
      exportMultipleRecipes();
} // slotExportSelected()

void
RecipeListDialog::populateListBox()
{
   RecipeModel::RecipeList recipes = m_model->getRecipeList();
   QStringList stringList;
   RecipeModel::RecipeList::const_iterator it = recipes.begin();
   for (; it != recipes.end(); it++) {
	  stringList.append( (*it).title());
   }
   stringList.sort();
   listBoxRecipes->clear();
   listBoxRecipes->insertStringList( stringList);
} // populateListBox()

void
RecipeListDialog::update()
{
   int selIdx = getSelectionIndex();
   QString selTitle = listBoxRecipes->text( selIdx);
   populateListBox();
   int newIdx = getIndex( selTitle);
   listBoxRecipes->setCurrentItem( newIdx);
   slotPreview( newIdx);
} // update()

/*!
  Preview recipe at position \a index.
*/
void
RecipeListDialog::slotPreview( int index)	// protected
{
   Recipe r = m_model->getRecipeList()[index];
   Repository::getInstance()->setCurrentRecipe( r);
   previewCookbook( r);
   pixmap->setPixmap( r.picture());
   textAuthor->setText( r.typist());
   textCreationDate->setText( r.created().toString());
   textModified->setText( r.modified().toString());
   previewCategories( r);
} // slotPreview()

/*!
  \todo option: if (cookbooks > 1)
                  show cookbooks recipe is part of to the user and let
                  her select the one to remove it from.
*/
void
RecipeListDialog::slotRemoveSelected() // protected
{
   for (uint a = 0; a < listBoxRecipes->count(); a++) {
      if (listBoxRecipes->isSelected( a)) {
         Recipe r( m_model->findByTitle( listBoxRecipes->text( a)));
         m_model->remove( r);
      }
   }
}

/*!
  Convenience function. Open the currently selected recipe and let the user
  edit it.

  \sa CreateRecipeWindow
  \sa slotEdit( const QString&)
*/
void
RecipeListDialog::slotEdit() // protected
{
   slotEdit( listBoxRecipes->currentText());
}

/*!
  Open the recipe with the associated name and let the user edit it.

  \sa CreateRecipeWindow
  \sa slotEdit()
*/
void
RecipeListDialog::slotEdit( const QString& name) // protected
{
   Recipe r( m_model->findByTitle( name));
   Mango* mango = Mango::getInstance();
   CreateRecipeWindow* win = new CreateRecipeWindow( r, mango);
   mango->addWindow( win);
}

/*!
  Open the currently selected recipe for viewing.
*/
void
RecipeListDialog::slotView()    // protected
{
   slotView( listBoxRecipes->currentText());
}

/*!
  Open the recipe associated with \a item for viewing.
*/
void
RecipeListDialog::slotView( QListBoxItem* item) // protected
{
   slotView( item->text());
}

/*!
  Open the recipe with \a name for viewing.
*/
void
RecipeListDialog::slotView( const QString& name) // protected
{
   Recipe r = m_model->findByTitle( name);
   RecipeModel* tmpModel = new RecipeModel();
   *tmpModel += r;
   Mango* mango = Mango::getInstance();
   PrintPreviewForm* view = new PrintPreviewForm( mango);
   view->setMDICaption( tr( "View recipe: %1") .arg( r.title()));
   view->setRecipes( tmpModel);
   mango->addWindow( view);
   delete tmpModel;
}

/*!
  \todo: implement.
  \sa DocManager
*/
void
RecipeListDialog::slotHelp()    // protected
{
   TodoDialog* dlg= new TodoDialog( "RecipeListDialog::slotHelp", this);
   dlg->show();
}

void
RecipeListDialog::previewCookbook( const Recipe& r) // private
{
   if (! r.cookbooks().empty()) {
	  QString cookbook = r.cookbooks().front();
	  if (r.cookbooks().size() > 1)
		 cookbook.append( " ...");
	  textCookbook->setText( cookbook);
   }
}

void
RecipeListDialog::previewCategories( const Recipe& r)
{
	// We have three lines for category preview.
	QString str;
	int numCat = r.categories().size();
	if (numCat >= 1)
		str = r.categories()[0];
	textCategory1->setText( str);
	if (numCat >= 2)
		str = r.categories()[1];
	else
		str = "";
	textCategory2->setText( str);
	if (numCat >= 3)
		str = r.categories()[2];
	else
		str = "";
	textCategory3->setText( str);
}

void
RecipeListDialog::exportSingleRecipe() // private
{
   Mango* mango = Mango::getInstance();
   ExportDialog* dlg = new ExportDialog( mango);
   Recipe r = m_model->findByTitle( listBoxRecipes->currentText());
   dlg->setCurrentRecipe( r);
   dlg->show();
}

void
RecipeListDialog::exportMultipleRecipes() // private
{
   Mango* mango = Mango::getInstance();
   ExportDialog* dlg = new ExportDialog( mango);
   RecipeModel cb;
   // FIXME: need to set some name for cb?
   for (uint a = 0; a < listBoxRecipes->count(); a++) {
      if (listBoxRecipes->isSelected( a)) {
         Recipe r( m_model->findByTitle( listBoxRecipes->text( a))); 
         cb.add( r);
      }
   }
   dlg->setMarkedRecipes( &cb);
   dlg->show();
}

int
RecipeListDialog::getSelectionIndex() const
{
   uint idx = 0;
   for (idx = 0; idx != listBoxRecipes->count(); idx++)
      if (listBoxRecipes->isSelected( idx))
         break;
   return idx;
}

/*!
  \return index of string in the list box. If the list box
                does not contain the string, 0 is returned.
*/
int
RecipeListDialog::getIndex( const QString& s) const
{
   uint idx = 0;
   for (idx = 0; idx != listBoxRecipes->count(); idx++)
      if (listBoxRecipes->text( idx) == s)
         break;
   return idx;
}
