File indexing completed on 2024-04-21 05:42:01

0001 /*
0002     SPDX-FileCopyrightText: 2011-2012 Ni Hui <shuizhuyuanluo@126.com>
0003 
0004     SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0005 */
0006 
0007 #include "pocreator.h"
0008 
0009 #include <gettext-po.h>
0010 #include <QColor>
0011 #include <QImage>
0012 #include <QLatin1String>
0013 #include <QPainter>
0014 #include <QWidget>
0015 
0016 #include <KLocalizedString>
0017 #include <KPluginFactory>
0018 
0019 #include "pocreatorsettings.h"
0020 #include "ui_pocreatorform.h"
0021 
0022 K_PLUGIN_CLASS_WITH_JSON(PoCreator, "pothumbnail.json")
0023 
0024 static bool readerror = false;
0025 
0026 static void xerror( int severity,
0027                     po_message_t /*message*/,
0028                     const char */*filename*/, size_t /*lineno*/, size_t /*column*/,
0029                     int /*multiline_p*/, const char */*message_text*/ )
0030 {
0031     if ( severity == PO_SEVERITY_ERROR || severity == PO_SEVERITY_FATAL_ERROR )
0032         readerror = true;
0033 }
0034 
0035 static void xerror2( int severity,
0036                      po_message_t /*message1*/,
0037                      const char */*filename1*/, size_t /*lineno1*/, size_t /*column1*/,
0038                      int /*multiline_p1*/, const char */*message_text1*/,
0039                      po_message_t /*message2*/,
0040                      const char */*filename2*/, size_t /*lineno2*/, size_t /*column2*/,
0041                      int /*multiline_p2*/, const char */*message_text2*/ )
0042 {
0043     if ( severity == PO_SEVERITY_ERROR || severity == PO_SEVERITY_FATAL_ERROR )
0044         readerror = true;
0045 }
0046 
0047 static bool get_po_info( const char* filepath, int& translate, int& untranslate, int& fuzzy, int& obsolete )
0048 {
0049     po_file_t pofile;
0050     const struct po_xerror_handler handler = { xerror, xerror2 };
0051 
0052     pofile = po_file_read( filepath, &handler );
0053     if ( pofile == NULL || readerror )
0054         return false;
0055 
0056     po_message_iterator_t it;
0057     it = po_message_iterator( pofile, NULL );
0058     po_message_t msg;
0059     const char* msgstr;
0060     while ( ( msg = po_next_message( it ) ) != NULL ) {
0061         if ( po_message_is_obsolete( msg ) )
0062             ++obsolete;
0063         else if ( po_message_is_fuzzy( msg ) )
0064             ++fuzzy;
0065         else {
0066             msgstr = po_message_msgstr( msg );
0067             if ( msgstr[0] == '\0' )
0068                 ++untranslate;
0069             else
0070                 ++translate;
0071         }
0072     }
0073     po_message_iterator_free( it );
0074 
0075     /// do not count domain header as translated message
0076     const char* header = po_file_domain_header( pofile, NULL );
0077     if ( header != NULL )
0078         --translate;
0079 
0080     po_file_free( pofile );
0081 
0082     return true;
0083 }
0084 
0085 PoCreator::PoCreator(QObject *parent, const QVariantList &args)
0086     : KIO::ThumbnailCreator(parent, args)
0087 {
0088 }
0089 
0090 PoCreator::~PoCreator()
0091 {
0092 }
0093 
0094 KIO::ThumbnailResult PoCreator::create( const KIO::ThumbnailRequest &request )
0095 {
0096     int translate = 0;
0097     int untranslate = 0;
0098     int fuzzy = 0;
0099     int obsolete = 0;
0100 
0101     if ( !get_po_info( request.url().toLocalFile().toLocal8Bit().constData(), translate, untranslate, fuzzy, obsolete ) )
0102         return KIO::ThumbnailResult::fail();
0103 
0104     int total = translate + untranslate + fuzzy + obsolete;
0105 
0106     if (total == 0) {
0107         // Treat a .po file with no strings as an invalid file
0108         return KIO::ThumbnailResult::fail();
0109     }
0110 
0111     int d = ( request.targetSize().width() < request.targetSize().height() ) ? request.targetSize().width() - 2 : request.targetSize().height() - 2;
0112 
0113     QImage pix( d + 2, d + 2, QImage::Format_ARGB32_Premultiplied );
0114     pix.fill( Qt::transparent ); /// transparent background
0115 
0116     int circle = 16 * 360;
0117     int untranslateAngle = untranslate * circle / total;
0118     int fuzzyAngle = fuzzy * circle / total;
0119     int obsoleteAngle = obsolete * circle / total;
0120     int translateAngle = circle - untranslateAngle - fuzzyAngle - obsoleteAngle;
0121 
0122     QPainter p( &pix );
0123     p.setRenderHint( QPainter::Antialiasing );
0124 
0125     if ( fuzzyAngle > 0 ) {
0126         p.setBrush( PoCreatorSettings::self()->fuzzyColor() );
0127         if ( fuzzy == total )
0128             p.drawEllipse( 1, 1, d, d );
0129         else
0130             p.drawPie( 1, 1, d, d, 0, -fuzzyAngle );
0131     }
0132     if ( untranslateAngle > 0 ) {
0133         p.setBrush( PoCreatorSettings::self()->untranslatedColor() );
0134         if ( untranslate == total )
0135             p.drawEllipse( 1, 1, d, d );
0136         else
0137             p.drawPie( 1, 1, d, d, -fuzzyAngle, -untranslateAngle );
0138     }
0139     if ( obsoleteAngle > 0 ) {
0140         p.setBrush( PoCreatorSettings::self()->obsoletedColor() );
0141         if ( obsolete == total )
0142             p.drawEllipse( 1, 1, d, d );
0143         else
0144             p.drawPie( 1, 1, d, d, -fuzzyAngle-untranslateAngle, -obsoleteAngle );
0145     }
0146     if ( translateAngle > 0 ) {
0147         p.setBrush( PoCreatorSettings::self()->translatedColor() );
0148         if ( translate == total )
0149             p.drawEllipse( 1, 1, d, d );
0150         else
0151             p.drawPie( 1, 1, d, d, -fuzzyAngle-untranslateAngle-obsoleteAngle, -translateAngle );
0152     }
0153 
0154     return KIO::ThumbnailResult::pass(pix);
0155 }
0156 
0157 #include "pocreator.moc"