xref: /haiku/src/add-ons/tracker/mark_as/MarkAs.cpp (revision 23f179da55b1bd1ba84fbf3d3c56947e2c8d0aca)
1 /*
2  * Copyright 2009, Axel Dörfler, axeld@pinc-software.de.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 
7 #include <new>
8 
9 #include <Directory.h>
10 #include <Entry.h>
11 #include <FindDirectory.h>
12 #include <MenuItem.h>
13 #include <Message.h>
14 #include <Node.h>
15 #include <Path.h>
16 #include <PopUpMenu.h>
17 #include <String.h>
18 #include <View.h>
19 #include <Window.h>
20 
21 
22 /*!	Returns the current mouse position in screen coordinates.
23 	Since there is no method to retrieve this in the Be API without a view,
24 	this looks a bit more complicated.
25 */
26 static BPoint
27 mouse_position()
28 {
29 	BWindow* window = new BWindow(BRect(-1000, -1000, -900, -900), "mouse",
30 		B_NO_BORDER_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL,
31 		B_AVOID_FRONT | B_AVOID_FOCUS);
32 	BView* view = new BView(window->Bounds(), "mouse", B_FOLLOW_ALL, 0);
33 	window->AddChild(view);
34 	window->Run();
35 
36 	window->Lock();
37 
38 	BPoint position;
39 	uint32 buttons;
40 	view->GetMouse(&position, &buttons);
41 	view->ConvertToScreen(&position);
42 
43 	window->Quit();
44 
45 	return position;
46 }
47 
48 
49 static void
50 add_status_item(BMenu* menu, const char* name)
51 {
52 	if (menu->FindItem(name) != NULL)
53 		return;
54 
55 	// Sort items alphabetically
56 	int32 index;
57 	for (index = 0; index < menu->CountItems(); index++) {
58 		if (strcmp(menu->ItemAt(index)->Label(), name) > 0)
59 			break;
60 	}
61 
62 	menu->AddItem(new BMenuItem(name, NULL), index);
63 }
64 
65 
66 static void
67 retrieve_status_items(BMenu* menu)
68 {
69 	BPath path;
70 	if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK)
71 		return;
72 
73 	path.Append("Mail/status");
74 
75 	BDirectory directory(path.Path());
76 
77 	entry_ref ref;
78 	while (directory.GetNextRef(&ref) == B_OK) {
79 		if (!strcmp(ref.name, ".") || !strcmp(ref.name, ".."))
80 			continue;
81 
82 		add_status_item(menu, ref.name);
83 	}
84 
85 	add_status_item(menu, "New");
86 	add_status_item(menu, "Read");
87 	add_status_item(menu, "Replied");
88 }
89 
90 
91 // #pragma mark -
92 
93 
94 extern "C" void
95 process_refs(entry_ref dir, BMessage* message, void* /*reserved*/)
96 {
97 	BPopUpMenu* menu = new BPopUpMenu("status");
98 	retrieve_status_items(menu);
99 
100 	BMenuItem* item = menu->Go(mouse_position() - BPoint(5, 5), false, true);
101 	if (item == NULL)
102 		return;
103 
104 	BString status = item->Label();
105 
106 	entry_ref ref;
107 	for (int i = 0; message->FindRef("refs", i, &ref) == B_OK; i++) {
108 		BNode node(&ref);
109 		BString type;
110 
111 		if (node.InitCheck() == B_OK
112 			&& node.ReadAttrString("BEOS:TYPE", &type) == B_OK
113 			&& type == "text/x-email") {
114 			BString previousStatus;
115 
116 			// Only update the attribute if there is an actual change
117 			if (node.ReadAttrString("MAIL:status", &previousStatus) != B_OK
118 				|| previousStatus != status)
119 				node.WriteAttrString("MAIL:status", &status);
120 		}
121 	}
122 }
123 
124