Browse files

Initial commit

git-svn-id: https://time-tracker-mac.googlecode.com/svn/trunk@2 4511c099-ca26-0410-9445-25cf1b1ba2ba
  • Loading branch information...
1 parent e5fadfd commit 433ffafa5af05c9111ec95479d6e10cad0e36b53 gruen0aermel committed Jan 11, 2007
View
BIN English.lproj/InfoPlist.strings
Binary file not shown.
View
31 English.lproj/MainMenu.nib/classes.nib
@@ -0,0 +1,31 @@
+{
+ IBClasses = (
+ {CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; },
+ {
+ ACTIONS = {
+ clickedAddProject = id;
+ clickedAddTask = id;
+ clickedChangeWorkPeriod = id;
+ clickedCountIdleTimeNo = id;
+ clickedCountIdleTimeYes = id;
+ clickedDelete = id;
+ clickedStartStopTimer = id;
+ };
+ CLASS = MainController;
+ LANGUAGE = ObjC;
+ OUTLETS = {
+ dtpEditWorkPeriodEndTime = id;
+ dtpEditWorkPeriodStartTime = id;
+ mainWindow = id;
+ panelEditWorkPeriod = id;
+ panelIdleNotification = id;
+ tvProjects = id;
+ tvTasks = id;
+ tvWorkPeriods = id;
+ };
+ SUPERCLASS = NSObject;
+ },
+ {CLASS = NSDatePicker; LANGUAGE = ObjC; SUPERCLASS = NSControl; }
+ );
+ IBVersion = 1;
+}
View
21 English.lproj/MainMenu.nib/info.nib
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>IBDocumentLocation</key>
+ <string>77 18 356 240 0 0 1024 746 </string>
+ <key>IBEditorPositions</key>
+ <dict>
+ <key>29</key>
+ <string>238 554 338 44 0 0 1024 746 </string>
+ </dict>
+ <key>IBFramework Version</key>
+ <string>439.0</string>
+ <key>IBOpenObjects</key>
+ <array>
+ <integer>29</integer>
+ </array>
+ <key>IBSystem Version</key>
+ <string>8F46</string>
+</dict>
+</plist>
View
BIN English.lproj/MainMenu.nib/keyedobjects.nib
Binary file not shown.
View
33 English.lproj/MainMenu~.nib/classes.nib
@@ -0,0 +1,33 @@
+{
+ IBClasses = (
+ {CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; },
+ {
+ ACTIONS = {
+ clickedAddProject = id;
+ clickedAddTask = id;
+ clickedChangeWorkPeriod = id;
+ clickedCountIdleTimeNo = id;
+ clickedCountIdleTimeYes = id;
+ clickedDeleteProject = id;
+ clickedDeleteTask = id;
+ clickedDeleteWorkPeriod = id;
+ clickedStartStopTimer = id;
+ };
+ CLASS = MainController;
+ LANGUAGE = ObjC;
+ OUTLETS = {
+ dtpEditWorkPeriodEndTime = id;
+ dtpEditWorkPeriodStartTime = id;
+ mainWindow = id;
+ panelEditWorkPeriod = id;
+ panelIdleNotification = id;
+ tvProjects = id;
+ tvTasks = id;
+ tvWorkPeriods = id;
+ };
+ SUPERCLASS = NSObject;
+ },
+ {CLASS = NSDatePicker; LANGUAGE = ObjC; SUPERCLASS = NSControl; }
+ );
+ IBVersion = 1;
+}
View
21 English.lproj/MainMenu~.nib/info.nib
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>IBDocumentLocation</key>
+ <string>77 18 356 240 0 0 1024 746 </string>
+ <key>IBEditorPositions</key>
+ <dict>
+ <key>29</key>
+ <string>238 554 338 44 0 0 1024 746 </string>
+ </dict>
+ <key>IBFramework Version</key>
+ <string>439.0</string>
+ <key>IBOpenObjects</key>
+ <array>
+ <integer>21</integer>
+ </array>
+ <key>IBSystem Version</key>
+ <string>8F46</string>
+</dict>
+</plist>
View
BIN English.lproj/MainMenu~.nib/keyedobjects.nib
Binary file not shown.
View
BIN Graphics/addprojecttool.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN Graphics/addtasktool.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN Graphics/appicon.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN Graphics/playitem.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN Graphics/playitem_hl.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN Graphics/playtool.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN Graphics/stopitem.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN Graphics/stopitem_hl.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN Graphics/stoptool.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN Icon.icns
Binary file not shown.
View
26 Info.plist
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>English</string>
+ <key>CFBundleExecutable</key>
+ <string>Time Tracker</string>
+ <key>CFBundleIconFile</key>
+ <string>Icon</string>
+ <key>CFBundleIdentifier</key>
+ <string>com.slooz.timetracker</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>1.0</string>
+ <key>NSMainNibFile</key>
+ <string>MainMenu</string>
+ <key>NSPrincipalClass</key>
+ <string>NSApplication</string>
+</dict>
+</plist>
View
4 LICENSE.txt
@@ -0,0 +1,4 @@
+Time Tracker is licensed under the GPL license. For other licensing options, please
+email junker@slooz.com
+
+(c) 2006, Ivan Dramaliev
View
64 MainController.h
@@ -0,0 +1,64 @@
+/* MainController */
+
+#import <Cocoa/Cocoa.h>
+#import "TProject.h"
+#import "TTask.h"
+#import "TWorkPeriod.h"
+
+@interface MainController : NSObject
+{
+ NSUserDefaults *defaults;
+ NSTimer *timer;
+ NSStatusItem *statusItem;
+ NSMenuItem *startStopMenuItem;
+
+ NSImage *playItemImage;
+ NSImage *playItemHighlightImage;
+
+ NSImage *stopItemImage;
+ NSImage *stopItemHighlightImage;
+
+ NSImage *playToolImage;
+ NSImage *stopToolImage;
+ NSImage *addTaskToolImage;
+ NSImage *addProjectToolImage;
+
+
+ IBOutlet NSTableView *tvProjects;
+ IBOutlet NSTableView *tvTasks;
+ IBOutlet NSTableView *tvWorkPeriods;
+ IBOutlet NSWindow *mainWindow;
+ IBOutlet NSPanel *panelEditWorkPeriod;
+ IBOutlet NSPanel *panelIdleNotification;
+
+ IBOutlet NSDatePicker *dtpEditWorkPeriodStartTime;
+ IBOutlet NSDatePicker *dtpEditWorkPeriodEndTime;
+
+ NSToolbarItem *startstopToolbarItem;
+ NSToolbarItem *addProjectToolbarItem;
+ NSToolbarItem *addTaskToolbarItem;
+
+ NSMutableArray *_projects;
+ TProject *_selProject;
+ TTask *_selTask;
+ TWorkPeriod *_curWorkPeriod;
+ TProject *_curProject;
+ TTask *_curTask;
+
+ NSDate *_lastNonIdleTime;
+}
+
+// actions
+- (IBAction)clickedAddProject:(id)sender;
+- (IBAction)clickedAddTask:(id)sender;
+- (IBAction)clickedStartStopTimer:(id)sender;
+- (IBAction)clickedDelete:(id)sender;
+- (IBAction)clickedChangeWorkPeriod:(id)sender;
+- (IBAction)clickedCountIdleTimeYes:(id)sender;
+- (IBAction)clickedCountIdleTimeNo:(id)sender;
+
+- (void) timerFunc: (NSTimer *) timer;
+- (void) stopTimer;
+- (int)idleTime;
+
+@end
View
564 MainController.m
@@ -0,0 +1,564 @@
+#include <IOKit/IOKitLib.h>
+
+#import "MainController.h"
+#import "TTask.h"
+#import "TProject.h"
+#import "TimeIntervalFormatter.h"
+#import "TWorkPeriod.h"
+
+@implementation MainController
+
+- (id) init
+{
+ _projects = [NSMutableArray new];
+ _selProject = nil;
+ _selTask = nil;
+ _curTask = nil;
+ _curProject = nil;
+ timer = nil;
+
+ return self;
+}
+
+- (IBAction)clickedStartStopTimer:(id)sender
+{
+ if (timer == nil) {
+ if (_selTask == nil)
+ return;
+ timer = [NSTimer scheduledTimerWithTimeInterval: 1 target: self selector: @selector (timerFunc:)
+ userInfo: nil repeats: YES];
+
+ [statusItem setImage:stopItemImage];
+ [statusItem setAlternateImage:stopItemHighlightImage];
+
+ [startstopToolbarItem setLabel:@"Stop"];
+ [startstopToolbarItem setPaletteLabel:@"Stop"];
+ [startstopToolbarItem setToolTip:@"Stop timer"];
+ [startstopToolbarItem setImage: stopToolImage];
+
+ _curWorkPeriod = [TWorkPeriod new];
+ [_curWorkPeriod setStartTime: [NSDate date]];
+ [_curWorkPeriod setEndTime: [NSDate date]];
+
+ [_selTask addWorkPeriod: _curWorkPeriod];
+ [tvWorkPeriods reloadData];
+ _curProject = _selProject;
+ _curTask = _selTask;
+ } else {
+ _curProject = nil;
+ _curTask = nil;
+ if (_selTask == nil)
+ [startstopToolbarItem setEnabled: NO];
+ [startstopToolbarItem setLabel:@"Start"];
+ [startstopToolbarItem setPaletteLabel:@"Start"];
+ [startstopToolbarItem setToolTip:@"Start timer"];
+ [startstopToolbarItem setImage: playToolImage];
+
+ [timer invalidate];
+ timer = nil;
+
+ [statusItem setImage:playItemImage];
+ [statusItem setAlternateImage:playItemHighlightImage];
+ [self stopTimer];
+
+ [_curWorkPeriod setEndTime: [NSDate date]];
+ [_curTask updateTotalTime];
+ [_curProject updateTotalTime];
+ [tvProjects reloadData];
+ [tvTasks reloadData];
+ [tvWorkPeriods reloadData];
+ }
+}
+
+- (void) stopTimer
+{
+ //[defaults setObject: [NSNumber numberWithInt: totalTime] forKey: @"TotalTime"];
+
+}
+
+- (void)toolbarWillAddItem:(NSNotification *)notification
+{
+}
+
+- (void)toolbarDidRemoveItem:(NSNotification *)notification
+{
+}
+
+- (NSToolbarItem *)toolbar:(NSToolbar *)toolbar itemForItemIdentifier:(NSString *)itemIdentifier willBeInsertedIntoToolbar:(BOOL)flag
+{
+ NSToolbarItem *toolbarItem = [[[NSToolbarItem alloc] initWithItemIdentifier: itemIdentifier] autorelease];
+
+ if ([itemIdentifier isEqual: @"Startstop"]) {
+ startstopToolbarItem = toolbarItem;
+ [toolbarItem setLabel:@"Start"];
+ [toolbarItem setPaletteLabel:@"Start"];
+ [toolbarItem setToolTip:@"Start timer"];
+ [toolbarItem setImage: playToolImage];
+ [toolbarItem setTarget:self];
+ [toolbarItem setAction:@selector(clickedStartStopTimer:)];
+ [toolbarItem setAutovalidates: NO];
+ [toolbarItem setEnabled: NO];
+ }
+
+ if ([itemIdentifier isEqual: @"AddProject"]) {
+ addProjectToolbarItem = toolbarItem;
+ [toolbarItem setLabel:@"Add project"];
+ [toolbarItem setPaletteLabel:@"Add project"];
+ [toolbarItem setToolTip:@"Add project"];
+ [toolbarItem setImage: addProjectToolImage];
+ [toolbarItem setTarget:self];
+ [toolbarItem setAction:@selector(clickedAddProject:)];
+ }
+
+ if ([itemIdentifier isEqual: @"AddTask"]) {
+ addTaskToolbarItem = toolbarItem;
+ [toolbarItem setLabel:@"Add task"];
+ [toolbarItem setPaletteLabel:@"Add task"];
+ [toolbarItem setToolTip:@"Add task"];
+ [toolbarItem setImage: addTaskToolImage];
+ [toolbarItem setTarget:self];
+ [toolbarItem setAction:@selector(clickedAddTask:)];
+ [toolbarItem setAutovalidates: NO];
+ [toolbarItem setEnabled: NO];
+ }
+
+ return toolbarItem;
+}
+
+- (NSArray *)toolbarAllowedItemIdentifiers:(NSToolbar *)toolbar
+{
+ return [NSArray arrayWithObjects: @"Startstop", NSToolbarSeparatorItemIdentifier, @"AddProject", @"AddTask", nil];
+}
+
+- (NSArray *)toolbarDefaultItemIdentifiers:(NSToolbar *)toolbar
+{
+ return [NSArray arrayWithObjects: @"Startstop", NSToolbarSeparatorItemIdentifier, @"AddProject", @"AddTask", nil];
+}
+
+- (NSArray *)toolbarSelectableItemIdentifiers:(NSToolbar *)toolbar
+{
+ return nil;
+}
+
+- (void)awakeFromNib
+{
+
+ defaults = [NSUserDefaults standardUserDefaults];
+
+ NSData *theData=[[NSUserDefaults standardUserDefaults] dataForKey:@"ProjectTimes"];
+ if (theData != nil)
+ _projects = (NSMutableArray *)[[NSMutableArray arrayWithArray: [NSUnarchiver unarchiveObjectWithData:theData]] retain];
+
+ //NSNumber *numTotalTime = [defaults objectForKey: @"TotalTime"];
+
+ /*NSZone *menuZone = [NSMenu menuZone];
+ NSMenu *m = [[NSMenu allocWithZone:menuZone] init];
+
+ startStopMenuItem = (NSMenuItem *)[m addItemWithTitle:@"Start" action:@selector(clickedStartStopTimer:) keyEquivalent:@""];
+ [startStopMenuItem setTarget:self];
+ [startStopMenuItem setTag:1];*/
+
+ /*if ([preferences isGrowlRunning]) {
+ [tempMenuItem setTitle:kRestartGrowl];
+ [tempMenuItem setToolTip:kRestartGrowlTooltip];
+ } else {
+ [tempMenuItem setToolTip:kStartGrowlTooltip];
+ }
+
+ tempMenuItem = (NSMenuItem *)[m addItemWithTitle:kStopGrowl action:@selector(stopGrowl:) keyEquivalent:@""];
+ [tempMenuItem setTag:2];
+ [tempMenuItem setTarget:self];
+ [tempMenuItem setToolTip:kStopGrowlTooltip];
+
+ tempMenuItem = (NSMenuItem *)[m addItemWithTitle:kStopGrowlMenu action:@selector(terminate:) keyEquivalent:@""];
+ [tempMenuItem setTag:5];
+ [tempMenuItem setTarget:NSApp];
+ [tempMenuItem setToolTip:kStopGrowlMenuTooltip];
+
+ [m addItem:[NSMenuItem separatorItem]];
+
+ tempMenuItem = (NSMenuItem *)[m addItemWithTitle:kSquelchMode action:@selector(squelchMode:) keyEquivalent:@""];
+ [tempMenuItem setTarget:self];
+ [tempMenuItem setTag:4];
+ [tempMenuItem setToolTip:kSquelchModeTooltip];
+
+ NSMenu *displays = [[NSMenu allocWithZone:menuZone] init];
+ NSString *name;
+ NSEnumerator *displayEnumerator = [[[GrowlPluginController controller] allDisplayPlugins] objectEnumerator];
+ while ((name = [displayEnumerator nextObject])) {
+ tempMenuItem = (NSMenuItem *)[displays addItemWithTitle:name action:@selector(defaultDisplay:) keyEquivalent:@""];
+ [tempMenuItem setTarget:self];
+ [tempMenuItem setTag:3];
+ }
+ tempMenuItem = (NSMenuItem *)[m addItemWithTitle:kDefaultDisplay action:NULL keyEquivalent:@""];
+ [tempMenuItem setTarget:self];
+ [tempMenuItem setSubmenu:displays];
+ [displays release];
+ [m addItem:[NSMenuItem separatorItem]];
+
+ tempMenuItem = (NSMenuItem *)[m addItemWithTitle:kOpenGrowlPreferences action:@selector(openGrowlPreferences:) keyEquivalent:@""];
+ [tempMenuItem setTarget:self];
+ [tempMenuItem setToolTip:kOpenGrowlPreferencesTooltip];*/
+
+
+ statusItem = [[[NSStatusBar systemStatusBar] statusItemWithLength:NSSquareStatusItemLength] retain];
+
+ [statusItem setTarget: self];
+ [statusItem setAction: @selector (clickedStartStopTimer:)];
+
+ NSBundle *bundle = [NSBundle mainBundle];
+
+ playItemImage = [[NSImage alloc] initWithContentsOfFile:[bundle pathForResource:@"playitem" ofType:@"png"]];
+ playItemHighlightImage = [[NSImage alloc] initWithContentsOfFile:[bundle pathForResource:@"playitem_hl" ofType:@"png"]];
+ stopItemImage = [[NSImage alloc] initWithContentsOfFile:[bundle pathForResource:@"stopitem" ofType:@"png"]];
+ stopItemHighlightImage = [[NSImage alloc] initWithContentsOfFile:[bundle pathForResource:@"stopitem_hl" ofType:@"png"]];
+
+ playToolImage = [[NSImage alloc] initWithContentsOfFile:[bundle pathForResource:@"playtool" ofType:@"png"]];
+ stopToolImage = [[NSImage alloc] initWithContentsOfFile:[bundle pathForResource:@"stoptool" ofType:@"png"]];
+ addTaskToolImage = [[NSImage alloc] initWithContentsOfFile:[bundle pathForResource:@"addtasktool" ofType:@"png"]];
+ addProjectToolImage = [[NSImage alloc] initWithContentsOfFile:[bundle pathForResource:@"addprojecttool" ofType:@"png"]];
+
+
+ [statusItem setImage:playItemImage];
+ [statusItem setAlternateImage:playItemHighlightImage];
+
+ //[statusItem setMenu:m]; // retains m
+ [statusItem setToolTip:@"Time Tracker"];
+ [statusItem setHighlightMode:NO];
+
+ //[m release];
+
+ NSToolbar *toolbar = [[NSToolbar alloc] initWithIdentifier: @"TimeTrackerToolbar"];
+ [toolbar setDelegate: self];
+ [mainWindow setToolbar: toolbar];
+ [startstopToolbarItem setEnabled: NO];
+
+ [tvWorkPeriods setTarget: self];
+ [tvWorkPeriods setDoubleAction: @selector(doubleClickWorkPeriod:)];
+}
+
+- (void) doubleClickWorkPeriod: (id) sender
+{
+ TWorkPeriod *wp = [[_selTask workPeriods] objectAtIndex: [tvWorkPeriods selectedRow]];
+ [dtpEditWorkPeriodStartTime setDateValue: [wp startTime]];
+ [dtpEditWorkPeriodEndTime setDateValue: [wp endTime]];
+ [panelEditWorkPeriod makeKeyAndOrderFront: self];
+ [NSApp runModalForWindow: panelEditWorkPeriod];
+}
+
+- (IBAction)clickedChangeWorkPeriod:(id)sender
+{
+ TWorkPeriod *wp = [[_selTask workPeriods] objectAtIndex: [tvWorkPeriods selectedRow]];
+ [wp setStartTime: [dtpEditWorkPeriodStartTime dateValue]];
+ [wp setEndTime: [dtpEditWorkPeriodEndTime dateValue]];
+ [_selTask updateTotalTime];
+ [_selProject updateTotalTime];
+ [tvProjects reloadData];
+ [tvTasks reloadData];
+ [tvWorkPeriods reloadData];
+ [NSApp stopModal];
+ [panelEditWorkPeriod orderOut: self];
+}
+
+- (void) timerFunc: (NSTimer *) atimer
+{
+ [_curWorkPeriod setEndTime: [NSDate date]];
+ [_curTask updateTotalTime];
+ [_curProject updateTotalTime];
+ [tvProjects reloadData];
+ [tvTasks reloadData];
+ [tvWorkPeriods reloadData];
+ int idleTime = [self idleTime];
+ if (idleTime == 0) {
+ [_lastNonIdleTime release];
+ _lastNonIdleTime = nil;
+ _lastNonIdleTime = [[NSDate date] retain];
+ }
+ if (idleTime > 5 * 60) {
+ [timer setFireDate: [NSDate distantFuture]];
+ [NSApp activateIgnoringOtherApps: YES];
+ [NSApp runModalForWindow: panelIdleNotification];
+ [panelIdleNotification orderOut: self];
+ }
+}
+
+- (void)windowWillClose:(NSNotification *)notification
+{
+ if ([notification object] == mainWindow)
+ [NSApp terminate: self];
+ if ([notification object] == panelEditWorkPeriod)
+ [NSApp stopModal];
+}
+
+- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender
+{
+ NSData *theData=[NSArchiver archivedDataWithRootObject:_projects];
+ [[NSUserDefaults standardUserDefaults] setObject:theData forKey:@"ProjectTimes"];
+ if (timer != nil)
+ [self stopTimer];
+ return NSTerminateNow;
+}
+
+- (int)numberOfRowsInTableView:(NSTableView *)tableView
+{
+ if (tableView == tvProjects) {
+ return [_projects count];
+ }
+ if (tableView == tvTasks) {
+ if (_selProject == nil)
+ return 0;
+ else
+ return [[_selProject tasks] count];
+ }
+ if (tableView == tvWorkPeriods) {
+ if (_selTask == nil)
+ return 0;
+ else
+ return [[_selTask workPeriods] count];
+ }
+ return 0;
+}
+
+- (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(int)rowIndex
+{
+ if (tableView == tvProjects) {
+ if ([[tableColumn identifier] isEqualToString: @"ProjectName"]) {
+ return [[_projects objectAtIndex: rowIndex] name];
+ }
+ if ([[tableColumn identifier] isEqualToString: @"TotalTime"]) {
+ return [TimeIntervalFormatter secondsToString: [[_projects objectAtIndex: rowIndex] totalTime]];
+ }
+ }
+
+ if (tableView == tvTasks) {
+ if ([[tableColumn identifier] isEqualToString: @"TaskName"]) {
+ return [[[_selProject tasks] objectAtIndex: rowIndex] name];
+ }
+ if ([[tableColumn identifier] isEqualToString: @"TotalTime"]) {
+ return [TimeIntervalFormatter secondsToString: [[[_selProject tasks] objectAtIndex: rowIndex] totalTime]];
+ }
+ }
+
+ if (tableView == tvWorkPeriods) {
+ if ([[tableColumn identifier] isEqualToString: @"Date"]) {
+ return [[[[_selTask workPeriods] objectAtIndex: rowIndex] startTime]
+ descriptionWithCalendarFormat: @"%m/%d/%Y"
+ timeZone: nil locale: nil];
+ }
+ if ([[tableColumn identifier] isEqualToString: @"StartTime"]) {
+ return [[[[_selTask workPeriods] objectAtIndex: rowIndex] startTime]
+ descriptionWithCalendarFormat: @"%H:%M:%S"
+ timeZone: nil locale: nil];
+ }
+ if ([[tableColumn identifier] isEqualToString: @"EndTime"]) {
+ NSDate *endTime = [[[_selTask workPeriods] objectAtIndex: rowIndex] endTime];
+ if (endTime == nil)
+ return @"";
+ else
+ return [endTime
+ descriptionWithCalendarFormat: @"%H:%M:%S"
+ timeZone: nil locale: nil];
+ }
+ if ([[tableColumn identifier] isEqualToString: @"Duration"]) {
+ return [TimeIntervalFormatter secondsToString: [[[_selTask workPeriods] objectAtIndex: rowIndex] totalTime]];
+ }
+ }
+
+ return nil;
+}
+
+- (IBAction)clickedAddProject:(id)sender
+{
+ TProject *proj = [TProject new];
+ [_projects addObject: proj];
+ [tvProjects reloadData];
+}
+
+- (IBAction)clickedAddTask:(id)sender
+{
+ TTask *task = [TTask new];
+ [_selProject addTask: task];
+ [tvTasks reloadData];
+}
+
+- (void)tableViewSelectionDidChange:(NSNotification *)notification
+{
+ if ([notification object] == tvProjects) {
+ if ([tvProjects selectedRow] == -1) {
+ _selProject = nil;
+ [addTaskToolbarItem setEnabled: NO];
+ } else {
+ _selProject = [_projects objectAtIndex: [tvProjects selectedRow]];
+ [addTaskToolbarItem setEnabled: YES];
+ }
+ [tvTasks deselectAll: self];
+ [tvTasks reloadData];
+ }
+
+ if ([notification object] == tvTasks) {
+ if ([tvTasks selectedRow] == -1) {
+ if (timer == nil)
+ [startstopToolbarItem setEnabled: NO];
+ _selTask = nil;
+ } else {
+ _selTask = [[_selProject tasks] objectAtIndex: [tvTasks selectedRow]];
+ [startstopToolbarItem setEnabled: YES];
+ }
+ [tvWorkPeriods reloadData];
+ }
+
+}
+
+- (void)tableView:(NSTableView *)tableView
+ setObjectValue:(id)obj
+ forTableColumn:(NSTableColumn *)tableColumn
+ row:(int)rowIndex
+{
+ if (tableView == tvProjects) {
+ if ([[tableColumn identifier] isEqualToString: @"ProjectName"])
+ [_selProject setName: obj];
+ }
+ if (tableView == tvTasks) {
+ if ([[tableColumn identifier] isEqualToString: @"TaskName"])
+ [_selTask setName: obj];
+ }
+}
+
+- (IBAction)clickedDelete:(id)sender
+{
+ if ([mainWindow firstResponder] == tvWorkPeriods) {
+ [[_selTask workPeriods] removeObjectAtIndex: [tvWorkPeriods selectedRow]];
+ [_selTask updateTotalTime];
+ [_selProject updateTotalTime];
+ [tvWorkPeriods deselectAll: self];
+ [tvWorkPeriods reloadData];
+ [tvTasks reloadData];
+ [tvProjects reloadData];
+ }
+ if ([mainWindow firstResponder] == tvTasks) {
+ [[_selProject tasks] removeObject: _selTask];
+ [_selProject updateTotalTime];
+ [tvTasks deselectAll: self];
+ [tvTasks reloadData];
+ [tvProjects reloadData];
+ }
+ if ([mainWindow firstResponder] == tvProjects) {
+ [_projects removeObject: _selProject];
+ [tvProjects deselectAll: self];
+ [tvProjects reloadData];
+ }
+}
+
+- (int)idleTime
+{
+ mach_port_t masterPort;
+ io_iterator_t iter;
+ io_registry_entry_t curObj;
+ int res = 0;
+
+ IOMasterPort(MACH_PORT_NULL, &masterPort);
+
+ IOServiceGetMatchingServices(masterPort,
+ IOServiceMatching("IOHIDSystem"),
+ &iter);
+ if (iter == 0) {
+ return 0;
+ }
+
+ curObj = IOIteratorNext(iter);
+
+ if (curObj == 0) {
+ return 0;
+ }
+
+ CFMutableDictionaryRef properties = 0;
+ CFTypeRef obj;
+
+ if (IORegistryEntryCreateCFProperties(curObj, &properties,
+ kCFAllocatorDefault, 0) ==
+ KERN_SUCCESS && properties != NULL) {
+
+ obj = CFDictionaryGetValue(properties, CFSTR("HIDIdleTime"));
+ CFRetain(obj);
+ } else {
+ obj = NULL;
+ }
+
+ if (obj) {
+ uint64_t tHandle;
+
+ CFTypeID type = CFGetTypeID(obj);
+
+ if (type == CFDataGetTypeID()) {
+ CFDataGetBytes((CFDataRef) obj,
+ CFRangeMake(0, sizeof(tHandle)),
+ (UInt8*) &tHandle);
+ } else if (type == CFNumberGetTypeID()) {
+ CFNumberGetValue((CFNumberRef)obj,
+ kCFNumberSInt64Type,
+ &tHandle);
+ } else {
+ return 0;
+ }
+
+ CFRelease(obj);
+
+ // essentially divides by 10^9
+ tHandle >>= 30;
+ res = tHandle;
+ } else {
+ }
+
+ /* Release our resources */
+ IOObjectRelease(curObj);
+ IOObjectRelease(iter);
+ CFRelease((CFTypeRef)properties);
+
+ return res;
+}
+
+- (IBAction)clickedCountIdleTimeYes:(id)sender
+{
+ [timer setFireDate: [NSDate dateWithTimeIntervalSinceNow: 1]];
+ [NSApp stopModal];
+}
+
+- (IBAction)clickedCountIdleTimeNo:(id)sender
+{
+ [NSApp stopModal];
+ [_curWorkPeriod setEndTime: _lastNonIdleTime];
+ [_lastNonIdleTime release];
+ _lastNonIdleTime = nil;
+ [_curTask updateTotalTime];
+ [_curProject updateTotalTime];
+ [tvProjects reloadData];
+ [tvTasks reloadData];
+ [tvWorkPeriods reloadData];
+
+ _curProject = nil;
+ _curTask = nil;
+ if (_selTask == nil)
+ [startstopToolbarItem setEnabled: NO];
+ [startstopToolbarItem setLabel:@"Start"];
+ [startstopToolbarItem setPaletteLabel:@"Start"];
+ [startstopToolbarItem setToolTip:@"Start timer"];
+ [startstopToolbarItem setImage: playToolImage];
+
+ [timer invalidate];
+ timer = nil;
+
+ [statusItem setImage:playItemImage];
+ [statusItem setAlternateImage:playItemHighlightImage];
+ [self stopTimer];
+
+ [_curTask updateTotalTime];
+ [_curProject updateTotalTime];
+ [tvProjects reloadData];
+ [tvTasks reloadData];
+ [tvWorkPeriods reloadData];
+
+
+}
+
+
+@end
View
27 TProject.h
@@ -0,0 +1,27 @@
+//
+// TProject.h
+// Time Tracker
+//
+// Created by Ivan Dramaliev on 10/18/05.
+// Copyright 2005 __MyCompanyName__. All rights reserved.
+//
+
+#import <Cocoa/Cocoa.h>
+#import "TTask.h"
+
+@interface TProject : NSObject <NSCoding> {
+ NSString *_name;
+ NSMutableArray *_tasks;
+ int _totalTime;
+}
+
+- (NSString *) name;
+- (void) setName: (NSString *) name;
+
+- (NSMutableArray *) tasks;
+- (void) addTask: (TTask *) task;
+
+- (int) totalTime;
+- (void) updateTotalTime;
+
+@end
View
87 TProject.m
@@ -0,0 +1,87 @@
+//
+// TProject.m
+// Time Tracker
+//
+// Created by Ivan Dramaliev on 10/18/05.
+// Copyright 2005 __MyCompanyName__. All rights reserved.
+//
+
+#import "TProject.h"
+
+
+@implementation TProject
+
+- (id) init
+{
+ [self setName: @"Untitled"];
+ _tasks = [NSMutableArray new];
+ _totalTime = 0;
+ return self;
+}
+
+- (NSString *) name
+{
+ return _name;
+}
+
+- (void) setName: (NSString *) name
+{
+ [name retain];
+ [_name release];
+ _name = name;
+}
+
+- (NSMutableArray *) tasks
+{
+ return _tasks;
+}
+
+- (void) addTask: (TTask *) task
+{
+ [_tasks addObject: task];
+}
+
+- (int) totalTime
+{
+ return _totalTime;
+}
+
+- (void) updateTotalTime
+{
+ _totalTime = 0;
+ int i;
+ for (i = 0; i < [_tasks count]; i++) {
+ _totalTime += [[_tasks objectAtIndex: i] totalTime];
+ }
+}
+
+- (void)encodeWithCoder:(NSCoder *)coder
+{
+ //[super encodeWithCoder:coder];
+ if ( [coder allowsKeyedCoding] ) {
+ [coder encodeObject:_name forKey:@"PName"];
+ [coder encodeObject:_tasks forKey:@"PTasks"];
+ } else {
+ [coder encodeObject:_name];
+ [coder encodeObject:_tasks];
+ }
+ return;
+}
+
+- (id)initWithCoder:(NSCoder *)coder
+{
+ //self = [super initWithCoder:coder];
+ if ( [coder allowsKeyedCoding] ) {
+ // Can decode keys in any order
+ _name = [[coder decodeObjectForKey:@"TName"] retain];
+ _tasks = [[NSMutableArray arrayWithArray: [coder decodeObjectForKey:@"PTasks"]] retain];
+ } else {
+ // Must decode keys in same order as encodeWithCoder:
+ _name = [[coder decodeObject] retain];
+ _tasks = [[NSMutableArray arrayWithArray: [coder decodeObject]] retain];
+ }
+ [self updateTotalTime];
+ return self;
+}
+
+@end
View
28 TTask.h
@@ -0,0 +1,28 @@
+//
+// TTask.h
+// Time Tracker
+//
+// Created by Ivan Dramaliev on 10/18/05.
+// Copyright 2005 __MyCompanyName__. All rights reserved.
+//
+
+#import <Cocoa/Cocoa.h>
+#import "TWorkPeriod.h"
+
+@interface TTask : NSObject <NSCoding> {
+ NSString *_name;
+ int _totalTime;
+ NSMutableArray *_workPeriods;
+}
+
+- (NSString *) name;
+- (void) setName: (NSString *) name;
+
+- (void) addWorkPeriod: (TWorkPeriod *) workPeriod;
+- (NSMutableArray *) workPeriods;
+
+- (int) totalTime;
+- (void) updateTotalTime;
+
+
+@end
View
88 TTask.m
@@ -0,0 +1,88 @@
+//
+// TTask.m
+// Time Tracker
+//
+// Created by Ivan Dramaliev on 10/18/05.
+// Copyright 2005 __MyCompanyName__. All rights reserved.
+//
+
+#import "TTask.h"
+
+
+@implementation TTask
+
+- (id) init
+{
+ [self setName: @"Untitled"];
+ _totalTime = 0;
+ _workPeriods = [NSMutableArray new];
+ return self;
+}
+
+- (NSString *) name
+{
+ return _name;
+}
+
+- (void) setName: (NSString *) name
+{
+ [name retain];
+ [_name release];
+ _name = name;
+}
+
+- (void) addWorkPeriod: (TWorkPeriod *) workPeriod
+{
+ [_workPeriods addObject: workPeriod];
+}
+
+- (NSMutableArray *) workPeriods
+{
+ return _workPeriods;
+}
+
+- (void) updateTotalTime
+{
+ _totalTime = 0;
+ int i;
+ for (i = 0; i < [_workPeriods count]; i++) {
+ _totalTime += [[_workPeriods objectAtIndex: i] totalTime];
+ }
+}
+
+- (int) totalTime
+{
+ return _totalTime;
+}
+
+
+- (void)encodeWithCoder:(NSCoder *)coder
+{
+ //[super encodeWithCoder:coder];
+ if ( [coder allowsKeyedCoding] ) {
+ [coder encodeObject:_name forKey:@"TName"];
+ [coder encodeObject:_workPeriods forKey:@"TWorkPeriods"];
+ } else {
+ [coder encodeObject:_name];
+ [coder encodeObject:_workPeriods];
+ }
+ return;
+}
+
+- (id)initWithCoder:(NSCoder *)coder
+{
+ //self = [super initWithCoder:coder];
+ if ( [coder allowsKeyedCoding] ) {
+ // Can decode keys in any order
+ _name = [[coder decodeObjectForKey:@"TName"] retain];
+ _workPeriods = [[NSMutableArray arrayWithArray: [coder decodeObjectForKey:@"TWorkPeriods"]] retain];
+ } else {
+ // Must decode keys in same order as encodeWithCoder:
+ _name = [[coder decodeObject] retain];
+ _workPeriods = [[NSMutableArray arrayWithArray: [coder decodeObject]] retain];
+ }
+ [self updateTotalTime];
+ return self;
+}
+
+@end
View
29 TWorkPeriod.h
@@ -0,0 +1,29 @@
+//
+// TWorkPeriod.h
+// Time Tracker
+//
+// Created by Ivan Dramaliev on 10/18/05.
+// Copyright 2005 __MyCompanyName__. All rights reserved.
+//
+
+#import <Cocoa/Cocoa.h>
+
+
+@interface TWorkPeriod : NSObject <NSCoding> {
+ int _totalTime;
+ NSDate *_startTime;
+ NSDate *_endTime;
+}
+
+- (void) setStartTime: (NSDate *) startTime;
+- (void) setEndTime: (NSDate *) endTime;
+
+- (void) updateTotalTime;
+
+- (int) totalTime;
+- (void) updateTotalTime;
+
+- (NSDate *) startTime;
+- (NSDate *) endTime;
+
+@end
View
91 TWorkPeriod.m
@@ -0,0 +1,91 @@
+//
+// TWorkPeriod.m
+// Time Tracker
+//
+// Created by Ivan Dramaliev on 10/18/05.
+// Copyright 2005 __MyCompanyName__. All rights reserved.
+//
+
+#import "TWorkPeriod.h"
+
+
+@implementation TWorkPeriod
+
+- (id) init
+{
+ _startTime = nil;
+ _endTime = nil;
+ return self;
+}
+
+- (void) setStartTime: (NSDate *) startTime
+{
+ [startTime retain];
+ [_startTime release];
+ _startTime = startTime;
+ [self updateTotalTime];
+}
+
+- (void) setEndTime: (NSDate *) endTime
+{
+ [endTime retain];
+ [_endTime release];
+ _endTime = endTime;
+ [self updateTotalTime];
+}
+
+- (void) updateTotalTime
+{
+ if (_endTime == nil || _startTime == nil) {
+ _totalTime = 0;
+ return;
+ }
+ double timeInterval = [_endTime timeIntervalSinceDate: _startTime];
+ _totalTime = (int) timeInterval;
+}
+
+- (int) totalTime
+{
+ return _totalTime;
+}
+
+- (NSDate *) startTime
+{
+ return _startTime;
+}
+
+- (NSDate *) endTime
+{
+ return _endTime;
+}
+
+- (void)encodeWithCoder:(NSCoder *)coder
+{
+ //[super encodeWithCoder:coder];
+ if ( [coder allowsKeyedCoding] ) {
+ [coder encodeObject:_startTime forKey:@"WPStartTime"];
+ [coder encodeObject:_endTime forKey:@"WPEndTime"];
+ } else {
+ [coder encodeObject:_startTime];
+ [coder encodeObject:_endTime];
+ }
+ return;
+}
+
+- (id)initWithCoder:(NSCoder *)coder
+{
+ //self = [super initWithCoder:coder];
+ if ( [coder allowsKeyedCoding] ) {
+ // Can decode keys in any order
+ _startTime = [[coder decodeObjectForKey:@"WPStartTime"] retain];
+ _endTime = [[coder decodeObjectForKey:@"WPEndTime"] retain];
+ } else {
+ // Must decode keys in same order as encodeWithCoder:
+ _startTime = [[coder decodeObject] retain];
+ _endTime = [[coder decodeObject] retain];
+ }
+ [self updateTotalTime];
+ return self;
+}
+
+@end
View
425 Time Tracker.xcodeproj/project.pbxproj
@@ -0,0 +1,425 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 42;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ 2C4528A70909AACB003C0369 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2C4528A60909AACB003C0369 /* Carbon.framework */; };
+ 2C4528B20909AAE5003C0369 /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2C4528B10909AAE5003C0369 /* IOKit.framework */; };
+ 2C9DB948090675EB0039C62A /* addprojecttool.png in Resources */ = {isa = PBXBuildFile; fileRef = 2C9DB944090675EB0039C62A /* addprojecttool.png */; };
+ 2C9DB949090675EB0039C62A /* addtasktool.png in Resources */ = {isa = PBXBuildFile; fileRef = 2C9DB945090675EB0039C62A /* addtasktool.png */; };
+ 2C9DB94A090675EB0039C62A /* playtool.png in Resources */ = {isa = PBXBuildFile; fileRef = 2C9DB946090675EB0039C62A /* playtool.png */; };
+ 2C9DB94B090675EB0039C62A /* stoptool.png in Resources */ = {isa = PBXBuildFile; fileRef = 2C9DB947090675EB0039C62A /* stoptool.png */; };
+ 2C9DB974090677B20039C62A /* Icon.icns in Resources */ = {isa = PBXBuildFile; fileRef = 2C9DB973090677B20039C62A /* Icon.icns */; };
+ 2C9DD71B0905824F00AA5C6E /* playitem_hl.png in Resources */ = {isa = PBXBuildFile; fileRef = 2C9DD7170905824F00AA5C6E /* playitem_hl.png */; };
+ 2C9DD71C0905824F00AA5C6E /* playitem.png in Resources */ = {isa = PBXBuildFile; fileRef = 2C9DD7180905824F00AA5C6E /* playitem.png */; };
+ 2C9DD71D0905824F00AA5C6E /* stopitem_hl.png in Resources */ = {isa = PBXBuildFile; fileRef = 2C9DD7190905824F00AA5C6E /* stopitem_hl.png */; };
+ 2C9DD71E0905824F00AA5C6E /* stopitem.png in Resources */ = {isa = PBXBuildFile; fileRef = 2C9DD71A0905824F00AA5C6E /* stopitem.png */; };
+ 2C9EC8D20905A5F2000651F2 /* TTask.m in Sources */ = {isa = PBXBuildFile; fileRef = 2C9EC8D10905A5F2000651F2 /* TTask.m */; };
+ 2C9EC8D70905A5FE000651F2 /* TProject.m in Sources */ = {isa = PBXBuildFile; fileRef = 2C9EC8D60905A5FE000651F2 /* TProject.m */; };
+ 2C9EC93F0905A9F6000651F2 /* TimeIntervalFormatter.m in Sources */ = {isa = PBXBuildFile; fileRef = 2C9EC93E0905A9F6000651F2 /* TimeIntervalFormatter.m */; };
+ 2C9EC9540905ABAE000651F2 /* TWorkPeriod.m in Sources */ = {isa = PBXBuildFile; fileRef = 2C9EC9530905ABAE000651F2 /* TWorkPeriod.m */; };
+ 2CFAEE2D09042FC000131DD6 /* MainController.m in Sources */ = {isa = PBXBuildFile; fileRef = 2CFAEE2C09042FC000131DD6 /* MainController.m */; };
+ 8D11072A0486CEB800E47090 /* MainMenu.nib in Resources */ = {isa = PBXBuildFile; fileRef = 29B97318FDCFA39411CA2CEA /* MainMenu.nib */; };
+ 8D11072B0486CEB800E47090 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C165CFE840E0CC02AAC07 /* InfoPlist.strings */; };
+ 8D11072D0486CEB800E47090 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; settings = {ATTRIBUTES = (); }; };
+ 8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXBuildStyle section */
+ 4A9504CCFFE6A4B311CA0CBA /* Debug */ = {
+ isa = PBXBuildStyle;
+ buildSettings = {
+ COPY_PHASE_STRIP = NO;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_ENABLE_FIX_AND_CONTINUE = YES;
+ GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ PREBINDING = NO;
+ ZERO_LINK = YES;
+ };
+ name = Debug;
+ };
+ 4A9504CDFFE6A4B311CA0CBA /* Release */ = {
+ isa = PBXBuildStyle;
+ buildSettings = {
+ COPY_PHASE_STRIP = YES;
+ GCC_ENABLE_FIX_AND_CONTINUE = NO;
+ GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
+ PREBINDING = NO;
+ ZERO_LINK = NO;
+ };
+ name = Release;
+ };
+/* End PBXBuildStyle section */
+
+/* Begin PBXFileReference section */
+ 089C165DFE840E0CC02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = "<group>"; };
+ 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = "<absolute>"; };
+ 13E42FB307B3F0F600E4EEF1 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = /System/Library/Frameworks/CoreData.framework; sourceTree = "<absolute>"; };
+ 29B97316FDCFA39411CA2CEA /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
+ 29B97319FDCFA39411CA2CEA /* English */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = English; path = English.lproj/MainMenu.nib; sourceTree = "<group>"; };
+ 29B97324FDCFA39411CA2CEA /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = "<absolute>"; };
+ 29B97325FDCFA39411CA2CEA /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = "<absolute>"; };
+ 2C4528A60909AACB003C0369 /* Carbon.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = /System/Library/Frameworks/Carbon.framework; sourceTree = "<absolute>"; };
+ 2C4528B10909AAE5003C0369 /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = /System/Library/Frameworks/IOKit.framework; sourceTree = "<absolute>"; };
+ 2C9DB944090675EB0039C62A /* addprojecttool.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = addprojecttool.png; path = Graphics/addprojecttool.png; sourceTree = "<group>"; };
+ 2C9DB945090675EB0039C62A /* addtasktool.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = addtasktool.png; path = Graphics/addtasktool.png; sourceTree = "<group>"; };
+ 2C9DB946090675EB0039C62A /* playtool.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = playtool.png; path = Graphics/playtool.png; sourceTree = "<group>"; };
+ 2C9DB947090675EB0039C62A /* stoptool.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = stoptool.png; path = Graphics/stoptool.png; sourceTree = "<group>"; };
+ 2C9DB973090677B20039C62A /* Icon.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = Icon.icns; sourceTree = "<group>"; };
+ 2C9DD7170905824F00AA5C6E /* playitem_hl.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = playitem_hl.png; path = Graphics/playitem_hl.png; sourceTree = "<group>"; };
+ 2C9DD7180905824F00AA5C6E /* playitem.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = playitem.png; path = Graphics/playitem.png; sourceTree = "<group>"; };
+ 2C9DD7190905824F00AA5C6E /* stopitem_hl.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = stopitem_hl.png; path = Graphics/stopitem_hl.png; sourceTree = "<group>"; };
+ 2C9DD71A0905824F00AA5C6E /* stopitem.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = stopitem.png; path = Graphics/stopitem.png; sourceTree = "<group>"; };
+ 2C9EC8D00905A5F2000651F2 /* TTask.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TTask.h; sourceTree = "<group>"; };
+ 2C9EC8D10905A5F2000651F2 /* TTask.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TTask.m; sourceTree = "<group>"; };
+ 2C9EC8D50905A5FE000651F2 /* TProject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TProject.h; sourceTree = "<group>"; };
+ 2C9EC8D60905A5FE000651F2 /* TProject.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TProject.m; sourceTree = "<group>"; };
+ 2C9EC93D0905A9F6000651F2 /* TimeIntervalFormatter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TimeIntervalFormatter.h; sourceTree = "<group>"; };
+ 2C9EC93E0905A9F6000651F2 /* TimeIntervalFormatter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TimeIntervalFormatter.m; sourceTree = "<group>"; };
+ 2C9EC9520905ABAE000651F2 /* TWorkPeriod.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TWorkPeriod.h; sourceTree = "<group>"; };
+ 2C9EC9530905ABAE000651F2 /* TWorkPeriod.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TWorkPeriod.m; sourceTree = "<group>"; };
+ 2CFAEE2B09042FC000131DD6 /* MainController.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = MainController.h; sourceTree = "<group>"; };
+ 2CFAEE2C09042FC000131DD6 /* MainController.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = MainController.m; sourceTree = "<group>"; };
+ 32CA4F630368D1EE00C91783 /* Time Tracker_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "Time Tracker_Prefix.pch"; sourceTree = "<group>"; };
+ 8D1107310486CEB800E47090 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; };
+ 8D1107320486CEB800E47090 /* Time Tracker.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Time Tracker.app"; sourceTree = BUILT_PRODUCTS_DIR; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ 8D11072E0486CEB800E47090 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */,
+ 2C4528A70909AACB003C0369 /* Carbon.framework in Frameworks */,
+ 2C4528B20909AAE5003C0369 /* IOKit.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 080E96DDFE201D6D7F000001 /* Classes */ = {
+ isa = PBXGroup;
+ children = (
+ 2C9EC9520905ABAE000651F2 /* TWorkPeriod.h */,
+ 2C9EC9530905ABAE000651F2 /* TWorkPeriod.m */,
+ 2C9EC93D0905A9F6000651F2 /* TimeIntervalFormatter.h */,
+ 2C9EC93E0905A9F6000651F2 /* TimeIntervalFormatter.m */,
+ 2C9EC8D00905A5F2000651F2 /* TTask.h */,
+ 2C9EC8D10905A5F2000651F2 /* TTask.m */,
+ 2C9EC8D50905A5FE000651F2 /* TProject.h */,
+ 2C9EC8D60905A5FE000651F2 /* TProject.m */,
+ 2CFAEE2B09042FC000131DD6 /* MainController.h */,
+ 2CFAEE2C09042FC000131DD6 /* MainController.m */,
+ );
+ name = Classes;
+ sourceTree = "<group>";
+ };
+ 1058C7A0FEA54F0111CA2CBB /* Linked Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ 2C4528A60909AACB003C0369 /* Carbon.framework */,
+ 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */,
+ );
+ name = "Linked Frameworks";
+ sourceTree = "<group>";
+ };
+ 1058C7A2FEA54F0111CA2CBB /* Other Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ 2C4528B10909AAE5003C0369 /* IOKit.framework */,
+ 29B97324FDCFA39411CA2CEA /* AppKit.framework */,
+ 13E42FB307B3F0F600E4EEF1 /* CoreData.framework */,
+ 29B97325FDCFA39411CA2CEA /* Foundation.framework */,
+ );
+ name = "Other Frameworks";
+ sourceTree = "<group>";
+ };
+ 19C28FACFE9D520D11CA2CBB /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 8D1107320486CEB800E47090 /* Time Tracker.app */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ 29B97314FDCFA39411CA2CEA /* Time Tracker */ = {
+ isa = PBXGroup;
+ children = (
+ 2C9DD7100905824100AA5C6E /* Graphics */,
+ 080E96DDFE201D6D7F000001 /* Classes */,
+ 29B97315FDCFA39411CA2CEA /* Other Sources */,
+ 29B97317FDCFA39411CA2CEA /* Resources */,
+ 29B97323FDCFA39411CA2CEA /* Frameworks */,
+ 19C28FACFE9D520D11CA2CBB /* Products */,
+ );
+ name = "Time Tracker";
+ sourceTree = "<group>";
+ };
+ 29B97315FDCFA39411CA2CEA /* Other Sources */ = {
+ isa = PBXGroup;
+ children = (
+ 32CA4F630368D1EE00C91783 /* Time Tracker_Prefix.pch */,
+ 29B97316FDCFA39411CA2CEA /* main.m */,
+ );
+ name = "Other Sources";
+ sourceTree = "<group>";
+ };
+ 29B97317FDCFA39411CA2CEA /* Resources */ = {
+ isa = PBXGroup;
+ children = (
+ 2C9DB973090677B20039C62A /* Icon.icns */,
+ 8D1107310486CEB800E47090 /* Info.plist */,
+ 089C165CFE840E0CC02AAC07 /* InfoPlist.strings */,
+ 29B97318FDCFA39411CA2CEA /* MainMenu.nib */,
+ );
+ name = Resources;
+ sourceTree = "<group>";
+ };
+ 29B97323FDCFA39411CA2CEA /* Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ 1058C7A0FEA54F0111CA2CBB /* Linked Frameworks */,
+ 1058C7A2FEA54F0111CA2CBB /* Other Frameworks */,
+ );
+ name = Frameworks;
+ sourceTree = "<group>";
+ };
+ 2C9DD7100905824100AA5C6E /* Graphics */ = {
+ isa = PBXGroup;
+ children = (
+ 2C9DB944090675EB0039C62A /* addprojecttool.png */,
+ 2C9DB945090675EB0039C62A /* addtasktool.png */,
+ 2C9DB946090675EB0039C62A /* playtool.png */,
+ 2C9DB947090675EB0039C62A /* stoptool.png */,
+ 2C9DD7170905824F00AA5C6E /* playitem_hl.png */,
+ 2C9DD7180905824F00AA5C6E /* playitem.png */,
+ 2C9DD7190905824F00AA5C6E /* stopitem_hl.png */,
+ 2C9DD71A0905824F00AA5C6E /* stopitem.png */,
+ );
+ name = Graphics;
+ sourceTree = "<group>";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+ 8D1107260486CEB800E47090 /* Time Tracker */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 2CFAEE2109042EE900131DD6 /* Build configuration list for PBXNativeTarget "Time Tracker" */;
+ buildPhases = (
+ 8D1107290486CEB800E47090 /* Resources */,
+ 8D11072C0486CEB800E47090 /* Sources */,
+ 8D11072E0486CEB800E47090 /* Frameworks */,
+ );
+ buildRules = (
+ );
+ buildSettings = {
+ GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
+ GCC_PRECOMPILE_PREFIX_HEADER = YES;
+ GCC_PREFIX_HEADER = "Time Tracker_Prefix.pch";
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ INFOPLIST_FILE = Info.plist;
+ INSTALL_PATH = "$(HOME)/Applications";
+ PRODUCT_NAME = "Time Tracker";
+ WRAPPER_EXTENSION = app;
+ };
+ dependencies = (
+ );
+ name = "Time Tracker";
+ productInstallPath = "$(HOME)/Applications";
+ productName = "Time Tracker";
+ productReference = 8D1107320486CEB800E47090 /* Time Tracker.app */;
+ productType = "com.apple.product-type.application";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 29B97313FDCFA39411CA2CEA /* Project object */ = {
+ isa = PBXProject;
+ buildConfigurationList = 2CFAEE2509042EE900131DD6 /* Build configuration list for PBXProject "Time Tracker" */;
+ buildSettings = {
+ };
+ buildStyles = (
+ 4A9504CCFFE6A4B311CA0CBA /* Debug */,
+ 4A9504CDFFE6A4B311CA0CBA /* Release */,
+ );
+ hasScannedForEncodings = 1;
+ mainGroup = 29B97314FDCFA39411CA2CEA /* Time Tracker */;
+ projectDirPath = "";
+ targets = (
+ 8D1107260486CEB800E47090 /* Time Tracker */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+ 8D1107290486CEB800E47090 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 8D11072A0486CEB800E47090 /* MainMenu.nib in Resources */,
+ 8D11072B0486CEB800E47090 /* InfoPlist.strings in Resources */,
+ 2C9DD71B0905824F00AA5C6E /* playitem_hl.png in Resources */,
+ 2C9DD71C0905824F00AA5C6E /* playitem.png in Resources */,
+ 2C9DD71D0905824F00AA5C6E /* stopitem_hl.png in Resources */,
+ 2C9DD71E0905824F00AA5C6E /* stopitem.png in Resources */,
+ 2C9DB948090675EB0039C62A /* addprojecttool.png in Resources */,
+ 2C9DB949090675EB0039C62A /* addtasktool.png in Resources */,
+ 2C9DB94A090675EB0039C62A /* playtool.png in Resources */,
+ 2C9DB94B090675EB0039C62A /* stoptool.png in Resources */,
+ 2C9DB974090677B20039C62A /* Icon.icns in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ 8D11072C0486CEB800E47090 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 8D11072D0486CEB800E47090 /* main.m in Sources */,
+ 2CFAEE2D09042FC000131DD6 /* MainController.m in Sources */,
+ 2C9EC8D20905A5F2000651F2 /* TTask.m in Sources */,
+ 2C9EC8D70905A5FE000651F2 /* TProject.m in Sources */,
+ 2C9EC93F0905A9F6000651F2 /* TimeIntervalFormatter.m in Sources */,
+ 2C9EC9540905ABAE000651F2 /* TWorkPeriod.m in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXVariantGroup section */
+ 089C165CFE840E0CC02AAC07 /* InfoPlist.strings */ = {
+ isa = PBXVariantGroup;
+ children = (
+ 089C165DFE840E0CC02AAC07 /* English */,
+ );
+ name = InfoPlist.strings;
+ sourceTree = "<group>";
+ };
+ 29B97318FDCFA39411CA2CEA /* MainMenu.nib */ = {
+ isa = PBXVariantGroup;
+ children = (
+ 29B97319FDCFA39411CA2CEA /* English */,
+ );
+ name = MainMenu.nib;
+ sourceTree = "<group>";
+ };
+/* End PBXVariantGroup section */
+
+/* Begin XCBuildConfiguration section */
+ 2CFAEE2209042EE900131DD6 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ARCHS = ppc;
+ COPY_PHASE_STRIP = NO;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_ENABLE_FIX_AND_CONTINUE = YES;
+ GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PRECOMPILE_PREFIX_HEADER = YES;
+ GCC_PREFIX_HEADER = "Time Tracker_Prefix.pch";
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ INFOPLIST_FILE = Info.plist;
+ INSTALL_PATH = "$(HOME)/Applications";
+ PREBINDING = NO;
+ PRODUCT_NAME = "Time Tracker";
+ WRAPPER_EXTENSION = app;
+ ZERO_LINK = YES;
+ };
+ name = Debug;
+ };
+ 2CFAEE2309042EE900131DD6 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ARCHS = ppc;
+ COPY_PHASE_STRIP = YES;
+ GCC_ENABLE_FIX_AND_CONTINUE = NO;
+ GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
+ GCC_PRECOMPILE_PREFIX_HEADER = YES;
+ GCC_PREFIX_HEADER = "Time Tracker_Prefix.pch";
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ INFOPLIST_FILE = Info.plist;
+ INSTALL_PATH = "$(HOME)/Applications";
+ PREBINDING = NO;
+ PRODUCT_NAME = "Time Tracker";
+ WRAPPER_EXTENSION = app;
+ ZERO_LINK = NO;
+ };
+ name = Release;
+ };
+ 2CFAEE2409042EE900131DD6 /* Default */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ARCHS = (
+ "<Multiple",
+ "values>",
+ ppc,
+ );
+ GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
+ GCC_PRECOMPILE_PREFIX_HEADER = YES;
+ GCC_PREFIX_HEADER = "Time Tracker_Prefix.pch";
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ INFOPLIST_FILE = Info.plist;
+ INSTALL_PATH = "$(HOME)/Applications";
+ PRODUCT_NAME = "Time Tracker";
+ WRAPPER_EXTENSION = app;
+ };
+ name = Default;
+ };
+ 2CFAEE2609042EE900131DD6 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ };
+ name = Debug;
+ };
+ 2CFAEE2709042EE900131DD6 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ };
+ name = Release;
+ };
+ 2CFAEE2809042EE900131DD6 /* Default */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ };
+ name = Default;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 2CFAEE2109042EE900131DD6 /* Build configuration list for PBXNativeTarget "Time Tracker" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 2CFAEE2209042EE900131DD6 /* Debug */,
+ 2CFAEE2309042EE900131DD6 /* Release */,
+ 2CFAEE2409042EE900131DD6 /* Default */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Default;
+ };
+ 2CFAEE2509042EE900131DD6 /* Build configuration list for PBXProject "Time Tracker" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 2CFAEE2609042EE900131DD6 /* Debug */,
+ 2CFAEE2709042EE900131DD6 /* Release */,
+ 2CFAEE2809042EE900131DD6 /* Default */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Default;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = 29B97313FDCFA39411CA2CEA /* Project object */;
+}
View
7 Time Tracker_Prefix.pch
@@ -0,0 +1,7 @@
+//
+// Prefix header for all source files of the 'Time Tracker' target in the 'Time Tracker' project
+//
+
+#ifdef __OBJC__
+ #import <Cocoa/Cocoa.h>
+#endif
View
18 TimeIntervalFormatter.h
@@ -0,0 +1,18 @@
+//
+// TimeIntervalFormatter.h
+// Time Tracker
+//
+// Created by Ivan Dramaliev on 10/18/05.
+// Copyright 2005 __MyCompanyName__. All rights reserved.
+//
+
+#import <Cocoa/Cocoa.h>
+
+
+@interface TimeIntervalFormatter : NSObject {
+
+}
+
++ (NSString *) secondsToString: (int) seconds;
+
+@end
View
25 TimeIntervalFormatter.m
@@ -0,0 +1,25 @@
+//
+// TimeIntervalFormatter.m
+// Time Tracker
+//
+// Created by Ivan Dramaliev on 10/18/05.
+// Copyright 2005 __MyCompanyName__. All rights reserved.
+//
+
+#import "TimeIntervalFormatter.h"
+
+
+@implementation TimeIntervalFormatter
+
++ (NSString *) secondsToString: (int) seconds
+{
+ int hours = seconds / 3600;
+ int minutes = (seconds % 3600) / 60;
+ int secs = seconds % 60;
+ return [NSString stringWithFormat: @"%@%d:%@%d:%@%d",
+ (hours < 10 ? @"0" : @""), hours,
+ (minutes < 10 ? @"0" : @""), minutes,
+ (secs < 10 ? @"0" : @""), secs];
+}
+
+@end
View
14 main.m
@@ -0,0 +1,14 @@
+//
+// main.m
+// Time Tracker
+//
+// Created by Ivan Dramaliev on 10/17/05.
+// Copyright __MyCompanyName__ 2005. All rights reserved.
+//
+
+#import <Cocoa/Cocoa.h>
+
+int main(int argc, char *argv[])
+{
+ return NSApplicationMain(argc, (const char **) argv);
+}

0 comments on commit 433ffaf

Please sign in to comment.