1 /* 2 Open Tracker License 3 4 Terms and Conditions 5 6 Copyright (c) 1991-2000, Be Incorporated. All rights reserved. 7 8 Permission is hereby granted, free of charge, to any person obtaining a copy of 9 this software and associated documentation files (the "Software"), to deal in 10 the Software without restriction, including without limitation the rights to 11 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 12 of the Software, and to permit persons to whom the Software is furnished to do 13 so, subject to the following conditions: 14 15 The above copyright notice and this permission notice applies to all licensees 16 and shall be included in all copies or substantial portions of the Software. 17 18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY, 20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 21 BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 22 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION 23 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 25 Except as contained in this notice, the name of Be Incorporated shall not be 26 used in advertising or otherwise to promote the sale, use or other dealings in 27 this Software without prior written authorization from Be Incorporated. 28 29 Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered trademarks 30 of Be Incorporated in the United States and other countries. Other brand product 31 names are registered trademarks or trademarks of their respective holders. 32 All rights reserved. 33 */ 34 35 36 #include <Application.h> 37 #include <Catalog.h> 38 #include <Directory.h> 39 #include <FindDirectory.h> 40 #include <Locale.h> 41 #include <MenuItem.h> 42 #include <Message.h> 43 #include <Mime.h> 44 #include <NodeInfo.h> 45 #include <Path.h> 46 #include <Query.h> 47 #include <Roster.h> 48 #include <String.h> 49 50 #include <kernel/fs_attr.h> 51 52 #include "Attributes.h" 53 #include "Commands.h" 54 55 #include "IconMenuItem.h" 56 #include "MimeTypes.h" 57 #include "TemplatesMenu.h" 58 59 #undef B_TRANSLATION_CONTEXT 60 #define B_TRANSLATION_CONTEXT "TemplatesMenu" 61 62 63 namespace BPrivate { 64 65 const char* kTemplatesDirectory = "Tracker/Tracker New Templates"; 66 67 } // namespace BPrivate 68 69 70 // #pragma mark - TemplatesMenu 71 72 73 TemplatesMenu::TemplatesMenu(const BMessenger &target, const char* label) 74 : 75 BMenu(label), 76 fTarget(target), 77 fOpenItem(NULL) 78 { 79 } 80 81 82 TemplatesMenu::~TemplatesMenu() 83 { 84 } 85 86 87 void 88 TemplatesMenu::AttachedToWindow() 89 { 90 BuildMenu(); 91 BMenu::AttachedToWindow(); 92 SetTargetForItems(fTarget); 93 } 94 95 96 status_t 97 TemplatesMenu::SetTargetForItems(BHandler* target) 98 { 99 status_t result = BMenu::SetTargetForItems(target); 100 if (result != B_OK) 101 return result; 102 103 for (int i = 0; i < CountItems(); i++) { 104 BMenu* submenu = ItemAt(i)->Submenu(); 105 if (submenu != NULL) { 106 result = SetTargetForSubmenuItems(submenu, target); 107 if (result != B_OK) 108 return result; 109 } 110 } 111 112 if (fOpenItem) 113 fOpenItem->SetTarget(be_app_messenger); 114 115 return result; 116 } 117 118 119 status_t 120 TemplatesMenu::SetTargetForItems(BMessenger messenger) 121 { 122 status_t result = BMenu::SetTargetForItems(messenger); 123 if (result != B_OK) 124 return result; 125 126 for (int i = 0; i < CountItems(); i++) { 127 BMenu* submenu = ItemAt(i)->Submenu(); 128 if (submenu != NULL) { 129 result = SetTargetForSubmenuItems(submenu, messenger); 130 if (result != B_OK) 131 return result; 132 } 133 } 134 135 if (fOpenItem) 136 fOpenItem->SetTarget(be_app_messenger); 137 138 return result; 139 } 140 141 142 bool 143 TemplatesMenu::BuildMenu(bool addItems) 144 { 145 // clear everything... 146 fOpenItem = NULL; 147 int32 count = CountItems(); 148 while (count--) 149 delete RemoveItem((int32)0); 150 151 // add the folder 152 IconMenuItem* menuItem = new IconMenuItem(B_TRANSLATE("New folder"), 153 new BMessage(kNewFolder), B_DIR_MIMETYPE, B_MINI_ICON); 154 AddItem(menuItem); 155 menuItem->SetShortcut('N', 0); 156 AddSeparatorItem(); 157 158 // the templates folder 159 BPath path; 160 find_directory (B_USER_SETTINGS_DIRECTORY, &path, true); 161 path.Append(kTemplatesDirectory); 162 mkdir(path.Path(), 0777); 163 164 count = 0; 165 count += IterateTemplateDirectory(addItems, &path, this); 166 167 // this is the message sent to open the templates folder 168 BDirectory templatesDir(path.Path()); 169 BMessage* message = new BMessage(B_REFS_RECEIVED); 170 BEntry entry; 171 entry_ref dirRef; 172 if (templatesDir.GetEntry(&entry) == B_OK) 173 entry.GetRef(&dirRef); 174 175 message->AddRef("refs", &dirRef); 176 177 // add item to show templates folder 178 fOpenItem = new BMenuItem(B_TRANSLATE("Edit templates" B_UTF8_ELLIPSIS), message); 179 AddItem(fOpenItem); 180 181 if (dirRef == entry_ref()) 182 fOpenItem->SetEnabled(false); 183 184 return count > 0; 185 } 186 187 188 BMenuItem* 189 TemplatesMenu::NewSubmenuItem(BPath subdirPath) 190 { 191 // add item to create new submenu folder 192 BDirectory templatesDir(subdirPath.Path()); 193 BEntry entry; 194 entry_ref dirRef; 195 if (templatesDir.GetEntry(&entry) == B_OK) 196 entry.GetRef(&dirRef); 197 BMessage* message = new BMessage(kNewTemplateSubmenu); 198 message->AddRef("refs", &dirRef); 199 BMenuItem* submenuItem = new BMenuItem(B_TRANSLATE("Add new submenu" B_UTF8_ELLIPSIS), message); 200 201 if (dirRef == entry_ref()) 202 submenuItem->SetEnabled(false); 203 204 return submenuItem; 205 } 206 207 208 void 209 TemplatesMenu::UpdateMenuState() 210 { 211 BuildMenu(false); 212 } 213 214 215 int 216 TemplatesMenu::IterateTemplateDirectory(bool addItems, BPath* path, BMenu* menu) 217 { 218 uint32 count = 0; 219 if (!path || !menu) 220 return count; 221 222 BEntry entry; 223 BList subMenus; 224 BList subDirs; 225 BList files; 226 BDirectory templatesDir(path->Path()); 227 while (templatesDir.GetNextEntry(&entry) == B_OK) { 228 BNode node(&entry); 229 BNodeInfo nodeInfo(&node); 230 char fileName[B_FILE_NAME_LENGTH]; 231 entry.GetName(fileName); 232 if (nodeInfo.InitCheck() == B_OK) { 233 char mimeType[B_MIME_TYPE_LENGTH]; 234 nodeInfo.GetType(mimeType); 235 236 BMimeType mime(mimeType); 237 if (mime.IsValid()) { 238 count++; 239 240 // If not adding items, we are just seeing if there 241 // are any to list. So if we find one, immediately 242 // bail and return the result. 243 if (!addItems) 244 return count; 245 246 entry_ref ref; 247 entry.GetRef(&ref); 248 249 // Check if the template is a directory 250 BDirectory dir(&entry); 251 if (dir.InitCheck() == B_OK) { 252 // check if the directory is a submenu, aka has kAttrTemplateSubMenu 253 // (_trk/_template_submenu) attribute 254 attr_info attrInfo; 255 if (node.GetAttrInfo(kAttrTemplateSubMenu, &attrInfo) == B_OK) { 256 ssize_t size; 257 bool value; 258 size = node.ReadAttr(kAttrTemplateSubMenu, B_BOOL_TYPE, 0, &value, 259 sizeof(bool)); 260 if (size == sizeof(bool) && value == true) { 261 // if submenu add it to subMenus list and iterate contents 262 BPath subdirPath; 263 if (entry.GetPath(&subdirPath) == B_OK) { 264 BMenu* subMenu = new BMenu(fileName); 265 count += IterateTemplateDirectory(addItems, &subdirPath, subMenu); 266 subMenus.AddItem((void*)subMenu); 267 continue; 268 } 269 continue; 270 } 271 } else { 272 // Otherwise add it to subDirs list 273 BMessage* message = new BMessage(kNewEntryFromTemplate); 274 message->AddRef("refs_template", &ref); 275 message->AddString("name", fileName); 276 subDirs.AddItem(new IconMenuItem(fileName, message, &nodeInfo, 277 B_MINI_ICON)); 278 continue; 279 } 280 } 281 282 // Add template files to files list 283 BMessage* message = new BMessage(kNewEntryFromTemplate); 284 message->AddRef("refs_template", &ref); 285 message->AddString("name", fileName); 286 files.AddItem(new IconMenuItem(fileName, message, &nodeInfo, B_MINI_ICON)); 287 } 288 } 289 } 290 291 // Add submenus to menu 292 int32 itemCount = subMenus.CountItems(); 293 for (int32 i = 0; i < itemCount; i++) 294 menu->AddItem((BMenu*)subMenus.ItemAt(i)); 295 296 if (itemCount > 0) 297 menu->AddSeparatorItem(); 298 299 // Add subdirs to menu 300 itemCount = subDirs.CountItems(); 301 for (int32 i = 0; i < itemCount; i++) 302 menu->AddItem((BMenuItem*)subDirs.ItemAt(i)); 303 304 if (itemCount > 0) 305 menu->AddSeparatorItem(); 306 307 // Add files to menu 308 itemCount = files.CountItems(); 309 for (int32 i = 0; i < itemCount; i++) 310 menu->AddItem((BMenuItem*)files.ItemAt(i)); 311 312 if (itemCount > 0) 313 menu->AddSeparatorItem(); 314 315 menu->AddItem(NewSubmenuItem(*path)); 316 317 return count > 0; 318 } 319 320 321 status_t 322 TemplatesMenu::SetTargetForSubmenuItems(BMenu* menu, BMessenger messenger) 323 { 324 if (!menu) 325 return B_ERROR; 326 327 status_t result; 328 329 result = menu->SetTargetForItems(messenger); 330 if (result != B_OK) 331 return result; 332 333 for (int i = 0; i < menu->CountItems(); i++) { 334 BMenu* submenu = menu->ItemAt(i)->Submenu(); 335 if (submenu != NULL) { 336 result = SetTargetForSubmenuItems(submenu, messenger); 337 if (result != B_OK) 338 return result; 339 } 340 } 341 return result; 342 } 343 344 345 status_t 346 TemplatesMenu::SetTargetForSubmenuItems(BMenu* menu, BHandler* target) 347 { 348 if (!menu || !target) 349 return B_ERROR; 350 351 status_t result; 352 353 result = menu->SetTargetForItems(target); 354 if (result != B_OK) 355 return result; 356 357 for (int i = 0; i < menu->CountItems(); i++) { 358 BMenu* submenu = menu->ItemAt(i)->Submenu(); 359 if (submenu != NULL) { 360 result = SetTargetForSubmenuItems(submenu, target); 361 if (result != B_OK) 362 return result; 363 } 364 } 365 return result; 366 } 367