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