1 /* 2 * Copyright 2005 - 2008, Haiku, Inc. 3 * Distributed under the terms of the MIT license. 4 * 5 * Authors: 6 * Robert Polic 7 * Axel Dörfler, axeld@pinc-software.de 8 * 9 * Copyright 1999, Be Incorporated. All Rights Reserved. 10 * This file may be used under the terms of the Be Sample Code License. 11 */ 12 13 14 #include <Bitmap.h> 15 #include <Directory.h> 16 #include <Volume.h> 17 #include <VolumeRoster.h> 18 #include <Path.h> 19 #include <FindDirectory.h> 20 #include <Screen.h> 21 #include <Alert.h> 22 #include <fs_index.h> 23 24 #include "PeopleApp.h" 25 #include "PeopleWindow.h" 26 #include "PersonIcons.h" 27 28 #include <string.h> 29 30 31 struct people_field gFields[] = { 32 { "META:name", 120, "Contact Name" }, 33 { "META:nickname", 120, "Nickname" }, 34 { "META:company", 120, "Company" }, 35 { "META:address", 120, "Address" }, 36 { "META:city", 90, "City" }, 37 { "META:state", 50, "State" }, 38 { "META:zip", 50, "Zip" }, 39 { "META:country", 120, "Country" }, 40 { "META:hphone", 90, "Home Phone" }, 41 { "META:wphone", 90, "Work Phone" }, 42 { "META:fax", 90, "Fax" }, 43 { "META:email", 120, "E-mail" }, 44 { "META:url", 120, "URL" }, 45 { "META:group", 120, "Group" }, 46 { NULL, 0, NULL } 47 }; 48 49 50 TPeopleApp::TPeopleApp(void) 51 : BApplication(APP_SIG), 52 fWindowCount(0) 53 { 54 fPosition.Set(6, TITLE_BAR_HEIGHT, 6 + WIND_WIDTH, TITLE_BAR_HEIGHT + WIND_HEIGHT); 55 BPoint pos = fPosition.LeftTop(); 56 57 BPath path; 58 find_directory(B_USER_SETTINGS_DIRECTORY, &path, true); 59 60 BDirectory dir(path.Path()); 61 BEntry entry; 62 if (dir.FindEntry("People_data", &entry) == B_NO_ERROR) { 63 fPrefs = new BFile(&entry, B_READ_WRITE); 64 if (fPrefs->InitCheck() == B_NO_ERROR) { 65 fPrefs->Read(&pos, sizeof(BPoint)); 66 if (BScreen(B_MAIN_SCREEN_ID).Frame().Contains(pos)) 67 fPosition.OffsetTo(pos); 68 } 69 } else { 70 fPrefs = new BFile(); 71 if (dir.CreateFile("People_data", fPrefs) != B_NO_ERROR) { 72 delete fPrefs; 73 fPrefs = NULL; 74 } 75 } 76 77 // create indices on all volumes 78 79 BVolumeRoster volumeRoster; 80 BVolume volume; 81 while (volumeRoster.GetNextVolume(&volume) == B_OK) { 82 for (int32 i = 0; gFields[i].attribute; i++) { 83 fs_create_index(volume.Device(), gFields[i].attribute, B_STRING_TYPE, 0); 84 } 85 } 86 87 // install person mime type 88 89 bool valid = false; 90 BMimeType mime; 91 mime.SetType(B_PERSON_MIMETYPE); 92 93 if (mime.IsInstalled()) { 94 BMessage info; 95 if (mime.GetAttrInfo(&info) == B_NO_ERROR) { 96 const char *string; 97 int32 index = 0; 98 while (info.FindString("attr:name", index++, &string) == B_OK) { 99 if (!strcmp(string, gFields[0].attribute)) { 100 valid = true; 101 break; 102 } 103 } 104 if (!valid) 105 mime.Delete(); 106 } 107 } 108 if (!valid) { 109 mime.Install(); 110 mime.SetShortDescription("Person"); 111 mime.SetLongDescription("Contact information for a person."); 112 mime.SetIcon(kPersonIcon, sizeof(kPersonIcon)); 113 mime.SetPreferredApp(APP_SIG); 114 115 // add relevant person fields to meta-mime type 116 117 BMessage fields; 118 for (int32 i = 0; gFields[i].attribute; i++) { 119 fields.AddString("attr:public_name", gFields[i].name); 120 fields.AddString("attr:name", gFields[i].attribute); 121 fields.AddInt32("attr:type", B_STRING_TYPE); 122 fields.AddBool("attr:viewable", true); 123 fields.AddBool("attr:editable", true); 124 fields.AddInt32("attr:width", gFields[i].width); 125 fields.AddInt32("attr:alignment", B_ALIGN_LEFT); 126 fields.AddBool("attr:extra", false); 127 } 128 129 mime.SetAttrInfo(&fields); 130 } 131 } 132 133 134 TPeopleApp::~TPeopleApp(void) 135 { 136 delete fPrefs; 137 } 138 139 140 void 141 TPeopleApp::AboutRequested(void) 142 { 143 (new BAlert("", "...by Robert Polic", "Big Deal"))->Go(); 144 } 145 146 147 void 148 TPeopleApp::ArgvReceived(int32 argc, char **argv) 149 { 150 TPeopleWindow* window = NULL; 151 152 for (int32 loop = 1; loop < argc; loop++) { 153 char* arg = argv[loop]; 154 155 int32 index; 156 for (index = 0; gFields[index].attribute; index++) { 157 if (!strncmp(gFields[index].attribute, arg, strlen(gFields[index].attribute))) 158 break; 159 } 160 161 if (gFields[index].attribute != NULL) { 162 if (!window) 163 window = NewWindow(); 164 165 while (arg[0] && arg[0] != ' ' && arg[0] != '=') 166 arg++; 167 168 if (arg[0]) { 169 arg++; 170 window->SetField(index, arg); 171 } 172 } 173 } 174 } 175 176 177 void 178 TPeopleApp::MessageReceived(BMessage *msg) 179 { 180 switch (msg->what) { 181 case M_NEW: 182 case B_SILENT_RELAUNCH: 183 NewWindow(); 184 break; 185 186 case M_WINDOW_QUITS: 187 SavePreferences(msg); 188 fWindowCount--; 189 if (fWindowCount < 1) 190 PostMessage(B_QUIT_REQUESTED); 191 break; 192 193 default: 194 BApplication::MessageReceived(msg); 195 } 196 } 197 198 199 void 200 TPeopleApp::RefsReceived(BMessage *message) 201 { 202 int32 index = 0; 203 204 while (message->HasRef("refs", index)) { 205 entry_ref ref; 206 message->FindRef("refs", index++, &ref); 207 208 TPeopleWindow* window = FindWindow(ref); 209 if (window != NULL) 210 window->Activate(true); 211 else { 212 BFile file(&ref, B_READ_ONLY); 213 if (file.InitCheck() == B_OK) 214 NewWindow(&ref); 215 } 216 } 217 } 218 219 220 void 221 TPeopleApp::ReadyToRun(void) 222 { 223 if (fWindowCount < 1) 224 NewWindow(); 225 } 226 227 228 TPeopleWindow* 229 TPeopleApp::NewWindow(entry_ref *ref) 230 { 231 TPeopleWindow *window; 232 233 window = new TPeopleWindow(fPosition, "New Person", ref); 234 window->Show(); 235 fWindowCount++; 236 fPosition.OffsetBy(20, 20); 237 238 if (fPosition.bottom > BScreen(B_MAIN_SCREEN_ID).Frame().bottom) 239 fPosition.OffsetTo(fPosition.left, TITLE_BAR_HEIGHT); 240 if (fPosition.right > BScreen(B_MAIN_SCREEN_ID).Frame().right) 241 fPosition.OffsetTo(6, fPosition.top); 242 243 return window; 244 } 245 246 247 TPeopleWindow* 248 TPeopleApp::FindWindow(entry_ref ref) 249 { 250 TPeopleWindow* window; 251 int32 index = 0; 252 253 while ((window = (TPeopleWindow *)WindowAt(index++))) { 254 if (window->FindView("PeopleView") != NULL && window->fRef && *window->fRef == ref) 255 return window; 256 } 257 return NULL; 258 } 259 260 261 void 262 TPeopleApp::SavePreferences(BMessage* message) 263 { 264 BRect frame; 265 if (message->FindRect("frame", &frame) != B_OK) 266 return; 267 268 BPoint leftTop = frame.LeftTop(); 269 270 if (fPrefs) { 271 fPrefs->Seek(0, 0); 272 fPrefs->Write(&leftTop, sizeof(BPoint)); 273 } 274 } 275 276