not quite so much needs to be delayed to the init() function
[personal-kdebase.git] / workspace / kcontrol / kfontinst / viewpart / FontViewPart.cpp
blobc428e790240e83a3a8d76599aa44e59728b615b3
1 /*
2 * KFontInst - KDE Font Installer
4 * Copyright 2003-2007 Craig Drummond <craig@kde.org>
6 * ----
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; see the file COPYING. If not, write to
20 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 * Boston, MA 02110-1301, USA.
24 #include "FontViewPart.h"
25 #include "Misc.h"
26 #include "KfiConstants.h"
27 #include "FcEngine.h"
28 #include "PreviewSelectAction.h"
29 #include <QtGui/QGridLayout>
30 #include <QtGui/QBoxLayout>
31 #include <QtGui/QPushButton>
32 #include <QtGui/QFrame>
33 #include <QtCore/QFile>
34 #include <QtGui/QLabel>
35 #include <QtGui/QValidator>
36 #include <QtCore/QRegExp>
37 #include <QtCore/QTimer>
38 #include <QtGui/QApplication>
39 #include <QtGui/QGroupBox>
40 #include <QtCore/QProcess>
41 #include <KDE/KLocale>
42 #include <KDE/KIO/NetAccess>
43 #include <KDE/KIO/Job>
44 #include <KDE/KIO/JobUiDelegate>
45 #include <KDE/KGlobal>
46 #include <KDE/KActionCollection>
47 #include <KDE/KComponentData>
48 #include <KDE/KMessageBox>
49 #include <KDE/KIntNumInput>
50 #include <KDE/KInputDialog>
51 #include <KDE/KDialog>
52 #include <KDE/KIcon>
53 #include <KDE/KMimeType>
54 //#include <KDE/KFileMetaInfo>
55 #include <KDE/KZip>
56 #include <KDE/KTempDir>
57 #include <KDE/KStandardDirs>
58 #include <KDE/KPluginFactory>
59 #include <KDE/KPluginLoader>
60 #include <KDE/KStandardAction>
61 #include <fontconfig/fontconfig.h>
63 // Enable the following to allow printing of non-installed fonts. Does not seem to work :-(
64 //#define KFI_PRINT_APP_FONTS
66 namespace KFI
69 K_PLUGIN_FACTORY(CFontViewPartFactory, registerPlugin<CFontViewPart>();)
70 K_EXPORT_PLUGIN(CFontViewPartFactory("kfontview"))
72 CFontViewPart::CFontViewPart(QWidget *parentWidget, QObject *parent, const QList<QVariant> &)
73 : KParts::ReadOnlyPart(parent),
74 itsConfig(KGlobal::config()),
75 itsProc(NULL),
76 itsTempDir(NULL)
78 // create browser extension (for printing when embedded into browser)
79 itsExtension = new BrowserExtension(this);
81 itsFrame=new QFrame(parentWidget);
83 QFrame *previewFrame=new QFrame(itsFrame);
84 QWidget *controls=new QWidget(itsFrame);
85 // QGroupBox *metaBox=new QGroupBox(i18n("Information:"), controls);
87 itsFaceWidget=new QWidget(controls);
89 QBoxLayout *mainLayout=new QBoxLayout(QBoxLayout::TopToBottom, itsFrame);
91 mainLayout->setMargin(KDialog::marginHint());
92 mainLayout->setSpacing(KDialog::spacingHint());
94 QBoxLayout *previewLayout=new QBoxLayout(QBoxLayout::LeftToRight, previewFrame),
95 *controlsLayout=new QBoxLayout(QBoxLayout::LeftToRight, controls),
96 *faceLayout=new QBoxLayout(QBoxLayout::LeftToRight, itsFaceWidget);
97 // QBoxLayout *metaLayout=new QBoxLayout(QBoxLayout::LeftToRight, metaBox);
99 // itsMetaLabel=new QLabel(metaBox);
100 // itsMetaLabel->setAlignment(Qt::AlignTop);
101 // metaLayout->addWidget(itsMetaLabel);
102 previewLayout->setMargin(0);
103 previewLayout->setSpacing(0);
104 faceLayout->setMargin(0);
105 faceLayout->setSpacing(KDialog::spacingHint());
106 controlsLayout->setMargin(0);
107 previewLayout->setSpacing(0);
109 itsFrame->setFrameShape(QFrame::NoFrame);
110 itsFrame->setFocusPolicy(Qt::ClickFocus);
111 previewFrame->setFrameShape(QFrame::StyledPanel);
112 previewFrame->setFrameShadow(QFrame::Sunken);
113 setComponentData(KComponentData(KFI_NAME));
115 itsPreview=new CFontPreview(previewFrame);
116 itsPreview->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
117 itsFaceLabel=new QLabel(i18n("Show Face:"), itsFaceWidget);
118 itsFaceSelector=new KIntNumInput(1, itsFaceWidget);
119 itsFaceSelector->setSliderEnabled(false);
120 itsInstallButton=new QPushButton(i18n("Install..."), controls);
121 itsInstallButton->setEnabled(false);
122 previewLayout->addWidget(itsPreview);
123 faceLayout->addWidget(itsFaceLabel);
124 faceLayout->addWidget(itsFaceSelector);
125 faceLayout->addItem(new QSpacerItem(KDialog::spacingHint(), 0, QSizePolicy::Fixed, QSizePolicy::Fixed));
126 itsFaceWidget->hide();
128 itsPreview->engine()->readConfig(*itsConfig);
129 CFcEngine::setTextCol(QApplication::palette().color(QPalette::Active, QPalette::Text));
130 connect(itsPreview, SIGNAL(doZoomIn()), SLOT(zoomIn()));
131 connect(itsPreview, SIGNAL(doZoomOut()), SLOT(zoomOut()));
133 //controlsLayout->addWidget(metaBox);
134 //controlsLayout->addStretch(2);
135 controlsLayout->addWidget(itsFaceWidget);
136 controlsLayout->addStretch(1);
137 controlsLayout->addWidget(itsInstallButton);
138 mainLayout->addWidget(previewFrame);
139 mainLayout->addWidget(controls);
140 connect(itsPreview, SIGNAL(status(bool)), SLOT(previewStatus(bool)));
141 connect(itsInstallButton, SIGNAL(clicked()), SLOT(install()));
142 connect(itsFaceSelector, SIGNAL(valueChanged(int)), SLOT(showFace(int)));
144 itsChangeTextAction=actionCollection()->addAction("changeText");
145 itsChangeTextAction->setIcon(KIcon("edit-rename"));
146 itsChangeTextAction->setText(i18n("Change Text..."));
147 connect(itsChangeTextAction, SIGNAL(triggered(bool)), SLOT(changeText()));
149 CPreviewSelectAction *displayTypeAction=new CPreviewSelectAction(this, CPreviewSelectAction::BlocksAndScripts);
150 actionCollection()->addAction("displayType", displayTypeAction);
151 connect(displayTypeAction, SIGNAL(range(const QList<CFcEngine::TRange> &)),
152 SLOT(displayType(const QList<CFcEngine::TRange> &)));
154 itsZoomInAction=actionCollection()->addAction(KStandardAction::ZoomIn, this, SLOT(zoomIn()));
155 itsZoomOutAction=actionCollection()->addAction(KStandardAction::ZoomOut, this, SLOT(zoomOut()));
157 itsZoomInAction->setEnabled(false);
158 itsZoomOutAction->setEnabled(false);
160 setXMLFile("kfontviewpart.rc");
161 setWidget(itsFrame);
162 itsExtension->enablePrint(false);
165 CFontViewPart::~CFontViewPart()
167 delete itsTempDir;
168 itsTempDir=NULL;
171 bool CFontViewPart::openUrl(const KUrl &url)
173 if (!url.isValid() || !closeUrl())
174 return false;
176 // itsMetaLabel->setText(QString());
177 // itsMetaInfo.clear();
179 if(KFI_KIO_FONTS_PROTOCOL==url.protocol() || KIO::NetAccess::mostLocalUrl(url, itsFrame).isLocalFile())
181 setUrl(url);
182 emit started(0);
183 setLocalFilePath(this->url().path());
184 bool ret=openFile();
185 if (ret)
186 emit completed();
187 return ret;
189 else
190 return ReadOnlyPart::openUrl(url);
193 bool CFontViewPart::openFile()
195 // NOTE: Can't do the real open here, as we don't seem to be able to use KIO::NetAccess functions
196 // during initial start-up. Bug report 111535 indicates that calling "konqueror <font>" crashes.
197 itsInstallButton->setEnabled(false);
198 QTimer::singleShot(0, this, SLOT(timeout()));
199 return true;
202 void CFontViewPart::timeout()
204 if(!itsInstallButton)
205 return;
207 bool isFonts(KFI_KIO_FONTS_PROTOCOL==url().protocol()),
208 isDisabled(false),
209 showFs(false);
210 KUrl displayUrl(url()),
211 fileUrl;
212 int fileIndex(-1);
213 QString name;
214 quint32 styleInfo(KFI_NO_STYLE_INFO);
216 // itsMetaUrl=url();
217 delete itsTempDir;
218 itsTempDir=NULL;
220 if(isFonts)
222 FcInitReinitialize();
225 // This is a fonts:/Url. Check to see whether we were passed any details in the query...
226 QString path=url().queryItem(KFI_FILE_QUERY)/*,
227 mime=url().queryItem(KFI_MIME_QUERY)*/;
229 name=url().queryItem(KFI_NAME_QUERY);
230 styleInfo=Misc::getIntQueryVal(url(), KFI_STYLE_QUERY, KFI_NO_STYLE_INFO);
231 fileIndex=Misc::getIntQueryVal(url(), KFI_KIO_FACE, -1);
233 if(name.isEmpty() && path.isEmpty())
235 // OK, no useable info in the query - stat fonts:/ to get the required info...
236 KIO::UDSEntry udsEntry;
238 if(KIO::NetAccess::stat(url(), udsEntry, NULL))
240 name=udsEntry.stringValue(KIO::UDSEntry::UDS_NAME);
241 styleInfo=udsEntry.numberValue(UDS_EXTRA_FC_STYLE);
242 isDisabled=udsEntry.numberValue(KIO::UDSEntry::UDS_HIDDEN, 0) ? true : false;
243 //mime=udsEntry.stringValue(KIO::UDSEntry::UDS_MIME_TYPE);
246 else if(!path.isEmpty())
248 // Its a disabled font, so we can get the file name and index from the query...
249 fileUrl=KUrl::fromPath(path);
250 name=url().fileName();
253 if(!name.isEmpty())
255 displayUrl.setFileName(name.replace("%20", " "));
256 displayUrl.setQuery(QString());
259 // What query to pass to meta info?
260 // if(path.isEmpty())
261 // {
262 // itsMetaUrl.removeQueryItem(KFI_NAME_QUERY);
263 // itsMetaUrl.addQueryItem(KFI_NAME_QUERY, name);
264 // itsMetaUrl.removeQueryItem(KFI_STYLE_QUERY);
265 // if(KFI_NO_STYLE_INFO!=styleInfo)
266 // itsMetaUrl.addQueryItem(KFI_STYLE_QUERY, QString().setNum(styleInfo));
267 // }
268 // else
269 // {
270 // itsMetaUrl.removeQueryItem(KFI_FILE_QUERY);
271 // itsMetaUrl.addQueryItem(KFI_FILE_QUERY, path);
272 // itsMetaUrl.removeQueryItem(KFI_KIO_FACE);
273 // if(fileIndex>0)
274 // itsMetaUrl.addQueryItem(KFI_KIO_FACE, QString().setNum(fileIndex));
275 // }
277 // itsMetaUrl.removeQueryItem(KFI_MIME_QUERY);
278 // itsMetaUrl.addQueryItem(KFI_MIME_QUERY, mime);
280 else
282 QString path(url().path());
284 // Is this a fonts/package file? If so, extract 1 scalable font...
285 if(Misc::isPackage(path))
287 KZip zip(path);
289 if(zip.open(QIODevice::ReadOnly))
291 const KArchiveDirectory *zipDir=zip.directory();
293 if(zipDir)
295 QStringList fonts(zipDir->entries());
297 if(fonts.count())
299 QStringList::ConstIterator it(fonts.begin()),
300 end(fonts.end());
302 for(; it!=end; ++it)
304 const KArchiveEntry *entry=zipDir->entry(*it);
306 if(entry && entry->isFile())
308 delete itsTempDir;
309 itsTempDir=new KTempDir(KStandardDirs::locateLocal("tmp", KFI_TMP_DIR_PREFIX));
310 itsTempDir->setAutoRemove(true);
312 ((KArchiveFile *)entry)->copyTo(itsTempDir->name());
314 QString mime(KMimeType::findByPath(itsTempDir->name()+entry->name())->name());
316 if(mime=="application/x-font-ttf" || mime=="application/x-font-otf" ||
317 mime=="application/x-font-type1")
319 setLocalFilePath(itsTempDir->name()+entry->name());
320 // itsMetaUrl=KUrl::fromPath(localFilePath());
321 break;
323 else
324 ::unlink(QFile::encodeName(itsTempDir->name()+entry->name()).data());
333 itsInstallButton->setEnabled(false);
334 if(!isFonts)
335 stat();
337 emit setWindowCaption(Misc::prettyUrl(displayUrl));
339 if(isFonts && -1!=fileIndex)
340 itsPreview->showFont(fileUrl, QString(), styleInfo, fileIndex);
341 else
342 itsPreview->showFont(isFonts ? url() : KUrl::fromPath(localFilePath()), isDisabled ? QString() : name, styleInfo);
344 if(!isFonts && itsPreview->engine()->getNumIndexes()>1)
346 showFs=true;
347 itsFaceSelector->setRange(1, itsPreview->engine()->getNumIndexes(), 1);
348 itsFaceSelector->blockSignals(true);
349 itsFaceSelector->setValue(1);
350 itsFaceSelector->blockSignals(false);
353 itsFaceWidget->setVisible(showFs);
356 void CFontViewPart::previewStatus(bool st)
358 bool printable(false);
360 if(st)
361 if(KFI_KIO_FONTS_PROTOCOL==url().protocol())
362 printable=!Misc::isHidden(url());
363 #ifdef KFI_PRINT_APP_FONTS
364 else
366 // TODO: Make this work! Plus, printing of disabled TTF/OTF's should also be possible!
367 KMimeType::Ptr mime=KMimeType::findByUrl(KUrl::fromPath(localFilePath()), 0, false, true);
369 printable=mime->is("application/x-font-ttf") || mime->is("application/x-font-otf");
371 #endif
373 itsChangeTextAction->setEnabled(st);
374 itsExtension->enablePrint(st && printable);
375 itsZoomInAction->setEnabled(st && !itsPreview->engine()->atMax());
376 itsZoomOutAction->setEnabled(st && !itsPreview->engine()->atMin());
378 // if(st)
379 // getMetaInfo(itsFaceSelector->isVisible() && itsFaceSelector->value()>0
380 // ? itsFaceSelector->value()-1 : 0);
381 // else
382 if(!st)
383 KMessageBox::error(itsFrame, i18n("Could not read font."));
386 void CFontViewPart::install()
388 if(!itsProc || QProcess::NotRunning==itsProc->state())
390 QStringList args;
392 if(!itsProc)
393 itsProc=new QProcess(this);
394 else
395 itsProc->kill();
397 args << "--embed" << QString().sprintf("0x%x", (unsigned int)(itsFrame->window()->winId()))
398 << "--caption" << KGlobal::caption().toUtf8()
399 << "--icon" << "kfontview"
400 << url().prettyUrl();
402 connect(itsProc, SIGNAL(finished(int, QProcess::ExitStatus)), SLOT(installlStatus()));
403 itsProc->start(KFI_INSTALLER, args);
404 itsInstallButton->setEnabled(false);
408 void CFontViewPart::installlStatus()
410 stat();
413 void CFontViewPart::changeText()
415 bool status;
416 QRegExpValidator validator(QRegExp(".*"), 0L);
417 QString oldStr(itsPreview->engine()->getPreviewString()),
418 newStr(KInputDialog::getText(i18n("Preview String"),
419 i18n("Please enter new string:"),
420 oldStr, &status, itsFrame, &validator));
422 if(status && newStr!=oldStr)
424 itsPreview->engine()->setPreviewString(newStr);
425 itsPreview->engine()->writeConfig(*itsConfig);
426 itsPreview->showFont();
430 void CFontViewPart::print()
432 QString exe(KStandardDirs::findExe(QLatin1String(KFI_PRINTER), KStandardDirs::installPath("libexec")));
434 if(exe.isEmpty())
435 KMessageBox::error(itsFrame, i18n("Failed to locate font printer."));
436 else
438 QStringList args;
440 if(KFI_KIO_FONTS_PROTOCOL==url().protocol())
442 Misc::TFont info;
444 itsPreview->engine()->getInfo(url(), 0, info);
446 args << "--embed" << QString().sprintf("0x%x", (unsigned int)(itsFrame->window()->winId()))
447 << "--caption" << KGlobal::caption().toUtf8()
448 << "--icon" << "kfontview"
449 << "--size" << "0"
450 << "--pfont" << QString(info.family+','+QString().setNum(info.styleInfo));
452 #ifdef KFI_PRINT_APP_FONTS
453 else
454 args << "--embed" << QString().sprintf("0x%x", (unsigned int)(itsFrame->window()->winId()))
455 << "--caption" << KGlobal::caption().toUtf8()
456 << "--icon" << "kfontview"
457 << "--size " << "0"
458 << localFilePath()
459 << QString().setNum(KFI_NO_STYLE_INFO);
460 #endif
462 if(args.count())
463 QProcess::startDetached(exe, args);
467 void CFontViewPart::displayType(const QList<CFcEngine::TRange> &range)
469 itsPreview->setUnicodeRange(range);
470 itsChangeTextAction->setEnabled(0==range.count());
473 void CFontViewPart::statResult(KJob *job)
475 bool exists=!job->error();
477 if(!Misc::root() && !exists && !itsStatName.isEmpty())
479 // OK, file does not exist in fonts:/System, try fonts:/Personal
480 stat(QString(KFI_KIO_FONTS_PROTOCOL":/")+i18n(KFI_KIO_FONTS_USER)+QChar('/')+itsStatName);
481 itsStatName=QString();
482 return;
485 itsInstallButton->setEnabled(!exists);
488 void CFontViewPart::showFace(int face)
490 itsPreview->showFace(face-1);
493 void CFontViewPart::zoomIn()
495 itsPreview->zoomIn();
496 itsZoomInAction->setEnabled(!itsPreview->engine()->atMax());
497 itsZoomOutAction->setEnabled(!itsPreview->engine()->atMin());
500 void CFontViewPart::zoomOut()
502 itsPreview->zoomOut();
503 itsZoomInAction->setEnabled(!itsPreview->engine()->atMax());
504 itsZoomOutAction->setEnabled(!itsPreview->engine()->atMin());
507 #if 0
508 void CFontViewPart::getMetaInfo(int face)
510 if(itsMetaInfo[face].isEmpty())
512 // Pass as much inofmration as possible to analyzer...
513 if(KFI_KIO_FONTS_PROTOCOL!=itsMetaUrl.protocol())
515 itsMetaUrl.removeQueryItem(KFI_KIO_FACE);
516 if(face>0)
517 itsMetaUrl.addQueryItem(KFI_KIO_FACE, QString().setNum(face));
520 KFileMetaInfo meta(itsMetaUrl);
522 if(meta.isValid() && meta.keys().count())
524 QStringList keys(meta.keys());
525 QStringList::const_iterator it(keys.begin()),
526 end(keys.end());
528 itsMetaInfo[face]="<table>";
529 for(; it!=end; ++it)
531 KFileMetaInfoItem mi(meta.item(*it));
533 itsMetaInfo[face]+="<tr><td><b>"+mi.name()+"</b></td></tr><tr><td>"+
534 mi.value().toString()+"</td></tr>";
537 itsMetaInfo[face]+="</table>";
538 itsMetaLabel->setText(itsMetaInfo[face]);
540 else
541 itsMetaLabel->setText(i18n("<p>No information</p>"));
543 else
544 itsMetaLabel->setText(itsMetaInfo[face]);
546 #endif
548 void CFontViewPart::stat(const QString &path)
550 KUrl statUrl;
552 if(path.isEmpty())
554 itsStatName=itsPreview->engine()->getName(url());
555 statUrl=Misc::root() ? KUrl(QString(KFI_KIO_FONTS_PROTOCOL":/")+itsStatName)
556 : KUrl(QString(KFI_KIO_FONTS_PROTOCOL":/")+i18n(KFI_KIO_FONTS_SYS)+QChar('/')+itsStatName);
558 else
559 statUrl=KUrl(path);
561 KIO::StatJob * job = KIO::stat(statUrl, KIO::HideProgressInfo);
562 job->ui()->setWindow(itsFrame->parentWidget());
563 job->setSide(KIO::StatJob::SourceSide);
564 connect(job, SIGNAL(result (KJob *)), this, SLOT(statResult(KJob *)));
567 BrowserExtension::BrowserExtension(CFontViewPart *parent)
568 : KParts::BrowserExtension(parent)
570 setURLDropHandlingEnabled(true);
573 void BrowserExtension::enablePrint(bool enable)
575 if(enable!=isActionEnabled("print"))
576 emit enableAction("print", enable);
579 void BrowserExtension::print()
581 static_cast<CFontViewPart*>(parent())->print();
586 #include "FontViewPart.moc"