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