tools/makeqpf/mainwindow.cpp
changeset 0 1918ee327afb
child 3 41300fa6a67c
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the tools applications of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include "mainwindow.h"
       
    43 
       
    44 #include <QFontComboBox>
       
    45 #include <QFontDatabase>
       
    46 #include <QFileDialog>
       
    47 #include <QMessageBox>
       
    48 #include <QListWidget>
       
    49 #include <QDebug>
       
    50 #include <QShortcut>
       
    51 #include <QCompleter>
       
    52 #include <QDirModel>
       
    53 #include <QTextCodec>
       
    54 
       
    55 QT_BEGIN_NAMESPACE
       
    56 
       
    57 MainWindow::MainWindow(const QString &customFont)
       
    58 {
       
    59     setupUi(this);
       
    60     pixelSize->setValue(QFontInfo(QFont()).pixelSize());
       
    61     populateCharacterRanges();
       
    62 
       
    63     {
       
    64         weightCombo->addItem(QLatin1String("Light"), QVariant(int(QFont::Light)));
       
    65         const int normalIdx = weightCombo->count();
       
    66         weightCombo->addItem(QLatin1String("Normal"), QVariant(int(QFont::Normal)));
       
    67         weightCombo->addItem(QLatin1String("DemiBold"), QVariant(int(QFont::DemiBold)));
       
    68         weightCombo->addItem(QLatin1String("Bold"), QVariant(int(QFont::Bold)));
       
    69         weightCombo->addItem(QLatin1String("Black"), QVariant(int(QFont::Black)));
       
    70 
       
    71         weightCombo->setCurrentIndex(normalIdx);
       
    72     }
       
    73 
       
    74     QShortcut *sc = new QShortcut(Qt::ControlModifier + Qt::Key_A, this);
       
    75     connect(sc, SIGNAL(activated()),
       
    76             this, SLOT(on_selectAll_clicked()));
       
    77     sc = new QShortcut(Qt::ControlModifier + Qt::Key_D, this);
       
    78     connect(sc, SIGNAL(activated()),
       
    79             this, SLOT(on_deselectAll_clicked()));
       
    80     sc = new QShortcut(Qt::ControlModifier + Qt::Key_I, this);
       
    81     connect(sc, SIGNAL(activated()),
       
    82             this, SLOT(on_invertSelection_clicked()));
       
    83 
       
    84     QCompleter *completer = new QCompleter(this);
       
    85     completer->setModel(new QDirModel(this));
       
    86     path->setCompleter(completer);
       
    87     path->setText(QDir::currentPath());
       
    88 
       
    89     completer = new QCompleter(this);
       
    90     completer->setModel(new QDirModel(this));
       
    91     sampleFile->setCompleter(completer);
       
    92     charCount->setText(QString());
       
    93 
       
    94     if (!customFont.isEmpty())
       
    95         addCustomFont(customFont);
       
    96 
       
    97     fontChanged();
       
    98 
       
    99     connect(fontComboBox, SIGNAL(currentFontChanged(QFont)),
       
   100             this, SLOT(fontChanged()));
       
   101     connect(pixelSize, SIGNAL(valueChanged(int)),
       
   102             this, SLOT(fontChanged()));
       
   103     connect(italic, SIGNAL(stateChanged(int)),
       
   104             this, SLOT(fontChanged()));
       
   105     connect(weightCombo, SIGNAL(currentIndexChanged(int)),
       
   106             this, SLOT(fontChanged()));
       
   107 }
       
   108 
       
   109 void MainWindow::on_actionAdd_Custom_Font_triggered()
       
   110 {
       
   111     QString fontFile = QFileDialog::getOpenFileName(this, tr("Add Custom Font"));
       
   112     if (fontFile.isEmpty())
       
   113         return;
       
   114     addCustomFont(fontFile);
       
   115 }
       
   116 
       
   117 void MainWindow::on_selectAll_clicked()
       
   118 {
       
   119     for (int i = 0; i < characterRangeView->count(); ++i)
       
   120         characterRangeView->item(i)->setCheckState(Qt::Checked);
       
   121 }
       
   122 
       
   123 void MainWindow::on_deselectAll_clicked()
       
   124 {
       
   125     for (int i = 0; i < characterRangeView->count(); ++i)
       
   126         characterRangeView->item(i)->setCheckState(Qt::Unchecked);
       
   127 }
       
   128 
       
   129 void MainWindow::on_invertSelection_clicked()
       
   130 {
       
   131     for (int i = 0; i < characterRangeView->count(); ++i) {
       
   132         QListWidgetItem *item = characterRangeView->item(i);
       
   133         if (item->checkState() == Qt::Checked)
       
   134             item->setCheckState(Qt::Unchecked);
       
   135         else
       
   136             item->setCheckState(Qt::Checked);
       
   137     }
       
   138 }
       
   139 
       
   140 void MainWindow::fontChanged()
       
   141 {
       
   142     QFont f = preview->font();
       
   143     f.setStyleStrategy(QFont::NoFontMerging);
       
   144     f.setPixelSize(pixelSize->value());
       
   145     f.setFamily(fontComboBox->currentFont().family());
       
   146     f.setItalic(italic->isChecked());
       
   147     f.setWeight(weightCombo->itemData(weightCombo->currentIndex()).toInt());
       
   148 
       
   149     if (!preview->isModified()) {
       
   150         QFontDatabase db;
       
   151         QFontDatabase::WritingSystem ws = db.writingSystems(f.family()).value(0, QFontDatabase::Any);
       
   152         QString sample = db.writingSystemSample(ws);
       
   153         preview->setText(sample);
       
   154         preview->setModified(false);
       
   155     }
       
   156 
       
   157     fileName->setText(QPF::fileNameForFont(f));
       
   158 
       
   159     preview->setFont(f);
       
   160 }
       
   161 
       
   162 void MainWindow::on_browsePath_clicked()
       
   163 {
       
   164     QString dir = QFileDialog::getExistingDirectory(this, tr("Select Directory"));
       
   165     if (!dir.isEmpty())
       
   166         path->setText(dir);
       
   167 }
       
   168 
       
   169 void MainWindow::on_browseSampleFile_clicked()
       
   170 {
       
   171     QString dir = QFileDialog::getOpenFileName(this, tr("Select Sample File"));
       
   172     if (!dir.isEmpty()) {
       
   173         sampleFile->setText(dir);
       
   174         on_sampleFile_editingFinished();
       
   175     }
       
   176 }
       
   177 
       
   178 void MainWindow::on_generate_clicked()
       
   179 {
       
   180     QFile f(path->text() + QDir::separator() + fileName->text());
       
   181     if (f.exists()) {
       
   182         if (QMessageBox::warning(this, QString(),
       
   183                                  tr("%1 already exists.\nDo you want to replace it?").arg(f.fileName()),
       
   184                                  QMessageBox::Yes | QMessageBox::No, QMessageBox::No)
       
   185             != QMessageBox::Yes) {
       
   186             statusBar()->showMessage(tr("Pre-rendering aborted..."));
       
   187             return;
       
   188         }
       
   189     }
       
   190 
       
   191     QList<QPF::CharacterRange> ranges;
       
   192 
       
   193     if (chooseFromSampleFile->isChecked()) {
       
   194         ranges = sampleFileRanges;
       
   195     } else if (chooseFromCodePoints->isChecked()) {
       
   196         ranges.clear();
       
   197         for (int i = 0; i < characterRangeView->count(); ++i) {
       
   198             QListWidgetItem *item = characterRangeView->item(i);
       
   199             if (item->checkState() != Qt::Checked)
       
   200                 continue;
       
   201 
       
   202             QPF::CharacterRange range = qVariantValue<QPF::CharacterRange>(item->data(Qt::UserRole));
       
   203             ranges.append(range);
       
   204         }
       
   205     }
       
   206 
       
   207     const int generationOptions = QPF::IncludeCMap | QPF::RenderGlyphs;
       
   208     QByteArray qpf = QPF::generate(preview->font(), generationOptions, ranges);
       
   209     f.open(QIODevice::WriteOnly | QIODevice::Truncate);
       
   210     f.write(qpf);
       
   211     f.close();
       
   212 
       
   213     statusBar()->showMessage(tr("Font successfully pre-rendered to %1").arg(fileName->text()));
       
   214 }
       
   215 
       
   216 void MainWindow::on_sampleFile_editingFinished()
       
   217 {
       
   218     sampleFileRanges.clear();
       
   219     QFile f(sampleFile->text());
       
   220     if (!f.open(QIODevice::ReadOnly | QIODevice::Text)) {
       
   221         sampleFileRanges.append(QPF::CharacterRange()); // default = all
       
   222         return;
       
   223     }
       
   224     QTextStream stream(&f);
       
   225     stream.setCodec(QTextCodec::codecForName("utf-8"));
       
   226     stream.setAutoDetectUnicode(true);
       
   227     QString text = stream.readAll();
       
   228 
       
   229     QSet<QChar> coverage;
       
   230     for (int i = 0; i < text.length(); ++i)
       
   231         coverage.insert(text.at(i));
       
   232 
       
   233     QList<QChar> sortedCoverage = QList<QChar>::fromSet(coverage);
       
   234     qSort(sortedCoverage);
       
   235     // play simple :)
       
   236     foreach (QChar ch, sortedCoverage) {
       
   237         QPF::CharacterRange r;
       
   238         r.start = ch.unicode();
       
   239         r.end = r.start + 1;
       
   240         sampleFileRanges.append(r);
       
   241     }
       
   242 
       
   243     charCount->setText(tr("(%1 unique characters found)").arg(sortedCoverage.count()));
       
   244 }
       
   245 
       
   246 void MainWindow::populateCharacterRanges()
       
   247 {
       
   248     QFile f(":/Blocks.txt");
       
   249     if (!f.open(QIODevice::ReadOnly | QIODevice::Text))
       
   250         return;
       
   251 
       
   252     QRegExp rangeExpr("([0-9a-f]+)\\.\\.([0-9a-f]+); (.+)");
       
   253     rangeExpr.setCaseSensitivity(Qt::CaseInsensitive);
       
   254 
       
   255     QString ellipsis(QChar(0x2026));
       
   256     if (!characterRangeView->fontMetrics().inFont(ellipsis.at(0)))
       
   257         ellipsis = QLatin1String("...");
       
   258 
       
   259     while (!f.atEnd()) {
       
   260         QString line = QString::fromAscii(f.readLine());
       
   261 
       
   262         if (line.endsWith(QLatin1Char('\n')))
       
   263             line.chop(1);
       
   264         if (line.endsWith(QLatin1Char('\r')))
       
   265             line.chop(1);
       
   266 
       
   267         line = line.trimmed();
       
   268 
       
   269         if (line.isEmpty() || line.startsWith(QLatin1Char('#')))
       
   270             continue;
       
   271 
       
   272         if (!rangeExpr.exactMatch(line) || rangeExpr.numCaptures() != 3)
       
   273             continue;
       
   274 
       
   275         QPF::CharacterRange range;
       
   276 
       
   277         bool ok = false;
       
   278         range.start = rangeExpr.cap(1).toUInt(&ok, /*base*/16);
       
   279         if (!ok)
       
   280             continue;
       
   281         range.end = rangeExpr.cap(2).toUInt(&ok, /*base*/16);
       
   282         if (!ok)
       
   283             continue;
       
   284 
       
   285         if (range.start >= 0xffff || range.end >= 0xffff)
       
   286             continue;
       
   287 
       
   288         QString description = rangeExpr.cap(3);
       
   289 
       
   290         QListWidgetItem *item = new QListWidgetItem(characterRangeView);
       
   291         QString text = description;
       
   292         text.append(QLatin1String(" ("));
       
   293         text.append(rangeExpr.cap(1));
       
   294         text.append(ellipsis);
       
   295         text.append(rangeExpr.cap(2));
       
   296         text.append(QLatin1String(")"));
       
   297         item->setText(text);
       
   298         item->setCheckState(Qt::Checked);
       
   299 
       
   300         item->setData(Qt::UserRole, qVariantFromValue(range));
       
   301     }
       
   302 }
       
   303 
       
   304 void MainWindow::addCustomFont(const QString &fontFile)
       
   305 {
       
   306     int id = QFontDatabase::addApplicationFont(fontFile);
       
   307     if (id < 0) {
       
   308         QMessageBox::warning(this, tr("Error Adding Custom Font"),
       
   309                              tr("The custom font %s could not be loaded.").arg(fontFile));
       
   310         return;
       
   311     }
       
   312     const QStringList families = QFontDatabase::applicationFontFamilies(id);
       
   313     if (families.isEmpty()) {
       
   314         QMessageBox::warning(this, tr("Error Adding Custom Font"),
       
   315                              tr("The custom font %s provides no font families.").arg(fontFile));
       
   316         return;
       
   317     }
       
   318     QFont f(families.first());
       
   319     fontComboBox->setCurrentFont(f);
       
   320 }
       
   321 
       
   322 QT_END_NAMESPACE