xref: /haiku/src/preferences/datatranslations/DataTranslationsWindow.cpp (revision 4466b89c65970de4c7236ac87faa2bee4589f413)
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_TRANSLATE_CONTEXT
44 #define B_TRANSLATE_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->Go();
286 }
287 
288 
289 void
290 DataTranslationsWindow::MessageReceived(BMessage* message)
291 {
292 	switch (message->what) {
293 		case kMsgTranslatorInfo:
294 		{
295 			int32 selected = fTranslatorListView->CurrentSelection(0);
296 			if (selected < 0)
297 				break;
298 
299 			TranslatorItem* item = fTranslatorListView->TranslatorAt(selected);
300 			if (item != NULL)
301 				_ShowInfoAlert(item->ID());
302 			break;
303 		}
304 
305 		case kMsgSelectedTranslator:
306 		{
307 			// Update the icon and translator info panel
308 			// to match the new selection
309 
310 			int32 selected = fTranslatorListView->CurrentSelection(0);
311 			if (selected < 0) {
312 				// If none selected, clear the old one
313 				fIconView->DrawIcon(false);
314 				fButton->SetEnabled(false);
315 				fRightBox->RemoveChild(fConfigView);
316 				_ShowInfoView();
317 				break;
318 			}
319 
320 			TranslatorItem* item = fTranslatorListView->TranslatorAt(selected);
321 			if (item == NULL)
322 				break;
323 
324 			_ShowConfigView(item->ID());
325 
326 			const char* name = NULL;
327 			const char* info = NULL;
328 			int32 version = 0;
329 			BPath path;
330 			_GetTranslatorInfo(item->ID(), name, info, version, path);
331 			fIconView->SetIcon(path);
332 			fButton->SetEnabled(true);
333 			break;
334 		}
335 
336 		case B_TRANSLATOR_ADDED:
337 		{
338 			int32 index = 0, id;
339 			while (message->FindInt32("translator_id", index++, &id) == B_OK) {
340 				const char* name;
341 				const char* info;
342 				int32 version;
343 				BPath path;
344 				if (_GetTranslatorInfo(id, name, info, version, path) == B_OK)
345 					fTranslatorListView->AddItem(new TranslatorItem(id, name));
346 			}
347 
348 			fTranslatorListView->SortItems();
349 			break;
350 		}
351 
352 		case B_TRANSLATOR_REMOVED:
353 		{
354 			int32 index = 0, id;
355 			while (message->FindInt32("translator_id", index++, &id) == B_OK) {
356 				for (int32 i = 0; i < fTranslatorListView->CountItems(); i++) {
357 					TranslatorItem* item = fTranslatorListView->TranslatorAt(i);
358 
359 					if (item == NULL)
360 						continue;
361 
362 					if (item->ID() == (translator_id)id) {
363 						fTranslatorListView->RemoveItem(i);
364 						delete item;
365 						break;
366 					}
367 				}
368 			}
369 			break;
370 		}
371 
372 		default:
373 			BWindow::MessageReceived(message);
374 			break;
375 	}
376 }
377