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