QLPreviewPanel in tableview with issue: "has no controller" - objective-c

I would like to display the urls from a table view in a QLPreviewPanel but i got this error:
[QL] QLError(): -[QLPreviewPanel reloadData] called while the panel
has no controller - Fix this or this will raise soon.
My table controller already conform to this two protocols : QLPreviewPanelDataSource, QLPreviewPanelDelegate.
How can i set the controller of [QLPreviewPanel sharedPreviewPanel] as my table controller?
- (void)didPressSpacebarForTableView:(NSTableView *)tableView {
NSLog(#"Spacebar clicked");
if ([QLPreviewPanel sharedPreviewPanelExists] && [[QLPreviewPanel sharedPreviewPanel] isVisible]) {
[[QLPreviewPanel sharedPreviewPanel] orderOut:nil];
} else {
[[QLPreviewPanel sharedPreviewPanel] reloadData];
[[QLPreviewPanel sharedPreviewPanel] makeKeyAndOrderFront:nil];
}
}
- (NSInteger)numberOfPreviewItemsInPreviewPanel:(QLPreviewPanel *)panel {
return [[(PasteboardItem *)[[_arrayController arrangedObjects] objectAtIndex:[_tableView selectedRow]] filenames] count];
}
- (id<QLPreviewItem>)previewPanel:(QLPreviewPanel *)panel previewItemAtIndex:(NSInteger)index {
NSString *path = [(PasteboardItem *)[[_arrayController arrangedObjects] objectAtIndex:[_tableView selectedRow]] filenames][index];
NSURL *url = [NSURL fileURLWithPath:path];
return url;
}
- (BOOL)acceptsPreviewPanelControl:(QLPreviewPanel *)panel {
return YES;
}
-(void)beginPreviewPanelControl:(QLPreviewPanel *)panel {
panel.dataSource = self;
panel.delegate = self;
}
- (void)endPreviewPanelControl:(QLPreviewPanel *)panel {
panel.dataSource = nil;
panel.delegate = nil;
}

I found the solution here: QuickLook consumer as a delegate from an NSViewController. In my case i need these 3 lines of code in the panel controller (NSWindowController) where i have the instance of my table view controller.
- (void)awakeFromNib {
NSResponder * aNextResponder = [self nextResponder];
[self setNextResponder:_tableController];
[_tableController setNextResponder:aNextResponder];
}

Related

Custom NSPopupButtonCell in NSTableView

I am trying to create a custom popup menu in a tableview. As I understand it I can should be able to do so by calling the [NSPopupButtonCell setView:myView] method passing in the custom view (which is just a NSView with an NSOutlineView in it).
So I have created a NSPopupButtonCell subclass and during initialisation I call setView and pass in the custom outline view..
EDIT
In IB I have set the table columns cell to a Popup Button Cell and set
the class to my custom LookupPopupButtonCell.
I still don't get my custom view displaying but my custom classes
initialisation methods appear to be getting called.
I have since replaced this approach with using a NSTableViewDelegate method dataCellForTableColumn. Now the popup shows my custom tableView.
Still no joy in getting the NSOutlineViewDelegate methods called though.
EDIT
OK I have managed to get things working using a NSPopupButton on a view. delegate works find and table view displays things fine. Seems that using NSPopupButtonCell the delegate methods never get called.
#implementation LookupPopupButtonCell
- (id)init
{
LOG(#"init called");
self = [super init];
if (self) {
[self initialise];
}
return self;
}
- (void)initialise
{
LOG(#"initialise called");
[self setFont:[NSFont fontWithName:#"System Regular" size:11]];
[self setBordered:NO];
[self setBezeled:NO];
// Set the Task Lookup Popup Menu
NSMenu *newLookupMenu = [[NSMenu allocWithZone:[NSMenu menuZone]] initWithTitle:#"Custom"];
NSMenuItem *newItem = [[NSMenuItem allocWithZone:[NSMenu menuZone]] initWithTitle:#"Lookup" action:nil keyEquivalent:#""];
[newItem setEnabled:YES];
TaskLookupViewController *viewController = [[TaskLookupViewController alloc] initWithNibName:#"TaskLookupViewController" bundle:nil];
[newItem setView:[viewController view]];
[newLookupMenu addItem:newItem];
[newItem release];
[self setMenu:newLookupMenu];
}
#end
#implementation TaskLookupViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Initialization code here.
[self initialise];
}
return self;
}
- (void)awakeFromNib{
LOG(#"awakeFromNib called...");
[self viewDidLoad];
}
- (void)viewDidLoad {
FLOG(#"viewDidLoad called for %#", self);
/*
FLOG(#" _outlineView is %#", _outlineView);
FLOG(#" _outlineView is %#", [_outlineView identifier]);
FLOG(#" _outlineView delegate is %#", [_outlineView delegate]);
FLOG(#" _outlineView dataSource is %#", [_outlineView dataSource]);
*/
[_outlineView setDataSource:self];
[_outlineView setDelegate:self];
[_outlineView reloadData];
[_outlineView selectRowIndexes:[NSIndexSet indexSetWithIndex:0] byExtendingSelection:NO];
[_outlineView setNeedsDisplay];
[_outlineView selectRowIndexes:[NSIndexSet indexSetWithIndex:2] byExtendingSelection:NO];
/*
FLOG(#" _outlineView delegate is %#", [_outlineView delegate]);
FLOG(#" _outlineView dataSource is %#", [_outlineView dataSource]);
*/
//NSTableColumn *tableColumn = [[_outlineView tableColumns] objectAtIndex:0];
//LOG(#" setting bindings");
//[tableColumn bind: #"value" toObject: _treeController withKeyPath: #"arrangedObjects.displayName" options: nil];
}
- (void)initialise {
LOG(#"initialise called");
_topLevelItems = [[NSArray arrayWithObjects:#"Project", #"Tasks and Deliverables", #"Finance", nil] retain];
_childrenDictionary = [NSMutableDictionary new];
[_childrenDictionary setObject:[NSArray arrayWithObjects:#"Scope", nil] forKey:#"Project"];
//[_childrenDictionary setObject:[NSArray arrayWithObjects:#"Issues", #"Risks", nil] forKey:#"Quality"];
[_childrenDictionary setObject:[NSArray arrayWithObjects:#"WBS", #"Functions", nil] forKey:#"Tasks and Deliverables"];
[_childrenDictionary setObject:[NSArray arrayWithObjects:#"Expenses", #"Ongoing Costs", #"Timesheets", nil] forKey:#"Finance"];
//[_childrenDictionary setObject:[NSArray arrayWithObjects:#"Applications", #"Interfaces", nil] forKey:#"IT Systems"];
//[_childrenDictionary setObject:[NSArray arrayWithObjects:#"People", #"Setup", nil] forKey:#"Administration"];
}
- (NSArray *)_childrenForItem:(id)item {
LOG(#"_childrenForItem called");
NSArray *children;
if (item == nil) {
children = _topLevelItems;
} else {
children = [_childrenDictionary objectForKey:item];
}
//FLOG(#" children are %#", children);
return children;
}
#end
#implementation TaskLookupViewController (NSOutlineViewDataSource)
- (void)outlineViewSelectionDidChange:(NSNotification *)notification {
LOG(#"outlineViewSelectionDidChange: called");
if ([_outlineView selectedRow] != -1) {
NSObject *item = [_outlineView itemAtRow:[_outlineView selectedRow]];
if ([_outlineView parentForItem:item] != nil) {
// Only change things for non-root items (root items can be selected, but are ignored)
FLOG(#" selected item is %#", item);
}
}
}
- (id)outlineView:(NSOutlineView *)outlineView child:(NSInteger)index ofItem:(id)item {
FLOG(#"outlineView:child:ofItem: called for item %#", item);
return [[self _childrenForItem:item] objectAtIndex:index];
}
- (BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item {
LOG(#"outlineView:isItemExpandable: called");
if ([outlineView parentForItem:item] == nil) {
return YES;
} else {
return YES;
}
}
- (NSInteger) outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item {
LOG(#"outlineView:numberOfChildrenOfItem: called");
FLOG(#" children count is %d", [[self _childrenForItem:item] count]);
return [[self _childrenForItem:item] count];
}
#end
#implementation TaskLookupViewController (NSOutlineViewDelegate)
- (BOOL)outlineView:(NSOutlineView *)outlineView isGroupItem:(id)item {
LOG(#"outlineView:isGroupItem: called");
return [_topLevelItems containsObject:item];
}
- (void)outlineView:(NSOutlineView *)outlineView willDisplayCell:(id)cell forTableColumn:(NSTableColumn *)tableColumn item:(id)item
{
LOG(#"willDisplayCell called");
[cell setTitle:#"Cell Title"];
}
- (NSView *)outlineView:(NSOutlineView *)outlineView viewForTableColumn:(NSTableColumn *)tableColumn item:(id)item {
LOG(#"outlineView:viewForTableColumn called");
// We just return a regular text view.
if ([_topLevelItems containsObject:item]) {
NSTextField *result = [outlineView makeViewWithIdentifier:#"HeaderTextField" owner:self];
// Uppercase the string value, but don't set anything else. NSOutlineView automatically applies attributes as necessary
NSString *value = [item uppercaseString];
[result setStringValue:value];
return result;
} else {
NSTextField *result = [outlineView makeViewWithIdentifier:#"ItemTextField" owner:self];
[result setStringValue:value];
return result;
}
}
- (BOOL)outlineView:(NSOutlineView *)outlineView shouldExpandItem:(id)item;
{
LOG(#"outlineView:shouldExpandItem: called");
return YES;
}
- (BOOL)outlineView:(NSOutlineView *)outlineView shouldSelectItem:(id)item;
{
LOG(#"outlineView:shouldSelectItem: called");
return YES;
}
- (BOOL)outlineView:(NSOutlineView *)outlineView shouldCollapseItem:(id)item;
{
LOG(#"outlineView:shouldCollapseItem: called");
return NO;
}
#end
#implementation TaskLookupViewController (NSTableViewDelegate)
- (NSCell *)tableView:(NSTableView *)tableView dataCellForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
LOG(#"tableView:dataCellForTableColumn:row: called");
NSString *identifier = [tableColumn identifier];
if ([identifier isEqualToString:#"task"]) {
//LOG(#" task column setting the cell");
LookupPopupButtonCell *cellView = [[LookupPopupButtonCell alloc] init];
return cellView;
}
NSTextFieldCell *cellView = [tableView makeViewWithIdentifier:#"hoursCell" owner:self];
return cellView;
}
#end
It seems you must use a VIEW based tableView to get the delegate messages. Blah, now to figure out how to bind one of them to Core Data, hopefully its not too hard !
Is there any way to reuse the same menu for each row ? I guess as long as the dataSource is not recreated each time its probably not too bad, still there could be lots of rows in this hierarchy!

How not to load the view in some cases?

I have a methods
- (void)viewDidAppear:(BOOL)animated
{
[self updateViews];
}
- (void) updateViews
{
NSInteger itemIndex = [[DataController sharedInstance] indexFromObjectProperty:itemUUID];
if (itemIndex == NSNotFound) {
[self.navigationController popViewControllerAnimated:YES];
}
NSDictionary *item = [[[DataController sharedInstance] getItems] objectAtIndex:itemIndex];
}
I need not to load the view in case itemIndex == NSNotFound but in debug mode this string is called and then the next string is accessing and it causes an exception. How to stop updating view and show root view controller?
There are two ways to easily do this:
Add a return:
- (void) updateViews
{
NSInteger itemIndex = [[DataController sharedInstance] indexFromObjectProperty:itemUUID];
if (itemIndex == NSNotFound) {
[self.navigationController popViewControllerAnimated:YES];
return; // exits the method
}
NSDictionary *item = [[[DataController sharedInstance] getItems] objectAtIndex:itemIndex];
}
or you have other things that you want to accomplish in this method (mainly if this is not the view being popped):
- (void) updateViews
{
NSInteger itemIndex = [[DataController sharedInstance] indexFromObjectProperty:itemUUID];
// nil dictionary
NSDictionary *item;
if (itemIndex == NSNotFound) {
[self.navigationController popViewControllerAnimated:YES];
} else {
// setup the dictionary
item = [[[DataController sharedInstance] getItems] objectAtIndex:itemIndex];
}
// continue updating
}

How to use SpaceBar button inside an application to invoke quick look

i had displayed some images in collectionview. now i want to select the image and press space button. If i pressed Space button , the image should quicklook in a seperate window. any idea?
On your view, do this:
- (void)keyDown:(NSEvent *)event
{
unichar firstChar = 0;
if ([[event charactersIgnoringModifiers] length] > 0)
firstChar = [[event charactersIgnoringModifiers] characterAtIndex:0];
if (firstChar == ' ')
{
if ([QLPreviewPanel sharedPreviewPanelExists]
&& [[QLPreviewPanel sharedPreviewPanel] isVisible])
{
[[QLPreviewPanel sharedPreviewPanel] orderOut:nil];
}
else
{
[[QLPreviewPanel sharedPreviewPanel] makeKeyAndOrderFront:nil];
[[NSApp mainWindow] makeKeyWindow];
}
}
else if (firstChar == NSRightArrowFunctionKey)
{
if ([QLPreviewPanel sharedPreviewPanelExists]
&& [[QLPreviewPanel sharedPreviewPanel] isVisible])
{
[[QLPreviewPanel sharedPreviewPanel] selectNextItem];
return;
}
}
else if (firstChar == NSLeftArrowFunctionKey)
{
if ([QLPreviewPanel sharedPreviewPanelExists]
&& [[QLPreviewPanel sharedPreviewPanel] isVisible])
{
[[QLPreviewPanel sharedPreviewPanel] selectPreviousItem];
return;
}
}
else
[super keyDown:event];
}
Then, I do this in my app's delegate (AppDelegate.m):
- (BOOL)acceptsPreviewPanelControl:(QLPreviewPanel *)panel
{
//note that this methods indeed gets called because NSApp's
//delegate is in the responder chain.
return YES;
}
- (void)beginPreviewPanelControl:(QLPreviewPanel *)panel
{
previewPanel = panel; //set an ivar
[panel setDataSource:self];
}
- (void)endPreviewPanelControl:(QLPreviewPanel *)panel
{
previewPanel = nil;
}
- (NSInteger)numberOfPreviewItemsInPreviewPanel:(QLPreviewPanel *)panel
{
//return a number of your choice (depends on your own app)
}
- (id <QLPreviewItem>)previewPanel:(QLPreviewPanel *)panel
previewItemAtIndex:(NSInteger)index
{
//return an object of your choice (depends on your app)
}
- (void)handleCurrentFileItemsSelectionChange:(NSNotification *)note
{
[previewPanel reloadData]; //referring to the ivar
}
i finally got. i just replaced imageViewes and put NSButton and setted spacebutton as keyequivalent as
- (BOOL)isOneOfMyKeyEquivs:(NSString *)keyChar
{
if (([keyChar isEqualToString:#" "])||([keyChar isEqualToString:#"\r"])) {
return YES;
} else {
return NO;
}
}
- (BOOL)performKeyEquivalent:(NSEvent *)theEvent
{
//NSLog(#"OK");
NSString* keyChar = [theEvent characters];
if ([self isOneOfMyKeyEquivs:keyChar])
{
[[self cell] setKeyEquivalent:keyChar];
}
return [super performKeyEquivalent:theEvent];
return NO;
}
and performed button action.

Singleton method not getting called in Cocos2d

I am calling a Singleton method that does not get called when I try doing this.
I get no errors or anything, just that I am unable to see the CCLOG message.
Under what reasons would a compiler not give you error and not allow you to call a method?
[[GameManager sharedGameManager] openSiteWithLinkType:kLinkTypeDeveloperSite];
The method is defined as follows:
-(void)openSiteWithLinkType:(LinkTypes)linkTypeToOpen
{
CCLOG(#"WE ARE IN openSiteWithLinkType"); //I NEVER SEE THIS MESSAGE
NSURL *urlToOpen = nil;
if (linkTypeToOpen == kLinkTypeDeveloperSite)
{
urlToOpen = [NSURL URLWithString:#"http://somesite.com"];
}
if (![[UIApplication sharedApplication]openURL:urlToOpen])
{
CCLOG(#"%#%#",#"Failed to open url:",[urlToOpen description]);
[self runSceneWithID:kMainMenuScene];
}
}
HERE IS THE CODE TO MY SINGLETON:
#import "GameManager.h"
#import "MainMenuScene.h"
#implementation GameManager
static GameManager* _sharedGameManager = nil;
#synthesize isMusicON;
#synthesize isSoundEffectsON;
#synthesize hasPlayerDied;
+(GameManager*) sharedGameManager
{
#synchronized([GameManager class])
{
if (!_sharedGameManager)
{
[[self alloc] init];
return _sharedGameManager;
}
return nil;
}
}
+(id)alloc
{
#synchronized ([GameManager class])
{
NSAssert(_sharedGameManager == nil,#"Attempted to allocate a second instance of the Game Manager singleton");
_sharedGameManager = [super alloc];
return _sharedGameManager;
}
return nil;
}
-(id)init
{
self = [super init];
if (self != nil)
{
//Game Manager initialized
CCLOG(#"Game Manager Singleton, init");
isMusicON = YES;
isSoundEffectsON = YES;
hasPlayerDied = NO;
currentScene = kNoSceneUninitialized;
}
return self;
}
-(void) runSceneWithID:(SceneTypes)sceneID
{
SceneTypes oldScene = currentScene;
currentScene = sceneID;
id sceneToRun = nil;
switch (sceneID)
{
case kMainMenuScene:
sceneToRun = [MainMenuScene node];
break;
default:
CCLOG(#"Unknown Scene ID, cannot switch scenes");
return;
break;
}
if (sceneToRun == nil)
{
//Revert back, since no new scene was found
currentScene = oldScene;
return;
}
//Menu Scenes have a value of < 100
if (sceneID < 100)
{
if (UI_USER_INTERFACE_IDIOM() != UIUserInterfaceIdiomPad)
{
CGSize screenSize = [CCDirector sharedDirector].winSizeInPixels;
if (screenSize.width == 960.0f)
{
//iPhone 4 retina
[sceneToRun setScaleX:0.9375f];
[sceneToRun setScaleY:0.8333f];
CCLOG(#"GM: Scaling for iPhone 4 (retina)");
}
else
{
[sceneToRun setScaleX:0.4688f];
[sceneToRun setScaleY:0.4166f];
CCLOG(#"GM: Scaling for iPhone 3G or older (non-retina)");
}
}
}
if ([[CCDirector sharedDirector] runningScene] == nil)
{
[[CCDirector sharedDirector] runWithScene:sceneToRun];
}
else
{
[[CCDirector sharedDirector] replaceScene:sceneToRun];
}
}
-(void)openSiteWithLinkType:(LinkTypes)linkTypeToOpen
{
CCLOG(#"WE ARE IN openSiteWithLinkType");
NSURL *urlToOpen = nil;
if (linkTypeToOpen == kLinkTypeDeveloperSite)
{
urlToOpen = [NSURL URLWithString:#"http://somesite.com"];
}
if (![[UIApplication sharedApplication]openURL:urlToOpen])
{
CCLOG(#"%#%#",#"Failed to open url:",[urlToOpen description]);
[self runSceneWithID:kMainMenuScene];
}
}
-(void) test
{
CCLOG(#"this is test");
}
#end
Perhaps sharedGameManager is returning nil? This won't cause an error.
Edit: The issue is in the new code you posted:
if (!_sharedGameManager) {
[[self alloc] init];
return _sharedGameManager;
}
return nil;
If _sharedGameManager is non-nil, this will return nil. You want:
if (!_sharedGameManager) {
[[self alloc] init];
}
return _sharedGameManager;
Check this Cocoa With Love article on how to make a proper singleton.

Navigating to another view iPhone sdk?

I want to navigate to another view. I have like a now playing button for my radio application. I would like the view to mentain its state... the view that I want to navigate to has a text field for url of the radion and a label for radio name. so how can I mentain the state of that view because right now when ever I try to navigate it navigates fine but the text field changes.. so what can I do to not change the text?
here is some code sorry about wierd names
if (self.bookDetailViewController_1 == nil)
{
iPhoneStreamingPlayerViewController *aBookDetail = [[iPhoneStreamingPlayerViewController alloc] initWithNibName:#"iPhoneStreamingPlayerView" bundle:nil];
self.bookDetailViewController_1= aBookDetail;
[aBookDetail release];
}
Music_appAppDelegate *delegate = [[UIApplication sharedApplication]delegate];
[delegate.booksNavController pushViewController:bookDetailViewController_1 animated:YES];
Singleton implementation
//.h
+ (className *)sharedInstance;
//.m
static className* sharedInstance = nil;
#implementation className
+ (className*)sharedInstance {
if (!sharedInstance) {
sharedInstance = [[super allocWithZone:NULL] init];
}
return sharedInstance;
}
+ (id)allocWithZone:(NSZone *)zone {
return [[self sharedInstance] retain];
}
- (id)copyWithZone:(NSZone *)zone {
return self;
}
- (id)retain {
return self;
}
- (NSUInteger)retainCount {
return NSUIntegerMax;
}
- (void)release { }
- (id)autorelease {
return self;
}
#end