/* * Copyright 2001-2011, Haiku. * Distributed under the terms of the MIT License. * * Authors: * Michael Pfeiffer * Philippe Houdoin */ #include "PrintersWindow.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include "pr_server.h" #include "AddPrinterDialog.h" #include "Globals.h" #include "JobListView.h" #include "Messages.h" #include "PrinterListView.h" #include "TestPageView.h" #include "ScreenSettings.h" #include "SpoolFolder.h" #undef B_TRANSLATION_CONTEXT #define B_TRANSLATION_CONTEXT "PrintersWindow" class TestPageWindow : public BWindow { public: TestPageWindow(BPrintJob* job, PrinterItem* printer); virtual ~TestPageWindow(); void MessageReceived(BMessage* message); private: BPrintJob* fJob; TestPageView* fTestPage; }; TestPageWindow::TestPageWindow(BPrintJob* job, PrinterItem* printer) : BWindow(job->PaperRect().OffsetByCopy(-20000, -20000), B_TRANSLATE("Test page"), B_TITLED_WINDOW, 0), fJob(job) { fTestPage = new TestPageView(job->PrintableRect(), printer); // SetLayout(new BGroupLayout(B_VERTICAL)); AddChild(fTestPage); } TestPageWindow::~TestPageWindow() { delete fJob; } void TestPageWindow::MessageReceived(BMessage* message) { if (message->what != kMsgPrintTestPage) { BWindow::MessageReceived(message); return; } fJob->BeginJob(); fJob->DrawView(fTestPage, fTestPage->Bounds(), B_ORIGIN); fJob->SpoolPage(); if (!fJob->CanContinue()) return; fJob->CommitJob(); Quit(); } // #pragma mark PrintersWindow main class PrintersWindow::PrintersWindow(ScreenSettings* settings) : BWindow(settings->WindowFrame(), B_TRANSLATE_SYSTEM_NAME("Printers"), B_TITLED_WINDOW, B_AUTO_UPDATE_SIZE_LIMITS), fSettings(settings), fSelectedPrinter(NULL), fAddingPrinter(false) { _BuildGUI(); } PrintersWindow::~PrintersWindow() { delete fSettings; } bool PrintersWindow::QuitRequested() { fSettings->SetWindowFrame(Frame()); bool result = Inherited::QuitRequested(); if (result) be_app->PostMessage(B_QUIT_REQUESTED); return result; } void PrintersWindow::MessageReceived(BMessage* msg) { switch (msg->what) { case kMsgPrinterSelected: { fSelectedPrinter = fPrinterListView->SelectedItem(); if (fSelectedPrinter) { BString text = B_TRANSLATE("Print jobs for %printer_name%"); text.ReplaceFirst("%printer_name%", fSelectedPrinter->Name()); fJobsBox->SetLabel(text); fMakeDefault->SetEnabled(true); fRemove->SetEnabled(true); fJobListView->SetSpoolFolder(fSelectedPrinter->Folder()); } else { fJobsBox->SetLabel( B_TRANSLATE("Print jobs: No printer selected")); fMakeDefault->SetEnabled(false); fRemove->SetEnabled(false); fSelectedPrinter = NULL; fJobListView->SetSpoolFolder(NULL); } _UpdateJobButtons(); _UpdatePrinterButtons(); break; } case kMsgAddPrinter: if (!fAddingPrinter) { fAddingPrinter = true; new AddPrinterDialog(this); } break; case kMsgAddPrinterClosed: fAddingPrinter = false; break; case kMsgRemovePrinter: { fSelectedPrinter = fPrinterListView->SelectedItem(); if (fSelectedPrinter) fSelectedPrinter->Remove(fPrinterListView); break; } case kMsgMakeDefaultPrinter: { PrinterItem* printer = fPrinterListView->SelectedItem(); if (printer && printer == fPrinterListView->ActivePrinter()) break; BMessenger msgr; if (printer && GetPrinterServerMessenger(msgr) == B_OK) { BMessage setActivePrinter(B_SET_PROPERTY); setActivePrinter.AddSpecifier("ActivePrinter"); setActivePrinter.AddString("data", printer->Name()); msgr.SendMessage(&setActivePrinter); _UpdatePrinterButtons(); } break; } case kMsgPrintTestPage: { fSelectedPrinter = fPrinterListView->SelectedItem(); if (fSelectedPrinter) PrintTestPage(fSelectedPrinter); break; } case kMsgCancelJob: fJobListView->CancelJob(); break; case kMsgRestartJob: fJobListView->RestartJob(); break; case kMsgJobSelected: _UpdateJobButtons(); break; case B_PRINTER_CHANGED: { // active printer could have been changed, even outside of prefs BString activePrinterName(ActivePrinterName()); PrinterItem* item = fPrinterListView->ActivePrinter(); if (item && item->Name() != activePrinterName) fPrinterListView->UpdateItem(item); for (int32 i = 0; i < fPrinterListView->CountItems(); ++i) { item = dynamic_cast(fPrinterListView->ItemAt(i)); if (item && item->Name() == activePrinterName) { fPrinterListView->UpdateItem(item); fPrinterListView->SetActivePrinter(item); break; } } } break; default: Inherited::MessageReceived(msg); } } void PrintersWindow::PrintTestPage(PrinterItem* printer) { BPrintJob* job = new BPrintJob(B_TRANSLATE("Test page")); job->ConfigPage(); // job->ConfigJob(); BMessage* settings = job->Settings(); if (settings == NULL) { delete job; return; } // enforce job config properties settings->AddInt32("copies", 1); settings->AddInt32("first_page", 1); settings->AddInt32("last_page", -1); BWindow* win = new TestPageWindow(job, printer); win->Show(); win->PostMessage(kMsgPrintTestPage); } void PrintersWindow::AddJob(SpoolFolder* folder, Job* job) { if (_IsSelected(folder->Item())) fJobListView->AddJob(job); fPrinterListView->UpdateItem(folder->Item()); _UpdatePrinterButtons(); } void PrintersWindow::RemoveJob(SpoolFolder* folder, Job* job) { if (_IsSelected(folder->Item())) fJobListView->RemoveJob(job); fPrinterListView->UpdateItem(folder->Item()); _UpdatePrinterButtons(); } void PrintersWindow::UpdateJob(SpoolFolder* folder, Job* job) { if (_IsSelected(folder->Item())) { fJobListView->UpdateJob(job); _UpdateJobButtons(); } fPrinterListView->UpdateItem(folder->Item()); _UpdatePrinterButtons(); } // #pragma mark - void PrintersWindow::_BuildGUI() { // ------------------------ Next, build the printers overview box BBox* printersBox = new BBox("printersBox"); printersBox->SetFont(be_bold_font); printersBox->SetLabel(B_TRANSLATE("Printers")); // Add Button BButton* addButton = new BButton("add", B_TRANSLATE("Add" B_UTF8_ELLIPSIS), new BMessage(kMsgAddPrinter)); addButton->SetExplicitMaxSize( BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET)); // Remove button fRemove = new BButton("remove", B_TRANSLATE("Remove"), new BMessage(kMsgRemovePrinter)); fRemove->SetExplicitMaxSize( BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET)); // Make Default button fMakeDefault = new BButton("default", B_TRANSLATE("Make default"), new BMessage(kMsgMakeDefaultPrinter)); fMakeDefault->SetExplicitMaxSize( BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET)); // Print Test Page button fPrintTestPage = new BButton("print_test_page", B_TRANSLATE("Print test page"), new BMessage(kMsgPrintTestPage)); fPrintTestPage->SetExplicitMaxSize( BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET)); // Disable all selection-based buttons fRemove->SetEnabled(false); fMakeDefault->SetEnabled(false); fPrintTestPage->SetEnabled(false); // Create listview with scroller fPrinterListView = new PrinterListView(BRect()); BScrollView* printerScrollView = new BScrollView("printer_scroller", fPrinterListView, B_FOLLOW_ALL, B_WILL_DRAW | B_FRAME_EVENTS, false, true, B_FANCY_BORDER); printerScrollView->SetExplicitMinSize( BSize(be_plain_font->Size() * 30, B_SIZE_UNSET)); float padding = be_control_look->DefaultItemSpacing(); BLayoutBuilder::Group<>(printersBox, B_HORIZONTAL, padding) .SetInsets(padding, padding * 2, padding, padding) .Add(printerScrollView) .AddGroup(B_VERTICAL, padding / 2, 0.0f) .SetInsets(0) .Add(addButton) .Add(fRemove) .Add(fMakeDefault) .Add(fPrintTestPage) .AddGlue(); // ------------------------ Lastly, build the jobs overview box fJobsBox = new BBox("jobsBox"); fJobsBox->SetFont(be_bold_font); fJobsBox->SetLabel(B_TRANSLATE("Print jobs: No printer selected")); // Cancel Job Button fCancel = new BButton("cancel", B_TRANSLATE("Cancel job"), new BMessage(kMsgCancelJob)); fCancel->SetExplicitMaxSize( BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET)); // Restart Job button fRestart = new BButton("restart", B_TRANSLATE("Restart job"), new BMessage(kMsgRestartJob)); fRestart->SetExplicitMaxSize( BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET)); // Disable all selection-based buttons fCancel->SetEnabled(false); fRestart->SetEnabled(false); // Create listview with scroller fJobListView = new JobListView(BRect()); BScrollView* jobScrollView = new BScrollView("jobs_scroller", fJobListView, B_FOLLOW_ALL, B_WILL_DRAW | B_FRAME_EVENTS, false, true, B_FANCY_BORDER); BLayoutBuilder::Group<>(fJobsBox, B_HORIZONTAL, padding) .SetInsets(padding, padding * 2, padding, padding) .Add(jobScrollView) .AddGroup(B_VERTICAL, padding / 2, 0.0f) .SetInsets(0) .Add(fCancel) .Add(fRestart) .AddGlue(); BLayoutBuilder::Group<>(this, B_VERTICAL, 0) .SetInsets(B_USE_WINDOW_SPACING) .Add(printersBox) .AddStrut(B_USE_DEFAULT_SPACING) .Add(fJobsBox); // There is a better solution? Layout(true); if (fPrintTestPage->Bounds().Width() > fRestart->Bounds().Width()) fRestart->SetExplicitMinSize( BSize(fPrintTestPage->Bounds().Width(), B_SIZE_UNSET)); else fPrintTestPage->SetExplicitMinSize( BSize(fRestart->Bounds().Width(), B_SIZE_UNSET)); } bool PrintersWindow::_IsSelected(PrinterItem* printer) { return fSelectedPrinter && fSelectedPrinter == printer; } void PrintersWindow::_UpdatePrinterButtons() { PrinterItem* item = fPrinterListView->SelectedItem(); fRemove->SetEnabled(item && !item->HasPendingJobs()); fMakeDefault->SetEnabled(item && !item->IsActivePrinter()); fPrintTestPage->SetEnabled(item); } void PrintersWindow::_UpdateJobButtons() { JobItem* item = fJobListView->SelectedItem(); if (item != NULL) { Job* job = item->GetJob(); fCancel->SetEnabled(job->Status() != kProcessing); fRestart->SetEnabled(job->Status() == kFailed); } else { fCancel->SetEnabled(false); fRestart->SetEnabled(false); } }