UnImportantNotice 2.0





OsiriX 6 Notice.

I wrote this plugin in the spirit of open-source software. The source code for OsiriX 6 has not been released, and therefore it can’t be considered open-source. UnImportantNotice will only be updated if OsiriX 6 becomes open-source. Your options are:

- Buy OsiriX 6 from Antoine and Joris over at Pixmeo. http://www.osirix-viewer.com/Store.html

- Switch to the Horos fork of OsiriX http://www.horosproject.org

- Downgrade to a previous version of OsiriX.


Welcome! Below is the source code for the UnImportantNotice OsiriX plugin. UnimportantNotice is an OsiriX plugin that can be used by folks who use OsiriX for reasons other than medical diagnostics, including patients, researchers, veterinarians, etc. Once the plugin is installed, non-MD versions of OsiriX will no longer display the "NOT FOR MEDICAL USAGE" banner in the main viewer and will no longer bring up the popup dialog with the, "Important Notice This version of OsiriX, being a free open-source software (FOSS), is not certified as a commercial medical device for primary diagnostic imaging." I hope you find it useful.


You can download the plugin from:

https://download.naturalimage.ch/UnImportantNotice2-0.zip


Source code is also available on github at:

https://github.com/spalte/UnImportantNotice


If you have an questions or comments, please contact me (Joël Spaltenstein) at spalte@naturalimage.ch.




/*  UnImportantNotice


 Copyright (c) 2013, Spaltenstein Natural Image

 All rights reserved.

 

 Redistribution and use in source and binary forms, with or without

 modification, are permitted provided that the following conditions are met:

 * Redistributions of source code must retain the above copyright

 notice, this list of conditions and the following disclaimer.

 * Redistributions in binary form must reproduce the above copyright

 notice, this list of conditions and the following disclaimer in the

 documentation and/or other materials provided with the distribution.

 * Neither the name of Spaltenstein Natural Image nor the

 names of its contributors may be used to endorse or promote products

 derived from this software without specific prior written permission.

 

 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND

 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED

 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE

 DISCLAIMED. IN NO EVENT SHALL SPALTENSTEIN NATURAL IMAGE BE LIABLE FOR ANY

 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES

 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;

 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND

 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT

 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS

 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.*/


#import <objc/runtime.h>


#import <Foundation/Foundation.h>


@class ViewerController;

@interface PluginFilter : NSObject

{

ViewerController*   viewerController;

}

@end


@interface UnImportantNoticeFilter : PluginFilter

@end


@implementation UnImportantNoticeFilter


- (void) initPlugin

{

Class AppControllerClass = objc_getClass("AppController");

if (AppControllerClass == nil)

{

NSLog(@"UnImportantNoticeFilter could not find the AppControllerClass");

return;

}

Class BrowserControllerClass = objc_getClass("BrowserController");

if (BrowserControllerClass == nil)

{

NSLog(@"UnImportantNoticeFilter could not find the BrowserControllerClass");

return;

}

    // get rid of the dialog when the window opens

Method importantMethod = class_getClassMethod(AppControllerClass, @selector(displayImportantNotice:));

Method unImportantMethod = class_getClassMethod([UnImportantNoticeFilter class], @selector(displayUnImportantNotice:));

if (importantMethod == NULL || unImportantMethod == NULL)

{

NSLog(@"UnImportantNoticeFilter could not find the important methods");

return;

}

IMP unImportantImp = method_getImplementation(unImportantMethod);

if (unImportantImp == NULL)

{

NSLog(@"UnImportantNoticeFilter could not find the unImportantImp");

return;

}

method_setImplementation(importantMethod, unImportantImp);

    

    // get rid of the message in the DCMView

    Method isFDAClearedMethod = class_getClassMethod(AppControllerClass, @selector(isFDACleared));

Method unImportantIsFDAClearedMethod = class_getClassMethod([UnImportantNoticeFilter class], @selector(isFDAClearedUnImportantNotice));

if (isFDAClearedMethod == NULL || unImportantIsFDAClearedMethod == NULL)

{

NSLog(@"UnImportantNoticeFilter could not find the isFDACleared methods");

return;

}

    

    IMP isFDAClearedUnImportantNoticeImp = method_getImplementation(unImportantIsFDAClearedMethod);

if (isFDAClearedUnImportantNoticeImp == NULL)

{

NSLog(@"UnImportantNoticeFilter could not find the isFDAClearedUnImportantNoticeImp");

return;

}

    

    const char* isFDAClearedUnImportantNoticeTypes = method_getTypeEncoding(isFDAClearedMethod);

    if (isFDAClearedUnImportantNoticeTypes) {

        if (class_addMethod(object_getClass(AppControllerClass), @selector(isFDAClearedUnImportantNotice), isFDAClearedUnImportantNoticeImp, isFDAClearedUnImportantNoticeTypes)) {

            Method unImportantIsFDAClearedMethodAppController = class_getClassMethod(AppControllerClass, @selector(isFDAClearedUnImportantNotice));

            method_exchangeImplementations(isFDAClearedMethod, unImportantIsFDAClearedMethodAppController);

        }

    }

    

    // get rid of the banner

    Method checkForBannerMethod = class_getInstanceMethod(BrowserControllerClass, @selector(checkForBanner:));

Method checkForUnImportantBannerMethod = class_getInstanceMethod([UnImportantNoticeFilter class], @selector(checkForUnImportantBanner:));

if (checkForBannerMethod == NULL || checkForUnImportantBannerMethod == NULL)

{

NSLog(@"UnImportantNoticeFilter could not find the important banner methods");

return;

}

IMP checkForUnImportantBannerImp = method_getImplementation(checkForUnImportantBannerMethod);

if (checkForUnImportantBannerImp == NULL)

{

NSLog(@"UnImportantNoticeFilter could not find the checkForUnImportantBannerImp");

return;

}

method_setImplementation(checkForBannerMethod, checkForUnImportantBannerImp);

}


+ (void)displayUnImportantNotice:(id)sender

{

NSLog(@"UnImportantNoticeFilter: short-circuited +[AppController displayImportantNotice:]");

}


+ (BOOL)isFDAClearedUnImportantNotice

{

    NSArray *symbols = [NSThread callStackSymbols];

    if ([symbols count] >=2) {

        NSString *secondFrame = [symbols objectAtIndex:1];

        if ([secondFrame rangeOfString:@"drawTextualData:annotationsLevel:fullText:onlyOrientation:"].location != NSNotFound) {

            static BOOL printedLog = NO;

            if (printedLog == NO) {

                NSLog(@"UnImportantNoticeFilter: short-circuited +[AppController isFDACleared] because it was called from -[DCMView drawTextualData:annotationsLevel:fullText:onlyOrientation:] (this message is printed only once)");

            }

            printedLog = YES;

            return YES;

        }

    }

    return [self  isFDAClearedUnImportantNotice];

}


- (void)checkForUnImportantBanner:(id)sender

{

    NSAutoreleasePool *pool = [NSAutoreleasePool new];

    NSImage *bannerImage = [[[NSImage alloc] init] autorelease];

    if( bannerImage) {

        [self performSelectorOnMainThread: @selector(installBanner:) withObject:bannerImage waitUntilDone:NO modes:[NSArray arrayWithObject:NSRunLoopCommonModes]];

    }

    [pool release];

    NSLog(@"UnImportantNoticeFilter: short-circuited -[BrowserController checkForBanner:]");

}



@end