Ticket #4588: mythtv-move_storagegroup_to_libmyth.patch
File mythtv-move_storagegroup_to_libmyth.patch, 56.7 KB (added by , 16 years ago) |
---|
-
libs/libmythtv/libmythtv.pro
120 120 121 121 # Misc. needed by backend/frontend 122 122 HEADERS += programinfo.h proglist.h 123 HEADERS += storagegroup.h124 123 HEADERS += RingBuffer.h avfringbuffer.h 125 124 HEADERS += ThreadedFileWriter.h previouslist.h 126 125 HEADERS += dbcheck.h customedit.h … … 141 140 HEADERS += importicons.h 142 141 143 142 SOURCES += programinfo.cpp proglist.cpp 144 SOURCES += storagegroup.cpp145 143 SOURCES += RingBuffer.cpp avfringbuffer.cpp 146 144 SOURCES += ThreadedFileWriter.cpp previouslist.cpp 147 145 SOURCES += dbcheck.cpp customedit.cpp -
libs/libmythtv/storagegroup.h
1 #ifndef _STORAGEGROUP_H2 #define _STORAGEGROUP_H3 4 #include <qstringlist.h>5 #include <qdeepcopy.h>6 7 #include "libmyth/settings.h"8 #include "libmyth/mythwidgets.h"9 10 class MPUBLIC StorageGroup: public ConfigurationWizard11 {12 public:13 StorageGroup(const QString group = "", const QString hostname = "");14 15 void Init(const QString group = "Default",16 const QString hostname = "");17 18 QString getName(void) const19 { return QDeepCopy<QString>(m_groupname); }20 21 QStringList GetDirList(void) const22 { return QDeepCopy<QStringList>(m_dirlist); }23 24 QString FindRecordingFile(QString filename);25 QString FindRecordingDir(QString filename);26 27 QString FindNextDirMostFree(void);28 29 static void CheckAllStorageGroupDirs(void);30 31 static const char *kDefaultStorageDir;32 static const QStringList kSpecialGroups;33 34 static QStringList getRecordingsGroups(void);35 36 private:37 QString m_groupname;38 QString m_hostname;39 QStringList m_dirlist;40 };41 42 class MPUBLIC StorageGroupEditor :43 public QObject, public ConfigurationDialog44 {45 Q_OBJECT46 public:47 StorageGroupEditor(QString group);48 virtual DialogCode exec(void);49 virtual void load(void);50 virtual void save(void) { };51 virtual void save(QString) { };52 virtual MythDialog* dialogWidget(MythMainWindow* parent,53 const char* widgetname=0);54 55 protected slots:56 void open(QString name);57 void doDelete(void);58 59 protected:60 QString m_group;61 ListBoxSetting *listbox;62 QString lastValue;63 };64 65 class MPUBLIC StorageGroupListEditor :66 public QObject, public ConfigurationDialog67 {68 Q_OBJECT69 public:70 StorageGroupListEditor(void);71 virtual DialogCode exec(void);72 virtual void load(void);73 virtual void save(void) { };74 virtual void save(QString) { };75 virtual MythDialog* dialogWidget(MythMainWindow* parent,76 const char* widgetname=0);77 78 protected slots:79 void open(QString name);80 void doDelete(void);81 82 protected:83 ListBoxSetting *listbox;84 QString lastValue;85 };86 87 #endif88 89 /* vim: set expandtab tabstop=4 shiftwidth=4: */ -
libs/libmythtv/storagegroup.cpp
1 #include <qdir.h>2 #include <qfile.h>3 #include <qregexp.h>4 5 #include "storagegroup.h"6 #include "libmyth/mythcontext.h"7 #include "libmyth/mythdbcon.h"8 #include "libmyth/util.h"9 10 #define LOC QString("SG(%1): ").arg(m_groupname)11 #define LOC_WARN QString("SG(%1) Warning: ").arg(m_groupname)12 #define LOC_ERR QString("SG(%1) Error: ").arg(m_groupname)13 14 const char *StorageGroup::kDefaultStorageDir = "/mnt/store";15 16 const QStringList StorageGroup::kSpecialGroups = QStringList()17 << "LiveTV"18 // << "Thumbnails"19 // << "DB Backups"20 ;21 22 /****************************************************************************/23 24 /** \brief StorageGroup constructor.25 * \param group storage group to search, blank will search all groups.26 * \param hostname hostname where to search, blank will search all hosts'27 * directories, but only in local directory structure.28 * This is parameter is ignored if group is an empty string.29 */30 StorageGroup::StorageGroup(const QString group, const QString hostname) :31 m_groupname(QDeepCopy<QString>(group)),32 m_hostname(QDeepCopy<QString>(hostname))33 {34 m_dirlist.clear();35 36 Init(m_groupname, m_hostname);37 }38 39 void StorageGroup::Init(const QString group, const QString hostname)40 {41 QString dirname;42 MSqlQuery query(MSqlQuery::InitCon());43 44 m_groupname = QDeepCopy<QString>(group);45 m_hostname = QDeepCopy<QString>(hostname);46 m_dirlist.clear();47 48 QString sql = "SELECT DISTINCT dirname "49 "FROM storagegroup ";50 51 if (!m_groupname.isEmpty())52 {53 sql.append("WHERE groupname = :GROUP");54 if (!m_hostname.isEmpty())55 sql.append(" AND hostname = :HOSTNAME");56 }57 58 query.prepare(sql);59 query.bindValue(":GROUP", m_groupname);60 query.bindValue(":HOSTNAME", m_hostname);61 62 if (!query.exec() || !query.isActive())63 MythContext::DBError("StorageGroup::StorageGroup()", query);64 else if (!query.next())65 {66 if (group != "Default")67 {68 VERBOSE(VB_FILE, LOC +69 QString("Unable to find storage group '%1', trying "70 "'Default' group!").arg(m_groupname));71 Init("Default", m_hostname);72 return;73 }74 else if (!m_hostname.isEmpty())75 {76 VERBOSE(VB_FILE, LOC +77 QString("Unable to find any directories for the local "78 "Default storage group, trying directories in all "79 "Default groups!").arg(m_groupname));80 Init("Default", "");81 return;82 }83 }84 else85 {86 do87 {88 dirname = query.value(0).toString();89 dirname.replace(QRegExp("^\\s*"), "");90 dirname.replace(QRegExp("\\s*$"), "");91 if (dirname.right(1) == "/")92 dirname.remove(dirname.length() - 1, 1);93 m_dirlist << QDeepCopy<QString>(dirname);94 }95 while (query.next());96 }97 98 if (!m_dirlist.size())99 {100 QString msg = "Directory value for Default Storage Group is empty. ";101 QString tmpDir = gContext->GetSetting("RecordFilePrefix");102 if (tmpDir != "")103 {104 msg += QString("Using old 'RecordFilePrefix' value of '%1'")105 .arg(tmpDir);106 }107 else108 {109 tmpDir = kDefaultStorageDir;110 msg += QString("Using hardcoded default value of '%1'")111 .arg(kDefaultStorageDir);112 }113 VERBOSE(VB_IMPORTANT, LOC_ERR + msg);114 m_dirlist << QDeepCopy<QString>(tmpDir);115 }116 }117 118 QString StorageGroup::FindRecordingFile(QString filename)119 {120 VERBOSE(VB_FILE, LOC + QString("FindRecordingFile: Searching for '%1'")121 .arg(filename));122 123 QString recDir = FindRecordingDir(filename);124 QString result = "";125 126 if (!recDir.isEmpty())127 {128 result = recDir + "/" + filename;129 VERBOSE(VB_FILE, LOC + QString("FindRecordingFile: Found '%1'")130 .arg(result));131 }132 else133 {134 VERBOSE(VB_FILE, LOC_ERR +135 QString("FindRecordingFile: Unable to find '%1'!")136 .arg(filename));137 }138 139 return result;140 }141 142 QString StorageGroup::FindRecordingDir(QString filename)143 {144 QString result = "";145 QFile checkFile("");146 147 unsigned int curDir = 0;148 while (curDir < m_dirlist.size())149 {150 QString testFile = m_dirlist[curDir] + "/" + filename;151 VERBOSE(VB_FILE, LOC + QString("FindRecordingDir: Checking '%1'")152 .arg(m_dirlist[curDir]));153 checkFile.setName(testFile);154 if (checkFile.exists())155 return QDeepCopy<QString>(m_dirlist[curDir]);156 157 curDir++;158 }159 160 if (m_groupname.isEmpty())161 {162 // Not found in any dir, so try RecordFilePrefix if it exists163 QString tmpFile =164 gContext->GetSetting("RecordFilePrefix") + "/" + filename;165 checkFile.setName(tmpFile);166 if (checkFile.exists())167 result = tmpFile;168 }169 else if (m_groupname != "Default")170 {171 // Not found in current group so try Default172 StorageGroup sgroup("Default");173 QString tmpFile = sgroup.FindRecordingDir(filename);174 result = (tmpFile.isEmpty()) ? result : tmpFile;175 }176 else177 {178 // Not found in Default so try any dir179 StorageGroup sgroup;180 QString tmpFile = sgroup.FindRecordingDir(filename);181 result = (tmpFile.isEmpty()) ? result : tmpFile;182 }183 184 return QDeepCopy<QString>(result);185 }186 187 QString StorageGroup::FindNextDirMostFree(void)188 {189 QString nextDir = kDefaultStorageDir;190 long long nextDirFree = 0;191 long long thisDirTotal;192 long long thisDirUsed;193 long long thisDirFree;194 195 VERBOSE(VB_FILE, LOC + QString("FindNextDirMostFree: Starting'"));196 197 if (m_dirlist.size())198 nextDir = m_dirlist[0];199 200 QDir checkDir("");201 unsigned int curDir = 0;202 while (curDir < m_dirlist.size())203 {204 checkDir.setPath(m_dirlist[curDir]);205 if (!checkDir.exists())206 {207 VERBOSE(VB_IMPORTANT, LOC_ERR +208 QString("FindNextDirMostFree: '%1' does not exist!")209 .arg(nextDir));210 curDir++;211 continue;212 }213 214 thisDirFree = getDiskSpace(m_dirlist[curDir], thisDirTotal,215 thisDirUsed);216 VERBOSE(VB_FILE, LOC +217 QString("FindNextDirMostFree: '%1' has %2 KiB free")218 .arg(m_dirlist[curDir])219 .arg(longLongToString(thisDirFree)));220 221 if (thisDirFree > nextDirFree)222 {223 nextDir = m_dirlist[curDir];224 nextDirFree = thisDirFree;225 }226 curDir++;227 }228 229 VERBOSE(VB_FILE, LOC + QString("FindNextDirMostFree: Using '%1'")230 .arg(nextDir));231 232 return QDeepCopy<QString>(nextDir);233 }234 235 void StorageGroup::CheckAllStorageGroupDirs(void)236 {237 QString m_groupname;238 QString dirname;239 MSqlQuery query(MSqlQuery::InitCon());240 241 query.prepare("SELECT groupname, dirname "242 "FROM storagegroup "243 "WHERE hostname = :HOSTNAME;");244 query.bindValue(":HOSTNAME", gContext->GetHostName());245 if (!query.exec() || !query.isActive())246 {247 MythContext::DBError("StorageGroup::CheckAllStorageGroupDirs()", query);248 return;249 }250 251 VERBOSE(VB_FILE, LOC + "CheckAllStorageGroupDirs(): Checking All Storage "252 "Group directories");253 254 QFile testFile("");255 QDir testDir("");256 while (query.next())257 {258 m_groupname = query.value(0).toString();259 dirname = query.value(1).toString();260 261 dirname.replace(QRegExp("^\\s*"), "");262 dirname.replace(QRegExp("\\s*$"), "");263 264 VERBOSE(VB_FILE, LOC +265 QString("Checking directory '%1' in group '%2'.")266 .arg(dirname).arg(m_groupname));267 268 testDir.setPath(dirname);269 if (!testDir.exists())270 {271 VERBOSE(VB_FILE, LOC_WARN +272 QString("Group '%1' references directory '%2' but this "273 "directory does not exist. This directory "274 "will not be used on this server.")275 .arg(m_groupname).arg(dirname));276 }277 else278 {279 testFile.setName(dirname + "/.test");280 if (testFile.open(IO_WriteOnly))281 testFile.remove();282 else283 VERBOSE(VB_IMPORTANT,284 LOC_ERR +285 QString("Group '%1' wants to use directory '%2', but "286 "this directory is not writeable.")287 .arg(m_groupname).arg(dirname));288 }289 }290 }291 292 QStringList StorageGroup::getRecordingsGroups(void)293 {294 QStringList groups;295 296 MSqlQuery query(MSqlQuery::InitCon());297 298 QString sql = "SELECT DISTINCT groupname "299 "FROM storagegroup "300 "WHERE groupname NOT IN (";301 for (QStringList::const_iterator it = StorageGroup::kSpecialGroups.begin();302 it != StorageGroup::kSpecialGroups.end(); ++it)303 sql.append(QString(" '%1',").arg(*it));304 sql = sql.left(sql.length() - 1);305 sql.append(" );");306 307 query.prepare(sql);308 if (query.exec() && query.isActive() && query.size() > 0)309 while (query.next())310 groups += QString::fromUtf8(query.value(0).toString());311 312 groups.sort();313 314 return QDeepCopy<QStringList>(groups);315 }316 317 /****************************************************************************/318 typedef enum {319 SGPopup_OK = 0,320 SGPopup_CANCEL,321 SGPopup_DELETE322 } SGPopupResult;323 324 class StorageGroupPopup325 {326 public:327 static SGPopupResult showPopup(MythMainWindow *parent, QString title,328 QString message, QString& text);329 };330 331 SGPopupResult StorageGroupPopup::showPopup(MythMainWindow *parent,332 QString title, QString message, QString& text)333 {334 MythPopupBox *popup = new MythPopupBox(parent, title);335 popup->addLabel(message);336 337 MythLineEdit *textEdit = new MythLineEdit(popup, "chooseEdit");338 textEdit->setText(text);339 popup->addWidget(textEdit);340 341 popup->addButton(QObject::tr("OK"), popup, SLOT(accept()));342 popup->addButton(QObject::tr("Cancel"), popup, SLOT(reject()));343 344 textEdit->setFocus();345 346 bool ok = (MythDialog::Accepted == popup->ExecPopup());347 if (ok)348 text = QDeepCopy<QString>(textEdit->text());349 350 popup->hide();351 popup->deleteLater();352 353 return (ok) ? SGPopup_OK : SGPopup_CANCEL;354 }355 356 /****************************************************************************/357 358 StorageGroupEditor::StorageGroupEditor(QString group) :359 m_group(group), listbox(new ListBoxSetting(this)), lastValue("")360 {361 QString dispGroup = group;362 363 if (group == "Default")364 dispGroup = QObject::tr("Default");365 else if (StorageGroup::kSpecialGroups.contains(group))366 dispGroup = QObject::tr(group);367 368 if (gContext->GetSetting("MasterServerIP","master") ==369 gContext->GetSetting("BackendServerIP","me"))370 {371 listbox->setLabel(tr("'%1' Storage Group Directories").arg(dispGroup));372 }373 else374 {375 listbox->setLabel(tr("Local '%1' Storage Group Directories")376 .arg(dispGroup));377 }378 379 addChild(listbox);380 }381 382 void StorageGroupEditor::open(QString name)383 {384 lastValue = name;385 386 if (name == "__CREATE_NEW_STORAGE_DIRECTORY__")387 {388 name = "";389 SGPopupResult result = StorageGroupPopup::showPopup(390 gContext->GetMainWindow(),391 tr("Add Storage Group Directory"),392 tr("Enter directory name or press SELECT to enter text via the "393 "On Screen Keyboard"), name);394 if (result == SGPopup_CANCEL)395 return;396 397 if (name.right(1) != "/")398 name.append("/");399 400 MSqlQuery query(MSqlQuery::InitCon());401 query.prepare("INSERT INTO storagegroup (groupname, hostname, dirname) "402 "VALUES (:NAME, :HOSTNAME, :DIRNAME);");403 query.bindValue(":NAME", m_group.utf8());404 query.bindValue(":DIRNAME", name.utf8());405 query.bindValue(":HOSTNAME", gContext->GetHostName());406 if (!query.exec())407 MythContext::DBError("StorageGroupEditor::open", query);408 else409 lastValue = name;410 } else {411 SGPopupResult result = StorageGroupPopup::showPopup(412 gContext->GetMainWindow(),413 tr("Edit Storage Group Directory"),414 tr("Enter directory name or press SELECT to enter text via the "415 "On Screen Keyboard"), name);416 if (result == SGPopup_CANCEL)417 return;418 419 if (name.right(1) != "/")420 name.append("/");421 422 MSqlQuery query(MSqlQuery::InitCon());423 424 query.prepare("DELETE FROM storagegroup "425 "WHERE groupname = :NAME "426 "AND dirname = :DIRNAME "427 "AND hostname = :HOSTNAME;");428 query.bindValue(":NAME", m_group.utf8());429 query.bindValue(":DIRNAME", lastValue.utf8());430 query.bindValue(":HOSTNAME", gContext->GetHostName());431 if (!query.exec())432 MythContext::DBError("StorageGroupEditor::open", query);433 434 query.prepare("INSERT INTO storagegroup (groupname, hostname, dirname) "435 "VALUES (:NAME, :HOSTNAME, :DIRNAME);");436 query.bindValue(":NAME", m_group.utf8());437 query.bindValue(":DIRNAME", name.utf8());438 query.bindValue(":HOSTNAME", gContext->GetHostName());439 if (!query.exec())440 MythContext::DBError("StorageGroupEditor::open", query);441 else442 lastValue = name;443 }444 };445 446 void StorageGroupEditor::doDelete(void)447 {448 QString name = listbox->getValue();449 if (name == "__CREATE_NEW_STORAGE_DIRECTORY__")450 return;451 452 QString message =453 tr("Remove '%1'\nDirectory From Storage Group?").arg(name);454 455 DialogCode value = MythPopupBox::Show2ButtonPopup(456 gContext->GetMainWindow(), "", message,457 tr("Yes, remove directory"),458 tr("No, Don't remove directory"),459 kDialogCodeButton1);460 461 if (kDialogCodeButton0 == value)462 {463 MSqlQuery query(MSqlQuery::InitCon());464 query.prepare("DELETE FROM storagegroup "465 "WHERE groupname = :NAME "466 "AND dirname = :DIRNAME "467 "AND hostname = :HOSTNAME;");468 query.bindValue(":NAME", m_group.utf8());469 query.bindValue(":DIRNAME", name.utf8());470 query.bindValue(":HOSTNAME", gContext->GetHostName());471 if (!query.exec())472 MythContext::DBError("StorageGroupEditor::doDelete", query);473 474 int lastIndex = listbox->getValueIndex(name);475 lastValue = "";476 load();477 listbox->setValue(lastIndex);478 }479 480 listbox->setFocus();481 }482 483 void StorageGroupEditor::load(void) {484 listbox->clearSelections();485 486 MSqlQuery query(MSqlQuery::InitCon());487 query.prepare("SELECT dirname, id FROM storagegroup "488 "WHERE groupname = :NAME AND hostname = :HOSTNAME "489 "ORDER BY id;");490 query.bindValue(":NAME", m_group.utf8());491 query.bindValue(":HOSTNAME", gContext->GetHostName());492 if (!query.exec() || !query.isActive())493 MythContext::DBError("StorageGroupEditor::doDelete", query);494 else495 {496 bool first = true;497 while (query.next())498 {499 if (first)500 {501 lastValue = query.value(0).toString();502 first = false;503 }504 listbox->addSelection(query.value(0).toString());505 }506 }507 508 listbox->addSelection(tr("(Add New Directory)"),509 "__CREATE_NEW_STORAGE_DIRECTORY__");510 511 listbox->setValue(lastValue);512 }513 514 DialogCode StorageGroupEditor::exec(void)515 {516 while (ConfigurationDialog::exec() == kDialogCodeAccepted)517 open(listbox->getValue());518 519 return kDialogCodeRejected;520 }521 522 MythDialog* StorageGroupEditor::dialogWidget(MythMainWindow* parent,523 const char* widgetName)524 {525 dialog = ConfigurationDialog::dialogWidget(parent, widgetName);526 connect(dialog, SIGNAL(menuButtonPressed()), this, SLOT(doDelete()));527 connect(dialog, SIGNAL(deleteButtonPressed()), this, SLOT(doDelete()));528 return dialog;529 }530 531 /****************************************************************************/532 533 StorageGroupListEditor::StorageGroupListEditor(void) :534 listbox(new ListBoxSetting(this)), lastValue("")535 {536 if (gContext->GetSetting("MasterServerIP","master") ==537 gContext->GetSetting("BackendServerIP","me"))538 listbox->setLabel(539 tr("Storage Groups (directories for new recordings)"));540 else541 listbox->setLabel(542 tr("Local Storage Groups (directories for new recordings)"));543 544 addChild(listbox);545 }546 547 void StorageGroupListEditor::open(QString name)548 {549 lastValue = name;550 551 if (name.left(28) == "__CREATE_NEW_STORAGE_GROUP__")552 {553 if (name.length() > 28)554 {555 name = name.mid(28);556 }557 else558 {559 name = "";560 SGPopupResult result = StorageGroupPopup::showPopup(561 gContext->GetMainWindow(),562 tr("Create New Storage Group"),563 tr("Enter group name or press SELECT to enter text via the "564 "On Screen Keyboard"), name);565 if (result == SGPopup_CANCEL)566 return;567 }568 }569 570 if (!name.isEmpty())571 {572 StorageGroupEditor sgEditor(name);573 sgEditor.exec();574 }575 };576 577 void StorageGroupListEditor::doDelete(void)578 {579 QString name = listbox->getValue();580 if (name.left(28) == "__CREATE_NEW_STORAGE_GROUP__")581 return;582 583 if ((gContext->GetSetting("MasterServerIP","master") ==584 gContext->GetSetting("BackendServerIP","me")) &&585 (name == "Default"))586 return;587 588 QString dispGroup = name;589 if (name == "Default")590 dispGroup = QObject::tr("Default");591 else if (StorageGroup::kSpecialGroups.contains(name))592 dispGroup = QObject::tr(name);593 594 QString message = tr("Delete '%1' Storage Group?").arg(dispGroup);595 596 DialogCode value = MythPopupBox::Show2ButtonPopup(597 gContext->GetMainWindow(),598 "", message,599 tr("Yes, delete group"),600 tr("No, Don't delete group"), kDialogCodeButton1);601 602 if (kDialogCodeButton0 == value)603 {604 MSqlQuery query(MSqlQuery::InitCon());605 query.prepare("DELETE FROM storagegroup "606 "WHERE groupname = :NAME AND hostname = :HOSTNAME;");607 query.bindValue(":NAME", name.utf8());608 query.bindValue(":HOSTNAME", gContext->GetHostName());609 if (!query.exec())610 MythContext::DBError("StorageGroupListEditor::doDelete", query);611 612 int lastIndex = listbox->getValueIndex(name);613 lastValue = "";614 load();615 listbox->setValue(lastIndex);616 }617 618 listbox->setFocus();619 }620 621 void StorageGroupListEditor::load(void)622 {623 QStringList names;624 QStringList masterNames;625 bool createAddDefaultButton = false;626 bool createAddSpecialGroupButton[StorageGroup::kSpecialGroups.size()];627 bool isMaster = (gContext->GetSetting("MasterServerIP","master") ==628 gContext->GetSetting("BackendServerIP","me"));629 630 MSqlQuery query(MSqlQuery::InitCon());631 query.prepare("SELECT distinct groupname "632 "FROM storagegroup "633 "WHERE hostname = :HOSTNAME "634 "ORDER BY groupname;");635 query.bindValue(":HOSTNAME", gContext->GetHostName());636 if (!query.exec())637 MythContext::DBError("StorageGroup::load getting local group names",638 query);639 else640 {641 while (query.next())642 names << QString::fromUtf8(query.value(0).toString());643 }644 645 query.prepare("SELECT distinct groupname "646 "FROM storagegroup "647 "ORDER BY groupname;");648 if (!query.exec())649 MythContext::DBError("StorageGroup::load getting all group names",650 query);651 else652 {653 while (query.next())654 masterNames << QString::fromUtf8(query.value(0).toString());655 }656 657 listbox->clearSelections();658 659 if (isMaster || names.contains("Default"))660 {661 listbox->addSelection(QObject::tr("Default"), "Default");662 lastValue = "Default";663 }664 else665 createAddDefaultButton = true;666 667 unsigned int curGroup = 0;668 QString groupName;669 while (curGroup < StorageGroup::kSpecialGroups.size())670 {671 groupName = StorageGroup::kSpecialGroups[curGroup];672 if (names.contains(groupName))673 {674 listbox->addSelection(QObject::tr(groupName), groupName);675 createAddSpecialGroupButton[curGroup] = false;676 }677 else678 createAddSpecialGroupButton[curGroup] = true;679 curGroup++;680 }681 682 unsigned int curName = 0;683 while (curName < names.size())684 {685 if ((names[curName] != "Default") &&686 (!StorageGroup::kSpecialGroups.contains(names[curName])))687 listbox->addSelection(names[curName]);688 curName++;689 }690 691 if (createAddDefaultButton)692 {693 listbox->addSelection(tr("(Create %1 group)").arg("Default"),694 "Default");695 lastValue = "Default";696 }697 698 curGroup = 0;699 while (curGroup < StorageGroup::kSpecialGroups.size())700 {701 groupName = StorageGroup::kSpecialGroups[curGroup];702 if (createAddSpecialGroupButton[curGroup])703 listbox->addSelection(tr("(Create %1 group)").arg(groupName),704 QString("__CREATE_NEW_STORAGE_GROUP__%1").arg(groupName));705 curGroup++;706 }707 708 if (isMaster)709 listbox->addSelection(tr("(Create %1 group)").arg("new"),710 "__CREATE_NEW_STORAGE_GROUP__");711 else712 {713 curName = 0;714 while (curName < masterNames.size())715 {716 if ((masterNames[curName] != "Default") &&717 (!StorageGroup::kSpecialGroups.contains(masterNames[curName])) &&718 (!names.contains(masterNames[curName])))719 listbox->addSelection(tr("(Create %1 group)")720 .arg(masterNames[curName]),721 "__CREATE_NEW_STORAGE_GROUP__" + masterNames[curName]);722 curName++;723 }724 }725 726 listbox->setValue(lastValue);727 }728 729 DialogCode StorageGroupListEditor::exec(void)730 {731 while (ConfigurationDialog::exec() == kDialogCodeAccepted)732 open(listbox->getValue());733 734 return kDialogCodeRejected;735 }736 737 MythDialog* StorageGroupListEditor::dialogWidget(MythMainWindow* parent,738 const char* widgetName)739 {740 dialog = ConfigurationDialog::dialogWidget(parent, widgetName);741 connect(dialog, SIGNAL(menuButtonPressed()), this, SLOT(doDelete()));742 connect(dialog, SIGNAL(deleteButtonPressed()), this, SLOT(doDelete()));743 return dialog;744 }745 746 /* vim: set expandtab tabstop=4 shiftwidth=4: */ -
libs/libmyth/libmyth.pro
23 23 HEADERS += screensaver.h screensaver-null.h settings.h themeinfo.h 24 24 HEADERS += uilistbtntype.h uitypes.h util.h util-x11.h 25 25 HEADERS += volumebase.h volumecontrol.h virtualkeyboard.h visual.h xmlparse.h 26 HEADERS += mythhdd.h mythcdrom.h 26 HEADERS += mythhdd.h mythcdrom.h storagegroup.h 27 27 HEADERS += compat.h 28 28 29 29 SOURCES += audiooutput.cpp audiooutputbase.cpp audiooutputnull.cpp … … 39 39 SOURCES += screensaver.cpp screensaver-null.cpp settings.cpp themeinfo.cpp 40 40 SOURCES += uilistbtntype.cpp uitypes.cpp util.cpp util-x11.cpp 41 41 SOURCES += volumebase.cpp volumecontrol.cpp virtualkeyboard.cpp xmlparse.cpp 42 SOURCES += mythhdd.cpp mythcdrom.cpp 42 SOURCES += mythhdd.cpp mythcdrom.cpp storagegroup.cpp 43 43 44 44 INCLUDEPATH += ../libmythsamplerate ../libmythsoundtouch ../.. ../ ./ 45 45 DEPENDPATH += ../libmythsamplerate ../libmythsoundtouch ../ ../libmythui … … 63 63 inc.files += visual.h volumebase.h output.h langsettings.h qmdcodec.h 64 64 inc.files += exitcodes.h mythconfig.h mythconfig.mak virtualkeyboard.h 65 65 inc.files += mythevent.h mythobservable.h mythsocket.h 66 inc.files += mythexp.h mythpluginapi.h compat.h66 inc.files += mythexp.h mythpluginapi.h storagegroup.h compat.h 67 67 inc.files += mythstorage.h mythconfigdialogs.h mythconfiggroups.h 68 68 69 69 # Allow both #include <blah.h> and #include <libmyth/blah.h> -
libs/libmyth/storagegroup.h
1 #ifndef _STORAGEGROUP_H 2 #define _STORAGEGROUP_H 3 4 #include <qstringlist.h> 5 #include <qdeepcopy.h> 6 7 #include "libmyth/settings.h" 8 #include "libmyth/mythwidgets.h" 9 10 class MPUBLIC StorageGroup: public ConfigurationWizard 11 { 12 public: 13 StorageGroup(const QString group = "", const QString hostname = ""); 14 15 void Init(const QString group = "Default", 16 const QString hostname = ""); 17 18 QString getName(void) const 19 { return QDeepCopy<QString>(m_groupname); } 20 21 QStringList GetDirList(void) const 22 { return QDeepCopy<QStringList>(m_dirlist); } 23 24 QString FindRecordingFile(QString filename); 25 QString FindRecordingDir(QString filename); 26 27 QString FindNextDirMostFree(void); 28 29 static void CheckAllStorageGroupDirs(void); 30 31 static const char *kDefaultStorageDir; 32 static const QStringList kSpecialGroups; 33 34 static QStringList getRecordingsGroups(void); 35 36 private: 37 QString m_groupname; 38 QString m_hostname; 39 QStringList m_dirlist; 40 }; 41 42 class MPUBLIC StorageGroupEditor : 43 public QObject, public ConfigurationDialog 44 { 45 Q_OBJECT 46 public: 47 StorageGroupEditor(QString group); 48 virtual DialogCode exec(void); 49 virtual void load(void); 50 virtual void save(void) { }; 51 virtual void save(QString) { }; 52 virtual MythDialog* dialogWidget(MythMainWindow* parent, 53 const char* widgetname=0); 54 55 protected slots: 56 void open(QString name); 57 void doDelete(void); 58 59 protected: 60 QString m_group; 61 ListBoxSetting *listbox; 62 QString lastValue; 63 }; 64 65 class MPUBLIC StorageGroupListEditor : 66 public QObject, public ConfigurationDialog 67 { 68 Q_OBJECT 69 public: 70 StorageGroupListEditor(void); 71 virtual DialogCode exec(void); 72 virtual void load(void); 73 virtual void save(void) { }; 74 virtual void save(QString) { }; 75 virtual MythDialog* dialogWidget(MythMainWindow* parent, 76 const char* widgetname=0); 77 78 protected slots: 79 void open(QString name); 80 void doDelete(void); 81 82 protected: 83 ListBoxSetting *listbox; 84 QString lastValue; 85 }; 86 87 #endif 88 89 /* vim: set expandtab tabstop=4 shiftwidth=4: */ -
libs/libmyth/storagegroup.cpp
1 #include <qdir.h> 2 #include <qfile.h> 3 #include <qregexp.h> 4 5 #include "storagegroup.h" 6 #include "libmyth/mythcontext.h" 7 #include "libmyth/mythdbcon.h" 8 #include "libmyth/util.h" 9 10 #define LOC QString("SG(%1): ").arg(m_groupname) 11 #define LOC_WARN QString("SG(%1) Warning: ").arg(m_groupname) 12 #define LOC_ERR QString("SG(%1) Error: ").arg(m_groupname) 13 14 const char *StorageGroup::kDefaultStorageDir = "/mnt/store"; 15 16 const QStringList StorageGroup::kSpecialGroups = QStringList() 17 << "LiveTV" 18 // << "Thumbnails" 19 // << "DB Backups" 20 ; 21 22 /****************************************************************************/ 23 24 /** \brief StorageGroup constructor. 25 * \param group storage group to search, blank will search all groups. 26 * \param hostname hostname where to search, blank will search all hosts' 27 * directories, but only in local directory structure. 28 * This is parameter is ignored if group is an empty string. 29 */ 30 StorageGroup::StorageGroup(const QString group, const QString hostname) : 31 m_groupname(QDeepCopy<QString>(group)), 32 m_hostname(QDeepCopy<QString>(hostname)) 33 { 34 m_dirlist.clear(); 35 36 Init(m_groupname, m_hostname); 37 } 38 39 void StorageGroup::Init(const QString group, const QString hostname) 40 { 41 QString dirname; 42 MSqlQuery query(MSqlQuery::InitCon()); 43 44 m_groupname = QDeepCopy<QString>(group); 45 m_hostname = QDeepCopy<QString>(hostname); 46 m_dirlist.clear(); 47 48 QString sql = "SELECT DISTINCT dirname " 49 "FROM storagegroup "; 50 51 if (!m_groupname.isEmpty()) 52 { 53 sql.append("WHERE groupname = :GROUP"); 54 if (!m_hostname.isEmpty()) 55 sql.append(" AND hostname = :HOSTNAME"); 56 } 57 58 query.prepare(sql); 59 query.bindValue(":GROUP", m_groupname); 60 query.bindValue(":HOSTNAME", m_hostname); 61 62 if (!query.exec() || !query.isActive()) 63 MythContext::DBError("StorageGroup::StorageGroup()", query); 64 else if (!query.next()) 65 { 66 if (group != "Default") 67 { 68 VERBOSE(VB_FILE, LOC + 69 QString("Unable to find storage group '%1', trying " 70 "'Default' group!").arg(m_groupname)); 71 Init("Default", m_hostname); 72 return; 73 } 74 else if (!m_hostname.isEmpty()) 75 { 76 VERBOSE(VB_FILE, LOC + 77 QString("Unable to find any directories for the local " 78 "Default storage group, trying directories in all " 79 "Default groups!").arg(m_groupname)); 80 Init("Default", ""); 81 return; 82 } 83 } 84 else 85 { 86 do 87 { 88 dirname = query.value(0).toString(); 89 dirname.replace(QRegExp("^\\s*"), ""); 90 dirname.replace(QRegExp("\\s*$"), ""); 91 if (dirname.right(1) == "/") 92 dirname.remove(dirname.length() - 1, 1); 93 m_dirlist << QDeepCopy<QString>(dirname); 94 } 95 while (query.next()); 96 } 97 98 if (!m_dirlist.size()) 99 { 100 QString msg = "Directory value for Default Storage Group is empty. "; 101 QString tmpDir = gContext->GetSetting("RecordFilePrefix"); 102 if (tmpDir != "") 103 { 104 msg += QString("Using old 'RecordFilePrefix' value of '%1'") 105 .arg(tmpDir); 106 } 107 else 108 { 109 tmpDir = kDefaultStorageDir; 110 msg += QString("Using hardcoded default value of '%1'") 111 .arg(kDefaultStorageDir); 112 } 113 VERBOSE(VB_IMPORTANT, LOC_ERR + msg); 114 m_dirlist << QDeepCopy<QString>(tmpDir); 115 } 116 } 117 118 QString StorageGroup::FindRecordingFile(QString filename) 119 { 120 VERBOSE(VB_FILE, LOC + QString("FindRecordingFile: Searching for '%1'") 121 .arg(filename)); 122 123 QString recDir = FindRecordingDir(filename); 124 QString result = ""; 125 126 if (!recDir.isEmpty()) 127 { 128 result = recDir + "/" + filename; 129 VERBOSE(VB_FILE, LOC + QString("FindRecordingFile: Found '%1'") 130 .arg(result)); 131 } 132 else 133 { 134 VERBOSE(VB_FILE, LOC_ERR + 135 QString("FindRecordingFile: Unable to find '%1'!") 136 .arg(filename)); 137 } 138 139 return result; 140 } 141 142 QString StorageGroup::FindRecordingDir(QString filename) 143 { 144 QString result = ""; 145 QFile checkFile(""); 146 147 unsigned int curDir = 0; 148 while (curDir < m_dirlist.size()) 149 { 150 QString testFile = m_dirlist[curDir] + "/" + filename; 151 VERBOSE(VB_FILE, LOC + QString("FindRecordingDir: Checking '%1'") 152 .arg(m_dirlist[curDir])); 153 checkFile.setName(testFile); 154 if (checkFile.exists()) 155 return QDeepCopy<QString>(m_dirlist[curDir]); 156 157 curDir++; 158 } 159 160 if (m_groupname.isEmpty()) 161 { 162 // Not found in any dir, so try RecordFilePrefix if it exists 163 QString tmpFile = 164 gContext->GetSetting("RecordFilePrefix") + "/" + filename; 165 checkFile.setName(tmpFile); 166 if (checkFile.exists()) 167 result = tmpFile; 168 } 169 else if (m_groupname != "Default") 170 { 171 // Not found in current group so try Default 172 StorageGroup sgroup("Default"); 173 QString tmpFile = sgroup.FindRecordingDir(filename); 174 result = (tmpFile.isEmpty()) ? result : tmpFile; 175 } 176 else 177 { 178 // Not found in Default so try any dir 179 StorageGroup sgroup; 180 QString tmpFile = sgroup.FindRecordingDir(filename); 181 result = (tmpFile.isEmpty()) ? result : tmpFile; 182 } 183 184 return QDeepCopy<QString>(result); 185 } 186 187 QString StorageGroup::FindNextDirMostFree(void) 188 { 189 QString nextDir = kDefaultStorageDir; 190 long long nextDirFree = 0; 191 long long thisDirTotal; 192 long long thisDirUsed; 193 long long thisDirFree; 194 195 VERBOSE(VB_FILE, LOC + QString("FindNextDirMostFree: Starting'")); 196 197 if (m_dirlist.size()) 198 nextDir = m_dirlist[0]; 199 200 QDir checkDir(""); 201 unsigned int curDir = 0; 202 while (curDir < m_dirlist.size()) 203 { 204 checkDir.setPath(m_dirlist[curDir]); 205 if (!checkDir.exists()) 206 { 207 VERBOSE(VB_IMPORTANT, LOC_ERR + 208 QString("FindNextDirMostFree: '%1' does not exist!") 209 .arg(nextDir)); 210 curDir++; 211 continue; 212 } 213 214 thisDirFree = getDiskSpace(m_dirlist[curDir], thisDirTotal, 215 thisDirUsed); 216 VERBOSE(VB_FILE, LOC + 217 QString("FindNextDirMostFree: '%1' has %2 KiB free") 218 .arg(m_dirlist[curDir]) 219 .arg(longLongToString(thisDirFree))); 220 221 if (thisDirFree > nextDirFree) 222 { 223 nextDir = m_dirlist[curDir]; 224 nextDirFree = thisDirFree; 225 } 226 curDir++; 227 } 228 229 VERBOSE(VB_FILE, LOC + QString("FindNextDirMostFree: Using '%1'") 230 .arg(nextDir)); 231 232 return QDeepCopy<QString>(nextDir); 233 } 234 235 void StorageGroup::CheckAllStorageGroupDirs(void) 236 { 237 QString m_groupname; 238 QString dirname; 239 MSqlQuery query(MSqlQuery::InitCon()); 240 241 query.prepare("SELECT groupname, dirname " 242 "FROM storagegroup " 243 "WHERE hostname = :HOSTNAME;"); 244 query.bindValue(":HOSTNAME", gContext->GetHostName()); 245 if (!query.exec() || !query.isActive()) 246 { 247 MythContext::DBError("StorageGroup::CheckAllStorageGroupDirs()", query); 248 return; 249 } 250 251 VERBOSE(VB_FILE, LOC + "CheckAllStorageGroupDirs(): Checking All Storage " 252 "Group directories"); 253 254 QFile testFile(""); 255 QDir testDir(""); 256 while (query.next()) 257 { 258 m_groupname = query.value(0).toString(); 259 dirname = query.value(1).toString(); 260 261 dirname.replace(QRegExp("^\\s*"), ""); 262 dirname.replace(QRegExp("\\s*$"), ""); 263 264 VERBOSE(VB_FILE, LOC + 265 QString("Checking directory '%1' in group '%2'.") 266 .arg(dirname).arg(m_groupname)); 267 268 testDir.setPath(dirname); 269 if (!testDir.exists()) 270 { 271 VERBOSE(VB_FILE, LOC_WARN + 272 QString("Group '%1' references directory '%2' but this " 273 "directory does not exist. This directory " 274 "will not be used on this server.") 275 .arg(m_groupname).arg(dirname)); 276 } 277 else 278 { 279 testFile.setName(dirname + "/.test"); 280 if (testFile.open(IO_WriteOnly)) 281 testFile.remove(); 282 else 283 VERBOSE(VB_IMPORTANT, 284 LOC_ERR + 285 QString("Group '%1' wants to use directory '%2', but " 286 "this directory is not writeable.") 287 .arg(m_groupname).arg(dirname)); 288 } 289 } 290 } 291 292 QStringList StorageGroup::getRecordingsGroups(void) 293 { 294 QStringList groups; 295 296 MSqlQuery query(MSqlQuery::InitCon()); 297 298 QString sql = "SELECT DISTINCT groupname " 299 "FROM storagegroup " 300 "WHERE groupname NOT IN ("; 301 for (QStringList::const_iterator it = StorageGroup::kSpecialGroups.begin(); 302 it != StorageGroup::kSpecialGroups.end(); ++it) 303 sql.append(QString(" '%1',").arg(*it)); 304 sql = sql.left(sql.length() - 1); 305 sql.append(" );"); 306 307 query.prepare(sql); 308 if (query.exec() && query.isActive() && query.size() > 0) 309 while (query.next()) 310 groups += QString::fromUtf8(query.value(0).toString()); 311 312 groups.sort(); 313 314 return QDeepCopy<QStringList>(groups); 315 } 316 317 /****************************************************************************/ 318 typedef enum { 319 SGPopup_OK = 0, 320 SGPopup_CANCEL, 321 SGPopup_DELETE 322 } SGPopupResult; 323 324 class StorageGroupPopup 325 { 326 public: 327 static SGPopupResult showPopup(MythMainWindow *parent, QString title, 328 QString message, QString& text); 329 }; 330 331 SGPopupResult StorageGroupPopup::showPopup(MythMainWindow *parent, 332 QString title, QString message, QString& text) 333 { 334 MythPopupBox *popup = new MythPopupBox(parent, title); 335 popup->addLabel(message); 336 337 MythLineEdit *textEdit = new MythLineEdit(popup, "chooseEdit"); 338 textEdit->setText(text); 339 popup->addWidget(textEdit); 340 341 popup->addButton(QObject::tr("OK"), popup, SLOT(accept())); 342 popup->addButton(QObject::tr("Cancel"), popup, SLOT(reject())); 343 344 textEdit->setFocus(); 345 346 bool ok = (MythDialog::Accepted == popup->ExecPopup()); 347 if (ok) 348 text = QDeepCopy<QString>(textEdit->text()); 349 350 popup->hide(); 351 popup->deleteLater(); 352 353 return (ok) ? SGPopup_OK : SGPopup_CANCEL; 354 } 355 356 /****************************************************************************/ 357 358 StorageGroupEditor::StorageGroupEditor(QString group) : 359 m_group(group), listbox(new ListBoxSetting(this)), lastValue("") 360 { 361 QString dispGroup = group; 362 363 if (group == "Default") 364 dispGroup = QObject::tr("Default"); 365 else if (StorageGroup::kSpecialGroups.contains(group)) 366 dispGroup = QObject::tr(group); 367 368 if (gContext->GetSetting("MasterServerIP","master") == 369 gContext->GetSetting("BackendServerIP","me")) 370 { 371 listbox->setLabel(tr("'%1' Storage Group Directories").arg(dispGroup)); 372 } 373 else 374 { 375 listbox->setLabel(tr("Local '%1' Storage Group Directories") 376 .arg(dispGroup)); 377 } 378 379 addChild(listbox); 380 } 381 382 void StorageGroupEditor::open(QString name) 383 { 384 lastValue = name; 385 386 if (name == "__CREATE_NEW_STORAGE_DIRECTORY__") 387 { 388 name = ""; 389 SGPopupResult result = StorageGroupPopup::showPopup( 390 gContext->GetMainWindow(), 391 tr("Add Storage Group Directory"), 392 tr("Enter directory name or press SELECT to enter text via the " 393 "On Screen Keyboard"), name); 394 if (result == SGPopup_CANCEL) 395 return; 396 397 if (name.right(1) != "/") 398 name.append("/"); 399 400 MSqlQuery query(MSqlQuery::InitCon()); 401 query.prepare("INSERT INTO storagegroup (groupname, hostname, dirname) " 402 "VALUES (:NAME, :HOSTNAME, :DIRNAME);"); 403 query.bindValue(":NAME", m_group.utf8()); 404 query.bindValue(":DIRNAME", name.utf8()); 405 query.bindValue(":HOSTNAME", gContext->GetHostName()); 406 if (!query.exec()) 407 MythContext::DBError("StorageGroupEditor::open", query); 408 else 409 lastValue = name; 410 } else { 411 SGPopupResult result = StorageGroupPopup::showPopup( 412 gContext->GetMainWindow(), 413 tr("Edit Storage Group Directory"), 414 tr("Enter directory name or press SELECT to enter text via the " 415 "On Screen Keyboard"), name); 416 if (result == SGPopup_CANCEL) 417 return; 418 419 if (name.right(1) != "/") 420 name.append("/"); 421 422 MSqlQuery query(MSqlQuery::InitCon()); 423 424 query.prepare("DELETE FROM storagegroup " 425 "WHERE groupname = :NAME " 426 "AND dirname = :DIRNAME " 427 "AND hostname = :HOSTNAME;"); 428 query.bindValue(":NAME", m_group.utf8()); 429 query.bindValue(":DIRNAME", lastValue.utf8()); 430 query.bindValue(":HOSTNAME", gContext->GetHostName()); 431 if (!query.exec()) 432 MythContext::DBError("StorageGroupEditor::open", query); 433 434 query.prepare("INSERT INTO storagegroup (groupname, hostname, dirname) " 435 "VALUES (:NAME, :HOSTNAME, :DIRNAME);"); 436 query.bindValue(":NAME", m_group.utf8()); 437 query.bindValue(":DIRNAME", name.utf8()); 438 query.bindValue(":HOSTNAME", gContext->GetHostName()); 439 if (!query.exec()) 440 MythContext::DBError("StorageGroupEditor::open", query); 441 else 442 lastValue = name; 443 } 444 }; 445 446 void StorageGroupEditor::doDelete(void) 447 { 448 QString name = listbox->getValue(); 449 if (name == "__CREATE_NEW_STORAGE_DIRECTORY__") 450 return; 451 452 QString message = 453 tr("Remove '%1'\nDirectory From Storage Group?").arg(name); 454 455 DialogCode value = MythPopupBox::Show2ButtonPopup( 456 gContext->GetMainWindow(), "", message, 457 tr("Yes, remove directory"), 458 tr("No, Don't remove directory"), 459 kDialogCodeButton1); 460 461 if (kDialogCodeButton0 == value) 462 { 463 MSqlQuery query(MSqlQuery::InitCon()); 464 query.prepare("DELETE FROM storagegroup " 465 "WHERE groupname = :NAME " 466 "AND dirname = :DIRNAME " 467 "AND hostname = :HOSTNAME;"); 468 query.bindValue(":NAME", m_group.utf8()); 469 query.bindValue(":DIRNAME", name.utf8()); 470 query.bindValue(":HOSTNAME", gContext->GetHostName()); 471 if (!query.exec()) 472 MythContext::DBError("StorageGroupEditor::doDelete", query); 473 474 int lastIndex = listbox->getValueIndex(name); 475 lastValue = ""; 476 load(); 477 listbox->setValue(lastIndex); 478 } 479 480 listbox->setFocus(); 481 } 482 483 void StorageGroupEditor::load(void) { 484 listbox->clearSelections(); 485 486 MSqlQuery query(MSqlQuery::InitCon()); 487 query.prepare("SELECT dirname, id FROM storagegroup " 488 "WHERE groupname = :NAME AND hostname = :HOSTNAME " 489 "ORDER BY id;"); 490 query.bindValue(":NAME", m_group.utf8()); 491 query.bindValue(":HOSTNAME", gContext->GetHostName()); 492 if (!query.exec() || !query.isActive()) 493 MythContext::DBError("StorageGroupEditor::doDelete", query); 494 else 495 { 496 bool first = true; 497 while (query.next()) 498 { 499 if (first) 500 { 501 lastValue = query.value(0).toString(); 502 first = false; 503 } 504 listbox->addSelection(query.value(0).toString()); 505 } 506 } 507 508 listbox->addSelection(tr("(Add New Directory)"), 509 "__CREATE_NEW_STORAGE_DIRECTORY__"); 510 511 listbox->setValue(lastValue); 512 } 513 514 DialogCode StorageGroupEditor::exec(void) 515 { 516 while (ConfigurationDialog::exec() == kDialogCodeAccepted) 517 open(listbox->getValue()); 518 519 return kDialogCodeRejected; 520 } 521 522 MythDialog* StorageGroupEditor::dialogWidget(MythMainWindow* parent, 523 const char* widgetName) 524 { 525 dialog = ConfigurationDialog::dialogWidget(parent, widgetName); 526 connect(dialog, SIGNAL(menuButtonPressed()), this, SLOT(doDelete())); 527 connect(dialog, SIGNAL(deleteButtonPressed()), this, SLOT(doDelete())); 528 return dialog; 529 } 530 531 /****************************************************************************/ 532 533 StorageGroupListEditor::StorageGroupListEditor(void) : 534 listbox(new ListBoxSetting(this)), lastValue("") 535 { 536 if (gContext->GetSetting("MasterServerIP","master") == 537 gContext->GetSetting("BackendServerIP","me")) 538 listbox->setLabel( 539 tr("Storage Groups (directories for new recordings)")); 540 else 541 listbox->setLabel( 542 tr("Local Storage Groups (directories for new recordings)")); 543 544 addChild(listbox); 545 } 546 547 void StorageGroupListEditor::open(QString name) 548 { 549 lastValue = name; 550 551 if (name.left(28) == "__CREATE_NEW_STORAGE_GROUP__") 552 { 553 if (name.length() > 28) 554 { 555 name = name.mid(28); 556 } 557 else 558 { 559 name = ""; 560 SGPopupResult result = StorageGroupPopup::showPopup( 561 gContext->GetMainWindow(), 562 tr("Create New Storage Group"), 563 tr("Enter group name or press SELECT to enter text via the " 564 "On Screen Keyboard"), name); 565 if (result == SGPopup_CANCEL) 566 return; 567 } 568 } 569 570 if (!name.isEmpty()) 571 { 572 StorageGroupEditor sgEditor(name); 573 sgEditor.exec(); 574 } 575 }; 576 577 void StorageGroupListEditor::doDelete(void) 578 { 579 QString name = listbox->getValue(); 580 if (name.left(28) == "__CREATE_NEW_STORAGE_GROUP__") 581 return; 582 583 if ((gContext->GetSetting("MasterServerIP","master") == 584 gContext->GetSetting("BackendServerIP","me")) && 585 (name == "Default")) 586 return; 587 588 QString dispGroup = name; 589 if (name == "Default") 590 dispGroup = QObject::tr("Default"); 591 else if (StorageGroup::kSpecialGroups.contains(name)) 592 dispGroup = QObject::tr(name); 593 594 QString message = tr("Delete '%1' Storage Group?").arg(dispGroup); 595 596 DialogCode value = MythPopupBox::Show2ButtonPopup( 597 gContext->GetMainWindow(), 598 "", message, 599 tr("Yes, delete group"), 600 tr("No, Don't delete group"), kDialogCodeButton1); 601 602 if (kDialogCodeButton0 == value) 603 { 604 MSqlQuery query(MSqlQuery::InitCon()); 605 query.prepare("DELETE FROM storagegroup " 606 "WHERE groupname = :NAME AND hostname = :HOSTNAME;"); 607 query.bindValue(":NAME", name.utf8()); 608 query.bindValue(":HOSTNAME", gContext->GetHostName()); 609 if (!query.exec()) 610 MythContext::DBError("StorageGroupListEditor::doDelete", query); 611 612 int lastIndex = listbox->getValueIndex(name); 613 lastValue = ""; 614 load(); 615 listbox->setValue(lastIndex); 616 } 617 618 listbox->setFocus(); 619 } 620 621 void StorageGroupListEditor::load(void) 622 { 623 QStringList names; 624 QStringList masterNames; 625 bool createAddDefaultButton = false; 626 bool createAddSpecialGroupButton[StorageGroup::kSpecialGroups.size()]; 627 bool isMaster = (gContext->GetSetting("MasterServerIP","master") == 628 gContext->GetSetting("BackendServerIP","me")); 629 630 MSqlQuery query(MSqlQuery::InitCon()); 631 query.prepare("SELECT distinct groupname " 632 "FROM storagegroup " 633 "WHERE hostname = :HOSTNAME " 634 "ORDER BY groupname;"); 635 query.bindValue(":HOSTNAME", gContext->GetHostName()); 636 if (!query.exec()) 637 MythContext::DBError("StorageGroup::load getting local group names", 638 query); 639 else 640 { 641 while (query.next()) 642 names << QString::fromUtf8(query.value(0).toString()); 643 } 644 645 query.prepare("SELECT distinct groupname " 646 "FROM storagegroup " 647 "ORDER BY groupname;"); 648 if (!query.exec()) 649 MythContext::DBError("StorageGroup::load getting all group names", 650 query); 651 else 652 { 653 while (query.next()) 654 masterNames << QString::fromUtf8(query.value(0).toString()); 655 } 656 657 listbox->clearSelections(); 658 659 if (isMaster || names.contains("Default")) 660 { 661 listbox->addSelection(QObject::tr("Default"), "Default"); 662 lastValue = "Default"; 663 } 664 else 665 createAddDefaultButton = true; 666 667 unsigned int curGroup = 0; 668 QString groupName; 669 while (curGroup < StorageGroup::kSpecialGroups.size()) 670 { 671 groupName = StorageGroup::kSpecialGroups[curGroup]; 672 if (names.contains(groupName)) 673 { 674 listbox->addSelection(QObject::tr(groupName), groupName); 675 createAddSpecialGroupButton[curGroup] = false; 676 } 677 else 678 createAddSpecialGroupButton[curGroup] = true; 679 curGroup++; 680 } 681 682 unsigned int curName = 0; 683 while (curName < names.size()) 684 { 685 if ((names[curName] != "Default") && 686 (!StorageGroup::kSpecialGroups.contains(names[curName]))) 687 listbox->addSelection(names[curName]); 688 curName++; 689 } 690 691 if (createAddDefaultButton) 692 { 693 listbox->addSelection(tr("(Create %1 group)").arg("Default"), 694 "Default"); 695 lastValue = "Default"; 696 } 697 698 curGroup = 0; 699 while (curGroup < StorageGroup::kSpecialGroups.size()) 700 { 701 groupName = StorageGroup::kSpecialGroups[curGroup]; 702 if (createAddSpecialGroupButton[curGroup]) 703 listbox->addSelection(tr("(Create %1 group)").arg(groupName), 704 QString("__CREATE_NEW_STORAGE_GROUP__%1").arg(groupName)); 705 curGroup++; 706 } 707 708 if (isMaster) 709 listbox->addSelection(tr("(Create %1 group)").arg("new"), 710 "__CREATE_NEW_STORAGE_GROUP__"); 711 else 712 { 713 curName = 0; 714 while (curName < masterNames.size()) 715 { 716 if ((masterNames[curName] != "Default") && 717 (!StorageGroup::kSpecialGroups.contains(masterNames[curName])) && 718 (!names.contains(masterNames[curName]))) 719 listbox->addSelection(tr("(Create %1 group)") 720 .arg(masterNames[curName]), 721 "__CREATE_NEW_STORAGE_GROUP__" + masterNames[curName]); 722 curName++; 723 } 724 } 725 726 listbox->setValue(lastValue); 727 } 728 729 DialogCode StorageGroupListEditor::exec(void) 730 { 731 while (ConfigurationDialog::exec() == kDialogCodeAccepted) 732 open(listbox->getValue()); 733 734 return kDialogCodeRejected; 735 } 736 737 MythDialog* StorageGroupListEditor::dialogWidget(MythMainWindow* parent, 738 const char* widgetName) 739 { 740 dialog = ConfigurationDialog::dialogWidget(parent, widgetName); 741 connect(dialog, SIGNAL(menuButtonPressed()), this, SLOT(doDelete())); 742 connect(dialog, SIGNAL(deleteButtonPressed()), this, SLOT(doDelete())); 743 return dialog; 744 } 745 746 /* vim: set expandtab tabstop=4 shiftwidth=4: */ -
programs/mythbackend/autoexpire.cpp
31 31 #include "libmyth/util.h" 32 32 #include "libmythtv/remoteutil.h" 33 33 #include "libmythtv/remoteencoder.h" 34 #include " libmythtv/storagegroup.h"34 #include "storagegroup.h" 35 35 #include "encoderlink.h" 36 36 #include "backendutil.h" 37 37 #include "compat.h" -
programs/mythbackend/main.cpp
39 39 #include "libmythtv/programinfo.h" 40 40 #include "libmythtv/dbcheck.h" 41 41 #include "libmythtv/jobqueue.h" 42 #include " libmythtv/storagegroup.h"42 #include "storagegroup.h" 43 43 #include "libmythtv/previewgenerator.h" 44 44 45 45 #include "mediaserver.h" -
programs/mythbackend/scheduler.cpp
34 34 #include "libmyth/compat.h" 35 35 #include "libmythtv/programinfo.h" 36 36 #include "libmythtv/scheduledrecording.h" 37 #include " libmythtv/storagegroup.h"37 #include "storagegroup.h" 38 38 #include "libmythtv/cardutil.h" 39 39 40 40 #define LOC QString("Scheduler: ") -
programs/mythtv-setup/main.cpp
30 30 #include "libmythtv/videosource.h" 31 31 #include "libmythtv/channeleditor.h" 32 32 #include "libmythtv/remoteutil.h" 33 #include " libmythtv/storagegroup.h"33 #include "storagegroup.h" 34 34 #include "backendsettings.h" 35 35 #include "checksetup.h" 36 36