|
MythTV
0.26-pre
|
00001 #include <unistd.h> 00002 #include <stdlib.h> 00003 00004 #include <iostream> 00005 #include <cstdlib> 00006 00007 // qt 00008 #include <QFile> 00009 #include <QKeyEvent> 00010 #include <QTextStream> 00011 #include <QDomDocument> 00012 00013 // myth 00014 #include <mythcontext.h> 00015 #include <remoteutil.h> 00016 #include <programinfo.h> 00017 #include <mythdb.h> 00018 #include <mythdialogbox.h> 00019 #include <mythuitext.h> 00020 #include <mythuibutton.h> 00021 #include <mythuicheckbox.h> 00022 #include <mythuibuttonlist.h> 00023 #include <mythuiprogressbar.h> 00024 #include <mythmainwindow.h> 00025 #include <mythsystem.h> 00026 #include <exitcodes.h> 00027 00028 // mytharchive 00029 #include "exportnative.h" 00030 #include "fileselector.h" 00031 #include "archiveutil.h" 00032 #include "recordingselector.h" 00033 #include "videoselector.h" 00034 #include "logviewer.h" 00035 00036 ExportNative::ExportNative( 00037 MythScreenStack *parent, MythScreenType *previousScreen, 00038 ArchiveDestination archiveDestination, QString name) : 00039 MythScreenType(parent, name), 00040 m_previousScreen(previousScreen), 00041 m_archiveDestination(archiveDestination), 00042 m_usedSpace(0), 00043 m_bCreateISO(false), 00044 m_bDoBurn(false), 00045 m_bEraseDvdRw(false), 00046 m_saveFilename(), 00047 m_archiveButtonList(NULL), 00048 m_nextButton(NULL), 00049 m_prevButton(NULL), 00050 m_cancelButton(NULL), 00051 m_addrecordingButton(NULL), 00052 m_addvideoButton(NULL), 00053 m_freespaceText(NULL), 00054 m_titleText(NULL), 00055 m_datetimeText(NULL), 00056 m_descriptionText(NULL), 00057 m_filesizeText(NULL), 00058 m_nofilesText(NULL), 00059 m_maxsizeText(NULL), 00060 m_minsizeText(NULL), 00061 m_currsizeText(NULL), 00062 m_currsizeErrText(NULL), 00063 m_sizeBar(NULL) 00064 { 00065 } 00066 00067 ExportNative::~ExportNative(void) 00068 { 00069 saveConfiguration(); 00070 00071 while (!m_archiveList.isEmpty()) 00072 delete m_archiveList.takeFirst(); 00073 m_archiveList.clear(); 00074 } 00075 00076 bool ExportNative::Create(void) 00077 { 00078 bool foundtheme = false; 00079 00080 // Load the theme for this screen 00081 foundtheme = LoadWindowFromXML("mythnative-ui.xml", "exportnative", this); 00082 00083 if (!foundtheme) 00084 return false; 00085 00086 bool err = false; 00087 UIUtilE::Assign(this, m_nextButton, "next_button", &err); 00088 UIUtilE::Assign(this, m_prevButton, "prev_button", &err); 00089 UIUtilE::Assign(this, m_cancelButton, "cancel_button", &err); 00090 00091 UIUtilE::Assign(this, m_titleText, "progtitle", &err); 00092 UIUtilE::Assign(this, m_datetimeText, "progdatetime", &err); 00093 UIUtilE::Assign(this, m_descriptionText, "progdescription", &err); 00094 UIUtilE::Assign(this, m_filesizeText, "filesize", &err); 00095 UIUtilE::Assign(this, m_nofilesText, "nofiles", &err); 00096 UIUtilE::Assign(this, m_sizeBar, "size_bar", &err); 00097 UIUtilE::Assign(this, m_archiveButtonList, "archivelist", &err); 00098 UIUtilE::Assign(this, m_addrecordingButton, "addrecording_button", &err); 00099 UIUtilE::Assign(this, m_addvideoButton, "addvideo_button", &err); 00100 00101 UIUtilW::Assign(this, m_maxsizeText, "maxsize"); 00102 UIUtilW::Assign(this, m_minsizeText, "minsize"); 00103 UIUtilW::Assign(this, m_currsizeText, "currentsize"); 00104 UIUtilW::Assign(this, m_currsizeErrText, "currentsize_error"); 00105 00106 if (err) 00107 { 00108 LOG(VB_GENERAL, LOG_ERR, "Cannot load screen 'exportnative'"); 00109 return false; 00110 } 00111 00112 connect(m_nextButton, SIGNAL(Clicked()), this, SLOT(handleNextPage())); 00113 connect(m_prevButton, SIGNAL(Clicked()), this, SLOT(handlePrevPage())); 00114 connect(m_cancelButton, SIGNAL(Clicked()), this, SLOT(handleCancel())); 00115 00116 00117 getArchiveList(); 00118 connect(m_archiveButtonList, SIGNAL(itemSelected(MythUIButtonListItem *)), 00119 this, SLOT(titleChanged(MythUIButtonListItem *))); 00120 00121 connect(m_addrecordingButton, SIGNAL(Clicked()), this, SLOT(handleAddRecording())); 00122 connect(m_addvideoButton, SIGNAL(Clicked()), this, SLOT(handleAddVideo())); 00123 00124 BuildFocusList(); 00125 00126 SetFocusWidget(m_nextButton); 00127 00128 loadConfiguration(); 00129 00130 return true; 00131 } 00132 00133 bool ExportNative::keyPressEvent(QKeyEvent *event) 00134 { 00135 if (GetFocusWidget()->keyPressEvent(event)) 00136 return true; 00137 00138 bool handled = false; 00139 QStringList actions; 00140 handled = GetMythMainWindow()->TranslateKeyPress("Archive", event, actions); 00141 00142 for (int i = 0; i < actions.size() && !handled; i++) 00143 { 00144 QString action = actions[i]; 00145 handled = true; 00146 00147 if (action == "MENU") 00148 { 00149 showMenu(); 00150 } 00151 else if (action == "DELETE") 00152 { 00153 removeItem(); 00154 } 00155 00156 else 00157 handled = false; 00158 } 00159 00160 if (!handled && MythScreenType::keyPressEvent(event)) 00161 handled = true; 00162 00163 return handled; 00164 } 00165 00166 void ExportNative::updateSizeBar() 00167 { 00168 int64_t size = 0; 00169 ArchiveItem *a; 00170 00171 for (int x = 0; x < m_archiveList.size(); x++) 00172 { 00173 a = m_archiveList.at(x); 00174 size += a->size; 00175 } 00176 00177 m_usedSpace = size / 1024 / 1024; 00178 uint freeSpace = m_archiveDestination.freeSpace / 1024; 00179 00180 QString tmpSize; 00181 00182 m_sizeBar->SetTotal(freeSpace); 00183 m_sizeBar->SetUsed(m_usedSpace); 00184 00185 tmpSize.sprintf("%0d Mb", freeSpace); 00186 00187 if (m_maxsizeText) 00188 m_maxsizeText->SetText(tmpSize); 00189 00190 if (m_minsizeText) 00191 m_minsizeText->SetText("0 Mb"); 00192 00193 tmpSize.sprintf("%0d Mb", m_usedSpace); 00194 00195 if (m_usedSpace > freeSpace) 00196 { 00197 if (m_currsizeText) 00198 m_currsizeText->Hide(); 00199 00200 if (m_currsizeErrText) 00201 { 00202 m_currsizeErrText->Show(); 00203 m_currsizeErrText->SetText(tmpSize); 00204 } 00205 } 00206 else 00207 { 00208 if (m_currsizeErrText) 00209 m_currsizeErrText->Hide(); 00210 00211 if (m_currsizeText) 00212 { 00213 m_currsizeText->Show(); 00214 m_currsizeText->SetText(tmpSize); 00215 } 00216 } 00217 } 00218 00219 void ExportNative::titleChanged(MythUIButtonListItem *item) 00220 { 00221 ArchiveItem *a; 00222 00223 a = qVariantValue<ArchiveItem *>(item->GetData()); 00224 00225 if (!a) 00226 return; 00227 00228 m_titleText->SetText(a->title); 00229 00230 m_datetimeText->SetText(a->startDate + " " + a->startTime); 00231 00232 m_descriptionText->SetText( 00233 (a->subtitle != "" ? a->subtitle + "\n" : "") + a->description); 00234 00235 m_filesizeText->SetText(formatSize(a->size / 1024, 2)); 00236 } 00237 00238 void ExportNative::handleNextPage() 00239 { 00240 if (m_archiveList.size() == 0) 00241 { 00242 ShowOkPopup(tr("You need to add at least one item to archive!")); 00243 return; 00244 } 00245 00246 runScript(); 00247 00248 m_previousScreen->Close(); 00249 Close(); 00250 } 00251 00252 void ExportNative::handlePrevPage() 00253 { 00254 Close(); 00255 } 00256 00257 void ExportNative::handleCancel() 00258 { 00259 m_previousScreen->Close(); 00260 Close(); 00261 } 00262 00263 void ExportNative::updateArchiveList(void) 00264 { 00265 m_archiveButtonList->Reset(); 00266 00267 if (m_archiveList.size() == 0) 00268 { 00269 m_titleText->Reset(); 00270 m_datetimeText->Reset(); 00271 m_descriptionText->Reset(); 00272 m_filesizeText->Reset(); 00273 m_nofilesText->Show(); 00274 } 00275 else 00276 { 00277 ArchiveItem *a; 00278 for (int x = 0; x < m_archiveList.size(); x++) 00279 { 00280 a = m_archiveList.at(x); 00281 00282 MythUIButtonListItem* item = new MythUIButtonListItem(m_archiveButtonList, a->title); 00283 item->SetData(qVariantFromValue(a)); 00284 } 00285 00286 m_archiveButtonList->SetItemCurrent(m_archiveButtonList->GetItemFirst()); 00287 titleChanged(m_archiveButtonList->GetItemCurrent()); 00288 m_nofilesText->Hide(); 00289 } 00290 00291 updateSizeBar(); 00292 } 00293 00294 void ExportNative::getArchiveListFromDB(void) 00295 { 00296 while (!m_archiveList.isEmpty()) 00297 delete m_archiveList.takeFirst(); 00298 m_archiveList.clear(); 00299 00300 MSqlQuery query(MSqlQuery::InitCon()); 00301 query.prepare("SELECT intid, type, title, subtitle, description, size, " 00302 "startdate, starttime, filename, hascutlist " 00303 "FROM archiveitems WHERE type = 'Recording' OR type = 'Video' " 00304 "ORDER BY title, subtitle"); 00305 00306 if (query.exec()) 00307 { 00308 while (query.next()) 00309 { 00310 ArchiveItem *item = new ArchiveItem; 00311 00312 item->id = query.value(0).toInt(); 00313 item->type = query.value(1).toString(); 00314 item->title = query.value(2).toString(); 00315 item->subtitle = query.value(3).toString(); 00316 item->description = query.value(4).toString(); 00317 item->size = query.value(5).toLongLong(); 00318 item->startDate = query.value(6).toString(); 00319 item->startTime = query.value(7).toString(); 00320 item->filename = query.value(8).toString(); 00321 item->hasCutlist = (query.value(9).toInt() > 0); 00322 item->useCutlist = false; 00323 item->editedDetails = false; 00324 00325 m_archiveList.append(item); 00326 } 00327 } 00328 } 00329 00330 void ExportNative::getArchiveList(void) 00331 { 00332 getArchiveListFromDB(); 00333 updateArchiveList(); 00334 } 00335 00336 void ExportNative::loadConfiguration(void) 00337 { 00338 m_bCreateISO = (gCoreContext->GetSetting("MythNativeCreateISO", "0") == "1"); 00339 m_bDoBurn = (gCoreContext->GetSetting("MythNativeBurnDVDr", "1") == "1"); 00340 m_bEraseDvdRw = (gCoreContext->GetSetting("MythNativeEraseDvdRw", "0") == "1"); 00341 m_saveFilename = gCoreContext->GetSetting("MythNativeSaveFilename", ""); 00342 } 00343 00344 void ExportNative::saveConfiguration(void) 00345 { 00346 // remove all old archive items from DB 00347 MSqlQuery query(MSqlQuery::InitCon()); 00348 query.prepare("DELETE FROM archiveitems;"); 00349 if (!query.exec()) 00350 MythDB::DBError("ExportNative::saveConfiguration - " 00351 "deleting archiveitems", query); 00352 00353 // save new list of archive items to DB 00354 ArchiveItem *a; 00355 for (int x = 0; x < m_archiveList.size(); x++) 00356 { 00357 a = m_archiveList.at(x); 00358 00359 query.prepare("INSERT INTO archiveitems (type, title, subtitle, " 00360 "description, startdate, starttime, size, filename, hascutlist, " 00361 "duration, cutduration, videowidth, videoheight, filecodec," 00362 "videocodec, encoderprofile) " 00363 "VALUES(:TYPE, :TITLE, :SUBTITLE, :DESCRIPTION, :STARTDATE, " 00364 ":STARTTIME, :SIZE, :FILENAME, :HASCUTLIST, :DURATION, " 00365 ":CUTDURATION, :VIDEOWIDTH, :VIDEOHEIGHT, :FILECODEC, " 00366 ":VIDEOCODEC, :ENCODERPROFILE);"); 00367 query.bindValue(":TYPE", a->type); 00368 query.bindValue(":TITLE", a->title); 00369 query.bindValue(":SUBTITLE", a->subtitle); 00370 query.bindValue(":DESCRIPTION", a->description); 00371 query.bindValue(":STARTDATE", a->startDate); 00372 query.bindValue(":STARTTIME", a->startTime); 00373 query.bindValue(":SIZE", 0); 00374 query.bindValue(":FILENAME", a->filename); 00375 query.bindValue(":HASCUTLIST", a->hasCutlist); 00376 query.bindValue(":DURATION", 0); 00377 query.bindValue(":CUTDURATION", 0); 00378 query.bindValue(":VIDEOWIDTH", 0); 00379 query.bindValue(":VIDEOHEIGHT", 0); 00380 query.bindValue(":FILECODEC", ""); 00381 query.bindValue(":VIDEOCODEC", ""); 00382 query.bindValue(":ENCODERPROFILE", ""); 00383 00384 if (!query.exec()) 00385 MythDB::DBError("archive item insert", query); 00386 } 00387 } 00388 00389 void ExportNative::showMenu() 00390 { 00391 MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack"); 00392 00393 MythDialogBox *menuPopup = new MythDialogBox(tr("Menu"), popupStack, "actionmenu"); 00394 00395 if (menuPopup->Create()) 00396 popupStack->AddScreen(menuPopup); 00397 00398 menuPopup->SetReturnEvent(this, "action"); 00399 00400 menuPopup->AddButton(tr("Remove Item"), SLOT(removeItem())); 00401 } 00402 00403 void ExportNative::removeItem() 00404 { 00405 MythUIButtonListItem *item = m_archiveButtonList->GetItemCurrent(); 00406 ArchiveItem *curItem = qVariantValue<ArchiveItem *>(item->GetData()); 00407 00408 if (!curItem) 00409 return; 00410 00411 MSqlQuery query(MSqlQuery::InitCon()); 00412 query.prepare("DELETE FROM archiveitems WHERE filename = :FILENAME;"); 00413 query.bindValue(":FILENAME", curItem->filename); 00414 if (query.exec() && query.numRowsAffected()) 00415 { 00416 getArchiveList(); 00417 } 00418 } 00419 00420 void ExportNative::createConfigFile(const QString &filename) 00421 { 00422 QDomDocument doc("NATIVEARCHIVEJOB"); 00423 00424 QDomElement root = doc.createElement("nativearchivejob"); 00425 doc.appendChild(root); 00426 00427 QDomElement job = doc.createElement("job"); 00428 root.appendChild(job); 00429 00430 QDomElement media = doc.createElement("media"); 00431 job.appendChild(media); 00432 00433 // now loop though selected archive items and add them to the xml file 00434 ArchiveItem *a; 00435 for (int x = 0; x < m_archiveList.size(); x++) 00436 { 00437 a = m_archiveList.at(x); 00438 00439 QDomElement file = doc.createElement("file"); 00440 file.setAttribute("type", a->type.toLower() ); 00441 file.setAttribute("title", a->title); 00442 file.setAttribute("filename", a->filename); 00443 file.setAttribute("delete", "0"); 00444 media.appendChild(file); 00445 } 00446 00447 // add the options to the xml file 00448 QDomElement options = doc.createElement("options"); 00449 options.setAttribute("createiso", m_bCreateISO); 00450 options.setAttribute("doburn", m_bDoBurn); 00451 options.setAttribute("mediatype", m_archiveDestination.type); 00452 options.setAttribute("dvdrsize", (qint64)m_archiveDestination.freeSpace); 00453 options.setAttribute("erasedvdrw", m_bEraseDvdRw); 00454 options.setAttribute("savedirectory", m_saveFilename); 00455 job.appendChild(options); 00456 00457 // finally save the xml to the file 00458 QFile f(filename); 00459 if (!f.open(QIODevice::WriteOnly)) 00460 { 00461 LOG(VB_GENERAL, LOG_ERR, 00462 QString("ExportNative::createConfigFile: " 00463 "Failed to open file for writing - %1") .arg(filename)); 00464 return; 00465 } 00466 00467 QTextStream t(&f); 00468 t << doc.toString(4); 00469 f.close(); 00470 } 00471 00472 void ExportNative::runScript() 00473 { 00474 QString tempDir = getTempDirectory(); 00475 QString logDir = tempDir + "logs"; 00476 QString configDir = tempDir + "config"; 00477 QString commandline; 00478 00479 // remove existing progress.log if present 00480 if (QFile::exists(logDir + "/progress.log")) 00481 QFile::remove(logDir + "/progress.log"); 00482 00483 // remove cancel flag file if present 00484 if (QFile::exists(logDir + "/mythburncancel.lck")) 00485 QFile::remove(logDir + "/mythburncancel.lck"); 00486 00487 createConfigFile(configDir + "/mydata.xml"); 00488 commandline = "mytharchivehelper --nativearchive --outfile " + configDir + 00489 "/mydata.xml"; // job file 00490 commandline += logPropagateArgs; 00491 if (!logPropagateQuiet()) 00492 commandline += " --quiet"; 00493 commandline += " > " + logDir + "/progress.log 2>&1 &"; // Logs 00494 00495 uint flags = kMSRunBackground | kMSDontBlockInputDevs | 00496 kMSDontDisableDrawing; 00497 uint retval = myth_system(commandline, flags); 00498 if (retval != GENERIC_EXIT_RUNNING && retval != GENERIC_EXIT_OK) 00499 { 00500 ShowOkPopup(QObject::tr("It was not possible to create the DVD. " 00501 "An error occured when running the scripts") ); 00502 return; 00503 } 00504 00505 showLogViewer(); 00506 } 00507 00508 void ExportNative::handleAddRecording() 00509 { 00510 MythScreenStack *mainStack = GetMythMainWindow()->GetMainStack(); 00511 00512 RecordingSelector *selector = new RecordingSelector(mainStack, &m_archiveList); 00513 00514 connect(selector, SIGNAL(haveResult(bool)), 00515 this, SLOT(selectorClosed(bool))); 00516 00517 if (selector->Create()) 00518 mainStack->AddScreen(selector); 00519 } 00520 00521 void ExportNative::selectorClosed(bool ok) 00522 { 00523 if (ok) 00524 updateArchiveList(); 00525 } 00526 00527 void ExportNative::handleAddVideo() 00528 { 00529 MSqlQuery query(MSqlQuery::InitCon()); 00530 query.prepare("SELECT title FROM videometadata"); 00531 if (query.exec() && query.size()) 00532 { 00533 } 00534 else 00535 { 00536 ShowOkPopup(tr("You don't have any videos!")); 00537 return; 00538 } 00539 00540 MythScreenStack *mainStack = GetMythMainWindow()->GetMainStack(); 00541 00542 VideoSelector *selector = new VideoSelector(mainStack, &m_archiveList); 00543 00544 connect(selector, SIGNAL(haveResult(bool)), 00545 this, SLOT(selectorClosed(bool))); 00546 00547 if (selector->Create()) 00548 mainStack->AddScreen(selector); 00549 }
1.7.6.1