00001 #include <qlayout.h>
00002 #include <qpushbutton.h>
00003 #include <qbuttongroup.h>
00004 #include <qlabel.h>
00005 #include <qcursor.h>
00006 #include <qsqldatabase.h>
00007 #include <qdatetime.h>
00008 #include <qapplication.h>
00009 #include <qregexp.h>
00010 #include <qheader.h>
00011
00012 #include <iostream>
00013 #include <map>
00014 #include <vector>
00015 #include <algorithm>
00016 using namespace std;
00017
00018 #include "programrecpriority.h"
00019 #include "scheduledrecording.h"
00020 #include "customedit.h"
00021 #include "proglist.h"
00022 #include "tv.h"
00023
00024 #include "exitcodes.h"
00025 #include "dialogbox.h"
00026 #include "mythcontext.h"
00027 #include "mythdbcon.h"
00028 #include "remoteutil.h"
00029
00030
00031
00032
00033 ProgramRecPriorityInfo::ProgramRecPriorityInfo(void) : ProgramInfo()
00034 {
00035 recTypeRecPriority = 0;
00036 recType = kNotRecording;
00037 }
00038
00039 ProgramRecPriorityInfo::ProgramRecPriorityInfo(const ProgramRecPriorityInfo &other)
00040 : ProgramInfo::ProgramInfo(other)
00041 {
00042 recTypeRecPriority = other.recTypeRecPriority;
00043 recType = other.recType;
00044 }
00045
00046 ProgramRecPriorityInfo& ProgramRecPriorityInfo::operator=(const ProgramInfo &other)
00047 {
00048 title = other.title;
00049 subtitle = other.subtitle;
00050 description = other.description;
00051 category = other.category;
00052 chanid = other.chanid;
00053 chanstr = other.chanstr;
00054 chansign = other.chansign;
00055 channame = other.channame;
00056 pathname = other.pathname;
00057 filesize = other.filesize;
00058 hostname = other.hostname;
00059
00060 startts = other.startts;
00061 endts = other.endts;
00062 spread = other.spread;
00063 startCol = other.startCol;
00064
00065 recstatus = other.recstatus;
00066 recordid = other.recordid;
00067 rectype = other.rectype;
00068 dupin = other.dupin;
00069 dupmethod = other.dupmethod;
00070 recgroup = other.recgroup;
00071 playgroup = other.playgroup;
00072 chancommfree = other.chancommfree;
00073
00074 sourceid = other.sourceid;
00075 inputid = other.inputid;
00076 cardid = other.cardid;
00077 schedulerid = other.schedulerid;
00078 recpriority = other.recpriority;
00079
00080 seriesid = other.seriesid;
00081 programid = other.programid;
00082
00083 return(*this);
00084 }
00085
00086 ProgramRecPriority::ProgramRecPriority(MythMainWindow *parent,
00087 const char *name)
00088 : MythDialog(parent, name)
00089 {
00090 curitem = NULL;
00091 bgTransBackup = NULL;
00092 pageDowner = false;
00093
00094 listCount = 0;
00095 dataCount = 0;
00096
00097 fullRect = QRect(0, 0, size().width(), size().height());
00098 listRect = QRect(0, 0, 0, 0);
00099 infoRect = QRect(0, 0, 0, 0);
00100
00101 theme = new XMLParse();
00102 theme->SetWMult(wmult);
00103 theme->SetHMult(hmult);
00104 if (!theme->LoadTheme(xmldata, "recpriorityprograms"))
00105 {
00106 DialogBox *dlg = new DialogBox(
00107 gContext->GetMainWindow(),
00108 QObject::tr(
00109 "The theme you are using does not contain the "
00110 "%1 element. Please contact the theme creator "
00111 "and ask if they could please update it.<br><br>"
00112 "The next screen will be empty. "
00113 "Escape out of it to return to the menu.")
00114 .arg("'recpriorityprograms'"));
00115
00116 dlg->AddButton(tr("OK"));
00117 dlg->exec();
00118 dlg->deleteLater();
00119
00120 return;
00121 }
00122
00123 LoadWindow(xmldata);
00124
00125 LayerSet *container = theme->GetSet("selector");
00126 if (container)
00127 {
00128 UIListType *ltype = (UIListType *)container->GetType("recprioritylist");
00129 if (ltype)
00130 {
00131 listsize = ltype->GetItems();
00132 }
00133 }
00134 else
00135 {
00136 VERBOSE(VB_IMPORTANT, "MythFrontEnd::ProgramRecPriority(): "
00137 "Failed to get selector object.");
00138 exit(FRONTEND_BUGGY_EXIT_NO_SELECTOR);
00139 }
00140
00141 bgTransBackup = gContext->LoadScalePixmap("trans-backup.png");
00142 if (!bgTransBackup)
00143 bgTransBackup = new QPixmap();
00144
00145 updateBackground();
00146
00147 FillList();
00148 sortType = (SortType)gContext->GetNumSetting("ProgramRecPrioritySorting",
00149 (int)byTitle);
00150 reverseSort = gContext->GetNumSetting("ProgramRecPriorityReverse", 0);
00151
00152 SortList();
00153 inList = inData = 0;
00154 setNoErase();
00155
00156 gContext->addListener(this);
00157 gContext->addCurrentLocation("ProgramRecPriority");
00158 }
00159
00160 ProgramRecPriority::~ProgramRecPriority()
00161 {
00162 gContext->removeListener(this);
00163 gContext->removeCurrentLocation();
00164 delete theme;
00165 if (bgTransBackup)
00166 delete bgTransBackup;
00167 if (curitem)
00168 delete curitem;
00169 }
00170
00171 void ProgramRecPriority::keyPressEvent(QKeyEvent *e)
00172 {
00173 bool handled = false;
00174 QStringList actions;
00175 if (gContext->GetMainWindow()->TranslateKeyPress("TV Frontend", e, actions))
00176 {
00177 for (unsigned int i = 0; i < actions.size() && !handled; i++)
00178 {
00179 QString action = actions[i];
00180 handled = true;
00181
00182 if (action == "UP")
00183 cursorUp();
00184 else if (action == "DOWN")
00185 cursorDown();
00186 else if (action == "PAGEUP")
00187 pageUp();
00188 else if (action == "PAGEDOWN")
00189 pageDown();
00190 else if (action == "RANKINC")
00191 changeRecPriority(1);
00192 else if (action == "RANKDEC")
00193 changeRecPriority(-1);
00194 else if ((action == "PAUSE") || (action == "PLAYBACK"))
00195 deactivate();
00196 else if (action == "ESCAPE" || action == "LEFT")
00197 {
00198 saveRecPriority();
00199 gContext->SaveSetting("ProgramRecPrioritySorting",
00200 (int)sortType);
00201 gContext->SaveSetting("ProgramRecPriorityReverse",
00202 (int)reverseSort);
00203 done(MythDialog::Accepted);
00204 }
00205 else if (action == "1")
00206 {
00207 if (sortType != byTitle)
00208 {
00209 sortType = byTitle;
00210 reverseSort = false;
00211 }
00212 else
00213 {
00214 reverseSort = !reverseSort;
00215 }
00216 SortList();
00217 update(fullRect);
00218 }
00219 else if (action == "2")
00220 {
00221 if (sortType != byRecPriority)
00222 {
00223 sortType = byRecPriority;
00224 reverseSort = false;
00225 }
00226 else
00227 {
00228 reverseSort = !reverseSort;
00229 }
00230 SortList();
00231 update(fullRect);
00232 }
00233 else if (action == "4")
00234 {
00235 if (sortType != byRecType)
00236 {
00237 sortType = byRecType;
00238 reverseSort = false;
00239 }
00240 else
00241 {
00242 reverseSort = !reverseSort;
00243 }
00244 SortList();
00245 update(fullRect);
00246 }
00247 else if (action == "5")
00248 {
00249 if (sortType != byCount)
00250 {
00251 sortType = byCount;
00252 reverseSort = false;
00253 }
00254 else
00255 {
00256 reverseSort = !reverseSort;
00257 }
00258 SortList();
00259 update(fullRect);
00260 }
00261 else if (action == "6")
00262 {
00263 if (sortType != byRecCount)
00264 {
00265 sortType = byRecCount;
00266 reverseSort = false;
00267 }
00268 else
00269 {
00270 reverseSort = !reverseSort;
00271 }
00272 SortList();
00273 update(fullRect);
00274 }
00275 else if (action == "7")
00276 {
00277 if (sortType != byLastRecord)
00278 {
00279 sortType = byLastRecord;
00280 reverseSort = false;
00281 }
00282 else
00283 {
00284 reverseSort = !reverseSort;
00285 }
00286 SortList();
00287 update(fullRect);
00288 }
00289 else if (action == "8")
00290 {
00291 if (sortType != byAvgDelay)
00292 {
00293 sortType = byAvgDelay;
00294 reverseSort = false;
00295 }
00296 else
00297 {
00298 reverseSort = !reverseSort;
00299 }
00300 SortList();
00301 update(fullRect);
00302 }
00303 else if (action == "PREVVIEW" || action == "NEXTVIEW")
00304 {
00305 reverseSort = false;
00306 if (sortType == byTitle)
00307 sortType = byRecPriority;
00308 else if (sortType == byRecPriority)
00309 sortType = byRecType;
00310 else
00311 sortType = byTitle;
00312 SortList();
00313 update(fullRect);
00314 }
00315 else if (action == "SELECT" || action == "MENU" ||
00316 action == "INFO")
00317 {
00318 saveRecPriority();
00319 edit();
00320 }
00321 else if (action == "CUSTOMEDIT")
00322 {
00323 saveRecPriority();
00324 customEdit();
00325 }
00326 else if (action == "DELETE")
00327 {
00328 saveRecPriority();
00329 remove();
00330 }
00331 else if (action == "UPCOMING")
00332 {
00333 saveRecPriority();
00334 upcoming();
00335 }
00336 else if (action == "DETAILS")
00337 details();
00338 else
00339 handled = false;
00340 }
00341 }
00342
00343 if (!handled)
00344 MythDialog::keyPressEvent(e);
00345 }
00346
00347 void ProgramRecPriority::LoadWindow(QDomElement &element)
00348 {
00349 for (QDomNode child = element.firstChild(); !child.isNull();
00350 child = child.nextSibling())
00351 {
00352 QDomElement e = child.toElement();
00353 if (!e.isNull())
00354 {
00355 if (e.tagName() == "font")
00356 {
00357 theme->parseFont(e);
00358 }
00359 else if (e.tagName() == "container")
00360 {
00361 parseContainer(e);
00362 }
00363 else
00364 {
00365 VERBOSE(VB_IMPORTANT,
00366 QString("ProgramRecPriority: Unknown child element: "
00367 "%1. Ignoring.").arg(e.tagName()));
00368 }
00369 }
00370 }
00371 }
00372
00373 void ProgramRecPriority::parseContainer(QDomElement &element)
00374 {
00375 QRect area;
00376 QString name;
00377 int context;
00378 theme->parseContainer(element, name, context, area);
00379
00380 if (name.lower() == "selector")
00381 listRect = area;
00382 if (name.lower() == "program_info")
00383 infoRect = area;
00384 }
00385
00386 void ProgramRecPriority::updateBackground(void)
00387 {
00388 QPixmap bground(size());
00389 bground.fill(this, 0, 0);
00390
00391 QPainter tmp(&bground);
00392
00393 LayerSet *container = theme->GetSet("background");
00394 if (!container)
00395 return;
00396
00397 container->Draw(&tmp, 0, 0);
00398
00399 tmp.end();
00400 myBackground = bground;
00401
00402 setPaletteBackgroundPixmap(myBackground);
00403 }
00404
00405 void ProgramRecPriority::paintEvent(QPaintEvent *e)
00406 {
00407 QRect r = e->rect();
00408 QPainter p(this);
00409
00410 if (r.intersects(listRect))
00411 {
00412 updateList(&p);
00413 }
00414 if (r.intersects(infoRect))
00415 {
00416 updateInfo(&p);
00417 }
00418 }
00419
00420 void ProgramRecPriority::cursorDown(bool page)
00421 {
00422 if (page == false)
00423 {
00424 if (inList > (int)((int)(listsize / 2) - 1)
00425 && ((int)(inData + listsize) <= (int)(dataCount - 1))
00426 && pageDowner == true)
00427 {
00428 inData++;
00429 inList = (int)(listsize / 2);
00430 }
00431 else
00432 {
00433 inList++;
00434
00435 if (inList >= listCount)
00436 inList = listCount - 1;
00437 }
00438 }
00439 else if (page == true && pageDowner == true)
00440 {
00441 if (inList >= (int)(listsize / 2) || inData != 0)
00442 {
00443 inData = inData + listsize;
00444 }
00445 else if (inList < (int)(listsize / 2) && inData == 0)
00446 {
00447 inData = (int)(listsize / 2) + inList;
00448 inList = (int)(listsize / 2);
00449 }
00450 }
00451 else if (page == true && pageDowner == false)
00452 {
00453 inList = listsize - 1;
00454 }
00455
00456 if ((int)(inData + inList) >= (int)(dataCount))
00457 {
00458 inData = dataCount - listsize;
00459 inList = listsize - 1;
00460 }
00461 else if ((int)(inData + listsize) >= (int)dataCount)
00462 {
00463 inData = dataCount - listsize;
00464 }
00465
00466 if (inData < 0)
00467 inData = 0;
00468
00469 if (inList >= listCount)
00470 inList = listCount - 1;
00471
00472 update(fullRect);
00473 }
00474
00475 void ProgramRecPriority::cursorUp(bool page)
00476 {
00477 if (page == false)
00478 {
00479 if (inList < ((int)(listsize / 2) + 1) && inData > 0)
00480 {
00481 inList = (int)(listsize / 2);
00482 inData--;
00483 if (inData < 0)
00484 {
00485 inData = 0;
00486 inList--;
00487 }
00488 }
00489 else
00490 {
00491 inList--;
00492 }
00493 }
00494 else if (page == true && inData > 0)
00495 {
00496 inData = inData - listsize;
00497 if (inData < 0)
00498 {
00499 inList = inList + inData;
00500 inData = 0;
00501 if (inList < 0)
00502 inList = 0;
00503 }
00504
00505 if (inList > (int)(listsize / 2))
00506 {
00507 inList = (int)(listsize / 2);
00508 inData = inData + (int)(listsize / 2) - 1;
00509 }
00510 }
00511 else if (page == true)
00512 {
00513 inData = 0;
00514 inList = 0;
00515 }
00516
00517 if (inList > -1)
00518 {
00519 update(fullRect);
00520 }
00521 else
00522 inList = 0;
00523 }
00524
00525 void ProgramRecPriority::edit(void)
00526 {
00527 if (!curitem)
00528 return;
00529
00530 ProgramRecPriorityInfo *rec = curitem;
00531
00532 if (rec)
00533 {
00534 int recid = 0;
00535
00536 {
00537 ScheduledRecording *record = new ScheduledRecording();
00538 record->loadByID(rec->recordid);
00539 if (record->getSearchType() == kNoSearch)
00540 record->loadByProgram(rec);
00541 record->exec();
00542 recid = record->getRecordID();
00543 record->deleteLater();
00544 }
00545
00546
00547
00548
00549 if (!recid)
00550 recid = rec->getRecordID();
00551
00552 MSqlQuery query(MSqlQuery::InitCon());
00553 query.prepare("SELECT recpriority, type, inactive FROM"
00554 " record WHERE recordid = :RECORDID ;");
00555 query.bindValue(":RECORDID", recid);
00556
00557 if (query.exec() && query.isActive())
00558 if (query.size() > 0)
00559 {
00560 query.next();
00561 int recPriority = query.value(0).toInt();
00562 int rectype = query.value(1).toInt();
00563 int inactive = query.value(2).toInt();
00564
00565 int cnt;
00566 QMap<QString, ProgramRecPriorityInfo>::Iterator it;
00567 ProgramRecPriorityInfo *progInfo;
00568
00569
00570
00571 for (cnt = 0, it = programData.begin(); cnt < inList+inData;
00572 cnt++, ++it);
00573 progInfo = &(it.data());
00574
00575 int rtRecPriors[11];
00576 rtRecPriors[0] = 0;
00577 rtRecPriors[kSingleRecord] =
00578 gContext->GetNumSetting("SingleRecordRecPriority", 1);
00579 rtRecPriors[kTimeslotRecord] =
00580 gContext->GetNumSetting("TimeslotRecordRecPriority", 0);
00581 rtRecPriors[kChannelRecord] =
00582 gContext->GetNumSetting("ChannelRecordRecPriority", 0);
00583 rtRecPriors[kAllRecord] =
00584 gContext->GetNumSetting("AllRecordRecPriority", 0);
00585 rtRecPriors[kWeekslotRecord] =
00586 gContext->GetNumSetting("WeekslotRecordRecPriority", 0);
00587 rtRecPriors[kFindOneRecord] =
00588 gContext->GetNumSetting("FindOneRecordRecPriority", -1);
00589 rtRecPriors[kOverrideRecord] =
00590 gContext->GetNumSetting("OverrideRecordRecPriority", 0);
00591 rtRecPriors[kDontRecord] =
00592 gContext->GetNumSetting("OverrideRecordRecPriority", 0);
00593 rtRecPriors[kFindDailyRecord] =
00594 gContext->GetNumSetting("FindOneRecordRecPriority", -1);
00595 rtRecPriors[kFindWeeklyRecord] =
00596 gContext->GetNumSetting("FindOneRecordRecPriority", -1);
00597
00598
00599 progInfo->recpriority = recPriority;
00600 progInfo->recType = (RecordingType)rectype;
00601 progInfo->recTypeRecPriority = rtRecPriors[progInfo->recType];
00602
00603
00604 origRecPriorityData[progInfo->recordid] =
00605 progInfo->recpriority;
00606
00607 progInfo->recstatus = inactive ? rsInactive : rsUnknown;
00608
00609 SortList();
00610 }
00611 else
00612 {
00613 RemoveCurItemFromList();
00614 }
00615 else
00616 MythContext::DBError("Get new recording priority query", query);
00617
00618 countMatches();
00619 update(fullRect);
00620 }
00621 }
00622
00623 void ProgramRecPriority::customEdit(void)
00624 {
00625 if (!curitem)
00626 return;
00627
00628 {
00629 ScheduledRecording *record = new ScheduledRecording();
00630 record->loadByID(curitem->recordid);
00631 record->deleteLater();
00632 }
00633
00634 CustomEdit *ce = new CustomEdit(gContext->GetMainWindow(),
00635 "customedit", curitem);
00636 ce->exec();
00637 delete ce;
00638 }
00639
00640 void ProgramRecPriority::remove(void)
00641 {
00642 if (!curitem)
00643 return;
00644
00645 ScheduledRecording *record = new ScheduledRecording();
00646 int recid = curitem->recordid;
00647 record->loadByID(recid);
00648
00649 QString message =
00650 tr("Delete '%1' %2 rule?").arg(record->getRecordTitle())
00651 .arg(curitem->RecTypeText());
00652
00653 bool ok = MythPopupBox::showOkCancelPopup(gContext->GetMainWindow(), "",
00654 message, false);
00655
00656 if (ok)
00657 {
00658 record->remove();
00659
00660 RemoveCurItemFromList();
00661
00662 countMatches();
00663 update(fullRect);
00664
00665 ScheduledRecording::signalChange(recid);
00666 }
00667 record->deleteLater();
00668 }
00669
00670 void ProgramRecPriority::deactivate(void)
00671 {
00672 if (!curitem)
00673 return;
00674
00675 ProgramRecPriorityInfo *rec = curitem;
00676
00677 if (rec)
00678 {
00679 MSqlQuery query(MSqlQuery::InitCon());
00680
00681 query.prepare("SELECT inactive FROM record "
00682 "WHERE recordid = :RECID ;");
00683 query.bindValue(":RECID", rec->recordid);
00684
00685 int inactive = 0;
00686 if (query.exec() && query.isActive())
00687 if (query.size() > 0)
00688 {
00689 query.next();
00690 inactive = query.value(0).toInt();
00691 if (inactive)
00692 inactive = 0;
00693 else
00694 inactive = 1;
00695
00696 query.prepare("UPDATE record SET inactive = :INACTIVE "
00697 "WHERE recordid = :RECID ;");
00698 query.bindValue(":INACTIVE", inactive);
00699 query.bindValue(":RECID", rec->recordid);
00700
00701 if (query.exec() && query.isActive())
00702 {
00703 ScheduledRecording::signalChange(0);
00704 int cnt;
00705 QMap<QString, ProgramRecPriorityInfo>::Iterator it;
00706 ProgramRecPriorityInfo *progInfo;
00707
00708
00709
00710 for (cnt = 0, it = programData.begin(); cnt < inList+inData;
00711 cnt++, ++it);
00712 progInfo = &(it.data());
00713 progInfo->recstatus = inactive ? rsInactive : rsUnknown;
00714 } else
00715 MythContext::DBError("Update recording schedule inactive query", query);
00716 }
00717
00718 QPainter p(this);
00719 updateInfo(&p);
00720 update(fullRect);
00721 }
00722 }
00723
00724 void ProgramRecPriority::upcoming(void)
00725 {
00726 if (!curitem)
00727 return;
00728
00729 if (listMatch[curitem->recordid] > 0)
00730 {
00731 ScheduledRecording *record = new ScheduledRecording();
00732 record->loadByID(curitem->recordid);
00733 record->runRuleList();
00734 record->deleteLater();
00735 }
00736 else
00737 {
00738 ProgLister *pl = NULL;
00739 QString trimTitle = curitem->title;
00740 trimTitle.remove(QRegExp(" \\(.*\\)$"));
00741 pl = new ProgLister(plTitle, trimTitle, "",
00742 gContext->GetMainWindow(), "proglist");
00743 pl->exec();
00744 delete pl;
00745 }
00746 }
00747
00748 void ProgramRecPriority::details(void)
00749 {
00750 if (!curitem)
00751 return;
00752
00753 curitem->showDetails();
00754 }
00755
00756 void ProgramRecPriority::changeRecPriority(int howMuch)
00757 {
00758 int tempRecPriority, cnt;
00759 QPainter p(this);
00760 QMap<QString, ProgramRecPriorityInfo>::Iterator it;
00761 ProgramRecPriorityInfo *progInfo;
00762
00763
00764
00765 for (cnt = 0, it = programData.begin(); cnt < inList+inData; cnt++, ++it);
00766 progInfo = &(it.data());
00767
00768
00769 tempRecPriority = progInfo->recpriority + howMuch;
00770 if (tempRecPriority > -100 && tempRecPriority < 100)
00771 {
00772 progInfo->recpriority = tempRecPriority;
00773
00774
00775 if (sortType == byRecPriority)
00776 SortList();
00777 updateList(&p);
00778 updateInfo(&p);
00779 }
00780 }
00781
00782 void ProgramRecPriority::saveRecPriority(void)
00783 {
00784 QMap<QString, ProgramRecPriorityInfo>::Iterator it;
00785
00786 for (it = programData.begin(); it != programData.end(); ++it)
00787 {
00788 ProgramRecPriorityInfo *progInfo = &(it.data());
00789 int key = progInfo->recordid;
00790
00791
00792
00793 if (progInfo->recpriority != origRecPriorityData[key])
00794 progInfo->ApplyRecordRecPriorityChange(progInfo->recpriority);
00795 }
00796 }
00797
00798 void ProgramRecPriority::FillList(void)
00799 {
00800 int cnt = 999, rtRecPriors[11];
00801 vector<ProgramInfo *> recordinglist;
00802
00803 programData.clear();
00804
00805 RemoteGetAllScheduledRecordings(recordinglist);
00806
00807 vector<ProgramInfo *>::reverse_iterator pgiter = recordinglist.rbegin();
00808
00809 for (; pgiter != recordinglist.rend(); pgiter++)
00810 {
00811 programData[QString::number(cnt)] = *(*pgiter);
00812
00813
00814
00815 origRecPriorityData[(*pgiter)->recordid] = (*pgiter)->recpriority;
00816
00817 delete (*pgiter);
00818 cnt--;
00819 dataCount++;
00820 }
00821
00822
00823
00824
00825
00826 rtRecPriors[0] = 0;
00827 rtRecPriors[kSingleRecord] =
00828 gContext->GetNumSetting("SingleRecordRecPriority", 1);
00829 rtRecPriors[kTimeslotRecord] =
00830 gContext->GetNumSetting("TimeslotRecordRecPriority", 0);
00831 rtRecPriors[kChannelRecord] =
00832 gContext->GetNumSetting("ChannelRecordRecPriority", 0);
00833 rtRecPriors[kAllRecord] =
00834 gContext->GetNumSetting("AllRecordRecPriority", 0);
00835 rtRecPriors[kWeekslotRecord] =
00836 gContext->GetNumSetting("WeekslotRecordRecPriority", 0);
00837 rtRecPriors[kFindOneRecord] =
00838 gContext->GetNumSetting("FindOneRecordRecPriority", -1);
00839 rtRecPriors[kOverrideRecord] =
00840 gContext->GetNumSetting("OverrideRecordRecPriority", 0);
00841 rtRecPriors[kDontRecord] =
00842 gContext->GetNumSetting("OverrideRecordRecPriority", 0);
00843 rtRecPriors[kFindDailyRecord] =
00844 gContext->GetNumSetting("FindOneRecordRecPriority", -1);
00845 rtRecPriors[kFindWeeklyRecord] =
00846 gContext->GetNumSetting("FindOneRecordRecPriority", -1);
00847
00848
00849
00850
00851
00852 MSqlQuery result(MSqlQuery::InitCon());
00853 result.prepare("SELECT recordid, title, chanid, starttime, startdate, "
00854 "type, inactive, last_record, avg_delay "
00855 "FROM record;");
00856
00857 if (result.exec() && result.isActive() && result.size() > 0)
00858 {
00859 countMatches();
00860
00861 while (result.next())
00862 {
00863 int recordid = result.value(0).toInt();
00864 QString title = QString::fromUtf8(result.value(1).toString());
00865 QString chanid = result.value(2).toString();
00866 QString tempTime = result.value(3).toString();
00867 QString tempDate = result.value(4).toString();
00868 RecordingType recType = (RecordingType)result.value(5).toInt();
00869 int recTypeRecPriority = rtRecPriors[recType];
00870 int inactive = result.value(6).toInt();
00871 QDateTime lastrec = result.value(7).toDateTime();
00872 int avgd = result.value(8).toInt();
00873
00874
00875
00876 QMap<QString, ProgramRecPriorityInfo>::Iterator it;
00877 for (it = programData.begin(); it != programData.end(); ++it)
00878 {
00879 ProgramRecPriorityInfo *progInfo = &(it.data());
00880
00881 if (progInfo->recordid == recordid)
00882 {
00883 progInfo->sortTitle = progInfo->title;
00884 progInfo->sortTitle.remove(QRegExp(tr("^(The |A |An )")));
00885
00886 progInfo->recTypeRecPriority = recTypeRecPriority;
00887 progInfo->recType = recType;
00888 progInfo->matchCount = listMatch[progInfo->recordid];
00889 progInfo->recCount = recMatch[progInfo->recordid];
00890 progInfo->last_record = lastrec;
00891 progInfo->avg_delay = avgd;
00892
00893 if (inactive)
00894 progInfo->recstatus = rsInactive;
00895 else if (conMatch[progInfo->recordid] > 0)
00896 progInfo->recstatus = rsConflict;
00897 else if (nowMatch[progInfo->recordid] > 0)
00898 progInfo->recstatus = rsRecording;
00899 else if (recMatch[progInfo->recordid] > 0)
00900 progInfo->recstatus = rsWillRecord;
00901 else
00902 progInfo->recstatus = rsUnknown;
00903
00904 break;
00905 }
00906 }
00907 }
00908 }
00909 else
00910 MythContext::DBError("Get program recording priorities query", result);
00911 }
00912
00913 void ProgramRecPriority::countMatches()
00914 {
00915 listMatch.clear();
00916 conMatch.clear();
00917 nowMatch.clear();
00918 recMatch.clear();
00919 ProgramList schedList;
00920 schedList.FromScheduler();
00921 QDateTime now = QDateTime::currentDateTime();
00922
00923 ProgramInfo *s;
00924 for (s = schedList.first(); s; s = schedList.next())
00925 {
00926 if (s->recendts > now && s->recstatus != rsNotListed)
00927 {
00928 listMatch[s->recordid]++;
00929 if (s->recstatus == rsConflict ||
00930 s->recstatus == rsOffLine)
00931 conMatch[s->recordid]++;
00932 else if (s->recstatus == rsWillRecord)
00933 recMatch[s->recordid]++;
00934 else if (s->recstatus == rsRecording)
00935 {
00936 nowMatch[s->recordid]++;
00937 recMatch[s->recordid]++;
00938 }
00939 }
00940 }
00941 }
00942
00943 typedef struct RecPriorityInfo
00944 {
00945 ProgramRecPriorityInfo *prog;
00946 int cnt;
00947 };
00948
00949 class titleSort
00950 {
00951 public:
00952 titleSort(bool reverseSort = false) {m_reverse = reverseSort;}
00953
00954 bool operator()(const RecPriorityInfo a, const RecPriorityInfo b)
00955 {
00956 if (a.prog->sortTitle != b.prog->sortTitle)
00957 {
00958 if (m_reverse)
00959 return (a.prog->sortTitle < b.prog->sortTitle);
00960 else
00961 return (a.prog->sortTitle > b.prog->sortTitle);
00962 }
00963
00964 int finalA = a.prog->recpriority + a.prog->recTypeRecPriority;
00965 int finalB = b.prog->recpriority + b.prog->recTypeRecPriority;
00966 if (finalA != finalB)
00967 {
00968 if (m_reverse)
00969 return finalA > finalB;
00970 else
00971 return finalA < finalB;
00972 }
00973
00974 int typeA = RecTypePriority(a.prog->recType);
00975 int typeB = RecTypePriority(b.prog->recType);
00976 if (typeA != typeB)
00977 {
00978 if (m_reverse)
00979 return typeA < typeB;
00980 else
00981 return typeA > typeB;
00982 }
00983
00984 if (m_reverse)
00985 return a.prog->recordid < b.prog->recordid;
00986 else
00987 return a.prog->recordid > b.prog->recordid;
00988 }
00989
00990 private:
00991 bool m_reverse;
00992 };
00993
00994 class programRecPrioritySort
00995 {
00996 public:
00997 programRecPrioritySort(bool reverseSort = false)
00998 {m_reverse = reverseSort;}
00999
01000 bool operator()(const RecPriorityInfo a, const RecPriorityInfo b)
01001 {
01002 int finalA = a.prog->recpriority + a.prog->recTypeRecPriority;
01003 int finalB = b.prog->recpriority + b.prog->recTypeRecPriority;
01004 if (finalA != finalB)
01005 {
01006 if (m_reverse)
01007 return finalA > finalB;
01008 else
01009 return finalA < finalB;
01010 }
01011
01012 int typeA = RecTypePriority(a.prog->recType);
01013 int typeB = RecTypePriority(b.prog->recType);
01014 if (typeA != typeB)
01015 {
01016 if (m_reverse)
01017 return typeA < typeB;
01018 else
01019 return typeA > typeB;
01020 }
01021
01022 if (m_reverse)
01023 return a.prog->recordid < b.prog->recordid;
01024 else
01025 return a.prog->recordid > b.prog->recordid;
01026 }
01027
01028 private:
01029 bool m_reverse;
01030 };
01031
01032 class programRecTypeSort
01033 {
01034 public:
01035 programRecTypeSort(bool reverseSort = false)
01036 {m_reverse = reverseSort;}
01037
01038 bool operator()(const RecPriorityInfo a, const RecPriorityInfo b)
01039 {
01040 int typeA = RecTypePriority(a.prog->recType);
01041 int typeB = RecTypePriority(b.prog->recType);
01042 if (typeA != typeB)
01043 {
01044 if (m_reverse)
01045 return (typeA < typeB);
01046 else
01047 return (typeA > typeB);
01048 }
01049
01050 int finalA = a.prog->recpriority + a.prog->recTypeRecPriority;
01051 int finalB = b.prog->recpriority + b.prog->recTypeRecPriority;
01052 if (finalA != finalB)
01053 {
01054 if (m_reverse)
01055 return finalA > finalB;
01056 else
01057 return finalA < finalB;
01058 }
01059
01060 if (m_reverse)
01061 return a.prog->recordid < b.prog->recordid;
01062 else
01063 return a.prog->recordid > b.prog->recordid;
01064 }
01065
01066 private:
01067 bool m_reverse;
01068 };
01069
01070 class programCountSort
01071 {
01072 public:
01073 programCountSort(bool reverseSort = false) {m_reverse = reverseSort;}
01074
01075 bool operator()(const RecPriorityInfo a, const RecPriorityInfo b)
01076 {
01077 int countA = a.prog->matchCount;
01078 int countB = b.prog->matchCount;
01079 int recCountA = a.prog->recCount;
01080 int recCountB = b.prog->recCount;
01081
01082 if (countA != countB)
01083 {
01084 if (m_reverse)
01085 return countA > countB;
01086 else
01087 return countA < countB;
01088 }
01089 if (recCountA != recCountB)
01090 {
01091 if (m_reverse)
01092 return recCountA > recCountB;
01093 else
01094 return recCountA < recCountB;
01095 }
01096 return (a.prog->sortTitle > b.prog->sortTitle);
01097 }
01098
01099 private:
01100 bool m_reverse;
01101 };
01102
01103 class programRecCountSort
01104 {
01105 public:
01106 programRecCountSort(bool reverseSort=false) {m_reverse = reverseSort;}
01107
01108 bool operator()(const RecPriorityInfo a, const RecPriorityInfo b)
01109 {
01110 int countA = a.prog->matchCount;
01111 int countB = b.prog->matchCount;
01112 int recCountA = a.prog->recCount;
01113 int recCountB = b.prog->recCount;
01114
01115 if (recCountA != recCountB)
01116 {
01117 if (m_reverse)
01118 return recCountA > recCountB;
01119 else
01120 return recCountA < recCountB;
01121 }
01122 if (countA != countB)
01123 {
01124 if (m_reverse)
01125 return countA > countB;
01126 else
01127 return countA < countB;
01128 }
01129 return (a.prog->sortTitle > b.prog->sortTitle);
01130 }
01131
01132 private:
01133 bool m_reverse;
01134 };
01135
01136 class programLastRecordSort
01137 {
01138 public:
01139 programLastRecordSort(bool reverseSort=false)
01140 {m_reverse = reverseSort;}
01141
01142 bool operator()(const RecPriorityInfo a, const RecPriorityInfo b)
01143 {
01144 QDateTime lastRecA = a.prog->last_record;
01145 QDateTime lastRecB = b.prog->last_record;
01146
01147 if (lastRecA != lastRecB)
01148 {
01149 if (m_reverse)
01150 return lastRecA > lastRecB;
01151 else
01152 return lastRecA < lastRecB;
01153 }
01154 return (a.prog->sortTitle > b.prog->sortTitle);
01155 }
01156
01157 private:
01158 bool m_reverse;
01159 };
01160
01161 class programAvgDelaySort
01162 {
01163 public:
01164 programAvgDelaySort(bool reverseSort=false)
01165 {m_reverse = reverseSort;}
01166
01167 bool operator()(const RecPriorityInfo a, const RecPriorityInfo b)
01168 {
01169 int avgA = a.prog->avg_delay;
01170 int avgB = b.prog->avg_delay;
01171
01172 if (avgA != avgB)
01173 {
01174 if (m_reverse)
01175 return avgA < avgB;
01176 else
01177 return avgA > avgB;
01178 }
01179 return (a.prog->sortTitle > b.prog->sortTitle);
01180 }
01181
01182 private:
01183 bool m_reverse;
01184 };
01185
01186 void ProgramRecPriority::SortList()
01187 {
01188 int i, j;
01189 bool cursorChanged = false;
01190 vector<RecPriorityInfo> sortedList;
01191 QMap<QString, ProgramRecPriorityInfo>::Iterator pit;
01192 vector<RecPriorityInfo>::iterator sit;
01193 ProgramRecPriorityInfo *progInfo;
01194 RecPriorityInfo *recPriorityInfo;
01195 QMap<QString, ProgramRecPriorityInfo> pdCopy;
01196
01197
01198
01199 for (i = 0, pit = programData.begin(); pit != programData.end(); ++pit, i++)
01200 {
01201 progInfo = &(pit.data());
01202 RecPriorityInfo tmp = {progInfo, i};
01203 sortedList.push_back(tmp);
01204 pdCopy[pit.key()] = pit.data();
01205 }
01206
01207
01208 switch(sortType)
01209 {
01210 case byTitle :
01211 if (reverseSort)
01212 sort(sortedList.begin(), sortedList.end(),
01213 titleSort(true));
01214 else
01215 sort(sortedList.begin(), sortedList.end(), titleSort());
01216 break;
01217 case byRecPriority :
01218 if (reverseSort)
01219 sort(sortedList.begin(), sortedList.end(),
01220 programRecPrioritySort(true));
01221 else
01222 sort(sortedList.begin(), sortedList.end(),
01223 programRecPrioritySort());
01224 break;
01225 case byRecType :
01226 if (reverseSort)
01227 sort(sortedList.begin(), sortedList.end(),
01228 programRecTypeSort(true));
01229 else
01230 sort(sortedList.begin(), sortedList.end(),
01231 programRecTypeSort());
01232 break;
01233 case byCount :
01234 if (reverseSort)
01235 sort(sortedList.begin(), sortedList.end(),
01236 programCountSort(true));
01237 else
01238 sort(sortedList.begin(), sortedList.end(),
01239 programCountSort());
01240 break;
01241 case byRecCount :
01242 if (reverseSort)
01243 sort(sortedList.begin(), sortedList.end(),
01244 programRecCountSort(true));
01245 else
01246 sort(sortedList.begin(), sortedList.end(),
01247 programRecCountSort());
01248 break;
01249 case byLastRecord :
01250 if (reverseSort)
01251 sort(sortedList.begin(), sortedList.end(),
01252 programLastRecordSort(true));
01253 else
01254 sort(sortedList.begin(), sortedList.end(),
01255 programLastRecordSort());
01256 break;
01257 case byAvgDelay :
01258 if (reverseSort)
01259 sort(sortedList.begin(), sortedList.end(),
01260 programAvgDelaySort(true));
01261 else
01262 sort(sortedList.begin(), sortedList.end(),
01263 programAvgDelaySort());
01264 break;
01265 }
01266
01267 programData.clear();
01268
01269
01270 for (i = 0, sit = sortedList.begin(); sit != sortedList.end(); i++, ++sit)
01271 {
01272 recPriorityInfo = &(*sit);
01273
01274
01275 for (j = 0,pit = pdCopy.begin(); j != recPriorityInfo->cnt; j++, ++pit);
01276
01277 progInfo = &(pit.data());
01278
01279
01280 programData[QString::number(999-i)] = pit.data();
01281
01282
01283
01284
01285 if (!cursorChanged && recPriorityInfo->cnt == inList+inData)
01286 {
01287 inList = dataCount - i - 1;
01288 if (inList > (int)((int)(listsize / 2) - 1))
01289 {
01290 inList = (int)(listsize / 2);
01291 inData = dataCount - i - 1 - inList;
01292 }
01293 else
01294 inData = 0;
01295
01296 if (dataCount > listsize && inData > dataCount - listsize)
01297 {
01298 inList += inData - (dataCount - listsize);
01299 inData = dataCount - listsize;
01300 }
01301 cursorChanged = true;
01302 }
01303 }
01304 }
01305
01306 void ProgramRecPriority::RemoveCurItemFromList(void)
01307 {
01308
01309
01310
01311 int cnt;
01312 QMap<QString, ProgramRecPriorityInfo>::Iterator it;
01313 for (cnt = 0, it = programData.begin(); cnt < inList+inData;
01314 cnt++, ++it);
01315 programData.remove(it);
01316 SortList();
01317 delete curitem;
01318 curitem = NULL;
01319 dataCount--;
01320
01321 if (cnt >= dataCount)
01322 cnt = dataCount - 1;
01323 if (dataCount <= listsize || cnt <= listsize / 2)
01324 inData = 0;
01325 else if (cnt >= dataCount - listsize + listsize / 2)
01326 inData = dataCount - listsize;
01327 else
01328 inData = cnt - listsize / 2;
01329 inList = cnt - inData;
01330 }
01331
01332 void ProgramRecPriority::updateList(QPainter *p)
01333 {
01334 QRect pr = listRect;
01335 QPixmap pix(pr.size());
01336 pix.fill(this, pr.topLeft());
01337 QPainter tmp(&pix);
01338
01339 int pastSkip = (int)inData;
01340 pageDowner = false;
01341 listCount = 0;
01342
01343 LayerSet *container = NULL;
01344 container = theme->GetSet("selector");
01345 if (container)
01346 {
01347 UIListType *ltype = (UIListType *)container->GetType("recprioritylist");
01348 if (ltype)
01349 {
01350 int cnt = 0;
01351 ltype->ResetList();
01352 ltype->SetActive(true);
01353
01354 QMap<QString, ProgramRecPriorityInfo>::Iterator it;
01355 for (it = programData.begin(); it != programData.end(); ++it)
01356 {
01357 if (cnt < listsize)
01358 {
01359 if (pastSkip <= 0)
01360 {
01361 ProgramRecPriorityInfo *progInfo = &(it.data());
01362
01363 int progRecPriority = progInfo->recpriority;
01364 int finalRecPriority = progRecPriority +
01365 progInfo->recTypeRecPriority;
01366
01367 QString tempSubTitle = progInfo->title;
01368 if ((progInfo->rectype == kSingleRecord ||
01369 progInfo->rectype == kOverrideRecord ||
01370 progInfo->rectype == kDontRecord) &&
01371 (progInfo->subtitle).stripWhiteSpace().length() > 0)
01372 tempSubTitle = tempSubTitle + " - \"" +
01373 progInfo->subtitle + "\"";
01374
01375 if (cnt == inList)
01376 {
01377 if (curitem)
01378 delete curitem;
01379 curitem = new ProgramRecPriorityInfo(*progInfo);
01380 ltype->SetItemCurrent(cnt);
01381 }
01382
01383 ltype->SetItemText(cnt, 1, progInfo->RecTypeChar());
01384 ltype->SetItemText(cnt, 2, tempSubTitle);
01385
01386 if (progRecPriority < 0)
01387 ltype->SetItemText(cnt, 3, "-");
01388 else
01389 ltype->SetItemText(cnt, 3, "+");
01390 ltype->SetItemText(cnt, 4,
01391 QString::number(abs(progRecPriority)));
01392
01393 if (finalRecPriority < 0)
01394 ltype->SetItemText(cnt, 5, "-");
01395 else
01396 ltype->SetItemText(cnt, 5, "+");
01397
01398 ltype->SetItemText(cnt, 6,
01399 QString::number(abs(finalRecPriority)));
01400
01401 if (progInfo->recType == kDontRecord ||
01402 progInfo->recstatus == rsInactive)
01403 ltype->EnableForcedFont(cnt, "inactive");
01404 else if (conMatch[progInfo->recordid] > 0)
01405 ltype->EnableForcedFont(cnt, "conflicting");
01406 else if (nowMatch[progInfo->recordid] > 0)
01407 ltype->EnableForcedFont(cnt, "recording");
01408 else if (recMatch[progInfo->recordid] > 0)
01409 ltype->EnableForcedFont(cnt, "record");
01410
01411 cnt++;
01412 listCount++;
01413 }
01414 pastSkip--;
01415 }
01416 else
01417 pageDowner = true;
01418 }
01419 }
01420
01421 ltype->SetDownArrow(pageDowner);
01422 if (inData > 0)
01423 ltype->SetUpArrow(true);
01424 else
01425 ltype->SetUpArrow(false);
01426 }
01427
01428 if (programData.count() <= 0)
01429 container = theme->GetSet("norecordings_list");
01430
01431 if (container)
01432 {
01433 container->Draw(&tmp, 0, 0);
01434 container->Draw(&tmp, 1, 0);
01435 container->Draw(&tmp, 2, 0);
01436 container->Draw(&tmp, 3, 0);
01437 container->Draw(&tmp, 4, 0);
01438 container->Draw(&tmp, 5, 0);
01439 container->Draw(&tmp, 6, 0);
01440 container->Draw(&tmp, 7, 0);
01441 container->Draw(&tmp, 8, 0);
01442 }
01443
01444 tmp.end();
01445 p->drawPixmap(pr.topLeft(), pix);
01446 }
01447
01448 void ProgramRecPriority::updateInfo(QPainter *p)
01449 {
01450 QRect pr = infoRect;
01451 QPixmap pix(pr.size());
01452 pix.fill(this, pr.topLeft());
01453 QPainter tmp(&pix);
01454
01455 if (programData.count() > 0 && curitem)
01456 {
01457 int progRecPriority, rectyperecpriority, finalRecPriority;
01458 RecordingType rectype;
01459
01460 progRecPriority = curitem->recpriority;
01461 rectyperecpriority = curitem->recTypeRecPriority;
01462 finalRecPriority = progRecPriority + rectyperecpriority;
01463
01464 rectype = curitem->recType;
01465
01466 QString subtitle = "";
01467 if (curitem->subtitle != "(null)" &&
01468 (curitem->rectype == kSingleRecord ||
01469 curitem->rectype == kOverrideRecord ||
01470 curitem->rectype == kDontRecord))
01471 {
01472 subtitle = curitem->subtitle;
01473 }
01474
01475 QString matchInfo;
01476 if (curitem->recstatus == rsInactive)
01477 matchInfo = QString("%1 %2").arg(listMatch[curitem->recordid])
01478 .arg(curitem->RecStatusText());
01479 else
01480 matchInfo = QString(tr("Recording %1 of %2"))
01481 .arg(recMatch[curitem->recordid])
01482 .arg(listMatch[curitem->recordid]);
01483
01484 subtitle = QString("(%1) %2").arg(matchInfo).arg(subtitle);
01485
01486 LayerSet *container = NULL;
01487 container = theme->GetSet("program_info");
01488 if (container)
01489 {
01490 UITextType *type = (UITextType *)container->GetType("title");
01491 if (type)
01492 type->SetText(curitem->title);
01493
01494 type = (UITextType *)container->GetType("subtitle");
01495 if (type)
01496 type->SetText(subtitle);
01497
01498 type = (UITextType *)container->GetType("type");
01499 if (type) {
01500 QString text;
01501 switch (rectype)
01502 {
01503 case kSingleRecord:
01504 text = tr("Recording just this showing");
01505 break;
01506 case kOverrideRecord:
01507 text = tr("Recording with override options");
01508 break;
01509 case kWeekslotRecord:
01510 text = tr("Recording every week");
01511 break;
01512 case kTimeslotRecord:
01513 text = tr("Recording in this timeslot");
01514 break;
01515 case kChannelRecord:
01516 text = tr("Recording on this channel");
01517 break;
01518 case kAllRecord:
01519 text = tr("Recording all showings");
01520 break;
01521 case kFindOneRecord:
01522 text = tr("Recording one showing");
01523 break;
01524 case kFindDailyRecord:
01525 text = tr("Recording a showing daily");
01526 break;
01527 case kFindWeeklyRecord:
01528 text = tr("Recording a showing weekly");
01529 break;
01530 case kDontRecord:
01531 text = tr("Not allowed to record this showing");
01532 break;
01533 case kNotRecording:
01534 text = tr("Not recording this showing");
01535 break;
01536 default:
01537 text = tr("Error!");
01538 break;
01539 }
01540 type->SetText(text);
01541 }
01542
01543 type = (UITextType *)container->GetType("typerecpriority");
01544 if (type) {
01545 type->SetText(QString::number(abs(rectyperecpriority)));
01546 }
01547 type = (UITextType *)container->GetType("typesign");
01548 if (type) {
01549 if (rectyperecpriority >= 0)
01550 type->SetText("+");
01551 else
01552 type->SetText("-");
01553 }
01554
01555 type = (UITextType *)container->GetType("recpriority");
01556 if (type) {
01557 if (curitem->recpriority >= 0)
01558 type->SetText("+"+QString::number(curitem->recpriority));
01559 else
01560 type->SetText(QString::number(curitem->recpriority));
01561 }
01562
01563 type = (UITextType *)container->GetType("recpriorityB");
01564 if (type) {
01565 type->SetText(QString::number(abs(progRecPriority)));
01566 }
01567
01568 type = (UITextType *)container->GetType("recprioritysign");
01569 if (type) {
01570 if (finalRecPriority >= 0)
01571 type->SetText("+");
01572 else
01573 type->SetText("-");
01574 }
01575
01576 type = (UITextType *)container->GetType("finalrecpriority");
01577 if (type) {
01578 if (finalRecPriority >= 0)
01579 type->SetText("+"+QString::number(finalRecPriority));
01580 else
01581 type->SetText(QString::number(finalRecPriority));
01582 }
01583 }
01584
01585 if (container)
01586 {
01587 container->Draw(&tmp, 4, 0);
01588 container->Draw(&tmp, 5, 0);
01589 container->Draw(&tmp, 6, 0);
01590 container->Draw(&tmp, 7, 0);
01591 container->Draw(&tmp, 8, 0);
01592 }
01593 }
01594 else
01595 {
01596 LayerSet *norec = theme->GetSet("norecordings_info");
01597 if (norec)
01598 {
01599 norec->Draw(&tmp, 4, 0);
01600 norec->Draw(&tmp, 5, 0);
01601 norec->Draw(&tmp, 6, 0);
01602 norec->Draw(&tmp, 7, 0);
01603 norec->Draw(&tmp, 8, 0);
01604 }
01605
01606 }
01607
01608 tmp.end();
01609 p->drawPixmap(pr.topLeft(), pix);
01610 }
01611
01612