ドロップしたファイルを日付でリネームする(その1)

私の使っているデジカメのファイル名の通番がそろそろ上限に達しラウンドしてまた0から始まり、以前の画像ファイルと名前が重なってくる可能性が出てきました。
そこでファイルの更新日付でファイル名をリネームするアプリを作ってみました。
画面のイメージを以下に示します。

操作は簡単で、Finderでリネームしたいファイルを選択してアプリの黄緑色のViewの上にドラッグアンドドロップするだけです。
ファイル名は以下のようにリネームされます。

 Prefix+年月日時分秒+"-"+連番+拡張子

 例:IMG20100624123519-001.JPG

●プロジェクトの作成

ドキュメントベースでないCocoaアプリケーションで"RenameByDate"と名付けてプロジェクトを作ります。


●独自Viewクラスの作成

xibファイルをダブルクリックしてInterface Builderを起動します。
Interface BuilderのLibraryウィンドウのClassesタブを選択し、検索フィールドに"NSView"と入力しクラスを絞り込みます。

NSViewを右クリックして表示されるメニューの"New Subclass..."を選びます。

表示されるダイアログで"UCDropView"と入力し"Generate source files"にチェックが入っていることを確認しOKをクリックします。

生成したファイルをプロジェクトに加えるかどうか聞いてくるのでチェックを付けて"Add"ボタンをクリックします。

●GUIの作成

LibraryウィンドウのClassesタブで"UC"で検索して先ほど作ったUCDropViewを見つけ出しそれをアプリケーションウィンドウにドラッグアンドドロップします。

他のパーツはLiblaryウィンドウの"Objects"タブから検索して以下のように配置します。

NSProgressIndicatorは"Indeterminate"のチェックを外しておきます。NSButtonはDisableにしておいてください。

ウィンドは固定サイズにするのでウィンドウのプロパティでMinimum SizeとMaximum Sizeを"Use Current"ボタンで今のサイズに設定します。

●UCDropViewの実装

UCDropViewのメンバー変数にはドラッグ中のフレームの強調表示のためのフラグと実際のドロップされたファイルの処理を行うdelegateを用意します。
UCDropViewはFinderからファイルをドロップされた時、delegateのdroppedFiles:メソッドを呼び出します。
メソッドとしては初期化処理(awakeFromNib)、Viewの描画(drawRect:)、NSDraggingDestinationプロトコルなどを実装します。

UCDropView.h : ドロップビュークラスのインターフェース

#import <Cocoa/ocoa.h>

@interface UCDropView : NSView {
@private
    BOOL	mbDragging;				// ドラッギング中フラグ
    id	 moDelegate;				// ドロップ時の処理を行うdelegate
}

// 初期化処理
- (void)awakeFromNib;

// Viewの描画
- (void)drawRect:(NSRect) dirtyRect;

// delegateの設定
- (void)setDelegate:(id)delegate;

//
// NSDraggingDestination Protocol
//
- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender;
- (void)draggingExited:(id <NSDraggingInfo>)sender;
- (BOOL)performDragOperation:(id <NSDraggingInfo>)sender;
- (void)concludeDragOperation:(id <NSDraggingInfo>)sender;

//
// 内部メソッド
//
// ドラッグ中に設定
- (void)setDragging:(BOOL)bDragging;

// ドラッグ情報からファイルリスト取得
- (NSArray *)fileListInDraggingInfo:(id <NSDraggingInfo>)info;

@end

UCDropView.m : ドロップビュークラスの実装ファイル

#import "UCDropView.h"

@implementation UCDropView
//
// 初期処理
//
- (void)awakeFromNib
{
    if ( [[self superclass] instancesRespondToSelector:@selector(awakeFromNib)] ) {
        [super awakeFromNib];
    }
	
    // ドラッグ受付対象の登録(ファインダーからのファイルパス)
    NSArray *arrTypes = [NSArray arrayWithObject:NSFilenamesPboardType];
    [self registerForDraggedTypes:arrTypes];
	
	mbDragging = NO;
	moDelegate = nil;
}

//
// 描画メソッド
//
- (void)drawRect:(NSRect) dirtyRect
{
	NSEraseRect(dirtyRect);
	
	[[NSColor colorWithCalibratedRed:0.3647 green:0.7373 blue:0.5922 alpha:1.0] set];
	NSRectFill(dirtyRect);
	
	NSFont *oFont = [NSFont fontWithName:@"Helvetica" size:24.0];
	NSDictionary *dicAttr = [NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:oFont, [NSColor blueColor], nil]
														forKeys:[NSArray arrayWithObjects:NSFontAttributeName, NSForegroundColorAttributeName, nil]];
	NSAttributedString * oAttrStr = [[[NSAttributedString alloc] initWithString:@"Drop Files Here" attributes:dicAttr] autorelease];
	float fX = (dirtyRect.size.width - [oAttrStr size].width) / 2.0;
	float fY = dirtyRect.size.height / 2.0 - [oAttrStr size].height /2.0;
	[oAttrStr drawAtPoint:NSMakePoint( fX, fY )];
	
	[[NSColor blackColor] set];
	NSFrameRect(dirtyRect);
	
	if ( mbDragging == YES ) {
        // ドラッギング中はフレーム枠を強調表示
        [[NSColor selectedControlColor] set];
        NSFrameRectWithWidth( dirtyRect, 2.0 );
    }
	
}

//
// delegateの設定
//
- (void)setDelegate:(id)delegate
{
	moDelegate = delegate;
}

//
// NSDraggingDestination Protocol
//
//
// Dragging in
//
- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
{
	[self setDragging:YES];
	//return NSDragOperationGeneric;
	return NSDragOperationCopy;		// ドラッグ中のカーソルが"+"になる
}

//
// Dragging out
//
- (void)draggingExited:(id <NSDraggingInfo>)sender
{
	[self setDragging:NO];
}

//
// ドロップ時の処理
//
- (BOOL)performDragOperation:(id <NSDraggingInfo>)sender
{
	NSArray *parrFiles = [self fileListInDraggingInfo:sender];
	if ( [moDelegate respondsToSelector:@selector(droppedFiles:)] ) {
		[moDelegate droppedFiles:parrFiles];
	}
	
	return YES;
}

//
// ドロップ完了
//
- (void)concludeDragOperation:(id <NSDraggingInfo>)sender
{
	[self setDragging:NO];
}

//
// 内部メソッド
//
//
// ドラッギング状態の設定と強制再描画
//
- (void)setDragging:(BOOL)bDragging
{
	mbDragging = bDragging;
	
	// 強調表示制御のために強制再描画要求
    [self setNeedsDisplay:YES];
}

//
// ドラッグ情報からファイルリストを取得する
//
- (NSArray *)fileListInDraggingInfo:(id <NSDraggingInfo>)info
{
	// ペーストボードオブジェクト取得
    NSPasteboard *oPasteBd = [info draggingPasteboard];
	
    // ドラッッグされたファイルの一覧取得
    NSArray *arrFiles = [oPasteBd propertyListForType:NSFilenamesPboardType];
	
    return arrFiles;
}

@end

●Application delegateクラスの実装

Xcode 3ではプロジェクト作成時に自動的にアプリケーションクラスのdelegateクラスが作成されます。(RenameByDateAppDelegate)
デフィルトではウィンドウへのアウトレットだけのひな形が作成されます。
これに画面上の各コントロールへのアウトレットを追加します。続いてInterface Builderでコントロールとアウトレットの接続を行います。
接続はInterface BuilderのMainMenu.xibのRename By Dateオブジェクトの上でコントロールキーを押しながらマウスを目的のコントロールの上までドラッグさせてボタンを離したときに表示されるアウトレットのリストから目的のものを選びます。

またUCDropViewにファイルがドロップされたときのdelegateメソッドも実装します。(今回はドロップされたファイルのパスとディレクトリか否かのフラグ、ファイルの更新日付をNSLogでコンソールに出力するだけです)

どを実装します。

RenameByDateAppDelegate.h : Application delagate

#import <Cocoa/Cocoa.h>
#import "UCDropView.h"

@interface RenameByDateAppDelegate : NSObject <NSApplicationDelegate> {
    NSWindow *window;
	UCDropView			*outDropView;	// Outlet : ファイルのドロップ領域のView
	NSProgressIndicator *outProgInd;	// Outlet : プログレスバー
	NSTextField			*outPrefix;		// Outlet : Prefixテキストフィールド
	NSButton			*outBtnCancel;	// Outlet : キャンセルボタン
}

@property (assign) IBOutlet NSWindow *window;
@property (assign) IBOutlet UCDropView *outDropView;
@property (assign) IBOutlet NSProgressIndicator *outProgInd;
@property (assign) IBOutlet NSTextField *outPrefix;
@property (assign) IBOutlet NSButton *outBtnCancel;

// アプリケーション起動時の処理
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification;

// UCDropViewからのコールバック(delegate)
- (void)droppedFiles:(NSArray *)arrFileList;

@end

RenameByDateAppDelegate.m : Application delagate

#import "RenameByDateAppDelegate.h"

@implementation RenameByDateAppDelegate

@synthesize window;
@synthesize outDropView;
@synthesize outProgInd;
@synthesize outPrefix;
@synthesize outBtnCancel;

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
	// Insert code here to initialize your application 
	// ドロップ時にファイルリストの通知をもらうようにする
	[outDropView setDelegate:self];
}

//
// UCDropViewからのコールバック(delegate)
//
- (void)droppedFiles:(NSArray *)arrFileList
{
	NSFileManager	*oFM = [NSFileManager defaultManager];
	BOOL	bDir;
	
	for ( NSString *strPath in arrFileList ) {
		[oFM fileExistsAtPath:strPath isDirectory:&bDir];
		NSDictionary *dicAttr = [oFM attributesOfItemAtPath:strPath error:NULL];
		NSDate	*oModDate = [dicAttr objectForKey:NSFileModificationDate];
		NSLog( @"%@, %d, %@\n", strPath, bDir, oModDate );
	}
}	

@end

サンプルプログラムのダウンロード(33KB)

【作成・確認環境】
MacOS X v10.6.4
Xcode v3.2.2

一覧に戻る