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