/* * Copyright 2002-2009, Haiku. * Distributed under the terms of the MIT License. * * Authors: * Michael Pfeiffer * Philippe Houdoin */ #include "AddPrinterDialog.h" #include "PrinterListView.h" #include "pr_server.h" #include "Globals.h" #include "Messages.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #undef TR_CONTEXT #define TR_CONTEXT "AddPrinterDialog" AddPrinterDialog::AddPrinterDialog(BWindow *parent) : Inherited(BRect(78.0, 71.0, 400, 300), TR("Add printer"), B_TITLED_WINDOW_LOOK, B_MODAL_APP_WINDOW_FEEL, B_NOT_ZOOMABLE | B_AUTO_UPDATE_SIZE_LIMITS), fPrintersPrefletMessenger(parent) { BuildGUI(0); Show(); } bool AddPrinterDialog::QuitRequested() { fPrintersPrefletMessenger.SendMessage(kMsgAddPrinterClosed); return Inherited::QuitRequested(); } void AddPrinterDialog::MessageReceived(BMessage* msg) { switch(msg->what) { case B_OK: AddPrinter(msg); PostMessage(B_QUIT_REQUESTED); break; case B_CANCEL: PostMessage(B_QUIT_REQUESTED); break; case kNameChangedMsg: fNameText = fName->Text(); Update(); break; case kPrinterSelectedMsg: StorePrinter(msg); break; case kTransportSelectedMsg: HandleChangedTransport(msg); break; default: Inherited::MessageReceived(msg); } } void AddPrinterDialog::AddPrinter(BMessage *msg) { BMessage m(PSRV_MAKE_PRINTER); BMessenger msgr; if (GetPrinterServerMessenger(msgr) != B_OK) return; BString transport; BString transportPath; if (fPrinterText != "Preview") { // Preview printer does not use transport add-on transport = fTransportText; transportPath = fTransportPathText; } m.AddString("driver", fPrinterText.String()); m.AddString("transport", transport.String()); m.AddString("transport path", transportPath.String()); m.AddString("printer name", fNameText.String()); m.AddString("connection", "Local"); msgr.SendMessage(&m); // request print_server to create printer } void AddPrinterDialog::StorePrinter(BMessage *msg) { BString name; if (msg->FindString("name", &name) != B_OK) name = ""; fPrinterText = name; Update(); } void AddPrinterDialog::HandleChangedTransport(BMessage *msg) { BString name; if (msg->FindString("name", &name) != B_OK) { name = ""; } fTransportText = name; BString path; if (msg->FindString("path", &path) == B_OK) { // transport path selected fTransportPathText = path; // mark sub menu void* pointer; if (msg->FindPointer("source", &pointer) == B_OK) { BMenuItem* item = (BMenuItem*)pointer; // Update printer name with Transport Path if not filled in if (strlen(fName->Text()) == 0) fName->SetText(item->Label()); BMenu* menu = item->Menu(); int32 index = fTransport->IndexOf(menu); item = fTransport->ItemAt(index); if (item != NULL) item->SetMarked(true); } } else { // transport selected fTransportPathText = ""; // remove mark from item in sub menu of transport sub menu for (int32 i = fTransport->CountItems()-1; i >= 0; i --) { BMenu* menu = fTransport->SubmenuAt(i); if (menu != NULL) { BMenuItem* item = menu->FindMarked(); if (item != NULL) item->SetMarked(false); } } } Update(); } void AddPrinterDialog::BuildGUI(int stage) { // add a "printer name" input field fName = new BTextControl("printer_name", TR("Printer name:"), B_EMPTY_STRING, NULL); fName->SetFont(be_bold_font); fName->SetAlignment(B_ALIGN_RIGHT, B_ALIGN_LEFT); fName->SetModificationMessage(new BMessage(kNameChangedMsg)); // add a "driver" popup menu field fPrinter = new BPopUpMenu(TR("")); BMenuField *printerMenuField = new BMenuField("drivers_list", TR("Printer type:"), fPrinter); printerMenuField->SetAlignment(B_ALIGN_RIGHT); FillMenu(fPrinter, "Print", kPrinterSelectedMsg); // add a "connected to" (aka transports list) menu field fTransport = new BPopUpMenu(TR("")); BMenuField *transportMenuField = new BMenuField("transports_list", TR("Connected to:"), fTransport); transportMenuField->SetAlignment(B_ALIGN_RIGHT); FillTransportMenu(fTransport); // add a "OK" button fOk = new BButton(NULL, TR("Add"), new BMessage((uint32)B_OK), B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM); // add a "Cancel button BButton *cancel = new BButton(NULL, TR("Cancel"), new BMessage(B_CANCEL)); SetLayout(new BGridLayout()); AddChild(BGridLayoutBuilder(0, 4) .Add(fName->CreateLabelLayoutItem(), 0, 0) .Add(fName->CreateTextViewLayoutItem(), 1, 0) .Add(printerMenuField->CreateLabelLayoutItem(), 0, 1) .Add(printerMenuField->CreateMenuBarLayoutItem(), 1, 1) .Add(transportMenuField->CreateLabelLayoutItem(), 0, 2) .Add(transportMenuField->CreateMenuBarLayoutItem(), 1, 2) .Add(BGroupLayoutBuilder(B_HORIZONTAL) .AddGlue() .Add(cancel) .Add(fOk) , 0, 3, 2) .SetInsets(8, 8, 8, 8) ); SetDefaultButton(fOk); fOk->MakeDefault(true); fName->MakeFocus(true); Update(); // Stage == 0 // init_icon 64x114 Add a Local or Network Printer // ------------------------------ // I would like to add a... // Local Printer // Network Printer // ------------------------------------------------ // Cancel Continue // Add local printer: // Stage == 1 // local_icon Add a Local Printer // ------------------------------ // Printer Name: ________________ // Printer Type: pick one // Connected to: pick one // ------------------------------------------------ // Cancel Add // This seems to be hard coded into the preferences dialog: // Don't show Network transport add-on in Printer Type menu. // If Printer Type == Preview disable Connect to popup menu. // If Printer Type == Serial Port add a submenu to menu item // with names in /dev/ports (if empty remove item from menu) // If Printer Type == Parallel Port add a submenu to menu item // with names in /dev/parallel (if empty remove item from menu) // Printer Driver Setup // Dialog Info // Would you like to make X the default printer? // No Yes // Add network printer: // Dialog Info // Apple Talk networking isn't currenty enabled. If you // wish to install a network printer you should enable // AppleTalk in the Network preferences. // Cancel Open Network // Stage == 2 // network_icon Add a Network Printer // ------------------------------ // Printer Name: ________________ // Printer Type: pick one // AppleTalk Printer: pick one // ------------------------------------------------ // Cancel Add } static directory_which gAddonDirs[] = { B_BEOS_ADDONS_DIRECTORY, B_COMMON_ADDONS_DIRECTORY, B_USER_ADDONS_DIRECTORY }; void AddPrinterDialog::FillMenu(BMenu* menu, const char* path, uint32 what) { for (uint32 i = 0; i < sizeof(gAddonDirs) / sizeof(directory_which); i ++) { BPath addonPath; if (find_directory(gAddonDirs[i], &addonPath) != B_OK) continue; if (addonPath.Append(path) != B_OK) continue; BDirectory dir(addonPath.Path()); if (dir.InitCheck() != B_OK) continue; BEntry entry; while (dir.GetNextEntry(&entry, true) == B_OK) { if (!entry.IsFile()) continue; BNode node(&entry); if (node.InitCheck() != B_OK) continue; BNodeInfo info(&node); if (info.InitCheck() != B_OK) continue; char type[B_MIME_TYPE_LENGTH + 1]; info.GetType(type); if (strcmp(type, B_APP_MIME_TYPE) != 0) continue; BPath path; if (entry.GetPath(&path) != B_OK) continue; BMessage* msg = new BMessage(what); msg->AddString("name", path.Leaf()); menu->AddItem(new BMenuItem(path.Leaf(), msg)); } } } void AddPrinterDialog::FillTransportMenu(BMenu* menu) { BMessenger msgr; if (GetPrinterServerMessenger(msgr) != B_OK) return; for (long idx=0; ; idx++) { BMessage reply, msg(B_GET_PROPERTY); msg.AddSpecifier("Transport", idx); if (msgr.SendMessage(&msg,&reply) != B_OK) break; BMessenger transport; if (reply.FindMessenger("result", &transport) != B_OK) break; // Got messenger to transport now msg.MakeEmpty(); msg.what = B_GET_PROPERTY; msg.AddSpecifier("Name"); if (transport.SendMessage(&msg,&reply) != B_OK) continue; BString transportName; if (reply.FindString("result",&transportName) != B_OK) continue; // Now get ports... BString portId, portName; msg.MakeEmpty(); msg.what = B_GET_PROPERTY; msg.AddSpecifier("Ports"); if (transport.SendMessage(&msg,&reply) != B_OK || reply.FindString("port_id", &portId) != B_OK) { // Can't find ports; so just show transport item, no menu BMessage* menuMsg = new BMessage(kTransportSelectedMsg); menuMsg->AddString("name", transportName); menu->AddItem(new BMenuItem(transportName.String(), menuMsg)); continue; } // We have at least one port; so create submenu BMenu* transportMenu = new BMenu(transportName.String()); menu->AddItem(transportMenu); transportMenu->SetRadioMode(true); menu->ItemAt(menu->IndexOf(transportMenu))-> SetMessage(new BMessage(kTransportSelectedMsg)); for (int32 pidx=0; reply.FindString("port_id", pidx, &portId) == B_OK; pidx++) { if (reply.FindString("port_name", pidx, &portName) != B_OK || !portName.Length()) portName = portId; // Create menu item in submenu for port BMessage* portMsg = new BMessage(kTransportSelectedMsg); portMsg->AddString("name", transportName); portMsg->AddString("path", portId); transportMenu->AddItem(new BMenuItem(portName.String(), portMsg)); } } } void AddPrinterDialog::Update() { fOk->SetEnabled(fNameText != "" && fPrinterText != "" && (fTransportText != "" || fPrinterText == "Preview")); fTransport->SetEnabled(fPrinterText != "Preview"); }