/***************************************************************************
 *   Copyright (C) 2003 by Sébastien Laoût                                 *
 *   slaout@linux62.org                                                    *
 *                                                                         *
 *   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.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.             *
 ***************************************************************************/

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <tqwidgetstack.h>
#include <tqregexp.h>
#include <tqpixmap.h>
#include <tqpainter.h>
#include <tqimage.h>
#include <tqbitmap.h>
#include <tqwhatsthis.h>
#include <tdepopupmenu.h>
#include <tqsignalmapper.h>
#include <tqdir.h>
#include <kicontheme.h>
#include <kiconloader.h>
#include <tdelocale.h>
#include <kstringhandler.h>
#include <tdemessagebox.h>
#include <tdefiledialog.h>
#include <kprogress.h>
#include <tdestandarddirs.h>
#include <tdeaboutdata.h>
#include <twin.h>
#include <tdeaccel.h>
#include <kpassivepopup.h>
#include <kxmlguifactory.h>
#include <tdecmdlineargs.h>
#include <tdeglobalaccel.h>
#include <tdeapplication.h>
#include <kkeydialog.h>
#include <dcopclient.h>
#include <kdebug.h>
#include <cstdlib>
#include <iostream>
#include "bnpview.h"
#include "basket.h"
#include "tools.h"
#include "settings.h"
#include "debugwindow.h"
#include "xmlwork.h"
#include "basketfactory.h"
#include "softwareimporters.h"
#include "colorpicker.h"
#include "regiongrabber.h"
#include "basketlistview.h"
#include "basketproperties.h"
#include "password.h"
#include "newbasketdialog.h"
#include "notedrag.h"
#include "formatimporter.h"
#include "basketstatusbar.h"
#include "backgroundmanager.h"
#include "noteedit.h" // To launch InlineEditors::initToolBars()
#include "archive.h"
#include "htmlexporter.h"
#include "crashhandler.h"
#include "likeback.h"
#include "backup.h"

/** class BNPView: */

const int BNPView::c_delayTooltipTime = 275;

BNPView::BNPView(TQWidget *parent, const char *name, KXMLGUIClient *aGUIClient,
				 TDEActionCollection *actionCollection, BasketStatusBar *bar)
	: DCOPObject("BasketIface"), TQSplitter(TQt::Horizontal, parent, name), m_actLockBasket(0), m_actPassBasket(0),
	m_loading(true), m_newBasketPopup(false), m_firstShow(true),
	m_regionGrabber(0), m_passiveDroppedSelection(0), m_passivePopup(0), m_actionCollection(actionCollection),
	m_guiClient(aGUIClient), m_statusbar(bar), m_tryHideTimer(0), m_hideTimer(0)
{
	/* Settings */
	Settings::loadConfig();

	Global::bnpView = this;

	// Needed when loading the baskets:
	Global::globalAccel       = new TDEGlobalAccel(this); // FIXME: might be null (KPart case)!
	Global::backgroundManager = new BackgroundManager();

	setupGlobalShortcuts();
	initialize();
	TQTimer::singleShot(0, this, TQ_SLOT(lateInit()));
}

BNPView::~BNPView()
{
    int treeWidth = Global::bnpView->sizes()[Settings::treeOnLeft() ? 0 : 1];

    Settings::setBasketTreeWidth(treeWidth);

    if (currentBasket() && currentBasket()->isDuringEdit())
		currentBasket()->closeEditor();

	Settings::saveConfig();

	Global::bnpView = 0;

	delete Global::systemTray;
	Global::systemTray = 0;
	delete m_colorPicker;
	delete m_statusbar;

	NoteDrag::createAndEmptyCuttingTmpFolder(); // Clean the temporary folder we used
}

void BNPView::lateInit()
{
/*
	InlineEditors* instance = InlineEditors::instance();

	if(instance)
	{
		TDEToolBar* toolbar = instance->richTextToolBar();

		if(toolbar)
			toolbar->hide();
	}
*/
	if(!isPart())
	{
		if (Settings::useSystray() && TDECmdLineArgs::parsedArgs() && TDECmdLineArgs::parsedArgs()->isSet("start-hidden"))
			if(Global::mainWindow()) Global::mainWindow()->hide();
		else if (Settings::useSystray() && tdeApp->isRestored())
			if(Global::mainWindow()) Global::mainWindow()->setShown(!Settings::startDocked());
		else
			showMainWindow();
	}

	// If the main window is hidden when session is saved, Container::queryClose()
	//  isn't called and the last value would be kept
	Settings::setStartDocked(true);
	Settings::saveConfig();

	/* System tray icon */
	Global::systemTray = new SystemTray(Global::mainWindow());
	connect( Global::systemTray, TQ_SIGNAL(showPart()), this, TQ_SIGNAL(showPart()) );
	if (Settings::useSystray())
		Global::systemTray->show();

	// Load baskets
	DEBUG_WIN << "Baskets are loaded from " + Global::basketsFolder();

	NoteDrag::createAndEmptyCuttingTmpFolder(); // If last exec hasn't done it: clean the temporary folder we will use
	Tag::loadTags(); // Tags should be ready before loading baskets, but tags need the mainContainer to be ready to create TDEActions!
	load();

	// If no basket has been found, try to import from an older version,
	if (!firstListViewItem()) {
		TQDir dir;
		dir.mkdir(Global::basketsFolder());
		if (FormatImporter::shouldImportBaskets()) {
			FormatImporter::importBaskets();
			load();
		}
		if (!firstListViewItem()) {
		// Create first basket:
			BasketFactory::newBasket(/*icon=*/"", /*name=*/i18n("General"), /*backgroundImage=*/"", /*backgroundColor=*/TQColor(), /*textColor=*/TQColor(), /*templateName=*/"1column", /*createIn=*/0);
		}
	}

	// Load the Welcome Baskets if it is the First Time:
	if (!Settings::welcomeBasketsAdded()) {
		addWelcomeBaskets();
		Settings::setWelcomeBasketsAdded(true);
		Settings::saveConfig();
	}

	m_tryHideTimer = new TQTimer(this);
	m_hideTimer    = new TQTimer(this);
	connect( m_tryHideTimer, TQ_SIGNAL(timeout()), this, TQ_SLOT(timeoutTryHide()) );
	connect( m_hideTimer,    TQ_SIGNAL(timeout()), this, TQ_SLOT(timeoutHide())    );

	// Preload every baskets for instant filtering:
/*StopWatch::start(100);
	TQListViewItemIterator it(m_tree);
	while (it.current()) {
		BasketListViewItem *item = ((BasketListViewItem*)it.current());
		item->basket()->load();
		tdeApp->processEvents();
		++it;
	}
StopWatch::check(100);*/
}

void BNPView::addWelcomeBaskets()
{
	// Possible paths where to find the welcome basket archive, trying the translated one, and falling back to the English one:
	TQStringList possiblePaths;
	if (TQString(TDEGlobal::locale()->encoding()) == TQString("UTF-8")) { // Welcome baskets are encoded in UTF-8. If the system is not, then use the English version:
		possiblePaths.append(TDEGlobal::dirs()->findResource("data", "basket/welcome/Welcome_" + TDEGlobal::locale()->language() + ".baskets"));
		possiblePaths.append(TDEGlobal::dirs()->findResource("data", "basket/welcome/Welcome_" + TQStringList::split("_", TDEGlobal::locale()->language())[0] + ".baskets"));
	}
	possiblePaths.append(TDEGlobal::dirs()->findResource("data", "basket/welcome/Welcome_en_US.baskets"));

	// Take the first EXISTING basket archive found:
	TQDir dir;
	TQString path;
	for (TQStringList::Iterator it = possiblePaths.begin(); it != possiblePaths.end(); ++it) {
		if (dir.exists(*it)) {
			path = *it;
			break;
		}
	}

	// Extract:
	if (!path.isEmpty())
		Archive::open(path);
}

void BNPView::onFirstShow()
{
	// Don't enable LikeBack until bnpview is shown. This way it works better with kontact.
	/* LikeBack */
/*	Global::likeBack = new LikeBack(LikeBack::AllButtons, / *showBarByDefault=* /true, Global::config(), Global::about());
	Global::likeBack->setServer("basket.linux62.org", "/likeback/send.php");
	Global:likeBack->setAcceptedLanguages(TQStringList::split(";", "en;fr"), i18n("Only english and french languages are accepted."));
	if (isPart())
		Global::likeBack->disableBar(); // See BNPView::shown() and BNPView::hide().
*/

	if (isPart())
		Global::likeBack->disableBar(); // See BNPView::shown() and BNPView::hide().

/*
	LikeBack::init(Global::config(), Global::about(), LikeBack::AllButtons);
	LikeBack::setServer("basket.linux62.org", "/likeback/send.php");
//	LikeBack::setServer("localhost", "/~seb/basket/likeback/send.php");
	LikeBack::setCustomLanguageMessage(i18n("Only english and french languages are accepted."));
//	LikeBack::setWindowNamesListing(LikeBack:: / *NoListing* / / *WarnUnnamedWindows* / AllWindows);
*/

	// In late init, because we need tdeApp->mainWidget() to be set!
	if (!isPart())
		connectTagsMenu();

	m_statusbar->setupStatusBar();

    int treeWidth = Settings::basketTreeWidth();
    if (treeWidth < 0)
      treeWidth = m_tree->fontMetrics().maxWidth() * 11;
    TQValueList<int> splitterSizes;
    splitterSizes.append(treeWidth);
    setSizes(splitterSizes);
}

void BNPView::setupGlobalShortcuts()
{
	/* Global shortcuts */
	TDEGlobalAccel *globalAccel = Global::globalAccel; // Better for the following lines

	// Ctrl+Shift+W only works when started standalone:
	TQWidget *basketMainWindow = (TQWidget*) (Global::bnpView->parent()->inherits("MainWindow") ? Global::bnpView->parent() : 0);

	if (basketMainWindow) {
		globalAccel->insert( "global_show_hide_main_window", i18n("Show/hide main window"),
							i18n("Allows you to show main Window if it is hidden, and to hide it if it is shown."),
							TQt::CTRL + TQt::ALT + TQt::SHIFT + TQt::Key_W, TQt::CTRL + TQt::ALT + TQt::SHIFT + TQt::Key_W,
							basketMainWindow, TQ_SLOT(changeActive()),           true, true );
	}
	globalAccel->insert( "global_paste", i18n("Paste clipboard contents in current basket"),
						 i18n("Allows you to paste clipboard contents in the current basket without having to open the main window."),
						 TQt::CTRL + TQt::ALT + TQt::SHIFT + TQt::Key_V, TQt::CTRL + TQt::ALT + TQt::SHIFT + TQt::Key_V,
						 Global::bnpView, TQ_SLOT(globalPasteInCurrentBasket()), true, true );
	globalAccel->insert( "global_show_current_basket", i18n("Show current basket name"),
						 i18n("Allows you to know basket is current without opening the main window."),
						 "", "",
						 Global::bnpView, TQ_SLOT(showPassiveContentForced()), true, true );
	globalAccel->insert( "global_paste_selection", i18n("Paste selection in current basket"),
						 i18n("Allows you to paste clipboard selection in the current basket without having to open the main window."),
						 TQt::CTRL + TQt::ALT + TQt::SHIFT + TQt::Key_S, TQt::CTRL + TQt::ALT + TQt::SHIFT + TQt::Key_S,
						 Global::bnpView, TQ_SLOT(pasteSelInCurrentBasket()),  true, true );
	globalAccel->insert( "global_new_basket", i18n("Create a new basket"),
						 i18n("Allows you to create a new basket without having to open the main window (you then can use the other global shortcuts to add a note, paste clipboard or paste selection in this new basket)."),
						 "", "",
						 Global::bnpView, TQ_SLOT(askNewBasket()),       true, true );
	globalAccel->insert( "global_previous_basket", i18n("Go to previous basket"),
						 i18n("Allows you to change current basket to the previous one without having to open the main window."),
						 "", "",
						 Global::bnpView,    TQ_SLOT(goToPreviousBasket()), true, true );
	globalAccel->insert( "global_next_basket", i18n("Go to next basket"),
						 i18n("Allows you to change current basket to the next one without having to open the main window."),
						 "", "",
						 Global::bnpView,    TQ_SLOT(goToNextBasket()),     true, true );
//	globalAccel->insert( "global_note_add_text", i18n("Insert plain text note"),
//						 i18n("Add a plain text note to the current basket without having to open the main window."),
//						 "", "", //TQt::CTRL+TQt::ALT+TQt::Key_T, TQt::CTRL+TQt::ALT+TQt::Key_T,
//						 Global::bnpView, TQ_SLOT(addNoteText()),        true, true );
	globalAccel->insert( "global_note_add_html", i18n("Insert text note"),
						 i18n("Add a text note to the current basket without having to open the main window."),
						 TQt::CTRL + TQt::ALT + TQt::SHIFT + TQt::Key_T, TQt::CTRL + TQt::ALT + TQt::SHIFT + TQt::Key_T, //"", "",
						 Global::bnpView, TQ_SLOT(addNoteHtml()),        true, true );
	globalAccel->insert( "global_note_add_image", i18n("Insert image note"),
						 i18n("Add an image note to the current basket without having to open the main window."),
						 "", "",
						 Global::bnpView, TQ_SLOT(addNoteImage()),       true, true );
	globalAccel->insert( "global_note_add_link", i18n("Insert link note"),
						 i18n("Add a link note to the current basket without having to open the main window."),
						 "", "",
						 Global::bnpView, TQ_SLOT(addNoteLink()),        true, true );
	globalAccel->insert( "global_note_add_color", i18n("Insert color note"),
						 i18n("Add a color note to the current basket without having to open the main window."),
						 "", "",
						 Global::bnpView, TQ_SLOT(addNoteColor()),       true, true );
	globalAccel->insert( "global_note_pick_color", i18n("Pick color from screen"),
						 i18n("Add a color note picked from one pixel on screen to the current basket without "
								 "having to open the main window."),
						 "", "",
						 Global::bnpView, TQ_SLOT(slotColorFromScreenGlobal()), true, true );
	globalAccel->insert( "global_note_grab_screenshot", i18n("Grab screen zone"),
						 i18n("Grab a screen zone as an image in the current basket without "
								 "having to open the main window."),
						 "", "",
						 Global::bnpView, TQ_SLOT(grabScreenshotGlobal()), true, true );
	globalAccel->readSettings();
	globalAccel->updateConnections();
}

void BNPView::initialize()
{
	/// Configure the List View Columns:
	m_tree  = new BasketTreeListView(this);
	m_tree->addColumn(i18n("Baskets"));
	m_tree->setColumnWidthMode(0, TQListView::Maximum);
	m_tree->setFullWidth(true);
	m_tree->setSorting(-1/*Disabled*/);
	m_tree->setRootIsDecorated(true);
	m_tree->setTreeStepSize(16);
	m_tree->setLineWidth(1);
	m_tree->setMidLineWidth(0);
	m_tree->setFocusPolicy(TQWidget::NoFocus);

	/// Configure the List View Drag and Drop:
	m_tree->setDragEnabled(true);
	m_tree->setAcceptDrops(true);
	m_tree->setItemsMovable(true);
	m_tree->setDragAutoScroll(true);
	m_tree->setDropVisualizer(true);
	m_tree->setDropHighlighter(true);

	/// Configure the Splitter:
	m_stack = new TQWidgetStack(this);

	setOpaqueResize(true);

	setCollapsible(m_tree,  true);
	setCollapsible(m_stack, false);
	setResizeMode(m_tree,  TQSplitter::KeepSize);
	setResizeMode(m_stack, TQSplitter::Stretch);

	/// Configure the List View Signals:
	connect( m_tree, TQ_SIGNAL(returnPressed(TQListViewItem*)),    this, TQ_SLOT(slotPressed(TQListViewItem*)) );
	connect( m_tree, TQ_SIGNAL(selectionChanged(TQListViewItem*)), this, TQ_SLOT(slotPressed(TQListViewItem*)) );
	connect( m_tree, TQ_SIGNAL(pressed(TQListViewItem*)),          this, TQ_SLOT(slotPressed(TQListViewItem*)) );
	connect( m_tree, TQ_SIGNAL(expanded(TQListViewItem*)),         this, TQ_SLOT(needSave(TQListViewItem*))    );
	connect( m_tree, TQ_SIGNAL(collapsed(TQListViewItem*)),        this, TQ_SLOT(needSave(TQListViewItem*))    );
	connect( m_tree, TQ_SIGNAL(contextMenu(TDEListView*, TQListViewItem*, const TQPoint&)),      this, TQ_SLOT(slotContextMenu(TDEListView*, TQListViewItem*, const TQPoint&))      );
	connect( m_tree, TQ_SIGNAL(mouseButtonPressed(int, TQListViewItem*, const TQPoint&, int)), this, TQ_SLOT(slotMouseButtonPressed(int, TQListViewItem*, const TQPoint&, int)) );
	connect( m_tree, TQ_SIGNAL(doubleClicked(TQListViewItem*, const TQPoint&, int)), this, TQ_SLOT(slotShowProperties(TQListViewItem*, const TQPoint&, int)) );

	connect( m_tree, TQ_SIGNAL(expanded(TQListViewItem*)),  this, TQ_SIGNAL(basketChanged()) );
	connect( m_tree, TQ_SIGNAL(collapsed(TQListViewItem*)), this, TQ_SIGNAL(basketChanged()) );
	connect( this,   TQ_SIGNAL(basketNumberChanged(int)),  this, TQ_SIGNAL(basketChanged()) );

	connect( this, TQ_SIGNAL(basketNumberChanged(int)), this, TQ_SLOT(slotBasketNumberChanged(int)) );
	connect( this, TQ_SIGNAL(basketChanged()),          this, TQ_SLOT(slotBasketChanged())          );

	/* LikeBack */
	Global::likeBack = new LikeBack(LikeBack::AllButtons, /*showBarByDefault=*/false, Global::config(), Global::about());
	Global::likeBack->setServer("basket.linux62.org", "/likeback/send.php");

// There are too much comments, and people reading comments are more and more international, so we accept only English:
//	Global::likeBack->setAcceptedLanguages(TQStringList::split(";", "en;fr"), i18n("Please write in English or French."));

//	if (isPart())
//		Global::likeBack->disableBar(); // See BNPView::shown() and BNPView::hide().

	Global::likeBack->sendACommentAction(actionCollection()); // Just create it!
	setupActions();

	/// What's This Help for the tree:
	TQWhatsThis::add(m_tree, i18n(
			"<h2>Basket Tree</h2>"
					"Here is the list of your baskets. "
					"You can organize your data by putting them in different baskets. "
					"You can group baskets by subject by creating new baskets inside others. "
					"You can browse between them by clicking a basket to open it, or reorganize them using drag and drop."));

	setTreePlacement(Settings::treeOnLeft());
}

void BNPView::setupActions()
{
	m_actSaveAsArchive = new TDEAction( i18n("&Basket Archive..."),  "baskets", 0,
	                                  this, TQ_SLOT(saveAsArchive()), actionCollection(), "basket_export_basket_archive" );
	m_actOpenArchive   = new TDEAction( i18n("&Basket Archive..."),  "baskets", 0,
	                                  this, TQ_SLOT(openArchive()),   actionCollection(), "basket_import_basket_archive" );

	m_actHideWindow = new TDEAction( i18n("&Hide Window"), "", TDEStdAccel::shortcut(TDEStdAccel::Close),
								   this, TQ_SLOT(hideOnEscape()), actionCollection(), "window_hide" );
	m_actHideWindow->setEnabled(Settings::useSystray()); // Init here !

	m_actExportToHtml = new TDEAction( i18n("&HTML Web Page..."), "text-html", 0,
	             this, TQ_SLOT(exportToHTML()),      actionCollection(), "basket_export_html" );
	new TDEAction( i18n("K&Notes"), "knotes", 0,
	             this, TQ_SLOT(importKNotes()),      actionCollection(), "basket_import_knotes" );
	new TDEAction( i18n("K&Jots"), "kjots", 0,
	             this, TQ_SLOT(importKJots()),       actionCollection(), "basket_import_kjots" );
	new TDEAction( i18n("&KnowIt..."), "knowit", 0,
	             this, TQ_SLOT(importKnowIt()),      actionCollection(), "basket_import_knowit" );
	new TDEAction( i18n("Tux&Cards..."), "tuxcards", 0,
	             this, TQ_SLOT(importTuxCards()),    actionCollection(), "basket_import_tuxcards" );
	new TDEAction( i18n("&Sticky Notes"), "gnome", 0,
	             this, TQ_SLOT(importStickyNotes()), actionCollection(), "basket_import_sticky_notes" );
	new TDEAction( i18n("&Tomboy"), "tintin", 0,
	             this, TQ_SLOT(importTomboy()),      actionCollection(), "basket_import_tomboy" );
	new TDEAction( i18n("Text &File..."), "text-plain", 0,
	             this, TQ_SLOT(importTextFile()),    actionCollection(), "basket_import_text_file" );

	new TDEAction( i18n("&Backup && Restore..."), "", 0,
	             this, TQ_SLOT(backupRestore()), actionCollection(), "basket_backup_restore" );

	/** Note : ****************************************************************/

	m_actDelNote  = new TDEAction( i18n("D&elete"), "edit-delete", "Delete",
								 this, TQ_SLOT(delNote()), actionCollection(), "edit_delete" );
	m_actCutNote  = KStdAction::cut(   this, TQ_SLOT(cutNote()),               actionCollection() );
	m_actCopyNote = KStdAction::copy(  this, TQ_SLOT(copyNote()),              actionCollection() );

	m_actSelectAll = KStdAction::selectAll( this, TQ_SLOT( slotSelectAll() ), actionCollection() );
	m_actSelectAll->setStatusText( i18n( "Selects all notes" ) );
	m_actUnselectAll = new TDEAction( i18n( "U&nselect All" ), "", this, TQ_SLOT( slotUnselectAll() ),
									actionCollection(), "edit_unselect_all" );
	m_actUnselectAll->setStatusText( i18n( "Unselects all selected notes" ) );
	m_actInvertSelection = new TDEAction( i18n( "&Invert Selection" ), CTRL+Key_Asterisk,
										this, TQ_SLOT( slotInvertSelection() ),
										actionCollection(), "edit_invert_selection" );
	m_actInvertSelection->setStatusText( i18n( "Inverts the current selection of notes" ) );

	m_actEditNote         = new TDEAction( i18n("Verb; not Menu", "&Edit..."), "edit",   "Return",
										 this, TQ_SLOT(editNote()), actionCollection(), "note_edit" );

	m_actOpenNote         = KStdAction::open( this, TQ_SLOT(openNote()), actionCollection(), "note_open" );
	m_actOpenNote->setIcon("window-new");
	m_actOpenNote->setText(i18n("&Open"));
	m_actOpenNote->setShortcut("F9");

	m_actOpenNoteWith     = new TDEAction( i18n("Open &With..."), "", "Shift+F9",
										 this, TQ_SLOT(openNoteWith()), actionCollection(), "note_open_with" );
	m_actSaveNoteAs       = KStdAction::saveAs( this, TQ_SLOT(saveNoteAs()), actionCollection(), "note_save_to_file" );
	m_actSaveNoteAs->setIcon("");
	m_actSaveNoteAs->setText(i18n("&Save to File..."));
	m_actSaveNoteAs->setShortcut("F10");

	m_actGroup        = new TDEAction( i18n("&Group"),          "attach",     "Ctrl+G",
									 this, TQ_SLOT(noteGroup()),    actionCollection(), "note_group" );
	m_actUngroup      = new TDEAction( i18n("U&ngroup"),        "",           "Ctrl+Shift+G",
									 this, TQ_SLOT(noteUngroup()),  actionCollection(), "note_ungroup" );

	m_actMoveOnTop    = new TDEAction( i18n("Move on &Top"),    "2uparrow",   "Ctrl+Shift+Home",
									 this, TQ_SLOT(moveOnTop()),    actionCollection(), "note_move_top" );
	m_actMoveNoteUp   = new TDEAction( i18n("Move &Up"),        "1uparrow",   "Ctrl+Shift+Up",
									 this, TQ_SLOT(moveNoteUp()),   actionCollection(), "note_move_up" );
	m_actMoveNoteDown = new TDEAction( i18n("Move &Down"),      "1downarrow", "Ctrl+Shift+Down",
									 this, TQ_SLOT(moveNoteDown()), actionCollection(), "note_move_down" );
	m_actMoveOnBottom = new TDEAction( i18n("Move on &Bottom"), "2downarrow", "Ctrl+Shift+End",
									 this, TQ_SLOT(moveOnBottom()), actionCollection(), "note_move_bottom" );
	m_actPaste = KStdAction::pasteText( this, TQ_SLOT(pasteInCurrentBasket()), actionCollection() );

	/** Insert : **************************************************************/

	TQSignalMapper *insertEmptyMapper  = new TQSignalMapper(this);
	TQSignalMapper *insertWizardMapper = new TQSignalMapper(this);
	connect( insertEmptyMapper,  TQ_SIGNAL(mapped(int)), this, TQ_SLOT(insertEmpty(int))  );
	connect( insertWizardMapper, TQ_SIGNAL(mapped(int)), this, TQ_SLOT(insertWizard(int)) );

//	m_actInsertText   = new TDEAction( i18n("Plai&n Text"), "text",     "Ctrl+T", actionCollection(), "insert_text"     );
	m_actInsertHtml   = new TDEAction( i18n("&Text"),       "text-html",     "Insert", actionCollection(), "insert_html"     );
	m_actInsertLink   = new TDEAction( i18n("&Link"),       "link",     "Ctrl+Y", actionCollection(), "insert_link"     );
	m_actInsertImage  = new TDEAction( i18n("&Image"),      "image-x-generic",    "",       actionCollection(), "insert_image"    );
	m_actInsertColor  = new TDEAction( i18n("&Color"),      "colorset", "",       actionCollection(), "insert_color"    );
	m_actInsertLauncher=new TDEAction( i18n("L&auncher"),   "launch",   "",       actionCollection(), "insert_launcher" );

	m_actImportKMenu  = new TDEAction( i18n("Import Launcher from &TDE Menu..."), "kmenu",      "", actionCollection(), "insert_kmenu"     );
	m_actImportIcon   = new TDEAction( i18n("Im&port Icon..."),                   "icons",      "", actionCollection(), "insert_icon"      );
	m_actLoadFile     = new TDEAction( i18n("Load From &File..."),                "fileimport", "", actionCollection(), "insert_from_file" );

//	connect( m_actInsertText,     TQ_SIGNAL(activated()), insertEmptyMapper, TQ_SLOT(map()) );
	connect( m_actInsertHtml,     TQ_SIGNAL(activated()), insertEmptyMapper, TQ_SLOT(map()) );
	connect( m_actInsertImage,    TQ_SIGNAL(activated()), insertEmptyMapper, TQ_SLOT(map()) );
	connect( m_actInsertLink,     TQ_SIGNAL(activated()), insertEmptyMapper, TQ_SLOT(map()) );
	connect( m_actInsertColor,    TQ_SIGNAL(activated()), insertEmptyMapper, TQ_SLOT(map()) );
	connect( m_actInsertLauncher, TQ_SIGNAL(activated()), insertEmptyMapper, TQ_SLOT(map()) );
//	insertEmptyMapper->setMapping(m_actInsertText,     NoteType::Text    );
	insertEmptyMapper->setMapping(m_actInsertHtml,     NoteType::Html    );
	insertEmptyMapper->setMapping(m_actInsertImage,    NoteType::Image   );
	insertEmptyMapper->setMapping(m_actInsertLink,     NoteType::Link    );
	insertEmptyMapper->setMapping(m_actInsertColor,    NoteType::Color   );
	insertEmptyMapper->setMapping(m_actInsertLauncher, NoteType::Launcher);

	connect( m_actImportKMenu, TQ_SIGNAL(activated()), insertWizardMapper, TQ_SLOT(map()) );
	connect( m_actImportIcon,  TQ_SIGNAL(activated()), insertWizardMapper, TQ_SLOT(map()) );
	connect( m_actLoadFile,    TQ_SIGNAL(activated()), insertWizardMapper, TQ_SLOT(map()) );
	insertWizardMapper->setMapping(m_actImportKMenu,  1 );
	insertWizardMapper->setMapping(m_actImportIcon,   2 );
	insertWizardMapper->setMapping(m_actLoadFile,     3 );

	m_colorPicker = new DesktopColorPicker();
	m_actColorPicker = new TDEAction( i18n("C&olor from Screen"), "kcolorchooser", "",
									this, TQ_SLOT(slotColorFromScreen()), actionCollection(), "insert_screen_color" );
	connect( m_colorPicker, TQ_SIGNAL(pickedColor(const TQColor&)), this, TQ_SLOT(colorPicked(const TQColor&)) );
	connect( m_colorPicker, TQ_SIGNAL(canceledPick()),             this, TQ_SLOT(colorPickingCanceled())     );

	m_actGrabScreenshot = new TDEAction( i18n("Grab Screen &Zone"), "ksnapshot", "",
									   this, TQ_SLOT(grabScreenshot()), actionCollection(), "insert_screen_capture" );
	//connect( m_actGrabScreenshot, TQ_SIGNAL(regionGrabbed(const TQPixmap&)), this, TQ_SLOT(screenshotGrabbed(const TQPixmap&)) );
	//connect( m_colorPicker, TQ_SIGNAL(canceledPick()),             this, TQ_SLOT(colorPickingCanceled())     );

//	m_insertActions.append( m_actInsertText     );
	m_insertActions.append( m_actInsertHtml     );
	m_insertActions.append( m_actInsertLink     );
	m_insertActions.append( m_actInsertImage    );
	m_insertActions.append( m_actInsertColor    );
	m_insertActions.append( m_actImportKMenu    );
	m_insertActions.append( m_actInsertLauncher );
	m_insertActions.append( m_actImportIcon     );
	m_insertActions.append( m_actLoadFile       );
	m_insertActions.append( m_actColorPicker    );
	m_insertActions.append( m_actGrabScreenshot );

	/** Basket : **************************************************************/

	// At this stage, main.cpp has not set tdeApp->mainWidget(), so Global::runInsideKontact()
	// returns true. We do it ourself:
	bool runInsideKontact = true;
	TQWidget *parentWidget = (TQWidget*) parent();
	while (parentWidget) {
		if (parentWidget->inherits("MainWindow"))
			runInsideKontact = false;
		parentWidget = (TQWidget*) parentWidget->parent();
	}

	// Use the "basket" incon in Kontact so it is consistent with the Kontact "New..." icon
	actNewBasket        = new TDEAction( i18n("&New Basket..."), (runInsideKontact ? "basket" : "document-new"), TDEStdAccel::shortcut(TDEStdAccel::New),
									   this, TQ_SLOT(askNewBasket()), actionCollection(), "basket_new" );
	actNewSubBasket     = new TDEAction( i18n("New &Sub-Basket..."), "", "Ctrl+Shift+N",
									   this, TQ_SLOT(askNewSubBasket()), actionCollection(), "basket_new_sub" );
	actNewSiblingBasket = new TDEAction( i18n("New Si&bling Basket..."), "", "",
									   this, TQ_SLOT(askNewSiblingBasket()), actionCollection(), "basket_new_sibling" );

	TDEActionMenu *newBasketMenu = new TDEActionMenu(i18n("&New"), "document-new", actionCollection(), "basket_new_menu");
	newBasketMenu->insert(actNewBasket);
	newBasketMenu->insert(actNewSubBasket);
	newBasketMenu->insert(actNewSiblingBasket);
	connect( newBasketMenu, TQ_SIGNAL(activated()), this, TQ_SLOT(askNewBasket()) );

	m_actPropBasket = new TDEAction( i18n("&Properties..."), "misc", "F2",
								   this, TQ_SLOT(propBasket()), actionCollection(), "basket_properties" );
	m_actDelBasket  = new TDEAction( i18n("Remove Basket", "&Remove"), "", 0,
								   this, TQ_SLOT(delBasket()), actionCollection(), "basket_remove" );
#ifdef HAVE_LIBGPGME
	m_actPassBasket = new TDEAction( i18n("Password protection", "Pass&word..."), "", 0,
								   this, TQ_SLOT(password()), actionCollection(), "basket_password" );
	m_actLockBasket = new TDEAction( i18n("Lock Basket", "&Lock"), "", "Ctrl+L",
								   this, TQ_SLOT(lockBasket()), actionCollection(), "basket_lock" );
#endif
	/** Edit : ****************************************************************/

	//m_actUndo     = KStdAction::undo(  this, TQ_SLOT(undo()),                 actionCollection() );
	//m_actUndo->setEnabled(false); // Not yet implemented !
	//m_actRedo     = KStdAction::redo(  this, TQ_SLOT(redo()),                 actionCollection() );
	//m_actRedo->setEnabled(false); // Not yet implemented !

	m_actShowFilter  = new TDEToggleAction( i18n("&Filter"), "filter", TDEStdAccel::shortcut(TDEStdAccel::Find),
										  actionCollection(), "edit_filter" );
	connect( m_actShowFilter, TQ_SIGNAL(toggled(bool)), this, TQ_SLOT(showHideFilterBar(bool)) );

	m_actFilterAllBaskets = new TDEToggleAction( i18n("Filter all &Baskets"), "edit-find", "Ctrl+Shift+F",
											   actionCollection(), "edit_filter_all_baskets" );
	connect( m_actFilterAllBaskets, TQ_SIGNAL(toggled(bool)), this, TQ_SLOT(toggleFilterAllBaskets(bool)) );

	m_actResetFilter = new TDEAction( i18n( "&Reset Filter" ), "locationbar_erase", "Ctrl+R",
									this, TQ_SLOT( slotResetFilter() ), actionCollection(), "edit_filter_reset" );

	/** Go : ******************************************************************/

	m_actPreviousBasket = new TDEAction( i18n( "&Previous Basket" ), "go-up",   "Alt+Up",
									   this, TQ_SLOT(goToPreviousBasket()), actionCollection(), "go_basket_previous" );
	m_actNextBasket     = new TDEAction( i18n( "&Next Basket" ),     "go-down", "Alt+Down",
									   this, TQ_SLOT(goToNextBasket()),     actionCollection(), "go_basket_next"     );
	m_actFoldBasket     = new TDEAction( i18n( "&Fold Basket" ),     "back",    "Alt+Left",
									   this, TQ_SLOT(foldBasket()),         actionCollection(), "go_basket_fold"     );
	m_actExpandBasket   = new TDEAction( i18n( "&Expand Basket" ),   "forward", "Alt+Right",
									   this, TQ_SLOT(expandBasket()),       actionCollection(), "go_basket_expand"   );
	// FOR_BETA_PURPOSE:
//	m_convertTexts = new TDEAction( i18n("Convert text notes to rich text notes"), "compfile", "",
//								  this, TQ_SLOT(convertTexts()), actionCollection(), "beta_convert_texts" );

	InlineEditors::instance()->initToolBars(actionCollection());

	actConfigGlobalShortcuts = KStdAction::keyBindings(this, TQ_SLOT(showGlobalShortcutsSettingsDialog()),
			actionCollection(), "options_configure_global_keybinding");
	actConfigGlobalShortcuts->setText(i18n("Configure &Global Shortcuts..."));

	/** Help : ****************************************************************/

	new TDEAction( i18n("&Welcome Baskets"), "", "", this, TQ_SLOT(addWelcomeBaskets()), actionCollection(), "help_welcome_baskets" );
}

TQListViewItem* BNPView::firstListViewItem()
{
	return m_tree->firstChild();
}

void BNPView::slotShowProperties(TQListViewItem *item, const TQPoint&, int)
{
	if (item)
		propBasket();
}

void BNPView::slotMouseButtonPressed(int button, TQListViewItem *item, const TQPoint &/*pos*/, int /*column*/)
{
	if (item && (button & TQt::MidButton)) {
		// TODO: Paste into ((BasketListViewItem*)listViewItem)->basket()
	}
}

void BNPView::slotContextMenu(TDEListView */*listView*/, TQListViewItem *item, const TQPoint &pos)
{
	TQString menuName;
	if (item) {
		Basket* basket = ((BasketListViewItem*)item)->basket();

		setCurrentBasket(basket);
		menuName = "basket_popup";
	} else {
		menuName = "tab_bar_popup";
		/*
		* "File -> New" create a new basket with the same parent basket as the the current one.
		* But when invoked when right-clicking the empty area at the bottom of the basket tree,
		* it is obvious the user want to create a new basket at the bottom of the tree (with no parent).
		* So we set a temporary variable during the time the popup menu is shown,
		 * so the slot askNewBasket() will do the right thing:
		*/
		setNewBasketPopup();
	}

	TQPopupMenu *menu = popupMenu(menuName);
	connect( menu, TQ_SIGNAL(aboutToHide()),  this, TQ_SLOT(aboutToHideNewBasketPopup()) );
	menu->exec(pos);
}

void BNPView::save()
{
	DEBUG_WIN << "Basket Tree: Saving...";

	// Create Document:
	TQDomDocument document("basketTree");
	TQDomElement root = document.createElement("basketTree");
	document.appendChild(root);

	// Save Basket Tree:
	save(m_tree->firstChild(), document, root);

	// Write to Disk:
	Basket::safelySaveToFile(Global::basketsFolder() + "baskets.xml", "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n" + document.toString());
// 	TQFile file(Global::basketsFolder() + "baskets.xml");
// 	if (file.open(IO_WriteOnly)) {
// 		TQTextStream stream(&file);
// 		stream.setEncoding(TQTextStream::UnicodeUTF8);
// 		TQString xml = document.toString();
// 		stream << "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n";
// 		stream << xml;
// 		file.close();
// 	}
}

void BNPView::save(TQListViewItem *firstItem, TQDomDocument &document, TQDomElement &parentElement)
{
	TQListViewItem *item = firstItem;
	while (item) {
//		Basket *basket = ((BasketListViewItem*)item)->basket();
		TQDomElement basketElement = this->basketElement(item, document, parentElement);
/*
		TQDomElement basketElement = document.createElement("basket");
		parentElement.appendChild(basketElement);
		// Save Attributes:
		basketElement.setAttribute("folderName", basket->folderName());
		if (item->firstChild()) // If it can be expanded/folded:
			basketElement.setAttribute("folded", XMLWork::trueOrFalse(!item->isOpen()));
		if (((BasketListViewItem*)item)->isCurrentBasket())
			basketElement.setAttribute("lastOpened", "true");
		// Save Properties:
		TQDomElement properties = document.createElement("properties");
		basketElement.appendChild(properties);
		basket->saveProperties(document, properties);
*/
		// Save Child Basket:
		if (item->firstChild())
			save(item->firstChild(), document, basketElement);
		// Next Basket:
		item = item->nextSibling();
	}
}

TQDomElement BNPView::basketElement(TQListViewItem *item, TQDomDocument &document, TQDomElement &parentElement)
{
	Basket *basket = ((BasketListViewItem*)item)->basket();
	TQDomElement basketElement = document.createElement("basket");
	parentElement.appendChild(basketElement);
	// Save Attributes:
	basketElement.setAttribute("folderName", basket->folderName());
	if (item->firstChild()) // If it can be expanded/folded:
		basketElement.setAttribute("folded", XMLWork::trueOrFalse(!item->isOpen()));
	if (((BasketListViewItem*)item)->isCurrentBasket())
		basketElement.setAttribute("lastOpened", "true");
	// Save Properties:
	TQDomElement properties = document.createElement("properties");
	basketElement.appendChild(properties);
	basket->saveProperties(document, properties);
	return basketElement;
}

void BNPView::saveSubHierarchy(TQListViewItem *item, TQDomDocument &document, TQDomElement &parentElement, bool recursive)
{
	TQDomElement element = basketElement(item, document, parentElement);
	if (recursive && item->firstChild())
		save(item->firstChild(), document, element);
}

void BNPView::load()
{
	TQDomDocument *doc = XMLWork::openFile("basketTree", Global::basketsFolder() + "baskets.xml");
	//BEGIN Compatibility with 0.6.0 Pre-Alpha versions:
	if (!doc)
		doc = XMLWork::openFile("basketsTree", Global::basketsFolder() + "baskets.xml");
	//END
	if (doc != 0) {
		TQDomElement docElem = doc->documentElement();
		load(m_tree, 0L, docElem);
	}
	m_loading = false;
}

void BNPView::load(TDEListView */*listView*/, TQListViewItem *item, const TQDomElement &baskets)
{
	TQDomNode n = baskets.firstChild();
	while ( ! n.isNull() ) {
		TQDomElement element = n.toElement();
		if ( (!element.isNull()) && element.tagName() == "basket" ) {
			TQString folderName = element.attribute("folderName");
			if (!folderName.isEmpty()) {
				Basket *basket = loadBasket(folderName);
				BasketListViewItem *basketItem = appendBasket(basket, item);
				basketItem->setOpen(!XMLWork::trueOrFalse(element.attribute("folded", "false"), false));
				basket->loadProperties(XMLWork::getElement(element, "properties"));
				if (XMLWork::trueOrFalse(element.attribute("lastOpened", element.attribute("lastOpenned", "false")), false)) // Compat with 0.6.0-Alphas
					setCurrentBasket(basket);
				// Load Sub-baskets:
				load(/*(TQListView*)*/0L, basketItem, element);
			}
		}
		n = n.nextSibling();
	}
}

Basket* BNPView::loadBasket(const TQString &folderName)
{
	if (folderName.isEmpty())
		return 0;

	DecoratedBasket *decoBasket = new DecoratedBasket(m_stack, folderName);
	Basket          *basket     = decoBasket->basket();
	m_stack->addWidget(decoBasket);
	connect( basket, TQ_SIGNAL(countsChanged(Basket*)), this, TQ_SLOT(countsChanged(Basket*)) );
	// Important: Create listViewItem and connect signal BEFORE loadProperties(), so we get the listViewItem updated without extra work:
	connect( basket, TQ_SIGNAL(propertiesChanged(Basket*)), this, TQ_SLOT(updateBasketListViewItem(Basket*)) );

	connect( basket->decoration()->filterBar(), TQ_SIGNAL(newFilter(const FilterData&)), this, TQ_SLOT(newFilterFromFilterBar()) );

	return basket;
}

int BNPView::basketCount(TQListViewItem *parent)
{
	int count = 0;

	TQListViewItem *item = (parent ? parent->firstChild() : m_tree->firstChild());
	while (item) {
		count += 1 + basketCount(item);
		item = item->nextSibling();
	}

	return count;
}

bool BNPView::canFold()
{
	BasketListViewItem *item = listViewItemForBasket(currentBasket());
	if (!item)
		return false;
	return item->parent() || (item->firstChild() && item->isOpen());
}

bool BNPView::canExpand()
{
	BasketListViewItem *item = listViewItemForBasket(currentBasket());
	if (!item)
		return false;
	return item->firstChild();
}

BasketListViewItem* BNPView::appendBasket(Basket *basket, TQListViewItem *parentItem)
{
	BasketListViewItem *newBasketItem;
	if (parentItem)
		newBasketItem = new BasketListViewItem(parentItem, ((BasketListViewItem*)parentItem)->lastChild(), basket);
	else {
		TQListViewItem *child     = m_tree->firstChild();
		TQListViewItem *lastChild = 0;
		while (child) {
			lastChild = child;
			child = child->nextSibling();
		}
		newBasketItem = new BasketListViewItem(m_tree, lastChild, basket);
	}

	emit basketNumberChanged(basketCount());

	return newBasketItem;
}

void BNPView::loadNewBasket(const TQString &folderName, const TQDomElement &properties, Basket *parent)
{
	Basket *basket = loadBasket(folderName);
	appendBasket(basket, (basket ? listViewItemForBasket(parent) : 0));
	basket->loadProperties(properties);
	setCurrentBasket(basket);
//	save();
}

BasketListViewItem* BNPView::lastListViewItem()
{
	TQListViewItem *child     = m_tree->firstChild();
	TQListViewItem *lastChild = 0;
	// Set lastChild to the last primary child of the list view:
	while (child) {
		lastChild = child;
		child = child->nextSibling();
	}
	// If this child have child(s), recursivly browse through them to find the real last one:
	while (lastChild && lastChild->firstChild()) {
		child = lastChild->firstChild();
		while (child) {
			lastChild = child;
			child = child->nextSibling();
		}
	}
	return (BasketListViewItem*)lastChild;
}

void BNPView::goToPreviousBasket()
{
	if (!m_tree->firstChild())
		return;

	BasketListViewItem *item     = listViewItemForBasket(currentBasket());
	BasketListViewItem *toSwitch = item->shownItemAbove();
	if (!toSwitch) {
		toSwitch = lastListViewItem();
		if (toSwitch && !toSwitch->isShown())
			toSwitch = toSwitch->shownItemAbove();
	}

	if (toSwitch)
		setCurrentBasket(toSwitch->basket());

	if (Settings::usePassivePopup())
		showPassiveContent();
}

void BNPView::goToNextBasket()
{
	if (!m_tree->firstChild())
		return;

	BasketListViewItem *item     = listViewItemForBasket(currentBasket());
	BasketListViewItem *toSwitch = item->shownItemBelow();
	if (!toSwitch)
		toSwitch = ((BasketListViewItem*)m_tree->firstChild());

	if (toSwitch)
		setCurrentBasket(toSwitch->basket());

	if (Settings::usePassivePopup())
		showPassiveContent();
}

void BNPView::foldBasket()
{
	BasketListViewItem *item = listViewItemForBasket(currentBasket());
	if (item && !item->firstChild())
		item->setOpen(false); // If Alt+Left is hitted and there is nothing to close, make sure the focus will go to the parent basket

	TQKeyEvent* keyEvent = new TQKeyEvent(TQEvent::KeyPress, TQt::Key_Left, 0, 0);
	TQApplication::postEvent(m_tree, keyEvent);
}

void BNPView::expandBasket()
{
	TQKeyEvent* keyEvent = new TQKeyEvent(TQEvent::KeyPress, TQt::Key_Right, 0, 0);
	TQApplication::postEvent(m_tree, keyEvent);
}

void BNPView::closeAllEditors()
{
	TQListViewItemIterator it(m_tree);
	while (it.current()) {
		BasketListViewItem *item = (BasketListViewItem*)(it.current());
		item->basket()->closeEditor();
		++it;
	}
}

bool BNPView::convertTexts()
{
	bool convertedNotes = false;
	KProgressDialog dialog(
			/*parent=*/0,
			/*name=*/"",
			/*caption=*/i18n("Plain Text Notes Conversion"),
			/*text=*/i18n("Converting plain text notes to rich text ones..."),
			/*modal=*/true);
	dialog.progressBar()->setTotalSteps(basketCount());
	dialog.show(); //setMinimumDuration(50/*ms*/);

	TQListViewItemIterator it(m_tree);
	while (it.current()) {
		BasketListViewItem *item = (BasketListViewItem*)(it.current());
		if (item->basket()->convertTexts())
			convertedNotes = true;
		dialog.progressBar()->advance(1);
		if (dialog.wasCancelled())
			break;
		++it;
	}

	return convertedNotes;
}

/** isRunning is to avoid recursive calls because this method can be called
 * when clicking the menu action or when using the filter-bar icon... either of those calls
 * call the other to be checked... and it can cause recursive calls.
 * PS: Uggly hack? Yes, I think so :-)
 */
void BNPView::toggleFilterAllBaskets(bool doFilter)
{
	static bool isRunning = false;
	if (isRunning)
		return;
	isRunning = true;

	// Set the state:
	m_actFilterAllBaskets->setChecked(doFilter);
	//currentBasket()->decoration()->filterBar()->setFilterAll(doFilter);

//	Basket *current = currentBasket();
	TQListViewItemIterator it(m_tree);
	while (it.current()) {
		BasketListViewItem *item = ((BasketListViewItem*)it.current());
		item->basket()->decoration()->filterBar()->setFilterAll(doFilter);
		++it;
	}

	// Protection is not necessary anymore:
	isRunning = false;

	if (doFilter)
		currentBasket()->decoration()->filterBar()->setEditFocus();

	// Filter every baskets:
	newFilter();
}

/** This function can be called recursively because we call tdeApp->processEvents().
 * If this function is called whereas another "instance" is running,
 * this new "instance" leave and set up a flag that is read by the first "instance"
 * to know it should re-begin the work.
 * PS: Yes, that's a very lame pseudo-threading but that works, and it's programmer-efforts cheap :-)
 */
void BNPView::newFilter()
{
	static bool alreadyEntered = false;
	static bool shouldRestart  = false;

	if (alreadyEntered) {
		shouldRestart = true;
		return;
	}
	alreadyEntered = true;
	shouldRestart  = false;

	Basket *current = currentBasket();
	const FilterData &filterData = current->decoration()->filterBar()->filterData();

	// Set the filter data for every other baskets, or reset the filter for every other baskets if we just disabled the filterInAllBaskets:
	TQListViewItemIterator it(m_tree);
	while (it.current()) {
		BasketListViewItem *item = ((BasketListViewItem*)it.current());
		if (item->basket() != current)
			if (isFilteringAllBaskets())
				item->basket()->decoration()->filterBar()->setFilterData(filterData); // Set the new FilterData for every other baskets
			else
				item->basket()->decoration()->filterBar()->setFilterData(FilterData()); // We just disabled the global filtering: remove the FilterData
		++it;
	}

	// Show/hide the "little filter icons" (during basket load)
	// or the "little numbers" (to show number of found notes in the baskets) is the tree:
	m_tree->triggerUpdate();
	tdeApp->processEvents();

	// Load every baskets for filtering, if they are not already loaded, and if necessary:
	if (filterData.isFiltering) {
		Basket *current = currentBasket();
		TQListViewItemIterator it(m_tree);
		while (it.current()) {
			BasketListViewItem *item = ((BasketListViewItem*)it.current());
			if (item->basket() != current) {
				Basket *basket = item->basket();
				if (!basket->loadingLaunched() && !basket->isLocked())
					basket->load();
				basket->filterAgain();
				m_tree->triggerUpdate();
				tdeApp->processEvents();
				if (shouldRestart) {
					alreadyEntered = false;
					shouldRestart  = false;
					newFilter();
					return;
				}
			}
			++it;
		}
	}

	m_tree->triggerUpdate();
//	tdeApp->processEvents();

	alreadyEntered = false;
	shouldRestart  = false;
}

void BNPView::newFilterFromFilterBar()
{
	if (isFilteringAllBaskets())
		TQTimer::singleShot(0, this, TQ_SLOT(newFilter())); // Keep time for the TQLineEdit to display the filtered character and refresh correctly!
}

bool BNPView::isFilteringAllBaskets()
{
	return m_actFilterAllBaskets->isChecked();
}


BasketListViewItem* BNPView::listViewItemForBasket(Basket *basket)
{
	TQListViewItemIterator it(m_tree);
	while (it.current()) {
		BasketListViewItem *item = ((BasketListViewItem*)it.current());
		if (item->basket() == basket)
			return item;
		++it;
	}
	return 0L;
}

Basket* BNPView::currentBasket()
{
	DecoratedBasket *decoBasket = (DecoratedBasket*)m_stack->visibleWidget();
	if (decoBasket)
		return decoBasket->basket();
	else
		return 0;
}

Basket* BNPView::parentBasketOf(Basket *basket)
{
	BasketListViewItem *item = (BasketListViewItem*)(listViewItemForBasket(basket)->parent());
	if (item)
		return item->basket();
	else
		return 0;
}

void BNPView::setCurrentBasket(Basket *basket)
{
	if (currentBasket() == basket)
		return;

	if (currentBasket())
		currentBasket()->closeBasket();

	if (basket)
		basket->aboutToBeActivated();

	BasketListViewItem *item = listViewItemForBasket(basket);
	if (item) {
		m_tree->setSelected(item, true);
		item->ensureVisible();
		m_stack->raiseWidget(basket->decoration());
		// If the window has changed size, only the current basket receive the event,
		// the others will receive ony one just before they are shown.
		// But this triggers unwanted animations, so we eliminate it:
		basket->relayoutNotes(/*animate=*/false);
		basket->openBasket();
		setCaption(item->basket()->basketName());
		countsChanged(basket);
		updateStatusBarHint();
		if (Global::systemTray)
			Global::systemTray->updateToolTip();
		m_tree->ensureItemVisible(m_tree->currentItem());
		item->basket()->setFocus();
	}
	m_tree->viewport()->update();
	emit basketChanged();
}

void BNPView::removeBasket(Basket *basket)
{
	if (basket->isDuringEdit())
		basket->closeEditor();

	// Find a new basket to switch to and select it.
	// Strategy: get the next sibling, or the previous one if not found.
	// If there is no such one, get the parent basket:
	BasketListViewItem *basketItem = listViewItemForBasket(basket);
	BasketListViewItem *nextBasketItem = (BasketListViewItem*)(basketItem->nextSibling());
	if (!nextBasketItem)
		nextBasketItem = basketItem->prevSibling();
	if (!nextBasketItem)
		nextBasketItem = (BasketListViewItem*)(basketItem->parent());

	if (nextBasketItem)
		setCurrentBasket(nextBasketItem->basket());

	// Remove from the view:
	basket->unsubscribeBackgroundImages();
	m_stack->removeWidget(basket->decoration());
//	delete basket->decoration();
	delete basketItem;
//	delete basket;

	// If there is no basket anymore, add a new one:
	if (!nextBasketItem)
		BasketFactory::newBasket(/*icon=*/"", /*name=*/i18n("General"), /*backgroundImage=*/"", /*backgroundColor=*/TQColor(), /*textColor=*/TQColor(), /*templateName=*/"1column", /*createIn=*/0);
	else // No need to save two times if we add a basket
		save();

	emit basketNumberChanged(basketCount());
}

void BNPView::setTreePlacement(bool onLeft)
{
	if (onLeft)
		moveToFirst(m_tree);
	else
		moveToLast(m_tree);
	//updateGeometry();
	tdeApp->postEvent( this, new TQResizeEvent(size(), size()) );
}

void BNPView::relayoutAllBaskets()
{
	TQListViewItemIterator it(m_tree);
	while (it.current()) {
		BasketListViewItem *item = ((BasketListViewItem*)it.current());
		//item->basket()->unbufferizeAll();
		item->basket()->unsetNotesWidth();
		item->basket()->relayoutNotes(true);
		++it;
	}
}

void BNPView::recomputeAllStyles()
{
	TQListViewItemIterator it(m_tree);
	while (it.current()) {
		BasketListViewItem *item = ((BasketListViewItem*)it.current());
		item->basket()->recomputeAllStyles();
		item->basket()->unsetNotesWidth();
		item->basket()->relayoutNotes(true);
		++it;
	}
}

void BNPView::removedStates(const TQValueList<State*> &deletedStates)
{
	TQListViewItemIterator it(m_tree);
	while (it.current()) {
		BasketListViewItem *item = ((BasketListViewItem*)it.current());
		item->basket()->removedStates(deletedStates);
		++it;
	}
}

void BNPView::linkLookChanged()
{
	TQListViewItemIterator it(m_tree);
	while (it.current()) {
		BasketListViewItem *item = ((BasketListViewItem*)it.current());
		item->basket()->linkLookChanged();
		++it;
	}
}

void BNPView::filterPlacementChanged(bool onTop)
{
	TQListViewItemIterator it(m_tree);
	while (it.current()) {
		BasketListViewItem *item        = static_cast<BasketListViewItem*>(it.current());
		DecoratedBasket    *decoration  = static_cast<DecoratedBasket*>(item->basket()->parent());
		decoration->setFilterBarPosition(onTop);
		++it;
	}
}

void BNPView::updateBasketListViewItem(Basket *basket)
{
	BasketListViewItem *item = listViewItemForBasket(basket);
	if (item)
		item->setup();

	if (basket == currentBasket()) {
		setCaption(basket->basketName());
		if (Global::systemTray)
			Global::systemTray->updateToolTip();
	}

	// Don't save if we are loading!
	if (!m_loading)
		save();
}

void BNPView::needSave(TQListViewItem*)
{
	if (!m_loading)
		// A basket has been collapsed/expanded or a new one is select: this is not urgent:
		TQTimer::singleShot(500/*ms*/, this, TQ_SLOT(save()));
}

void BNPView::slotPressed(TQListViewItem *item, const TQPoint &/*pos*/, int /*column*/)
{
	Basket *basket = currentBasket();
	if (basket == 0)
		return;

	// Impossible to Select no Basket:
	if (!item)
		m_tree->setSelected(listViewItemForBasket(basket), true);
	else if (dynamic_cast<BasketListViewItem*>(item) != 0 && currentBasket() != ((BasketListViewItem*)item)->basket()) {
		setCurrentBasket( ((BasketListViewItem*)item)->basket() );
		needSave(0);
	}
	basket->setFocus();
}

DecoratedBasket* BNPView::currentDecoratedBasket()
{
	if (currentBasket())
		return currentBasket()->decoration();
	else
		return 0;
}

// Redirected actions :

void BNPView::exportToHTML()              { HTMLExporter exporter(currentBasket());  }
void BNPView::editNote()                  { currentBasket()->noteEdit();             }
void BNPView::cutNote()                   { currentBasket()->noteCut();              }
void BNPView::copyNote()                  { currentBasket()->noteCopy();             }
void BNPView::delNote()                   { currentBasket()->noteDelete();           }
void BNPView::openNote()                  { currentBasket()->noteOpen();             }
void BNPView::openNoteWith()              { currentBasket()->noteOpenWith();         }
void BNPView::saveNoteAs()                { currentBasket()->noteSaveAs();           }
void BNPView::noteGroup()                 { currentBasket()->noteGroup();            }
void BNPView::noteUngroup()               { currentBasket()->noteUngroup();          }
void BNPView::moveOnTop()                 { currentBasket()->noteMoveOnTop();        }
void BNPView::moveOnBottom()              { currentBasket()->noteMoveOnBottom();     }
void BNPView::moveNoteUp()                { currentBasket()->noteMoveNoteUp();       }
void BNPView::moveNoteDown()              { currentBasket()->noteMoveNoteDown();     }
void BNPView::slotSelectAll()             { currentBasket()->selectAll();            }
void BNPView::slotUnselectAll()           { currentBasket()->unselectAll();          }
void BNPView::slotInvertSelection()       { currentBasket()->invertSelection();      }
void BNPView::slotResetFilter()           { currentDecoratedBasket()->resetFilter(); }

void BNPView::importKJots()       { SoftwareImporters::importKJots();       }
void BNPView::importKNotes()      { SoftwareImporters::importKNotes();      }
void BNPView::importKnowIt()      { SoftwareImporters::importKnowIt();      }
void BNPView::importTuxCards()    { SoftwareImporters::importTuxCards();    }
void BNPView::importStickyNotes() { SoftwareImporters::importStickyNotes(); }
void BNPView::importTomboy()      { SoftwareImporters::importTomboy();      }
void BNPView::importTextFile()    { SoftwareImporters::importTextFile();    }

void BNPView::backupRestore()
{
	BackupDialog dialog;
	dialog.exec();
}

void BNPView::countsChanged(Basket *basket)
{
	if (basket == currentBasket())
		notesStateChanged();
}

void BNPView::notesStateChanged()
{
	Basket *basket = currentBasket();

	// Update statusbar message :
	if (currentBasket()->isLocked())
		setSelectionStatus(i18n("Locked"));
	else if (!basket->isLoaded())
		setSelectionStatus(i18n("Loading..."));
	else if (basket->count() == 0)
		setSelectionStatus(i18n("No notes"));
	else {
		TQString count     = i18n("%n note",     "%n notes",    basket->count()         );
		TQString selecteds = i18n("%n selected", "%n selected", basket->countSelecteds());
		TQString showns    = (currentDecoratedBasket()->filterData().isFiltering ? i18n("all matches") : i18n("no filter"));
		if (basket->countFounds() != basket->count())
			showns = i18n("%n match", "%n matches", basket->countFounds());
		setSelectionStatus(
				i18n("e.g. '18 notes, 10 matches, 5 selected'", "%1, %2, %3").arg(count, showns, selecteds) );
	}

	// If we added a note that match the global filter, update the count number in the tree:
	if (isFilteringAllBaskets())
		listViewItemForBasket(basket)->listView()->triggerUpdate();

	if (currentBasket()->redirectEditActions()) {
		m_actSelectAll         ->setEnabled( !currentBasket()->selectedAllTextInEditor() );
		m_actUnselectAll       ->setEnabled( currentBasket()->hasSelectedTextInEditor()  );
	} else {
		m_actSelectAll         ->setEnabled( basket->countSelecteds() < basket->countFounds() );
		m_actUnselectAll       ->setEnabled( basket->countSelecteds() > 0                     );
	}
	m_actInvertSelection   ->setEnabled( basket->countFounds() > 0 );

	updateNotesActions();
}

void BNPView::updateNotesActions()
{
	bool isLocked             = currentBasket()->isLocked();
	bool oneSelected          = currentBasket()->countSelecteds() == 1;
	bool oneOrSeveralSelected = currentBasket()->countSelecteds() >= 1;
	bool severalSelected      = currentBasket()->countSelecteds() >= 2;

	// FIXME: m_actCheckNotes is also modified in void BNPView::areSelectedNotesCheckedChanged(bool checked)
	//        bool Basket::areSelectedNotesChecked() should return false if bool Basket::showCheckBoxes() is false
//	m_actCheckNotes->setChecked( oneOrSeveralSelected &&
//	                             currentBasket()->areSelectedNotesChecked() &&
//	                             currentBasket()->showCheckBoxes()             );

	Note *selectedGroup = (severalSelected ? currentBasket()->selectedGroup() : 0);

	m_actEditNote            ->setEnabled( !isLocked && oneSelected && !currentBasket()->isDuringEdit() );
	if (currentBasket()->redirectEditActions()) {
		m_actCutNote         ->setEnabled( currentBasket()->hasSelectedTextInEditor() );
		m_actCopyNote        ->setEnabled( currentBasket()->hasSelectedTextInEditor() );
		m_actPaste           ->setEnabled( true                                       );
		m_actDelNote         ->setEnabled( currentBasket()->hasSelectedTextInEditor() );
	} else {
		m_actCutNote         ->setEnabled( !isLocked && oneOrSeveralSelected );
		m_actCopyNote        ->setEnabled(              oneOrSeveralSelected );
		m_actPaste           ->setEnabled( !isLocked                         );
		m_actDelNote         ->setEnabled( !isLocked && oneOrSeveralSelected );
	}
	m_actOpenNote        ->setEnabled(              oneOrSeveralSelected );
	m_actOpenNoteWith    ->setEnabled(              oneSelected          ); // TODO: oneOrSeveralSelected IF SAME TYPE
	m_actSaveNoteAs      ->setEnabled(              oneSelected          ); // IDEM?
	m_actGroup           ->setEnabled( !isLocked && severalSelected && (!selectedGroup || selectedGroup->isColumn()) );
	m_actUngroup         ->setEnabled( !isLocked && selectedGroup && !selectedGroup->isColumn() );
	m_actMoveOnTop       ->setEnabled( !isLocked && oneOrSeveralSelected && !currentBasket()->isFreeLayout() );
	m_actMoveNoteUp      ->setEnabled( !isLocked && oneOrSeveralSelected ); // TODO: Disable when unavailable!
	m_actMoveNoteDown    ->setEnabled( !isLocked && oneOrSeveralSelected );
	m_actMoveOnBottom    ->setEnabled( !isLocked && oneOrSeveralSelected && !currentBasket()->isFreeLayout() );

	for (TDEAction *action = m_insertActions.first(); action; action = m_insertActions.next())
		action->setEnabled( !isLocked );

	// From the old Note::contextMenuEvent(...) :
/*	if (useFile() || m_type == Link) {
	m_type == Link ? i18n("&Open target")         : i18n("&Open")
	m_type == Link ? i18n("Open target &with...") : i18n("Open &with...")
	m_type == Link ? i18n("&Save target as...")   : i18n("&Save a copy as...")
		// If useFile() theire is always a file to open / open with / save, but :
	if (m_type == Link) {
			if (url().prettyURL().isEmpty() && runCommand().isEmpty())     // no URL nor runCommand :
	popupMenu->setItemEnabled(7, false);                       //  no possible Open !
			if (url().prettyURL().isEmpty())                               // no URL :
	popupMenu->setItemEnabled(8, false);                       //  no possible Open with !
			if (url().prettyURL().isEmpty() || url().path().endsWith("/")) // no URL or target a folder :
	popupMenu->setItemEnabled(9, false);                       //  not possible to save target file
}
} else if (m_type != Color) {
	popupMenu->insertSeparator();
	popupMenu->insertItem( SmallIconSet("document-save-as"), i18n("&Save a copy as..."), this, TQ_SLOT(slotSaveAs()), 0, 10 );
}*/
}

// BEGIN Color picker (code from KColorEdit):

/* Activate the mode
 */
void BNPView::slotColorFromScreen(bool global)
{
	m_colorPickWasGlobal = global;
	if (isMainWindowActive()) {
		if(Global::mainWindow()) Global::mainWindow()->hide();
		m_colorPickWasShown = true;
	} else
		m_colorPickWasShown = false;

		currentBasket()->saveInsertionData();
		m_colorPicker->pickColor();

/*	m_gettingColorFromScreen = true;
		tdeApp->processEvents();
		TQTimer::singleShot( 100, this, TQ_SLOT(grabColorFromScreen()) );*/
}

void BNPView::slotColorFromScreenGlobal()
{
	slotColorFromScreen(true);
}

void BNPView::colorPicked(const TQColor &color)
{
	if (!currentBasket()->isLoaded()) {
		showPassiveLoading(currentBasket());
		currentBasket()->load();
	}
	currentBasket()->insertColor(color);

	if (m_colorPickWasShown)
		showMainWindow();

	if (Settings::usePassivePopup())
		showPassiveDropped(i18n("Picked color to basket <i>%1</i>"));
}

void BNPView::colorPickingCanceled()
{
	if (m_colorPickWasShown)
		showMainWindow();
}

void BNPView::slotConvertTexts()
{
/*
	int result = KMessageBox::questionYesNoCancel(
		this,
		i18n(
			"<p>This will convert every text notes into rich text notes.<br>"
			"The content of the notes will not change and you will be able to apply formating to those notes.</p>"
			"<p>This process cannot be reverted back: you will not be able to convert the rich text notes to plain text ones later.</p>"
			"<p>As a beta-tester, you are strongly encouraged to do the convert process because it is to test if plain text notes are still needed.<br>"
			"If nobody complain about not having plain text notes anymore, then the final version is likely to not support plain text notes anymore.</p>"
			"<p><b>Which basket notes do you want to convert?</b></p>"
		),
		i18n("Convert Text Notes"),
		KGuiItem(i18n("Only in the Current Basket")),
		KGuiItem(i18n("In Every Baskets"))
	);
	if (result == KMessageBox::Cancel)
		return;
*/

	bool conversionsDone;
//	if (result == KMessageBox::Yes)
//		conversionsDone = currentBasket()->convertTexts();
//	else
		conversionsDone = convertTexts();

	if (conversionsDone)
		KMessageBox::information(this, i18n("The plain text notes have been converted to rich text."), i18n("Conversion Finished"));
	else
		KMessageBox::information(this, i18n("There are no plain text notes to convert."), i18n("Conversion Finished"));
}

TQPopupMenu* BNPView::popupMenu(const TQString &menuName)
{
	TQPopupMenu *menu = 0;
	bool hack = false; // TODO fix this
	// When running in kontact and likeback Information message is shown
	// factory is 0. Don't show error then and don't crash either :-)

	if(m_guiClient)
	{
		KXMLGUIFactory* factory = m_guiClient->factory();
		if(factory)
		{
			menu = (TQPopupMenu *)factory->container(menuName, m_guiClient);
		}
		else
			hack = isPart();
	}
	if (menu == 0) {
		if(!hack)
		{
			TDEStandardDirs stdDirs;
			KMessageBox::error( this, i18n(
					"<p><b>The file basketui.rc seems to not exist or is too old.<br>"
							"%1 cannot run without it and will stop.</b></p>"
							"<p>Please check your installation of %2.</p>"
							"<p>If you do not have administrator access to install the application "
							"system wide, you can copy the file basketui.rc from the installation "
							"archive to the folder <a href='file://%3'>%4</a>.</p>"
							"<p>As last ressort, if you are sure the application is correctly installed "
							"but you had a preview version of it, try to remove the "
							"file %5basketui.rc</p>")
							.arg(tdeApp->aboutData()->programName(), tdeApp->aboutData()->programName(),
								stdDirs.saveLocation("data", "basket/")).arg(stdDirs.saveLocation("data", "basket/"), stdDirs.saveLocation("data", "basket/")),
					i18n("Ressource not Found"), KMessageBox::AllowLink );
		}
		if(!isPart())
			exit(1); // We SHOULD exit right now and abord everything because the caller except menu != 0 to not crash.
		else
			menu = new TDEPopupMenu; // When running in kpart we cannot exit
	}
	return menu;
}

void BNPView::showHideFilterBar(bool show, bool switchFocus)
{
//	if (show != m_actShowFilter->isChecked())
//		m_actShowFilter->setChecked(show);
	m_actShowFilter->setChecked(currentDecoratedBasket()->filterData().isFiltering);

	currentDecoratedBasket()->setFilterBarShown(show, switchFocus);
	currentDecoratedBasket()->resetFilter();
}

void BNPView::insertEmpty(int type)
{
	if (currentBasket()->isLocked()) {
		showPassiveImpossible(i18n("Cannot add note."));
		return;
	}
	currentBasket()->insertEmptyNote(type);
}

void BNPView::insertWizard(int type)
{
	if (currentBasket()->isLocked()) {
		showPassiveImpossible(i18n("Cannot add note."));
		return;
	}
	currentBasket()->insertWizard(type);
}

// BEGIN Screen Grabbing: // FIXME

void BNPView::grabScreenshot(bool global)
{
	if (m_regionGrabber) {
		KWin::activateWindow(m_regionGrabber->winId());
		return;
	}

	// Delay before to take a screenshot because if we hide the main window OR the systray popup menu,
	// we should wait the windows below to be repainted!!!
	// A special case is where the action is triggered with the global keyboard shortcut.
	// In this case, global is true, and we don't wait.
	// In the future, if global is also defined for other cases, check for
	// enum TDEAction::ActivationReason { UnknownActivation, EmulatedActivation, AccelActivation, PopupMenuActivation, ToolBarActivation };
	int delay = (isMainWindowActive() ? 500 : (global/*tdeApp->activePopupWidget()*/ ? 0 : 200));

	m_colorPickWasGlobal = global;
	if (isMainWindowActive()) {
		if(Global::mainWindow()) Global::mainWindow()->hide();
		m_colorPickWasShown = true;
	} else
		m_colorPickWasShown = false;

		currentBasket()->saveInsertionData();
		m_regionGrabber = new RegionGrabber(delay);
		connect( m_regionGrabber, TQ_SIGNAL(regionGrabbed(const TQPixmap&)), this, TQ_SLOT(screenshotGrabbed(const TQPixmap&)) );
}

void BNPView::grabScreenshotGlobal()
{
	grabScreenshot(true);
}

void BNPView::screenshotGrabbed(const TQPixmap &pixmap)
{
	delete m_regionGrabber;
	m_regionGrabber = 0;

	// Cancelled (pressed Escape):
	if (pixmap.isNull()) {
		if (m_colorPickWasShown)
			showMainWindow();
		return;
	}

	if (!currentBasket()->isLoaded()) {
		showPassiveLoading(currentBasket());
		currentBasket()->load();
	}
	currentBasket()->insertImage(pixmap);

	if (m_colorPickWasShown)
		showMainWindow();

	if (Settings::usePassivePopup())
		showPassiveDropped(i18n("Grabbed screen zone to basket <i>%1</i>"));
}

Basket* BNPView::basketForFolderName(const TQString &/*folderName*/)
{
/*	TQPtrList<Basket> basketsList = listBaskets();
	Basket *basket;
	for (basket = basketsList.first(); basket; basket = basketsList.next())
	if (basket->folderName() == folderName)
	return basket;
*/
	return 0;
}

void BNPView::setFiltering(bool filtering)
{
	m_actShowFilter->setChecked(filtering);
	m_actResetFilter->setEnabled(filtering);
}

void BNPView::undo()
{
	// TODO
}

void BNPView::redo()
{
	// TODO
}

void BNPView::pasteToBasket(int /*index*/, TQClipboard::Mode /*mode*/)
{
	//TODO: REMOVE!
	//basketAt(index)->pasteNote(mode);
}

void BNPView::propBasket()
{
	BasketPropertiesDialog dialog(currentBasket(), this);
	dialog.exec();
}

void BNPView::delBasket()
{
//	DecoratedBasket *decoBasket    = currentDecoratedBasket();
	Basket          *basket        = currentBasket();

#if 0
	KDialogBase *dialog = new KDialogBase(this, /*name=*/0, /*modal=*/true, /*caption=*/i18n("Delete Basket"),
										  KDialogBase::User1 | KDialogBase::User2 | KDialogBase::No, KDialogBase::User1,
										 /*separator=*/false,
										 /*user1=*/KGuiItem(i18n("Delete Only that Basket")/*, icon=""*/),
										 /*user2=*/KGuiItem(i18n("Delete Note & Children")/*, icon=""*/) );
	TQStringList basketsList;
	basketsList.append("Basket 1");
	basketsList.append("  Basket 2");
	basketsList.append("    Basket 3");
	basketsList.append("  Basket 4");
	KMessageBox::createKMessageBox(
			dialog, TQMessageBox::Information,
			i18n("<qt>Do you really want to remove the basket <b>%1</b> and its contents?</qt>")
				.arg(Tools::textToHTMLWithoutP(basket->basketName())),
			basketsList, /*ask=*/"", /*checkboxReturn=*/0, /*options=*/KMessageBox::Notify/*, const TQString &details=TQString()*/);
#endif

	int really = KMessageBox::questionYesNo( this,
											 i18n("<qt>Do you really want to remove the basket <b>%1</b> and its contents?</qt>")
													 .arg(Tools::textToHTMLWithoutP(basket->basketName())),
											 i18n("Remove Basket"),
													 KGuiItem(i18n("&Remove Basket"), "edit-delete"), KStdGuiItem::cancel());

	if (really == KMessageBox::No)
		return;

	TQStringList basketsList = listViewItemForBasket(basket)->childNamesTree();
	if (basketsList.count() > 0) {
		int deleteChilds = KMessageBox::questionYesNoList( this,
				i18n("<qt><b>%1</b> have the following children baskets.<br>Do you want to remove them too?</qt>")
						.arg(Tools::textToHTMLWithoutP(basket->basketName())),
				basketsList,
				i18n("Remove Children Baskets"),
						KGuiItem(i18n("&Remove Children Baskets"), "edit-delete"));

		if (deleteChilds == KMessageBox::No)
			listViewItemForBasket(basket)->moveChildsBaskets();
	}

	doBasketDeletion(basket);

//	basketNumberChanged();
//	rebuildBasketsMenu();
}

void BNPView::doBasketDeletion(Basket *basket)
{
	basket->closeEditor();

	TQListViewItem *basketItem = listViewItemForBasket(basket);
	TQListViewItem *nextOne;
	for (TQListViewItem *child = basketItem->firstChild(); child; child = nextOne) {
		nextOne = child->nextSibling();
		// First delete the child baskets:
		doBasketDeletion(((BasketListViewItem*)child)->basket());
	}
	// Then, basket have no child anymore, delete it:
	DecoratedBasket *decoBasket = basket->decoration();
	basket->deleteFiles();
	removeBasket(basket);
	// Remove the action to avoir keyboard-shortcut clashes:
	delete basket->m_action; // FIXME: It's quick&dirty. In the future, the Basket should be deleted, and then the TDEAction deleted in the Basket destructor.
	delete decoBasket;
//	delete basket;
}

void BNPView::password()
{
#ifdef HAVE_LIBGPGME
	PasswordDlg dlg(tdeApp->activeWindow(), "Password");
	Basket *cur = currentBasket();

	dlg.setType(cur->encryptionType());
	dlg.setKey(cur->encryptionKey());
	if(dlg.exec()) {
		cur->setProtection(dlg.type(), dlg.key());
		if (cur->encryptionType() != Basket::NoEncryption)
			cur->lock();
	}
#endif
}

void BNPView::lockBasket()
{
#ifdef HAVE_LIBGPGME
	Basket *cur = currentBasket();

	cur->lock();
#endif
}

void BNPView::saveAsArchive()
{
	Basket *basket = currentBasket();

	TQDir dir;

	TDEConfig *config = TDEGlobal::config();
	config->setGroup("Basket Archive");
	TQString folder = config->readEntry("lastFolder", TQDir::homeDirPath()) + "/";
	TQString url = folder + TQString(basket->basketName()).replace("/", "_") + ".baskets";

	TQString filter = "*.baskets|" + i18n("Basket Archives") + "\n*|" + i18n("All Files");
	TQString destination = url;
	for (bool askAgain = true; askAgain; ) {
		destination = KFileDialog::getSaveFileName(destination, filter, this, i18n("Save as Basket Archive"));
		if (destination.isEmpty()) // User canceled
			return;
		if (dir.exists(destination)) {
			int result = KMessageBox::questionYesNoCancel(
				this,
				"<qt>" + i18n("The file <b>%1</b> already exists. Do you really want to override it?")
					.arg(KURL(destination).fileName()),
				i18n("Override File?"),
				KGuiItem(i18n("&Override"), "document-save")
			);
			if (result == KMessageBox::Cancel)
				return;
			else if (result == KMessageBox::Yes)
				askAgain = false;
		} else
			askAgain = false;
	}
	bool withSubBaskets = true;//KMessageBox::questionYesNo(this, i18n("Do you want to export sub-baskets too?"), i18n("Save as Basket Archive")) == KMessageBox::Yes;

	config->writeEntry("lastFolder", KURL(destination).directory());
	config->sync();

	Archive::save(basket, withSubBaskets, destination);
}

TQString BNPView::s_fileToOpen = "";

void BNPView::delayedOpenArchive()
{
	Archive::open(s_fileToOpen);
}

void BNPView::openArchive()
{
	TQString filter = "*.baskets|" + i18n("Basket Archives") + "\n*|" + i18n("All Files");
	TQString path = KFileDialog::getOpenFileName(TQString(), filter, this, i18n("Open Basket Archive"));
	if (!path.isEmpty()) // User has not canceled
		Archive::open(path);
}


void BNPView::activatedTagShortcut()
{
	Tag *tag = Tag::tagForTDEAction((TDEAction*)sender());
	currentBasket()->activatedTagShortcut(tag);
}

void BNPView::slotBasketNumberChanged(int number)
{
	m_actPreviousBasket->setEnabled(number > 1);
	m_actNextBasket    ->setEnabled(number > 1);
}

void BNPView::slotBasketChanged()
{
	m_actFoldBasket->setEnabled(canFold());
	m_actExpandBasket->setEnabled(canExpand());
	setFiltering(currentBasket() && currentBasket()->decoration()->filterData().isFiltering);
}

void BNPView::currentBasketChanged()
{
}

void BNPView::isLockedChanged()
{
	bool isLocked = currentBasket()->isLocked();

	setLockStatus(isLocked);

//	m_actLockBasket->setChecked(isLocked);
	m_actPropBasket->setEnabled(!isLocked);
	m_actDelBasket ->setEnabled(!isLocked);
	updateNotesActions();
}

void BNPView::askNewBasket()
{
	askNewBasket(0, 0);
}

void BNPView::askNewBasket(Basket *parent, Basket *pickProperties)
{
	NewBasketDefaultProperties properties;
	if (pickProperties) {
		properties.icon            = pickProperties->icon();
		properties.backgroundImage = pickProperties->backgroundImageName();
		properties.backgroundColor = pickProperties->backgroundColorSetting();
		properties.textColor       = pickProperties->textColorSetting();
		properties.freeLayout      = pickProperties->isFreeLayout();
		properties.columnCount     = pickProperties->columnsCount();
	}

	NewBasketDialog(parent, properties, this).exec();
}

void BNPView::askNewSubBasket()
{
	askNewBasket( /*parent=*/currentBasket(), /*pickPropertiesOf=*/currentBasket() );
}

void BNPView::askNewSiblingBasket()
{
	askNewBasket( /*parent=*/parentBasketOf(currentBasket()), /*pickPropertiesOf=*/currentBasket() );
}

void BNPView::globalPasteInCurrentBasket()
{
	currentBasket()->setInsertPopupMenu();
	pasteInCurrentBasket();
	currentBasket()->cancelInsertPopupMenu();
}

void BNPView::pasteInCurrentBasket()
{
	currentBasket()->pasteNote();

	if (Settings::usePassivePopup())
		showPassiveDropped(i18n("Clipboard content pasted to basket <i>%1</i>"));
}

void BNPView::pasteSelInCurrentBasket()
{
	currentBasket()->pasteNote(TQClipboard::Selection);

	if (Settings::usePassivePopup())
		showPassiveDropped(i18n("Selection pasted to basket <i>%1</i>"));
}

void BNPView::showPassiveDropped(const TQString &title)
{
	if ( ! currentBasket()->isLocked() ) {
		// TODO: Keep basket, so that we show the message only if something was added to a NOT visible basket
		m_passiveDroppedTitle     = title;
		m_passiveDroppedSelection = currentBasket()->selectedNotes();
		TQTimer::singleShot( c_delayTooltipTime, this, TQ_SLOT(showPassiveDroppedDelayed()) );
		// DELAY IT BELOW:
	} else
		showPassiveImpossible(i18n("No note was added."));
}

void BNPView::showPassiveDroppedDelayed()
{
	if (isMainWindowActive() || m_passiveDroppedSelection == 0)
		return;

	TQString title = m_passiveDroppedTitle;

	delete m_passivePopup; // Delete previous one (if exists): it will then hide it (only one at a time)
	m_passivePopup = new KPassivePopup(Settings::useSystray() ? (TQWidget*)Global::systemTray : this);
	TQPixmap contentsPixmap = NoteDrag::feedbackPixmap(m_passiveDroppedSelection);
	TQMimeSourceFactory::defaultFactory()->setPixmap("_passivepopup_image_", contentsPixmap);
	m_passivePopup->setView(
			title.arg(Tools::textToHTMLWithoutP(currentBasket()->basketName())),
	(contentsPixmap.isNull() ? "" : "<img src=\"_passivepopup_image_\">"),
	tdeApp->iconLoader()->loadIcon(currentBasket()->icon(), TDEIcon::NoGroup, 16, TDEIcon::DefaultState, 0L, true));
	m_passivePopup->show();
}

void BNPView::showPassiveImpossible(const TQString &message)
{
	delete m_passivePopup; // Delete previous one (if exists): it will then hide it (only one at a time)
	m_passivePopup = new KPassivePopup(Settings::useSystray() ? (TQWidget*)Global::systemTray : (TQWidget*)this);
	m_passivePopup->setView(
			TQString("<font color=red>%1</font>")
			.arg(i18n("Basket <i>%1</i> is locked"))
			.arg(Tools::textToHTMLWithoutP(currentBasket()->basketName())),
	message,
	tdeApp->iconLoader()->loadIcon(currentBasket()->icon(), TDEIcon::NoGroup, 16, TDEIcon::DefaultState, 0L, true));
	m_passivePopup->show();
}

void BNPView::showPassiveContentForced()
{
	showPassiveContent(/*forceShow=*/true);
}

void BNPView::showPassiveContent(bool forceShow/* = false*/)
{
	if (!forceShow && isMainWindowActive())
		return;

	// FIXME: Duplicate code (2 times)
	TQString message;

	delete m_passivePopup; // Delete previous one (if exists): it will then hide it (only one at a time)
	m_passivePopup = new KPassivePopup(Settings::useSystray() ? (TQWidget*)Global::systemTray : (TQWidget*)this);
	m_passivePopup->setView(
			"<qt>" + tdeApp->makeStdCaption( currentBasket()->isLocked()
			? TQString("%1 <font color=gray30>%2</font>")
			.arg(Tools::textToHTMLWithoutP(currentBasket()->basketName()), i18n("(Locked)"))
	: Tools::textToHTMLWithoutP(currentBasket()->basketName()) ),
	message,
	tdeApp->iconLoader()->loadIcon(currentBasket()->icon(), TDEIcon::NoGroup, 16, TDEIcon::DefaultState, 0L, true));
	m_passivePopup->show();
}

void BNPView::showPassiveLoading(Basket *basket)
{
	if (isMainWindowActive())
		return;

	delete m_passivePopup; // Delete previous one (if exists): it will then hide it (only one at a time)
	m_passivePopup = new KPassivePopup(Settings::useSystray() ? (TQWidget*)Global::systemTray : (TQWidget*)this);
	m_passivePopup->setView(
			Tools::textToHTMLWithoutP(basket->basketName()),
	i18n("Loading..."),
	tdeApp->iconLoader()->loadIcon(basket->icon(), TDEIcon::NoGroup, 16, TDEIcon::DefaultState, 0L, true));
	m_passivePopup->show();
}

void BNPView::addNoteText()  { showMainWindow(); currentBasket()->insertEmptyNote(NoteType::Text);  }
void BNPView::addNoteHtml()  { showMainWindow(); currentBasket()->insertEmptyNote(NoteType::Html);  }
void BNPView::addNoteImage() { showMainWindow(); currentBasket()->insertEmptyNote(NoteType::Image); }
void BNPView::addNoteLink()  { showMainWindow(); currentBasket()->insertEmptyNote(NoteType::Link);  }
void BNPView::addNoteColor() { showMainWindow(); currentBasket()->insertEmptyNote(NoteType::Color); }

void BNPView::aboutToHideNewBasketPopup()
{
	TQTimer::singleShot(0, this, TQ_SLOT(cancelNewBasketPopup()));
}

void BNPView::cancelNewBasketPopup()
{
	m_newBasketPopup = false;
}

void BNPView::setNewBasketPopup()
{
	m_newBasketPopup = true;
}

void BNPView::setCaption(TQString s)
{
	emit setWindowCaption(s);
}

void BNPView::updateStatusBarHint()
{
	m_statusbar->updateStatusBarHint();
}

void BNPView::setSelectionStatus(TQString s)
{
	m_statusbar->setSelectionStatus(s);
}

void BNPView::setLockStatus(bool isLocked)
{
	m_statusbar->setLockStatus(isLocked);
}

void BNPView::postStatusbarMessage(const TQString& msg)
{
	m_statusbar->postStatusbarMessage(msg);
}

void BNPView::setStatusBarHint(const TQString &hint)
{
	m_statusbar->setStatusBarHint(hint);
}

void BNPView::setUnsavedStatus(bool isUnsaved)
{
	m_statusbar->setUnsavedStatus(isUnsaved);
}

void BNPView::setActive(bool active)
{
//	std::cout << "Main Window Position: setActive(" << (active ? "true" : "false") << ")" << std::endl;
	TDEMainWindow* win = Global::mainWindow();
	if(!win)
		return;

	if (active) {
		tdeApp->updateUserTimestamp(); // If "activate on mouse hovering systray", or "on drag throught systray"
		Global::systemTray->setActive();   //  FIXME: add this in the places it need
	} else
		Global::systemTray->setInactive();
}

void BNPView::hideOnEscape()
{
	if (Settings::useSystray())
		setActive(false);
}

bool BNPView::isPart()
{
	return (strcmp(name(), "BNPViewPart") == 0);
}

bool BNPView::isMainWindowActive()
{
	TDEMainWindow* main = Global::mainWindow();
	if (main && main->isActiveWindow())
		return true;
	return false;
}

void BNPView::newBasket()
{
	askNewBasket();
}

void BNPView::handleCommandLine()
{
	TDECmdLineArgs *args = TDECmdLineArgs::parsedArgs();

	/* Custom data folder */
	TQCString customDataFolder = args->getOption("data-folder");
	if (customDataFolder != 0 && !customDataFolder.isEmpty())
	{
		Global::setCustomSavesFolder(customDataFolder);
	}
	/* Debug window */
	if (args->isSet("debug")) {
		new DebugWindow();
		Global::debugWindow->show();
	}

	/* Crash Handler to Mail Developers when Crashing: */
#ifndef BASKET_USE_DRKONQI
	if (!args->isSet("use-drkonquy"))
		TDECrash::setCrashHandler(Crash::crashHandler);
#endif
}

/** Scenario of "Hide main window to system tray icon when mouse move out of the window" :
 * - At enterEvent() we stop m_tryHideTimer
 * - After that and before next, we are SURE cursor is hovering window
 * - At leaveEvent() we restart m_tryHideTimer
 * - Every 'x' ms, timeoutTryHide() seek if cursor hover a widget of the application or not
 * - If yes, we musn't hide the window
 * - But if not, we start m_hideTimer to hide main window after a configured elapsed time
 * - timeoutTryHide() continue to be called and if cursor move again to one widget of the app, m_hideTimer is stopped
 * - If after the configured time cursor hasn't go back to a widget of the application, timeoutHide() is called
 * - It then hide the main window to systray icon
 * - When the user will show it, enterEvent() will be called the first time he enter mouse to it
 * - ...
 */

/** Why do as this ? Problems with the use of only enterEvent() and leaveEvent() :
 * - Resize window or hover titlebar isn't possible : leave/enterEvent
 *   are
 *   > Use the grip or Alt+rightDND to resize window
 *   > Use Alt+DND to move window
 * - Each menu trigger the leavEvent
 */

void BNPView::enterEvent(TQEvent*)
{
	if(m_tryHideTimer)
		m_tryHideTimer->stop();
	if(m_hideTimer)
		m_hideTimer->stop();
}

void BNPView::leaveEvent(TQEvent*)
{
	if (Settings::useSystray() && Settings::hideOnMouseOut() && m_tryHideTimer)
		m_tryHideTimer->start(50);
}

void BNPView::timeoutTryHide()
{
	// If a menu is displayed, do nothing for the moment
	if (tdeApp->activePopupWidget() != 0L)
		return;

	if (tdeApp->widgetAt(TQCursor::pos()) != 0L)
		m_hideTimer->stop();
	else if ( ! m_hideTimer->isActive() ) // Start only one time
		m_hideTimer->start(Settings::timeToHideOnMouseOut() * 100, true);

	// If a sub-dialog is oppened, we musn't hide the main window:
	if (tdeApp->activeWindow() != 0L && tdeApp->activeWindow() != Global::mainWindow())
		m_hideTimer->stop();
}

void BNPView::timeoutHide()
{
	// We check that because the setting can have been set to off
	if (Settings::useSystray() && Settings::hideOnMouseOut())
		setActive(false);
	m_tryHideTimer->stop();
}

void BNPView::changedSelectedNotes()
{
//	tabChanged(0); // FIXME: NOT OPTIMIZED
}

/*void BNPView::areSelectedNotesCheckedChanged(bool checked)
{
	m_actCheckNotes->setChecked(checked && currentBasket()->showCheckBoxes());
}*/

void BNPView::enableActions()
{
	Basket *basket = currentBasket();
	if(!basket)
		return;
	if(m_actLockBasket)
		m_actLockBasket->setEnabled(!basket->isLocked() && basket->isEncrypted());
	if(m_actPassBasket)
		m_actPassBasket->setEnabled(!basket->isLocked());
	m_actPropBasket->setEnabled(!basket->isLocked());
	m_actDelBasket->setEnabled(!basket->isLocked());
	m_actExportToHtml->setEnabled(!basket->isLocked());
	m_actShowFilter->setEnabled(!basket->isLocked());
	m_actFilterAllBaskets->setEnabled(!basket->isLocked());
	m_actResetFilter->setEnabled(!basket->isLocked());
	basket->decoration()->filterBar()->setEnabled(!basket->isLocked());
}

void BNPView::showMainWindow()
{
	TDEMainWindow *win = Global::mainWindow();

	if (win)
	{
		win->show();
	}
	setActive(true);
	emit showPart();
}

void BNPView::populateTagsMenu()
{
	TDEPopupMenu *menu = (TDEPopupMenu*)(popupMenu("tags"));
	if (menu == 0 || currentBasket() == 0) // TODO: Display a messagebox. [menu is 0, surely because on first launch, the XMLGUI does not work!]
		return;
	menu->clear();

	Note *referenceNote;
	if (currentBasket()->focusedNote() && currentBasket()->focusedNote()->isSelected())
		referenceNote = currentBasket()->focusedNote();
	else
		referenceNote = currentBasket()->firstSelected();

	populateTagsMenu(*menu, referenceNote);

	m_lastOpenedTagsMenu = menu;
//	connect( menu, TQ_SIGNAL(aboutToHide()), this, TQ_SLOT(disconnectTagsMenu()) );
}

void BNPView::populateTagsMenu(TDEPopupMenu &menu, Note *referenceNote)
{
	if (currentBasket() == 0)
		return;

	currentBasket()->m_tagPopupNote = referenceNote;
	bool enable = currentBasket()->countSelecteds() > 0;

	TQValueList<Tag*>::iterator it;
	Tag *currentTag;
	State *currentState;
	int i = 10;
	for (it = Tag::all.begin(); it != Tag::all.end(); ++it) {
		// Current tag and first state of it:
		currentTag = *it;
		currentState = currentTag->states().first();
		TQKeySequence sequence;
		if (!currentTag->shortcut().isNull())
			sequence = currentTag->shortcut().operator TQKeySequence();
		menu.insertItem(StateMenuItem::checkBoxIconSet(
			(referenceNote ? referenceNote->hasTag(currentTag) : false),
			menu.colorGroup()),
			new StateMenuItem(currentState, sequence, true),
			i
		);
		if (!currentTag->shortcut().isNull())
			menu.setAccel(sequence, i);
		menu.setItemEnabled(i, enable);
		++i;
	}

	menu.insertSeparator();
//	menu.insertItem( /*SmallIconSet("edit-delete"),*/ "&Assign new Tag...", 1 );
	//id = menu.insertItem( SmallIconSet("edit-delete"), "&Remove All", -2 );
	//if (referenceNote->states().isEmpty())
	//	menu.setItemEnabled(id, false);
//	menu.insertItem( SmallIconSet("configure"),  "&Customize...", 3 );
	menu.insertItem( new IndentedMenuItem(i18n("&Assign new Tag...")),          1 );
	menu.insertItem( new IndentedMenuItem(i18n("&Remove All"),   "edit-delete"), 2 );
	menu.insertItem( new IndentedMenuItem(i18n("&Customize..."), "configure"),  3 );

	menu.setItemEnabled(1, enable);
	if (!currentBasket()->selectedNotesHaveTags())
		menu.setItemEnabled(2, false);

	connect( &menu, TQ_SIGNAL(activated(int)), currentBasket(), TQ_SLOT(toggledTagInMenu(int)) );
	connect( &menu, TQ_SIGNAL(aboutToHide()),  currentBasket(), TQ_SLOT(unlockHovering())      );
	connect( &menu, TQ_SIGNAL(aboutToHide()),  currentBasket(), TQ_SLOT(disableNextClick())    );
}

void BNPView::connectTagsMenu()
{
	connect( popupMenu("tags"), TQ_SIGNAL(aboutToShow()), this, TQ_SLOT(populateTagsMenu())   );
	connect( popupMenu("tags"), TQ_SIGNAL(aboutToHide()), this, TQ_SLOT(disconnectTagsMenu()) );
}

/*
 * The Tags menu is ONLY created once the BasKet KPart is first shown.
 * So we can use this menu only from then?
 * When the KPart is changed in Kontact, and then the BasKet KPart is shown again,
 * Kontact created a NEW Tags menu. So we should connect again.
 * But when Kontact main window is hidden and then re-shown, the menu does not change.
 * So we disconnect at hide event to ensure only one connection: the next show event will not connects another time.
 */

void BNPView::showEvent(TQShowEvent*)
{
	if (isPart())
		TQTimer::singleShot( 0, this, TQ_SLOT(connectTagsMenu()) );

	if (m_firstShow) {
		m_firstShow = false;
		onFirstShow();
	}
	if (isPart()/*TODO: && !LikeBack::enabledBar()*/) {
		Global::likeBack->enableBar();
	}
}

void BNPView::hideEvent(TQHideEvent*)
{
	if (isPart()) {
		disconnect( popupMenu("tags"), TQ_SIGNAL(aboutToShow()), this, TQ_SLOT(populateTagsMenu())   );
		disconnect( popupMenu("tags"), TQ_SIGNAL(aboutToHide()), this, TQ_SLOT(disconnectTagsMenu()) );
	}

	if (isPart())
		Global::likeBack->disableBar();
}

void BNPView::disconnectTagsMenu()
{
	TQTimer::singleShot( 0, this, TQ_SLOT(disconnectTagsMenuDelayed()) );
}

void BNPView::disconnectTagsMenuDelayed()
{
	disconnect( m_lastOpenedTagsMenu, TQ_SIGNAL(activated(int)), currentBasket(), TQ_SLOT(toggledTagInMenu(int)) );
	disconnect( m_lastOpenedTagsMenu, TQ_SIGNAL(aboutToHide()),  currentBasket(), TQ_SLOT(unlockHovering())      );
	disconnect( m_lastOpenedTagsMenu, TQ_SIGNAL(aboutToHide()),  currentBasket(), TQ_SLOT(disableNextClick())    );
}

void BNPView::showGlobalShortcutsSettingsDialog()
{
	KKeyDialog::configure(Global::globalAccel);
	//.setCaption(..)
	Global::globalAccel->writeSettings();
}

#include "bnpview.moc"
