/***************************************************************************
 *   Copyright (C) 2003 by S�astien Laot                                 *
 *   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 <tqlabel.h>
#include <tqlayout.h>
#include <tqlineedit.h>
#include <klineedit.h>
#include <kurlrequester.h>
#include <kicondialog.h>
#include <kcolordialog.h>
#include <kservice.h>
#include <tdeconfig.h>
#include <tdemessagebox.h>
#include <tdelocale.h>
#include <tdemainwindow.h>
#include <tdetoolbar.h>
#include <tdeaction.h>
#include <kurifilter.h>
#include <kdebug.h>
#include <kstdaction.h>
#include <tdeglobalsettings.h>

#include "noteedit.h"
#include "notecontent.h"
 // Use Tools::
#include "notefactory.h"
#include "note.h"
#include "basket.h"
#include "settings.h"
#include "tools.h"
#include "variouswidgets.h"
#include "focusedwidgets.h"

#include <iostream>

/** class NoteEditor: */

NoteEditor::NoteEditor(NoteContent *noteContent)
{
	m_isEmpty  = false;
	m_canceled = false;
	m_widget   = 0;
	m_textEdit = 0;
	m_lineEdit = 0;
	m_noteContent = noteContent;
}

Note* NoteEditor::note()
{
	return m_noteContent->note();
}

NoteEditor* NoteEditor::editNoteContent(NoteContent *noteContent, TQWidget *parent)
{
	TextContent *textContent = dynamic_cast<TextContent*>(noteContent);
	if (textContent)
		return new TextEditor(textContent, parent);

	HtmlContent *htmlContent = dynamic_cast<HtmlContent*>(noteContent);
	if (htmlContent)
		return new HtmlEditor(htmlContent, parent);

	ImageContent *imageContent = dynamic_cast<ImageContent*>(noteContent);
	if (imageContent)
		return new ImageEditor(imageContent, parent);

	AnimationContent *animationContent = dynamic_cast<AnimationContent*>(noteContent);
	if (animationContent)
		return new AnimationEditor(animationContent, parent);

	FileContent *fileContent = dynamic_cast<FileContent*>(noteContent); // Same for SoundContent
	if (fileContent)
		return new FileEditor(fileContent, parent);

	LinkContent *linkContent = dynamic_cast<LinkContent*>(noteContent);
	if (linkContent)
		return new LinkEditor(linkContent, parent);

	LauncherContent *launcherContent = dynamic_cast<LauncherContent*>(noteContent);
	if (launcherContent)
		return new LauncherEditor(launcherContent, parent);

	ColorContent *colorContent = dynamic_cast<ColorContent*>(noteContent);
	if (colorContent)
		return new ColorEditor(colorContent, parent);

	UnknownContent *unknownContent = dynamic_cast<UnknownContent*>(noteContent);
	if (unknownContent)
		return new UnknownEditor(unknownContent, parent);

	return 0;
}

void NoteEditor::setInlineEditor(TQWidget *inlineEditor)
{
	m_widget   = inlineEditor;
	m_textEdit = 0;
	m_lineEdit = 0;

	KTextEdit *textEdit = dynamic_cast<KTextEdit*>(inlineEditor);
	if (textEdit)
		m_textEdit = textEdit;
	else {
		TQLineEdit *lineEdit = dynamic_cast<TQLineEdit*>(inlineEditor);
		if (lineEdit)
			m_lineEdit = lineEdit;
	}
}

#include <iostream>

/** class TextEditor: */

TextEditor::TextEditor(TextContent *textContent, TQWidget *parent)
 : NoteEditor(textContent), m_textContent(textContent)
{
	FocusedTextEdit *textEdit = new FocusedTextEdit(/*disableUpdatesOnKeyPress=*/true, parent);
	textEdit->setLineWidth(0);
	textEdit->setMidLineWidth(0);
	textEdit->setTextFormat(TQt::PlainText);
	textEdit->setPaletteBackgroundColor(note()->backgroundColor());
	textEdit->setPaletteForegroundColor(note()->textColor());
	textEdit->setFont(note()->font());
	textEdit->setHScrollBarMode(TQScrollView::AlwaysOff);
	if (Settings::spellCheckTextNotes())
		textEdit->setCheckSpellingEnabled(true);
	textEdit->setText(m_textContent->text());
	textEdit->moveCursor(KTextEdit::MoveEnd, false); // FIXME: Sometimes, the cursor flicker at ends before being positionned where clicked (because kapp->processEvents() I think)
	textEdit->verticalScrollBar()->setCursor(TQt::ArrowCursor);
	setInlineEditor(textEdit);
	connect( textEdit, TQ_SIGNAL(escapePressed()), this, TQ_SIGNAL(askValidation())            );
	connect( textEdit, TQ_SIGNAL(mouseEntered()),  this, TQ_SIGNAL(mouseEnteredEditorWidget()) );

	connect( textEdit, TQ_SIGNAL(cursorPositionChanged(int, int)), textContent->note()->basket(), TQ_SLOT(editorCursorPositionChanged()) );
	// In case it is a very big note, the top is displayed and Enter is pressed: the cursor is on bottom, we should enure it visible:
	TQTimer::singleShot( 0, textContent->note()->basket(), TQ_SLOT(editorCursorPositionChanged()) );
}

TextEditor::~TextEditor()
{
	delete widget(); // TODO: delete that in validate(), so we can remove one method
}

void TextEditor::autoSave(bool toFileToo)
{
	bool autoSpellCheck = true;
	if (toFileToo) {
		if (Settings::spellCheckTextNotes() != textEdit()->checkSpellingEnabled()) {
			Settings::setSpellCheckTextNotes(textEdit()->checkSpellingEnabled());
			Settings::saveConfig();
		}

		autoSpellCheck = textEdit()->checkSpellingEnabled();
		textEdit()->setCheckSpellingEnabled(false);
	}

	m_textContent->setText(textEdit()->text());

	if (toFileToo) {
		m_textContent->saveToFile();
		m_textContent->setEdited();
		textEdit()->setCheckSpellingEnabled(autoSpellCheck);
	}
}

void TextEditor::validate()
{
	if (Settings::spellCheckTextNotes() != textEdit()->checkSpellingEnabled()) {
		Settings::setSpellCheckTextNotes(textEdit()->checkSpellingEnabled());
		Settings::saveConfig();
	}

	textEdit()->setCheckSpellingEnabled(false);
	if (textEdit()->text().isEmpty())
		setEmpty();
	m_textContent->setText(textEdit()->text());
	m_textContent->saveToFile();
	m_textContent->setEdited();

//	delete widget();
}

/** class HtmlEditor: */

HtmlEditor::HtmlEditor(HtmlContent *htmlContent, TQWidget *parent)
 : NoteEditor(htmlContent), m_htmlContent(htmlContent)
{
	FocusedTextEdit *textEdit = new FocusedTextEdit(/*disableUpdatesOnKeyPress=*/true, parent);
	textEdit->setLineWidth(0);
	textEdit->setMidLineWidth(0);
	textEdit->setTextFormat(TQt::RichText);
	textEdit->setAutoFormatting(Settings::autoBullet() ? TQTextEdit::AutoAll : TQTextEdit::AutoNone);
	textEdit->setPaletteBackgroundColor(note()->backgroundColor());
	textEdit->setPaletteForegroundColor(note()->textColor());
	textEdit->setFont(note()->font());
	textEdit->setHScrollBarMode(TQScrollView::AlwaysOff);
	textEdit->setText(m_htmlContent->html());
	textEdit->moveCursor(KTextEdit::MoveEnd, false);
	textEdit->verticalScrollBar()->setCursor(TQt::ArrowCursor);
	setInlineEditor(textEdit);

	connect( textEdit,                                    TQ_SIGNAL(mouseEntered()),  this, TQ_SIGNAL(mouseEnteredEditorWidget()) );
	connect( textEdit,                                    TQ_SIGNAL(escapePressed()), this, TQ_SIGNAL(askValidation()) );

	connect( InlineEditors::instance()->richTextFont,     TQ_SIGNAL(textChanged(const TQString&)), textEdit, TQ_SLOT(setFamily(const TQString&)) );
	connect( InlineEditors::instance()->richTextFontSize, TQ_SIGNAL(sizeChanged(int)),            textEdit, TQ_SLOT(setPointSize(int))         );
	connect( InlineEditors::instance()->richTextColor,    TQ_SIGNAL(activated(const TQColor&)),    textEdit, TQ_SLOT(setColor(const TQColor&))   );

	connect( InlineEditors::instance()->richTextFont,     TQ_SIGNAL(escapePressed()),  textEdit, TQ_SLOT(setFocus()) );
	connect( InlineEditors::instance()->richTextFont,     TQ_SIGNAL(returnPressed2()), textEdit, TQ_SLOT(setFocus()) );
	connect( InlineEditors::instance()->richTextFont,     TQ_SIGNAL(activated(int)),   textEdit, TQ_SLOT(setFocus()) );

	connect( InlineEditors::instance()->richTextFontSize, TQ_SIGNAL(escapePressed()),  textEdit, TQ_SLOT(setFocus()) );
	connect( InlineEditors::instance()->richTextFontSize, TQ_SIGNAL(returnPressed2()), textEdit, TQ_SLOT(setFocus()) );
	connect( InlineEditors::instance()->richTextFontSize, TQ_SIGNAL(activated(int)),   textEdit, TQ_SLOT(setFocus()) );

	connect( InlineEditors::instance()->richTextColor,    TQ_SIGNAL(escapePressed()),  textEdit, TQ_SLOT(setFocus()) );
	connect( InlineEditors::instance()->richTextColor,    TQ_SIGNAL(returnPressed2()), textEdit, TQ_SLOT(setFocus()) );

	connect( textEdit,  TQ_SIGNAL(cursorPositionChanged(int, int)),  this, TQ_SLOT(cursorPositionChanged())   );
	connect( textEdit,  TQ_SIGNAL(clicked(int, int)),                this, TQ_SLOT(cursorPositionChanged())   );
	connect( textEdit,  TQ_SIGNAL(currentFontChanged(const TQFont&)), this, TQ_SLOT(fontChanged(const TQFont&)) );
//	connect( textEdit,  TQ_SIGNAL(currentVerticalAlignmentChanged(TQTextEdit::VerticalAlignment)), this, TQ_SLOT(slotVerticalAlignmentChanged()) );

	connect( InlineEditors::instance()->richTextBold,      TQ_SIGNAL(toggled(bool)),    textEdit, TQ_SLOT(setBold(bool)) );
	connect( InlineEditors::instance()->richTextItalic,    TQ_SIGNAL(toggled(bool)),    textEdit, TQ_SLOT(setItalic(bool)) );
	connect( InlineEditors::instance()->richTextUnderline, TQ_SIGNAL(toggled(bool)),    textEdit, TQ_SLOT(setUnderline(bool)) );
	//REMOVE:
	//connect( InlineEditors::instance()->richTextBold,      TQ_SIGNAL(activated()), this, TQ_SLOT(setBold())      );
	//connect( InlineEditors::instance()->richTextItalic,    TQ_SIGNAL(activated()), this, TQ_SLOT(setItalic())    );
	//connect( InlineEditors::instance()->richTextUnderline, TQ_SIGNAL(activated()), this, TQ_SLOT(setUnderline()) );
	connect( InlineEditors::instance()->richTextLeft,      TQ_SIGNAL(activated()), this, TQ_SLOT(setLeft())      );
	connect( InlineEditors::instance()->richTextCenter,    TQ_SIGNAL(activated()), this, TQ_SLOT(setCentered())  );
	connect( InlineEditors::instance()->richTextRight,     TQ_SIGNAL(activated()), this, TQ_SLOT(setRight())     );
	connect( InlineEditors::instance()->richTextJustified, TQ_SIGNAL(activated()), this, TQ_SLOT(setBlock())     );

//	InlineEditors::instance()->richTextToolBar()->show();
	cursorPositionChanged();
	fontChanged(textEdit->currentFont());
	//TQTimer::singleShot( 0, this, TQ_SLOT(cursorPositionChanged()) );
	InlineEditors::instance()->enableRichTextToolBar();

	connect( InlineEditors::instance()->richTextUndo,      TQ_SIGNAL(activated()), textEdit, TQ_SLOT(undo())         );
	connect( InlineEditors::instance()->richTextRedo,      TQ_SIGNAL(activated()), textEdit, TQ_SLOT(redo())         );
	connect( textEdit, TQ_SIGNAL(undoAvailable(bool)), InlineEditors::instance()->richTextUndo, TQ_SLOT(setEnabled(bool)) );
	connect( textEdit, TQ_SIGNAL(redoAvailable(bool)), InlineEditors::instance()->richTextRedo, TQ_SLOT(setEnabled(bool)) );
	connect( textEdit, TQ_SIGNAL(textChanged()), this, TQ_SLOT(textChanged()));
	InlineEditors::instance()->richTextUndo->setEnabled(false);
	InlineEditors::instance()->richTextRedo->setEnabled(false);

	connect( textEdit, TQ_SIGNAL(cursorPositionChanged(int, int)), htmlContent->note()->basket(), TQ_SLOT(editorCursorPositionChanged()) );
	// In case it is a very big note, the top is displayed and Enter is pressed: the cursor is on bottom, we should enure it visible:
	TQTimer::singleShot( 0, htmlContent->note()->basket(), TQ_SLOT(editorCursorPositionChanged()) );
}

void HtmlEditor::cursorPositionChanged()
{
	InlineEditors::instance()->richTextFont->setCurrentFont(  textEdit()->currentFont().family() );
	if (InlineEditors::instance()->richTextColor->color() != textEdit()->color())
		InlineEditors::instance()->richTextColor->setColor(   textEdit()->color()                );
	InlineEditors::instance()->richTextBold->setChecked(      textEdit()->bold()                 );
	InlineEditors::instance()->richTextItalic->setChecked(    textEdit()->italic()               );
	InlineEditors::instance()->richTextUnderline->setChecked( textEdit()->underline()            );

	switch (textEdit()->alignment()) {
		default:
		case 1/*TQt::AlignLeft*/:     InlineEditors::instance()->richTextLeft->setChecked(true);      break;
		case 4/*TQt::AlignCenter*/:   InlineEditors::instance()->richTextCenter->setChecked(true);    break;
		case 2/*TQt::AlignRight*/:    InlineEditors::instance()->richTextRight->setChecked(true);     break;
		case -8/*TQt::AlignJustify*/: InlineEditors::instance()->richTextJustified->setChecked(true); break;
	}
}

void HtmlEditor::textChanged()
{
	// The following is a workaround for an apparent TQt bug.
	// When I start typing in a textEdit, the undo&redo actions are not enabled until I click
	// or move the cursor - probably, the signal undoAvailable() is not emitted.
	// So, I had to intervene and do that manually.
	InlineEditors::instance()->richTextUndo->setEnabled(textEdit()->isUndoAvailable());
	InlineEditors::instance()->richTextRedo->setEnabled(textEdit()->isRedoAvailable());
}

void HtmlEditor::fontChanged(const TQFont &font)
{
	InlineEditors::instance()->richTextFontSize->setFontSize(font.pointSize());
}

/*void HtmlEditor::slotVe<rticalAlignmentChanged(TQTextEdit::VerticalAlignment align)
{
	TQTextEdit::VerticalAlignment align = textEdit()
	switch (align) {
		case KTextEdit::AlignSuperScript:
			InlineEditors::instance()->richTextSuper->setChecked(true);
			InlineEditors::instance()->richTextSub->setChecked(false);
			break;
		case KTextEdit::AlignSubScript:
			InlineEditors::instance()->richTextSuper->setChecked(false);
			InlineEditors::instance()->richTextSub->setChecked(true);
			break;
		default:
			InlineEditors::instance()->richTextSuper->setChecked(false);
			InlineEditors::instance()->richTextSub->setChecked(false);
	}

	NoteHtmlEditor::buttonToggled(int id) :
		case 106:
			if (isOn && m_toolbar->isButtonOn(107))
				m_toolbar->setButton(107, false);
			m_text->setVerticalAlignment(isOn ? KTextEdit::AlignSuperScript : KTextEdit::AlignNormal);
			break;
		case 107:
			if (isOn && m_toolbar->isButtonOn(106))
				m_toolbar->setButton(106, false);
			m_text->setVerticalAlignment(isOn ? KTextEdit::AlignSubScript   : KTextEdit::AlignNormal);
			break;
}*/

 // REMOVE: These functions are unused - it's now done by direct connection to textEdit
 //void HtmlEditor::setBold()      { textEdit()->setBold(      InlineEditors::instance()->richTextBold->isChecked()      ); }
 //void HtmlEditor::setItalic()    { textEdit()->setItalic(    InlineEditors::instance()->richTextItalic->isChecked()    ); }
 //void HtmlEditor::setUnderline() { textEdit()->setUnderline( InlineEditors::instance()->richTextUnderline->isChecked() ); }
void HtmlEditor::setLeft()      { textEdit()->setAlignment(TQt::AlignLeft);    }
void HtmlEditor::setCentered()  { textEdit()->setAlignment(TQt::AlignCenter);  }
void HtmlEditor::setRight()     { textEdit()->setAlignment(TQt::AlignRight);   }
void HtmlEditor::setBlock()     { textEdit()->setAlignment(TQt::AlignJustify); }

HtmlEditor::~HtmlEditor()
{
	delete widget();
}

void HtmlEditor::autoSave(bool toFileToo)
{
	m_htmlContent->setHtml(textEdit()->text());
	if (toFileToo) {
		m_htmlContent->saveToFile();
	m_htmlContent->setEdited();
	}
}

void HtmlEditor::validate()
{
	if (Tools::htmlToText(textEdit()->text()).isEmpty())
		setEmpty();
	m_htmlContent->setHtml(textEdit()->text());
	m_htmlContent->saveToFile();
	m_htmlContent->setEdited();

	disconnect();
	widget()->disconnect();
	if (InlineEditors::instance())
	{
		InlineEditors::instance()->disableRichTextToolBar();
//		if (InlineEditors::instance()->richTextToolBar())
//			InlineEditors::instance()->richTextToolBar()->hide();
	}
	delete widget();
	setInlineEditor(0);
}

/** class ImageEditor: */

ImageEditor::ImageEditor(ImageContent *imageContent, TQWidget *parent)
 : NoteEditor(imageContent)
{
	int choice = KMessageBox::questionYesNo(parent, i18n(
		"Images can not be edited here at the moment (the next version of BasKet Note Pads will include an image editor).\n"
		"Do you want to open it with an application that understand it?"),
		i18n("Edit Image Note"),
		KStdGuiItem::open(),
		KStdGuiItem::cancel());

	if (choice == KMessageBox::Yes)
		note()->basket()->noteOpen(note());
}

/** class AnimationEditor: */

AnimationEditor::AnimationEditor(AnimationContent *animationContent, TQWidget *parent)
 : NoteEditor(animationContent)
{
	int choice = KMessageBox::questionYesNo(parent, i18n(
		"This animated image can not be edited here.\n"
		"Do you want to open it with an application that understands it?"),
		i18n("Edit Animation Note"),
		KStdGuiItem::open(),
		KStdGuiItem::cancel());

	if (choice == KMessageBox::Yes)
		note()->basket()->noteOpen(note());
}

/** class FileEditor: */

FileEditor::FileEditor(FileContent *fileContent, TQWidget *parent)
 : NoteEditor(fileContent), m_fileContent(fileContent)
{
	FocusedLineEdit *lineEdit = new FocusedLineEdit(parent);
	lineEdit->setLineWidth(0);
	lineEdit->setMidLineWidth(0);
	lineEdit->setPaletteBackgroundColor(note()->backgroundColor());
	lineEdit->setPaletteForegroundColor(note()->textColor());
	lineEdit->setFont(note()->font());
	lineEdit->setText(m_fileContent->fileName());
	lineEdit->selectAll();
	setInlineEditor(lineEdit);
	connect( lineEdit, TQ_SIGNAL(returnPressed()), this, TQ_SIGNAL(askValidation())            );
	connect( lineEdit, TQ_SIGNAL(escapePressed()), this, TQ_SIGNAL(askValidation())            );
	connect( lineEdit, TQ_SIGNAL(mouseEntered()),  this, TQ_SIGNAL(mouseEnteredEditorWidget()) );
}

FileEditor::~FileEditor()
{
	delete widget();
}

void FileEditor::autoSave(bool toFileToo)
{
	// FIXME: How to detect cancel?
	if (toFileToo && !lineEdit()->text().isEmpty() && m_fileContent->trySetFileName(lineEdit()->text())) {
		m_fileContent->setFileName(lineEdit()->text());
		m_fileContent->setEdited();
	}
}

void FileEditor::validate()
{
	autoSave(/*toFileToo=*/true);
}

/** class LinkEditor: */

LinkEditor::LinkEditor(LinkContent *linkContent, TQWidget *parent)
 : NoteEditor(linkContent)
{
	LinkEditDialog dialog(linkContent, parent);
	if (dialog.exec() == TQDialog::Rejected)
		cancel();
	if (linkContent->url().isEmpty() && linkContent->title().isEmpty())
		setEmpty();
}

/** class LauncherEditor: */

LauncherEditor::LauncherEditor(LauncherContent *launcherContent, TQWidget *parent)
 : NoteEditor(launcherContent)
{
	LauncherEditDialog dialog(launcherContent, parent);
	if (dialog.exec() == TQDialog::Rejected)
		cancel();
	if (launcherContent->name().isEmpty() && launcherContent->exec().isEmpty())
		setEmpty();
}

/** class ColorEditor: */

ColorEditor::ColorEditor(ColorContent *colorContent, TQWidget *parent)
 : NoteEditor(colorContent)
{
	KColorDialog dialog(parent, /*name=*/"EditColor", /*modal=*/true);
	dialog.setColor(colorContent->color());
	dialog.setCaption(i18n("Edit Color Note"));
	if (dialog.exec() == TQDialog::Accepted) {
		if (dialog.color() != colorContent->color()) {
			colorContent->setColor(dialog.color());
			colorContent->setEdited();
		}
	} else
		cancel();

	/* This code don't allow to set a caption to the dialog:
	TQColor color = colorContent()->color();
	if (KColorDialog::getColor(color, parent) == TQDialog::Accepted && color != m_color) {
		colorContent()->setColor(color);
		setEdited();
	}*/
}

/** class UnknownEditor: */

UnknownEditor::UnknownEditor(UnknownContent *unknownContent, TQWidget *parent)
 : NoteEditor(unknownContent)
{
	KMessageBox::information(parent, i18n(
		"The type of this note is unknown and can not be edited here.\n"
		"You however can drag or copy the note into an application that understands it."),
		i18n("Edit Unknown Note"));
}

/*********************************************************************/


/** class DebuggedLineEdit: */

DebuggedLineEdit::DebuggedLineEdit(const TQString &text, TQWidget *parent)
 : TQLineEdit(text, parent)
{
}

DebuggedLineEdit::~DebuggedLineEdit()
{
}

void DebuggedLineEdit::keyPressEvent(TQKeyEvent *event)
{
	TQString oldText = text();
	TQLineEdit::keyPressEvent(event);
	if (oldText != text())
		emit textChanged(text());
}


/** class LinkEditDialog: */

LinkEditDialog::LinkEditDialog(LinkContent *contentNote, TQWidget *parent/*, TQKeyEvent *ke*/)
 : KDialogBase(KDialogBase::Plain, i18n("Edit Link Note"), KDialogBase::Ok | KDialogBase::Cancel,
               KDialogBase::Ok, parent, /*name=*/"EditLink", /*modal=*/true, /*separator=*/true),
   m_noteContent(contentNote)
{
	TQWidget     *page   = plainPage();
	TQGridLayout *layout = new TQGridLayout(page, /*nRows=*/4, /*nCols=*/2, /*margin=*/0, spacingHint());

	m_url = new KURLRequester(m_noteContent->url().url(), page);

	TQWidget *wid1 = new TQWidget(page);
	TQHBoxLayout *titleLay = new TQHBoxLayout(wid1, /*margin=*/0, spacingHint());
	m_title = new DebuggedLineEdit(m_noteContent->title(), wid1);
	m_autoTitle = new TQPushButton(i18n("Auto"), wid1);
	m_autoTitle->setToggleButton(true);
	m_autoTitle->setOn(m_noteContent->autoTitle());
	titleLay->addWidget(m_title);
	titleLay->addWidget(m_autoTitle);

	TQWidget *wid = new TQWidget(page);
	TQHBoxLayout *hLay = new TQHBoxLayout(wid, /*margin=*/0, spacingHint());
	m_icon = new TDEIconButton(wid);
	TQLabel *label3 = new TQLabel(m_icon, i18n("&Icon:"), page);
	KURL filteredURL = NoteFactory::filteredURL(KURL(m_url->lineEdit()->text()));//KURIFilter::self()->filteredURI(KURL(m_url->lineEdit()->text()));
	m_icon->setIconType(TDEIcon::NoGroup, TDEIcon::MimeType);
	m_icon->setIconSize(LinkLook::lookForURL(filteredURL)->iconSize());
	m_autoIcon = new TQPushButton(i18n("Auto"), wid); // Create before to know size here:
	/* Icon button: */
	m_icon->setIcon(m_noteContent->icon());
	int minSize = m_autoIcon->sizeHint().height();
	// Make the icon button at least the same heigh than the other buttons for a better alignment (nicer to the eyes):
	if (m_icon->sizeHint().height() < minSize)
		m_icon->setFixedSize(minSize, minSize);
	else
		m_icon->setFixedSize(m_icon->sizeHint().height(), m_icon->sizeHint().height()); // Make it square
	/* Auto button: */
	m_autoIcon->setToggleButton(true);
	m_autoIcon->setOn(m_noteContent->autoIcon());
	hLay->addWidget(m_icon);
	hLay->addWidget(m_autoIcon);
	hLay->addStretch();

	m_url->lineEdit()->setMinimumWidth(m_url->lineEdit()->fontMetrics().maxWidth()*20);
	m_title->setMinimumWidth(m_title->fontMetrics().maxWidth()*20);

	//m_url->setShowLocalProtocol(true);
	TQLabel      *label1 = new TQLabel(m_url,   i18n("Ta&rget:"),    page);
	TQLabel      *label2 = new TQLabel(m_title, i18n("&Title:"),  page);
	layout->addWidget(label1,  0, 0, TQt::AlignVCenter);
	layout->addWidget(label2,  1, 0, TQt::AlignVCenter);
	layout->addWidget(label3,  2, 0, TQt::AlignVCenter);
	layout->addWidget(m_url,   0, 1, TQt::AlignVCenter);
	layout->addWidget(wid1,    1, 1, TQt::AlignVCenter);
	layout->addWidget(wid,     2, 1, TQt::AlignVCenter);

	m_isAutoModified = false;
	connect( m_url,   TQ_SIGNAL(textChanged(const TQString&)), this, TQ_SLOT(urlChanged(const TQString&))     );
	connect( m_title, TQ_SIGNAL(textChanged(const TQString&)), this, TQ_SLOT(doNotAutoTitle(const TQString&)) );
	connect( m_icon,  TQ_SIGNAL(iconChanged(TQString))       , this, TQ_SLOT(doNotAutoIcon(TQString))         );
	connect( m_autoTitle, TQ_SIGNAL(clicked()), this, TQ_SLOT(guessTitle()) );
	connect( m_autoIcon,  TQ_SIGNAL(clicked()), this, TQ_SLOT(guessIcon())  );

	TQWidget *stretchWidget = new TQWidget(page);
	stretchWidget->setSizePolicy(TQSizePolicy(/*hor=*/TQSizePolicy::Fixed, /*ver=*/TQSizePolicy::Expanding, /*hStretch=*/1, /*vStretch=*/255)); // Make it fill ALL vertical space
	layout->addWidget(stretchWidget, 3, 1, TQt::AlignVCenter);


	urlChanged("");

//	if (ke)
//		kapp->postEvent(m_url->lineEdit(), ke);
}

LinkEditDialog::~LinkEditDialog()
{
}

void LinkEditDialog::polish()
{
	KDialogBase::polish();
	if (m_url->lineEdit()->text().isEmpty()) {
		m_url->setFocus();
		m_url->lineEdit()->end(false);
	} else {
		m_title->setFocus();
		m_title->end(false);
	}
}


void LinkEditDialog::urlChanged(const TQString&)
{
	m_isAutoModified = true;
//	guessTitle();
//	guessIcon();
	// Optimization (filter only once):
	KURL filteredURL = NoteFactory::filteredURL(KURL(m_url->url()));//KURIFilter::self()->filteredURI(KURL(m_url->url()));
	if (m_autoIcon->isOn())
		m_icon->setIcon(NoteFactory::iconForURL(filteredURL));
	if (m_autoTitle->isOn()) {
		m_title->setText(NoteFactory::titleForURL(filteredURL));
		m_autoTitle->setOn(true); // Because the setText() will disable it!
	}
}

void LinkEditDialog::doNotAutoTitle(const TQString&)
{
	if (m_isAutoModified)
		m_isAutoModified = false;
	else
		m_autoTitle->setOn(false);
}

void LinkEditDialog::doNotAutoIcon(TQString)
{
	m_autoIcon->setOn(false);
}

void LinkEditDialog::guessIcon()
{
	if (m_autoIcon->isOn()) {
		KURL filteredURL = NoteFactory::filteredURL(KURL(m_url->url()));//KURIFilter::self()->filteredURI(KURL(m_url->url()));
		m_icon->setIcon(NoteFactory::iconForURL(filteredURL));
	}
}

void LinkEditDialog::guessTitle()
{
	if (m_autoTitle->isOn()) {
		KURL filteredURL = NoteFactory::filteredURL(KURL(m_url->url()));//KURIFilter::self()->filteredURI(KURL(m_url->url()));
		m_title->setText(NoteFactory::titleForURL(filteredURL));
		m_autoTitle->setOn(true); // Because the setText() will disable it!
	}
}

void LinkEditDialog::slotOk()
{
	KURL filteredURL = NoteFactory::filteredURL(KURL(m_url->url()));//KURIFilter::self()->filteredURI(KURL(m_url->url()));
	m_noteContent->setLink(filteredURL, m_title->text(), m_icon->icon(), m_autoTitle->isOn(), m_autoIcon->isOn());
	m_noteContent->setEdited();

	/* Change icon size if link look have changed */
	LinkLook *linkLook = LinkLook::lookForURL(filteredURL);
	TQString icon = m_icon->icon();             // When we change size, icon isn't changed and keep it's old size
	m_icon->setSizePolicy(TQSizePolicy::Minimum, TQSizePolicy::Minimum); // Reset size policy
	m_icon->setIconSize(linkLook->iconSize()); //  So I store it's name and reload it after size change !
	m_icon->setIcon(icon);
	int minSize = m_autoIcon->sizeHint().height();
	// Make the icon button at least the same heigh than the other buttons for a better alignment (nicer to the eyes):
	if (m_icon->sizeHint().height() < minSize)
		m_icon->setFixedSize(minSize, minSize);
	else
		m_icon->setFixedSize(m_icon->sizeHint().height(), m_icon->sizeHint().height()); // Make it square

	KDialogBase::slotOk();
}

/** class LauncherEditDialog: */

LauncherEditDialog::LauncherEditDialog(LauncherContent *contentNote, TQWidget *parent)
 : KDialogBase(KDialogBase::Plain, i18n("Edit Launcher Note"), KDialogBase::Ok | KDialogBase::Cancel,
               KDialogBase::Ok, parent, /*name=*/"EditLauncher", /*modal=*/true, /*separator=*/true),
   m_noteContent(contentNote)
{
	TQWidget     *page   = plainPage();
	TQGridLayout *layout = new TQGridLayout(page, /*nRows=*/4, /*nCols=*/2, /*margin=*/0, spacingHint());

	KService service(contentNote->fullPath());

	m_command = new RunCommandRequester(service.exec(), i18n("Choose a command to run:"), page);
	m_name    = new TQLineEdit(service.name(), page);

	TQWidget *wid = new TQWidget(page);
	TQHBoxLayout *hLay = new TQHBoxLayout(wid, /*margin=*/0, spacingHint());
	m_icon = new TDEIconButton(wid);
	TQLabel *label = new TQLabel(m_icon, i18n("&Icon:"), page);
	m_icon->setIconType(TDEIcon::NoGroup, TDEIcon::Application);
	m_icon->setIconSize(LinkLook::launcherLook->iconSize());
	TQPushButton *guessButton = new TQPushButton(i18n("&Guess"), wid);
	/* Icon button: */
	m_icon->setIcon(service.icon());
	int minSize = guessButton->sizeHint().height();
	// Make the icon button at least the same heigh than the other buttons for a better alignment (nicer to the eyes):
	if (m_icon->sizeHint().height() < minSize)
		m_icon->setFixedSize(minSize, minSize);
	else
		m_icon->setFixedSize(m_icon->sizeHint().height(), m_icon->sizeHint().height()); // Make it square
	/* Guess button: */
	hLay->addWidget(m_icon);
	hLay->addWidget(guessButton);
	hLay->addStretch();

	m_command->lineEdit()->setMinimumWidth(m_command->lineEdit()->fontMetrics().maxWidth()*20);

	TQLabel *label1 = new TQLabel(m_command->lineEdit(), i18n("Comman&d:"), page);
	TQLabel *label2 = new TQLabel(m_name,                i18n("&Name:"),    page);
	layout->addWidget(label1,    0, 0, TQt::AlignVCenter);
	layout->addWidget(label2,    1, 0, TQt::AlignVCenter);
	layout->addWidget(label,     2, 0, TQt::AlignVCenter);
	layout->addWidget(m_command, 0, 1, TQt::AlignVCenter);
	layout->addWidget(m_name,    1, 1, TQt::AlignVCenter);
	layout->addWidget(wid,       2, 1, TQt::AlignVCenter);

	TQWidget *stretchWidget = new TQWidget(page);
	stretchWidget->setSizePolicy(TQSizePolicy(/*hor=*/TQSizePolicy::Fixed, /*ver=*/TQSizePolicy::Expanding, /*hStretch=*/1, /*vStretch=*/255)); // Make it fill ALL vertical space
	layout->addWidget(stretchWidget, 3, 1, TQt::AlignVCenter);

	connect( guessButton, TQ_SIGNAL(clicked()), this, TQ_SLOT(guessIcon()) );
}

LauncherEditDialog::~LauncherEditDialog()
{
}

void LauncherEditDialog::polish()
{
	KDialogBase::polish();
	if (m_command->runCommand().isEmpty()) {
		m_command->lineEdit()->setFocus();
		m_command->lineEdit()->end(false);
	} else {
		m_name->setFocus();
		m_name->end(false);
	}
}

void LauncherEditDialog::slotOk()
{
	// TODO: Remember if a string has been modified AND IS DIFFERENT FROM THE ORIGINAL!

	TDEConfig conf(m_noteContent->fullPath());
	conf.setGroup("Desktop Entry");
	conf.writeEntry("Exec", m_command->runCommand());
	conf.writeEntry("Name", m_name->text());
	conf.writeEntry("Icon", m_icon->icon());

	// Just for faster feedback: conf object will save to disk (and then m_note->loadContent() called)
	m_noteContent->setLauncher(m_name->text(), m_icon->icon(), m_command->runCommand());
	m_noteContent->setEdited();

	KDialogBase::slotOk();
}

void LauncherEditDialog::guessIcon()
{
	m_icon->setIcon( NoteFactory::iconForCommand(m_command->runCommand()) );
}

/** class InlineEditors: */

InlineEditors::InlineEditors()
{
}

InlineEditors::~InlineEditors()
{
}

InlineEditors* InlineEditors::instance()
{
	static InlineEditors *instance = 0;
	if (!instance)
		instance = new InlineEditors();
	return instance;
}

void InlineEditors::initToolBars(TDEActionCollection *actionCollection)
{
	TQFont defaultFont;
	TQColor textColor = (Global::bnpView && Global::bnpView->currentBasket() ?
		Global::bnpView->currentBasket()->textColor() :
		TDEGlobalSettings::textColor());

	// Init the RichTextEditor Toolbar:
	richTextFont = new FocusedFontCombo(Global::mainWindow());
	richTextFont->setFixedWidth(richTextFont->sizeHint().width() * 2 / 3);
	richTextFont->setCurrentFont(defaultFont.family());
	KWidgetAction *action = new KWidgetAction(richTextFont, i18n("Font"), TQt::Key_F6,
	                                          /*receiver=*/0, /*slot=*/"", actionCollection, "richtext_font");

	richTextFontSize = new FontSizeCombo(/*rw=*/true, Global::mainWindow());
	richTextFontSize->setFontSize(defaultFont.pointSize());
	action = new KWidgetAction(richTextFontSize, i18n("Font Size"), TQt::Key_F7,
	                                          /*receiver=*/0, /*slot=*/"", actionCollection, "richtext_font_size");

	richTextColor = new FocusedColorCombo(Global::mainWindow());
	richTextColor->setFixedWidth(richTextColor->sizeHint().height() * 2);
	richTextColor->setColor(textColor);
	action = new KWidgetAction(richTextColor, i18n("Color"), TDEShortcut(), 0, TQ_SLOT(), actionCollection, "richtext_color");

	richTextBold      = new TDEToggleAction( i18n("Bold"),        "format-text-bold",   "Ctrl+B", actionCollection, "richtext_bold"      );
	richTextItalic    = new TDEToggleAction( i18n("Italic"),      "format-text-italic", "Ctrl+I", actionCollection, "richtext_italic"    );
	richTextUnderline = new TDEToggleAction( i18n("Underline"),   "format-text-underline",  "Ctrl+U", actionCollection, "richtext_underline" );

//	richTextSuper     = new TDEToggleAction( i18n("Superscript"), "text_super",  "",       actionCollection, "richtext_super"     );
//	richTextSub       = new TDEToggleAction( i18n("Subscript"),   "text_sub",    "",       actionCollection, "richtext_sub"       );

	richTextLeft      = new TDEToggleAction( i18n("Align Left"),  "format-text-direction-ltr",   "",       actionCollection, "richtext_left"      );
	richTextCenter    = new TDEToggleAction( i18n("Centered"),    "text_center", "",       actionCollection, "richtext_center"    );
	richTextRight     = new TDEToggleAction( i18n("Align Right"), "format-text-direction-rtl",  "",       actionCollection, "richtext_right"     );
	richTextJustified = new TDEToggleAction( i18n("Justified"),   "text_block",  "",       actionCollection, "richtext_block"     );

	richTextLeft->setExclusiveGroup("rt_justify");
	richTextCenter->setExclusiveGroup("rt_justify");
	richTextRight->setExclusiveGroup("rt_justify");
	richTextJustified->setExclusiveGroup("rt_justify");

	richTextUndo      = new TDEAction( i18n("Undo"), "edit-undo", "", actionCollection, "richtext_undo");
	richTextRedo      = new TDEAction( i18n("Redo"), "edit-redo", "", actionCollection, "richtext_redo");

	disableRichTextToolBar();
}

TDEToolBar* InlineEditors::richTextToolBar()
{
	if (Global::mainWindow()) {
		Global::mainWindow()->toolBar(); // Make sure we create the main toolbar FIRST, so it will be on top of the edit toolbar!
		return Global::mainWindow()->toolBar("richTextEditToolBar");
	} else
		return 0;
}

void InlineEditors::enableRichTextToolBar()
{
	richTextFont->setEnabled(true);
	richTextFontSize->setEnabled(true);
	richTextColor->setEnabled(true);
	richTextBold->setEnabled(true);
	richTextItalic->setEnabled(true);
	richTextUnderline->setEnabled(true);
	richTextLeft->setEnabled(true);
	richTextCenter->setEnabled(true);
	richTextRight->setEnabled(true);
	richTextJustified->setEnabled(true);
	richTextUndo->setEnabled(true);
	richTextRedo->setEnabled(true);
}

void InlineEditors::disableRichTextToolBar()
{
	disconnect(richTextFont);
	disconnect(richTextFontSize);
	disconnect(richTextColor);
	disconnect(richTextBold);
	disconnect(richTextItalic);
	disconnect(richTextUnderline);
	disconnect(richTextLeft);
	disconnect(richTextCenter);
	disconnect(richTextRight);
	disconnect(richTextJustified);
	disconnect(richTextUndo);
	disconnect(richTextRedo);

	richTextFont->setEnabled(false);
	richTextFontSize->setEnabled(false);
	richTextColor->setEnabled(false);
	richTextBold->setEnabled(false);
	richTextItalic->setEnabled(false);
	richTextUnderline->setEnabled(false);
	richTextLeft->setEnabled(false);
	richTextCenter->setEnabled(false);
	richTextRight->setEnabled(false);
	richTextJustified->setEnabled(false);
	richTextUndo->setEnabled(false);
	richTextRedo->setEnabled(false);

	// Return to a "proper" state:
	TQFont defaultFont;
	TQColor textColor = (Global::bnpView && Global::bnpView->currentBasket() ?
		Global::bnpView->currentBasket()->textColor() :
		TDEGlobalSettings::textColor());
	richTextFont->setCurrentFont(defaultFont.family());
	richTextFontSize->setFontSize(defaultFont.pointSize());
	richTextColor->setColor(textColor);
	richTextBold->setChecked(false);
	richTextItalic->setChecked(false);
	richTextUnderline->setChecked(false);
	richTextLeft->setChecked(false);
	richTextCenter->setChecked(false);
	richTextRight->setChecked(false);
	richTextJustified->setChecked(false);
}

#include "noteedit.moc"
