1 /***************************************************************************
2 * Copyright (C) 2007 by Pierre Marchand *
3 * pierre@oep-h.com *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
20
21
22
23 #include "aboutwidget.h"
24 #include "browserwidget.h"
25 #include "dataexport.h"
26 #include "dataloader.h"
27 #include "dumpdialog.h"
28 #include "floatingwidget.h"
29 #include "floatingwidgetsregister.h"
30 #include "fmactivate.h"
31 #include "fmfontdb.h"
32 #include "fmfontextract.h"
33 #include "fmmatchraster.h"
34 #include "fmlayout.h"
35 #include "fmpaths.h"
36 #include "fmrepair.h"
37 #include "fontbook.h"
38 #include "fontcomparewidget.h"
39 #include "fontitem.h"
40 // #include "helpwidget.h"
41 #include "helpbrowser.h"
42 #include "hyphenate/fmhyphenator.h"
43 #include "importedfontsdialog.h"
44 #include "importtags.h"
45 //#include "listdockwidget.h"
46 #include "mainviewwidget.h"
47 #include "panosedialog.h"
48 #include "panosewidget.h"
49 #include "playwidget.h"
50 #include "prefspaneldialog.h"
51 #include "remotedir.h"
52 //#include "savedata.h"
53 #include "shortcuts.h"
54 #include "systray.h"
55 #include "tagswidget.h"
56 #include "tttableview.h"
57 #include "typotek.h"
58 #include "winutils.h"
59
60 #include <QDesktopWidget>
61 #include <QtGui>
62 #include <QTextEdit>
63 #include <QTextStream>
64 #include <QCloseEvent>
65 #include <QFileDialog>
66 #include <QDir>
67 #include <QProgressDialog>
68 #include <QProgressBar>
69 #include <QDomDocument>
70 #include <QProcess>
71 #include <QDockWidget>
72 #include <QStackedWidget>
73 #include <QMessageBox>
74
75 #ifdef HAVE_FONTCONFIG
76 #include <fontconfig/fontconfig.h>
77 #endif
78
79
80 #ifdef HAVE_PYTHONQT
81 #include "fmpython_w.h"
82 #include "fmscriptconsole.h"
83 #define MAX_RECENT_PYSCRIPTS 10
84 #endif // HAVE_PYTHONQT
85
86 #ifdef Q_WS_MAC
87 #include <ApplicationServices/ApplicationServices.h>
88 #endif
89
90 typotek* typotek::instance = 0;
91 bool typotek::matrix = false;
92 QString typotek::fonteditorPath = "/usr/bin/fontforge";
93 extern bool __FM_SHOW_FONTLOADED;
94 extern int fm_num_face_opened;
95
96
97 /// LazyInit *********************************************
run()98 void LazyInit::run()
99 {
100 /// We keep this for further needs
101 emit endOfRun();
102 }
103 ///******************************************************
104
105 /// a bit of globalness *******************************************
106 namespace fontmatrix
107 {
exploreDirs(const QDir & dir,int deep)108 QStringList exploreDirs ( const QDir &dir, int deep )
109 {
110 static QStringList retDirList;
111 if ( deep > 10 )
112 return QStringList();
113 if ( deep == 0 )
114 retDirList.clear();
115 retDirList << dir.absolutePath();
116 QStringList localEntries ( dir.entryList ( QDir::AllDirs | QDir::NoDotAndDotDot ) );
117 foreach ( QString dirEntry, localEntries )
118 {
119 // qDebug() << "[exploreDirs] - " + dir.absolutePath() + "/" + dirEntry;
120 QDir d ( dir.absolutePath() + "/" + dirEntry );
121 exploreDirs ( d, deep + 1 );
122 if ( !retDirList.contains ( d.absolutePath() ) )
123 retDirList << d.absolutePath();
124 }
125
126 return retDirList;
127 }
128
129
130 QMap<QString , Qt::DockWidgetArea> DockPosition;
131
fillDockPos()132 void fillDockPos()
133 {
134 DockPosition["Float"] = Qt::LeftDockWidgetArea;
135 DockPosition["Left"] = Qt::LeftDockWidgetArea;
136 DockPosition["Right"]= Qt::RightDockWidgetArea;
137 DockPosition["Top"]= Qt::TopDockWidgetArea;
138 DockPosition["Bottom"]= Qt::BottomDockWidgetArea;
139 }
140 }
141
142 /// *****************************************************
143
getInstance()144 typotek * typotek::getInstance()
145 {
146 if(!instance)
147 {
148 instance = new typotek;
149 Q_ASSERT(instance);
150 }
151 return instance;
152 }
153
typotek()154 typotek::typotek()
155 {
156 setWindowTitle ( "Fontmatrix" );
157 setupDrop();
158 theMainView = 0;
159 hyphenator = 0;
160 theHelp = 0;
161 dataLoader = 0;
162 playVisible = false;
163
164 m_dpiX = ( double ) QApplication::desktop()->physicalDpiX();
165 m_dpiY = ( double ) QApplication::desktop()->physicalDpiY();
166 #ifdef Q_WS_MAC
167 CGDirectDisplayID macDId = CGMainDisplayID();
168 CGRect macDRect = CGDisplayBounds(macDId);
169 CGSize macDSize = CGDisplayScreenSize(macDId);
170
171 double macDisplayPxWidth(macDRect.size.width);
172 double macDisplayPxHeight(macDRect.size.height);
173 double macDisplayPhysicalWidth(double(macDSize.width) / 25.4);
174 double macDisplayPhysicalHeight(double(macDSize.height) / 25.4);
175
176 m_dpiX = macDisplayPxWidth / macDisplayPhysicalWidth;
177 m_dpiY = macDisplayPxHeight / macDisplayPhysicalHeight;
178 #endif
179
180 qDebug()<< m_dpiX << m_dpiY;
181 }
182
initMatrix()183 void typotek::initMatrix()
184 {
185 qDebug()<<"Main Thread:"<<thread();
186 if(matrix)
187 return;
188 matrix = true;
189 fontmatrix::fillDockPos();
190
191 checkOwnDir();
192 readSettings();
193 initDir();
194
195
196 theMainView = new MainViewWidget ( this );
197 theBrowser = new BrowserWidget(this);
198 mainStack = new QStackedWidget(this);
199
200 mainStack->addWidget(theMainView);
201 mainStack->addWidget(theBrowser);
202 setCentralWidget ( mainStack );
203
204 if ( QSystemTrayIcon::isSystemTrayAvailable() )
205 systray = new Systray();
206 else
207 systray = 0;
208
209 setDockOptions(QMainWindow::AnimatedDocks | QMainWindow::ForceTabbedDocks);
210
211 // installDock("Main", tr ( "Browse Fonts" ), ListDockWidget::getInstance() , tr ( "Show/hide fonts browsing sidebar" ));
212 // installDock("Tags", tr ( "Tags" ), TagsWidget::getInstance() , tr ( "Show/hide tags list sidebar" ) );
213 // installDock("Panose", tr ( "Panose"), PanoseWidget::getInstance(), tr ( "Browse fonts by means of Panose attributes" ) );
214
215 // force tabifyication
216 // QStringList dl;
217 // dl << "Tags" << "Panose" << "Main";
218 // for(int i(1); i < dl.count(); ++i)
219 // {
220 // if(dockArea[dl[i]] != "Float")
221 // {
222 // for(int j(i-1); j >=0 ; --j)
223 // {
224 // if(dockArea[dl[j]] == dockArea[dl[i]])
225 // tabifyDockWidget(dockWidget[dl[j]], dockWidget[dl[i]]);
226 // }
227 // }
228 // }
229
230 createActions();
231 createMenus();
232 createStatusBar();
233 doConnect();
234
235 showToltalFilteredFonts();
236
237 if(!hyphenator)
238 {
239 QSettings st;
240 QString dP( st.value("Sample/HyphenationDict", "hyph.dic").toString() );
241 if(QFileInfo(dP).exists())
242 {
243 hyphenator = new FMHyphenator();
244 if (!hyphenator->loadDict(dP, st.value("Sample/HyphLeft", 2).toInt(), st.value("Sample/HyphRight", 3).toInt())) {
245 st.setValue("Sample/HyphenationDict", "");
246 st.setValue("Sample/HyphLeft", 2);
247 st.setValue("Sample/HyphRight", 3);
248 }
249 }
250 else
251 {
252 hyphenator = new FMHyphenator(); // init the hyphenator anyway for the prefs
253 st.setValue("Sample/HyphenationDict", "");
254 st.setValue("Sample/HyphLeft", 2);
255 st.setValue("Sample/HyphRight", 3);
256 qDebug()<<"Err H"<<dP;
257 }
258 }
259 }
260
installDock(const QString & id,const QString & name,QWidget * w,const QString & tip)261 void typotek::installDock(const QString& id, const QString& name, QWidget * w, const QString& tip)
262 {
263 QDockWidget * dw = new QDockWidget(name);
264 dw->setObjectName(id);
265 dockWidget[id] = dw;
266 dw->setWidget( w );
267 dw->setStatusTip ( tip );
268 addDockWidget(fontmatrix::DockPosition[dockArea[id]], dw);
269 qDebug()<<"I"<<id<<dockArea[id]<<dockVisible[id];
270 if(dockArea[id] == QString("Float"))
271 dw->setFloating(true);
272 if(!dockGeometry[id].isNull())
273 dw->setGeometry(dockGeometry[id]);
274
275 connect(dw , SIGNAL(dockLocationChanged( Qt::DockWidgetArea )),
276 this, SLOT(slotDockAreaChanged(Qt::DockWidgetArea )));
277 }
278
postInit()279 void typotek::postInit()
280 {
281 // TODO restore last filter
282 // theMainView->slotViewAll();
283
284 QSettings st;
285 QString cname(st.value("CurrentFont", QString()).toString());
286 // if(!cname.isEmpty())
287 // {
288 // if(!ListDockWidget::getInstance()->fontTree->slotSetCurrent(cname))
289 // theMainView->displayWelcomeMessage();
290 // }
291 // else
292 // theMainView->displayWelcomeMessage();
293 }
294
doConnect()295 void typotek::doConnect()
296 {
297 if(getSystray())
298 connect ( FMActivate::getInstance() ,SIGNAL ( activationEvent ( const QStringList& ) ), getSystray(),SLOT ( updateTagMenu ( const QStringList& ) ) );
299
300 // connect(FMLayout::getLayout()->optionDialog,SIGNAL(finished( int )),this,SLOT(slotUpdateLayOptStatus()));
301 #ifdef HAVE_PYTHONQT
302 connect(FMScriptConsole::getInstance(),SIGNAL(finished()), this, SLOT(slotUpdateScriptConsoleStatus()));
303 #endif
304 connect(toggleMainViewButton, SIGNAL(toggled(bool)), this, SLOT(toggleMainView(bool)));
305 }
306
closeEvent(QCloseEvent * event)307 void typotek::closeEvent ( QCloseEvent *event )
308 {
309 QSettings settings ;
310 if ( systray )
311 {
312 if ( systray->isVisible() && settings.value ( "Systray/CloseToTray", true ).toBool() )
313 {
314 if ( !settings.value ( "Systray/CloseNoteShown", false ).toBool() )
315 {
316 QMessageBox::information ( this, tr ( "Fontmatrix" ),
317 tr ( "The program will keep running in the "
318 "system tray. To terminate the program, "
319 "choose <b>Exit</b> in the context menu "
320 "of the system tray entry." ) );
321 settings.setValue ( "Systray/CloseNoteShown", true );
322 }
323 hide();
324 event->ignore();
325 return;
326 }
327 }
328
329 foreach(FloatingWidget *f, FloatingWidgetsRegister::AllWidgets())
330 {
331 f->close();
332 }
333 writeSettings();
334
335 delete PlayWidget::getInstance();
336 delete FontCompareWidget::getInstance();
337 delete theMainView;
338
339 event->accept();
340
341 }
342
343 /// IMPORT
344 // if announce == true user will be shown a dialog of imported fonts
345 // if announce == false and collect == true all fonts imported will be
346 // collected and announced next time announce == true
open(QString path,bool recursive,bool announce,bool collect)347 void typotek::open ( QString path, bool recursive, bool announce, bool collect )
348 {
349 static QStringList nameList;
350 static QStringList tali; // tali gets reseted when announce = true then the shouldAskTali is also set to true
351 static bool shouldAskTali = true; // initial tags is only asked once if collect == true
352 QStringList pathList;
353
354 QFileInfo finfo ( path );
355 if ( finfo.isDir() || path.isEmpty() ) // importing a directory
356 {
357 static QSettings settings;
358 static QString dir = settings.value ( "Places/LastUsedFolder", QDir::homePath() ).toString(); // first time use the home path then remember the last used dir
359 QDir d ( dir );
360 if ( !d.exists() )
361 dir = QDir::homePath();
362
363 QString tmpdir;
364
365 if ( !path.isEmpty() )
366 tmpdir = path;
367 else
368 tmpdir = QFileDialog::getExistingDirectory ( this, tr ( "Add Directory" ), dir , QFileDialog::ShowDirsOnly );
369
370 if ( tmpdir.isEmpty() )
371 return; // user choose to cancel the import process
372
373 dir = tmpdir; // only set dir if importing wasn't cancelled
374 settings.setValue ( "Places/LastUsedFolder", dir );
375
376
377 QStringList dirList;
378 if(recursive)
379 dirList = fontmatrix::exploreDirs ( dir,0 ) ;
380 else
381 dirList.append(dir);
382 // qDebug() << dirList.join ( "\n" );
383
384 QStringList yetHereFonts;
385 // for(int i=0;i < fontMap.count() ; ++i)
386 // yetHereFonts << fontMap[i]->path();
387 yetHereFonts = FMFontDb::DB()->AllFontNames();
388
389 QStringList filters;
390 filters << "*.otf" << "*.pfb" << "*.ttf" << "*.ttc";
391 foreach ( QString dr, dirList )
392 {
393 QDir d ( dr );
394 QFileInfoList fil= d.entryInfoList ( filters );
395 foreach ( QFileInfo fp, fil )
396 {
397 if ( ( !yetHereFonts.contains ( fp.absoluteFilePath() ) ) )
398 {
399 if ( fp.isSymLink() ) // #12232
400 {
401 QFileInfo fsym ( fp.symLinkTarget() );
402 if ( ( !fsym.isSymLink() ) // hey, donnot try to fool us with nested symlinks :)
403 && ( fsym.exists() )
404 && ( !yetHereFonts.contains ( fsym.absoluteFilePath() ) ) )
405 pathList << fsym.absoluteFilePath();
406
407 }
408 else
409 pathList << fp.absoluteFilePath();
410 }
411 }
412 }
413 }
414 else if ( finfo.isFile() )
415 pathList << finfo.absoluteFilePath();
416
417 // It can happen that you wrongly select a dir, it is time to let the user cancel the import.
418 // I want it :) - pm
419 if ( /*( pathList.count() > 1 )
420 &&*/ ( QMessageBox::question ( this,
421 QString ( "Fontmatrix - %1" ).arg ( tr ( "Confirmation" ) ) ,
422 tr ( "Do you confirm you want to import %n font(s)?", "", pathList.count()),
423 QMessageBox::Yes | QMessageBox::No,
424 QMessageBox::No )
425 != QMessageBox::Yes ) )
426 {
427 return;
428 }
429
430 /* Everybody say it’s useless...
431 NO IT'S NOT. I'm a keen fan of this feature. Let's make it optional */
432 QStringList tagsList ( FMFontDb::DB()->getTags() );
433 if ( useInitialTags && shouldAskTali )
434 {
435 ImportTags imp ( this,tagsList );
436 imp.exec();
437 tali = imp.tags();
438 shouldAskTali = false;
439 }
440
441 QProgressDialog progress ( tr ( "Importing font files... " ), tr ( "cancel" ), 0, pathList.count(), this );
442 bool showProgress = pathList.count() > 1;
443 if ( showProgress ) // show progress bar only if there's more than one font
444 {
445 progress.setWindowModality ( Qt::WindowModal );
446 progress.setAutoReset ( false );
447 progress.setValue ( 0 );
448 progress.show();
449 }
450 FMFontDb::DB()->TransactionBegin();
451 QString importstring ( tr ( "Import" ) + " %1" );
452 FMFontDb *DB ( FMFontDb::DB() );
453 QList<FontItem*> nf;
454 for ( int i = 0 ; i < pathList.count(); ++i )
455 {
456 QString pathCur ( pathList.at ( i ) );
457 if ( showProgress )
458 {
459 progress.setLabelText ( importstring.arg ( pathCur ) );
460 progress.setValue ( i );
461 if ( progress.wasCanceled() )
462 break;
463 }
464
465
466
467 {
468 QFile ff ( pathCur );
469 QFileInfo fi ( pathCur );
470 {
471 FontItem *fitem ( DB->Font ( fi.absoluteFilePath(), true ) );
472 if ( fitem )
473 {
474 nf << fitem;
475 fitem->setActivated ( false );
476 if ( announce || collect )
477 nameList << fitem->fancyName();
478 }
479 else
480 {
481 QString errorFont ( tr ( "Cannot import this font because it is broken:" ) +" "+fi.fileName() );
482 statusBar()->showMessage ( errorFont );
483 if ( announce || collect )
484 nameList << "__FAILEDTOLOAD__" + fi.fileName();
485 }
486 }
487 }
488 }
489
490 QStringList tl;
491 foreach ( QString tag, tali )
492 {
493 tl.clear();
494 foreach ( FontItem* f, nf )
495 {
496 tl << f->path();
497 }
498 DB->addTag ( tl, tag );
499 }
500 DB->TransactionEnd();
501 progress.close();
502
503 if ( announce )
504 {
505 if ( showFontListDialog )
506 {
507 // The User needs and deserves to know what fonts hve been imported
508 ImportedFontsDialog ifd ( this, nameList );
509 ifd.exec();
510 }
511 else // show info in the statusbar
512 {
513 statusBar()->showMessage ( tr ( "Fonts imported: %1" ).arg ( nameList.count() ), 3000 );
514 }
515 nameList.clear();
516 tali.clear();
517 shouldAskTali = true;
518 }
519 emit newFontsArrived();
520 }
521
importFiles()522 void typotek::importFiles()
523 {
524 QStringList flist = QFileDialog::getOpenFileNames(this,
525 tr("Select Files to Import"),
526 QDir::homePath(),
527 QString("%1 (*.otf *.ttf *.ttc *.pfb)").arg(tr("Font Files")));
528 if(!flist.isEmpty())
529 openList(flist);
530 }
531
532 /// Import files in a drop event.
openList(QStringList files)533 void typotek::openList ( QStringList files )
534 {
535 QStringList pathList;
536 QStringList nameList;
537 QStringList tali;
538 QStringList tagsList ( FMFontDb::DB()->getTags() );
539 if ( useInitialTags )
540 {
541 ImportTags imp ( this,tagsList );
542 imp.exec();
543 tali = imp.tags();
544 }
545
546 FMFontDb *DB ( FMFontDb::DB() );
547 QStringList fontMap ( DB->AllFontNames() );
548 foreach ( QString file, files )
549 {
550 QFileInfo fp ( file );
551 if ( ( !fontMap.contains ( fp.absoluteFilePath() ) ) )
552 {
553 if ( fp.isSymLink() ) // #12232
554 {
555 QFileInfo fsym ( fp.symLinkTarget() );
556 if ( ( !fsym.isSymLink() )
557 && ( fsym.exists() )
558 && ( !fontMap.contains ( fsym.absoluteFilePath() ) ) )
559 pathList << fsym.absoluteFilePath();
560
561 }
562 else
563 pathList << fp.absoluteFilePath();
564 }
565 }
566
567 DB->TransactionBegin();
568 QProgressDialog progress ( tr ( "Importing font files... " ),tr ( "cancel" ), 0, pathList.count(), this );
569 progress.setWindowModality ( Qt::WindowModal );
570 progress.setAutoReset ( false );
571
572 QList<FontItem*> nf;
573 QString importstring ( tr ( "Import" ) +" %1" );
574 for ( int i = 0 ; i < pathList.count(); ++i )
575 {
576 progress.setLabelText ( importstring.arg ( pathList.at ( i ) ) );
577 progress.setValue ( i );
578 if ( progress.wasCanceled() )
579 break;
580
581 QFile ff ( pathList.at ( i ) );
582 QFileInfo fi ( pathList.at ( i ) );
583
584 FontItem *fitem = DB->Font ( fi.absoluteFilePath() ,true );
585 if ( fitem )
586 {
587 nf << fitem;
588 nameList << fitem->fancyName();
589 }
590 else
591 {
592 QString errorFont ( tr ( "Cannot import this font because it is broken: " ) +" "+fi.fileName() );
593 // statusBar()->showMessage ( errorFont );
594 nameList << "__FAILEDTOLOAD__" + fi.fileName();
595 }
596 }
597 QStringList tl;
598 foreach ( QString tag, tali )
599 {
600 tl.clear();
601 foreach ( FontItem* f, nf )
602 {
603 tl << f->path();
604 }
605 DB->addTag ( tl, tag );
606 }
607 DB->TransactionEnd();
608 progress.close();
609
610 // The User needs and deserves to know what fonts hve been imported
611 if ( showFontListDialog )
612 {
613 // The User needs and deserves to know what fonts hve been imported
614 ImportedFontsDialog ifd ( this, nameList );
615 ifd.exec();
616 }
617 else // show info in the statusbar
618 {
619 statusBar()->showMessage ( tr ( "Fonts imported: %1" ).arg ( nameList.count() ), 3000 );
620 }
621 emit newFontsArrived();
622
623 }
624
625 /// EXPORT
slotExportFontSet()626 void typotek::slotExportFontSet()
627 {
628 // QStringList tagsList(FMFontDb::DB()->getTags());
629 // QStringList items ( tagsList );
630 // bool ok;
631 // QString item = QInputDialog::getItem ( this, tr ( "Fontmatrix Tags" ),
632 // tr ( "Choose the tag for filter exported fonts" ), items, 0, false, &ok );
633 // if ( ok && !item.isEmpty() )
634 // {
635
636
637 // QString dir( QDir::homePath() );
638 // dir = QFileDialog::getExistingDirectory ( this, tr ( "Choose Directory" ), dir , QFileDialog::ShowDirsOnly );
639 // if ( dir.isEmpty() )
640 // return;
641
642 // DataExport dx(dir,item);
643 // dx.doExport();
644 // }
645 new DataExport(this);
646 }
647
648
about()649 void typotek::about()
650 {
651 AboutWidget aabout(this);
652 aabout.exec();
653 }
654
createActions()655 void typotek::createActions()
656 {
657 Shortcuts *scuts = Shortcuts::getInstance();
658
659 openAct = new QAction ( QIcon ( ":/fontmatrix_import_icon" ), tr ( "&Import Directory..." ), this );
660 openAct->setShortcut ( Qt::CTRL + Qt::Key_O );
661 openAct->setToolTip( tr ( "Import a directory" ) );
662 scuts->add(openAct);
663 connect ( openAct, SIGNAL ( triggered() ), this, SLOT ( open() ) );
664
665 importFilesAction = new QAction(QIcon ( ":/fontmatrix_import_icon" ), tr ( "Import &Files..." ), this );
666 importFilesAction->setShortcut( Qt::CTRL + Qt::SHIFT + Qt::Key_O );
667 importFilesAction->setToolTip(tr("Import Files"));
668 scuts->add(importFilesAction);
669 connect(importFilesAction, SIGNAL(triggered()), this, SLOT(importFiles()));
670
671 exportFontSetAct = new QAction(tr("Export &fonts"),this);
672 exportFontSetAct->setStatusTip(tr("Export a fontset"));
673 scuts->add(exportFontSetAct);
674 connect( exportFontSetAct,SIGNAL(triggered( )),this,SLOT(slotExportFontSet()));
675
676
677 fontBookAct = new QAction ( QIcon ( ":/fontmatrix_fontbookexport_icon.png" ), tr ( "Export font book..." ),this );
678 fontBookAct->setStatusTip ( tr ( "Export a PDF document that shows selected fonts" ) );
679 scuts->add(fontBookAct);
680 connect ( fontBookAct, SIGNAL ( triggered() ), this, SLOT ( fontBook() ) );
681
682 dumpInfoAct = new QAction(tr("Export font info for packaging..."), this);
683 dumpInfoAct->setStatusTip ( tr ( "Fill a template file with metadata for packaging currently selected font to a Linux distribution" ) );
684 connect(dumpInfoAct, SIGNAL(triggered()), this, SLOT(slotDumpInfo()));
685
686 exitAct = new QAction ( tr ( "E&xit" ), this );
687 exitAct->setShortcut ( Qt::CTRL + Qt::Key_Q );
688 exitAct->setStatusTip ( tr ( "Exit the application" ) );
689 exitAct->setMenuRole(QAction::QuitRole);
690 scuts->add(exitAct);
691 connect ( exitAct, SIGNAL ( triggered() ), this, SLOT ( close() ) );
692
693
694 aboutAct = new QAction ( tr ( "&About" ), this );
695 aboutAct->setStatusTip ( tr ( "Show information about Fontmatrix" ) );
696 aboutAct->setMenuRole(QAction::AboutRole);
697 scuts->add(aboutAct);
698 connect ( aboutAct, SIGNAL ( triggered() ), this, SLOT ( about() ) );
699
700 aboutQtAct = new QAction ( tr ( "About &Qt" ), this );
701 aboutQtAct->setStatusTip ( tr ( "Show information about Qt" ) );
702 aboutQtAct->setMenuRole(QAction::AboutQtRole);
703 scuts->add(aboutQtAct);
704 connect (aboutQtAct,SIGNAL(triggered()), QApplication::instance(),SLOT(aboutQt()));
705
706 helpAct = new QAction ( tr ( "Help" ), this );
707 helpAct->setShortcut ( Qt::Key_F1 );
708 helpAct->setStatusTip ( tr ( "Read documentation on Fontmatrix" ) );
709 helpAct->setCheckable(true);
710 helpAct->setChecked(false);
711 scuts->add(helpAct);
712 connect ( helpAct,SIGNAL ( triggered( ) ),this,SLOT ( helpBegin() ) );
713
714 // tagsetAct = new QAction ( tr ( "&Tag Sets" ),this );
715 // tagsetAct->setIcon ( QIcon ( ":/fontmatrix_tagseteditor_icon.png" ) );
716 // scuts->add(tagsetAct);
717 // connect ( tagsetAct,SIGNAL ( triggered( ) ),this,SLOT ( popupTagsetEditor() ) );
718
719 activCurAct = new QAction ( tr ( "Activate all current" ),this );
720 activCurAct->setStatusTip ( tr ( "Activate all currently visible fonts" ) );
721 scuts->add(activCurAct);
722 connect ( activCurAct,SIGNAL ( triggered( ) ),this,SLOT ( slotActivateCurrents() ) );
723
724 deactivCurAct = new QAction ( tr ( "Deactivate all current" ),this );
725 deactivCurAct->setStatusTip ( tr ( "Deactivate all currently visible fonts" ) );
726 scuts->add(deactivCurAct);
727 connect ( deactivCurAct,SIGNAL ( triggered( ) ),this,SLOT ( slotDeactivateCurrents() ) );
728
729 fonteditorAct = new QAction ( tr ( "Edit current font" ),this );
730 scuts->add(fonteditorAct);
731 connect ( fonteditorAct,SIGNAL ( triggered( ) ),this,SLOT ( slotEditFont() ) );
732 if ( QFile::exists ( fonteditorPath ) )
733 {
734 fonteditorAct->setStatusTip ( tr ( "Edit currently selected font in a font editor of your choice" ) );
735 }
736 else
737 {
738 fonteditorAct->setEnabled ( false );
739 fonteditorAct->setStatusTip ( tr ( "You don't seem to have a font editor installed. Path to font editor can be set in Preferences dialog." ) );
740 }
741
742 reloadAct = new QAction( tr ("Reload Filtered"), this );
743 reloadAct->setStatusTip(tr ("Reload informations for filtered fonts from the font files they belong to"));
744 scuts->add(reloadAct);
745 connect(reloadAct, SIGNAL(triggered()), this, SLOT(slotReloadFiltered()));
746
747 reloadSingleAct = new QAction(tr("Reload Selected"), this);
748 reloadSingleAct->setStatusTip(tr ("Reload informations for selected font from the font file"));
749 scuts->add(reloadSingleAct);
750 connect(reloadSingleAct, SIGNAL(triggered()), this, SLOT(slotReloadSingle()));
751
752 prefsAct = new QAction ( tr ( "Preferences" ),this );
753 prefsAct->setStatusTip ( tr ( "Setup Fontmatrix" ) );
754 prefsAct->setMenuRole(QAction::PreferencesRole);
755 scuts->add(prefsAct);
756 connect ( prefsAct,SIGNAL ( triggered() ),this,SLOT ( slotPrefsPanelDefault() ) );
757
758 repairAct = new QAction ( tr("Check Database"), this);
759 repairAct->setStatusTip ( tr ( "Check Fontmatrix database for dead links to font files" ) );
760 scuts->add(repairAct);
761 connect( repairAct, SIGNAL ( triggered() ),this,SLOT (slotRepair()));
762
763 // if ( systray )
764 // connect ( theMainView, SIGNAL ( newTag ( QString ) ), systray, SLOT ( newTag ( QString ) ) );
765
766 tagAll = new QAction(tr("Tag All Filtered..."), this);
767 tagAll->setStatusTip ( tr ( "Tag all currently visible files" ) );
768 scuts->add(tagAll);
769 connect(tagAll,SIGNAL(triggered()),this,SLOT(slotTagAll()));
770
771 showTTTAct = new QAction(tr("Show TrueType tables"),this);
772 showTTTAct->setStatusTip ( tr ( "View hexadecimal values of TrueType tables for currently selected font file" ) );
773 scuts->add(showTTTAct);
774 connect(showTTTAct,SIGNAL(triggered( )),this,SLOT(slotShowTTTables()));
775
776 editPanoseAct = new QAction(tr("Edit PANOSE metadata"), this);
777 editPanoseAct->setStatusTip ( tr ( "Edit PANOSE metadata without saving changes to font files" ) );
778 scuts->add(editPanoseAct);
779 connect(editPanoseAct, SIGNAL(triggered()), this, SLOT(slotEditPanose()));
780
781
782 playAction = new QAction(tr("Playground"), this);
783 playAction->setShortcut(Qt::CTRL + Qt::Key_G);
784 playAction->setToolTip(tr("Show/Hide Playground"));
785 playAction->setCheckable(true);
786 playAction->setChecked(false);
787 scuts->add(playAction);
788 connect(playAction, SIGNAL(triggered(bool)), PlayWidget::getInstance(), SLOT(setVisible(bool)));
789
790 compareAction = new QAction(tr("Compare"), this);
791 compareAction->setShortcut(Qt::CTRL + Qt::Key_R);
792 compareAction->setToolTip(tr("Show/Hide Compare glyphs"));
793 compareAction->setCheckable(true);
794 compareAction->setChecked(false);
795 scuts->add(compareAction);
796 connect(compareAction, SIGNAL(triggered(bool)), FontCompareWidget::getInstance(), SLOT(setVisible(bool)));
797
798 closeAllFloat = new QAction(tr("Close All"), this);
799 closeAllFloat->setToolTip(tr("Close all floating windows"));
800 scuts->add(closeAllFloat);
801 connect(closeAllFloat, SIGNAL(triggered()), this, SLOT(closeAllFloatings()));
802
803 showAllFloat = new QAction(tr("Show All"), this);
804 showAllFloat->setToolTip(tr("Show all floating windows"));
805 scuts->add(showAllFloat);
806 connect(showAllFloat, SIGNAL(triggered()), this, SLOT(showAllFloatings()));
807
808 hideAllFloat = new QAction(tr("Hide All"), this);
809 hideAllFloat->setToolTip(tr("Hide all floating windows"));
810 scuts->add(hideAllFloat);
811 connect(hideAllFloat, SIGNAL(triggered()), this, SLOT(hideAllFloatings()));
812
813 floatSep = new QAction(this);
814 floatSep->setSeparator(true);
815
816
817 extractFontAction = new QAction(tr("Extract fonts..."),this);
818 extractFontAction->setStatusTip ( tr ( "Extract fonts from documents like PDF to PFM file format" ) );
819 scuts->add(extractFontAction);
820 connect(extractFontAction,SIGNAL(triggered()),this,SLOT(slotExtractFont()));
821
822 matchRasterAct = new QAction(tr("Find a font using raster sample..."), this); // FIXME find a name for it
823 matchRasterAct->setStatusTip ( tr ( "Find a font using a raster sample of a letter" ) );
824 scuts->add(matchRasterAct);
825 connect(matchRasterAct,SIGNAL(triggered()),this,SLOT(slotMatchRaster()));
826
827
828 #ifdef HAVE_PYTHONQT
829 execScriptAct = new QAction(tr("Execute Script..."),this);
830 execScriptAct->setStatusTip ( tr ( "Execute a Python script" ) );
831 scuts->add(execScriptAct);
832 connect(execScriptAct,SIGNAL(triggered()),this,SLOT(slotExecScript()));
833
834 execLastScriptAct = new QAction(tr("Execute Last Script"),this);
835 execLastScriptAct->setStatusTip ( tr ( "Execute the last chosen Python script" ) );
836 scuts->add(execLastScriptAct);
837 connect(execLastScriptAct,SIGNAL(triggered()),this,SLOT(slotExecLastScript()));
838
839 scriptConsoleAct = new QAction(tr("Script Console..."), this);
840 scriptConsoleAct->setStatusTip ( tr ( "Open Python scripting console" ) );
841 scriptConsoleAct->setCheckable(true);
842 scuts->add(scriptConsoleAct);
843 connect(scriptConsoleAct, SIGNAL(triggered()), this, SLOT(slotSwitchScriptConsole()));
844
845 #endif
846 }
847
createMenus()848 void typotek::createMenus()
849 {
850 fileMenu = menuBar()->addMenu ( tr ( "&File" ) );
851
852 fileMenu->addAction ( openAct );
853 fileMenu->addAction ( importFilesAction );
854 fileMenu->addAction ( exportFontSetAct );
855 fileMenu->addSeparator();
856
857 fileMenu->addAction ( fontBookAct );
858 fileMenu->addAction ( dumpInfoAct );
859 fileMenu->addSeparator();
860 fileMenu->addAction ( exitAct );
861
862 editMenu = menuBar()->addMenu ( tr ( "&Edit" ) );
863 // editMenu->addAction ( tagsetAct );
864 editMenu->addSeparator();
865 editMenu->addAction( tagAll );
866 editMenu->addAction ( activCurAct );
867 editMenu->addAction ( deactivCurAct );
868 editMenu->addSeparator();
869 editMenu->addAction ( fonteditorAct );
870 editMenu->addAction ( editPanoseAct );
871 editMenu->addSeparator();
872 editMenu->addAction(reloadSingleAct);
873 editMenu->addAction(reloadAct);
874 editMenu->addSeparator();
875 editMenu->addAction ( prefsAct );
876
877 viewMenu = menuBar()->addMenu(tr("&View"));
878 viewMenu->addAction(playAction);
879 viewMenu->addAction(compareAction);
880 viewMenu->addSeparator();
881 connect(viewMenu, SIGNAL(aboutToShow()), this,SLOT(updateFloatingStatus()));
882
883 #ifdef HAVE_PYTHONQT
884 scriptMenu = menuBar()->addMenu ( tr ( "&Scripts" ) );;
885 scriptMenu->addAction(execScriptAct);
886 scriptMenu->addAction(scriptConsoleAct);
887 scriptMenu->addAction(execLastScriptAct);
888 #endif
889
890 servicesMenu = menuBar()->addMenu ( tr ( "&Service" ) );
891 servicesMenu->addAction(extractFontAction);
892 servicesMenu->addAction(matchRasterAct);
893 #ifdef PLATFORM_APPLE
894 // TODO
895 #elif _WIN32
896 // TODO
897 #else
898 servicesMenu->addAction( repairAct );
899 #endif
900 servicesMenu->addAction(showTTTAct);
901 servicesMenu->addSeparator();
902 // servicesMenu->addAction(layOptAct);
903
904 helpMenu = menuBar()->addMenu ( tr ( "&Help" ) );
905 helpMenu->addAction ( helpAct );
906 helpMenu->addAction ( aboutAct );
907 helpMenu->addAction ( aboutQtAct );
908
909 }
910
createStatusBar()911 void typotek::createStatusBar()
912 {
913 // statusBar()->showMessage ( tr ( "Ready" ) );
914
915 statusProgressBar = new QProgressBar(this);
916 statusProgressBar->setMaximumSize(200,20);
917 statusBar()->addPermanentWidget(statusProgressBar);
918 statusProgressBar->hide();
919
920 QFont statusFontFont ( "sans-serif", 10 );
921 curFontPresentation = new QLabel ( "" );
922 curFontPresentation->setFrameShape(QFrame::StyledPanel);
923 curFontPresentation->setAlignment ( Qt::AlignRight );
924 curFontPresentation->setFont ( statusFontFont );
925 statusBar()->insertWidget ( 0, curFontPresentation );
926
927 countFilteredFonts = new QLabel ( "" );
928 countFilteredFonts->setFrameShape(QFrame::StyledPanel);
929 countFilteredFonts->setAlignment ( Qt::AlignRight );
930 countFilteredFonts->setFont ( statusFontFont );
931 statusBar()->addPermanentWidget ( countFilteredFonts );
932
933 toggleMainViewButton = new QToolButton(this);
934 toggleMainViewButton->setText(tr("Browse Directories"));
935 toggleMainViewButton->setCheckable(true);
936 toggleMainViewButton->setToolTip(tr("Toggle Files/Collection view"));
937 statusBar()->addPermanentWidget(toggleMainViewButton);
938 }
939
readSettings()940 void typotek::readSettings()
941 {
942 relayStartingStepIn(tr("Load settings"));
943 QSettings settings;
944 QPoint pos = settings.value ( "WState/pos", QPoint ( 200, 200 ) ).toPoint();
945 QSize size = settings.value ( "WState/size", QSize ( 400, 400 ) ).toSize();
946 resize ( size );
947 move ( pos );
948
949 fonteditorPath = settings.value ( "FontEditor", "/usr/bin/fontforge" ).toString();
950 useInitialTags = settings.value ( "UseInitialTags", false ).toBool();
951 showFontListDialog = settings.value("ShowImportedFonts", true).toBool();
952 previewSize = settings.value("Preview/Size", 28.0).toDouble();
953 previewRTL = settings.value("Preview/RTL", false).toBool();
954 previewSubtitled = settings.value("Preview/Subtitled", false).toBool();
955 m_theWord = settings.value("Preview/Word", "<name>" ).toString();
956
957 // QStringList dl;
958 // dl << "Main" << "Tags" << "Panose";
959 // foreach(const QString & ds, dl)
960 // {
961 // dockArea[ds] = settings.value("Docks/"+ds+"Pos", "Left").toString();
962 // dockVisible[ds] = settings.value("Docks/"+ds+"Visible", true).toBool();
963 // dockGeometry[ds] = settings.value("Docks/"+ds+"Geometry", QRect()).toRect();
964 // qDebug()<<ds<< dockArea[ds] << dockVisible[ds] <<dockGeometry[ds];
965 // }
966
967 panoseMatchTreshold = settings.value("Panose/MatchTreshold" , 1000 ).toInt();
968
969 webBrowser = settings.value("Info/Browser", "Fontmatrix").toString();
970 webBrowserOptions = settings.value("Info/BrowserOptions", "").toString();
971 previewInfoFontSize = settings.value("Info/PreviewSize", 20.0).toDouble();
972
973 infoStyle = settings.value("Info/Style", FMPaths::ResourcesDir() + "info.css").toString();
974
975 templatesDir = settings.value ( "Places/TemplatesDir", "./").toString();
976 m_welcomeURL = settings.value("Places/WelcomeURL").toString();
977 m_remoteTmpDir = settings.value("Places/RemoteTmpDir", QDir::tempPath()).toString();
978
979 defaultOTFScript = settings.value("OTF/Script").toString();
980 defaultOTFLang = settings.value("OTF/Lang").toString();
981 defaultOTFGPOS = settings.value("OTF/GPOS").toString().split(";",QString::SkipEmptyParts);
982 defaultOTFGSUB = settings.value("OTF/GSUB").toString().split(";",QString::SkipEmptyParts);
983 chartInfoFontSize = settings.value("ChartInfoFontSize", 8).toInt();
984 chartInfoFontName = settings.value("ChartInfoFontFamily", QFont().family() ).toString();
985
986
987 databaseDriver = settings.value("Database/Driver","QSQLITE").toString();
988 databaseHostname = settings.value("Database/Hostname","").toString();
989 databaseDbName = settings.value("Database/DbName", ownDir.absolutePath()+ QDir::separator() + "Data.sql").toString();
990 databaseUser = settings.value("Database/User","").toString();
991 databasePassword = settings.value("Database/Password","").toString();
992 if( !QSqlDatabase::drivers().contains(databaseDriver) )
993 {
994 qDebug()<<"The SQL driver you request is not available("<< databaseDriver <<")";
995 }
996
997 }
998
writeSettings()999 void typotek::writeSettings()
1000 {
1001 QSettings settings;
1002 settings.setValue( "WState/pos", pos() );
1003 settings.setValue( "WState/size", size() );
1004 theMainView->saveSplitterState();
1005
1006 // QStringList dl;
1007 // dl << "Main" << "Tags" << "Panose";
1008 // foreach(const QString & ds, dl)
1009 // {
1010 // if(dockWidget[ds]->isFloating())
1011 // {
1012 // dockArea[ds] = "Float";
1013 // }
1014 // settings.setValue( "Docks/"+ds+"Pos", dockArea[ds] );
1015 // settings.setValue( "Docks/"+ds+"Visible", dockWidget[ds]->isVisible());
1016 // settings.setValue( "Docks/"+ds+"Geometry", dockWidget[ds]->geometry());
1017 // }
1018
1019
1020 settings.setValue("Info/PreviewSize", previewInfoFontSize );
1021 settings.setValue("Info/Style", infoStyle );
1022
1023 settings.setValue("Preview/Word", m_theWord);
1024
1025 settings.setValue( "Panose/MatchTreshold", panoseMatchTreshold);
1026
1027 settings.setValue( "Database/Driver",databaseDriver);
1028 settings.setValue( "Database/Hostname",databaseHostname);
1029 settings.setValue( "Database/DbName",databaseDbName);
1030 settings.setValue( "Database/User",databaseUser);
1031 settings.setValue( "Database/Password",databasePassword);
1032
1033 if(theMainView->selectedFont())
1034 settings.setValue("CurrentFont", theMainView->selectedFont()->path());
1035
1036
1037 }
1038
maybeSave()1039 bool typotek::maybeSave()
1040 {
1041
1042 return true;
1043 }
1044
~typotek()1045 typotek::~typotek()
1046 {
1047 }
1048
fillTagsList()1049 void typotek::fillTagsList()
1050 {
1051
1052 }
1053
checkOwnDir()1054 void typotek::checkOwnDir()
1055 {
1056 relayStartingStepIn(tr("Check for Fontmatrix own dir"));
1057 QString sep(QDir::separator());
1058
1059 #ifdef PLATFORM_APPLE
1060
1061 QString rootDir(QDir::homePath() + sep + "Library" + sep + "Fontmatrix" + sep);
1062 managedDir.setPath(QDir::homePath() + sep + "Library" + sep + "Fonts");
1063 ownDir.setPath(rootDir);
1064 if ( !managedDir.exists() )
1065 managedDir.mkpath ( QDir::homePath() + sep + "Library" + sep + "Fonts" );
1066 if(!ownDir.exists())
1067 ownDir.mkpath (rootDir);
1068
1069 ResourceFile.setFileName ( rootDir + "Resource.xml" );
1070
1071 #elif _WIN32
1072 // For win we do not hide things because it does
1073 // not work yet. So if you need to debug it will be simpler.
1074 QString fontmanaged ( sep + "fontmatrix" );
1075 managedDir.setPath ( QDir::homePath() + fontmanaged );
1076 if ( !managedDir.exists() )
1077 managedDir.mkpath ( QDir::homePath() + fontmanaged );
1078 ownDir = managedDir;
1079 ResourceFile.setFileName ( QDir::homePath() + sep +"fontmatrix.data" );
1080 #else
1081 QString rootDir(QDir::homePath() + sep + ".Fontmatrix" + sep);
1082 ownDir.setPath(rootDir);
1083 // Where activated fonts are sym-linked
1084 managedDir.setPath ( rootDir + "Activated" );
1085 if ( !managedDir.exists() )
1086 managedDir.mkpath ( rootDir + "Activated" );
1087
1088 addFcDirItem( managedDir.absolutePath() );
1089
1090 ResourceFile.setFileName ( rootDir + "Resource.xml" );
1091 #endif
1092 }
1093
addFcDirItem(const QString & dirPath)1094 void typotek::addFcDirItem(const QString & dirPath)
1095 {
1096 #ifdef HAVE_FONTCONFIG
1097 QFile fcfile ( QDir::homePath() + "/.config/fontconfig/fonts.conf" );
1098 if ( !fcfile.open ( QFile::ReadWrite ) )
1099 {
1100 return;
1101 }
1102 else
1103 {
1104 QDomDocument fc ( "fontconfig" );
1105
1106 // .fonts.conf is empty, it seems that we just created it.
1107 // Wed have to populate it a bit
1108 if ( fcfile.size() == 0 )
1109 {
1110 QString ds ( "<?xml version='1.0'?><!DOCTYPE fontconfig SYSTEM 'fonts.dtd'><fontconfig></fontconfig>" );
1111 fc.setContent ( ds );
1112 }
1113 else
1114 {
1115 fc.setContent ( &fcfile );
1116 }
1117
1118 bool isconfigured = false;
1119 QDomNodeList dirlist = fc.elementsByTagName ( "dir" );
1120 for ( int i=0;i < dirlist.count();++i )
1121 {
1122 if ( dirlist.at ( i ).toElement().text() == dirPath )
1123 isconfigured = true;
1124 }
1125 if ( !isconfigured )
1126 {
1127 QDomElement root = fc.documentElement();
1128 QDomElement direlem = fc.createElement ( "dir" );
1129 QDomText textelem = fc.createTextNode ( dirPath );
1130 direlem.appendChild ( textelem );
1131 root.appendChild ( direlem );
1132 fcfile.resize ( 0 );
1133
1134 QTextStream ts ( &fcfile );
1135 fc.save ( ts,4 );
1136
1137 }
1138 fcfile.close();
1139 }
1140 #endif
1141 }
1142
getSystemFontDirs()1143 QStringList typotek::getSystemFontDirs()
1144 {
1145 QStringList retList;
1146 #ifdef HAVE_FONTCONFIG // For Unices (OSX excluded)
1147 QStringList tmpList;
1148 FcConfig* FcInitLoadConfig();
1149 FcStrList *sysDirList = FcConfigGetFontDirs(0);
1150 QString sysDir( (char*)FcStrListNext(sysDirList) );
1151 while(!sysDir.isEmpty())
1152 {
1153 if(!sysDir.contains("Fontmatrix"))
1154 {
1155 tmpList << sysDir;
1156 }
1157 sysDir = ( (char*)FcStrListNext(sysDirList) );
1158 }
1159 // Because we will go recursivly through these directories, we just want to list the top most ones.
1160 foreach(QString path, tmpList)
1161 {
1162 // qDebug()<< "PATH"<<path;
1163 bool root(true);
1164 foreach(QString ref, tmpList)
1165 {
1166 if(path != ref)
1167 {
1168 if(path.startsWith(ref))
1169 {
1170 root = false;
1171 break;
1172 }
1173 // qDebug()<<"\tREF"<<ref<<root;
1174 }
1175 }
1176 if(root)
1177 retList << path;
1178 }
1179
1180 #endif //HAVE_FONTCONFIG
1181 #ifdef PLATFORM_APPLE
1182 retList << "/Library/Fonts";
1183 retList << "/System/Library/Fonts";
1184 #endif // PLATFORM_APPLE
1185 #if _WIN32
1186 retList << getWin32SystemFontDir();
1187 #endif // _WIN32
1188
1189 qDebug()<<retList.join("\n");
1190 return retList;
1191 }
1192
isSysFont(FontItem * f)1193 bool typotek::isSysFont(FontItem * f)
1194 {
1195 if(f)
1196 {
1197 if(sysFontList.contains(f->path()))
1198 return true;
1199 }
1200 return false;
1201 }
1202
initDir()1203 void typotek::initDir()
1204 {
1205 /// let’s load system fonts
1206 #define SYSTEM_FONTS 1
1207 if(SYSTEM_FONTS)
1208 {
1209 relayStartingStepIn ( tr ( "Loading System Fonts") );
1210 m_sysTagName = tr ( "System Fonts" );
1211 QStringList tagsList(FMFontDb::DB()->getTags());
1212
1213 QList<FontItem*> sysFontPtrs;
1214
1215 QStringList sysDir ( getSystemFontDirs() );
1216
1217 QStringList yetHereFonts;
1218 QList<FontItem*> fontMap(FMFontDb::DB()->AllFonts());
1219 for ( int i=0;i < fontMap.count() ; ++i )
1220 yetHereFonts << fontMap[i]->path();
1221
1222 for ( int sIdx ( 0 ); sIdx < sysDir.count(); ++sIdx )
1223 {
1224 QDir theDir ( sysDir[sIdx] );
1225 QStringList syspathList;
1226 QStringList nameList;
1227
1228 QStringList dirList ( fontmatrix::exploreDirs ( theDir,0 ) );
1229 QStringList filters;
1230 filters << "*.otf" << "*.pfb" << "*.ttf" << "*.ttc";
1231 foreach ( QString dr, dirList )
1232 {
1233 QDir d ( dr );
1234 QFileInfoList fil= d.entryInfoList ( filters );
1235 foreach ( QFileInfo fp, fil )
1236 {
1237 if ( !yetHereFonts.contains ( fp.absoluteFilePath() ) )
1238 syspathList << fp.absoluteFilePath();
1239 sysFontList << fp.absoluteFilePath();
1240 }
1241 }
1242
1243 int sysFontCount ( syspathList.count() );
1244 if(sysFontCount > 0)
1245 {
1246 relayStartingStepIn ( tr ( "Adding" ) +" "+ QString::number ( sysFontCount ) +" "+tr ( "fonts from","followed by a directory name" ) +" "+sysDir[sIdx]);
1247 qDebug()<< ( tr ( "Adding" ) +" "+ QString::number ( sysFontCount ) +" "+tr ( "fonts from","followed by a directory name" ) +" "+sysDir[sIdx]);
1248 FMFontDb::DB()->TransactionBegin();
1249 for ( int i = 0 ; i < sysFontCount; ++i )
1250 {
1251 QFile ff ( syspathList.at ( i ) );
1252 QFileInfo fi ( syspathList.at ( i ) );
1253 {
1254 FontItem *fitem = FMFontDb::DB()->Font( fi.absoluteFilePath(), false );
1255 if ( fitem )
1256 {
1257 // qDebug()<<"\t"<<fitem <<fitem->path();
1258 fitem->setActivated ( true );
1259 // fitem->addTag ( m_sysTagName );
1260 sysFontPtrs << fitem;
1261 }
1262 else
1263 {
1264 qDebug() << "Cannot open this font because its broken: " << fi.fileName() ;
1265 }
1266 }
1267 }
1268 FMFontDb::DB()->TransactionEnd();
1269 }
1270 }
1271
1272 if(sysFontPtrs.count() > 0)
1273 relayStartingStepIn ( QString::number ( sysFontPtrs.count() ) + " " + tr ( "system fonts added." ) );
1274
1275 // So much complicated only because otherwise, tags were added twice with SQLite ???
1276 QStringList tl;
1277 foreach(FontItem* sfp, sysFontPtrs)
1278 {
1279 tl << sfp->path();
1280 }
1281 FMFontDb::DB()->addTag(tl, m_sysTagName);
1282 }
1283
1284
1285 // qDebug()<<"TIME(fonts) : "<<fontsTime.elapsed();
1286 /// Remote dirs
1287 //TODO
1288 // QSettings settings;
1289 // QStringList remoteDirV ( settings.value ( "RemoteDirectories" ).toStringList() );
1290 // if ( !remoteDirV.isEmpty() )
1291 // {
1292 // relayStartingStepIn ( tr ( "Catching" ) +" "+ QString::number ( remoteDirV.count() ) +" "+tr ( "font descriptions from network" ) );
1293 // remoteDir = new RemoteDir ( remoteDirV );
1294 // connect ( remoteDir,SIGNAL ( listIsReady() ),this,SLOT ( slotRemoteIsReady() ) );
1295 // remoteDir->run();
1296 // }
1297 }
1298
1299 static bool slotRemoteIsReadyRunOnce = false;
slotRemoteIsReady()1300 void typotek::slotRemoteIsReady()
1301 {
1302 if(!slotRemoteIsReadyRunOnce)
1303 slotRemoteIsReadyRunOnce = true;
1304 else
1305 return;
1306 QStringList tagsList(FMFontDb::DB()->getTags());
1307
1308 // qDebug()<<"typotek::slotRemoteIsReady()";
1309 QList<RemoteDir::FontInfo> listInfo(remoteDir->rFonts());
1310 // qDebug()<< "Have got "<< listInfo.count() <<"remote font descriptions";
1311 for(int rf(0) ;rf < listInfo.count(); ++rf)
1312 {
1313 // qDebug()<< rf <<" : " <<listInfo[rf].dump();
1314 FontItem *fi = new FontItem ( listInfo[rf].file , true );
1315 if(!fi->isValid())
1316 {
1317 qDebug() << "ERROR loading : " << listInfo[rf].file;
1318 continue;
1319 }
1320 fi->fileRemote(listInfo[rf].family,listInfo[rf].variant,listInfo[rf].type, listInfo[rf].info, listInfo[rf].pix);
1321 // fontMap.append ( fi );
1322 // realFontMap[fi->path() ] = fi;
1323 fi->setTags ( listInfo[rf].tags );
1324 foreach(QString tag, listInfo[rf].tags)
1325 {
1326 if(!tag.isEmpty() && !tagsList.contains(tag))
1327 {
1328 tagsList << tag;
1329 }
1330 }
1331 }
1332 // theMainView->slotReloadFontList();
1333 showStatusMessage( QString::number(listInfo.count())+ " " + tr("font descriptions imported from network"));
1334 // qDebug()<<"END OF slotRemoteIsReady()";
1335 }
1336
1337
fontBook()1338 void typotek::fontBook()
1339 {
1340 FontBook fontbook;
1341 fontbook.doBook(FontBook::Full);
1342 }
1343
1344
1345
getSelectedFont()1346 FontItem * typotek::getSelectedFont()
1347 {
1348 return theMainView->selectedFont();
1349 }
1350
keyPressEvent(QKeyEvent * event)1351 void typotek::keyPressEvent ( QKeyEvent * event )
1352 {
1353 // qDebug() << "typotek::keyPressEvent(QKeyEvent * "<<event<<")";
1354 if(/*event->modifiers().testFlag(Qt::ControlModifier) &&*/ event->key() == Qt::Key_J)
1355 qDebug()<<"NUM FACES OPENED:"<<fm_num_face_opened;
1356 }
1357
slotActivateCurrents()1358 void typotek::slotActivateCurrents()
1359 {
1360 if ( QMessageBox::question ( this,tr ( "Fontmatrix care" ),tr ( "You are about to activate a bunch of fonts,\nit is time to cancel if it was not your intent" ), QMessageBox::Ok|QMessageBox::Cancel, QMessageBox::Cancel ) == QMessageBox::Ok )
1361 theMainView->slotActivateAll();
1362 }
1363
slotDeactivateCurrents()1364 void typotek::slotDeactivateCurrents()
1365 {
1366 if ( QMessageBox::question ( this,tr ( "Fontmatrix care" ),tr ( "You are about to deactivate a bunch of fonts,\nit is time to cancel if it was not your intent" ),QMessageBox::Ok|QMessageBox::Cancel, QMessageBox::Cancel ) == QMessageBox::Ok )
1367 theMainView->slotDesactivateAll();
1368 }
1369
helpBegin()1370 void typotek::helpBegin()
1371 {
1372 theHelp = new HelpBrowser(this,tr("Fontmatrix Help"));
1373 helpAct->setChecked(true);
1374
1375 connect( theHelp, SIGNAL( closed() ), this, SLOT(helpEnd()) );
1376
1377 disconnect ( helpAct,SIGNAL ( triggered( ) ),this,SLOT ( helpBegin() ) );
1378 connect ( helpAct,SIGNAL ( triggered( ) ),this,SLOT ( helpEnd() ) );
1379
1380 theHelp->show();
1381 }
1382
helpEnd()1383 void typotek::helpEnd()
1384 {
1385 helpAct->setChecked(false);
1386
1387 disconnect ( helpAct,SIGNAL ( triggered( ) ),this,SLOT ( helpEnd() ) );
1388 connect ( helpAct,SIGNAL ( triggered( ) ),this,SLOT ( helpBegin() ) );
1389
1390 theHelp->deleteLater();
1391 }
1392
slotEditFont()1393 void typotek::slotEditFont()
1394 {
1395 FontItem *item = theMainView->selectedFont();
1396 if ( !item )
1397 {
1398 statusBar()->showMessage ( tr ( "There is no font selected" ), 3000 );
1399 return;
1400 }
1401
1402 QStringList arguments;
1403 arguments << "-nosplash" << item->path() ;
1404
1405 QProcess *myProcess = new QProcess ( this );
1406 myProcess->start ( fonteditorPath, arguments );
1407 }
1408
setupDrop()1409 void typotek::setupDrop()
1410 {
1411 setAcceptDrops ( true );
1412 // was pretty hard!
1413 }
1414
dropEvent(QDropEvent * event)1415 void typotek::dropEvent ( QDropEvent * event )
1416 {
1417
1418 qDebug() << "typotek::dropEvent ("<< event->mimeData()->text() <<")";
1419 // qDebug()<<"F: "<<event->mimeData()->formats().join(";");
1420
1421 // event->acceptProposedAction();
1422 QStringList uris = event->mimeData()->text().split ( "\n" );
1423 QStringList ret;
1424
1425 for ( int i = 0; i < uris.count() ; ++i )
1426 {
1427 qDebug() << "dropped uri["<< i <<"] -> "<< uris[i];
1428 QUrl url ( uris[i].trimmed() );
1429 qDebug() << "\tURL -> " << url.toLocalFile();
1430 if ( url.scheme() == "file" )
1431 {
1432 if ( url.toLocalFile().endsWith ( "ttf",Qt::CaseInsensitive ) )
1433 {
1434 ret << url.toLocalFile();
1435 }
1436 else if ( url.toLocalFile().endsWith ( "ttc",Qt::CaseInsensitive ) )
1437 {
1438 ret << url.toLocalFile();
1439 }
1440 else if ( url.toLocalFile().endsWith ( "otf",Qt::CaseInsensitive ) )
1441 {
1442 ret << url.toLocalFile();
1443 }
1444 else if ( url.toLocalFile().endsWith ( "pfb",Qt::CaseInsensitive ) )
1445 {
1446 ret << url.toLocalFile();
1447 }
1448 else
1449 {
1450 qDebug() << url.toLocalFile () << "is not a supported font file";
1451 }
1452 }
1453 else if ( url.scheme() == "http" )
1454 {
1455 // TODO Get fonts over http
1456 qDebug() << "Support of DragNDrop over http is sheduled";
1457 statusBar()->showMessage ( tr ( "Support of DragNDrop over http is sheduled but not yet effective" ), 3000 );
1458 }
1459 else
1460 {
1461 qDebug() << "Protocol not supported";
1462 }
1463 }
1464
1465 // qDebug() << ret.join("||");
1466 if ( ret.count() )
1467 openList( ret );
1468
1469 }
1470
dragEnterEvent(QDragEnterEvent * event)1471 void typotek::dragEnterEvent ( QDragEnterEvent * event )
1472 {
1473 qDebug() << event->mimeData()->formats().join ( "|" );
1474 if ( event->mimeData()->hasFormat ( "text/uri-list" ) )
1475 {
1476 event->acceptProposedAction();
1477 qDebug() << "dragEnterEvent accepted " ;
1478 }
1479 else
1480 {
1481 qDebug() << "dragEnterEvent refused";
1482 statusBar()->showMessage ( tr ( "You bring something over me I can’t handle" ), 3000 );
1483 }
1484 }
1485
slotPrefsPanel(PrefsPanelDialog::PAGE page)1486 void typotek::slotPrefsPanel(PrefsPanelDialog::PAGE page)
1487 {
1488 PrefsPanelDialog pp ( this );
1489
1490 // FIXME if Systray is not available, systray->whatever() will segault
1491 if ( QSystemTrayIcon::isSystemTrayAvailable() )
1492 pp.initSystrayPrefs ( QSystemTrayIcon::isSystemTrayAvailable(),
1493 systray->isVisible(),
1494 systray->hasActivateAll(),
1495 systray->allConfirmation(),
1496 systray->tagsConfirmation() );
1497 else
1498 pp.initSystrayPrefs ( false,false,false,false,false );
1499 pp.initSampleTextPrefs();
1500 pp.initFilesAndFolders();
1501 pp.initShortcuts();
1502 pp.showPage(page);
1503 pp.exec();
1504 }
1505
slotPrefsPanelDefault()1506 void typotek::slotPrefsPanelDefault()
1507 {
1508 slotPrefsPanel(PrefsPanelDialog::PAGE_GENERAL);
1509 }
1510
forwardUpdateView()1511 void typotek::forwardUpdateView()
1512 {
1513 // theMainView->slotView ( true );
1514 }
1515
setSystrayVisible(bool isVisible)1516 void typotek::setSystrayVisible ( bool isVisible )
1517 {
1518 systray->slotSetVisible ( isVisible );
1519 }
1520
showActivateAllSystray(bool isVisible)1521 void typotek::showActivateAllSystray ( bool isVisible )
1522 {
1523 systray->slotSetActivateAll ( isVisible );
1524 }
1525
systrayAllConfirmation(bool isEnabled)1526 void typotek::systrayAllConfirmation ( bool isEnabled )
1527 {
1528 systray->requireAllConfirmation ( isEnabled );
1529 }
1530
systrayTagsConfirmation(bool isEnabled)1531 void typotek::systrayTagsConfirmation ( bool isEnabled )
1532 {
1533 systray->requireTagsConfirmation ( isEnabled );
1534 }
1535
slotCloseToSystray(bool isEnabled)1536 void typotek::slotCloseToSystray ( bool isEnabled )
1537 {
1538 QSettings settings ;
1539 settings.setValue ( "Systray/CloseToTray", isEnabled );
1540 settings.setValue ( "Systray/CloseNoteShown", false );
1541 }
1542
slotSystrayStart(bool isEnabled)1543 void typotek::slotSystrayStart( bool isEnabled )
1544 {
1545 QSettings settings ;
1546 settings.setValue ( "Systray/StartToTray", isEnabled );
1547 }
1548
1549
namedSample(QString name)1550 QString typotek::namedSample ( QString name )
1551 {
1552 QString cn(name);
1553 if(cn == QString("NEW_SAMPLE"))
1554 return tr("Edit me!");
1555 if(cn.isEmpty())
1556 cn = currentNamedSample;
1557 else
1558 currentNamedSample = cn;
1559
1560 if(!dataLoader)
1561 dataLoader = new DataLoader();
1562
1563 const QMap<QString,QString>& us(dataLoader->userSamples());
1564 foreach(const QString& k, us.keys())
1565 {
1566 QString id(QString("User::") + k);
1567 // qDebug()<<"\t"<<id;
1568 if(id == cn)
1569 {
1570 return us[k];
1571 }
1572 }
1573
1574 const QMap<QString, QMap<QString,QString> >& ss(dataLoader->systemSamples());
1575 foreach(const QString& pk, ss.keys())
1576 {
1577 foreach(const QString& sk, ss[pk].keys())
1578 {
1579 QString id(pk + QString("::") + sk);
1580 // qDebug()<<"\t"<<id;
1581 if(id == cn)
1582 {
1583 return ss[pk][sk];
1584 }
1585 }
1586 }
1587 return namedSample(defaultSampleName());
1588 }
1589
namedSamplesNames()1590 QMap<QString,QList<QString> > typotek::namedSamplesNames()
1591 {
1592 if(!dataLoader)
1593 dataLoader = new DataLoader();
1594
1595 QMap<QString,QList<QString> > ret;
1596 const QMap<QString,QString>& us(dataLoader->userSamples());
1597 const QMap<QString, QMap<QString,QString> >& ss(dataLoader->systemSamples());
1598 foreach(const QString& key, ss.keys())
1599 {
1600 ret[key] << ss[key].keys();
1601 }
1602 ret[QString("User")] << us.keys();
1603 return ret;
1604 }
1605
addNamedSample(QString name,QString sample)1606 void typotek::addNamedSample ( QString name, QString sample )
1607 {
1608 if(!dataLoader)
1609 dataLoader = new DataLoader();
1610
1611 dataLoader->update(name, sample);
1612 // theMainView->refillSampleList();
1613 }
1614
removeNamedSample(const QString & key)1615 void typotek::removeNamedSample(const QString& key)
1616 {
1617 if(!dataLoader)
1618 dataLoader = new DataLoader();
1619
1620 dataLoader->remove(key);
1621 // theMainView->refillSampleList();
1622 }
1623
changeSample(QString name,QString text)1624 void typotek::changeSample ( QString name, QString text )
1625 {
1626 if(!dataLoader)
1627 dataLoader = new DataLoader();
1628
1629 dataLoader->update(name, text);
1630 // theMainView->refillSampleList();
1631 }
1632
defaultSampleName()1633 QString typotek::defaultSampleName()
1634 {
1635 if(!dataLoader)
1636 dataLoader = new DataLoader();
1637
1638 const QMap<QString,QString>& us(dataLoader->userSamples());
1639 if(us.contains(tr("default")))
1640 return QString("User::") + QString("default");
1641 else if(us.count() > 0)
1642 return QString("User::") + us.keys().first();
1643 else
1644 {
1645 const QMap<QString, QMap<QString,QString> >& ss(dataLoader->systemSamples());
1646 QString l(QLocale::system().language());
1647 if((ss.contains(l)) && (ss[l].count() > 0))
1648 return l + QString("::") + ss[l].keys().first();
1649 else
1650 {
1651 foreach(QString k, ss.keys())
1652 {
1653 if(ss[k].count() > 0)
1654 return k + QString("::") +ss[k].keys().first();
1655 }
1656 }
1657 }
1658 return QString();
1659 }
1660
setWord(QString s,bool updateView)1661 void typotek::setWord ( QString s, bool updateView )
1662 {
1663 if(s == m_theWord)
1664 return;
1665 m_theWord = s;
1666 QList<FontItem*> fontMap(FMFontDb::DB()->AllFonts());
1667 for(int i(0); i < fontMap.count(); ++i)
1668 fontMap[i]->clearPreview() ;
1669
1670 emit previewHasChanged();
1671 }
1672
setPreviewSize(double d)1673 void typotek::setPreviewSize(double d)
1674 {
1675 if(previewSize == d)
1676 return;
1677
1678 // previewSize = d;
1679 // if(previewSize != ListDockWidget::getInstance()->previewSize->value())
1680 // ListDockWidget::getInstance()->previewSize->setValue(previewSize);
1681 QList<FontItem*> fontMap(FMFontDb::DB()->AllFonts());
1682 for(int i(0); i < fontMap.count(); ++i)
1683 fontMap[i]->clearPreview() ;
1684 emit previewHasChanged();
1685 }
1686
setPreviewRTL(bool d)1687 void typotek::setPreviewRTL(bool d)
1688 {
1689 if(previewRTL == d)
1690 return;
1691 previewRTL = d;
1692 QList<FontItem*> fontMap(FMFontDb::DB()->AllFonts());
1693 for(int i(0); i < fontMap.count(); ++i)
1694 fontMap[i]->clearPreview() ;
1695 emit previewHasChanged();
1696 }
1697
setPreviewSubtitled(bool d)1698 void typotek::setPreviewSubtitled(bool d)
1699 {
1700 if(previewSubtitled == d)
1701 return;
1702 previewSubtitled = d;
1703 QList<FontItem*> fontMap(FMFontDb::DB()->AllFonts());
1704 for(int i(0); i < fontMap.count(); ++i)
1705 fontMap[i]->clearPreview() ;
1706 emit previewHasChanged();
1707 }
1708
setFontEditorPath(const QString & path)1709 void typotek::setFontEditorPath ( const QString &path )
1710 {
1711 fonteditorPath = path;
1712 if ( QFile::exists ( fonteditorPath ) )
1713 {
1714 fonteditorAct->setEnabled ( true );
1715 fonteditorAct->setStatusTip ( tr ( "Try to run font editor with the selected font as argument" ) );
1716 }
1717 else
1718 {
1719 fonteditorAct->setEnabled ( false );
1720 fonteditorAct->setStatusTip ( tr ( "You don't seem to have font editor installed. Path to font editor can be set in preferences." ) );
1721 }
1722 QSettings settings ;
1723 settings.setValue ( "FontEditor", fonteditorPath );
1724 }
1725
slotUseInitialTags(bool isEnabled)1726 void typotek::slotUseInitialTags ( bool isEnabled )
1727 {
1728 useInitialTags = isEnabled;
1729 QSettings settings ;
1730 settings.setValue ( "UseInitialTags", isEnabled );
1731 }
1732
showImportedFonts(int show)1733 void typotek::showImportedFonts(int show) // 0 == show dialog, 2 == do not show
1734 {
1735 bool doShow = true;
1736 if (show == Qt::Checked)
1737 doShow = false;
1738 showFontListDialog = doShow;
1739 QSettings settings;
1740 settings.setValue("ShowImportedFonts", doShow);
1741 }
1742
showImportedFonts()1743 bool typotek::showImportedFonts()
1744 {
1745 return showFontListDialog;
1746 }
1747
setTemplatesDir(const QString & dir)1748 void typotek::setTemplatesDir(const QString & dir)
1749 {
1750 templatesDir = dir;
1751 QSettings settings;
1752 settings.setValue("Places/TemplatesDir", templatesDir);
1753
1754 }
1755
changeFontSizeSettings(double fSize,double lSize)1756 void typotek::changeFontSizeSettings(double fSize, double lSize)
1757 {
1758 QSettings settings;
1759 settings.setValue("Sample/FontSize", fSize);
1760 settings.setValue("Sample/Interline", lSize);
1761 // theMainView->reSize(fSize,lSize);
1762 }
1763
relayStartingStepIn(QString s)1764 void typotek::relayStartingStepIn(QString s)
1765 {
1766 int i( Qt::AlignRight | Qt::AlignBottom );
1767 QColor c(Qt::white);
1768 emit relayStartingStepOut( s, i , c );
1769 }
1770
removeFontItem(QString key)1771 void typotek::removeFontItem(QString key)
1772 {
1773 // FontItem *fit = realFontMap.value(key);
1774 // if(!fit)
1775 // return;
1776 // fontMap.removeAll(fit);
1777 // delete fit;
1778 // realFontMap.remove(key);
1779 // qDebug()<< key << "has been removed";
1780 FMFontDb::DB()->Remove(key);
1781 }
1782
removeFontItem(QStringList keyList)1783 void typotek::removeFontItem(QStringList keyList)
1784 {
1785 foreach(QString key, keyList)
1786 {
1787 removeFontItem(key);
1788 }
1789 }
1790
showStatusMessage(const QString & message)1791 void typotek::showStatusMessage(const QString & message)
1792 {
1793 statusBar()->showMessage(message, 3000);
1794 }
1795
setRemoteTmpDir(const QString & s)1796 void typotek::setRemoteTmpDir(const QString & s)
1797 {
1798 if(s.isEmpty())
1799 m_remoteTmpDir = QDir::temp().path();
1800 else
1801 m_remoteTmpDir = s;
1802
1803 QSettings settings;
1804 settings.setValue("Places/RemoteTmpDir", m_remoteTmpDir);
1805 }
1806
slotRepair()1807 void typotek::slotRepair()
1808 {
1809 FmRepair repair(this);
1810 repair.exec();
1811 }
1812
slotTagAll()1813 void typotek::slotTagAll()
1814 {
1815 QStringList tagsList(FMFontDb::DB()->getTags());
1816 ImportTags imp(this,tagsList);
1817 imp.exec();
1818 QStringList tali = imp.tags();
1819
1820 if(tali.isEmpty())
1821 return;
1822 for(int t(0); t < tali.count(); ++t)
1823 {
1824 if(!tagsList.contains(tali[t]))
1825 {
1826 tagsList.append(tali[t]);
1827 }
1828 }
1829
1830 FMFontDb::DB()->TransactionBegin();
1831 QList<FontItem*> curfonts = theMainView->curFonts();
1832 for(int i(0) ; i < curfonts.count(); ++i)
1833 {
1834 for(int t(0); t < tali.count(); ++t)
1835 {
1836 curfonts[i]->addTag(tali[t]);
1837 }
1838
1839 }
1840 FMFontDb::DB()->TransactionEnd();
1841 // TagsWidget::getInstance()->newTag();
1842 }
1843
1844
1845 //void typotek::printFamily()
1846 //{
1847 // FontItem * font(theMainView->selectedFont());
1848 // if(!font)
1849 // return;
1850 // QPrinter thePrinter ( QPrinter::HighResolution );
1851 // QPrintDialog dialog(&thePrinter, this);
1852 // dialog.setWindowTitle("Fontmatrix - " + tr("Print Family") +" - " + font->family());
1853
1854 // if ( dialog.exec() != QDialog::Accepted )
1855 // return;
1856
1857 // thePrinter.setFullPage ( true );
1858 // QPainter aPainter ( &thePrinter );
1859
1860 // QGraphicsScene tmpScene(thePrinter.paperRect());
1861 // QGraphicsScene pScene(thePrinter.paperRect());
1862
1863 // qDebug()<<thePrinter.paperRect();
1864
1865 // QMap<int , double> logWidth;
1866 // QMap<int , double> logAscend;
1867 // QMap<int , double> logDescend;
1868 // QMap<int , QString> sampleString;
1869 // QMap<int , FontItem*> sampleFont;
1870
1871 // QStringList stl1(namedSample ( theMainView->sampleName() ).split ( QRegExp("\\W") ));
1872 // if(stl1.count() < 10 )
1873 // {
1874 // QMessageBox::information(this,"Fontmatrix",tr("Not enough text to make a sample"));
1875 // return;
1876 // }
1877 // QStringList stl;
1878 // int idxS(0);
1879 // int idxE( qrand() % 9 );
1880 // while((idxS + idxE) < stl1.count())
1881 // {
1882 // QString t(QStringList(stl1.mid(idxS,idxE)).join( " " ));
1883 // qDebug()<<"s e T"<<idxS<<idxE<<t;
1884 // if(!t.isEmpty())
1885 // stl << t;
1886
1887 // idxS += idxE;
1888 // idxE = qrand() % 9;
1889 // }
1890 // QList<FontItem*> familyFonts(FMFontDb::DB()->Fonts(theMainView->selectedFont()->family(), FMFontDb::Family ));
1891
1892 //// if(familyFonts.count() > stl.count())
1893 // {
1894 // int diff ( familyFonts.count() );
1895 // for (int i(0); i < diff; ++i)
1896 // {
1897 // sampleString[i] = stl[ i % stl.count() ];
1898 // }
1899 // }
1900
1901 // // first we’ll get widths for font size 1000
1902 // for(int fidx(0); fidx < familyFonts.count(); ++fidx)
1903 // {
1904 // sampleFont[fidx] = familyFonts[fidx];
1905 // bool rasterState(sampleFont[fidx]->rasterFreetype());
1906 // sampleFont[fidx]->setFTRaster(false);
1907 // sampleFont[fidx]->setRenderReturnWidth(true);
1908 // logWidth[fidx] = familyFonts[fidx]->renderLine(&tmpScene, sampleString[fidx], QPointF(0.0, 1000.0) , 999999.0, 1000.0, 1) ;
1909 // sampleFont[fidx]->setRenderReturnWidth(false);
1910 // sampleFont[fidx]->setFTRaster(rasterState);
1911 // logAscend[fidx] = 1000.0 - tmpScene.itemsBoundingRect().top();
1912 // logDescend[fidx] = tmpScene.itemsBoundingRect().bottom() - 1000.0;
1913 // qDebug()<< sampleString[fidx] << logWidth[fidx];
1914 // QList<QGraphicsItem*> lgit(tmpScene.items());
1915 // foreach(QGraphicsItem* git, lgit)
1916 // {
1917 // tmpScene.removeItem(git);
1918 // delete git;
1919 // }
1920 // }
1921 // double defWidth(0.8 * pScene.width() );
1922 // double defHeight(0.9 * pScene.height() );
1923 // double xOff( 0.1 * pScene.width() );
1924 // double yPos(0.1 * pScene.height() );
1925
1926 // QFont nameFont;
1927 // nameFont.setPointSizeF(100.0);
1928 // nameFont.setItalic(true);
1929
1930 // for(int fidx(0); fidx < familyFonts.count(); ++fidx)
1931 // {
1932 // double scaleFactor(1000.0 / logWidth[fidx] );
1933 // double fSize( defWidth * scaleFactor );
1934 // double fAscend(logAscend[fidx] * fSize / 1000.0);
1935 // double fDescend(logDescend[fidx] * fSize / 1000.0 );
1936 // if( yPos + fAscend + fDescend > defHeight)
1937 // {
1938 // pScene.render(&aPainter);
1939 // thePrinter.newPage();
1940 // QList<QGraphicsItem*> lgit(pScene.items());
1941 // foreach(QGraphicsItem* git, lgit)
1942 // {
1943 // pScene.removeItem(git);
1944 // delete git;
1945 // }
1946 // yPos = 0.1 * pScene.height();
1947
1948 // }
1949
1950 // yPos += fAscend;
1951 // QPointF origine(xOff, yPos );
1952
1953 // qDebug()<< sampleString[fidx] << fSize;
1954
1955 // bool rasterState(sampleFont[fidx]->rasterFreetype());
1956 // sampleFont[fidx]->setFTRaster(false);
1957 // sampleFont[fidx]->renderLine(&pScene, sampleString[fidx], origine, pScene.width(), fSize, 100);
1958 // pScene.addLine(QLineF(origine, QPointF(xOff + defWidth, yPos)));
1959 // sampleFont[fidx]->setFTRaster(rasterState);
1960
1961 // yPos += fDescend ;
1962
1963 // QGraphicsSimpleTextItem * nameText = pScene.addSimpleText( familyFonts[fidx]->fancyName(), nameFont) ;
1964 // nameText->setPos(xOff, yPos);
1965 //// nameText->setBrush(Qt::gray);
1966 // yPos += nameText->boundingRect().height();
1967 // }
1968
1969 // pScene.render(&aPainter);
1970 //}
1971
showEvent(QShowEvent * event)1972 void typotek::showEvent(QShowEvent * event)
1973 {
1974 QMainWindow::showEvent(event);
1975 }
1976
slotDockAreaChanged(Qt::DockWidgetArea area)1977 void typotek::slotDockAreaChanged(Qt::DockWidgetArea area)
1978 {
1979 QDockWidget * dw(reinterpret_cast<QDockWidget*>(sender()));
1980
1981 if(dw)
1982 {
1983 QString wId(dw->objectName());
1984 if(area == Qt::LeftDockWidgetArea)
1985 dockArea[wId] = "Left";
1986 else if(area ==Qt::RightDockWidgetArea)
1987 dockArea[wId] ="Right";
1988 else if(area == Qt::TopDockWidgetArea)
1989 dockArea[wId] ="Top";
1990 else if(area == Qt::BottomDockWidgetArea)
1991 dockArea[wId] = "Bottom";
1992 }
1993 }
1994
1995
getHyphenator() const1996 FMHyphenator* typotek::getHyphenator() const
1997 {
1998 return hyphenator;
1999 }
2000
2001 //void typotek::slotSwitchLayOptVisible()
2002 //{
2003 // if(FMLayout::getLayout()->optionDialog->isVisible())
2004 // FMLayout::getLayout()->optionDialog->setVisible(false);
2005 // else
2006 // FMLayout::getLayout()->optionDialog->setVisible(true);
2007 // slotUpdateLayOptStatus();
2008 //}
2009
2010 //void typotek::slotUpdateLayOptStatus()
2011 //{
2012 // if(FMLayout::getLayout()->optionDialog->isVisible())
2013 // layOptAct->setChecked(true);
2014 // else
2015 // layOptAct->setChecked(false);
2016 //}
2017
2018 #ifdef HAVE_PYTHONQT
slotSwitchScriptConsole()2019 void typotek::slotSwitchScriptConsole()
2020 {
2021 if(FMScriptConsole::getInstance()->isVisible())
2022 FMScriptConsole::getInstance()->setVisible(false);
2023 else
2024 FMScriptConsole::getInstance()->setVisible(true);
2025 slotUpdateScriptConsoleStatus();
2026 }
2027
slotUpdateScriptConsoleStatus()2028 void typotek::slotUpdateScriptConsoleStatus()
2029 {
2030 if(FMScriptConsole::getInstance()->isVisible())
2031 scriptConsoleAct->setChecked(true);
2032 else
2033 scriptConsoleAct->setChecked(false);
2034 }
2035 #else
slotSwitchScriptConsole()2036 void typotek::slotSwitchScriptConsole(){}
slotUpdateScriptConsoleStatus()2037 void typotek::slotUpdateScriptConsoleStatus(){}
2038 #endif
2039
getDefaultOTFScript() const2040 QString typotek::getDefaultOTFScript() const
2041 {
2042 return defaultOTFScript;
2043 }
2044
setDefaultOTFScript(const QString & theValue)2045 void typotek::setDefaultOTFScript ( const QString& theValue )
2046 {
2047 if(theValue != defaultOTFScript)
2048 {
2049 QSettings st;
2050 st.setValue("OTF/Script" , theValue);
2051 }
2052 defaultOTFScript = theValue;
2053
2054 }
2055
getDefaultOTFLang() const2056 QString typotek::getDefaultOTFLang() const
2057 {
2058 return defaultOTFLang;
2059 }
2060
setDefaultOTFLang(const QString & theValue)2061 void typotek::setDefaultOTFLang ( const QString& theValue )
2062 {
2063 if(theValue != defaultOTFLang)
2064 {
2065 QSettings st;
2066 st.setValue("OTF/Lang" , theValue);
2067 }
2068 defaultOTFLang = theValue;
2069 }
2070
getDefaultOTFGPOS() const2071 QStringList typotek::getDefaultOTFGPOS() const
2072 {
2073 return defaultOTFGPOS;
2074 }
2075
setDefaultOTFGPOS(const QStringList & theValue)2076 void typotek::setDefaultOTFGPOS ( const QStringList& theValue )
2077 {
2078 if(theValue != defaultOTFGPOS)
2079 {
2080 QSettings st;
2081 st.setValue("OTF/GPOS" , theValue.join(";"));
2082 }
2083 defaultOTFGPOS = theValue;
2084 }
2085
getDefaultOTFGSUB() const2086 QStringList typotek::getDefaultOTFGSUB() const
2087 {
2088 return defaultOTFGSUB;
2089 }
2090
setDefaultOTFGSUB(const QStringList & theValue)2091 void typotek::setDefaultOTFGSUB ( const QStringList& theValue )
2092 {
2093 if(theValue != defaultOTFGSUB)
2094 {
2095 QSettings st;
2096 st.setValue("OTF/GSUB" , theValue.join(";"));
2097 }
2098 defaultOTFGSUB = theValue;
2099 }
2100
startProgressJob(int max)2101 void typotek::startProgressJob(int max)
2102 {
2103 statusProgressBar->reset();
2104 statusProgressBar->setRange(0,max);
2105 statusProgressBar->show();
2106 }
2107
runProgressJob(int i)2108 void typotek::runProgressJob(int i)
2109 {
2110 if(i)
2111 {
2112 statusProgressBar->setValue(i);
2113 }
2114 else
2115 {
2116 int v(statusProgressBar->value());
2117 statusProgressBar->setValue( ++v );
2118 }
2119 }
2120
endProgressJob()2121 void typotek::endProgressJob()
2122 {
2123 statusProgressBar->hide();
2124 statusProgressBar->reset();
2125 }
2126
slotShowTTTables()2127 void typotek::slotShowTTTables()
2128 {
2129 if(theMainView->selectedFont())
2130 {
2131 QDialog dia(this);
2132 QGridLayout glayout(&dia);
2133 TTTableView tv(theMainView->selectedFont(),&dia);
2134 QPushButton pbutton(tr("Close"),&dia);
2135 glayout.addWidget(&tv,0,0,3,3);
2136 glayout.addWidget(&pbutton,3,2);
2137 pbutton.setDefault(true);
2138
2139 QRect drect(dia.rect());
2140 drect.setX(this->geometry().x() + 32);
2141 drect.setY(this->geometry().y() + 32);
2142 drect.setWidth(tv.rect().width() * 1.2);
2143 drect.setHeight(tv.rect().height() * 1.2);
2144 dia.setGeometry(drect);
2145 connect(&pbutton,SIGNAL(released()),&dia,SLOT(close()));
2146 dia.exec();
2147 }
2148 }
2149
slotEditPanose()2150 void typotek::slotEditPanose()
2151 {
2152 if(theMainView->selectedFont())
2153 {
2154 FMPanoseDialog dia(theMainView->selectedFont(), this);
2155 dia.exec();
2156 if(dia.getOk() && ( dia.getSourcePanose() != dia.getTargetPanose() ))
2157 {
2158 // qDebug()<< "Update Panose"<<theMainView->selectedFont()->path();
2159 FMFontDb::DB()->setValue(theMainView->selectedFont()->path(), FMFontDb::Panose, dia.getTargetPanose());
2160 // theMainView->slotInfoFont();
2161 }
2162 }
2163 }
2164
slotDumpInfo()2165 void typotek::slotDumpInfo()
2166 {
2167 if(theMainView->selectedFont())
2168 {
2169 FMDumpDialog dia(theMainView->selectedFont(), this);
2170 if(dia.exec() != QDialog::Accepted)
2171 {
2172 qDebug()<< "Dump not saved";
2173 }
2174 }
2175
2176 }
2177
slotReloadFiltered()2178 void typotek::slotReloadFiltered()
2179 {
2180 FontItem * cf(theMainView->selectedFont());
2181 QString cfName;
2182 if(cf)
2183 cf->path();
2184
2185 QStringList toReload;
2186 QApplication::changeOverrideCursor(Qt::WaitCursor);
2187 QMap<QString, QStringList> tagsRec;
2188 FMFontDb *db(FMFontDb::DB());
2189 foreach(FontItem* f, theMainView->curFonts())
2190 {
2191 toReload << f->path();
2192 tagsRec[f->path()] = f->tags();
2193 db->Remove(f->path());
2194 }
2195 QList<FontItem*> renewedFonts;
2196 foreach(QString p, toReload)
2197 {
2198 FontItem * it(db->Font(p, true));
2199 if(it)
2200 {
2201 renewedFonts << it;
2202 }
2203 }
2204 db->TransactionBegin();
2205 foreach(FontItem* it, renewedFonts)
2206 {
2207 it->setTags(tagsRec[it->path()]);
2208 }
2209 db->TransactionEnd();
2210
2211 if(toReload.count() > renewedFonts.count())
2212 {
2213 //! Number of fonts we failed to reload
2214 showStatusMessage(tr("Failed to reload %n fonts", "", toReload.count() - renewedFonts.count()));
2215 // theMainView->slotReloadFontList();
2216 }
2217 if(!cfName.isEmpty())
2218 {
2219 // theMainView->forceReloadSelection();
2220 theMainView->slotFontSelectedByName(cfName);
2221 }
2222
2223 QApplication::restoreOverrideCursor();
2224
2225 }
2226
slotReloadSingle()2227 void typotek::slotReloadSingle()
2228 {
2229 FontItem * cf(theMainView->selectedFont());
2230 if(cf)
2231 {
2232 QString curName(cf->path());
2233 QStringList t(cf->tags());
2234 FMFontDb::DB()->Remove(curName);
2235 cf = FMFontDb::DB()->Font(curName, true);
2236 if(cf)
2237 {
2238 cf->setTags(t);
2239 // theMainView->forceReloadSelection();
2240 theMainView->slotFontSelectedByName(curName);
2241 }
2242 }
2243 }
2244
slotExtractFont()2245 void typotek::slotExtractFont()
2246 {
2247 FMFontExtract ex(this);
2248 ex.exec();
2249 }
2250
slotMatchRaster()2251 void typotek::slotMatchRaster()
2252 {
2253 FMMatchRaster mr(this);
2254 mr.exec();
2255 }
2256
2257
2258 #ifdef HAVE_PYTHONQT
slotExecScript()2259 void typotek::slotExecScript()
2260 {
2261 lastScript = QFileDialog::getOpenFileName(this,"Fontmatrix",QDir::homePath(),tr("Python scripts (*.py)"));
2262 if(!lastScript.isEmpty())
2263 {
2264 if((recentScripts.count() < MAX_RECENT_PYSCRIPTS) && (!recentScripts.values().contains(lastScript)))
2265 {
2266 QFileInfo fInfo(lastScript);
2267 QAction * sca (new QAction(fInfo.baseName(), this));
2268 recentScripts[sca] = lastScript;
2269 connect(sca, SIGNAL(triggered()), this, SLOT(slotExecRecentScript()));
2270 scriptMenu->addAction(sca);
2271 }
2272 FMPythonW::getInstance()->runFile(lastScript);
2273 }
2274 else
2275 qDebug()<<"Error: Script path empty";
2276 }
slotExecLastScript()2277 void typotek::slotExecLastScript()
2278 {
2279 if(!lastScript.isEmpty())
2280 {
2281 FMPythonW::getInstance()->runFile(lastScript);
2282 }
2283 else
2284 qDebug()<<"Error: Script path empty";
2285 }
slotExecRecentScript()2286 void typotek::slotExecRecentScript()
2287 {
2288 if(sender())
2289 {
2290 QAction * sca = reinterpret_cast<QAction*>(sender());
2291 if(sca)
2292 {
2293 if(recentScripts.contains(sca))
2294 {
2295 lastScript = recentScripts[sca];
2296 FMPythonW::getInstance()->runFile(lastScript);
2297 }
2298 }
2299 }
2300 }
2301 #else
slotExecScript()2302 void typotek::slotExecScript(){}
slotExecLastScript()2303 void typotek::slotExecLastScript(){}
slotExecRecentScript()2304 void typotek::slotExecRecentScript(){}
2305 #endif
2306
showToltalFilteredFonts()2307 void typotek::showToltalFilteredFonts()
2308 {
2309 countFilteredFonts->setText( tr( "Filtered Font(s): %n", "number of filtererd fonts showed in status bar", FMFontDb::DB()->countFilteredFonts() ) );
2310 }
2311
presentFontName(QString s)2312 void typotek::presentFontName(QString s)
2313 {
2314 curFontPresentation->setText(QString("%1 : <b>%2</b>")
2315 .arg(tr("Current Font", "followed by currently selected font name (in status bar)"))
2316 .arg(s));
2317 }
2318
2319
getPanoseMatchTreshold() const2320 int typotek::getPanoseMatchTreshold() const
2321 {
2322 return panoseMatchTreshold;
2323 }
2324
2325
setPanoseMatchTreshold(int theValue)2326 void typotek::setPanoseMatchTreshold ( int theValue )
2327 {
2328 panoseMatchTreshold = theValue;
2329 }
2330
2331
getWebBrowser() const2332 QString typotek::getWebBrowser() const
2333 {
2334 return webBrowser;
2335 }
2336
2337
setWebBrowser(const QString & theValue)2338 void typotek::setWebBrowser ( const QString& theValue )
2339 {
2340 webBrowser = theValue;
2341 }
2342
2343
getWebBrowserOptions() const2344 QString typotek::getWebBrowserOptions() const
2345 {
2346 return webBrowserOptions;
2347 }
2348
2349
setWebBrowserOptions(const QString & theValue)2350 void typotek::setWebBrowserOptions ( const QString& theValue )
2351 {
2352 webBrowserOptions = theValue;
2353 }
2354
hide()2355 void typotek::hide()
2356 {
2357 foreach(const QString& k, dockWidget.keys())
2358 {
2359 dockVisible[k] = dockWidget[k]->isVisible();
2360 dockWidget[k]->hide();
2361 }
2362 visibleFloatingWidgets.clear();
2363 foreach(FloatingWidget* f, FloatingWidgetsRegister::AllWidgets())
2364 {
2365 visibleFloatingWidgets[f] = f->isVisible();
2366 f->setVisible(false);
2367 }
2368
2369 playVisible = PlayWidget::getInstance()->isVisible();
2370
2371 QMainWindow::hide();
2372 }
2373
show()2374 void typotek::show()
2375 {
2376 foreach(const QString& k, dockWidget.keys())
2377 {
2378 dockWidget[k]->setVisible(dockVisible[k]);
2379 }
2380 foreach(FloatingWidget *f, visibleFloatingWidgets.keys())
2381 {
2382 f->setVisible(visibleFloatingWidgets[f]);
2383 }
2384
2385 PlayWidget::getInstance()->setVisible(playVisible);
2386
2387 QMainWindow::show();
2388 }
2389
setInfoStyle(const QString & theValue)2390 void typotek::setInfoStyle ( const QString& theValue )
2391 {
2392 infoStyle = theValue;
2393 }
2394
word(FontItem * item,const QString & alt)2395 QString typotek::word(FontItem * item, const QString& alt)
2396 {
2397 if(item)
2398 {
2399 QString word(m_theWord);
2400 if(word.isEmpty() && !alt.isEmpty())
2401 word = alt;
2402 word.replace("<name>", item->fancyName());
2403 word.replace("<family>", item->family());
2404 word.replace("<variant>", item->variant());
2405 return word;
2406 }
2407
2408 return m_theWord;
2409 }
2410
2411
updateFloatingStatus()2412 void typotek::updateFloatingStatus()
2413 {
2414 playAction->setChecked( PlayWidget::getInstance()->isVisible() );
2415 compareAction->setChecked(FontCompareWidget::getInstance()->isVisible());
2416
2417 viewMenu->removeAction(closeAllFloat);
2418 viewMenu->removeAction(showAllFloat);
2419 viewMenu->removeAction(hideAllFloat);
2420 viewMenu->removeAction(floatSep);
2421
2422 QList<FloatingWidget*> fwl(FloatingWidgetsRegister::AllWidgets());
2423 foreach(FloatingWidget* f, floatingWidgets.keys())
2424 {
2425 if(!fwl.contains(f))
2426 {
2427 viewMenu->removeAction(floatingWidgets[f]);
2428 floatingWidgets.remove(f);
2429 }
2430 }
2431
2432 foreach(FloatingWidget* f, fwl)
2433 {
2434 if(floatingWidgets.contains(f))
2435 {
2436 floatingWidgets[f]->setChecked(f->isVisible());
2437 }
2438 else
2439 {
2440 QAction *wa(new QAction(f->getActionName(),this));
2441 wa->setCheckable(true);
2442 connect(f, SIGNAL(visibilityChange()), this, SLOT(updateFloatingStatus()));
2443 connect(wa, SIGNAL(triggered(bool)), f, SLOT(activate(bool)));
2444 floatingWidgets.insert(f, wa);
2445 floatingWidgets[f]->setChecked(f->isVisible());
2446 viewMenu->addAction(wa);
2447 }
2448 }
2449 if(floatingWidgets.count() > 0)
2450 {
2451 viewMenu->addAction(floatSep);
2452 viewMenu->addAction(closeAllFloat);
2453 }
2454 if(floatingWidgets.count() > 1)
2455 {
2456 viewMenu->addAction(showAllFloat);
2457 viewMenu->addAction(hideAllFloat);
2458 }
2459 }
2460
2461
closeAllFloatings()2462 void typotek::closeAllFloatings()
2463 {
2464 foreach(FloatingWidget* f, floatingWidgets.keys())
2465 {
2466 f->close();
2467 }
2468 }
2469
showAllFloatings()2470 void typotek::showAllFloatings()
2471 {
2472 foreach(FloatingWidget* f, floatingWidgets.keys())
2473 {
2474 f->setVisible(true);
2475 }
2476 }
2477
hideAllFloatings()2478 void typotek::hideAllFloatings()
2479 {
2480 foreach(FloatingWidget* f, floatingWidgets.keys())
2481 {
2482 f->setVisible(false);
2483 }
2484 }
2485
2486
toggleMainView(bool v)2487 void typotek::toggleMainView(bool v)
2488 {
2489 if(v)
2490 mainStack->setCurrentWidget(theBrowser);
2491 else
2492 mainStack->setCurrentWidget(theMainView);
2493 }
2494
pushObject(QObject * o)2495 void typotek::pushObject(QObject *o)
2496 {
2497 o->moveToThread(sender()->thread());
2498 }
2499