xref: /haiku/src/preferences/printers/JobListView.cpp (revision 3ecb7fb4415b319b6aac606551d51efad21037df)
1 /*
2  * Copyright 2001-2010, Haiku.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Michael Pfeiffer
7  */
8 
9 
10 #include "JobListView.h"
11 
12 #include <stdio.h>
13 
14 #include <Catalog.h>
15 #include <Locale.h>
16 #include <MimeType.h>
17 #include <Roster.h>
18 #include <Window.h>
19 
20 #include "pr_server.h"
21 #include "Globals.h"
22 #include "Jobs.h"
23 #include "Messages.h"
24 #include "SpoolFolder.h"
25 
26 
27 #undef B_TRANSLATION_CONTEXT
28 #define B_TRANSLATION_CONTEXT "JobListView"
29 
30 
31 // #pragma mark -- JobListView
32 
33 
34 JobListView::JobListView(BRect frame)
35 	:
36 	Inherited(frame, "jobs_list", B_SINGLE_SELECTION_LIST, B_FOLLOW_ALL,
37 		B_WILL_DRAW | B_FRAME_EVENTS | B_NAVIGABLE | B_FULL_UPDATE_ON_RESIZE)
38 {
39 }
40 
41 
42 JobListView::~JobListView()
43 {
44 	while (!IsEmpty())
45 		delete RemoveItem((int32)0);
46 }
47 
48 
49 void
50 JobListView::AttachedToWindow()
51 {
52 	Inherited::AttachedToWindow();
53 
54 	SetSelectionMessage(new BMessage(kMsgJobSelected));
55 	SetTarget(Window());
56 }
57 
58 
59 void
60 JobListView::SetSpoolFolder(SpoolFolder* folder)
61 {
62 	// clear list
63 	while (!IsEmpty())
64 		delete RemoveItem((int32)0);
65 
66 	if (folder == NULL)
67 		return;
68 
69 	// Find directory containing printer definition nodes
70 	for (int32 i = 0; i < folder->CountJobs(); i++)
71 		AddJob(folder->JobAt(i));
72 }
73 
74 
75 JobItem*
76 JobListView::FindJob(Job* job) const
77 {
78 	const int32 n = CountItems();
79 	for (int32 i = 0; i < n; i++) {
80 		JobItem* item = dynamic_cast<JobItem*>(ItemAt(i));
81 		if (item && item->GetJob() == job)
82 			return item;
83 	}
84 	return NULL;
85 }
86 
87 
88 JobItem*
89 JobListView::SelectedItem() const
90 {
91 	return dynamic_cast<JobItem*>(ItemAt(CurrentSelection()));
92 }
93 
94 
95 void
96 JobListView::AddJob(Job* job)
97 {
98 	AddItem(new JobItem(job));
99 	Invalidate();
100 }
101 
102 
103 void
104 JobListView::RemoveJob(Job* job)
105 {
106 	JobItem* item = FindJob(job);
107 	if (item) {
108 		RemoveItem(item);
109 		delete item;
110 		Invalidate();
111 	}
112 }
113 
114 
115 void
116 JobListView::UpdateJob(Job* job)
117 {
118 	JobItem* item = FindJob(job);
119 	if (item) {
120 		item->Update();
121 		InvalidateItem(IndexOf(item));
122 	}
123 }
124 
125 
126 void
127 JobListView::RestartJob()
128 {
129 	JobItem* item = SelectedItem();
130 	if (item && item->GetJob()->Status() == kFailed) {
131 		// setting the state changes the file attribute and
132 		// we will receive a notification from SpoolFolder
133 		item->GetJob()->SetStatus(kWaiting);
134 	}
135 }
136 
137 
138 void
139 JobListView::CancelJob()
140 {
141 	JobItem* item = SelectedItem();
142 	if (item && item->GetJob()->Status() != kProcessing) {
143 		item->GetJob()->SetStatus(kFailed);
144 		item->GetJob()->Remove();
145 	}
146 }
147 
148 
149 // #pragma mark -- JobItem
150 
151 
152 JobItem::JobItem(Job* job)
153 	:
154 	BListItem(0, false),
155 	fJob(job),
156 	fIcon(NULL)
157 {
158 	fJob->Acquire();
159 	Update();
160 }
161 
162 
163 JobItem::~JobItem()
164 {
165 	fJob->Release();
166 	delete fIcon;
167 }
168 
169 
170 void
171 JobItem::Update()
172 {
173 	BNode node(&fJob->EntryRef());
174 	if (node.InitCheck() != B_OK)
175 		return;
176 
177 	node.ReadAttrString(PSRV_SPOOL_ATTR_DESCRIPTION, &fName);
178 
179 	BString mimeType;
180 	node.ReadAttrString(PSRV_SPOOL_ATTR_MIMETYPE, &mimeType);
181 
182 	entry_ref ref;
183 	if (fIcon == NULL && be_roster->FindApp(mimeType.String(), &ref) == B_OK) {
184 #ifdef HAIKU_TARGET_PLATFORM_HAIKU
185 		font_height fontHeight;
186 		be_plain_font->GetHeight(&fontHeight);
187 		float height = (fontHeight.ascent + fontHeight.descent
188 			+ fontHeight.leading) * 2.0;
189 		BRect rect(0, 0, height, height);
190 		fIcon = new BBitmap(rect, B_RGBA32);
191 #else
192 		BRect rect(0, 0, B_MINI_ICON - 1, B_MINI_ICON - 1);
193 		fIcon = new BBitmap(rect, B_CMAP8);
194 #endif
195 		BMimeType type(mimeType.String());
196 		if (type.GetIcon(fIcon, B_MINI_ICON) != B_OK) {
197 			delete fIcon;
198 			fIcon = NULL;
199 		}
200 	}
201 
202 	fPages = "";
203 	int32 pages;
204 	if (node.ReadAttr(PSRV_SPOOL_ATTR_PAGECOUNT,
205 		B_INT32_TYPE, 0, &pages, sizeof(pages)) == sizeof(pages)) {
206 		fPages << pages;
207 		if (pages > 1)
208 			fPages << " " << B_TRANSLATE("pages") << ".";
209 		else
210 			fPages << " " << B_TRANSLATE("page") << ".";
211 	} else {
212 		fPages << "??? " << B_TRANSLATE("pages") << ".";
213 	}
214 
215 	fSize = "";
216 	off_t size;
217 	if (node.GetSize(&size) == B_OK) {
218 		char buffer[80];
219 		snprintf(buffer, sizeof(buffer), B_TRANSLATE("%.2f KB"),
220 			size / 1024.0);
221 		fSize = buffer;
222 	}
223 
224 	fStatus = "";
225 	switch (fJob->Status()) {
226 		case kWaiting:
227 			fStatus = B_TRANSLATE("Waiting");
228 			break;
229 
230 		case kProcessing:
231 			fStatus = B_TRANSLATE("Processing");
232 			break;
233 
234 		case kFailed:
235 			fStatus = B_TRANSLATE("Failed");
236 			break;
237 
238 		case kCompleted:
239 			fStatus = B_TRANSLATE("Completed");
240 			break;
241 
242 		default:
243 			fStatus = B_TRANSLATE("Unknown status");
244 	}
245 }
246 
247 
248 void
249 JobItem::Update(BView *owner, const BFont *font)
250 {
251 	BListItem::Update(owner, font);
252 
253 	font_height height;
254 	font->GetHeight(&height);
255 
256 	SetHeight((height.ascent + height.descent + height.leading) * 2.0 + 8.0);
257 }
258 
259 
260 void
261 JobItem::DrawItem(BView *owner, BRect, bool complete)
262 {
263 	BListView* list = dynamic_cast<BListView*>(owner);
264 	if (list) {
265 		BFont font;
266 		owner->GetFont(&font);
267 
268 		font_height height;
269 		font.GetHeight(&height);
270 		float fntheight = height.ascent + height.descent + height.leading;
271 
272 		BRect bounds = list->ItemFrame(list->IndexOf(this));
273 
274 		rgb_color color = owner->ViewColor();
275 		rgb_color oldLowColor = owner->LowColor();
276 		rgb_color oldHighColor = owner->HighColor();
277 
278 		if (IsSelected())
279 			color = ui_color(B_LIST_SELECTED_BACKGROUND_COLOR);
280 
281 		owner->SetHighColor(color);
282 		owner->SetLowColor(color);
283 
284 		owner->FillRect(bounds);
285 
286 		owner->SetLowColor(oldLowColor);
287 		owner->SetHighColor(oldHighColor);
288 
289 		BPoint iconPt(bounds.LeftTop() + BPoint(2.0, 2.0));
290 		float iconHeight = B_MINI_ICON;
291 #ifdef HAIKU_TARGET_PLATFORM_HAIKU
292 		if (fIcon)
293 			iconHeight = fIcon->Bounds().Height();
294 #endif
295 		BPoint leftTop(bounds.LeftTop() + BPoint(12.0 + iconHeight, 2.0));
296 		BPoint namePt(leftTop + BPoint(0.0, fntheight));
297 		BPoint statusPt(leftTop + BPoint(0.0, fntheight * 2.0));
298 
299 		float x = owner->StringWidth(fPages.String()) + 32.0;
300 		BPoint pagePt(bounds.RightTop() + BPoint(-x, fntheight));
301 		BPoint sizePt(bounds.RightTop() + BPoint(-x, fntheight * 2.0));
302 
303 		drawing_mode mode = owner->DrawingMode();
304 #ifdef HAIKU_TARGET_PLATFORM_HAIKU
305 	owner->SetDrawingMode(B_OP_ALPHA);
306 #else
307 	owner->SetDrawingMode(B_OP_OVER);
308 #endif
309 
310 		if (fIcon)
311 			owner->DrawBitmap(fIcon, iconPt);
312 
313 		// left of item
314 		owner->DrawString(fName.String(), fName.Length(), namePt);
315 		owner->DrawString(fStatus.String(), fStatus.Length(), statusPt);
316 
317 		// right of item
318 		owner->DrawString(fPages.String(), fPages.Length(), pagePt);
319 		owner->DrawString(fSize.String(), fSize.Length(), sizePt);
320 
321 		owner->SetDrawingMode(mode);
322 	}
323 }
324