00001 #include <QDir>
00002 #include <QFile>
00003 #include <QRegExp>
00004 #include <QUrl>
00005 #include <QVector>
00006
00007 #include "storagegroupeditor.h"
00008 #include "mythcorecontext.h"
00009 #include "mythdb.h"
00010 #include "mythlogging.h"
00011 #include "mythmiscutil.h"
00012
00013 #define LOC QString("SGE(%1): ").arg(m_groupname)
00014
00015 typedef enum {
00016 SGPopup_OK = 0,
00017 SGPopup_CANCEL,
00018 SGPopup_DELETE
00019 } SGPopupResult;
00020
00021 class StorageGroupPopup
00022 {
00023 public:
00024 static SGPopupResult showPopup(MythMainWindow *parent, QString title,
00025 QString message, QString& text);
00026 };
00027
00028 SGPopupResult StorageGroupPopup::showPopup(MythMainWindow *parent,
00029 QString title, QString message, QString& text)
00030 {
00031 MythPopupBox *popup = new MythPopupBox(parent, title.toAscii().constData());
00032 popup->addLabel(message);
00033
00034 MythLineEdit *textEdit = new MythLineEdit(popup, "chooseEdit");
00035 textEdit->setText(text);
00036 popup->addWidget(textEdit);
00037
00038 popup->addButton(QObject::tr("OK"), popup, SLOT(accept()));
00039 popup->addButton(QObject::tr("Cancel"), popup, SLOT(reject()));
00040
00041 textEdit->setFocus();
00042
00043 bool ok = (MythDialog::Accepted == popup->ExecPopup());
00044 if (ok)
00045 {
00046 text = textEdit->text();
00047 text.detach();
00048 }
00049
00050 popup->hide();
00051 popup->deleteLater();
00052
00053 return (ok) ? SGPopup_OK : SGPopup_CANCEL;
00054 }
00055
00056
00057
00058 StorageGroupEditor::StorageGroupEditor(QString group) :
00059 m_group(group), listbox(new ListBoxSetting(this)), lastValue("")
00060 {
00061 QString dispGroup = group;
00062
00063 if (group == "Default")
00064 dispGroup = QObject::tr("Default");
00065 else if (StorageGroup::kSpecialGroups.contains(group))
00066 dispGroup = QObject::tr(group.toLatin1().constData());
00067
00068 if (gCoreContext->IsMasterHost())
00069 {
00070 listbox->setLabel(tr("'%1' Storage Group Directories").arg(dispGroup));
00071 }
00072 else
00073 {
00074 listbox->setLabel(tr("Local '%1' Storage Group Directories")
00075 .arg(dispGroup));
00076 }
00077
00078 addChild(listbox);
00079 }
00080
00081 void StorageGroupEditor::open(QString name)
00082 {
00083 lastValue = name;
00084
00085 if (name == "__CREATE_NEW_STORAGE_DIRECTORY__")
00086 {
00087 name = "";
00088 SGPopupResult result = StorageGroupPopup::showPopup(
00089 GetMythMainWindow(),
00090 tr("Add Storage Group Directory"),
00091 tr("Enter directory name or press SELECT to enter text via the "
00092 "On Screen Keyboard"), name);
00093 if (result == SGPopup_CANCEL)
00094 return;
00095
00096 if (name.isEmpty())
00097 return;
00098
00099 if (name.right(1) != "/")
00100 name.append("/");
00101
00102 MSqlQuery query(MSqlQuery::InitCon());
00103 query.prepare("INSERT INTO storagegroup (groupname, hostname, dirname) "
00104 "VALUES (:NAME, :HOSTNAME, :DIRNAME);");
00105 query.bindValue(":NAME", m_group);
00106 query.bindValue(":DIRNAME", name);
00107 query.bindValue(":HOSTNAME", gCoreContext->GetHostName());
00108 if (!query.exec())
00109 MythDB::DBError("StorageGroupEditor::open", query);
00110 else
00111 lastValue = name;
00112 } else {
00113 SGPopupResult result = StorageGroupPopup::showPopup(
00114 GetMythMainWindow(),
00115 tr("Edit Storage Group Directory"),
00116 tr("Enter directory name or press SELECT to enter text via the "
00117 "On Screen Keyboard"), name);
00118 if (result == SGPopup_CANCEL)
00119 return;
00120
00121 if (name.right(1) != "/")
00122 name.append("/");
00123
00124 MSqlQuery query(MSqlQuery::InitCon());
00125
00126 query.prepare("DELETE FROM storagegroup "
00127 "WHERE groupname = :NAME "
00128 "AND dirname = :DIRNAME "
00129 "AND hostname = :HOSTNAME;");
00130 query.bindValue(":NAME", m_group);
00131 query.bindValue(":DIRNAME", lastValue);
00132 query.bindValue(":HOSTNAME", gCoreContext->GetHostName());
00133 if (!query.exec())
00134 MythDB::DBError("StorageGroupEditor::open", query);
00135
00136 query.prepare("INSERT INTO storagegroup (groupname, hostname, dirname) "
00137 "VALUES (:NAME, :HOSTNAME, :DIRNAME);");
00138 query.bindValue(":NAME", m_group);
00139 query.bindValue(":DIRNAME", name);
00140 query.bindValue(":HOSTNAME", gCoreContext->GetHostName());
00141 if (!query.exec())
00142 MythDB::DBError("StorageGroupEditor::open", query);
00143 else
00144 lastValue = name;
00145 }
00146 };
00147
00148 void StorageGroupEditor::doDelete(void)
00149 {
00150 QString name = listbox->getValue();
00151 if (name == "__CREATE_NEW_STORAGE_DIRECTORY__")
00152 return;
00153
00154 QString message =
00155 tr("Remove '%1'\nDirectory From Storage Group?").arg(name);
00156
00157 DialogCode value = MythPopupBox::Show2ButtonPopup(
00158 GetMythMainWindow(), "", message,
00159 tr("Yes, remove directory"),
00160 tr("No, Don't remove directory"),
00161 kDialogCodeButton1);
00162
00163 if (kDialogCodeButton0 == value)
00164 {
00165 MSqlQuery query(MSqlQuery::InitCon());
00166 query.prepare("DELETE FROM storagegroup "
00167 "WHERE groupname = :NAME "
00168 "AND dirname = :DIRNAME "
00169 "AND hostname = :HOSTNAME;");
00170 query.bindValue(":NAME", m_group);
00171 query.bindValue(":DIRNAME", name);
00172 query.bindValue(":HOSTNAME", gCoreContext->GetHostName());
00173 if (!query.exec())
00174 MythDB::DBError("StorageGroupEditor::doDelete", query);
00175
00176 int lastIndex = listbox->getValueIndex(name);
00177 lastValue = "";
00178 Load();
00179 listbox->setValue(lastIndex);
00180 }
00181
00182 listbox->setFocus();
00183 }
00184
00185 void StorageGroupEditor::Load(void)
00186 {
00187 listbox->clearSelections();
00188
00189 MSqlQuery query(MSqlQuery::InitCon());
00190 query.prepare("SELECT dirname, id FROM storagegroup "
00191 "WHERE groupname = :NAME AND hostname = :HOSTNAME "
00192 "ORDER BY id;");
00193 query.bindValue(":NAME", m_group);
00194 query.bindValue(":HOSTNAME", gCoreContext->GetHostName());
00195 if (!query.exec() || !query.isActive())
00196 MythDB::DBError("StorageGroupEditor::doDelete", query);
00197 else
00198 {
00199 bool first = true;
00200 QString dirname;
00201 while (query.next())
00202 {
00203
00204
00205
00206 dirname = QString::fromUtf8(query.value(0)
00207 .toByteArray().constData());
00208 if (first)
00209 {
00210 lastValue = dirname;
00211 first = false;
00212 }
00213 listbox->addSelection(dirname);
00214 }
00215 }
00216
00217 listbox->addSelection(tr("(Add New Directory)"),
00218 "__CREATE_NEW_STORAGE_DIRECTORY__");
00219
00220 if (!lastValue.isEmpty())
00221 listbox->setValue(lastValue);
00222 }
00223
00224 DialogCode StorageGroupEditor::exec(void)
00225 {
00226 while (ConfigurationDialog::exec() == kDialogCodeAccepted)
00227 open(listbox->getValue());
00228
00229 return kDialogCodeRejected;
00230 }
00231
00232 MythDialog* StorageGroupEditor::dialogWidget(MythMainWindow* parent,
00233 const char* widgetName)
00234 {
00235 dialog = ConfigurationDialog::dialogWidget(parent, widgetName);
00236 connect(dialog, SIGNAL(menuButtonPressed()), this, SLOT(doDelete()));
00237 connect(dialog, SIGNAL(deleteButtonPressed()), this, SLOT(doDelete()));
00238 return dialog;
00239 }
00240
00241
00242
00243 StorageGroupListEditor::StorageGroupListEditor(void) :
00244 listbox(new ListBoxSetting(this)), lastValue("")
00245 {
00246 if (gCoreContext->IsMasterHost())
00247 listbox->setLabel(
00248 tr("Storage Groups (directories for new recordings)"));
00249 else
00250 listbox->setLabel(
00251 tr("Local Storage Groups (directories for new recordings)"));
00252
00253 addChild(listbox);
00254 }
00255
00256 void StorageGroupListEditor::open(QString name)
00257 {
00258 lastValue = name;
00259
00260 if (name.left(28) == "__CREATE_NEW_STORAGE_GROUP__")
00261 {
00262 if (name.length() > 28)
00263 {
00264 name = name.mid(28);
00265 }
00266 else
00267 {
00268 name = "";
00269 SGPopupResult result = StorageGroupPopup::showPopup(
00270 GetMythMainWindow(),
00271 tr("Create New Storage Group"),
00272 tr("Enter group name or press SELECT to enter text via the "
00273 "On Screen Keyboard"), name);
00274 if (result == SGPopup_CANCEL)
00275 return;
00276 }
00277 }
00278
00279 if (!name.isEmpty())
00280 {
00281 StorageGroupEditor sgEditor(name);
00282 sgEditor.exec();
00283 }
00284 };
00285
00286 void StorageGroupListEditor::doDelete(void)
00287 {
00288 QString name = listbox->getValue();
00289 if (name.left(28) == "__CREATE_NEW_STORAGE_GROUP__")
00290 return;
00291
00292 bool is_master_host = gCoreContext->IsMasterHost();
00293
00294 QString dispGroup = name;
00295 if (name == "Default")
00296 dispGroup = QObject::tr("Default");
00297 else if (StorageGroup::kSpecialGroups.contains(name))
00298 dispGroup = QObject::tr(name.toLatin1().constData());
00299
00300 QString message = tr("Delete '%1' Storage Group?").arg(dispGroup);
00301 if (is_master_host)
00302 {
00303 if (name == "Default")
00304 {
00305 message.append("\n" + tr("(from remote hosts)"));
00306 }
00307 else
00308 {
00309 message.append("\n" + tr("(from all hosts"));
00310 }
00311 }
00312
00313 DialogCode value = MythPopupBox::Show2ButtonPopup(
00314 GetMythMainWindow(),
00315 "", message,
00316 tr("Yes, delete group"),
00317 tr("No, Don't delete group"), kDialogCodeButton1);
00318
00319 if (kDialogCodeButton0 == value)
00320 {
00321 MSqlQuery query(MSqlQuery::InitCon());
00322 QString sql = "DELETE FROM storagegroup "
00323 "WHERE groupname = :NAME";
00324 if (is_master_host)
00325 {
00326
00327
00328
00329 if (name == "Default")
00330 sql.append(" AND hostname != :HOSTNAME");
00331 }
00332 else
00333 {
00334
00335
00336 sql.append(" AND hostname = :HOSTNAME");
00337 }
00338 sql.append(';');
00339 query.prepare(sql);
00340 query.bindValue(":NAME", name);
00341 if (!is_master_host || (name == "Default"))
00342 query.bindValue(":HOSTNAME", gCoreContext->GetHostName());
00343 if (!query.exec())
00344 MythDB::DBError("StorageGroupListEditor::doDelete", query);
00345
00346 int lastIndex = listbox->getValueIndex(name);
00347 lastValue = "";
00348 Load();
00349 listbox->setValue(lastIndex);
00350 }
00351
00352 listbox->setFocus();
00353 }
00354
00355 void StorageGroupListEditor::Load(void)
00356 {
00357 QStringList names;
00358 QStringList masterNames;
00359 bool createAddDefaultButton = false;
00360 QVector< bool > createAddSpecialGroupButton( StorageGroup::kSpecialGroups.size() );
00361 bool isMaster = gCoreContext->IsMasterHost();
00362
00363 MSqlQuery query(MSqlQuery::InitCon());
00364 query.prepare("SELECT distinct groupname "
00365 "FROM storagegroup "
00366 "WHERE hostname = :HOSTNAME "
00367 "ORDER BY groupname;");
00368 query.bindValue(":HOSTNAME", gCoreContext->GetHostName());
00369 if (!query.exec())
00370 MythDB::DBError("StorageGroup::Load getting local group names",
00371 query);
00372 else
00373 {
00374 while (query.next())
00375 names << query.value(0).toString();
00376 }
00377
00378 query.prepare("SELECT distinct groupname "
00379 "FROM storagegroup "
00380 "ORDER BY groupname;");
00381 if (!query.exec())
00382 MythDB::DBError("StorageGroup::Load getting all group names",
00383 query);
00384 else
00385 {
00386 while (query.next())
00387 masterNames << query.value(0).toString();
00388 }
00389
00390 listbox->clearSelections();
00391
00392 if (isMaster || names.contains("Default"))
00393 {
00394 listbox->addSelection(QObject::tr("Default"), "Default");
00395 lastValue = "Default";
00396 }
00397 else
00398 createAddDefaultButton = true;
00399
00400 int curGroup = 0;
00401 QString groupName;
00402 while (curGroup < StorageGroup::kSpecialGroups.size())
00403 {
00404 groupName = StorageGroup::kSpecialGroups[curGroup];
00405 if (names.contains(groupName))
00406 {
00407 listbox->addSelection(
00408 QObject::tr(groupName.toLatin1().constData()), groupName);
00409 createAddSpecialGroupButton[curGroup] = false;
00410 }
00411 else
00412 createAddSpecialGroupButton[curGroup] = true;
00413 curGroup++;
00414 }
00415
00416 int curName = 0;
00417 while (curName < names.size())
00418 {
00419 if ((names[curName] != "Default") &&
00420 (!StorageGroup::kSpecialGroups.contains(names[curName])))
00421 listbox->addSelection(names[curName]);
00422 curName++;
00423 }
00424
00425 if (createAddDefaultButton)
00426 {
00427 listbox->addSelection(tr("(Create %1 group)").arg("Default"),
00428 "Default");
00429 lastValue = "Default";
00430 }
00431
00432 curGroup = 0;
00433 while (curGroup < StorageGroup::kSpecialGroups.size())
00434 {
00435 groupName = StorageGroup::kSpecialGroups[curGroup];
00436 if (createAddSpecialGroupButton[curGroup])
00437 listbox->addSelection(tr("(Create %1 group)").arg(groupName),
00438 QString("__CREATE_NEW_STORAGE_GROUP__%1").arg(groupName));
00439 curGroup++;
00440 }
00441
00442 if (isMaster)
00443 listbox->addSelection(tr("(Create %1 group)").arg("new"),
00444 "__CREATE_NEW_STORAGE_GROUP__");
00445 else
00446 {
00447 curName = 0;
00448 while (curName < masterNames.size())
00449 {
00450 if ((masterNames[curName] != "Default") &&
00451 (!StorageGroup::kSpecialGroups.contains(masterNames[curName])) &&
00452 (!names.contains(masterNames[curName])))
00453 listbox->addSelection(tr("(Create %1 group)")
00454 .arg(masterNames[curName]),
00455 "__CREATE_NEW_STORAGE_GROUP__" + masterNames[curName]);
00456 curName++;
00457 }
00458 }
00459
00460 listbox->setValue(lastValue);
00461 }
00462
00463 DialogCode StorageGroupListEditor::exec(void)
00464 {
00465 while (ConfigurationDialog::exec() == kDialogCodeAccepted)
00466 open(listbox->getValue());
00467
00468 return kDialogCodeRejected;
00469 }
00470
00471 MythDialog* StorageGroupListEditor::dialogWidget(MythMainWindow* parent,
00472 const char* widgetName)
00473 {
00474 dialog = ConfigurationDialog::dialogWidget(parent, widgetName);
00475 connect(dialog, SIGNAL(menuButtonPressed()), this, SLOT(doDelete()));
00476 connect(dialog, SIGNAL(deleteButtonPressed()), this, SLOT(doDelete()));
00477 return dialog;
00478 }
00479
00480