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 166 count += IterateTemplateDirectory(addItems, &path, this); 167 168 AddSeparatorItem(); 169 170 // this is the message sent to open the templates folder 171 BDirectory templatesDir(path.Path()); 172 BMessage* message = new BMessage(B_REFS_RECEIVED); 173 BEntry entry; 174 entry_ref dirRef; 175 if (templatesDir.GetEntry(&entry) == B_OK) 176 entry.GetRef(&dirRef); 177 178 message->AddRef("refs", &dirRef); 179 180 // add item to show templates folder 181 fOpenItem = new BMenuItem(B_TRANSLATE("Edit templates" B_UTF8_ELLIPSIS), message); 182 AddItem(fOpenItem); 183 if (dirRef == entry_ref()) 184 fOpenItem->SetEnabled(false); 185 186 return count > 0; 187 } 188 189 190 void 191 TemplatesMenu::UpdateMenuState() 192 { 193 BuildMenu(false); 194 } 195 196 197 int 198 TemplatesMenu::IterateTemplateDirectory(bool addItems, BPath* path, BMenu* menu) 199 { 200 uint32 count = 0; 201 if (!path || !menu) 202 return count; 203 204 BEntry entry; 205 BList subMenus; 206 BList subDirs; 207 BList files; 208 BDirectory templatesDir(path->Path()); 209 while (templatesDir.GetNextEntry(&entry) == B_OK) { 210 BNode node(&entry); 211 BNodeInfo nodeInfo(&node); 212 char fileName[B_FILE_NAME_LENGTH]; 213 entry.GetName(fileName); 214 if (nodeInfo.InitCheck() == B_OK) { 215 char mimeType[B_MIME_TYPE_LENGTH]; 216 nodeInfo.GetType(mimeType); 217 218 BMimeType mime(mimeType); 219 if (mime.IsValid()) { 220 count++; 221 222 // If not adding items, we are just seeing if there 223 // are any to list. So if we find one, immediately 224 // bail and return the result. 225 if (!addItems) 226 return count; 227 228 entry_ref ref; 229 entry.GetRef(&ref); 230 231 // Check if the template is a directory 232 BDirectory dir(&entry); 233 if (dir.InitCheck() == B_OK) { 234 // check if the directory is a submenu, aka has kAttrTemplateSubMenu 235 // (_trk/_template_submenu) attribute 236 attr_info attrInfo; 237 if (node.GetAttrInfo(kAttrTemplateSubMenu, &attrInfo) == B_OK) { 238 ssize_t size; 239 bool value; 240 size = node.ReadAttr(kAttrTemplateSubMenu, B_BOOL_TYPE, 0, &value, 241 sizeof(bool)); 242 if (size == sizeof(bool) && value == true) { 243 // if submenu add it to subMenus list and iterate contents 244 BPath subdirPath; 245 if (entry.GetPath(&subdirPath) == B_OK) { 246 BMenu* subMenu = new BMenu(fileName); 247 count += IterateTemplateDirectory(addItems, &subdirPath, subMenu); 248 subMenus.AddItem((void*)subMenu); 249 continue; 250 } 251 continue; 252 } 253 } else { 254 // Otherwise add it to subDirs list 255 BMessage* message = new BMessage(kNewEntryFromTemplate); 256 message->AddRef("refs_template", &ref); 257 message->AddString("name", fileName); 258 subDirs.AddItem(new IconMenuItem(fileName, message, &nodeInfo, 259 B_MINI_ICON)); 260 continue; 261 } 262 } 263 264 // Add template files to files list 265 BMessage* message = new BMessage(kNewEntryFromTemplate); 266 message->AddRef("refs_template", &ref); 267 message->AddString("name", fileName); 268 files.AddItem(new IconMenuItem(fileName, message, &nodeInfo, B_MINI_ICON)); 269 } 270 } 271 } 272 273 // Add submenus to menu 274 for (int32 i = 0; i < subMenus.CountItems(); i++) 275 menu->AddItem((BMenu*)subMenus.ItemAt(i)); 276 277 if (subMenus.CountItems() > 0) 278 menu->AddSeparatorItem(); 279 280 // Add subdirs to menu 281 for (int32 i = 0; i < subDirs.CountItems(); i++) 282 menu->AddItem((BMenuItem*)subDirs.ItemAt(i)); 283 284 if (subDirs.CountItems() > 0) 285 menu->AddSeparatorItem(); 286 287 // Add files to menu 288 for (int32 i = 0; i < files.CountItems(); i++) 289 menu->AddItem((BMenuItem*)files.ItemAt(i)); 290 291 return count > 0; 292 } 293 294 295 status_t 296 TemplatesMenu::SetTargetForSubmenuItems(BMenu* menu, BMessenger messenger) 297 { 298 if (!menu) 299 return B_ERROR; 300 301 status_t result; 302 303 result = menu->SetTargetForItems(messenger); 304 if (result != B_OK) 305 return result; 306 307 for (int i = 0; i < menu->CountItems(); i++) { 308 BMenu* submenu = menu->ItemAt(i)->Submenu(); 309 if (submenu != NULL) { 310 result = SetTargetForSubmenuItems(submenu, messenger); 311 if (result != B_OK) 312 return result; 313 } 314 } 315 return result; 316 } 317 318 319 status_t 320 TemplatesMenu::SetTargetForSubmenuItems(BMenu* menu, BHandler* target) 321 { 322 if (!menu || !target) 323 return B_ERROR; 324 325 status_t result; 326 327 result = menu->SetTargetForItems(target); 328 if (result != B_OK) 329 return result; 330 331 for (int i = 0; i < menu->CountItems(); i++) { 332 BMenu* submenu = menu->ItemAt(i)->Submenu(); 333 if (submenu != NULL) { 334 result = SetTargetForSubmenuItems(submenu, target); 335 if (result != B_OK) 336 return result; 337 } 338 } 339 return result; 340 } 341