1 /* 2 * Copyright 2001-2011, Haiku. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Michael Pfeiffer 7 * Philippe Houdoin 8 */ 9 10 11 #include "PrintersWindow.h" 12 13 #include <stdio.h> 14 15 #include <Application.h> 16 #include <Button.h> 17 #include <Catalog.h> 18 #include <ControlLook.h> 19 #include <FindDirectory.h> 20 #include <GroupLayout.h> 21 #include <Layout.h> 22 #include <LayoutBuilder.h> 23 #include <ListView.h> 24 #include <Locale.h> 25 #include <PrintJob.h> 26 #include <ScrollView.h> 27 28 #include "pr_server.h" 29 #include "AddPrinterDialog.h" 30 #include "Globals.h" 31 #include "JobListView.h" 32 #include "Messages.h" 33 #include "PrinterListView.h" 34 #include "TestPageView.h" 35 #include "SpoolFolder.h" 36 37 38 #undef B_TRANSLATION_CONTEXT 39 #define B_TRANSLATION_CONTEXT "PrintersWindow" 40 41 42 class TestPageWindow : public BWindow { 43 public: 44 TestPageWindow(BPrintJob* job, PrinterItem* printer); 45 virtual ~TestPageWindow(); 46 47 void MessageReceived(BMessage* message); 48 private: 49 BPrintJob* fJob; 50 TestPageView* fTestPage; 51 }; 52 53 54 TestPageWindow::TestPageWindow(BPrintJob* job, PrinterItem* printer) 55 : BWindow(job->PaperRect().OffsetByCopy(-20000, -20000), B_TRANSLATE("Test page"), 56 B_TITLED_WINDOW, 0), fJob(job) 57 { 58 fTestPage = new TestPageView(job->PrintableRect(), printer); 59 60 // SetLayout(new BGroupLayout(B_VERTICAL)); 61 AddChild(fTestPage); 62 } 63 64 65 TestPageWindow::~TestPageWindow() 66 { 67 delete fJob; 68 } 69 70 71 void 72 TestPageWindow::MessageReceived(BMessage* message) 73 { 74 if (message->what != kMsgPrintTestPage) { 75 BWindow::MessageReceived(message); 76 return; 77 } 78 79 fJob->BeginJob(); 80 81 fJob->DrawView(fTestPage, fTestPage->Bounds(), B_ORIGIN); 82 fJob->SpoolPage(); 83 84 if (!fJob->CanContinue()) 85 return; 86 87 fJob->CommitJob(); 88 89 Quit(); 90 } 91 92 93 // #pragma mark PrintersWindow main class 94 95 96 PrintersWindow::PrintersWindow(BRect frame) 97 : 98 BWindow(BRect(78, 71, 761, 509), B_TRANSLATE_SYSTEM_NAME("Printers"), 99 B_TITLED_WINDOW, B_AUTO_UPDATE_SIZE_LIMITS), 100 fSelectedPrinter(NULL), 101 fAddingPrinter(false) 102 { 103 _BuildGUI(); 104 } 105 106 107 bool 108 PrintersWindow::QuitRequested() 109 { 110 bool result = Inherited::QuitRequested(); 111 if (result) 112 be_app->PostMessage(B_QUIT_REQUESTED); 113 114 return result; 115 } 116 117 118 void 119 PrintersWindow::MessageReceived(BMessage* msg) 120 { 121 switch(msg->what) { 122 case kMsgPrinterSelected: 123 { 124 fSelectedPrinter = fPrinterListView->SelectedItem(); 125 if (fSelectedPrinter) { 126 BString text = B_TRANSLATE("Print jobs for %printer_name%"); 127 text.ReplaceFirst("%printer_name%", fSelectedPrinter->Name()); 128 129 fJobsBox->SetLabel(text); 130 fMakeDefault->SetEnabled(true); 131 fRemove->SetEnabled(true); 132 fJobListView->SetSpoolFolder(fSelectedPrinter->Folder()); 133 } else { 134 fJobsBox->SetLabel( 135 B_TRANSLATE("Print jobs: No printer selected")); 136 fMakeDefault->SetEnabled(false); 137 fRemove->SetEnabled(false); 138 fSelectedPrinter = NULL; 139 fJobListView->SetSpoolFolder(NULL); 140 } 141 _UpdateJobButtons(); 142 _UpdatePrinterButtons(); 143 break; 144 } 145 146 case kMsgAddPrinter: 147 if (!fAddingPrinter) { 148 fAddingPrinter = true; 149 new AddPrinterDialog(this); 150 } 151 break; 152 153 case kMsgAddPrinterClosed: 154 fAddingPrinter = false; 155 break; 156 157 case kMsgRemovePrinter: 158 { 159 fSelectedPrinter = fPrinterListView->SelectedItem(); 160 if (fSelectedPrinter) 161 fSelectedPrinter->Remove(fPrinterListView); 162 break; 163 } 164 165 case kMsgMakeDefaultPrinter: 166 { 167 PrinterItem* printer = fPrinterListView->SelectedItem(); 168 if (printer && printer == fPrinterListView->ActivePrinter()) 169 break; 170 BMessenger msgr; 171 if (printer && GetPrinterServerMessenger(msgr) == B_OK) { 172 BMessage setActivePrinter(B_SET_PROPERTY); 173 setActivePrinter.AddSpecifier("ActivePrinter"); 174 setActivePrinter.AddString("data", printer->Name()); 175 msgr.SendMessage(&setActivePrinter); 176 _UpdatePrinterButtons(); 177 } 178 break; 179 } 180 181 case kMsgPrintTestPage: 182 { 183 fSelectedPrinter = fPrinterListView->SelectedItem(); 184 if (fSelectedPrinter) 185 PrintTestPage(fSelectedPrinter); 186 break; 187 } 188 189 case kMsgCancelJob: 190 fJobListView->CancelJob(); 191 break; 192 193 case kMsgRestartJob: 194 fJobListView->RestartJob(); 195 break; 196 197 case kMsgJobSelected: 198 _UpdateJobButtons(); 199 break; 200 201 case B_PRINTER_CHANGED: 202 { 203 // active printer could have been changed, even outside of prefs 204 BString activePrinterName(ActivePrinterName()); 205 PrinterItem* item = fPrinterListView->ActivePrinter(); 206 if (item && item->Name() != activePrinterName) 207 fPrinterListView->UpdateItem(item); 208 209 for (int32 i = 0; i < fPrinterListView->CountItems(); ++i) { 210 item = dynamic_cast<PrinterItem*>(fPrinterListView->ItemAt(i)); 211 if (item && item->Name() == activePrinterName) { 212 fPrinterListView->UpdateItem(item); 213 fPrinterListView->SetActivePrinter(item); 214 break; 215 } 216 } 217 } break; 218 219 default: 220 Inherited::MessageReceived(msg); 221 } 222 } 223 224 225 void 226 PrintersWindow::PrintTestPage(PrinterItem* printer) 227 { 228 BPrintJob* job = new BPrintJob(B_TRANSLATE("Test page")); 229 job->ConfigPage(); 230 231 // job->ConfigJob(); 232 233 BMessage* settings = job->Settings(); 234 if (settings == NULL) { 235 delete job; 236 return; 237 } 238 239 // enforce job config properties 240 settings->AddInt32("copies", 1); 241 settings->AddInt32("first_page", 1); 242 settings->AddInt32("last_page", -1); 243 244 BWindow* win = new TestPageWindow(job, printer); 245 win->Show(); 246 win->PostMessage(kMsgPrintTestPage); 247 } 248 249 250 void 251 PrintersWindow::AddJob(SpoolFolder* folder, Job* job) 252 { 253 if (_IsSelected(folder->Item())) 254 fJobListView->AddJob(job); 255 fPrinterListView->UpdateItem(folder->Item()); 256 _UpdatePrinterButtons(); 257 } 258 259 260 void 261 PrintersWindow::RemoveJob(SpoolFolder* folder, Job* job) 262 { 263 if (_IsSelected(folder->Item())) 264 fJobListView->RemoveJob(job); 265 fPrinterListView->UpdateItem(folder->Item()); 266 _UpdatePrinterButtons(); 267 } 268 269 270 void 271 PrintersWindow::UpdateJob(SpoolFolder* folder, Job* job) 272 { 273 if (_IsSelected(folder->Item())) { 274 fJobListView->UpdateJob(job); 275 _UpdateJobButtons(); 276 } 277 fPrinterListView->UpdateItem(folder->Item()); 278 _UpdatePrinterButtons(); 279 } 280 281 282 // #pragma mark - 283 284 285 void 286 PrintersWindow::_BuildGUI() 287 { 288 // ------------------------ Next, build the printers overview box 289 BBox* printersBox = new BBox("printersBox"); 290 printersBox->SetFont(be_bold_font); 291 printersBox->SetLabel(B_TRANSLATE("Printers")); 292 293 // Add Button 294 BButton* addButton = new BButton("add", 295 B_TRANSLATE("Add" B_UTF8_ELLIPSIS), new BMessage(kMsgAddPrinter)); 296 addButton->SetExplicitMaxSize( 297 BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET)); 298 299 // Remove button 300 fRemove = new BButton("remove", 301 B_TRANSLATE("Remove"), new BMessage(kMsgRemovePrinter)); 302 fRemove->SetExplicitMaxSize( 303 BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET)); 304 305 // Make Default button 306 fMakeDefault = new BButton("default", 307 B_TRANSLATE("Make default"), new BMessage(kMsgMakeDefaultPrinter)); 308 fMakeDefault->SetExplicitMaxSize( 309 BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET)); 310 311 // Print Test Page button 312 fPrintTestPage = new BButton("print_test_page", 313 B_TRANSLATE("Print test page"), new BMessage(kMsgPrintTestPage)); 314 fPrintTestPage->SetExplicitMaxSize( 315 BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET)); 316 317 // Disable all selection-based buttons 318 fRemove->SetEnabled(false); 319 fMakeDefault->SetEnabled(false); 320 fPrintTestPage->SetEnabled(false); 321 322 // Create listview with scroller 323 fPrinterListView = new PrinterListView(BRect()); 324 BScrollView* printerScrollView = new BScrollView("printer_scroller", 325 fPrinterListView, B_FOLLOW_ALL, B_WILL_DRAW | B_FRAME_EVENTS, 326 false, true, B_FANCY_BORDER); 327 328 printerScrollView->SetExplicitMinSize( 329 BSize(be_plain_font->Size() * 30, B_SIZE_UNSET)); 330 331 float padding = be_control_look->DefaultItemSpacing(); 332 333 BLayoutBuilder::Group<>(printersBox, B_HORIZONTAL, padding) 334 .SetInsets(padding, padding * 2, padding, padding) 335 .Add(printerScrollView) 336 .AddGroup(B_VERTICAL, padding / 2, 0.0f) 337 .SetInsets(0) 338 .Add(addButton) 339 .Add(fRemove) 340 .Add(fMakeDefault) 341 .Add(fPrintTestPage) 342 .AddGlue(); 343 344 // ------------------------ Lastly, build the jobs overview box 345 fJobsBox = new BBox("jobsBox"); 346 fJobsBox->SetFont(be_bold_font); 347 fJobsBox->SetLabel(B_TRANSLATE("Print jobs: No printer selected")); 348 349 // Cancel Job Button 350 fCancel = new BButton("cancel", 351 B_TRANSLATE("Cancel job"), new BMessage(kMsgCancelJob)); 352 fCancel->SetExplicitMaxSize( 353 BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET)); 354 355 // Restart Job button 356 fRestart = new BButton("restart", 357 B_TRANSLATE("Restart job"), new BMessage(kMsgRestartJob)); 358 fRestart->SetExplicitMaxSize( 359 BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET)); 360 361 // Disable all selection-based buttons 362 fCancel->SetEnabled(false); 363 fRestart->SetEnabled(false); 364 365 // Create listview with scroller 366 fJobListView = new JobListView(BRect()); 367 BScrollView* jobScrollView = new BScrollView("jobs_scroller", 368 fJobListView, B_FOLLOW_ALL, B_WILL_DRAW | B_FRAME_EVENTS, 369 false, true, B_FANCY_BORDER); 370 371 BLayoutBuilder::Group<>(fJobsBox, B_HORIZONTAL, padding) 372 .SetInsets(padding, padding * 2, padding, padding) 373 .Add(jobScrollView) 374 .AddGroup(B_VERTICAL, padding / 2, 0.0f) 375 .SetInsets(0) 376 .Add(fCancel) 377 .Add(fRestart) 378 .AddGlue(); 379 380 BLayoutBuilder::Group<>(this, B_VERTICAL, 0) 381 .SetInsets(B_USE_WINDOW_SPACING) 382 .Add(printersBox) 383 .AddStrut(B_USE_DEFAULT_SPACING) 384 .Add(fJobsBox); 385 386 // There is a better solution? 387 Layout(true); 388 if (fPrintTestPage->Bounds().Width() > fRestart->Bounds().Width()) 389 fRestart->SetExplicitMinSize( 390 BSize(fPrintTestPage->Bounds().Width(), B_SIZE_UNSET)); 391 else 392 fPrintTestPage->SetExplicitMinSize( 393 BSize(fRestart->Bounds().Width(), B_SIZE_UNSET)); 394 } 395 396 397 bool 398 PrintersWindow::_IsSelected(PrinterItem* printer) 399 { 400 return fSelectedPrinter && fSelectedPrinter == printer; 401 } 402 403 404 void 405 PrintersWindow::_UpdatePrinterButtons() 406 { 407 PrinterItem* item = fPrinterListView->SelectedItem(); 408 fRemove->SetEnabled(item && !item->HasPendingJobs()); 409 fMakeDefault->SetEnabled(item && !item->IsActivePrinter()); 410 fPrintTestPage->SetEnabled(item); 411 } 412 413 414 void 415 PrintersWindow::_UpdateJobButtons() 416 { 417 JobItem* item = fJobListView->SelectedItem(); 418 if (item != NULL) { 419 Job* job = item->GetJob(); 420 fCancel->SetEnabled(job->Status() != kProcessing); 421 fRestart->SetEnabled(job->Status() == kFailed); 422 } else { 423 fCancel->SetEnabled(false); 424 fRestart->SetEnabled(false); 425 } 426 } 427 428 429