root/trunk/Controllers/JVTranscriptCriterionController.m

Revision 3718, 18.1 kB (checked in by rinoa, 1 year ago)

Fixes strings that were supposed to be localized. Adding patch submitted in #1084 by redgecko.

  • Property svn:executable set to *
Line 
1 // Concept by Joar Wingfors.
2 // Created by Timothy Hatcher for Colloquy.
3 // Copyright Joar Wingfors and Timothy Hatcher. All rights reserved.
4
5 #import "JVTranscriptCriterionController.h"
6 #import "JVChatMessage.h"
7 #import "JVDirectChatPanel.h"
8 #import "JVChatRoomPanel.h"
9
10 @implementation JVTranscriptCriterionController
11 + (id) controller {
12         return [[[self alloc] init] autorelease];
13 }
14
15 #pragma mark -
16
17 - (id) init {
18         if( ( self = [super init] ) ) {
19                 _query = @"";
20                 _changed = NO;
21                 _smartTranscriptCriterion = NO;
22                 [self setKind:JVTranscriptMessageBodyCriterionKind];
23                 [self setOperation:JVTranscriptTextContainsCriterionOperation];
24                 [self setQueryUnits:JVTranscriptNoCriterionQueryUnits];
25         }
26
27         return self;
28 }
29
30 - (id) initWithCoder:(NSCoder *) coder {
31         if( [coder allowsKeyedCoding] ) {
32                 self = [self init];
33                 [self setKind:[coder decodeIntForKey:@"kind"]];
34                 [self setQuery:[coder decodeObjectForKey:@"query"]];
35                 [self setOperation:[coder decodeIntForKey:@"operation"]];
36                 [self setQueryUnits:[coder decodeIntForKey:@"queryUnits"]];
37                 [self setUsesSmartTranscriptCriterion:[coder decodeBoolForKey:@"smartTranscriptCriterion"]];
38                 return self;
39         } else [NSException raise:NSInvalidArchiveOperationException format:@"Only supports NSKeyedArchiver coders"];
40         return nil;
41 }
42
43 - (void) encodeWithCoder:(NSCoder *) coder {
44         if( [coder allowsKeyedCoding] ) {
45                 [coder encodeInt:[self kind] forKey:@"kind"];
46                 [coder encodeObject:[self query] forKey:@"query"];
47                 [coder encodeInt:[self operation] forKey:@"operation"];
48                 [coder encodeInt:[self queryUnits] forKey:@"queryUnits"];
49                 [coder encodeBool:[self usesSmartTranscriptCriterion] forKey:@"smartTranscriptCriterion"];
50         } else [NSException raise:NSInvalidArchiveOperationException format:@"Only supports NSKeyedArchiver coders"];
51 }
52
53 - (id) copyWithZone:(NSZone *) zone {
54         JVTranscriptCriterionController *ret = [[JVTranscriptCriterionController alloc] init];
55         [ret setKind:[self kind]];
56         [ret setQuery:[self query]];
57         [ret setOperation:[self operation]];
58         [ret setQueryUnits:[self queryUnits]];
59         [ret setUsesSmartTranscriptCriterion:[self usesSmartTranscriptCriterion]];
60         return ret;
61 }
62
63 - (id) mutableCopyWithZone:(NSZone *) zone {
64         return [self copyWithZone:zone];
65 }
66
67 - (void) dealloc {
68         [subview release];
69         [kindMenu release];
70         [expandedKindMenu release];
71         [_query release];
72
73         subview = nil;
74         kindMenu = nil;
75         expandedKindMenu = nil;
76         _query = nil;
77
78         [super dealloc];
79 }
80
81 #pragma mark -
82
83 - (void) awakeFromNib {
84         [tabView selectTabViewItemWithIdentifier:[NSString stringWithFormat:@"%d", [self format]]];
85
86         if( [self usesSmartTranscriptCriterion] ) {
87                 [textKindButton setMenu:expandedKindMenu];
88                 [dateKindButton setMenu:expandedKindMenu];
89                 [booleanKindButton setMenu:expandedKindMenu];
90                 [listKindButton setMenu:expandedKindMenu];
91         }
92
93         if( [self format] == JVTranscriptTextCriterionFormat ) {
94                 [textKindButton selectItemAtIndex:[textKindButton indexOfItemWithTag:[self kind]]];
95                 [textOperationButton selectItemAtIndex:[textOperationButton indexOfItemWithTag:[self operation]]];
96                 [textQuery setObjectValue:[self query]];
97         } else if( [self format] == JVTranscriptDateCriterionFormat ) {
98                 [dateKindButton selectItemAtIndex:[dateKindButton indexOfItemWithTag:[self kind]]];
99                 [dateOperationButton selectItemAtIndex:[dateOperationButton indexOfItemWithTag:[self operation]]];
100                 [dateQuery setObjectValue:[self query]];
101                 [dateUnitsButton selectItemAtIndex:[dateUnitsButton indexOfItemWithTag:[self queryUnits]]];
102         } else if( [self format] == JVTranscriptBooleanCriterionFormat ) {
103                 [booleanKindButton selectItemAtIndex:[booleanKindButton indexOfItemWithTag:[self kind]]];
104         } else if( [self format] == JVTranscriptListCriterionFormat ) {
105                 [listKindButton selectItemAtIndex:[listKindButton indexOfItemWithTag:[self kind]]];
106                 [listOperationButton selectItemAtIndex:[listOperationButton indexOfItemWithTag:[self operation]]];
107                 int index = [listQuery indexOfItemWithRepresentedObject:[self query]];
108                 if( index == -1 && [[self query] isKindOfClass:[NSNumber class]] )
109                         index = [listQuery indexOfItemWithTag:[(NSNumber *)[self query] intValue]];
110                 [listQuery selectItemAtIndex:index];
111         }
112 }
113
114 #pragma mark -
115
116 - (NSView *) view {
117         if( ! subview ) [NSBundle loadNibNamed:@"JVTranscriptCriterion" owner:self];
118         return subview;
119 }
120
121 #pragma mark -
122
123 - (JVTranscriptCriterionFormat) format {
124         return _format;
125 }
126
127 - (void) setFormat:(JVTranscriptCriterionFormat) format {
128         if( format != _format ) {
129                 _format = format;
130
131                 [tabView selectTabViewItemWithIdentifier:[NSString stringWithFormat:@"%d", format]];
132
133                 if( [self format] == JVTranscriptTextCriterionFormat ) {
134                         [textKindButton selectItemAtIndex:[textKindButton indexOfItemWithTag:[self kind]]];
135                 } else if( [self format] == JVTranscriptDateCriterionFormat ) {
136                         [dateKindButton selectItemAtIndex:[dateKindButton indexOfItemWithTag:[self kind]]];
137                 } else if( [self format] == JVTranscriptBooleanCriterionFormat ) {
138                         [booleanKindButton selectItemAtIndex:[booleanKindButton indexOfItemWithTag:[self kind]]];
139                 } else if( [self format] == JVTranscriptListCriterionFormat ) {
140                         [listKindButton selectItemAtIndex:[listKindButton indexOfItemWithTag:[self kind]]];
141                 }
142         }
143 }
144
145 #pragma mark -
146
147 - (JVTranscriptCriterionKind) kind {
148         return _kind;
149 }
150
151 - (void) setKind:(JVTranscriptCriterionKind) kind {
152         if( kind != _kind ) {
153                 _kind = kind;
154
155                 switch( kind ) {
156                 case JVTranscriptSenderNameCriterionKind:
157                 case JVTranscriptMessageBodyCriterionKind:
158                 case JVTranscriptSourceNameCriterionKind:
159                 case JVTranscriptSourceServerAddressCriterionKind:
160                         [self setFormat:JVTranscriptTextCriterionFormat];
161                         break;
162                 case JVTranscriptDateReceivedCriterionKind:
163                         [self setFormat:JVTranscriptDateCriterionFormat];
164                         break;
165                 default:
166                 case JVTranscriptSenderInBuddyListCriterionKind:
167                 case JVTranscriptSenderNotInBuddyListCriterionKind:
168                 case JVTranscriptSenderIgnoredCriterionKind:
169                 case JVTranscriptSenderNotIgnoredCriterionKind:
170                 case JVTranscriptMessageIgnoredCriterionKind:
171                 case JVTranscriptMessageNotIgnoredCriterionKind:
172                 case JVTranscriptMessageAddressedToMeCriterionKind:
173                 case JVTranscriptMessageNotAddressedToMeCriterionKind:
174                 case JVTranscriptMessageFromMeCriterionKind:
175                 case JVTranscriptMessageNotFromMeCriterionKind:
176                 case JVTranscriptMessageHighlightedCriterionKind:
177                 case JVTranscriptMessageNotHighlightedCriterionKind:
178                 case JVTranscriptMessageIsActionCriterionKind:
179                 case JVTranscriptMessageIsNotActionCriterionKind:
180                 case JVTranscriptSourceIsChatRoomCriterionKind:
181                 case JVTranscriptSourceIsNotChatRoomCriterionKind:
182                 case JVTranscriptSourceIsPrivateChatCriterionKind:
183                 case JVTranscriptSourceIsNotPrivateChatCriterionKind:
184                 case JVTranscriptEveryMessageCriterionKind:
185                         [self setFormat:JVTranscriptBooleanCriterionFormat];
186                 }
187         }
188 }
189
190 #pragma mark -
191
192 - (IBAction) selectCriterionKind:(id) sender {
193         _changed = YES;
194         [self setKind:[[sender selectedItem] tag]];
195
196         if( [self format] == JVTranscriptTextCriterionFormat ) {
197                 [self setOperation:JVTranscriptTextContainsCriterionOperation];
198                 [self setQueryUnits:JVTranscriptNoCriterionQueryUnits];
199         } else if( [self format] == JVTranscriptDateCriterionFormat ) {
200                 [self setOperation:JVTranscriptIsLessThanCriterionOperation];
201                 [self setQueryUnits:JVTranscriptMinuteCriterionQueryUnits];
202         } else if( [self format] == JVTranscriptBooleanCriterionFormat ) {
203                 [self setOperation:JVTranscriptNoCriterionOperation];
204                 [self setQueryUnits:JVTranscriptNoCriterionQueryUnits];
205         } else if( [self format] == JVTranscriptListCriterionFormat ) {
206                 [self setOperation:JVTranscriptIsEqualCriterionOperation];
207                 [self setQueryUnits:JVTranscriptNoCriterionQueryUnits];
208         }
209 }
210
211 - (IBAction) selectCriterionOperation:(id) sender {
212         _changed = YES;
213         [self setOperation:[[sender selectedItem] tag]];
214 }
215
216 - (IBAction) selectCriterionQueryUnits:(id) sender {
217         _changed = YES;
218         [self setQueryUnits:[[sender selectedItem] tag]];
219 }
220
221 - (IBAction) changeQuery:(id) sender {
222         _changed = YES;
223         if( [self format] == JVTranscriptTextCriterionFormat ) {
224                 [self setQuery:[textQuery stringValue]];
225         } else if( [self format] == JVTranscriptDateCriterionFormat ) {
226                 [self setQuery:[NSNumber numberWithDouble:[dateQuery doubleValue]]];
227         } else if( [self format] == JVTranscriptListCriterionFormat ) {
228                 NSMenuItem *mitem = [listQuery selectedItem];
229                 if( [mitem representedObject] ) [self setQuery:[mitem representedObject]];
230                 else [self setQuery:[NSNumber numberWithInt:[mitem tag]]];
231         }
232 }
233
234 - (void) controlTextDidChange:(NSNotification *) notification {
235         _changed = YES;
236 }
237
238 - (IBAction) noteOtherChanges:(id) sender {
239         _changed = YES;
240 }
241
242 #pragma mark -
243
244 - (BOOL) changedSinceLastMatch {
245         return _changed;
246 }
247
248 - (BOOL) matchMessage:(JVChatMessage *) message fromChatView:(id <JVChatViewController>) chatView ignoringCase:(BOOL) ignoreCase {
249         _changed = NO;
250         if( [self format] == JVTranscriptTextCriterionFormat ) {
251                 NSString *value = nil;
252                 if( [self kind] == JVTranscriptSenderNameCriterionKind ) value = [message senderName];
253                 else if( [self kind] == JVTranscriptMessageBodyCriterionKind ) value = [message bodyAsPlainText];
254                 else if( [self kind] == JVTranscriptSourceNameCriterionKind ) value = [chatView title];
255                 else if( [self kind] == JVTranscriptSourceServerAddressCriterionKind ) value = [[chatView connection] server];
256
257                 BOOL match = NO;
258                 JVTranscriptCriterionOperation oper = [self operation];
259                 if( oper == JVTranscriptTextMatchCriterionOperation || oper == JVTranscriptTextDoesNotMatchCriterionOperation ) {
260                         AGRegex *regex = [AGRegex regexWithPattern:[self query] options:( ignoreCase ? AGRegexCaseInsensitive : 0 )];
261                         AGRegexMatch *result = [regex findInString:value];
262                         if( result ) match = YES;
263                         if( oper == JVTranscriptTextDoesNotMatchCriterionOperation ) match = ! match;
264                 } else if( oper >= 3 && oper <= 6 ) {
265                         unsigned int options = ( ignoreCase ? NSCaseInsensitiveSearch : 0 );
266                         if( oper == JVTranscriptTextBeginsWithCriterionOperation ) options = NSAnchoredSearch;
267                         else if( oper == JVTranscriptTextEndsWithCriterionOperation ) options = ( NSAnchoredSearch | NSBackwardsSearch );
268                         NSRange range = [value rangeOfString:[self query] options:options];
269                         match = ( range.location != NSNotFound );
270                         if( oper == JVTranscriptTextDoesNotContainCriterionOperation ) match = ! match;
271                 } else if( oper == JVTranscriptIsEqualCriterionOperation ) {
272                         if( ! ignoreCase ) match = [value isEqualToString:[self query]];
273                         else match = ! [value caseInsensitiveCompare:[self query]];
274                 }
275
276                 return match;
277         } else if( [self kind] == JVTranscriptDateReceivedCriterionKind ) {
278                 double diff = ABS( [[message date] timeIntervalSinceNow] );
279                 double comp = [[self query] doubleValue];
280                 JVTranscriptCriterionOperation oper = [self operation];
281                 JVTranscriptCriterionQueryUnits unit = [self queryUnits];
282
283                 switch( unit ) {
284                         case JVTranscriptMonthCriterionQueryUnits: comp *= 4.;
285                         case JVTranscriptWeekCriterionQueryUnits: comp *= 7.;
286                         case JVTranscriptDayCriterionQueryUnits: comp *= 24.;
287                         case JVTranscriptHourCriterionQueryUnits: comp *= 60.;
288                         case JVTranscriptMinuteCriterionQueryUnits: comp *= 60.;
289                         default: comp = comp; // no change
290                 }
291
292                 if( oper == JVTranscriptIsLessThanCriterionOperation ) return ( diff < comp );
293                 else return ( diff > comp );
294         } else {
295                 switch( [self kind] ) {
296                 default:
297                         return NO;
298                 case JVTranscriptSenderInBuddyListCriterionKind:
299                 case JVTranscriptSenderNotInBuddyListCriterionKind:
300                         return NO;
301                 case JVTranscriptSenderIgnoredCriterionKind:
302                         return ( [message ignoreStatus] == JVUserIgnored );
303                 case JVTranscriptSenderNotIgnoredCriterionKind:
304                         return ( [message ignoreStatus] != JVUserIgnored );
305                 case JVTranscriptMessageIgnoredCriterionKind:
306                         return ( [message ignoreStatus] == JVMessageIgnored );
307                 case JVTranscriptMessageNotIgnoredCriterionKind:
308                         return ( [message ignoreStatus] != JVMessageIgnored );
309                 case JVTranscriptMessageFromMeCriterionKind:
310                         return [message senderIsLocalUser];
311                 case JVTranscriptMessageNotFromMeCriterionKind:
312                         return ( ! [message senderIsLocalUser] );
313                 case JVTranscriptMessageAddressedToMeCriterionKind:
314                 case JVTranscriptMessageNotAddressedToMeCriterionKind: {
315                         if( ! chatView || ! [chatView connection] ) return NO;
316                         AGRegex *regex = [AGRegex regexWithPattern:[NSString stringWithFormat:@"^%@[:;,-]", [[[chatView connection] localUser] nickname]] options:( ignoreCase ? AGRegexCaseInsensitive : 0 )];
317                         AGRegexMatch *match = [regex findInString:[message bodyAsPlainText]];
318                         if( [match count] && [self kind] == JVTranscriptMessageAddressedToMeCriterionKind ) return YES;
319                         else if( ! [match count] && [self kind] == JVTranscriptMessageNotAddressedToMeCriterionKind ) return YES;
320                         return NO; }
321                 case JVTranscriptMessageHighlightedCriterionKind:
322                         return [message isHighlighted];
323                 case JVTranscriptMessageNotHighlightedCriterionKind:
324                         return ( ! [message isHighlighted] );
325                 case JVTranscriptMessageIsActionCriterionKind:
326                         return [message isAction];
327                 case JVTranscriptMessageIsNotActionCriterionKind:
328                         return ( ! [message isAction] );
329                 case JVTranscriptSourceIsChatRoomCriterionKind:
330                         if( ! chatView ) return NO;
331                         return [chatView isMemberOfClass:[JVChatRoomPanel class]];
332                 case JVTranscriptSourceIsNotChatRoomCriterionKind:
333                         if( ! chatView ) return NO;
334                         return ( ! [chatView isMemberOfClass:[JVChatRoomPanel class]] );
335                 case JVTranscriptSourceIsPrivateChatCriterionKind:
336                         if( ! chatView ) return NO;
337                         return [chatView isMemberOfClass:[JVDirectChatPanel class]];
338                 case JVTranscriptSourceIsNotPrivateChatCriterionKind:
339                         if( ! chatView ) return NO;
340                         return ( ! [chatView isMemberOfClass:[JVDirectChatPanel class]] );
341                 case JVTranscriptEveryMessageCriterionKind:
342                         return YES;
343                 }
344         }
345
346         return NO;
347 }
348
349 #pragma mark -
350
351 - (id) query {
352         return _query;
353 }
354
355 - (void) setQuery:(id) query {
356         [_query autorelease];
357         _query = [query retain];
358
359         if( [self format] == JVTranscriptTextCriterionFormat ) {
360                 [textQuery setObjectValue:query];
361         } else if( [self format] == JVTranscriptDateCriterionFormat ) {
362                 [dateQuery setObjectValue:query];
363         } else if( [self format] == JVTranscriptListCriterionFormat ) {
364                 int index = [listQuery indexOfItemWithRepresentedObject:query];
365                 if( index == -1 && [query isKindOfClass:[NSNumber class]] )
366                         index = [listQuery indexOfItemWithTag:[(NSNumber *)query intValue]];
367                 [listQuery selectItemAtIndex:index];
368         }
369 }
370
371 #pragma mark -
372
373 - (JVTranscriptCriterionOperation) operation {
374         return _operation;
375 }
376
377 - (void) setOperation:(JVTranscriptCriterionOperation) operation {
378         _operation = operation;
379
380         if( [self format] == JVTranscriptTextCriterionFormat ) {
381                 [textOperationButton selectItemAtIndex:[textOperationButton indexOfItemWithTag:[self operation]]];
382         } else if( [self format] == JVTranscriptDateCriterionFormat ) {
383                 [dateOperationButton selectItemAtIndex:[dateOperationButton indexOfItemWithTag:[self operation]]];
384         } else if( [self format] == JVTranscriptListCriterionFormat ) {
385                 [listOperationButton selectItemAtIndex:[listOperationButton indexOfItemWithTag:[self operation]]];
386         }
387 }
388
389 #pragma mark -
390
391 - (JVTranscriptCriterionQueryUnits) queryUnits {
392         return _queryUnits;
393 }
394
395 - (void) setQueryUnits:(JVTranscriptCriterionQueryUnits) units {
396         _queryUnits = units;
397
398         if( [self format] == JVTranscriptDateCriterionFormat ) {
399                 [dateUnitsButton selectItemAtIndex:[dateUnitsButton indexOfItemWithTag:[self queryUnits]]];
400         }
401 }
402
403 #pragma mark -
404
405 - (BOOL) usesSmartTranscriptCriterion {
406         return _smartTranscriptCriterion;
407 }
408
409 - (void) setUsesSmartTranscriptCriterion:(BOOL) use {
410         _smartTranscriptCriterion = use;
411
412         if( use ) {
413                 [textKindButton setMenu:expandedKindMenu];
414                 [dateKindButton setMenu:expandedKindMenu];
415                 [booleanKindButton setMenu:expandedKindMenu];
416                 [listKindButton setMenu:expandedKindMenu];
417         } else {
418                 [textKindButton setMenu:kindMenu];
419                 [dateKindButton setMenu:kindMenu];
420                 [booleanKindButton setMenu:kindMenu];
421                 [listKindButton setMenu:kindMenu];
422         }
423
424         if( [self format] == JVTranscriptTextCriterionFormat ) {
425                 [textKindButton selectItemAtIndex:[textKindButton indexOfItemWithTag:[self kind]]];
426         } else if( [self format] == JVTranscriptDateCriterionFormat ) {
427                 [dateKindButton selectItemAtIndex:[dateKindButton indexOfItemWithTag:[self kind]]];
428         } else if( [self format] == JVTranscriptBooleanCriterionFormat ) {
429                 [booleanKindButton selectItemAtIndex:[booleanKindButton indexOfItemWithTag:[self kind]]];
430         } else if( [self format] == JVTranscriptListCriterionFormat ) {
431                 [listKindButton selectItemAtIndex:[listKindButton indexOfItemWithTag:[self kind]]];
432         }
433 }
434
435 #pragma mark -
436
437 - (NSView *) firstKeyView {
438         if( [self format] == JVTranscriptTextCriterionFormat ) {
439                 return textKindButton;
440         } else if( [self format] == JVTranscriptDateCriterionFormat ) {
441                 return dateKindButton;
442         } else if( [self format] == JVTranscriptBooleanCriterionFormat ) {
443                 return booleanKindButton;
444         } else if( [self format] == JVTranscriptListCriterionFormat ) {
445                 return listKindButton;
446         } else return nil;
447 }
448
449 - (NSView *) lastKeyView {
450         if( [self format] == JVTranscriptTextCriterionFormat ) {
451                 return textQuery;
452         } else if( [self format] == JVTranscriptDateCriterionFormat ) {
453                 return dateUnitsButton;
454         } else if( [self format] == JVTranscriptBooleanCriterionFormat ) {
455                 return booleanKindButton;
456         } else if( [self format] == JVTranscriptListCriterionFormat ) {
457                 return listQuery;
458         } else return nil;
459 }
460
461 #pragma mark -
462
463 - (NSString *) description {
464         [self view];
465         if( [self format] == JVTranscriptTextCriterionFormat ) {
466                 return [NSString stringWithFormat:NSLocalizedString( @"%@ %@ \"%@\"", "description format for kind, operation and query, JVTranscriptCriterionController" ), [textKindButton titleOfSelectedItem], [textOperationButton titleOfSelectedItem], [self query]];
467         } else if( [self format] == JVTranscriptDateCriterionFormat ) {
468                 return [NSString stringWithFormat:NSLocalizedString( @"%@ %@ %@ %@", "description format for kind, operation, query and unit, JVTranscriptCriterionController" ), [dateKindButton titleOfSelectedItem], [dateOperationButton titleOfSelectedItem], [self query], [dateUnitsButton titleOfSelectedItem]];
469         } else if( [self format] == JVTranscriptBooleanCriterionFormat ) {
470                 return [booleanKindButton titleOfSelectedItem];
471         } else if( [self format] == JVTranscriptListCriterionFormat ) {
472                 return [NSString stringWithFormat:NSLocalizedString( @"%@ %@ %@", "description format for kind, operation and type, JVTranscriptCriterionController" ), [listKindButton titleOfSelectedItem], [listOperationButton titleOfSelectedItem], [listQuery titleOfSelectedItem]];
473         } else return [super description];
474 }
475 @end
Note: See TracBrowser for help on using the browser.