xref: /haiku/src/preferences/datatranslations/DataTranslationsWindow.cpp (revision 89d652d5e0defd9d095c778709cef82f5f10c357)
1 /*
2  * Copyright 2002-2010, Haiku, Inc.
3  * Distributed under the terms of the MIT license.
4  *
5  * Authors:
6  *		Oliver Siebenmarck
7  *		Andrew McCall, mccall@digitalparadise.co.uk
8  *		Michael Wilber
9  *		Maxime Simon
10  */
11 
12 
13 #include "DataTranslations.h"
14 #include "DataTranslationsWindow.h"
15 #include "IconView.h"
16 #include "TranslatorListView.h"
17 
18 #include <Application.h>
19 #include <Alignment.h>
20 #include <Alert.h>
21 #include <Bitmap.h>
22 #include <Box.h>
23 #include <Button.h>
24 #include <ControlLook.h>
25 #include <LayoutBuilder.h>
26 #include <ListView.h>
27 #include <Path.h>
28 #include <Screen.h>
29 #include <ScrollView.h>
30 #include <String.h>
31 #include <StringView.h>
32 #include <TextView.h>
33 #include <TranslationDefs.h>
34 #include <TranslatorRoster.h>
35 
36 
37 const uint32 kMsgTranslatorInfo = 'trin';
38 const uint32 kMsgSelectedTranslator = 'trsl';
39 
40 
41 DataTranslationsWindow::DataTranslationsWindow()
42 	:
43 	BWindow(BRect(0, 0, 550, 350), "DataTranslations", B_TITLED_WINDOW,
44 		B_ASYNCHRONOUS_CONTROLS | B_NOT_ZOOMABLE | B_NOT_RESIZABLE
45 			| B_AUTO_UPDATE_SIZE_LIMITS)
46 {
47 	MoveTo(static_cast<DataTranslationsApplication *>(be_app)->WindowCorner());
48 
49 	_SetupViews();
50 
51 	// Make sure that the window isn't positioned off screen
52 	BScreen screen;
53 	BRect screenFrame = screen.Frame();
54 	if (!screenFrame.Contains(Frame()))
55 		CenterOnScreen();
56 
57 	BTranslatorRoster *roster = BTranslatorRoster::Default();
58 	roster->StartWatching(this);
59 
60 	Show();
61 }
62 
63 
64 DataTranslationsWindow::~DataTranslationsWindow()
65 {
66 	BTranslatorRoster *roster = BTranslatorRoster::Default();
67 	roster->StopWatching(this);
68 }
69 
70 
71 // Reads the installed translators and adds them to our BListView
72 status_t
73 DataTranslationsWindow::_PopulateListView()
74 {
75 	BTranslatorRoster *roster = BTranslatorRoster::Default();
76 
77 	// Get all Translators on the system. Gives us the number of translators
78 	// installed in num_translators and a reference to the first one
79 	int32 numTranslators;
80 	translator_id *translators = NULL;
81 	roster->GetAllTranslators(&translators, &numTranslators);
82 
83 	for (int32 i = 0; i < numTranslators; i++) {
84 		// Getting the first three Infos: Name, Info & Version
85 		int32 version;
86 		const char *name, *info;
87 		roster->GetTranslatorInfo(translators[i], &name, &info, &version);
88 		fTranslatorListView->AddItem(new TranslatorItem(translators[i], name));
89 	}
90 
91 	delete[] translators;
92 	return B_OK;
93 }
94 
95 
96 status_t
97 DataTranslationsWindow::_GetTranslatorInfo(int32 id, const char*& name,
98 	const char*& info, int32& version, BPath& path)
99 {
100 	// Returns information about the translator with the given id
101 
102 	if (id < 0)
103 		return B_BAD_VALUE;
104 
105 	BTranslatorRoster *roster = BTranslatorRoster::Default();
106 	if (roster->GetTranslatorInfo(id, &name, &info, &version) != B_OK)
107 		return B_ERROR;
108 
109 	// Get the translator's path
110 	entry_ref ref;
111 	if (roster->GetRefFor(id, &ref) == B_OK) {
112 		BEntry entry(&ref);
113 		path.SetTo(&entry);
114 	} else
115 		path.Unset();
116 
117 	return B_OK;
118 }
119 
120 
121 status_t
122 DataTranslationsWindow::_ShowConfigView(int32 id)
123 {
124 	// Shows the config panel for the translator with the given id
125 
126 	if (id < 0)
127 		return B_BAD_VALUE;
128 
129 	BTranslatorRoster *roster = BTranslatorRoster::Default();
130 
131 	// fConfigView is NULL the first time this function
132 	// is called, prevent a segment fault
133 	if (fConfigView)
134 		fRightBox->RemoveChild(fConfigView);
135 
136 	BMessage emptyMsg;
137 	BRect rect(0, 0, 200, 233);
138 	status_t ret = roster->MakeConfigurationView(id, &emptyMsg,
139 		&fConfigView, &rect);
140 
141 	if (ret != B_OK)
142 		return ret;
143 
144 	fConfigView->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
145 		// force config views to all have the same color
146 	fRightBox->AddChild(fConfigView);
147 
148 	return B_OK;
149 }
150 
151 
152 void
153 DataTranslationsWindow::_SetupViews()
154 {
155 	fConfigView = NULL;
156 	// This is NULL until a translator is
157 	// selected from the listview
158 
159 	// Add the translators list view
160 	fTranslatorListView = new TranslatorListView("TransList");
161 	fTranslatorListView->SetSelectionMessage(
162 		new BMessage(kMsgSelectedTranslator));
163 
164 	BScrollView *scrollView = new BScrollView("scroll_trans",
165 		fTranslatorListView, B_WILL_DRAW | B_FRAME_EVENTS, false,
166 		true, B_FANCY_BORDER);
167 
168 	// Box around the config and info panels
169 	fRightBox = new BBox("Right_Side");
170 	fRightBox->SetExplicitAlignment(BAlignment(B_ALIGN_USE_FULL_WIDTH,
171 			B_ALIGN_USE_FULL_HEIGHT));
172 
173 	// Add the translator icon view
174 	fIconView = new IconView(BRect(0, 0, 31, 31), "Icon",
175 		B_FOLLOW_LEFT | B_FOLLOW_BOTTOM, B_WILL_DRAW | B_FRAME_EVENTS);
176 
177 	// Add the translator info button
178 	BButton *button = new BButton("STD", "Info" B_UTF8_ELLIPSIS,
179 		new BMessage(kMsgTranslatorInfo), B_WILL_DRAW | B_FRAME_EVENTS | B_NAVIGABLE);
180 
181 	// Populate the translators list view
182 	_PopulateListView();
183 
184 	// Build the layout
185 	float padding = be_control_look->DefaultItemSpacing();
186 	BLayoutBuilder::Group<>(this, B_HORIZONTAL, padding)
187 		.SetInsets(padding, padding, padding, padding)
188 		.Add(scrollView, 3)
189 		.AddGrid(padding, padding, 6)
190 			.SetInsets(0, 0, 0, 0)
191 			.Add(fRightBox, 0, 0, 3, 1)
192 			.Add(fIconView, 0, 1)
193 			.Add(button, 2, 1);
194 
195 	fTranslatorListView->MakeFocus();
196 	fTranslatorListView->Select(0);
197 }
198 
199 
200 bool
201 DataTranslationsWindow::QuitRequested()
202 {
203 	BPoint pt(Frame().LeftTop());
204 	dynamic_cast<DataTranslationsApplication *>(be_app)->SetWindowCorner(pt);
205 	be_app->PostMessage(B_QUIT_REQUESTED);
206 
207 	return true;
208 }
209 
210 
211 void
212 DataTranslationsWindow::_ShowInfoAlert(int32 id)
213 {
214 	const char* name = NULL;
215 	const char* info = NULL;
216 	BPath path;
217 	int32 version = 0;
218 	_GetTranslatorInfo(id, name, info, version, path);
219 
220 	BString message;
221 	message << "Name: " << name << "\nVersion: ";
222 
223 	// Convert the version number into a readable format
224 	message << (int)B_TRANSLATION_MAJOR_VERSION(version)
225 		<< '.' << (int)B_TRANSLATION_MINOR_VERSION(version)
226 		<< '.' << (int)B_TRANSLATION_REVISION_VERSION(version);
227 	message << "\nInfo: " << info <<
228 		"\n\nPath:\n" << path.Path() << "\n";
229 
230 	BAlert* alert = new BAlert("info", message.String(), "OK");
231 	BTextView *view = alert->TextView();
232 	BFont font;
233 
234 	view->SetStylable(true);
235 
236 	view->GetFont(&font);
237 	font.SetFace(B_BOLD_FACE);
238 
239 	const char* labels[] = {"Name:", "Version:", "Info:", "Path:", NULL};
240 	for (int32 i = 0; labels[i]; i++) {
241 		int32 index = message.FindFirst(labels[i]);
242 		view->SetFontAndColor(index, index + strlen(labels[i]), &font);
243 	}
244 
245 	alert->Go();
246 }
247 
248 
249 void
250 DataTranslationsWindow::MessageReceived(BMessage *message)
251 {
252 	switch (message->what) {
253 		case kMsgTranslatorInfo:
254 		{
255 			int32 selected = fTranslatorListView->CurrentSelection(0);
256 			if (selected < 0) {
257 				// If no translator is selected, show a message explaining
258 				// what the config panel is for
259 				(new BAlert("Panel Info",
260 					"Translation Settings\n\n"
261 					"Use this control panel to set values that various\n"
262 					"translators use when no other settings are specified\n"
263 					"in the application.",
264 					"OK"))->Go();
265 				break;
266 			}
267 
268 			TranslatorItem* item = fTranslatorListView->TranslatorAt(selected);
269 			if (item != NULL)
270 				_ShowInfoAlert(item->ID());
271 			break;
272 		}
273 
274 		case kMsgSelectedTranslator:
275 		{
276 			// Update the icon and translator info panel
277 			// to match the new selection
278 
279 			int32 selected = fTranslatorListView->CurrentSelection(0);
280 			if (selected < 0) {
281 				// If none selected, clear the old one
282 				fIconView->DrawIcon(false);
283 				fRightBox->RemoveChild(fConfigView);
284 				break;
285 			}
286 
287 			TranslatorItem* item = fTranslatorListView->TranslatorAt(selected);
288 			if (item == NULL)
289 				break;
290 
291 			_ShowConfigView(item->ID());
292 
293 			const char* name = NULL;
294 			const char* info = NULL;
295 			int32 version = 0;
296 			BPath path;
297 			_GetTranslatorInfo(item->ID(), name, info, version, path);
298 			fIconView->SetIcon(path);
299 			break;
300 		}
301 
302 		case B_TRANSLATOR_ADDED:
303 		{
304 			int32 index = 0, id;
305 			while (message->FindInt32("translator_id", index++, &id) == B_OK) {
306 				const char* name;
307 				const char* info;
308 				int32 version;
309 				BPath path;
310 				if (_GetTranslatorInfo(id, name, info, version, path) == B_OK)
311 					fTranslatorListView->AddItem(new TranslatorItem(id, name));
312 			}
313 
314 			fTranslatorListView->SortItems();
315 			break;
316 		}
317 
318 		case B_TRANSLATOR_REMOVED:
319 		{
320 			int32 index = 0, id;
321 			while (message->FindInt32("translator_id", index++, &id) == B_OK) {
322 				for (int32 i = 0; i < fTranslatorListView->CountItems(); i++) {
323 					TranslatorItem* item = fTranslatorListView->TranslatorAt(i);
324 
325 					if (item == NULL)
326 						continue;
327 
328 					if (item->ID() == (translator_id)id) {
329 						fTranslatorListView->RemoveItem(i);
330 						delete item;
331 						break;
332 					}
333 				}
334 			}
335 			break;
336 		}
337 
338 		default:
339 			BWindow::MessageReceived(message);
340 			break;
341 	}
342 }
343 
344