File indexing completed on 2022-09-27 16:29:16

0001 /**
0002  * SPDX-FileCopyrightText: (C) 2003 Sébastien Laoût <slaout@linux62.org>
0003  *
0004  * SPDX-License-Identifier: GPL-2.0-or-later
0005  */
0006 
0007 #include "linklabel.h"
0008 
0009 #include <QApplication>
0010 #include <QBoxLayout>
0011 #include <QCheckBox>
0012 #include <QCursor>
0013 #include <QFrame>
0014 #include <QGridLayout>
0015 #include <QGroupBox>
0016 #include <QHBoxLayout>
0017 #include <QLabel>
0018 #include <QLayout>
0019 #include <QLocale>
0020 #include <QPainter>
0021 #include <QPixmap>
0022 #include <QStyle>
0023 #include <QUrl>
0024 #include <QVBoxLayout>
0025 #include <QtCore/QEvent>
0026 
0027 #include <KAboutData>
0028 #include <KCModule>
0029 #include <KComboBox>
0030 #include <KIconLoader>
0031 #include <KLocalizedString>
0032 
0033 #include "global.h"
0034 #include "htmlexporter.h"
0035 #include "kcolorcombo2.h"
0036 #include "tools.h"
0037 #include "variouswidgets.h"
0038 
0039 /** LinkLook */
0040 
0041 LinkLook *LinkLook::soundLook = new LinkLook(/*useLinkColor=*/false, /*canPreview=*/false);
0042 LinkLook *LinkLook::fileLook = new LinkLook(/*useLinkColor=*/false, /*canPreview=*/true);
0043 LinkLook *LinkLook::localLinkLook = new LinkLook(/*useLinkColor=*/true, /*canPreview=*/true);
0044 LinkLook *LinkLook::networkLinkLook = new LinkLook(/*useLinkColor=*/true, /*canPreview=*/false);
0045 LinkLook *LinkLook::launcherLook = new LinkLook(/*useLinkColor=*/true, /*canPreview=*/false);
0046 LinkLook *LinkLook::crossReferenceLook = new LinkLook(/*useLinkColor=*/true, /*canPreview=*/false);
0047 
0048 LinkLook::LinkLook(bool useLinkColor, bool canPreview)
0049 {
0050     m_useLinkColor = useLinkColor;
0051     m_canPreview = canPreview;
0052     m_iconSize = 0;
0053 }
0054 
0055 LinkLook::LinkLook(const LinkLook &other)
0056 {
0057     m_useLinkColor = other.useLinkColor();
0058     m_canPreview = other.canPreview();
0059     setLook(other.italic(), other.bold(), other.underlining(), other.color(), other.hoverColor(), other.iconSize(), other.preview());
0060 }
0061 
0062 void LinkLook::setLook(bool italic, bool bold, int underlining, QColor color, QColor hoverColor, int iconSize, int preview)
0063 {
0064     m_italic = italic;
0065     m_bold = bold;
0066     m_underlining = underlining;
0067     m_color = color;
0068     m_hoverColor = hoverColor;
0069     m_iconSize = iconSize;
0070     m_preview = (canPreview() ? preview : None);
0071 }
0072 
0073 int LinkLook::previewSize() const
0074 {
0075     if (previewEnabled()) {
0076         switch (preview()) {
0077         default:
0078         case None:
0079             return 0;
0080         case IconSize:
0081             return iconSize();
0082         case TwiceIconSize:
0083             return iconSize() * 2;
0084         case ThreeIconSize:
0085             return iconSize() * 3;
0086         }
0087     } else
0088         return 0;
0089 }
0090 
0091 QColor LinkLook::effectiveColor() const
0092 {
0093     if (m_color.isValid())
0094         return m_color;
0095     else
0096         return defaultColor();
0097 }
0098 
0099 QColor LinkLook::effectiveHoverColor() const
0100 {
0101     if (m_hoverColor.isValid())
0102         return m_hoverColor;
0103     else
0104         return defaultHoverColor();
0105 }
0106 
0107 QColor LinkLook::defaultColor() const
0108 {
0109     if (m_useLinkColor)
0110         return qApp->palette().color(QPalette::Link);
0111     else
0112         return qApp->palette().color(QPalette::Text);
0113 }
0114 
0115 QColor LinkLook::defaultHoverColor() const
0116 {
0117     return Qt::red;
0118 }
0119 
0120 LinkLook *LinkLook::lookForURL(const QUrl &url)
0121 {
0122     return url.isLocalFile() ? localLinkLook : networkLinkLook;
0123 }
0124 
0125 QString LinkLook::toCSS(const QString &cssClass, const QColor &defaultTextColor) const
0126 {
0127     // Set the link class:
0128     QString css = QString("{ display: block; width: 100%;");
0129     if (underlineOutside())
0130         css += " text-decoration: underline;";
0131     else
0132         css += " text-decoration: none;";
0133     if (m_italic == true)
0134         css += " font-style: italic;";
0135     if (m_bold == true)
0136         css += " font-weight: bold;";
0137     QColor textColor = (color().isValid() || m_useLinkColor ? effectiveColor() : defaultTextColor);
0138     css += QString(" color: %1; }\n").arg(textColor.name());
0139 
0140     QString css2 = css;
0141     css.prepend(QString("   .%1 a").arg(cssClass));
0142     css2.prepend(QString("   a.%1").arg(cssClass));
0143 
0144     // Set the hover state class:
0145     QString hover;
0146     if (m_underlining == OnMouseHover)
0147         hover = "text-decoration: underline;";
0148     else if (m_underlining == OnMouseOutside)
0149         hover = "text-decoration: none;";
0150     if (effectiveHoverColor() != effectiveColor()) {
0151         if (!hover.isEmpty())
0152             hover += ' ';
0153         hover += QString("color: %4;").arg(effectiveHoverColor().name());
0154     }
0155 
0156     // But include it only if it contain a different style than non-hover state:
0157     if (!hover.isEmpty()) {
0158         css += QString("   .%1 a:hover { %2 }\n").arg(cssClass, hover);
0159         css2 += QString("    a:hover.%1 { %2 }\n").arg(cssClass, hover);
0160     }
0161     return css + css2;
0162 }
0163 
0164 /** LinkLabel */
0165 
0166 LinkLabel::LinkLabel(int hAlign, int vAlign, QWidget *parent, Qt::WindowFlags f)
0167     : QFrame(parent, f)
0168     , m_isSelected(false)
0169     , m_isHovered(false)
0170     , m_look(nullptr)
0171 {
0172     initLabel(hAlign, vAlign);
0173 }
0174 
0175 LinkLabel::LinkLabel(const QString &title, const QString &icon, LinkLook *look, int hAlign, int vAlign, QWidget *parent, Qt::WindowFlags f)
0176     : QFrame(parent, f)
0177     , m_isSelected(false)
0178     , m_isHovered(false)
0179     , m_look(nullptr)
0180 {
0181     initLabel(hAlign, vAlign);
0182     setLink(title, icon, look);
0183 }
0184 
0185 void LinkLabel::initLabel(int hAlign, int vAlign)
0186 {
0187     m_layout = new QBoxLayout(QBoxLayout::LeftToRight, this);
0188     m_icon = new QLabel(this);
0189     m_title = new QLabel(this);
0190     m_spacer1 = new QSpacerItem(0, 0, QSizePolicy::Preferred /*Expanding*/, QSizePolicy::Preferred /*Expanding*/);
0191     m_spacer2 = new QSpacerItem(0, 0, QSizePolicy::Preferred /*Expanding*/, QSizePolicy::Preferred /*Expanding*/);
0192 
0193     m_hAlign = hAlign;
0194     m_vAlign = vAlign;
0195 
0196     m_title->setTextFormat(Qt::PlainText);
0197 
0198     // DEGUB:
0199     // m_icon->setPaletteBackgroundColor("lightblue");
0200     // m_title->setPaletteBackgroundColor("lightyellow");
0201 }
0202 
0203 LinkLabel::~LinkLabel()
0204 {
0205 }
0206 
0207 void LinkLabel::setLink(const QString &title, const QString &icon, LinkLook *look)
0208 {
0209     if (look)
0210         m_look = look; // Needed for icon size
0211 
0212     m_title->setText(title);
0213     m_title->setVisible(!title.isEmpty());
0214 
0215     if (icon.isEmpty())
0216         m_icon->clear();
0217     else {
0218         QPixmap pixmap = QIcon::fromTheme(icon).pixmap(m_look->iconSize());
0219         if (!pixmap.isNull())
0220             m_icon->setPixmap(pixmap);
0221     }
0222     m_icon->setVisible(!icon.isEmpty());
0223 
0224     if (look)
0225         setLook(look);
0226 }
0227 
0228 void LinkLabel::setLook(LinkLook *look) // FIXME: called externally (so, without setLink()) it's buggy (icon not
0229 {
0230     m_look = look;
0231 
0232     QFont font;
0233     font.setBold(look->bold());
0234     font.setUnderline(look->underlineOutside());
0235     font.setItalic(look->italic());
0236     m_title->setFont(font);
0237     QPalette palette;
0238     if (m_isSelected)
0239         palette.setColor(m_title->foregroundRole(), QApplication::palette().color(QPalette::Text));
0240     else
0241         palette.setColor(m_title->foregroundRole(), look->effectiveColor());
0242 
0243     m_title->setPalette(palette);
0244 #if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
0245     m_icon->setVisible(!m_icon->pixmap(Qt::ReturnByValueConstant::ReturnByValue).isNull());
0246 #else
0247     m_icon->setVisible(m_icon->pixmap() && !m_icon->pixmap()->isNull());
0248 #endif
0249     setAlign(m_hAlign, m_vAlign);
0250 }
0251 
0252 void LinkLabel::setAlign(int hAlign, int vAlign)
0253 {
0254     m_hAlign = hAlign;
0255     m_vAlign = vAlign;
0256 
0257     if (!m_look)
0258         return;
0259 
0260     // Define alignment flags :
0261     Qt::Alignment hFlag, vFlag;
0262     switch (hAlign) {
0263     default:
0264     case 0:
0265         hFlag = Qt::AlignLeft;
0266         break;
0267     case 1:
0268         hFlag = Qt::AlignHCenter;
0269         break;
0270     case 2:
0271         hFlag = Qt::AlignRight;
0272         break;
0273     }
0274     switch (vAlign) {
0275     case 0:
0276         vFlag = Qt::AlignTop;
0277         break;
0278     default:
0279     case 1:
0280         vFlag = Qt::AlignVCenter;
0281         break;
0282     case 2:
0283         vFlag = Qt::AlignBottom;
0284         break;
0285     }
0286 
0287     // Clear the widget :
0288     m_layout->removeItem(m_spacer1);
0289     m_layout->removeWidget(m_icon);
0290     m_layout->removeWidget(m_title);
0291     m_layout->removeItem(m_spacer2);
0292 
0293     // Otherwise, minimumSize will be incoherent (last size ? )
0294     m_layout->setSizeConstraint(QLayout::SetMinimumSize);
0295 
0296     // And re-populate the widget with the appropriates things and order
0297     bool addSpacers = (hAlign == 1);
0298     m_layout->setDirection(QBoxLayout::LeftToRight);
0299     // m_title->setSizePolicy( QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Maximum/*Expanding*/, 0, 0, false) );
0300     m_icon->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
0301     m_spacer1->changeSize(QSizePolicy::Expanding, QSizePolicy::Preferred);
0302     m_spacer2->changeSize(QSizePolicy::Expanding, QSizePolicy::Preferred);
0303 
0304     m_icon->setAlignment(hFlag | vFlag);
0305     m_title->setAlignment(hFlag | vFlag);
0306     if (hAlign)
0307         m_title->setWordWrap(true);
0308 
0309     if ((addSpacers && (vAlign != 0)) || (m_title->text().isEmpty() && hAlign == 2))
0310         m_layout->addItem(m_spacer1);
0311     if (hAlign == 2) { // If align at right, icon is at right
0312         m_layout->addWidget(m_title);
0313         m_layout->addWidget(m_icon);
0314     } else {
0315         m_layout->addWidget(m_icon);
0316         m_layout->addWidget(m_title);
0317     }
0318     if ((addSpacers && (vAlign != 2)) || (m_title->text().isEmpty() && hAlign == 0))
0319         m_layout->addItem(m_spacer2);
0320 }
0321 
0322 void LinkLabel::enterEvent(QEvent *)
0323 {
0324     m_isHovered = true;
0325 
0326     if (!m_isSelected) {
0327         QPalette palette;
0328         palette.setColor(m_title->foregroundRole(), m_look->effectiveHoverColor());
0329         m_title->setPalette(palette);
0330     }
0331 
0332     QFont font = m_title->font();
0333     font.setUnderline(m_look->underlineInside());
0334     m_title->setFont(font);
0335 }
0336 
0337 void LinkLabel::leaveEvent(QEvent *)
0338 {
0339     m_isHovered = false;
0340 
0341     if (!m_isSelected) {
0342         QPalette palette;
0343         palette.setColor(m_title->foregroundRole(), m_look->effectiveColor());
0344         m_title->setPalette(palette);
0345     }
0346 
0347     QFont font = m_title->font();
0348     font.setUnderline(m_look->underlineOutside());
0349     m_title->setFont(font);
0350 }
0351 
0352 void LinkLabel::setSelected(bool selected)
0353 {
0354     m_isSelected = selected;
0355     QPalette palette;
0356 
0357     if (selected)
0358         palette.setColor(m_title->foregroundRole(), QApplication::palette().color(QPalette::HighlightedText));
0359     else if (m_isHovered)
0360         palette.setColor(m_title->foregroundRole(), m_look->effectiveHoverColor());
0361     else
0362         palette.setColor(m_title->foregroundRole(), m_look->effectiveColor());
0363 
0364     m_title->setPalette(palette);
0365 }
0366 
0367 void LinkLabel::setPaletteBackgroundColor(const QColor &color)
0368 {
0369     QPalette framePalette;
0370     framePalette.setColor(QFrame::foregroundRole(), color);
0371     QFrame::setPalette(framePalette);
0372 
0373     QPalette titlePalette;
0374     titlePalette.setColor(m_title->foregroundRole(), color);
0375     m_title->setPalette(titlePalette);
0376 }
0377 
0378 int LinkLabel::heightForWidth(int w) const
0379 {
0380     int iconS = (m_icon->isVisible()) ? m_look->iconSize() : 0;                   // Icon size
0381     int iconW = iconS;                                                            // Icon width to remove to w
0382     int titleH = (m_title->isVisible()) ? m_title->heightForWidth(w - iconW) : 0; // Title height
0383 
0384     return (titleH >= iconS) ? titleH : iconS; // No margin for the moment !
0385 }
0386 
0387 /** class LinkDisplay
0388  */
0389 
0390 LinkDisplay::LinkDisplay()
0391     : m_title()
0392     , m_icon()
0393     , m_preview()
0394     , m_look(nullptr)
0395     , m_font()
0396     , m_minWidth(0)
0397     , m_width(0)
0398     , m_height(0)
0399 {
0400 }
0401 
0402 void LinkDisplay::setLink(const QString &title, const QString &icon, LinkLook *look, const QFont &font)
0403 {
0404     setLink(title, icon, m_preview, look, font);
0405 }
0406 
0407 void LinkDisplay::setLink(const QString &title, const QString &icon, const QPixmap &preview, LinkLook *look, const QFont &font)
0408 {
0409     m_title = title;
0410     m_icon = icon;
0411     m_preview = preview;
0412     m_look = look;
0413     m_font = font;
0414 
0415     // "Constants":
0416     int BUTTON_MARGIN = qApp->style()->pixelMetric(QStyle::PM_ButtonMargin);
0417     int LINK_MARGIN = BUTTON_MARGIN + 2;
0418 
0419     // Recompute m_minWidth:
0420     QRect textRect = QFontMetrics(labelFont(font, false)).boundingRect(0, 0, /*width=*/1, 500000, Qt::AlignLeft | Qt::AlignTop | Qt::TextWordWrap, m_title);
0421     int iconPreviewWidth = qMax(m_look->iconSize(), (m_look->previewEnabled() ? m_preview.width() : 0));
0422     m_minWidth = BUTTON_MARGIN - 1 + iconPreviewWidth + LINK_MARGIN + textRect.width();
0423     // Recompute m_maxWidth:
0424     textRect = QFontMetrics(labelFont(font, false)).boundingRect(0, 0, /*width=*/50000000, 500000, Qt::AlignLeft | Qt::AlignTop | Qt::TextWordWrap, m_title);
0425     m_maxWidth = BUTTON_MARGIN - 1 + iconPreviewWidth + LINK_MARGIN + textRect.width();
0426     // Adjust m_width:
0427     if (m_width < m_minWidth)
0428         setWidth(m_minWidth);
0429     // Recompute m_height:
0430     m_height = heightForWidth(m_width);
0431 }
0432 
0433 void LinkDisplay::setWidth(qreal width)
0434 {
0435     if (width < m_minWidth)
0436         width = m_minWidth;
0437 
0438     if (width != m_width) {
0439         m_width = width;
0440         m_height = heightForWidth(m_width);
0441     }
0442 }
0443 
0444 /** Paint on @p painter
0445  *       in (@p x, @p y, @p width, @p height)
0446  *       using @p palette for the button drawing (if @p isHovered)
0447  *       and the LinkLook color() for the text,
0448  *       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.
0449  *       It will draw the button if @p isIconButtonHovered.
0450  */
0451 void LinkDisplay::paint(QPainter *painter, qreal x, qreal y, qreal width, qreal height, const QPalette &palette, bool isDefaultColor, bool isSelected, bool isHovered, bool isIconButtonHovered) const
0452 {
0453     qreal BUTTON_MARGIN = qApp->style()->pixelMetric(QStyle::PM_ButtonMargin);
0454     qreal LINK_MARGIN = BUTTON_MARGIN + 2;
0455 
0456     QPixmap pixmap;
0457     // Load the preview...:
0458     if (!isHovered && m_look->previewEnabled() && !m_preview.isNull())
0459         pixmap = m_preview;
0460     // ... Or the icon (if no preview or if the "Open" icon should be shown):
0461     else {
0462         qreal iconSize = m_look->iconSize();
0463         QString iconName = (isHovered ? Global::openNoteIcon() : m_icon);
0464         KIconLoader::States iconState = (isIconButtonHovered ? KIconLoader::ActiveState : KIconLoader::DefaultState);
0465         pixmap = KIconLoader::global()->loadIcon(iconName, KIconLoader::Desktop, iconSize, iconState, QStringList(), nullptr, /*canReturnNull=*/false);
0466     }
0467     qreal iconPreviewWidth = qMax(m_look->iconSize(), (m_look->previewEnabled() ? m_preview.width() : 0));
0468     qreal pixmapX = (iconPreviewWidth - pixmap.width()) / 2;
0469     qreal pixmapY = (height - pixmap.height()) / 2;
0470     // Draw the button (if any) and the icon:
0471     if (isHovered) {
0472         QStyleOption opt;
0473         opt.rect = QRect(-1, -1, iconPreviewWidth + 2 * BUTTON_MARGIN, height + 2);
0474         opt.state = isIconButtonHovered ? (QStyle::State_MouseOver | QStyle::State_Enabled) : QStyle::State_Enabled;
0475         qApp->style()->drawPrimitive(QStyle::PE_PanelButtonCommand, &opt, painter);
0476     }
0477     painter->drawPixmap(x + BUTTON_MARGIN - 1 + pixmapX, y + pixmapY, pixmap);
0478 
0479     // Figure out the text color:
0480     if (isSelected) {
0481         painter->setPen(qApp->palette().color(QPalette::HighlightedText));
0482     } else if (isIconButtonHovered)
0483         painter->setPen(m_look->effectiveHoverColor());
0484     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:
0485         painter->setPen(palette.color(QPalette::Active, QPalette::WindowText));
0486     else
0487         painter->setPen(m_look->effectiveColor());
0488     // Draw the text:
0489     painter->setFont(labelFont(m_font, isIconButtonHovered));
0490     painter->drawText(x + BUTTON_MARGIN - 1 + iconPreviewWidth + LINK_MARGIN, y, width - BUTTON_MARGIN + 1 - iconPreviewWidth - LINK_MARGIN, height, Qt::AlignLeft | Qt::AlignVCenter | Qt::TextWordWrap, m_title);
0491 }
0492 
0493 QPixmap LinkDisplay::feedbackPixmap(qreal width, qreal height, const QPalette &palette, bool isDefaultColor)
0494 {
0495     qreal theWidth = qMin(width, maxWidth());
0496     qreal theHeight = qMin(height, heightForWidth(theWidth));
0497     QPixmap pixmap(theWidth, theHeight);
0498     pixmap.fill(palette.color(QPalette::Active, QPalette::Background));
0499     QPainter painter(&pixmap);
0500     paint(&painter,
0501           0,
0502           0,
0503           theWidth,
0504           theHeight,
0505           palette,
0506           isDefaultColor,
0507           /*isSelected=*/false,
0508           /*isHovered=*/false,
0509           /*isIconButtonHovered=*/false);
0510     painter.end();
0511     return pixmap;
0512 }
0513 
0514 bool LinkDisplay::iconButtonAt(const QPointF &pos) const
0515 {
0516     qreal BUTTON_MARGIN = qApp->style()->pixelMetric(QStyle::PM_ButtonMargin);
0517     //  int LINK_MARGIN      = BUTTON_MARGIN + 2;
0518     qreal iconPreviewWidth = qMax(m_look->iconSize(), (m_look->previewEnabled() ? m_preview.width() : 0));
0519 
0520     return pos.x() <= BUTTON_MARGIN - 1 + iconPreviewWidth + BUTTON_MARGIN;
0521 }
0522 
0523 QRectF LinkDisplay::iconButtonRect() const
0524 {
0525     qreal BUTTON_MARGIN = qApp->style()->pixelMetric(QStyle::PM_ButtonMargin);
0526     //  int LINK_MARGIN      = BUTTON_MARGIN + 2;
0527     qreal iconPreviewWidth = qMax(m_look->iconSize(), (m_look->previewEnabled() ? m_preview.width() : 0));
0528 
0529     return QRectF(0, 0, BUTTON_MARGIN - 1 + iconPreviewWidth + BUTTON_MARGIN, m_height);
0530 }
0531 
0532 QFont LinkDisplay::labelFont(QFont font, bool isIconButtonHovered) const
0533 {
0534     if (m_look->italic())
0535         font.setItalic(true);
0536     if (m_look->bold())
0537         font.setBold(true);
0538     if (isIconButtonHovered) {
0539         if (m_look->underlineInside())
0540             font.setUnderline(true);
0541     } else {
0542         if (m_look->underlineOutside())
0543             font.setUnderline(true);
0544     }
0545     return font;
0546 }
0547 
0548 qreal LinkDisplay::heightForWidth(qreal width) const
0549 {
0550     qreal BUTTON_MARGIN = qApp->style()->pixelMetric(QStyle::PM_ButtonMargin);
0551     qreal LINK_MARGIN = BUTTON_MARGIN + 2;
0552     qreal iconPreviewWidth = qMax(m_look->iconSize(), (m_look->previewEnabled() ? m_preview.width() : 0));
0553     qreal iconPreviewHeight = qMax(m_look->iconSize(), (m_look->previewEnabled() ? m_preview.height() : 0));
0554 
0555     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);
0556     return qMax(textRect.height(), iconPreviewHeight + 2 * BUTTON_MARGIN - 2);
0557 }
0558 
0559 QString LinkDisplay::toHtml(const QString & /*imageName*/) const
0560 {
0561     // TODO
0562     return QString();
0563 }
0564 
0565 QString LinkDisplay::toHtml(HTMLExporter *exporter, const QUrl &url, const QString &title)
0566 {
0567     QString linkIcon;
0568     if (m_look->previewEnabled() && !m_preview.isNull()) {
0569         QString fileName = Tools::fileNameForNewFile("preview_" + url.fileName() + ".png", exporter->iconsFolderPath);
0570         QString fullPath = exporter->iconsFolderPath + fileName;
0571         m_preview.save(fullPath, "PNG");
0572         linkIcon = QString("<img src=\"%1\" width=\"%2\" height=\"%3\" alt=\"\">").arg(exporter->iconsFolderName + fileName, QString::number(m_preview.width()), QString::number(m_preview.height()));
0573     } else {
0574         linkIcon = exporter->iconsFolderName + exporter->copyIcon(m_icon, m_look->iconSize());
0575         linkIcon = QString("<img src=\"%1\" width=\"%2\" height=\"%3\" alt=\"\">").arg(linkIcon, QString::number(m_look->iconSize()), QString::number(m_look->iconSize()));
0576     }
0577 
0578     QString linkTitle = Tools::textToHTMLWithoutP(title.isEmpty() ? m_title : title);
0579 
0580     return QString("<a href=\"%1\">%2 %3</a>").arg(url.toDisplayString(), linkIcon, linkTitle);
0581 }
0582 
0583 /** LinkLookEditWidget **/
0584 
0585 LinkLookEditWidget::LinkLookEditWidget(KCModule *module, const QString exTitle, const QString exIcon, QWidget *parent, Qt::WindowFlags fl)
0586     : QWidget(parent, fl)
0587 {
0588     QLabel *label;
0589     QVBoxLayout *layout = new QVBoxLayout(this);
0590 
0591     m_italic = new QCheckBox(i18n("I&talic"), this);
0592     layout->addWidget(m_italic);
0593 
0594     m_bold = new QCheckBox(i18n("&Bold"), this);
0595     layout->addWidget(m_bold);
0596 
0597     QGridLayout *gl = new QGridLayout;
0598     layout->addLayout(gl);
0599     gl->addItem(new QSpacerItem(0, 0, QSizePolicy::Expanding), 1, /*2*/ 3);
0600 
0601     m_underlining = new KComboBox(this);
0602     m_underlining->addItem(i18n("Always"));
0603     m_underlining->addItem(i18n("Never"));
0604     m_underlining->addItem(i18n("On mouse hovering"));
0605     m_underlining->addItem(i18n("When mouse is outside"));
0606     label = new QLabel(this);
0607     label->setText(i18n("&Underline:"));
0608     label->setBuddy(m_underlining);
0609     gl->addWidget(label, 0, 0);
0610     gl->addWidget(m_underlining, 0, 1);
0611 
0612     m_color = new KColorCombo2(QRgb(), this);
0613     label = new QLabel(this);
0614     label->setText(i18n("Colo&r:"));
0615     label->setBuddy(m_color);
0616     gl->addWidget(label, 1, 0);
0617     gl->addWidget(m_color, 1, 1);
0618 
0619     m_hoverColor = new KColorCombo2(QRgb(), this);
0620     label = new QLabel(this);
0621     label->setText(i18n("&Mouse hover color:"));
0622     label->setBuddy(m_hoverColor);
0623     gl->addWidget(label, 2, 0);
0624     gl->addWidget(m_hoverColor, 2, 1);
0625 
0626     QHBoxLayout *icoLay = new QHBoxLayout(nullptr);
0627     m_iconSize = new IconSizeCombo(this);
0628     icoLay->addWidget(m_iconSize);
0629     label = new QLabel(this);
0630     label->setText(i18n("&Icon size:"));
0631     label->setBuddy(m_iconSize);
0632     gl->addWidget(label, 3, 0);
0633     gl->addItem(icoLay, 3, 1);
0634 
0635     m_preview = new KComboBox(this);
0636     m_preview->addItem(i18n("None"));
0637     m_preview->addItem(i18n("Icon size"));
0638     m_preview->addItem(i18n("Twice the icon size"));
0639     m_preview->addItem(i18n("Three times the icon size"));
0640     m_label = new QLabel(this);
0641     m_label->setText(i18n("&Preview:"));
0642     m_label->setBuddy(m_preview);
0643     m_hLabel = new HelpLabel(i18n("You disabled preview but still see images?"),
0644                              i18n("<p>This is normal because there are several type of notes.<br>"
0645                                   "This setting only applies to file and local link notes.<br>"
0646                                   "The images you see are image notes, not file notes.<br>"
0647                                   "File notes are generic documents, whereas image notes are pictures you can draw in.</p>"
0648                                   "<p>When dropping files to baskets, %1 detects their type and shows you the content of the files.<br>"
0649                                   "For instance, when dropping image or text files, image and text notes are created for them.<br>"
0650                                   "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>"
0651                                   "<p>If you do not want the application to create notes depending on the content of the files you drop, "
0652                                   "go to the \"General\" page and uncheck \"Image or animation\" in the \"View Content of Added Files for the Following Types\" group.</p>",
0653                                   // TODO: Note: you can resize down maximum size of images...
0654                                   QGuiApplication::applicationDisplayName(),
0655                                   QGuiApplication::applicationDisplayName()),
0656                              this);
0657     gl->addWidget(m_label, 4, 0);
0658     gl->addWidget(m_preview, 4, 1);
0659     gl->addWidget(m_hLabel, 5, 1, 1, 2);
0660 
0661     QGroupBox *gb = new QGroupBox(i18n("Example"), this);
0662     QHBoxLayout *gbLayout = new QHBoxLayout;
0663     gb->setLayout(gbLayout);
0664 
0665     m_exLook = new LinkLook;
0666     m_example = new LinkLabel(exTitle, exIcon, m_exLook, 1, 1);
0667     gbLayout->addWidget(m_example);
0668     m_example->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
0669     m_example->setCursor(QCursor(Qt::PointingHandCursor));
0670     layout->addWidget(gb);
0671     m_exTitle = exTitle;
0672     m_exIcon = exIcon;
0673 
0674     connect(m_italic, &QCheckBox::stateChanged, this, &LinkLookEditWidget::slotChangeLook);
0675     connect(m_bold, &QCheckBox::stateChanged, this, &LinkLookEditWidget::slotChangeLook);
0676     connect(m_underlining, SIGNAL(activated(int)), this, SLOT(slotChangeLook()));
0677     connect(m_color, SIGNAL(activated(int)), this, SLOT(slotChangeLook()));
0678     connect(m_hoverColor, SIGNAL(activated(int)), this, SLOT(slotChangeLook()));
0679     connect(m_iconSize, SIGNAL(activated(int)), this, SLOT(slotChangeLook()));
0680     connect(m_preview, SIGNAL(activated(int)), this, SLOT(slotChangeLook()));
0681 
0682     connect(m_italic, SIGNAL(stateChanged(int)), module, SLOT(changed()));
0683     connect(m_bold, SIGNAL(stateChanged(int)), module, SLOT(changed()));
0684     connect(m_underlining, SIGNAL(activated(int)), module, SLOT(changed()));
0685     connect(m_color, SIGNAL(activated(int)), module, SLOT(changed()));
0686     connect(m_hoverColor, SIGNAL(activated(int)), module, SLOT(changed()));
0687     connect(m_iconSize, SIGNAL(activated(int)), module, SLOT(changed()));
0688     connect(m_preview, SIGNAL(activated(int)), module, SLOT(changed()));
0689 }
0690 
0691 void LinkLookEditWidget::set(LinkLook *look)
0692 {
0693     m_look = look;
0694 
0695     m_italic->setChecked(look->italic());
0696     m_bold->setChecked(look->bold());
0697     m_underlining->setCurrentIndex(look->underlining());
0698     m_preview->setCurrentIndex(look->preview());
0699     m_color->setDefaultColor(m_look->defaultColor());
0700     m_color->setColor(m_look->color());
0701     m_hoverColor->setDefaultColor(m_look->defaultHoverColor());
0702     m_hoverColor->setColor(m_look->hoverColor());
0703     m_iconSize->setSize(look->iconSize());
0704     m_exLook = new LinkLook(*look);
0705     m_example->setLook(m_exLook);
0706 
0707     if (!look->canPreview()) {
0708         m_label->setEnabled(false);
0709         m_hLabel->setEnabled(false);
0710         m_preview->setEnabled(false);
0711     }
0712     slotChangeLook();
0713 }
0714 
0715 void LinkLookEditWidget::slotChangeLook()
0716 {
0717     saveToLook(m_exLook);
0718     m_example->setLink(m_exTitle, m_exIcon, m_exLook); // and can't reload it at another size
0719 }
0720 
0721 LinkLookEditWidget::~LinkLookEditWidget()
0722 {
0723 }
0724 
0725 void LinkLookEditWidget::saveChanges()
0726 {
0727     saveToLook(m_look);
0728 }
0729 
0730 void LinkLookEditWidget::saveToLook(LinkLook *look)
0731 {
0732     look->setLook(m_italic->isChecked(), m_bold->isChecked(), m_underlining->currentIndex(), m_color->color(), m_hoverColor->color(), m_iconSize->iconSize(), (look->canPreview() ? m_preview->currentIndex() : LinkLook::None));
0733 }