1 /***************************************************************************
2  *   Copyright (C) 2003 by Sébastien Laoût                                 *
3  *   slaout@linux62.org                                                    *
4  *                                                                         *
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.                                   *
9  *                                                                         *
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.                          *
14  *                                                                         *
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  ***************************************************************************/
20 
21 #include "linklabel.h"
22 
23 #include <QtCore/QEvent>
24 #include <QLabel>
25 #include <QLayout>
26 #include <QHBoxLayout>
27 #include <QVBoxLayout>
28 #include <QBoxLayout>
29 #include <QGridLayout>
30 #include <QPixmap>
31 #include <QFrame>
32 #include <QCursor>
33 #include <QCheckBox>
34 #include <QPainter>
35 #include <QStyle>
36 #include <QGroupBox>
37 #include <QApplication>
38 #include <QLocale>
39 #include <QUrl>
40 
41 #include <KAboutData>
42 #include <KComboBox>
43 #include <KIconLoader>
44 #include <KCModule>
45 #include <KLocalizedString>
46 
47 #include "variouswidgets.h"
48 #include "tools.h"
49 #include "global.h"
50 #include "kcolorcombo2.h"
51 #include "htmlexporter.h"
52 
53 /** LinkLook */
54 
55 LinkLook *LinkLook::soundLook       = new LinkLook(/*useLinkColor=*/false, /*canPreview=*/false);
56 LinkLook *LinkLook::fileLook        = new LinkLook(/*useLinkColor=*/false, /*canPreview=*/true);
57 LinkLook *LinkLook::localLinkLook   = new LinkLook(/*useLinkColor=*/true,  /*canPreview=*/true);
58 LinkLook *LinkLook::networkLinkLook = new LinkLook(/*useLinkColor=*/true,  /*canPreview=*/false);
59 LinkLook *LinkLook::launcherLook    = new LinkLook(/*useLinkColor=*/true,  /*canPreview=*/false);
60 LinkLook *LinkLook::crossReferenceLook=new LinkLook(/*useLinkColor=*/true,  /*canPreview=*/false);
61 
LinkLook(bool useLinkColor,bool canPreview)62 LinkLook::LinkLook(bool useLinkColor, bool canPreview)
63 {
64     m_useLinkColor = useLinkColor;
65     m_canPreview   = canPreview;
66     m_iconSize     = 0;
67 }
68 
LinkLook(const LinkLook & other)69 LinkLook::LinkLook(const LinkLook &other)
70 {
71     m_useLinkColor = other.useLinkColor();
72     m_canPreview   = other.canPreview();
73     setLook(other.italic(), other.bold(), other.underlining(),
74             other.color(), other.hoverColor(),
75             other.iconSize(), other.preview());
76 }
77 
setLook(bool italic,bool bold,int underlining,QColor color,QColor hoverColor,int iconSize,int preview)78 void LinkLook::setLook(bool italic, bool bold, int underlining,
79                        QColor color, QColor hoverColor,
80                        int iconSize, int preview)
81 {
82     m_italic      = italic;
83     m_bold        = bold;
84     m_underlining = underlining;
85     m_color       = color;
86     m_hoverColor  = hoverColor;
87     m_iconSize    = iconSize;
88     m_preview     = (canPreview() ? preview : None);
89 }
90 
previewSize() const91 int LinkLook::previewSize() const
92 {
93     if (previewEnabled()) {
94         switch (preview()) {
95         default:
96         case None:          return 0;
97         case IconSize:      return iconSize();
98         case TwiceIconSize: return iconSize() * 2;
99         case ThreeIconSize: return iconSize() * 3;
100         }
101     } else
102         return 0;
103 }
104 
effectiveColor() const105 QColor LinkLook::effectiveColor() const
106 {
107     if (m_color.isValid())
108         return m_color;
109     else
110         return defaultColor();
111 }
112 
effectiveHoverColor() const113 QColor LinkLook::effectiveHoverColor() const
114 {
115     if (m_hoverColor.isValid())
116         return m_hoverColor;
117     else
118         return defaultHoverColor();
119 }
120 
defaultColor() const121 QColor LinkLook::defaultColor() const
122 {
123     if (m_useLinkColor)
124         return qApp->palette().color(QPalette::Link);
125     else
126         return qApp->palette().color(QPalette::Text);
127 }
128 
defaultHoverColor() const129 QColor LinkLook::defaultHoverColor() const
130 {
131     return Qt::red;
132 }
133 
lookForURL(const QUrl & url)134 LinkLook* LinkLook::lookForURL(const QUrl &url)
135 {
136     return url.isLocalFile() ? localLinkLook : networkLinkLook;
137 }
138 
toCSS(const QString & cssClass,const QColor & defaultTextColor) const139 QString LinkLook::toCSS(const QString &cssClass, const QColor &defaultTextColor) const
140 {
141     // Set the link class:
142     QString css = QString("{ display: block; width: 100%;");
143     if (underlineOutside())
144         css += " text-decoration: underline;";
145     else
146         css += " text-decoration: none;";
147     if (m_italic == true)
148         css += " font-style: italic;";
149     if (m_bold == true)
150         css += " font-weight: bold;";
151     QColor textColor = (color().isValid() || m_useLinkColor ? effectiveColor() : defaultTextColor);
152     css += QString(" color: %1; }\n").arg(textColor.name());
153 
154    QString css2 = css;
155    css.prepend(QString("   .%1 a").arg(cssClass));
156    css2.prepend(QString("   a.%1").arg(cssClass));
157 
158     // Set the hover state class:
159     QString hover;
160     if (m_underlining == OnMouseHover)
161         hover = "text-decoration: underline;";
162     else if (m_underlining == OnMouseOutside)
163         hover = "text-decoration: none;";
164     if (effectiveHoverColor() != effectiveColor()) {
165         if (!hover.isEmpty())
166             hover += " ";
167         hover += QString("color: %4;").arg(effectiveHoverColor().name());
168     }
169 
170     // But include it only if it contain a different style than non-hover state:
171     if (!hover.isEmpty()) {
172         css += QString("   .%1 a:hover { %2 }\n").arg(cssClass, hover);
173         css2 += QString("    a:hover.%1 { %2 }\n").arg(cssClass, hover);
174     }
175     return css + css2;
176 }
177 
178 /** LinkLabel */
179 
LinkLabel(int hAlign,int vAlign,QWidget * parent,Qt::WindowFlags f)180 LinkLabel::LinkLabel(int hAlign, int vAlign, QWidget *parent, Qt::WindowFlags f)
181         : QFrame(parent, f), m_isSelected(false), m_isHovered(false), m_look(0)
182 {
183     initLabel(hAlign, vAlign);
184 }
185 
LinkLabel(const QString & title,const QString & icon,LinkLook * look,int hAlign,int vAlign,QWidget * parent,Qt::WindowFlags f)186 LinkLabel::LinkLabel(const QString &title, const QString &icon, LinkLook *look, int hAlign, int vAlign,
187                      QWidget *parent, Qt::WindowFlags f)
188         : QFrame(parent, f), m_isSelected(false), m_isHovered(false), m_look(0)
189 {
190     initLabel(hAlign, vAlign);
191     setLink(title, icon, look);
192 }
193 
initLabel(int hAlign,int vAlign)194 void LinkLabel::initLabel(int hAlign, int vAlign)
195 {
196     m_layout  = new QBoxLayout(QBoxLayout::LeftToRight, this);
197     m_icon    = new QLabel(this);
198     m_title   = new QLabel(this);
199     m_spacer1 = new QSpacerItem(0, 0, QSizePolicy::Preferred/*Expanding*/, QSizePolicy::Preferred/*Expanding*/);
200     m_spacer2 = new QSpacerItem(0, 0, QSizePolicy::Preferred/*Expanding*/, QSizePolicy::Preferred/*Expanding*/);
201 
202     m_hAlign = hAlign;
203     m_vAlign = vAlign;
204 
205     m_title->setTextFormat(Qt::PlainText);
206 
207     // DEGUB:
208     //m_icon->setPaletteBackgroundColor("lightblue");
209     //m_title->setPaletteBackgroundColor("lightyellow");
210 }
211 
~LinkLabel()212 LinkLabel::~LinkLabel()
213 {
214 }
215 
setLink(const QString & title,const QString & icon,LinkLook * look)216 void LinkLabel::setLink(const QString &title, const QString &icon, LinkLook *look)
217 {
218     if (look)
219         m_look = look; // Needed for icon size
220 
221     m_title->setText(title);
222     m_title->setVisible(! title.isEmpty());
223 
224     if (icon.isEmpty())
225         m_icon->clear();
226     else {
227         QPixmap pixmap = DesktopIcon(icon, m_look->iconSize(), m_look->iconSize());
228         if (!pixmap.isNull())
229             m_icon->setPixmap(pixmap);
230     }
231     m_icon->setVisible(! icon.isEmpty());
232 
233     if (look)
234         setLook(look);
235 }
236 
setLook(LinkLook * look)237 void LinkLabel::setLook(LinkLook *look) // FIXME: called externaly (so, without setLink()) it's buggy (icon not
238 {
239     m_look = look;
240 
241     QFont font;
242     font.setBold(look->bold());
243     font.setUnderline(look->underlineOutside());
244     font.setItalic(look->italic());
245     m_title->setFont(font);
246     QPalette palette;
247     if (m_isSelected)
248         palette.setColor(m_title->foregroundRole(), QApplication::palette().color(QPalette::Text));
249     else
250         palette.setColor(m_title->foregroundRole(), look->effectiveColor());
251 
252     m_title->setPalette(palette);
253 
254 
255     m_icon->setVisible(m_icon->pixmap() && ! m_icon->pixmap()->isNull());
256 
257     setAlign(m_hAlign, m_vAlign);
258 }
259 
setAlign(int hAlign,int vAlign)260 void LinkLabel::setAlign(int hAlign, int vAlign)
261 {
262     m_hAlign = hAlign;
263     m_vAlign = vAlign;
264 
265     if (!m_look)
266         return;
267 
268     // Define alignment flags :
269     Qt::Alignment hFlag, vFlag;
270     switch (hAlign) {
271     default:
272     case 0: hFlag = Qt::AlignLeft;    break;
273     case 1: hFlag = Qt::AlignHCenter; break;
274     case 2: hFlag = Qt::AlignRight;   break;
275     }
276     switch (vAlign) {
277     case 0: vFlag = Qt::AlignTop;     break;
278     default:
279     case 1: vFlag = Qt::AlignVCenter; break;
280     case 2: vFlag = Qt::AlignBottom;  break;
281     }
282 
283     // Clear the widget :
284     m_layout->removeItem(m_spacer1);
285     m_layout->removeWidget(m_icon);
286     m_layout->removeWidget(m_title);
287     m_layout->removeItem(m_spacer2);
288 
289     // Otherwise, minimumSize will be incoherent (last size ? )
290     m_layout->setSizeConstraint(QLayout::SetMinimumSize);
291 
292     // And re-populate the widget with the appropriates things and order
293     bool addSpacers = (hAlign == 1);
294     m_layout->setDirection(QBoxLayout::LeftToRight);
295     //m_title->setSizePolicy( QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Maximum/*Expanding*/, 0, 0, false) );
296     m_icon->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
297     m_spacer1->changeSize(QSizePolicy::Expanding, QSizePolicy::Preferred);
298     m_spacer2->changeSize(QSizePolicy::Expanding, QSizePolicy::Preferred);
299 
300     m_icon->setAlignment(hFlag | vFlag);
301     m_title->setAlignment(hFlag | vFlag);
302     if (hAlign)
303         m_title->setWordWrap(true);
304 
305     if ((addSpacers && (vAlign != 0)) ||
306             (m_title->text().isEmpty() && hAlign == 2))
307         m_layout->addItem(m_spacer1);
308     if (hAlign == 2) { // If align at right, icon is at right
309         m_layout->addWidget(m_title);
310         m_layout->addWidget(m_icon);
311     } else {
312         m_layout->addWidget(m_icon);
313         m_layout->addWidget(m_title);
314     }
315     if ((addSpacers && (vAlign != 2)) ||
316             (m_title->text().isEmpty() && hAlign == 0))
317         m_layout->addItem(m_spacer2);
318 }
319 
enterEvent(QEvent *)320 void LinkLabel::enterEvent(QEvent*)
321 {
322     m_isHovered = true;
323 
324     if (!m_isSelected) {
325         QPalette palette;
326         palette.setColor(m_title->foregroundRole(), m_look->effectiveHoverColor());
327         m_title->setPalette(palette);
328     }
329 
330     QFont font = m_title->font();
331     font.setUnderline(m_look->underlineInside());
332     m_title->setFont(font);
333 }
334 
leaveEvent(QEvent *)335 void LinkLabel::leaveEvent(QEvent*)
336 {
337     m_isHovered = false;
338 
339     if (!m_isSelected) {
340         QPalette palette;
341         palette.setColor(m_title->foregroundRole(), m_look->effectiveColor());
342         m_title->setPalette(palette);
343     }
344 
345     QFont font = m_title->font();
346     font.setUnderline(m_look->underlineOutside());
347     m_title->setFont(font);
348 }
349 
setSelected(bool selected)350 void LinkLabel::setSelected(bool selected)
351 {
352     m_isSelected = selected;
353     QPalette palette;
354 
355     if (selected)
356         palette.setColor(m_title->foregroundRole(), QApplication::palette().color(QPalette::HighlightedText));
357     else if (m_isHovered)
358         palette.setColor(m_title->foregroundRole(), m_look->effectiveHoverColor());
359     else
360         palette.setColor(m_title->foregroundRole(), m_look->effectiveColor());
361 
362     m_title->setPalette(palette);
363 }
364 
setPaletteBackgroundColor(const QColor & color)365 void LinkLabel::setPaletteBackgroundColor(const QColor &color)
366 {
367     QPalette framePalette;
368     framePalette.setColor(QFrame::foregroundRole(), color);
369     QFrame::setPalette(framePalette);
370 
371     QPalette titlePalette;
372     titlePalette.setColor(m_title->foregroundRole(), color);
373     m_title->setPalette(titlePalette);
374 }
375 
heightForWidth(int w) const376 int LinkLabel::heightForWidth(int w) const
377 {
378     int iconS  = (m_icon->isVisible()) ? m_look->iconSize()                 : 0; // Icon size
379     int iconW  = iconS;                                                          // Icon width to remove to w
380     int titleH = (m_title->isVisible()) ? m_title->heightForWidth(w - iconW) : 0; // Title height
381 
382     return (titleH >= iconS) ? titleH : iconS; // No margin for the moment !
383 }
384 
385 /** class LinkDisplay
386  */
387 
LinkDisplay()388 LinkDisplay::LinkDisplay()
389         : m_title(), m_icon(), m_preview(), m_look(0), m_font(), m_minWidth(0), m_width(0), m_height(0)
390 {
391 }
392 
setLink(const QString & title,const QString & icon,LinkLook * look,const QFont & font)393 void LinkDisplay::setLink(const QString &title, const QString &icon, LinkLook *look, const QFont &font)
394 {
395     setLink(title, icon, m_preview, look, font);
396 }
397 
setLink(const QString & title,const QString & icon,const QPixmap & preview,LinkLook * look,const QFont & font)398 void LinkDisplay::setLink(const QString &title, const QString &icon, const QPixmap &preview, LinkLook *look, const QFont &font)
399 {
400     m_title   = title;
401     m_icon    = icon;
402     m_preview = preview;
403     m_look    = look;
404     m_font    = font;
405 
406     // "Constants":
407     int BUTTON_MARGIN = qApp->style()->pixelMetric(QStyle::PM_ButtonMargin);
408     int LINK_MARGIN   = BUTTON_MARGIN + 2;
409 
410     // Recompute m_minWidth:
411     QRect textRect = QFontMetrics(labelFont(font, false)).boundingRect(0, 0, /*width=*/1, 500000, Qt::AlignLeft | Qt::AlignTop | Qt::TextWordWrap, m_title);
412     int iconPreviewWidth = qMax(m_look->iconSize(), (m_look->previewEnabled() ? m_preview.width() : 0));
413     m_minWidth = BUTTON_MARGIN - 1 + iconPreviewWidth + LINK_MARGIN + textRect.width();
414     // Recompute m_maxWidth:
415     textRect = QFontMetrics(labelFont(font, false)).boundingRect(0, 0, /*width=*/50000000, 500000, Qt::AlignLeft | Qt::AlignTop | Qt::TextWordWrap, m_title);
416     m_maxWidth = BUTTON_MARGIN - 1 + iconPreviewWidth + LINK_MARGIN + textRect.width();
417     // Adjust m_width:
418     if (m_width < m_minWidth)
419         setWidth(m_minWidth);
420     // Recompute m_height:
421     m_height = heightForWidth(m_width);
422 }
423 
setWidth(qreal width)424 void LinkDisplay::setWidth(qreal width)
425 {
426     if (width < m_minWidth)
427         width = m_minWidth;
428 
429     if (width != m_width) {
430         m_width  = width;
431         m_height = heightForWidth(m_width);
432     }
433 }
434 
435 /** Paint on @p painter
436   *       in (@p x, @p y, @p width, @p height)
437   *       using @p palette for the button drawing (if @p isHovered)
438   *       and the LinkLook color() for the text,
439   *       unless [the LinkLook !color.isValid() and it does not useLinkColor()] or [@p isDefaultColor is false]: in this case it will use @p palette's active text color.
440   *       It will draw the button if @p isIconButtonHovered.
441   */
paint(QPainter * painter,qreal x,qreal y,qreal width,qreal height,const QPalette & palette,bool isDefaultColor,bool isSelected,bool isHovered,bool isIconButtonHovered) const442 void LinkDisplay::paint(QPainter *painter, qreal x, qreal y, qreal width, qreal height, const QPalette &palette,
443                         bool isDefaultColor, bool isSelected, bool isHovered, bool isIconButtonHovered) const
444 {
445     qreal BUTTON_MARGIN = qApp->style()->pixelMetric(QStyle::PM_ButtonMargin);
446     qreal LINK_MARGIN   = BUTTON_MARGIN + 2;
447 
448     QPixmap pixmap;
449     // Load the preview...:
450     if (!isHovered && m_look->previewEnabled() && !m_preview.isNull())
451         pixmap  = m_preview;
452     // ... Or the icon (if no preview or if the "Open" icon should be shown):
453     else {
454         qreal           iconSize   = m_look->iconSize();
455         QString       iconName   = (isHovered ? Global::openNoteIcon() : m_icon);
456         KIconLoader::States iconState  = (isIconButtonHovered ? KIconLoader::ActiveState : KIconLoader::DefaultState);
457         pixmap = KIconLoader::global()->loadIcon(
458                      iconName, KIconLoader::Desktop, iconSize, iconState, QStringList(),
459                      0L, /*canReturnNull=*/false
460                  );
461     }
462     qreal iconPreviewWidth  = qMax(m_look->iconSize(), (m_look->previewEnabled() ? m_preview.width()  : 0));
463     qreal pixmapX = (iconPreviewWidth - pixmap.width()) / 2;
464     qreal pixmapY = (height - pixmap.height()) / 2;
465     // Draw the button (if any) and the icon:
466     if (isHovered) {
467         QStyleOption opt;
468         opt.rect = QRect(-1, -1, iconPreviewWidth + 2 * BUTTON_MARGIN, height + 2);
469         opt.state = isIconButtonHovered ? (QStyle::State_MouseOver | QStyle::State_Enabled)  : QStyle::State_Enabled;
470         qApp->style()->drawPrimitive(QStyle::PE_PanelButtonCommand, &opt, painter);
471     }
472     painter->drawPixmap(x + BUTTON_MARGIN - 1 + pixmapX, y + pixmapY, pixmap);
473 
474     // Figure out the text color:
475     if (isSelected) {
476         painter->setPen(qApp->palette().color(QPalette::HighlightedText));
477     } else if (isIconButtonHovered)
478         painter->setPen(m_look->effectiveHoverColor());
479     else if (!isDefaultColor || (!m_look->color().isValid() && !m_look->useLinkColor())) // If the color is FORCED or if the link color default to the text color:
480         painter->setPen(palette.color(QPalette::Active, QPalette::WindowText));
481     else
482         painter->setPen(m_look->effectiveColor());
483     // Draw the text:
484     painter->setFont(labelFont(m_font, isIconButtonHovered));
485     painter->drawText(x + BUTTON_MARGIN - 1 + iconPreviewWidth + LINK_MARGIN, y, width - BUTTON_MARGIN + 1 - iconPreviewWidth - LINK_MARGIN, height,
486                       Qt::AlignLeft | Qt::AlignVCenter | Qt::TextWordWrap, m_title);
487 }
488 
feedbackPixmap(qreal width,qreal height,const QPalette & palette,bool isDefaultColor)489 QPixmap LinkDisplay::feedbackPixmap(qreal width, qreal height, const QPalette &palette, bool isDefaultColor)
490 {
491     qreal theWidth  = qMin(width, maxWidth());
492     qreal theHeight = qMin(height, heightForWidth(theWidth));
493     QPixmap pixmap(theWidth, theHeight);
494     pixmap.fill(palette.color(QPalette::Active, QPalette::Background));
495     QPainter painter(&pixmap);
496     paint(&painter, 0, 0, theWidth, theHeight, palette, isDefaultColor,
497           /*isSelected=*/false, /*isHovered=*/false, /*isIconButtonHovered=*/false);
498     painter.end();
499     return pixmap;
500 }
501 
iconButtonAt(const QPointF & pos) const502 bool LinkDisplay::iconButtonAt(const QPointF &pos) const
503 {
504     qreal BUTTON_MARGIN    = qApp->style()->pixelMetric(QStyle::PM_ButtonMargin);
505 //  int LINK_MARGIN      = BUTTON_MARGIN + 2;
506     qreal iconPreviewWidth = qMax(m_look->iconSize(), (m_look->previewEnabled() ? m_preview.width()  : 0));
507 
508     return pos.x() <= BUTTON_MARGIN - 1 + iconPreviewWidth + BUTTON_MARGIN;
509 }
510 
iconButtonRect() const511 QRectF LinkDisplay::iconButtonRect() const
512 {
513     qreal BUTTON_MARGIN    = qApp->style()->pixelMetric(QStyle::PM_ButtonMargin);
514 //  int LINK_MARGIN      = BUTTON_MARGIN + 2;
515     qreal iconPreviewWidth = qMax(m_look->iconSize(), (m_look->previewEnabled() ? m_preview.width()  : 0));
516 
517     return QRectF(0, 0, BUTTON_MARGIN - 1 + iconPreviewWidth + BUTTON_MARGIN, m_height);
518 }
519 
labelFont(QFont font,bool isIconButtonHovered) const520 QFont LinkDisplay::labelFont(QFont font, bool isIconButtonHovered) const
521 {
522     if (m_look->italic())
523         font.setItalic(true);
524     if (m_look->bold())
525         font.setBold(true);
526     if (isIconButtonHovered) {
527         if (m_look->underlineInside())
528             font.setUnderline(true);
529     } else {
530         if (m_look->underlineOutside())
531             font.setUnderline(true);
532     }
533     return font;
534 }
535 
heightForWidth(qreal width) const536 qreal LinkDisplay::heightForWidth(qreal width) const
537 {
538     qreal BUTTON_MARGIN     = qApp->style()->pixelMetric(QStyle::PM_ButtonMargin);
539     qreal LINK_MARGIN       = BUTTON_MARGIN + 2;
540     qreal iconPreviewWidth  = qMax(m_look->iconSize(), (m_look->previewEnabled() ? m_preview.width()  : 0));
541     qreal iconPreviewHeight = qMax(m_look->iconSize(), (m_look->previewEnabled() ? m_preview.height() : 0));
542 
543     QRectF textRect = QFontMetrics(labelFont(m_font, false)).boundingRect(0, 0, width - BUTTON_MARGIN + 1 - iconPreviewWidth - LINK_MARGIN, 500000, Qt::AlignLeft | Qt::AlignTop | Qt::TextWordWrap, m_title);
544     return qMax(textRect.height(), iconPreviewHeight + 2*BUTTON_MARGIN - 2);
545 }
546 
toHtml(const QString &) const547 QString LinkDisplay::toHtml(const QString &/*imageName*/) const
548 {
549     // TODO
550     return "";
551 }
552 
toHtml(HTMLExporter * exporter,const QUrl & url,const QString & title)553 QString LinkDisplay::toHtml(HTMLExporter *exporter, const QUrl &url, const QString &title)
554 {
555     QString linkIcon;
556     if (m_look->previewEnabled() && !m_preview.isNull()) {
557         QString fileName = Tools::fileNameForNewFile("preview_" + url.fileName() + ".png", exporter->iconsFolderPath);
558         QString fullPath = exporter->iconsFolderPath + fileName;
559         m_preview.save(fullPath, "PNG");
560         linkIcon = QString("<img src=\"%1\" width=\"%2\" height=\"%3\" alt=\"\">")
561                    .arg(exporter->iconsFolderName + fileName, QString::number(m_preview.width()), QString::number(m_preview.height()));
562     } else {
563         linkIcon = exporter->iconsFolderName + exporter->copyIcon(m_icon, m_look->iconSize());
564         linkIcon = QString("<img src=\"%1\" width=\"%2\" height=\"%3\" alt=\"\">")
565                    .arg(linkIcon, QString::number(m_look->iconSize()), QString::number(m_look->iconSize()));
566     }
567 
568     QString linkTitle = Tools::textToHTMLWithoutP(title.isEmpty() ? m_title : title);
569 
570     return QString("<a href=\"%1\">%2 %3</a>").arg(url.toDisplayString(), linkIcon, linkTitle);
571 }
572 
573 /** LinkLookEditWidget **/
574 
LinkLookEditWidget(KCModule * module,const QString exTitle,const QString exIcon,QWidget * parent,Qt::WindowFlags fl)575 LinkLookEditWidget::LinkLookEditWidget(KCModule *module, const QString exTitle, const QString exIcon,
576                                        QWidget *parent, Qt::WindowFlags fl)
577         : QWidget(parent, fl)
578 {
579     QLabel      *label;
580     QVBoxLayout *layout = new QVBoxLayout(this);
581 
582     m_italic = new QCheckBox(i18n("I&talic"), this);
583     layout->addWidget(m_italic);
584 
585     m_bold = new QCheckBox(i18n("&Bold"), this);
586     layout->addWidget(m_bold);
587 
588     QGridLayout *gl = new QGridLayout;
589     layout->addLayout(gl);
590     gl->addItem(new QSpacerItem(0, 0, QSizePolicy::Expanding), 1, /*2*/3);
591 
592     m_underlining = new KComboBox(this);
593     m_underlining->addItem(i18n("Always"));
594     m_underlining->addItem(i18n("Never"));
595     m_underlining->addItem(i18n("On mouse hovering"));
596     m_underlining->addItem(i18n("When mouse is outside"));
597     label = new QLabel(this);
598     label->setText(i18n("&Underline:"));
599     label->setBuddy(m_underlining);
600     gl->addWidget(label, 0, 0);
601     gl->addWidget(m_underlining, 0, 1);
602 
603     m_color = new KColorCombo2(QRgb(), this);
604     label = new QLabel(this);
605     label->setText(i18n("Colo&r:"));
606     label->setBuddy(m_color);
607     gl->addWidget(label,   1, 0);
608     gl->addWidget(m_color, 1, 1);
609 
610     m_hoverColor = new KColorCombo2(QRgb(), this);
611     label = new QLabel(this);
612     label->setText(i18n("&Mouse hover color:"));
613     label->setBuddy(m_hoverColor);
614     gl->addWidget(label,        2, 0);
615     gl->addWidget(m_hoverColor, 2, 1);
616 
617     QHBoxLayout *icoLay = new QHBoxLayout(0);
618     m_iconSize = new IconSizeCombo(this);
619     icoLay->addWidget(m_iconSize);
620     label = new QLabel(this);
621     label->setText(i18n("&Icon size:"));
622     label->setBuddy(m_iconSize);
623     gl->addWidget(label,  3, 0);
624     gl->addItem(icoLay, 3, 1);
625 
626     m_preview = new KComboBox(this);
627     m_preview->addItem(i18n("None"));
628     m_preview->addItem(i18n("Icon size"));
629     m_preview->addItem(i18n("Twice the icon size"));
630     m_preview->addItem(i18n("Three times the icon size"));
631     m_label = new QLabel(this);
632     m_label->setText(i18n("&Preview:"));
633     m_label->setBuddy(m_preview);
634     m_hLabel = new HelpLabel(
635         i18n("You disabled preview but still see images?"),
636         i18n("<p>This is normal because there are several type of notes.<br>"
637              "This setting only applies to file and local link notes.<br>"
638              "The images you see are image notes, not file notes.<br>"
639              "File notes are generic documents, whereas image notes are pictures you can draw in.</p>"
640              "<p>When dropping files to baskets, %1 detects their type and shows you the content of the files.<br>"
641              "For instance, when dropping image or text files, image and text notes are created for them.<br>"
642              "For type of files %2 does not understand, they are shown as generic file notes with just an icon or file preview and a filename.</p>"
643              "<p>If you do not want the application to create notes depending on the content of the files you drop, "
644              "go to the \"General\" page and uncheck \"Image or animation\" in the \"View Content of Added Files for the Following Types\" group.</p>",
645              // TODO: Note: you can resize down maximum size of images...
646              QGuiApplication::applicationDisplayName(), QGuiApplication::applicationDisplayName()),
647         this);
648     gl->addWidget(m_label,   4, 0);
649     gl->addWidget(m_preview, 4, 1);
650     gl->addWidget(m_hLabel, 5, 1, 1, 2);
651 
652     QGroupBox *gb = new QGroupBox(i18n("Example"), this);
653     QHBoxLayout* gbLayout = new QHBoxLayout;
654     gb->setLayout(gbLayout);
655 
656     m_exLook = new LinkLook;
657     m_example = new LinkLabel(exTitle, exIcon, m_exLook, 1, 1);
658     gbLayout->addWidget(m_example);
659     m_example->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
660     m_example->setCursor(QCursor(Qt::PointingHandCursor));
661     layout->addWidget(gb);
662     m_exTitle = exTitle;
663     m_exIcon  = exIcon;
664 
665     connect(m_italic,      SIGNAL(stateChanged(int)),      this,   SLOT(slotChangeLook()));
666     connect(m_bold,        SIGNAL(stateChanged(int)),      this,   SLOT(slotChangeLook()));
667     connect(m_underlining, SIGNAL(activated(int)),         this,   SLOT(slotChangeLook()));
668     connect(m_color,       SIGNAL(activated(int)), this,   SLOT(slotChangeLook()));
669     connect(m_hoverColor,  SIGNAL(activated(int)), this,   SLOT(slotChangeLook()));
670     connect(m_iconSize,    SIGNAL(activated(int)),         this,   SLOT(slotChangeLook()));
671     connect(m_preview,     SIGNAL(activated(int)),         this,   SLOT(slotChangeLook()));
672 
673     connect(m_italic,      SIGNAL(stateChanged(int)),      module, SLOT(changed()));
674     connect(m_bold,        SIGNAL(stateChanged(int)),      module, SLOT(changed()));
675     connect(m_underlining, SIGNAL(activated(int)),         module, SLOT(changed()));
676     connect(m_color,       SIGNAL(activated(int)), module, SLOT(changed()));
677     connect(m_hoverColor,  SIGNAL(activated(int)), module, SLOT(changed()));
678     connect(m_iconSize,    SIGNAL(activated(int)),         module, SLOT(changed()));
679     connect(m_preview,     SIGNAL(activated(int)),         module, SLOT(changed()));
680 }
681 
set(LinkLook * look)682 void LinkLookEditWidget::set(LinkLook *look)
683 {
684     m_look = look;
685 
686     m_italic->setChecked(look->italic());
687     m_bold->setChecked(look->bold());
688     m_underlining->setCurrentIndex(look->underlining());
689     m_preview->setCurrentIndex(look->preview());
690     m_color->setDefaultColor(m_look->defaultColor());
691     m_color->setColor(m_look->color());
692     m_hoverColor->setDefaultColor(m_look->defaultHoverColor());
693     m_hoverColor->setColor(m_look->hoverColor());
694     m_iconSize->setSize(look->iconSize());
695     m_exLook = new LinkLook(*look);
696     m_example->setLook(m_exLook);
697 
698     if (!look->canPreview()) {
699         m_label->setEnabled(false);
700         m_hLabel->setEnabled(false);
701         m_preview->setEnabled(false);
702     }
703     slotChangeLook();
704 }
705 
slotChangeLook()706 void LinkLookEditWidget::slotChangeLook()
707 {
708     saveToLook(m_exLook);
709     m_example->setLink(m_exTitle, m_exIcon, m_exLook); // and can't reload it at another size
710 }
711 
~LinkLookEditWidget()712 LinkLookEditWidget::~LinkLookEditWidget()
713 {
714 }
715 
saveChanges()716 void LinkLookEditWidget::saveChanges()
717 {
718     saveToLook(m_look);
719 }
720 
saveToLook(LinkLook * look)721 void LinkLookEditWidget::saveToLook(LinkLook *look)
722 {
723     look->setLook(m_italic->isChecked(), m_bold->isChecked(), m_underlining->currentIndex(),
724                   m_color->color(), m_hoverColor->color(),
725                   m_iconSize->iconSize(), (look->canPreview() ? m_preview->currentIndex() : LinkLook::None));
726 }
727 
728