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