|
1 /**************************************************************************** |
|
2 ** |
|
3 ** Copyright (C) 2008-2010 Nokia Corporation and/or its subsidiary(-ies). |
|
4 ** All rights reserved. |
|
5 ** Contact: Nokia Corporation (developer.feedback@nokia.com) |
|
6 ** |
|
7 ** This file is part of the HbCore module of the UI Extensions for Mobile. |
|
8 ** |
|
9 ** GNU Lesser General Public License Usage |
|
10 ** This file may be used under the terms of the GNU Lesser General Public |
|
11 ** License version 2.1 as published by the Free Software Foundation and |
|
12 ** appearing in the file LICENSE.LGPL included in the packaging of this file. |
|
13 ** Please review the following information to ensure the GNU Lesser General |
|
14 ** Public License version 2.1 requirements will be met: |
|
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
|
16 ** |
|
17 ** In addition, as a special exception, Nokia gives you certain additional |
|
18 ** rights. These rights are described in the Nokia Qt LGPL Exception |
|
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
|
20 ** |
|
21 ** If you have questions regarding the use of this file, please contact |
|
22 ** Nokia at developer.feedback@nokia.com. |
|
23 ** |
|
24 ****************************************************************************/ |
|
25 |
|
26 #include "hbtextmeasurementutility_r.h" |
|
27 #include "hbtextmeasurementutility_r_p.h" |
|
28 #include "hbwidgetbase.h" |
|
29 #include "hbfontspec.h" |
|
30 #include "hbinstance.h" |
|
31 #include "hbfeaturemanager_r.h" |
|
32 |
|
33 #include <QGraphicsWidget> |
|
34 #include <QTextStream> |
|
35 #include <QFile> |
|
36 #include <QDir> |
|
37 #include <QDate> |
|
38 #include <QTimer> |
|
39 #include <QFont> |
|
40 |
|
41 #include <QDebug> // for qWarning |
|
42 |
|
43 #include <qmath.h> |
|
44 |
|
45 #ifndef Q_OS_SYMBIAN |
|
46 #include <iostream> |
|
47 #endif |
|
48 |
|
49 const QChar KCSVSeparator(','); |
|
50 const QString KUnknown("UNKNOWN"); |
|
51 |
|
52 class HbTextRecord |
|
53 { |
|
54 public: |
|
55 HbTextRecord(); |
|
56 QString fontLogicalName() const; |
|
57 HbFontSpec::Role fontRole(const QString logicalName) const; |
|
58 bool operator<(const HbTextRecord &other)const; |
|
59 static bool recordLessThan(HbTextRecord *rc1, HbTextRecord *rc2); |
|
60 static bool recordFullCompare(HbTextRecord *rc1, HbTextRecord *rc2); |
|
61 public: |
|
62 QString mRecordName; // Record name |
|
63 int mWidth; // Text item width (in pixels) |
|
64 HbFontSpec mFontSpec; // Font spec |
|
65 int mRowCount; |
|
66 }; |
|
67 |
|
68 |
|
69 HbTextRecord::HbTextRecord() |
|
70 { |
|
71 } |
|
72 |
|
73 QString HbTextRecord::fontLogicalName() const |
|
74 { |
|
75 QString logicalName(KUnknown); |
|
76 switch(mFontSpec.role()){ |
|
77 case HbFontSpec::Primary: |
|
78 logicalName = "qfn_primary"; |
|
79 break; |
|
80 case HbFontSpec::Secondary: |
|
81 logicalName = "qfn_secondary"; |
|
82 break; |
|
83 case HbFontSpec::Title: |
|
84 logicalName = "qfn_title"; |
|
85 break; |
|
86 case HbFontSpec::PrimarySmall: |
|
87 logicalName = "qfn_primary_small"; |
|
88 break; |
|
89 case HbFontSpec::Digital: |
|
90 logicalName = "qfn_digital"; |
|
91 break; |
|
92 default: |
|
93 break; |
|
94 } |
|
95 return logicalName; |
|
96 } |
|
97 |
|
98 HbFontSpec::Role HbTextRecord::fontRole(const QString logicalName) const |
|
99 { |
|
100 HbFontSpec::Role fontRole(HbFontSpec::Undefined); |
|
101 if ( logicalName == "qfn_primary" ) { |
|
102 fontRole = HbFontSpec::Primary; |
|
103 } else if ( logicalName == "qfn_secondary" ) { |
|
104 fontRole = HbFontSpec::Secondary; |
|
105 } else if ( logicalName == "qfn_title" ) { |
|
106 fontRole = HbFontSpec::Title; |
|
107 } else if ( logicalName == "qfn_primary_small" ) { |
|
108 fontRole = HbFontSpec::PrimarySmall; |
|
109 } else if ( logicalName == "qfn_digital" ) { |
|
110 fontRole = HbFontSpec::Digital; |
|
111 } |
|
112 return fontRole; |
|
113 } |
|
114 |
|
115 bool HbTextRecord::operator<(const HbTextRecord& other)const |
|
116 { |
|
117 return this->mRecordName < other.mRecordName; |
|
118 } |
|
119 |
|
120 bool HbTextRecord::recordLessThan(HbTextRecord* rc1, HbTextRecord* rc2) |
|
121 { |
|
122 return rc1->mRecordName < rc2->mRecordName; |
|
123 } |
|
124 |
|
125 bool HbTextRecord::recordFullCompare(HbTextRecord* rc1, HbTextRecord* rc2) |
|
126 { |
|
127 if (!rc1->mRecordName.compare(rc2->mRecordName)) { |
|
128 if (rc1->mFontSpec == rc2->mFontSpec) { |
|
129 if (rc1->mRowCount == rc2->mRowCount) { |
|
130 if (rc1->mWidth == rc2->mWidth) { |
|
131 return true; |
|
132 } else { |
|
133 qDebug() << "HbTextMeasurementUtility::recordFullCompare: Sizes don't match"; |
|
134 } |
|
135 } else { |
|
136 qDebug() << "HbTextMeasurementUtility::recordFullCompare: Row counts don't match"; |
|
137 } |
|
138 } else { |
|
139 qDebug() << "HbTextMeasurementUtility::recordFullCompare: Fonts don't match"; |
|
140 } |
|
141 } else { |
|
142 qDebug() << "HbTextMeasurementUtility::recordFullCompare: Names don't match"; |
|
143 } |
|
144 qDebug() << "HbTextMeasurementUtility::recordFullCompare: -- record1:" |
|
145 << rc1->mRecordName << rc1->mFontSpec.role() << rc1->mFontSpec.textHeight() << rc1->mRowCount << rc1->mWidth; |
|
146 qDebug() << "HbTextMeasurementUtility::recordFullCompare: -- record2:" |
|
147 << rc2->mRecordName << rc2->mFontSpec.role() << rc2->mFontSpec.textHeight() << rc2->mRowCount << rc2->mWidth; |
|
148 return false; |
|
149 } |
|
150 |
|
151 |
|
152 |
|
153 void HbTextMeasurementUtilityPrivate::readEntries(QTextStream &csvReader) |
|
154 { |
|
155 // Read the file header. |
|
156 QString line = csvReader.readLine(); |
|
157 |
|
158 while ( !csvReader.atEnd() ) { |
|
159 |
|
160 line = csvReader.readLine(); |
|
161 QStringList list = line.split(KCSVSeparator); |
|
162 if ( list.count() != 5 ) { |
|
163 qDebug() << "HbTextMeasurementUtilityPrivate::readEntries: Invalid csv file row read"; |
|
164 continue; |
|
165 } |
|
166 HbTextRecord *record = new HbTextRecord(); |
|
167 record->mRecordName = list.at(0); |
|
168 record->mFontSpec.setRole(record->fontRole(list.at(1))); |
|
169 record->mFontSpec.setTextHeight(list.at(2).toInt()); |
|
170 record->mWidth = list.at(3).toInt(); |
|
171 record->mRowCount = list.at(4).toInt(); |
|
172 records.append(record); |
|
173 } |
|
174 } |
|
175 |
|
176 |
|
177 /*! |
|
178 Write a report headers to csv file |
|
179 \internal |
|
180 */ |
|
181 void HbTextMeasurementUtilityPrivate::writeHeaders(QTextStream &csvWriter) |
|
182 { |
|
183 csvWriter << "Layout"; |
|
184 csvWriter << KCSVSeparator; |
|
185 csvWriter << "Font"; |
|
186 csvWriter << KCSVSeparator; |
|
187 csvWriter << "Row height"; |
|
188 csvWriter << KCSVSeparator; |
|
189 csvWriter << "Row width"; |
|
190 csvWriter << KCSVSeparator; |
|
191 csvWriter << "Max rows"; |
|
192 csvWriter << "\n"; |
|
193 } |
|
194 |
|
195 /*! |
|
196 Write a text item record to csv file |
|
197 \internal |
|
198 */ |
|
199 void HbTextMeasurementUtilityPrivate::writeEntry( |
|
200 QTextStream &csvWriter, |
|
201 const HbTextRecord *record) |
|
202 { |
|
203 // "Layout" |
|
204 csvWriter << record->mRecordName; |
|
205 csvWriter << KCSVSeparator; |
|
206 // "Font" |
|
207 csvWriter << record->fontLogicalName(); |
|
208 csvWriter << KCSVSeparator; |
|
209 // "Row height" |
|
210 csvWriter << qRound(record->mFontSpec.textHeight()-0.5); // Floor. |
|
211 csvWriter << KCSVSeparator; |
|
212 // "Row width" |
|
213 csvWriter << record->mWidth; |
|
214 csvWriter << KCSVSeparator; |
|
215 // "Max rows" |
|
216 csvWriter << record->mRowCount; |
|
217 csvWriter << '\n'; |
|
218 } |
|
219 |
|
220 /*! |
|
221 Validate records by removing duplicate items. |
|
222 \internal |
|
223 */ |
|
224 bool HbTextMeasurementUtilityPrivate::validateRecords(HbDeviceProfile &profile) |
|
225 { |
|
226 if (records.isEmpty()) { |
|
227 qDebug() << "HbTextMeasurementUtility::validateRecords: No result entries"; |
|
228 return false; |
|
229 } |
|
230 QList<HbTextRecord*> temp; |
|
231 qSort(records.begin(), records.end(), &HbTextRecord::recordLessThan); |
|
232 bool ret = true; |
|
233 |
|
234 foreach (HbTextRecord *record, records) { |
|
235 |
|
236 bool validRecord = true; |
|
237 |
|
238 for(int i=0; i<temp.count();i++) { |
|
239 if (!temp[i]->mRecordName.compare(record->mRecordName)) { |
|
240 // duplicate with same data. |
|
241 if (HbTextRecord::recordFullCompare(temp[i], record)) { |
|
242 qDebug() << "HbTextMeasurementUtility::validateRecords: Duplicate removed"; |
|
243 validRecord = false; |
|
244 break; |
|
245 } else { // duplicates id with unequal data. |
|
246 qDebug() << "HbTextMeasurementUtility::validateRecords: Duplicate text id found"; |
|
247 ret = false; |
|
248 continue; // search still duplicates with same data. |
|
249 } |
|
250 } |
|
251 } |
|
252 if (validRecord) { |
|
253 temp.append(record); |
|
254 } else { |
|
255 delete record; |
|
256 } |
|
257 } |
|
258 |
|
259 records = temp; |
|
260 foreach (const HbTextRecord *record, records) { |
|
261 if ( !record->fontLogicalName().compare(KUnknown) ) { |
|
262 qDebug() << "HbTextMeasurementUtility::validateRecords: Result item" << record->mRecordName << "Fontspec is null"; |
|
263 ret = false; |
|
264 } |
|
265 |
|
266 if ( record->mWidth > profile.logicalSize().width() ) { |
|
267 qDebug() << "HbTextMeasurementUtility::validateRecords: Result item" << record->mRecordName << "width is too wide"; |
|
268 qDebug() << "HbTextMeasurementUtility::validateRecords: Profile width: " << profile.logicalSize().width(); |
|
269 qDebug() << "HbTextMeasurementUtility::validateRecords: Record width:" << record->mWidth; |
|
270 ret = false; |
|
271 } |
|
272 } |
|
273 return ret; |
|
274 } |
|
275 |
|
276 /*! |
|
277 \internal |
|
278 */ |
|
279 void HbTextMeasurementUtilityPrivate::doMeasureItems() |
|
280 { |
|
281 #ifndef HB_TEXT_MEASUREMENT_UTILITY |
|
282 return; |
|
283 #else |
|
284 // Process all pending events. |
|
285 for (int i = 0; i < 3; ++i) { |
|
286 QCoreApplication::sendPostedEvents(); |
|
287 QCoreApplication::processEvents(); |
|
288 } |
|
289 |
|
290 QList<HbMainWindow*> mainWindows; |
|
291 if (mWindow) { |
|
292 mainWindows.append(mWindow); |
|
293 } else { |
|
294 mainWindows = hbInstance->allMainWindows(); |
|
295 } |
|
296 foreach (HbMainWindow* mainWindow, mainWindows ) { |
|
297 QGraphicsScene* scene = mainWindow->scene(); //krazy:exclude=qclasses |
|
298 QList<QGraphicsItem*> sceneItems = scene->items(); |
|
299 foreach (QGraphicsItem* sceneItem, sceneItems ) { |
|
300 if ( sceneItem->isWidget() ) { |
|
301 HbWidgetBase* widget = qobject_cast<HbWidgetBase*>(static_cast<QGraphicsWidget*>(sceneItem)); |
|
302 QVariant textId = widget |
|
303 ? widget->property( HbTextMeasurementUtilityNameSpace::textIdPropertyName ) |
|
304 : QVariant(); |
|
305 if( widget && widget->isVisible() && ( textId != QVariant::Invalid ) |
|
306 && ( !textId.toString().isEmpty() ) ) { |
|
307 HbTextRecord *record = new HbTextRecord(); |
|
308 record->mRecordName = textId.toString(); |
|
309 record->mWidth = qRound(widget->size().width() - 0.5); // Floor |
|
310 record->mFontSpec = widget->effectiveFontSpec(); |
|
311 if ( record->mFontSpec != widget->fontSpec() ) { |
|
312 qDebug() << "HbTextMeasurementUtility::measureItems: fontSpec and effectiveFontSpec do not match for item" |
|
313 << record->mRecordName; |
|
314 qDebug() << "- fontSpec, role:" << widget->fontSpec().role() << "textHeight:" << widget->fontSpec().textHeight(); |
|
315 qDebug() << "- effectiveFontSpec, role:" << record->mFontSpec.role() << "textHeight:" << record->mFontSpec.textHeight(); |
|
316 } |
|
317 record->mFontSpec.setTextHeight(qRound(record->mFontSpec.textHeight() - 0.5)); // Floor |
|
318 QVariant rowCount = widget->property( HbTextMeasurementUtilityNameSpace::textMaxLines ); |
|
319 record->mRowCount = rowCount.toInt(); |
|
320 if (record->mRowCount <= 0) { |
|
321 record->mRowCount = -1; |
|
322 } |
|
323 records.append(record); |
|
324 } |
|
325 } |
|
326 } |
|
327 } |
|
328 #endif |
|
329 } |
|
330 |
|
331 QString HbTextMeasurementUtilityPrivate::reportFilePath(HbDeviceProfile &profile, const QString &domainName) const |
|
332 { |
|
333 #ifdef Q_OS_SYMBIAN |
|
334 const QString KDriveF("F:\\"); |
|
335 const QString KDriveC("C:\\"); |
|
336 const QString KDirectory("data\\log\\qtestcase\\loc\\"); |
|
337 |
|
338 QString filePath; |
|
339 if (QFile::exists(KDriveF)) { |
|
340 filePath = KDriveF + KDirectory; |
|
341 } else { |
|
342 filePath = KDriveC + KDirectory; |
|
343 } |
|
344 #else |
|
345 QString filePath(QDir::tempPath()); |
|
346 filePath.append(QDir::separator()); |
|
347 filePath.append("loc"); |
|
348 filePath.append(QDir::separator()); |
|
349 filePath.append(profile.name()); |
|
350 filePath.append(QDir::separator()); |
|
351 #endif |
|
352 filePath = QDir::toNativeSeparators(filePath); |
|
353 |
|
354 QDir dir(filePath); |
|
355 if (!dir.exists()) { |
|
356 dir.mkpath(filePath); |
|
357 } |
|
358 |
|
359 // Make sure there are no illegal characters in "domainName" |
|
360 QString tempName = domainName; |
|
361 tempName.remove(QRegExp("[^a-zA-Z0-9]")); |
|
362 if (tempName.isEmpty()) { |
|
363 tempName = "unknown"; |
|
364 } |
|
365 |
|
366 filePath.append(tempName); |
|
367 filePath.append('_'); |
|
368 filePath.append(profile.name()); |
|
369 filePath.append('_'); |
|
370 filePath.append(QString::number(QDate::currentDate().year())); |
|
371 filePath.append("wk"); |
|
372 filePath.append(QString::number(QDate::currentDate().weekNumber())); |
|
373 filePath.append(".csv"); |
|
374 return filePath; |
|
375 } |
|
376 |
|
377 |
|
378 /*! |
|
379 @alpha |
|
380 @hbcore |
|
381 \class HbTextMeasurementUtility |
|
382 \brief HbTextMeasurementUtility is used for measuring available space for localized texts. |
|
383 |
|
384 This class collects metrics from localized text items and writes a report to |
|
385 a CSV file. The report is intended to be used when lenghts of text strings are decided |
|
386 and texts are localized to different language variants. |
|
387 |
|
388 The report contains the following data for each measured text item: |
|
389 - Layout: The logical name for the measuser text item (typically the logical text id). |
|
390 - Font: The logical fong (e.g. qfn_primary, qfn_secondary, etc.). |
|
391 - Row height: Height of one text row in pixels. This measure corresponds to HbFontSpec::textHeight(). |
|
392 - Row width: Width of one text row in pixels. |
|
393 - Max rows: Maximum row count for the measured text item. |
|
394 |
|
395 The text strings (set to text items) must have been allocated with hbTrId function. |
|
396 It stores the logical text id's to text items and this uses that information when |
|
397 collecting the metrics. |
|
398 |
|
399 Also the localization test mode (see: locTestMode) mush have been enabled |
|
400 before any hbTrId calls. In practice it's best to enable it before launching the |
|
401 application, or before creating the HbMainWindow, at latest. |
|
402 */ |
|
403 |
|
404 |
|
405 /*! |
|
406 \enum HbTextMeasurementUtility::LocTestMode |
|
407 The LocTestMode enum identifies the possible localization test modes. |
|
408 */ |
|
409 /*! |
|
410 \var HbTextMeasurementUtility::Disabled |
|
411 Localization tests disabled. |
|
412 */ |
|
413 /*! |
|
414 \var HbTextMeasurementUtility::Manual |
|
415 Manual localization test mode. The client needs to call readReport, measureItems |
|
416 and writeReport functions explicitly. |
|
417 */ |
|
418 /*! |
|
419 \var HbTextMeasurementUtility::Automatic |
|
420 Automatic localization test mode. The UI framework calls readReport, measureItems |
|
421 and writeReport automatically when needed. |
|
422 |
|
423 Notice that for performance reasons there's (at least) half a second timeout |
|
424 between measureItems calls. You should wait a while before moving between views |
|
425 in order to guarantee that the metrics will be harvested properly. |
|
426 */ |
|
427 |
|
428 |
|
429 /*! |
|
430 Default constructor. |
|
431 */ |
|
432 HbTextMeasurementUtility::HbTextMeasurementUtility() |
|
433 { |
|
434 d = new HbTextMeasurementUtilityPrivate; |
|
435 #ifndef HB_TEXT_MEASUREMENT_UTILITY |
|
436 d->mLocTestMode_cached = HbTextMeasurementUtility::Disabled; |
|
437 #else |
|
438 d->mLocTestMode_cached = HbFeatureManager::instance()->featureStatus( HbFeatureManager::TextMeasurement ); |
|
439 #endif |
|
440 } |
|
441 |
|
442 /*! |
|
443 Destructor. |
|
444 */ |
|
445 HbTextMeasurementUtility::~HbTextMeasurementUtility() |
|
446 { |
|
447 qDeleteAll(d->records); |
|
448 delete d; |
|
449 } |
|
450 |
|
451 /*! |
|
452 Returns singleton instance. |
|
453 */ |
|
454 HbTextMeasurementUtility *HbTextMeasurementUtility::instance() |
|
455 { |
|
456 static HbTextMeasurementUtility theUtility; |
|
457 return &theUtility; |
|
458 } |
|
459 |
|
460 /*! |
|
461 Sets the localization test mode to \a mode. |
|
462 */ |
|
463 void HbTextMeasurementUtility::setLocTestMode( int mode ) |
|
464 { |
|
465 #ifndef HB_TEXT_MEASUREMENT_UTILITY |
|
466 Q_UNUSED( mode ); |
|
467 return; |
|
468 #else |
|
469 HbFeatureManager::instance()->setFeatureStatus( HbFeatureManager::TextMeasurement, mode ); |
|
470 d->mLocTestMode_cached = mode; |
|
471 #endif |
|
472 } |
|
473 |
|
474 /*! |
|
475 Returns the current localization test mode. |
|
476 */ |
|
477 int HbTextMeasurementUtility::locTestMode() const |
|
478 { |
|
479 return d->mLocTestMode_cached; |
|
480 } |
|
481 |
|
482 /*! |
|
483 Measures all currently visible text items. |
|
484 This method is asynchronous if time interval \a after (in milliseconds) is larger than zero, |
|
485 and synchronous otherwise. This method will process any pending events in both cases, so |
|
486 the synchronous call should be sufficient in most of the cases. |
|
487 |
|
488 It's possible to give \a window parameter if the measurement is only made for text items |
|
489 of specific HbMainWindow. The measurement is made for all text items in all HbMainWindows |
|
490 if the parameter is omitted. |
|
491 */ |
|
492 void HbTextMeasurementUtility::measureItems(int after, HbMainWindow *window) |
|
493 { |
|
494 #ifndef HB_TEXT_MEASUREMENT_UTILITY |
|
495 Q_UNUSED( after ); |
|
496 Q_UNUSED( window ); |
|
497 return; |
|
498 #else |
|
499 // Store the window pointer, because it would not survive the singleShot timer call. |
|
500 d->mWindow = window; |
|
501 |
|
502 if (after > 0) { |
|
503 // Asynchronous |
|
504 QTimer::singleShot(after, d, SLOT(doMeasureItems())); |
|
505 } else { |
|
506 // Synchronous |
|
507 d->doMeasureItems(); |
|
508 } |
|
509 #endif |
|
510 } |
|
511 |
|
512 /*! |
|
513 Reads existing layout metric report file, see writeReport for the file locations. |
|
514 |
|
515 By using this method it is possible to update existing data instead of overwriting |
|
516 data that is measurered earlier. |
|
517 |
|
518 This method should be called before first call of measureItems() and after reset(). |
|
519 If there are some metrics data in memory, the file is not read for optimization reasons. |
|
520 */ |
|
521 bool HbTextMeasurementUtility::readReport( HbDeviceProfile &profile, const QString &domainName ) |
|
522 { |
|
523 #ifndef HB_TEXT_MEASUREMENT_UTILITY |
|
524 Q_UNUSED( profile ); |
|
525 Q_UNUSED( domainName ); |
|
526 return false; |
|
527 #else |
|
528 if (!d->records.isEmpty()) { |
|
529 return false; |
|
530 } |
|
531 QString filePath = d->reportFilePath(profile, domainName); |
|
532 QFile file; |
|
533 file.setFileName(filePath); |
|
534 if (!file.exists()) { |
|
535 return false; |
|
536 } |
|
537 if (!file.open(QFile::ReadOnly | QFile::Text)) { |
|
538 #ifndef Q_OS_SYMBIAN |
|
539 std::cerr << "Error: Cannot read file "; |
|
540 std::cerr << qPrintable(filePath); |
|
541 std::cerr << qPrintable(file.errorString()) << std::endl; |
|
542 #endif |
|
543 return false; |
|
544 } |
|
545 QTextStream csvReader(&file); |
|
546 d->readEntries(csvReader); |
|
547 file.close(); |
|
548 |
|
549 return true; |
|
550 #endif |
|
551 } |
|
552 |
|
553 |
|
554 /*! |
|
555 Writes a layout metric report into a file. |
|
556 |
|
557 The report contains metrics data for each text item at the time of last |
|
558 call to the measureItems() method. |
|
559 |
|
560 Report is written to a csv (Comma Separated Values) file. |
|
561 |
|
562 On Symbian environment the report is written to memory directory |
|
563 /data/log/qtestcase/loc/. Memory card is used if it exists (in F: drive). |
|
564 Otherwise C: drive is used. |
|
565 |
|
566 On other environments the report is written to system temp path + "loc". |
|
567 |
|
568 A subdirectory will be created for each orientation and/or resolution, |
|
569 e.g. "NHD-3.2-inch_portrait". |
|
570 |
|
571 The CSV file name will be of format <domainName>_<device profile name>_<week number>.csv, |
|
572 e.g. "myapp_NHD-3.2-inch_portrait_2010wk38.csv". |
|
573 */ |
|
574 bool HbTextMeasurementUtility::writeReport(HbDeviceProfile &profile, const QString &domainName) |
|
575 { |
|
576 #ifndef HB_TEXT_MEASUREMENT_UTILITY |
|
577 Q_UNUSED( profile ); |
|
578 Q_UNUSED( domainName ); |
|
579 return false; |
|
580 #else |
|
581 qDebug() << "HbTextMeasurementUtility::writeReport: Using profile" << profile.name(); |
|
582 |
|
583 QString filePath = d->reportFilePath(profile, domainName); |
|
584 QFile file(filePath); |
|
585 if (!file.open(QFile::WriteOnly | QFile::Text)) { |
|
586 #ifndef Q_OS_SYMBIAN |
|
587 std::cerr << "Error: Cannot write file "; |
|
588 std::cerr << qPrintable(filePath); |
|
589 std::cerr << qPrintable(file.errorString()) << std::endl; |
|
590 #endif |
|
591 return false; |
|
592 } |
|
593 bool ret = writeReport(profile, &file); |
|
594 |
|
595 file.close(); |
|
596 #ifndef Q_OS_SYMBIAN |
|
597 if (file.error()) { |
|
598 std::cerr << "Error: Cannot write file "; |
|
599 std::cerr << qPrintable(filePath); |
|
600 std::cerr << qPrintable(file.errorString()) << std::endl; |
|
601 } |
|
602 #endif |
|
603 return ret; |
|
604 #endif |
|
605 } |
|
606 |
|
607 |
|
608 /*! |
|
609 Overloaded function provided for convenience. Here you can manually specify QIODevice where to write report. |
|
610 */ |
|
611 bool HbTextMeasurementUtility::writeReport(HbDeviceProfile &profile, QIODevice *device) |
|
612 { |
|
613 #ifndef HB_TEXT_MEASUREMENT_UTILITY |
|
614 Q_UNUSED( device ); |
|
615 return false; |
|
616 #else |
|
617 |
|
618 if( device == 0 ) { |
|
619 return false; |
|
620 } |
|
621 |
|
622 bool succeed = d->validateRecords(profile); |
|
623 if (succeed) { |
|
624 qDebug() << "HbTextMeasurementUtility::writeReport: Measurements OK"; |
|
625 } else { |
|
626 qDebug() << "HbTextMeasurementUtility::writeReport: Measurements NOT OK"; |
|
627 } |
|
628 |
|
629 QTextStream csvWriter(device); |
|
630 d->writeHeaders(csvWriter); |
|
631 foreach (const HbTextRecord *record, d->records) { |
|
632 d->writeEntry(csvWriter, record); |
|
633 } |
|
634 return succeed; |
|
635 #endif |
|
636 } |
|
637 |
|
638 /*! |
|
639 Reset layout metrics data from memory. |
|
640 */ |
|
641 void HbTextMeasurementUtility::reset() |
|
642 { |
|
643 d->records.clear(); |
|
644 } |
|
645 |
|
646 |
|
647 |
|
648 |