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