* Copyright (C) 2010 Andriy Rysin (rysin@kde.org)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "flags.h"
#include <kiconloader.h>
#include <klocalizedstring.h>
#include <plasma/svg.h>
#include <plasma/theme.h>
#include <KFontUtils>
#include <QStandardPaths>
#include <QStringList>
#include <QPixmap>
#include <QPainter>
#include <QIcon>
#include <QFontDatabase>
#include <math.h>
#include "x11_helper.h"
#include "keyboard_config.h"
#include "xkb_rules.h"
static const int FLAG_MAX_SIZE = 22;
static const char flagTemplate[] = "kf5/locale/countries/%1/flag.png";
int iconSize(int s)
{
if (s < 16) {
return 16;
} else if (s < 22) {
return 22;
} else if (s < 32) {
return 32;
} else if (s < 48) {
return 48;
} else if (s < 64) {
return 64;
} else {
return 128;
}
}
Flags::Flags():
svg(NULL)
{
transparentPixmap = new QPixmap(FLAG_MAX_SIZE, FLAG_MAX_SIZE);
transparentPixmap->fill(Qt::transparent);
}
Flags::~Flags()
{
if( svg != NULL ) {
disconnect(svg, &Plasma::Svg::repaintNeeded, this, &Flags::themeChanged);
delete svg;
}
delete transparentPixmap;
}
const QIcon Flags::getIcon(const QString& layout)
{
if( ! iconMap.contains(layout) ) {
iconMap[ layout ] = createIcon(layout);
}
return iconMap[ layout ];
}
QIcon Flags::createIcon(const QString& layout)
{
QIcon icon;
if( ! layout.isEmpty() ) {
QString file;
if( layout == QLatin1String("epo") ) {
file = QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral("kcmkeyboard/pics/epo.png"));
}
else {
QString countryCode = getCountryFromLayoutName( layout );
if( ! countryCode.isEmpty() ) {
file = QStandardPaths::locate(QStandardPaths::GenericDataLocation, QString(flagTemplate).arg(countryCode));
}
}
if (!file.isEmpty()) {
QImage flagImg;
flagImg.load(file);
const int size = iconSize(qMax(flagImg.width(), flagImg.height()));
QPixmap iconPix(size, size);
iconPix.fill(Qt::transparent);
QRect dest(flagImg.rect());
dest.moveCenter(iconPix.rect().center());
QPainter painter(&iconPix);
painter.drawImage(dest, flagImg);
painter.end();
icon.addPixmap(iconPix);
}
}
return icon;
}
QString Flags::getCountryFromLayoutName(const QString& layout) const
{
QString countryCode = layout;
if( countryCode == QLatin1String("nec_vndr/jp") )
return QStringLiteral("jp");
if( countryCode.length() > 2 )
return QLatin1String("");
return countryCode;
}
QString Flags::getShortText(const LayoutUnit& layoutUnit, const KeyboardConfig& keyboardConfig)
{
if( layoutUnit.isEmpty() )
return QStringLiteral("--");
QString layoutText = layoutUnit.layout;
foreach(const LayoutUnit& lu, keyboardConfig.layouts) {
if( layoutUnit.layout == lu.layout && layoutUnit.variant == lu.variant ) {
layoutText = lu.getDisplayName();
break;
}
}
return layoutText;
}
QString Flags::getFullText(const LayoutUnit& layoutUnit, const KeyboardConfig& keyboardConfig, const Rules* rules)
{
QString shortText = Flags::getShortText(layoutUnit, keyboardConfig);
QString longText = Flags::getLongText(layoutUnit, rules);
return i18nc("short layout label - full layout name", "%1 - %2", shortText, longText);
}
static QString getDisplayText(const QString& layout, const QString& variant, const Rules* rules)
{
if( variant.isEmpty() )
return layout;
if( rules == NULL || rules->version == QLatin1String("1.0") )
return i18nc("layout - variant", "%1 - %2", layout, variant);
return variant;
}
QString Flags::getLongText(const LayoutUnit& layoutUnit, const Rules* rules)
{
if( rules == NULL ) {
return getDisplayText(layoutUnit.layout, layoutUnit.variant, rules);
}
QString layoutText = layoutUnit.layout;
const LayoutInfo* layoutInfo = rules->getLayoutInfo(layoutUnit.layout);
if( layoutInfo != NULL ) {
layoutText = layoutInfo->description;
if( ! layoutUnit.variant.isEmpty() ) {
const VariantInfo* variantInfo = layoutInfo->getVariantInfo(layoutUnit.variant);
QString variantText = variantInfo != NULL ? variantInfo->description : layoutUnit.variant;
layoutText = getDisplayText(layoutText, variantText, rules);
}
}
return layoutText;
}
static
QString getPixmapKey(const KeyboardConfig& keyboardConfig)
{
switch(keyboardConfig.indicatorType) {
case KeyboardConfig::SHOW_FLAG:
return QStringLiteral("_fl");
case KeyboardConfig::SHOW_LABEL_ON_FLAG:
return QStringLiteral("_bt");
case KeyboardConfig::SHOW_LABEL:
return QStringLiteral("_lb");
}
return QStringLiteral("_");
}
void Flags::drawLabel(QPainter& painter, const QString& layoutText, bool flagShown)
{
QFont font = painter.font();
QRect rect = painter.window();
font.setPointSize(KFontUtils::adaptFontSize(painter, layoutText, rect.size(), rect.height()));
getSvg();
const QColor textColor = flagShown ? Qt::black : Plasma::Theme().color(Plasma::Theme::TextColor);
painter.setPen(textColor);
painter.setFont(font);
painter.drawText(rect, Qt::AlignCenter, layoutText);
}
const QIcon Flags::getIconWithText(const LayoutUnit& layoutUnit, const KeyboardConfig& keyboardConfig)
{
const QString keySuffix(getPixmapKey(keyboardConfig));
const QString key(layoutUnit.toString() + keySuffix);
if( iconOrTextMap.contains(key) ) {
return iconOrTextMap[ key ];
}
if( keyboardConfig.indicatorType == KeyboardConfig::SHOW_FLAG ) {
QIcon icon = getIcon(layoutUnit.layout);
if( ! icon.isNull() ) {
iconOrTextMap[ key ] = icon;
return icon;
}
}
QString layoutText = Flags::getShortText(layoutUnit, keyboardConfig);
const QSize TRAY_ICON_SIZE(128, 128);
QPixmap pixmap = QPixmap(TRAY_ICON_SIZE);
pixmap.fill(Qt::transparent);
QPainter painter(&pixmap);
painter.setRenderHint(QPainter::SmoothPixmapTransform);
if( keyboardConfig.indicatorType == KeyboardConfig::SHOW_LABEL_ON_FLAG ) {
QIcon iconf = createIcon(layoutUnit.layout);
painter.drawPixmap(pixmap.rect(), iconf.pixmap(TRAY_ICON_SIZE));
}
drawLabel(painter, layoutText, keyboardConfig.isFlagShown());
painter.end();
QIcon icon(pixmap);
iconOrTextMap[ key ] = icon;
return icon;
}
Plasma::Svg* Flags::getSvg()
{
if( svg == NULL ) {
svg = new Plasma::Svg;
svg->setImagePath(QStringLiteral("widgets/labeltexture"));
svg->setContainsMultipleImages(true);
connect(svg, &Plasma::Svg::repaintNeeded, this, &Flags::themeChanged);
}
return svg;
}
void Flags::themeChanged()
{
clearCache();
emit pixmapChanged();
}
void Flags::clearCache()
{
iconOrTextMap.clear();
}