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