aboutsummaryrefslogtreecommitdiff
path: root/QSThingsPlugin/Handlers/ThingsTaskHandler.m
blob: 406e5ab8814af4daba4c6ca868e75e8708ffe76e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
#import "ThingsTaskHandler.h"

NS_ASSUME_NONNULL_BEGIN

@implementation ThingsTaskHandler

- (BOOL)objectHasChildren:(QSObject *)object {
  return YES;
}

- (void)setQuickIconForObject:(QSObject *)object {
  NSImage *baseImage = [QSResourceManager imageNamed:@"com.culturedcode.ThingsMac"];
  NSString *badge = @"checkmark.circle";
  NSColor *color = [NSColor colorWithRed:0.310 green:0.616 blue:0.976 alpha:1.0];
  
  if (object.primaryType == kProjectType) {
    badge = @"circle";
    color = [NSColor colorWithRed:0.157 green:0.376 blue:0.733 alpha:1.0];
  }
  NSImage *imageWithBadge = [baseImage imageOfSize:NSMakeSize(512, 512) withSystemBadge:badge ofColor:color];
  
  if (imageWithBadge) {
    [object setIcon:imageWithBadge];
  } else {
    [object setIcon:baseImage];
  }
}

- (BOOL)loadChildrenForObject:(QSObject *)object {
  NSDictionary *contents = [object objectForType:object.primaryType];
  
  if (!contents) {
    NSLog(@"Malformed Things Task: No content.");
    return NO;
  }

  NSString *path = [contents objectForKey:@"path"];
  if (!path) {
    NSLog(@"Malformed Things Task: No path.");
    return NO;
  }
  
  NSString *uuid = [contents objectForKey:@"uuid"];
  if (!uuid) {
    NSLog(@"Malformed Things Task: No uuid.");
    return NO;
  }
  
  // Tasks and Projects are basically the same thing in the Things database. So we use the same handler.
  // The big difference is that projects can't have projects, and tasks can't have tasks

  NSMutableArray *children = [NSMutableArray array];
  [children addObjectsFromArray:[self tagsForTaskIdentifiedBy:uuid usingDatabaseAt:path ]];
  [children addObjectsFromArray:[self areasForTaskIdentifiedBy:uuid usingDatabaseAt:path ]];

  if (object.primaryType == kProjectType) {
    [children addObjectsFromArray:[self tasksForTaskIdentifiedBy:uuid usingDatabaseAt:path ]];
    [children addObjectsFromArray:[self tasksInHeadingsForTaskIdentifiedBy:uuid usingDatabaseAt:path ]];
  } else {
    [children addObjectsFromArray:[self projectsForTaskIdentifiedBy:uuid usingDatabaseAt:path ]];
  }

  [object setChildren:children];
  return YES;
}

- (NSArray *)tagsForTaskIdentifiedBy:(NSString *)uuid usingDatabaseAt:(NSString *)path {
  NSString *query = [NSString stringWithFormat: @"SELECT "
            "tag.uuid as uuid, "
            "tag.title as title "
            "FROM TMTask AS task "
            "LEFT JOIN TMTaskTag as junction "
            "ON junction.tasks = task.uuid "
            "LEFT JOIN TMTag as tag "
            "ON junction.tags = tag.uuid "
            "WHERE task.uuid = '%@' "
            "AND tag.uuid IS NOT NULL "
            "ORDER BY tag.title;", uuid];
  
  NSArray *results = [SQLHelper executeSql:query onFile:path];
  NSMutableArray *objects = [NSMutableArray array];
  [results enumerateObjectsUsingBlock:^(NSDictionary *dictionary, NSUInteger i, BOOL *stop) {
    [objects addObject:[ObjectHelper tagFromSQLResult:dictionary usingPath:path ]];
  }];
  
  return objects;
}

- (NSArray *)projectsForTaskIdentifiedBy:(NSString *)uuid usingDatabaseAt:(NSString *)path {
  NSString *query = [NSString stringWithFormat: @"SELECT "
            "project.uuid as uuid, "
            "project.creationDate as creationDate, "
            "project.status as status, "
            "project.title as title, "
            "project.notes as notes, "
            "project.area as area "
            "FROM TMTask AS task "
            "LEFT JOIN TMTask as project "
            "ON task.project = project.uuid "
            "AND project.type = 1 "
            "WHERE task.uuid = '%@' "
            "AND project.uuid IS NOT NULL "
            "AND project.trashed = 0 "
            "AND project.status = 0 "
            "ORDER BY project.title;", uuid];
  
  NSArray *results = [SQLHelper executeSql:query onFile:path];
  NSMutableArray *objects = [NSMutableArray array];
  [results enumerateObjectsUsingBlock:^(NSDictionary *dictionary, NSUInteger i, BOOL *stop) {
    [objects addObject:[ObjectHelper projectFromSQLResult:dictionary usingPath:path ]];
  }];
  
  return objects;
}

- (NSArray *)areasForTaskIdentifiedBy:(NSString *)uuid usingDatabaseAt:(NSString *)path {
  NSString *query = [NSString stringWithFormat: @"SELECT "
            "area.uuid as uuid, "
            "area.title as title "
            "FROM TMTask AS task "
            "LEFT JOIN TMTask as project "
            "ON task.project = project.uuid "
            "LEFT JOIN TMArea as area "
            "ON task.area = area.uuid OR project.area = area.uuid "
            "WHERE task.uuid = '%@' "
            "AND area.uuid IS NOT NULL "
            "ORDER BY area.title;", uuid];

  NSArray *results = [SQLHelper executeSql:query onFile:path];
  NSMutableArray *objects = [NSMutableArray array];
  if (results) {
    [results enumerateObjectsUsingBlock:^(NSDictionary *dictionary, NSUInteger i, BOOL *stop) {
      [objects addObject:[ObjectHelper areaFromSQLResult:dictionary usingPath:path ]];
    }];
  }
  
  return objects;
}

- (NSArray *)tasksForTaskIdentifiedBy:(NSString *)uuid usingDatabaseAt:(NSString *)path {
  NSString *query = [NSString stringWithFormat: @"SELECT "
            "uuid, "
            "creationDate, "
            "status, "
            "title, "
            "notes, "
            "area "
            "FROM TMTask "
            "WHERE project = '%@' "
            "AND type = 0 "
            "AND trashed = 0 "
            "AND status = 0 "
            "ORDER BY title;", uuid];
  
  NSArray *results = [SQLHelper executeSql:query onFile:path];
  NSMutableArray *objects = [NSMutableArray array];
  [results enumerateObjectsUsingBlock:^(NSDictionary *dictionary, NSUInteger i, BOOL *stop) {
    [objects addObject:[ObjectHelper taskFromSQLResult:dictionary usingPath:path ]];
  }];
  
  return objects;
}

- (NSArray *)tasksInHeadingsForTaskIdentifiedBy:(NSString *)uuid usingDatabaseAt:(NSString *)path {
  NSString *query = [NSString stringWithFormat: @"SELECT "
            "task.uuid as uuid, "
            "task.creationDate as creationDate, "
            "task.status as status, "
            "task.title as title, "
            "task.notes as notes, "
            "task.area as area "
            "FROM TMTask AS heading "
            "LEFT JOIN TMTask AS task "
            "ON task.heading = heading.uuid "
            "WHERE heading.project = '%@' "
            "AND task.type = 0 "
            "AND task.trashed = 0 "
            "AND task.status = 0 "
            "ORDER BY task.title;", uuid];
  
  NSArray *results = [SQLHelper executeSql:query onFile:path];
  NSMutableArray *objects = [NSMutableArray array];
  [results enumerateObjectsUsingBlock:^(NSDictionary *dictionary, NSUInteger i, BOOL *stop) {
    [objects addObject:[ObjectHelper taskFromSQLResult:dictionary usingPath:path ]];
  }];
  
  return objects;
}

@end

NS_ASSUME_NONNULL_END