Initial project import

This commit is contained in:
Morgan McMillian 2018-01-20 15:44:35 -08:00
parent b52fa83c6f
commit 9b4d7572f0
66 changed files with 3617 additions and 0 deletions

177
.cproject Normal file
View File

@ -0,0 +1,177 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?fileVersion 4.0.0?><cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage">
<storageModule moduleId="org.eclipse.cdt.core.settings">
<cconfiguration id="com.qnx.qcc.toolChain.947755685">
<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="com.qnx.qcc.toolChain.947755685" moduleId="org.eclipse.cdt.core.settings" name="Device-Debug">
<externalSettings/>
<extensions>
<extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="com.qnx.tools.ide.qde.core.QDEBynaryParser" point="org.eclipse.cdt.core.BinaryParser"/>
</extensions>
</storageModule>
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
<configuration artifactName="${ProjName}" buildProperties="" id="com.qnx.qcc.toolChain.947755685" name="Device-Debug" parent="org.eclipse.cdt.build.core.emptycfg">
<folderInfo id="com.qnx.qcc.toolChain.947755685.1896283368" name="/" resourcePath="">
<toolChain id="com.qnx.qcc.toolChain.2014421305" name="com.qnx.qcc.toolChain" superClass="com.qnx.qcc.toolChain">
<option id="com.qnx.qcc.option.os.1573788448" name="Target OS:" superClass="com.qnx.qcc.option.os"/>
<option id="com.qnx.qcc.option.cpu.1986230114" name="Target CPU:" superClass="com.qnx.qcc.option.cpu" value="com.qnx.qcc.option.gen.cpu.armle-v7" valueType="enumerated"/>
<option id="com.qnx.qcc.option.compiler.510586552" name="Compiler:" superClass="com.qnx.qcc.option.compiler"/>
<option id="com.qnx.qcc.option.runtime.2053006510" name="Runtime:" superClass="com.qnx.qcc.option.runtime"/>
<targetPlatform archList="all" binaryParser="com.qnx.tools.ide.qde.core.QDEBynaryParser" id="com.qnx.qcc.targetPlatform.1320737159" osList="all" superClass="com.qnx.qcc.targetPlatform"/>
<builder autoBuildTarget="Device-Debug" enableAutoBuild="true" id="com.qnx.qcc.toolChain.947755685.843346825" incrementalBuildTarget="Device-Debug" managedBuildOn="false" name="device-debug builder" parallelBuildOn="true" parallelizationNumber="optimal" superClass="qml.device-debug"/>
<tool id="com.qnx.qcc.tool.compiler.982729952" name="QCC Compiler" superClass="com.qnx.qcc.tool.compiler">
<option id="com.qnx.qcc.option.compiler.optlevel.855903159" superClass="com.qnx.qcc.option.compiler.optlevel" value="com.qnx.qcc.option.compiler.optlevel.0" valueType="enumerated"/>
<inputType id="com.qnx.qcc.inputType.compiler.477042557" superClass="com.qnx.qcc.inputType.compiler"/>
</tool>
<tool id="com.qnx.qcc.tool.assembler.1797181361" name="QCC Assembler" superClass="com.qnx.qcc.tool.assembler">
<inputType id="com.qnx.qcc.inputType.assembler.1841210258" superClass="com.qnx.qcc.inputType.assembler"/>
</tool>
<tool id="com.qnx.qcc.tool.linker.1610983011" name="QCC Linker" superClass="com.qnx.qcc.tool.linker"/>
<tool id="com.qnx.qcc.tool.archiver.1879992688" name="QCC Archiver" superClass="com.qnx.qcc.tool.archiver"/>
</toolChain>
</folderInfo>
<sourceEntries>
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="src"/>
</sourceEntries>
</configuration>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
</cconfiguration>
<cconfiguration id="com.qnx.qcc.toolChain.163195910">
<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="com.qnx.qcc.toolChain.163195910" moduleId="org.eclipse.cdt.core.settings" name="Device-Release">
<externalSettings/>
<extensions>
<extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="com.qnx.tools.ide.qde.core.QDEBynaryParser" point="org.eclipse.cdt.core.BinaryParser"/>
</extensions>
</storageModule>
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
<configuration artifactName="${ProjName}" buildProperties="" id="com.qnx.qcc.toolChain.163195910" name="Device-Release" parent="org.eclipse.cdt.build.core.emptycfg">
<folderInfo id="com.qnx.qcc.toolChain.163195910.1206948577" name="/" resourcePath="">
<toolChain id="com.qnx.qcc.toolChain.1283594665" name="com.qnx.qcc.toolChain" superClass="com.qnx.qcc.toolChain">
<option id="com.qnx.qcc.option.os.1197908864" name="Target OS:" superClass="com.qnx.qcc.option.os"/>
<option id="com.qnx.qcc.option.cpu.466390908" name="Target CPU:" superClass="com.qnx.qcc.option.cpu" value="com.qnx.qcc.option.gen.cpu.armle-v7" valueType="enumerated"/>
<option id="com.qnx.qcc.option.compiler.15338540" name="Compiler:" superClass="com.qnx.qcc.option.compiler"/>
<option id="com.qnx.qcc.option.runtime.299787303" name="Runtime:" superClass="com.qnx.qcc.option.runtime"/>
<targetPlatform archList="all" binaryParser="com.qnx.tools.ide.qde.core.QDEBynaryParser" id="com.qnx.qcc.targetPlatform.1678112032" osList="all" superClass="com.qnx.qcc.targetPlatform"/>
<builder autoBuildTarget="Device-Release" enableAutoBuild="true" id="com.qnx.qcc.toolChain.163195910.1237349782" incrementalBuildTarget="Device-Release" managedBuildOn="false" name="device-release builder" parallelBuildOn="true" parallelizationNumber="optimal" superClass="qml.device-release"/>
<tool id="com.qnx.qcc.tool.compiler.941986831" name="QCC Compiler" superClass="com.qnx.qcc.tool.compiler">
<option id="com.qnx.qcc.option.compiler.optlevel.1235834023" superClass="com.qnx.qcc.option.compiler.optlevel" value="com.qnx.qcc.option.compiler.optlevel.0" valueType="enumerated"/>
<inputType id="com.qnx.qcc.inputType.compiler.1681397245" superClass="com.qnx.qcc.inputType.compiler"/>
</tool>
<tool id="com.qnx.qcc.tool.assembler.361527844" name="QCC Assembler" superClass="com.qnx.qcc.tool.assembler">
<inputType id="com.qnx.qcc.inputType.assembler.1525015751" superClass="com.qnx.qcc.inputType.assembler"/>
</tool>
<tool id="com.qnx.qcc.tool.linker.1383975900" name="QCC Linker" superClass="com.qnx.qcc.tool.linker"/>
<tool id="com.qnx.qcc.tool.archiver.1235730427" name="QCC Archiver" superClass="com.qnx.qcc.tool.archiver"/>
</toolChain>
</folderInfo>
<sourceEntries>
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="src"/>
</sourceEntries>
</configuration>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
</cconfiguration>
<cconfiguration id="com.qnx.qcc.toolChain.1123754513">
<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="com.qnx.qcc.toolChain.1123754513" moduleId="org.eclipse.cdt.core.settings" name="Device-Profile">
<externalSettings/>
<extensions>
<extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="com.qnx.tools.ide.qde.core.QDEBynaryParser" point="org.eclipse.cdt.core.BinaryParser"/>
</extensions>
</storageModule>
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
<configuration artifactName="${ProjName}" buildProperties="" id="com.qnx.qcc.toolChain.1123754513" name="Device-Profile" parent="org.eclipse.cdt.build.core.emptycfg">
<folderInfo id="com.qnx.qcc.toolChain.1123754513.837787992" name="/" resourcePath="">
<toolChain id="com.qnx.qcc.toolChain.748818496" name="com.qnx.qcc.toolChain" superClass="com.qnx.qcc.toolChain">
<option id="com.qnx.qcc.option.os.261302143" name="Target OS:" superClass="com.qnx.qcc.option.os"/>
<option id="com.qnx.qcc.option.cpu.172430544" name="Target CPU:" superClass="com.qnx.qcc.option.cpu" value="com.qnx.qcc.option.gen.cpu.armle-v7" valueType="enumerated"/>
<option id="com.qnx.qcc.option.compiler.730158518" name="Compiler:" superClass="com.qnx.qcc.option.compiler"/>
<option id="com.qnx.qcc.option.runtime.2089538649" name="Runtime:" superClass="com.qnx.qcc.option.runtime"/>
<targetPlatform archList="all" binaryParser="com.qnx.tools.ide.qde.core.QDEBynaryParser" id="com.qnx.qcc.targetPlatform.993250872" osList="all" superClass="com.qnx.qcc.targetPlatform"/>
<builder autoBuildTarget="Device-Profile" enableAutoBuild="true" id="com.qnx.qcc.toolChain.1123754513.1154586437" incrementalBuildTarget="Device-Profile" managedBuildOn="false" name="device-profile builder" parallelBuildOn="true" parallelizationNumber="optimal" superClass="qml.device-profile"/>
<tool id="com.qnx.qcc.tool.compiler.9203464" name="QCC Compiler" superClass="com.qnx.qcc.tool.compiler">
<option id="com.qnx.qcc.option.compiler.optlevel.1794424905" superClass="com.qnx.qcc.option.compiler.optlevel" value="com.qnx.qcc.option.compiler.optlevel.0" valueType="enumerated"/>
<inputType id="com.qnx.qcc.inputType.compiler.513797780" superClass="com.qnx.qcc.inputType.compiler"/>
</tool>
<tool id="com.qnx.qcc.tool.assembler.1201586451" name="QCC Assembler" superClass="com.qnx.qcc.tool.assembler">
<inputType id="com.qnx.qcc.inputType.assembler.1088281760" superClass="com.qnx.qcc.inputType.assembler"/>
</tool>
<tool id="com.qnx.qcc.tool.linker.2016751733" name="QCC Linker" superClass="com.qnx.qcc.tool.linker"/>
<tool id="com.qnx.qcc.tool.archiver.1749336552" name="QCC Archiver" superClass="com.qnx.qcc.tool.archiver"/>
</toolChain>
</folderInfo>
<sourceEntries>
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="src"/>
</sourceEntries>
</configuration>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
</cconfiguration>
<cconfiguration id="com.qnx.qcc.toolChain.861397188">
<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="com.qnx.qcc.toolChain.861397188" moduleId="org.eclipse.cdt.core.settings" name="Simulator-Debug">
<externalSettings/>
<extensions>
<extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="com.qnx.tools.ide.qde.core.QDEBynaryParser" point="org.eclipse.cdt.core.BinaryParser"/>
</extensions>
</storageModule>
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
<configuration artifactName="${ProjName}" buildProperties="" id="com.qnx.qcc.toolChain.861397188" name="Simulator-Debug" parent="org.eclipse.cdt.build.core.emptycfg">
<folderInfo id="com.qnx.qcc.toolChain.861397188.1626520056" name="/" resourcePath="">
<toolChain id="com.qnx.qcc.toolChain.1003832125" name="com.qnx.qcc.toolChain" superClass="com.qnx.qcc.toolChain">
<option id="com.qnx.qcc.option.os.1415020463" name="Target OS:" superClass="com.qnx.qcc.option.os"/>
<option id="com.qnx.qcc.option.cpu.1782568602" name="Target CPU:" superClass="com.qnx.qcc.option.cpu"/>
<option id="com.qnx.qcc.option.compiler.249976083" name="Compiler:" superClass="com.qnx.qcc.option.compiler"/>
<option id="com.qnx.qcc.option.runtime.643365857" name="Runtime:" superClass="com.qnx.qcc.option.runtime"/>
<targetPlatform archList="all" binaryParser="com.qnx.tools.ide.qde.core.QDEBynaryParser" id="com.qnx.qcc.targetPlatform.1328196709" osList="all" superClass="com.qnx.qcc.targetPlatform"/>
<builder autoBuildTarget="Simulator-Debug" enableAutoBuild="true" id="com.qnx.qcc.toolChain.861397188.161893676" incrementalBuildTarget="Simulator-Debug" managedBuildOn="false" name="simulator-debug builder" parallelBuildOn="true" parallelizationNumber="optimal" superClass="qml.simulator-debug"/>
<tool id="com.qnx.qcc.tool.compiler.280821553" name="QCC Compiler" superClass="com.qnx.qcc.tool.compiler">
<option id="com.qnx.qcc.option.compiler.optlevel.877904971" superClass="com.qnx.qcc.option.compiler.optlevel" value="com.qnx.qcc.option.compiler.optlevel.0" valueType="enumerated"/>
<inputType id="com.qnx.qcc.inputType.compiler.1615469303" superClass="com.qnx.qcc.inputType.compiler"/>
</tool>
<tool id="com.qnx.qcc.tool.assembler.601725037" name="QCC Assembler" superClass="com.qnx.qcc.tool.assembler">
<inputType id="com.qnx.qcc.inputType.assembler.1913985478" superClass="com.qnx.qcc.inputType.assembler"/>
</tool>
<tool id="com.qnx.qcc.tool.linker.438910673" name="QCC Linker" superClass="com.qnx.qcc.tool.linker"/>
<tool id="com.qnx.qcc.tool.archiver.868243104" name="QCC Archiver" superClass="com.qnx.qcc.tool.archiver"/>
</toolChain>
</folderInfo>
<sourceEntries>
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="src"/>
</sourceEntries>
</configuration>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
</cconfiguration>
</storageModule>
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
<project id="RenamedTodo.null.398227093" name="RenamedTodo"/>
</storageModule>
<storageModule moduleId="scannerConfiguration">
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="com.qnx.tools.ide.qde.managedbuilder.core.qccScannerInfo"/>
<scannerConfigBuildInfo instanceId="com.qnx.qcc.toolChain.861397188">
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="com.qnx.tools.ide.qde.managedbuilder.core.qccScannerInfo"/>
</scannerConfigBuildInfo>
<scannerConfigBuildInfo instanceId="com.qnx.qcc.toolChain.947755685">
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="com.qnx.tools.ide.qde.managedbuilder.core.qccScannerInfo"/>
</scannerConfigBuildInfo>
<scannerConfigBuildInfo instanceId="com.qnx.qcc.toolChain.1123754513">
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="com.qnx.tools.ide.qde.managedbuilder.core.qccScannerInfo"/>
</scannerConfigBuildInfo>
<scannerConfigBuildInfo instanceId="com.qnx.qcc.toolChain.163195910">
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="com.qnx.tools.ide.qde.managedbuilder.core.qccScannerInfo"/>
</scannerConfigBuildInfo>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
<storageModule moduleId="refreshScope"/>
</cproject>

45
.project Normal file
View File

@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>RenamedTodo</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>com.rim.tad.tools.qml.core.qmlFileBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.wst.jsdt.core.javascriptValidator</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
<triggers>auto,full,incremental,</triggers>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>com.qnx.tools.bbt.xml.core.bbtXMLValidationBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.wst.jsdt.core.jsNature</nature>
<nature>org.eclipse.cdt.core.cnature</nature>
<nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
<nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
<nature>com.qnx.tools.ide.bbt.core.bbtnature</nature>
<nature>org.eclipse.cdt.core.ccnature</nature>
<nature>org.eclipse.cdt.qt.core.qtNature</nature>
<nature>com.rim.tad.tools.qml.core.qmlNature</nature>
</natures>
</projectDescription>

6
Makefile Normal file
View File

@ -0,0 +1,6 @@
QMAKE_TARGET = RenamedTodo
PROJECT_DIR := $(dir $(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST)))
I18N_DIR := $(PROJECT_DIR)/translations
include mk/cs-base.mk

6
RenamedTodo.pro Normal file
View File

@ -0,0 +1,6 @@
APP_NAME = RenamedTodo
CONFIG += qt warn_on cascades10
LIBS += -lbbsystem -lbb
include(config.pri)

50
assets/.assets.index Normal file
View File

@ -0,0 +1,50 @@
1
48
AboutPage.qml
AppCover.qml
EditSheet.qml
FilterPage.qml
help.html
HelpPage.qml
humane.js
icons/123.png
icons/abc.png
icons/Add.png
icons/Capitalize.png
icons/Check.png
icons/Clock.png
icons/Clock_a.png
icons/Date.png
icons/Delete.png
icons/DownBox.png
icons/Funnel.png
icons/ic_bbm.png
icons/Info.png
icons/invoke.png
icons/Pencil.png
icons/PriceTag.png
icons/Recycle.png
icons/rtd_512_3-110.png
icons/rtd_512_3-144.png
icons/rtd_512_3-86.png
icons/rtd_512_3-90.png
icons/rtd_512_3-96.png
icons/rtd_splash_1440s.png
icons/rtd_splash_720s.png
icons/rtd_splash_768p.png
icons/Search.png
icons/Sort.png
icons/Undo.png
main.qml
SettingsPage.qml
TaskItem.qml
TaskPage.qml
VisualStyle.bright/Appointment.png
VisualStyle.bright/ArrowCircleAlt.png
VisualStyle.bright/PriceTag.png
VisualStyle.bright/Watch.png
VisualStyle.dark/Appointment.png
VisualStyle.dark/ArrowCircleAlt.png
VisualStyle.dark/PriceTag.png
VisualStyle.dark/Watch.png
Watch_a.png

106
assets/AboutPage.qml Normal file
View File

@ -0,0 +1,106 @@
/*
* Copyright 2012-2018 Morgan McMillian <gilag@monkeystew.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import bb.cascades 1.0
Page {
ScrollView {
Container {
layout: DockLayout {
}
horizontalAlignment: HorizontalAlignment.Fill
Container {
horizontalAlignment: HorizontalAlignment.Fill
Container {
horizontalAlignment: HorizontalAlignment.Center
preferredHeight: 35.0
}
Container {
horizontalAlignment: HorizontalAlignment.Center
Label {
text: "Renamed Todo"
textStyle.fontSize: FontSize.Large
}
}
Container {
horizontalAlignment: HorizontalAlignment.Center
Label {
text: "v" + appversion
textStyle.fontSize: FontSize.Small
}
}
Container {
horizontalAlignment: HorizontalAlignment.Center
Label {
text: "Copyright (c) Morgan McMillian 2012-2018"
textStyle.fontSize: FontSize.XSmall
}
}
Container {
horizontalAlignment: HorizontalAlignment.Center
Label {
text: "All rights reserved."
textStyle.fontSize: FontSize.XSmall
}
}
Container {
horizontalAlignment: HorizontalAlignment.Center
preferredHeight: 40.0
}
Container {
horizontalAlignment: HorizontalAlignment.Center
Label {
text: "https://monkeystew.org/renamed-todo/"
textStyle.fontSize: FontSize.XSmall
content.flags: TextContentFlag.ActiveText
}
}
Container {
horizontalAlignment: HorizontalAlignment.Center
preferredHeight: 30.0
}
Container {
horizontalAlignment: HorizontalAlignment.Center
preferredHeight: 30.0
}
Container {
horizontalAlignment: HorizontalAlignment.Center
preferredHeight: 30.0
}
Divider {
}
Container {
horizontalAlignment: HorizontalAlignment.Center
preferredHeight: 30.0
}
Container {
leftPadding: 10.0
rightPadding: 10.0
horizontalAlignment: HorizontalAlignment.Fill
Button {
text: "Email Support"
horizontalAlignment: HorizontalAlignment.Center
onClicked: {
_Taskslayer.getSupport(0)
}
}
}
}
}
}
}

103
assets/AppCover.qml Normal file
View File

@ -0,0 +1,103 @@
/*
* Copyright 2012-2018 Morgan McMillian <gilag@monkeystew.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import bb.cascades 1.0
import "humane.js" as HumaneDate
SceneCover {
// SceneCover
property alias topList: topList
property bool empty
id: appCover
content: Container {
Container {
visible: empty ? false : true
ListView {
dataModel: ArrayDataModel {
id: topList
}
listItemComponents: [
ListItemComponent {
Container {
layout: StackLayout {
}
Container {
layout: DockLayout {
}
horizontalAlignment: HorizontalAlignment.Fill
leftPadding: 10.0
rightPadding: 10.0
topPadding: 10.0
Container {
layout: StackLayout {
orientation: LayoutOrientation.LeftToRight
}
Container {
minWidth: 50.0
Label {
text: ListItemData.priority
textStyle.fontSize: FontSize.Medium
textStyle.color: Color.Blue
}
}
}
Container {
layout: StackLayout {
}
leftPadding: 30.0
Container {
Label {
text: ListItemData.detail
multiline: true
textStyle.fontSize: FontSize.XSmall
textStyle.color: Color.Black
}
}
Container {
Label {
text: HumaneDate.humaneDate(ListItemData.dateCreated)
textStyle.fontSize: FontSize.XXSmall
textStyle.color: Color.Gray
}
}
}
}
Divider {
}
}
}
]
}
}
Container {
layout: DockLayout {
}
visible: empty
verticalAlignment: VerticalAlignment.Fill
horizontalAlignment: HorizontalAlignment.Fill
opacity: 1.0
Container {
verticalAlignment: VerticalAlignment.Center
horizontalAlignment: HorizontalAlignment.Center
topPadding: 100.0
Label {
text: "no tasks"
horizontalAlignment: HorizontalAlignment.Center
}
}
}
} // end content
}// end SceneCover

384
assets/EditSheet.qml Normal file
View File

@ -0,0 +1,384 @@
/*
* Copyright 2012-2018 Morgan McMillian <gilag@monkeystew.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import bb.cascades 1.0
import bb.system 1.0
Sheet {
id: editSheet
signal saveTask(string text)
signal modifySetting(string setting, variant value)
property alias text: taskText.text
property alias textfield: taskText
property alias title: addBar.title
property alias pri: priority.selectedValue
property alias labels: labels
property bool displayed: false
property bool datenew
property bool newtask
property bool taskitem
Page {
id: addPage
titleBar: TitleBar {
id: addBar
title: "Add"
dismissAction: ActionItem {
title: "Cancel"
onTriggered: {
editSheet.close()
taskText.text = ""
priority.resetSelectedOption()
}
}
acceptAction: ActionItem {
title: "Save"
onTriggered: {
editSheet.close()
editSheet.saveTask(taskText.text)
priority.resetSelectedOption()
}
}
}
Container {
layout: StackLayout {
}
Container {
leftPadding: 10.0
rightPadding: 10.0
topPadding: 10.0
bottomPadding: 10.0
TextArea {
id: taskText
preferredHeight: 720.0
}
Container {
id: toolbar
layout: StackLayout {
orientation: LayoutOrientation.LeftToRight
}
// background: Color.create("#262626")
// preferredWidth: 768.0
Container {
leftPadding: 25.0
rightPadding: 25.0
minHeight: 81.0
ImageButton {
defaultImageSource: "asset:///ArrowCircleAlt.png"
onClicked: {
taskText.preferredHeight = 200.0
priority.visible = true
priority.expanded = true
toolbar.visible = false
}
}
}
Container {
leftPadding: 25.0
rightPadding: 25.0
minHeight: 81.0
ImageButton {
defaultImageSource: "asset:///PriceTag.png"
onClicked: {
taskText.preferredHeight = 200.0
labels.visible = true
labels.expanded = true
toolbar.visible = false
}
}
}
Container {
leftPadding: 25.0
rightPadding: 25.0
minHeight: 81.0
ImageButton {
defaultImageSource: "asset:///Appointment.png"
onClicked: {
taskText.preferredHeight = 200.0
duedate.visible = true
duebtn.visible = true
duedate.expanded = true
toolbar.visible = false
}
}
}
Container {
visible: newtask
leftPadding: 25.0
rightPadding: 25.0
minHeight: 81.0
ImageToggleButton {
imageSourceDefault: "asset:///Watch.png"
imageSourceChecked: "asset:///Watch_a.png"
checked: datenew
onCheckedChanged: {
if (checked) {
modifySetting("datenew", true)
createToggleToast.body = "Date new tasks enabled"
} else {
modifySetting("datenew", false)
createToggleToast.body = "Date new tasks disabled"
}
displayed ? createToggleToast.show() : displayed = true
}
}
}
}
DropDown {
id: priority
title: "Priority"
visible: false
preferredWidth: 720.0
onSelectedIndexChanged: {
//console.log("priority set to : " + selectedValue);
if (selectedValue == "-") {
taskText.text = taskText.text.replace(/\([A-Z]\)\s/, "");
} else {
if (taskText.text.match(/\([A-Z]\)/)) {
taskText.text = taskText.text.replace(/\([A-Z]\)/, "(" +
selectedValue + ")");
} else {
taskText.text = "(" + selectedValue + ") " + taskText.text;
}
}
priority.visible = false
toolbar.visible = true
taskText.preferredHeight = 720.0
taskText.requestFocus()
}
onExpandedChanged: {
if (expanded === false) {
priority.visible = false
toolbar.visible = true
taskText.preferredHeight = 720.0
taskText.requestFocus()
}
}
Option {
text: "-"
value: "-"
}
Option {
text: "A"
value: "A"
selected: editSheet.pri == "A"
}
Option {
text: "B"
value: "B"
selected: editSheet.pri == "B"
}
Option {
text: "C"
value: "C"
selected: editSheet.pri == "C"
}
Option {
text: "D"
value: "D"
selected: editSheet.pri == "D"
}
Option {
text: "E"
value: "E"
selected: editSheet.pri == "E"
}
Option {
text: "F"
value: "F"
selected: editSheet.pri == "F"
}
Option {
text: "G"
value: "G"
selected: editSheet.pri == "G"
}
Option {
text: "H"
value: "H"
selected: editSheet.pri == "H"
}
Option {
text: "I"
value: "I"
selected: editSheet.pri == "I"
}
Option {
text: "J"
value: "J"
selected: editSheet.pri == "J"
}
Option {
text: "K"
value: "K"
selected: editSheet.pri == "K"
}
Option {
text: "L"
value: "L"
selected: editSheet.pri == "L"
}
Option {
text: "M"
value: "M"
selected: editSheet.pri == "M"
}
Option {
text: "N"
value: "N"
selected: editSheet.pri == "N"
}
Option {
text: "O"
value: "O"
selected: editSheet.pri == "O"
}
Option {
text: "P"
value: "P"
selected: editSheet.pri == "P"
}
Option {
text: "Q"
value: "Q"
selected: editSheet.pri == "Q"
}
Option {
text: "R"
value: "R"
selected: editSheet.pri == "R"
}
Option {
text: "S"
value: "S"
selected: editSheet.pri == "S"
}
Option {
text: "T"
value: "T"
selected: editSheet.pri == "T"
}
Option {
text: "U"
value: "U"
selected: editSheet.pri == "U"
}
Option {
text: "V"
value: "V"
selected: editSheet.pri == "V"
}
Option {
text: "W"
value: "W"
selected: editSheet.pri == "W"
}
Option {
text: "X"
value: "X"
selected: editSheet.pri == "X"
}
Option {
text: "Y"
value: "Y"
selected: editSheet.pri == "Y"
}
Option {
text: "Z"
value: "Z"
selected: editSheet.pri == "Z"
}
}
DropDown {
id: labels
title: "Project or Context"
visible: false
preferredWidth: 720.0
onSelectedIndexChanged: {
if (selectedValue != undefined) {
taskText.text = taskText.text + selectedValue + " "
}
labels.visible = false
toolbar.visible = true
taskText.preferredHeight = 720.0
taskText.requestFocus()
}
onExpandedChanged: {
if (expanded === false) {
labels.visible = false
toolbar.visible = true
taskText.preferredHeight = 720.0
taskText.requestFocus()
}
}
}
DateTimePicker {
id: duedate
title: "Due date"
visible: false
preferredWidth: 720.0
}
Container {
id: duebtn
visible: false
layout: StackLayout {
orientation: LayoutOrientation.LeftToRight
}
Button {
text: "Nevermind"
onClicked: {
duedate.visible = false
duebtn.visible = false
toolbar.visible = true
taskText.preferredHeight = 720.0
taskText.requestFocus()
}
preferredWidth: 350.0
}
Button {
text: "Add date"
onClicked: {
if (taskitem) {
taskText.text = taskText.text +
"due:" + taskItem.ListItem.view.dataModel.formatDate(duedate.value) + " "
} else {
taskText.text = taskText.text +
"due:" + taskModel.formatDate(duedate.value) + " "
}
// taskText.text = taskText.text +
// "due:" + taskModel.formatDate(duedate.value) + " "
duedate.visible = false
duebtn.visible = false
toolbar.visible = true
taskText.preferredHeight = 720.0
taskText.requestFocus()
}
preferredWidth: 350.0
}
}
// Divider {
// }
}
}
onCreationCompleted: {
// TODO this
}
attachedObjects: [
SystemToast {
id: createToggleToast
}
]
}
}

105
assets/FilterPage.qml Normal file
View File

@ -0,0 +1,105 @@
/*
* Copyright 2012-2018 Morgan McMillian <gilag@monkeystew.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import bb.cascades 1.0
Page {
id: filterPage
property alias filterModel: filterModel
property alias warningtext: warningtext
signal resetFilter()
titleBar: TitleBar {
id: titleBar
title: " Filter List"
}
Container {
Container {
id: warningtext
leftPadding: 30.0
topPadding: 30.0
rightPadding: 30.0
bottomPadding: 30.0
visible: false
Label {
text: "There are no project or context tags in your task list to " +
"filter on. You can define a project tag by prefixing some text " +
"with the + symbol or a context tag with the @ symbol in your tasks."
multiline: true
textStyle.fontStyle: FontStyle.Italic
}
}
ListView {
id: filterList
dataModel: GroupDataModel {
id: filterModel
sortingKeys: [ "type" ]
grouping: ItemGrouping.ByFullValue
signal changeFilter(string filter, bool enabled)
}
listItemComponents: [
ListItemComponent {
type: "listItem"
Container {
id: filterItem
layout: StackLayout {
}
Container {
layout: DockLayout {
}
horizontalAlignment: HorizontalAlignment.Fill
topPadding: 15.0
leftPadding: 20.0
rightPadding: 30.0
Label {
text: ListItemData.title
}
CheckBox {
id: filterCheck
horizontalAlignment: HorizontalAlignment.Right
// TODO: checked: <bool> need it out of the taskModel
checked: ListItemData.checked
onCheckedChanged: {
//console.log(filterCheck.checked)
filterItem.ListItem.view.dataModel.changeFilter(ListItemData.title, filterCheck.checked)
}
}
}
Divider {
}
}
}
]
function itemType(data, indexPath) {
if (indexPath.length == 1) {
return "header";
} else {
return "listItem";
}
}
}
}
actions: [
ActionItem {
title: "Reset"
imageSource: "icons/Delete.png"
ActionBar.placement: ActionBarPlacement.OnBar
onTriggered: {
resetFilter();
navi.pop();
}
}
]
}

35
assets/HelpPage.qml Normal file
View File

@ -0,0 +1,35 @@
/*
* Copyright 2012-2018 Morgan McMillian <gilag@monkeystew.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import bb.cascades 1.0
Page {
id: helpPage
titleBar: TitleBar {
title: " Help"
}
Container {
layout: DockLayout {
}
ScrollView {
WebView {
id: webView
url: "local:///assets/help.html"
settings.defaultFontSize: 30
}
}
}
}

272
assets/SettingsPage.qml Normal file
View File

@ -0,0 +1,272 @@
/*
* Copyright 2012-2018 Morgan McMillian <gilag@monkeystew.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import bb.cascades 1.0
import bb.cascades.pickers 1.0
Page {
id: settingsPage
signal modifySetting(string setting, variant value)
property bool datenew
property bool windowsbreak
property bool autoarchive
property int sort
property string path
property string sync
property string dboxpath
titleBar: TitleBar {
title: " Settings"
}
ScrollView {
Container {
layout: StackLayout {}
Container {
topPadding: 15.0
}
Container {
layout: DockLayout {}
horizontalAlignment: HorizontalAlignment.Fill
verticalAlignment: VerticalAlignment.Fill
Container {
verticalAlignment: VerticalAlignment.Center
leftPadding: 30.0
Label {
text: "Date new tasks"
textStyle.fontWeight: FontWeight.Bold
}
}
Container {
rightPadding: 30.0
horizontalAlignment: HorizontalAlignment.Right
ToggleButton {
checked: datenew
onCheckedChanged: {
if (checked) {
modifySetting("datenew", true)
} else {
modifySetting("datenew", false)
}
}
}
}
}
Divider {}
Container {
layout: DockLayout {}
horizontalAlignment: HorizontalAlignment.Fill
verticalAlignment: VerticalAlignment.Fill
Container {
leftPadding: 30.0
verticalAlignment: VerticalAlignment.Center
Label {
text: "Windows line breaks"
textStyle.fontWeight: FontWeight.Bold
}
}
Container {
rightPadding: 30.0
horizontalAlignment: HorizontalAlignment.Right
ToggleButton {
checked: windowsbreak
onCheckedChanged: {
if (checked) {
modifySetting("windowsbreak", true)
} else {
modifySetting("windowsbreak", false)
}
}
}
}
}
Divider {}
Container {
layout: DockLayout {}
horizontalAlignment: HorizontalAlignment.Fill
verticalAlignment: VerticalAlignment.Fill
Container {
leftPadding: 30.0
verticalAlignment: VerticalAlignment.Center
Label {
text: "Auto archive"
textStyle.fontWeight: FontWeight.Bold
}
}
Container {
rightPadding: 30.0
horizontalAlignment: HorizontalAlignment.Right
ToggleButton {
checked: autoarchive
onCheckedChanged: {
if (checked) {
modifySetting("autoarchive", true)
} else {
modifySetting("autoarchive", false)
}
}
}
}
}
Divider {}
Container {
layout: DockLayout {}
horizontalAlignment: HorizontalAlignment.Fill
Container {
leftPadding: 30.0
rightPadding: 30.0
DropDown {
title: "Sort by:"
preferredWidth: 1440.0
onSelectedIndexChanged: {
modifySetting("sort", selectedValue)
}
Option {
text: "Priority"
value: 0
selected: sort == 0
}
Option {
text: "Due date"
value: 3
selected: sort == 3
}
Option {
text: "Line number"
value: 1
selected: sort == 1
}
Option {
text: "Text A>Z"
value: 2
selected: sort == 2
}
}
}
}
Divider {}
Container {
layout: DockLayout {}
horizontalAlignment: HorizontalAlignment.Fill
Container {
leftPadding: 30.0
rightPadding: 30.0
DropDown {
title: "File location:"
preferredWidth: 1440.0
onSelectedIndexChanged: {
modifySetting("path", selectedValue)
}
Option {
text: "Local sandbox"
value: "data/todo"
selected: path == "data/todo"
}
Option {
text: "Local shared"
value: "shared/misc/todo"
selected: path == "shared/misc/todo"
}
}
}
}
Divider {}
Container {
layout: DockLayout {}
horizontalAlignment: HorizontalAlignment.Fill
Container {
leftPadding: 30.0
rightPadding: 30.0
DropDown {
title: "Storage:"
preferredWidth: 1440.0
onSelectedIndexChanged: {
if (sync != selectedValue) {
modifySetting("sync", selectedValue)
}
}
Option {
text: "Local only"
value: "local"
selected: sync == "local"
}
}
}
}
Container {
layout: DockLayout {}
horizontalAlignment: HorizontalAlignment.Fill
Container {
leftPadding: 30.0
rightPadding: 30.0
topPadding: 10.0
TextField {
id: dboxPath
hintText: "Dropbox location"
text: dboxpath
visible: sync == "dropbox"
onTextChanged: {
if (dboxPath.text.length > 0) {
modifySetting("dbox_path", dboxPath.text)
}
}
}
}
}
Divider {}
Container {
layout: DockLayout {}
horizontalAlignment: HorizontalAlignment.Fill
leftPadding: 30.0
rightPadding: 30.0
Button {
preferredWidth: 1440.0
text: "Export sandbox files"
onClicked: {
exportPicker.open()
}
}
}
Divider {}
Container {
layout: DockLayout {}
horizontalAlignment: HorizontalAlignment.Fill
leftPadding: 30.0
rightPadding: 30.0
Button {
preferredWidth: 1440.0
text: "Purge local sandbox"
onClicked: {
taskModel.promptPurgeSandbox()
}
}
}
Divider {}
}
}
attachedObjects: [
FilePicker {
id: exportPicker
title: "Export"
mode: FilePicker.SaverMultiple
type: FileType.Document
viewMode: FilePickerViewMode.ListView
defaultSaveFileNames: ["todo.txt","done.txt"]
onFileSelected: {
console.log("FileSelected signal received : " + selectedFiles);
taskModel.exportFiles(selectedFiles)
}
}
]
}

179
assets/TaskItem.qml Normal file
View File

@ -0,0 +1,179 @@
/*
* Copyright 2012-2018 Morgan McMillian <gilag@monkeystew.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import bb.cascades 1.0
import "humane.js" as HumaneDate
Container {
id: taskItem
Container {
layout: StackLayout {
}
Container {
layout: DockLayout {
}
horizontalAlignment: HorizontalAlignment.Fill
leftPadding: 10.0
rightPadding: 10.0
topPadding: 10.0
Container {
layout: StackLayout {
orientation: LayoutOrientation.LeftToRight
}
Container {
minWidth: 50.0
Label {
text: ListItemData.priority
textStyle.fontSize: FontSize.Large
//textStyle.color: Color.Blue
textStyle.color: getPriorityColor(ListItemData.priority)
}
}
}
Container {
layout: StackLayout {
}
leftPadding: 40.0
Container {
Label {
text: ListItemData.detail
multiline: true
textStyle.fontSize: FontSize.Medium
//textStyle.color: ListItemData.complete ? Color.Gray : Color.Black
textStyle.color: getDetailColor(ListItemData.complete)
}
}
Container {
layout: StackLayout {
orientation: LayoutOrientation.LeftToRight
}
topPadding: 5.0
Container {
rightPadding: ListItemData.dateDue.length > 0 ? 10.0 : 0
Label {
text: ListItemData.dateDue.length > 0 ? "Due " +
HumaneDate.humaneDate(ListItemData.dateDue) : ""
textStyle.fontSize: FontSize.XXSmall
textStyle.color: Color.Gray
textStyle.fontWeight: FontWeight.Bold
}
}
Container {
Label {
text: ListItemData.complete ? "Completed " +
HumaneDate.humaneDate(ListItemData.dateCompleted) :
ListItemData.dateCreated ? "Created " +
HumaneDate.humaneDate(ListItemData.dateCreated) : ""
textStyle.fontSize: FontSize.XXSmall
//textStyle.color: ListItemData.complete ? Color.LightGray : Color.Gray
textStyle.color: Color.Gray
}
}
}
}
}
Divider {
}
}
function getDetailColor(complete) {
if (complete) return Color.Gray;
switch (Application.themeSupport.theme.colorTheme.style) {
case VisualStyle.Bright:
return Color.Black;
case VisualStyle.Dark:
return Color.White;
}
return Color.Black;
}
function getPriorityColor(priority) {
// TODO make each priority a different color
switch (Application.themeSupport.theme.colorTheme.style) {
case VisualStyle.Bright:
return Color.Blue;
case VisualStyle.Dark:
return Color.Yellow;
}
return Color.Gray;
}
contextActions: [
ActionSet {
title: ListItemData.detail
ActionItem {
title: "Edit"
imageSource: "icons/Pencil.png"
onTriggered: {
editItem.open()
editItem.newtask = false;
editItem.text = ListItemData.text
// editItem.pri = ListItemData.priority
editItem.labels.removeAll();
for (var i = 0; i < taskItem.ListItem.view.dataModel.filters.length; i ++) {
var o = opt.createObject();
o.text = taskItem.ListItem.view.dataModel.filters[i].title;
o.value = taskItem.ListItem.view.dataModel.filters[i].title;
editItem.labels.add(o);
}
editItem.textfield.requestFocus();
}
}
ActionItem {
title: "Complete"
imageSource: "icons/Check.png"
enabled: ListItemData.complete ? false : true
onTriggered: {
taskItem.ListItem.view.dataModel.setValue(taskItem.ListItem.indexPath, "complete", true)
}
}
ActionItem {
title: "Undo Complete"
imageSource: "icons/Undo.png"
enabled: ListItemData.complete
onTriggered: {
taskItem.ListItem.view.dataModel.setValue(taskItem.ListItem.indexPath, "complete", false)
}
}
InvokeActionItem {
title: "Share"
query {
mimeType: "text/plain"
invokeActionId: "bb.action.SHARE"
}
data: ListItemData.text
}
DeleteActionItem {
title: "Delete"
onTriggered: {
taskItem.ListItem.view.dataModel.promptDelete(taskItem.ListItem.indexPath)
}
}
}
]
attachedObjects: [
EditSheet {
id: editItem
title: "Edit"
taskitem: true
onSaveTask: {
taskItem.ListItem.view.dataModel.updateTask(taskItem.ListItem.indexPath, text)
}
},
ComponentDefinition {
id: opt
Option {
}
}
]
}

114
assets/TaskPage.qml Normal file
View File

@ -0,0 +1,114 @@
/*
* Copyright 2012-2018 Morgan McMillian <gilag@monkeystew.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import bb.cascades 1.0
Page {
id: taskPage
signal itemUpdate(int idx, string text)
signal setValue(int idx, string key, variant value)
signal delTask(int idx)
property alias title: titleBar.title
property string itemtext
property variant idx
property bool complete
titleBar: TitleBar {
id: titleBar
title: " Task"
}
Container {
layout: DockLayout {
}
Container {
topPadding: 30
leftPadding: 30
rightPadding: 30
Label {
id: taskText
multiline: true
text: itemtext
}
}
}
actions: [
ActionItem {
title: "Edit"
imageSource: "icons/Pencil.png"
ActionBar.placement: ActionBarPlacement.OnBar
onTriggered: {
editItem.open()
editItem.newtask = false
editItem.text = itemtext
editItem.labels.removeAll();
for (var i = 0; i < taskModel.filters.length; i ++) {
var o = opt.createObject();
o.text = taskModel.filters[i].title;
o.value = taskModel.filters[i].title;
editItem.labels.add(o);
}
editItem.textfield.requestFocus()
}
},
ActionItem {
title: "Complete"
imageSource: "icons/Check.png"
enabled: complete ? false : true
onTriggered: {
setValue(idx, "complete", true)
navi.pop()
}
},
ActionItem {
title: "Undo Complete"
imageSource: "icons/Undo.png"
enabled: complete
onTriggered: {
setValue(idx, "complete", false)
navi.pop()
}
},
InvokeActionItem {
title: "Share"
query {
mimeType: "text/plain"
invokeActionId: "bb.action.SHARE"
}
data: itemtext
},
DeleteActionItem {
title: "Delete"
onTriggered: {
delTask(idx)
navi.pop()
}
}
]
attachedObjects: [
EditSheet {
id: editItem
title: "Edit"
onSaveTask: {
itemUpdate(idx, text)
itemtext = text
}
},
ComponentDefinition {
id: opt
Option {
}
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 493 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 542 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 682 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

BIN
assets/Watch_a.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 840 B

81
assets/help.html Normal file
View File

@ -0,0 +1,81 @@
<HTML>
<HEAD>
<TITLE>Renamed Todo Help</TITLE>
<STYLE type="text/css">
.Q { font-weight: bold; }
.A { font-weight: normal; font-style: italic; }
</STYLE>
</HEAD>
<BODY><p>&nbsp;</p>
<DIV class="Q">
Q: What is the todo.txt file format?
<DIV id="faq1" class="A">
<p>
The todo.txt file is simply a plain text file that follows a specification
created by <a href="http://ginatrapani.org/">Gina Trapani</a> and used in applications published by the <a href="http://todotxt.com/">Todo.txt Community</a>. The todo.txt file is both human and machine readable by following a few simple rules. You can find more information including the specifications <a href="https://github.com/ginatrapani/todo.txt-cli/wiki/The-Todo.txt-Format">here</a>.
</p>
</DIV>
</DIV>
<DIV class="Q">
Q: How do I add filters?
<DIV id="faq1" class="A">
<p>
Filters are created automatically by special text identified in the tasks you create. The two kinds of text it looks for are projects and contexts.
<p>
<span style="font-weight: bold;">Project:</span>&nbsp;
Denoted by prefixing some text with "+"<br/>
<span style="font-weight: bold;">Context:</span>&nbsp;
Denoted by prefixing some text with "@"<br/>
</p>
So for example the task "Contact Tom by @email to discuss the new +program" results in "@email" and "+program" added to the filter list.
</p>
</DIV>
</DIV>
<DIV class="Q">
Q: What is the difference between "Local sandbox" and "Local shared" in the file location settings?
<DIV id="faq1" class="A">
<p>
<span style="font-weight: bold;">Local sandbox:</span>&nbsp;
The todo.txt file is located within the application sandbox
storage space and is only accessible to this app. This is the
default location when you start the app for the first time and the best
option if you do not need or want your file accessible from any other
application or process.<BR/>
<span style="font-weight: bold;">Local shared:</span>&nbsp;
The todo.txt file is located within the shared application storage space
in "Shared/misc/todo". This location is accessible from any other
application.
</p>
</DIV>
</DIV>
<DIV class="Q">
Q: Can I export my todo.txt list from the local sandbox?
<DIV id="faq1" class="A">
<p>
You can export the todo.txt and done.txt files from your local sandbox by
opening the "Settings" page in the pull down menu at the top of the screen
and pressing the "Export sandbox files". From there you will be prompted to
select an accessible location.
</p>
</DIV>
</DIV>
<DIV class="Q">
Q: What happened to Dropbox support?
<DIV id="faq1" class="A">
<p>
Dropbox support has been temporarily removed from this open source edition. I plan to
rework a large portion of the sync code and re-introduce it along with support for
other cloud providers soon.
</p>
</DIV>
</DIV>
<DIV class="Q">
Q: How can I get some additional help?
<DIV id="faq1" class="A">
<p>
For any feedback or questions you can send me <a href="mailto:rtd@monkeystew.com?subject=Renamed Todo for BlackBerry 10">email</a> or visit us at <a href="http://monkeystew.org">monkeystew.org</a>
</p>
</DIV>
</DIV><p>&nbsp;</p>
</BODY>
</HTML>

150
assets/humane.js Normal file
View File

@ -0,0 +1,150 @@
/*
* Javascript Humane Dates
* Copyright (c) 2008 Dean Landolt (deanlandolt.com)
* Re-write by Zach Leatherman (zachleat.com)
*
* Adopted from the John Resig's pretty.js
* at http://ejohn.org/blog/javascript-pretty-date
* and henrah's proposed modification
* at http://ejohn.org/blog/javascript-pretty-date/#comment-297458
*
* Licensed under the MIT license.
*/
function humaneDate(date, compareTo){
if(!date) {
return;
}
var testme = new Date;
compareTo = testme.getFullYear() + "-" + (testme.getMonth()+1) + "-" + testme.getDate();
var lang = {
ago: 'ago',
from: 'from now',
now: 'today',
minute: 'minute',
minutes: 'minutes',
hour: 'hour',
hours: 'hours',
today: 'today',
day: 'day',
days: 'days',
week: 'week',
weeks: 'weeks',
month: 'month',
months: 'months',
year: 'year',
years: 'years'
},
formats = [
[60, lang.now],
[3600, lang.minute, lang.minutes, 60], // 60 minutes, 1 minute
[86400, lang.hour, lang.hours, 3600], // 24 hours, 1 hour
[604800, lang.day, lang.days, 86400], // 7 days, 1 day
[2628000, lang.week, lang.weeks, 604800], // ~1 month, 1 week
[31536000, lang.month, lang.months, 2628000], // 1 year, ~1 month
[Infinity, lang.year, lang.years, 31536000] // Infinity, 1 year
],
isString = typeof date == 'string',
date = isString ?
new Date(('' + date).replace(/-/g,"/").replace(/[TZ]/g," ")) :
date,
cIsString = typeof compareTo == 'string',
compareTo = cIsString ?
new Date(('' + compareTo).replace(/-/g,"/").replace(/[TZ]/g," ")) :
compareTo,
seconds = (compareTo - date +
(compareTo.getTimezoneOffset() -
// if we received a GMT time from a string, doesn't include time zone bias
// if we got a date object, the time zone is built in, we need to remove it.
(isString ? 0 : date.getTimezoneOffset())
) * 60000
) / 1000,
token;
if(seconds < 0) {
seconds = Math.abs(seconds);
token = lang.from ? ' ' + lang.from : '';
} else {
token = lang.ago ? ' ' + lang.ago : '';
}
/*
* 0 seconds && < 60 seconds Now
* 60 seconds 1 Minute
* > 60 seconds && < 60 minutes X Minutes
* 60 minutes 1 Hour
* > 60 minutes && < 24 hours X Hours
* 24 hours 1 Day
* > 24 hours && < 7 days X Days
* 7 days 1 Week
* > 7 days && < ~ 1 Month X Weeks
* ~ 1 Month 1 Month
* > ~ 1 Month && < 1 Year X Months
* 1 Year 1 Year
* > 1 Year X Years
*
* Single units are +10%. 1 Year shows first at 1 Year + 10%
*/
function normalize(val, single)
{
var margin = 0.1;
if(val >= single && val <= single * (1+margin)) {
return single;
}
return val;
}
for(var i = 0, format = formats[0]; formats[i]; format = formats[++i]) {
if(seconds < format[0]) {
if(i === 0) {
// Now
return format[1];
}
var val = Math.ceil(normalize(seconds, format[3]) / (format[3]));
// Since the source is only passing a date don't reference hours, use today
if (format[2] == lang.hours) { return lang.today; }
// Again, since it's only the date adjust the days value to round down
if (format[2] == lang.days) {
val = Math.floor(normalize(seconds, format[3]) / (format[3]));
}
return val +
' ' +
(val != 1 ? format[2] : format[1]) +
(i > 0 ? token : '');
}
}
};
if(typeof jQuery != 'undefined') {
jQuery.fn.humaneDates = function(options)
{
var settings = jQuery.extend({
'lowercase': false
}, options);
return this.each(function()
{
var $t = jQuery(this),
date = $t.attr('datetime') || $t.attr('title');
date = humaneDate(date);
if(date && settings['lowercase']) {
date = date.toLowerCase();
}
if(date && $t.html() != date) {
// don't modify the dom if we don't have to
$t.html(date);
}
});
};
}

BIN
assets/icons/123.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

BIN
assets/icons/Add.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 941 B

BIN
assets/icons/Capitalize.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

BIN
assets/icons/Check.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

BIN
assets/icons/Clock.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

BIN
assets/icons/Clock_a.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

BIN
assets/icons/Date.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

BIN
assets/icons/Delete.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

BIN
assets/icons/DownBox.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

BIN
assets/icons/Funnel.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

BIN
assets/icons/Info.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

BIN
assets/icons/Pencil.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

BIN
assets/icons/PriceTag.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

BIN
assets/icons/Recycle.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

BIN
assets/icons/Search.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

BIN
assets/icons/Sort.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

BIN
assets/icons/Undo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

BIN
assets/icons/abc.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

BIN
assets/icons/ic_bbm.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 836 B

BIN
assets/icons/invoke.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

398
assets/main.qml Normal file
View File

@ -0,0 +1,398 @@
/*
* Copyright 2012-2018 Morgan McMillian <gilag@monkeystew.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import bb.cascades 1.0
import com.monkeystew.taskmodel 1.0
NavigationPane {
id: navi
property string appversion
property variant coverpage
Menu.definition: MenuDefinition {
helpAction: HelpActionItem {
onTriggered: {
var page = helpPage.createObject()
navi.push(page)
}
}
settingsAction: SettingsActionItem {
onTriggered: {
var page = settingsPage.createObject();
page.modifySetting.connect(taskModel.modifySetting)
page.datenew = taskModel.setting("datenew", false)
page.windowsbreak = taskModel.setting("windowsbreak", false)
page.autoarchive = taskModel.setting("autoarchive", false)
page.sort = taskModel.setting("sort", 0)
page.path = taskModel.setting("path", "data/todo")
page.sync = taskModel.setting("sync", "local")
page.dboxpath = taskModel.setting("dbox_path", "/todo/todo.txt")
navi.push(page)
}
}
actions: [
ActionItem {
title: "About"
imageSource: "asset:///icons/Info.png"
onTriggered: {
var page = aboutPage.createObject()
navi.push(page)
}
}
// ActionItem {
// title: "Invite"
// imageSource: "asset:///icons/ic_bbm.png"
// onTriggered: {
// _Taskslayer.sendBBMInvite()
// }
// }
]
}
Page {
id: mainPage
titleBar: TitleBar {
id: titleBar
title: " Renamed Todo"
visibility: ChromeVisibility.Default
}
Container {
Container {
id: searchContainer
visible: false
layout: StackLayout {
orientation: LayoutOrientation.LeftToRight
}
preferredHeight: 120.0
//background: Color.create("#0098F0")
background: mainPage.getSearchBackground()
Container {
verticalAlignment: VerticalAlignment.Center
leftPadding: 15.0
rightPadding: 10.0
TextField {
id: searchField
hintText: "Search"
onTextChanging: {
taskModel.search(searchField.text);
}
}
}
Container {
maxWidth: 220.0
verticalAlignment: VerticalAlignment.Center
leftPadding: 10.0
rightPadding: 15.0
Button {
text: "Cancel"
onClicked: {
titleBar.visibility = ChromeVisibility.Default
searchContainer.visible = false
searchField.text = ""
}
}
}
}
Container {
horizontalAlignment: HorizontalAlignment.Fill
Container {
id: appliedFilters
layout: DockLayout {
}
visible: false
horizontalAlignment: HorizontalAlignment.Fill
Container {
background: Color.create("#333333")
horizontalAlignment: HorizontalAlignment.Fill
Label {
id: filterList
text: taskModel.activeFilters()
textStyle.color: Color.White
textStyle.fontSize: FontSize.XSmall
}
}
}
}
Container {
id: sortdropdown
horizontalAlignment: HorizontalAlignment.Center
visible: false
DropDown {
id: sortselection
title: "Sort"
onSelectedIndexChanged: {
if (selectedValue != undefined) {
taskModel.sort = selectedValue
sortdropdown.visible = false
}
}
Option {
text: "Priority"
value: 0
}
Option {
text: "Due date"
value: 3
}
Option {
text: "Line number"
value: 1
}
Option {
text: "Text A>Z"
value: 2
}
}
}
ListView {
id: listView
dataModel: taskModel
listItemComponents: [
ListItemComponent {
TaskItem {
// see TaskItem.qml
}
}
]
onTriggered: {
var chosenItem = taskModel.data(indexPath)
var page = taskPage.createObject();
page.itemUpdate.connect(taskModel.updateTask)
page.setValue.connect(taskModel.setValue)
page.delTask.connect(taskModel.promptDelete)
page.itemtext = chosenItem.text
page.complete = chosenItem.complete
page.idx = indexPath
navi.push(page)
}
/*leadingVisual: TextField {
* id: searchField
* onTextChanging: {
* //
* }
* }*/
}
}
attachedObjects: [
TaskModel {
id: taskModel
},
EditSheet {
id: addNew
onSaveTask: {
taskModel.addFullTask(text)
}
},
ComponentDefinition {
id: taskPage
source: "asset:///TaskPage.qml"
},
ComponentDefinition {
id: filterPage
source: "asset:///FilterPage.qml"
},
ComponentDefinition {
id: settingsPage
source: "asset:///SettingsPage.qml"
},
ComponentDefinition {
id: aboutPage
source: "asset:///AboutPage.qml"
},
ComponentDefinition {
id: helpPage
source: "asset:///HelpPage.qml"
},
ComponentDefinition {
id: appCover
source: "asset:///AppCover.qml"
},
ComponentDefinition {
id: opt
Option {}
}
]
actions: [
ActionItem {
title: "Add"
imageSource: "asset:///icons/Add.png"
ActionBar.placement: ActionBarPlacement.OnBar
onTriggered: {
addNew.open();
addNew.newtask = true;
addNew.datenew = taskModel.setting("datenew", false);
addNew.modifySetting.connect(taskModel.modifySetting);
addNew.text = "";
addNew.labels.removeAll();
for (var i=0; i < taskModel.filters.length; i++) {
var o = opt.createObject();
o.text = taskModel.filters[i].title;
o.value = taskModel.filters[i].title;
addNew.labels.add(o);
}
addNew.textfield.requestFocus();
}
},
ActionItem {
id: searchButton
title: "Search"
imageSource: "asset:///icons/Search.png"
ActionBar.placement: ActionBarPlacement.OnBar
onTriggered: {
if (searchContainer.visible) {
titleBar.visibility = ChromeVisibility.Default
searchContainer.visible = false
searchField.text = ""
} else {
searchContainer.visible = true
searchField.requestFocus()
titleBar.visibility = ChromeVisibility.Hidden
}
}
},
ActionItem {
title: "Filter"
imageSource: "asset:///icons/Funnel.png"
ActionBar.placement: ActionBarPlacement.OnBar
onTriggered: {
var page = filterPage.createObject();
if (taskModel.filters.length <= 0) {
if (appliedFilters.visible) {
taskModel.resetFilter()
} else {
page.warningtext.visible = true
}
}
page.filterModel.insertList(taskModel.filters);
page.filterModel.changeFilter.connect(taskModel.changeFilter);
page.resetFilter.connect(taskModel.resetFilter);
navi.push(page);
}
},
ActionItem {
title: "Sort"
imageSource: "asset:///icons/Sort.png"
onTriggered: {
sortdropdown.visible = sortdropdown.visible ? false : true
sortselection.resetSelectedIndex()
}
},
// ActionItem {
// title: "Sort by priority"
// imageSource: "icons/Capitalize.png"
// onTriggered: {
// taskModel.sort = 0;
// }
// },
// ActionItem {
// title: "Sort by line"
// imageSource: "icons/123.png"
// onTriggered: {
// taskModel.sort = 1;
// }
// },
// ActionItem {
// title: "Sort by text (a>z)"
// imageSource: "icons/abc.png"
// onTriggered: {
// taskModel.sort = 2;
// }
// },
// ActionItem {
// title: "Sort by due date"
// onTriggered: {
// taskModel.sort = 3;
// }
// },
ActionItem {
title: "Archive"
imageSource: "asset:///icons/DownBox.png"
onTriggered: {
taskModel.archive();
}
},
ActionItem {
title: "Reload"
imageSource: "asset:///icons/Recycle.png"
onTriggered: {
taskModel.refresh();
taskModel.setView();
}
}
]
onCreationCompleted: {
taskModel.refresh();
taskModel.setView();
_Taskslayer.addNewTask.connect(newTask)
_Taskslayer.searchTaskList.connect(searchTasks)
taskModel.listUpdated.connect(listUpdated)
coverpage = appCover.createObject();
coverpage.topList.append(taskModel.tododata)
if (taskModel.tododata.length > 0) {
coverpage.empty = false
} else {
coverpage.empty = true
}
Application.cover = coverpage
console.log(themeStyleToString(Application.themeSupport.theme.colorTheme.style))
}
function searchTasks(data) {
searchContainer.visible = true
searchField.requestFocus()
searchField.text = data
titleBar.visibility = ChromeVisibility.Hidden
}
function newTask(data) {
addNew.open();
addNew.newtask = true;
addNew.datenew = taskModel.setting("datenew", false);
addNew.modifySetting.connect(taskModel.modifySetting);
addNew.text = data;
addNew.textfield.requestFocus();
}
function listUpdated() {
coverpage.topList.clear()
coverpage.topList.append(taskModel.tododata)
if (taskModel.tododata.length > 0) {
coverpage.empty = false
} else {
coverpage.empty = true
}
}
function themeStyleToString(style) {
switch (style) {
case VisualStyle.Bright:
return "Theme: Bright"
case VisualStyle.Dark:
return "Theme: Dark"
}
return "Theme: UNKNOWN :("
}
function getSearchBackground() {
switch (Application.themeSupport.theme.colorTheme.style) {
case VisualStyle.Bright:
return Color.create("#0098F0")
case VisualStyle.Dark:
return Color.create("#262626")
}
return Color.Gray;
}
}
onPopTransitionEnded: {
page.destroy()
taskModel.setView()
filterList.text = taskModel.activeFilters()
appliedFilters.visible = taskModel.activeFilters().length > 0 ? true : false
}
}

118
bar-descriptor.xml Normal file
View File

@ -0,0 +1,118 @@
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<!--
Copyright (c) 2011-2015 BlackBerry Limited.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<qnx xmlns="http://www.qnx.com/schemas/application/1.0">
<!-- BlackBerry 10 application descriptor file.
Specifies parameters for identifying, installing, and launching native applications on BlackBerry 10.
-->
<!-- A universally unique application identifier. Must be unique across all BlackBerry 10 applications.
Using a reverse DNS-style name as the id is recommended. (Eg. com.example.ExampleApplication.) Required. -->
<id>com.monkeystew.RenamedTodo</id>
<configuration name="Device-Debug">
<platformArchitecture>armle-v7</platformArchitecture>
<asset path="arm/o.le-v7-g/RenamedTodo" entry="true" type="Qnx/Elf">RenamedTodo</asset>
</configuration>
<configuration name="Device-Release">
<entryPointType>Qnx/Cascades</entryPointType>
<platformArchitecture>armle-v7</platformArchitecture>
<asset path="arm/o.le-v7/RenamedTodo.so" entry="true" type="Qnx/Elf">RenamedTodo.so</asset>
</configuration>
<configuration name="Device-Profile">
<platformArchitecture>armle-v7</platformArchitecture>
<asset path="arm-p/o.le-v7-g/RenamedTodo" entry="true" type="Qnx/Elf">RenamedTodo</asset>
</configuration>
<configuration name="Simulator-Debug">
<platformArchitecture>x86</platformArchitecture>
<asset path="x86/o-g/RenamedTodo" entry="true" type="Qnx/Elf">RenamedTodo</asset>
</configuration>
<!-- The name that is displayed in the BlackBerry 10 application installer.
May have multiple values for each language. See samples or xsd schema file. Optional. -->
<name>Renamed Todo</name>
<!-- A string value of the format <0-999>.<0-999>.<0-999> that represents application version which can be used to check for application upgrade.
Values can also be 1-part or 2-part. It is not necessary to have a 3-part value.
An updated version of application must have a versionNumber value higher than the previous version. Required. -->
<versionNumber>0.9.0</versionNumber>
<!-- Fourth digit segment of the package version. First three segments are taken from the
<versionNumber> element. Must be an integer from 0 to 2^16-1 -->
<buildId>1</buildId>
<!-- A string value (such as "v1", "2.5", or "Alpha 1") that represents the version of the application, as it should be shown to users. Optional. -->
<!-- <versionLabel></versionLabel> -->
<!-- Description, displayed in the BlackBerry 10 application installer.
May have multiple values for each language. See samples or xsd schema file. Optional. -->
<description>The RenamedTodo application</description>
<!-- Copyright information. Optional. -->
<!-- <copyright></copyright> -->
<!-- Name of author which is used for signing. Must match the developer name of your development certificate. -->
<description>The Renamed Todo applicationn</description>
<icon>
<image>rtd_512_3-86.png</image>
<image>rtd_512_3-90.png</image>
<image>rtd_512_3-96.png</image>
<image>rtd_512_3-110.png</image>
<image>rtd_512_3-144.png</image>
</icon>
<splashScreens>
<image>rtd_splash_1440s.png</image>
<image>rtd_splash_720s.png</image>
<image>rtd_splash_768p.png</image>
</splashScreens>
<authorId>gYAAgP-_4D6fs0QDWOhZdtQjf2I</authorId>
<author>Morgan McMillian</author>
<!-- Unique author ID assigned by signing authority. Required if using debug tokens. -->
<!-- <authorId>ABC1234YjsnUk235h</authorId> -->
<initialWindow>
<autoOrients>true</autoOrients>
<systemChrome>none</systemChrome>
</initialWindow>
<!-- The icon for the application, which should be 114x114. -->
<!-- <asset path="icon.png">icon.png</asset> -->
<asset path="assets">assets</asset>
<!-- Locale support -->
<asset path="translations" dest="qm">
<include name="*.qm"/>
</asset>
<asset path="assets/icons/rtd_512_3-86.png">rtd_512_3-86.png</asset>
<asset path="assets/icons/rtd_512_3-90.png">rtd_512_3-90.png</asset>
<asset path="assets/icons/rtd_512_3-96.png">rtd_512_3-96.png</asset>
<asset path="assets/icons/rtd_512_3-110.png">rtd_512_3-110.png</asset>
<asset path="assets/icons/rtd_512_3-144.png">rtd_512_3-144.png</asset>
<asset path="assets/icons/rtd_splash_1440s.png">rtd_splash_1440s.png</asset>
<asset path="assets/icons/rtd_splash_720s.png">rtd_splash_720s.png</asset>
<asset path="assets/icons/rtd_splash_768p.png">rtd_splash_768p.png</asset>
<!-- Request permission to execute native code. Required for native applications. -->
<permission system="true">run_native</permission>
<env var="LD_LIBRARY_PATH" value="app/native/lib:/usr/lib/qt4/lib"/>
</qnx>

134
config.pri Normal file
View File

@ -0,0 +1,134 @@
# Config.pri file version 2.0. Auto-generated by IDE. Any changes made by user will be lost!
BASEDIR = $$quote($$_PRO_FILE_PWD_)
device {
CONFIG(debug, debug|release) {
profile {
CONFIG += \
config_pri_assets \
config_pri_source_group1
} else {
CONFIG += \
config_pri_assets \
config_pri_source_group1
}
}
CONFIG(release, debug|release) {
!profile {
CONFIG += \
config_pri_assets \
config_pri_source_group1
}
}
}
simulator {
CONFIG(debug, debug|release) {
!profile {
CONFIG += \
config_pri_assets \
config_pri_source_group1
}
}
}
config_pri_assets {
OTHER_FILES += \
$$quote($$BASEDIR/assets/AboutPage.qml) \
$$quote($$BASEDIR/assets/AppCover.qml) \
$$quote($$BASEDIR/assets/EditSheet.qml) \
$$quote($$BASEDIR/assets/FilterPage.qml) \
$$quote($$BASEDIR/assets/HelpPage.qml) \
$$quote($$BASEDIR/assets/SettingsPage.qml) \
$$quote($$BASEDIR/assets/TaskItem.qml) \
$$quote($$BASEDIR/assets/TaskPage.qml) \
$$quote($$BASEDIR/assets/VisualStyle.bright/Appointment.png) \
$$quote($$BASEDIR/assets/VisualStyle.bright/ArrowCircleAlt.png) \
$$quote($$BASEDIR/assets/VisualStyle.bright/PriceTag.png) \
$$quote($$BASEDIR/assets/VisualStyle.bright/Watch.png) \
$$quote($$BASEDIR/assets/VisualStyle.dark/Appointment.png) \
$$quote($$BASEDIR/assets/VisualStyle.dark/ArrowCircleAlt.png) \
$$quote($$BASEDIR/assets/VisualStyle.dark/PriceTag.png) \
$$quote($$BASEDIR/assets/VisualStyle.dark/Watch.png) \
$$quote($$BASEDIR/assets/Watch_a.png) \
$$quote($$BASEDIR/assets/help.html) \
$$quote($$BASEDIR/assets/humane.js) \
$$quote($$BASEDIR/assets/icons/123.png) \
$$quote($$BASEDIR/assets/icons/Add.png) \
$$quote($$BASEDIR/assets/icons/Capitalize.png) \
$$quote($$BASEDIR/assets/icons/Check.png) \
$$quote($$BASEDIR/assets/icons/Clock.png) \
$$quote($$BASEDIR/assets/icons/Clock_a.png) \
$$quote($$BASEDIR/assets/icons/Date.png) \
$$quote($$BASEDIR/assets/icons/Delete.png) \
$$quote($$BASEDIR/assets/icons/DownBox.png) \
$$quote($$BASEDIR/assets/icons/Funnel.png) \
$$quote($$BASEDIR/assets/icons/Info.png) \
$$quote($$BASEDIR/assets/icons/Pencil.png) \
$$quote($$BASEDIR/assets/icons/PriceTag.png) \
$$quote($$BASEDIR/assets/icons/Recycle.png) \
$$quote($$BASEDIR/assets/icons/Search.png) \
$$quote($$BASEDIR/assets/icons/Sort.png) \
$$quote($$BASEDIR/assets/icons/Undo.png) \
$$quote($$BASEDIR/assets/icons/abc.png) \
$$quote($$BASEDIR/assets/icons/ic_bbm.png) \
$$quote($$BASEDIR/assets/icons/invoke.png) \
$$quote($$BASEDIR/assets/icons/rtd_512_3-110.png) \
$$quote($$BASEDIR/assets/icons/rtd_512_3-144.png) \
$$quote($$BASEDIR/assets/icons/rtd_512_3-86.png) \
$$quote($$BASEDIR/assets/icons/rtd_512_3-90.png) \
$$quote($$BASEDIR/assets/icons/rtd_512_3-96.png) \
$$quote($$BASEDIR/assets/icons/rtd_splash_1440s.png) \
$$quote($$BASEDIR/assets/icons/rtd_splash_720s.png) \
$$quote($$BASEDIR/assets/icons/rtd_splash_768p.png) \
$$quote($$BASEDIR/assets/main.qml)
}
config_pri_source_group1 {
SOURCES += \
$$quote($$BASEDIR/src/LocalFile.cpp) \
$$quote($$BASEDIR/src/TaskModel.cpp) \
$$quote($$BASEDIR/src/applicationui.cpp) \
$$quote($$BASEDIR/src/main.cpp)
HEADERS += \
$$quote($$BASEDIR/src/LocalFile.h) \
$$quote($$BASEDIR/src/TaskModel.h) \
$$quote($$BASEDIR/src/applicationui.hpp)
}
CONFIG += precompile_header
PRECOMPILED_HEADER = $$quote($$BASEDIR/precompiled.h)
lupdate_inclusion {
SOURCES += \
$$quote($$BASEDIR/../src/*.c) \
$$quote($$BASEDIR/../src/*.c++) \
$$quote($$BASEDIR/../src/*.cc) \
$$quote($$BASEDIR/../src/*.cpp) \
$$quote($$BASEDIR/../src/*.cxx) \
$$quote($$BASEDIR/../assets/*.qml) \
$$quote($$BASEDIR/../assets/*.js) \
$$quote($$BASEDIR/../assets/*.qs) \
$$quote($$BASEDIR/../assets/VisualStyle.bright/*.qml) \
$$quote($$BASEDIR/../assets/VisualStyle.bright/*.js) \
$$quote($$BASEDIR/../assets/VisualStyle.bright/*.qs) \
$$quote($$BASEDIR/../assets/VisualStyle.dark/*.qml) \
$$quote($$BASEDIR/../assets/VisualStyle.dark/*.js) \
$$quote($$BASEDIR/../assets/VisualStyle.dark/*.qs) \
$$quote($$BASEDIR/../assets/icons/*.qml) \
$$quote($$BASEDIR/../assets/icons/*.js) \
$$quote($$BASEDIR/../assets/icons/*.qs)
HEADERS += \
$$quote($$BASEDIR/../src/*.h) \
$$quote($$BASEDIR/../src/*.h++) \
$$quote($$BASEDIR/../src/*.hh) \
$$quote($$BASEDIR/../src/*.hpp) \
$$quote($$BASEDIR/../src/*.hxx)
}
TRANSLATIONS = $$quote($${TARGET}.ts)

5
precompiled.h Normal file
View File

@ -0,0 +1,5 @@
// This file is used to store precompiled headers.
#include <QObject>
#include <QString>
#include <QVariant>

103
src/LocalFile.cpp Normal file
View File

@ -0,0 +1,103 @@
/*
* Copyright 2012-2018 Morgan McMillian <gilag@monkeystew.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "LocalFile.h"
LocalFile::LocalFile() {
mPath = "data/todo";
mFile = mPath + "/todo.txt";
mDone = mPath + "/done.txt";
if (!dir.exists(mPath)) {
dir.mkdir(mPath);
}
}
LocalFile::~LocalFile() {
// TODO Auto-generated destructor stub
}
QStringList LocalFile::load() const {
QStringList data;
QFile file(mFile);
file.open(QIODevice::ReadOnly);
QTextStream in(&file);
while (!in.atEnd()) {
QString line = in.readLine();
data << line;
}
return data;
}
QStringList LocalFile::loadArchive() const {
QStringList data;
QFile file(mDone);
file.open(QIODevice::ReadOnly);
QTextStream in(&file);
while (!in.atEnd()) {
QString line = in.readLine();
data << line;
}
return data;
}
void LocalFile::save(const QStringList &data) {
QSettings settings;
QString lnend = settings.value("windowsbreak").toBool() ? "\r\n" : "\n";
QFile file(mFile);
file.open(QIODevice::WriteOnly);
QTextStream out(&file);
foreach (QString line, data) {
out << line << lnend;
}
file.close();
}
void LocalFile::saveArchive(const QStringList &data) {
QSettings settings;
QString lnend = settings.value("windowsbreak").toBool() ? "\r\n" : "\n";
QFile file(mDone);
file.open(QIODevice::WriteOnly);
QTextStream out(&file);
foreach (QString line, data) {
out << line << lnend;
}
file.close();
}
void LocalFile::archive(const QStringList &data) {
QSettings settings;
QString lnend = settings.value("windowsbreak").toBool() ? "\r\n" : "\n";
QFile file(mDone);
file.open(QIODevice::Append);
QTextStream out(&file);
foreach (QString line, data) {
out << line << lnend;
}
file.close();
}
QString LocalFile::path() const {
return mPath;
}
void LocalFile::setPath(const QString &path) {
mPath = path;
if (!dir.exists(mPath)) {
dir.mkdir(mPath);
}
mFile = mPath + "/todo.txt";
mDone = mPath + "/done.txt";
}

48
src/LocalFile.h Normal file
View File

@ -0,0 +1,48 @@
/*
* Copyright 2012-2018 Morgan McMillian <gilag@monkeystew.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef LOCALFILE_H_
#define LOCALFILE_H_
#include <QDir>
#include <QFile>
#include <QDebug>
#include <QSettings>
#include <QTextStream>
class LocalFile {
public:
LocalFile();
virtual ~LocalFile();
QStringList load() const;
QStringList loadArchive() const;
QString path() const;
void save(const QStringList &data);
void saveArchive(const QStringList &data);
void setPath(const QString &path);
void archive(const QStringList &data);
private:
QDir dir;
QString mPath;
QString mFile;
QString mDone;
};
#endif /* LOCALFILE_H_ */

664
src/TaskModel.cpp Normal file
View File

@ -0,0 +1,664 @@
/*
* Copyright 2012-2018 Morgan McMillian <gilag@monkeystew.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "TaskModel.h"
TaskModel::TaskModel(QObject* parent) {
setParent(parent);
QSettings settings;
mOffline = false;
mDelete = -1;
ts_settings = new QSettings("Morgan McMillian", "RenamedTodo");
toast = new SystemToast(this);
mSort = settings.value("sort").toInt();
if (!mSort) mSort = PRIORITY;
QString fpath = settings.value("path").toString();
if (!fpath.isNull()) {
localfile.setPath(fpath);
}
regxComp.setPattern("^x ");
regxPri.setPattern("\\(([A-Z])\\) ");
regxDate.setPattern("([0-9]{4}-[0-9]{2}-[0-9]{2}) ?");
regxProj.setPattern("(\\+[^ ]+)");
regxCtx.setPattern("(@[^ ]+)");
qDebug() << "I am life! " << this;
}
TaskModel::~TaskModel() {
delete toast;
qDebug() << "I am death! " << this;
}
int TaskModel::sort() const {
return mSort;
}
void TaskModel::setSort(const int &sort) {
QSettings settings;
mSort = sort;
settings.setValue("sort", sort);
setView();
emit listUpdated();
}
QVariant TaskModel::setting(const QString &setting, const QVariant &defVal) const {
QSettings settings;
if (settings.value(setting).isNull()) {
return defVal;
}
return settings.value(setting);
}
QString TaskModel::activeFilters() {
QString filterlist;
foreach(QString item, mFilters) {
filterlist = filterlist + item + ",";
}
if (filterlist.size() > 0) {
return " Filter: " + filterlist;
} else {
return "";
}
}
QString TaskModel::formatDate(const QDateTime &date) const {
return date.toString("yyyy-MM-dd");
}
void TaskModel::modifySetting(const QString &setting, const QVariant &value) {
QSettings settings;
settings.setValue(setting, value);
if (setting == "sort") mSort = value.toInt();
if (setting == "path") {
localfile.setPath(value.toString());
load();
}
}
void TaskModel::onFileDataChanged(QStringList data) {
localfile.save(data);
load();
setView();
}
void TaskModel::onArchiveData(QStringList data) {
localfile.saveArchive(data);
mArchiveData = data;
}
QVariantList TaskModel::filters() const {
QVariantList filters;
foreach (QString project, mProjects) {
QVariantMap map;
map["type"] = "Projects";
map["title"] = project;
if (mFilters.indexOf(project) >= 0) {
map["checked"] = true;
} else {
map["checked"] = false;
}
filters.append(map);
}
foreach (QString context, mContexts) {
QVariantMap map;
map["type"] = "Contexts";
map["title"] = context;
if (mFilters.indexOf(context) >= 0) {
map["checked"] = true;
} else {
map["checked"] = false;
}
filters.append(map);
}
foreach (QString duedate, mDueDates) {
QVariantMap map;
qDebug() << "::" + duedate;
map["type"] = "Due Dates";
map["title"] = duedate;
if (mFilters.indexOf(duedate) >= 0) {
map["checked"] = true;
} else {
map["checked"] = false;
}
filters.append(map);
}
return filters;
}
QVariantList TaskModel::tododata() {
QVariantList rData;
foreach (QString item, mTodoList) {
QVariantMap map = parseTask(item);
rData.append(map);
}
return rData;
}
void TaskModel::refresh() {
QSettings settings;
load();
emit listUpdated();
}
void TaskModel::commit() {
QSettings settings;
QString lnend = settings.value("windowsbreak").toBool() ? "\r\n" : "\n";
save();
}
void TaskModel::load() {
mTodoData.clear();
QStringList dummy;
dummy = localfile.load();
foreach (QString item, dummy) {
QVariantMap map = parseTask(item);
mTodoData.append(map);
}
mArchiveData = localfile.loadArchive();
}
void TaskModel::save() {
QStringList data;
foreach (QVariant map, mTodoData) {
QString listitem = buildTask(map.toMap());
data.append(listitem);
}
localfile.save(data);
load();
setView();
emit listUpdated();
}
void TaskModel::archive() {
QSettings settings;
QString lnend = settings.value("windowsbreak").toBool() ? "\r\n" : "\n";
foreach (QVariant map, mTodoData) {
QVariantMap task = map.toMap();
if (task["complete"].toBool()) {
QString architem = buildTask(task);
mArchiveData.append(architem);
mTodoData.removeAt(mTodoData.indexOf(task));
}
}
if (mArchiveData.size() > 0) {
localfile.saveArchive(mArchiveData);
commit();
} else {
load();
setView();
}
}
void TaskModel::search(const QString &text) {
mSearch = text;
setView();
}
void TaskModel::setValue(int idx, const QString &key, const QVariant &value) {
//qDebug() << "index: " << idx;
//qDebug() << "key: " << key;
//qDebug() << "value: " << value;
//qDebug() << "check: " << QVariantListDataModel::value(idx).value<QVariantMap>();
QSettings settings;
if (idx >=0 && idx < size()) {
QVariantMap current = QVariantListDataModel::value(idx).value<QVariantMap>();
QVariantMap updated = current;
updated[key] = value;
if (key == "complete" && value == true) {
updated["priority"] = "";
updated["dateCompleted"] = QDate::currentDate().toString("yyyy-MM-dd");
} else if (key == "complete" && value == false) {
updated["dateCompleted"] = "";
}
QString rtask = buildTask(updated);
updated["text"] = QVariant(rtask);
//qDebug() << "current: " << current;
//qDebug() << "idx: " << idx;
//qDebug() << "orig idx: " << mTodoData.indexOf(current);
//qDebug() << "test0:" << mTodoData.value(0);
//qDebug() << "testX:" << mTodoData.value(mTodoData.size()-1);
int origidx = mTodoData.indexOf(current);
mTodoData.replace(origidx, updated);
//setView();
commit();
if (key == "complete" && value == true && settings.value("autoarchive").toBool()) {
archive();
}
}
//qDebug() << "new: " << QVariantListDataModel::value(idx).value<QVariantMap>();
}
void TaskModel::exportFiles(const QStringList &files) {
QString epath = files[0];
QRegExp epathrgx("todo.txt$");
epath.replace(epathrgx, "");
LocalFile exportfrom;
LocalFile exportto;
exportto.setPath(epath);
QStringList todo = exportfrom.load();
QStringList done = exportfrom.loadArchive();
exportto.save(todo);
exportto.saveArchive(done);
}
void TaskModel::promptPurgeSandbox() {
dialog = new SystemDialog("PURGE", "CANCEL");
dialog->setTitle("Purge local sandbox");
dialog->setBody("Erase local sandbox files? WARNING This cannot be undone.");
bool success = QObject::connect(dialog, SIGNAL(finished(bb::system::SystemUiResult::Type)),
this, SLOT(onConfirmPurge(bb::system::SystemUiResult::Type)));
if (success) {
dialog->show();
} else {
dialog->deleteLater();
}
}
void TaskModel::onConfirmPurge(bb::system::SystemUiResult::Type value) {
QStringList empty;
LocalFile sandbox;
switch(value) {
case bb::system::SystemUiResult::ConfirmButtonSelection:
qDebug() << "PURGE";
sandbox.save(empty);
sandbox.saveArchive(empty);
load();
setView();
break;
case bb::system::SystemUiResult::CancelButtonSelection:
qDebug() << "CANCEL";
break;
default:
break;
}
dialog->deleteLater();
}
void TaskModel::promptDelete(int idx) {
dialog = new SystemDialog("DELETE", "CANCEL");
dialog->setTitle("Delete Task");
dialog->setBody("Permanently delete this Entry?");
bool success = QObject::connect(dialog, SIGNAL(finished(bb::system::SystemUiResult::Type)),
this, SLOT(onDeleteTask(bb::system::SystemUiResult::Type)));
if (success) {
mDelete = idx;
dialog->show();
} else {
mDelete = -1;
dialog->deleteLater();
}
}
void TaskModel::onDeleteTask(bb::system::SystemUiResult::Type value) {
switch(value) {
case bb::system::SystemUiResult::ConfirmButtonSelection:
//qDebug() << "DELETE";
delTask(mDelete);
break;
case bb::system::SystemUiResult::CancelButtonSelection:
//qDebug() << "CANCEL";
mDelete = -1;
break;
default:
break;
}
dialog->deleteLater();
}
void TaskModel::delTask(int idx) {
if (idx >=0 && idx < size()) {
QVariantMap current = QVariantListDataModel::value(idx).value<QVariantMap>();
int origidx = mTodoData.indexOf(current);
//qDebug() << "idx: " << idx;
//qDebug() << "orig idx: " << mTodoData.indexOf(current);
mTodoData.removeAt(origidx);
//setView();
commit();
mDelete = -1;
}
}
void TaskModel::changeFilter(const QString &filter, const bool &enabled) {
int idx = mFilters.indexOf(filter);
if (enabled) {
if (idx == -1) mFilters.append(filter);
} else {
if (idx >= 0) mFilters.removeAt(idx);
}
//qDebug() << "Filter List: " << mFilters;
}
void TaskModel::resetFilter() {
mFilters.clear();
setView();
toast->setBody("Filters removed.");
toast->show();
}
void TaskModel::addFullTask(const QString &task) {
QVariantMap map = parseTask(task);
QSettings settings;
if (settings.value("datenew").toBool()) {
map["dateCreated"] = QDate::currentDate().toString("yyyy-MM-dd");
}
mTodoData.append(map);
//setView();
commit();
}
void TaskModel::updateTask(int idx, const QString &task) {
if (idx >=0 && idx < size()) {
QVariantMap current = QVariantListDataModel::value(idx).value<QVariantMap>();
int origidx = mTodoData.indexOf(current);
QVariantMap map = parseTask(task);
if (origidx >= 0) {
mTodoData.replace(origidx, map);
//setView();
commit();
} else {
// TODO produce some error message
qDebug() << "ERROR: origidx = " << origidx;
}
}
}
QVariantMap TaskModel::parseTask(QString rawTask) {
QVariantMap task;
int pos = 0;
QString item = rawTask;
bool complete = false;
QString priority = "";
QString dateCompleted = "";
QString dateCreated = "";
QString dateDue = "";
QString detail = "";
//qDebug() << "..parsing projects..";
QStringList prj;
pos = 0;
while ((pos = regxProj.indexIn(item,pos)) != -1) {
prj << regxProj.cap(1);
pos += regxProj.matchedLength();
}
if (prj.size() > 0) {
foreach (QString p, prj) {
if (mProjects.indexOf(p) < 0) {
mProjects << p;
}
}
}
//qDebug() << "my projects: " << mProjects;
//qDebug() << "..parsing contexts..";
QStringList ctx;
pos = 0;
while ((pos = regxCtx.indexIn(item,pos)) != -1) {
ctx << regxCtx.cap(1);
pos += regxCtx.matchedLength();
}
if (ctx.size() > 0) {
foreach (QString c, ctx) {
if (mContexts.indexOf(c) < 0) {
mContexts << c;
}
}
}
//qDebug() << "my contexts: " << mContexts;
QRegExp regxDue("due:([0-9]{4}-[0-9]{2}-[0-9]{2}) ?");
if (regxDue.indexIn(item,0) != -1) {
dateDue = regxDue.cap(1);
QString duestr = "due:" + dateDue;
if (dateDue.length() > 0) {
if (mDueDates.indexOf(duestr) < 0) {
mDueDates << duestr;
}
}
}
//qDebug() << "---*****---";
if (regxComp.indexIn(item) == 0) {
//qDebug() << "complete: true";
complete = true;
item.replace(regxComp, "");
pos = 0;
QStringList dates;
while ((pos = regxDate.indexIn(item,pos)) != -1) {
dates << regxDate.cap(1);
pos += regxDate.matchedLength();
}
if (dates.size() > 0) {
//qDebug() << "completed: " << dates.at(0);
dateCompleted = dates.at(0);
if (dates.size() >= 2) {
//qDebug() << "created: " << dates.at(1);
dateCreated = dates.at(1);
pos = regxDate.indexIn(item,0);
item.replace(QRegExp("^([0-9]{4}-[0-9]{2}-[0-9]{2} )"), "");
}
}
pos = regxDate.indexIn(item,0);
item.replace(QRegExp("^([0-9]{4}-[0-9]{2}-[0-9]{2} )"), "");
} else if (regxDate.indexIn(item) >= 0 && regxDate.indexIn(item) < 5) {
dateCreated = regxDate.cap(1);
// item.replace(regxDate.cap(1) + " ", "");
// item.replace(QRegExp("^([0-9]{4}-[0-9]{2}-[0-9]{2} )"), "");
item.remove(regxDate.indexIn(item), 11);
}
if (regxPri.indexIn(item) >= 0) {
//qDebug() << "priority: " << regxPri.cap(1);
priority = regxPri.cap(1);
item.replace(regxPri, "");
}
detail = item;
task["complete"] = QVariant(complete);
task["priority"] = QVariant(priority);
task["dateCompleted"] = QVariant(dateCompleted);
task["dateCreated"] = QVariant(dateCreated);
task["dateDue"] = QVariant(dateDue);
task["detail"] = QVariant(detail);
task["text"] = QVariant(rawTask);
return task;
}
QString TaskModel::buildTask(const QVariantMap &task) {
QString text = "";
bool complete = task["complete"].toBool();
QString priority = task["priority"].toString();
QString dateCompleted = task["dateCompleted"].toString();
QString dateCreated = task["dateCreated"].toString();
QString detail = task["detail"].toString();
if (complete) text = text + "x ";
if (priority.length() > 0) text = text + "(" + priority + ") ";
if (dateCompleted.length() > 0) text = text + dateCompleted + " ";
if (dateCreated.length() > 0) text = text + dateCreated + " ";
if (detail.length() > 0) text = text + detail;
return text;
}
bool TaskModel::sortByPriority(const QString &a, const QString &b) {
QString matchA;
QString matchB;
QRegExp pri("\\(([A-Z])\\) ");
QRegExp done("^x ");
QRegExp date("([0-9]{4}-[0-9]{2}-[0-9]{2}) ?");
QRegExp sca("^@");
QRegExp scp("^\\+");
if (pri.indexIn(a) >= 0) {
matchA = pri.cap(1);
} else if (done.indexIn(a) == 0) {
matchA = "}";
} else {
matchA = a.toLower();
matchA.replace(date,"");
matchA.replace(sca,"");
matchA.replace(scp,"");
}
//qDebug() << "a: " << a;
//qDebug() << "matchA: " << matchA;
if (pri.indexIn(b) >= 0) {
matchB = pri.cap(1);
} else if (done.indexIn(b) == 0) {
matchB = "}";
} else {
matchB = b.toLower();
matchB.replace(date,"");
matchB.replace(sca,"");
matchB.replace(scp,"");
}
//qDebug() << "b: " << b;
//qDebug() << "matchB: " << matchB;
return matchA < matchB;
}
bool TaskModel::sortByText(const QString &a, const QString &b) {
QString matchA = a;
QString matchB = b;
QRegExp pri("\\([A-Z]\\) ");
QRegExp done("^x ");
QRegExp date("([0-9]{4}-[0-9]{2}-[0-9]{2}) ?");
QRegExp sca("^@");
QRegExp scp("^\\+");
matchA.replace(done, "");
matchA.replace(pri, "");
matchA.replace(date, "");
matchA.replace(sca,"");
matchA.replace(scp,"");
//qDebug() << "A: " << matchA;
matchB.replace(done, "");
matchB.replace(pri, "");
matchB.replace(date, "");
matchB.replace(sca,"");
matchB.replace(scp,"");
//qDebug() << "B: " << matchB;
return matchA.toLower() < matchB.toLower();
}
bool TaskModel::sortByDueDate(const QString &a, const QString &b) {
QString matchA = a;
QString matchB = b;
QRegExp regxDue("(due:)([0-9]{4}-[0-9]{2}-[0-9]{2}) ?");
QRegExp pri("\\([A-Z]\\) ");
QRegExp done("^x ");
QRegExp date("([0-9]{4}-[0-9]{2}-[0-9]{2}) ?");
QRegExp sca("^@");
QRegExp scp("^\\+");
if (regxDue.indexIn(a,0) != -1) {
matchA = regxDue.cap(2);
} else if (done.indexIn(a) == 0) {
matchA = "}";
} else {
matchA.replace(done, "");
matchA.replace(pri, "");
matchA.replace(date, "");
matchA.replace(sca,"");
matchA.replace(scp,"");
}
if (regxDue.indexIn(b,0) != -1) {
matchB = regxDue.cap(2);
} else if (done.indexIn(b) == 0) {
matchB = "}";
} else {
matchB.replace(done, "");
matchB.replace(pri, "");
matchB.replace(date, "");
matchB.replace(sca,"");
matchB.replace(scp,"");
}
return matchA.toLower() < matchB.toLower();
}
void TaskModel::setView() {
mTodoList.clear();
mProjects.clear();
mContexts.clear();
mDueDates.clear();
//qDebug() << "::" << mFilters;
foreach (QVariant map, mTodoData) {
QString listitem = buildTask(map.toMap());
if (mSearch.length() > 0) {
if (listitem.contains(mSearch, Qt::CaseInsensitive)) {
mTodoList.append(listitem);
}
} else if (mFilters.length() > 0) {
// TODO this results in an "or" condition, probably should be "and" instead
foreach (QString filter, mFilters) {
if (listitem.indexOf(filter) >=0) {
mTodoList.append(listitem);
break;
}
}
} else {
mTodoList.append(listitem);
}
}
clear();
switch (mSort) {
case PRIORITY:
qSort(mTodoList.begin(), mTodoList.end(), sortByPriority);
break;
case ID:
// this is the default
break;
case TEXT:
qSort(mTodoList.begin(), mTodoList.end(), sortByText);
break;
case DUE:
qSort(mTodoList.begin(), mTodoList.end(), sortByDueDate);
break;
}
foreach (QString item, mTodoList) {
QVariantMap map = parseTask(item);
append(map);
}
emit listUpdated();
}

112
src/TaskModel.h Normal file
View File

@ -0,0 +1,112 @@
/*
* Copyright 2012-2018 Morgan McMillian <gilag@monkeystew.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef TASKMODEL_H_
#define TASKMODEL_H_
#include <bb/cascades/QListDataModel>
#include <bb/system/SystemDialog>
#include <bb/system/SystemUiButton>
#include <bb/system/SystemToast>
#include <QRegExp>
#include <QSettings>
#include "LocalFile.h"
using namespace bb::cascades;
using namespace bb::system;
class TaskModel: public bb::cascades::QVariantListDataModel {
Q_OBJECT
Q_PROPERTY(int sort READ sort WRITE setSort NOTIFY sortChanged)
Q_PROPERTY(QVariantList filters READ filters FINAL)
Q_PROPERTY(QVariantList tododata READ tododata FINAL)
public:
TaskModel(QObject* parent = 0);
virtual ~TaskModel();
enum SortType { PRIORITY, ID, TEXT, DUE };
Q_ENUMS(SortType);
int sort() const;
void setSort(const int &sort);
QVariantList filters() const;
QVariantList tododata();
Q_INVOKABLE void refresh();
Q_INVOKABLE void commit();
Q_INVOKABLE void load();
Q_INVOKABLE void save();
Q_INVOKABLE void archive();
Q_INVOKABLE void search(const QString &text);
Q_INVOKABLE QVariant setting(const QString &setting, const QVariant &defVal) const;
Q_INVOKABLE QString activeFilters();
Q_INVOKABLE QString formatDate(const QDateTime &date) const;
Q_INVOKABLE void promptPurgeSandbox();
Q_INVOKABLE void exportFiles(const QStringList &files);
Q_SLOT void setView();
Q_SLOT void setValue(int idx, const QString &key, const QVariant &value);
Q_SLOT void updateTask(int idx, const QString &task);
Q_SLOT void addFullTask(const QString &task);
Q_SLOT void promptDelete(int idx);
Q_SLOT void delTask(int idx);
Q_SLOT void changeFilter(const QString &filter, const bool &enabled);
Q_SLOT void resetFilter();
Q_SLOT void modifySetting(const QString &setting, const QVariant &value);
Q_SLOT void onFileDataChanged(QStringList data);
Q_SLOT void onArchiveData(QStringList data);
Q_SLOT void onDeleteTask(bb::system::SystemUiResult::Type value);
Q_SLOT void onConfirmPurge(bb::system::SystemUiResult::Type value);
Q_SIGNAL void sortChanged(SortType sort);
Q_SIGNAL void listUpdated();
private:
QVariantMap parseTask(QString rawTask);
QString buildTask(const QVariantMap &task);
static bool sortByPriority(const QString &a, const QString &b);
static bool sortByText(const QString &a, const QString &b);
static bool sortByDueDate(const QString &a, const QString &b);
QRegExp regxComp;
QRegExp regxPri;
QRegExp regxDate;
QRegExp regxProj;
QRegExp regxCtx;
QSettings *ts_settings;
LocalFile localfile;
SystemDialog *dialog;
SystemToast *toast;
QStringList mProjects;
QStringList mContexts;
QStringList mDueDates;
QStringList mFilters;
QStringList mTodoList;
QStringList mArchiveData;
QVariantList mTodoData;
QString mSearch;
int mSort;
int mDelete;
bool mOffline;
};
#endif /* TASKMODEL_H_ */

107
src/applicationui.cpp Normal file
View File

@ -0,0 +1,107 @@
/*
* Copyright (c) 2011-2015 BlackBerry Limited.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "applicationui.hpp"
#include "TaskModel.h"
#include <bb/cascades/Application>
#include <bb/cascades/QmlDocument>
#include <bb/cascades/AbstractPane>
#include <bb/cascades/LocaleHandler>
#include <bb/cascades/pickers/FilePicker>
#include <bb/cascades/SceneCover>
#include <bb/ApplicationInfo>
using namespace bb::cascades;
ApplicationUI::ApplicationUI() :
QObject()
{
// prepare the invoke manager
invokeManager = new bb::system::InvokeManager(this);
connect(invokeManager, SIGNAL(invoked(const bb::system::InvokeRequest&)),
this, SLOT(onInvoke(const bb::system::InvokeRequest&)));
// prepare the localization
m_pTranslator = new QTranslator(this);
m_pLocaleHandler = new LocaleHandler(this);
bool res = QObject::connect(m_pLocaleHandler, SIGNAL(systemLanguageChanged()), this, SLOT(onSystemLanguageChanged()));
// This is only available in Debug builds
Q_ASSERT(res);
// Since the variable is not used in the app, this is added to avoid a
// compiler warning
Q_UNUSED(res);
// initial load
onSystemLanguageChanged();
qmlRegisterType<TaskModel>("com.monkeystew.taskmodel", 1, 0, "TaskModel");
qmlRegisterType<SceneCover>("bb.cascades", 1, 0, "SceneCover");
qmlRegisterUncreatableType<AbstractCover>("bb.cascades", 1, 0, "AbstractCover",
"An AbstractCover cannot be created.");
// Create scene document from main.qml asset, the parent is set
// to ensure the document gets destroyed properly at shut down.
QmlDocument *qml = QmlDocument::create("asset:///main.qml").parent(this);
qml->setContextProperty("_Taskslayer", this);
// Create root object for the UI
AbstractPane *root = qml->createRootObject<AbstractPane>();
// Set created root object as the application scene
Application::instance()->setScene(root);
bb::ApplicationInfo appinfo;
qDebug() << "APP VER_ " << appinfo.version();
root->setProperty("appversion", appinfo.version());
}
void ApplicationUI::onSystemLanguageChanged()
{
QCoreApplication::instance()->removeTranslator(m_pTranslator);
// Initiate, load and install the application translation files.
QString locale_string = QLocale().name();
QString file_name = QString("RenamedTodo_%1").arg(locale_string);
if (m_pTranslator->load(file_name, "app/native/qm")) {
QCoreApplication::instance()->installTranslator(m_pTranslator);
}
}
void ApplicationUI::onInvoke(const bb::system::InvokeRequest& request)
{
if (request.action() == "bb.action.SHARE") {
Q_EMIT addNewTask(QString::fromUtf8(request.data()));
} else if (request.action() == "bb.action.SEARCH.EXTENDED") {
Q_EMIT searchTaskList(QString::fromUtf8(request.data()));
}
}
void ApplicationUI::getSupport(const int target)
{
bb::system::InvokeRequest request;
switch(target)
{
case 0:
request.setTarget("sys.pim.uib.email.hybridcomposer");
request.setAction("bb.action.COMPOSE");
request.setMimeType("message/rfc822");
request.setUri(QUrl("mailto:rtd@monkeystew.com?subject=Renamed Todo for BlackBerry 10"));
invokeManager->invoke(request);
break;
}
}

60
src/applicationui.hpp Normal file
View File

@ -0,0 +1,60 @@
/*
* Copyright (c) 2011-2015 BlackBerry Limited.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ApplicationUI_HPP_
#define ApplicationUI_HPP_
#include <QObject>
#include <bb/system/InvokeManager>
#include <bb/system/InvokeRequest>
namespace bb
{
namespace cascades
{
class LocaleHandler;
}
}
class QTranslator;
/*!
* @brief Application UI object
*
* Use this object to create and init app UI, to create context objects, to register the new meta types etc.
*/
class ApplicationUI : public QObject
{
Q_OBJECT
public:
ApplicationUI();
virtual ~ApplicationUI() {}
Q_INVOKABLE void getSupport(const int target);
Q_SIGNALS:
void addNewTask(QString data);
void searchTaskList(QString data);
private slots:
void onSystemLanguageChanged();
void onInvoke(const bb::system::InvokeRequest &request);
private:
QTranslator* m_pTranslator;
bb::cascades::LocaleHandler* m_pLocaleHandler;
bb::system::InvokeManager *invokeManager;
};
#endif /* ApplicationUI_HPP_ */

38
src/main.cpp Normal file
View File

@ -0,0 +1,38 @@
/*
* Copyright (c) 2011-2015 BlackBerry Limited.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "applicationui.hpp"
#include <bb/cascades/Application>
#include <QLocale>
#include <QTranslator>
#include <Qt/qdeclarativedebug.h>
using namespace bb::cascades;
Q_DECL_EXPORT int main(int argc, char **argv)
{
Application app(argc, argv);
// Create the Application UI object, this is where the main.qml file
// is loaded and the application scene is set.
ApplicationUI appui;
// Enter the application main event loop.
return Application::exec();
}

12
translations/Makefile Normal file
View File

@ -0,0 +1,12 @@
QMAKE_TARGET = RenamedTodo
LUPDATE = $(QNX_HOST)/usr/bin/lupdate
LRELEASE = $(QNX_HOST)/usr/bin/lrelease
update: $(QMAKE_TARGET).pro FORCE
$(LUPDATE) $(QMAKE_TARGET).pro
release: $(QMAKE_TARGET).pro $(QMAKE_TARGET).ts
$(LRELEASE) $(QMAKE_TARGET).pro
FORCE:

View File

@ -0,0 +1 @@
include (../RenamedTodo.pro)

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.0">
</TS>