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