diff --git a/ExifImageViewer/.cproject b/ExifImageViewer/.cproject new file mode 100644 index 0000000..8d8c35a --- /dev/null +++ b/ExifImageViewer/.cproject @@ -0,0 +1,179 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ExifImageViewer/.gitignore b/ExifImageViewer/.gitignore new file mode 100644 index 0000000..2c15b78 --- /dev/null +++ b/ExifImageViewer/.gitignore @@ -0,0 +1,7 @@ +arm +arm-p +x86 +assets/.assets.index +translations/*.qm +.settings +.device diff --git a/ExifImageViewer/.project b/ExifImageViewer/.project new file mode 100644 index 0000000..a7bcef7 --- /dev/null +++ b/ExifImageViewer/.project @@ -0,0 +1,44 @@ + + + ExifImageView + + + + + + com.rim.tad.tools.qml.core.qmlFileBuilder + + + + + org.eclipse.cdt.managedbuilder.core.genmakebuilder + + + + + com.rim.tad.tools.wst.jsdt.core.javascriptValidator + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder + full,incremental, + + + + + com.qnx.tools.bbt.xml.core.bbtXMLValidationBuilder + + + + + + com.rim.tad.tools.wst.jsdt.core.jsNature + org.eclipse.cdt.core.cnature + org.eclipse.cdt.managedbuilder.core.managedBuildNature + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + com.qnx.tools.ide.bbt.core.bbtnature + org.eclipse.cdt.core.ccnature + com.rim.tad.tools.qml.core.qmlNature + + diff --git a/ExifImageViewer/ExifImageView.pro b/ExifImageViewer/ExifImageView.pro new file mode 100644 index 0000000..1802da0 --- /dev/null +++ b/ExifImageViewer/ExifImageView.pro @@ -0,0 +1,7 @@ +APP_NAME = ExifImageView + +CONFIG += qt warn_on cascades10 + +LIBS += -lexif + +include(config.pri) diff --git a/ExifImageViewer/LICENSE b/ExifImageViewer/LICENSE new file mode 100644 index 0000000..7a4a3ea --- /dev/null +++ b/ExifImageViewer/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. \ No newline at end of file diff --git a/ExifImageViewer/Makefile b/ExifImageViewer/Makefile new file mode 100644 index 0000000..e3c6e9e --- /dev/null +++ b/ExifImageViewer/Makefile @@ -0,0 +1,6 @@ +QMAKE_TARGET = ExifImageView +PROJECT_DIR := $(dir $(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST))) +I18N_DIR := $(PROJECT_DIR)/translations + +include mk/cs-base.mk + diff --git a/ExifImageViewer/README.md b/ExifImageViewer/README.md new file mode 100644 index 0000000..396691c --- /dev/null +++ b/ExifImageViewer/README.md @@ -0,0 +1,37 @@ +Exif Image Viewer + +======================================================================== +Sample Description. + +The Exif Image Viewer sample demonstrates how to load an image with exif +orientation data and display it with the correct rotation applied and filled +to the available space. + +You will learn how to: +- Use the Exif library that is provided on the device to read Exif data embedded in + images +- Use the Qt d-pointer PIMPLE design pattern +- Use a custom C++ class in QML + +======================================================================== +Requirements: + +BlackBerry 10 Native SDK + +======================================================================== +Running the example: + +1. Clone the Sample repository. +2. Launch BlackBerry 10 Native SDK, and from the File menu, select Import. +3. Expand General, and select Existing Projects into Workspace. Click Next. +4. Browse to the location of your sample directory, and then click OK. +5. The sample project should display in the Projects section. + Click Finish to import the project into your workspace. +6. In the Project Explorer pane, Right-click the project (for example hellocascades) + and select Build Project. +7. In the Project Explorer pane, Right-click the project (for example hellocascades) + and select Run As > BlackBerry C/C++ Application. +8. The application will now install and launch on your device if not you might + have to set up your environment: + http://developer.blackberry.com/cascades/documentation/getting_started/setting_up.html + diff --git a/ExifImageViewer/assets/ic_open.png b/ExifImageViewer/assets/ic_open.png new file mode 100644 index 0000000..931936b Binary files /dev/null and b/ExifImageViewer/assets/ic_open.png differ diff --git a/ExifImageViewer/assets/main.qml b/ExifImageViewer/assets/main.qml new file mode 100644 index 0000000..7667bd3 --- /dev/null +++ b/ExifImageViewer/assets/main.qml @@ -0,0 +1,76 @@ +/* Copyright (c) 2013 BlackBerry Limited. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import bb.cascades 1.0 +import bb.utility 1.0 +import bb.cascades.pickers 1.0 + +Page { + actionBarVisibility: ChromeVisibility.Overlay + + Container { + horizontalAlignment: HorizontalAlignment.Fill + verticalAlignment: VerticalAlignment.Fill + ImageView { + id: imageView + scalingMethod: ScalingMethod.AspectFit + horizontalAlignment: HorizontalAlignment.Center + verticalAlignment: VerticalAlignment.Center + attachedObjects: [ + ExifReader { + id: exifReader + onRotationChanged: { + imageView.rotationZ = rotation + imageView.visible = true + } + } + ] + image: exifReader.image + maxHeight: (exifReader.rotation == 270 || exifReader.rotation == 90) ? layout.layoutFrame.width : layout.layoutFrame.height + maxWidth: (exifReader.rotation == 270 || exifReader.rotation == 90) ? layout.layoutFrame.height : layout.layoutFrame.width + minHeight: maxHeight + minWidth: maxWidth + + // adjust layout for image rotation + translationY: (exifReader.rotation == 270 || exifReader.rotation == 90) ? (layout.layoutFrame.height - layout.layoutFrame.width)/2 : 0 + } + attachedObjects: LayoutUpdateHandler { + id: layout + } + } + actions: [ + ActionItem { + title: qsTr("select_an_image") + Retranslate.onLocaleOrLanguageChanged + imageSource: "asset:///ic_open.png" + ActionBar.placement: ActionBarPlacement.OnBar + onTriggered:picker.open() + attachedObjects: [ + FilePicker { + id: picker + mode: FilePickerMode.Picker + type: FileType.Picture + onFileSelected: { + var src = "file://" + selectedFiles[0] + if (exifReader.imageSource == src) + return + + imageView.visible = false + imageView.imageSource = exifReader.imageSource = src + } + } + ] + } + ] +} diff --git a/ExifImageViewer/bar-descriptor.xml b/ExifImageViewer/bar-descriptor.xml new file mode 100644 index 0000000..fe876e6 --- /dev/null +++ b/ExifImageViewer/bar-descriptor.xml @@ -0,0 +1,102 @@ + + + + + + + + com.example.ExifImageView + + + ExifImageView + + + 1.0.0 + en,fr,de,ar + + + 1 + + + + + + The ExifImageView application + + + + + + Example Inc. + + armle-v7 + ExifImageView + + + Qnx/Cascades + armle-v7 + ExifImageView.so + + + armle-v7 + ExifImageView + + + x86 + ExifImageView + + + + + + + true + none + false + + + + + icon.png + + + icon.png + assets + + + + + + + + run_native + access_shared + + + diff --git a/ExifImageViewer/config.pri b/ExifImageViewer/config.pri new file mode 100644 index 0000000..09c01e9 --- /dev/null +++ b/ExifImageViewer/config.pri @@ -0,0 +1,65 @@ +# Auto-generated by IDE. Any changes made by user will be lost! +BASEDIR = $$quote($$_PRO_FILE_PWD_) + +device { + CONFIG(debug, debug|release) { + SOURCES += $$quote($$BASEDIR/src/ExifReader.cpp) \ + $$quote($$BASEDIR/src/applicationui.cpp) \ + $$quote($$BASEDIR/src/main.cpp) + + HEADERS += $$quote($$BASEDIR/src/ExifReader.hpp) \ + $$quote($$BASEDIR/src/ExifReader_p.hpp) \ + $$quote($$BASEDIR/src/applicationui.hpp) + } + + CONFIG(release, debug|release) { + SOURCES += $$quote($$BASEDIR/src/ExifReader.cpp) \ + $$quote($$BASEDIR/src/applicationui.cpp) \ + $$quote($$BASEDIR/src/main.cpp) + + HEADERS += $$quote($$BASEDIR/src/ExifReader.hpp) \ + $$quote($$BASEDIR/src/ExifReader_p.hpp) \ + $$quote($$BASEDIR/src/applicationui.hpp) + } +} + +simulator { + CONFIG(debug, debug|release) { + SOURCES += $$quote($$BASEDIR/src/ExifReader.cpp) \ + $$quote($$BASEDIR/src/applicationui.cpp) \ + $$quote($$BASEDIR/src/main.cpp) + + HEADERS += $$quote($$BASEDIR/src/ExifReader.hpp) \ + $$quote($$BASEDIR/src/ExifReader_p.hpp) \ + $$quote($$BASEDIR/src/applicationui.hpp) + } +} + +INCLUDEPATH += $$quote($$BASEDIR/src) + +CONFIG += precompile_header + +PRECOMPILED_HEADER = $$quote($$BASEDIR/precompiled.h) + +lupdate_inclusion { + SOURCES += $$quote($$BASEDIR/../src/*.c) \ + $$quote($$BASEDIR/../src/*.c++) \ + $$quote($$BASEDIR/../src/*.cc) \ + $$quote($$BASEDIR/../src/*.cpp) \ + $$quote($$BASEDIR/../src/*.cxx) \ + $$quote($$BASEDIR/../assets/*.qml) \ + $$quote($$BASEDIR/../assets/*.js) \ + $$quote($$BASEDIR/../assets/*.qs) + + HEADERS += $$quote($$BASEDIR/../src/*.h) \ + $$quote($$BASEDIR/../src/*.h++) \ + $$quote($$BASEDIR/../src/*.hh) \ + $$quote($$BASEDIR/../src/*.hpp) \ + $$quote($$BASEDIR/../src/*.hxx) +} + +TRANSLATIONS = $$quote($${TARGET}_ar.ts) \ + $$quote($${TARGET}_de.ts) \ + $$quote($${TARGET}_en.ts) \ + $$quote($${TARGET}_fr.ts) \ + $$quote($${TARGET}.ts) diff --git a/ExifImageViewer/icon.png b/ExifImageViewer/icon.png new file mode 100644 index 0000000..4da03ad Binary files /dev/null and b/ExifImageViewer/icon.png differ diff --git a/ExifImageViewer/precompiled.h b/ExifImageViewer/precompiled.h new file mode 100644 index 0000000..6213dc4 --- /dev/null +++ b/ExifImageViewer/precompiled.h @@ -0,0 +1,2 @@ +// This file is used to store precompiled headers. +// It is intentionally left blank. It is up to you to decide which headers should be included here. diff --git a/ExifImageViewer/src/ExifReader.cpp b/ExifImageViewer/src/ExifReader.cpp new file mode 100644 index 0000000..d84e0df --- /dev/null +++ b/ExifImageViewer/src/ExifReader.cpp @@ -0,0 +1,123 @@ +/* Copyright (c) 2013 BlackBerry Limited. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include "ExifReader.hpp" +#include "ExifReader_p.hpp" + +#include + +#include +#include + +#include +#include + +namespace bb { +namespace extensions { + +ExifReaderPrivate::ExifReaderPrivate(ExifReader *parent) : + QObject(parent), q_ptr(parent), rotation(0) { +} +ExifReaderPrivate::~ExifReaderPrivate() { +} + +void ExifReaderPrivate::readImage(QUrl imageSource) { + // WARNING: this is run from another (non-ui) thread, use only thread-safe calls + qreal rotation = ExifReader::getImageRotation(imageSource); + QMetaObject::invokeMethod(this, "readImageFinished", Qt::QueuedConnection, Q_ARG(qreal, rotation)); +} +void ExifReaderPrivate::readImageFinished(qreal r) { + Q_Q(ExifReader); + // slot will be scheduled on the main thread's event loop, so we are now safe to access/modify instance variables + + if (r < 0) { + rotation = 0; + qDebug() << "Unable to read rotation for" << imageSource; + } else + rotation = r; + + emit q->rotationChanged(); +} + +ExifReader::ExifReader(QObject * parent) : + QObject(parent), d_ptr(new ExifReaderPrivate(this)) { +} + +ExifReader::~ExifReader() { +} + +qreal ExifReader::rotation() const { + Q_D(const ExifReader); + return d->rotation; +} + +QUrl ExifReader::imageSource() const { + Q_D(const ExifReader); + return d->imageSource; +} +void ExifReader::setImageSource(QUrl imageSource) { + Q_D(ExifReader); + if (imageSource == d->imageSource) + return; + + d->imageSource = imageSource; + emit imageSourceChanged(); + + if (imageSource.isEmpty()) { + d->rotation = 0; + emit rotationChanged(); + } + else { + QtConcurrent::run(d, &ExifReaderPrivate::readImage, imageSource); + } +} + +qreal ExifReader::getImageRotation(QUrl _url) { + qreal rotation = -1; + QString url = _url.toLocalFile(); + if (url.endsWith("jpg", Qt::CaseInsensitive) || url.endsWith("tiff", Qt::CaseInsensitive)) { + + // hold onto this so constData() is valid + QByteArray ba = url.toLocal8Bit(); + ExifData* exifData = exif_data_new_from_file(ba.constData()); + if (exifData != NULL) { + ExifEntry* exifEntry = exif_content_get_entry(exifData->ifd[EXIF_IFD_0], + EXIF_TAG_ORIENTATION); + + if (exifEntry != NULL) { + char value[256] = { 0, }; + memset(value, 0, sizeof(value)); + exif_entry_get_value(exifEntry, value, sizeof(value)); + + //qDebug() << "Orientation: " << value << endl; + QString orient = QString::fromLocal8Bit(value); + if (orient.compare("bottom-right", Qt::CaseInsensitive) == 0) { + rotation = 180.0; + } else if (orient.compare("right-top", Qt::CaseInsensitive) == 0) { + rotation = 90.0; + } else if (orient.compare("left-bottom", Qt::CaseInsensitive) == 0) { + rotation = 270.0; + } + + delete exifEntry; + } + delete exifData; + } + } + return rotation; +} + +} /* namespace extensions */ +} /* namespace bb */ diff --git a/ExifImageViewer/src/ExifReader.hpp b/ExifImageViewer/src/ExifReader.hpp new file mode 100644 index 0000000..59d7f54 --- /dev/null +++ b/ExifImageViewer/src/ExifReader.hpp @@ -0,0 +1,66 @@ +/* Copyright (c) 2013 BlackBerry Limited. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef EXIFREADER_HPP_ +#define EXIFREADER_HPP_ + +#include +#include +#include +#include + +namespace bb { +namespace extensions { + +class ExifReaderPrivate; + +/* ExifReader: read exif orientation data from an image + * - qml-capable class design + * - exposes funtional piece as a static method + * - leverages QThreadPool and QtConcurrentRun + */ + +class ExifReader: public QObject { + Q_OBJECT + + Q_PROPERTY(qreal rotation READ rotation NOTIFY rotationChanged FINAL) + Q_PROPERTY(QUrl imageSource READ imageSource WRITE setImageSource NOTIFY imageSourceChanged FINAL) + +public: + ExifReader(QObject *parent = NULL); + virtual ~ExifReader(); + +public slots: + static qreal getImageRotation(QUrl); + + qreal rotation() const; + QUrl imageSource() const; + void setImageSource(QUrl imageSource); + +signals: + void rotationChanged(); + void imageSourceChanged(); + +private: + ExifReaderPrivate *d_ptr; + Q_DECLARE_PRIVATE(ExifReader); +}; + +} /* namespace extensions */ +} /* namespace bb */ + +QML_DECLARE_TYPE(bb::extensions::ExifReader); + +#endif /* EXIFREADER_HPP_ */ diff --git a/ExifImageViewer/src/ExifReader_p.hpp b/ExifImageViewer/src/ExifReader_p.hpp new file mode 100644 index 0000000..40f4e99 --- /dev/null +++ b/ExifImageViewer/src/ExifReader_p.hpp @@ -0,0 +1,61 @@ +/* Copyright (c) 2013 BlackBerry Limited. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef EXIFREADER_P_HPP_ +#define EXIFREADER_P_HPP_ + +#include +#include +#include +#include +#include + +namespace bb { +namespace extensions { + +class ExifReader; + +/* ExifReaderPrivate + * - private header file hides implementation details + * - allows altering ExifReaderPrivate without breaking binary compatibility for ExifReader users + */ + +class ExifReaderPrivate: public QObject { + Q_OBJECT + +public: + ExifReaderPrivate(ExifReader *parent); + virtual ~ExifReaderPrivate(); + +public: + void readImage(QUrl imageSource); + +private slots: + void readImageFinished(qreal rotation); + +private: + ExifReader *q_ptr; + Q_DECLARE_PUBLIC(ExifReader); + + qreal rotation; + QUrl imageSource; + QVariant image; +}; + +} /* namespace utility */ +} /* namespace extensions */ + + +#endif /* EXIFREADER_P_HPP_ */ diff --git a/ExifImageViewer/src/applicationui.cpp b/ExifImageViewer/src/applicationui.cpp new file mode 100644 index 0000000..3965981 --- /dev/null +++ b/ExifImageViewer/src/applicationui.cpp @@ -0,0 +1,62 @@ +/* Copyright (c) 2013 BlackBerry Limited. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include "applicationui.hpp" +#include "ExifReader.hpp" + +#include +#include +#include +#include + +using namespace bb::cascades; + +ApplicationUI::ApplicationUI(bb::cascades::Application *app) : + QObject(app) +{ + // prepare the localization + m_pTranslator = new QTranslator(this); + m_pLocaleHandler = new LocaleHandler(this); + if(!QObject::connect(m_pLocaleHandler, SIGNAL(systemLanguageChanged()), this, SLOT(onSystemLanguageChanged()))) { + // This is an abnormal situation! Something went wrong! + // Add own code to recover here + qWarning() << "Recovering from a failed connect()"; + } + // initial load + onSystemLanguageChanged(); + + qmlRegisterType("bb.utility", 1, 0, "ExifReader"); + + // Create scene document from main.qml asset, the parent is set + // to ensure the document gets destroyed properly at shut down. + QmlDocument *qml = QmlDocument::create("asset:///main.qml").parent(this); + + // Create root object for the UI + AbstractPane *root = qml->createRootObject(); + + // Set created root object as the application scene + app->setScene(root); +} + +void ApplicationUI::onSystemLanguageChanged() +{ + QCoreApplication::instance()->removeTranslator(m_pTranslator); + // Initiate, load and install the application translation files. + QString locale_string = QLocale().name(); + QString file_name = QString("ExifImageView_%1").arg(locale_string); + if (m_pTranslator->load(file_name, "app/native/qm")) { + QCoreApplication::instance()->installTranslator(m_pTranslator); + } +} diff --git a/ExifImageViewer/src/applicationui.hpp b/ExifImageViewer/src/applicationui.hpp new file mode 100644 index 0000000..3b708a8 --- /dev/null +++ b/ExifImageViewer/src/applicationui.hpp @@ -0,0 +1,51 @@ +/* Copyright (c) 2013 BlackBerry Limited. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef ApplicationUI_HPP_ +#define ApplicationUI_HPP_ + +#include + +namespace bb +{ + namespace cascades + { + class Application; + class LocaleHandler; + } +} + +class QTranslator; + +/*! + * @brief Application object + * + * + */ + +class ApplicationUI : public QObject +{ + Q_OBJECT +public: + ApplicationUI(bb::cascades::Application *app); + virtual ~ApplicationUI() { } +private slots: + void onSystemLanguageChanged(); +private: + QTranslator* m_pTranslator; + bb::cascades::LocaleHandler* m_pLocaleHandler; +}; + +#endif /* ApplicationUI_HPP_ */ diff --git a/ExifImageViewer/src/main.cpp b/ExifImageViewer/src/main.cpp new file mode 100644 index 0000000..8f5bf7b --- /dev/null +++ b/ExifImageViewer/src/main.cpp @@ -0,0 +1,36 @@ +/* Copyright (c) 2013 BlackBerry Limited. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include + +#include +#include +#include "applicationui.hpp" + +#include + +using namespace bb::cascades; + +Q_DECL_EXPORT int main(int argc, char **argv) +{ + Application app(argc, argv); + + // Create the Application UI object, this is where the main.qml file + // is loaded and the application scene is set. + new ApplicationUI(&app); + + // Enter the application main event loop. + return Application::exec(); +} diff --git a/ExifImageViewer/translations/ExifImageView.pro b/ExifImageViewer/translations/ExifImageView.pro new file mode 100644 index 0000000..68b9b25 --- /dev/null +++ b/ExifImageViewer/translations/ExifImageView.pro @@ -0,0 +1 @@ +include (../ExifImageView.pro) diff --git a/ExifImageViewer/translations/ExifImageView.ts b/ExifImageViewer/translations/ExifImageView.ts new file mode 100644 index 0000000..fd5611a --- /dev/null +++ b/ExifImageViewer/translations/ExifImageView.ts @@ -0,0 +1,11 @@ + + + + + main + + select_an_image + + + + diff --git a/ExifImageViewer/translations/ExifImageView_ar.ts b/ExifImageViewer/translations/ExifImageView_ar.ts new file mode 100644 index 0000000..3dc3e1a --- /dev/null +++ b/ExifImageViewer/translations/ExifImageView_ar.ts @@ -0,0 +1,12 @@ + + + + + main + + + select_an_image + صورة إختر + + + diff --git a/ExifImageViewer/translations/ExifImageView_de.ts b/ExifImageViewer/translations/ExifImageView_de.ts new file mode 100644 index 0000000..d536898 --- /dev/null +++ b/ExifImageViewer/translations/ExifImageView_de.ts @@ -0,0 +1,12 @@ + + + + + main + + + select_an_image + Wählen sie ein bild + + + diff --git a/ExifImageViewer/translations/ExifImageView_en.ts b/ExifImageViewer/translations/ExifImageView_en.ts new file mode 100644 index 0000000..c70a432 --- /dev/null +++ b/ExifImageViewer/translations/ExifImageView_en.ts @@ -0,0 +1,12 @@ + + + + + main + + + select_an_image + Select an image + + + diff --git a/ExifImageViewer/translations/ExifImageView_fr.ts b/ExifImageViewer/translations/ExifImageView_fr.ts new file mode 100644 index 0000000..be3e72c --- /dev/null +++ b/ExifImageViewer/translations/ExifImageView_fr.ts @@ -0,0 +1,12 @@ + + + + + main + + + select_an_image + Choisir un image + + + diff --git a/ExifImageViewer/translations/Makefile b/ExifImageViewer/translations/Makefile new file mode 100644 index 0000000..31af41a --- /dev/null +++ b/ExifImageViewer/translations/Makefile @@ -0,0 +1,12 @@ +QMAKE_TARGET = ExifImageView +LUPDATE = $(QNX_HOST)/usr/bin/lupdate +LRELEASE = $(QNX_HOST)/usr/bin/lrelease + +update: $(QMAKE_TARGET).pro FORCE + $(LUPDATE) $(QMAKE_TARGET).pro + +release: $(QMAKE_TARGET).pro $(QMAKE_TARGET).ts + $(LRELEASE) $(QMAKE_TARGET).pro + +FORCE: +