1 /***************************************************************************
2  *   Copyright (C) 2010 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 #include "browserwidget.h"
22 #include "ui_browserwidget.h"
23 
24 #include "fmfontdb.h"
25 #include "fontitem.h"
26 #include "fminfodisplay.h"
27 #include "floatingwidgetsregister.h"
28 #include "samplewidget.h"
29 #include "chartwidget.h"
30 #include "typotek.h"
31 
32 #include <QDirModel>
33 #include <QDir>
34 #include <QSettings>
35 #include <QFileSystemWatcher>
36 #include <QDebug>
37 
BrowserWidget(QWidget * parent)38 BrowserWidget::BrowserWidget(QWidget *parent) :
39 		QWidget(parent),
40 		ui(new Ui::BrowserWidget)
41 {
42 	ui->setupUi(this);
43 
44 	ui->infoButton->setEnabled(false);
45 	ui->sampleButton->setEnabled(false);
46 	ui->chartButton->setEnabled(false);
47 
48 	folderViewContextMenu = 0;
49 	currentPage = BROWSER_VIEW_SAMPLE;
50 	sample = chart = 0;
51 	ffilter << "*.otf" << "*.ttf" << "*.ttc" << "*.pfb";
52 	theDirModel = new QDirModel(ffilter, QDir::AllDirs | QDir::Files | QDir::Drives | QDir::NoDotAndDotDot, QDir::DirsFirst | QDir::Name);
53 	theDirModel->setLazyChildCount(true);
54 	ui->browserView->setModel(theDirModel);
55 	ui->browserView->hideColumn(1);
56 	ui->browserView->hideColumn(2);
57 	ui->browserView->hideColumn(3);
58 	ui->browserView->setContextMenuPolicy(Qt::CustomContextMenu);
59 
60 	QSettings settings;
61 	QString lastUsedDir = settings.value("Places/LastUsedFolder", QDir::homePath()).toString();
62 	QDir d(lastUsedDir);
63 	if (!d.exists())
64 		lastUsedDir = QDir::homePath();
65 	QModelIndex luIdx(theDirModel->index(lastUsedDir, 0));
66 	ui->browserView->setCurrentIndex(luIdx);
67 	QModelIndexList hierarchy;
68 	while(luIdx.isValid())
69 	{
70 		hierarchy.prepend(luIdx);
71 		luIdx = luIdx.parent();
72 	}
73 	foreach(QModelIndex idx, hierarchy)
74 		ui->browserView->expand(idx);
75 
76 	dirWatcher = new QFileSystemWatcher(this);
77 	initWatcher(theDirModel->index(0,0));
78 
79 	connect(ui->infoButton, SIGNAL(clicked()), this, SLOT(slotShowInfo()));
80 	connect(ui->sampleButton, SIGNAL(clicked()), this, SLOT(slotShowSample()));
81 	connect(ui->chartButton, SIGNAL(clicked()), this, SLOT(slotShowChart()));
82 
83 	connect(ui->importButton, SIGNAL(clicked()), this, SLOT(slotImport()));
84 
85 	connect(ui->browserView, SIGNAL(activated( const QModelIndex& )), this, SLOT(slotFolderItemclicked(QModelIndex)));
86 	connect(ui->browserView, SIGNAL(clicked( const QModelIndex& )), this, SLOT(slotFolderItemclicked(QModelIndex)));
87 	connect(ui->browserView,SIGNAL(pressed( const QModelIndex& )),this,SLOT(slotFolderPressed(QModelIndex)));
88 
89 	connect(ui->browserView, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(slotFolderViewContextMenu(const QPoint &)));
90 
91 	connect(dirWatcher, SIGNAL(directoryChanged(QString)), this, SLOT(slotFolderRefresh(QString)));
92 
93 }
94 
~BrowserWidget()95 BrowserWidget::~BrowserWidget()
96 {
97 	delete ui;
98 }
99 
initWatcher(QModelIndex parent)100 void BrowserWidget::initWatcher(QModelIndex parent)
101 {
102 	//	qDebug()<<"initWatcher"<<theDirModel->filePath(parent);
103 	for(int fIdx(0); fIdx < theDirModel->rowCount(parent); ++fIdx)
104 	{
105 		QModelIndex mIdx(theDirModel->index(fIdx,0, parent));
106 		//		qDebug()<<"\t"<<theDirModel->filePath(mIdx)<<folderView->isExpanded(mIdx);
107 		if(ui->browserView->isExpanded(mIdx))
108 		{
109 			QString fp(theDirModel->filePath(mIdx));
110 			dirWatcher->addPath(fp);
111 			qDebug()<<"***Watch"<<fp;
112 			initWatcher(mIdx);
113 		}
114 	}
115 }
116 
slotFolderAddToWatcher(QModelIndex mIdx)117 void BrowserWidget::slotFolderAddToWatcher(QModelIndex mIdx)
118 {
119 	qDebug()<<"Add to watcher"<<theDirModel->filePath(mIdx);
120 	dirWatcher->addPath(theDirModel->filePath(mIdx));
121 }
122 
slotFolderItemclicked(QModelIndex mIdx)123 void BrowserWidget::slotFolderItemclicked(QModelIndex mIdx)
124 {
125 	if(curVariant.isEmpty())
126 	{
127 		ui->infoButton->setEnabled(true);
128 		ui->sampleButton->setEnabled(true);
129 		ui->chartButton->setEnabled(true);
130 	}
131 	QString path(theDirModel->data(mIdx,QDirModel::FilePathRole).toString());
132 	QFileInfo pf(path);
133 	if(!pf.isDir())
134 	{
135 		if(FMFontDb::DB()->insertTemporaryFont(path))
136 		{
137 //			emit folderSelectFont(pf.absoluteFilePath());
138 			QString fid(pf.absoluteFilePath());
139 			if(fid != curVariant)
140 			{
141 				if(chart != 0)
142 					uniBlock = reinterpret_cast<ChartWidget*>(chart)->currentBlock();
143 				delete sample;
144 				delete chart;
145 				sample = chart = 0;
146 				curVariant = fid;
147 //				currentIndex = index.row();
148 				switch(currentPage)
149 				{
150 				case BROWSER_VIEW_INFO: slotShowInfo();
151 					break;
152 				case BROWSER_VIEW_SAMPLE: slotShowSample();
153 					break;
154 				case BROWSER_VIEW_CHART: slotShowChart();
155 					break;
156 				default:
157 					break;
158 				}
159 
160 //				emit fontSelected(curVariant);
161 			}
162 		}
163 	}
164 	settingsDir(path);
165 }
166 
slotFolderPressed(QModelIndex mIdx)167 void BrowserWidget::slotFolderPressed(QModelIndex mIdx)
168 {
169 	currentFIndex = mIdx;
170 }
171 
slotFolderRefresh(const QString & dirPath)172 void BrowserWidget::slotFolderRefresh(const QString &dirPath)
173 {
174 	if(ui->browserView->isVisible())
175 	{
176 		qDebug()<<"Refresh"<<dirPath;
177 		theDirModel->refresh(theDirModel->index(dirPath, 0 ));
178 	}
179 }
180 
slotFolderRemoveFromWatcher(QModelIndex mIdx)181 void BrowserWidget::slotFolderRemoveFromWatcher(QModelIndex mIdx)
182 {
183 	qDebug()<<"Remove from watcher"<<theDirModel->filePath(mIdx);
184 	dirWatcher->removePath(theDirModel->filePath(mIdx));
185 }
186 
settingsDir(const QString & path)187 void BrowserWidget::settingsDir(const QString &path)
188 {
189 	static QString s;
190 	if (s == path)
191 		return;
192 
193 	QFileInfo fi(path);
194 	QString dirPath = fi.absoluteFilePath();
195 	if (fi.isFile())
196 		dirPath = fi.absoluteDir().absolutePath();
197 
198 	QSettings settings;
199 	settings.setValue("Places/LastUsedFolder", dirPath);
200 
201 	s = path;
202 }
203 
204 
slotShowInfo()205 void BrowserWidget::slotShowInfo()
206 {
207 	FMInfoDisplay fid(FMFontDb::DB()->Font(curVariant));
208 	ui->webView->setContent(fid.getHtml().toUtf8(), "application/xhtml+xml");
209 	ui->displayStack->setCurrentIndex(BROWSER_VIEW_INFO);
210 	currentPage = BROWSER_VIEW_INFO;
211 	updateButtons();
212 }
213 
slotShowChart()214 void BrowserWidget::slotShowChart()
215 {
216 	FloatingWidget * fw(FloatingWidgetsRegister::Widget(curVariant, ChartWidget::Name));
217 	if(fw == 0)
218 	{
219 		if(0 == chart)
220 		{
221 			ChartWidget *cw(new ChartWidget(curVariant, uniBlock, ui->pageChart));
222 			ui->displayStack->insertWidget(BROWSER_VIEW_CHART, cw);
223 			chart = cw;
224 			connect(chart, SIGNAL(detached()), this, SLOT(slotDetachChart()));
225 		}
226 		ui->displayStack->setCurrentWidget(chart);
227 	}
228 	else
229 	{
230 		fw->show();
231 	}
232 	currentPage = BROWSER_VIEW_CHART;
233 	updateButtons();
234 }
235 
236 
slotShowSample()237 void BrowserWidget::slotShowSample()
238 {
239 	FloatingWidget * fw(FloatingWidgetsRegister::Widget(curVariant, SampleWidget::Name));
240 	if(fw == 0)
241 	{
242 		if(0 == sample)
243 		{
244 			SampleWidget *sw(new SampleWidget(curVariant, ui->pageSample));
245 			ui->displayStack->insertWidget(BROWSER_VIEW_SAMPLE, sw);
246 			sample = sw;
247 			connect(sample, SIGNAL(detached()), this, SLOT(slotDetachSample()));
248 		}
249 		ui->displayStack->setCurrentWidget(sample);
250 	}
251 	else
252 	{
253 		fw->show();
254 	}
255 	currentPage = BROWSER_VIEW_SAMPLE;
256 	updateButtons();
257 }
258 
slotDetachChart()259 void BrowserWidget::slotDetachChart()
260 {
261 	disconnect(chart, SIGNAL(detached()), this, SLOT(slotDetachChart()));
262 	chart = 0;
263 	slotShowInfo();
264 }
265 
slotDetachSample()266 void BrowserWidget::slotDetachSample()
267 {
268 	disconnect(sample, SIGNAL(detached()), this, SLOT(slotDetachSample()));
269 	sample = 0;
270 	slotShowInfo();
271 }
272 
slotFolderViewContextMenu(const QPoint & p)273 void BrowserWidget::slotFolderViewContextMenu(const QPoint &p)
274 {
275 	qDebug()<<"P"<<p;
276 	QDirModel *dm = static_cast<QDirModel*>(ui->browserView->model());
277 	if (!dm)
278 		return;
279 
280 	QModelIndex mi = ui->browserView->currentIndex();
281 	if (!mi.isValid())
282 		return;
283 
284 	slotFolderItemclicked(mi); // make sure the font in question is loaded
285 				   // with a direct right click it would crash without this
286 
287 	if (!folderViewContextMenu)
288 		folderViewContextMenu = new FolderViewMenu();
289 
290 	folderViewContextMenu->exec(dm->fileInfo(mi), mapToGlobal(p));
291 }
292 
updateButtons()293 void BrowserWidget::updateButtons()
294 {
295 	static QList<QToolButton*> buttons;
296 	if(buttons.isEmpty())
297 	{
298 		buttons << ui->sampleButton
299 				<< ui->infoButton
300 				<< ui->chartButton;
301 		foreach(QToolButton * b, buttons)
302 		{
303 			b->setCheckable(true);
304 		}
305 	}
306 	foreach(QToolButton * b, buttons)
307 	{
308 		b->setChecked(false);
309 	}
310 	switch(currentPage)
311 	{
312 	case BROWSER_VIEW_SAMPLE: ui->sampleButton->setChecked(true);
313 		break;
314 	case BROWSER_VIEW_CHART: ui->chartButton->setChecked(true);
315 		break;
316 	case BROWSER_VIEW_INFO : ui->infoButton->setChecked(true);
317 		break;
318 	default:break;
319 	}
320 }
321 
slotImport()322 void BrowserWidget::slotImport()
323 {
324 	if(!curVariant.isEmpty())
325 		typotek::getInstance()->open(curVariant, false, true);
326 }
327 
FolderViewMenu()328 FolderViewMenu::FolderViewMenu() : QMenu()
329 {
330 	dirAction = new QAction(tr("Import Directory"), 0);
331 	dirRecursiveAction = new QAction(tr("Import recursively"), 0);
332 	fileAction = new QAction(tr("Import File"), 0);
333 
334 	addAction(dirAction);
335 	addAction(dirRecursiveAction);
336 	addAction(fileAction);
337 
338 	connect(dirAction, SIGNAL(triggered()), this, SLOT(slotImportDir()));
339 	connect(dirRecursiveAction, SIGNAL(triggered()), this, SLOT(slotImportDirRecursively()));
340 	connect(fileAction, SIGNAL(triggered()), this, SLOT(slotImportFile()));
341 }
342 
exec(const QFileInfo & fi,const QPoint & p)343 void FolderViewMenu::exec(const QFileInfo &fi, const QPoint &p)
344 {
345 	if (fi.isDir()) {
346 		dirAction->setEnabled(true);
347 		dirRecursiveAction->setEnabled(true);
348 		fileAction->setEnabled(false);
349 	} else if (fi.isFile()) {
350 		dirAction->setEnabled(false);
351 		dirRecursiveAction->setEnabled(false);
352 		fileAction->setEnabled(true);
353 	} else
354 		return; // not a file or a directory
355 
356 	selectedFileOrDir = fi;
357 
358 	QMenu::exec(p);
359 }
360 
361 
slotImportDir()362 void FolderViewMenu::slotImportDir()
363 {
364 //	QDir dir(selectedFileOrDir.absoluteFilePath());
365 //	QStringList ffilter;
366 //	ffilter << "*.otf" << "*.ttf" << "*.pfb";
367 //	QStringList fontList = dir.entryList(ffilter);
368 //	if (fontList.count() < 1)
369 //		return;
370 //	QString lastItem = fontList.at(fontList.count() - 1);
371 //	fontList.removeAt(fontList.count() - 1);
372 //	foreach(QString tmpFontPath, fontList) {
373 //		QString absPath = dir.absolutePath() + "/" + tmpFontPath;
374 //		typotek::getInstance()->open(absPath, false, true);
375 //	}
376 	typotek::getInstance()->open(selectedFileOrDir.absoluteFilePath(),false, true); // import the last font with the announce flag set to true
377 }
378 
slotImportDirRecursively()379 void FolderViewMenu::slotImportDirRecursively()
380 {
381 	typotek::getInstance()->open(selectedFileOrDir.absoluteFilePath());
382 }
383 
slotImportFile()384 void FolderViewMenu::slotImportFile()
385 {
386 	typotek::getInstance()->open(selectedFileOrDir.absoluteFilePath());
387 }
388 
~FolderViewMenu()389 FolderViewMenu::~FolderViewMenu()
390 {
391 
392 }
393