Browse Source

v0.1

master
pankraz 4 years ago
parent
commit
7e37546ae9
  1. 45
      CHANGELOG.md
  2. BIN
      Friendiqa.apk
  3. 92
      README.md
  4. 10
      source-android/android/AndroidManifest.xml
  5. 34
      source-android/android/androidnative.gradle
  6. 2
      source-android/android/build.gradle
  7. 6
      source-android/android/gradle.properties
  8. 4
      source-android/android/gradle.properties~
  9. 2
      source-android/android/local.properties
  10. 1
      source-android/android/local.properties~
  11. BIN
      source-android/android/res/drawable-hdpi/splash.png
  12. BIN
      source-android/android/res/drawable-ldpi/icon.png
  13. BIN
      source-android/android/res/drawable-ldpi/splash.png
  14. BIN
      source-android/android/res/drawable-mdpi/splash.png
  15. BIN
      source-android/android/res/drawable-xhdpi/splash.png
  16. BIN
      source-android/android/res/drawable-xxhdpi/splash.png
  17. BIN
      source-android/android/res/drawable-xxxhdpi/splash.png
  18. BIN
      source-android/android/res/drawable/friendiqa.png
  19. BIN
      source-android/android/res/drawable/icon.png
  20. 96
      source-android/android/src/ExampleService.java
  21. 16
      source-android/android/src/FriendiqaActivity.java
  22. 1
      source-android/androidnative.pri
  23. 14
      source-android/application.qrc
  24. 47
      source-android/common/filesystem.cpp
  25. 6
      source-android/common/filesystem.h
  26. 22
      source-android/common/friendiqa.cpp
  27. 56
      source-android/common/imageselectandroid.cpp
  28. 23
      source-android/common/imageselectandroid.h
  29. 348
      source-android/common/qasystemdispatcher.cpp
  30. 47
      source-android/common/qasystemdispatcher.h
  31. 22
      source-android/common/quickandroid.cpp
  32. 21
      source-android/common/quickandroid.h
  33. 21
      source-android/common/xhr.cpp
  34. 31
      source-android/friendiqa.pro
  35. 713
      source-android/friendiqa.pro.user
  36. 390
      source-android/friendiqa.pro.user.feb2a9e
  37. BIN
      source-android/images/addImage.png
  38. 9
      source-android/js/helper.js
  39. 78
      source-android/js/news.js
  40. 63
      source-android/js/newsworker.js
  41. 167
      source-android/js/service.js
  42. 10
      source-android/qml/calendarqml/CalendarTab.qml
  43. 1
      source-android/qml/configqml/ConfigTab.qml
  44. 10
      source-android/qml/configqml/InfoBox.qml
  45. 2
      source-android/qml/contactqml/ContactComponent.qml
  46. 15
      source-android/qml/contactqml/ContactDetailsComponent.qml
  47. 101
      source-android/qml/contactqml/Contactlist.qml
  48. 96
      source-android/qml/contactqml/FriendsTab.qml
  49. 289
      source-android/qml/contactqml/GroupComponent.qml
  50. 5
      source-android/qml/friendiqa.qml
  51. 148
      source-android/qml/genericqml/ImageDialog.qml
  52. 59
      source-android/qml/genericqml/ImagePicker.qml
  53. 8
      source-android/qml/genericqml/OSSettingsAndroid.qml
  54. 7
      source-android/qml/genericqml/OSSettingsLinux.qml
  55. 189
      source-android/qml/genericqml/PermissionDialog.qml
  56. 48
      source-android/qml/newsqml/Conversation.qml
  57. 8
      source-android/qml/newsqml/FriendicaActivities.qml
  58. 121
      source-android/qml/newsqml/ImageDialog.qml
  59. 27
      source-android/qml/newsqml/MessageSend.qml
  60. 65
      source-android/qml/newsqml/NewsTab.qml
  61. 163
      source-android/qml/newsqml/Newsitem.qml
  62. 2
      source-android/qml/newsqml/PermissionDialog.qml
  63. 244
      source-android/qml/photoqml/ImageUploadDialog.qml
  64. 10
      source-android/qml/photoqml/PhotoComponent.qml
  65. 21
      source-android/qml/photoqml/PhotoPlaceholder.qml
  66. 34
      source-android/qml/photoqml/PhotoTab.qml
  67. 8
      source-android/qml/photoqml/PhotogroupComponent.qml
  68. BIN
      source-android/translations/friendiqa-de.qm
  69. 211
      source-android/translations/friendiqa-de.ts
  70. BIN
      source-android/translations/friendiqa-es.qm
  71. 200
      source-android/translations/friendiqa-es.ts
  72. 8
      source-linux/application.qrc
  73. 3
      source-linux/common/filesystem.cpp
  74. 50
      source-linux/common/imagepickerandroid.cpp
  75. 23
      source-linux/common/imagepickerandroid.h
  76. 22
      source-linux/common/xhr.cpp
  77. 15
      source-linux/friendiqa.pro
  78. 336
      source-linux/friendiqa.pro.user
  79. 336
      source-linux/friendiqa.pro.user.4e26e1d
  80. 336
      source-linux/friendiqa.pro.user.edcf3fd
  81. BIN
      source-linux/images/addImage.png
  82. 7
      source-linux/js/helper.js
  83. 63
      source-linux/js/news.js
  84. 52
      source-linux/js/newsworker.js
  85. 168
      source-linux/js/service.js
  86. 4
      source-linux/qml/configqml/InfoBox.qml
  87. 15
      source-linux/qml/contactqml/ContactDetailsComponent.qml
  88. 101
      source-linux/qml/contactqml/Contactlist.qml
  89. 96
      source-linux/qml/contactqml/FriendsTab.qml
  90. 288
      source-linux/qml/contactqml/GroupComponent.qml
  91. 5
      source-linux/qml/friendiqa.qml
  92. 4
      source-linux/qml/genericqml/AttachmentDialog.qml
  93. 148
      source-linux/qml/genericqml/ImageDialog.qml
  94. 4
      source-linux/qml/genericqml/PermissionDialog.qml
  95. 74
      source-linux/qml/newsqml/AttachmentDialog.qml
  96. 44
      source-linux/qml/newsqml/Conversation.qml
  97. 8
      source-linux/qml/newsqml/FriendicaActivities.qml
  98. 121
      source-linux/qml/newsqml/ImageDialog.qml
  99. 6
      source-linux/qml/newsqml/MessageSend.qml
  100. 55
      source-linux/qml/newsqml/NewsTab.qml

45
CHANGELOG.md

@ -1,30 +1,19 @@
## v0.004#
## v0.1#
# News #
* Conversation opens as child of news item
* Pull-to-refresh news
* Delete Icon
* Animated Gif attachments shown below news item
* Improved image selector for new message
* Gif attachments for new message
* Timeline reloaded after new message
# Contacts #
* Contact details window mechanism completely reworked
* New calendar icon for Friendica contacts
* "Connect" opens connect request page for Friendica contacs
# Calendar #
* new calendar tab
* shows own public events and public events of Friendica contacts
* list view of events of selected date
* click on event to show details
# Config #
* the icon of the server is shown if url is correct
* Click on icon for server details
# Translations #
* German
* Native Android image selector for new message
* Click on contacts shows contact details on news page
* Fix problem with news list after deletion of item
# Contacts #
* Clean contacts with no news
# Images #
* Upload pictures with description to album (permissions cannot be set due to API problems)
* Delete pictures or albums from client and server (long press on picture in overview)
* Fix problem when enlarging photo
# Translations #
* German, Spanish

BIN
Friendiqa.apk

92
README.md

@ -3,14 +3,14 @@
QML based client for the Friendica Social Network.
Tabs for news (incl. Direct Messages), friends, photos and events.
OS: currently Linux and Android(4.3).
Source code is a QtCreator project.
Source code is a QtCreator project.
## Screenshots ##
![Newstab](Screenshots/NewsTab.jpg)
![Friendstab](Screenshots/FriendsTab.jpg)
![Photostab](Screenshots/PhotoTab.jpg)
![Eventstab](Screenshots/EventsTab.jpg)
![Eventstab](Screenshots/EventsTab.jpg)
![Configtab](Screenshots/ConfigTab.jpg)
@ -19,38 +19,40 @@ QML based client for the Friendica Social Network.
# News #
Currently supported:
* Shows Posts from friends, favorited messages, Direct Messages and Notifications
* Open links in external browser
* Click on contact photo for contact details
* Click on like text for additional contact info
* Open links in external browser
*
Click on contact photo for contact details
* Click on like text for additional contact info
* Deletion, Reposting, Answering of Posts
* Liking, disliking, favoriting
* Attending for event posts
* Attending for event posts
* Update fetches new posts (up to last 50) since last in local DB
* More shows older posts from local DB
* Create new Message with images or direct messages, Contact/Group access rights(can be stored), smileys
* New image dialog
* Create new Message with images or direct messages, Contact/Group access rights(can be stored), smileys
* Native Android image dialog
ToDo:
* Videos and other binary data as attachment (sending and receiving)
* More than one attachment
* Rich text editing in Send Dialog
* Attachments for Direct messages (currently not supported in API)
* Videos and other binary data as attachment (sending and receiving, currently not supported in API)
* More than one attachment (currently not supported in API)
* Rich text editing in Send Dialog
* Attachments for Direct messages (currently not supported in API)
# Friends #
Currently supported:
* Tabs for friends, other contacts and groups
* Grid of all known contacts with locally downloaded pictures
* Large friend item for addional information and functionality
* Show news of contact from local database
* Send direct message, if contact is following
* Show public pictures of contact (screenscraping of contact's website, works only with certain theme)
* Open website of contact or connect page (for other contacts)
* Tabs for friends, other contacts and groups
* Grid of all known contacts with locally downloaded pictures
* Large friend item for addional information and functionality
* Show news of contact from local database
* Send direct message, if contact is following
* Show public pictures of contact (screenscraping of contact's website, works only with certain theme)
* Open website of contact or connect page (for other contacts)
* Clean other contacts with no news
ToDo:
* More information for contact from description page, possibly private information for friends
* More information for contact from description page, possibly private information for friends (currently not supported in API)
* Groups: create, change, delete
@ -58,45 +60,45 @@ ToDo:
Currently supported:
* Download all own images to local directory
* Show albums in grid, show images in album in grid and fullscreen
* Upload pictures to albums with description
* Delete pictures on client and server
* Show albums and images of contacts
* Pinch to zoom, swipe to scroll
* Pinch to zoom, swipe to scroll
ToDo:
* Private images of friends
* Support for all themes of friends
* Delete downloaded own images
# Events #
* download own public events and public events of Friendica contacts
* list view of events of selected date
* click on event to show details
ToDo
* private events
# Events #
* download own public events and show public events of Friendica contacts
* list view of events of selected date
* click on event to show details
ToDo
* private events
# Config #
Currently supported:
* Multiple accounts
* Maximum news (deleted after use of Quit button)
* View mode for news (tree or timeline)
* Maximum news (surplus deleted after use of Quit button)
* View mode for news (tree or timeline)
ToDo
* OAuth?
# Other #
ToDo
* Video tab
* Photo upload to album (needs API change)
* Translation
* Blingbling
# Translations #
* German
# Translations #
* German, Spanish
## License ##
Pubished under the [GPL v3](http://gplv3.fsf.org).

10
source-android/android/AndroidManifest.xml

@ -1,7 +1,11 @@
<?xml version="1.0"?>
<manifest package="org.qtproject.friendiqa" xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="0.4" android:versionCode="4" android:installLocation="auto">
<application android:hardwareAccelerated="true" android:name="org.qtproject.qt5.android.bindings.QtApplication" android:label="Friendiqa" android:icon="@drawable/friendiqa" android:logo="@drawable/friendiqa">
<activity android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|layoutDirection|locale|fontScale|keyboard|keyboardHidden|navigation" android:name="org.qtproject.qt5.android.bindings.QtActivity" android:label="Friendiqa" android:screenOrientation="unspecified" android:launchMode="singleTop">
<manifest package="org.qtproject.friendiqa" xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="0.1" android:versionCode="1" android:installLocation="auto">
<application android:hardwareAccelerated="true" android:vmSafeMode="true" android:name="org.qtproject.qt5.android.bindings.QtApplication" android:label="Friendiqa" android:icon="@drawable/friendiqa" android:logo="@drawable/friendiqa" android:theme="@android:style/Theme.Holo.Light">
<activity android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|layoutDirection|locale|fontScale|keyboard|keyboardHidden|navigation"
android:name="androidnative.friendiqa.FriendiqaActivity"
android:label="Friendiqa"
android:screenOrientation="unspecified"
android:launchMode="singleTop">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>

34
source-android/android/androidnative.gradle

@ -0,0 +1,34 @@
// Obtain androidPackageSourceDir
// androidPackageSourceDir is the absolute path of the folder containing build.gradle and AndroidManifests.xml
// This code also works with androiddeployqt.
import groovy.json.JsonSlurper
String getAndroidPackageSourceDir() {
String res = System.getProperty("user.dir");
FileTree tree = fileTree(dir: res + "/..").include("android*deployment-settings.json");
if (tree.getFiles().size() > 0) {
def inputFile = tree.getFiles().toArray()[0];
def InputJSON = new JsonSlurper().parseText(inputFile.text);
res = InputJSON["android-package-source-directory"]
} else {
println("android*deployment-settings.json not found. Set androidPackageSourceDir to user.dir");
}
return res;
}
String setAndroidNativePath(String path) {
String androidPackageSourceDir = getAndroidPackageSourceDir();
String androidNativePath = androidPackageSourceDir + path + "/java/src";
LinkedHashSet hash = android.sourceSets.main.java.srcDirs;
hash.add(androidNativePath);
android.sourceSets.main.java.srcDirs = hash;
}
ext {
setAndroidNativePath = this.&setAndroidNativePath;
}

2
source-android/android/build.gradle

@ -55,3 +55,5 @@ android {
abortOnError false
}
}
apply from: "androidnative.gradle"
setAndroidNativePath("/../androidnative.pri");

6
source-android/android/gradle.properties

@ -1,4 +1,4 @@
androidBuildToolsVersion=23.0.2
androidCompileSdkVersion=23
androidBuildToolsVersion=25.0.3
androidCompileSdkVersion=25
buildDir=.build
qt5AndroidDir=/home/pankraz/Qt/5.8/android_armv7/src/android/java
qt5AndroidDir=/home/pankraz/Qt/5.9.1/android_armv7/src/android/java

4
source-android/android/gradle.properties~

@ -0,0 +1,4 @@
androidBuildToolsVersion=25.0.3
androidCompileSdkVersion=25
buildDir=.build
qt5AndroidDir=/home/pankraz/Qt/5.9.1/android_armv7/src/android/java

2
source-android/android/local.properties

@ -1 +1 @@
sdk.dir=/opt/android-sdk
sdk.dir=/home/pankraz/android-sdk_alt

1
source-android/android/local.properties~

@ -0,0 +1 @@
sdk.dir=/home/pankraz/android-sdk_alt

BIN
source-android/android/res/drawable-hdpi/splash.png

After

Width: 766  |  Height: 1024  |  Size: 11 KiB

BIN
source-android/android/res/drawable-ldpi/icon.png

Before

Width: 32  |  Height: 32  |  Size: 1.5 KiB

BIN
source-android/android/res/drawable-ldpi/splash.png

After

Width: 766  |  Height: 1024  |  Size: 11 KiB

BIN
source-android/android/res/drawable-mdpi/splash.png

After

Width: 766  |  Height: 1024  |  Size: 11 KiB

BIN
source-android/android/res/drawable-xhdpi/splash.png

After

Width: 766  |  Height: 1024  |  Size: 11 KiB

BIN
source-android/android/res/drawable-xxhdpi/splash.png

After

Width: 766  |  Height: 1024  |  Size: 11 KiB

BIN
source-android/android/res/drawable-xxxhdpi/splash.png

After

Width: 766  |  Height: 1024  |  Size: 11 KiB

BIN
source-android/android/res/drawable/friendiqa.png

Before

Width: 32  |  Height: 32  |  Size: 1.5 KiB

BIN
source-android/android/res/drawable/icon.png

Before

Width: 32  |  Height: 32  |  Size: 1.5 KiB

96
source-android/android/src/ExampleService.java

@ -0,0 +1,96 @@
package androidnative.example;
import androidnative.SystemDispatcher;
import android.app.Notification;
import android.app.NotificationManager;
import android.util.Log;
import android.os.Handler;
import android.app.Activity;
import android.view.View;
import android.content.Context;
import java.util.Map;
import org.qtproject.qt5.android.QtNative;
public class ExampleService {
static {
SystemDispatcher.addListener(new SystemDispatcher.Listener() {
NotificationManager m_notificationManager;
Notification.Builder m_builder;
private void notificationManagerNotify(Map data) {
final Activity activity = QtNative.activity();
final Map messageData = data;
Runnable runnable = new Runnable () {
public void run() {
try {
String title = (String) messageData.get("title");
String message = (String) messageData.get("message");
if (m_notificationManager == null) {
m_notificationManager = (NotificationManager) activity.getSystemService(Context.NOTIFICATION_SERVICE);
m_builder = new Notification.Builder(activity);
// Small Icon is a must to make notification works.
// And that is why you need to inherit QtActivity
//m_builder.setSmallIcon(drawable.icon);
}
m_builder.setContentTitle(title);
m_builder.setContentText(message);
m_notificationManager.notify(1, m_builder.build());
// Test function. Remove it later.
SystemDispatcher.dispatch("Notifier.notifyFinished");
} catch (Exception e) {
Log.d("",e.getMessage());
}
};
};
activity.runOnUiThread(runnable);
}
private void hapticFeedbackPerform(Map data) {
final Activity activity = QtNative.activity();
final Map messageData = data;
Runnable runnable = new Runnable () {
public void run() {
int feedbackConstant = (Integer) messageData.get("feedbackConstant");
int flags = (Integer) messageData.get("flags");
Log.d("",String.format("hapticFeedbackPerform(%d,%d)",feedbackConstant,flags));
View rootView = activity.getWindow().getDecorView().getRootView();
rootView.performHapticFeedback(feedbackConstant, flags);
// Test function. Remove it later.
SystemDispatcher.dispatch("hapticFeedbackPerformFinished");
};
};
activity.runOnUiThread(runnable);
}
public void onDispatched(String name , Map data) {
if (name.equals("Notifier.notify")) {
notificationManagerNotify(data);
return;
} else if (name.equals("hapticFeedbackPerform")) {
hapticFeedbackPerform(data);
return;
}
return;
}
});
}
}

16
source-android/android/src/FriendiqaActivity.java

@ -0,0 +1,16 @@
package androidnative.friendiqa;
import androidnative.AndroidNativeActivity;
/**
* Created by benlau on 8/3/2017.
*/
public class FriendiqaActivity extends AndroidNativeActivity {
public FriendiqaActivity() {
super();
QT_ANDROID_THEMES = new String[] {""};
QT_ANDROID_DEFAULT_THEME = "";
}
}

1
source-android/androidnative.pri

@ -0,0 +1 @@
Subproject commit 86774d715cead715661892dd8f95c7854894fa9f

14
source-android/application.qrc

@ -4,14 +4,13 @@
<file>qml/newsqml/NewsTab.qml</file>
<file>qml/newsqml/Newsitem.qml</file>
<file>qml/newsqml/MessageSend.qml</file>
<file>qml/newsqml/PermissionDialog.qml</file>
<file>qml/newsqml/Conversation.qml</file>
<file>qml/newsqml/ImageDialog.qml</file>
<file>qml/newsqml/FriendicaActivities.qml</file>
<file>qml/contactqml/FriendsTab.qml</file>
<file>qml/contactqml/GroupComponent.qml</file>
<file>qml/contactqml/ContactComponent.qml</file>
<file>qml/contactqml/ContactDetailsComponent.qml</file>
<file>qml/contactqml/Contactlist.qml</file>
<file>qml/genericqml/BlueButton.qml</file>
<file>qml/photoqml/PhotoComponent.qml</file>
<file>qml/photoqml/PhotogroupComponent.qml</file>
@ -208,7 +207,14 @@
<file>qml/calendarqml/EventList.qml</file>
<file>translations/friendiqa-de.qm</file>
<file>translations/friendiqa-de.ts</file>
<file>translations/friendiqa-es.ts</file>
<file>translations/friendiqa-es.qm</file>
<file>qml/photoqml/ImageUploadDialog.qml</file>
<file>qml/genericqml/ImageDialog.qml</file>
<file>qml/genericqml/PermissionDialog.qml</file>
<file>images/addImage.png</file>
<file>common/imageselectandroid.h</file>
<file>common/imageselectandroid.cpp</file>
<file>qml/genericqml/ImagePicker.qml</file>
<file>common/quickandroid.h</file>
<file>common/quickandroid.cpp</file>
</qresource>
</RCC>

47
source-android/common/filesystem.cpp

@ -54,6 +54,7 @@ void FILESYSTEM::makeDir(QString name)
void FILESYSTEM::rmDir()
{
QDir dir(m_Directory);
//qDebug()<<m_Directory;
if (dir.removeRecursively()){
emit success(m_Directory);
}
@ -63,6 +64,8 @@ void FILESYSTEM::rmDir()
void FILESYSTEM::rmFile(QString name)
{
QDir dir(m_Directory);
//qDebug()<<m_Directory;
//qDebug(name);
if(dir.remove(name)){
emit success(name);
}
@ -79,3 +82,47 @@ QFileInfoList FILESYSTEM::fileList()
//qDebug() << "filelist " << m_Filelist;
return dir.entryInfoList();
}
void FILESYSTEM::searchImage()
{
QAndroidJniObject ACTION_PICK = QAndroidJniObject::getStaticObjectField("android/content/Intent", "ACTION_PICK", "Ljava/lang/String;");
QAndroidJniObject EXTERNAL_CONTENT_URI = QAndroidJniObject::getStaticObjectField("android/provider/MediaStore$Images$Media", "EXTERNAL_CONTENT_URI", "Landroid/net/Uri;");
QAndroidJniObject intent=QAndroidJniObject("android/content/Intent", "(Ljava/lang/String;Landroid/net/Uri;)V", ACTION_PICK.object<jstring>(), EXTERNAL_CONTENT_URI.object<jobject>());
if (ACTION_PICK.isValid() && intent.isValid())
{
intent.callObjectMethod("setType", "(Ljava/lang/String;)Landroid/content/Intent;", QAndroidJniObject::fromString("image/*").object<jstring>());
QtAndroid::startActivity(intent.object<jobject>(), 101,this);
qDebug() << "OK";
}
else
{
qDebug() << "ERRO";
}
}
void FILESYSTEM::handleActivityResult(int receiverRequestCode, int resultCode, const QAndroidJniObject &data)
{
jint RESULT_OK = QAndroidJniObject::getStaticField<jint>("android/app/Activity", "RESULT_OK");
if (receiverRequestCode == 101 && resultCode == RESULT_OK)
{
QAndroidJniObject uri = data.callObjectMethod("getData", "()Landroid/net/Uri;");
QAndroidJniObject dadosAndroid = QAndroidJniObject::getStaticObjectField("android/provider/MediaStore$MediaColumns", "DATA", "Ljava/lang/String;");
QAndroidJniEnvironment env;
jobjectArray projecao = (jobjectArray)env->NewObjectArray(1, env->FindClass("java/lang/String"), NULL);
jobject projacaoDadosAndroid = env->NewStringUTF(dadosAndroid.toString().toStdString().c_str());
env->SetObjectArrayElement(projecao, 0, projacaoDadosAndroid);
QAndroidJniObject contentResolver = QtAndroid::androidActivity().callObjectMethod("getContentResolver", "()Landroid/content/ContentResolver;");
QAndroidJniObject cursor = contentResolver.callObjectMethod("query", "(Landroid/net/Uri;[Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;)Landroid/database/Cursor;", uri.object<jobject>(), projecao, NULL, NULL, NULL);
jint columnIndex = cursor.callMethod<jint>("getColumnIndex", "(Ljava/lang/String;)I", dadosAndroid.object<jstring>());
cursor.callMethod<jboolean>("moveToFirst", "()Z");
QAndroidJniObject resultUri = cursor.callObjectMethod("getString", "(I)Ljava/lang/String;", columnIndex);
QString imageSelect = "file://" + resultUri.toString();
emit imageselected(imageSelect);
}
else
{
qDebug() << "Select error";
}
}

6
source-android/common/filesystem.h

@ -4,8 +4,9 @@
#include <QDir>
#include <QObject>
#include <QtAndroidExtras>
#include <QAndroidActivityResultReceiver>
class FILESYSTEM : public QObject
class FILESYSTEM : public QObject, public QAndroidActivityResultReceiver
{
Q_OBJECT
Q_PROPERTY(QString Directory READ Directory WRITE setDirectory NOTIFY directoryChanged)
@ -23,8 +24,10 @@ public:
//bool direxist(QString Directory);
QString homePath() const;
QString cameraPath() const;
virtual void handleActivityResult(int receiverRequestCode, int resultCode, const QAndroidJniObject &data);
signals:
void imageselected(QString);
void directoryChanged();
//void fileListContent(QList data);
void success(QString data);
@ -34,6 +37,7 @@ public slots:
void makeDir(QString name);
void rmDir();
void rmFile(QString name);
void searchImage();
//void fileList();
private:

22
source-android/common/friendiqa.cpp

@ -3,6 +3,26 @@
#include <QtQuick>
#include "xhr.h"
#include "filesystem.h"
//#include "qadrawableprovider.h"
//#include "androidnative.pri/cpp/AndroidNative/systemdispatcher.h"
#include "AndroidNative/systemdispatcher.h"
#include "AndroidNative/environment.h"
#include "AndroidNative/debug.h"
#include "AndroidNative/mediascannerconnection.h"
//#include "debugwrapper.h"
#ifdef Q_OS_ANDROID
#include <QtAndroidExtras/QAndroidJniObject>
#include <QtAndroidExtras/QAndroidJniEnvironment>
JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void*) {
Q_UNUSED(vm);
qDebug("NativeInterface::JNI_OnLoad()"); // It must call this function within JNI_OnLoad to enable System Dispatcher
AndroidNative::SystemDispatcher::registerNatives();
return JNI_VERSION_1_6;
}
#endif
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
@ -11,6 +31,8 @@ int main(int argc, char *argv[]) {
qtTranslator.load("friendiqa-" + QLocale::system().name(),":/translations");
app.installTranslator(&qtTranslator);
// qmlRegisterType<QASystemDispatcher>("SystemDispatcher", 0, 1, "SystemDispatcher");
XHR* xhr = XHR::instance();
view.rootContext()->setContextProperty("xhr", xhr);
FILESYSTEM* filesystem = FILESYSTEM::instance();

56
source-android/common/imageselectandroid.cpp

@ -0,0 +1,56 @@
#include "imageselectandroid.h"
imageSelectAndroid::imageSelectAndroid()
{
}
imageSelectAndroid *imageSelectAndroid::instance()
{
static imageSelectAndroid imageselectandroid;
return &imageselectandroid;
}
void imageSelectAndroid::searchImage()
{
QAndroidJniObject ACTION_PICK = QAndroidJniObject::getStaticObjectField("android/content/Intent", "ACTION_PICK", "Ljava/lang/String;");
QAndroidJniObject EXTERNAL_CONTENT_URI = QAndroidJniObject::getStaticObjectField("android/provider/MediaStore$Images$Media", "EXTERNAL_CONTENT_URI", "Landroid/net/Uri;");
QAndroidJniObject intent=QAndroidJniObject("android/content/Intent", "(Ljava/lang/String;Landroid/net/Uri;)V", ACTION_PICK.object<jstring>(), EXTERNAL_CONTENT_URI.object<jobject>());
if (ACTION_PICK.isValid() && intent.isValid())
{
intent.callObjectMethod("setType", "(Ljava/lang/String;)Landroid/content/Intent;", QAndroidJniObject::fromString("image/*").object<jstring>());
QtAndroid::startActivity(intent.object<jobject>(), 101, this);
qDebug() << "OK";
}
else
{
qDebug() << "ERRO";
}
}
void imageSelectAndroid::handleActivityResult(int receiverRequestCode, int resultCode, const QAndroidJniObject &data)
{ qDebug() << "done";
jint RESULT_OK = QAndroidJniObject::getStaticField<jint>("android/app/Activity", "RESULT_OK");
if (receiverRequestCode == 101 && resultCode == RESULT_OK)
{
qDebug() << "done";
QAndroidJniObject uri = data.callObjectMethod("getData", "()Landroid/net/Uri;");
QAndroidJniObject dadosAndroid = QAndroidJniObject::getStaticObjectField("android/provider/MediaStore$MediaColumns", "DATA", "Ljava/lang/String;");
QAndroidJniEnvironment env;
jobjectArray projecao = (jobjectArray)env->NewObjectArray(1, env->FindClass("java/lang/String"), NULL);
jobject projacaoDadosAndroid = env->NewStringUTF(dadosAndroid.toString().toStdString().c_str());
env->SetObjectArrayElement(projecao, 0, projacaoDadosAndroid);
QAndroidJniObject contentResolver = QtAndroid::androidActivity().callObjectMethod("getContentResolver", "()Landroid/content/ContentResolver;");
QAndroidJniObject cursor = contentResolver.callObjectMethod("query", "(Landroid/net/Uri;[Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;)Landroid/database/Cursor;", uri.object<jobject>(), projecao, NULL, NULL, NULL);
jint columnIndex = cursor.callMethod<jint>("getColumnIndex", "(Ljava/lang/String;)I", dadosAndroid.object<jstring>());
cursor.callMethod<jboolean>("moveToFirst", "()Z");
QAndroidJniObject resultUri = cursor.callObjectMethod("getString", "(I)Ljava/lang/String;", columnIndex);
QString imageSelect = "file://" + resultUri.toString();
emit imageselected(imageSelect);
}
else
{
qDebug() << "Select error";
}
}

23
source-android/common/imageselectandroid.h

@ -0,0 +1,23 @@
#ifndef IMAGEPICKANDROID_H
#define IMAGEPICKANDROID_H
#include <QObject>
#include <QtAndroidExtras>
#include <QDebug>
class imageSelectAndroid : public QObject, public QAndroidActivityResultReceiver
{
Q_OBJECT
public:
imageSelectAndroid();
static imageSelectAndroid *instance();
void searchImage();
virtual void handleActivityResult(int receiverRequestCode, int resultCode, const QAndroidJniObject & data);
signals:
void imageselected(QString);
};
#endif // IMAGEPICKANDROID_H

348
source-android/common/qasystemdispatcher.cpp

@ -0,0 +1,348 @@
// Author: Ben Lau (https://github.com/benlau)
#include <QCoreApplication>
#include <QPointer>
#include <QtCore>
#include <QPair>
#include <QQueue>
#include "qasystemdispatcher.h"
static QPointer<QASystemDispatcher> m_instance;
QString QASystemDispatcher::ACTIVITY_RESUME_MESSAGE = "Activity.onResume";
QString QASystemDispatcher::ACTIVITY_RESULT_MESSAGE = "Activity.onActivityResult";
#ifdef Q_OS_ANDROID
#include <QAndroidJniObject>
#include <QAndroidJniEnvironment>
#define JCLASS_Name "quickandroid/SystemDispatcher"
#define DISPATCH_SIGNATURE "(Ljava/lang/String;Ljava/util/Map;)V"
#define EMIT_SIGNATURE "(Ljava/lang/String;Ljava/util/Map;)V"
static QVariantMap createVariantMap(jobject data);
static jobject createHashMap(const QVariantMap &data);
static QVariant convertToQVariant(QAndroidJniObject value) {
QVariant v;
if (!value.isValid()) {
return v;
}
QAndroidJniEnvironment env;
jclass jclass_of_string = env->FindClass("java/lang/String");
jclass jclass_of_integer = env->FindClass("java/lang/Integer");
jclass jclass_of_boolean = env->FindClass("java/lang/Boolean");
jclass jclass_of_list = env->FindClass("java/util/List");
jclass jclass_of_map = env->FindClass("java/util/Map");
if (env->IsInstanceOf(value.object<jobject>(),jclass_of_boolean)) {
v = QVariant::fromValue<bool>(value.callMethod<jboolean>("booleanValue","()Z"));
} else if (env->IsInstanceOf(value.object<jobject>(),jclass_of_integer)) {
v = value.callMethod<jint>("intValue","()I");
} else if (env->IsInstanceOf(value.object<jobject>(),jclass_of_string)) {
v = value.toString();
} else if (env->IsInstanceOf(value.object<jobject>(), jclass_of_map)) {
v = createVariantMap(value.object<jobject>());
} else if (env->IsInstanceOf(value.object<jobject>(),jclass_of_list)) {
QVariantList list;
int count = value.callMethod<jint>("size","()I");
for (int i = 0 ; i < count ; i++) {
QAndroidJniObject item = value.callObjectMethod("get","(I)Ljava/lang/Object;",i);
list.append(convertToQVariant(item));
}
v = list;
}
env->DeleteLocalRef(jclass_of_string);
env->DeleteLocalRef(jclass_of_integer);
env->DeleteLocalRef(jclass_of_boolean);
env->DeleteLocalRef(jclass_of_list);
env->DeleteLocalRef(jclass_of_map);
return v;
}
static QVariantMap createVariantMap(jobject data) {
QVariantMap res;
QAndroidJniEnvironment env;
/* Reference : https://community.oracle.com/thread/1549999 */
// Get the HashMap Class
jclass jclass_of_hashmap = (env)->GetObjectClass(data);
// Get link to Method "entrySet"
jmethodID entrySetMethod = (env)->GetMethodID(jclass_of_hashmap, "entrySet", "()Ljava/util/Set;");
// Invoke the "entrySet" method on the HashMap object
jobject jobject_of_entryset = env->CallObjectMethod(data, entrySetMethod);
// Get the Set Class
jclass jclass_of_set = (env)->FindClass("java/util/Set"); // Problem during compilation !!!!!
if (jclass_of_set == 0) {
qWarning() << "java/util/Set lookup failed\n";
return res;
}
// Get link to Method "iterator"
jmethodID iteratorMethod = env->GetMethodID(jclass_of_set, "iterator", "()Ljava/util/Iterator;");
// Invoke the "iterator" method on the jobject_of_entryset variable of type Set
jobject jobject_of_iterator = env->CallObjectMethod(jobject_of_entryset, iteratorMethod);
// Get the "Iterator" class
jclass jclass_of_iterator = (env)->FindClass("java/util/Iterator");
// Get link to Method "hasNext"
jmethodID hasNextMethod = env->GetMethodID(jclass_of_iterator, "hasNext", "()Z");
jmethodID nextMethod = env->GetMethodID(jclass_of_iterator, "next", "()Ljava/lang/Object;");
while (env->CallBooleanMethod(jobject_of_iterator, hasNextMethod) ) {
jobject jEntry = env->CallObjectMethod(jobject_of_iterator,nextMethod);
QAndroidJniObject entry = QAndroidJniObject(jEntry);
QAndroidJniObject key = entry.callObjectMethod("getKey","()Ljava/lang/Object;");
QAndroidJniObject value = entry.callObjectMethod("getValue","()Ljava/lang/Object;");
QString k = key.toString();
QVariant v = convertToQVariant(value);
env->DeleteLocalRef(jEntry);
if (v.isNull()) {
continue;
}
res[k] = v;
}
if (env->ExceptionOccurred()) {
env->ExceptionDescribe();
env->ExceptionClear();
}
env->DeleteLocalRef(jclass_of_hashmap);
env->DeleteLocalRef(jobject_of_entryset);
env->DeleteLocalRef(jclass_of_set);
env->DeleteLocalRef(jobject_of_iterator);
env->DeleteLocalRef(jclass_of_iterator);
return res;
}
static jobject convertToJObject(QVariant v) {
jobject res = 0;
QAndroidJniEnvironment env;
if (v.type() == QVariant::String) {
QString str = v.toString();
res = env->NewStringUTF(str.toLocal8Bit().data());
} else if (v.type() == QVariant::Int) {
jclass integerClass = env->FindClass("java/lang/Integer");
jmethodID integerConstructor = env->GetMethodID(integerClass, "<init>", "(I)V");
res = env->NewObject(integerClass,integerConstructor,v.toInt());
env->DeleteLocalRef(integerClass);
} else if (v.type() == QVariant::Bool) {
jclass booleanClass = env->FindClass("java/lang/Boolean");
jmethodID booleanConstructor = env->GetMethodID(booleanClass,"<init>","(Z)V");
res = env->NewObject(booleanClass,booleanConstructor,v.toBool());
env->DeleteLocalRef(booleanClass);
} else if (v.type() == QVariant::Map) {
res = createHashMap(v.toMap());
} else if (v.type() == QVariant::List){
QVariantList list = v.value<QVariantList>();
jclass arrayListClass = env->FindClass("java/util/ArrayList");
jmethodID init = env->GetMethodID(arrayListClass, "<init>", "(I)V");
res = env->NewObject( arrayListClass, init, list.size());
jmethodID add = env->GetMethodID( arrayListClass, "add",
"(Ljava/lang/Object;)Z");
for (int i = 0 ; i < list.size() ; i++) {
jobject item = convertToJObject(list.at(i));
env->CallBooleanMethod(res,add, item);
env->DeleteLocalRef(item);
}
env->DeleteLocalRef(arrayListClass);
} else {
qWarning() << "QASystemDispatcher: Non-supported data type - " << v.type();
}
return res;
}
static jobject createHashMap(const QVariantMap &data) {
QAndroidJniEnvironment env;
jclass mapClass = env->FindClass("java/util/HashMap");
if (mapClass == NULL) {
qWarning() << "Failed to find class" << "java/util/HashMap";
return NULL;
}
jsize map_len = data.size();
jmethodID init = env->GetMethodID(mapClass, "<init>", "(I)V");
jobject hashMap = env->NewObject( mapClass, init, map_len);
jmethodID put = env->GetMethodID( mapClass, "put",
"(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
QMapIterator<QString, QVariant> iter(data);
while (iter.hasNext()) {
iter.next();
QString key = iter.key();
jstring jkey = env->NewStringUTF(key.toLocal8Bit().data());
QVariant v = iter.value();
jobject item = convertToJObject(v);
if (item == 0) {
continue;
}
env->CallObjectMethod(hashMap,put,jkey,item);
env->DeleteLocalRef(item);
env->DeleteLocalRef(jkey);
}
if (env->ExceptionOccurred()) {
env->ExceptionDescribe();
env->ExceptionClear();
}
env->DeleteLocalRef(mapClass);
return hashMap;
}
static void jniEmit(JNIEnv* env,jobject object,jstring name,jobject data) {
Q_UNUSED(object);
Q_UNUSED(env);
QAndroidJniObject tmp(name);
QString str = tmp.toString();
QVariantMap map;
if (data != 0) {
map = createVariantMap(data);
}
if (m_instance.isNull()) {
return;
}
QMetaObject::invokeMethod(m_instance.data(),"dispatched",Qt::AutoConnection,
Q_ARG(QString, str),
Q_ARG(QVariantMap,map));
}
#endif
QASystemDispatcher::QASystemDispatcher(QObject* parent) : QObject(parent)
{
}
QASystemDispatcher::~QASystemDispatcher()
{
}
QASystemDispatcher *QASystemDispatcher::instance()
{
if (!m_instance) {
QCoreApplication* app = QCoreApplication::instance();
m_instance = new QASystemDispatcher(app);
}
return m_instance;
}
void QASystemDispatcher::dispatch(QString type, QVariantMap message)
{
Q_UNUSED(type);
Q_UNUSED(message);
#ifdef Q_OS_ANDROID
QAndroidJniEnvironment env;
jstring jType = env->NewStringUTF(type.toLocal8Bit().data());
jobject jData = createHashMap(message);
QAndroidJniObject::callStaticMethod<void>(JCLASS_Name, "dispatch",
DISPATCH_SIGNATURE,
jType,jData);
env->DeleteLocalRef(jType);
env->DeleteLocalRef(jData);
#else
static bool dispatching = false;
static QQueue<QPair<QString,QVariantMap> > queue;
if (dispatching) {
queue.enqueue(QPair<QString,QVariantMap> (type,message) );
return;
}
dispatching = true;
emit dispatched(type,message);
qWarning() << "QASystemDispatcher: emitted"
while (queue.size() > 0) {
QPair<QString,QVariantMap> pair = queue.dequeue();
emit dispatched(pair.first,pair.second);
}
dispatching = false;
#endif
}
void QASystemDispatcher::loadClass(QString javaClassName)
{
QVariantMap message;
message["className"] = javaClassName;
dispatch("quickandroid.SystemDispatcher.loadClass",message);
}
void QASystemDispatcher::registerNatives()
{
#ifdef Q_OS_ANDROID
QAndroidJniEnvironment env;
jclass clazz = env->FindClass(JCLASS_Name);
if (!clazz)
{
qCritical() << QString("Can't find %1 class").arg(QString(JCLASS_Name));
return ;
}
JNINativeMethod methods[] =
{
{"jniEmit", EMIT_SIGNATURE, (void *)&jniEmit},
};
int numMethods = sizeof(methods) / sizeof(methods[0]);
if (env->RegisterNatives(clazz, methods, numMethods) < 0) {
if (env->ExceptionOccurred()) {
env->ExceptionDescribe();
env->ExceptionClear();
qCritical() << "Exception occurred!!!";
return;
}
}
QAndroidJniObject::callStaticMethod<void>(JCLASS_Name, "init",
"()V");
#endif
}

47
source-android/common/qasystemdispatcher.h

@ -0,0 +1,47 @@
// Author: Ben Lau (https://github.com/benlau)
#pragma once
#include <QObject>
#include <QVariantMap>
/// QASystemDispatcher provides an simple messaging interface between C/C++/QML and Java code.
class QASystemDispatcher : public QObject
{
Q_OBJECT
public:
~QASystemDispatcher();
static QASystemDispatcher* instance();
/// Dispatch a message via Dispatcher
/** The message will be first passed to Java's SystemDispatcher and invoke
* registered listener. Once it is finished, it will emit the
* "dispatched" signal.
*
*/
Q_INVOKABLE void dispatch(QString type , QVariantMap message = QVariantMap());
/// Load a Java class
/** It will dispatch a message to Java and let it to load a Java class. That
* will force to run code in static block.
*
*/
Q_INVOKABLE void loadClass(QString javaClassName);
/// Register JNI native methods. This function must be called in JNI_OnLoad. Otherwise, the messenger will not be working
static void registerNatives();
/// The name of message that will be dispatched during Activity.onActivityResult.
static QString ACTIVITY_RESULT_MESSAGE;
/// The name of message that will be dispatched during Activity.onResume.
static QString ACTIVITY_RESUME_MESSAGE;
signals:
/// The signal is emitted when a message is dispatched.
void dispatched(QString type , QVariantMap message);
public:
explicit QASystemDispatcher(QObject* parent = 0);
};

22
source-android/common/quickandroid.cpp

@ -0,0 +1,22 @@
#include <QtQml>
#include <QVariantMap>
#include "quickandroid.h"
//#include "qadevice.h"
//#include "qamousesensor.h"
#ifdef Q_OS_ANDROID
#include <QAndroidJniEnvironment>
#include <QAndroidJniObject>
#endif
void QuickAndroid::registerTypes()
{
// "A" has been changed to a QML object. So now this function will do nothing.
// Keep here for compatible purpose only.
}
//qreal QuickAndroid::dp()
//{
// return QADevice::readDp();
//}

21
source-android/common/quickandroid.h

@ -0,0 +1,21 @@
#ifndef QUICKANDROID_H
#define QUICKANDROID_H
#include <QtGlobal>
/// Quick Android Context
class QuickAndroid
{
public:
static void registerTypes();
/// Obtain the detected "dp" value.
/** This function has been deprecated. Please use QADevice::dp()
@deprecated.
* @brief dp
* @return The detected "dp" value
*/
static qreal dp();
};
#endif // QUICKANDROID_H

21
source-android/common/xhr.cpp

@ -3,7 +3,10 @@
#include <QHttpPart>
#include <QTextCodec>
#include <QUrlQuery>
#include <QNetworkCookieJar>
#include <QNetworkCookie>
#include <QList>
#include <QDataStream>
#include "uploadableimage.h"
XHR *XHR::instance()
@ -114,7 +117,8 @@ void XHR::get()
QByteArray loginData = m_login.toLocal8Bit().toBase64();
QString headerData = "Basic " + loginData;
request.setRawHeader("Authorization", headerData.toLocal8Bit());
// QNetworkCookieJar* cJar = new QNetworkCookieJar;
// manager.setCookieJar(cJar);
request.setUrl(requrl);
reply = manager.get(request);
@ -184,7 +188,7 @@ void XHR::onReplySuccess()
qDebug() << "!";
emit this->success( bufferToString() );
buffer.clear();
reply->deleteLater();
// reply->deleteLater();
}
void XHR::onRequestFinished()
@ -206,6 +210,15 @@ void XHR::onReadyRead()
{
qDebug() << ".";
buffer += reply->readAll();
// QList<QNetworkCookie> list = manager.cookieJar()->cookiesForUrl(m_url);
// QFile f("/home/pankraz/cookie.txt");
// f.open(QIODevice::ReadWrite);
// for(int i = 0; i < list.size(); ++i){
// QDataStream s(&f);
// s << list.at(i).toRawForm();
// }
// f.close();
}
//void XHR::updateDownloadProgress(qint64 bytesRead, qint64 totalBytes)
@ -227,5 +240,3 @@ QString XHR::bufferToString()
{
return QTextCodec::codecForName("utf-8")->toUnicode(buffer);
}

31
source-android/friendiqa.pro

@ -10,14 +10,20 @@
# - translation filenames have to be changed
# The name of your application
TEMPLATE = app
TARGET = friendiqa
CONFIG += debug
QT += qml quick gui widgets androidextras
include(androidnative.pri/androidnative.pri)
SOURCES += common/friendiqa.cpp \
common/uploadableimage.cpp \
common/xhr.cpp \
common/filesystem.cpp
common/filesystem.cpp \
ANDROID_PACKAGE_SOURCE_DIR = $$PWD/android
RESOURCES = application.qrc
@ -30,18 +36,16 @@ OTHER_FILES += qml/friendiqa.qml \
qml/configqml/*.qml
js/*.js
# German translation is enabled as an example. If you aren't
# planning to localize your app, remember to comment out the
# following TRANSLATIONS line. And also do not forget to
# modify the localized app name in the the .desktop file.
TRANSLATIONS += translations/friendiqa-de.ts \
translations/friendiqa-es.ts
HEADERS += \
common/uploadableimage.h \
common/xhr.h \
common/filesystem.h
common/filesystem.h
DISTFILES += \
qml/calendarqml/*.qml \
android/AndroidManifest.xml \
android/gradle/wrapper/gradle-wrapper.jar \
android/gradlew \
@ -49,8 +53,15 @@ DISTFILES += \
android/build.gradle \
android/gradle/wrapper/gradle-wrapper.properties \
android/gradlew.bat \
translations/friendiqa-es.qm
ANDROID_PACKAGE_SOURCE_DIR = $$PWD/android
translations/*.ts \
qml/*.qml \
qml/newsqml/*.qml \
qml/contactqml/*.qml \
qml/photoqml/*.qml \
qml/configqml/*.qml \
js/*.js \
android/androidnative.gradle \
android/src/FriendiqaActivity.java \
android/src/ExampleService.java

713
source-android/friendiqa.pro.user

@ -0,0 +1,713 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE QtCreatorProject>
<!-- Written by QtCreator 4.4.1, 2017-11-07T21:01:34. -->
<qtcreator>
<data>
<variable>EnvironmentId</variable>
<value type="QByteArray">{8825bc46-5cad-4a59-be78-bf9eeaa7217a}</value>
</data>
<data>
<variable>ProjectExplorer.Project.ActiveTarget</variable>
<value type="int">0</value>
</data>
<data>
<variable>ProjectExplorer.Project.EditorSettings</variable>
<valuemap type="QVariantMap">
<value type="bool" key="EditorConfiguration.AutoIndent">true</value>
<value type="bool" key="EditorConfiguration.AutoSpacesForTabs">false</value>
<value type="bool" key="EditorConfiguration.CamelCaseNavigation">true</value>
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.0">
<value type="QString" key="language">Cpp</value>
<valuemap type="QVariantMap" key="value">
<value type="QByteArray" key="CurrentPreferences">CppGlobal</value>
</valuemap>
</valuemap>
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.1">
<value type="QString" key="language">QmlJS</value>
<valuemap type="QVariantMap" key="value">
<value type="QByteArray" key="CurrentPreferences">QmlJSGlobal</value>
</valuemap>
</valuemap>
<value type="int" key="EditorConfiguration.CodeStyle.Count">2</value>
<value type="QByteArray" key="EditorConfiguration.Codec">UTF-8</value>
<value type="bool" key="EditorConfiguration.ConstrainTooltips">false</value>
<value type="int" key="EditorConfiguration.IndentSize">4</value>
<value type="bool" key="EditorConfiguration.KeyboardTooltips">false</value>
<value type="int" key="EditorConfiguration.MarginColumn">80</value>
<value type="bool" key="EditorConfiguration.MouseHiding">true</value>
<value type="bool" key="EditorConfiguration.MouseNavigation">true</value>
<value type="int" key="EditorConfiguration.PaddingMode">1</value>
<value type="bool" key="EditorConfiguration.ScrollWheelZooming">true</value>
<value type="bool" key="EditorConfiguration.ShowMargin">false</value>
<value type="int" key="EditorConfiguration.SmartBackspaceBehavior">0</value>
<value type="bool" key="EditorConfiguration.SmartSelectionChanging">true</value>
<value type="bool" key="EditorConfiguration.SpacesForTabs">true</value>
<value type="int" key="EditorConfiguration.TabKeyBehavior">0</value>
<value type="int" key="EditorConfiguration.TabSize">8</value>
<value type="bool" key="EditorConfiguration.UseGlobal">true</value>
<value type="int" key="EditorConfiguration.Utf8BomBehavior">1</value>
<value type="bool" key="EditorConfiguration.addFinalNewLine">true</value>
<value type="bool" key="EditorConfiguration.cleanIndentation">true</value>
<value type="bool" key="EditorConfiguration.cleanWhitespace">true</value>
<value type="bool" key="EditorConfiguration.inEntireDocument">false</value>
</valuemap>
</data>
<data>
<variable>ProjectExplorer.Project.PluginSettings</variable>
<valuemap type="QVariantMap">
<valuelist type="QVariantList" key="ClangStaticAnalyzer.SuppressedDiagnostics"/>
</valuemap>
</data>
<data>
<variable>ProjectExplorer.Project.Target.0</variable>
<valuemap type="QVariantMap">
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Android</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Android</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">{8e3757e7-5698-4d0f-9f13-55359b1a832e}</value>
<value type="int" key="ProjectExplorer.Target.ActiveBuildConfiguration">1</value>
<value type="int" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
<value type="int" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0">
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/home/pankraz/build/debug</value>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">qmake</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibrary">true</value>
<value type="QString" key="QtProjectManager.QMakeBuildStep.QMakeArguments"></value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.SeparateDebugInfo">false</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.UseQtQuickCompiler">false</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments">
<value type="QString">-w</value>
<value type="QString">-r</value>
</valuelist>
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">false</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments"></value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.2">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Anwendungsdaten kopieren</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.AndroidPackageInstallationStep</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.3">
<value type="QString" key="BuildTargetSdk">android-25</value>
<value type="QString" key="KeystoreLocation"></value>
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Android-APK erstellen</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QmakeProjectManager.AndroidBuildApkStep</value>
<value type="int" key="Qt4ProjectManager.AndroidDeployQtStep.DeployQtAction">2</value>
<value type="bool" key="UseGradle">true</value>
<value type="bool" key="VerboseOutput">false</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">4</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments">
<value type="QString">-w</value>
<value type="QString">-r</value>
</valuelist>
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">true</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Bereinigen</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Debug</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
<value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">2</value>
<value type="bool" key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild">true</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.1">
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/home/pankraz/build/release</value>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">qmake</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibrary">false</value>
<value type="QString" key="QtProjectManager.QMakeBuildStep.QMakeArguments"></value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.SeparateDebugInfo">false</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.UseQtQuickCompiler">false</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments">
<value type="QString">-w</value>
<value type="QString">-r</value>
</valuelist>
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">false</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments"></value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.2">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Anwendungsdaten kopieren</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.AndroidPackageInstallationStep</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.3">
<value type="QString" key="BuildTargetSdk">android-25</value>
<value type="QString" key="KeystoreLocation">/home/pankraz/ownCloud/clientsync/android_release.keystore</value>
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Android-APK erstellen</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QmakeProjectManager.AndroidBuildApkStep</value>
<value type="int" key="Qt4ProjectManager.AndroidDeployQtStep.DeployQtAction">2</value>
<value type="bool" key="UseGradle">true</value>
<value type="bool" key="VerboseOutput">false</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">4</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments">
<value type="QString">-w</value>
<value type="QString">-r</value>
</valuelist>
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">true</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Bereinigen</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Release</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
<value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">0</value>
<value type="bool" key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild">true</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.2">
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/home/pankraz/build/profile</value>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">qmake</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibrary">true</value>
<value type="QString" key="QtProjectManager.QMakeBuildStep.QMakeArguments"></value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.SeparateDebugInfo">true</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.UseQtQuickCompiler">false</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments">
<value type="QString">-w</value>
<value type="QString">-r</value>
</valuelist>
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">false</value>