xref: /haiku/src/kits/tracker/TemplatesMenu.cpp (revision 94c66b276e92f206678ca2e2c816d2665946afdd)
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