📄 qqcell.mm
字号:
/* * LumaQQ - Cross platform QQ client, special edition for Mac * * Copyright (C) 2007 luma <stubma@163.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 0 2111-1307 USA */#import "QQCell.h"#import "User.h"#import "Group.h"#import "Cluster.h"#import "FileTool.h"#import "PreferenceCache.h"#import "NSString-Validate.h"#import "ImageTool.h"#import "QQConstants.h"#import "Dummy.h"#import "SearchedUser.h"#import "AdvancedSearchedUser.h"#import "FontTool.h"#import "ParentLocatableOutlineDataSource.h"static int s_identifier = 0;@implementation QQCell- (id) init { self = [super init]; if(self) { m_QQ = 0; m_internalId = 0; m_searchStyle = NO; m_checkStyle = NO; m_memberStyle = NO; m_largeClusterHeadStyle = NO; m_ignoreLargeUserHeadPreference = NO; m_checker = [[NSButtonCell alloc] init]; [m_checker setAllowsMixedState:YES]; [m_checker setButtonType:NSSwitchButton]; [m_checker setTitle:kStringEmpty]; m_stateMap = [[NSMutableDictionary dictionary] retain]; m_identifier = s_identifier++; } return self;}- (id)initWithQQ:(UInt32)QQ { self = [super init]; if(self) { m_QQ = QQ; m_internalId = 0; m_searchStyle = NO; m_checkStyle = NO; m_checker = [[NSButtonCell alloc] init]; [m_checker setButtonType:NSSwitchButton]; [m_checker setTitle:kStringEmpty]; [m_checker setAllowsMixedState:YES]; m_stateMap = [[NSMutableDictionary dictionary] retain]; m_identifier = s_identifier++; } return self;}- (void) dealloc { [m_checker release]; [m_stateMap release]; [super dealloc];}- (id)copyWithZone:(NSZone*)zone { QQCell* newCopy = [[QQCell alloc] init]; [newCopy setQQ:m_QQ]; [newCopy setInternalId:m_internalId]; [newCopy setSearchStyle:m_searchStyle]; [newCopy setCheckStyle:m_checkStyle]; [newCopy setLargeClusterHeadStyle:m_largeClusterHeadStyle]; [newCopy setIgnoreLargeUserHeadPreference:m_ignoreLargeUserHeadPreference]; [newCopy setMemberStyle:m_memberStyle]; [newCopy setShowStatus:m_showStatus]; [newCopy setHead:m_head]; [newCopy setStateMap:m_stateMap]; [newCopy setIdentifier:m_identifier]; return newCopy;}- (void)drawGroupWithFrame:(NSRect)cellFrame inView:(NSView *)controlView { // get group object Group* g = [self objectValue]; // get group image NSImage* imgMain = nil; if([g isBlacklist]) imgMain = [ImageTool imageWithName:kImageBlacklistGroup size:kSizeSmall]; else if([g isStranger]) imgMain = [ImageTool imageWithName:kImageStrangerGroup size:kSizeSmall]; else imgMain = [ImageTool imageWithName:kImageFriendlyGroup size:kSizeSmall]; // get main image rect and draw NSSize imgSize = [imgMain size]; int x = (m_checkStyle ? [self drawChecker:cellFrame inView:controlView] : cellFrame.origin.x) + kSpacing; int y = NSMinY(cellFrame); NSRect imgRect = NSMakeRect(x, y, MIN(NSWidth(cellFrame), imgSize.width), MIN(NSHeight(cellFrame), imgSize.height)); if ([controlView isFlipped]) imgRect.origin.y += ceil((cellFrame.size.height + imgRect.size.height) / 2); else imgRect.origin.y += ceil((cellFrame.size.height - imgRect.size.height) / 2); [imgMain compositeToPoint:imgRect.origin operation:NSCompositeSourceOver]; // blink some icon if has message unread if([g messageCount] == 0 || [g messageCount] > 0 && [g frame] == 1) { // compose group string NSString* string = [NSString stringWithFormat:@"%@ (%d/%d)", [g name], [g onlineUserCount], [g userCount]]; // get string attribute NSMutableDictionary* attributes = [NSMutableDictionary dictionary]; [attributes setObject:[FontTool nickFontWithPreference:m_QQ] forKey:NSFontAttributeName]; // get string bound NSRect bound = [string boundingRectWithSize:cellFrame.size options:NSStringDrawingUsesLineFragmentOrigin attributes:attributes]; // draw center vertical [string drawAtPoint:NSMakePoint(x + imgSize.width + kSpacing, cellFrame.origin.y + MAX(0, (cellFrame.size.height - bound.size.height) / 2)) withAttributes:attributes]; } [g setFrame:(([g frame] + 1) % 2)];}- (void)drawMobileWithFrame:(NSRect)cellFrame inView:(NSView*)controlView { // get group object Mobile* m = [self objectValue]; // get group image NSImage* imgMain = [NSImage imageNamed:kImageMobiles]; // get main image rect NSSize imgSize = [imgMain size]; // compare cell frame and image size if(imgSize.height > NSHeight(cellFrame)) imgMain = [ImageTool imageWithName:[imgMain name] size:NSMakeSize(cellFrame.size.height, cellFrame.size.height)]; // draw image int x = (m_checkStyle ? [self drawChecker:cellFrame inView:controlView] : cellFrame.origin.x) + kSpacing; int y = NSMinY(cellFrame); NSRect imgRect = NSMakeRect(x, y, MIN(NSWidth(cellFrame), imgSize.width), MIN(NSHeight(cellFrame), imgSize.height)); if ([controlView isFlipped]) imgRect.origin.y += ceil((cellFrame.size.height + imgRect.size.height) / 2); else imgRect.origin.y += ceil((cellFrame.size.height - imgRect.size.height) / 2); [imgMain compositeToPoint:imgRect.origin operation:NSCompositeSourceOver]; // blink some icon if has message unread if([m messageCount] == 0 || [m messageCount] > 0 && [m frame] == 1) { // compose group string NSString* string = ([m name] == nil || [[m name] isEmpty]) ? [m mobile] : [m name]; // get string attribute PreferenceCache* cache = [PreferenceCache cache:m_QQ]; NSMutableDictionary* attributes = [NSMutableDictionary dictionary]; [attributes setObject:[FontTool nickFontWithPreference:m_QQ] forKey:NSFontAttributeName]; [attributes setObject:[cache nickFontColor] forKey:NSForegroundColorAttributeName]; // get string bound NSRect bound = [string boundingRectWithSize:cellFrame.size options:NSStringDrawingUsesLineFragmentOrigin attributes:attributes]; // draw center vertical [string drawAtPoint:NSMakePoint(x + imgSize.width + kSpacing, cellFrame.origin.y + MAX(0, (cellFrame.size.height - bound.size.height) / 2)) withAttributes:attributes]; } [m setFrame:(([m frame] + 1) % 2)];}- (void)drawSearchStyleUserWithFrame:(NSRect)cellFrame inView:(NSView*)controlView { // get head NSImage* imgMain = [ImageTool headWithId:[[self objectValue] head] size:kSizeSmall]; // get main image rect and draw NSSize imgSize = [imgMain size]; int x = cellFrame.origin.x + kSpacing; int y = NSMinY(cellFrame); NSRect imgRect = NSMakeRect(x, y, MIN(NSWidth(cellFrame), imgSize.width), MIN(NSHeight(cellFrame), imgSize.height)); if ([controlView isFlipped]) imgRect.origin.y += ceil((cellFrame.size.height + imgRect.size.height) / 2); else imgRect.origin.y += ceil((cellFrame.size.height - imgRect.size.height) / 2); [imgMain compositeToPoint:imgRect.origin operation:NSCompositeSourceOver]; // get text x start x += imgRect.size.width + kSpacing; // get qq string NSString* qqStr = [NSString stringWithFormat:@"%u", [[self objectValue] QQ]]; // get string attribute NSMutableDictionary* attributes = [NSMutableDictionary dictionary]; NSFont* font = [FontTool nickFontWithPreference:m_QQ]; font = [[NSFontManager sharedFontManager] convertFont:font toSize:[NSFont systemFontSize]]; [attributes setObject:font forKey:NSFontAttributeName]; // get string bound NSRect bound = [qqStr boundingRectWithSize:cellFrame.size options:NSStringDrawingUsesLineFragmentOrigin attributes:attributes]; // draw center vertical [qqStr drawAtPoint:NSMakePoint(x, cellFrame.origin.y + MAX(0, (cellFrame.size.height - bound.size.height) / 2)) withAttributes:attributes];}- (void)drawUserWithFrame:(NSRect)cellFrame inView:(NSView *)controlView { if(m_searchStyle) { [self drawSearchStyleUserWithFrame:cellFrame inView:controlView]; return; } // get user object User* u = [self objectValue]; // get preference PreferenceCache* cache = [PreferenceCache cache:m_QQ]; // get large flag BOOL bLarge = [cache showLargeUserHead]; if(m_ignoreLargeUserHeadPreference) bLarge = cellFrame.size.height >= kSizeLarge.height; // head NSImage* imgMain = [u head:m_QQ handleStatus:YES]; if(!bLarge) imgMain = [ImageTool imageWithName:[imgMain name] size:kSizeSmall]; // get main image rect NSSize imgSize = [imgMain size]; int x = (m_checkStyle ? [self drawChecker:cellFrame inView:controlView] : cellFrame.origin.x) + kSpacing; int y = NSMinY(cellFrame); NSRect imgRect = NSMakeRect(x, y, MIN(NSWidth(cellFrame), imgSize.width), MIN(NSHeight(cellFrame), imgSize.height)); if ([controlView isFlipped]) imgRect.origin.y += ceil((cellFrame.size.height + imgRect.size.height) / 2); else imgRect.origin.y += ceil((cellFrame.size.height - imgRect.size.height) / 2); // blink some icon if has message unread int frame = [u frameArray][0] % 2; if([u messageCount] + [u mobileMessageCount] == 0 || [u messageCount] + [u mobileMessageCount] > 0 && frame == 1) { [imgMain compositeToPoint:imgRect.origin operation:NSCompositeSourceOver]; // draw status decoration or mobile chatting decoration, mobile chatting first if([u mobileChatting]) { NSImage* mobileChatting = bLarge ? [NSImage imageNamed:kImageMobileChatting] : [ImageTool imageWithName:kImageMobileChatting size:NSMakeSize(10, 10)]; [self drawDecoration:mobileChatting headRect:imgRect]; } else { switch(m_status) { case kQQStatusAway: [self drawDecoration:[NSImage imageNamed:kImageAway] headRect:imgRect]; break; case kQQStatusHidden: [self drawDecoration:[NSImage imageNamed:kImageHidden] headRect:imgRect]; break; case kQQStatusQMe: [self drawDecoration:[NSImage imageNamed:kImageQMe] headRect:imgRect]; break; case kQQStatusBusy: [self drawDecoration:[NSImage imageNamed:kImageBusy] headRect:imgRect]; break; case kQQStatusMute:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -