source: trunk/macosx/MessageWindowController.m @ 3923

Last change on this file since 3923 was 3923, checked in by livings124, 15 years ago

get rid of an unnecessary width check

  • Property svn:keywords set to Date Rev Author Id
File size: 11.1 KB
Line 
1/******************************************************************************
2 * $Id: MessageWindowController.m 3923 2007-11-21 20:22:04Z livings124 $
3 *
4 * Copyright (c) 2006-2007 Transmission authors and contributors
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 *****************************************************************************/
24
25#import "MessageWindowController.h"
26#import <transmission.h>
27
28#define LEVEL_ERROR 0
29#define LEVEL_INFO  1
30#define LEVEL_DEBUG 2
31
32#define UPDATE_SECONDS  0.6
33#define MAX_MESSAGES    4000
34
35@interface MessageWindowController (Private)
36
37- (void) resizeColumn;
38- (NSString *) stringForMessage: (NSDictionary *) message;
39
40@end
41
42@implementation MessageWindowController
43
44- (id) init
45{
46    if ((self = [super initWithWindowNibName: @"MessageWindow"]))
47    {
48        fMessages = [[NSMutableArray alloc] init];
49       
50        fTimer = [NSTimer scheduledTimerWithTimeInterval: UPDATE_SECONDS target: self
51                    selector: @selector(updateLog:) userInfo: nil repeats: YES];
52       
53        tr_setMessageLevel([[NSUserDefaults standardUserDefaults] integerForKey: @"MessageLevel"]);
54        tr_setMessageQueuing(1);
55    }
56    return self;
57}
58
59- (void) dealloc
60{
61    [fTimer invalidate];
62    [fMessages release];
63   
64    [fAttributes release];
65   
66    [super dealloc];
67}
68
69- (void) awakeFromNib
70{
71    NSWindow * window = [self window];
72    [window setFrameAutosaveName: @"MessageWindowFrame"];
73    [window setFrameUsingName: @"MessageWindowFrame"];
74   
75    [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(resizeColumn)
76                    name: @"NSTableViewColumnDidResizeNotification" object: fMessageTable];
77   
78    //initially sort peer table by IP
79    if ([[fMessageTable sortDescriptors] count] == 0)
80    {
81        [fMessageTable setSortDescriptors: [NSArray arrayWithObject: [[fMessageTable tableColumnWithIdentifier: @"Date"]
82                                            sortDescriptorPrototype]]];
83        [self updateLog: nil];
84    }
85   
86    fErrorImage = [NSImage imageNamed: @"RedDot.png"];
87    fInfoImage = [NSImage imageNamed: @"YellowDot.png"];
88    fDebugImage = [NSImage imageNamed: @"PurpleDot.png"];
89   
90    //set images to popup button items
91    [[fLevelButton itemAtIndex: LEVEL_ERROR] setImage: fErrorImage];
92    [[fLevelButton itemAtIndex: LEVEL_INFO] setImage: fInfoImage];
93    [[fLevelButton itemAtIndex: LEVEL_DEBUG] setImage: fDebugImage];
94   
95    //select proper level in popup button
96    int level = tr_getMessageLevel();
97    switch (level)
98    {
99        case TR_MSG_ERR:
100            [fLevelButton selectItemAtIndex: LEVEL_ERROR];
101            break;
102        case TR_MSG_INF:
103            [fLevelButton selectItemAtIndex: LEVEL_INFO];
104            break;
105        case TR_MSG_DBG:
106            [fLevelButton selectItemAtIndex: LEVEL_DEBUG];
107    }
108}
109
110- (void) updateLog: (NSTimer *) timer
111{
112    tr_msg_list * messages, * currentMessage;
113    if ((messages = tr_getQueuedMessages()) == NULL)
114        return;
115   
116    for (currentMessage = messages; currentMessage != NULL; currentMessage = currentMessage->next)
117        [fMessages addObject: [NSDictionary dictionaryWithObjectsAndKeys:
118                                [NSString stringWithUTF8String: currentMessage->message], @"Message",
119                                [NSDate dateWithTimeIntervalSince1970: currentMessage->when], @"Date",
120                                [NSNumber numberWithInt: currentMessage->level], @"Level", nil]];
121   
122    tr_freeMessageList(messages);
123   
124    int total = [fMessages count];
125    if (total > MAX_MESSAGES)
126    {
127        //remove the oldest
128        NSSortDescriptor * descriptor = [[[NSSortDescriptor alloc] initWithKey: @"Date" ascending: YES] autorelease];
129        NSArray * descriptors = [[NSArray alloc] initWithObjects: descriptor, nil];
130        [fMessages sortUsingDescriptors: descriptors];
131        [descriptors release];
132       
133        [fMessages removeObjectsInRange: NSMakeRange(0, total-MAX_MESSAGES)];
134       
135        [fMessageTable noteHeightOfRowsWithIndexesChanged: [NSIndexSet indexSetWithIndexesInRange: NSMakeRange(0, MAX_MESSAGES)]];
136    }
137   
138    [fMessages sortUsingDescriptors: [fMessageTable sortDescriptors]];
139   
140    [fMessageTable reloadData];
141}
142
143- (int) numberOfRowsInTableView: (NSTableView *) tableView
144{
145    return [fMessages count];
146}
147
148- (id) tableView: (NSTableView *) tableView objectValueForTableColumn: (NSTableColumn *) column row: (int) row
149{
150    NSString * ident = [column identifier];
151    NSDictionary * message = [fMessages objectAtIndex: row];
152
153    if ([ident isEqualToString: @"Date"])
154        return [message objectForKey: @"Date"];
155    else if ([ident isEqualToString: @"Level"])
156    {
157        switch ([[message objectForKey: @"Level"] intValue])
158        {
159            case TR_MSG_ERR:
160                return fErrorImage;
161            case TR_MSG_INF:
162                return fInfoImage;
163            case TR_MSG_DBG:
164                return fDebugImage;
165            default:
166                return nil;
167        }
168    }
169    else
170        return [message objectForKey: @"Message"];
171}
172
173#warning don't cut off end
174- (float) tableView: (NSTableView *) tableView heightOfRow: (int) row
175{
176    NSTableColumn * column = [tableView tableColumnWithIdentifier: @"Message"];
177   
178    if (!fAttributes)
179        fAttributes = [[[[column dataCell] attributedStringValue] attributesAtIndex: 0 effectiveRange: NULL] retain];
180   
181    int count = [[[fMessages objectAtIndex: row] objectForKey: @"Message"] sizeWithAttributes: fAttributes].width / [column width];
182    return [tableView rowHeight] * (float)(count+1);
183}
184
185- (void) tableView: (NSTableView *) tableView sortDescriptorsDidChange: (NSArray *) oldDescriptors
186{
187    [fMessages sortUsingDescriptors: [fMessageTable sortDescriptors]];
188    [fMessageTable reloadData];
189}
190
191- (void) copy: (id) sender
192{
193    NSPasteboard * pb = [NSPasteboard generalPasteboard];
194    [pb declareTypes: [NSArray arrayWithObject: NSStringPboardType] owner: self];
195   
196    NSIndexSet * indexes = [fMessageTable selectedRowIndexes];
197    NSMutableArray * messageStrings = [NSMutableArray arrayWithCapacity: [indexes count]];
198   
199    NSEnumerator * enumerator = [[fMessages objectsAtIndexes: indexes] objectEnumerator];
200    NSDictionary * message;
201    while ((message = [enumerator nextObject]))
202        [messageStrings addObject: [self stringForMessage: message]];
203   
204    [pb setString: [messageStrings componentsJoinedByString: @"\n"] forType: NSStringPboardType];
205}
206
207- (BOOL) validateMenuItem: (NSMenuItem *) menuItem
208{
209    SEL action = [menuItem action];
210   
211    if (action == @selector(copy:))
212        return [fMessageTable numberOfSelectedRows] > 0;
213   
214    return YES;
215}
216
217- (void) changeLevel: (id) sender
218{
219    [self updateLog: nil];
220   
221    int level;
222    switch ([fLevelButton indexOfSelectedItem])
223    {
224        case LEVEL_ERROR:
225            level = TR_MSG_ERR;
226            break;
227        case LEVEL_INFO:
228            level = TR_MSG_INF;
229            break;
230        case LEVEL_DEBUG:
231            level = TR_MSG_DBG;
232            break;
233    }
234   
235    tr_setMessageLevel(level);
236    [[NSUserDefaults standardUserDefaults] setInteger: level forKey: @"MessageLevel"];
237}
238
239- (void) clearLog: (id) sender
240{
241    [fMessages removeAllObjects];
242    [fMessageTable reloadData];
243}
244
245- (void) writeToFile: (id) sender
246{
247    //make the array sorted by date
248    NSSortDescriptor * descriptor = [[[NSSortDescriptor alloc] initWithKey: @"Date" ascending: YES] autorelease];
249    NSArray * descriptors = [[NSArray alloc] initWithObjects: descriptor, nil];
250    NSArray * sortedMessages = [fMessages sortedArrayUsingDescriptors: descriptors];
251    [descriptors release];
252   
253    //create the text to output
254    NSMutableArray * messageStrings = [NSMutableArray arrayWithCapacity: [fMessages count]];
255    NSEnumerator * enumerator = [sortedMessages objectEnumerator];
256    NSDictionary * message;
257    while ((message = [enumerator nextObject]))
258        [messageStrings addObject: [self stringForMessage: message]];
259   
260    NSString * fileString = [[messageStrings componentsJoinedByString: @"\n"] retain];
261   
262    NSSavePanel * panel = [NSSavePanel savePanel];
263    [panel setRequiredFileType: @"txt"];
264    [panel setCanSelectHiddenExtension: YES];
265   
266    [panel beginSheetForDirectory: nil file: NSLocalizedString(@"untitled", "Save log panel -> default file name")
267            modalForWindow: [self window] modalDelegate: self
268            didEndSelector: @selector(writeToFileSheetClosed:returnCode:contextInfo:) contextInfo: fileString];
269}
270
271- (void) writeToFileSheetClosed: (NSSavePanel *) panel returnCode: (int) code contextInfo: (NSString *) string
272{
273    if (code == NSOKButton)
274    {
275        if (![string writeToFile: [panel filename] atomically: YES encoding: NSUTF8StringEncoding error: nil])
276        {
277            NSAlert * alert = [[NSAlert alloc] init];
278            [alert addButtonWithTitle: NSLocalizedString(@"OK", "Save log alert panel -> button")];
279            [alert setMessageText: [NSString stringWithFormat: NSLocalizedString(@"Log Could Not Be Saved",
280                                    "Save log alert panel -> title")]];
281            [alert setInformativeText: [NSString stringWithFormat:
282                    NSLocalizedString(@"There was a problem creating the file \"%@\".",
283                                        "Save log alert panel -> message"), [[panel filename] lastPathComponent]]];
284            [alert setAlertStyle: NSWarningAlertStyle];
285           
286            [alert runModal];
287            [alert release];
288        }
289    }
290   
291    [string release];
292}
293
294@end
295
296@implementation MessageWindowController (Private)
297
298- (void) resizeColumn
299{
300    [fMessageTable noteHeightOfRowsWithIndexesChanged: [NSIndexSet indexSetWithIndexesInRange:
301                    NSMakeRange(0, [fMessageTable numberOfRows])]];
302}
303
304- (NSString *) stringForMessage: (NSDictionary *) message
305{
306    NSString * level;
307    switch ([[message objectForKey: @"Level"] intValue])
308    {
309        case TR_MSG_ERR:
310            level = @"Error";
311            break;
312        case TR_MSG_INF:
313            level = @"Info";
314            break;
315        case TR_MSG_DBG:
316            level = @"Debug";
317            break;
318        default:
319            level = @"";
320    }
321   
322    return [NSString stringWithFormat: @"%@ [%@] %@", [message objectForKey: @"Date"], level, [message objectForKey: @"Message"]];
323}
324
325@end
Note: See TracBrowser for help on using the repository browser.