MythTV  0.26-pre
storagegroupeditor.cpp
Go to the documentation of this file.
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             /* The storagegroup.dirname column uses utf8_bin collation, so Qt
00204              * uses QString::fromAscii() for toString(). Explicitly convert the
00205              * value using QString::fromUtf8() to prevent corruption. */
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             // From the master host, delete the group completely (versus just
00327             // local directory list) unless it's the Default group, then just
00328             // delete remote overrides of the Default group
00329             if (name == "Default")
00330                 sql.append(" AND hostname != :HOSTNAME");
00331         }
00332         else
00333         {
00334             // For non-master hosts, delete only the local override of the
00335             // group directory list
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 /* vim: set expandtab tabstop=4 shiftwidth=4: */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends