|
MythTV
0.26-pre
|
00001 #include <cstdlib> 00002 00003 // Qt 00004 #include <QApplication> 00005 #include <QDir> 00006 #include <QFileInfo> 00007 #include <QDomDocument> 00008 00009 // Myth 00010 #include <mythcontext.h> 00011 #include <mythdbcon.h> 00012 #include <mythuihelper.h> 00013 #include <mythmainwindow.h> 00014 #include <mythuitext.h> 00015 #include <mythuitextedit.h> 00016 #include <mythuibutton.h> 00017 #include <mythuibuttonlist.h> 00018 #include <mythdialogbox.h> 00019 #include <mythsystem.h> 00020 #include <exitcodes.h> 00021 00022 // mytharchive 00023 #include "importnative.h" 00024 #include "archiveutil.h" 00025 #include "logviewer.h" 00026 00027 00029 00030 static bool loadDetailsFromXML(const QString &filename, FileDetails *details) 00031 { 00032 QDomDocument doc("mydocument"); 00033 QFile file(filename); 00034 if (!file.open(QIODevice::ReadOnly)) 00035 return false; 00036 00037 if (!doc.setContent(&file)) 00038 { 00039 file.close(); 00040 return false; 00041 } 00042 file.close(); 00043 00044 QString docType = doc.doctype().name(); 00045 00046 if (docType == "MYTHARCHIVEITEM") 00047 { 00048 QDomNodeList itemNodeList = doc.elementsByTagName("item"); 00049 QString type, dbVersion; 00050 00051 if (itemNodeList.count() < 1) 00052 { 00053 LOG(VB_GENERAL, LOG_ERR, 00054 "Couldn't find an 'item' element in XML file"); 00055 return false; 00056 } 00057 00058 QDomNode n = itemNodeList.item(0); 00059 QDomElement e = n.toElement(); 00060 type = e.attribute("type"); 00061 dbVersion = e.attribute("databaseversion"); 00062 if (type == "recording") 00063 { 00064 QDomNodeList nodeList = e.elementsByTagName("recorded"); 00065 if (nodeList.count() < 1) 00066 { 00067 LOG(VB_GENERAL, LOG_ERR, 00068 "Couldn't find a 'recorded' element in XML file"); 00069 return false; 00070 } 00071 00072 n = nodeList.item(0); 00073 e = n.toElement(); 00074 n = e.firstChild(); 00075 while (!n.isNull()) 00076 { 00077 e = n.toElement(); 00078 if (!e.isNull()) 00079 { 00080 if (e.tagName() == "title") 00081 details->title = e.text(); 00082 00083 if (e.tagName() == "subtitle") 00084 details->subtitle = e.text(); 00085 00086 if (e.tagName() == "starttime") 00087 details->startTime = QDateTime::fromString(e.text(), Qt::ISODate); 00088 00089 if (e.tagName() == "description") 00090 details->description = e.text(); 00091 } 00092 n = n.nextSibling(); 00093 } 00094 00095 // get channel info 00096 n = itemNodeList.item(0); 00097 e = n.toElement(); 00098 nodeList = e.elementsByTagName("channel"); 00099 if (nodeList.count() < 1) 00100 { 00101 LOG(VB_GENERAL, LOG_ERR, 00102 "Couldn't find a 'channel' element in XML file"); 00103 details->chanID = ""; 00104 details->chanNo = ""; 00105 details->chanName = ""; 00106 details->callsign = ""; 00107 return false; 00108 } 00109 00110 n = nodeList.item(0); 00111 e = n.toElement(); 00112 details->chanID = e.attribute("chanid"); 00113 details->chanNo = e.attribute("channum"); 00114 details->chanName = e.attribute("name"); 00115 details->callsign = e.attribute("callsign"); 00116 return true; 00117 } 00118 else if (type == "video") 00119 { 00120 QDomNodeList nodeList = e.elementsByTagName("videometadata"); 00121 if (nodeList.count() < 1) 00122 { 00123 LOG(VB_GENERAL, LOG_ERR, 00124 "Couldn't find a 'videometadata' element in XML file"); 00125 return false; 00126 } 00127 00128 n = nodeList.item(0); 00129 e = n.toElement(); 00130 n = e.firstChild(); 00131 while (!n.isNull()) 00132 { 00133 e = n.toElement(); 00134 if (!e.isNull()) 00135 { 00136 if (e.tagName() == "title") 00137 { 00138 details->title = e.text(); 00139 details->subtitle = ""; 00140 details->startTime = QDateTime(); 00141 } 00142 00143 if (e.tagName() == "plot") 00144 { 00145 details->description = e.text(); 00146 } 00147 } 00148 n = n.nextSibling(); 00149 } 00150 00151 details->chanID = "N/A"; 00152 details->chanNo = "N/A"; 00153 details->chanName = "N/A"; 00154 details->callsign = "N/A"; 00155 00156 return true; 00157 } 00158 } 00159 00160 return false; 00161 } 00162 00164 00165 ArchiveFileSelector::ArchiveFileSelector(MythScreenStack *parent) : 00166 FileSelector(parent, NULL, FSTYPE_FILE, "", "*.xml"), 00167 m_nextButton(NULL), 00168 m_prevButton(NULL), 00169 m_progTitle(NULL), 00170 m_progSubtitle(NULL), 00171 m_progStartTime(NULL) 00172 { 00173 m_curDirectory = gCoreContext->GetSetting("MythNativeLoadFilename", "/"); 00174 } 00175 00176 ArchiveFileSelector::~ArchiveFileSelector(void) 00177 { 00178 gCoreContext->SaveSetting("MythNativeLoadFilename", m_curDirectory); 00179 } 00180 00181 bool ArchiveFileSelector::Create(void) 00182 { 00183 bool foundtheme = false; 00184 00185 // Load the theme for this screen 00186 foundtheme = LoadWindowFromXML("mythnative-ui.xml", "archivefile_selector", this); 00187 00188 if (!foundtheme) 00189 return false; 00190 00191 bool err = false; 00192 UIUtilW::Assign(this, m_titleText, "title"); 00193 UIUtilE::Assign(this, m_fileButtonList, "filelist", &err); 00194 UIUtilE::Assign(this, m_locationEdit, "location_edit", &err); 00195 UIUtilE::Assign(this, m_backButton, "back_button", &err); 00196 UIUtilE::Assign(this, m_homeButton, "home_button", &err); 00197 UIUtilE::Assign(this, m_nextButton, "next_button", &err); 00198 UIUtilE::Assign(this, m_prevButton, "prev_button", &err); 00199 UIUtilE::Assign(this, m_cancelButton, "cancel_button", &err); 00200 UIUtilE::Assign(this, m_progTitle, "title_text", &err); 00201 UIUtilE::Assign(this, m_progSubtitle, "subtitle_text", &err); 00202 UIUtilE::Assign(this, m_progStartTime, "starttime_text", &err); 00203 00204 if (err) 00205 { 00206 LOG(VB_GENERAL, LOG_ERR, "Cannot load screen 'archivefile_selector'"); 00207 return false; 00208 } 00209 00210 if (m_titleText) 00211 m_titleText->SetText(tr("Find File To Import")); 00212 00213 connect(m_nextButton, SIGNAL(Clicked()), this, SLOT(nextPressed())); 00214 connect(m_cancelButton, SIGNAL(Clicked()), this, SLOT(cancelPressed())); 00215 connect(m_prevButton, SIGNAL(Clicked()), this, SLOT(prevPressed())); 00216 00217 connect(m_locationEdit, SIGNAL(LosingFocus()), 00218 this, SLOT(locationEditLostFocus())); 00219 m_locationEdit->SetText(m_curDirectory); 00220 00221 connect(m_backButton, SIGNAL(Clicked()), this, SLOT(backPressed())); 00222 connect(m_homeButton, SIGNAL(Clicked()), this, SLOT(homePressed())); 00223 00224 connect(m_fileButtonList, SIGNAL(itemSelected(MythUIButtonListItem *)), 00225 this, SLOT(itemSelected(MythUIButtonListItem *))); 00226 00227 connect(m_fileButtonList, SIGNAL(itemClicked(MythUIButtonListItem *)), 00228 this, SLOT(itemClicked(MythUIButtonListItem *))); 00229 00230 BuildFocusList(); 00231 00232 SetFocusWidget(m_fileButtonList); 00233 00234 updateSelectedList(); 00235 updateFileList(); 00236 00237 return true; 00238 } 00239 00240 void ArchiveFileSelector::itemSelected(MythUIButtonListItem *item) 00241 { 00242 m_xmlFile.clear(); 00243 00244 if (!item) 00245 return; 00246 00247 FileData *fileData = qVariantValue<FileData*>(item->GetData()); 00248 if (!fileData) 00249 return; 00250 00251 if (loadDetailsFromXML(m_curDirectory + "/" + fileData->filename, &m_details)) 00252 { 00253 m_xmlFile = m_curDirectory + "/" + fileData->filename; 00254 m_progTitle->SetText(m_details.title); 00255 m_progSubtitle->SetText(m_details.subtitle); 00256 m_progStartTime->SetText(m_details.startTime.toString("dd MMM yy (hh:mm)")); 00257 } 00258 else 00259 { 00260 m_progTitle->Reset(); 00261 m_progSubtitle->Reset(); 00262 m_progStartTime->Reset(); 00263 } 00264 } 00265 00266 void ArchiveFileSelector::nextPressed() 00267 { 00268 if (m_xmlFile == "") 00269 { 00270 ShowOkPopup(tr("The selected item is not a valid archive file!")); 00271 } 00272 else 00273 { 00274 MythScreenStack *mainStack = GetMythMainWindow()->GetMainStack(); 00275 00276 ImportNative *native = new ImportNative(mainStack, this, m_xmlFile, m_details); 00277 00278 if (native->Create()) 00279 mainStack->AddScreen(native); 00280 } 00281 } 00282 00283 void ArchiveFileSelector::prevPressed() 00284 { 00285 Close(); 00286 } 00287 00288 void ArchiveFileSelector::cancelPressed() 00289 { 00290 Close(); 00291 } 00292 00294 00295 ImportNative::ImportNative( 00296 MythScreenStack *parent, MythScreenType *previousScreen, 00297 const QString &xmlFile, FileDetails details) : 00298 MythScreenType(parent, "ImportNative"), 00299 m_xmlFile(xmlFile), 00300 m_details(details), 00301 m_previousScreen(previousScreen), 00302 m_progTitle_text(NULL), 00303 m_progDateTime_text(NULL), 00304 m_progDescription_text(NULL), 00305 m_chanID_text(NULL), 00306 m_chanNo_text(NULL), 00307 m_chanName_text(NULL), 00308 m_callsign_text(NULL), 00309 m_localChanID_text(NULL), 00310 m_localChanNo_text(NULL), 00311 m_localChanName_text(NULL), 00312 m_localCallsign_text(NULL), 00313 m_searchChanID_button(NULL), 00314 m_searchChanNo_button(NULL), 00315 m_searchChanName_button(NULL), 00316 m_searchCallsign_button(NULL), 00317 m_finishButton(NULL), 00318 m_prevButton(NULL), 00319 m_cancelButton(NULL), 00320 m_isValidXMLSelected(false) 00321 { 00322 } 00323 00324 ImportNative::~ImportNative() 00325 { 00326 } 00327 00328 bool ImportNative::Create(void) 00329 { 00330 bool foundtheme = false; 00331 00332 // Load the theme for this screen 00333 foundtheme = LoadWindowFromXML("mythnative-ui.xml", "importnative", this); 00334 00335 if (!foundtheme) 00336 return false; 00337 00338 bool err = false; 00339 UIUtilE::Assign(this, m_progTitle_text, "progtitle", &err); 00340 UIUtilE::Assign(this, m_progDateTime_text, "progdatetime", &err); 00341 UIUtilE::Assign(this, m_progDescription_text, "progdescription", &err); 00342 00343 UIUtilE::Assign(this, m_chanID_text, "chanid", &err); 00344 UIUtilE::Assign(this, m_chanNo_text, "channo", &err); 00345 UIUtilE::Assign(this, m_chanName_text, "name", &err); 00346 UIUtilE::Assign(this, m_callsign_text, "callsign", &err); 00347 00348 UIUtilE::Assign(this, m_localChanID_text, "local_chanid", &err); 00349 UIUtilE::Assign(this, m_localChanNo_text, "local_channo", &err); 00350 UIUtilE::Assign(this, m_localChanName_text, "local_name", &err); 00351 UIUtilE::Assign(this, m_localCallsign_text, "local_callsign", &err); 00352 00353 UIUtilE::Assign(this, m_searchChanID_button, "searchchanid_button", &err); 00354 UIUtilE::Assign(this, m_searchChanNo_button, "searchchanno_button", &err); 00355 UIUtilE::Assign(this, m_searchChanName_button, "searchname_button", &err); 00356 UIUtilE::Assign(this, m_searchCallsign_button ,"searchcallsign_button", &err); 00357 00358 UIUtilE::Assign(this, m_finishButton, "finish_button", &err); 00359 UIUtilE::Assign(this, m_prevButton, "prev_button", &err); 00360 UIUtilE::Assign(this, m_cancelButton, "cancel_button", &err); 00361 00362 if (err) 00363 { 00364 LOG(VB_GENERAL, LOG_ERR, "Cannot load screen 'importarchive'"); 00365 return false; 00366 } 00367 00368 connect(m_finishButton, SIGNAL(Clicked()), this, SLOT(finishedPressed())); 00369 connect(m_prevButton, SIGNAL(Clicked()), this, SLOT(prevPressed())); 00370 connect(m_cancelButton, SIGNAL(Clicked()), this, SLOT(cancelPressed())); 00371 00372 connect(m_searchChanID_button, SIGNAL(Clicked()), this, SLOT(searchChanID())); 00373 connect(m_searchChanNo_button, SIGNAL(Clicked()), this, SLOT(searchChanNo())); 00374 connect(m_searchChanName_button, SIGNAL(Clicked()), this, SLOT(searchName())); 00375 connect(m_searchCallsign_button, SIGNAL(Clicked()), this, SLOT(searchCallsign())); 00376 00377 m_progTitle_text->SetText(m_details.title); 00378 00379 m_progDateTime_text->SetText(m_details.startTime.toString("dd MMM yy (hh:mm)")); 00380 m_progDescription_text->SetText( 00381 (m_details.subtitle == "" ? m_details.subtitle + "\n" : "") + m_details.description); 00382 00383 m_chanID_text->SetText(m_details.chanID); 00384 m_chanNo_text->SetText(m_details.chanNo); 00385 m_chanName_text->SetText(m_details.chanName); 00386 m_callsign_text->SetText(m_details.callsign); 00387 00388 findChannelMatch(m_details.chanID, m_details.chanNo, 00389 m_details.chanName, m_details.callsign); 00390 00391 BuildFocusList(); 00392 00393 SetFocusWidget(m_finishButton); 00394 00395 return true; 00396 } 00397 00398 bool ImportNative::keyPressEvent(QKeyEvent *event) 00399 { 00400 if (GetFocusWidget()->keyPressEvent(event)) 00401 return true; 00402 00403 bool handled = false; 00404 QStringList actions; 00405 handled = GetMythMainWindow()->TranslateKeyPress("Global", event, actions); 00406 00407 for (int i = 0; i < actions.size() && !handled; i++) 00408 { 00409 QString action = actions[i]; 00410 handled = true; 00411 00412 if (action == "MENU") 00413 { 00414 } 00415 else 00416 handled = false; 00417 } 00418 00419 if (!handled && MythScreenType::keyPressEvent(event)) 00420 handled = true; 00421 00422 return handled; 00423 } 00424 00425 void ImportNative::finishedPressed() 00426 00427 { 00428 if (m_details.chanID != "N/A" && m_localChanID_text->GetText() == "") 00429 { 00430 ShowOkPopup(tr("You need to select a valid channel id!")); 00431 return; 00432 } 00433 00434 QString commandline; 00435 QString tempDir = gCoreContext->GetSetting("MythArchiveTempDir", ""); 00436 QString chanID = m_localChanID_text->GetText(); 00437 00438 if (chanID == "") 00439 chanID = m_details.chanID; 00440 00441 if (tempDir == "") 00442 return; 00443 00444 if (!tempDir.endsWith("/")) 00445 tempDir += "/"; 00446 00447 QString logDir = tempDir + "logs"; 00448 00449 // remove existing progress.log if prescent 00450 if (QFile::exists(logDir + "/progress.log")) 00451 QFile::remove(logDir + "/progress.log"); 00452 00453 commandline = "mytharchivehelper --importarchive --infile \"" + m_xmlFile + 00454 "\" --chanid " + chanID; 00455 commandline += logPropagateArgs; 00456 if (!logPropagateQuiet()) 00457 commandline += " --quiet"; 00458 commandline += " > " + logDir + "/progress.log 2>&1 &"; 00459 00460 uint flags = kMSRunBackground | kMSDontBlockInputDevs | 00461 kMSDontDisableDrawing; 00462 uint retval = myth_system(commandline, flags); 00463 if (retval != GENERIC_EXIT_RUNNING && retval != GENERIC_EXIT_OK) 00464 { 00465 ShowOkPopup(tr("It was not possible to import the Archive. " 00466 " An error occured when running 'mytharchivehelper'") ); 00467 return; 00468 } 00469 00470 showLogViewer(); 00471 00472 m_previousScreen->Close(); 00473 Close(); 00474 } 00475 00476 void ImportNative::prevPressed() 00477 { 00478 Close(); 00479 } 00480 00481 void ImportNative::cancelPressed() 00482 { 00483 m_previousScreen->Close(); 00484 Close(); 00485 } 00486 00487 void ImportNative::findChannelMatch(const QString &chanID, const QString &chanNo, 00488 const QString &name, const QString &callsign) 00489 { 00490 // find best match in channel table for this recording 00491 00492 // look for an exact match - maybe the user is importing back an old recording 00493 MSqlQuery query(MSqlQuery::InitCon()); 00494 query.prepare("SELECT chanid, channum, name, callsign FROM channel " 00495 "WHERE chanid = :CHANID AND channum = :CHANNUM AND name = :NAME " 00496 "AND callsign = :CALLSIGN;"); 00497 query.bindValue(":CHANID", chanID); 00498 query.bindValue(":CHANNUM", chanNo); 00499 query.bindValue(":NAME", name); 00500 query.bindValue(":CALLSIGN", callsign); 00501 00502 if (query.exec() && query.next()) 00503 { 00504 // got match 00505 m_localChanID_text->SetText(query.value(0).toString()); 00506 m_localChanNo_text->SetText(query.value(1).toString()); 00507 m_localChanName_text->SetText(query.value(2).toString()); 00508 m_localCallsign_text->SetText(query.value(3).toString()); 00509 return; 00510 } 00511 00512 // try to find callsign 00513 query.prepare("SELECT chanid, channum, name, callsign FROM channel " 00514 "WHERE callsign = :CALLSIGN;"); 00515 query.bindValue(":CALLSIGN", callsign); 00516 00517 if (query.exec() && query.next()) 00518 { 00519 // got match 00520 m_localChanID_text->SetText(query.value(0).toString()); 00521 m_localChanNo_text->SetText(query.value(1).toString()); 00522 m_localChanName_text->SetText(query.value(2).toString()); 00523 m_localCallsign_text->SetText(query.value(3).toString()); 00524 return; 00525 } 00526 00527 // try to find name 00528 query.prepare("SELECT chanid, channum, name, callsign FROM channel " 00529 "WHERE name = :NAME;"); 00530 query.bindValue(":NAME", callsign); 00531 00532 if (query.exec() && query.next()) 00533 { 00534 // got match 00535 m_localChanID_text->SetText(query.value(0).toString()); 00536 m_localChanNo_text->SetText(query.value(1).toString()); 00537 m_localChanName_text->SetText(query.value(2).toString()); 00538 m_localCallsign_text->SetText(query.value(3).toString()); 00539 return; 00540 } 00541 00542 // give up 00543 m_localChanID_text->Reset(); 00544 m_localChanNo_text->Reset(); 00545 m_localChanName_text->Reset(); 00546 m_localCallsign_text->Reset(); 00547 } 00548 00549 void ImportNative::showList(const QString &caption, QString &value, 00550 const char *slot) 00551 { 00552 MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack"); 00553 00554 MythUISearchDialog *searchDialog = new 00555 MythUISearchDialog(popupStack, caption, m_searchList, true, value); 00556 00557 if (!searchDialog->Create()) 00558 { 00559 delete searchDialog; 00560 searchDialog = NULL; 00561 return; 00562 } 00563 00564 connect(searchDialog, SIGNAL(haveResult(QString)), this, slot); 00565 00566 popupStack->AddScreen(searchDialog); 00567 } 00568 00569 void ImportNative::fillSearchList(const QString &field) 00570 { 00571 00572 m_searchList.clear(); 00573 00574 QString querystr; 00575 querystr = QString("SELECT %1 FROM channel ORDER BY %2").arg(field).arg(field); 00576 00577 MSqlQuery query(MSqlQuery::InitCon()); 00578 00579 if (query.exec(querystr)) 00580 { 00581 while (query.next()) 00582 { 00583 m_searchList << query.value(0).toString(); 00584 } 00585 } 00586 } 00587 00588 void ImportNative::searchChanID() 00589 { 00590 QString s; 00591 00592 fillSearchList("chanid"); 00593 00594 s = m_chanID_text->GetText(); 00595 showList(tr("Select a channel id"), s, SLOT(gotChanID(QString))); 00596 } 00597 00598 void ImportNative::gotChanID(QString value) 00599 { 00600 MSqlQuery query(MSqlQuery::InitCon()); 00601 query.prepare("SELECT chanid, channum, name, callsign " 00602 "FROM channel WHERE chanid = :CHANID;"); 00603 query.bindValue(":CHANID", value); 00604 00605 if (query.exec() && query.next()) 00606 { 00607 m_localChanID_text->SetText(query.value(0).toString()); 00608 m_localChanNo_text->SetText(query.value(1).toString()); 00609 m_localChanName_text->SetText(query.value(2).toString()); 00610 m_localCallsign_text->SetText(query.value(3).toString()); 00611 } 00612 } 00613 00614 void ImportNative::searchChanNo() 00615 { 00616 QString s; 00617 00618 fillSearchList("channum"); 00619 00620 s = m_chanNo_text->GetText(); 00621 showList(tr("Select a channel number"), s, SLOT(gotChanNo(QString))); 00622 } 00623 00624 void ImportNative::gotChanNo(QString value) 00625 { 00626 MSqlQuery query(MSqlQuery::InitCon()); 00627 query.prepare("SELECT chanid, channum, name, callsign " 00628 "FROM channel WHERE channum = :CHANNUM;"); 00629 query.bindValue(":CHANNUM", value); 00630 00631 if (query.exec() && query.next()) 00632 { 00633 m_localChanID_text->SetText(query.value(0).toString()); 00634 m_localChanNo_text->SetText(query.value(1).toString()); 00635 m_localChanName_text->SetText(query.value(2).toString()); 00636 m_localCallsign_text->SetText(query.value(3).toString()); 00637 } 00638 } 00639 00640 void ImportNative::searchName() 00641 { 00642 QString s; 00643 00644 fillSearchList("name"); 00645 00646 s = m_chanName_text->GetText(); 00647 showList(tr("Select a channel name"), s, SLOT(gotName(QString))); 00648 } 00649 00650 void ImportNative::gotName(QString value) 00651 { 00652 MSqlQuery query(MSqlQuery::InitCon()); 00653 query.prepare("SELECT chanid, channum, name, callsign " 00654 "FROM channel WHERE name = :NAME;"); 00655 query.bindValue(":NAME", value); 00656 00657 if (query.exec() && query.next()) 00658 { 00659 m_localChanID_text->SetText(query.value(0).toString()); 00660 m_localChanNo_text->SetText(query.value(1).toString()); 00661 m_localChanName_text->SetText(query.value(2).toString()); 00662 m_localCallsign_text->SetText(query.value(3).toString()); 00663 } 00664 } 00665 00666 void ImportNative::searchCallsign() 00667 { 00668 QString s; 00669 00670 fillSearchList("callsign"); 00671 00672 s = m_callsign_text->GetText(); 00673 showList(tr("Select a Callsign"), s, SLOT(gotCallsign(QString))); 00674 } 00675 00676 void ImportNative::gotCallsign(QString value) 00677 { 00678 MSqlQuery query(MSqlQuery::InitCon()); 00679 query.prepare("SELECT chanid, channum, name, callsign " 00680 "FROM channel WHERE callsign = :CALLSIGN;"); 00681 query.bindValue(":CALLSIGN", value); 00682 00683 if (query.exec() && query.next()) 00684 { 00685 m_localChanID_text->SetText(query.value(0).toString()); 00686 m_localChanNo_text->SetText(query.value(1).toString()); 00687 m_localChanName_text->SetText(query.value(2).toString()); 00688 m_localCallsign_text->SetText(query.value(3).toString()); 00689 } 00690 }
1.7.6.1