Version 0.002 with working FriendsTabView

This commit is contained in:
LubuWest 2016-10-19 21:37:26 +02:00
parent bc4adba50c
commit 42de63fe63
77 changed files with 6830 additions and 387 deletions

View File

@ -1,387 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE QtCreatorProject>
<!-- Written by QtCreator 4.1.0, 2016-09-26T21:14:21. -->
<qtcreator>
<data>
<variable>EnvironmentId</variable>
<value type="QByteArray">{feb2a9e8-6b42-4908-9ecd-b9e4d47e7412}</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"/>
</data>
<data>
<variable>ProjectExplorer.Project.Target.0</variable>
<valuemap type="QVariantMap">
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Android für armeabi-v7a (GCC 4.9, Qt 5.5.1)</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Android für armeabi-v7a (GCC 4.9, Qt 5.5.1)</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">{10172d6f-97b2-4745-a95e-fc1020afb172}</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/bin</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-18</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">false</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/ownCloud/clientsync/Friendiqa/v0.001/bin</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-18</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">false</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/ownCloud/clientsync/Friendiqa/v0.001/build-friendiqa-Android_f_r_armeabi_v7a_GCC_4_9_Qt_5_5_1-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>
<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-23</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">false</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">Profile</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>
<value type="int" key="ProjectExplorer.Target.BuildConfigurationCount">3</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
<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">Deployment auf Android-Gerät</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.AndroidDeployQtStep</value>
<value type="bool" key="UninstallPreviousPackage">true</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deployment</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deployment auf Android-Gerät</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Deployment auf Android-Gerät</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.AndroidDeployConfiguration2</value>
</valuemap>
<value type="int" key="ProjectExplorer.Target.DeployConfigurationCount">1</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.PluginSettings"/>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
<value type="bool" key="Analyzer.QmlProfiler.AggregateTraces">false</value>
<value type="bool" key="Analyzer.QmlProfiler.FlushEnabled">false</value>
<value type="uint" key="Analyzer.QmlProfiler.FlushInterval">1000</value>
<value type="QString" key="Analyzer.QmlProfiler.LastTraceFile"></value>
<value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
<valuelist type="QVariantList" key="Analyzer.Valgrind.AddedSuppressionFiles"/>
<value type="bool" key="Analyzer.Valgrind.Callgrind.CollectBusEvents">false</value>
<value type="bool" key="Analyzer.Valgrind.Callgrind.CollectSystime">false</value>
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableBranchSim">false</value>
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableCacheSim">false</value>
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableEventToolTips">true</value>
<value type="double" key="Analyzer.Valgrind.Callgrind.MinimumCostRatio">0.01</value>
<value type="double" key="Analyzer.Valgrind.Callgrind.VisualisationMinimumCostRatio">10</value>
<value type="bool" key="Analyzer.Valgrind.FilterExternalIssues">true</value>
<value type="int" key="Analyzer.Valgrind.LeakCheckOnFinish">1</value>
<value type="int" key="Analyzer.Valgrind.NumCallers">25</value>
<valuelist type="QVariantList" key="Analyzer.Valgrind.RemovedSuppressionFiles"/>
<value type="int" key="Analyzer.Valgrind.SelfModifyingCodeDetection">1</value>
<value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
<value type="bool" key="Analyzer.Valgrind.ShowReachable">false</value>
<value type="bool" key="Analyzer.Valgrind.TrackOrigins">true</value>
<value type="QString" key="Analyzer.Valgrind.ValgrindExecutable">valgrind</value>
<valuelist type="QVariantList" key="Analyzer.Valgrind.VisibleErrorKinds">
<value type="int">0</value>
<value type="int">1</value>
<value type="int">2</value>
<value type="int">3</value>
<value type="int">4</value>
<value type="int">5</value>
<value type="int">6</value>
<value type="int">7</value>
<value type="int">8</value>
<value type="int">9</value>
<value type="int">10</value>
<value type="int">11</value>
<value type="int">12</value>
<value type="int">13</value>
<value type="int">14</value>
</valuelist>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">friendiqa</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.AndroidRunConfiguration:/home/pankraz/ownCloud/clientsync/Friendiqa/v0.001/source-android/friendiqa.pro</value>
<value type="QString" key="QMakeProjectManager.QmakeAndroidRunConfiguration.ProFile">friendiqa.pro</value>
<value type="uint" key="RunConfiguration.QmlDebugServerPort">3768</value>
<value type="bool" key="RunConfiguration.UseCppDebugger">false</value>
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
<value type="bool" key="RunConfiguration.UseMultiProcess">false</value>
<value type="bool" key="RunConfiguration.UseQmlDebugger">false</value>
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
</valuemap>
<value type="int" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
</valuemap>
</data>
<data>
<variable>ProjectExplorer.Project.TargetCount</variable>
<value type="int">1</value>
</data>
<data>
<variable>ProjectExplorer.Project.Updater.FileVersion</variable>
<value type="int">18</value>
</data>
<data>
<variable>Version</variable>
<value type="int">18</value>
</data>
</qtcreator>

Binary file not shown.

View File

@ -0,0 +1,56 @@
<?xml version="1.0"?>
<manifest package="org.qtproject.friendiqa" xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="0.001" android:versionCode="1" android:installLocation="auto">
<application android:hardwareAccelerated="true" android:name="org.qtproject.qt5.android.bindings.QtApplication" android:label="Friendiqa" android:icon="@drawable/icon">
<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">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
<meta-data android:name="android.app.lib_name" android:value="friendiqa"/>
<meta-data android:name="android.app.qt_sources_resource_id" android:resource="@array/qt_sources"/>
<meta-data android:name="android.app.repository" android:value="default"/>
<meta-data android:name="android.app.qt_libs_resource_id" android:resource="@array/qt_libs"/>
<meta-data android:name="android.app.bundled_libs_resource_id" android:resource="@array/bundled_libs"/>
<!-- Deploy Qt libs as part of package -->
<meta-data android:name="android.app.bundle_local_qt_libs" android:value="-- %%BUNDLE_LOCAL_QT_LIBS%% --"/>
<meta-data android:name="android.app.bundled_in_lib_resource_id" android:resource="@array/bundled_in_lib"/>
<meta-data android:name="android.app.bundled_in_assets_resource_id" android:resource="@array/bundled_in_assets"/>
<!-- Run with local libs -->
<meta-data android:name="android.app.use_local_qt_libs" android:value="-- %%USE_LOCAL_QT_LIBS%% --"/>
<meta-data android:name="android.app.libs_prefix" android:value="/data/local/tmp/qt/"/>
<meta-data android:name="android.app.load_local_libs" android:value="-- %%INSERT_LOCAL_LIBS%% --"/>
<meta-data android:name="android.app.load_local_jars" android:value="-- %%INSERT_LOCAL_JARS%% --"/>
<meta-data android:name="android.app.static_init_classes" android:value="-- %%INSERT_INIT_CLASSES%% --"/>
<!-- Messages maps -->
<meta-data android:value="@string/ministro_not_found_msg" android:name="android.app.ministro_not_found_msg"/>
<meta-data android:value="@string/ministro_needed_msg" android:name="android.app.ministro_needed_msg"/>
<meta-data android:value="@string/fatal_error_msg" android:name="android.app.fatal_error_msg"/>
<!-- Messages maps -->
<!-- Splash screen -->
<!--
<meta-data android:name="android.app.splash_screen_drawable" android:resource="@drawable/logo"/>
-->
<!-- Splash screen -->
<!-- Background running -->
<!-- Warning: changing this value to true may cause unexpected crashes if the
application still try to draw after
"applicationStateChanged(Qt::ApplicationSuspended)"
signal is sent! -->
<meta-data android:name="android.app.background_running" android:value="false"/>
<!-- Background running -->
</activity>
</application>
<uses-sdk android:minSdkVersion="18" android:targetSdkVersion="22"/>
<supports-screens android:largeScreens="true" android:normalScreens="true" android:anyDensity="true" android:smallScreens="true"/>
<!-- The following comment will be replaced upon deployment with default permissions based on the dependencies of the application.
Remove the comment if you do not require these default permissions. -->
<!-- %%INSERT_PERMISSIONS -->
<!-- The following comment will be replaced upon deployment with default features based on the dependencies of the application.
Remove the comment if you do not require these default features. -->
<!-- %%INSERT_FEATURES -->
</manifest>

View File

@ -0,0 +1,57 @@
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:1.1.0'
}
}
allprojects {
repositories {
jcenter()
}
}
apply plugin: 'com.android.application'
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
}
android {
/*******************************************************
* The following variables:
* - androidBuildToolsVersion,
* - androidCompileSdkVersion
* - qt5AndroidDir - holds the path to qt android files
* needed to build any Qt application
* on Android.
*
* are defined in gradle.properties file. This file is
* updated by QtCreator and androiddeployqt tools.
* Changing them manually might break the compilation!
*******************************************************/
compileSdkVersion androidCompileSdkVersion.toInteger()
buildToolsVersion androidBuildToolsVersion
sourceSets {
main {
manifest.srcFile 'AndroidManifest.xml'
java.srcDirs = [qt5AndroidDir + '/src', 'src', 'java']
aidl.srcDirs = [qt5AndroidDir + '/src', 'src', 'aidl']
res.srcDirs = [qt5AndroidDir + '/res', 'res']
resources.srcDirs = ['src']
renderscript.srcDirs = ['src']
assets.srcDirs = ['assets']
jniLibs.srcDirs = ['libs']
}
}
lintOptions {
abortOnError false
}
}

View File

@ -0,0 +1,9 @@
## This file is automatically generated by QtCreator.
#
# This file must *NOT* be checked into Version Control Systems,
# as it contains information specific to your local configuration.
androidBuildToolsVersion=23.0.2
androidCompileSdkVersion=18
buildDir=.build
qt5AndroidDir=/home/pankraz/bin/Qt5.5.1/5.5/android_armv7/src/android/java

View File

@ -0,0 +1,6 @@
#Wed Apr 10 15:27:10 PDT 2013
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=http\://services.gradle.org/distributions/gradle-1.12-all.zip

View File

@ -0,0 +1,164 @@
#!/usr/bin/env bash
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn ( ) {
echo "$*"
}
die ( ) {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
esac
# For Cygwin, ensure paths are in UNIX format before anything is touched.
if $cygwin ; then
[ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
fi
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >&-
APP_HOME="`pwd -P`"
cd "$SAVED" >&-
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
function splitJvmOpts() {
JVM_OPTS=("$@")
}
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"

View File

@ -0,0 +1,90 @@
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windowz variants
if not "%OS%" == "Windows_NT" goto win9xME_args
if "%@eval[2+2]" == "4" goto 4NT_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
goto execute
:4NT_args
@rem Get arguments from the 4NT Shell from JP Software
set CMD_LINE_ARGS=%$
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

View File

@ -0,0 +1,6 @@
## This file is automatically generated by QtCreator.
#
# This file must *NOT* be checked into Version Control Systems,
# as it contains information specific to your local configuration.
sdk.dir=/opt/android-sdk

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -0,0 +1,25 @@
<?xml version='1.0' encoding='utf-8'?>
<resources>
<array name="qt_sources">
<item>https://download.qt-project.org/ministro/android/qt5/qt-5.4</item>
</array>
<!-- The following is handled automatically by the deployment tool. It should
not be edited manually. -->
<array name="bundled_libs">
<!-- %%INSERT_EXTRA_LIBS%% -->
</array>
<array name="qt_libs">
<!-- %%INSERT_QT_LIBS%% -->
</array>
<array name="bundled_in_lib">
<!-- %%INSERT_BUNDLED_IN_LIB%% -->
</array>
<array name="bundled_in_assets">
<!-- %%INSERT_BUNDLED_IN_ASSETS%% -->
</array>
</resources>

View File

@ -0,0 +1,24 @@
<RCC>
<qresource prefix="/">
<file>js/layout.js</file>
<file>js/photoworker.js</file>
<file>js/service.js</file>
<file>qml/FriendComponent.qml</file>
<file>qml/MessageSend.qml</file>
<file>qml/Newsitem.qml</file>
<file>qml/PhotoComponent.qml</file>
<file>qml/PhotogroupComponent.qml</file>
<file>qml/PhotoPlaceholder.qml</file>
<file>qml/friendiqa.qml</file>
<file>qml/PhotoTab.qml</file>
<file>qml/ConfigTab.qml</file>
<file>qml/FriendsTab.qml</file>
<file>qml/NewsTab.qml</file>
<file>js/news.js</file>
<file>js/newsworker.js</file>
<file>js/helper.js</file>
<file>images/defaultcontact.jpg</file>
<file>qml/InfoBox.qml</file>
<file>qml/GroupComponent.qml</file>
</qresource>
</RCC>

View File

@ -0,0 +1,49 @@
#include "filesystem.h"
FILESYSTEM *FILESYSTEM::instance()
{
static FILESYSTEM filesystem;
return &filesystem;
}
FILESYSTEM::FILESYSTEM(QObject *parent) : QObject(parent){}
void FILESYSTEM::setDirectory(QString Directory)
{
if (Directory!=m_Directory) {
m_Directory = Directory;
emit directoryChanged();
}
}
QString FILESYSTEM::Directory() const
{
return m_Directory;
}
void FILESYSTEM::makeDir(QString name)
{
QDir dir(m_Directory);
if (dir.mkdir(name)){
emit success(name);
}
else {emit error(name,1);}
}
void FILESYSTEM::rmDir(QString name)
{
QDir dir(m_Directory);
if (dir.rmdir(name)){
emit success(name);
}
else {emit error(name,1);}
}
void FILESYSTEM::rmFile(QString name)
{
QDir dir(m_Directory);
if(dir.remove(name)){
emit success(name);
}
else {emit error(name,1);}
}

View File

@ -0,0 +1,49 @@
#ifndef FILESYSTEM_H
#define FILESYSTEM_H
#include <QDir>
#include <QObject>
class FILESYSTEM : public QObject
{
Q_OBJECT
Q_PROPERTY(QString Directory READ Directory WRITE setDirectory NOTIFY directoryChanged)
public:
static FILESYSTEM *instance();
explicit FILESYSTEM(QObject *parent = 0);
void setDirectory(QString Directory);
QString Directory() const;
signals:
void directoryChanged();
void success(QString data);
void error(QString data, int code);
public slots:
//void setDirectory(QString Directory);
void makeDir(QString name);
void rmDir(QString name);
void rmFile(QString name);
private slots:
//void onReplyError(QNetworkReply::NetworkError code);
// void onReplySuccess();
//void onReadyRead();
// void onSSLError(const QList<QSslError> &errors);
private:
//QByteArray buffer;
QString m_Directory;
//QString m_login;
//QHash<QString, QString> params;
//QHash<QString, QString> files;
//QNetworkAccessManager manager;
//QNetworkRequest request;
//QNetworkReply *reply;
//QString bufferToString();
};
#endif // FILSYSTEM_H

View File

@ -0,0 +1,22 @@
#include <QApplication>
#include <QtQml/QQmlEngine>
#include <QtQuick>
#include "xhr.h"
#include "filesystem.h"
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
QQuickView view;
XHR* xhr = XHR::instance();
view.rootContext()->setContextProperty("xhr", xhr);
FILESYSTEM* filesystem = FILESYSTEM::instance();
view.rootContext()->setContextProperty("filesystem", filesystem);
view.setSource(QUrl("qrc:/qml/friendiqa.qml"));
view.show();
view.connect(view.rootContext()->engine(), SIGNAL(quit()), &app, SLOT(quit()));
return app.exec();
}

View File

@ -0,0 +1,90 @@
#include "uploadableimage.h"
#include <QBuffer>
#include <QDebug>
#include <QFileInfo>
#include <QUrl>
void UploadableImage::setSource(const QString &a) {
if (a != m_source) {
m_source = a;
//m_base64 = "";
m_mimetype = "";
m_filename = "";
qDebug() << "UploadableImage::setSource : " << m_source;
if (m_source=="") {
emit sourceChanged();
//emit base64Changed();
emit mimetypeChanged();
emit filenameChanged();
return;
}
QImage fullimage = QImage(QUrl(m_source).toLocalFile());
if (fullimage.width() > 800 || fullimage.height() > 800) {
if (fullimage.width() > fullimage.height()) {
m_image = fullimage.scaledToWidth(800);
} else {
m_image = fullimage.scaledToHeight(800);
}
} else {
m_image = fullimage;
}
qDebug() << "UploadableImage::setSource : " << m_image.width() << "x" << m_image.height();
emit sourceChanged();
QFileInfo fi(m_source);
m_filename = fi.fileName();
emit filenameChanged();
QString filetype = fi.suffix().toUpper();
if (filetype!="PNG" && filetype!="JPG") {
filetype = "JPG";
}
qDebug() << "UploadableImage::setSource : " << "Saving as " << filetype;
m_mimetype = "image/"+filetype.toLower();
emit mimetypeChanged();
/*
QByteArray byteArray;
QBuffer buffer(&byteArray);
m_image.save(&buffer, filetype.toLatin1().constData());
QString b64 = QString::fromLatin1(byteArray.toBase64().data());
for(int k=0; k<b64.length(); k+=76) {
m_base64 += b64.mid(k,76) + "\n";
}
m_base64 = m_base64.trimmed();
emit base64Changed();
*/
}
}
QString UploadableImage::source() const {
return m_source;
}
//QString UploadableImage::base64() const {
// return m_base64;
//}
QString UploadableImage::filename() const {
return m_filename;
}
QString UploadableImage::mimetype() const {
return m_mimetype;
}
QByteArray UploadableImage::bytes() {
QByteArray byteArray;
QBuffer buffer(&byteArray);
m_image.save(&buffer, "PNG");
return byteArray;
}

View File

@ -0,0 +1,40 @@
#ifndef UPLOADABLEIMAGE_H
#define UPLOADABLEIMAGE_H
#include <QObject>
#include <QQuickItem>
#include <QImage>
class UploadableImage : public QObject
{
Q_OBJECT
Q_PROPERTY(QString source READ source WRITE setSource NOTIFY sourceChanged)
//Q_PROPERTY(QString base64 READ base64 NOTIFY base64Changed)
Q_PROPERTY(QString filename READ filename NOTIFY filenameChanged)
Q_PROPERTY(QString mimetype READ mimetype NOTIFY mimetypeChanged)
Q_PROPERTY(QByteArray bytes READ bytes)
public:
void setSource(const QString &a);
QString source() const;
//QString base64() const;
QString filename() const;
QString mimetype() const;
QByteArray bytes();
signals:
void sourceChanged();
//void base64Changed();
void filenameChanged();
void mimetypeChanged();
private:
QString m_source;
QImage m_image;
//QString m_base64;
QString m_filename;
QString m_mimetype;
};
#endif // UPLOADABLEIMAGE_H

View File

@ -0,0 +1,168 @@
#include "xhr.h"
#include <QHttpPart>
#include <QTextCodec>
#include <QUrlQuery>
#include "uploadableimage.h"
XHR *XHR::instance()
{
static XHR xhr;
return &xhr;
}
XHR::XHR(QObject *parent) : QObject(parent)
{
request.setSslConfiguration(QSslConfiguration::defaultConfiguration());
}
void XHR::setUrl(QString url)
{
if (url!=m_url) {
m_url = url;
emit urlChanged();
}
}
void XHR::setLogin(QString login)
{
if (login!=m_login) {
m_login = login;
emit loginChanged();
}
}
QString XHR::url() const
{
return m_url;
}
QString XHR::login() const
{
return m_login;
}
void XHR::setParam(QString name, QString value)
{
params.insert(name, value);
}
void XHR::setImageFileParam(QString name, QString url)
{
files.insert(name, url);
}
void XHR::clearParams()
{
files.clear();
params.clear();
}
void XHR::get()
{
QUrlQuery query;
QHashIterator<QString, QString> i(params);
while(i.hasNext()) {
i.next();
query.addQueryItem(i.key(), i.value());
}
QUrl requrl(m_url);
requrl.setQuery(query);
QByteArray loginData = m_login.toLocal8Bit().toBase64();
QString headerData = "Basic " + loginData;
request.setRawHeader("Authorization", headerData.toLocal8Bit());
request.setUrl(requrl);
reply = manager.get(request);
connect(reply, &QNetworkReply::finished, this, &XHR::onReplySuccess);
connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(onReplyError(QNetworkReply::NetworkError)));
connect(reply, &QNetworkReply::readyRead, this, &XHR::onReadyRead);
}
void XHR::post()
{
qDebug() << "start post to " << m_url;
QHttpMultiPart *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);
QHashIterator<QString, QString> iparams(params);
while(iparams.hasNext()) {
iparams.next();
qDebug() << "\t add param " << iparams.key() << " : " << iparams.value();
QHttpPart textPart;
textPart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"" + iparams.key() + "\""));
textPart.setBody(iparams.value().toUtf8());
multiPart->append(textPart);
}
UploadableImage uimg;
QHashIterator<QString, QString> ifiles(files);
while(ifiles.hasNext()) {
ifiles.next();
uimg.setSource(ifiles.value());
qDebug() << "\t image: " << uimg.mimetype() << ", " << ifiles.key();
QHttpPart imagePart;
imagePart.setHeader(QNetworkRequest::ContentTypeHeader, QVariant(uimg.mimetype()));
imagePart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"" + ifiles.key() + "\"; filename=\""+uimg.filename()+"\""));
imagePart.setBody(uimg.bytes());
multiPart->append(imagePart);
}
QByteArray loginData = m_login.toLocal8Bit().toBase64();
QString headerData = "Basic " + loginData;
request.setRawHeader(QByteArray("Authorization"), headerData.toLocal8Bit());
request.setUrl(m_url);
reply = manager.post(request, multiPart);
qDebug() << "\t request sent";
connect(reply, &QNetworkReply::finished, this, &XHR::onReplySuccess);
connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(onReplyError(QNetworkReply::NetworkError)));
connect(reply, &QNetworkReply::readyRead, this, &XHR::onReadyRead);
connect(reply, &QNetworkReply::sslErrors, this, &XHR::onSSLError);
qDebug() << "\t reply signals connected";
}
void XHR::onReplyError(QNetworkReply::NetworkError code)
{
qDebug() << code;
emit this->error( bufferToString(), (int) code);
reply->deleteLater();
}
void XHR::onReplySuccess()
{
qDebug() << "!";
emit this->success( bufferToString() );
reply->deleteLater();
}
void XHR::onReadyRead()
{
qDebug() << ".";
buffer += reply->readAll();
}
void XHR::onSSLError(const QList<QSslError> &errors)
{
qDebug() << "XHR::onSSLError :" ;
QListIterator<QSslError> ierrs(errors);
while(ierrs.hasNext()) {
qDebug() << "\t" << ierrs.next().errorString();
}
}
QString XHR::bufferToString()
{
return QTextCodec::codecForName("utf-8")->toUnicode(buffer);
}

View File

@ -0,0 +1,60 @@
#ifndef XHR_H
#define XHR_H
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QNetworkRequest>
#include <QObject>
class XHR : public QObject
{
Q_OBJECT
Q_PROPERTY(QString url READ url WRITE setUrl NOTIFY urlChanged)
Q_PROPERTY(QString login READ login WRITE setLogin NOTIFY loginChanged)
public:
static XHR *instance();
explicit XHR(QObject *parent = 0);
void setUrl(QString url);
// void setLogin(QString login);
QString url() const;
QString login() const;
signals:
void urlChanged();
void loginChanged();
void success(QString data);
void error(QString data, int code);
public slots:
void setLogin(QString login);
void setParam(QString name, QString value);
void setImageFileParam(QString name, QString url);
void clearParams();
void post();
void get();
private slots:
void onReplyError(QNetworkReply::NetworkError code);
void onReplySuccess();
void onReadyRead();
void onSSLError(const QList<QSslError> &errors);
private:
QByteArray buffer;
QString m_url;
QString m_login;
QHash<QString, QString> params;
QHash<QString, QString> files;
QNetworkAccessManager manager;
QNetworkRequest request;
QNetworkReply *reply;
QString bufferToString();
};
#endif // XHR_H

View File

@ -0,0 +1,40 @@
# NOTICE:
#
# Application name defined in TARGET has a corresponding QML filename.
# If name defined in TARGET is changed, the following needs to be done
# to match new name:
# - corresponding QML filename must be changed
# - desktop icon filename must be changed
# - desktop filename must be changed
# - icon definition filename in desktop file must be changed
# - translation filenames have to be changed
# The name of your application
TARGET = friendiqa
CONFIG += debug
QT += qml quick gui widgets
SOURCES += common/friendiqa.cpp \
common/uploadableimage.cpp \
common/xhr.cpp \
common/filesystem.cpp
RESOURCES = application.qrc
OTHER_FILES += qml/friendiqa.qml \
translations/*.ts \
qml/*.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
HEADERS += \
common/uploadableimage.h \
common/xhr.h \
common/filesystem.h

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -0,0 +1,12 @@
WorkerScript.onMessage = function(msg) {
msg.model.clear();
for (var j=0;j<msg.albums.length;j++){
if (msg.albums[j]) {
var albumobject=msg.albums[j];
var data=({"albumobject": albumobject,"foreignPicture": msg.foreignPicture})}
// print("Albums:"+j+msg.albums.length+JSON.stringify(data));
msg.model.append(data);}
if (j==msg.albums.length){
msg.model.sync()
};
}

View File

@ -0,0 +1,111 @@
.pragma library
.import QtQuick.LocalStorage 2.0 as Sql
function friendicaRequest(login,api,rootwindow,callback) {
var xhrequest= new XMLHttpRequest();
xhrequest.onreadystatechange = function() {
if (xhrequest.readyState === XMLHttpRequest.HEADERS_RECEIVED) {
} else if(xhrequest.readyState === XMLHttpRequest.DONE) {
try{ if (xhrequest.responseText!=""){
callback(xhrequest.responseText)
}else{
showMessage("Error",api+" NO RESPONSE",rootwindow)
callback(xhrequest.responseText)
}
}
catch (e){
showMessage("Error", api+" "+e,rootwindow)
}
}
}
xhrequest.open("GET", login.server+api,true,login.username,Qt.atob(login.password));
xhrequest.send();
}
function friendicaPostRequest(login,api,rootwindow,callback) {
var xhrequest= new XMLHttpRequest();
xhrequest.onreadystatechange = function() {
if (xhrequest.readyState === XMLHttpRequest.HEADERS_RECEIVED) {
} else if(xhrequest.readyState === XMLHttpRequest.DONE) {
try{ if (xhrequest.responseText!=""){
callback(xhrequest.responseText)
}else{
showMessage("Error",api+" NO RESPONSE",rootwindow)
callback(xhrequest.responseText)
}
}
catch (e){
showMessage("Error", api+" "+e,rootwindow)
}
}
}
xhrequest.open("POST", login.server+api,true,login.username,Qt.atob(login.password));
xhrequest.send();
}
function friendicaWebRequest(url,rootwindow,callback) {
var xhrequest = new XMLHttpRequest();
xhrequest.onreadystatechange = function() {
if (xhrequest.readyState === XMLHttpRequest.HEADERS_RECEIVED) {
} else if(xhrequest.readyState === XMLHttpRequest.DONE) {
try{ callback(xhrequest.responseText);
}
catch (e){
showMessage("Error",url+" "+e, rootwindow)
}
}
}
xhrequest.open("GET", url,true);
xhrequest.send();
}
function readData(database,table,username,callback,filter,filtervalue) { // reads and applies data from DB
if (filter){
var where = " AND "+ filter +" = '" + filtervalue+"'";
} else { var where="";}
var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
if(!db) { return; }
db.transaction( function(tx) {
// print('select * from '+table'+where username= "'+username+'"'+'where);
var rsArray=[];
var rs = tx.executeSql('select * from '+table+' where username= "'+username+'"'+where);
for(var i = 0; i < rs.rows.length; i++) {
rsArray.push(rs.rows.item(i))
}
callback(rsArray);
});
}
function readField(field,database,table, username, callback,filter,filtervalue) { // reads and applies data from DB
if (filter){
var where = " AND "+ filter +" = '" + filtervalue+"'";
} else { var where="";}
var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
if(!db) { return; }
db.transaction( function(tx) {
// print('... read from database ' + field)
var rsArray=[];
print('select DISTINCT '+field+' from '+table+' WHERE username="'+username+'"'+where+' ORDER BY '+field+' ASC');
var rs = tx.executeSql('select DISTINCT '+field+' from '+table+' WHERE username="'+username+'"'+where+' ORDER BY '+field+' ASC');
for(var i = 0; i < rs.rows.length; i++) {
rsArray.push(rs.rows.item(i)[field])
}
callback(rsArray);
});
}
function showMessage(header,message,rootwindow){
var messageString='import QtQuick 2.0; import QtQuick.Dialogs 1.2; MessageDialog{ visible: true; title:"'+header+'";standardButtons: StandardButton.Ok; text:" '+message+'"}';
var messageObject=Qt.createQmlObject(messageString,rootwindow,"messageOutput");
}
function inArray(list, prop, val) {
if (list.length > 0 ) {
for (var i in list) { if (list[i][prop] === val) {
return i;
}
}
} return -1;
}

View File

@ -0,0 +1,44 @@
function showFriends(db) {
Service.readActiveConfig(db,function(login){
Service.requestFriends(login.url,login.user,login.password,displayFriends);
});
}
function displayFriends(obj){
for (var i=0; i<obj.length; i++){
print(obj[i]);
if (obj[i]) {friendsModel.append({"friendName": obj[i]});
};
}}
function ensureVisibility(c,f)
{
if (f.contentX >= c.x)
f.contentX = c.x;
else if (f.contentX+f.width <= c.x+c.width)
f.contentX = c.x+c.width-f.width;
if (f.contentY >= c.y)
f.contentY = c.y;
else if (f.contentY+f.height <= c.y+c.height)
f.contentY = c.y+c.height-f.height;
}
function createObject(objectQml,qmlParameters,parentitem,callback) {
var component = Qt.createComponent(objectQml);
if (component.status === Component.Ready || component.status === Component.Error)
finishCreation(component,qmlParameters,parentitem,callback);
else
component.statusChanged.connect(finishCreation(qmlParameters));
}
function finishCreation(component,qmlParameters,parentitem,callback) {
if (component.status === Component.Ready) {
var createdObject = component.createObject(parentitem, qmlParameters);
if (createdObject === null)
print("Error creating image"); }
else if (component.status === Component.Error)
print("Error loading component:"+component.errorString());
else {print("created")}
callback(createdObject);
}

View File

@ -0,0 +1,311 @@
.pragma library
.import QtQuick.LocalStorage 2.0 as Sql
.import "qrc:/js/helper.js" as Helperjs
function requestFriends(login,database,rootwindow,callback){
// return array of friends
Helperjs.friendicaRequest(login,"/api/statuses/friends", rootwindow,function (obj){
var friends=JSON.parse(obj);
for (var i=0;i<friends.length;i++){ friends[i].isFriend=1}
callback(friends)
});
}
function requestGroups(login,database,rootwindow,callback){
// retrieve, save and return groups, currently not implemented
var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
Helperjs.friendicaRequest(login,"/api/friendica/group_show",rootwindow, function (obj){
var groups=JSON.parse(obj);
for (var i=0;i<groups.length;i++){
var memberarray=[]; for (var user in groups[i].user){memberarray.push(parseInt(groups[i].user[user].id))}
//print("Members: "+groups[i].user)
//updateGroupInDB(login,database,groups[i])
db.transaction( function(tx) {
var result = tx.executeSql('SELECT * from groups where username="'+login.username+'" AND gid = "'+groups[i].gid+'"'); // check for group id
if(result.rows.length === 1) {// use update
print(groups[i].gid +' exists, update it')
result = tx.executeSql('UPDATE groups SET username="'+login.username+'", groupname="'+groups[i].name+'", members="'+JSON.stringify(memberarray)+'"');
} else {// use insert
result = tx.executeSql('INSERT INTO groups VALUES (?,?,?,?)', [login.username,groups[i].name,groups[i].gid,JSON.stringify(memberarray)])}
});
}
//Helperjs.readData(database,"groups",login.username,callback)
callback()
});}
function getFriendsTimeline(login,database,contacts,rootwindow,callback){// retrieve and return timeline since last news, return contacts which are not friends for update (friends can be updated in Friendstab)
var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
var parameter = "";
db.transaction( function(tx) {
var result = tx.executeSql('SELECT status_id from news WHERE username="'+login.username+'" ORDER BY status_id DESC LIMIT 1'); // check for last news id
try{parameter="&since_id="+result.rows.item(0).status_id;}catch(e){};})
var newContacts=[];
Helperjs.friendicaRequest(login,"/api/statuses/friends_timeline"+parameter, rootwindow,function (obj){
var news=JSON.parse(obj);
for (var i=0;i<news.length;i++){
if(contacts.indexOf(news[i].user.id)==-1 && !(inArray(newContacts,"id",news[i].user.id))){
news[i].user.isFriend=0;
newContacts.push(news[i].user);
}
if (news[i].friendica_activities.like.length>0){
print("Like Contact"+JSON.stringify(news[i].friendica_activities.like));
for (var j=0;j<news[i].friendica_activities.like.length;j++){
if(contacts.indexOf(news[i].friendica_activities.like[j].id)==-1 && !(inArray(newContacts,"id",news[i].friendica_activities.like[j].id))){
news[i].friendica_activities.like[j].isFriend=0;
newContacts.push(news[i].friendica_activities.like[j]);
}
}
}
if (news[i].friendica_activities.dislike.length>0){
print("DisLike Contact"+JSON.stringify(news[i].friendica_activities.dislike));
for (var k=0;j<news[k].friendica_activities.dislike.length;k++){
if(contacts.indexOf(news[i].friendica_activities.dislike[k].id)==-1 && !(inArray(newContacts,"id",news[i].friendica_activties.dislike[k].id))){
news[i].friendica_activities.dislike[k].isFriend=0;
newContacts.push(news[i].friendica_activities.dislike[k]);
}
}
}
}
callback(news,newContacts)
})}
function storeNews(login,database,news,rootwindow,callback){
// save news after contacts download, call next function
var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
for (var i=0;i<news.length;i++){
print('store news data for ' + news[i].id+JSON.stringify(news[i].friendica_activities));
var ausdruck=news[i];
var likearray=[]; for (var user in news[i].friendica_activities.like){likearray.push(parseInt(news[i].friendica_activities.like[user].id))}
var dislikearray=[]; for (var user in news[i].friendica_activities.dislike){parseInt(news[i].friendica_activities.dislike[user].id)}
var attendyesarray=[]; for (var user in news[i].friendica_activities.attendyes){attendyesarray.push(parseInt(news[i].friendica_activities.attendyes[user].id))}
var attendnoarray=[]; for (var user in news[i].friendica_activities.attendno){attendnoarray.push(parseInt(news[i].friendica_activities.attendno[user].id))}
var attendmaybearray=[]; for (var user in news[i].friendica_activities.attendmaybe){attendmaybearray.push(parseInt(news[i].friendica_activities.attendmaybe[user].id))}
db.transaction( function(tx) {
var result = tx.executeSql('SELECT * from news where status_id = "'+news[i].id+'"'); // check for news id
if(result.rows.length === 1) {// use update
print(news[i].id +' exists, update it')
result = tx.executeSql('UPDATE news SET username="'+login.username+'", messagetype=0, text="'+Qt.btoa(news[i].text)+'", created_at="'+Date.parse(cleanDate(news[i].created_at))+'", in_reply_to_status_id="'+news[i].in_reply_to_status_id+'", source="'+news[i].source+'", status_id="'+news[i].id+'", in_reply_to_user_id="'+news[i].in_reply_to_user_id+'", geo="'+news[i].geo+'", favorited="'+news[i].favorited+'", uid="'+news[i].user.id+'", statusnet_html="'+Qt.btoa(news[i].status_html)+'", statusnet_conversation_id="'+news[i].statusnet_conversation_id+'",like="'+JSON.stringify(likearray)+'", dislike="'+JSON.stringify(dislikearray)+'", attendyes="'+JSON.stringify(attendyesarray)+'",attendno="'+JSON.stringify(attendnoarray)+'",attendmaybe="'+JSON.stringify(attendmaybearray)+'" where status_id="'+news[i].status_id+'"');
} else {// use insert
result = tx.executeSql('INSERT INTO news (username,messagetype,text,created_at,in_reply_to_status_id,source,status_id,in_reply_to_user_id,geo,favorited,uid,statusnet_html,statusnet_conversation_id,like,dislike,attendyes,attendno,attendmaybe) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)', [login.username,0,Qt.btoa(news[i].text),Date.parse(cleanDate(news[i].created_at)), news[i].in_reply_to_status_id, news[i].source, news[i].id,news[i].in_reply_to_user_id,news[i].geo,news[i].favorited, news[i].user.id,Qt.btoa(news[i].statusnet_html),news[i].statusnet_conversation_id, JSON.stringify(likearray),JSON.stringify(dislikearray),JSON.stringify(attendyesarray),JSON.stringify(attendnoarray),JSON.stringify(attendmaybearray)])}})
}
getDirectMessage(login,database,rootwindow,callback)
}
function getDirectMessage(login,database,rootwindow,callback){
var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
Helperjs.friendicaRequest(login,"/api/direct_messages/all",rootwindow, function (obj){
var messages=JSON.parse(obj);
for (var i=0;i<messages.length;i++){
// print('store message data for '+JSON.stringify(messages[i]));
db.transaction( function(tx) {
var result = tx.executeSql('SELECT * from news where status_id = "'+messages[i].id+'"'); // check for news id
if(result.rows.length === 1) {// use update
print(messages[i].id +' exists, update it')
result = tx.executeSql('UPDATE news SET username="'+login.username+'", messagetype=1, text="'+Qt.btoa(messages[i].text)+'", created_at="'+Date.parse(cleanDate(messages[i].created_at))+'", source="Friendica", status_id="'+messages[i].id+'", uid="'+messages[i].sender.id+'", statusnet_html="'+Qt.btoa(messages[i].text)+'" where status_id="'+messages[i].status_id+'"');
} else {// use insert
result = tx.executeSql('INSERT INTO news (username,messagetype,text,created_at,source,status_id,uid,statusnet_html) VALUES (?,?,?,?,?,?,?,?)', [login.username,1,Qt.btoa(messages[i].text),Date.parse(cleanDate(messages[i].created_at)), "Friendica", messages[i].id, messages[i].sender.id,Qt.btoa(messages[i].text)])}
});
}
})
getNotifications(login,database,rootwindow,callback)
}
function getNotifications(login,database,rootwindow,callback){
Helperjs.friendicaRequest(login,"/api/friendica/notifications", rootwindow,function (obj){
var messages=JSON.parse(obj);
for (var i=0;i<messages.length;i++){
var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
//print('store message data for '+JSON.stringify(messages[i]));
db.transaction( function(tx) {
var result = tx.executeSql('SELECT * from news where status_id = "'+messages[i].id+'"'); // check for news id
if(result.rows.length === 1) {// use update
print(messages[i].id +' exists, update it')
result = tx.executeSql('UPDATE news SET username="'+login.username+'", messagetype=2, text="'+Qt.btoa(messages[i].msg_html)+'", created_at="'+messages[i].timestamp+'", source="Friendica", status_id="'+messages[i].id+'", uid="'+messages[i].uid+'", statusnet_html="'+Qt.btoa(messages[i].msg_html)+'", statusnet_conversation_id="'+messages[i].parent+'" where status_id="'+messages[i].id+'"');
} else {// use insert
result = tx.executeSql('INSERT INTO news (username,messagetype,text,created_at,source,status_id, uid,statusnet_html,statusnet_conversation_id) VALUES (?,?,?,?,?,?,?,?,?)', [login.username,2,Qt.btoa(messages[i].msg_html),messages[i].timestamp,"Friendica", messages[i].id, messages[i].uid,Qt.btoa(messages[i].msg_html),messages[i].parent])}
});
}
})
newsfromdb(database,login.username,callback)
}
function newsfromdb(database,username,callback,contact,stop_time){
// return news before stop_time (used by More button), in brackets of 20 entries, or by specified contact
var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
db.transaction( function(tx) {
if (!stop_time){var stop="";
try{var rs = tx.executeSql('select created_at from news WHERE username="'+username+'" ORDER BY created_at DESC LIMIT 1');
stop="<="+rs.rows.item(0).created_at}catch(e){stop="<99999999999999"}}
else{var stop="<"+stop_time}
var contactfilter="";if(contact){contactfilter=" AND uid='"+contact+"'"}
var newsrs=tx.executeSql('select * from news WHERE username="'+username+'" AND created_at'+stop+contactfilter+' ORDER BY created_at DESC LIMIT 20');
var newsArray=[];
for(var i = 0; i < newsrs.rows.length; i++) {
newsArray.push(newsrs.rows.item(i));
Helperjs.readData(database,"contacts",username,function(userdata){
newsArray[i].user=userdata[0];
},"id",newsArray[i].uid);
if(newsArray[i].in_reply_to_user_id){
Helperjs.readData(database,"contacts",username,function(replytodata){
newsArray[i].reply_user=replytodata[0];
},"id",newsArray[i].in_reply_to_user_id);
}
if (newsArray[i].messagetype==0){
//userdata for likes
var likeArray=JSON.parse(newsArray[i].like);
var likeHelper=[];
for (var j=0;j<likeArray.length;j++){
Helperjs.readData(database,"contacts",username,function(userdata){
likeHelper[j]=userdata[0];
},"id",likeArray[j]);
}
newsArray[i].like=likeHelper;
//userdata for dislikes
var dislikeArray=JSON.parse(newsArray[i].dislike);
var dislikeHelper=[];
for (var k=0;k<dislikeArray.length;k++){
Helperjs.readData(database,"contacts",username,function(userdata){
dislikeHelper[j]=userdata[0];
},"id",dislikeArray[k]);
}
newsArray[i].dislike=dislikeHelper;
//userdata for attendyes
var attendyesArray=JSON.parse(newsArray[i].attendyes);
var attendyesHelper=[];
for (var l=0;l<attendyesArray.length;l++){
Helperjs.readData(database,"contacts",username,function(userdata){
attendyesHelper[j]=userdata[0];
},"id",attendyesArray[l]);
}
newsArray[i].attendyes=attendyesHelper;
//userdata for attendno
var attendnoArray=JSON.parse(newsArray[i].attendno);
var attendnoHelper=[];
for (var m=0;m<attendnoArray.length;m++){
Helperjs.readData(database,"contacts",username,function(userdata){
attendnoHelper[j]=userdata[0];
},"id",attendnoArray[m]);
}
newsArray[i].attendno=attendnoHelper;
//userdata for attendmaybe
var attendmaybeArray=JSON.parse(newsArray[i].attendmaybe);
var attendmaybeHelper=[];
for (var n=0;n<attendmaybeArray.length;n++){
Helperjs.readData(database,"contacts",username,function(userdata){
attendmaybeHelper[j]=userdata[0];
},"id",attendmaybeArray[l]);
}
newsArray[i].attendmaybe=attendmaybeHelper;
}
}
callback(newsArray)});
}
function deleteNews(login,database,newsid,rootwindow,callback){
Helperjs.friendicaPostRequest(login,"/api/statuses/destroy?id="+newsid, rootwindow,function (obj){
print("Delete "+obj);
var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
print('delete news data for ' + newsid);
db.transaction( function(tx) {var result = tx.executeSql('DELETE from news where status_id ='+newsid); // delete news id
Helperjs.showMessage("Delete",result,rootwindow)});
})}
function retweetNews(login,database,newsid,rootwindow,callback){
Helperjs.friendicaRequest(login,"/api/statuses/retweet?id="+newsid, rootwindow,function (obj){
var answer=JSON.parse(obj);
Helperjs.showMessage("Repost",answer,rootwindow);
})}
function favorite(login,favorite,newsid,rootwindow){
// toggle favorites
if(favorite){ Helperjs.friendicaPostRequest(login,"/api/favorites/create?id="+newsid, rootwindow,function (obj){
print("Favorite "+obj);
})}
else {Helperjs.friendicaPostRequest(login,"/api/favorites/destroy?id="+newsid, rootwindow,function (obj){
print("Favorite destroyed "+obj);
})}
}
function likerequest(login,database,toggle,verb,newsid,rootwindow){
Helperjs.friendicaPostRequest(login,"/api/friendica/activity/"+verb+"?id="+newsid, rootwindow,function (obj){
print("likereturn "+obj);
if (obj=='"ok"'){
var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
db.transaction( function(tx) {var result = tx.executeSql('UPDATE news SET '+verb+'d ='+toggle+' where status_id ='+newsid);
})}})
}
function like(login,database,toggle,verb,newsid,rootwindow){
if(verb=="like"&& toggle==1){
likerequest(login,database,1,"like",newsid,rootwindow);
likerequest(login,database,0,"undislike",newsid,rootwindow);}
if(verb=="dislike"&& toggle==1){
likerequest(login,database,1,"dislike",newsid,rootwindow);
likerequest(login,database,0,"unlike",newsid,rootwindow);}
if(toggle==0){
likerequest(login,database,0,"un"+verb,newsid,rootwindow);}
}
function attend(login,database,attend,newsid,rootwindow,callback){
Helperjs.friendicaPostRequest(login,"/api/friendica/activity/attend"+attend+"?id="+newsid, rootwindow,function (obj){
var attendReturn=JSON.parse(obj);
// print("attend: "+obj);
//if (attendReturn=="OK")
{
var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
db.transaction( function(tx) {var result = tx.executeSql('UPDATE news SET attend="+attend+" where status_id ='+newsid);
callback();
})}})}
function requestConversation(login,database,newsid,rootwindow,callback){
Helperjs.friendicaRequest(login,"/api/conversation/show?id="+newsid,rootwindow, function (obj){
print(obj+JSON.stringify(obj));
var news=JSON.parse(obj);
for (var i=0;i<news.length;i++){
var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
print('store news data for ' + news[i].id);
db.transaction( function(tx) {
var result = tx.executeSql('SELECT * from news where status_id = "'+news[i].id+'"'); // check for news id
if(result.rows.length === 1) {// use update
print(news[i].id +' exists, update it')
result = tx.executeSql('UPDATE news SET username="'+login.username+'", messagetype=0, text="'+Qt.btoa(news[i].text)+'", truncated="'+news[i].truncated+'", created_at="'+Date.parse(cleanDate(news[i].created_at))+'", in_reply_to_status_id="'+news[i].in_reply_to_status_id+'", source="'+news[i].source+'", status_id="'+news[i].id+'", in_reply_to_user_id="'+news[i].in_reply_to_user_id+'", geo="'+news[i].geo+'", favorited="'+news[i].favorited+'", uid="'+news[i].user.id+'", statusnet_html="'+Qt.btoa(news[i].status_html)+'", statusnet_conversation_id="'+news[i].statusnet_conversation_id+'", attachments="'+news[i].attachments+'" where status_id="'+news[i].status_id+'"');
} else {// use insert
result = tx.executeSql('INSERT INTO news VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)', [login.username,0,Qt.btoa(news[i].text),news[i].truncated,Date.parse(cleanDate(news[i].created_at)), news[i].in_reply_to_status_id, news[i].source, news[i].id,news[i].in_reply_to_user_id,news[i].geo,news[i].favorited, news[i].user.id,Qt.btoa(news[i].statusnet_html),news[i].statusnet_conversation_id, news[i].attachments,0,0,0]);
}});
if(news[i].user.following!=true){
updateContactInDB(login,database,rootwindow,news[i].user)}
}
callback();
}
);}
function conversationfromdb(database,user,conversationId,callback){
var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
db.transaction( function(tx) {
print('select * from news WHERE statusnet_conversation_id='+conversationId+' ORDER BY status_id DESC');
var newsrs=tx.executeSql('select * from news WHERE statusnet_conversation_id='+conversationId+' ORDER BY status_id DESC');
var newsArray=[];
for(var i = 0; i < newsrs.rows.length; i++) {
newsArray.push(newsrs.rows.item(i))
Helperjs.readData(database,"contacts",function(userdata){
newsArray[i].user=userdata[0];
},"id",newsArray[i].uid);
}
callback(newsArray);
});}
function inArray(list, prop, val) {
if (list.length > 0 ) {
for (var i in list) { if (list[i][prop] === val) {
return true;
}
}
} return false;
}
function cleanDate(date){
var cleanedDate= date.slice(0,3)+", "+date.slice(8,11)+date.slice(4,7)+date.slice(25,30)+date.slice(10,25);
return cleanedDate
}

View File

@ -0,0 +1,48 @@
WorkerScript.onMessage = function(msg) {
if(msg.appendnews!==true){ msg.model.clear()};
for (var j=0;j<msg.news.length;j++){
if (msg.news[j]) {
var newsitemobject=msg.news[j];
var likeText="";var dislikeText="";var attendyesText="";var attendnoText="";var attendmaybeText="";
if (newsitemobject.messagetype==0){
if (msg.news[j].like.length>0){
if (msg.news[j].like.length==1){likeText= Qt.atob(msg.news[j].like[0].name)+" "+ qsTr("likes this.")}
else {likeText= msg.news[j].like.length+" "+ qsTr("like this.")}
}
if (msg.news[j].dislike.length>0){
if (msg.news[j].dislike.length==1){dislikeText= QT.atob(msg.news[j].dislike[0].name)+" "+ qsTr("doesn't like this.")}
else {dislikeText= msg.news[j].dislike.length+" "+ qsTr("don't like this.")}
}
if (msg.news[j].attendyes.length>0){
if (msg.news[j].attendyes.length==1){attendyesText= Qt.atob(msg.news[j].attendyes[0].name)+" "+ qsTr("will attend.")}
else {attendyesText= msg.news[j].attendyes.length+" "+ qsTr("persons will attend.")}
}
if (msg.news[j].attendno.length>0){
if (msg.news[j].attendno.length==1){attendnoText= Qt.atob(msg.news[j].attendno[0].name)+" "+ qsTr("will not attend.")}
else {attendnoText= msg.news[j].attendno.length+" "+ qsTr("persons will not attend.")}
}
if (msg.news[j].attendmaybe.length>0){
if (msg.news[j].attendmaybe.length==1){attendmaybeText= Qt.atob(msg.news[j].attendmaybe[0].name)+" "+ qsTr("may attend.")}
else {attendmaybeText= msg.news[j].attendmaybe.length+" "+ qsTr("persons may attend.")}
}
}
var friendica_activities={likeText:likeText,dislikeText:dislikeText,attendyesText:attendyesText,attendnoText:attendnoText,attendmaybeText:attendmaybeText}
var seconds=(msg.currentTime-newsitemobject.created_at)/1000;
var timestring="";
if (seconds<60) {timestring=seconds+" "+qsTr("seconds") +" "+qsTr("ago");}
else if (seconds<90){timestring=Math.round(seconds/60)+" "+qsTr("minute") +" "+qsTr("ago");}
else if (seconds<3600){timestring=Math.round(seconds/60)+" "+qsTr("minutes") +" "+qsTr("ago");}
else if (seconds<5400){timestring=Math.round(seconds/3600)+" "+qsTr("hour") +" "+qsTr("ago");}
else if (seconds<86400){timestring=Math.round(seconds/3600)+" "+qsTr("hours") +" "+qsTr("ago");}
else if (seconds<129600){timestring=Math.round(seconds/86400)+" "+qsTr("day") +" "+qsTr("ago");}
else if (seconds<3888000){timestring=Math.round(seconds/86400)+" "+qsTr("days") +" "+qsTr("ago");}
else if (seconds<5832000){timestring=Math.round(seconds/3888000)+" "+qsTr("month") +" "+qsTr("ago");}
else if (seconds<69984000){timestring=Math.round(seconds/3888000)+" "+qsTr("months") +" "+qsTr("ago");}
else {timestring=Math.round(seconds/69984000)+" "+qsTr("years") +" "+qsTr("ago");}
var data=({"newsitemobject": newsitemobject,"dateDiff":timestring,"friendica_activities":friendica_activities})}
// print("News:"+j+msg.news.length+JSON.stringify(data));
msg.model.append(data);}
if (j==msg.news.length){
msg.model.sync()
};
}

View File

@ -0,0 +1,15 @@
WorkerScript.onMessage = function(msg) {
if (msg.firstalbum==0){msg.model.clear();}
var limit=0; if (msg.albums.length-msg.firstalbum<20){limit=msg.albums.length} else{limit=msg.firstalbum+20}
for (var j=msg.firstalbum;j<limit;j++){
if (msg.albums[msg.firstalbum]) {
// print("album"+msg.albums[j].name);
if(msg.foreignPicture){
var albumname=msg.albums[j].name.trim();var albumlink=msg.albums[j].link
}else{
var albumname=msg.albums[j].toString();var albumlink=""}
msg.model.append({"albumlink":albumlink,"foreignPicture":msg.foreignPicture,"albumname":albumname});
msg.model.sync()
};
}
}

View File

@ -0,0 +1,222 @@
//.pragma library
.import QtQuick.LocalStorage 2.0 as Sql
.import "qrc:/js/helper.js" as Helperjs
.import "qrc:/js/news.js" as Newsjs
// IMAGE FUNCTIONS
function requestList(login,database,rootwindow,callback) {
//get list of own images and call download function
Helperjs.friendicaRequest(login,"/api/friendica/photos/list", rootwindow,function (helperobject){
print("return"+helperobject);
var obj=JSON.parse(helperobject);
Helperjs.readField("id",database,"imageData",login.username,function(AllStoredImages){
if (AllStoredImages.length>0){
for(var i=0;i< AllStoredImages.length;i++){
var position=Helperjs.inArray(obj,"resourceID",AllStoredImages[i]);
if (position>-1){obj.splice(position,1)}
//obj.splice(obj.indexOf(AllStoredImages[i]),1);// list of objects instead of list!!!
}
}}
);
callback(obj);
})}
function dataRequest(login,photoID,database,rootwindow) {
// check if image exist and call download function
Helperjs.friendicaRequest(login,"/api/friendica/photo?photo_id="+photoID, rootwindow, function (obj){
try{ if(obj==""){currentImageNo=currentImageNo+1}else{
var image = JSON.parse(obj);
print('storeData() for ' + JSON.stringify(obj));
try{sprite.destroy();}catch(e){}
if (obj["link"]["0"]){var source=obj["link"]["0"]} else {var source=obj["link"]["4"]}//source for profile picture or original size
print("Source"+obj["link"]["0"]+source)
obj["source"]=source;
var filename=obj.filename;
if (filename==""){// check if file as any filename
if (obj.type=="image/jpeg") {obj["filename"]=obj["id"]+".jpg"}
else if (obj.type=="image/png") {obj["filename"]=obj["id"]+".png"}
}
// check if text name has valid image format ending, otherwise append appropriate ending
if(["jpg","png"].indexOf(obj["filename"].substring(obj["filename"].lastIndexOf(".")+1,obj["filename"].length))==-1){
print("falscheEndung: "+obj["filename"].substring(obj["filename"].lastIndexOf(".")+1,obj["filename"].length));
{ if (obj.type=="image/jpeg") {obj["filename"]=obj["filename"]+".jpg"}
else if (obj.type=="image/png") {obj["filename"]=obj["filename"]+".png"}
}
print("obj.Filename: "+obj["filename"]+" filename: "+filename)
}
saveImage(obj,login.imagestore,function(obj,sprite){
//sprite.destroy(500);
var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
db.transaction( function(tx) {
print('... check if a object exists: '+obj["id"])
var result = tx.executeSql('SELECT * from imageData where id = "'+obj["id"]+'"');
if(result.rows.length === 1) {// use update
print(obj["id"] +' exists, update it')
result = tx.executeSql('UPDATE imageData SET username ="' +login.username+ '",id="'+obj.id+'", created="'+obj.created+'", edited="'+obj.edited+'", profile="'+obj.profile+'", link="'+obj.source+'", filename="'+obj.filename+'",title="'+obj.title+'", desc="'+obj.desc+'", type="'+obj.type+'", width="'+obj.width+'", height="'+obj.height+'", album="'+obj.album+'", location="file://'+login.imagestore+'" where id="'+obj["id"]+'"');
} else {// use insert print('... does not exists, create it')
result = tx.executeSql('INSERT INTO imageData VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?)', [login.username,obj.id,obj.created,obj.edited, obj.title, obj.desc, obj.album, obj.filename, obj.type, obj.height, obj.width,obj. profile,obj.source,'file://'+login.imagestore]);
print("Inserted");}
})})}}
catch (e){print("Data retrieval failure! "+ e+obj);}
})}
function saveImage(obj,storagedirectory,callback) {
// create image component from base64 code and save it
print("Storing "+storagedirectory+obj.filename+obj.width+"x"+obj.height);
var maxSize=Math.max(fotostab.width,fotostab.height);
var helpwidth=(obj.width<maxSize)?obj.width:maxSize;
var helpheight=(obj.height<maxSize)?obj.height:maxSize;
if (obj.width>obj.height){ //landscape
helpheight=helpwidth*obj.height/obj.width
} else { //portrait
helpwidth=helpheight*obj.width/obj.height
}
var component=Qt.createComponent("qrc:/qml/PhotoPlaceholder.qml");
var sprite = component.createObject(fotostab, {"x":0,"y":0,"imageName":storagedirectory+obj.filename ,"width":helpwidth,"height":helpheight,"source": obj.source,"downloadtype":"picture"});
callback(obj,sprite)
}
function deleteImageData(database,user,field,selection,callback) { // does nothing useful at the moment
var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
print(' delete Image Data() for ' + field +"="+selection)
db.transaction( function(tx) {
result = tx.executeSql('UPDATE imageData SET data="" where '+ field +'="'+selection+'"');
callback(result)})
}
function requestFriendsAlbumPictures(friend,rootwindow,callback){
// screenscraping of albums page of contact without user and password
Helperjs.friendicaWebRequest(friend.url.replace("profile","photos"),rootwindow,function(photohtml){
var photoarray=[];
var arr = photohtml.split("sidebar-photos-albums-li");
for (var i=2;i<arr.length;i++){
var albumlink = arr[i].substring(arr[i].indexOf('http'),arr[i].indexOf('class')-2);
var albumname=arr[i].substring(arr[i].indexOf('/span')+6,arr[i].indexOf('</a>')-1);
var album={'link':albumlink,'name':albumname}
photoarray.push(album);
}
//print("Album"+JSON.stringify(photoarray));
callback(photoarray)
})
}
function requestFriendsPictures(link,rootwindow,callback){
// screenscraping of pictures page for given album
Helperjs.friendicaWebRequest(link,rootwindow,function(photohtml){
var photoarray=[];
var basehtml=photohtml.substring(photohtml.indexOf('<base')+12,photohtml.indexOf('/>',photohtml.indexOf('<base'))-2);
// old theme
if (photohtml.indexOf("photo-album-image-wrapper-end")>-1){ //theme 1
var arr = photohtml.split("photo-album-image-wrapper-end");}
// other themes
if (photohtml.indexOf("photo-album-wrapper")>-1){ //theme 2
var photoarea=photohtml.substring(photohtml.indexOf("photo-album-wrapper"),photohtml.indexOf("photo-album-end"))
var arr = photoarea.split("</a>");}
for (var i=0;i<arr.length-1;i++){
var photoname=arr[i].substring(arr[i].lastIndexOf('alt')+5,arr[i].lastIndexOf('title')-2);
var thumblink=arr[i].substring(arr[i].lastIndexOf('<img')+10,arr[i].lastIndexOf('alt')-2);
var imagetype=thumblink.substring(thumblink.lastIndexOf("."));
var photolink=thumblink.substring(0,thumblink.length-imagetype.length-2)+"-0"+imagetype
if(thumblink.substring(0,4)!=="http"){thumblink=basehtml+thumblink}
if(photolink.substring(0,4)!=="http"){photolink=basehtml+photolink}
var photo={'link':photolink,'name':photoname,'thumb':thumblink}
photoarray.push(photo);
}
callback(photoarray)
})
}
// CONFIG FUNCTIONS
function initDatabase(database) { // initialize the database object
var db =Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
print('initDatabase()'+database[0]+database[1]+database[2]+database[3])
db.transaction( function(tx) {
print('... create table')
tx.executeSql('CREATE TABLE IF NOT EXISTS imageData(username TEXT,id INT, created TEXT,edited TEXT, title TEXT, desc TEXT, album TEXT,filename TEXT, type TEXT, height INT, width INT, profile INT, link TEXT,location TEXT)');
tx.executeSql('CREATE TABLE IF NOT EXISTS config(server TEXT, username TEXT, password TEXT, imagestore TEXT, maxnews INT, timerInterval INT, newsViewType TEXT,isActive INT)');
tx.executeSql('CREATE TABLE IF NOT EXISTS news(username TEXT, messagetype INT, text TEXT, created_at INT, in_reply_to_status_id INT, source TEXT, status_id INT, in_reply_to_user_id INT, geo TEXT,favorited TEXT, uid INT, statusnet_html TEXT, statusnet_conversation_id TEXT,like TEXT, dislike TEXT, attendyes TEXT,attendno TEXT, attendmaybe TEXT)');
tx.executeSql('CREATE TABLE IF NOT EXISTS contacts(username TEXT, id INT, name TEXT, screen_name TEXT, location TEXT,description TEXT, profile_image BLOB, url TEXT, protected TEXT, followers_count INT, friends_count INT, created_at TEXT, favourites_count TEXT, utc_offset TEXT, time_zone TEXT, statuses_count INT, following TEXT, verified TEXT, statusnet_blocking TEXT, notifications TEXT, statusnet_profile_url TEXT, cid INT, network TEXT, isFriend INT)');
tx.executeSql('CREATE TABLE IF NOT EXISTS groups(username TEXT, groupname TEXT, gid INT, members TEXT)');
})}
function storeConfig(database,obj) { // stores config to DB
var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
print('storeConfig() for ' + obj.username)
print('database: ' + database[0]);
db.transaction( function(tx) {
print('... check if a object exists: '+obj.username)
var result = tx.executeSql('SELECT * from config WHERE username="'+obj.username+'"');
if(result.rows.length === 1) {// use update
print(obj.username +' exists, update it');
var result2 = tx.executeSql('UPDATE config SET server="'+obj.server+'",password="'+obj.password+'", imagestore="'+obj.imagestore+'", maxnews="+obj.maxnews+", isActive=0 WHERE username="'+obj.username +'"');
var result3 = tx.executeSql('UPDATE config SET isActive=1 WHERE username !="'+obj.username +'"');
var result4 = tx.executeSql('UPDATE config SET maxnews='+obj.maxnews);
} else {// use insert print('... does not exists, create it')
var result2 = tx.executeSql('INSERT INTO config VALUES (?,?,?,?,?,?,?,?)', [obj.server, obj.username, obj.password, obj.imagestore, obj.maxnews, 0,"list",0]);
var result3 = tx.executeSql('UPDATE config SET isActive=1 WHERE username !="'+obj.username +'"');
var result4 = tx.executeSql('UPDATE config SET maxnews='+obj.maxnews);
print("Inserted");}
});}
function getServerConfig(login,rootwindow,callback){
// check server with given credentials
try {Helperjs.friendicaRequest(login,"/api/statusnet/config",rootwindow, function (obj){
var serverconfig = JSON.parse(obj);
var serverconfigString="import QtQuick 2.0; import QtQuick.Dialogs 1.2; MessageDialog{ visible: true; title:'Server';standardButtons: StandardButton.Ok;text: 'SUCCESS! \nName: "+serverconfig.site.name+"\nLanguage: "+serverconfig.site.language+
"\nEmail: "+serverconfig.site.email+"\nTimezone: "+serverconfig.site.timezone+"\nClosed: "+serverconfig.site.closed+
"\nText limit: "+serverconfig.site.textlimit+"\nShort Url length: "+serverconfig.site.shorturllength+
"\nFriendica version: "+serverconfig.site.friendica.FRIENDICA_VERSION+"\nDFRN version: "+serverconfig.site.friendica.DFRN_PROTOCOL_VERSION +
"\nDB Update version: "+serverconfig.site.friendica.DB_UPDATE_VERSION+"'}";
callback(serverconfigString);
})}
catch (e){callback (e);
}}
function readConfig(database,callback,filter,filtervalue) { // reads config
print('readConfig()')
if (filter){var where = " WHERE "+ filter +" = '" + filtervalue+"'";} else { var where="";}
var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3],initDatabase(database));
db.transaction( function(tx) {
var tables = tx.executeSql("SELECT * FROM sqlite_master WHERE type='table'");
if (tables.rows.length==0){print("no database");callback("")} else {
print('... read from database '+where)
var rs = tx.executeSql('select * from config'+where);
var rsArray=[];
if (rs.rows.length>0){
for(var i = 0; i < rs.rows.length; i++) {
rsArray.push(rs.rows.item(i))
}
var rsObject={server:rsArray[0].server,username:rsArray[0].username, password:rsArray[0].password,imagestore:rsArray[0].imagestore,maxnews:rsArray[0].maxnews,isActive:rsArray[0].isActive};
} else {
var rsObject=""
}
callback(rsObject);}}
);
}
function readActiveConfig(database){
var obj;
readConfig(database,function(config){
obj=config},"isActive", 0);
return obj;
}
function deleteConfig(database,userobj,callback) { // delete user data from DB
print('deleteConfig()')
if (userobj){var where = " WHERE username='"+ userobj.username+"' and server='"+userobj.server+"'";} else { return "no user selected!";}
var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
if(!db) { return; }
db.transaction( function(tx) {
print('... read from database '+where)
var rs = tx.executeSql('delete * from config'+where);
print(rs.toString);
callback(rs);
});
}

View File

@ -0,0 +1,29 @@
import QtQuick 2.0
import QtQuick.Controls 1.2
Item {
ComboBox{
id: selectionTypeCombo
width: 150
model: ["album", "type","filename"]
onCurrentIndexChanged:{
var login=Service.readActiveConfig(db);
if (currentText!==""){
photogroupModel.clear();
Service.readData(db, "imageData",function(filter){
for (var j=0;j<filter.length;j++){
Service.readField("data",db,"imageData",function(obj){
// obj.sort(function(obj1,obj2){return obj1.data-obj2.data});
if (obj) {
for (var k=0;k<obj.length;k++){
print("Photomodel:"+obj[k].location+obj[k].filename);
photoModel.append({imageString: obj[k].location+obj[k].filename,photoDescription:obj[k].filename})
};
}
if (obj[0]) {photogroupModel.append({photoDescription: filter[j]})};
},currentText,filter[j]);
}},"username",login.username)
}
}
}
}

View File

@ -0,0 +1,44 @@
import QtQuick 2.0
import QtMultimedia 5.0
import QtQuick.Controls 1.2
Item {
Rectangle {
VideoOutput {
anchors.fill: parent
source: localCamera
}
Camera {
id: localCamera
}
Button {
id: shotButton
width: 200; height: 75
text: "Take Photo"
onClicked: {
localCamera.imageCapture.capture();
} }
Connections {
target: localCamera.imageCapture
onImageSaved: {
photofile= imagePaths.append({"path": path})
listView.positionViewAtEnd(); }
}
Image {
id: photoFromCamera
anchors.fill: parent
fillMode: Image.PreserveAspectFit
source: photo
}
Button {
text: "Upload"
onClicked:{
var login=Service.readActiveConfig(db);
img.src=file;
Service.Upload(login,file)
}
}
}
}

View File

@ -0,0 +1,250 @@
import QtQuick 2.0
import QtQuick.Dialogs 1.2
import QtQuick.Controls 1.2
import "qrc:/js/service.js" as Service
import "qrc:/js/layout.js" as Layoutjs
import "qrc:/js/helper.js" as Helperjs
import "qrc:/qml"
StackView{
id: configStack
anchors.fill:parent
focus: true
Keys.onReleased: if (event.key === Qt.Key_Back && stackView.depth > 1) {
stackView.pop(); event.accepted = true;
}
initialItem: Flickable{
width:root.width-5*mm
height:root.height-12*mm
contentHeight: configBackground.height
boundsBehavior: Flickable.StopAtBounds
Rectangle{
id:configBackground
color: "grey"
width:parent.width
height:Math.max(80*mm,root.height-12*mm)
focus: true
ComboBox{
y:mm
width: root.width/2
model: ListModel{
id: usermodel
}
onCurrentIndexChanged:{
try {Service.readConfig(db,function(obj){
servername.text=obj.server;
username.text= obj.username;
password.text=Qt.atob(obj.password);
imagestore.text=obj.imagestore;
maxNewsText.text=obj.maxnews;
if( obj.isActive==0){isActiveField.text=qsTr("yes")} else {isActiveField.text=qsTr("no")}
},"username",currentText)}
catch (e){print(e)}
}
}
Text {
text: "Server"
x: 4*mm; y: 10*mm
}
Text {
text: "User"
x: 4*mm; y: 20*mm
}
Text {
text: "Password"
x: 4*mm; y: 30*mm
}
Text {
text: "Image dir."
x: 4*mm; y: 40*mm
}
Text {
text: "Max. News"
x: 4*mm; y: 50*mm
}
Text {
text: "is Active"
x: 4*mm; y: 60*mm
}
Rectangle{color: "white"; x: 25*mm; y: 10*mm; width: root.width/2; height: 5*mm;}
Flickable {
id: servernameFlickable
x: 25*mm; y: 10*mm; width: root.width/2; height: 5*mm;
contentWidth: servername.paintedWidth
contentHeight: servername.paintedHeight
clip: true
TextEdit {
id: servername
width: servernameFlickable.width
height: servernameFlickable.height
focus: true
text:"https://..."
//wrapMode: TextEdit.NoWrap
//validator: RegExpValidator { regExp: /^(((http|https|ftp):\/\/)?([[a-zA-Z0-9]\-\.])+(\.)([[a-zA-Z0-9]]){2,4}([[a-zA-Z0-9]\/+=%&_\.~?\-]*))*$/}
// onEditingFinished:{}
onCursorRectangleChanged: Layoutjs.ensureVisibility(cursorRectangle,servernameFlickable)
}
}
Rectangle{
color: "white"
x: 25*mm; y: 20*mm; width: root.width/2; height: 5*mm;
TextInput {
id: username
anchors.fill: parent
selectByMouse: true
}
}
Rectangle{
color: "white"
x: 25*mm; y: 30*mm; width: root.width/2; height: 5*mm;
TextInput {
id: password
anchors.fill: parent
selectByMouse: true
echoMode: TextInput.PasswordEchoOnEdit
}
}
Rectangle{color: "white"; x: 25*mm; y: 40*mm; width: root.width/2-9*mm; height: 5*mm;}
Flickable {
id: imagestoreFlickable
x: 25*mm; y: 40*mm; width: root.width/2-9*mm; height: 5*mm;
clip: true
TextInput {
id: imagestore
width: imagestoreFlickable.width
height: imagestoreFlickable.height
wrapMode: TextEdit.NoWrap
onCursorRectangleChanged: Layoutjs.ensureVisibility(cursorRectangle,imagestoreFlickable)
}
}
Slider{ id: maxNews
x:37*mm; y: 50*mm;width: root.width/3;height:5*mm
minimumValue: 0;maximumValue:100000; stepSize: 1000
}
Rectangle{color: "white"; x: 25*mm; y: 50*mm; width: 9*mm; height: 5*mm;
TextEdit{id:maxNewsText;
anchors.fill: parent
verticalAlignment:TextEdit.AlignRight
text:maxNews.value
focus: true
selectByMouse: true
}
}
Rectangle{
x: 25*mm; y: 60*mm; width: root.width/2; height: 5*mm;
Text{
id: isActiveField
anchors.fill: parent
}
}
FileDialog {
id: imagestoreDialog
title: "Please choose a directory"
folder: shortcuts.pictures
selectFolder: true
onAccepted: {
var imagestoreString=imagestoreDialog.folder.toString(); imagestoreString=imagestoreString.replace(/^(file:\/{2})/,"")+"/"
imagestore.text=imagestoreString;
console.log("You chose: " + imagestoreDialog.folder)
}
onRejected: {
console.log("Canceled")
}
}
Button {
x: root.width/2+18*mm; y: 40*mm; width: 7*mm; height: 5*mm;
text: "..."
onClicked:
{imagestoreDialog.open()}
}
Button {
x: 25*mm; y: 70*mm; width: implicitWidth; height: implicitHeight;
text: "Update"
onClicked:{
var userconfig={server: servername.text, username: username.text, password:Qt.btoa(password.text), imagestore:imagestore.text,maxnews:maxNewsText.text};
var errormessage="";
if (servername.text==""){errormessage=qsTr("No server given! ")}
//if (!servername.acceptableInput){errormessage+=qsTr("Server name not valid! ")}
else if (username.text==""){errormessage+=qsTr("No username given! ")}
else if (password.text=="") {errormessage+=qsTr("No password given! ")}
else if (imagestore.text=="") {errormessage+=qsTr("No image directory given!")}
else if (maxNewsText.text=="") {errormessage+=qsTr("No maximum news number given!")}
else {errormessage=""}
if (errormessage=="") {
filesystem.Directory=userconfig.imagestore;
filesystem.makeDir("contacts");
Service.storeConfig(db,userconfig);
Service.readConfig(db,function(userconfig){Service.getServerConfig(userconfig,configBackground, function(obj){
var serverString=obj;
var serverconfigObject=Qt.createQmlObject(serverString,configBackground,"serverconfigOutput");
usermodel.append({text:username.text});
//reset values
root.login=userconfig;
root.contactlist=[];
root.news=[]
root.newContacts=[]
root.currentContact= 0
root.contactLoadType= ""
root.currentIndex=0;
newstab.active=true;
})},"isActive",0);
}
else {Helperjs.show("Error", errormessage,root)}
}}
Button {
x: root.width/2+2*mm; y: mm; width: 5*mm; height: 5*mm;
text: "-"
onClicked:{
var userconfig={server: servername.text, username: username.text, password: Qt.btoa(password.text)};
Service.deleteConfig(db,userconfig);
}}
Button {
x: root.width/2+8*mm; y: mm; width: 5*mm; height: 5*mm;
text: "+"
onClicked:{
servername.text="https://..."
username.text=""
password.text=""
imagestore.text=""
maxNews.value=1000
isActiveField.text=""
}
}
Button {
x: root.width/2+14*mm; y: mm; width: 5*mm; height: 5*mm;
text: "?"
onClicked:{
configStack.push({item:"qrc:/qml/InfoBox.qml"});
}
}
Component.onCompleted: {
try{Helperjs.readData(db,"config",root.login.username,function(users){
users.sort(function(obj1, obj2) {
return obj1.isActive - obj2.isActive;
});
for (var i=0; i<users.length;i++){
if (users[i]) {usermodel.append({text:users[i].username});};
};})}
catch (e){print(e)}
}
}
}
}

View File

@ -0,0 +1,133 @@
import QtQuick 2.0
import QtQuick.Controls 1.3
import "qrc:/js/service.js" as Service
import "qrc:/js/layout.js" as Layoutjs
Item {
id: friendComponent
property date createdAtDate: new Date(friend.created_at)
Rectangle {
id: wrapper
width: 16*mm
height: 15*mm
border.color: "grey"
color:"white"
Image {
id: photoImage
x:1
y:1
width: 10*mm
height:10*mm
source:"file://"+ friend.profile_image
}
Label {
id: namelabel
x: 1
width: wrapper.width-4
height: 3*mm
text: friend.screen_name
anchors.topMargin: 0
anchors.left: photoImage.left
color: "#303030"
font.pixelSize: 3*mm
anchors.top: photoImage.bottom
}
Button{
id:infobutton
width: 5*mm
height: 5*mm
text:"?"
anchors.left: photoImage.right
anchors.leftMargin: 3
anchors.topMargin: 3
anchors.top: parent.top
onClicked:{
//print("State: "+ friendComponent.state);
friendComponent.state="large"}
}
Rectangle{
id: detailsrectangle
anchors.top: namelabel.bottom
anchors.topMargin: 2*mm
opacity: 0
Flickable{
id:namelabelflickable
width: root.width-10*mm
height:wrapper.height-27*mm-3
boundsBehavior:Flickable.StopAtBounds
flickableDirection:Flickable.VerticalFlick
contentWidth:width
contentHeight: namelabeltext.height
clip:true
Text{
id:namelabeltext
//anchors.top: parent.top
width: namelabelflickable.width
height: implicitHeight
font.pixelSize: 3*mm
textFormat:Text.RichText
wrapMode: Text.Wrap
text:"<b>"+qsTr("Description")+": </b> "+Qt.atob(friend.description)+"<br> <b>"+qsTr("Server Type")+":</b> "+friend.location+"<br> <b>"+qsTr("Posts")+":</b> "+friend.statuses_count+
"<br> <b>"+qsTr("URL")+":</b> <a href='"+ friend.url+"'>"+friend.url+"</a><br> <b>"+
qsTr("Created at")+":</b> "+createdAtDate.toLocaleString(Qt.locale())
onLinkActivated: {
Qt.openUrlExternally(link)}
}
}
Row{
anchors.top: namelabelflickable.bottom
anchors.topMargin: 2*mm
spacing:4
Button{
id:photobutton
text:"Photos"
visible:friend.location=="Friendica"? 1:0
onClicked:{root.currentIndex=2;
fotostab.active=true;
root.fotoSignal(friend) ;
}
}
Button{
id:messagebutton
text:"Messages"
onClicked:{root.currentIndex=0;
newstab.active=true;
root.messageSignal(friend.id) ;
}
}
Button{
id:dmbutton
visible: friend.following=="true"?true:false
text: "DM"
onClicked:{root.currentIndex=0;
newstab.active=true;
root.directmessageSignal(friend.screen_name);
}
}
Button{
id: closeButton
text: "close"
onClicked:{friendComponent.state=""}
}
}
}
}
states: [
State {
name: "large"
PropertyChanges { target: namelabel; font.pixelSize: 4*mm; width:friendsTabView.width-4*mm; text:Qt.atob(friend.name)+" (@"+friend.screen_name+")"}
PropertyChanges { target: friendComponent; z: 2 }
PropertyChanges { target: wrapper; width:friendsTabView.width-3*mm;height:friendsTabView.height-14*mm}
PropertyChanges { target: photoImage; width:15*mm;height:15*mm }
PropertyChanges { target:friendComponent.GridView.view;contentY:friendComponent.y;contentX:friendComponent.x;interactive:false}
PropertyChanges { target: detailsrectangle; opacity:1 }
}
]
}

View File

@ -0,0 +1,174 @@
import QtQuick 2.0
import QtQuick.Dialogs 1.2
import QtQuick.Controls 1.2
import "qrc:/js/service.js" as Service
import "qrc:/js/helper.js" as Helperjs
import "qrc:/js/news.js" as Newsjs
import "qrc:/qml"
Rectangle {
y:1
color: "white"
TabView{
id:friendsTabView
// property var contacts: []
// property var groups: []
tabPosition: Qt.TopEdge
x:mm
y:mm
width: root.width-5*mm
height: root.height-10*mm
currentIndex: 0
signal friendsSignal(var username)
signal contactsSignal(var username)
signal groupsSignal(var username)
onCurrentIndexChanged:{
if (currentIndex==0){friendsSignal(root.login.username)}
else if (currentIndex==1){contactsSignal(root.login.username)}
else if (currentIndex==2){groupsSignal(root.login.username)}
}
Tab{
title: qsTr("Friends")
Rectangle{
id: friendsGridTab
function showFriends(username){
try {friendsModel.clear()} catch(e){print(e)};
Helperjs.readData(db,"contacts",username,function(friends){
for (var i=0;i<friends.length;i++){
friendsModel.append({"friend":friends[i]});
}},"isFriend",1)
}
Button {
id: updateFriendsButton
text: qsTr("Update")
anchors.top: parent.top
anchors.right: parent.right
onClicked: {
try {friendsModel.clear()} catch(e){print(e)};
root.contactLoadType="friends";
Newsjs.requestFriends(root.login,db,root,function(nc){
root.newContacts=nc
})
}}
ProgressBar{
id: newContactsProgress
width: 15*mm
height: updateFriendsButton.height
anchors.top: parent.top
anchors.right:updateFriendsButton.left
anchors.rightMargin:mm
visible: (root.currentContact!=root.newContacts.length)?true:false
value: root.currentContact/root.newContacts.length
}
GridView {
id: friendsView
x:mm
y:updateFriendsButton.height+mm
width:friendsGridTab.width-2*mm
height:friendsGridTab.height-updateFriendsButton.height-2*mm
clip: true
cellHeight: 16*mm
cellWidth: 17*mm
add: Transition {
NumberAnimation { properties: "x,y"; from: 300; duration: 1000 }
}
model: friendsModel
delegate: FriendComponent { }
}
ListModel{id:friendsModel}
Component.onCompleted: {
friendsTabView.friendsSignal.connect(showFriends);
showFriends(root.login.username)
}
}
}
Tab{
title: qsTr("Other Contacts")
Rectangle{
id: contactsGridTab
function showContacts(username){
try {contactsModel.clear()} catch(e){print(e)};
Helperjs.readData(db, "contacts",root.login.username,function(friendsobject){
for (var j=0;j<friendsobject.length;j++){
contactsModel.append({"friend":friendsobject[j]});
}
},"isFriend",0)}
GridView {
id: contactsView
x:mm
y:mm
width:contactsGridTab.width-2*mm
height:contactsGridTab.height-2*mm
clip: true
cellHeight: 16*mm
cellWidth: 17*mm
add: Transition {
NumberAnimation { properties: "x,y"; from: 300; duration: 1000 }
}
model: contactsModel
delegate: FriendComponent { }
}
ListModel{id: contactsModel}
Component.onCompleted: {
friendsTabView.contactsSignal.connect(showContacts);
}
}
}
Tab{
title: qsTr("Groups")
Rectangle{
id: groupsGridTab
function showGroups(username){
try {groupsModel.clear()} catch(e){print(e)};
print("showGroups"+username);
Helperjs.readData(db, "groups",root.login.username,function(groupsobject){
for (var j=0;j<groupsobject.length;j++){
groupsModel.append({"group":groupsobject[j]});
}})}
Button {
id: updateGroupsButton
text: qsTr("Update")
anchors.top: parent.top
anchors.right: parent.right
onClicked: {
print("Update groups");
Newsjs.requestGroups(root.login,root.db,root,function(){
showGroups(root.login.username)})}
}
GridView {
id: groupsView
x:mm
y:updateGroupsButton.height+mm
width:groupsGridTab.width-2*mm
height:groupsGridTab.height-updateGroupsButton.height-2*mm
clip: true
cellHeight: 16*mm
cellWidth: 17*mm
add: Transition {
NumberAnimation { properties: "x,y"; from: 300; duration: 1000 }
}
model: groupsModel
delegate: GroupComponent { }
}
ListModel{
id: groupsModel
}
Component.onCompleted: {
friendsTabView.groupsSignal.connect(showGroups);
}
}
}
}
}

View File

@ -0,0 +1,148 @@
import QtQuick 2.0
import QtQuick.Controls 1.3
import "qrc:/js/service.js" as Service
import "qrc:/js/layout.js" as Layoutjs
Item {
id: groupComponent
Rectangle {
id: wrapper
width: 16*mm
height: 15*mm
border.color: "grey"
color:"white"
Label {
id: namelabel
x: 1
width: wrapper.width-2
height: 3*mm
text: group.groupname
color: "#303030"
font.pixelSize: 3*mm
anchors.centerIn:parent
}
Button{
id:infobutton
width: 5*mm
height: 5*mm
text:"?"
anchors.top: namelabel.bottom;anchors.topMargin: 3
onClicked:{
print("State: "+ groupComponent.state+groupView.contentY);
groupComponent.state="large"}
}
Rectangle{
id: detailsrectangle
anchors.top: infobutton.bottom
anchors.topMargin: 2*mm
opacity: 0
Component { id:footerComponent
Rectangle{
border.color: "#EEEEEE"
border.width: 1
width:parent.width
height:6*mm
Text{
font.pixelSize: 3*mm
anchors.centerIn: parent
text:qsTr("+")
}
MouseArea{anchors.fill:parent
onClicked:{var contactitems="";
readData(db,"contacts",root.login.username, function(contacts){for (var i=0;i<contacts.length;i++){
contactitems=contactitems+"MenuItem{text:'"+contacts[i].screen_name+"'; onTriggered: groupModel.append(' @"+contacts[i]+"')}"
}},"isFriend",0)
var menuString="import QtQuick.Controls 1.4; Menu {"+contactitems+"}";
print("menustring: "+menuString);
var contactlistObject=Qt.createQmlObject(menuString,messageSend,"contactmenuOutput");
contactlistObject.popup();
Newsjs.addToGroup
}}}}
Component { id:groupMember
Rectangle{
border.color: "#EEEEEE"
border.width: 1
width:parent.width
height:6*mm
Text{
font.pixelSize: 3*mm
anchors.left: parent.left
text:groupmember.screen_name
}
}}
ListView{
id:namelabeltext
anchors.top: parent.top
width: root.width-10*mm
height:wrapper.height-20*mm
clip: true
spacing: 0
footer: footerComponent
model: groupModel
delegate: groupMember
}
ListModel{id: groupModel}
}
Row{
anchors.top: namelabeltext.bottom
anchors.topMargin: 2*mm
spacing:4
Button{
id:photobutton
text:"Photos"
visible:friend.location=="Friendica"? 1:0
onClicked:{root.currentIndex=2;
fotostab.active=true;
root.fotoSignal(friend) ;
}
}
Button{
id:messagebutton
text:"Messages"
onClicked:{root.currentIndex=0;
newstab.active=true;
root.messageSignal(friend.id) ;
}
}
Button{id:dmbutton
visible: friend.following=="true"?true:false
text: "DM"
onClicked:{root.currentIndex=0;
newstab.active=true;
root.directmessageSignal(friend.screen_name);
}
}
Button{
id: closeButton
text: "close"
onClicked:{friendComponent.state=""}
}
}
}
states: [
State {
name: "large"
PropertyChanges { target: namelabel; font.pixelSize: 4*mm; width:friendsView.width; text:Qt.atob(friend.name)+" (@"+friend.screen_name+")"}
PropertyChanges { target: friendComponent; z: 2 }
PropertyChanges { target: wrapper; width:friendsView.width;height:friendsView.height -2*mm-1}
PropertyChanges { target: photoImage; width:15*mm;height:15*mm }
PropertyChanges { target:friendComponent.GridView.view ;contentY:friendComponent.y;contentX:friendComponent.x;interactive:false}
PropertyChanges { target: detailsrectangle; opacity:1 }
}
]
}

View File

@ -0,0 +1,22 @@
import QtQuick 2.0
import QtQuick.Controls 1.2
Rectangle{
color:"white"
width:infoBoxText.contentWidth
height:infoBoxText.contentHeight
Text{id:infoBoxText
textFormat: Text.RichText
wrapMode: Text.Wrap
text: "<b>Friendiqa v0.001 </b><br>Licensed under GPL 3<br> "+
"Sourcecode: <a href='https://github.com/LubuWest/Friendiqa'>https://github.com/LubuWest/Friendica</a><br>"+
"C++ code by <a href='https://kirgroup.com/profile/fabrixxm'>Fabio</a><br>"+
"QML and Javascript code by <a href='https://freunde.ma-nic.de/profile/marco'>Marco</a>"
onLinkActivated:{
Qt.openUrlExternally(link)}
}
Button{
text:qsTr("Close")
onClicked:{configStack.pop()}
anchors.top:infoBoxText.bottom
}
}

View File

@ -0,0 +1,132 @@
// message.qml
// message with buttons
import QtQuick 2.0
import QtQml 2.2
import QtQuick.Controls 1.3
import QtQuick.Dialogs 1.2
import QtQuick.LocalStorage 2.0
//import "../qml"
import "qrc:/js/service.js" as Service
Item{
id:messageSend
property var login
property string parentId: ""
property string reply_to_user:""
property string attachImageURL: "";
property int directmessage: 0;
property var contacts: []
// title: parentId !== "" ? qsTr("Reply to "+reply_to_user) : qsTr("New post")
function statusUpdate(title,status,in_reply_to_status_id,attachImageURL) {
xhr.url= login.server + "/api/statuses/update.xml";
xhr.setLogin(login.username+":"+Qt.atob(login.password));
print("login: "+login.username+":"+Qt.atob(login.password));
xhr.clearParams();
xhr.setParam("source", "Friendiqa");
xhr.setParam("status", status);
if (parentId!="") {xhr.setParam("in_reply_to_status_id", parentid)};
if (title!=="") {xhr.setParam("title", title)};
if (attachImageURL!=="") {xhr.setImageFileParam("media", attachImageURL )};
xhr.post();
}
function dmUpdate(title,text,replyto,screen_name,attachImageURL) {
xhr.url= login.server + "/api/direct_messages/new.xml";
xhr.setLogin(login.username+":"+Qt.atob(login.password));
xhr.clearParams();
xhr.setParam("text", text);
xhr.setParam("screen_name", screen_name);
if (parentId!="") {xhr.setParam("replyto", replyto)};
if (title!=="") {xhr.setParam("title", title)};
if (attachImageURL!=="") {xhr.setImageFileParam("media", attachImageURL )};
xhr.post();
}
Column {
id:messageColumn
spacing: 2
TextField {
id: titleField
width: parent.width
placeholderText: qsTr("Title (optional)")
visible: messageSend.parentId === ""
}
TextArea {
id: bodyField
width: parent.width
height: 30*mm
wrapMode: TextEdit.Wrap
}
CheckBox{
id:dmCheckbox
text:"DM"
enabled: false
checked: (directmessage==1)?true:false
onClicked:{
if(dmCheckbox.checkedState==Qt.Checked){directmessage=1}
else if(dmCheckbox.checkedState==Qt.Unchecked){directmessage=0}
}
}
Row{
spacing:2
Button {
id: cancelButton
text: qsTr("Cancel")
onClicked: {newsStack.pop()}
}
Button {
id: attachButton
text: qsTr("Attach")
onClicked: {imageAttachmentDialog.open()}
}
Button{
id:contactButton
text:qsTr("cc")
visible:(directmessage==0)
onClicked:{
var contactitems="";
for (var i=0;i<contacts.length;i++){
contactitems=contactitems+"MenuItem{text:'"+contacts[i]+"'; onTriggered: bodyField.append(' @"+contacts[i]+"')}"
}
var menuString="import QtQuick.Controls 1.4; Menu {"+contactitems+"}";
// print(menuString);
var contactlistObject=Qt.createQmlObject(menuString,messageSend,"contactmenuOutput")
contactlistObject.popup() }
}
Button {
id: sendButton
text: qsTr("Send")
onClicked: {
print("login: "+login.server+login.username);
if (directmessage==0){
statusUpdate(titleField.text,bodyField.text,messageSend.parentId,attachImageURL.toString());}
else {dmUpdate( titleField.text,bodyField.text,"",messageSend.reply_to_user) }
newsStack.pop()
}
}
}
}
FileDialog {
id: imageAttachmentDialog
title: "Please choose a picture"
folder: shortcuts.pictures
selectFolder: false
onAccepted: {
attachImageURL=imageAttachmentDialog.fileUrl;
var imageAttachementObject=Qt.createQmlObject('import QtQuick 2.0; Image {source:"'+attachImageURL.toString()+'"; width: 30*mm; height: 30*mm;fillMode: Image.PreserveAspectFit}',messageColumn,"attachedImage");
console.log("You chose: " + attachImageURL)
}
onRejected: {
console.log("Canceled")
}
}
}

View File

@ -0,0 +1,155 @@
import QtQuick 2.0
import QtQuick.Dialogs 1.2
import QtQuick.Controls 1.2
import QtQuick.LocalStorage 2.0 as Sql
import "qrc:/js/news.js" as Newsjs
import "qrc:/js/helper.js" as Helperjs
Item {
property string newstabStatus:"news"
function showNews(newsToShow){
newsBusy.running=false;
var currentTime= new Date();
var msg = {'currentTime': currentTime, 'model': newsModel,'news':newsToShow};
newsWorker.sendMessage(msg);
}
function onFriendsMessages(friend){print(" Friend "+friend);
newstabStatus="friendmessage";
Newsjs.newsfromdb(db,root.login.username, function(dbnews){showNews(dbnews)},friend)
}
function onDirectMessage(friend){
newsStack.push({item:"qrc:/qml/MessageSend.qml",properties:{"reply_to_user": friend,"directmessage":1,"login":root.login}});
}
function cleanNews(database){
var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
db.transaction( function(tx) {
var maxnewsrs = tx.executeSql("SELECT DISTINCT maxnews FROM config");
var maxnews=maxnewsrs.rows.item(0);
var newscountrs = tx.executeSql('SELECT COUNT(*) from news');
var newscount = newscountrs.rows.item(0);
if (newscount>maxnews){var lastvalidtimers= tx.executeSql('select created_at from news ORDER BY created_at DESC LIMIT ' +(newscount-maxnews));
var lastvalidtime=lastvalidtimers.rows.item(-1);
var deleters = tx.executeSql('DELETE from news WHERE created_at<'+lastvalidtime)}
});
Qt.quit()
}
StackView{
id: newsStack
anchors.fill:parent
focus: true
Keys.onReleased: if (event.key === Qt.Key_Back && stackView.depth > 1) {
stackView.pop(); event.accepted = true;
}
initialItem:Rectangle {
y:1
color: "white"
width:root.width-2*mm
height:root.height-8*mm
Button {
id: newMessageButton
text: qsTr("+")
anchors.top: parent.top
anchors.right: parent.right
onClicked: {
Helperjs.readField("screen_name",root.db,"contacts",root.login.username,function(friends){
newsStack.push({item:"qrc:/qml/MessageSend.qml",properties:{"contacts": friends,"login":root.login}})
},"isFriend",1);
}
}
Button {
id: quitButton
text: qsTr("Quit")
anchors.top: parent.top
anchors.right: newMessageButton.left
onClicked: {cleanNews(root.db)}
}
Component { id:footerComponent
Rectangle{
border.color: "#EEEEEE"
border.width: 1
width:parent.width
height:6*mm
Text{
font.pixelSize: 1.5*mm
anchors.centerIn: parent
text:qsTr("More")
}
MouseArea{anchors.fill:parent
onClicked:{
var currentTime= new Date();
if(newstabStatus=="news"){
var lastnews_id=newsModel.get(newsModel.count-1).newsitemobject.created_at;
Newsjs.newsfromdb(root.db,root.login.username, function(news){
var msg = {'currentTime': currentTime, 'model': newsModel,'news':news,'appendnews':true};
newsWorker.sendMessage(msg);
},false,lastnews_id)}
else if(newstabStatus=="friendmessage"){
Newsjs.newsfromdb(root.db,root.login.username, function(news){
var msg = {'currentTime': currentTime, 'model': newsModel,'news':news,'appendnews':true};
newsWorker.sendMessage(msg);
},newsModel.get(newsModel.count-1).newsitemobject.uid,newsModel.get(newsModel.count-1).newsitemobject.created_at)}
}}
}
}
ListView {
id: newsView
anchors.fill: parent
anchors.topMargin: 8*root.mm
anchors.leftMargin: 3*root.mm; anchors.rightMargin: root.mm
anchors.bottomMargin: 1*root.mm
clip: true
spacing: 0
footer: footerComponent
model: newsModel
delegate: Newsitem{}
}
ListModel{id: newsModel}
WorkerScript {
id: newsWorker
source: "qrc:/js/newsworker.js"
}
Button {
id: update
anchors.top: parent.top
anchors.right: quitButton.left
text: "Update"
onClicked: { //try{newsModel.clear()} catch(e){}
newsBusy.running=true;
root.contactLoadType="news";
Newsjs.getFriendsTimeline(login,db,contactlist,newstab,function(ns,nc){
root.news=ns;root.newContacts=nc;root.currentContact=0;
if (ns.length==0){
Newsjs.getDirectMessage(root.login,root.db,root,function(dbnews){showNews(dbnews)});
newsBusy.running=false}
})}
}
BusyIndicator{
id: newsBusy
anchors.centerIn:update
//anchors.right: update.left
//anchors.top:parent.top
width:7*mm
height: 7*mm
}
Component.onCompleted: {
root.messageSignal.connect(onFriendsMessages);
root.directmessageSignal.connect(onDirectMessage);
root.newsSignal.connect(showNews);
try{newsModel.clear()} catch(e){}
Newsjs.newsfromdb(root.db,root.login.username, function(dbnews){
showNews(dbnews)
})
}
}
}
}

View File

@ -0,0 +1,286 @@
import QtQuick 2.0
import QtQuick.LocalStorage 2.0
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
import "qrc:/js/news.js" as Newsjs
import "qrc:/js/layout.js" as Layoutjs
Item {
id: newsitem
width: newsView.width
height:Math.max((itemMessage.height+createdAtLabel.height+friendicaActivities.height+4*mm),profileImage.height+user_name.height+mm)
// property var friendica_activities
property string conversation_id: ""
property string attending: ""
onAttendingChanged: {attendLabel.visible=true;
attendLabel.text= qsTr("attending: ")+ qsTr(attending)}
signal replyto(string parent_id)
Rectangle{width:newsitem.width; height: 1; anchors.bottom: newsitem.bottom; color:"light grey"}
Rectangle{
width:newsitem.width
height:newsitem.height-1
color: (newsitemobject.directmessage)?"#ffe6e6" : "white"
Column {
id: authorcolumn
width: 8*mm
Image {
id:profileImage
source: "file://"+newsitemobject.user.profile_image
x:1
width: 7*mm
height: 7*mm
MouseArea{
anchors.fill: parent
onPressAndHold: { newsmenu.popup()}
}
onStatusChanged: if (profileImage.status == Image.Error) {source="qrc:/images/defaultcontact.jpg"}
}
Label {
id:user_name
color: "grey"
//height:3.5*mm
width:parent.width
font.pixelSize: 1.5*mm
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
text: Qt.atob(newsitemobject.user.name)
}
}
Column {
id:newscolumn
anchors.left: authorcolumn.right
Row{
spacing: 5*mm
Label {
color: "grey"
text: if (newsitemobject.messagetype==0){qsTr("Source: ")+newsitemobject.source
} else if (newsitemobject.messagetype==1){ qsTr("Direct Message")} else {" Notification"}
font.pixelSize: 1.5*mm
}
Label {
id:createdAtLabel
color: "grey"
height:3.5*mm
font.pixelSize: 1.5*mm
horizontalAlignment: Label.AlignRight
text: dateDiff
}
CheckBox {
id:favoritedCheckbox
style: CheckBoxStyle {
background: Rectangle {
implicitWidth: 6*mm
implicitHeight:2*mm
color:"white"
}
indicator:
Rectangle{x:3*mm
width: 3*mm
implicitHeight:2*mm
Text{
anchors.centerIn: parent
color:control.checked?"black":"grey"
text:"\u2605"
}}
}
checked:(newsitemobject.favorited>0)
Text{
anchors.left: parent.right
color: "grey"
font.pixelSize: 1.5*mm
text: (newsitemobject.favorited>0)? newsitemobject.favorited+qsTr(" Favorites"):""
}
onClicked:{
if(favoritedCheckbox.checkedState==Qt.Checked)
{Newsjs.favorite(login,true,newsitemobject.status_id,root)}
else
if(favoritedCheckbox.checkedState==Qt.Unchecked)
{Newsjs.favorite(login,false,newsitemobject.status_id,root)}
}
}
}
Text {
color: "#404040"
linkColor: "light green"
id: itemMessage
textFormat: Text.RichText
text: Qt.atob(newsitemobject.statusnet_html)
width: newsitem.width-8*mm-2
height: implicitHeight
wrapMode: Text.Wrap
onLinkActivated:{ print("link "+link);
Qt.openUrlExternally(link)}
}
Row{id: friendicaActivities
spacing:mm
Label{color: "grey"
font.pixelSize: 1.5*mm
text: friendica_activities.likeText
}
Label{color: "grey"
font.pixelSize: 1.5*mm
text: friendica_activities.dislikeText
}
Label{color: "grey"
font.pixelSize: 1.5*mm
text: friendica_activities.attendyesText
}
Label{color: "grey"
font.pixelSize: 1.5*mm
text: friendica_activities.attendnoText
}
Label{color: "grey"
font.pixelSize: 1.5*mm
text: friendica_activities.attendmaybeText
}
}
Row {
CheckBox{id:likeCheckbox
height:3*mm
width:8*mm
checked:(newsitemobject.liked==1)?true:false
style: CheckBoxStyle {
background: Rectangle {
implicitWidth: 7*mm
implicitHeight: 3*mm
color:"white"
}
indicator:
Rectangle{
implicitWidth: 3*mm
implicitHeight:3*mm
color:control.checked?"yellow":"white"
x: 5*mm
Text{
font.pixelSize: 1.5*mm
color:"grey"
text:":-)"
}}
}
onClicked: {
if(likeCheckbox.checked==true){Newsjs.like(root.login,root.db,1,"like",newsitemobject.status_id,root);dislikeCheckbox.checked=false}
else{Newsjs.like(root.login,root.db,0,"like",newsitemobject.status_id,root)}}
}
CheckBox{id: dislikeCheckbox
height:3*mm
width:8*mm
checked: (newsitemobject.disliked==1)?true:false
style: CheckBoxStyle {
background: Rectangle {
implicitWidth: 7*mm
implicitHeight:3*mm
color:"white"
}
indicator:
Rectangle{
implicitWidth: 3*mm
implicitHeight:3*mm
color:control.checked?"yellow":"white"
x:5*mm
Text{
font.pixelSize: 1.5*mm
color:"grey"
text:":-("
}}
}
onClicked: {
if (dislikeCheckbox.checked==true){Newsjs.like(root.login,root.db,1,"dislike",newsitemobject.status_id);likeCheckbox.checked=false}
else {Newsjs.like(root.login,root.db,0,"dislike",newsitemobject.status_id,root)}}
}
Label {
id:replytoLabel
color: "grey"
height:3.5*mm
font.pixelSize: 1.5*mm
horizontalAlignment: Label.AlignRight
text: try {qsTr("In reply to ")+newsitemobject.reply_user.screen_name
}catch(e){" "}
}
Label {
id:attendLabel
visible: false
color: "grey"
height:3.5*mm
font.pixelSize: 1.5*mm
horizontalAlignment: Label.AlignRight
text: qsTr("attending: ")+ qsTr(attending)
}
}
}
Menu {
id:newsmenu
MenuItem {
text: qsTr("Reply")
onTriggered: {
newsStack.push({item:"qrc:/qml/MessageSend.qml",properties:{"reply_to_user": newsitemobject.user.screen_name,"parentId":newsitemobject.status_id}});
}
}
MenuItem {
text: qsTr("DM")
onTriggered: {
root.directmessageSignal(newsitemobject.user.screen_name);
}
}
MenuItem {
text: qsTr("Repost")
onTriggered: {
Newsjs.retweetNews(root.login,db,newsitemobject.status_id,root,function(reply){
print(reply);
})
}
}
MenuItem {
text: qsTr("Conversation")
onTriggered: {
Newsjs.requestConversation(root.login,db,newsitemobject.status_id,root,function(){
var currentTime= new Date();
Newsjs.conversationfromdb(db,root.login.username,newsitemobject.statusnet_conversation_id, function(newsarray){
newsModel.clear();
var msg = {'currentTime': currentTime, 'model': newsModel,'news':newsarray,'latestmessage':0};
newsWorker.sendMessage(msg);
});
}
)}
}
Menu{
title: qsTr("Attending")
MenuItem{text:qsTr("yes")
onTriggered: {Newsjs.attend(root.login,db,"yes",newsitemobject.status_id,root,function(){
newsitem.attending="yes";
attendLabel.visible=true})}
}
MenuItem{text:qsTr("maybe")
onTriggered: {Newsjs.attend(root.login,db,"maybe",newsitemobject.status_id,root,function(){
newsitem.attending="maybe"})}
}
MenuItem{text:qsTr("no")
onTriggered: {Newsjs.attend(root.login,db,"no",newsitemobject.status_id,root,function(){
newsitem.attending="no"})}
}
}
MenuItem {
text: qsTr("Delete")
onTriggered: {
Newsjs.deleteNews(root.login,db,newsitemobject.status_id,root,function(reply){
print(JSON.stringify(reply));
newsModel.remove(index);
})
}
}
}
}}

View File

@ -0,0 +1,100 @@
import QtQuick 2.0
import QtQuick.LocalStorage 2.0
import QtQuick.Controls 1.2
Package {
Item { id: stackItem; Package.name: 'stack'; z: stackItem.PathView.z;width:16.5*mm;height:16.5*mm}
Item { id: listItem; Package.name: 'list'; width: root.width-1*mm; height: root.height-8*mm; }
Item { id: gridItem; Package.name: 'grid';}
Item {
id: photoWrapper
width: 16.5*mm; height: 16.5*mm
z: stackItem.PathView.z
property string hqphotolink: photoLink
Rectangle {
id: placeHolder
color: 'lightblue'; antialiasing: true
anchors.fill:parent
//width: parent.width; height: parent.height;
}
BusyIndicator { anchors.centerIn: parent; running: realImage.status != Image.Ready }
Image {
id: realImage;
// property string hqphotolink: photoLink
width: photoWrapper.width; height: photoWrapper.height
antialiasing: true;
asynchronous: true
cache: false
fillMode: Image.PreserveAspectFit;
source: imageLocation
// onStatusChanged: if (realImage.status == Image.Ready) print(realImage.paintedHeight+"x"+realImage.paintedWidth)
}
Rectangle{
id:phototextRectangle
color:"black"
z:3
opacity: 0.5
width:phototext.contentWidth
height: phototext.contentHeight
anchors.bottom: photoWrapper.bottom
}
Text {
id:phototext
z:4
text: photoDescription.trim()
width:15*mm
anchors.bottom: photoWrapper.bottom
color: "white"
font.pixelSize: 2*mm
wrapMode:Text.Wrap
}
MouseArea {
width: realImage.paintedWidth; height: realImage.paintedHeight; anchors.centerIn: realImage
onClicked: {
if (albumWrapper.state == 'inGrid') {
gridItem.GridView.view.currentIndex = index;
//print("photoLink"+realImage.photoLink)
albumWrapper.state = 'fullscreen'
} else {
gridItem.GridView.view.currentIndex = index;
albumWrapper.state = 'inGrid'
}
}
}
states: [
State {
name: 'stacked'; when: albumWrapper.state == ''
ParentChange { target: photoWrapper; parent: stackItem; }//x: 1*mm; y: 1*mm }
PropertyChanges { target: photoWrapper; opacity: stackItem.PathView.onPath ? 1.0 : 0.0 }
PropertyChanges { target: phototext; opacity: 0.0 }
PropertyChanges { target: phototextRectangle; opacity: 0.0 }
},
State {
name: 'inGrid'; when: albumWrapper.state == 'inGrid'
ParentChange { target: photoWrapper; parent: gridItem; x: 1*mm; y: 1*mm;}
PropertyChanges { target: phototext; opacity: 1.0 }
PropertyChanges { target: phototextRectangle; opacity: 0.5 }
PropertyChanges { target: placeHolder; opacity: 1.0 }
},
State {
name: 'fullscreen'; when: albumWrapper.state == 'fullscreen'
ParentChange {
target: photoWrapper; parent: listItem; x: 1; y: 1;
width: root.width-mm; height: root.heigh-8*mm
}
PropertyChanges { target: placeHolder; opacity: 0.0 }
PropertyChanges { target: realImage; source: photoWrapper.hqphotolink}
PropertyChanges { target: phototext; anchors.bottom: realImage.bottom}
PropertyChanges { target: phototext; width:realImage.width }
PropertyChanges { target: phototextRectangle; anchors.bottom: realImage.bottom }
PropertyChanges { target: realImage; width: Math.min(listItem.width,sourceSize.width);height: Math.min(listItem.height,sourceSize.height) }
}
]
}
}

View File

@ -0,0 +1,26 @@
import QtQuick 2.0
import "qrc:/js/helper.js" as Helperjs
Image {
id:photoPlaceholder
property string imageName:"x.jpg"
property string downloadtype:""
fillMode: Image.PreserveAspectFit
onStatusChanged: {
if (photoPlaceholder.status == Image.Ready) {
print("Source: "+source+"Photo width"+width+" height"+height+" Ratio "+ fillMode);
var saveprocess=photoPlaceholder.grabToImage(function(result){
var saveresult=result.saveToFile(imageName.toString());
if (saveresult){
if ((downloadtype=="picture")&&(newImages.length>0)){
photoPlaceholder.destroy();
currentImageNo=currentImageNo+1
}
else if ((downloadtype=="contact")&&(root.newContacts.length>0))
{
photoPlaceholder.destroy(100);
root.currentContact=root.currentContact+1
}
}});
}}}

View File

@ -0,0 +1,140 @@
import QtQuick 2.0
import QtQuick.Dialogs 1.2
import QtQuick.Controls 1.4
import QtQml.Models 2.1
import "qrc:/js/service.js" as Service
import "qrc:/js/helper.js" as Helperjs
import "qrc:/qml"
Rectangle {
id:fotorectangle
y:1
width:root.width-mm
height:root.height-5*mm
color: '#fff'
property var newImages:[]
property int currentImageNo: 0
//onLoginChanged:{var msg = {'model': photogroupModel,'albums':[],'firstalbum':0,'foreignPicture':false};
// photoWorker.sendMessage(msg);
//}
onNewImagesChanged:{
if(newImages.length>0){
Service.dataRequest(root.login,newImages[currentImageNo].id,root.db,fotorectangle);
newImagesProgress.visible=true //download first image
}}
onCurrentImageNoChanged:{
if(currentImageNo<newImages.length){Service.dataRequest(root.login,newImages[currentImageNo].id,root.db,fotorectangle)};
if(currentImageNo==newImages.length){newImagesProgress.visible=false;showOwnFotos();
newImages=[];currentImageNo=0}
// download next image if photoplaceholder is finished saving
}
ProgressBar{
id: newImagesProgress
width: 15*mm
height: updatePhotolist.height
anchors.top: parent.top
anchors.right:updatePhotolist.left
anchors.rightMargin:mm
visible: false
value: currentImageNo/newImages.length
}
Button{
id: updatePhotolist
anchors.top: parent.top
anchors.right:showFotos.left
anchors.rightMargin:mm
text: qsTr("Update")
onClicked: {
Service.requestList(root.login,root.db, fotostab,function(obj){
newImages=obj;
})}}
Button{
id: showFotos
anchors.top: parent.top
anchors.right: parent.right
anchors.rightMargin:2*mm
text: qsTr("Show")
onClicked: {showOwnFotos()}
}
DelegateModel{
id: visualphotoModel
delegate: PhotogroupComponent{}
model: photogroupModel
}
ListModel{
id: photogroupModel
}
GridView {
id: albumgridview
cellWidth: 17*mm
cellHeight: 17*mm
x: mm;y:8*mm
width: parent.width-2*mm; height: parent.height-9*mm
clip: true
model: visualphotoModel.parts.album
footer:
Rectangle{
border.color: "#EEEEEE"
border.width: 1
width:12*mm
height:6*mm
Text{
font.pixelSize: 1.5*mm
anchors.centerIn: parent
text:qsTr("More")
}
MouseArea{anchors.fill:parent
onClicked:{
var lastalbum_id=photogroupModel.get(photogroupModel.count-1);
if(photogroupModel.get(photogroupModel.count-1).foreignPictures==false){Service.requestFriendsAlbumPictures(friend,fotostab,function(albums){
var msg = {'model': photogroupModel,'albums':albums,'firstalbum':lastalbum_id+1,'foreignPicture':true};
photoWorker.sendMessage(msg); })}
else { Helperjs.readField("album",root.db, "imageData",root.login.username,function(albums){
var msg = { 'model': photogroupModel,'albums':albums,'foreignPicture': false,'firstalbum':lastalbum_id+1};
photoWorker.sendMessage(msg)})}
}}}
}
Rectangle { id: photoBackground; color: 'light grey'; width: parent.width; height: parent.height; opacity: 0; visible: opacity != 0.0 }
ListView { anchors.fill: parent; model: visualphotoModel.parts.browser; interactive: false }
Button {
id: backButton
text: qsTr("Back")
x: parent.width - backButton.width - 3*mm
y: -backButton.height - 4*mm
onClicked: {photoBackground.opacity=0}
// visible: Qt.platform.os !== "android"
}
ListView {anchors.fill: parent; model: visualphotoModel.parts.fullscreen; interactive: false }
WorkerScript{id: photoWorker;source: "qrc:/js/photoworker.js"}
function showOwnFotos(){
try {photogroupModel.clear()}catch (e){print(e)}
Helperjs.readField("album",root.db, "imageData",root.login.username,function(albums){
if (albums[0]) {
var msg = { 'model': photogroupModel,'albums':albums,'firstalbum':0,'foreignPicture': false};
photoWorker.sendMessage(msg);
};
})
}
function onFriendsFotos(friend){print("Friend "+friend.url);
try {photogroupModel.clear()}catch (e){print(e)}
Service.requestFriendsAlbumPictures(friend,fotostab,function(albums){
var msg = {'model': photogroupModel,'albums':albums,'firstalbum':0,'foreignPicture':true};
photoWorker.sendMessage(msg);
})
}
Component.onCompleted: { root.fotoSignal.connect(onFriendsFotos);}
}

View File

@ -0,0 +1,48 @@
import QtQuick 2.0
import QtQuick.Dialogs 1.2
import QtQuick.Controls 1.2
Item {
Rectangle{
property string photofile:"../images/Update.png"
color: "grey"
FileDialog {
id: fileDialog
title: "Please choose a file"
folder: shortcuts.pictures
selectMultiple: true
onAccepted: {
photofile=fileDialog.fileUrls[0];
console.log("You chose: " + fileDialog.fileUrls)
// img.src=file;
}
onRejected: {
console.log("Canceled")
}
}
Component.onCompleted: {fileDialog.open()}
Image {
id: photoFromFilesystem
x: 20;y:50
height: 200
fillMode: Image.PreserveAspectFit
source: photofile
onStatusChanged:{
if (photoFromFilesystem.status == Image.Ready) {
Layoutjs.showFriends(db)
}
}
Button {
text: "Upload"
onClicked:{
var login=Service.readActiveConfig(db);
Service.uploadMedia(login,photofile, function(returnvalue){print("Upload return"+returnvalue)})
}}
}
}
}

View File

@ -0,0 +1,119 @@
import QtQuick 2.0
import QtQuick.LocalStorage 2.0
import QtQuick.Controls 1.3
import QtQml.Models 2.1
import "qrc:/js/service.js" as Service
import "qrc:/js/helper.js" as Helperjs
Package {
Item {
Package.name: 'browser'
GridView {
id: photosGridView; model: visualModel.parts.grid; width: albumgridview.width; height: albumgridview.height
cellWidth: 16.5*mm; cellHeight: 16.5*mm; interactive: false;anchors.margins:2*mm
onCurrentIndexChanged: photosListView.positionViewAtIndex(currentIndex, ListView.Contain)
}
}
Item {
Package.name: 'fullscreen'
ListView {
id: photosListView; model: visualModel.parts.list; orientation: Qt.Horizontal
width: parent.width; height: parent.height; interactive: false
onCurrentIndexChanged: photosGridView.positionViewAtIndex(currentIndex, GridView.Contain)
highlightRangeMode: ListView.StrictlyEnforceRange; snapMode: ListView.SnapOneItem
}
}
Item {
Package.name: 'album'
id: albumWrapper; width: 16.5*mm; height: 16.5*mm //-albumtext.contentHeight
DelegateModel {
id: visualModel; delegate: PhotoComponent { }
model: photoModel
}
PathView {
id: photosPathView;
model: visualModel.parts.stack;
pathItemCount: 1
anchors.centerIn: parent;
path: Path {
PathAttribute { name: 'z'; value: 9999.0 }
PathLine { x: 1; y: 1 }
PathAttribute { name: 'z'; value: 0.0 }
}
}
Rectangle{
color:"black"
opacity: 0.5
width:albumtext.contentWidth
height: albumtext.contentHeight
anchors.bottom: albumWrapper.bottom
}
Text {
id:albumtext
text: albumname //foreignPicture ? album.name.trim() : album
width:albumWrapper.width-1*mm
height: albumtext.contentHeight
wrapMode:Text.Wrap
color: "white"
font.family: "Monospace"
font.pixelSize: 2*mm
anchors.bottom: albumWrapper.bottom
}
ListModel{
id: photoModel
}
Component.onCompleted:{
try {photoModel.clear()}catch (e){print(e)}
if(foreignPicture){
//print("Albumlink"+album.link);
Service.requestFriendsPictures(albumlink,fotostab,function(obj){
if (obj) {
for (var k=0;k<obj.length;k++){
//print("Photomodel:"+obj[k].thumb+obj[k].name+obj[k].link);
photoModel.append({"imageLocation": obj[k].thumb,"photoDescription":obj[k].name,"photoLink":obj[k].link})
};
}
})}
else{
Helperjs.readData(db,"imageData",root.login.username,function(obj){
// obj.sort(function(obj1,obj2){return obj1.data-obj2.data});
if (obj) {
for (var k=0;k<obj.length;k++){
// print("Photomodel:"+obj[k].location+obj[k].filename);
photoModel.append({"imageLocation": obj[k].location+obj[k].filename,"photoDescription":obj[k].filename,"photoLink":obj[k].location+obj[k].filename})
};
}
},"album",albumname)}
}
MouseArea {
anchors.fill: parent
onClicked: albumWrapper.state = 'inGrid'
}
states: [
State {
name: 'inGrid'
PropertyChanges { target: photosGridView; interactive: true }
PropertyChanges { target: photoBackground; opacity: 1 }
PropertyChanges { target: backButton; onClicked: albumWrapper.state = ''; y: 6 }
},
State {
name: 'fullscreen'; extend: 'inGrid'
PropertyChanges { target: photosGridView; interactive: false }
PropertyChanges { target: photosListView; interactive: true }
PropertyChanges { target: photoBackground; opacity: 1 }
PropertyChanges { target: backButton; y: -backButton.height - 8 }
}
]
} //album Ende
} //Package Ende
//item Ende

View File

@ -0,0 +1,112 @@
import QtQuick 2.0
import QtQuick.LocalStorage 2.0
import QtQuick.Window 2.0
import QtQuick.Dialogs 1.2
import QtQuick.Controls 1.2
import QtQml.Models 2.1
import "qrc:/js/news.js" as Newsjs
import "qrc:/js/service.js" as Service
import "qrc:/js/layout.js" as Layoutjs
import "qrc:/js/helper.js" as Helperjs
import "qrc:/qml"
TabView{
id:root
tabPosition: Qt.BottomEdge
width: Screen.desktopAvailableWidth
height: Screen.desktopAvailableHeight
property var db: ["Photos", "1.0", "Stores Friendica data", 100000000]
property var login: Service.readActiveConfig(db)
property var contactlist: []
property real mm: Screen.pixelDensity
signal messageSignal(var friend)
signal fotoSignal(var friend)
signal directmessageSignal(var friend)
signal newsSignal(var news)
currentIndex: (login=="")? 3:0
property var news:[]
property var newContacts:[]
property int currentContact: 0
property string contactLoadType: ""
onLoginChanged:{Newsjs.newsfromdb( db,login.username, function(dbnews){
newsSignal(dbnews)
})}
onNewContactsChanged:{if(newContacts.length>0){// download first contact image and update db
print("newcontact"+JSON.stringify(newContacts[0]));
updateContactInDB(login,db,newContacts[currentContact].isFriend,newContacts[currentContact])}
}
onCurrentContactChanged:{// download next contact image after photoplaceholder is finished saving and update db
print("Current contact"+JSON.stringify(newContacts[currentContact]));
if(currentContact<newContacts.length){
updateContactInDB(login,db,newContacts[currentContact].isFriend,newContacts[currentContact])}
else if(currentContact==newContacts.length){//newImagesProgress.visible=false;
if (newContacts.length==0) {}
else if (contactLoadType=="news"){
Newsjs.storeNews(login,db,news,root,function(dbnews){
root.newsSignal(dbnews);
root.newContacts=[];
root.currentContact=0;
root.news=[]
})// show news
}
else if (contactLoadType=="friends"){
root.friendsSignal(login.username);
// show friends
Helperjs.readField("id",db,"contacts",login.username,function(contacts){contactlist=contacts;
root.newContacts=[];
root.currentContact=0},"isFriend",1) }
}
}
function updateContactInDB(login,database,isFriend,contact){// for newstab and friendstab
try{var imagename=login.imagestore+"contacts/"+contact.screen_name+".jpg";
var component=Qt.createComponent("qrc:/qml/PhotoPlaceholder.qml");
print("imageName "+imagename+" source "+ contact.profile_image_url)
var sprite = component.createObject(root, {"fillMode": "Image.PreserveAspectFit","x":root.width,"y":50,"imageName":imagename,"source": contact.profile_image_url,"downloadtype":"contact"});} catch(e){print("Fehler beim Profilbild"+e)}
var db=LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
var result;
db.transaction( function(tx) {
result = tx.executeSql('SELECT * from contacts where id = '+contact.id); // check for news id
if(result.rows.length === 1) {// use update
result = tx.executeSql('UPDATE contacts SET username="'+login.username+'", id='+contact.id+', name="'+Qt.btoa(contact.name)+'", screen_name="'+contact.screen_name+'", location="'+contact.location+'",description="'+Qt.btoa(contact.description)+'", profile_image="'+imagename+'", url="'+contact.url+'" , protected="'+contact.protected+'", followers_count='+contact.followers_count+', friends_count='+contact.friends_count+', created_at="'+ Newsjs.cleanDate(contact.created_at)+'", favourites_count="'+contact.favorites_count+'", utc_offset="'+contact.utc_offset+'", time_zone="'+contact.time_zone+'", statuses_count='+contact.statuses_count+', following="'+contact.following+'", verified ="'+contact.verified+'", statusnet_blocking="'+contact.statusnet_blocking+'", notifications="'+contact.notifictions+'", statusnet_profile_url="'+contact.statusnet_profile_url+'", cid='+contact.cid+', network="'+contact.network+'", isFriend='+isFriend+' where id='+contact.id);
} else {// use insert
result = tx.executeSql('INSERT INTO contacts VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)', [login.username,contact.id,Qt.btoa(contact.name),contact.screen_name,contact.location,Qt.btoa(contact.description),imagename,contact.url,contact.protected,contact.followers_count, contact.friends_count,Newsjs.cleanDate(contact.created_at),contact.favorites_count,contact.utc_offset,contact.time_zone,contact.statuses_count,contact.following,contact.verfied,contact.statusnet_blocking,contact.notifications,contact.statusnet_profile_url,contact.cid,contact.network,isFriend]);}
});
}
Component.onCompleted: {
if (login==""){Service.initDatabase(db)}
Helperjs.readField("id",db,"contacts",login.username,function(contacts){contactlist=contacts},"isFriend",1)
}
Tab{
title: qsTr("News")
id: newstab
property string newstabStatus:"news"
source: "qrc:/qml/NewsTab.qml"
}
Tab{
title: qsTr("Contacts")
id: friendstab
source: "qrc:/qml/FriendsTab.qml"
}
Tab{
title: qsTr("Photos")
id: fotostab
source: "qrc:/qml/PhotoTab.qml"
}
Tab{
title: qsTr("Config")
source: "qrc:/qml/ConfigTab.qml"
}
}

View File

@ -0,0 +1,24 @@
<RCC>
<qresource prefix="/">
<file>js/layout.js</file>
<file>js/photoworker.js</file>
<file>js/service.js</file>
<file>qml/FriendComponent.qml</file>
<file>qml/MessageSend.qml</file>
<file>qml/Newsitem.qml</file>
<file>qml/PhotoComponent.qml</file>
<file>qml/PhotogroupComponent.qml</file>
<file>qml/PhotoPlaceholder.qml</file>
<file>qml/friendiqa.qml</file>
<file>qml/PhotoTab.qml</file>
<file>qml/ConfigTab.qml</file>
<file>qml/FriendsTab.qml</file>
<file>qml/NewsTab.qml</file>
<file>js/news.js</file>
<file>js/newsworker.js</file>
<file>js/helper.js</file>
<file>images/defaultcontact.jpg</file>
<file>qml/InfoBox.qml</file>
<file>qml/GroupComponent.qml</file>
</qresource>
</RCC>

View File

@ -0,0 +1,49 @@
#include "filesystem.h"
FILESYSTEM *FILESYSTEM::instance()
{
static FILESYSTEM filesystem;
return &filesystem;
}
FILESYSTEM::FILESYSTEM(QObject *parent) : QObject(parent){}
void FILESYSTEM::setDirectory(QString Directory)
{
if (Directory!=m_Directory) {
m_Directory = Directory;
emit directoryChanged();
}
}
QString FILESYSTEM::Directory() const
{
return m_Directory;
}
void FILESYSTEM::makeDir(QString name)
{
QDir dir(m_Directory);
if (dir.mkdir(name)){
emit success(name);
}
else {emit error(name,1);}
}
void FILESYSTEM::rmDir(QString name)
{
QDir dir(m_Directory);
if (dir.rmdir(name)){
emit success(name);
}
else {emit error(name,1);}
}
void FILESYSTEM::rmFile(QString name)
{
QDir dir(m_Directory);
if(dir.remove(name)){
emit success(name);
}
else {emit error(name,1);}
}

View File

@ -0,0 +1,49 @@
#ifndef FILESYSTEM_H
#define FILESYSTEM_H
#include <QDir>
#include <QObject>
class FILESYSTEM : public QObject
{
Q_OBJECT
Q_PROPERTY(QString Directory READ Directory WRITE setDirectory NOTIFY directoryChanged)
public:
static FILESYSTEM *instance();
explicit FILESYSTEM(QObject *parent = 0);
void setDirectory(QString Directory);
QString Directory() const;
signals:
void directoryChanged();
void success(QString data);
void error(QString data, int code);
public slots:
//void setDirectory(QString Directory);
void makeDir(QString name);
void rmDir(QString name);
void rmFile(QString name);
private slots:
//void onReplyError(QNetworkReply::NetworkError code);
// void onReplySuccess();
//void onReadyRead();
// void onSSLError(const QList<QSslError> &errors);
private:
//QByteArray buffer;
QString m_Directory;
//QString m_login;
//QHash<QString, QString> params;
//QHash<QString, QString> files;
//QNetworkAccessManager manager;
//QNetworkRequest request;
//QNetworkReply *reply;
//QString bufferToString();
};
#endif // FILSYSTEM_H

View File

@ -0,0 +1,22 @@
#include <QApplication>
#include <QtQml/QQmlEngine>
#include <QtQuick>
#include "xhr.h"
#include "filesystem.h"
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
QQuickView view;
XHR* xhr = XHR::instance();
view.rootContext()->setContextProperty("xhr", xhr);
FILESYSTEM* filesystem = FILESYSTEM::instance();
view.rootContext()->setContextProperty("filesystem", filesystem);
view.setSource(QUrl("qrc:/qml/friendiqa.qml"));
view.show();
view.connect(view.rootContext()->engine(), SIGNAL(quit()), &app, SLOT(quit()));
return app.exec();
}

View File

@ -0,0 +1,90 @@
#include "uploadableimage.h"
#include <QBuffer>
#include <QDebug>
#include <QFileInfo>
#include <QUrl>
void UploadableImage::setSource(const QString &a) {
if (a != m_source) {
m_source = a;
//m_base64 = "";
m_mimetype = "";
m_filename = "";
qDebug() << "UploadableImage::setSource : " << m_source;
if (m_source=="") {
emit sourceChanged();
//emit base64Changed();
emit mimetypeChanged();
emit filenameChanged();
return;
}
QImage fullimage = QImage(QUrl(m_source).toLocalFile());
if (fullimage.width() > 800 || fullimage.height() > 800) {
if (fullimage.width() > fullimage.height()) {
m_image = fullimage.scaledToWidth(800);
} else {
m_image = fullimage.scaledToHeight(800);
}
} else {
m_image = fullimage;
}
qDebug() << "UploadableImage::setSource : " << m_image.width() << "x" << m_image.height();
emit sourceChanged();
QFileInfo fi(m_source);
m_filename = fi.fileName();
emit filenameChanged();
QString filetype = fi.suffix().toUpper();
if (filetype!="PNG" && filetype!="JPG") {
filetype = "JPG";
}
qDebug() << "UploadableImage::setSource : " << "Saving as " << filetype;
m_mimetype = "image/"+filetype.toLower();
emit mimetypeChanged();
/*
QByteArray byteArray;
QBuffer buffer(&byteArray);
m_image.save(&buffer, filetype.toLatin1().constData());
QString b64 = QString::fromLatin1(byteArray.toBase64().data());
for(int k=0; k<b64.length(); k+=76) {
m_base64 += b64.mid(k,76) + "\n";
}
m_base64 = m_base64.trimmed();
emit base64Changed();
*/
}
}
QString UploadableImage::source() const {
return m_source;
}
//QString UploadableImage::base64() const {
// return m_base64;
//}
QString UploadableImage::filename() const {
return m_filename;
}
QString UploadableImage::mimetype() const {
return m_mimetype;
}
QByteArray UploadableImage::bytes() {
QByteArray byteArray;
QBuffer buffer(&byteArray);
m_image.save(&buffer, "PNG");
return byteArray;
}

View File

@ -0,0 +1,40 @@
#ifndef UPLOADABLEIMAGE_H
#define UPLOADABLEIMAGE_H
#include <QObject>
#include <QQuickItem>
#include <QImage>
class UploadableImage : public QObject
{
Q_OBJECT
Q_PROPERTY(QString source READ source WRITE setSource NOTIFY sourceChanged)
//Q_PROPERTY(QString base64 READ base64 NOTIFY base64Changed)
Q_PROPERTY(QString filename READ filename NOTIFY filenameChanged)
Q_PROPERTY(QString mimetype READ mimetype NOTIFY mimetypeChanged)
Q_PROPERTY(QByteArray bytes READ bytes)
public:
void setSource(const QString &a);
QString source() const;
//QString base64() const;
QString filename() const;
QString mimetype() const;
QByteArray bytes();
signals:
void sourceChanged();
//void base64Changed();
void filenameChanged();
void mimetypeChanged();
private:
QString m_source;
QImage m_image;
//QString m_base64;
QString m_filename;
QString m_mimetype;
};
#endif // UPLOADABLEIMAGE_H

View File

@ -0,0 +1,168 @@
#include "xhr.h"
#include <QHttpPart>
#include <QTextCodec>
#include <QUrlQuery>
#include "uploadableimage.h"
XHR *XHR::instance()
{
static XHR xhr;
return &xhr;
}
XHR::XHR(QObject *parent) : QObject(parent)
{
request.setSslConfiguration(QSslConfiguration::defaultConfiguration());
}
void XHR::setUrl(QString url)
{
if (url!=m_url) {
m_url = url;
emit urlChanged();
}
}
void XHR::setLogin(QString login)
{
if (login!=m_login) {
m_login = login;
emit loginChanged();
}
}
QString XHR::url() const
{
return m_url;
}
QString XHR::login() const
{
return m_login;
}
void XHR::setParam(QString name, QString value)
{
params.insert(name, value);
}
void XHR::setImageFileParam(QString name, QString url)
{
files.insert(name, url);
}
void XHR::clearParams()
{
files.clear();
params.clear();
}
void XHR::get()
{
QUrlQuery query;
QHashIterator<QString, QString> i(params);
while(i.hasNext()) {
i.next();
query.addQueryItem(i.key(), i.value());
}
QUrl requrl(m_url);
requrl.setQuery(query);
QByteArray loginData = m_login.toLocal8Bit().toBase64();
QString headerData = "Basic " + loginData;
request.setRawHeader("Authorization", headerData.toLocal8Bit());
request.setUrl(requrl);
reply = manager.get(request);
connect(reply, &QNetworkReply::finished, this, &XHR::onReplySuccess);
connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(onReplyError(QNetworkReply::NetworkError)));
connect(reply, &QNetworkReply::readyRead, this, &XHR::onReadyRead);
}
void XHR::post()
{
qDebug() << "start post to " << m_url;
QHttpMultiPart *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);
QHashIterator<QString, QString> iparams(params);
while(iparams.hasNext()) {
iparams.next();
qDebug() << "\t add param " << iparams.key() << " : " << iparams.value();
QHttpPart textPart;
textPart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"" + iparams.key() + "\""));
textPart.setBody(iparams.value().toUtf8());
multiPart->append(textPart);
}
UploadableImage uimg;
QHashIterator<QString, QString> ifiles(files);
while(ifiles.hasNext()) {
ifiles.next();
uimg.setSource(ifiles.value());
qDebug() << "\t image: " << uimg.mimetype() << ", " << ifiles.key();
QHttpPart imagePart;
imagePart.setHeader(QNetworkRequest::ContentTypeHeader, QVariant(uimg.mimetype()));
imagePart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"" + ifiles.key() + "\"; filename=\""+uimg.filename()+"\""));
imagePart.setBody(uimg.bytes());
multiPart->append(imagePart);
}
QByteArray loginData = m_login.toLocal8Bit().toBase64();
QString headerData = "Basic " + loginData;
request.setRawHeader(QByteArray("Authorization"), headerData.toLocal8Bit());
request.setUrl(m_url);
reply = manager.post(request, multiPart);
qDebug() << "\t request sent";
connect(reply, &QNetworkReply::finished, this, &XHR::onReplySuccess);
connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(onReplyError(QNetworkReply::NetworkError)));
connect(reply, &QNetworkReply::readyRead, this, &XHR::onReadyRead);
connect(reply, &QNetworkReply::sslErrors, this, &XHR::onSSLError);
qDebug() << "\t reply signals connected";
}
void XHR::onReplyError(QNetworkReply::NetworkError code)
{
qDebug() << code;
emit this->error( bufferToString(), (int) code);
reply->deleteLater();
}
void XHR::onReplySuccess()
{
qDebug() << "!";
emit this->success( bufferToString() );
reply->deleteLater();
}
void XHR::onReadyRead()
{
qDebug() << ".";
buffer += reply->readAll();
}
void XHR::onSSLError(const QList<QSslError> &errors)
{
qDebug() << "XHR::onSSLError :" ;
QListIterator<QSslError> ierrs(errors);
while(ierrs.hasNext()) {
qDebug() << "\t" << ierrs.next().errorString();
}
}
QString XHR::bufferToString()
{
return QTextCodec::codecForName("utf-8")->toUnicode(buffer);
}

View File

@ -0,0 +1,60 @@
#ifndef XHR_H
#define XHR_H
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QNetworkRequest>
#include <QObject>
class XHR : public QObject
{
Q_OBJECT
Q_PROPERTY(QString url READ url WRITE setUrl NOTIFY urlChanged)
Q_PROPERTY(QString login READ login WRITE setLogin NOTIFY loginChanged)
public:
static XHR *instance();
explicit XHR(QObject *parent = 0);
void setUrl(QString url);
// void setLogin(QString login);
QString url() const;
QString login() const;
signals:
void urlChanged();
void loginChanged();
void success(QString data);
void error(QString data, int code);
public slots:
void setLogin(QString login);
void setParam(QString name, QString value);
void setImageFileParam(QString name, QString url);
void clearParams();
void post();
void get();
private slots:
void onReplyError(QNetworkReply::NetworkError code);
void onReplySuccess();
void onReadyRead();
void onSSLError(const QList<QSslError> &errors);
private:
QByteArray buffer;
QString m_url;
QString m_login;
QHash<QString, QString> params;
QHash<QString, QString> files;
QNetworkAccessManager manager;
QNetworkRequest request;
QNetworkReply *reply;
QString bufferToString();
};
#endif // XHR_H

View File

@ -0,0 +1,40 @@
# NOTICE:
#
# Application name defined in TARGET has a corresponding QML filename.
# If name defined in TARGET is changed, the following needs to be done
# to match new name:
# - corresponding QML filename must be changed
# - desktop icon filename must be changed
# - desktop filename must be changed
# - icon definition filename in desktop file must be changed
# - translation filenames have to be changed
# The name of your application
TARGET = friendiqa
CONFIG += debug
QT += qml quick gui widgets
SOURCES += common/friendiqa.cpp \
common/uploadableimage.cpp \
common/xhr.cpp \
common/filesystem.cpp
RESOURCES = application.qrc
OTHER_FILES += qml/friendiqa.qml \
translations/*.ts \
qml/*.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
HEADERS += \
common/uploadableimage.h \
common/xhr.h \
common/filesystem.h

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -0,0 +1,12 @@
WorkerScript.onMessage = function(msg) {
msg.model.clear();
for (var j=0;j<msg.albums.length;j++){
if (msg.albums[j]) {
var albumobject=msg.albums[j];
var data=({"albumobject": albumobject,"foreignPicture": msg.foreignPicture})}
// print("Albums:"+j+msg.albums.length+JSON.stringify(data));
msg.model.append(data);}
if (j==msg.albums.length){
msg.model.sync()
};
}

View File

@ -0,0 +1,111 @@
.pragma library
.import QtQuick.LocalStorage 2.0 as Sql
function friendicaRequest(login,api,rootwindow,callback) {
var xhrequest= new XMLHttpRequest();
xhrequest.onreadystatechange = function() {
if (xhrequest.readyState === XMLHttpRequest.HEADERS_RECEIVED) {
} else if(xhrequest.readyState === XMLHttpRequest.DONE) {
try{ if (xhrequest.responseText!=""){
callback(xhrequest.responseText)
}else{
showMessage("Error",api+" NO RESPONSE",rootwindow)
callback(xhrequest.responseText)
}
}
catch (e){
showMessage("Error", api+" "+e,rootwindow)
}
}
}
xhrequest.open("GET", login.server+api,true,login.username,Qt.atob(login.password));
xhrequest.send();
}
function friendicaPostRequest(login,api,rootwindow,callback) {
var xhrequest= new XMLHttpRequest();
xhrequest.onreadystatechange = function() {
if (xhrequest.readyState === XMLHttpRequest.HEADERS_RECEIVED) {
} else if(xhrequest.readyState === XMLHttpRequest.DONE) {
try{ if (xhrequest.responseText!=""){
callback(xhrequest.responseText)
}else{
showMessage("Error",api+" NO RESPONSE",rootwindow)
callback(xhrequest.responseText)
}
}
catch (e){
showMessage("Error", api+" "+e,rootwindow)
}
}
}
xhrequest.open("POST", login.server+api,true,login.username,Qt.atob(login.password));
xhrequest.send();
}
function friendicaWebRequest(url,rootwindow,callback) {
var xhrequest = new XMLHttpRequest();
xhrequest.onreadystatechange = function() {
if (xhrequest.readyState === XMLHttpRequest.HEADERS_RECEIVED) {
} else if(xhrequest.readyState === XMLHttpRequest.DONE) {
try{ callback(xhrequest.responseText);
}
catch (e){
showMessage("Error",url+" "+e, rootwindow)
}
}
}
xhrequest.open("GET", url,true);
xhrequest.send();
}
function readData(database,table,username,callback,filter,filtervalue) { // reads and applies data from DB
if (filter){
var where = " AND "+ filter +" = '" + filtervalue+"'";
} else { var where="";}
var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
if(!db) { return; }
db.transaction( function(tx) {
// print('select * from '+table'+where username= "'+username+'"'+'where);
var rsArray=[];
var rs = tx.executeSql('select * from '+table+' where username= "'+username+'"'+where);
for(var i = 0; i < rs.rows.length; i++) {
rsArray.push(rs.rows.item(i))
}
callback(rsArray);
});
}
function readField(field,database,table, username, callback,filter,filtervalue) { // reads and applies data from DB
if (filter){
var where = " AND "+ filter +" = '" + filtervalue+"'";
} else { var where="";}
var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
if(!db) { return; }
db.transaction( function(tx) {
// print('... read from database ' + field)
var rsArray=[];
print('select DISTINCT '+field+' from '+table+' WHERE username="'+username+'"'+where+' ORDER BY '+field+' ASC');
var rs = tx.executeSql('select DISTINCT '+field+' from '+table+' WHERE username="'+username+'"'+where+' ORDER BY '+field+' ASC');
for(var i = 0; i < rs.rows.length; i++) {
rsArray.push(rs.rows.item(i)[field])
}
callback(rsArray);
});
}
function showMessage(header,message,rootwindow){
var messageString='import QtQuick 2.0; import QtQuick.Dialogs 1.2; MessageDialog{ visible: true; title:"'+header+'";standardButtons: StandardButton.Ok; text:" '+message+'"}';
var messageObject=Qt.createQmlObject(messageString,rootwindow,"messageOutput");
}
function inArray(list, prop, val) {
if (list.length > 0 ) {
for (var i in list) { if (list[i][prop] === val) {
return i;
}
}
} return -1;
}

View File

@ -0,0 +1,44 @@
function showFriends(db) {
Service.readActiveConfig(db,function(login){
Service.requestFriends(login.url,login.user,login.password,displayFriends);
});
}
function displayFriends(obj){
for (var i=0; i<obj.length; i++){
print(obj[i]);
if (obj[i]) {friendsModel.append({"friendName": obj[i]});
};
}}
function ensureVisibility(c,f)
{
if (f.contentX >= c.x)
f.contentX = c.x;
else if (f.contentX+f.width <= c.x+c.width)
f.contentX = c.x+c.width-f.width;
if (f.contentY >= c.y)
f.contentY = c.y;
else if (f.contentY+f.height <= c.y+c.height)
f.contentY = c.y+c.height-f.height;
}
function createObject(objectQml,qmlParameters,parentitem,callback) {
var component = Qt.createComponent(objectQml);
if (component.status === Component.Ready || component.status === Component.Error)
finishCreation(component,qmlParameters,parentitem,callback);
else
component.statusChanged.connect(finishCreation(qmlParameters));
}
function finishCreation(component,qmlParameters,parentitem,callback) {
if (component.status === Component.Ready) {
var createdObject = component.createObject(parentitem, qmlParameters);
if (createdObject === null)
print("Error creating image"); }
else if (component.status === Component.Error)
print("Error loading component:"+component.errorString());
else {print("created")}
callback(createdObject);
}

View File

@ -0,0 +1,311 @@
.pragma library
.import QtQuick.LocalStorage 2.0 as Sql
.import "qrc:/js/helper.js" as Helperjs
function requestFriends(login,database,rootwindow,callback){
// return array of friends
Helperjs.friendicaRequest(login,"/api/statuses/friends", rootwindow,function (obj){
var friends=JSON.parse(obj);
for (var i=0;i<friends.length;i++){ friends[i].isFriend=1}
callback(friends)
});
}
function requestGroups(login,database,rootwindow,callback){
// retrieve, save and return groups, currently not implemented
var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
Helperjs.friendicaRequest(login,"/api/friendica/group_show",rootwindow, function (obj){
var groups=JSON.parse(obj);
for (var i=0;i<groups.length;i++){
var memberarray=[]; for (var user in groups[i].user){memberarray.push(parseInt(groups[i].user[user].id))}
//print("Members: "+groups[i].user)
//updateGroupInDB(login,database,groups[i])
db.transaction( function(tx) {
var result = tx.executeSql('SELECT * from groups where username="'+login.username+'" AND gid = "'+groups[i].gid+'"'); // check for group id
if(result.rows.length === 1) {// use update
print(groups[i].gid +' exists, update it')
result = tx.executeSql('UPDATE groups SET username="'+login.username+'", groupname="'+groups[i].name+'", members="'+JSON.stringify(memberarray)+'"');
} else {// use insert
result = tx.executeSql('INSERT INTO groups VALUES (?,?,?,?)', [login.username,groups[i].name,groups[i].gid,JSON.stringify(memberarray)])}
});
}
//Helperjs.readData(database,"groups",login.username,callback)
callback()
});}
function getFriendsTimeline(login,database,contacts,rootwindow,callback){// retrieve and return timeline since last news, return contacts which are not friends for update (friends can be updated in Friendstab)
var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
var parameter = "";
db.transaction( function(tx) {
var result = tx.executeSql('SELECT status_id from news WHERE username="'+login.username+'" ORDER BY status_id DESC LIMIT 1'); // check for last news id
try{parameter="&since_id="+result.rows.item(0).status_id;}catch(e){};})
var newContacts=[];
Helperjs.friendicaRequest(login,"/api/statuses/friends_timeline"+parameter, rootwindow,function (obj){
var news=JSON.parse(obj);
for (var i=0;i<news.length;i++){
if(contacts.indexOf(news[i].user.id)==-1 && !(inArray(newContacts,"id",news[i].user.id))){
news[i].user.isFriend=0;
newContacts.push(news[i].user);
}
if (news[i].friendica_activities.like.length>0){
print("Like Contact"+JSON.stringify(news[i].friendica_activities.like));
for (var j=0;j<news[i].friendica_activities.like.length;j++){
if(contacts.indexOf(news[i].friendica_activities.like[j].id)==-1 && !(inArray(newContacts,"id",news[i].friendica_activities.like[j].id))){
news[i].friendica_activities.like[j].isFriend=0;
newContacts.push(news[i].friendica_activities.like[j]);
}
}
}
if (news[i].friendica_activities.dislike.length>0){
print("DisLike Contact"+JSON.stringify(news[i].friendica_activities.dislike));
for (var k=0;j<news[k].friendica_activities.dislike.length;k++){
if(contacts.indexOf(news[i].friendica_activities.dislike[k].id)==-1 && !(inArray(newContacts,"id",news[i].friendica_activties.dislike[k].id))){
news[i].friendica_activities.dislike[k].isFriend=0;
newContacts.push(news[i].friendica_activities.dislike[k]);
}
}
}
}
callback(news,newContacts)
})}
function storeNews(login,database,news,rootwindow,callback){
// save news after contacts download, call next function
var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
for (var i=0;i<news.length;i++){
print('store news data for ' + news[i].id+JSON.stringify(news[i].friendica_activities));
var ausdruck=news[i];
var likearray=[]; for (var user in news[i].friendica_activities.like){likearray.push(parseInt(news[i].friendica_activities.like[user].id))}
var dislikearray=[]; for (var user in news[i].friendica_activities.dislike){parseInt(news[i].friendica_activities.dislike[user].id)}
var attendyesarray=[]; for (var user in news[i].friendica_activities.attendyes){attendyesarray.push(parseInt(news[i].friendica_activities.attendyes[user].id))}
var attendnoarray=[]; for (var user in news[i].friendica_activities.attendno){attendnoarray.push(parseInt(news[i].friendica_activities.attendno[user].id))}
var attendmaybearray=[]; for (var user in news[i].friendica_activities.attendmaybe){attendmaybearray.push(parseInt(news[i].friendica_activities.attendmaybe[user].id))}
db.transaction( function(tx) {
var result = tx.executeSql('SELECT * from news where status_id = "'+news[i].id+'"'); // check for news id
if(result.rows.length === 1) {// use update
print(news[i].id +' exists, update it')
result = tx.executeSql('UPDATE news SET username="'+login.username+'", messagetype=0, text="'+Qt.btoa(news[i].text)+'", created_at="'+Date.parse(cleanDate(news[i].created_at))+'", in_reply_to_status_id="'+news[i].in_reply_to_status_id+'", source="'+news[i].source+'", status_id="'+news[i].id+'", in_reply_to_user_id="'+news[i].in_reply_to_user_id+'", geo="'+news[i].geo+'", favorited="'+news[i].favorited+'", uid="'+news[i].user.id+'", statusnet_html="'+Qt.btoa(news[i].status_html)+'", statusnet_conversation_id="'+news[i].statusnet_conversation_id+'",like="'+JSON.stringify(likearray)+'", dislike="'+JSON.stringify(dislikearray)+'", attendyes="'+JSON.stringify(attendyesarray)+'",attendno="'+JSON.stringify(attendnoarray)+'",attendmaybe="'+JSON.stringify(attendmaybearray)+'" where status_id="'+news[i].status_id+'"');
} else {// use insert
result = tx.executeSql('INSERT INTO news (username,messagetype,text,created_at,in_reply_to_status_id,source,status_id,in_reply_to_user_id,geo,favorited,uid,statusnet_html,statusnet_conversation_id,like,dislike,attendyes,attendno,attendmaybe) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)', [login.username,0,Qt.btoa(news[i].text),Date.parse(cleanDate(news[i].created_at)), news[i].in_reply_to_status_id, news[i].source, news[i].id,news[i].in_reply_to_user_id,news[i].geo,news[i].favorited, news[i].user.id,Qt.btoa(news[i].statusnet_html),news[i].statusnet_conversation_id, JSON.stringify(likearray),JSON.stringify(dislikearray),JSON.stringify(attendyesarray),JSON.stringify(attendnoarray),JSON.stringify(attendmaybearray)])}})
}
getDirectMessage(login,database,rootwindow,callback)
}
function getDirectMessage(login,database,rootwindow,callback){
var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
Helperjs.friendicaRequest(login,"/api/direct_messages/all",rootwindow, function (obj){
var messages=JSON.parse(obj);
for (var i=0;i<messages.length;i++){
// print('store message data for '+JSON.stringify(messages[i]));
db.transaction( function(tx) {
var result = tx.executeSql('SELECT * from news where status_id = "'+messages[i].id+'"'); // check for news id
if(result.rows.length === 1) {// use update
print(messages[i].id +' exists, update it')
result = tx.executeSql('UPDATE news SET username="'+login.username+'", messagetype=1, text="'+Qt.btoa(messages[i].text)+'", created_at="'+Date.parse(cleanDate(messages[i].created_at))+'", source="Friendica", status_id="'+messages[i].id+'", uid="'+messages[i].sender.id+'", statusnet_html="'+Qt.btoa(messages[i].text)+'" where status_id="'+messages[i].status_id+'"');
} else {// use insert
result = tx.executeSql('INSERT INTO news (username,messagetype,text,created_at,source,status_id,uid,statusnet_html) VALUES (?,?,?,?,?,?,?,?)', [login.username,1,Qt.btoa(messages[i].text),Date.parse(cleanDate(messages[i].created_at)), "Friendica", messages[i].id, messages[i].sender.id,Qt.btoa(messages[i].text)])}
});
}
})
getNotifications(login,database,rootwindow,callback)
}
function getNotifications(login,database,rootwindow,callback){
Helperjs.friendicaRequest(login,"/api/friendica/notifications", rootwindow,function (obj){
var messages=JSON.parse(obj);
for (var i=0;i<messages.length;i++){
var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
//print('store message data for '+JSON.stringify(messages[i]));
db.transaction( function(tx) {
var result = tx.executeSql('SELECT * from news where status_id = "'+messages[i].id+'"'); // check for news id
if(result.rows.length === 1) {// use update
print(messages[i].id +' exists, update it')
result = tx.executeSql('UPDATE news SET username="'+login.username+'", messagetype=2, text="'+Qt.btoa(messages[i].msg_html)+'", created_at="'+messages[i].timestamp+'", source="Friendica", status_id="'+messages[i].id+'", uid="'+messages[i].uid+'", statusnet_html="'+Qt.btoa(messages[i].msg_html)+'", statusnet_conversation_id="'+messages[i].parent+'" where status_id="'+messages[i].id+'"');
} else {// use insert
result = tx.executeSql('INSERT INTO news (username,messagetype,text,created_at,source,status_id, uid,statusnet_html,statusnet_conversation_id) VALUES (?,?,?,?,?,?,?,?,?)', [login.username,2,Qt.btoa(messages[i].msg_html),messages[i].timestamp,"Friendica", messages[i].id, messages[i].uid,Qt.btoa(messages[i].msg_html),messages[i].parent])}
});
}
})
newsfromdb(database,login.username,callback)
}
function newsfromdb(database,username,callback,contact,stop_time){
// return news before stop_time (used by More button), in brackets of 20 entries, or by specified contact
var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
db.transaction( function(tx) {
if (!stop_time){var stop="";
try{var rs = tx.executeSql('select created_at from news WHERE username="'+username+'" ORDER BY created_at DESC LIMIT 1');
stop="<="+rs.rows.item(0).created_at}catch(e){stop="<99999999999999"}}
else{var stop="<"+stop_time}
var contactfilter="";if(contact){contactfilter=" AND uid='"+contact+"'"}
var newsrs=tx.executeSql('select * from news WHERE username="'+username+'" AND created_at'+stop+contactfilter+' ORDER BY created_at DESC LIMIT 20');
var newsArray=[];
for(var i = 0; i < newsrs.rows.length; i++) {
newsArray.push(newsrs.rows.item(i));
Helperjs.readData(database,"contacts",username,function(userdata){
newsArray[i].user=userdata[0];
},"id",newsArray[i].uid);
if(newsArray[i].in_reply_to_user_id){
Helperjs.readData(database,"contacts",username,function(replytodata){
newsArray[i].reply_user=replytodata[0];
},"id",newsArray[i].in_reply_to_user_id);
}
if (newsArray[i].messagetype==0){
//userdata for likes
var likeArray=JSON.parse(newsArray[i].like);
var likeHelper=[];
for (var j=0;j<likeArray.length;j++){
Helperjs.readData(database,"contacts",username,function(userdata){
likeHelper[j]=userdata[0];
},"id",likeArray[j]);
}
newsArray[i].like=likeHelper;
//userdata for dislikes
var dislikeArray=JSON.parse(newsArray[i].dislike);
var dislikeHelper=[];
for (var k=0;k<dislikeArray.length;k++){
Helperjs.readData(database,"contacts",username,function(userdata){
dislikeHelper[j]=userdata[0];
},"id",dislikeArray[k]);
}
newsArray[i].dislike=dislikeHelper;
//userdata for attendyes
var attendyesArray=JSON.parse(newsArray[i].attendyes);
var attendyesHelper=[];
for (var l=0;l<attendyesArray.length;l++){
Helperjs.readData(database,"contacts",username,function(userdata){
attendyesHelper[j]=userdata[0];
},"id",attendyesArray[l]);
}
newsArray[i].attendyes=attendyesHelper;
//userdata for attendno
var attendnoArray=JSON.parse(newsArray[i].attendno);
var attendnoHelper=[];
for (var m=0;m<attendnoArray.length;m++){
Helperjs.readData(database,"contacts",username,function(userdata){
attendnoHelper[j]=userdata[0];
},"id",attendnoArray[m]);
}
newsArray[i].attendno=attendnoHelper;
//userdata for attendmaybe
var attendmaybeArray=JSON.parse(newsArray[i].attendmaybe);
var attendmaybeHelper=[];
for (var n=0;n<attendmaybeArray.length;n++){
Helperjs.readData(database,"contacts",username,function(userdata){
attendmaybeHelper[j]=userdata[0];
},"id",attendmaybeArray[l]);
}
newsArray[i].attendmaybe=attendmaybeHelper;
}
}
callback(newsArray)});
}
function deleteNews(login,database,newsid,rootwindow,callback){
Helperjs.friendicaPostRequest(login,"/api/statuses/destroy?id="+newsid, rootwindow,function (obj){
print("Delete "+obj);
var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
print('delete news data for ' + newsid);
db.transaction( function(tx) {var result = tx.executeSql('DELETE from news where status_id ='+newsid); // delete news id
Helperjs.showMessage("Delete",result,rootwindow)});
})}
function retweetNews(login,database,newsid,rootwindow,callback){
Helperjs.friendicaRequest(login,"/api/statuses/retweet?id="+newsid, rootwindow,function (obj){
var answer=JSON.parse(obj);
Helperjs.showMessage("Repost",answer,rootwindow);
})}
function favorite(login,favorite,newsid,rootwindow){
// toggle favorites
if(favorite){ Helperjs.friendicaPostRequest(login,"/api/favorites/create?id="+newsid, rootwindow,function (obj){
print("Favorite "+obj);
})}
else {Helperjs.friendicaPostRequest(login,"/api/favorites/destroy?id="+newsid, rootwindow,function (obj){
print("Favorite destroyed "+obj);
})}
}
function likerequest(login,database,toggle,verb,newsid,rootwindow){
Helperjs.friendicaPostRequest(login,"/api/friendica/activity/"+verb+"?id="+newsid, rootwindow,function (obj){
print("likereturn "+obj);
if (obj=='"ok"'){
var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
db.transaction( function(tx) {var result = tx.executeSql('UPDATE news SET '+verb+'d ='+toggle+' where status_id ='+newsid);
})}})
}
function like(login,database,toggle,verb,newsid,rootwindow){
if(verb=="like"&& toggle==1){
likerequest(login,database,1,"like",newsid,rootwindow);
likerequest(login,database,0,"undislike",newsid,rootwindow);}
if(verb=="dislike"&& toggle==1){
likerequest(login,database,1,"dislike",newsid,rootwindow);
likerequest(login,database,0,"unlike",newsid,rootwindow);}
if(toggle==0){
likerequest(login,database,0,"un"+verb,newsid,rootwindow);}
}
function attend(login,database,attend,newsid,rootwindow,callback){
Helperjs.friendicaPostRequest(login,"/api/friendica/activity/attend"+attend+"?id="+newsid, rootwindow,function (obj){
var attendReturn=JSON.parse(obj);
// print("attend: "+obj);
//if (attendReturn=="OK")
{
var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
db.transaction( function(tx) {var result = tx.executeSql('UPDATE news SET attend="+attend+" where status_id ='+newsid);
callback();
})}})}
function requestConversation(login,database,newsid,rootwindow,callback){
Helperjs.friendicaRequest(login,"/api/conversation/show?id="+newsid,rootwindow, function (obj){
print(obj+JSON.stringify(obj));
var news=JSON.parse(obj);
for (var i=0;i<news.length;i++){
var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
print('store news data for ' + news[i].id);
db.transaction( function(tx) {
var result = tx.executeSql('SELECT * from news where status_id = "'+news[i].id+'"'); // check for news id
if(result.rows.length === 1) {// use update
print(news[i].id +' exists, update it')
result = tx.executeSql('UPDATE news SET username="'+login.username+'", messagetype=0, text="'+Qt.btoa(news[i].text)+'", truncated="'+news[i].truncated+'", created_at="'+Date.parse(cleanDate(news[i].created_at))+'", in_reply_to_status_id="'+news[i].in_reply_to_status_id+'", source="'+news[i].source+'", status_id="'+news[i].id+'", in_reply_to_user_id="'+news[i].in_reply_to_user_id+'", geo="'+news[i].geo+'", favorited="'+news[i].favorited+'", uid="'+news[i].user.id+'", statusnet_html="'+Qt.btoa(news[i].status_html)+'", statusnet_conversation_id="'+news[i].statusnet_conversation_id+'", attachments="'+news[i].attachments+'" where status_id="'+news[i].status_id+'"');
} else {// use insert
result = tx.executeSql('INSERT INTO news VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)', [login.username,0,Qt.btoa(news[i].text),news[i].truncated,Date.parse(cleanDate(news[i].created_at)), news[i].in_reply_to_status_id, news[i].source, news[i].id,news[i].in_reply_to_user_id,news[i].geo,news[i].favorited, news[i].user.id,Qt.btoa(news[i].statusnet_html),news[i].statusnet_conversation_id, news[i].attachments,0,0,0]);
}});
if(news[i].user.following!=true){
updateContactInDB(login,database,rootwindow,news[i].user)}
}
callback();
}
);}
function conversationfromdb(database,user,conversationId,callback){
var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
db.transaction( function(tx) {
print('select * from news WHERE statusnet_conversation_id='+conversationId+' ORDER BY status_id DESC');
var newsrs=tx.executeSql('select * from news WHERE statusnet_conversation_id='+conversationId+' ORDER BY status_id DESC');
var newsArray=[];
for(var i = 0; i < newsrs.rows.length; i++) {
newsArray.push(newsrs.rows.item(i))
Helperjs.readData(database,"contacts",function(userdata){
newsArray[i].user=userdata[0];
},"id",newsArray[i].uid);
}
callback(newsArray);
});}
function inArray(list, prop, val) {
if (list.length > 0 ) {
for (var i in list) { if (list[i][prop] === val) {
return true;
}
}
} return false;
}
function cleanDate(date){
var cleanedDate= date.slice(0,3)+", "+date.slice(8,11)+date.slice(4,7)+date.slice(25,30)+date.slice(10,25);
return cleanedDate
}

View File

@ -0,0 +1,48 @@
WorkerScript.onMessage = function(msg) {
if(msg.appendnews!==true){ msg.model.clear()};
for (var j=0;j<msg.news.length;j++){
if (msg.news[j]) {
var newsitemobject=msg.news[j];
var likeText="";var dislikeText="";var attendyesText="";var attendnoText="";var attendmaybeText="";
if (newsitemobject.messagetype==0){
if (msg.news[j].like.length>0){
if (msg.news[j].like.length==1){likeText= Qt.atob(msg.news[j].like[0].name)+" "+ qsTr("likes this.")}
else {likeText= msg.news[j].like.length+" "+ qsTr("like this.")}
}
if (msg.news[j].dislike.length>0){
if (msg.news[j].dislike.length==1){dislikeText= QT.atob(msg.news[j].dislike[0].name)+" "+ qsTr("doesn't like this.")}
else {dislikeText= msg.news[j].dislike.length+" "+ qsTr("don't like this.")}
}
if (msg.news[j].attendyes.length>0){
if (msg.news[j].attendyes.length==1){attendyesText= Qt.atob(msg.news[j].attendyes[0].name)+" "+ qsTr("will attend.")}
else {attendyesText= msg.news[j].attendyes.length+" "+ qsTr("persons will attend.")}
}
if (msg.news[j].attendno.length>0){
if (msg.news[j].attendno.length==1){attendnoText= Qt.atob(msg.news[j].attendno[0].name)+" "+ qsTr("will not attend.")}
else {attendnoText= msg.news[j].attendno.length+" "+ qsTr("persons will not attend.")}
}
if (msg.news[j].attendmaybe.length>0){
if (msg.news[j].attendmaybe.length==1){attendmaybeText= Qt.atob(msg.news[j].attendmaybe[0].name)+" "+ qsTr("may attend.")}
else {attendmaybeText= msg.news[j].attendmaybe.length+" "+ qsTr("persons may attend.")}
}
}
var friendica_activities={likeText:likeText,dislikeText:dislikeText,attendyesText:attendyesText,attendnoText:attendnoText,attendmaybeText:attendmaybeText}
var seconds=(msg.currentTime-newsitemobject.created_at)/1000;
var timestring="";
if (seconds<60) {timestring=seconds+" "+qsTr("seconds") +" "+qsTr("ago");}
else if (seconds<90){timestring=Math.round(seconds/60)+" "+qsTr("minute") +" "+qsTr("ago");}
else if (seconds<3600){timestring=Math.round(seconds/60)+" "+qsTr("minutes") +" "+qsTr("ago");}
else if (seconds<5400){timestring=Math.round(seconds/3600)+" "+qsTr("hour") +" "+qsTr("ago");}
else if (seconds<86400){timestring=Math.round(seconds/3600)+" "+qsTr("hours") +" "+qsTr("ago");}
else if (seconds<129600){timestring=Math.round(seconds/86400)+" "+qsTr("day") +" "+qsTr("ago");}
else if (seconds<3888000){timestring=Math.round(seconds/86400)+" "+qsTr("days") +" "+qsTr("ago");}
else if (seconds<5832000){timestring=Math.round(seconds/3888000)+" "+qsTr("month") +" "+qsTr("ago");}
else if (seconds<69984000){timestring=Math.round(seconds/3888000)+" "+qsTr("months") +" "+qsTr("ago");}
else {timestring=Math.round(seconds/69984000)+" "+qsTr("years") +" "+qsTr("ago");}
var data=({"newsitemobject": newsitemobject,"dateDiff":timestring,"friendica_activities":friendica_activities})}
// print("News:"+j+msg.news.length+JSON.stringify(data));
msg.model.append(data);}
if (j==msg.news.length){
msg.model.sync()
};
}

View File

@ -0,0 +1,15 @@
WorkerScript.onMessage = function(msg) {
if (msg.firstalbum==0){msg.model.clear();}
var limit=0; if (msg.albums.length-msg.firstalbum<20){limit=msg.albums.length} else{limit=msg.firstalbum+20}
for (var j=msg.firstalbum;j<limit;j++){
if (msg.albums[msg.firstalbum]) {
// print("album"+msg.albums[j].name);
if(msg.foreignPicture){
var albumname=msg.albums[j].name.trim();var albumlink=msg.albums[j].link
}else{
var albumname=msg.albums[j].toString();var albumlink=""}
msg.model.append({"albumlink":albumlink,"foreignPicture":msg.foreignPicture,"albumname":albumname});
msg.model.sync()
};
}
}

View File

@ -0,0 +1,222 @@
//.pragma library
.import QtQuick.LocalStorage 2.0 as Sql
.import "qrc:/js/helper.js" as Helperjs
.import "qrc:/js/news.js" as Newsjs
// IMAGE FUNCTIONS
function requestList(login,database,rootwindow,callback) {
//get list of own images and call download function
Helperjs.friendicaRequest(login,"/api/friendica/photos/list", rootwindow,function (helperobject){
print("return"+helperobject);
var obj=JSON.parse(helperobject);
Helperjs.readField("id",database,"imageData",login.username,function(AllStoredImages){
if (AllStoredImages.length>0){
for(var i=0;i< AllStoredImages.length;i++){
var position=Helperjs.inArray(obj,"resourceID",AllStoredImages[i]);
if (position>-1){obj.splice(position,1)}
//obj.splice(obj.indexOf(AllStoredImages[i]),1);// list of objects instead of list!!!
}
}}
);
callback(obj);
})}
function dataRequest(login,photoID,database,rootwindow) {
// check if image exist and call download function
Helperjs.friendicaRequest(login,"/api/friendica/photo?photo_id="+photoID, rootwindow, function (obj){
try{ if(obj==""){currentImageNo=currentImageNo+1}else{
var image = JSON.parse(obj);
print('storeData() for ' + JSON.stringify(obj));
try{sprite.destroy();}catch(e){}
if (obj["link"]["0"]){var source=obj["link"]["0"]} else {var source=obj["link"]["4"]}//source for profile picture or original size
print("Source"+obj["link"]["0"]+source)
obj["source"]=source;
var filename=obj.filename;
if (filename==""){// check if file as any filename
if (obj.type=="image/jpeg") {obj["filename"]=obj["id"]+".jpg"}
else if (obj.type=="image/png") {obj["filename"]=obj["id"]+".png"}
}
// check if text name has valid image format ending, otherwise append appropriate ending
if(["jpg","png"].indexOf(obj["filename"].substring(obj["filename"].lastIndexOf(".")+1,obj["filename"].length))==-1){
print("falscheEndung: "+obj["filename"].substring(obj["filename"].lastIndexOf(".")+1,obj["filename"].length));
{ if (obj.type=="image/jpeg") {obj["filename"]=obj["filename"]+".jpg"}
else if (obj.type=="image/png") {obj["filename"]=obj["filename"]+".png"}
}
print("obj.Filename: "+obj["filename"]+" filename: "+filename)
}
saveImage(obj,login.imagestore,function(obj,sprite){
//sprite.destroy(500);
var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
db.transaction( function(tx) {
print('... check if a object exists: '+obj["id"])
var result = tx.executeSql('SELECT * from imageData where id = "'+obj["id"]+'"');
if(result.rows.length === 1) {// use update
print(obj["id"] +' exists, update it')
result = tx.executeSql('UPDATE imageData SET username ="' +login.username+ '",id="'+obj.id+'", created="'+obj.created+'", edited="'+obj.edited+'", profile="'+obj.profile+'", link="'+obj.source+'", filename="'+obj.filename+'",title="'+obj.title+'", desc="'+obj.desc+'", type="'+obj.type+'", width="'+obj.width+'", height="'+obj.height+'", album="'+obj.album+'", location="file://'+login.imagestore+'" where id="'+obj["id"]+'"');
} else {// use insert print('... does not exists, create it')
result = tx.executeSql('INSERT INTO imageData VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?)', [login.username,obj.id,obj.created,obj.edited, obj.title, obj.desc, obj.album, obj.filename, obj.type, obj.height, obj.width,obj. profile,obj.source,'file://'+login.imagestore]);
print("Inserted");}
})})}}
catch (e){print("Data retrieval failure! "+ e+obj);}
})}
function saveImage(obj,storagedirectory,callback) {
// create image component from base64 code and save it
print("Storing "+storagedirectory+obj.filename+obj.width+"x"+obj.height);
var maxSize=Math.max(fotostab.width,fotostab.height);
var helpwidth=(obj.width<maxSize)?obj.width:maxSize;
var helpheight=(obj.height<maxSize)?obj.height:maxSize;
if (obj.width>obj.height){ //landscape
helpheight=helpwidth*obj.height/obj.width
} else { //portrait
helpwidth=helpheight*obj.width/obj.height
}
var component=Qt.createComponent("qrc:/qml/PhotoPlaceholder.qml");
var sprite = component.createObject(fotostab, {"x":0,"y":0,"imageName":storagedirectory+obj.filename ,"width":helpwidth,"height":helpheight,"source": obj.source,"downloadtype":"picture"});
callback(obj,sprite)
}
function deleteImageData(database,user,field,selection,callback) { // does nothing useful at the moment
var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
print(' delete Image Data() for ' + field +"="+selection)
db.transaction( function(tx) {
result = tx.executeSql('UPDATE imageData SET data="" where '+ field +'="'+selection+'"');
callback(result)})
}
function requestFriendsAlbumPictures(friend,rootwindow,callback){
// screenscraping of albums page of contact without user and password
Helperjs.friendicaWebRequest(friend.url.replace("profile","photos"),rootwindow,function(photohtml){
var photoarray=[];
var arr = photohtml.split("sidebar-photos-albums-li");
for (var i=2;i<arr.length;i++){
var albumlink = arr[i].substring(arr[i].indexOf('http'),arr[i].indexOf('class')-2);
var albumname=arr[i].substring(arr[i].indexOf('/span')+6,arr[i].indexOf('</a>')-1);
var album={'link':albumlink,'name':albumname}
photoarray.push(album);
}
//print("Album"+JSON.stringify(photoarray));
callback(photoarray)
})
}
function requestFriendsPictures(link,rootwindow,callback){
// screenscraping of pictures page for given album
Helperjs.friendicaWebRequest(link,rootwindow,function(photohtml){
var photoarray=[];
var basehtml=photohtml.substring(photohtml.indexOf('<base')+12,photohtml.indexOf('/>',photohtml.indexOf('<base'))-2);
// old theme
if (photohtml.indexOf("photo-album-image-wrapper-end")>-1){ //theme 1
var arr = photohtml.split("photo-album-image-wrapper-end");}
// other themes
if (photohtml.indexOf("photo-album-wrapper")>-1){ //theme 2
var photoarea=photohtml.substring(photohtml.indexOf("photo-album-wrapper"),photohtml.indexOf("photo-album-end"))
var arr = photoarea.split("</a>");}
for (var i=0;i<arr.length-1;i++){
var photoname=arr[i].substring(arr[i].lastIndexOf('alt')+5,arr[i].lastIndexOf('title')-2);
var thumblink=arr[i].substring(arr[i].lastIndexOf('<img')+10,arr[i].lastIndexOf('alt')-2);
var imagetype=thumblink.substring(thumblink.lastIndexOf("."));
var photolink=thumblink.substring(0,thumblink.length-imagetype.length-2)+"-0"+imagetype
if(thumblink.substring(0,4)!=="http"){thumblink=basehtml+thumblink}
if(photolink.substring(0,4)!=="http"){photolink=basehtml+photolink}
var photo={'link':photolink,'name':photoname,'thumb':thumblink}
photoarray.push(photo);
}
callback(photoarray)
})
}
// CONFIG FUNCTIONS
function initDatabase(database) { // initialize the database object
var db =Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
print('initDatabase()'+database[0]+database[1]+database[2]+database[3])
db.transaction( function(tx) {
print('... create table')
tx.executeSql('CREATE TABLE IF NOT EXISTS imageData(username TEXT,id INT, created TEXT,edited TEXT, title TEXT, desc TEXT, album TEXT,filename TEXT, type TEXT, height INT, width INT, profile INT, link TEXT,location TEXT)');
tx.executeSql('CREATE TABLE IF NOT EXISTS config(server TEXT, username TEXT, password TEXT, imagestore TEXT, maxnews INT, timerInterval INT, newsViewType TEXT,isActive INT)');
tx.executeSql('CREATE TABLE IF NOT EXISTS news(username TEXT, messagetype INT, text TEXT, created_at INT, in_reply_to_status_id INT, source TEXT, status_id INT, in_reply_to_user_id INT, geo TEXT,favorited TEXT, uid INT, statusnet_html TEXT, statusnet_conversation_id TEXT,like TEXT, dislike TEXT, attendyes TEXT,attendno TEXT, attendmaybe TEXT)');
tx.executeSql('CREATE TABLE IF NOT EXISTS contacts(username TEXT, id INT, name TEXT, screen_name TEXT, location TEXT,description TEXT, profile_image BLOB, url TEXT, protected TEXT, followers_count INT, friends_count INT, created_at TEXT, favourites_count TEXT, utc_offset TEXT, time_zone TEXT, statuses_count INT, following TEXT, verified TEXT, statusnet_blocking TEXT, notifications TEXT, statusnet_profile_url TEXT, cid INT, network TEXT, isFriend INT)');
tx.executeSql('CREATE TABLE IF NOT EXISTS groups(username TEXT, groupname TEXT, gid INT, members TEXT)');
})}
function storeConfig(database,obj) { // stores config to DB
var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
print('storeConfig() for ' + obj.username)
print('database: ' + database[0]);
db.transaction( function(tx) {
print('... check if a object exists: '+obj.username)
var result = tx.executeSql('SELECT * from config WHERE username="'+obj.username+'"');
if(result.rows.length === 1) {// use update
print(obj.username +' exists, update it');
var result2 = tx.executeSql('UPDATE config SET server="'+obj.server+'",password="'+obj.password+'", imagestore="'+obj.imagestore+'", maxnews="+obj.maxnews+", isActive=0 WHERE username="'+obj.username +'"');
var result3 = tx.executeSql('UPDATE config SET isActive=1 WHERE username !="'+obj.username +'"');
var result4 = tx.executeSql('UPDATE config SET maxnews='+obj.maxnews);
} else {// use insert print('... does not exists, create it')
var result2 = tx.executeSql('INSERT INTO config VALUES (?,?,?,?,?,?,?,?)', [obj.server, obj.username, obj.password, obj.imagestore, obj.maxnews, 0,"list",0]);
var result3 = tx.executeSql('UPDATE config SET isActive=1 WHERE username !="'+obj.username +'"');
var result4 = tx.executeSql('UPDATE config SET maxnews='+obj.maxnews);
print("Inserted");}
});}
function getServerConfig(login,rootwindow,callback){
// check server with given credentials
try {Helperjs.friendicaRequest(login,"/api/statusnet/config",rootwindow, function (obj){
var serverconfig = JSON.parse(obj);
var serverconfigString="import QtQuick 2.0; import QtQuick.Dialogs 1.2; MessageDialog{ visible: true; title:'Server';standardButtons: StandardButton.Ok;text: 'SUCCESS! \nName: "+serverconfig.site.name+"\nLanguage: "+serverconfig.site.language+
"\nEmail: "+serverconfig.site.email+"\nTimezone: "+serverconfig.site.timezone+"\nClosed: "+serverconfig.site.closed+
"\nText limit: "+serverconfig.site.textlimit+"\nShort Url length: "+serverconfig.site.shorturllength+
"\nFriendica version: "+serverconfig.site.friendica.FRIENDICA_VERSION+"\nDFRN version: "+serverconfig.site.friendica.DFRN_PROTOCOL_VERSION +
"\nDB Update version: "+serverconfig.site.friendica.DB_UPDATE_VERSION+"'}";
callback(serverconfigString);
})}
catch (e){callback (e);
}}
function readConfig(database,callback,filter,filtervalue) { // reads config
print('readConfig()')
if (filter){var where = " WHERE "+ filter +" = '" + filtervalue+"'";} else { var where="";}
var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3],initDatabase(database));
db.transaction( function(tx) {
var tables = tx.executeSql("SELECT * FROM sqlite_master WHERE type='table'");
if (tables.rows.length==0){print("no database");callback("")} else {
print('... read from database '+where)
var rs = tx.executeSql('select * from config'+where);
var rsArray=[];
if (rs.rows.length>0){
for(var i = 0; i < rs.rows.length; i++) {
rsArray.push(rs.rows.item(i))
}
var rsObject={server:rsArray[0].server,username:rsArray[0].username, password:rsArray[0].password,imagestore:rsArray[0].imagestore,maxnews:rsArray[0].maxnews,isActive:rsArray[0].isActive};
} else {
var rsObject=""
}
callback(rsObject);}}
);
}
function readActiveConfig(database){
var obj;
readConfig(database,function(config){
obj=config},"isActive", 0);
return obj;
}
function deleteConfig(database,userobj,callback) { // delete user data from DB
print('deleteConfig()')
if (userobj){var where = " WHERE username='"+ userobj.username+"' and server='"+userobj.server+"'";} else { return "no user selected!";}
var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
if(!db) { return; }
db.transaction( function(tx) {
print('... read from database '+where)
var rs = tx.executeSql('delete * from config'+where);
print(rs.toString);
callback(rs);
});
}

View File

@ -0,0 +1,44 @@
import QtQuick 2.0
import QtMultimedia 5.0
import QtQuick.Controls 1.2
Item {
Rectangle {
VideoOutput {
anchors.fill: parent
source: localCamera
}
Camera {
id: localCamera
}
Button {
id: shotButton
width: 200; height: 75
text: "Take Photo"
onClicked: {
localCamera.imageCapture.capture();
} }
Connections {
target: localCamera.imageCapture
onImageSaved: {
photofile= imagePaths.append({"path": path})
listView.positionViewAtEnd(); }
}
Image {
id: photoFromCamera
anchors.fill: parent
fillMode: Image.PreserveAspectFit
source: photo
}
Button {
text: "Upload"
onClicked:{
var login=Service.readActiveConfig(db);
img.src=file;
Service.Upload(login,file)
}
}
}
}

View File

@ -0,0 +1,250 @@
import QtQuick 2.0
import QtQuick.Dialogs 1.2
import QtQuick.Controls 1.2
import "qrc:/js/service.js" as Service
import "qrc:/js/layout.js" as Layoutjs
import "qrc:/js/helper.js" as Helperjs
import "qrc:/qml"
StackView{
id: configStack
anchors.fill:parent
focus: true
Keys.onReleased: if (event.key === Qt.Key_Back && stackView.depth > 1) {
stackView.pop(); event.accepted = true;
}
initialItem: Flickable{
width:root.width-5*mm
height:root.height-12*mm
contentHeight: configBackground.height
boundsBehavior: Flickable.StopAtBounds
Rectangle{
id:configBackground
color: "grey"
width:parent.width
height:Math.max(80*mm,root.height-12*mm)
focus: true
ComboBox{
y:mm
width: root.width/2
model: ListModel{
id: usermodel
}
onCurrentIndexChanged:{
try {Service.readConfig(db,function(obj){
servername.text=obj.server;
username.text= obj.username;
password.text=Qt.atob(obj.password);
imagestore.text=obj.imagestore;
maxNewsText.text=obj.maxnews;
if( obj.isActive==0){isActiveField.text=qsTr("yes")} else {isActiveField.text=qsTr("no")}
},"username",currentText)}
catch (e){print(e)}
}
}
Text {
text: "Server"
x: 4*mm; y: 10*mm
}
Text {
text: "User"
x: 4*mm; y: 20*mm
}
Text {
text: "Password"
x: 4*mm; y: 30*mm
}
Text {
text: "Image dir."
x: 4*mm; y: 40*mm
}
Text {
text: "Max. News"
x: 4*mm; y: 50*mm
}
Text {
text: "is Active"
x: 4*mm; y: 60*mm
}
Rectangle{color: "white"; x: 25*mm; y: 10*mm; width: root.width/2; height: 5*mm;}
Flickable {
id: servernameFlickable
x: 25*mm; y: 10*mm; width: root.width/2; height: 5*mm;
contentWidth: servername.paintedWidth
contentHeight: servername.paintedHeight
clip: true
TextEdit {
id: servername
width: servernameFlickable.width
height: servernameFlickable.height
focus: true
text:"https://..."
//wrapMode: TextEdit.NoWrap
//validator: RegExpValidator { regExp: /^(((http|https|ftp):\/\/)?([[a-zA-Z0-9]\-\.])+(\.)([[a-zA-Z0-9]]){2,4}([[a-zA-Z0-9]\/+=%&_\.~?\-]*))*$/}
// onEditingFinished:{}
onCursorRectangleChanged: Layoutjs.ensureVisibility(cursorRectangle,servernameFlickable)
}
}
Rectangle{
color: "white"
x: 25*mm; y: 20*mm; width: root.width/2; height: 5*mm;
TextInput {
id: username
anchors.fill: parent
selectByMouse: true
}
}
Rectangle{
color: "white"
x: 25*mm; y: 30*mm; width: root.width/2; height: 5*mm;
TextInput {
id: password
anchors.fill: parent
selectByMouse: true
echoMode: TextInput.PasswordEchoOnEdit
}
}
Rectangle{color: "white"; x: 25*mm; y: 40*mm; width: root.width/2-9*mm; height: 5*mm;}
Flickable {
id: imagestoreFlickable
x: 25*mm; y: 40*mm; width: root.width/2-9*mm; height: 5*mm;
clip: true
TextInput {
id: imagestore
width: imagestoreFlickable.width
height: imagestoreFlickable.height
wrapMode: TextEdit.NoWrap
onCursorRectangleChanged: Layoutjs.ensureVisibility(cursorRectangle,imagestoreFlickable)
}
}
Slider{ id: maxNews
x:37*mm; y: 50*mm;width: root.width/3;height:5*mm
minimumValue: 0;maximumValue:100000; stepSize: 1000
}
Rectangle{color: "white"; x: 25*mm; y: 50*mm; width: 9*mm; height: 5*mm;
TextEdit{id:maxNewsText;
anchors.fill: parent
verticalAlignment:TextEdit.AlignRight
text:maxNews.value
focus: true
selectByMouse: true
}
}
Rectangle{
x: 25*mm; y: 60*mm; width: root.width/2; height: 5*mm;
Text{
id: isActiveField
anchors.fill: parent
}
}
FileDialog {
id: imagestoreDialog
title: "Please choose a directory"
folder: shortcuts.pictures
selectFolder: true
onAccepted: {
var imagestoreString=imagestoreDialog.folder.toString(); imagestoreString=imagestoreString.replace(/^(file:\/{2})/,"")+"/"
imagestore.text=imagestoreString;
console.log("You chose: " + imagestoreDialog.folder)
}
onRejected: {
console.log("Canceled")
}
}
Button {
x: root.width/2+18*mm; y: 40*mm; width: 7*mm; height: 5*mm;
text: "..."
onClicked:
{imagestoreDialog.open()}
}
Button {
x: 25*mm; y: 70*mm; width: implicitWidth; height: implicitHeight;
text: "Update"
onClicked:{
var userconfig={server: servername.text, username: username.text, password:Qt.btoa(password.text), imagestore:imagestore.text,maxnews:maxNewsText.text};
var errormessage="";
if (servername.text==""){errormessage=qsTr("No server given! ")}
//if (!servername.acceptableInput){errormessage+=qsTr("Server name not valid! ")}
else if (username.text==""){errormessage+=qsTr("No username given! ")}
else if (password.text=="") {errormessage+=qsTr("No password given! ")}
else if (imagestore.text=="") {errormessage+=qsTr("No image directory given!")}
else if (maxNewsText.text=="") {errormessage+=qsTr("No maximum news number given!")}
else {errormessage=""}
if (errormessage=="") {
filesystem.Directory=userconfig.imagestore;
filesystem.makeDir("contacts");
Service.storeConfig(db,userconfig);
Service.readConfig(db,function(userconfig){Service.getServerConfig(userconfig,configBackground, function(obj){
var serverString=obj;
var serverconfigObject=Qt.createQmlObject(serverString,configBackground,"serverconfigOutput");
usermodel.append({text:username.text});
//reset values
root.login=userconfig;
root.contactlist=[];
root.news=[]
root.newContacts=[]
root.currentContact= 0
root.contactLoadType= ""
root.currentIndex=0;
newstab.active=true;
})},"isActive",0);
}
else {Helperjs.show("Error", errormessage,root)}
}}
Button {
x: root.width/2+2*mm; y: mm; width: 5*mm; height: 5*mm;
text: "-"
onClicked:{
var userconfig={server: servername.text, username: username.text, password: Qt.btoa(password.text)};
Service.deleteConfig(db,userconfig);
}}
Button {
x: root.width/2+8*mm; y: mm; width: 5*mm; height: 5*mm;
text: "+"
onClicked:{
servername.text="https://..."
username.text=""
password.text=""
imagestore.text=""
maxNews.value=1000
isActiveField.text=""
}
}
Button {
x: root.width/2+14*mm; y: mm; width: 5*mm; height: 5*mm;
text: "?"
onClicked:{
configStack.push({item:"qrc:/qml/InfoBox.qml"});
}
}
Component.onCompleted: {
try{Helperjs.readData(db,"config",root.login.username,function(users){
users.sort(function(obj1, obj2) {
return obj1.isActive - obj2.isActive;
});
for (var i=0; i<users.length;i++){
if (users[i]) {usermodel.append({text:users[i].username});};
};})}
catch (e){print(e)}
}
}
}
}

View File

@ -0,0 +1,133 @@
import QtQuick 2.0
import QtQuick.Controls 1.3
import "qrc:/js/service.js" as Service
import "qrc:/js/layout.js" as Layoutjs
Item {
id: friendComponent
property date createdAtDate: new Date(friend.created_at)
Rectangle {
id: wrapper
width: 16*mm
height: 15*mm
border.color: "grey"
color:"white"
Image {
id: photoImage
x:1
y:1
width: 10*mm
height:10*mm
source:"file://"+ friend.profile_image
}
Label {
id: namelabel
x: 1
width: wrapper.width-4
height: 3*mm
text: friend.screen_name
anchors.topMargin: 0
anchors.left: photoImage.left
color: "#303030"
font.pixelSize: 3*mm
anchors.top: photoImage.bottom
}
Button{
id:infobutton
width: 5*mm
height: 5*mm
text:"?"
anchors.left: photoImage.right
anchors.leftMargin: 3
anchors.topMargin: 3
anchors.top: parent.top
onClicked:{
//print("State: "+ friendComponent.state);
friendComponent.state="large"}
}
Rectangle{
id: detailsrectangle
anchors.top: namelabel.bottom
anchors.topMargin: 2*mm
opacity: 0
Flickable{
id:namelabelflickable
width: root.width-10*mm
height:wrapper.height-27*mm-3
boundsBehavior:Flickable.StopAtBounds
flickableDirection:Flickable.VerticalFlick
contentWidth:width
contentHeight: namelabeltext.height
clip:true
Text{
id:namelabeltext
//anchors.top: parent.top
width: namelabelflickable.width
height: implicitHeight
font.pixelSize: 3*mm
textFormat:Text.RichText
wrapMode: Text.Wrap
text:"<b>"+qsTr("Description")+": </b> "+Qt.atob(friend.description)+"<br> <b>"+qsTr("Server Type")+":</b> "+friend.location+"<br> <b>"+qsTr("Posts")+":</b> "+friend.statuses_count+
"<br> <b>"+qsTr("URL")+":</b> <a href='"+ friend.url+"'>"+friend.url+"</a><br> <b>"+
qsTr("Created at")+":</b> "+createdAtDate.toLocaleString(Qt.locale())
onLinkActivated: {
Qt.openUrlExternally(link)}
}
}
Row{
anchors.top: namelabelflickable.bottom
anchors.topMargin: 2*mm
spacing:4
Button{
id:photobutton
text:"Photos"
visible:friend.location=="Friendica"? 1:0
onClicked:{root.currentIndex=2;
fotostab.active=true;
root.fotoSignal(friend) ;
}
}
Button{
id:messagebutton
text:"Messages"
onClicked:{root.currentIndex=0;
newstab.active=true;
root.messageSignal(friend.id) ;
}
}
Button{
id:dmbutton
visible: friend.following=="true"?true:false
text: "DM"
onClicked:{root.currentIndex=0;
newstab.active=true;
root.directmessageSignal(friend.screen_name);
}
}
Button{
id: closeButton
text: "close"
onClicked:{friendComponent.state=""}
}
}
}
}
states: [
State {
name: "large"
PropertyChanges { target: namelabel; font.pixelSize: 4*mm; width:friendsTabView.width-4*mm; text:Qt.atob(friend.name)+" (@"+friend.screen_name+")"}
PropertyChanges { target: friendComponent; z: 2 }
PropertyChanges { target: wrapper; width:friendsTabView.width-3*mm;height:friendsTabView.height-14*mm}
PropertyChanges { target: photoImage; width:15*mm;height:15*mm }
PropertyChanges { target:friendComponent.GridView.view;contentY:friendComponent.y;contentX:friendComponent.x;interactive:false}
PropertyChanges { target: detailsrectangle; opacity:1 }
}
]
}

View File

@ -0,0 +1,174 @@
import QtQuick 2.0
import QtQuick.Dialogs 1.2
import QtQuick.Controls 1.2
import "qrc:/js/service.js" as Service
import "qrc:/js/helper.js" as Helperjs
import "qrc:/js/news.js" as Newsjs
import "qrc:/qml"
Rectangle {
y:1
color: "white"
TabView{
id:friendsTabView
// property var contacts: []
// property var groups: []
tabPosition: Qt.TopEdge
x:mm
y:mm
width: root.width-5*mm
height: root.height-10*mm
currentIndex: 0
signal friendsSignal(var username)
signal contactsSignal(var username)
signal groupsSignal(var username)
onCurrentIndexChanged:{
if (currentIndex==0){friendsSignal(root.login.username)}
else if (currentIndex==1){contactsSignal(root.login.username)}
else if (currentIndex==2){groupsSignal(root.login.username)}
}
Tab{
title: qsTr("Friends")
Rectangle{
id: friendsGridTab
function showFriends(username){
try {friendsModel.clear()} catch(e){print(e)};
Helperjs.readData(db,"contacts",username,function(friends){
for (var i=0;i<friends.length;i++){
friendsModel.append({"friend":friends[i]});
}},"isFriend",1)
}
Button {
id: updateFriendsButton
text: qsTr("Update")
anchors.top: parent.top
anchors.right: parent.right
onClicked: {
try {friendsModel.clear()} catch(e){print(e)};
root.contactLoadType="friends";
Newsjs.requestFriends(root.login,db,root,function(nc){
root.newContacts=nc
})
}}
ProgressBar{
id: newContactsProgress
width: 15*mm
height: updateFriendsButton.height
anchors.top: parent.top
anchors.right:updateFriendsButton.left
anchors.rightMargin:mm
visible: (root.currentContact!=root.newContacts.length)?true:false
value: root.currentContact/root.newContacts.length
}
GridView {
id: friendsView
x:mm
y:updateFriendsButton.height+mm
width:friendsGridTab.width-2*mm
height:friendsGridTab.height-updateFriendsButton.height-2*mm
clip: true
cellHeight: 16*mm
cellWidth: 17*mm
add: Transition {
NumberAnimation { properties: "x,y"; from: 300; duration: 1000 }
}
model: friendsModel
delegate: FriendComponent { }
}
ListModel{id:friendsModel}
Component.onCompleted: {
friendsTabView.friendsSignal.connect(showFriends);
showFriends(root.login.username)
}
}
}
Tab{
title: qsTr("Other Contacts")
Rectangle{
id: contactsGridTab
function showContacts(username){
try {contactsModel.clear()} catch(e){print(e)};
Helperjs.readData(db, "contacts",root.login.username,function(friendsobject){
for (var j=0;j<friendsobject.length;j++){
contactsModel.append({"friend":friendsobject[j]});
}
},"isFriend",0)}
GridView {
id: contactsView
x:mm
y:mm
width:contactsGridTab.width-2*mm
height:contactsGridTab.height-2*mm
clip: true
cellHeight: 16*mm
cellWidth: 17*mm
add: Transition {
NumberAnimation { properties: "x,y"; from: 300; duration: 1000 }
}
model: contactsModel
delegate: FriendComponent { }
}
ListModel{id: contactsModel}
Component.onCompleted: {
friendsTabView.contactsSignal.connect(showContacts);
}
}
}
Tab{
title: qsTr("Groups")
Rectangle{
id: groupsGridTab
function showGroups(username){
try {groupsModel.clear()} catch(e){print(e)};
print("showGroups"+username);
Helperjs.readData(db, "groups",root.login.username,function(groupsobject){
for (var j=0;j<groupsobject.length;j++){
groupsModel.append({"group":groupsobject[j]});
}})}
Button {
id: updateGroupsButton
text: qsTr("Update")
anchors.top: parent.top
anchors.right: parent.right
onClicked: {
print("Update groups");
Newsjs.requestGroups(root.login,root.db,root,function(){
showGroups(root.login.username)})}
}
GridView {
id: groupsView
x:mm
y:updateGroupsButton.height+mm
width:groupsGridTab.width-2*mm
height:groupsGridTab.height-updateGroupsButton.height-2*mm
clip: true
cellHeight: 16*mm
cellWidth: 17*mm
add: Transition {
NumberAnimation { properties: "x,y"; from: 300; duration: 1000 }
}
model: groupsModel
delegate: GroupComponent { }
}
ListModel{
id: groupsModel
}
Component.onCompleted: {
friendsTabView.groupsSignal.connect(showGroups);
}
}
}
}
}

View File

@ -0,0 +1,148 @@
import QtQuick 2.0
import QtQuick.Controls 1.3
import "qrc:/js/service.js" as Service
import "qrc:/js/layout.js" as Layoutjs
Item {
id: groupComponent
Rectangle {
id: wrapper
width: 16*mm
height: 15*mm
border.color: "grey"
color:"white"
Label {
id: namelabel
x: 1
width: wrapper.width-2
height: 3*mm
text: group.groupname
color: "#303030"
font.pixelSize: 3*mm
anchors.centerIn:parent
}
Button{
id:infobutton
width: 5*mm
height: 5*mm
text:"?"
anchors.top: namelabel.bottom;anchors.topMargin: 3
onClicked:{
print("State: "+ groupComponent.state+groupView.contentY);
groupComponent.state="large"}
}
Rectangle{
id: detailsrectangle
anchors.top: infobutton.bottom
anchors.topMargin: 2*mm
opacity: 0
Component { id:footerComponent
Rectangle{
border.color: "#EEEEEE"
border.width: 1
width:parent.width
height:6*mm
Text{
font.pixelSize: 3*mm
anchors.centerIn: parent
text:qsTr("+")
}
MouseArea{anchors.fill:parent
onClicked:{var contactitems="";
readData(db,"contacts",root.login.username, function(contacts){for (var i=0;i<contacts.length;i++){
contactitems=contactitems+"MenuItem{text:'"+contacts[i].screen_name+"'; onTriggered: groupModel.append(' @"+contacts[i]+"')}"
}},"isFriend",0)
var menuString="import QtQuick.Controls 1.4; Menu {"+contactitems+"}";
print("menustring: "+menuString);
var contactlistObject=Qt.createQmlObject(menuString,messageSend,"contactmenuOutput");
contactlistObject.popup();
Newsjs.addToGroup
}}}}
Component { id:groupMember
Rectangle{
border.color: "#EEEEEE"
border.width: 1
width:parent.width
height:6*mm
Text{
font.pixelSize: 3*mm
anchors.left: parent.left
text:groupmember.screen_name
}
}}
ListView{
id:namelabeltext
anchors.top: parent.top
width: root.width-10*mm
height:wrapper.height-20*mm
clip: true
spacing: 0
footer: footerComponent
model: groupModel
delegate: groupMember
}
ListModel{id: groupModel}
}
Row{
anchors.top: namelabeltext.bottom
anchors.topMargin: 2*mm
spacing:4
Button{
id:photobutton
text:"Photos"
visible:friend.location=="Friendica"? 1:0
onClicked:{root.currentIndex=2;
fotostab.active=true;
root.fotoSignal(friend) ;
}
}
Button{
id:messagebutton
text:"Messages"
onClicked:{root.currentIndex=0;
newstab.active=true;
root.messageSignal(friend.id) ;
}
}
Button{id:dmbutton
visible: friend.following=="true"?true:false
text: "DM"
onClicked:{root.currentIndex=0;
newstab.active=true;
root.directmessageSignal(friend.screen_name);
}
}
Button{
id: closeButton
text: "close"
onClicked:{friendComponent.state=""}
}
}
}
states: [
State {
name: "large"
PropertyChanges { target: namelabel; font.pixelSize: 4*mm; width:friendsView.width; text:Qt.atob(friend.name)+" (@"+friend.screen_name+")"}
PropertyChanges { target: friendComponent; z: 2 }
PropertyChanges { target: wrapper; width:friendsView.width;height:friendsView.height -2*mm-1}
PropertyChanges { target: photoImage; width:15*mm;height:15*mm }
PropertyChanges { target:friendComponent.GridView.view ;contentY:friendComponent.y;contentX:friendComponent.x;interactive:false}
PropertyChanges { target: detailsrectangle; opacity:1 }
}
]
}

View File

@ -0,0 +1,22 @@
import QtQuick 2.0
import QtQuick.Controls 1.2
Rectangle{
color:"white"
width:infoBoxText.contentWidth
height:infoBoxText.contentHeight
Text{id:infoBoxText
textFormat: Text.RichText
wrapMode: Text.Wrap
text: "<b>Friendiqa v0.001 </b><br>Licensed under GPL 3<br> "+
"Sourcecode: <a href='https://github.com/LubuWest/Friendiqa'>https://github.com/LubuWest/Friendica</a><br>"+
"C++ code by <a href='https://kirgroup.com/profile/fabrixxm'>Fabio</a><br>"+
"QML and Javascript code by <a href='https://freunde.ma-nic.de/profile/marco'>Marco</a>"
onLinkActivated:{
Qt.openUrlExternally(link)}
}
Button{
text:qsTr("Close")
onClicked:{configStack.pop()}
anchors.top:infoBoxText.bottom
}
}

View File

@ -0,0 +1,132 @@
// message.qml
// message with buttons
import QtQuick 2.0
import QtQml 2.2
import QtQuick.Controls 1.3
import QtQuick.Dialogs 1.2
import QtQuick.LocalStorage 2.0
//import "../qml"
import "qrc:/js/service.js" as Service
Item{
id:messageSend
property var login
property string parentId: ""
property string reply_to_user:""
property string attachImageURL: "";
property int directmessage: 0;
property var contacts: []
// title: parentId !== "" ? qsTr("Reply to "+reply_to_user) : qsTr("New post")
function statusUpdate(title,status,in_reply_to_status_id,attachImageURL) {
xhr.url= login.server + "/api/statuses/update.xml";
xhr.setLogin(login.username+":"+Qt.atob(login.password));
print("login: "+login.username+":"+Qt.atob(login.password));
xhr.clearParams();
xhr.setParam("source", "Friendiqa");
xhr.setParam("status", status);
if (parentId!="") {xhr.setParam("in_reply_to_status_id", parentid)};
if (title!=="") {xhr.setParam("title", title)};
if (attachImageURL!=="") {xhr.setImageFileParam("media", attachImageURL )};
xhr.post();
}
function dmUpdate(title,text,replyto,screen_name,attachImageURL) {
xhr.url= login.server + "/api/direct_messages/new.xml";
xhr.setLogin(login.username+":"+Qt.atob(login.password));
xhr.clearParams();
xhr.setParam("text", text);
xhr.setParam("screen_name", screen_name);
if (parentId!="") {xhr.setParam("replyto", replyto)};
if (title!=="") {xhr.setParam("title", title)};
if (attachImageURL!=="") {xhr.setImageFileParam("media", attachImageURL )};
xhr.post();
}
Column {
id:messageColumn
spacing: 2
TextField {
id: titleField
width: parent.width
placeholderText: qsTr("Title (optional)")
visible: messageSend.parentId === ""
}
TextArea {
id: bodyField
width: parent.width
height: 30*mm
wrapMode: TextEdit.Wrap
}
CheckBox{
id:dmCheckbox
text:"DM"
enabled: false
checked: (directmessage==1)?true:false
onClicked:{
if(dmCheckbox.checkedState==Qt.Checked){directmessage=1}
else if(dmCheckbox.checkedState==Qt.Unchecked){directmessage=0}
}
}
Row{
spacing:2
Button {
id: cancelButton
text: qsTr("Cancel")
onClicked: {newsStack.pop()}
}
Button {
id: attachButton
text: qsTr("Attach")
onClicked: {imageAttachmentDialog.open()}
}
Button{
id:contactButton
text:qsTr("cc")
visible:(directmessage==0)
onClicked:{
var contactitems="";
for (var i=0;i<contacts.length;i++){
contactitems=contactitems+"MenuItem{text:'"+contacts[i]+"'; onTriggered: bodyField.append(' @"+contacts[i]+"')}"
}
var menuString="import QtQuick.Controls 1.4; Menu {"+contactitems+"}";
// print(menuString);
var contactlistObject=Qt.createQmlObject(menuString,messageSend,"contactmenuOutput")
contactlistObject.popup() }
}
Button {
id: sendButton
text: qsTr("Send")
onClicked: {
print("login: "+login.server+login.username);
if (directmessage==0){
statusUpdate(titleField.text,bodyField.text,messageSend.parentId,attachImageURL.toString());}
else {dmUpdate( titleField.text,bodyField.text,"",messageSend.reply_to_user) }
newsStack.pop()
}
}
}
}
FileDialog {
id: imageAttachmentDialog
title: "Please choose a picture"
folder: shortcuts.pictures
selectFolder: false
onAccepted: {
attachImageURL=imageAttachmentDialog.fileUrl;
var imageAttachementObject=Qt.createQmlObject('import QtQuick 2.0; Image {source:"'+attachImageURL.toString()+'"; width: 30*mm; height: 30*mm;fillMode: Image.PreserveAspectFit}',messageColumn,"attachedImage");
console.log("You chose: " + attachImageURL)
}
onRejected: {
console.log("Canceled")
}
}
}

View File

@ -0,0 +1,155 @@
import QtQuick 2.0
import QtQuick.Dialogs 1.2
import QtQuick.Controls 1.2
import QtQuick.LocalStorage 2.0 as Sql
import "qrc:/js/news.js" as Newsjs
import "qrc:/js/helper.js" as Helperjs
Item {
property string newstabStatus:"news"
function showNews(newsToShow){
newsBusy.running=false;
var currentTime= new Date();
var msg = {'currentTime': currentTime, 'model': newsModel,'news':newsToShow};
newsWorker.sendMessage(msg);
}
function onFriendsMessages(friend){print(" Friend "+friend);
newstabStatus="friendmessage";
Newsjs.newsfromdb(db,root.login.username, function(dbnews){showNews(dbnews)},friend)
}
function onDirectMessage(friend){
newsStack.push({item:"qrc:/qml/MessageSend.qml",properties:{"reply_to_user": friend,"directmessage":1,"login":root.login}});
}
function cleanNews(database){
var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
db.transaction( function(tx) {
var maxnewsrs = tx.executeSql("SELECT DISTINCT maxnews FROM config");
var maxnews=maxnewsrs.rows.item(0);
var newscountrs = tx.executeSql('SELECT COUNT(*) from news');
var newscount = newscountrs.rows.item(0);
if (newscount>maxnews){var lastvalidtimers= tx.executeSql('select created_at from news ORDER BY created_at DESC LIMIT ' +(newscount-maxnews));
var lastvalidtime=lastvalidtimers.rows.item(-1);
var deleters = tx.executeSql('DELETE from news WHERE created_at<'+lastvalidtime)}
});
Qt.quit()
}
StackView{
id: newsStack
anchors.fill:parent
focus: true
Keys.onReleased: if (event.key === Qt.Key_Back && stackView.depth > 1) {
stackView.pop(); event.accepted = true;
}
initialItem:Rectangle {
y:1
color: "white"
width:root.width-2*mm
height:root.height-8*mm
Button {
id: newMessageButton
text: qsTr("+")
anchors.top: parent.top
anchors.right: parent.right
onClicked: {
Helperjs.readField("screen_name",root.db,"contacts",root.login.username,function(friends){
newsStack.push({item:"qrc:/qml/MessageSend.qml",properties:{"contacts": friends,"login":root.login}})
},"isFriend",1);
}
}
Button {
id: quitButton
text: qsTr("Quit")
anchors.top: parent.top
anchors.right: newMessageButton.left
onClicked: {cleanNews(root.db)}
}
Component { id:footerComponent
Rectangle{
border.color: "#EEEEEE"
border.width: 1
width:parent.width
height:6*mm
Text{
font.pixelSize: 1.5*mm
anchors.centerIn: parent
text:qsTr("More")
}
MouseArea{anchors.fill:parent
onClicked:{
var currentTime= new Date();
if(newstabStatus=="news"){
var lastnews_id=newsModel.get(newsModel.count-1).newsitemobject.created_at;
Newsjs.newsfromdb(root.db,root.login.username, function(news){
var msg = {'currentTime': currentTime, 'model': newsModel,'news':news,'appendnews':true};
newsWorker.sendMessage(msg);
},false,lastnews_id)}
else if(newstabStatus=="friendmessage"){
Newsjs.newsfromdb(root.db,root.login.username, function(news){
var msg = {'currentTime': currentTime, 'model': newsModel,'news':news,'appendnews':true};
newsWorker.sendMessage(msg);
},newsModel.get(newsModel.count-1).newsitemobject.uid,newsModel.get(newsModel.count-1).newsitemobject.created_at)}
}}
}
}
ListView {
id: newsView
anchors.fill: parent
anchors.topMargin: 8*root.mm
anchors.leftMargin: 3*root.mm; anchors.rightMargin: root.mm
anchors.bottomMargin: 1*root.mm
clip: true
spacing: 0
footer: footerComponent
model: newsModel
delegate: Newsitem{}
}
ListModel{id: newsModel}
WorkerScript {
id: newsWorker
source: "qrc:/js/newsworker.js"
}
Button {
id: update
anchors.top: parent.top
anchors.right: quitButton.left
text: "Update"
onClicked: { //try{newsModel.clear()} catch(e){}
newsBusy.running=true;
root.contactLoadType="news";
Newsjs.getFriendsTimeline(login,db,contactlist,newstab,function(ns,nc){
root.news=ns;root.newContacts=nc;root.currentContact=0;
if (ns.length==0){
Newsjs.getDirectMessage(root.login,root.db,root,function(dbnews){showNews(dbnews)});
newsBusy.running=false}
})}
}
BusyIndicator{
id: newsBusy
anchors.centerIn:update
//anchors.right: update.left
//anchors.top:parent.top
width:7*mm
height: 7*mm
}
Component.onCompleted: {
root.messageSignal.connect(onFriendsMessages);
root.directmessageSignal.connect(onDirectMessage);
root.newsSignal.connect(showNews);
try{newsModel.clear()} catch(e){}
Newsjs.newsfromdb(root.db,root.login.username, function(dbnews){
showNews(dbnews)
})
}
}
}
}

View File

@ -0,0 +1,286 @@
import QtQuick 2.0
import QtQuick.LocalStorage 2.0
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
import "qrc:/js/news.js" as Newsjs
import "qrc:/js/layout.js" as Layoutjs
Item {
id: newsitem
width: newsView.width
height:Math.max((itemMessage.height+createdAtLabel.height+friendicaActivities.height+4*mm),profileImage.height+user_name.height+mm)
// property var friendica_activities
property string conversation_id: ""
property string attending: ""
onAttendingChanged: {attendLabel.visible=true;
attendLabel.text= qsTr("attending: ")+ qsTr(attending)}
signal replyto(string parent_id)
Rectangle{width:newsitem.width; height: 1; anchors.bottom: newsitem.bottom; color:"light grey"}
Rectangle{
width:newsitem.width
height:newsitem.height-1
color: (newsitemobject.directmessage)?"#ffe6e6" : "white"
Column {
id: authorcolumn
width: 8*mm
Image {
id:profileImage
source: "file://"+newsitemobject.user.profile_image
x:1
width: 7*mm
height: 7*mm
MouseArea{
anchors.fill: parent
onPressAndHold: { newsmenu.popup()}
}
onStatusChanged: if (profileImage.status == Image.Error) {source="qrc:/images/defaultcontact.jpg"}
}
Label {
id:user_name
color: "grey"
//height:3.5*mm
width:parent.width
font.pixelSize: 1.5*mm
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
text: Qt.atob(newsitemobject.user.name)
}
}
Column {
id:newscolumn
anchors.left: authorcolumn.right
Row{
spacing: 5*mm
Label {
color: "grey"
text: if (newsitemobject.messagetype==0){qsTr("Source: ")+newsitemobject.source
} else if (newsitemobject.messagetype==1){ qsTr("Direct Message")} else {" Notification"}
font.pixelSize: 1.5*mm
}
Label {
id:createdAtLabel
color: "grey"
height:3.5*mm
font.pixelSize: 1.5*mm
horizontalAlignment: Label.AlignRight
text: dateDiff
}
CheckBox {
id:favoritedCheckbox
style: CheckBoxStyle {
background: Rectangle {
implicitWidth: 6*mm
implicitHeight:2*mm
color:"white"
}
indicator:
Rectangle{x:3*mm
width: 3*mm
implicitHeight:2*mm
Text{
anchors.centerIn: parent
color:control.checked?"black":"grey"
text:"\u2605"
}}
}
checked:(newsitemobject.favorited>0)
Text{
anchors.left: parent.right
color: "grey"
font.pixelSize: 1.5*mm
text: (newsitemobject.favorited>0)? newsitemobject.favorited+qsTr(" Favorites"):""
}
onClicked:{
if(favoritedCheckbox.checkedState==Qt.Checked)
{Newsjs.favorite(login,true,newsitemobject.status_id,root)}
else
if(favoritedCheckbox.checkedState==Qt.Unchecked)
{Newsjs.favorite(login,false,newsitemobject.status_id,root)}
}
}
}
Text {
color: "#404040"
linkColor: "light green"
id: itemMessage
textFormat: Text.RichText
text: Qt.atob(newsitemobject.statusnet_html)
width: newsitem.width-8*mm-2
height: implicitHeight
wrapMode: Text.Wrap
onLinkActivated:{ print("link "+link);
Qt.openUrlExternally(link)}
}
Row{id: friendicaActivities
spacing:mm
Label{color: "grey"
font.pixelSize: 1.5*mm
text: friendica_activities.likeText
}
Label{color: "grey"
font.pixelSize: 1.5*mm
text: friendica_activities.dislikeText
}
Label{color: "grey"
font.pixelSize: 1.5*mm
text: friendica_activities.attendyesText
}
Label{color: "grey"
font.pixelSize: 1.5*mm
text: friendica_activities.attendnoText
}
Label{color: "grey"
font.pixelSize: 1.5*mm
text: friendica_activities.attendmaybeText
}
}
Row {
CheckBox{id:likeCheckbox
height:3*mm
width:8*mm
checked:(newsitemobject.liked==1)?true:false
style: CheckBoxStyle {
background: Rectangle {
implicitWidth: 7*mm
implicitHeight: 3*mm
color:"white"
}
indicator:
Rectangle{
implicitWidth: 3*mm
implicitHeight:3*mm
color:control.checked?"yellow":"white"
x: 5*mm
Text{
font.pixelSize: 1.5*mm
color:"grey"
text:":-)"
}}
}
onClicked: {
if(likeCheckbox.checked==true){Newsjs.like(root.login,root.db,1,"like",newsitemobject.status_id,root);dislikeCheckbox.checked=false}
else{Newsjs.like(root.login,root.db,0,"like",newsitemobject.status_id,root)}}
}
CheckBox{id: dislikeCheckbox
height:3*mm
width:8*mm
checked: (newsitemobject.disliked==1)?true:false
style: CheckBoxStyle {
background: Rectangle {
implicitWidth: 7*mm
implicitHeight:3*mm
color:"white"
}
indicator:
Rectangle{
implicitWidth: 3*mm
implicitHeight:3*mm
color:control.checked?"yellow":"white"
x:5*mm
Text{
font.pixelSize: 1.5*mm
color:"grey"
text:":-("
}}
}
onClicked: {
if (dislikeCheckbox.checked==true){Newsjs.like(root.login,root.db,1,"dislike",newsitemobject.status_id);likeCheckbox.checked=false}
else {Newsjs.like(root.login,root.db,0,"dislike",newsitemobject.status_id,root)}}
}
Label {
id:replytoLabel
color: "grey"
height:3.5*mm
font.pixelSize: 1.5*mm
horizontalAlignment: Label.AlignRight
text: try {qsTr("In reply to ")+newsitemobject.reply_user.screen_name
}catch(e){" "}
}
Label {
id:attendLabel
visible: false
color: "grey"
height:3.5*mm
font.pixelSize: 1.5*mm
horizontalAlignment: Label.AlignRight
text: qsTr("attending: ")+ qsTr(attending)
}
}
}
Menu {
id:newsmenu
MenuItem {
text: qsTr("Reply")
onTriggered: {
newsStack.push({item:"qrc:/qml/MessageSend.qml",properties:{"reply_to_user": newsitemobject.user.screen_name,"parentId":newsitemobject.status_id}});
}
}
MenuItem {
text: qsTr("DM")
onTriggered: {
root.directmessageSignal(newsitemobject.user.screen_name);
}
}
MenuItem {
text: qsTr("Repost")
onTriggered: {
Newsjs.retweetNews(root.login,db,newsitemobject.status_id,root,function(reply){
print(reply);
})
}
}
MenuItem {
text: qsTr("Conversation")
onTriggered: {
Newsjs.requestConversation(root.login,db,newsitemobject.status_id,root,function(){
var currentTime= new Date();
Newsjs.conversationfromdb(db,root.login.username,newsitemobject.statusnet_conversation_id, function(newsarray){
newsModel.clear();
var msg = {'currentTime': currentTime, 'model': newsModel,'news':newsarray,'latestmessage':0};
newsWorker.sendMessage(msg);
});
}
)}
}
Menu{
title: qsTr("Attending")
MenuItem{text:qsTr("yes")
onTriggered: {Newsjs.attend(root.login,db,"yes",newsitemobject.status_id,root,function(){
newsitem.attending="yes";
attendLabel.visible=true})}
}
MenuItem{text:qsTr("maybe")
onTriggered: {Newsjs.attend(root.login,db,"maybe",newsitemobject.status_id,root,function(){
newsitem.attending="maybe"})}
}
MenuItem{text:qsTr("no")
onTriggered: {Newsjs.attend(root.login,db,"no",newsitemobject.status_id,root,function(){
newsitem.attending="no"})}
}
}
MenuItem {
text: qsTr("Delete")
onTriggered: {
Newsjs.deleteNews(root.login,db,newsitemobject.status_id,root,function(reply){
print(JSON.stringify(reply));
newsModel.remove(index);
})
}
}
}
}}

View File

@ -0,0 +1,100 @@
import QtQuick 2.0
import QtQuick.LocalStorage 2.0
import QtQuick.Controls 1.2
Package {
Item { id: stackItem; Package.name: 'stack'; z: stackItem.PathView.z;width:16.5*mm;height:16.5*mm}
Item { id: listItem; Package.name: 'list'; width: root.width-1*mm; height: root.height-8*mm; }
Item { id: gridItem; Package.name: 'grid';}
Item {
id: photoWrapper
width: 16.5*mm; height: 16.5*mm
z: stackItem.PathView.z
property string hqphotolink: photoLink
Rectangle {
id: placeHolder
color: 'lightblue'; antialiasing: true
anchors.fill:parent
//width: parent.width; height: parent.height;
}
BusyIndicator { anchors.centerIn: parent; running: realImage.status != Image.Ready }
Image {
id: realImage;
// property string hqphotolink: photoLink
width: photoWrapper.width; height: photoWrapper.height
antialiasing: true;
asynchronous: true
cache: false
fillMode: Image.PreserveAspectFit;
source: imageLocation
// onStatusChanged: if (realImage.status == Image.Ready) print(realImage.paintedHeight+"x"+realImage.paintedWidth)
}
Rectangle{
id:phototextRectangle
color:"black"
z:3
opacity: 0.5
width:phototext.contentWidth
height: phototext.contentHeight
anchors.bottom: photoWrapper.bottom
}
Text {
id:phototext
z:4
text: photoDescription.trim()
width:15*mm
anchors.bottom: photoWrapper.bottom
color: "white"
font.pixelSize: 2*mm
wrapMode:Text.Wrap
}
MouseArea {
width: realImage.paintedWidth; height: realImage.paintedHeight; anchors.centerIn: realImage
onClicked: {
if (albumWrapper.state == 'inGrid') {
gridItem.GridView.view.currentIndex = index;
//print("photoLink"+realImage.photoLink)
albumWrapper.state = 'fullscreen'
} else {
gridItem.GridView.view.currentIndex = index;
albumWrapper.state = 'inGrid'
}
}
}
states: [
State {
name: 'stacked'; when: albumWrapper.state == ''
ParentChange { target: photoWrapper; parent: stackItem; }//x: 1*mm; y: 1*mm }
PropertyChanges { target: photoWrapper; opacity: stackItem.PathView.onPath ? 1.0 : 0.0 }
PropertyChanges { target: phototext; opacity: 0.0 }
PropertyChanges { target: phototextRectangle; opacity: 0.0 }
},
State {
name: 'inGrid'; when: albumWrapper.state == 'inGrid'
ParentChange { target: photoWrapper; parent: gridItem; x: 1*mm; y: 1*mm;}
PropertyChanges { target: phototext; opacity: 1.0 }
PropertyChanges { target: phototextRectangle; opacity: 0.5 }
PropertyChanges { target: placeHolder; opacity: 1.0 }
},
State {
name: 'fullscreen'; when: albumWrapper.state == 'fullscreen'
ParentChange {
target: photoWrapper; parent: listItem; x: 1; y: 1;
width: root.width-mm; height: root.heigh-8*mm
}
PropertyChanges { target: placeHolder; opacity: 0.0 }
PropertyChanges { target: realImage; source: photoWrapper.hqphotolink}
PropertyChanges { target: phototext; anchors.bottom: realImage.bottom}
PropertyChanges { target: phototext; width:realImage.width }
PropertyChanges { target: phototextRectangle; anchors.bottom: realImage.bottom }
PropertyChanges { target: realImage; width: Math.min(listItem.width,sourceSize.width);height: Math.min(listItem.height,sourceSize.height) }
}
]
}
}

View File

@ -0,0 +1,26 @@
import QtQuick 2.0
import "qrc:/js/helper.js" as Helperjs
Image {
id:photoPlaceholder
property string imageName:"x.jpg"
property string downloadtype:""
fillMode: Image.PreserveAspectFit
onStatusChanged: {
if (photoPlaceholder.status == Image.Ready) {
print("Source: "+source+"Photo width"+width+" height"+height+" Ratio "+ fillMode);
var saveprocess=photoPlaceholder.grabToImage(function(result){
var saveresult=result.saveToFile(imageName.toString());
if (saveresult){
if ((downloadtype=="picture")&&(newImages.length>0)){
photoPlaceholder.destroy();
currentImageNo=currentImageNo+1
}
else if ((downloadtype=="contact")&&(root.newContacts.length>0))
{
photoPlaceholder.destroy(100);
root.currentContact=root.currentContact+1
}
}});
}}}

View File

@ -0,0 +1,140 @@
import QtQuick 2.0
import QtQuick.Dialogs 1.2
import QtQuick.Controls 1.4
import QtQml.Models 2.1
import "qrc:/js/service.js" as Service
import "qrc:/js/helper.js" as Helperjs
import "qrc:/qml"
Rectangle {
id:fotorectangle
y:1
width:root.width-mm
height:root.height-5*mm
color: '#fff'
property var newImages:[]
property int currentImageNo: 0
//onLoginChanged:{var msg = {'model': photogroupModel,'albums':[],'firstalbum':0,'foreignPicture':false};
// photoWorker.sendMessage(msg);
//}
onNewImagesChanged:{
if(newImages.length>0){
Service.dataRequest(root.login,newImages[currentImageNo].id,root.db,fotorectangle);
newImagesProgress.visible=true //download first image
}}
onCurrentImageNoChanged:{
if(currentImageNo<newImages.length){Service.dataRequest(root.login,newImages[currentImageNo].id,root.db,fotorectangle)};
if(currentImageNo==newImages.length){newImagesProgress.visible=false;showOwnFotos();
newImages=[];currentImageNo=0}
// download next image if photoplaceholder is finished saving
}
ProgressBar{
id: newImagesProgress
width: 15*mm
height: updatePhotolist.height
anchors.top: parent.top
anchors.right:updatePhotolist.left
anchors.rightMargin:mm
visible: false
value: currentImageNo/newImages.length
}
Button{
id: updatePhotolist
anchors.top: parent.top
anchors.right:showFotos.left
anchors.rightMargin:mm
text: qsTr("Update")
onClicked: {
Service.requestList(root.login,root.db, fotostab,function(obj){
newImages=obj;
})}}
Button{
id: showFotos
anchors.top: parent.top
anchors.right: parent.right
anchors.rightMargin:2*mm
text: qsTr("Show")
onClicked: {showOwnFotos()}
}
DelegateModel{
id: visualphotoModel
delegate: PhotogroupComponent{}
model: photogroupModel
}
ListModel{
id: photogroupModel
}
GridView {
id: albumgridview
cellWidth: 17*mm
cellHeight: 17*mm
x: mm;y:8*mm
width: parent.width-2*mm; height: parent.height-9*mm
clip: true
model: visualphotoModel.parts.album
footer:
Rectangle{
border.color: "#EEEEEE"
border.width: 1
width:12*mm
height:6*mm
Text{
font.pixelSize: 1.5*mm
anchors.centerIn: parent
text:qsTr("More")
}
MouseArea{anchors.fill:parent
onClicked:{
var lastalbum_id=photogroupModel.get(photogroupModel.count-1);
if(photogroupModel.get(photogroupModel.count-1).foreignPictures==false){Service.requestFriendsAlbumPictures(friend,fotostab,function(albums){
var msg = {'model': photogroupModel,'albums':albums,'firstalbum':lastalbum_id+1,'foreignPicture':true};
photoWorker.sendMessage(msg); })}
else { Helperjs.readField("album",root.db, "imageData",root.login.username,function(albums){
var msg = { 'model': photogroupModel,'albums':albums,'foreignPicture': false,'firstalbum':lastalbum_id+1};
photoWorker.sendMessage(msg)})}
}}}
}
Rectangle { id: photoBackground; color: 'light grey'; width: parent.width; height: parent.height; opacity: 0; visible: opacity != 0.0 }
ListView { anchors.fill: parent; model: visualphotoModel.parts.browser; interactive: false }
Button {
id: backButton
text: qsTr("Back")
x: parent.width - backButton.width - 3*mm
y: -backButton.height - 4*mm
onClicked: {photoBackground.opacity=0}
// visible: Qt.platform.os !== "android"
}
ListView {anchors.fill: parent; model: visualphotoModel.parts.fullscreen; interactive: false }
WorkerScript{id: photoWorker;source: "qrc:/js/photoworker.js"}
function showOwnFotos(){
try {photogroupModel.clear()}catch (e){print(e)}
Helperjs.readField("album",root.db, "imageData",root.login.username,function(albums){
if (albums[0]) {
var msg = { 'model': photogroupModel,'albums':albums,'firstalbum':0,'foreignPicture': false};
photoWorker.sendMessage(msg);
};
})
}
function onFriendsFotos(friend){print("Friend "+friend.url);
try {photogroupModel.clear()}catch (e){print(e)}
Service.requestFriendsAlbumPictures(friend,fotostab,function(albums){
var msg = {'model': photogroupModel,'albums':albums,'firstalbum':0,'foreignPicture':true};
photoWorker.sendMessage(msg);
})
}
Component.onCompleted: { root.fotoSignal.connect(onFriendsFotos);}
}

View File

@ -0,0 +1,48 @@
import QtQuick 2.0
import QtQuick.Dialogs 1.2
import QtQuick.Controls 1.2
Item {
Rectangle{
property string photofile:"../images/Update.png"
color: "grey"
FileDialog {
id: fileDialog
title: "Please choose a file"
folder: shortcuts.pictures
selectMultiple: true
onAccepted: {
photofile=fileDialog.fileUrls[0];
console.log("You chose: " + fileDialog.fileUrls)
// img.src=file;
}
onRejected: {
console.log("Canceled")
}
}
Component.onCompleted: {fileDialog.open()}
Image {
id: photoFromFilesystem
x: 20;y:50
height: 200
fillMode: Image.PreserveAspectFit
source: photofile
onStatusChanged:{
if (photoFromFilesystem.status == Image.Ready) {
Layoutjs.showFriends(db)
}
}
Button {
text: "Upload"
onClicked:{
var login=Service.readActiveConfig(db);
Service.uploadMedia(login,photofile, function(returnvalue){print("Upload return"+returnvalue)})
}}
}
}
}

View File

@ -0,0 +1,119 @@
import QtQuick 2.0
import QtQuick.LocalStorage 2.0
import QtQuick.Controls 1.3
import QtQml.Models 2.1
import "qrc:/js/service.js" as Service
import "qrc:/js/helper.js" as Helperjs
Package {
Item {
Package.name: 'browser'
GridView {
id: photosGridView; model: visualModel.parts.grid; width: albumgridview.width; height: albumgridview.height
cellWidth: 16.5*mm; cellHeight: 16.5*mm; interactive: false;anchors.margins:2*mm
onCurrentIndexChanged: photosListView.positionViewAtIndex(currentIndex, ListView.Contain)
}
}
Item {
Package.name: 'fullscreen'
ListView {
id: photosListView; model: visualModel.parts.list; orientation: Qt.Horizontal
width: parent.width; height: parent.height; interactive: false
onCurrentIndexChanged: photosGridView.positionViewAtIndex(currentIndex, GridView.Contain)
highlightRangeMode: ListView.StrictlyEnforceRange; snapMode: ListView.SnapOneItem
}
}
Item {
Package.name: 'album'
id: albumWrapper; width: 16.5*mm; height: 16.5*mm //-albumtext.contentHeight
DelegateModel {
id: visualModel; delegate: PhotoComponent { }
model: photoModel
}
PathView {
id: photosPathView;
model: visualModel.parts.stack;
pathItemCount: 1
anchors.centerIn: parent;
path: Path {
PathAttribute { name: 'z'; value: 9999.0 }
PathLine { x: 1; y: 1 }
PathAttribute { name: 'z'; value: 0.0 }
}
}
Rectangle{
color:"black"
opacity: 0.5
width:albumtext.contentWidth
height: albumtext.contentHeight
anchors.bottom: albumWrapper.bottom
}
Text {
id:albumtext
text: albumname //foreignPicture ? album.name.trim() : album
width:albumWrapper.width-1*mm
height: albumtext.contentHeight
wrapMode:Text.Wrap
color: "white"
font.family: "Monospace"
font.pixelSize: 2*mm
anchors.bottom: albumWrapper.bottom
}
ListModel{
id: photoModel
}
Component.onCompleted:{
try {photoModel.clear()}catch (e){print(e)}
if(foreignPicture){
//print("Albumlink"+album.link);
Service.requestFriendsPictures(albumlink,fotostab,function(obj){
if (obj) {
for (var k=0;k<obj.length;k++){
//print("Photomodel:"+obj[k].thumb+obj[k].name+obj[k].link);
photoModel.append({"imageLocation": obj[k].thumb,"photoDescription":obj[k].name,"photoLink":obj[k].link})
};
}
})}
else{
Helperjs.readData(db,"imageData",root.login.username,function(obj){
// obj.sort(function(obj1,obj2){return obj1.data-obj2.data});
if (obj) {
for (var k=0;k<obj.length;k++){
// print("Photomodel:"+obj[k].location+obj[k].filename);
photoModel.append({"imageLocation": obj[k].location+obj[k].filename,"photoDescription":obj[k].filename,"photoLink":obj[k].location+obj[k].filename})
};
}
},"album",albumname)}
}
MouseArea {
anchors.fill: parent
onClicked: albumWrapper.state = 'inGrid'
}
states: [
State {
name: 'inGrid'
PropertyChanges { target: photosGridView; interactive: true }
PropertyChanges { target: photoBackground; opacity: 1 }
PropertyChanges { target: backButton; onClicked: albumWrapper.state = ''; y: 6 }
},
State {
name: 'fullscreen'; extend: 'inGrid'
PropertyChanges { target: photosGridView; interactive: false }
PropertyChanges { target: photosListView; interactive: true }
PropertyChanges { target: photoBackground; opacity: 1 }
PropertyChanges { target: backButton; y: -backButton.height - 8 }
}
]
} //album Ende
} //Package Ende
//item Ende

View File

@ -0,0 +1,112 @@
import QtQuick 2.0
import QtQuick.LocalStorage 2.0
import QtQuick.Window 2.0
import QtQuick.Dialogs 1.2
import QtQuick.Controls 1.2
import QtQml.Models 2.1
import "qrc:/js/news.js" as Newsjs
import "qrc:/js/service.js" as Service
import "qrc:/js/layout.js" as Layoutjs
import "qrc:/js/helper.js" as Helperjs
import "qrc:/qml"
TabView{
id:root
tabPosition: Qt.BottomEdge
width: 400//Screen.desktopAvailableWidth
height: 400// Screen.desktopAvailableHeight
property var db: ["Photos", "1.0", "Stores Friendica data", 100000000]
property var login: Service.readActiveConfig(db)
property var contactlist: []
property real mm: Screen.pixelDensity
signal messageSignal(var friend)
signal fotoSignal(var friend)
signal directmessageSignal(var friend)
signal newsSignal(var news)
currentIndex: (login=="")? 3:0
property var news:[]
property var newContacts:[]
property int currentContact: 0
property string contactLoadType: ""
onLoginChanged:{Newsjs.newsfromdb( db,login.username, function(dbnews){
newsSignal(dbnews)
})}
onNewContactsChanged:{if(newContacts.length>0){// download first contact image and update db
print("newcontact"+JSON.stringify(newContacts[0]));
updateContactInDB(login,db,newContacts[currentContact].isFriend,newContacts[currentContact])}
}
onCurrentContactChanged:{// download next contact image after photoplaceholder is finished saving and update db
print("Current contact"+JSON.stringify(newContacts[currentContact]));
if(currentContact<newContacts.length){
updateContactInDB(login,db,newContacts[currentContact].isFriend,newContacts[currentContact])}
else if(currentContact==newContacts.length){//newImagesProgress.visible=false;
if (newContacts.length==0) {}
else if (contactLoadType=="news"){
Newsjs.storeNews(login,db,news,root,function(dbnews){
root.newsSignal(dbnews);
root.newContacts=[];
root.currentContact=0;
root.news=[]
})// show news
}
else if (contactLoadType=="friends"){
root.friendsSignal(login.username);
// show friends
Helperjs.readField("id",db,"contacts",login.username,function(contacts){contactlist=contacts;
root.newContacts=[];
root.currentContact=0},"isFriend",1) }
}
}
function updateContactInDB(login,database,isFriend,contact){// for newstab and friendstab
try{var imagename=login.imagestore+"contacts/"+contact.screen_name+".jpg";
var component=Qt.createComponent("qrc:/qml/PhotoPlaceholder.qml");
print("imageName "+imagename+" source "+ contact.profile_image_url)
var sprite = component.createObject(root, {"fillMode": "Image.PreserveAspectFit","x":root.width,"y":50,"imageName":imagename,"source": contact.profile_image_url,"downloadtype":"contact"});} catch(e){print("Fehler beim Profilbild"+e)}
var db=LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
var result;
db.transaction( function(tx) {
result = tx.executeSql('SELECT * from contacts where id = '+contact.id); // check for news id
if(result.rows.length === 1) {// use update
result = tx.executeSql('UPDATE contacts SET username="'+login.username+'", id='+contact.id+', name="'+Qt.btoa(contact.name)+'", screen_name="'+contact.screen_name+'", location="'+contact.location+'",description="'+Qt.btoa(contact.description)+'", profile_image="'+imagename+'", url="'+contact.url+'" , protected="'+contact.protected+'", followers_count='+contact.followers_count+', friends_count='+contact.friends_count+', created_at="'+ Newsjs.cleanDate(contact.created_at)+'", favourites_count="'+contact.favorites_count+'", utc_offset="'+contact.utc_offset+'", time_zone="'+contact.time_zone+'", statuses_count='+contact.statuses_count+', following="'+contact.following+'", verified ="'+contact.verified+'", statusnet_blocking="'+contact.statusnet_blocking+'", notifications="'+contact.notifictions+'", statusnet_profile_url="'+contact.statusnet_profile_url+'", cid='+contact.cid+', network="'+contact.network+'", isFriend='+isFriend+' where id='+contact.id);
} else {// use insert
result = tx.executeSql('INSERT INTO contacts VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)', [login.username,contact.id,Qt.btoa(contact.name),contact.screen_name,contact.location,Qt.btoa(contact.description),imagename,contact.url,contact.protected,contact.followers_count, contact.friends_count,Newsjs.cleanDate(contact.created_at),contact.favorites_count,contact.utc_offset,contact.time_zone,contact.statuses_count,contact.following,contact.verfied,contact.statusnet_blocking,contact.notifications,contact.statusnet_profile_url,contact.cid,contact.network,isFriend]);}
});
}
Component.onCompleted: {
if (login==""){Service.initDatabase(db)}
Helperjs.readField("id",db,"contacts",login.username,function(contacts){contactlist=contacts},"isFriend",1)
}
Tab{
title: qsTr("News")
id: newstab
property string newstabStatus:"news"
source: "qrc:/qml/NewsTab.qml"
}
Tab{
title: qsTr("Contacts")
id: friendstab
source: "qrc:/qml/FriendsTab.qml"
}
Tab{
title: qsTr("Photos")
id: fotostab
source: "qrc:/qml/PhotoTab.qml"
}
Tab{
title: qsTr("Config")
source: "qrc:/qml/ConfigTab.qml"
}
}