Don't enable the header control if there isn't a header or topic for regular or group chats respectively. Fixes #13791
2 * Adium is the legal property of its developers, whose names are listed in the copyright file included
3 * with this source distribution.
5 * This program is free software; you can redistribute it and/or modify it under the terms of the GNU
6 * General Public License as published by the Free Software Foundation; either version 2 of the License,
7 * or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
10 * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
11 * Public License for more details.
13 * You should have received a copy of the GNU General Public License along with this program; if not,
14 * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 #import "ESWebKitMessageViewPreferences.h"
18 #import "AIWebKitMessageViewPlugin.h"
19 #import "AIWebkitMessageViewStyle.h"
20 #import "AIWebKitPreviewMessageViewController.h"
21 #import "AIPreviewChat.h"
23 #import <Adium/AIAccountControllerProtocol.h>
24 #import <Adium/AIContactControllerProtocol.h>
25 #import <Adium/AIContentControllerProtocol.h>
26 #import <Adium/AIInterfaceControllerProtocol.h>
27 #import <Adium/AIAccount.h>
28 #import <Adium/AIChat.h>
29 #import <Adium/AIContentMessage.h>
30 #import <Adium/AIContentObject.h>
31 #import <Adium/AIContentEvent.h>
32 #import <Adium/AIListContact.h>
33 #import <Adium/AIHTMLDecoder.h>
34 #import <Adium/AIService.h>
35 #import <Adium/JVFontPreviewField.h>
36 #import <AIUtilities/AIAttributedStringAdditions.h>
37 #import <AIUtilities/AIColorAdditions.h>
38 #import <AIUtilities/AIFontAdditions.h>
39 #import <AIUtilities/AIMenuAdditions.h>
40 #import <AIUtilities/AIPopUpButtonAdditions.h>
41 #import <AIUtilities/AIBundleAdditions.h>
42 #import <AIUtilities/AIDateFormatterAdditions.h>
43 #import <AIUtilities/AIImageAdditions.h>
44 #import <AIUtilities/AIImageViewWithImagePicker.h>
46 #import "AIPreviewContentMessage.h"
48 #define WEBKIT_PREVIEW_CONVERSATION_FILE @"Preview"
49 #define PREF_GROUP_DISPLAYFORMAT @"Display Format" //To watch when the contact name display format changes
51 @interface ESWebKitMessageViewPreferences ()
52 - (void)configurePreferencesForTab;
53 - (void)_setBackgroundImage:(NSImage *)image;
54 - (NSMenu *)_stylesMenu;
55 - (NSMenu *)_variantsMenu;
56 - (NSMenu *)_backgroundImageTypeMenu;
57 - (void)_addBackgroundImageTypeChoice:(NSInteger)tag toMenu:(NSMenu *)menu withTitle:(NSString *)title;
58 - (void)_configureChatPreview;
59 - (AIChat *)previewChatWithDictionary:(NSDictionary *)previewDict fromPath:(NSString *)previewPath listObjects:(NSDictionary **)outListObjects;
60 - (void)_fillContentOfChat:(AIChat *)inChat withDictionary:(NSDictionary *)previewDict fromPath:(NSString *)previewPath listObjects:(NSDictionary *)listObjects;
61 - (NSMutableDictionary *)_addParticipants:(NSDictionary *)participants toChat:(AIChat *)inChat fromPath:(NSString *)previewPath;
62 - (void)_applySettings:(NSDictionary *)chatDict toChat:(AIPreviewChat *)inChat withParticipants:(NSDictionary *)participants;
63 - (void)_addContent:(NSArray *)chatArray toChat:(AIChat *)inChat withParticipants:(NSDictionary *)participants;
64 - (void)_setDisplayFontFace:(NSString *)face size:(NSNumber *)size;
69 @implementation ESWebKitMessageViewPreferences
71 - (NSString *)paneIdentifier
75 - (NSString *)paneName{
76 return AILocalizedString(@"Messages", "Title of the messages preferences");
78 - (NSString *)nibName{
79 return @"WebKitPreferencesView";
83 return [NSImage imageNamed:@"pref-messages"];
87 * @brief Configure the preference view
92 previewListObjectsDict = nil;
95 [popUp_backgroundImageType setMenu:[self _backgroundImageTypeMenu]];
96 [popUp_styles setMenu:[self _stylesMenu]];
99 [fontPreviewField_currentFont setShowFontFace:YES];
100 [fontPreviewField_currentFont setShowPointSize:YES];
102 //We want to be able to obtain bigger images than the image picker will feed us
103 [imageView_backgroundImage setUsePictureTaker:NO];
105 //Configure the chat preview
106 [self _configureChatPreview];
108 [tabView_messageType selectTabViewItem:tabViewItem_regularChat];
110 [self configurePreferencesForTab];
114 * @brief Close the preference view
116 - (void)viewWillClose
118 //Hide the alpha component
119 [[NSColorPanel sharedColorPanel] setShowsAlpha:NO];
121 [[NSNotificationCenter defaultCenter] removeObserver:self];
122 [previewListObjectsDict release]; previewListObjectsDict = nil;
124 [previewController release]; previewController = nil;
125 [view_previewLocation setFrame:[preview frame]];
126 [[preview superview] replaceSubview:preview with:view_previewLocation];
127 [preview release]; preview = nil;
128 //Matches the retain performed in -[ESWebKitMessageViewPreferences _configureChatPreview]
129 [view_previewLocation release];
134 - (void)messageStyleXtrasDidChange
137 NSDictionary *prefDict = [adium.preferenceController preferencesForGroup:self.preferenceGroupForCurrentTab];
139 [popUp_styles setMenu:[self _stylesMenu]];
140 [popUp_styles selectItemWithRepresentedObject:[prefDict objectForKey:KEY_WEBKIT_STYLE]];
144 //Preferences ----------------------------------------------------------------------------------------------------------
145 #pragma mark Preferences
146 - (AIWebkitStyleType)currentTab
148 if (tabView_messageType.selectedTabViewItem == tabViewItem_regularChat) {
149 return AIWebkitRegularChat;
151 return AIWebkitGroupChat;
155 - (NSString *)preferenceGroupForCurrentTab
157 NSString *prefGroup = nil;
159 switch(self.currentTab) {
160 case AIWebkitRegularChat:
161 prefGroup = PREF_GROUP_WEBKIT_REGULAR_MESSAGE_DISPLAY;
164 case AIWebkitGroupChat:
165 prefGroup = PREF_GROUP_WEBKIT_GROUP_MESSAGE_DISPLAY;
172 - (void)configurePreferencesForTab
174 //Configure our controls to represent the global preferences
176 NSDictionary *prefDict = [adium.preferenceController preferencesForGroup:self.preferenceGroupForCurrentTab];
178 [checkBox_showUserIcons setState:([[previewController messageStyle] allowsUserIcons] ?
179 [[prefDict objectForKey:KEY_WEBKIT_SHOW_USER_ICONS] boolValue] :
181 [checkBox_showHeader setState:[[prefDict objectForKey:KEY_WEBKIT_SHOW_HEADER] boolValue]];
182 [checkBox_showMessageColors setState:([[previewController messageStyle] allowsColors] ?
183 [[prefDict objectForKey:KEY_WEBKIT_SHOW_MESSAGE_COLORS] boolValue] :
185 [checkBox_showMessageFonts setState:[[prefDict objectForKey:KEY_WEBKIT_SHOW_MESSAGE_FONTS] boolValue]];
187 [checkBox_useRegularChatForGroup setState:[[adium.preferenceController preferenceForKey:KEY_WEBKIT_USE_REGULAR_PREFERENCES
188 group:self.preferenceGroupForCurrentTab] boolValue]];
190 //Allow the alpha component to be set for our background color
191 [[NSColorPanel sharedColorPanel] setShowsAlpha:YES];
193 [previewController setIsGroupChat:(self.currentTab == AIWebkitGroupChat)];
195 // The preview controller will send us a preferences changed message also.
196 [previewController preferencesChangedForGroup:self.preferenceGroupForCurrentTab
199 preferenceDict:[adium.preferenceController preferencesForGroup:self.preferenceGroupForCurrentTab]
203 - (void)tabView:(NSTabView *)tabView didSelectTabViewItem:(NSTabViewItem *)tabViewItem
205 [self configurePreferencesForTab];
209 * @brief Update our preference view to reflect changed preferences
211 - (void)preferencesChangedForGroup:(NSString *)group key:(NSString *)key object:(AIListObject *)object
212 preferenceDict:(NSDictionary *)prefDict firstTime:(BOOL)firstTime
214 if (!viewIsOpen) return;
216 if ([group isEqualToString:self.preferenceGroupForCurrentTab]) {
220 //Ensure our style/variant menus are showing the correct selection
221 style = [prefDict objectForKey:KEY_WEBKIT_STYLE];
222 if (!style || ![popUp_styles selectItemWithRepresentedObject:style]) {
223 style = [[plugin messageStyleBundleWithIdentifier:style] bundleIdentifier];
224 [popUp_styles selectItemWithRepresentedObject:style];
227 //When the active style changes, rebuild our variant menu for the new style
228 if (!key || [key isEqualToString:KEY_WEBKIT_STYLE]) {
229 [popUp_variants setMenu:[self _variantsMenu]];
232 variant = [prefDict objectForKey:[plugin styleSpecificKey:@"Variant" forStyle:style]];
233 if (!variant || ![popUp_variants selectItemWithRepresentedObject:variant]) {
234 variant = [AIWebkitMessageViewStyle defaultVariantForBundle:[plugin messageStyleBundleWithIdentifier:style]];
235 [popUp_variants selectItemWithRepresentedObject:variant];
238 [popUp_variants synchronizeTitleAndSelectedItem];
240 //Configure our style-specific controls to represent the current style
241 NSString *fontFamily = [prefDict objectForKey:[plugin styleSpecificKey:@"FontFamily" forStyle:style]];
242 if (!fontFamily) fontFamily = [[plugin messageStyleBundleWithIdentifier:style] objectForInfoDictionaryKey:KEY_WEBKIT_DEFAULT_FONT_FAMILY];
243 if (!fontFamily) fontFamily = [[NSFont systemFontOfSize:0] familyName];
245 NSNumber *fontSize = [prefDict objectForKey:[plugin styleSpecificKey:@"FontSize" forStyle:style]];
246 if (!fontSize) fontSize = [[plugin messageStyleBundleWithIdentifier:style] objectForInfoDictionaryKey:KEY_WEBKIT_DEFAULT_FONT_SIZE];
247 if (!fontSize) fontSize = [NSNumber numberWithInteger:[[NSFont systemFontOfSize:0] pointSize]];
249 NSFont *defaultFont = [NSFont cachedFontWithName:fontFamily size:[fontSize integerValue]];
250 [fontPreviewField_currentFont setFont:defaultFont];
252 //Style-specific background prefs
253 NSData *backgroundImage = [adium.preferenceController preferenceForKey:[plugin styleSpecificKey:@"Background" forStyle:style]
254 group:PREF_GROUP_WEBKIT_BACKGROUND_IMAGES];
255 if (backgroundImage) {
256 [imageView_backgroundImage setImage:[[[NSImage alloc] initWithData:backgroundImage] autorelease]];
258 [imageView_backgroundImage setImage:nil];
261 NSColor *backgroundColor = [[prefDict objectForKey:[plugin styleSpecificKey:@"BackgroundColor" forStyle:style]] representedColor];
262 [colorWell_customBackgroundColor setColor:(backgroundColor ? backgroundColor : [NSColor whiteColor])] ;
264 [checkBox_useCustomBackground setState:[[prefDict objectForKey:[plugin styleSpecificKey:@"UseCustomBackground" forStyle:style]] boolValue]];
265 [popUp_backgroundImageType selectItemWithTag:[[prefDict objectForKey:[plugin styleSpecificKey:@"BackgroundType" forStyle:style]] integerValue]];
267 [self configureControlDimming];
272 * @brief Save changed preferences
274 - (IBAction)changePreference:(id)sender
277 if (sender == checkBox_showUserIcons) {
278 [adium.preferenceController setPreference:[NSNumber numberWithBool:[sender state]]
279 forKey:KEY_WEBKIT_SHOW_USER_ICONS
280 group:self.preferenceGroupForCurrentTab];
282 } else if (sender == checkBox_showHeader) {
283 [adium.preferenceController setPreference:[NSNumber numberWithBool:[sender state]]
284 forKey:KEY_WEBKIT_SHOW_HEADER
285 group:self.preferenceGroupForCurrentTab];
287 } else if (sender == checkBox_showMessageColors) {
288 [adium.preferenceController setPreference:[NSNumber numberWithBool:[sender state]]
289 forKey:KEY_WEBKIT_SHOW_MESSAGE_COLORS
290 group:self.preferenceGroupForCurrentTab];
292 } else if (sender == checkBox_showMessageFonts) {
293 [adium.preferenceController setPreference:[NSNumber numberWithBool:[sender state]]
294 forKey:KEY_WEBKIT_SHOW_MESSAGE_FONTS
295 group:self.preferenceGroupForCurrentTab];
296 } else if (sender == checkBox_useCustomBackground) {
297 [adium.preferenceController setPreference:[NSNumber numberWithBool:[sender state]]
298 forKey:[plugin styleSpecificKey:@"UseCustomBackground"
299 forStyle:[[popUp_styles selectedItem] representedObject]]
300 group:self.preferenceGroupForCurrentTab];
301 } else if (sender == checkBox_useRegularChatForGroup) {
302 [adium.preferenceController setPreference:[NSNumber numberWithBool:[sender state]]
303 forKey:KEY_WEBKIT_USE_REGULAR_PREFERENCES
304 group:self.preferenceGroupForCurrentTab];
306 [self configurePreferencesForTab];
307 } else if (sender == colorWell_customBackgroundColor) {
308 [adium.preferenceController setPreference:[[colorWell_customBackgroundColor color] stringRepresentation]
309 forKey:[plugin styleSpecificKey:@"BackgroundColor"
310 forStyle:[[popUp_styles selectedItem] representedObject]]
311 group:self.preferenceGroupForCurrentTab];
313 } else if (sender == popUp_backgroundImageType) {
314 [adium.preferenceController setPreference:[NSNumber numberWithInteger:[[popUp_backgroundImageType selectedItem] tag]]
315 forKey:[plugin styleSpecificKey:@"BackgroundType"
316 forStyle:[[popUp_styles selectedItem] representedObject]]
317 group:self.preferenceGroupForCurrentTab];
319 } else if (sender == popUp_styles) {
320 [adium.preferenceController setPreference:[[sender selectedItem] representedObject]
321 forKey:KEY_WEBKIT_STYLE
322 group:self.preferenceGroupForCurrentTab];
324 } else if (sender == popUp_variants) {
325 NSString *activeStyle = [adium.preferenceController preferenceForKey:KEY_WEBKIT_STYLE
326 group:self.preferenceGroupForCurrentTab];
328 [adium.preferenceController setPreference:[[sender selectedItem] representedObject]
329 forKey:[plugin styleSpecificKey:@"Variant" forStyle:activeStyle]
330 group:self.preferenceGroupForCurrentTab];
333 [self configureControlDimming];
337 - (void)configureControlDimming
339 // Controls are enabled if we're the regular chat tab, or we're not using regular preferences.
340 BOOL anyControlsEnabled = (self.currentTab == AIWebkitRegularChat || ![[adium.preferenceController preferenceForKey:KEY_WEBKIT_USE_REGULAR_PREFERENCES
341 group:self.preferenceGroupForCurrentTab] boolValue]);
343 // General controls with no other qualifiers.
344 [popUp_styles setEnabled:anyControlsEnabled];
345 [fontPreviewField_currentFont setEnabled:anyControlsEnabled];
346 [checkBox_showMessageFonts setEnabled:anyControlsEnabled];
347 [checkBox_showMessageColors setEnabled:anyControlsEnabled];
348 [button_setFont setEnabled:anyControlsEnabled];
349 [button_defaultFont setEnabled:anyControlsEnabled];
351 //Only enable if there are multiple variant choices
352 [popUp_variants setEnabled:[popUp_variants numberOfItems] > 0 && anyControlsEnabled];
354 //Disable the custom background controls if the style doesn't support them
355 AIWebkitMessageViewStyle *messageStyle = [previewController messageStyle];
356 BOOL allowCustomBackground = [messageStyle allowsCustomBackground] && anyControlsEnabled;
357 [checkBox_useCustomBackground setEnabled:allowCustomBackground];
359 allowCustomBackground = allowCustomBackground && checkBox_useCustomBackground.state;
361 [colorWell_customBackgroundColor setEnabled:allowCustomBackground];
362 [popUp_backgroundImageType setEnabled:allowCustomBackground];
363 [imageView_backgroundImage setEnabled:allowCustomBackground];
365 //Disable the header control if this style doesn't have a header or topic
366 if (self.currentTab == AIWebkitGroupChat)
367 [checkBox_showHeader setEnabled:[messageStyle hasTopic] && anyControlsEnabled];
369 [checkBox_showHeader setEnabled:[messageStyle hasHeader] && anyControlsEnabled];
371 //Disable user icon toggling if the style doesn't support them
372 [checkBox_showUserIcons setEnabled:[messageStyle allowsUserIcons] && anyControlsEnabled];
374 [checkBox_showMessageColors setEnabled:[messageStyle allowsColors] && anyControlsEnabled];
378 * @brief Save changes to the font field
380 - (void)fontPreviewField:(JVFontPreviewField *)field didChangeToFont:(NSFont *)font
382 [self _setDisplayFontFace:[font fontName] size:[NSNumber numberWithInteger:[font pointSize]]];
385 - (IBAction)resetDisplayFontToDefault:(id)sender
387 [self _setDisplayFontFace:nil size:0];
391 * @brief Set the display font of the active style.
393 * @param face New font face, nil to remove custom font
394 * @param size New font size, nil to remove custom size
396 - (void)_setDisplayFontFace:(NSString *)face size:(NSNumber *)size
398 NSString *activeStyle = [adium.preferenceController preferenceForKey:KEY_WEBKIT_STYLE
399 group:self.preferenceGroupForCurrentTab];
401 [adium.preferenceController setPreference:face
402 forKey:[plugin styleSpecificKey:@"FontFamily" forStyle:activeStyle]
403 group:self.preferenceGroupForCurrentTab];
404 [adium.preferenceController setPreference:size
405 forKey:[plugin styleSpecificKey:@"FontSize" forStyle:activeStyle]
406 group:self.preferenceGroupForCurrentTab];
411 * @brief Save changes to the background image
413 - (void)imageViewWithImagePicker:(AIImageViewWithImagePicker *)picker didChangeToImage:(NSImage *)image
415 [self _setBackgroundImage:image];
419 * @brief Remove the background image
421 - (void)deleteInImageViewWithImagePicker:(AIImageViewWithImagePicker *)picker
423 [self _setBackgroundImage:nil];
427 * @brief Set the background image of the active style.
429 * @param image New background image, nil to remove background image
431 - (void)_setBackgroundImage:(NSImage *)image
433 NSString *style = [[popUp_styles selectedItem] representedObject];
435 /* Save the new image. We store the images in a separate preference group since they may get big.
436 * This will let loading other groups not be affected by its presence.
438 [adium.preferenceController setPreference:[image PNGRepresentation]
439 forKey:[plugin styleSpecificKey:@"Background" forStyle:style]
440 group:PREF_GROUP_WEBKIT_BACKGROUND_IMAGES];
444 * @brief Builds and returns a menu of available styles
446 - (NSMenu *)_stylesMenu
448 NSMenu *menu = [[NSMenu allocWithZone:[NSMenu menuZone]] initWithTitle:@""];
449 NSMutableArray *menuItemArray = [NSMutableArray array];
450 NSArray *availableStyles = [[plugin availableMessageStyles] allValues];
451 NSMenuItem *menuItem;
453 for (NSBundle *style in availableStyles) {
454 menuItem = [[NSMenuItem allocWithZone:[NSMenu menuZone]] initWithTitle:[style name]
458 [menuItem setRepresentedObject:[style bundleIdentifier]];
459 [menuItemArray addObject:menuItem];
463 [menuItemArray sortUsingSelector:@selector(titleCompare:)];
465 for (menuItem in menuItemArray) {
466 [menu addItem:menuItem];
469 return [menu autorelease];
473 * @brief Build & return a menu of variants for the passed style
475 - (NSMenu *)_variantsMenu
477 NSMenu *menu = [[NSMenu allocWithZone:[NSMenu menuZone]] initWithTitle:@""];
479 //Add a menu item for each variant
480 for (NSString *variant in previewController.messageStyle.availableVariants) {
481 [menu addItemWithTitle:variant
485 representedObject:variant];
488 return [menu autorelease];
492 * @brief Build & return a menu of choices for background display
494 - (NSMenu *)_backgroundImageTypeMenu
496 NSMenu *menu = [[NSMenu allocWithZone:[NSMenu menuZone]] init];
498 [self _addBackgroundImageTypeChoice:BackgroundNormal toMenu:menu withTitle:AILocalizedString(@"Normal","Background image display preference: The image will be displayed normally")];
499 [self _addBackgroundImageTypeChoice:BackgroundCenter toMenu:menu withTitle:AILocalizedString(@"Centered","Background image display preference: The image will be centered in the window")];
500 [self _addBackgroundImageTypeChoice:BackgroundTile toMenu:menu withTitle:AILocalizedString(@"Tiled","Background image display preference: The image will be tiled (repeated) in the window to fill available space")];
501 [self _addBackgroundImageTypeChoice:BackgroundTileCenter toMenu:menu withTitle:AILocalizedString(@"Tiled (Centered)","Background image display preference: The image will be tiled and centered in the window")];
502 [self _addBackgroundImageTypeChoice:BackgroundScale toMenu:menu withTitle:AILocalizedString(@"Scaled", "Background image display preference: The image will be increased or decreased in size to fit the window")];
504 return [menu autorelease];
506 - (void)_addBackgroundImageTypeChoice:(NSInteger)tag toMenu:(NSMenu *)menu withTitle:(NSString *)title
508 NSMenuItem *menuItem = [[NSMenuItem allocWithZone:[NSMenu menuZone]] initWithTitle:title
511 [menuItem setTag:tag];
512 [menu addItem:menuItem];
517 //Chat Preview ---------------------------------------------------------------------------------------------------------
518 #pragma mark Chat Preview
520 * @brief Configure our chat preview
522 - (void)_configureChatPreview
524 NSDictionary *previewDict;
525 NSString *previewFilePath;
526 NSString *previewPath;
529 //Create our fake chat and message controller for the live preview
530 previewFilePath = [[NSBundle bundleForClass:[self class]] pathForResource:WEBKIT_PREVIEW_CONVERSATION_FILE ofType:@"plist"];
531 previewDict = [[NSDictionary alloc] initWithContentsOfFile:previewFilePath];
532 previewPath = [previewFilePath stringByDeletingLastPathComponent];
534 NSDictionary *listObjects;
535 previewChat = [self previewChatWithDictionary:previewDict fromPath:previewPath listObjects:&listObjects];
536 previewController = [[AIWebKitPreviewMessageViewController messageDisplayControllerForChat:previewChat
537 withPlugin:plugin] retain];
539 //Enable live refreshing of our preview
540 [previewController setShouldReflectPreferenceChanges:YES];
541 [previewController setPreferencesChangedDelegate:self];
543 //Add fake users and content to our chat
544 [self _fillContentOfChat:previewChat withDictionary:previewDict fromPath:previewPath listObjects:listObjects];
545 [previewDict release];
547 //Place the preview chat in our view
548 preview = [[previewController messageView] retain];
549 [preview setFrame:[view_previewLocation frame]];
550 //Will be released in viewWillClose
551 [view_previewLocation retain];
552 [[view_previewLocation superview] replaceSubview:view_previewLocation with:preview];
554 //Disable drag and drop onto the preview chat - Jeff doesn't need your porn :)
555 if ([preview respondsToSelector:@selector(setAllowsDragAndDrop:)]) {
556 [(ESWebView *)preview setAllowsDragAndDrop:NO];
559 //Disable forwarding of events so the preferences responder chain works properly
560 if ([preview respondsToSelector:@selector(setShouldForwardEvents:)]) {
561 [(ESWebView *)preview setShouldForwardEvents:NO];
565 - (AIChat *)previewChatWithDictionary:(NSDictionary *)previewDict fromPath:(NSString *)previewPath listObjects:(NSDictionary **)outListObjects
567 AIPreviewChat *previewChat = [AIPreviewChat previewChat];
568 [previewChat setDisplayName:AILocalizedString(@"Sample Conversation", "Title for the sample conversation")];
570 //Process and create all participants
571 *outListObjects = [self _addParticipants:[previewDict objectForKey:@"Participants"]
572 toChat:previewChat fromPath:previewPath];
574 //Setup the chat, and its source/destination
575 [self _applySettings:[previewDict objectForKey:@"Chat"]
576 toChat:previewChat withParticipants:*outListObjects];
582 * @brief Fill the content of the specified chat using content archived in the dictionary
584 - (void)_fillContentOfChat:(AIChat *)inChat withDictionary:(NSDictionary *)previewDict fromPath:(NSString *)previewPath listObjects:(NSDictionary *)listObjects
586 //Add the archived chat content
587 [self _addContent:[previewDict objectForKey:@"Preview Messages"]
588 toChat:inChat withParticipants:listObjects];
592 * @brief Add participants
594 - (NSMutableDictionary *)_addParticipants:(NSDictionary *)participants toChat:(AIChat *)inChat fromPath:(NSString *)previewPath
596 NSMutableDictionary *listObjectDict = [NSMutableDictionary dictionary];
597 AIService *aimService = [adium.accountController firstServiceWithServiceID:@"AIM"];
599 for (NSDictionary *participant in participants) {
600 NSString *UID, *alias, *userIconName;
601 AIListContact *listContact;
604 UID = [participant objectForKey:@"UID"];
605 listContact = [[AIListContact alloc] initWithUID:UID service:aimService];
608 if ((alias = [participant objectForKey:@"Display Name"])) {
609 [[NSNotificationCenter defaultCenter] postNotificationName:Contact_ApplyDisplayName
611 userInfo:[NSDictionary dictionaryWithObject:alias forKey:@"Alias"]];
615 if ((userIconName = [participant objectForKey:@"UserIcon Name"])) {
616 [listContact setValue:[previewPath stringByAppendingPathComponent:userIconName]
617 forProperty:@"UserIconPath"
621 [listObjectDict setObject:listContact forKey:UID];
622 [listContact release];
625 return listObjectDict;
629 * @brief Chat settings
631 - (void)_applySettings:(NSDictionary *)chatDict toChat:(AIPreviewChat *)inChat withParticipants:(NSDictionary *)participants
633 NSString *dateOpened, *type, *name, *UID;
636 if ((dateOpened = [chatDict objectForKey:@"Date Opened"])) {
637 [inChat setDateOpened:[NSDate dateWithNaturalLanguageString:dateOpened]];
641 type = [chatDict objectForKey:@"Type"];
642 if ([type isEqualToString:@"IM"]) {
643 if ((UID = [chatDict objectForKey:@"Destination UID"])) {
644 [inChat addParticipatingListObject:[participants objectForKey:UID] notify:YES];
646 if ((UID = [chatDict objectForKey:@"Source UID"])) {
647 [inChat setAccount:(AIAccount *)[participants objectForKey:UID]];
650 if ((name = [chatDict objectForKey:@"Name"])) {
651 [inChat setName:name];
655 //We don't want the interface controller to try to open this fake chat
656 [inChat setIsOpen:YES];
660 * @brief Chat content
662 - (void)_addContent:(NSArray *)chatArray toChat:(AIChat *)inChat withParticipants:(NSDictionary *)participants
664 NSDictionary *messageDict;
666 for (messageDict in chatArray) {
667 AIContentObject *content = nil;
668 AIListObject *source;
669 NSString *from, *msgType;
670 NSAttributedString *message;
672 msgType = [messageDict objectForKey:@"Type"];
673 from = [messageDict objectForKey:@"From"];
675 source = (from ? [participants objectForKey:from] : nil);
677 if ([msgType isEqualToString:CONTENT_MESSAGE_TYPE]) {
678 //Create message content object
683 message = [AIHTMLDecoder decodeHTML:[messageDict objectForKey:@"Message"]];
684 to = [messageDict objectForKey:@"To"];
685 outgoing = [[messageDict objectForKey:@"Outgoing"] boolValue];
687 //The other person is always the one we're chatting with right now
688 dest = [participants objectForKey:to];
689 content = [AIPreviewContentMessage messageInChat:inChat
692 date:[NSDate dateWithNaturalLanguageString:[messageDict objectForKey:@"Date"]]
694 autoreply:[[messageDict objectForKey:@"Autoreply"] boolValue]];
696 //AIContentMessage won't know whether the message is outgoing unless we tell it since neither our source
697 //nor our destination are AIAccount objects.
698 [(AIPreviewContentMessage *)content setIsOutgoing:outgoing];
700 } else if ([msgType isEqualToString:CONTENT_STATUS_TYPE]) {
701 //Create status content object
702 NSString *statusMessageType;
704 message = [AIHTMLDecoder decodeHTML:[messageDict objectForKey:@"Message"]];
705 statusMessageType = [messageDict objectForKey:@"Status Message Type"];
707 //Create our content object
708 content = [AIContentEvent eventInChat:inChat
711 date:[NSDate dateWithNaturalLanguageString:[messageDict objectForKey:@"Date"]]
713 withType:statusMessageType];
717 [content setTrackContent:NO];
718 [content setPostProcessContent:NO];
719 [content setDisplayContentImmediately:NO];
721 [adium.contentController displayContentObject:content
722 usingContentFilters:YES
727 //We finished adding untracked content
728 [[NSNotificationCenter defaultCenter] postNotificationName:Content_ChatDidFinishAddingUntrackedContent