1
/***************************************************************************
2
* Copyright (C) 2003 by S�astien Laot *
5
* This program is free software; you can redistribute it and/or modify *
6
* it under the terms of the GNU General Public License as published by *
7
* the Free Software Foundation; either version 2 of the License, or *
8
* (at your option) any later version. *
10
* This program is distributed in the hope that it will be useful, *
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13
* GNU General Public License for more details. *
15
* You should have received a copy of the GNU General Public License *
16
* along with this program; if not, write to the *
17
* Free Software Foundation, Inc., *
18
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19
***************************************************************************/
25
#include <qstylesheet.h>
26
#include <qfontmetrics.h>
29
#include <qstringlist.h>
31
#include <ktextedit.h>
33
#include <kcolordialog.h>
34
#include <kmessagebox.h>
36
#include <kglobalsettings.h>
37
#include <kpixmapeffect.h>
39
#include <kurifilter.h>
40
//#include <kstringhandler.h>
41
#include <kfilemetainfo.h>
42
#include <qdatetime.h>
43
#include <kmultipledrag.h>
45
#include <qfileinfo.h>
46
//#include <kio/kfileitem.h>
47
#include <kfileitem.h>
48
#include <kio/previewjob.h>
49
#include <kio/global.h>
53
#include "notecontent.h"
61
#include "notefactory.h"
62
#include "linklabel.h"
65
#include "focusedwidgets.h"
66
#include "debugwindow.h"
67
#include "kcolorcombo2.h"
68
#include "htmlexporter.h"
72
#include <arts/kplayobject.h>
73
#include <arts/kplayobjectfactory.h>
74
#include <arts/kartsserver.h>
75
#include <arts/kartsdispatcher.h>
78
/** class NoteContent:
81
const int NoteContent::FEEDBACK_DARKING = 105;
83
NoteContent::NoteContent(Note *parent, const QString &fileName)
86
parent->setContent(this);
87
setFileName(fileName);
90
void NoteContent::saveToNode(QDomDocument &doc, QDomElement &content)
93
QDomText textNode = doc.createTextNode(fileName());
94
content.appendChild(textNode);
98
QRect NoteContent::zoneRect(int zone, const QPoint &/*pos*/)
100
if (zone == Note::Content)
101
return QRect(0, 0, note()->width(), note()->height()); // Too wide and height, but it will be clipped by Note::zoneRect()
106
KURL NoteContent::urlToOpen(bool /*with*/)
108
return (useFile() ? KURL(fullPath()) : KURL());
111
void NoteContent::setFileName(const QString &fileName)
113
m_fileName = fileName;
116
bool NoteContent::trySetFileName(const QString &fileName)
118
if (useFile() && fileName != m_fileName) {
119
QString newFileName = Tools::fileNameForNewFile(fileName, basket()->fullPath());
121
dir.rename(fullPath(), basket()->fullPathForFileName(newFileName));
125
return false; // !useFile() or unsuccesful rename
128
QString NoteContent::fullPath()
130
if (note() && useFile())
131
return note()->fullPath();
136
void NoteContent::contentChanged(int newMinWidth)
138
m_minWidth = newMinWidth;
140
// note()->unbufferize();
141
note()->requestRelayout(); // TODO: It should re-set the width! m_width = 0 ? contentChanged: setWidth, geteight, if size havent changed, only repaint and not relayout
145
Basket* NoteContent::basket()
148
return note()->basket();
153
void NoteContent::setEdited()
155
note()->setLastModificationDate(QDateTime::currentDateTime());
159
/** All the Content Classes:
162
NoteType::Id TextContent::type() { return NoteType::Text; }
163
NoteType::Id HtmlContent::type() { return NoteType::Html; }
164
NoteType::Id ImageContent::type() { return NoteType::Image; }
165
NoteType::Id AnimationContent::type() { return NoteType::Animation; }
166
NoteType::Id SoundContent::type() { return NoteType::Sound; }
167
NoteType::Id FileContent::type() { return NoteType::File; }
168
NoteType::Id LinkContent::type() { return NoteType::Link; }
169
NoteType::Id LauncherContent::type() { return NoteType::Launcher; }
170
NoteType::Id ColorContent::type() { return NoteType::Color; }
171
NoteType::Id UnknownContent::type() { return NoteType::Unknown; }
173
QString TextContent::typeName() { return i18n("Plain Text"); }
174
QString HtmlContent::typeName() { return i18n("Text"); }
175
QString ImageContent::typeName() { return i18n("Image"); }
176
QString AnimationContent::typeName() { return i18n("Animation"); }
177
QString SoundContent::typeName() { return i18n("Sound"); }
178
QString FileContent::typeName() { return i18n("File"); }
179
QString LinkContent::typeName() { return i18n("Link"); }
180
QString LauncherContent::typeName() { return i18n("Launcher"); }
181
QString ColorContent::typeName() { return i18n("Color"); }
182
QString UnknownContent::typeName() { return i18n("Unknown"); }
184
QString TextContent::lowerTypeName() { return "text"; }
185
QString HtmlContent::lowerTypeName() { return "html"; }
186
QString ImageContent::lowerTypeName() { return "image"; }
187
QString AnimationContent::lowerTypeName() { return "animation"; }
188
QString SoundContent::lowerTypeName() { return "sound"; }
189
QString FileContent::lowerTypeName() { return "file"; }
190
QString LinkContent::lowerTypeName() { return "link"; }
191
QString LauncherContent::lowerTypeName() { return "launcher"; }
192
QString ColorContent::lowerTypeName() { return "color"; }
193
QString UnknownContent::lowerTypeName() { return "unknown"; }
195
QString NoteContent::toText(const QString &cuttedFullPath)
197
return (cuttedFullPath.isEmpty() ? fullPath() : cuttedFullPath);
200
QString TextContent::toText(const QString &/*cuttedFullPath*/) { return text(); }
201
QString HtmlContent::toText(const QString &/*cuttedFullPath*/) { return Tools::htmlToText(html()); }
202
QString LinkContent::toText(const QString &/*cuttedFullPath*/)
205
return url().prettyURL();
206
else if (title().isEmpty() && url().isEmpty())
208
else if (url().isEmpty())
210
else if (title().isEmpty())
211
return url().prettyURL();
213
return QString("%1 <%2>").arg(title(), url().prettyURL());
215
QString ColorContent::toText(const QString &/*cuttedFullPath*/) { return color().name(); }
216
QString UnknownContent::toText(const QString &/*cuttedFullPath*/) { return ""; }
218
// TODO: If imageName.isEmpty() return fullPath() because it's for external use, else return fileName() because it's to display in a tooltip
219
QString TextContent::toHtml(const QString &/*imageName*/, const QString &/*cuttedFullPath*/)
220
{ return Tools::textToHTMLWithoutP(text()); }
222
QString HtmlContent::toHtml(const QString &/*imageName*/, const QString &/*cuttedFullPath*/)
223
{ return Tools::htmlToParagraph(html()); }
225
QString ImageContent::toHtml(const QString &/*imageName*/, const QString &cuttedFullPath)
226
{ return QString("<img src=\"%1\">").arg(cuttedFullPath.isEmpty() ? fullPath() : cuttedFullPath); }
228
QString AnimationContent::toHtml(const QString &/*imageName*/, const QString &cuttedFullPath)
229
{ return QString("<img src=\"%1\">").arg(cuttedFullPath.isEmpty() ? fullPath() : cuttedFullPath); }
231
QString SoundContent::toHtml(const QString &/*imageName*/, const QString &cuttedFullPath)
232
{ return QString("<a href=\"%1\">%2</a>").arg((cuttedFullPath.isEmpty() ? fullPath() : cuttedFullPath), fileName()); } // With the icon?
234
QString FileContent::toHtml(const QString &/*imageName*/, const QString &cuttedFullPath)
235
{ return QString("<a href=\"%1\">%2</a>").arg((cuttedFullPath.isEmpty() ? fullPath() : cuttedFullPath), fileName()); } // With the icon?
237
QString LinkContent::toHtml(const QString &/*imageName*/, const QString &/*cuttedFullPath*/)
238
{ return QString("<a href=\"%1\">%2</a>").arg(url().prettyURL(), title()); } // With the icon?
240
QString LauncherContent::toHtml(const QString &/*imageName*/, const QString &cuttedFullPath)
241
{ return QString("<a href=\"%1\">%2</a>").arg((cuttedFullPath.isEmpty() ? fullPath() : cuttedFullPath), name()); } // With the icon?
243
QString ColorContent::toHtml(const QString &/*imageName*/, const QString &/*cuttedFullPath*/)
244
{ return QString("<span style=\"color: %1\">%2</span>").arg(color().name(), color().name()); }
246
QString UnknownContent::toHtml(const QString &/*imageName*/, const QString &/*cuttedFullPath*/)
249
QPixmap ImageContent::toPixmap() { return pixmap(); }
250
QPixmap AnimationContent::toPixmap() { return movie().framePixmap(); }
252
void NoteContent::toLink(KURL *url, QString *title, const QString &cuttedFullPath)
255
*url = KURL(cuttedFullPath.isEmpty() ? fullPath() : cuttedFullPath);
256
*title = (cuttedFullPath.isEmpty() ? fullPath() : cuttedFullPath);
262
void LinkContent::toLink(KURL *url, QString *title, const QString &/*cuttedFullPath*/)
265
*title = this->title();
268
void LauncherContent::toLink(KURL *url, QString *title, const QString &cuttedFullPath)
270
*url = KURL(cuttedFullPath.isEmpty() ? fullPath() : cuttedFullPath);
273
void UnknownContent::toLink(KURL *url, QString *title, const QString &/*cuttedFullPath*/)
279
bool TextContent::useFile() { return true; }
280
bool HtmlContent::useFile() { return true; }
281
bool ImageContent::useFile() { return true; }
282
bool AnimationContent::useFile() { return true; }
283
bool SoundContent::useFile() { return true; }
284
bool FileContent::useFile() { return true; }
285
bool LinkContent::useFile() { return false; }
286
bool LauncherContent::useFile() { return true; }
287
bool ColorContent::useFile() { return false; }
288
bool UnknownContent::useFile() { return true; }
290
bool TextContent::canBeSavedAs() { return true; }
291
bool HtmlContent::canBeSavedAs() { return true; }
292
bool ImageContent::canBeSavedAs() { return true; }
293
bool AnimationContent::canBeSavedAs() { return true; }
294
bool SoundContent::canBeSavedAs() { return true; }
295
bool FileContent::canBeSavedAs() { return true; }
296
bool LinkContent::canBeSavedAs() { return true; }
297
bool LauncherContent::canBeSavedAs() { return true; }
298
bool ColorContent::canBeSavedAs() { return false; }
299
bool UnknownContent::canBeSavedAs() { return false; }
301
QString TextContent::saveAsFilters() { return "text/plain"; }
302
QString HtmlContent::saveAsFilters() { return "text/html"; }
303
QString ImageContent::saveAsFilters() { return "image/png"; } // TODO: Offer more types
304
QString AnimationContent::saveAsFilters() { return "image/gif"; } // TODO: MNG...
305
QString SoundContent::saveAsFilters() { return "audio/x-mp3"; } // TODO: OGG...
306
QString FileContent::saveAsFilters() { return "*"; } // TODO: Get MIME type of the url target
307
QString LinkContent::saveAsFilters() { return "*"; } // TODO: idem File + If isDir(): return
308
QString LauncherContent::saveAsFilters() { return "application/x-desktop"; }
309
QString ColorContent::saveAsFilters() { return ""; }
310
QString UnknownContent::saveAsFilters() { return ""; }
312
bool TextContent::match(const FilterData &data) { return (text().find(data.string, /*index=*/0, /*cs=*/false) != -1); }
313
bool HtmlContent::match(const FilterData &data) { return (m_textEquivalent/*toText("")*/.find(data.string, /*index=*/0, /*cs=*/false) != -1); } //OPTIM_FILTER
314
bool ImageContent::match(const FilterData &/*data*/) { return false; }
315
bool AnimationContent::match(const FilterData &/*data*/) { return false; }
316
bool SoundContent::match(const FilterData &data) { return (fileName().find(data.string, /*index=*/0, /*cs=*/false) != -1); }
317
bool FileContent::match(const FilterData &data) { return (fileName().find(data.string, /*index=*/0, /*cs=*/false) != -1); }
318
bool LinkContent::match(const FilterData &data) { return (title().find(data.string, 0, false) != -1 || url().prettyURL().find(data.string, 0, false) != -1); }
319
bool LauncherContent::match(const FilterData &data) { return (exec().find(data.string, 0, false) != -1 || name().find(data.string, 0, false) != -1); }
320
bool ColorContent::match(const FilterData &data) { return (color().name().find(data.string, /*index=*/0, /*cs=*/false) != -1); }
321
bool UnknownContent::match(const FilterData &data) { return (mimeTypes().find(data.string, /*index=*/0, /*cs=*/false) != -1); }
323
QString TextContent::editToolTipText() { return i18n("Edit this plain text"); }
324
QString HtmlContent::editToolTipText() { return i18n("Edit this text"); }
325
QString ImageContent::editToolTipText() { return i18n("Edit this image"); }
326
QString AnimationContent::editToolTipText() { return i18n("Edit this animation"); }
327
QString SoundContent::editToolTipText() { return i18n("Edit the file name of this sound"); }
328
QString FileContent::editToolTipText() { return i18n("Edit the name of this file"); }
329
QString LinkContent::editToolTipText() { return i18n("Edit this link"); }
330
QString LauncherContent::editToolTipText() { return i18n("Edit this launcher"); }
331
QString ColorContent::editToolTipText() { return i18n("Edit this color"); }
332
QString UnknownContent::editToolTipText() { return i18n("Edit this unknown object"); }
334
QString TextContent::cssClass() { return ""; }
335
QString HtmlContent::cssClass() { return ""; }
336
QString ImageContent::cssClass() { return ""; }
337
QString AnimationContent::cssClass() { return ""; }
338
QString SoundContent::cssClass() { return "sound"; }
339
QString FileContent::cssClass() { return "file"; }
340
QString LinkContent::cssClass() { return (LinkLook::lookForURL(m_url) == LinkLook::localLinkLook ? "local" : "network"); }
341
QString LauncherContent::cssClass() { return "launcher"; }
342
QString ColorContent::cssClass() { return "" ; }
343
QString UnknownContent::cssClass() { return ""; }
345
void TextContent::fontChanged() { setText(text()); }
346
void HtmlContent::fontChanged() { setHtml(html()); }
347
void ImageContent::fontChanged() { setPixmap(pixmap()); }
348
void AnimationContent::fontChanged() { setMovie(movie()); }
349
void FileContent::fontChanged() { setFileName(fileName()); }
350
void LinkContent::fontChanged() { setLink(url(), title(), icon(), autoTitle(), autoIcon()); }
351
void LauncherContent::fontChanged() { setLauncher(name(), icon(), exec()); }
352
void ColorContent::fontChanged() { setColor(color()); }
353
void UnknownContent::fontChanged() { loadFromFile(/*lazyLoad=*/false); } // TODO: Optimize: setMimeTypes()
355
//QString TextContent::customOpenCommand() { return (Settings::isTextUseProg() && ! Settings::textProg().isEmpty() ? Settings::textProg() : QString()); }
356
QString HtmlContent::customOpenCommand() { return (Settings::isHtmlUseProg() && ! Settings::htmlProg().isEmpty() ? Settings::htmlProg() : QString()); }
357
QString ImageContent::customOpenCommand() { return (Settings::isImageUseProg() && ! Settings::imageProg().isEmpty() ? Settings::imageProg() : QString()); }
358
QString AnimationContent::customOpenCommand() { return (Settings::isAnimationUseProg() && ! Settings::animationProg().isEmpty() ? Settings::animationProg() : QString()); }
359
QString SoundContent::customOpenCommand() { return (Settings::isSoundUseProg() && ! Settings::soundProg().isEmpty() ? Settings::soundProg() : QString()); }
361
void LinkContent::serialize(QDataStream &stream) { stream << url() << title() << icon() << (Q_UINT64)autoTitle() << (Q_UINT64)autoIcon(); }
362
void ColorContent::serialize(QDataStream &stream) { stream << color(); }
364
QPixmap TextContent::feedbackPixmap(int width, int height)
366
QRect textRect = QFontMetrics(note()->font()).boundingRect(0, 0, width, height, Qt::AlignAuto | Qt::AlignTop | Qt::WordBreak, text());
367
QPixmap pixmap( QMIN(width, textRect.width()), QMIN(height, textRect.height()) );
368
pixmap.fill(note()->backgroundColor().dark(FEEDBACK_DARKING));
369
QPainter painter(&pixmap);
370
painter.setPen(note()->textColor());
371
painter.setFont(note()->font());
372
painter.drawText(0, 0, pixmap.width(), pixmap.height(), Qt::AlignAuto | Qt::AlignTop | Qt::WordBreak, text());
377
QPixmap HtmlContent::feedbackPixmap(int width, int height)
379
QSimpleRichText richText(html(), note()->font());
380
richText.setWidth(width);
381
QColorGroup colorGroup(basket()->colorGroup());
382
colorGroup.setColor(QColorGroup::Text, note()->textColor());
383
colorGroup.setColor(QColorGroup::Background, note()->backgroundColor().dark(FEEDBACK_DARKING));
384
QPixmap pixmap( QMIN(width, richText.widthUsed()), QMIN(height, richText.height()) );
385
pixmap.fill(note()->backgroundColor().dark(FEEDBACK_DARKING));
386
QPainter painter(&pixmap);
387
painter.setPen(note()->textColor());
388
richText.draw(&painter, 0, 0, QRect(0, 0, pixmap.width(), pixmap.height()), colorGroup);
393
QPixmap ImageContent::feedbackPixmap(int width, int height)
395
if (width >= m_pixmap.width() && height >= m_pixmap.height()) { // Full size
396
if (m_pixmap.hasAlpha()) {
397
QPixmap opaque(m_pixmap.width(), m_pixmap.height());
398
opaque.fill(note()->backgroundColor().dark(FEEDBACK_DARKING));
399
QPainter painter(&opaque);
400
painter.drawPixmap(0, 0, m_pixmap);
405
} else { // Scalled down
406
QImage imageToScale = m_pixmap.convertToImage();
408
pmScaled.convertFromImage(imageToScale./*smoothScale*/scale(width, height, QImage::ScaleMin));
409
if (pmScaled.hasAlpha()) {
410
QPixmap opaque(pmScaled.width(), pmScaled.height());
411
opaque.fill(note()->backgroundColor().dark(FEEDBACK_DARKING));
412
QPainter painter(&opaque);
413
painter.drawPixmap(0, 0, pmScaled);
421
QPixmap AnimationContent::feedbackPixmap(int width, int height)
423
QPixmap pixmap = m_movie.framePixmap();
424
if (width >= pixmap.width() && height >= pixmap.height()) // Full size
426
else { // Scalled down
427
QImage imageToScale = pixmap.convertToImage();
429
pmScaled.convertFromImage(imageToScale./*smoothScale*/scale(width, height, QImage::ScaleMin));
434
QPixmap LinkContent::feedbackPixmap(int width, int height)
436
QColorGroup colorGroup(basket()->colorGroup());
437
colorGroup.setColor(QColorGroup::Text, note()->textColor());
438
colorGroup.setColor(QColorGroup::Background, note()->backgroundColor().dark(FEEDBACK_DARKING));
439
return m_linkDisplay.feedbackPixmap(width, height, colorGroup, /*isDefaultColor=*/note()->textColor() == basket()->textColor());
442
QPixmap ColorContent::feedbackPixmap(int width, int height)
444
// TODO: Duplicate code: make a rect() method!
445
QRect textRect = QFontMetrics(note()->font()).boundingRect(color().name());
446
int rectHeight = (textRect.height() + 2)*3/2;
447
int rectWidth = rectHeight * 14 / 10; // 1.4 times the height, like A4 papers.
449
QColorGroup colorGroup(basket()->colorGroup());
450
colorGroup.setColor(QColorGroup::Text, note()->textColor());
451
colorGroup.setColor(QColorGroup::Background, note()->backgroundColor().dark(FEEDBACK_DARKING));
453
QPixmap pixmap( QMIN(width, rectWidth + RECT_MARGIN + textRect.width() + RECT_MARGIN), QMIN(height, rectHeight) );
454
pixmap.fill(note()->backgroundColor().dark(FEEDBACK_DARKING));
455
QPainter painter(&pixmap);
456
paint(&painter, pixmap.width(), pixmap.height(), colorGroup, false, false, false); // We don't care of the three last boolean parameters.
461
QPixmap FileContent::feedbackPixmap(int width, int height)
463
QColorGroup colorGroup(basket()->colorGroup());
464
colorGroup.setColor(QColorGroup::Text, note()->textColor());
465
colorGroup.setColor(QColorGroup::Background, note()->backgroundColor().dark(FEEDBACK_DARKING));
466
return m_linkDisplay.feedbackPixmap(width, height, colorGroup, /*isDefaultColor=*/note()->textColor() == basket()->textColor());
469
QPixmap LauncherContent::feedbackPixmap(int width, int height)
471
QColorGroup colorGroup(basket()->colorGroup());
472
colorGroup.setColor(QColorGroup::Text, note()->textColor());
473
colorGroup.setColor(QColorGroup::Background, note()->backgroundColor().dark(FEEDBACK_DARKING));
474
return m_linkDisplay.feedbackPixmap(width, height, colorGroup, /*isDefaultColor=*/note()->textColor() == basket()->textColor());
477
QPixmap UnknownContent::feedbackPixmap(int width, int height)
479
QRect textRect = QFontMetrics(note()->font()).boundingRect(0, 0, /*width=*/1, 500000, Qt::AlignAuto | Qt::AlignTop | Qt::WordBreak, m_mimeTypes);
481
QColorGroup colorGroup(basket()->colorGroup());
482
colorGroup.setColor(QColorGroup::Text, note()->textColor());
483
colorGroup.setColor(QColorGroup::Background, note()->backgroundColor().dark(FEEDBACK_DARKING));
485
QPixmap pixmap( QMIN(width, DECORATION_MARGIN + textRect.width() + DECORATION_MARGIN), QMIN(height, DECORATION_MARGIN + textRect.height() + DECORATION_MARGIN) );
486
QPainter painter(&pixmap);
487
paint(&painter, pixmap.width() + 1, pixmap.height(), colorGroup, false, false, false); // We don't care of the three last boolean parameters.
488
painter.setPen(note()->backgroundColor().dark(FEEDBACK_DARKING));
489
painter.drawPoint(0, 0);
490
painter.drawPoint(pixmap.width() - 1, 0);
491
painter.drawPoint(0, pixmap.height() - 1);
492
painter.drawPoint(pixmap.width() - 1, pixmap.height() - 1);
498
/** class TextContent:
501
TextContent::TextContent(Note *parent, const QString &fileName, bool lazyLoad)
502
: NoteContent(parent, fileName), m_simpleRichText(0)
504
basket()->addWatchedFile(fullPath());
505
loadFromFile(lazyLoad);
508
TextContent::~TextContent()
510
delete m_simpleRichText;
513
int TextContent::setWidthAndGetHeight(int width)
515
if (m_simpleRichText) {
517
m_simpleRichText->setWidth(width);
518
return m_simpleRichText->height();
520
return 10; // Lazy loaded
523
void TextContent::paint(QPainter *painter, int width, int height, const QColorGroup &colorGroup, bool /*isDefaultColor*/, bool /*isSelected*/, bool /*isHovered*/)
525
if (m_simpleRichText) {
527
m_simpleRichText->draw(painter, 0, 0, QRect(0, 0, width, height), colorGroup);
531
bool TextContent::loadFromFile(bool lazyLoad)
533
DEBUG_WIN << "Loading TextContent From " + basket()->folderName() + fileName();
536
bool success = basket()->loadFromFile(fullPath(), &content, /*isLocalEncoding=*/true);
539
setText(content, lazyLoad);
541
std::cout << "FAILED TO LOAD TextContent: " << fullPath() << std::endl;
542
setText("", lazyLoad);
543
if (!QFile::exists(fullPath()))
544
saveToFile(); // Reserve the fileName so no new note will have the same name!
549
bool TextContent::finishLazyLoad()
551
int width = (m_simpleRichText ? m_simpleRichText->width() : 1);
552
delete m_simpleRichText;
553
QString html = "<html><head><meta name=\"qrichtext\" content=\"1\" /></head><body>" + Tools::tagURLs(Tools::textToHTML(m_text)); // Don't collapse multiple spaces!
554
m_simpleRichText = new QSimpleRichText(html, note()->font());
555
m_simpleRichText->setWidth(1); // We put a width of 1 pixel, so usedWidth() is egual to the minimum width
556
int minWidth = m_simpleRichText->widthUsed();
557
m_simpleRichText->setWidth(width);
558
contentChanged(minWidth + 1);
563
bool TextContent::saveToFile()
565
return basket()->saveToFile(fullPath(), text(), /*isLocalEncoding=*/true);
568
QString TextContent::linkAt(const QPoint &pos)
570
if (m_simpleRichText)
571
return m_simpleRichText->anchorAt(pos);
573
return ""; // Lazy loaded
577
QString TextContent::messageWhenOpenning(OpenMessage where)
580
case OpenOne: return i18n("Opening plain text...");
581
case OpenSeveral: return i18n("Opening plain texts...");
582
case OpenOneWith: return i18n("Opening plain text with...");
583
case OpenSeveralWith: return i18n("Opening plain texts with...");
584
case OpenOneWithDialog: return i18n("Open plain text with:");
585
case OpenSeveralWithDialog: return i18n("Open plain texts with:");
590
void TextContent::setText(const QString &text, bool lazyLoad)
599
void TextContent::exportToHTML(HTMLExporter *exporter, int indent)
602
QString html = "<html><head><meta name=\"qrichtext\" content=\"1\" /></head><body>" +
603
Tools::tagURLs(Tools::textToHTMLWithoutP(text().replace("\t", " "))); // Don't collapse multiple spaces!
604
exporter->stream << html.replace(" ", " ").replace("\n", "\n" + spaces.fill(' ', indent + 1));
607
/** class HtmlContent:
610
HtmlContent::HtmlContent(Note *parent, const QString &fileName, bool lazyLoad)
611
: NoteContent(parent, fileName), m_simpleRichText(0)
613
basket()->addWatchedFile(fullPath());
614
loadFromFile(lazyLoad);
617
HtmlContent::~HtmlContent()
619
delete m_simpleRichText;
622
int HtmlContent::setWidthAndGetHeight(int width)
624
if (m_simpleRichText) {
626
m_simpleRichText->setWidth(width);
627
return m_simpleRichText->height();
629
return 10; // Lazy loaded
632
void HtmlContent::paint(QPainter *painter, int width, int height, const QColorGroup &colorGroup, bool /*isDefaultColor*/, bool /*isSelected*/, bool /*isHovered*/)
634
if (m_simpleRichText) {
636
m_simpleRichText->draw(painter, 0, 0, QRect(0, 0, width, height), colorGroup);
640
bool HtmlContent::loadFromFile(bool lazyLoad)
642
DEBUG_WIN << "Loading HtmlContent From " + basket()->folderName() + fileName();
645
bool success = basket()->loadFromFile(fullPath(), &content, /*isLocalEncoding=*/true);
648
setHtml(content, lazyLoad);
650
std::cout << "FAILED TO LOAD HtmlContent: " << fullPath() << std::endl;
651
setHtml("", lazyLoad);
652
if (!QFile::exists(fullPath()))
653
saveToFile(); // Reserve the fileName so no new note will have the same name!
658
bool HtmlContent::finishLazyLoad()
660
int width = (m_simpleRichText ? m_simpleRichText->width() : 1);
661
delete m_simpleRichText;
662
m_simpleRichText = new QSimpleRichText(Tools::tagURLs(m_html), note()->font());
663
m_simpleRichText->setWidth(1); // We put a width of 1 pixel, so usedWidth() is egual to the minimum width
664
int minWidth = m_simpleRichText->widthUsed();
665
m_simpleRichText->setWidth(width);
666
contentChanged(minWidth + 1);
671
bool HtmlContent::saveToFile()
673
return basket()->saveToFile(fullPath(), html(), /*isLocalEncoding=*/true);
676
QString HtmlContent::linkAt(const QPoint &pos)
678
if (m_simpleRichText)
679
return m_simpleRichText->anchorAt(pos);
681
return ""; // Lazy loaded
685
QString HtmlContent::messageWhenOpenning(OpenMessage where)
688
case OpenOne: return i18n("Opening text...");
689
case OpenSeveral: return i18n("Opening texts...");
690
case OpenOneWith: return i18n("Opening text with...");
691
case OpenSeveralWith: return i18n("Opening texts with...");
692
case OpenOneWithDialog: return i18n("Open text with:");
693
case OpenSeveralWithDialog: return i18n("Open texts with:");
698
void HtmlContent::setHtml(const QString &html, bool lazyLoad)
701
m_textEquivalent = toText(""); //OPTIM_FILTER
708
void HtmlContent::exportToHTML(HTMLExporter *exporter, int indent)
711
exporter->stream << Tools::htmlToParagraph(Tools::tagURLs(html().replace("\t", " ")))
712
.replace(" ", " ")
713
.replace("\n", "\n" + spaces.fill(' ', indent + 1));
716
/** class ImageContent:
719
ImageContent::ImageContent(Note *parent, const QString &fileName, bool lazyLoad)
720
: NoteContent(parent, fileName), m_format(0)
722
basket()->addWatchedFile(fullPath());
723
loadFromFile(lazyLoad);
726
int ImageContent::setWidthAndGetHeight(int width)
729
// Don't store width: we will get it on paint!
730
if (width >= m_pixmap.width()) // Full size
731
return m_pixmap.height();
732
else { // Scalled down
733
double height = m_pixmap.height() * (double)width / m_pixmap.width();
734
return int((double)(int)height <= (height - 0.5) ? height + 1 : height);
738
void ImageContent::paint(QPainter *painter, int width, int /*height*/, const QColorGroup &/*colorGroup*/, bool /*isDefaultColor*/, bool /*isSelected*/, bool /*isHovered*/)
741
// KPixmap pixmap = m_pixmap;
742
// if (note()->isSelected())
743
// pixmap = KPixmapEffect::selectedPixmap(m_pixmap, KGlobalSettings::highlightColor());
745
if (width >= m_pixmap.width()) // Full size
746
painter->drawPixmap(0, 0, m_pixmap);
747
else { // Scalled down
748
double scale = ((double)width) / m_pixmap.width();
749
painter->scale(scale, scale);
750
painter->drawPixmap(0, 0, m_pixmap); // TODO: Smooth !!!
754
bool ImageContent::loadFromFile(bool lazyLoad)
759
return finishLazyLoad();
762
bool ImageContent::finishLazyLoad()
764
DEBUG_WIN << "Loading ImageContent From " + basket()->folderName() + fileName();
768
if (basket()->loadFromFile(fullPath(), &content))
770
QBuffer buffer(content);
772
buffer.open(IO_ReadOnly);
773
m_format = (char* /* from const char* */)QImageIO::imageFormat(&buffer); // See QImageIO to know what formats can be supported.
776
m_pixmap.loadFromData(content);
782
std::cout << "FAILED TO LOAD ImageContent: " << fullPath() << std::endl;
783
m_format = (char*)"PNG"; // If the image is set later, it should be saved without destruction, so we use PNG by default.
784
m_pixmap.resize(1, 1); // Create a 1x1 pixels image instead of an undefined one.
786
m_pixmap.setMask(m_pixmap.createHeuristicMask());
788
if (!QFile::exists(fullPath()))
789
saveToFile(); // Reserve the fileName so no new note will have the same name!
793
bool ImageContent::saveToFile()
798
buffer.open(IO_WriteOnly);
799
m_pixmap.save(&buffer, m_format);
800
return basket()->saveToFile(fullPath(), ba);
804
void ImageContent::toolTipInfos(QStringList *keys, QStringList *values)
806
keys->append(i18n("Size"));
807
values->append(i18n("%1 by %2 pixels").arg(QString::number(m_pixmap.width()), QString::number(m_pixmap.height())));
810
QString ImageContent::messageWhenOpenning(OpenMessage where)
813
case OpenOne: return i18n("Opening image...");
814
case OpenSeveral: return i18n("Opening images...");
815
case OpenOneWith: return i18n("Opening image with...");
816
case OpenSeveralWith: return i18n("Opening images with...");
817
case OpenOneWithDialog: return i18n("Open image with:");
818
case OpenSeveralWithDialog: return i18n("Open images with:");
823
void ImageContent::setPixmap(const QPixmap &pixmap)
826
// Since it's scalled, the height is always greater or equal to the size of the tag emblems (16)
827
contentChanged(16 + 1); // TODO: always good? I don't think...
830
void ImageContent::exportToHTML(HTMLExporter *exporter, int /*indent*/)
832
int width = m_pixmap.width();
833
int height = m_pixmap.height();
834
int contentWidth = note()->width() - note()->contentX() - 1 - Note::NOTE_MARGIN;
836
QString imageName = exporter->copyFile(fullPath(), /*createIt=*/true);
838
if (contentWidth <= m_pixmap.width()) { // Scalled down
839
double scale = ((double)contentWidth) / m_pixmap.width();
840
width = (int)(m_pixmap.width() * scale);
841
height = (int)(m_pixmap.height() * scale);
842
exporter->stream << "<a href=\"" << exporter->dataFolderName << imageName << "\" title=\"" << i18n("Click for full size view") << "\">";
845
exporter->stream << "<img src=\"" << exporter->dataFolderName << imageName
846
<< "\" width=\"" << width << "\" height=\"" << height << "\" alt=\"\">";
848
if (contentWidth <= m_pixmap.width()) // Scalled down
849
exporter->stream << "</a>";
852
/** class AnimationContent:
855
int AnimationContent::INVALID_STATUS = -100;
857
AnimationContent::AnimationContent(Note *parent, const QString &fileName, bool lazyLoad)
858
: NoteContent(parent, fileName), m_oldStatus(INVALID_STATUS)
860
basket()->addWatchedFile(fullPath());
861
loadFromFile(lazyLoad);
864
int AnimationContent::setWidthAndGetHeight(int /*width*/)
867
return m_movie.framePixmap().height() ; // TODO!!!
870
void AnimationContent::paint(QPainter *painter, int width, int /*height*/, const QColorGroup &/*colorGroup*/, bool /*isDefaultColor*/, bool /*isSelected*/, bool /*isHovered*/)
873
// DEBUG_WIN << "AnimationContent::paint()";
874
const QPixmap &frame = m_movie.framePixmap();
875
if (width >= frame.width()) // Full size
876
painter->drawPixmap(0, 0, frame);
878
painter->drawPixmap(0, 0, frame); // TODO: Scall down
881
bool AnimationContent::loadFromFile(bool lazyLoad)
886
return finishLazyLoad();
889
bool AnimationContent::finishLazyLoad()
891
DEBUG_WIN << "Loading MovieContent From " + basket()->folderName() + fileName();
892
// return setMovie(QMovie(fullPath()));
894
bool success = false;
896
if (basket()->loadFromFile(fullPath(), &content))
897
success = setMovie(QMovie(content, content.size()));
903
bool AnimationContent::saveToFile()
910
QString AnimationContent::messageWhenOpenning(OpenMessage where)
913
case OpenOne: return i18n("Opening animation...");
914
case OpenSeveral: return i18n("Opening animations...");
915
case OpenOneWith: return i18n("Opening animation with...");
916
case OpenSeveralWith: return i18n("Opening animations with...");
917
case OpenOneWithDialog: return i18n("Open animation with:");
918
case OpenSeveralWithDialog: return i18n("Open animations with:");
923
bool AnimationContent::setMovie(const QMovie &movie)
925
if (!m_movie.isNull()) {
930
m_movie.connectUpdate( this, SLOT(movieUpdated(const QRect&)) );
931
m_movie.connectResize( this, SLOT(movieResized(const QSize&)) );
932
m_movie.connectStatus( this, SLOT(movieStatus(int)) );
933
contentChanged( m_movie.framePixmap().width() + 1 ); // TODO
937
void AnimationContent::movieUpdated(const QRect&)
939
note()->unbufferize();
943
void AnimationContent::movieResized(const QSize&)
945
note()->requestRelayout(); // ?
948
/** When a user drop a .gif file, for instance, we don't know if it is an image
949
* or an animtion (gif file contain multiple images).
950
* To determin that, we assume this is an animation and count the number of images.
951
* QMovie send, in this order:
952
* - For a unique image: QMovie::EndOfFrame, QMovie::EndOfLoop, QMovie::EndOfMovie.
953
* - For animation: QMovie::EndOfFrame... (for each image), QMovie::EndOfLoop,
954
* and it then restart that for each loop.
956
void AnimationContent::movieStatus(int status)
958
DEBUG_WIN << "movieStatus()";
960
// At least two frames: it's an animation, everything is OK
961
if (m_oldStatus == QMovie::EndOfFrame && status == QMovie::EndOfFrame) {
962
movie().disconnectStatus(this);
963
m_oldStatus = INVALID_STATUS;
964
// if (note()->isFocused()) // When inserting a new note we ensure it visble
965
// basket()->ensureNoteVisible(note()); // But after loading it has certainly grown and if it was
967
// Only one image: it's an image, change note's type
968
else if (m_oldStatus == QMovie::EndOfFrame && status == QMovie::EndOfLoop) {
969
movie().disconnectStatus(this);
970
m_oldStatus = INVALID_STATUS;
971
note()->setContent(new ImageContent(note(), fileName()));
973
//delete this; // CRASH, as always !!!!!!!!!
974
//QTimer::singleShot(0, this, SLOT(loadContent())); // Delayed to avoid crash!
975
//QTimer::singleShot(100, this, SLOT(saveProperties())); // We should save it's an image and not an animation
976
// if (note()->isFocused())
977
// QTimer::singleShot(25, note(), SLOT(delayedEnsureVisible()));
980
m_oldStatus = status;
983
void AnimationContent::exportToHTML(HTMLExporter *exporter, int /*indent*/)
985
exporter->stream << QString("<img src=\"%1\" width=\"%2\" height=\"%3\" alt=\"\">")
986
.arg( exporter->dataFolderName + exporter->copyFile(fullPath(), /*createIt=*/true),
987
QString::number(movie().framePixmap().size().width()),
988
QString::number(movie().framePixmap().size().height()) );
991
/** class FileContent:
994
FileContent::FileContent(Note *parent, const QString &fileName)
995
: NoteContent(parent, fileName), m_previewJob(0)
997
basket()->addWatchedFile(fullPath());
998
setFileName(fileName); // FIXME: TO THAT HERE BECAUSE NoteContent() constructor seems to don't be able to call virtual methods???
1001
int FileContent::setWidthAndGetHeight(int width)
1003
m_linkDisplay.setWidth(width);
1004
return m_linkDisplay.height();
1007
void FileContent::paint(QPainter *painter, int width, int height, const QColorGroup &colorGroup, bool isDefaultColor, bool isSelected, bool isHovered)
1009
m_linkDisplay.paint(painter, 0, 0, width, height, colorGroup, isDefaultColor, isSelected, isHovered, isHovered && note()->hoveredZone() == Note::Custom0);
1012
bool FileContent::loadFromFile(bool /*lazyLoad*/)
1014
setFileName(fileName()); // File changed: get new file preview!
1018
void FileContent::toolTipInfos(QStringList *keys, QStringList *values)
1020
// Get the size of the file:
1021
uint size = QFileInfo(fullPath()).size();
1022
QString humanFileSize = KIO::convertSize((KIO::filesize_t)size);
1024
keys->append(i18n("Size"));
1025
values->append(humanFileSize);
1027
KMimeType::Ptr mime = KMimeType::findByURL(KURL(fullPath()));
1029
keys->append(i18n("Type"));
1030
values->append(mime->comment());
1033
KFileMetaInfo infos = KFileMetaInfo(KURL(fullPath()));
1034
if (infos.isValid() && !infos.isEmpty()) {
1035
QStringList groups = infos.preferredKeys();
1037
for (QStringList::Iterator it = groups.begin(); i < 6 && it != groups.end(); ++it) {
1038
KFileMetaInfoItem metaInfoItem = infos.item(*it);
1039
if (!metaInfoItem.string().isEmpty()) {
1040
keys->append(metaInfoItem.translatedKey());
1041
values->append(metaInfoItem.string());
1048
int FileContent::zoneAt(const QPoint &pos)
1050
return (m_linkDisplay.iconButtonAt(pos) ? 0 : Note::Custom0);
1053
QRect FileContent::zoneRect(int zone, const QPoint &/*pos*/)
1055
QRect linkRect = m_linkDisplay.iconButtonRect();
1057
if (zone == Note::Custom0)
1058
return QRect(linkRect.width(), 0, note()->width(), note()->height()); // Too wide and height, but it will be clipped by Note::zoneRect()
1059
else if (zone == Note::Content)
1065
QString FileContent::zoneTip(int zone)
1067
return (zone == Note::Custom0 ? i18n("Open this file") : QString());
1070
void FileContent::setCursor(QWidget *widget, int zone)
1072
if (zone == Note::Custom0)
1073
widget->setCursor(Qt::PointingHandCursor);
1077
int FileContent::xEditorIndent()
1079
return m_linkDisplay.iconButtonRect().width() + 2;
1083
QString FileContent::messageWhenOpenning(OpenMessage where)
1086
case OpenOne: return i18n("Opening file...");
1087
case OpenSeveral: return i18n("Opening files...");
1088
case OpenOneWith: return i18n("Opening file with...");
1089
case OpenSeveralWith: return i18n("Opening files with...");
1090
case OpenOneWithDialog: return i18n("Open file with:");
1091
case OpenSeveralWithDialog: return i18n("Open files with:");
1096
void FileContent::setFileName(const QString &fileName)
1098
NoteContent::setFileName(fileName);
1099
KURL url = KURL(fullPath());
1100
if (linkLook()->previewEnabled())
1101
m_linkDisplay.setLink(fileName, NoteFactory::iconForURL(url), linkLook(), note()->font()); // FIXME: move iconForURL outside of NoteFactory !!!!!
1103
m_linkDisplay.setLink(fileName, NoteFactory::iconForURL(url), QPixmap(), linkLook(), note()->font());
1104
startFetchingUrlPreview();
1105
contentChanged(m_linkDisplay.minWidth());
1108
void FileContent::linkLookChanged()
1111
//setFileName(fileName());
1112
//startFetchingUrlPreview();
1115
void FileContent::newPreview(const KFileItem*, const QPixmap &preview)
1117
LinkLook *linkLook = this->linkLook();
1118
m_linkDisplay.setLink(fileName(), NoteFactory::iconForURL(KURL(fullPath())), (linkLook->previewEnabled() ? preview : QPixmap()), linkLook, note()->font());
1119
contentChanged(m_linkDisplay.minWidth());
1122
void FileContent::removePreview(const KFileItem*)
1124
newPreview(0, QPixmap());
1127
void FileContent::startFetchingUrlPreview()
1129
KURL url(fullPath());
1130
LinkLook *linkLook = this->linkLook();
1132
// delete m_previewJob;
1133
if (!url.isEmpty() && linkLook->previewSize() > 0) {
1134
KURL filteredUrl = NoteFactory::filteredURL(url);//KURIFilter::self()->filteredURI(url);
1136
urlList.append(filteredUrl);
1137
m_previewJob = KIO::filePreview(urlList, linkLook->previewSize(), linkLook->previewSize(), linkLook->iconSize());
1138
connect( m_previewJob, SIGNAL(gotPreview(const KFileItem*, const QPixmap&)), this, SLOT(newPreview(const KFileItem*, const QPixmap&)) );
1139
connect( m_previewJob, SIGNAL(failed(const KFileItem*)), this, SLOT(removePreview(const KFileItem*)) );
1143
void FileContent::exportToHTML(HTMLExporter *exporter, int indent)
1146
QString fileName = exporter->copyFile(fullPath(), true);
1147
exporter->stream << m_linkDisplay.toHtml(exporter, KURL(exporter->dataFolderName + fileName), "").replace("\n", "\n" + spaces.fill(' ', indent + 1));
1150
/** class SoundContent:
1153
SoundContent::SoundContent(Note *parent, const QString &fileName)
1154
: FileContent(parent, fileName)
1156
setFileName(fileName); // FIXME: TO THAT HERE BECAUSE NoteContent() constructor seems to don't be able to call virtual methods???
1160
QString SoundContent::zoneTip(int zone)
1162
return (zone == Note::Custom0 ? i18n("Open this sound") : QString());
1165
void SoundContent::setHoveredZone(int oldZone, int newZone)
1169
if (newZone == Note::Custom0 || newZone == Note::Content)
1170
std::cout << "Compiled without aRts: sound is not played." << std::endl;
1172
static KArtsDispatcher *s_dispatcher = new KArtsDispatcher(); // Needed for s_playObj (we don't use it directly)
1173
static KArtsServer *s_playServer = new KArtsServer();
1174
static KDE::PlayObjectFactory *s_playFactory = new KDE::PlayObjectFactory(s_playServer);
1175
static KDE::PlayObject *s_playObj = 0;
1177
Q_UNUSED(s_dispatcher); // Avoid the compiler to tell us it is not used!
1178
if (newZone == Note::Custom0 || newZone == Note::Content) {
1179
// Start the sound preview:
1180
if (oldZone != Note::Custom0 && oldZone != Note::Content) { // Don't restart if it was already in one of those zones
1181
s_playObj = s_playFactory->createPlayObject(fullPath(), true);
1185
// Stop the sound preview, if it was started:
1196
QString SoundContent::messageWhenOpenning(OpenMessage where)
1199
case OpenOne: return i18n("Opening sound...");
1200
case OpenSeveral: return i18n("Opening sounds...");
1201
case OpenOneWith: return i18n("Opening sound with...");
1202
case OpenSeveralWith: return i18n("Opening sounds with...");
1203
case OpenOneWithDialog: return i18n("Open sound with:");
1204
case OpenSeveralWithDialog: return i18n("Open sounds with:");
1209
/** class LinkContent:
1212
LinkContent::LinkContent(Note *parent, const KURL &url, const QString &title, const QString &icon, bool autoTitle, bool autoIcon)
1213
: NoteContent(parent), m_previewJob(0)
1215
setLink(url, title, icon, autoTitle, autoIcon);
1218
int LinkContent::setWidthAndGetHeight(int width)
1220
m_linkDisplay.setWidth(width);
1221
return m_linkDisplay.height();
1224
void LinkContent::paint(QPainter *painter, int width, int height, const QColorGroup &colorGroup, bool isDefaultColor, bool isSelected, bool isHovered)
1226
m_linkDisplay.paint(painter, 0, 0, width, height, colorGroup, isDefaultColor, isSelected, isHovered, isHovered && note()->hoveredZone() == Note::Custom0);
1229
void LinkContent::saveToNode(QDomDocument &doc, QDomElement &content)
1231
content.setAttribute("title", title() );
1232
content.setAttribute("icon", icon() );
1233
content.setAttribute("autoTitle", (autoTitle() ? "true" : "false"));
1234
content.setAttribute("autoIcon", (autoIcon() ? "true" : "false"));
1235
QDomText textNode = doc.createTextNode(url().prettyURL());
1236
content.appendChild(textNode);
1240
void LinkContent::toolTipInfos(QStringList *keys, QStringList *values)
1242
keys->append(i18n("Target"));
1243
values->append(m_url.prettyURL());
1246
int LinkContent::zoneAt(const QPoint &pos)
1248
return (m_linkDisplay.iconButtonAt(pos) ? 0 : Note::Custom0);
1251
QRect LinkContent::zoneRect(int zone, const QPoint &/*pos*/)
1253
QRect linkRect = m_linkDisplay.iconButtonRect();
1255
if (zone == Note::Custom0)
1256
return QRect(linkRect.width(), 0, note()->width(), note()->height()); // Too wide and height, but it will be clipped by Note::zoneRect()
1257
else if (zone == Note::Content)
1263
QString LinkContent::zoneTip(int zone)
1265
return (zone == Note::Custom0 ? i18n("Open this link") : QString());
1268
void LinkContent::setCursor(QWidget *widget, int zone)
1270
if (zone == Note::Custom0)
1271
widget->setCursor(Qt::PointingHandCursor);
1274
QString LinkContent::statusBarMessage(int zone)
1276
if (zone == Note::Custom0 || zone == Note::Content)
1277
return m_url.prettyURL();
1283
KURL LinkContent::urlToOpen(bool /*with*/)
1285
return NoteFactory::filteredURL(url());//KURIFilter::self()->filteredURI(url());
1288
QString LinkContent::messageWhenOpenning(OpenMessage where)
1290
if (url().isEmpty())
1291
return i18n("Link have no URL to open.");
1294
case OpenOne: return i18n("Opening link target...");
1295
case OpenSeveral: return i18n("Opening link targets...");
1296
case OpenOneWith: return i18n("Opening link target with...");
1297
case OpenSeveralWith: return i18n("Opening link targets with...");
1298
case OpenOneWithDialog: return i18n("Open link target with:");
1299
case OpenSeveralWithDialog: return i18n("Open link targets with:");
1304
void LinkContent::setLink(const KURL &url, const QString &title, const QString &icon, bool autoTitle, bool autoIcon)
1306
m_autoTitle = autoTitle;
1307
m_autoIcon = autoIcon;
1308
m_url = NoteFactory::filteredURL(KURL(url));//KURIFilter::self()->filteredURI(url);
1309
m_title = (autoTitle ? NoteFactory::titleForURL(m_url) : title);
1310
m_icon = (autoIcon ? NoteFactory::iconForURL(m_url) : icon);
1312
LinkLook *look = LinkLook::lookForURL(m_url);
1313
if (look->previewEnabled())
1314
m_linkDisplay.setLink(m_title, m_icon, look, note()->font());
1316
m_linkDisplay.setLink(m_title, m_icon, QPixmap(), look, note()->font());
1317
startFetchingUrlPreview();
1318
contentChanged(m_linkDisplay.minWidth());
1321
void LinkContent::linkLookChanged()
1326
void LinkContent::newPreview(const KFileItem*, const QPixmap &preview)
1328
LinkLook *linkLook = LinkLook::lookForURL(url());
1329
m_linkDisplay.setLink(title(), icon(), (linkLook->previewEnabled() ? preview : QPixmap()), linkLook, note()->font());
1330
contentChanged(m_linkDisplay.minWidth());
1333
void LinkContent::removePreview(const KFileItem*)
1335
newPreview(0, QPixmap());
1338
// Code dupicated from FileContent::startFetchingUrlPreview()
1339
void LinkContent::startFetchingUrlPreview()
1341
KURL url = this->url();
1342
LinkLook *linkLook = LinkLook::lookForURL(this->url());
1344
// delete m_previewJob;
1345
if (!url.isEmpty() && linkLook->previewSize() > 0) {
1346
KURL filteredUrl = NoteFactory::filteredURL(url);//KURIFilter::self()->filteredURI(url);
1348
urlList.append(filteredUrl);
1349
m_previewJob = KIO::filePreview(urlList, linkLook->previewSize(), linkLook->previewSize(), linkLook->iconSize());
1350
connect( m_previewJob, SIGNAL(gotPreview(const KFileItem*, const QPixmap&)), this, SLOT(newPreview(const KFileItem*, const QPixmap&)) );
1351
connect( m_previewJob, SIGNAL(failed(const KFileItem*)), this, SLOT(removePreview(const KFileItem*)) );
1355
void LinkContent::exportToHTML(HTMLExporter *exporter, int indent)
1357
QString linkTitle = title();
1360
// // Append address (useful for print version of the page/basket):
1361
// if (exportData.formatForImpression && (!autoTitle() && title() != NoteFactory::titleForURL(url().prettyURL()))) {
1362
// // The address is on a new line, unless title is empty (empty lines was replaced by ):
1363
// if (linkTitle == " "/*" "*/)
1364
// linkTitle = url().prettyURL()/*""*/;
1366
// linkTitle = linkTitle + " <" + url().prettyURL() + ">"/*+ "<br>"*/;
1367
// //linkTitle += "<i>" + url().prettyURL() + "</i>";
1372
QFileInfo fInfo(url().path());
1373
// DEBUG_WIN << url().path()
1374
// << "IsFile:" + QString::number(fInfo.isFile())
1375
// << "IsDir:" + QString::number(fInfo.isDir());
1376
if (exportData.embedLinkedFiles && fInfo.isFile()) {
1377
// DEBUG_WIN << "Embed file";
1378
linkURL = exportData.dataFolderName + Basket::copyFile(url().path(), exportData.dataFolderPath, true);
1379
} else if (exportData.embedLinkedFolders && fInfo.isDir()) {
1380
// DEBUG_WIN << "Embed folder";
1381
linkURL = exportData.dataFolderName + Basket::copyFile(url().path(), exportData.dataFolderPath, true);
1383
// DEBUG_WIN << "Embed LINK";
1391
exporter->stream << m_linkDisplay.toHtml(exporter, linkURL, linkTitle).replace("\n", "\n" + spaces.fill(' ', indent + 1));
1394
/** class LauncherContent:
1397
LauncherContent::LauncherContent(Note *parent, const QString &fileName)
1398
: NoteContent(parent, fileName)
1400
basket()->addWatchedFile(fullPath());
1401
loadFromFile(/*lazyLoad=*/false);
1404
int LauncherContent::setWidthAndGetHeight(int width)
1406
m_linkDisplay.setWidth(width);
1407
return m_linkDisplay.height();
1410
void LauncherContent::paint(QPainter *painter, int width, int height, const QColorGroup &colorGroup, bool isDefaultColor, bool isSelected, bool isHovered)
1412
m_linkDisplay.paint(painter, 0, 0, width, height, colorGroup, isDefaultColor, isSelected, isHovered, isHovered && note()->hoveredZone() == Note::Custom0);
1415
bool LauncherContent::loadFromFile(bool /*lazyLoad*/) // TODO: saveToFile() ?? Is it possible?
1417
DEBUG_WIN << "Loading LauncherContent From " + basket()->folderName() + fileName();
1418
KService service(fullPath());
1419
setLauncher(service.name(), service.icon(), service.exec());
1424
void LauncherContent::toolTipInfos(QStringList *keys, QStringList *values)
1426
KService service(fullPath());
1428
QString exec = service.exec();
1429
if (service.terminal())
1430
exec = i18n("%1 <i>(run in terminal)</i>").arg(exec);
1432
if (!service.comment().isEmpty() && service.comment() != service.name()) {
1433
keys->append(i18n("Comment"));
1434
values->append(service.comment());
1437
keys->append(i18n("Command"));
1438
values->append(exec);
1441
int LauncherContent::zoneAt(const QPoint &pos)
1443
return (m_linkDisplay.iconButtonAt(pos) ? 0 : Note::Custom0);
1446
QRect LauncherContent::zoneRect(int zone, const QPoint &/*pos*/)
1448
QRect linkRect = m_linkDisplay.iconButtonRect();
1450
if (zone == Note::Custom0)
1451
return QRect(linkRect.width(), 0, note()->width(), note()->height()); // Too wide and height, but it will be clipped by Note::zoneRect()
1452
else if (zone == Note::Content)
1458
QString LauncherContent::zoneTip(int zone)
1460
return (zone == Note::Custom0 ? i18n("Launch this application") : QString());
1463
void LauncherContent::setCursor(QWidget *widget, int zone)
1465
if (zone == Note::Custom0)
1466
widget->setCursor(Qt::PointingHandCursor);
1470
KURL LauncherContent::urlToOpen(bool with)
1472
if (KService(fullPath()).exec().isEmpty())
1475
return (with ? KURL() : KURL(fullPath())); // Can open the appliation, but not with another application :-)
1478
QString LauncherContent::messageWhenOpenning(OpenMessage where)
1480
if (KService(fullPath()).exec().isEmpty())
1481
return i18n("The launcher have no command to run.");
1484
case OpenOne: return i18n("Launching application...");
1485
case OpenSeveral: return i18n("Launching applications...");
1487
case OpenSeveralWith:
1488
case OpenOneWithDialog:
1489
case OpenSeveralWithDialog: // TODO: "Open this application with this file as parameter"?
1494
void LauncherContent::setLauncher(const QString &name, const QString &icon, const QString &exec)
1500
m_linkDisplay.setLink(name, icon, LinkLook::launcherLook, note()->font());
1501
contentChanged(m_linkDisplay.minWidth());
1504
void LauncherContent::exportToHTML(HTMLExporter *exporter, int indent)
1507
QString fileName = exporter->copyFile(fullPath(), /*createIt=*/true);
1508
exporter->stream << m_linkDisplay.toHtml(exporter, KURL(exporter->dataFolderName + fileName), "").replace("\n", "\n" + spaces.fill(' ', indent + 1));
1511
/** class ColorContent:
1514
const int ColorContent::RECT_MARGIN = 2;
1516
ColorContent::ColorContent(Note *parent, const QColor &color)
1517
: NoteContent(parent)
1522
int ColorContent::setWidthAndGetHeight(int /*width*/) // We do not need width because we can't word-break, and width is always >= minWidth()
1524
// FIXME: Duplicate from setColor():
1525
QRect textRect = QFontMetrics(note()->font()).boundingRect(color().name());
1526
int rectHeight = (textRect.height() + 2)*3/2;
1530
void ColorContent::paint(QPainter *painter, int width, int height, const QColorGroup &colorGroup, bool /*isDefaultColor*/, bool /*isSelected*/, bool /*isHovered*/)
1532
// FIXME: Duplicate from setColor():
1533
QRect textRect = QFontMetrics(note()->font()).boundingRect(color().name());
1534
int rectHeight = (textRect.height() + 2)*3/2;
1535
int rectWidth = rectHeight * 14 / 10; // 1.4 times the height, like A4 papers.
1537
// FIXME: Duplicate from CommonColorSelector::drawColorRect:
1539
painter->fillRect(1, 1, rectWidth - 2, rectHeight - 2, color());
1541
QColor stroke = color().dark(125);
1542
painter->setPen(stroke);
1543
painter->drawLine(1, 0, rectWidth - 2, 0);
1544
painter->drawLine(0, 1, 0, rectHeight - 2);
1545
painter->drawLine(1, rectHeight - 1, rectWidth - 2, rectHeight - 1);
1546
painter->drawLine(rectWidth - 1, 1, rectWidth - 1, rectHeight - 2);
1548
painter->setPen(Tools::mixColor(color(), stroke));
1549
painter->drawPoint(1, 1);
1550
painter->drawPoint(1, rectHeight - 2);
1551
painter->drawPoint(rectWidth - 2, rectHeight - 2);
1552
painter->drawPoint(rectWidth - 2, 1);
1555
painter->setFont(note()->font());
1556
painter->setPen(colorGroup.text());
1557
painter->drawText(rectWidth + RECT_MARGIN, 0, width - rectWidth - RECT_MARGIN, height, Qt::AlignAuto | Qt::AlignVCenter, color().name());
1560
void ColorContent::saveToNode(QDomDocument &doc, QDomElement &content)
1562
QDomText textNode = doc.createTextNode(color().name());
1563
content.appendChild(textNode);
1567
void ColorContent::toolTipInfos(QStringList *keys, QStringList *values)
1569
int hue, saturation, value;
1570
m_color.getHsv(hue, saturation, value);
1572
keys->append(i18n("RGB Colorspace: Red/Green/Blue", "RGB"));
1573
values->append(i18n("<i>Red</i>: %1, <i>Green</i>: %2, <i>Blue</i>: %3,").arg(QString::number(m_color.red()), QString::number(m_color.green()), QString::number(m_color.blue())));
1575
keys->append(i18n("HSV Colorspace: Hue/Saturation/Value", "HSV"));
1576
values->append(i18n("<i>Hue</i>: %1, <i>Saturation</i>: %2, <i>Value</i>: %3,").arg(QString::number(hue), QString::number(saturation), QString::number(value)));
1578
static QString cssColors[] = {
1582
"fuchsia", "ff00ff",
1597
static QString cssExtendedColors[] = {
1598
"aliceblue", "f0f8ff",
1599
"antiquewhite", "faebd7",
1600
"aquamarine", "7fffd4",
1604
"blanchedalmond", "ffebcd",
1605
"blueviolet", "8a2be2",
1607
"burlywood", "deb887",
1608
"cadetblue", "5f9ea0",
1609
"chartreuse", "7fff00",
1610
"chocolate", "d2691e",
1612
"cornflowerblue", "6495ed",
1613
"cornsilk", "fff8dc",
1614
"crimson", "dc1436",
1616
"darkblue", "00008b",
1617
"darkcyan", "008b8b",
1618
"darkgoldenrod", "b8860b",
1619
"darkgray", "a9a9a9",
1620
"darkgreen", "006400",
1621
"darkkhaki", "bdb76b",
1622
"darkmagenta", "8b008b",
1623
"darkolivegreen", "556b2f",
1624
"darkorange", "ff8c00",
1625
"darkorchid", "9932cc",
1626
"darkred", "8b0000",
1627
"darksalmon", "e9967a",
1628
"darkseagreen", "8fbc8f",
1629
"darkslateblue", "483d8b",
1630
"darkslategray", "2f4f4f",
1631
"darkturquoise", "00ced1",
1632
"darkviolet", "9400d3",
1633
"deeppink", "ff1493",
1634
"deepskyblue", "00bfff",
1635
"dimgray", "696969",
1636
"dodgerblue", "1e90ff",
1637
"firebrick", "b22222",
1638
"floralwhite", "fffaf0",
1639
"forestgreen", "228b22",
1640
"gainsboro", "dcdcdc",
1641
"ghostwhite", "f8f8ff",
1643
"goldenrod", "daa520",
1644
"greenyellow", "adff2f",
1645
"honeydew", "f0fff0",
1646
"hotpink", "ff69b4",
1647
"indianred", "cd5c5c",
1651
"lavender", "e6e6fa",
1652
"lavenderblush", "fff0f5",
1653
"lawngreen", "7cfc00",
1654
"lemonchiffon", "fffacd",
1655
"lightblue", "add8e6",
1656
"lightcoral", "f08080",
1657
"lightcyan", "e0ffff",
1658
"lightgoldenrodyellow", "fafad2",
1659
"lightgreen", "90ee90",
1660
"lightgrey", "d3d3d3",
1661
"lightpink", "ffb6c1",
1662
"lightsalmon", "ffa07a",
1663
"lightseagreen", "20b2aa",
1664
"lightskyblue", "87cefa",
1665
"lightslategray", "778899",
1666
"lightsteelblue", "b0c4de",
1667
"lightyellow", "ffffe0",
1668
"limegreen", "32cd32",
1670
"magenta", "ff00ff",
1671
"mediumaquamarine", "66cdaa",
1672
"mediumblue", "0000cd",
1673
"mediumorchid", "ba55d3",
1674
"mediumpurple", "9370db",
1675
"mediumseagreen", "3cb371",
1676
"mediumslateblue", "7b68ee",
1677
"mediumspringgreen", "00fa9a",
1678
"mediumturquoise", "48d1cc",
1679
"mediumvioletred", "c71585",
1680
"midnightblue", "191970",
1681
"mintcream", "f5fffa",
1682
"mistyrose", "ffe4e1",
1683
"moccasin", "ffe4b5",
1684
"navajowhite", "ffdead",
1685
"oldlace", "fdf5e6",
1686
"olivedrab", "6b8e23",
1688
"orangered", "ff4500",
1690
"palegoldenrod", "eee8aa",
1691
"palegreen", "98fb98",
1692
"paleturquoise", "afeeee",
1693
"palevioletred", "db7093",
1694
"papayawhip", "ffefd5",
1695
"peachpuff", "ffdab9",
1699
"powderblue", "b0e0e6",
1700
"rosybrown", "bc8f8f",
1701
"royalblue", "4169e1",
1702
"saddlebrown", "8b4513",
1704
"sandybrown", "f4a460",
1705
"seagreen", "2e8b57",
1706
"seashell", "fff5ee",
1708
"skyblue", "87ceeb",
1709
"slateblue", "6a5acd",
1710
"slategray", "708090",
1712
"springgreen", "00ff7f",
1713
"steelblue", "4682b4",
1715
"thistle", "d8bfd8",
1717
"turquoise", "40e0d0",
1720
"whitesmoke", "f5f5f5",
1721
"yellowgreen", "9acd32"
1724
QString colorHex = color().name().mid(1); // Take the hexadecimal name of the color, without the '#'.
1726
bool cssColorFound = false;
1727
for (int i = 0; i < 2*16; i += 2) {
1728
if (colorHex == cssColors[i+1]) {
1729
keys->append(i18n("CSS Color Name"));
1730
values->append(cssColors[i]);
1731
cssColorFound = true;
1737
for (int i = 0; i < 2*124; i += 2) {
1738
if (colorHex == cssExtendedColors[i+1]) {
1739
keys->append(i18n("CSS Extended Color Name"));
1740
values->append(cssExtendedColors[i]);
1745
keys->append(i18n("Is Web Color"));
1746
values->append(Tools::isWebColor(color()) ? i18n("Yes") : i18n("No"));
1750
void ColorContent::setColor(const QColor &color)
1754
QRect textRect = QFontMetrics(note()->font()).boundingRect(color.name());
1755
int rectHeight = (textRect.height() + 2)*3/2;
1756
int rectWidth = rectHeight * 14 / 10; // 1.4 times the height, like A4 papers.
1757
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.
1760
void ColorContent::addAlternateDragObjects(KMultipleDrag *dragObject)
1762
dragObject->addDragObject( new QColorDrag(color()) );
1764
// addDragObject(new KColorDrag( note->color(), 0 ));
1765
// addDragObject(new QTextDrag( note->color().name(), 0 ));
1767
/* // Creata and add the QDragObject:
1768
storedDrag = new QStoredDrag("application/x-color");
1769
storedDrag->setEncodedData(*array);
1770
dragObject->addDragObject(storedDrag);
1774
void ColorContent::exportToHTML(HTMLExporter *exporter, int /*indent*/)
1776
// FIXME: Duplicate from setColor(): TODO: rectSize()
1777
QRect textRect = QFontMetrics(note()->font()).boundingRect(color().name());
1778
int rectHeight = (textRect.height() + 2)*3/2;
1779
int rectWidth = rectHeight * 14 / 10; // 1.4 times the height, like A4 papers.
1781
QString fileName = /*Tools::fileNameForNewFile(*/QString("color_%1.png").arg(color().name().lower().mid(1))/*, exportData.iconsFolderPath)*/;
1782
QString fullPath = exporter->iconsFolderPath + fileName;
1783
QPixmap colorIcon = KColorCombo2::colorRectPixmap(color(), /*isDefault=*/false, rectWidth, rectHeight);
1784
colorIcon.save(fullPath, "PNG");
1785
QString iconHtml = QString("<img src=\"%1\" width=\"%2\" height=\"%3\" alt=\"\">")
1786
.arg(exporter->iconsFolderName + fileName, QString::number(colorIcon.width()), QString::number(colorIcon.height()));
1788
exporter->stream << iconHtml + " " + color().name();
1793
/** class UnknownContent:
1796
const int UnknownContent::DECORATION_MARGIN = 2;
1798
UnknownContent::UnknownContent(Note *parent, const QString &fileName)
1799
: NoteContent(parent, fileName)
1801
basket()->addWatchedFile(fullPath());
1802
loadFromFile(/*lazyLoad=*/false);
1805
int UnknownContent::setWidthAndGetHeight(int width)
1808
QRect textRect = QFontMetrics(note()->font()).boundingRect(0, 0, width, 500000, Qt::AlignAuto | Qt::AlignTop | Qt::WordBreak, m_mimeTypes);
1809
return DECORATION_MARGIN + textRect.height() + DECORATION_MARGIN;
1812
// TODO: Move this function from note.cpp to class Tools:
1813
extern void drawGradient( QPainter *p, const QColor &colorTop, const QColor & colorBottom,
1814
int x, int y, int w, int h,
1815
bool sunken, bool horz, bool flat ); /*const*/
1817
void UnknownContent::paint(QPainter *painter, int width, int height, const QColorGroup &colorGroup, bool /*isDefaultColor*/, bool /*isSelected*/, bool /*isHovered*/)
1820
painter->setPen(colorGroup.text());
1822
// FIXME: Duplicate from ColorContent::paint() and CommonColorSelector::drawColorRect:
1823
// Fill with gradient:
1824
drawGradient(painter, colorGroup.background(), colorGroup.background().dark(110), 1, 1, width - 2, height - 2, /*sunken=*/false, /*horz=*/true, /*flat=*/false);
1826
QColor stroke = Tools::mixColor(colorGroup.background(), colorGroup.text());
1827
painter->setPen(stroke);
1828
painter->drawLine(1, 0, width - 2, 0);
1829
painter->drawLine(0, 1, 0, height - 2);
1830
painter->drawLine(1, height - 1, width - 2, height - 1);
1831
painter->drawLine(width - 1, 1, width - 1, height - 2);
1833
painter->setPen(Tools::mixColor(colorGroup.background(), stroke));
1834
painter->drawPoint(1, 1);
1835
painter->drawPoint(1, height - 2);
1836
painter->drawPoint(width - 2, height - 2);
1837
painter->drawPoint(width - 2, 1);
1839
painter->setPen(colorGroup.text());
1840
painter->drawText(DECORATION_MARGIN, DECORATION_MARGIN, width - 2*DECORATION_MARGIN, height - 2*DECORATION_MARGIN,
1841
Qt::AlignAuto | Qt::AlignVCenter | Qt::WordBreak, m_mimeTypes);
1844
bool UnknownContent::loadFromFile(bool /*lazyLoad*/)
1846
DEBUG_WIN << "Loading UnknownContent From " + basket()->folderName() + fileName();
1847
QFile file(fullPath());
1848
if (file.open(IO_ReadOnly)) {
1849
QDataStream stream(&file);
1852
// Get the MIME-types names:
1854
if (!stream.atEnd()) {
1856
if (!line.isEmpty()) {
1857
if (m_mimeTypes.isEmpty())
1858
m_mimeTypes += line;
1860
m_mimeTypes += QString("\n") + line;
1863
} while (!line.isEmpty() && !stream.atEnd());
1867
QRect textRect = QFontMetrics(note()->font()).boundingRect(0, 0, /*width=*/1, 500000, Qt::AlignAuto | Qt::AlignTop | Qt::WordBreak, m_mimeTypes);
1868
contentChanged(DECORATION_MARGIN + textRect.width() + DECORATION_MARGIN + 1);
1872
void UnknownContent::addAlternateDragObjects(KMultipleDrag *dragObject)
1874
QFile file(fullPath());
1875
if (file.open(IO_ReadOnly)) {
1876
QDataStream stream(&file);
1877
// Get the MIME types names:
1878
QValueList<QString> mimes;
1881
if (!stream.atEnd()) {
1883
if (!line.isEmpty())
1886
} while (!line.isEmpty() && !stream.atEnd());
1888
Q_UINT64 size; // TODO: It was Q_UINT32 in version 0.5.0 !
1890
QStoredDrag *storedDrag;
1891
for (uint i = 0; i < mimes.count(); ++i) {
1894
// Allocate memory to retreive size bytes and store them:
1895
array = new QByteArray(size);
1896
stream.readRawBytes(array->data(), size);
1897
// Creata and add the QDragObject:
1898
storedDrag = new QStoredDrag(*(mimes.at(i)));
1899
storedDrag->setEncodedData(*array);
1900
dragObject->addDragObject(storedDrag);
1901
delete array; // FIXME: Should we?
1907
void UnknownContent::exportToHTML(HTMLExporter *exporter, int indent)
1910
exporter->stream << "<div class=\"unknown\">" << mimeTypes().replace("\n", "\n" + spaces.fill(' ', indent + 1 + 1)) << "</div>";
1916
void NoteFactory__loadNode(const QDomElement &content, const QString &lowerTypeName, Note *parent, bool lazyLoad)
1918
if (lowerTypeName == "text") new TextContent( parent, content.text(), lazyLoad );
1919
else if (lowerTypeName == "html") new HtmlContent( parent, content.text(), lazyLoad );
1920
else if (lowerTypeName == "image") new ImageContent( parent, content.text(), lazyLoad );
1921
else if (lowerTypeName == "animation") new AnimationContent( parent, content.text(), lazyLoad );
1922
else if (lowerTypeName == "sound") new SoundContent( parent, content.text() );
1923
else if (lowerTypeName == "file") new FileContent( parent, content.text() );
1924
else if (lowerTypeName == "link") {
1925
bool autoTitle = content.attribute("title") == content.text();
1926
bool autoIcon = content.attribute("icon") == NoteFactory::iconForURL(KURL(content.text()));
1927
autoTitle = XMLWork::trueOrFalse( content.attribute("autoTitle"), autoTitle);
1928
autoIcon = XMLWork::trueOrFalse( content.attribute("autoIcon"), autoIcon );
1929
new LinkContent( parent, KURL(content.text()), content.attribute("title"), content.attribute("icon"), autoTitle, autoIcon );
1930
} else if (lowerTypeName == "launcher") new LauncherContent( parent, content.text() );
1931
else if (lowerTypeName == "color") new ColorContent( parent, QColor(content.text()) );
1932
else if (lowerTypeName == "unknown") new UnknownContent( parent, content.text() );
1935
#include "notecontent.moc"