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