Example #1
0
void ClipboardDialog::on_listWidgetFormats_currentItemChanged(
        QListWidgetItem *current, QListWidgetItem *)
{
    ui->actionRemove_Format->setEnabled(current != NULL);

    QTextEdit *edit = ui->textEditContent;
    QString mime = current ? current->text() : QString();

    edit->clear();
    const QByteArray bytes = m_data.value(mime).toByteArray();
    if ( mime.startsWith(QString("image")) ) {
        edit->document()->addResource( QTextDocument::ImageResource,
                                       QUrl("data://1"), bytes );
        edit->setHtml( QString("<img src=\"data://1\" />") );
    } else {
        QTextCodec *codec = QTextCodec::codecForName("utf-8");
        if (mime == QLatin1String("text/html"))
            codec = QTextCodec::codecForHtml(bytes, codec);
        else
            codec = QTextCodec::codecForUtfText(bytes, codec);
        edit->setPlainText( codec ? codec->toUnicode(bytes) : QString() );
    }

    ui->labelProperties->setText(
        tr("<strong> mime:</strong> %1 <strong>size:</strong> %2 bytes")
            .arg(escapeHtml(mime))
            .arg(QString::number(bytes.size())));
}
Example #2
0
ItemData::ItemData(const QModelIndex &index, int maxBytes, QWidget *parent)
    : QLabel(parent)
    , ItemWidget(this)
{
    setTextInteractionFlags(Qt::TextSelectableByMouse);
    setContentsMargins(4, 4, 4, 4);
    setTextFormat(Qt::RichText);

    QString text;

    const QStringList formats = index.data(contentType::formats).toStringList();
    for (int i = 0; i < formats.size(); ++i ) {
        QByteArray data = index.data(contentType::firstFormat + i).toByteArray();
        const int size = data.size();
        bool trimmed = size > maxBytes;
        if (trimmed)
            data = data.left(maxBytes);

        const QString &format = formats[i];
        bool hasText = format.startsWith("text/") ||
                       format.startsWith("application/x-copyq-owner-window-title");
        const QString content = hasText ? escapeHtml(stringFromBytes(data, format)) : hexData(data);
        text.append( QString("<p>") );
        text.append( QString("<b>%1</b> (%2 bytes)<pre>%3</pre>")
                     .arg(format)
                     .arg(size)
                     .arg(content) );
        text.append( QString("</p>") );

        if (trimmed)
            text.append( QString("<p>...</p>") );
    }

    setText(text);
}
Example #3
0
ItemData::ItemData(const QModelIndex &index, int maxBytes, QWidget *parent)
    : QLabel(parent)
    , ItemWidget(this)
{
    setTextInteractionFlags(Qt::TextSelectableByMouse);
    setContentsMargins(4, 4, 4, 4);
    setTextFormat(Qt::RichText);

    QString text;

    const QVariantMap data = index.data(contentType::data).toMap();
    foreach ( const QString &format, data.keys() ) {
        QByteArray bytes = data[format].toByteArray();
        const int size = bytes.size();
        bool trimmed = size > maxBytes;
        if (trimmed)
            bytes = bytes.left(maxBytes);

        bool hasText = format.startsWith("text/") ||
                       format.startsWith("application/x-copyq-owner-window-title");
        const QString content = hasText ? escapeHtml(stringFromBytes(bytes, format)) : hexData(bytes);
        text.append( QString("<p>") );
        text.append( QString("<b>%1</b> (%2 bytes)<pre>%3</pre>")
                     .arg(format)
                     .arg(size)
                     .arg(content) );
        text.append( QString("</p>") );

        if (trimmed)
            text.append( QString("<p>...</p>") );
    }

    setText(text);
}
Example #4
0
void MDataWidget::setData(const MetaData& md)
{

    // Sometimes ignore the date
    QString albtxt;
    if (md.year < 1000 || md.album.contains(QString::number(md.year))) {
        albtxt = md.album.trimmed();
    } else {
        albtxt = md.album.trimmed() + " (" +
            QString::number(md.year) + ")";
    }
    lab_album->setText(albtxt);
    lab_album->setToolTip(QString::fromUtf8("<i></i>") + escapeHtml(albtxt));

    lab_artist->setText(md.artist);
    lab_artist->setToolTip(QString::fromUtf8("<i></i>") +
                           escapeHtml(md.artist));

    lab_title->setText(md.title);
    lab_title->setToolTip(QString::fromUtf8("<i></i>") + escapeHtml(md.title));
}
Example #5
0
void ChromeClientQt::setToolTip(const String &tip, TextDirection)
{
#ifndef QT_NO_TOOLTIP
    QWidget* view = m_webPage->view();
    if (!view)
        return;

    if (tip.isEmpty()) {
        view->setToolTip(QString());
        QToolTip::hideText();
    } else {
        QString dtip = QLatin1String("<p>") + escapeHtml(tip) + QLatin1String("</p>");
        view->setToolTip(dtip);
    }
#else
    Q_UNUSED(tip);
#endif
}
Example #6
0
std::string ReplayBuilder::htmlTitle() {
  std::stringstream titleStream;
  titleStream << (stageName_ == 0 ? "Unknown" : stageName_);
  titleStream << ": ";
  for (int x = 0; x < numTeams_; x++) {
    char *teamName = teamNames_[x];
    if (teamName != 0) {
      if (x != 0) {
        titleStream << " vs ";
      }
      titleStream << escapeHtml(teamName);
    }
  }
  if (timestamp_ != 0) {
    titleStream << " @ ";
    titleStream << timestamp_;
  }
  return titleStream.str();
}
Example #7
0
QString AboutDialog::aboutPage()
{
    return
        "<html>"

        // CSS
        "<head><style type=\"text/css\">"
        "body{font-size:10pt;background:white;color:#333;margin:1.5em}"
        "p, li{white-space:pre-wrap;margin-left:1ex}"
        "a{text-decoration:none}"
        ".h1{font-size:26pt;color:#666;white-space:pre}"
        ".h1x{font-size:16pt;color:#888;white-space:pre}"
        ".h2{width:100%;font-size:16pt;margin-left:1ex;margin-top:0.2em}"
        ".h2x{font-size:12pt}"
        ".h3{font-size:9pt;color:#666}"
        ".links td{padding:0}"
        ".link{font-size:9pt}"
        ".pp{margin-left:4ex}"
        ".ppp{margin-left:4ex;font-size:9pt}"
        "table{border:0}"
        ".odd {background:#def}"
        "td{padding:0.1em}"
        "#keys{margin-left:4ex}"
        ".key{font-family:monospace;font-size:9pt;padding-left:0.5em}"
        ".logo{float:left}"
        ".info{font-size:9pt}"
        "</style></head>"

        "<body>"

        // logo
        "<img class='logo' src=':/images/logo.png' />"

        // title
        "<div class='h1'>CopyQ</div>"
        // subtitle
        "<div class=\"h1x\">" + escapeHtml(tr("Clipboard Manager"))
            + " " COPYQ_VERSION "</div>"

        "<p>"
        "<table class='links'>"
            + helpLink( tr("Author"), QString::fromUtf8("Lukáš Holeček") )
            + helpLink( tr("E-mail"), helpMail("*****@*****.**") )
            + helpLink( tr("Web"), helpUrl("https://hluk.github.io/CopyQ/") )
            + helpLink( tr("Wiki"), helpUrl("https://github.com/hluk/CopyQ/wiki") )
            + helpLink( tr("Donate"), helpUrl("https://www.bountysource.com/teams/copyq") )
            +
        "</table>"
        "</p>"

        // copyright
        "<p class='info'>Copyright (c) 2009 - 2016</p>"

        "<p></p>"

        + helpTitle(tr("Development"))
        + "<p class=\"pp\">"
            // developers
            + helpDeveloper("Adam Batkin", "*****@*****.**")
            + helpDeveloper("Giacomo Margarito", "*****@*****.**")
            + helpDeveloper("Greg Carp", "*****@*****.**")
            + helpDeveloper("Ilya Plenne", "*****@*****.**")
            + helpDeveloper("Jörg Thalheim", "*****@*****.**")
            + helpDeveloper("Kim Jzhone", "*****@*****.**")
            + helpDeveloper("Kos Ivantsov", "*****@*****.**")
            + helpDeveloper("lightonflux", "*****@*****.**")
            + helpDeveloper("Lukas Holecek", "*****@*****.**")
            + helpDeveloper("Marjolein Hoekstra", "http://twitter.com/cleverclogs")
            + helpDeveloper("Martin Lepadusch", "*****@*****.**")
            + helpDeveloper("Matt d'Entremont", "*****@*****.**")
            + helpDeveloper("Michal Čihař", "*****@*****.**")
            + helpDeveloper("Patricio M. Ros", "*****@*****.**")
            + helpDeveloper("Ryan Wooden", "*****@*****.**")
            + helpDeveloper("Scott Kostyshak", "*****@*****.**")
            + helpDeveloper("Sebastian Schuberth", "*****@*****.**")
            + helpDeveloper("Tomas Nilzon", "*****@*****.**")
            + helpDeveloper("Wilfried Caruel", "*****@*****.**")
            + helpDeveloper("x2357", "*****@*****.**")
            +
        "</p>"

            // libraries
            + helpLib("Qt", tr("Library used in the application", "Qt library description"),
                      "Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies)", "https://www.qt.io/")
            + helpLib("Weblate", tr("Free web-based translation management system", "Weblate description"),
                      "Copyright (c) 2012 - 2013 Michal &#268;iha&#345;", "https://weblate.org")
            + helpLib("Font Awesome", tr("Iconic font used in the application", "Font Awesome description"),
                      "Created & Maintained by Dave Gandy", "https://fortawesome.github.io/Font-Awesome/")
            + helpLib("LibQxt", tr("Library used in the application", "LibQxt library description"),
                      "Copyright (c) 2006 - 2011, the LibQxt project", "http://libqxt.org")
            + helpLib("Solarized", tr("Color palette used for themes", "Solarized palette/themes description"),
                      "Copyright (c) 2011 Ethan Schoonover", "http://ethanschoonover.com/solarized")

        // keyboard title
        + helpTitle(tr("Keyboard"))

        + helpParagraph(tr("Application shortcuts can be changed in Preferences dialog."))

#ifndef NO_GLOBAL_SHORTCUTS
        + helpParagraph(tr("Global shortcuts (system-wide shortcuts) can be set in Command dialog (default shortcut is F6)."))
#endif

        + helpParagraph(tr("Type any text to search the clipboard history."))

        // keyboard table
        + "<p><table id=\"keys\">"
            + helpKeys( tr("Item list navigation"), tr("Up/Down, Page Up/Down, Home/End") )
            + helpKeys( tr("Tab navigation"),
                        tr("Left, Right, %1, %2", "Keys for tab navigation (%1, %2 are the standard keys).")
                        .arg(QKeySequence(QKeySequence::NextChild).toString(QKeySequence::NativeText))
                        .arg(QKeySequence(QKeySequence::PreviousChild).toString(QKeySequence::NativeText))
                        )
            + helpKeys( tr("Move selected items"), tr("Ctrl+Up/Down, Ctrl+Home/End") )
            + helpKeys( tr("Reset search or hide window"), tr("Escape") )
            + helpKeys( tr("Delete item"), shortcutToRemove() )
            + helpKeys( tr("Put selected items into clipboard"), tr("Enter") )
            + helpKeys( tr("Change item display format"), tr("Ctrl+Left/Right") )
            + helpKeys( tr("Edit Item"), tr("F2") )
            +
        "</table></p>"

        + "<p></p>"

        "</body></html>";
}
Example #8
0
static QString aboutPage()
{
    return
        "<html>"

        // CSS
        "<head><style type=\"text/css\">"
        "body{font-size:10pt;background-color:white;color:black}"
        "p, li{white-space:pre-wrap;margin-left:1ex}"
        ".h1{font-size:20pt;color:#444}"
        ".h1x{font-size:12pt;font-style:italic;color:#222;}"
        ".h2{width:100%;font-size:16pt;color:#333;margin-left:1ex;margin-top:0.2em}"
        ".h2x{font-size:12pt;color:#222;}"
        ".h3{font-size:9pt;font-style:italic;color:#444}"
        ".pp{margin-left:4ex}"
        ".ppp{margin-left:4ex;font-size:9pt}"
        "table{border:0}"
        ".odd {background-color:#def}"
        "td{padding:0.1em}"
        "#keys{margin-left:4ex}"
        ".key{color:#333;font-family:monospace;font-size:9pt;padding-left:0.5em}"
        "</style></head>"

        "<body>"

        "<p><table><tr>"

        // logo
        "<td><img src=\":/images/logo.svg\" /></td>"

        "<td>"

        // title
        "<div class='h1'>CopyQ</div>"
        // subtitle
        "<div class=\"h1x\">" + escapeHtml(AboutDialog::tr("Clipboard Manager"))
            + " v" COPYQ_VERSION "</div>"

        "<p></p>"

        "<p><table>"

        // copyright
        "<tr><td colspan=\"2\">Copyright (c) 2009 - 2013</td></tr>"
        // author
        "<tr><td colspan=\"2\">Lukas Holecek</td></tr>"
        // e-mail
        "<tr>"
        "<td class='h3'>" + escapeHtml(AboutDialog::tr("E-mail")) + "</td>"
        "<td><a href=\"mailto:[email protected]\">[email protected]</a></td>"
        "</tr>"
        // web
        "<tr>"
        "<td class='h3'>" + escapeHtml(AboutDialog::tr("Web")) + "</td>"
        "<td><a href=\"https://code.google.com/p/copyq\">https://code.google.com/p/copyq</a></td>"
        "</tr>"
        "<tr>"
        "<td></td>"
        "<td><a href=\"http://github.com/hluk/copyq\">github.com/hluk/copyq</a></td>"
        "</tr>"

        "</table></p>"

        "</td>"

        "</tr></table></p>"

        // developers
        "<div class='h2'>" + AboutDialog::tr("Development") + "</div>"
        "<p class=\"pp\">"
        "Adam Batkin (<a href=\"mailto:[email protected]\">[email protected]</a>)<br />"
        "Ilya Plenne (<a href=\"mailto:[email protected]\">[email protected]</a>)<br />"
        "lightonflux (<a href=\"mailto:[email protected]\">[email protected]</a>)<br />"
        "Sebastian Schuberth (<a href=\"mailto:[email protected]\">[email protected]</a>)"
        "</p>"

        // libraries
        "<p class=\"ppp\"><span class='h2x'>LibQxt</span> (" + escapeHtml(AboutDialog::tr("Library used in the application")) + ")<br />"
        "Copyright (c) 2006 - 2011, the LibQxt project (<a href=\"http://libqxt.org/\">http://libqxt.org</a>).<br />"
        "All rights reserved.</p>"

        "<p class=\"ppp\"><span class='h2x'>Font Awesome</span> (" + escapeHtml(AboutDialog::tr("Iconic font used in the application")) + ")<br />"
        "Created & Maintained by Dave Gandy (<a href=\"http://fortawesome.github.com/Font-Awesome/\">http://fortawesome.github.com/Font-Awesome/</a>).</p>"

        // keyboard title
        "<div class='h2'>" + escapeHtml(AboutDialog::tr("Keyboard")) + "</div>"
        "<p class=\"pp\">" + escapeHtml(AboutDialog::tr("Type any text to search the clipboard history.")) + "</p>"

        // keyboard table
        "<p><table id=\"keys\">"
        "<tr class=\"odd\">"
        "<td>" + escapeHtml(AboutDialog::tr("Item list navigation")) + "</td>"
        "<td class=\"key\">" + escapeHtml(AboutDialog::tr("Up/Down, Page Up/Down, Home/End")) + "</td>"
        "</tr>"
        "<tr><td>" + escapeHtml(AboutDialog::tr("Tab navigation")) + "</td>"
        "<td class=\"key\">" + escapeHtml(AboutDialog::tr("Left, Right, Tab, Shift+Tab")) + "</td>"
        "</tr>"
        "<tr class=\"odd\">"
        "<td>" + escapeHtml(AboutDialog::tr("Move selected items")) + "</td>"
        "<td class=\"key\">" + escapeHtml(AboutDialog::tr("Ctrl+Up/Down, Ctrl+Home/End")) + "</td>"
        "</tr>"
        "<tr><td>" + escapeHtml(AboutDialog::tr("Reset search or hide window")) + "</td>"
        "<td class=\"key\">" + escapeHtml(AboutDialog::tr("Escape")) + "</td>"
        "</tr>"
        "<tr class=\"odd\">"
        "<td>" + escapeHtml(AboutDialog::tr("Delete item")) + "</td>"
        "<td class=\"key\">" + escapeHtml(AboutDialog::tr("Delete")) + "</td>"
        "</tr>"
        "<tr><td>" + escapeHtml(AboutDialog::tr("Put selected items into clipboard")) + "</td>"
        "<td class=\"key\">" + escapeHtml(AboutDialog::tr("Enter")) + "</td>"
        "</tr>"
        "<tr class=\"odd\">"
        "<td>" + escapeHtml(AboutDialog::tr("Change item display format")) + "</td>"
        "<td class=\"key\">" + escapeHtml(AboutDialog::tr("Ctrl+Left/Right")) + "</td>"
        "</tr>"
        "</table></p>"

        "<p></p>"

        "</body></html>";
}
void
FdoNotifyPlugin::nowPlaying( const QVariant& input )
{
    tDebug( LOGVERBOSE ) << Q_FUNC_INFO;
    if ( !input.canConvert< QVariantMap >() )
        return;

    QVariantMap map = input.toMap();
    if ( !map.contains( "trackinfo" ) || !map[ "trackinfo" ].canConvert< Tomahawk::InfoSystem::InfoStringHash >() )
        return;

    InfoStringHash hash = map[ "trackinfo" ].value< Tomahawk::InfoSystem::InfoStringHash >();
    if ( !hash.contains( "title" ) || !hash.contains( "artist" ) || !hash.contains( "album" ) )
        return;

    QString messageText;
    // If the window manager supports notification styling then use it.
    if ( m_wmSupportsBodyMarkup )
    {
        // Remark: If using xml-based markup in notifications, the supplied strings need to be escaped.
        QString album;
        if ( !hash[ "album" ].isEmpty() )
            album = QString( "\n<i>%1</i> %2" )
                    .arg( tr( "on", "'on' is followed by an album name" ) )
                    .arg( escapeHtml( hash[ "album" ] ) );

        messageText = tr( "%1%4 %2%3.", "%1 is a title, %2 is an artist and %3 is replaced by either the previous message or nothing, %4 is the preposition used to link track and artist ('by' in english)" )
                        .arg( escapeHtml( hash[ "title" ] ) )
                        .arg( escapeHtml( hash[ "artist" ] ) )
                        .arg( album )
                        .arg( QString( "\n<i>%1</i>" ).arg( tr( "by", "preposition to link track and artist" ) ) );

        // Dirty hack(TM) so that KNotify/QLabel recognizes the message as Rich Text
        messageText = QString( "<i></i>%1" ).arg( messageText );
    }
    else
    {
        QString album;
        if ( !hash[ "album" ].isEmpty() )
            album = QString( " %1" ).arg( tr( "on \"%1\"", "%1 is an album name" ).arg( hash[ "album" ] ) );

        messageText = tr( "\"%1\" by %2%3.", "%1 is a title, %2 is an artist and %3 is replaced by either the previous message or nothing" )
                        .arg( hash[ "title" ] )
                        .arg( hash[ "artist" ] )
                        .arg( album );
    }

    tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "sending message" << messageText;

    QVariantMap hints;
    hints["desktop-entry"] = QString( "tomahawk" );

    // If there is a cover availble use it, else use Tomahawk logo as default.
    QImage image;
    if ( map.contains( "coveruri" ) && map[ "coveruri" ].canConvert< QString >() )
        image = QImage( map[ "coveruri" ].toString(), "PNG" );
    else
        image = QImage( RESPATH "icons/tomahawk-icon-512x512.png" );
    // Convert image to QVariant and scale to a consistent size.
    hints[ "image_data" ] = ImageConverter::variantForImage( image.scaledToHeight( getNotificationIconHeight() ) );


    QDBusPendingReply<> reply = notifications_interface->Notify(
        TOMAHAWK_APPLICATION_NAME,      // app_name
        m_nowPlayingId,                 // notification_id
        "",                             // app_icon
        tr( "Tomahawk - Now Playing" ), // summary
        messageText,                    // body
        QStringList(),                  // actions
        hints,                          // hints
        -1                              // expire_timeout
    );

    QDBusPendingCallWatcher* watcher = new QDBusPendingCallWatcher( reply, this );
    connect( watcher, SIGNAL( finished( QDBusPendingCallWatcher* ) ), SLOT( dbusPlayingReplyReceived( QDBusPendingCallWatcher* ) ) );
}
void FdoNotifyPlugin::inboxReceived( const QVariant& input )
{
    tDebug( LOGVERBOSE ) << Q_FUNC_INFO;
    if ( !input.canConvert< QVariantMap >() )
        return;

    QVariantMap map = input.toMap();

    if ( !map.contains( "trackinfo" ) || !map[ "trackinfo" ].canConvert< Tomahawk::InfoSystem::InfoStringHash >() )
        return;
    if ( !map.contains( "sourceinfo" ) || !map[ "sourceinfo" ].canConvert< Tomahawk::InfoSystem::InfoStringHash >() )
        return;

    InfoStringHash hash = map[ "trackinfo" ].value< Tomahawk::InfoSystem::InfoStringHash >();
    if ( !hash.contains( "title" ) || !hash.contains( "artist" ) )
        return;

    InfoStringHash src = map[ "sourceinfo" ].value< Tomahawk::InfoSystem::InfoStringHash >();
    if ( !src.contains( "friendlyname" ) )
        return;

    QString messageText;
    // If the window manager supports notification styling then use it.
    if ( m_wmSupportsBodyMarkup )
    {
        // Remark: If using xml-based markup in notifications, the supplied strings need to be escaped.
        messageText = tr( "%1 sent you\n%2%4 %3.", "%1 is a nickname, %2 is a title, %3 is an artist, %4 is the preposition used to link track and artist ('by' in english)" )
                        .arg( escapeHtml( src["friendlyname"] ) )
                        .arg( escapeHtml( hash[ "title" ] ) )
                        .arg( escapeHtml( hash[ "artist" ] ) )
                        .arg( QString( "\n<i>%1</i>" ).arg( tr( "by", "preposition to link track and artist" ) ) );

        // Dirty hack(TM) so that KNotify/QLabel recognizes the message as Rich Text
        messageText = QString( "<i></i>%1" ).arg( messageText );
    }
    else
    {
        messageText = tr( "%1 sent you \"%2\" by %3.", "%1 is a nickname, %2 is a title, %3 is an artist" )
                        .arg( src["friendlyname"] )
                        .arg( hash[ "title" ] )
                        .arg( hash[ "artist" ] );
    }

    tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "sending message" << messageText;

    QVariantMap hints;
    hints["desktop-entry"] = QString( "tomahawk" );

    // Convert image to QVariant and scale to a consistent size.
    hints[ "image_data" ] = ImageConverter::variantForImage( QImage( RESPATH "images/inbox-512x512.png" ).scaledToHeight( getNotificationIconHeight() ) );
    notifications_interface->Notify(
        "Tomahawk",                  // app_name
        m_nowPlayingId,              // notification_id
        "",                          // app_icon
        "Tomahawk - Track received", // summary
        messageText,                 // body
        QStringList(),               // actions
        hints,                       // hints
        -1                           // expire_timeout
    );
}
QString Manager::Impl::escapeNotificationText(const QString &text) const {
	return _markupSupported ? escapeHtml(text) : text;
}
Example #12
0
QString Record::toString(const QString &format, const QString &timeFormat) const
{
    return format.arg( escapeHtml(text) ).arg( time.toString(timeFormat) );
}
QScriptValue ScriptEngine::htmlEscape(const QString &string)
{
    return escapeHtml(string);
}
Example #14
0
QString AboutDialog::aboutPage()
{
    return
        "<html>"

        "<head><style type='text/css'>"
        "body{font-size:10pt;background:white;color:#333;margin:1.0em}"
        "p,li{margin-left:4ex;white-space:pre-wrap;margin-left:1ex}"
        "a{text-decoration:none}"
        "table{border:0}"
        "td{padding:0.1em}"
        "#title{font-size:26pt;color:#666;white-space:pre;margin-bottom:0.2em}"
        "#subtitle{font-size:16pt;color:#888;white-space:pre;margin-bottom:0.2em}"
        "#version{font-size:12pt}"
        ".copyright{font-size:9pt;color:#666}"
        ".icon{font-family:" + iconFontFamily() + "}"
        ".help-icon{color:#999;padding-left:1em;padding-right:1em}"
        ".library{font-size:12pt}"
        ".info{color:#666}"
        "</style></head>"

        "<body>"

        "<table><tr valign='middle'>"
        "<td><img src=':/images/logo.png' width='128' /></td>"
        "<td>"
        "<div id='title'>CopyQ</div>"
        "<div id='subtitle'>" + escapeHtml(tr("Clipboard Manager")) + "</div>"
        "<div id='version'>" + COPYQ_VERSION "</div>"
        "</td>"
        "</tr></table>"

        "<p>"
        "<table class='links'>"
            + helpLink( tr("Author"), QString::fromUtf8("Lukáš Holeček"), IconUser )
            + helpLink( tr("E-mail"), helpMail("*****@*****.**"), IconEnvelope )
            + helpLink( tr("Web"), helpUrl("https://hluk.github.io/CopyQ/"), IconHome )
            + helpLink( tr("Donate"), helpUrl("https://www.bountysource.com/teams/copyq"), IconGift )
            +
        "</table>"
        "</p>"

        "<p class='copyright'>Copyright (c) 2009 - 2019</p>"

        "<p></p>"

        + "<p>"
            + helpDeveloper("Adam Batkin", "*****@*****.**")
            + helpDeveloper("Giacomo Margarito", "*****@*****.**")
            + helpDeveloper("Greg Carp", "*****@*****.**")
            + helpDeveloper("Ilya Plenne", "*****@*****.**")
            + helpDeveloper("Jörg Thalheim", "*****@*****.**")
            + helpDeveloper("Kim Jzhone", "*****@*****.**")
            + helpDeveloper("Kos Ivantsov", "*****@*****.**")
            + helpDeveloper("lightonflux", "*****@*****.**")
            + helpDeveloper("Lukas Holecek", "*****@*****.**")
            + helpDeveloper("Marjolein Hoekstra", "http://twitter.com/cleverclogs")
            + helpDeveloper("Martin Lepadusch", "*****@*****.**")
            + helpDeveloper("Matt d'Entremont", "*****@*****.**")
            + helpDeveloper("Michal Čihař", "*****@*****.**")
            + helpDeveloper("Patricio M. Ros", "*****@*****.**")
            + helpDeveloper("Robert Orzanna", "*****@*****.**")
            + helpDeveloper("Ryan Wooden", "*****@*****.**")
            + helpDeveloper("Scott Kostyshak", "*****@*****.**")
            + helpDeveloper("Sebastian Schuberth", "*****@*****.**")
            + helpDeveloper("Tomas Nilzon", "*****@*****.**")
            + helpDeveloper("Wilfried Caruel", "*****@*****.**")
            + helpDeveloper("x2357", "*****@*****.**")
            +
        "</p>"

            + helpLib("Qt Toolkit",
                      "Copyright (c) 2016 The Qt Company Ltd. and other contributors", "https://www.qt.io/")
            + helpLib("Weblate",
                      "Copyright (c) 2012 - 2017 Michal &#268;iha&#345;", "https://weblate.org")
            + helpLib("Font Awesome",
                      "Copyright (c) 2017 Fonticons, Inc.", "https://fontawesome.com")
            + helpLib("LibQxt",
                      "Copyright (c) 2006 - 2011, the LibQxt project", "http://libqxt.org")
            + helpLib("Solarized",
                      "Copyright (c) 2011 Ethan Schoonover", "http://ethanschoonover.com/solarized")

        + "<p></p>"

        "</body></html>";
}