xref: /haiku/src/preferences/datatranslations/DataTranslationsWindow.cpp (revision 1c09002cbee8e797a0f8bbfc5678dfadd39ee1a7)
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 <Button.h>
23 #include <Catalog.h>
24 #include <ControlLook.h>
25 #include <Entry.h>
26 #include <LayoutBuilder.h>
27 #include <ListView.h>
28 #include <Path.h>
29 #include <Screen.h>
30 #include <ScrollView.h>
31 #include <String.h>
32 #include <StringView.h>
33 #include <TextView.h>
34 #include <TranslationDefs.h>
35 #include <TranslatorRoster.h>
36 
37 #include "DataTranslations.h"
38 #include "DataTranslationsSettings.h"
39 #include "IconView.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 	// fConfigView is NULL the first time this function
143 	// is called, prevent a segment fault
144 	if (fConfigView)
145 		fRightBox->RemoveChild(fConfigView);
146 
147 	BMessage emptyMsg;
148 	BRect rect(0, 0, 200, 233);
149 	status_t ret = roster->MakeConfigurationView(id, &emptyMsg,
150 		&fConfigView, &rect);
151 
152 	if (ret != B_OK)
153 		return ret;
154 
155 	fConfigView->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
156 		// force config views to all have the same color
157 	fRightBox->AddChild(fConfigView);
158 
159 	return B_OK;
160 }
161 
162 
163 void
164 DataTranslationsWindow::_SetupViews()
165 {
166 	fConfigView = NULL;
167 	// This is NULL until a translator is
168 	// selected from the listview
169 
170 	// Add the translators list view
171 	fTranslatorListView = new TranslatorListView("TransList");
172 	fTranslatorListView->SetSelectionMessage(
173 		new BMessage(kMsgSelectedTranslator));
174 
175 	BScrollView* scrollView = new BScrollView("scroll_trans",
176 		fTranslatorListView, B_WILL_DRAW | B_FRAME_EVENTS, false,
177 		true, B_FANCY_BORDER);
178 
179 	// Box around the config and info panels
180 	fRightBox = new BBox("Right_Side");
181 	fRightBox->SetExplicitAlignment(BAlignment(B_ALIGN_USE_FULL_WIDTH,
182 			B_ALIGN_USE_FULL_HEIGHT));
183 
184 	// Add the translator icon view
185 	fIconView = new IconView(BRect(0, 0, 31, 31), B_TRANSLATE("Icon"),
186 		B_FOLLOW_LEFT | B_FOLLOW_BOTTOM, B_WILL_DRAW | B_FRAME_EVENTS);
187 
188 	// Add the translator info button
189 	BButton* button = new BButton("STD", B_TRANSLATE("Info" B_UTF8_ELLIPSIS),
190 		new BMessage(kMsgTranslatorInfo), B_WILL_DRAW | B_FRAME_EVENTS | B_NAVIGABLE);
191 
192 	// Populate the translators list view
193 	_PopulateListView();
194 
195 	// Build the layout
196 	float padding = be_control_look->DefaultItemSpacing();
197 	BLayoutBuilder::Group<>(this, B_HORIZONTAL, padding)
198 		.SetInsets(padding, padding, padding, padding)
199 		.Add(scrollView, 3)
200 		.AddGrid(padding, padding, 6)
201 			.SetInsets(0, 0, 0, 0)
202 			.Add(fRightBox, 0, 0, 3, 1)
203 			.Add(fIconView, 0, 1)
204 			.Add(button, 2, 1);
205 
206 	fTranslatorListView->MakeFocus();
207 	fTranslatorListView->Select(0);
208 }
209 
210 
211 bool
212 DataTranslationsWindow::QuitRequested()
213 {
214 	BPoint pt(Frame().LeftTop());
215 	DataTranslationsSettings::Instance()->SetWindowCorner(pt);
216 	be_app->PostMessage(B_QUIT_REQUESTED);
217 	return true;
218 }
219 
220 
221 void
222 DataTranslationsWindow::_ShowInfoAlert(int32 id)
223 {
224 	const char* name = NULL;
225 	const char* info = NULL;
226 	BPath path;
227 	int32 version = 0;
228 	_GetTranslatorInfo(id, name, info, version, path);
229 
230 	BString message;
231 	// Convert the version number into a readable format
232 	snprintf(message.LockBuffer(2048), 2048,
233 		B_TRANSLATE("Name:\t%s \nVersion:\t%ld.%ld.%ld\nInfo:\t%s\n\nPath:\n%s\n"),
234 			name, B_TRANSLATION_MAJOR_VERSION(version),
235 			B_TRANSLATION_MINOR_VERSION(version),
236 			B_TRANSLATION_REVISION_VERSION(version), info, path.Path());
237 	message.UnlockBuffer();
238 
239 	BAlert* alert = new BAlert(B_TRANSLATE("Info"), message.String(),
240 		B_TRANSLATE("OK"));
241 	BTextView* view = alert->TextView();
242 	BFont font;
243 
244 	view->SetStylable(true);
245 
246 	view->GetFont(&font);
247 	font.SetFace(B_BOLD_FACE);
248 
249 	const char* labels[] = { B_TRANSLATE("Name:"), B_TRANSLATE("Version:"),
250 		B_TRANSLATE("Info:"), B_TRANSLATE("Path:"), NULL };
251 	for (int32 i = 0; labels[i]; i++) {
252 		int32 index = message.FindFirst(labels[i]);
253 		view->SetFontAndColor(index, index + strlen(labels[i]), &font);
254 	}
255 
256 	alert->Go();
257 }
258 
259 
260 void
261 DataTranslationsWindow::MessageReceived(BMessage* message)
262 {
263 	switch (message->what) {
264 		case kMsgTranslatorInfo:
265 		{
266 			int32 selected = fTranslatorListView->CurrentSelection(0);
267 			if (selected < 0) {
268 				// If no translator is selected, show a message explaining
269 				// what the config panel is for
270 				(new BAlert(B_TRANSLATE("Panel Info"),
271 					B_TRANSLATE("Translation Settings\n\n"
272 					"Use this control panel to set values that various\n"
273 					"translators use when no other settings are specified\n"
274 					"in the application."),
275 					B_TRANSLATE("OK")))->Go();
276 				break;
277 			}
278 
279 			TranslatorItem* item = fTranslatorListView->TranslatorAt(selected);
280 			if (item != NULL)
281 				_ShowInfoAlert(item->ID());
282 			break;
283 		}
284 
285 		case kMsgSelectedTranslator:
286 		{
287 			// Update the icon and translator info panel
288 			// to match the new selection
289 
290 			int32 selected = fTranslatorListView->CurrentSelection(0);
291 			if (selected < 0) {
292 				// If none selected, clear the old one
293 				fIconView->DrawIcon(false);
294 				fRightBox->RemoveChild(fConfigView);
295 				break;
296 			}
297 
298 			TranslatorItem* item = fTranslatorListView->TranslatorAt(selected);
299 			if (item == NULL)
300 				break;
301 
302 			_ShowConfigView(item->ID());
303 
304 			const char* name = NULL;
305 			const char* info = NULL;
306 			int32 version = 0;
307 			BPath path;
308 			_GetTranslatorInfo(item->ID(), name, info, version, path);
309 			fIconView->SetIcon(path);
310 			break;
311 		}
312 
313 		case B_TRANSLATOR_ADDED:
314 		{
315 			int32 index = 0, id;
316 			while (message->FindInt32("translator_id", index++, &id) == B_OK) {
317 				const char* name;
318 				const char* info;
319 				int32 version;
320 				BPath path;
321 				if (_GetTranslatorInfo(id, name, info, version, path) == B_OK)
322 					fTranslatorListView->AddItem(new TranslatorItem(id, name));
323 			}
324 
325 			fTranslatorListView->SortItems();
326 			break;
327 		}
328 
329 		case B_TRANSLATOR_REMOVED:
330 		{
331 			int32 index = 0, id;
332 			while (message->FindInt32("translator_id", index++, &id) == B_OK) {
333 				for (int32 i = 0; i < fTranslatorListView->CountItems(); i++) {
334 					TranslatorItem* item = fTranslatorListView->TranslatorAt(i);
335 
336 					if (item == NULL)
337 						continue;
338 
339 					if (item->ID() == (translator_id)id) {
340 						fTranslatorListView->RemoveItem(i);
341 						delete item;
342 						break;
343 					}
344 				}
345 			}
346 			break;
347 		}
348 
349 		default:
350 			BWindow::MessageReceived(message);
351 			break;
352 	}
353 }
354 
355