/***************************************************************************
 *   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.             *
 ***************************************************************************/

#include <tqfile.h>
#include <tqdir.h>
#include <tqdom.h>
#include <tqpainter.h>
#include <tqstylesheet.h>
#include <tqfontmetrics.h>
#include <tqwidget.h>
#include <tqcursor.h>
#include <tqstringlist.h>
#include <tqbuffer.h>
#include <ktextedit.h>
#include <kservice.h>
#include <kcolordialog.h>
#include <kmessagebox.h>
#include <klocale.h>
#include <kglobalsettings.h>
#include <kpixmapeffect.h>
#include <tqbitmap.h>
#include <kurifilter.h>
//#include <kstringhandler.h>
#include <kfilemetainfo.h>
#include <tqdatetime.h>
#include <kmultipledrag.h>

#include <tqfileinfo.h>
//#include <kio/kfileitem.h>
#include <kfileitem.h>
#include <kio/previewjob.h>
#include <kio/global.h>

#include <iostream>

#include "notecontent.h"
#include "note.h"
#include "noteedit.h"
#include "tag.h"
#include "basket.h"
#include "filter.h"
#include "xmlwork.h"
#include "tools.h"
#include "notefactory.h"
#include "linklabel.h"
#include "global.h"
#include "settings.h"
#include "focusedwidgets.h"
#include "debugwindow.h"
#include "kcolorcombo2.h"
#include "htmlexporter.h"

#include "config.h"
#ifndef WITHOUT_ARTS
	#include <arts/kplayobject.h>
	#include <arts/kplayobjectfactory.h>
	#include <arts/kartsserver.h>
	#include <arts/kartsdispatcher.h>
#endif

/** class NoteContent:
 */

const int NoteContent::FEEDBACK_DARKING = 105;

NoteContent::NoteContent(Note *parent, const TQString &fileName)
 : m_note(parent)
{
	parent->setContent(this);
	setFileName(fileName);
}

void NoteContent::saveToNode(TQDomDocument &doc, TQDomElement &content)
{
	if (useFile()) {
		TQDomText textNode = doc.createTextNode(fileName());
		content.appendChild(textNode);
	}
}

TQRect NoteContent::zoneRect(int zone, const TQPoint &/*pos*/)
{
	if (zone == Note::Content)
		return TQRect(0, 0, note()->width(), note()->height()); // Too wide and height, but it will be clipped by Note::zoneRect()
	else
		return TQRect();
}

KURL NoteContent::urlToOpen(bool /*with*/)
{
	return (useFile() ? KURL(fullPath()) : KURL());
}

void NoteContent::setFileName(const TQString &fileName)
{
	m_fileName = fileName;
}

bool NoteContent::trySetFileName(const TQString &fileName)
{
	if (useFile() && fileName != m_fileName) {
		TQString newFileName = Tools::fileNameForNewFile(fileName, basket()->fullPath());
		TQDir dir;
		dir.rename(fullPath(), basket()->fullPathForFileName(newFileName));
		return true;
	}

	return false; // !useFile() or unsuccesful rename
}

TQString NoteContent::fullPath()
{
	if (note() && useFile())
		return note()->fullPath();
	else
		return "";
}

void NoteContent::contentChanged(int newMinWidth)
{
	m_minWidth = newMinWidth;
	if (note()) {
//		note()->unbufferize();
		note()->requestRelayout(); // TODO: It should re-set the width!  m_width = 0 ?   contentChanged: setWidth, geteight, if size havent changed, only repaint and not relayout
	}
}

Basket* NoteContent::basket()
{
	if (note())
		return note()->basket();
	else
		return 0;
}

void NoteContent::setEdited()
{
	note()->setLastModificationDate(TQDateTime::currentDateTime());
	basket()->save();
}

/** All the Content Classes:
 */

NoteType::Id TextContent::type()      { return NoteType::Text;      }
NoteType::Id HtmlContent::type()      { return NoteType::Html;      }
NoteType::Id ImageContent::type()     { return NoteType::Image;     }
NoteType::Id AnimationContent::type() { return NoteType::Animation; }
NoteType::Id SoundContent::type()     { return NoteType::Sound;     }
NoteType::Id FileContent::type()      { return NoteType::File;      }
NoteType::Id LinkContent::type()      { return NoteType::Link;      }
NoteType::Id LauncherContent::type()  { return NoteType::Launcher;  }
NoteType::Id ColorContent::type()     { return NoteType::Color;     }
NoteType::Id UnknownContent::type()   { return NoteType::Unknown;   }

TQString TextContent::typeName()      { return i18n("Plain Text"); }
TQString HtmlContent::typeName()      { return i18n("Text");       }
TQString ImageContent::typeName()     { return i18n("Image");      }
TQString AnimationContent::typeName() { return i18n("Animation");  }
TQString SoundContent::typeName()     { return i18n("Sound");      }
TQString FileContent::typeName()      { return i18n("File");       }
TQString LinkContent::typeName()      { return i18n("Link");       }
TQString LauncherContent::typeName()  { return i18n("Launcher");   }
TQString ColorContent::typeName()     { return i18n("Color");      }
TQString UnknownContent::typeName()   { return i18n("Unknown");    }

TQString TextContent::lowerTypeName()      { return "text";      }
TQString HtmlContent::lowerTypeName()      { return "html";      }
TQString ImageContent::lowerTypeName()     { return "image";     }
TQString AnimationContent::lowerTypeName() { return "animation"; }
TQString SoundContent::lowerTypeName()     { return "sound";     }
TQString FileContent::lowerTypeName()      { return "file";      }
TQString LinkContent::lowerTypeName()      { return "link";      }
TQString LauncherContent::lowerTypeName()  { return "launcher";  }
TQString ColorContent::lowerTypeName()     { return "color";     }
TQString UnknownContent::lowerTypeName()   { return "unknown";   }

TQString NoteContent::toText(const TQString &cuttedFullPath)
{
	return (cuttedFullPath.isEmpty() ? fullPath() : cuttedFullPath);
}

TQString TextContent::toText(const TQString &/*cuttedFullPath*/)      { return text();                    }
TQString HtmlContent::toText(const TQString &/*cuttedFullPath*/)      { return Tools::htmlToText(html()); }
TQString LinkContent::toText(const TQString &/*cuttedFullPath*/)
{
	if (autoTitle())
		return url().prettyURL();
	else if (title().isEmpty() && url().isEmpty())
		return "";
	else if (url().isEmpty())
		return title();
	else if (title().isEmpty())
		return url().prettyURL();
	else
		return TQString("%1 <%2>").arg(title(), url().prettyURL());
}
TQString ColorContent::toText(const TQString &/*cuttedFullPath*/)     { return color().name();                }
TQString UnknownContent::toText(const TQString &/*cuttedFullPath*/)   { return "";                            }

// TODO: If imageName.isEmpty() return fullPath() because it's for external use, else return fileName() because it's to display in a tooltip
TQString TextContent::toHtml(const TQString &/*imageName*/, const TQString &/*cuttedFullPath*/)
{ return Tools::textToHTMLWithoutP(text());                                                       }

TQString HtmlContent::toHtml(const TQString &/*imageName*/, const TQString &/*cuttedFullPath*/)
{ return Tools::htmlToParagraph(html());                                                          }

TQString ImageContent::toHtml(const TQString &/*imageName*/, const TQString &cuttedFullPath)
{ return TQString("<img src=\"%1\">").arg(cuttedFullPath.isEmpty() ? fullPath() : cuttedFullPath); }

TQString AnimationContent::toHtml(const TQString &/*imageName*/, const TQString &cuttedFullPath)
{ return TQString("<img src=\"%1\">").arg(cuttedFullPath.isEmpty() ? fullPath() : cuttedFullPath); }

TQString SoundContent::toHtml(const TQString &/*imageName*/, const TQString &cuttedFullPath)
{ return TQString("<a href=\"%1\">%2</a>").arg((cuttedFullPath.isEmpty() ? fullPath() : cuttedFullPath), fileName()); } // With the icon?

TQString FileContent::toHtml(const TQString &/*imageName*/, const TQString &cuttedFullPath)
{ return TQString("<a href=\"%1\">%2</a>").arg((cuttedFullPath.isEmpty() ? fullPath() : cuttedFullPath), fileName()); } // With the icon?

TQString LinkContent::toHtml(const TQString &/*imageName*/, const TQString &/*cuttedFullPath*/)
{ return TQString("<a href=\"%1\">%2</a>").arg(url().prettyURL(), title());                        } // With the icon?

TQString LauncherContent::toHtml(const TQString &/*imageName*/, const TQString &cuttedFullPath)
{ return TQString("<a href=\"%1\">%2</a>").arg((cuttedFullPath.isEmpty() ? fullPath() : cuttedFullPath), name());     } // With the icon?

TQString ColorContent::toHtml(const TQString &/*imageName*/, const TQString &/*cuttedFullPath*/)
{ return TQString("<span style=\"color: %1\">%2</span>").arg(color().name(), color().name());  }

TQString UnknownContent::toHtml(const TQString &/*imageName*/, const TQString &/*cuttedFullPath*/)
{ return "";                                                                                  }

TQPixmap ImageContent::toPixmap()     { return pixmap();              }
TQPixmap AnimationContent::toPixmap() { return movie().framePixmap(); }

void NoteContent::toLink(KURL *url, TQString *title, const TQString &cuttedFullPath)
{
	if (useFile()) {
		*url   = KURL(cuttedFullPath.isEmpty() ? fullPath() : cuttedFullPath);
		*title =     (cuttedFullPath.isEmpty() ? fullPath() : cuttedFullPath);
	} else {
		*url   = KURL();
		*title = TQString();
	}
}
void LinkContent::toLink(KURL *url, TQString *title, const TQString &/*cuttedFullPath*/)
{
	*url   = this->url();
	*title = this->title();
}

void LauncherContent::toLink(KURL *url, TQString *title, const TQString &cuttedFullPath)
{
	*url   = KURL(cuttedFullPath.isEmpty() ? fullPath() : cuttedFullPath);
	*title = name();
}
void UnknownContent::toLink(KURL *url, TQString *title, const TQString &/*cuttedFullPath*/)
{
	*url   = KURL();
	*title = TQString();
}

bool TextContent::useFile()      { return true;  }
bool HtmlContent::useFile()      { return true;  }
bool ImageContent::useFile()     { return true;  }
bool AnimationContent::useFile() { return true;  }
bool SoundContent::useFile()     { return true;  }
bool FileContent::useFile()      { return true;  }
bool LinkContent::useFile()      { return false; }
bool LauncherContent::useFile()  { return true;  }
bool ColorContent::useFile()     { return false; }
bool UnknownContent::useFile()   { return true;  }

bool TextContent::canBeSavedAs()      { return true;  }
bool HtmlContent::canBeSavedAs()      { return true;  }
bool ImageContent::canBeSavedAs()     { return true;  }
bool AnimationContent::canBeSavedAs() { return true;  }
bool SoundContent::canBeSavedAs()     { return true;  }
bool FileContent::canBeSavedAs()      { return true;  }
bool LinkContent::canBeSavedAs()      { return true;  }
bool LauncherContent::canBeSavedAs()  { return true;  }
bool ColorContent::canBeSavedAs()     { return false; }
bool UnknownContent::canBeSavedAs()   { return false; }

TQString TextContent::saveAsFilters()      { return "text/plain";            }
TQString HtmlContent::saveAsFilters()      { return "text/html";             }
TQString ImageContent::saveAsFilters()     { return "image/png";             } // TODO: Offer more types
TQString AnimationContent::saveAsFilters() { return "image/gif";             } // TODO: MNG...
TQString SoundContent::saveAsFilters()     { return "audio/x-mp3";           } // TODO: OGG...
TQString FileContent::saveAsFilters()      { return "*";                     } // TODO: Get MIME type of the url target
TQString LinkContent::saveAsFilters()      { return "*";                     } // TODO: idem File + If isDir(): return
TQString LauncherContent::saveAsFilters()  { return "application/x-desktop"; }
TQString ColorContent::saveAsFilters()     { return "";                      }
TQString UnknownContent::saveAsFilters()   { return "";                      }

bool TextContent::match(const FilterData &data)          { return (text().find(data.string, /*index=*/0, /*cs=*/false) != -1);         }
bool HtmlContent::match(const FilterData &data)          { return (m_textEquivalent/*toText("")*/.find(data.string, /*index=*/0, /*cs=*/false) != -1);     } //OPTIM_FILTER
bool ImageContent::match(const FilterData &/*data*/)     { return false;                                                               }
bool AnimationContent::match(const FilterData &/*data*/) { return false;                                                               }
bool SoundContent::match(const FilterData &data)         { return (fileName().find(data.string, /*index=*/0, /*cs=*/false) != -1);     }
bool FileContent::match(const FilterData &data)          { return (fileName().find(data.string, /*index=*/0, /*cs=*/false) != -1);     }
bool LinkContent::match(const FilterData &data)          { return (title().find(data.string, 0, false) != -1 || url().prettyURL().find(data.string, 0, false) != -1); }
bool LauncherContent::match(const FilterData &data)      { return (exec().find(data.string, 0, false) != -1 || name().find(data.string, 0, false) != -1); }
bool ColorContent::match(const FilterData &data)         { return (TQString(color().name()).find(data.string, /*index=*/0, /*cs=*/false) != -1); }
bool UnknownContent::match(const FilterData &data)       { return (mimeTypes().find(data.string, /*index=*/0, /*cs=*/false) != -1);    }

TQString TextContent::editToolTipText()      { return i18n("Edit this plain text");             }
TQString HtmlContent::editToolTipText()      { return i18n("Edit this text");                   }
TQString ImageContent::editToolTipText()     { return i18n("Edit this image");                  }
TQString AnimationContent::editToolTipText() { return i18n("Edit this animation");              }
TQString SoundContent::editToolTipText()     { return i18n("Edit the file name of this sound"); }
TQString FileContent::editToolTipText()      { return i18n("Edit the name of this file");       }
TQString LinkContent::editToolTipText()      { return i18n("Edit this link");                   }
TQString LauncherContent::editToolTipText()  { return i18n("Edit this launcher");               }
TQString ColorContent::editToolTipText()     { return i18n("Edit this color");                  }
TQString UnknownContent::editToolTipText()   { return i18n("Edit this unknown object");         }

TQString TextContent::cssClass()      { return "";         }
TQString HtmlContent::cssClass()      { return "";         }
TQString ImageContent::cssClass()     { return "";         }
TQString AnimationContent::cssClass() { return "";         }
TQString SoundContent::cssClass()     { return "sound";    }
TQString FileContent::cssClass()      { return "file";     }
TQString LinkContent::cssClass()      { return (LinkLook::lookForURL(m_url) == LinkLook::localLinkLook ? "local" : "network"); }
TQString LauncherContent::cssClass()  { return "launcher"; }
TQString ColorContent::cssClass()     { return ""     ;    }
TQString UnknownContent::cssClass()   { return "";         }

void TextContent::fontChanged()      { setText(text());                                          }
void HtmlContent::fontChanged()      { setHtml(html());                                          }
void ImageContent::fontChanged()     { setPixmap(pixmap());                                      }
void AnimationContent::fontChanged() { setMovie(movie());                                        }
void FileContent::fontChanged()      { setFileName(fileName());                                  }
void LinkContent::fontChanged()      { setLink(url(), title(), icon(), autoTitle(), autoIcon()); }
void LauncherContent::fontChanged()  { setLauncher(name(), icon(), exec());                      }
void ColorContent::fontChanged()     { setColor(color());                                        }
void UnknownContent::fontChanged()   { loadFromFile(/*lazyLoad=*/false);                         } // TODO: Optimize: setMimeTypes()

//TQString TextContent::customOpenCommand()      { return (Settings::isTextUseProg()      && ! Settings::textProg().isEmpty()      ? Settings::textProg()      : TQString()); }
TQString HtmlContent::customOpenCommand()      { return (Settings::isHtmlUseProg()      && ! Settings::htmlProg().isEmpty()      ? Settings::htmlProg()      : TQString()); }
TQString ImageContent::customOpenCommand()     { return (Settings::isImageUseProg()     && ! Settings::imageProg().isEmpty()     ? Settings::imageProg()     : TQString()); }
TQString AnimationContent::customOpenCommand() { return (Settings::isAnimationUseProg() && ! Settings::animationProg().isEmpty() ? Settings::animationProg() : TQString()); }
TQString SoundContent::customOpenCommand()     { return (Settings::isSoundUseProg()     && ! Settings::soundProg().isEmpty()     ? Settings::soundProg()     : TQString()); }

void LinkContent::serialize(TQDataStream &stream)  { stream << url() << title() << icon() << (TQ_UINT64)autoTitle() << (TQ_UINT64)autoIcon(); }
void ColorContent::serialize(TQDataStream &stream) { stream << color();  }

TQPixmap TextContent::feedbackPixmap(int width, int height)
{
	TQRect textRect = TQFontMetrics(note()->font()).boundingRect(0, 0, width, height, TQt::AlignAuto | TQt::AlignTop | TQt::WordBreak, text());
	TQPixmap pixmap( TQMIN(width, textRect.width()), TQMIN(height, textRect.height()) );
	pixmap.fill(note()->backgroundColor().dark(FEEDBACK_DARKING));
	TQPainter painter(&pixmap);
	painter.setPen(note()->textColor());
	painter.setFont(note()->font());
	painter.drawText(0, 0, pixmap.width(), pixmap.height(), TQt::AlignAuto | TQt::AlignTop | TQt::WordBreak, text());
	painter.end();
	return pixmap;
}

TQPixmap HtmlContent::feedbackPixmap(int width, int height)
{
	TQSimpleRichText richText(html(), note()->font());
	richText.setWidth(width);
	TQColorGroup colorGroup(basket()->colorGroup());
	colorGroup.setColor(TQColorGroup::Text,       note()->textColor());
	colorGroup.setColor(TQColorGroup::Background, note()->backgroundColor().dark(FEEDBACK_DARKING));
	TQPixmap pixmap( TQMIN(width, richText.widthUsed()), TQMIN(height, richText.height()) );
	pixmap.fill(note()->backgroundColor().dark(FEEDBACK_DARKING));
	TQPainter painter(&pixmap);
	painter.setPen(note()->textColor());
	richText.draw(&painter, 0, 0, TQRect(0, 0, pixmap.width(), pixmap.height()), colorGroup);
	painter.end();
	return pixmap;
}

TQPixmap ImageContent::feedbackPixmap(int width, int height)
{
	if (width >= m_pixmap.width() && height >= m_pixmap.height()) { // Full size
		if (m_pixmap.hasAlpha()) {
			TQPixmap opaque(m_pixmap.width(), m_pixmap.height());
			opaque.fill(note()->backgroundColor().dark(FEEDBACK_DARKING));
			TQPainter painter(&opaque);
			painter.drawPixmap(0, 0, m_pixmap);
			painter.end();
			return opaque;
		} else
			return m_pixmap;
	} else { // Scalled down
		TQImage imageToScale = m_pixmap.convertToImage();
		TQPixmap pmScaled;
		pmScaled.convertFromImage(imageToScale./*smoothScale*/scale(width, height, TQ_ScaleMin));
		if (pmScaled.hasAlpha()) {
			TQPixmap opaque(pmScaled.width(), pmScaled.height());
			opaque.fill(note()->backgroundColor().dark(FEEDBACK_DARKING));
			TQPainter painter(&opaque);
			painter.drawPixmap(0, 0, pmScaled);
			painter.end();
			return opaque;
		} else
			return pmScaled;
	}
}

TQPixmap AnimationContent::feedbackPixmap(int width, int height)
{
	TQPixmap pixmap = m_movie.framePixmap();
	if (width >= pixmap.width() && height >= pixmap.height()) // Full size
		return pixmap;
	else { // Scalled down
		TQImage imageToScale = pixmap.convertToImage();
		TQPixmap pmScaled;
		pmScaled.convertFromImage(imageToScale./*smoothScale*/scale(width, height, TQ_ScaleMin));
		return pmScaled;
	}
}

TQPixmap LinkContent::feedbackPixmap(int width, int height)
{
	TQColorGroup colorGroup(basket()->colorGroup());
	colorGroup.setColor(TQColorGroup::Text,       note()->textColor());
	colorGroup.setColor(TQColorGroup::Background, note()->backgroundColor().dark(FEEDBACK_DARKING));
	return m_linkDisplay.feedbackPixmap(width, height, colorGroup, /*isDefaultColor=*/note()->textColor() == basket()->textColor());
}

TQPixmap ColorContent::feedbackPixmap(int width, int height)
{
	// TODO: Duplicate code: make a rect() method!
	TQRect textRect = TQFontMetrics(note()->font()).boundingRect(color().name());
	int rectHeight = (textRect.height() + 2)*3/2;
	int rectWidth  = rectHeight * 14 / 10; // 1.4 times the height, like A4 papers.

	TQColorGroup colorGroup(basket()->colorGroup());
	colorGroup.setColor(TQColorGroup::Text,       note()->textColor());
	colorGroup.setColor(TQColorGroup::Background, note()->backgroundColor().dark(FEEDBACK_DARKING));

	TQPixmap pixmap( TQMIN(width, rectWidth + RECT_MARGIN + textRect.width() + RECT_MARGIN), TQMIN(height, rectHeight) );
	pixmap.fill(note()->backgroundColor().dark(FEEDBACK_DARKING));
	TQPainter painter(&pixmap);
	paint(&painter, pixmap.width(), pixmap.height(), colorGroup, false, false, false); // We don't care of the three last boolean parameters.
	painter.end();
	return pixmap;
}

TQPixmap FileContent::feedbackPixmap(int width, int height)
{
	TQColorGroup colorGroup(basket()->colorGroup());
	colorGroup.setColor(TQColorGroup::Text,       note()->textColor());
	colorGroup.setColor(TQColorGroup::Background, note()->backgroundColor().dark(FEEDBACK_DARKING));
	return m_linkDisplay.feedbackPixmap(width, height, colorGroup, /*isDefaultColor=*/note()->textColor() == basket()->textColor());
}

TQPixmap LauncherContent::feedbackPixmap(int width, int height)
{
	TQColorGroup colorGroup(basket()->colorGroup());
	colorGroup.setColor(TQColorGroup::Text,       note()->textColor());
	colorGroup.setColor(TQColorGroup::Background, note()->backgroundColor().dark(FEEDBACK_DARKING));
	return m_linkDisplay.feedbackPixmap(width, height, colorGroup, /*isDefaultColor=*/note()->textColor() == basket()->textColor());
}

TQPixmap UnknownContent::feedbackPixmap(int width, int height)
{
	TQRect textRect = TQFontMetrics(note()->font()).boundingRect(0, 0, /*width=*/1, 500000, TQt::AlignAuto | TQt::AlignTop | TQt::WordBreak, m_mimeTypes);

	TQColorGroup colorGroup(basket()->colorGroup());
	colorGroup.setColor(TQColorGroup::Text,       note()->textColor());
	colorGroup.setColor(TQColorGroup::Background, note()->backgroundColor().dark(FEEDBACK_DARKING));

	TQPixmap pixmap( TQMIN(width, DECORATION_MARGIN + textRect.width() + DECORATION_MARGIN), TQMIN(height, DECORATION_MARGIN + textRect.height() + DECORATION_MARGIN) );
	TQPainter painter(&pixmap);
	paint(&painter, pixmap.width() + 1, pixmap.height(), colorGroup, false, false, false); // We don't care of the three last boolean parameters.
	painter.setPen(note()->backgroundColor().dark(FEEDBACK_DARKING));
	painter.drawPoint(0,                  0);
	painter.drawPoint(pixmap.width() - 1, 0);
	painter.drawPoint(0,                  pixmap.height() - 1);
	painter.drawPoint(pixmap.width() - 1, pixmap.height() - 1);
	painter.end();
	return pixmap;
}


/** class TextContent:
 */

TextContent::TextContent(Note *parent, const TQString &fileName, bool lazyLoad)
 : NoteContent(parent, fileName), m_simpleRichText(0)
{
	basket()->addWatchedFile(fullPath());
	loadFromFile(lazyLoad);
}

TextContent::~TextContent()
{
	delete m_simpleRichText;
}

int TextContent::setWidthAndGetHeight(int width)
{
	if (m_simpleRichText) {
		width -= 1;
		m_simpleRichText->setWidth(width);
		return m_simpleRichText->height();
	} else
		return 10; // Lazy loaded
}

void TextContent::paint(TQPainter *painter, int width, int height, const TQColorGroup &colorGroup, bool /*isDefaultColor*/, bool /*isSelected*/, bool /*isHovered*/)
{
	if (m_simpleRichText) {
		width -= 1;
		m_simpleRichText->draw(painter, 0, 0, TQRect(0, 0, width, height), colorGroup);
	}
}

bool TextContent::loadFromFile(bool lazyLoad)
{
	DEBUG_WIN << "Loading TextContent From " + basket()->folderName() + fileName();

	TQString content;
	bool success = basket()->loadFromFile(fullPath(), &content, /*isLocalEncoding=*/true);

	if (success)
		setText(content, lazyLoad);
	else {
		std::cout << "FAILED TO LOAD TextContent: " << fullPath() << std::endl;
		setText("", lazyLoad);
		if (!TQFile::exists(fullPath()))
			saveToFile(); // Reserve the fileName so no new note will have the same name!
	}
	return success;
}

bool TextContent::finishLazyLoad()
{
	int width = (m_simpleRichText ? m_simpleRichText->width() : 1);
	delete m_simpleRichText;
	TQString html = "<html><head><meta name=\"qrichtext\" content=\"1\" /></head><body>" + Tools::tagURLs(Tools::textToHTML(m_text)); // Don't collapse multiple spaces!
	m_simpleRichText = new TQSimpleRichText(html, note()->font());
	m_simpleRichText->setWidth(1); // We put a width of 1 pixel, so usedWidth() is egual to the minimum width
	int minWidth = m_simpleRichText->widthUsed();
	m_simpleRichText->setWidth(width);
	contentChanged(minWidth + 1);

	return true;
}

bool TextContent::saveToFile()
{
	return basket()->saveToFile(fullPath(), text(), /*isLocalEncoding=*/true);
}

TQString TextContent::linkAt(const TQPoint &pos)
{
	if (m_simpleRichText)
		return m_simpleRichText->anchorAt(pos);
	else
		return ""; // Lazy loaded
}


TQString TextContent::messageWhenOpenning(OpenMessage where)
{
	switch (where) {
		case OpenOne:               return i18n("Opening plain text...");
		case OpenSeveral:           return i18n("Opening plain texts...");
		case OpenOneWith:           return i18n("Opening plain text with...");
		case OpenSeveralWith:       return i18n("Opening plain texts with...");
		case OpenOneWithDialog:     return i18n("Open plain text with:");
		case OpenSeveralWithDialog: return i18n("Open plain texts with:");
		default:                    return "";
	}
}

void TextContent::setText(const TQString &text, bool lazyLoad)
{
	m_text = text;
	if (!lazyLoad)
		finishLazyLoad();
	else
		contentChanged(10);
}

void TextContent::exportToHTML(HTMLExporter *exporter, int indent)
{
	TQString spaces;
	TQString html = "<html><head><meta name=\"qrichtext\" content=\"1\" /></head><body>" +
	               Tools::tagURLs(Tools::textToHTMLWithoutP(text().replace("\t", "                "))); // Don't collapse multiple spaces!
	exporter->stream << html.replace("  ", " &nbsp;").replace("\n", "\n" + spaces.fill(' ', indent + 1));
}

/** class HtmlContent:
 */

HtmlContent::HtmlContent(Note *parent, const TQString &fileName, bool lazyLoad)
 : NoteContent(parent, fileName), m_simpleRichText(0)
{
	basket()->addWatchedFile(fullPath());
	loadFromFile(lazyLoad);
}

HtmlContent::~HtmlContent()
{
	delete m_simpleRichText;
}

int HtmlContent::setWidthAndGetHeight(int width)
{
	if (m_simpleRichText) {
		width -= 1;
		m_simpleRichText->setWidth(width);
		return m_simpleRichText->height();
	} else
		return 10; // Lazy loaded
}

void HtmlContent::paint(TQPainter *painter, int width, int height, const TQColorGroup &colorGroup, bool /*isDefaultColor*/, bool /*isSelected*/, bool /*isHovered*/)
{
	if (m_simpleRichText) {
		width -= 1;
		m_simpleRichText->draw(painter, 0, 0, TQRect(0, 0, width, height), colorGroup);
	}
}

bool HtmlContent::loadFromFile(bool lazyLoad)
{
	DEBUG_WIN << "Loading HtmlContent From " + basket()->folderName() + fileName();

	TQString content;
	bool success = basket()->loadFromFile(fullPath(), &content, /*isLocalEncoding=*/true);

	if (success)
		setHtml(content, lazyLoad);
	else {
		std::cout << "FAILED TO LOAD HtmlContent: " << fullPath() << std::endl;
		setHtml("", lazyLoad);
		if (!TQFile::exists(fullPath()))
			saveToFile(); // Reserve the fileName so no new note will have the same name!
	}
	return success;
}

bool HtmlContent::finishLazyLoad()
{
	int width = (m_simpleRichText ? m_simpleRichText->width() : 1);
	delete m_simpleRichText;
	m_simpleRichText = new TQSimpleRichText(Tools::tagURLs(m_html), note()->font());
	m_simpleRichText->setWidth(1); // We put a width of 1 pixel, so usedWidth() is egual to the minimum width
	int minWidth = m_simpleRichText->widthUsed();
	m_simpleRichText->setWidth(width);
	contentChanged(minWidth + 1);

	return true;
}

bool HtmlContent::saveToFile()
{
	return basket()->saveToFile(fullPath(), html(), /*isLocalEncoding=*/true);
}

TQString HtmlContent::linkAt(const TQPoint &pos)
{
	if (m_simpleRichText)
		return m_simpleRichText->anchorAt(pos);
	else
		return ""; // Lazy loaded
}


TQString HtmlContent::messageWhenOpenning(OpenMessage where)
{
	switch (where) {
		case OpenOne:               return i18n("Opening text...");
		case OpenSeveral:           return i18n("Opening texts...");
		case OpenOneWith:           return i18n("Opening text with...");
		case OpenSeveralWith:       return i18n("Opening texts with...");
		case OpenOneWithDialog:     return i18n("Open text with:");
		case OpenSeveralWithDialog: return i18n("Open texts with:");
		default:                    return "";
	}
}

void HtmlContent::setHtml(const TQString &html, bool lazyLoad)
{
	m_html = html;
	m_textEquivalent = toText(""); //OPTIM_FILTER
	if (!lazyLoad)
		finishLazyLoad();
	else
		contentChanged(10);
}

void HtmlContent::exportToHTML(HTMLExporter *exporter, int indent)
{
	TQString spaces;
	exporter->stream << Tools::htmlToParagraph(Tools::tagURLs(html().replace("\t", "                ")))
	                    .replace("  ", " &nbsp;")
	                    .replace("\n", "\n" + spaces.fill(' ', indent + 1));
}

/** class ImageContent:
 */

ImageContent::ImageContent(Note *parent, const TQString &fileName, bool lazyLoad)
 : NoteContent(parent, fileName), m_format(0)
{
	basket()->addWatchedFile(fullPath());
	loadFromFile(lazyLoad);
}

int ImageContent::setWidthAndGetHeight(int width)
{
	width -= 1;
	// Don't store width: we will get it on paint!
	if (width >= m_pixmap.width()) // Full size
		return m_pixmap.height();
	else { // Scalled down
		double height = m_pixmap.height() * (double)width / m_pixmap.width();
		return int((double)(int)height <= (height - 0.5) ? height + 1 : height);
	}
}

void ImageContent::paint(TQPainter *painter, int width, int /*height*/, const TQColorGroup &/*colorGroup*/, bool /*isDefaultColor*/, bool /*isSelected*/, bool /*isHovered*/)
{
	width -= 1;
//	KPixmap pixmap = m_pixmap;
//	if (note()->isSelected())
//		pixmap = KPixmapEffect::selectedPixmap(m_pixmap, KGlobalSettings::highlightColor());

	if (width >= m_pixmap.width()) // Full size
		painter->drawPixmap(0, 0, m_pixmap);
	else { // Scalled down
		double scale = ((double)width) / m_pixmap.width();
		painter->scale(scale, scale);
		painter->drawPixmap(0, 0, m_pixmap);  // TODO: Smooth !!!
	}
}

bool ImageContent::loadFromFile(bool lazyLoad)
{
	if (lazyLoad)
		return true;
	else
		return finishLazyLoad();
}

bool ImageContent::finishLazyLoad()
{
	DEBUG_WIN << "Loading ImageContent From " + basket()->folderName() + fileName();

	TQByteArray content;

	if (basket()->loadFromFile(fullPath(), &content))
	{
		TQBuffer buffer(content);

		buffer.open(IO_ReadOnly);
		m_format = (char* /* from const char* */)TQImageIO::imageFormat(TQT_TQIODEVICE(&buffer)); // See TQImageIO to know what formats can be supported.
		buffer.close();
		if (m_format) {
			m_pixmap.loadFromData(content);
			setPixmap(m_pixmap);
			return true;
		}
	}

	std::cout << "FAILED TO LOAD ImageContent: " << fullPath() << std::endl;
	m_format = (char*)"PNG"; // If the image is set later, it should be saved without destruction, so we use PNG by default.
	m_pixmap.resize(1, 1); // Create a 1x1 pixels image instead of an undefined one.
	m_pixmap.fill();
	m_pixmap.setMask(m_pixmap.createHeuristicMask());
	setPixmap(m_pixmap);
	if (!TQFile::exists(fullPath()))
		saveToFile(); // Reserve the fileName so no new note will have the same name!
	return false;
}

bool ImageContent::saveToFile()
{
	TQByteArray ba;
	TQBuffer buffer(ba);

	buffer.open(IO_WriteOnly);
	m_pixmap.save(&buffer, m_format);
	return basket()->saveToFile(fullPath(), ba);
}


void ImageContent::toolTipInfos(TQStringList *keys, TQStringList *values)
{
	keys->append(i18n("Size"));
	values->append(i18n("%1 by %2 pixels").arg(TQString::number(m_pixmap.width()), TQString::number(m_pixmap.height())));
}

TQString ImageContent::messageWhenOpenning(OpenMessage where)
{
	switch (where) {
		case OpenOne:               return i18n("Opening image...");
		case OpenSeveral:           return i18n("Opening images...");
		case OpenOneWith:           return i18n("Opening image with...");
		case OpenSeveralWith:       return i18n("Opening images with...");
		case OpenOneWithDialog:     return i18n("Open image with:");
		case OpenSeveralWithDialog: return i18n("Open images with:");
		default:                    return "";
	}
}

void ImageContent::setPixmap(const TQPixmap &pixmap)
{
	m_pixmap = pixmap;
	// Since it's scalled, the height is always greater or equal to the size of the tag emblems (16)
	contentChanged(16 + 1); // TODO: always good? I don't think...
}

void ImageContent::exportToHTML(HTMLExporter *exporter, int /*indent*/)
{
	int width  = m_pixmap.width();
	int height = m_pixmap.height();
	int contentWidth = note()->width() - note()->contentX() - 1 - Note::NOTE_MARGIN;

	TQString imageName = exporter->copyFile(fullPath(), /*createIt=*/true);

	if (contentWidth <= m_pixmap.width()) { // Scalled down
		double scale = ((double)contentWidth) / m_pixmap.width();
		width  = (int)(m_pixmap.width()  * scale);
		height = (int)(m_pixmap.height() * scale);
		exporter->stream << "<a href=\"" << exporter->dataFolderName << imageName << "\" title=\"" << i18n("Click for full size view") << "\">";
	}

	exporter->stream << "<img src=\"" << exporter->dataFolderName << imageName
	                 << "\" width=\"" << width << "\" height=\"" << height << "\" alt=\"\">";

	if (contentWidth <= m_pixmap.width()) // Scalled down
		exporter->stream << "</a>";
}

/** class AnimationContent:
 */

int AnimationContent::INVALID_STATUS = -100;

AnimationContent::AnimationContent(Note *parent, const TQString &fileName, bool lazyLoad)
 : NoteContent(parent, fileName), m_oldStatus(INVALID_STATUS)
{
	basket()->addWatchedFile(fullPath());
	loadFromFile(lazyLoad);
}

int AnimationContent::setWidthAndGetHeight(int /*width*/)
{
	/*width -= 1*/;
	return  m_movie.framePixmap().height()  ; // TODO!!!
}

void AnimationContent::paint(TQPainter *painter, int width, int /*height*/, const TQColorGroup &/*colorGroup*/, bool /*isDefaultColor*/, bool /*isSelected*/, bool /*isHovered*/)
{
	/*width -= 1*/;
//	DEBUG_WIN << "AnimationContent::paint()";
	const TQPixmap &frame = m_movie.framePixmap();
	if (width >= frame.width()) // Full size
		painter->drawPixmap(0, 0, frame);
	else // Scalled down
		painter->drawPixmap(0, 0, frame);  // TODO: Scall down
}

bool AnimationContent::loadFromFile(bool lazyLoad)
{
	if (lazyLoad)
		return true;
	else
		return finishLazyLoad();
}

bool AnimationContent::finishLazyLoad()
{
	DEBUG_WIN << "Loading MovieContent From " + basket()->folderName() + fileName();
//	return setMovie(TQMovie(fullPath()));

	bool success = false;
	TQByteArray content;
	if (basket()->loadFromFile(fullPath(), &content))
		success = setMovie(TQMovie(content, content.size()));
	if (!success)
		setMovie(TQMovie());
	return success;
}

bool AnimationContent::saveToFile()
{
	// Impossible!
	return false;
}


TQString AnimationContent::messageWhenOpenning(OpenMessage where)
{
	switch (where) {
		case OpenOne:               return i18n("Opening animation...");
		case OpenSeveral:           return i18n("Opening animations...");
		case OpenOneWith:           return i18n("Opening animation with...");
		case OpenSeveralWith:       return i18n("Opening animations with...");
		case OpenOneWithDialog:     return i18n("Open animation with:");
		case OpenSeveralWithDialog: return i18n("Open animations with:");
		default:                    return "";
	}
}

bool AnimationContent::setMovie(const TQMovie &movie)
{
	if (!m_movie.isNull()) {
		// Disconnect?
		return false;
	}
	m_movie = movie;
	m_movie.connectUpdate( this, TQT_SLOT(movieUpdated(const TQRect&)) );
	m_movie.connectResize( this, TQT_SLOT(movieResized(const TQSize&)) );
	m_movie.connectStatus( this, TQT_SLOT(movieStatus(int))           );
	contentChanged(  m_movie.framePixmap().width() + 1  ); // TODO
	return true;
}

void AnimationContent::movieUpdated(const TQRect&)
{
	note()->unbufferize();
	note()->update();
}

void AnimationContent::movieResized(const TQSize&)
{
	note()->requestRelayout(); // ?
}

/** When a user drop a .gif file, for instance, we don't know if it is an image
  * or an animtion (gif file contain multiple images).
  * To determin that, we assume this is an animation and count the number of images.
  * TQMovie send, in this order:
  * - For a unique image: TQMovie::EndOfFrame, TQMovie::EndOfLoop, TQMovie::EndOfMovie.
  * - For animation:      TQMovie::EndOfFrame... (for each image), TQMovie::EndOfLoop,
  *                       and it then restart that for each loop.
  */
void AnimationContent::movieStatus(int status)
{
	DEBUG_WIN << "movieStatus()";

	// At least two frames: it's an animation, everything is OK
	if (m_oldStatus == TQMovie::EndOfFrame && status == TQMovie::EndOfFrame) {
		movie().disconnectStatus(this);
		m_oldStatus = INVALID_STATUS;
//		if (note()->isFocused())                 // When inserting a new note we ensure it visble
//			basket()->ensureNoteVisible(note()); //  But after loading it has certainly grown and if it was
	}
	// Only one image: it's an image, change note's type
	else if (m_oldStatus == TQMovie::EndOfFrame && status == TQMovie::EndOfLoop) {
		movie().disconnectStatus(this);
		m_oldStatus = INVALID_STATUS;
		note()->setContent(new ImageContent(note(), fileName()));
		basket()->save();
		//delete this; // CRASH, as always !!!!!!!!!
		//TQTimer::singleShot(0,   this, TQT_SLOT(loadContent()));    // Delayed to avoid crash!
		//TQTimer::singleShot(100, this, TQT_SLOT(saveProperties())); // We should save it's an image and not an animation
//		if (note()->isFocused())
//			TQTimer::singleShot(25, note(), TQT_SLOT(delayedEnsureVisible()));
	}
	else
		m_oldStatus = status;
}

void AnimationContent::exportToHTML(HTMLExporter *exporter, int /*indent*/)
{
	exporter->stream << TQString("<img src=\"%1\" width=\"%2\" height=\"%3\" alt=\"\">")
	                    .arg( exporter->dataFolderName + exporter->copyFile(fullPath(), /*createIt=*/true),
	                          TQString::number(movie().framePixmap().size().width()),
	                          TQString::number(movie().framePixmap().size().height()) );
}

/** class FileContent:
 */

FileContent::FileContent(Note *parent, const TQString &fileName)
 : NoteContent(parent, fileName), m_previewJob(0)
{
	basket()->addWatchedFile(fullPath());
	setFileName(fileName); // FIXME: TO THAT HERE BECAUSE NoteContent() constructor seems to don't be able to call virtual methods???
}

int FileContent::setWidthAndGetHeight(int width)
{
	m_linkDisplay.setWidth(width);
	return m_linkDisplay.height();
}

void FileContent::paint(TQPainter *painter, int width, int height, const TQColorGroup &colorGroup, bool isDefaultColor, bool isSelected, bool isHovered)
{
	m_linkDisplay.paint(painter, 0, 0, width, height, colorGroup, isDefaultColor, isSelected, isHovered, isHovered && note()->hoveredZone() == Note::Custom0);
}

bool FileContent::loadFromFile(bool /*lazyLoad*/)
{
	setFileName(fileName()); // File changed: get new file preview!
	return true;
}

void FileContent::toolTipInfos(TQStringList *keys, TQStringList *values)
{
	// Get the size of the file:
	uint size = TQFileInfo(fullPath()).size();
	TQString humanFileSize = KIO::convertSize((KIO::filesize_t)size);

	keys->append(i18n("Size"));
	values->append(humanFileSize);

	KMimeType::Ptr mime = KMimeType::findByURL(KURL(fullPath()));
	if (mime) {
		keys->append(i18n("Type"));
		values->append(mime->comment());
	}

	KFileMetaInfo infos = KFileMetaInfo(KURL(fullPath()));
	if (infos.isValid() && !infos.isEmpty()) {
		TQStringList groups = infos.preferredKeys();
		int i = 0;
		for (TQStringList::Iterator it = groups.begin(); i < 6 && it != groups.end(); ++it) {
			KFileMetaInfoItem metaInfoItem = infos.item(*it);
			if (!metaInfoItem.string().isEmpty()) {
				keys->append(metaInfoItem.translatedKey());
				values->append(metaInfoItem.string());
				++i;
			}
		}
	}
}

int FileContent::zoneAt(const TQPoint &pos)
{
	return (m_linkDisplay.iconButtonAt(pos) ? 0 : Note::Custom0);
}

TQRect FileContent::zoneRect(int zone, const TQPoint &/*pos*/)
{
	TQRect linkRect = m_linkDisplay.iconButtonRect();

	if (zone == Note::Custom0)
		return TQRect(linkRect.width(), 0, note()->width(), note()->height()); // Too wide and height, but it will be clipped by Note::zoneRect()
	else if (zone == Note::Content)
		return linkRect;
	else
		return TQRect();
}

TQString FileContent::zoneTip(int zone)
{
	return (zone == Note::Custom0 ? i18n("Open this file") : TQString());
}

void FileContent::setCursor(TQWidget *widget, int zone)
{
	if (zone == Note::Custom0)
		widget->setCursor(TQt::PointingHandCursor);
}


int FileContent::xEditorIndent()
{
	return m_linkDisplay.iconButtonRect().width() + 2;
}


TQString FileContent::messageWhenOpenning(OpenMessage where)
{
	switch (where) {
		case OpenOne:               return i18n("Opening file...");
		case OpenSeveral:           return i18n("Opening files...");
		case OpenOneWith:           return i18n("Opening file with...");
		case OpenSeveralWith:       return i18n("Opening files with...");
		case OpenOneWithDialog:     return i18n("Open file with:");
		case OpenSeveralWithDialog: return i18n("Open files with:");
		default:                    return "";
	}
}

void FileContent::setFileName(const TQString &fileName)
{
	NoteContent::setFileName(fileName);
	KURL url = KURL(fullPath());
	if (linkLook()->previewEnabled())
		m_linkDisplay.setLink(fileName, NoteFactory::iconForURL(url),            linkLook(), note()->font()); // FIXME: move iconForURL outside of NoteFactory !!!!!
	else
		m_linkDisplay.setLink(fileName, NoteFactory::iconForURL(url), TQPixmap(), linkLook(), note()->font());
	startFetchingUrlPreview();
	contentChanged(m_linkDisplay.minWidth());
}

void FileContent::linkLookChanged()
{
	fontChanged();
	//setFileName(fileName());
	//startFetchingUrlPreview();
}

void FileContent::newPreview(const KFileItem*, const TQPixmap &preview)
{
	LinkLook *linkLook = this->linkLook();
	m_linkDisplay.setLink(fileName(), NoteFactory::iconForURL(KURL(fullPath())), (linkLook->previewEnabled() ? preview : TQPixmap()), linkLook, note()->font());
	contentChanged(m_linkDisplay.minWidth());
}

void FileContent::removePreview(const KFileItem*)
{
	newPreview(0, TQPixmap());
}

void FileContent::startFetchingUrlPreview()
{
	KURL url(fullPath());
	LinkLook *linkLook = this->linkLook();

//	delete m_previewJob;
	if (!url.isEmpty() && linkLook->previewSize() > 0) {
		KURL filteredUrl = NoteFactory::filteredURL(url);//KURIFilter::self()->filteredURI(url);
		KURL::List urlList;
		urlList.append(filteredUrl);
		m_previewJob = KIO::filePreview(urlList, linkLook->previewSize(), linkLook->previewSize(), linkLook->iconSize());
		connect( m_previewJob, TQT_SIGNAL(gotPreview(const KFileItem*, const TQPixmap&)), this, TQT_SLOT(newPreview(const KFileItem*, const TQPixmap&)) );
		connect( m_previewJob, TQT_SIGNAL(failed(const KFileItem*)),                     this, TQT_SLOT(removePreview(const KFileItem*))              );
	}
}

void FileContent::exportToHTML(HTMLExporter *exporter, int indent)
{
	TQString spaces;
	TQString fileName = exporter->copyFile(fullPath(), true);
	exporter->stream << m_linkDisplay.toHtml(exporter, KURL(exporter->dataFolderName + fileName), "").replace("\n", "\n" + spaces.fill(' ', indent + 1));
}

/** class SoundContent:
 */

SoundContent::SoundContent(Note *parent, const TQString &fileName)
 : FileContent(parent, fileName)
{
	setFileName(fileName); // FIXME: TO THAT HERE BECAUSE NoteContent() constructor seems to don't be able to call virtual methods???
}


TQString SoundContent::zoneTip(int zone)
{
	return (zone == Note::Custom0 ? i18n("Open this sound") : TQString());
}

void SoundContent::setHoveredZone(int oldZone, int newZone)
{
#ifdef WITHOUT_ARTS
	Q_UNUSED(oldZone);
	if (newZone == Note::Custom0 || newZone == Note::Content)
		std::cout << "Compiled without aRts: sound is not played." << std::endl;
#else
	static KArtsDispatcher        *s_dispatcher  = new KArtsDispatcher(); // Needed for s_playObj (we don't use it directly)
	static KArtsServer            *s_playServer  = new KArtsServer();
	static KDE::PlayObjectFactory *s_playFactory = new KDE::PlayObjectFactory(s_playServer);
	static KDE::PlayObject        *s_playObj     = 0;

	Q_UNUSED(s_dispatcher); // Avoid the compiler to tell us it is not used!
	if (newZone == Note::Custom0 || newZone == Note::Content) {
		// Start the sound preview:
		if (oldZone != Note::Custom0 && oldZone != Note::Content) { // Don't restart if it was already in one of those zones
			s_playObj = s_playFactory->createPlayObject(fullPath(), true);
			s_playObj->play();
		}
	} else {
		// Stop the sound preview, if it was started:
		if (s_playObj) {
			s_playObj->halt();
			delete s_playObj;
			s_playObj = 0;
		}
	}
#endif
}


TQString SoundContent::messageWhenOpenning(OpenMessage where)
{
	switch (where) {
		case OpenOne:               return i18n("Opening sound...");
		case OpenSeveral:           return i18n("Opening sounds...");
		case OpenOneWith:           return i18n("Opening sound with...");
		case OpenSeveralWith:       return i18n("Opening sounds with...");
		case OpenOneWithDialog:     return i18n("Open sound with:");
		case OpenSeveralWithDialog: return i18n("Open sounds with:");
		default:                    return "";
	}
}

/** class LinkContent:
 */

LinkContent::LinkContent(Note *parent, const KURL &url, const TQString &title, const TQString &icon, bool autoTitle, bool autoIcon)
 : NoteContent(parent), m_previewJob(0)
{
	setLink(url, title, icon, autoTitle, autoIcon);
}

int LinkContent::setWidthAndGetHeight(int width)
{
	m_linkDisplay.setWidth(width);
	return m_linkDisplay.height();
}

void LinkContent::paint(TQPainter *painter, int width, int height, const TQColorGroup &colorGroup, bool isDefaultColor, bool isSelected, bool isHovered)
{
	m_linkDisplay.paint(painter, 0, 0, width, height, colorGroup, isDefaultColor, isSelected, isHovered, isHovered && note()->hoveredZone() == Note::Custom0);
}

void LinkContent::saveToNode(TQDomDocument &doc, TQDomElement &content)
{
	content.setAttribute("title",      title()                        );
	content.setAttribute("icon",       icon()                         );
	content.setAttribute("autoTitle", (autoTitle() ? "true" : "false"));
	content.setAttribute("autoIcon",  (autoIcon()  ? "true" : "false"));
	TQDomText textNode = doc.createTextNode(url().prettyURL());
	content.appendChild(textNode);
}


void LinkContent::toolTipInfos(TQStringList *keys, TQStringList *values)
{
	keys->append(i18n("Target"));
	values->append(m_url.prettyURL());
}

int LinkContent::zoneAt(const TQPoint &pos)
{
	return (m_linkDisplay.iconButtonAt(pos) ? 0 : Note::Custom0);
}

TQRect LinkContent::zoneRect(int zone, const TQPoint &/*pos*/)
{
	TQRect linkRect = m_linkDisplay.iconButtonRect();

	if (zone == Note::Custom0)
		return TQRect(linkRect.width(), 0, note()->width(), note()->height()); // Too wide and height, but it will be clipped by Note::zoneRect()
	else if (zone == Note::Content)
		return linkRect;
	else
		return TQRect();
}

TQString LinkContent::zoneTip(int zone)
{
	return (zone == Note::Custom0 ? i18n("Open this link") : TQString());
}

void LinkContent::setCursor(TQWidget *widget, int zone)
{
	if (zone == Note::Custom0)
		widget->setCursor(TQt::PointingHandCursor);
}

TQString LinkContent::statusBarMessage(int zone)
{
	if (zone == Note::Custom0 || zone == Note::Content)
		return m_url.prettyURL();
	else
		return "";
}


KURL LinkContent::urlToOpen(bool /*with*/)
{
	return NoteFactory::filteredURL(url());//KURIFilter::self()->filteredURI(url());
}

TQString LinkContent::messageWhenOpenning(OpenMessage where)
{
	if (url().isEmpty())
		return i18n("Link have no URL to open.");

	switch (where) {
		case OpenOne:               return i18n("Opening link target...");
		case OpenSeveral:           return i18n("Opening link targets...");
		case OpenOneWith:           return i18n("Opening link target with...");
		case OpenSeveralWith:       return i18n("Opening link targets with...");
		case OpenOneWithDialog:     return i18n("Open link target with:");
		case OpenSeveralWithDialog: return i18n("Open link targets with:");
		default:                    return "";
	}
}

void LinkContent::setLink(const KURL &url, const TQString &title, const TQString &icon, bool autoTitle, bool autoIcon)
{
	m_autoTitle = autoTitle;
	m_autoIcon  = autoIcon;
	m_url       = NoteFactory::filteredURL(KURL(url));//KURIFilter::self()->filteredURI(url);
	m_title     = (autoTitle ? NoteFactory::titleForURL(m_url) : title);
	m_icon      = (autoIcon  ? NoteFactory::iconForURL(m_url)  : icon);

	LinkLook *look = LinkLook::lookForURL(m_url);
	if (look->previewEnabled())
		m_linkDisplay.setLink(m_title, m_icon,            look, note()->font());
	else
		m_linkDisplay.setLink(m_title, m_icon, TQPixmap(), look, note()->font());
	startFetchingUrlPreview();
	contentChanged(m_linkDisplay.minWidth());
}

void LinkContent::linkLookChanged()
{
	fontChanged();
}

void LinkContent::newPreview(const KFileItem*, const TQPixmap &preview)
{
	LinkLook *linkLook = LinkLook::lookForURL(url());
	m_linkDisplay.setLink(title(), icon(), (linkLook->previewEnabled() ? preview : TQPixmap()), linkLook, note()->font());
	contentChanged(m_linkDisplay.minWidth());
}

void LinkContent::removePreview(const KFileItem*)
{
	newPreview(0, TQPixmap());
}

// Code dupicated from FileContent::startFetchingUrlPreview()
void LinkContent::startFetchingUrlPreview()
{
	KURL url = this->url();
	LinkLook *linkLook = LinkLook::lookForURL(this->url());

//	delete m_previewJob;
	if (!url.isEmpty() && linkLook->previewSize() > 0) {
		KURL filteredUrl = NoteFactory::filteredURL(url);//KURIFilter::self()->filteredURI(url);
		KURL::List urlList;
		urlList.append(filteredUrl);
		m_previewJob = KIO::filePreview(urlList, linkLook->previewSize(), linkLook->previewSize(), linkLook->iconSize());
		connect( m_previewJob, TQT_SIGNAL(gotPreview(const KFileItem*, const TQPixmap&)), this, TQT_SLOT(newPreview(const KFileItem*, const TQPixmap&)) );
		connect( m_previewJob, TQT_SIGNAL(failed(const KFileItem*)),                     this, TQT_SLOT(removePreview(const KFileItem*))              );
	}
}

void LinkContent::exportToHTML(HTMLExporter *exporter, int indent)
{
	TQString linkTitle = title();

// TODO:
//	// Append address (useful for print version of the page/basket):
//	if (exportData.formatForImpression && (!autoTitle() && title() != NoteFactory::titleForURL(url().prettyURL()))) {
//		// The address is on a new line, unless title is empty (empty lines was replaced by &nbsp;):
//		if (linkTitle == " "/*"&nbsp;"*/)
//			linkTitle = url().prettyURL()/*""*/;
//		else
//			linkTitle = linkTitle + " <" + url().prettyURL() + ">"/*+ "<br>"*/;
//		//linkTitle += "<i>" + url().prettyURL() + "</i>";
//	}

	KURL linkURL;
/*
	TQFileInfo fInfo(url().path());
//	DEBUG_WIN << url().path()
//	          << "IsFile:" + TQString::number(fInfo.isFile())
//	          << "IsDir:"  + TQString::number(fInfo.isDir());
	if (exportData.embedLinkedFiles && fInfo.isFile()) {
//		DEBUG_WIN << "Embed file";
		linkURL = exportData.dataFolderName + Basket::copyFile(url().path(), exportData.dataFolderPath, true);
	} else if (exportData.embedLinkedFolders && fInfo.isDir()) {
//		DEBUG_WIN << "Embed folder";
		linkURL = exportData.dataFolderName + Basket::copyFile(url().path(), exportData.dataFolderPath, true);
	} else {
//		DEBUG_WIN << "Embed LINK";
*/
		linkURL = url();
/*
	}
*/

	TQString spaces;
	exporter->stream << m_linkDisplay.toHtml(exporter, linkURL, linkTitle).replace("\n", "\n" + spaces.fill(' ', indent + 1));
}

/** class LauncherContent:
 */

LauncherContent::LauncherContent(Note *parent, const TQString &fileName)
 : NoteContent(parent, fileName)
{
	basket()->addWatchedFile(fullPath());
	loadFromFile(/*lazyLoad=*/false);
}

int LauncherContent::setWidthAndGetHeight(int width)
{
	m_linkDisplay.setWidth(width);
	return m_linkDisplay.height();
}

void LauncherContent::paint(TQPainter *painter, int width, int height, const TQColorGroup &colorGroup, bool isDefaultColor, bool isSelected, bool isHovered)
{
	m_linkDisplay.paint(painter, 0, 0, width, height, colorGroup, isDefaultColor, isSelected, isHovered, isHovered && note()->hoveredZone() == Note::Custom0);
}

bool LauncherContent::loadFromFile(bool /*lazyLoad*/) // TODO: saveToFile() ?? Is it possible?
{
	DEBUG_WIN << "Loading LauncherContent From " + basket()->folderName() + fileName();
	KService service(fullPath());
	setLauncher(service.name(), service.icon(), service.exec());
	return true;
}


void LauncherContent::toolTipInfos(TQStringList *keys, TQStringList *values)
{
	KService service(fullPath());

	TQString exec = service.exec();
	if (service.terminal())
		exec = i18n("%1 <i>(run in terminal)</i>").arg(exec);

	if (!service.comment().isEmpty() && service.comment() != service.name()) {
		keys->append(i18n("Comment"));
		values->append(service.comment());
	}

	keys->append(i18n("Command"));
	values->append(exec);
}

int LauncherContent::zoneAt(const TQPoint &pos)
{
	return (m_linkDisplay.iconButtonAt(pos) ? 0 : Note::Custom0);
}

TQRect LauncherContent::zoneRect(int zone, const TQPoint &/*pos*/)
{
	TQRect linkRect = m_linkDisplay.iconButtonRect();

	if (zone == Note::Custom0)
		return TQRect(linkRect.width(), 0, note()->width(), note()->height()); // Too wide and height, but it will be clipped by Note::zoneRect()
	else if (zone == Note::Content)
		return linkRect;
	else
		return TQRect();
}

TQString LauncherContent::zoneTip(int zone)
{
	return (zone == Note::Custom0 ? i18n("Launch this application") : TQString());
}

void LauncherContent::setCursor(TQWidget *widget, int zone)
{
	if (zone == Note::Custom0)
		widget->setCursor(TQt::PointingHandCursor);
}


KURL LauncherContent::urlToOpen(bool with)
{
	if (KService(fullPath()).exec().isEmpty())
		return KURL();

	return (with ? KURL() : KURL(fullPath())); // Can open the appliation, but not with another application :-)
}

TQString LauncherContent::messageWhenOpenning(OpenMessage where)
{
	if (KService(fullPath()).exec().isEmpty())
		return i18n("The launcher have no command to run.");

	switch (where) {
		case OpenOne:               return i18n("Launching application...");
		case OpenSeveral:           return i18n("Launching applications...");
		case OpenOneWith:
		case OpenSeveralWith:
		case OpenOneWithDialog:
		case OpenSeveralWithDialog:            // TODO: "Open this application with this file as parameter"?
		default:                    return "";
	}
}

void LauncherContent::setLauncher(const TQString &name, const TQString &icon, const TQString &exec)
{
	m_name = name;
	m_icon = icon;
	m_exec = exec;

	m_linkDisplay.setLink(name, icon, LinkLook::launcherLook, note()->font());
	contentChanged(m_linkDisplay.minWidth());
}

void LauncherContent::exportToHTML(HTMLExporter *exporter, int indent)
{
	TQString spaces;
	TQString fileName = exporter->copyFile(fullPath(), /*createIt=*/true);
	exporter->stream << m_linkDisplay.toHtml(exporter, KURL(exporter->dataFolderName + fileName), "").replace("\n", "\n" + spaces.fill(' ', indent + 1));
}

/** class ColorContent:
 */

const int ColorContent::RECT_MARGIN = 2;

ColorContent::ColorContent(Note *parent, const TQColor &color)
 : NoteContent(parent)
{
	setColor(color);
}

int ColorContent::setWidthAndGetHeight(int /*width*/) // We do not need width because we can't word-break, and width is always >= minWidth()
{
	// FIXME: Duplicate from setColor():
	TQRect textRect = TQFontMetrics(note()->font()).boundingRect(color().name());
	int rectHeight = (textRect.height() + 2)*3/2;
	return rectHeight;
}

void ColorContent::paint(TQPainter *painter, int width, int height, const TQColorGroup &colorGroup, bool /*isDefaultColor*/, bool /*isSelected*/, bool /*isHovered*/)
{
	// FIXME: Duplicate from setColor():
	TQRect textRect = TQFontMetrics(note()->font()).boundingRect(color().name());
	int rectHeight = (textRect.height() + 2)*3/2;
	int rectWidth  = rectHeight * 14 / 10; // 1.4 times the height, like A4 papers.

	// FIXME: Duplicate from CommonColorSelector::drawColorRect:
	// Fill:
	painter->fillRect(1, 1, rectWidth - 2, rectHeight - 2, color());
	// Stroke:
	TQColor stroke = color().dark(125);
	painter->setPen(stroke);
	painter->drawLine(1,             0,              rectWidth - 2, 0);
	painter->drawLine(0,             1,              0,             rectHeight - 2);
	painter->drawLine(1,             rectHeight - 1, rectWidth - 2, rectHeight - 1);
	painter->drawLine(rectWidth - 1, 1,              rectWidth - 1, rectHeight - 2);
	// Round corners:
	painter->setPen(Tools::mixColor(color(), stroke));
	painter->drawPoint(1,             1);
	painter->drawPoint(1,             rectHeight - 2);
	painter->drawPoint(rectWidth - 2, rectHeight - 2);
	painter->drawPoint(rectWidth - 2, 1);

	// Draw the text:
	painter->setFont(note()->font());
	painter->setPen(colorGroup.text());
	painter->drawText(rectWidth + RECT_MARGIN, 0, width - rectWidth - RECT_MARGIN, height, TQt::AlignAuto | TQt::AlignVCenter, color().name());
}

void ColorContent::saveToNode(TQDomDocument &doc, TQDomElement &content)
{
	TQDomText textNode = doc.createTextNode(color().name());
	content.appendChild(textNode);
}


void ColorContent::toolTipInfos(TQStringList *keys, TQStringList *values)
{
	int hue, saturation, value;
	m_color.getHsv(&hue, &saturation, &value);

	keys->append(i18n("RGB Colorspace: Red/Green/Blue", "RGB"));
	values->append(i18n("<i>Red</i>: %1, <i>Green</i>: %2, <i>Blue</i>: %3,").arg(TQString::number(m_color.red()), TQString::number(m_color.green()), TQString::number(m_color.blue())));

	keys->append(i18n("HSV Colorspace: Hue/Saturation/Value", "HSV"));
	values->append(i18n("<i>Hue</i>: %1, <i>Saturation</i>: %2, <i>Value</i>: %3,").arg(TQString::number(hue), TQString::number(saturation), TQString::number(value)));

	static TQString cssColors[] = {
		"aqua",    "00ffff",
		"black",   "000000",
		"blue",    "0000ff",
		"fuchsia", "ff00ff",
		"gray",    "808080",
		"green",   "008000",
		"lime",    "00ff00",
		"maroon",  "800000",
		"navy",    "000080",
		"olive",   "808000",
		"purple",  "800080",
		"red",     "ff0000",
		"silver",  "c0c0c0",
		"teal",    "008080",
		"white",   "ffffff",
		"yellow",  "ffff00"
	};

	static TQString cssExtendedColors[] = {
		"aliceblue",            "f0f8ff",
		"antiquewhite",         "faebd7",
		"aquamarine",           "7fffd4",
		"azure",                "f0ffff",
		"beige",                "f5f5dc",
		"bisque",               "ffe4c4",
		"blanchedalmond",       "ffebcd",
		"blueviolet",           "8a2be2",
		"brown",                "a52a2a",
		"burlywood",            "deb887",
		"cadetblue",            "5f9ea0",
		"chartreuse",           "7fff00",
		"chocolate",            "d2691e",
		"coral",                "ff7f50",
		"cornflowerblue",       "6495ed",
		"cornsilk",             "fff8dc",
		"crimson",              "dc1436",
		"cyan",                 "00ffff",
		"darkblue",             "00008b",
		"darkcyan",             "008b8b",
		"darkgoldenrod",        "b8860b",
		"darkgray",             "a9a9a9",
		"darkgreen",            "006400",
		"darkkhaki",            "bdb76b",
		"darkmagenta",          "8b008b",
		"darkolivegreen",       "556b2f",
		"darkorange",           "ff8c00",
		"darkorchid",           "9932cc",
		"darkred",              "8b0000",
		"darksalmon",           "e9967a",
		"darkseagreen",         "8fbc8f",
		"darkslateblue",        "483d8b",
		"darkslategray",        "2f4f4f",
		"darkturquoise",        "00ced1",
		"darkviolet",           "9400d3",
		"deeppink",             "ff1493",
		"deepskyblue",          "00bfff",
		"dimgray",              "696969",
		"dodgerblue",           "1e90ff",
		"firebrick",            "b22222",
		"floralwhite",          "fffaf0",
		"forestgreen",          "228b22",
		"gainsboro",            "dcdcdc",
		"ghostwhite",           "f8f8ff",
		"gold",                 "ffd700",
		"goldenrod",            "daa520",
		"greenyellow",          "adff2f",
		"honeydew",             "f0fff0",
		"hotpink",              "ff69b4",
		"indianred",            "cd5c5c",
		"indigo",               "4b0082",
		"ivory",                "fffff0",
		"khaki",                "f0e68c",
		"lavender",             "e6e6fa",
		"lavenderblush",        "fff0f5",
		"lawngreen",            "7cfc00",
		"lemonchiffon",         "fffacd",
		"lightblue",            "add8e6",
		"lightcoral",           "f08080",
		"lightcyan",            "e0ffff",
		"lightgoldenrodyellow", "fafad2",
		"lightgreen",           "90ee90",
		"lightgrey",            "d3d3d3",
		"lightpink",            "ffb6c1",
		"lightsalmon",          "ffa07a",
		"lightseagreen",        "20b2aa",
		"lightskyblue",         "87cefa",
		"lightslategray",       "778899",
		"lightsteelblue",       "b0c4de",
		"lightyellow",          "ffffe0",
		"limegreen",            "32cd32",
		"linen",                "faf0e6",
		"magenta",              "ff00ff",
		"mediumaquamarine",     "66cdaa",
		"mediumblue",           "0000cd",
		"mediumorchid",         "ba55d3",
		"mediumpurple",         "9370db",
		"mediumseagreen",       "3cb371",
		"mediumslateblue",      "7b68ee",
		"mediumspringgreen",    "00fa9a",
		"mediumturquoise",      "48d1cc",
		"mediumvioletred",      "c71585",
		"midnightblue",         "191970",
		"mintcream",            "f5fffa",
		"mistyrose",            "ffe4e1",
		"tqmoccasin",             "ffe4b5",
		"navajowhite",          "ffdead",
		"oldlace",              "fdf5e6",
		"olivedrab",            "6b8e23",
		"orange",               "ffa500",
		"orangered",            "ff4500",
		"orchid",               "da70d6",
		"palegoldenrod",        "eee8aa",
		"palegreen",            "98fb98",
		"paleturquoise",        "afeeee",
		"palevioletred",        "db7093",
		"papayawhip",           "ffefd5",
		"peachpuff",            "ffdab9",
		"peru",                 "cd853f",
		"pink",                 "ffc0cb",
		"plum",                 "dda0dd",
		"powderblue",           "b0e0e6",
		"rosybrown",            "bc8f8f",
		"royalblue",            "4169e1",
		"saddlebrown",          "8b4513",
		"salmon",               "fa8072",
		"sandybrown",           "f4a460",
		"seagreen",             "2e8b57",
		"seashell",             "fff5ee",
		"sienna",               "a0522d",
		"skyblue",              "87ceeb",
		"slateblue",            "6a5acd",
		"slategray",            "708090",
		"snow",                 "fffafa",
		"springgreen",          "00ff7f",
		"steelblue",            "4682b4",
		"tan",                  "d2b48c",
		"thistle",              "d8bfd8",
		"tomato",               "ff6347",
		"turquoise",            "40e0d0",
		"violet",               "ee82ee",
		"wheat",                "f5deb3",
		"whitesmoke",           "f5f5f5",
		"yellowgreen",          "9acd32"
	};

	TQString colorHex = color().name().mid(1); // Take the hexadecimal name of the color, without the '#'.

	bool cssColorFound = false;
	for (int i = 0; i < 2*16; i += 2) {
		if (colorHex == cssColors[i+1]) {
			keys->append(i18n("CSS Color Name"));
			values->append(cssColors[i]);
			cssColorFound = true;
			break;
		}
	}

	if (!cssColorFound)
		for (int i = 0; i < 2*124; i += 2) {
			if (colorHex == cssExtendedColors[i+1]) {
				keys->append(i18n("CSS Extended Color Name"));
				values->append(cssExtendedColors[i]);
				break;
			}
		}

	keys->append(i18n("Is Web Color"));
	values->append(Tools::isWebColor(color()) ? i18n("Yes") : i18n("No"));

}

void ColorContent::setColor(const TQColor &color)
{
	m_color = color;

	TQRect textRect = TQFontMetrics(note()->font()).boundingRect(color.name());
	int rectHeight = (textRect.height() + 2)*3/2;
	int rectWidth  = rectHeight * 14 / 10; // 1.4 times the height, like A4 papers.
	contentChanged(rectWidth + RECT_MARGIN + textRect.width() + RECT_MARGIN); // The second RECT_MARGIN is because textRect.width() is too short. I done a bug? Can't figure out.
}

void ColorContent::addAlternateDragObjects(KMultipleDrag *dragObject)
{
	dragObject->addDragObject( new TQColorDrag(color()) );

//	addDragObject(new KColorDrag( note->color(), 0 ));
//	addDragObject(new TQTextDrag( note->color().name(), 0 ));

/*	// Creata and add the TQDragObject:
	storedDrag = new TQStoredDrag("application/x-color");
	storedDrag->setEncodedData(*array);
	dragObject->addDragObject(storedDrag);
	delete array;*/
}

void ColorContent::exportToHTML(HTMLExporter *exporter, int /*indent*/)
{
	// FIXME: Duplicate from setColor(): TODO: rectSize()
	TQRect textRect = TQFontMetrics(note()->font()).boundingRect(color().name());
	int rectHeight = (textRect.height() + 2)*3/2;
	int rectWidth  = rectHeight * 14 / 10; // 1.4 times the height, like A4 papers.

	TQString fileName = /*Tools::fileNameForNewFile(*/TQString(TQString("color_%1.png").arg(color().name()).lower().mid(1))/*, exportData.iconsFolderPath)*/;
	TQString fullPath = exporter->iconsFolderPath + fileName;
	TQPixmap colorIcon = KColorCombo2::colorRectPixmap(color(), /*isDefault=*/false, rectWidth, rectHeight);
	colorIcon.save(fullPath, "PNG");
	TQString iconHtml = TQString("<img src=\"%1\" width=\"%2\" height=\"%3\" alt=\"\">")
	                   .arg(exporter->iconsFolderName + fileName, TQString::number(colorIcon.width()), TQString::number(colorIcon.height()));

	exporter->stream << iconHtml + " " + color().name();
}



/** class UnknownContent:
 */

const int UnknownContent::DECORATION_MARGIN = 2;

UnknownContent::UnknownContent(Note *parent, const TQString &fileName)
 : NoteContent(parent, fileName)
{
	basket()->addWatchedFile(fullPath());
	loadFromFile(/*lazyLoad=*/false);
}

int UnknownContent::setWidthAndGetHeight(int width)
{
	width -= 1;
	TQRect textRect = TQFontMetrics(note()->font()).boundingRect(0, 0, width, 500000, TQt::AlignAuto | TQt::AlignTop | TQt::WordBreak, m_mimeTypes);
	return DECORATION_MARGIN + textRect.height() + DECORATION_MARGIN;
}

// TODO: Move this function from note.cpp to class Tools:
extern void drawGradient( TQPainter *p, const TQColor &colorTop, const TQColor & colorBottom,
						  int x, int y, int w, int h,
						  bool sunken, bool horz, bool flat  ); /*const*/

void UnknownContent::paint(TQPainter *painter, int width, int height, const TQColorGroup &colorGroup, bool /*isDefaultColor*/, bool /*isSelected*/, bool /*isHovered*/)
{
	width -= 1;
	painter->setPen(colorGroup.text());

	// FIXME: Duplicate from ColorContent::paint() and CommonColorSelector::drawColorRect:
	// Fill with gradient:
	drawGradient(painter, colorGroup.background(), colorGroup.background().dark(110), 1, 1, width - 2, height - 2, /*sunken=*/false, /*horz=*/true, /*flat=*/false);
	// Stroke:
	TQColor stroke = Tools::mixColor(colorGroup.background(), colorGroup.text());
	painter->setPen(stroke);
	painter->drawLine(1,         0,          width - 2, 0);
	painter->drawLine(0,         1,          0,         height - 2);
	painter->drawLine(1,         height - 1, width - 2, height - 1);
	painter->drawLine(width - 1, 1,          width - 1, height - 2);
	// Round corners:
	painter->setPen(Tools::mixColor(colorGroup.background(), stroke));
	painter->drawPoint(1,         1);
	painter->drawPoint(1,         height - 2);
	painter->drawPoint(width - 2, height - 2);
	painter->drawPoint(width - 2, 1);

	painter->setPen(colorGroup.text());
	painter->drawText(DECORATION_MARGIN, DECORATION_MARGIN, width - 2*DECORATION_MARGIN, height - 2*DECORATION_MARGIN,
	                  TQt::AlignAuto | TQt::AlignVCenter | TQt::WordBreak, m_mimeTypes);
}

bool UnknownContent::loadFromFile(bool /*lazyLoad*/)
{
	DEBUG_WIN << "Loading UnknownContent From " + basket()->folderName() + fileName();
	TQFile file(fullPath());
	if (file.open(IO_ReadOnly)) {
		TQDataStream stream(&file);
		TQString line;
		m_mimeTypes = "";
		// Get the MIME-types names:
		do {
			if (!stream.atEnd()) {
				stream >> line;
				if (!line.isEmpty()) {
					if (m_mimeTypes.isEmpty())
						m_mimeTypes += line;
					else
						m_mimeTypes += TQString("\n") + line;
				}
			}
		} while (!line.isEmpty() && !stream.atEnd());
		file.close();
	}

	TQRect textRect = TQFontMetrics(note()->font()).boundingRect(0, 0, /*width=*/1, 500000, TQt::AlignAuto | TQt::AlignTop | TQt::WordBreak, m_mimeTypes);
	contentChanged(DECORATION_MARGIN + textRect.width() + DECORATION_MARGIN + 1);
	return true;
}

void UnknownContent::addAlternateDragObjects(KMultipleDrag *dragObject)
{
	TQFile file(fullPath());
	if (file.open(IO_ReadOnly)) {
		TQDataStream stream(&file);
		// Get the MIME types names:
		TQValueList<TQString> mimes;
		TQString line;
		do {
			if (!stream.atEnd()) {
				stream >> line;
				if (!line.isEmpty())
					mimes.append(line);
			}
		} while (!line.isEmpty() && !stream.atEnd());
		// Add the streams:
		TQ_UINT64     size; // TODO: It was TQ_UINT32 in version 0.5.0 !
		TQByteArray  *array;
		TQStoredDrag *storedDrag;
		for (uint i = 0; i < mimes.count(); ++i) {
			// Get the size:
			stream >> size;
			// Allocate memory to retreive size bytes and store them:
			array = new TQByteArray(size);
			stream.readRawBytes(array->data(), size);
			// Creata and add the TQDragObject:
			storedDrag = new TQStoredDrag(*(mimes.at(i)));
			storedDrag->setEncodedData(*array);
			dragObject->addDragObject(storedDrag);
			delete array; // FIXME: Should we?
		}
		file.close();
	}
}

void UnknownContent::exportToHTML(HTMLExporter *exporter, int indent)
{
	TQString spaces;
	exporter->stream << "<div class=\"unknown\">" << mimeTypes().replace("\n", "\n" + spaces.fill(' ', indent + 1 + 1)) << "</div>";
}




void NoteFactory__loadNode(const TQDomElement &content, const TQString &lowerTypeName, Note *parent, bool lazyLoad)
{
	if        (lowerTypeName == "text")      new TextContent(      parent, content.text(), lazyLoad );
	else if   (lowerTypeName == "html")      new HtmlContent(      parent, content.text(), lazyLoad );
	else if   (lowerTypeName == "image")     new ImageContent(     parent, content.text(), lazyLoad );
	else if   (lowerTypeName == "animation") new AnimationContent( parent, content.text(), lazyLoad );
	else if   (lowerTypeName == "sound")     new SoundContent(     parent, content.text()           );
	else if   (lowerTypeName == "file")      new FileContent(      parent, content.text()           );
	else if   (lowerTypeName == "link") {
		bool autoTitle = content.attribute("title") == content.text();
		bool autoIcon  = content.attribute("icon")  == NoteFactory::iconForURL(KURL(content.text()));
		autoTitle = XMLWork::trueOrFalse( content.attribute("autoTitle"), autoTitle);
		autoIcon  = XMLWork::trueOrFalse( content.attribute("autoIcon"),  autoIcon );
		new LinkContent( parent, KURL(content.text()), content.attribute("title"), content.attribute("icon"), autoTitle, autoIcon );
	} else if (lowerTypeName == "launcher")  new LauncherContent(  parent, content.text()         );
	else if   (lowerTypeName == "color")     new ColorContent(     parent, TQColor(content.text()) );
	else if   (lowerTypeName == "unknown")   new UnknownContent(   parent, content.text()         );
}

#include "notecontent.moc"