"Fossies" - the Fresh Open Source Software Archive

Member "MP3Diags-unstable-1.5.01/src/SessionEditorDlgImpl.cpp" (3 Apr 2019, 17468 Bytes) of package /linux/privat/MP3Diags-unstable-1.5.01.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "SessionEditorDlgImpl.cpp" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 1.3.04_vs_1.5.01.

    1 /***************************************************************************
    2  *   MP3 Diags - diagnosis, repairs and tag editing for MP3 files          *
    3  *                                                                         *
    4  *   Copyright (C) 2009 by Marian Ciobanu                                  *
    5  *   ciobi@inbox.com                                                       *
    6  *                                                                         *
    7  *   This program is free software; you can redistribute it and/or modify  *
    8  *   it under the terms of the GNU General Public License version 2 as     *
    9  *   published by the Free Software Foundation.                            *
   10  *                                                                         *
   11  *   This program is distributed in the hope that it will be useful,       *
   12  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
   13  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
   14  *   GNU General Public License for more details.                          *
   15  *                                                                         *
   16  *   You should have received a copy of the GNU General Public License     *
   17  *   along with this program; if not, write to the                         *
   18  *   Free Software Foundation, Inc.,                                       *
   19  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
   20  ***************************************************************************/
   21 
   22 
   23 #include  <QMessageBox>
   24 #include  <QFileDialog>
   25 #include  <QTimer>
   26 #include  <QHeaderView>
   27 #include  <QSettings>
   28 #include  <QDesktopServices>
   29 #include  <QtGlobal>
   30 
   31 #include  "SessionEditorDlgImpl.h"
   32 
   33 #include  "CheckedDir.h"
   34 #include  "Helpers.h"
   35 #include  "Transformation.h"
   36 #include  "StoredSettings.h"
   37 #include  "OsFile.h"
   38 #include  "Translation.h"
   39 #include  "CommonData.h"
   40 #include  "Widgets.h"
   41 
   42 using namespace std;
   43 //using namespace pearl;
   44 
   45 
   46 void SessionEditorDlgImpl::commonConstr() // common code for both constructors
   47 {
   48     setupUi(this);
   49 
   50     m_pDirModel = new CheckedDirModel(this, CheckedDirModel::USER_CHECKABLE);
   51 
   52     m_pDirModel->setFilter(QDir::AllDirs | QDir::NoDotAndDotDot | QDir::Hidden | QDir::Drives);
   53     m_pDirModel->setSorting(QDir::IgnoreCase);
   54     m_pDirectoriesT->setModel(m_pDirModel);
   55     m_pDirectoriesT->expand(m_pDirModel->index("/"));
   56     m_pDirectoriesT->header()->hide();
   57     m_pDirectoriesT->header()->setStretchLastSection(false); m_pDirectoriesT->header()->setSectionResizeMode(0, QHeaderView::ResizeToContents);
   58 
   59     m_bOpenLastSession = true;
   60 
   61     { QAction* p (new QAction(this)); p->setShortcut(QKeySequence("F1")); connect(p, SIGNAL(triggered()), this, SLOT(onHelp())); addAction(p); }
   62 
   63     QPalette grayPalette (m_pBackupE->palette());
   64     grayPalette.setColor(QPalette::Base, grayPalette.color(QPalette::Disabled, QPalette::Window));
   65     m_pBackupE->setPalette(grayPalette);
   66     m_pFileNameE->setPalette(grayPalette);
   67 
   68     { // language
   69         int nCrt (0);
   70         const vector<string>& vstrTranslations (TranslatorHandler::getGlobalTranslator().getTranslations());
   71         string strTmpTranslation (m_strTranslation); // !!! needed because on_m_pTranslationCbB_currentIndexChanged() will get triggered and change m_strTranslation
   72         for (int i = 0; i < cSize(vstrTranslations); ++i)
   73         {
   74             m_pTranslationCbB->addItem(convStr(TranslatorHandler::getLanguageInfo(vstrTranslations[i])));
   75             if (strTmpTranslation == vstrTranslations[i])
   76             {
   77                 nCrt = i;
   78             }
   79         }
   80         m_pTranslationCbB->setCurrentIndex(nCrt);
   81         m_strTranslation = vstrTranslations[m_pTranslationCbB->currentIndex()];
   82     }
   83 }
   84 
   85 // returns the OS's "Documents" location
   86 static QString getDocDir() //ttt1 maybe move to Helpers
   87 {
   88 #if QT_VERSION >= 0x040400
   89     //QString qs = QDesktopServices::storageLocation(QDesktopServices::DocumentsLocation);
   90     QString qs = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation); //ttt9 make sure this is OK
   91     //ttt1 note that QStandardPaths should be used in Qt5: https://forum.qt.io/topic/28658/differences-qdesktopservices-vs-qstandardpaths
   92 #else
   93   #ifndef WIN32
   94     QString qs (QDir::homePath() + "/Documents"); // OK on openSUSE, not sure how standardized it is //ttt3 this is localized, so not OK; OTOH this branch only matters for Qt 4.3
   95   #else
   96     QSettings settings (QSettings::UserScope, "Microsoft", "Windows");
   97     settings.beginGroup("CurrentVersion/Explorer/Shell Folders");
   98     QString qs (fromNativeSeparators(settings.value("Personal").toString()));
   99   #endif
  100 #endif
  101     return qs;
  102 }
  103 
  104 
  105 // used for creating a new session;
  106 SessionEditorDlgImpl::SessionEditorDlgImpl(QWidget* pParent, const string& strDir, bool bFirstTime, const string& strTranslation) : QDialog(pParent, getDialogWndFlags()), Ui::SessionEditorDlg(), m_strDir(strDir), m_bNew(true), m_strTranslation(strTranslation)
  107 {
  108     commonConstr();
  109 
  110     bool bAutoFileName (false);
  111     {
  112         QString qs = getDocDir();
  113         if (QFileInfo(qs).isDir())
  114         {
  115             qs += "/MP3Diags";
  116             QString qsBranch ("-unstable");
  117             if (qsBranch.indexOf("QQQBRANCH_") == 0)
  118             {
  119                 qsBranch = "-unstable";
  120             }
  121             qs += qsBranch;
  122             qs += SESS_EXT;
  123             if (!QDir().exists(qs))
  124             {
  125                 m_pFileNameE->setText(toNativeSeparators(qs));
  126                 bAutoFileName = true;
  127             }
  128         }
  129     }
  130 
  131     //setWindowTitle("MP3 Diags - Create a new session or load an existing one");
  132     setWindowTitle();
  133     m_pDontCreateBackupRB->setChecked(true);
  134     m_pScanAtStartupCkB->setChecked(true);
  135 
  136     m_pFileNameE->setToolTip(bAutoFileName ?
  137         tr("This is the name of the \"settings file\"\n\n"
  138         "It is supposed to be a file that doesn't already exist. You don't need to set it up. MP3 Diags\n"
  139         "will store its settings in this file.\n\n"
  140         "The name was generated automatically. If you want to choose a different name, simply click on\n"
  141         "the button at the right to change it.", "this is a multiline tooltip") :
  142 
  143         tr("Here you need to specify the name of a \"settings file\"\n\n"
  144         "This is supposed to be a file that doesn't already exist. You don't need to set it up. MP3 Diags\n"
  145         "will store its settings in this file.\n\n"
  146         "To change it, simply click on the button at the right to choose the name of the settings file.", "this is a multiline tooltip"));
  147 
  148     if (!bFirstTime)
  149     {
  150         m_pOpenLastCkB->hide();
  151         m_pOpenSessionsB->hide();
  152     }
  153 }
  154 
  155 
  156 // used for editing an existing session;
  157 SessionEditorDlgImpl::SessionEditorDlgImpl(QWidget* pParent, const string& strSessFile) : QDialog(pParent, getDialogWndFlags()), Ui::SessionEditorDlg(), m_bNew(false)
  158 {
  159     SessionSettings st (strSessFile);
  160     {
  161         CommonData commonData(st, 0, 0, 0, 0, 0, 0, 0, 0, 0, false);
  162         st.loadMiscConfigSettings(&commonData, SessionSettings::DONT_INIT_GUI);
  163         m_strTranslation = commonData.m_strTranslation;
  164     }
  165 
  166     commonConstr();
  167 
  168     setWindowTitle();
  169     m_pFileNameE->setReadOnly(true);
  170     m_pFileNameE->setText(toNativeSeparators(convStr(strSessFile)));
  171     m_pFileNameB->hide();
  172     m_pOpenLastCkB->hide();
  173     //m_pLoadB->hide();
  174     m_pOpenSessionsB->hide();
  175 
  176     m_strSessFile = strSessFile;
  177     CB_ASSERT (!m_strSessFile.empty());
  178 
  179     //SessionSettings st (m_strSessFile);
  180     vector<string> vstrCheckedDirs, vstrUncheckedDirs;
  181     st.loadDirs(vstrCheckedDirs, vstrUncheckedDirs);
  182 
  183     m_pScanAtStartupCkB->setChecked(st.loadScanAtStartup());
  184 
  185     TransfConfig tc;
  186     st.loadTransfConfig(tc);
  187     if (TransfConfig::Options::PO_MOVE_OR_ERASE == tc.m_options.m_eProcOrigChange)
  188     {
  189         m_pCreateBackupRB->setChecked(true);
  190     }
  191     else
  192     {
  193         m_pDontCreateBackupRB->setChecked(true);
  194     }
  195     m_pBackupE->setText(toNativeSeparators(convStr(tc.getProcOrigDir())));
  196 
  197     m_pDirModel->setDirs(vstrCheckedDirs, vstrUncheckedDirs, m_pDirectoriesT);
  198 
  199     QTimer::singleShot(1, this, SLOT(onShow()));
  200 }
  201 
  202 
  203 SessionEditorDlgImpl::~SessionEditorDlgImpl()
  204 {
  205     delete m_pDirModel;
  206 }
  207 
  208 void SessionEditorDlgImpl::onShow()
  209 {
  210     m_pDirModel->expandNodes(m_pDirectoriesT);
  211 }
  212 
  213 
  214 void SessionEditorDlgImpl::setWindowTitle()
  215 {
  216     QDialog::setWindowTitle(m_bNew ? tr("MP3 Diags - Create new session") : tr("MP3 Diags - Edit session"));
  217 }
  218 
  219 // returns the name of an INI file for OK and an empty string for Cancel; returns "*" to just go to the sessions dialog;
  220 string SessionEditorDlgImpl::run()
  221 {
  222     GlobalSettings gs;
  223     int nWidth, nHeight;
  224     gs.loadSessionEdtSize(nWidth, nHeight);
  225     if (nWidth > 400 && nHeight > 400) { resize(nWidth, nHeight); }
  226 
  227     if (QDialog::Accepted != exec()) { return ""; }
  228 
  229     gs.saveSessionEdtSize(width(), height());
  230     m_strTranslation = TranslatorHandler::getGlobalTranslator().getTranslations()[m_pTranslationCbB->currentIndex()];
  231 
  232     return m_strSessFile;
  233 }
  234 
  235 
  236 void SessionEditorDlgImpl::on_m_pOkB_clicked()
  237 {
  238     m_bOpenLastSession = m_pOpenLastCkB->isChecked();
  239     vector<string> vstrCheckedDirs;
  240     vector<string> vstrUncheckedDirs;
  241 
  242     if (m_bNew)
  243     {
  244         QString qstrFile (fromNativeSeparators(m_pFileNameE->text()));
  245         if (!qstrFile.isEmpty() && !qstrFile.endsWith(SESS_EXT)) { qstrFile += SESS_EXT; m_pFileNameE->setText(toNativeSeparators(qstrFile)); }
  246         //m_strSessFile = convStr(QFileInfo(qstrFile).canonicalFilePath());
  247         m_strSessFile = convStr(qstrFile);
  248         if (m_strSessFile.empty())
  249         {
  250             showCritical(this, tr("Error"), tr("You need to specify the name of the settings file.\n\nThis is supposed to be a file that doesn't already exist. You don't need to set it up, but just to pick a name for it. MP3 Diags will store its settings in this file."));
  251             on_m_pFileNameB_clicked();
  252             return;
  253         }
  254     }
  255 
  256     vstrCheckedDirs = m_pDirModel->getCheckedDirs();
  257 
  258     if (vstrCheckedDirs.empty())
  259     {
  260         showCritical(this, tr("Error"), tr("You need to select at least a directory to be included in the session."));
  261         return;
  262     }
  263 
  264     if (m_pCreateBackupRB->isChecked())
  265     {
  266         QString s (fromNativeSeparators(m_pBackupE->text()));
  267         if (s.isEmpty() || !QFileInfo(s).isDir())
  268         {
  269             showCritical(this, tr("Error"), tr("If you want to create backups, you must select an existing directory to store them."));
  270             return;
  271         }
  272     }
  273 
  274     vstrUncheckedDirs = m_pDirModel->getUncheckedDirs();
  275 
  276     {
  277         if (m_bNew)
  278         {
  279             removeSession(m_strSessFile);
  280         }
  281 
  282         SessionSettings st (m_strSessFile);
  283 
  284         TransfConfig tc;
  285         if (!m_bNew)
  286         {
  287             st.loadTransfConfig(tc);
  288         }
  289 
  290         if (m_pDontCreateBackupRB->isChecked())
  291         {
  292             tc.m_options.m_eProcOrigChange = TransfConfig::Options::PO_ERASE; //ttt2 inconsistency with how config handles this; perhaps just hide the backup settings for existing sessions
  293         }
  294         else
  295         {
  296             tc.m_options.m_eProcOrigChange = TransfConfig::Options::PO_MOVE_OR_ERASE;
  297             tc.setProcOrigDir(fromNativeSeparators(convStr(m_pBackupE->text())));
  298         }
  299 
  300         st.saveTransfConfig(tc);
  301 
  302         st.saveDirs(vstrCheckedDirs, vstrUncheckedDirs);
  303 
  304         st.saveScanAtStartup(m_pScanAtStartupCkB->isChecked());
  305 
  306         {
  307             CommonData commonData(st, 0, 0, 0, 0, 0, 0, 0, 0, 0, false);
  308             st.loadMiscConfigSettings(&commonData, SessionSettings::DONT_INIT_GUI);
  309             commonData.m_strTranslation = m_strTranslation;
  310             st.saveMiscConfigSettings(&commonData);
  311         }
  312 
  313 
  314         if (!st.sync())
  315         {
  316             showCritical(this, tr("Error"), tr("Failed to write to file %1").arg(m_pFileNameE->text()));
  317             if (m_bNew)
  318             {
  319                 removeSession(m_strSessFile);
  320             }
  321             return;
  322         }
  323     }
  324 
  325     accept();
  326 }
  327 
  328 
  329 void SessionEditorDlgImpl::on_m_pCancelB_clicked()
  330 {
  331     reject();
  332 }
  333 
  334 void SessionEditorDlgImpl::on_m_pBackupB_clicked()
  335 {
  336     QString s (fromNativeSeparators(m_pBackupE->text()));
  337     if (s.isEmpty())
  338     {
  339         s = QDir::homePath();
  340     }
  341     QFileDialog dlg (this, tr("Select folder"), s, tr("All files (*)"));
  342     //dlg.setAcceptMode(QFileDialog::AcceptSave);
  343 
  344     dlg.setFileMode(QFileDialog::Directory);
  345     if (QDialog::Accepted != dlg.exec()) { return; }
  346 
  347     QStringList fileNames (dlg.selectedFiles());
  348     if (1 != fileNames.size()) { return; }
  349 
  350     s = fileNames.first();
  351     QFileInfo f (s);
  352     if (!f.isDir())
  353     {
  354         return;
  355     }
  356 
  357     m_pBackupE->setText(toNativeSeparators(s));
  358 
  359     m_pCreateBackupRB->setChecked(true);
  360 }
  361 
  362 
  363 void SessionEditorDlgImpl::on_m_pFileNameB_clicked()
  364 {
  365     QString s (fromNativeSeparators(m_pFileNameE->text()));
  366     if (s.isEmpty())
  367     {
  368         // Normally we'd like to not have this as a special case, and not use QFileDialog::getSaveFileName(). However, there seems to be a bug in QFileDialog that makes this "special case" necessary. (The issue is triggered when MP3Diags.ini already exists, so it gets here with an empty name.)
  369         // What we'd like to happen when using QFileDialog's constructor is for the the OS's "Documents" folder to be current and the file name to be empty. What happens is that the parent of the "documents" dir will get current and the name of the dir will be filled in as a file name.
  370         // The reason QFileDialog::getSaveFileName works while the constructor doesn't is that the former makes use of some private fields that the constructor cannot access (like QFileDialogPrivate::workingDirectory(dir);)
  371         // The reason to want to use the constructor is consistency across platforms, e.g. so we don't get native dialogs on Windows. Not sure what the best approach is.
  372         if (m_strDir.empty())
  373         {
  374             //s = QDir::homePath();
  375             s = getDocDir();
  376         }
  377         else
  378         {
  379             s = convStr(m_strDir);
  380         }
  381         s = QFileDialog::getSaveFileName(this, tr("Enter configuration file"), s, tr("MP3 Diags session files (*%1)").arg(SESS_EXT));
  382         if (s == "") { return; }
  383     }
  384     else
  385     {
  386         QFileDialog dlg (this, tr("Enter configuration file"), s, tr("MP3 Diags session files (*%1)").arg(SESS_EXT));
  387         dlg.setAcceptMode(QFileDialog::AcceptSave);
  388 
  389         //dlg.setFileMode(QFileDialog::Directory);
  390         //dlg.setFileMode(QFileDialog::AnyFile);
  391         if (QDialog::Accepted != dlg.exec()) { return; }
  392 
  393         QStringList fileNames (dlg.selectedFiles());
  394         if (1 != fileNames.size()) { return; }
  395 
  396         s = fileNames.first();
  397     }
  398 
  399     if (!s.endsWith(SESS_EXT)) { s += SESS_EXT; }
  400 
  401     m_pFileNameE->setText(toNativeSeparators(s));
  402 }
  403 
  404 
  405 /*static*/ string SessionEditorDlgImpl::getDataFileName(const string& strSessFile)
  406 {
  407     CB_ASSERT (endsWith(strSessFile, SESS_EXT));
  408     return strSessFile.substr(0, strSessFile.size() - SESS_EXT_LEN) + ".dat";
  409 }
  410 
  411 /*static*/ string SessionEditorDlgImpl::getLogFileName(const string& strSessFile)
  412 {
  413     CB_ASSERT (endsWith(strSessFile, SESS_EXT));
  414     return strSessFile.substr(0, strSessFile.size() - SESS_EXT_LEN) + ".transf_log.txt";
  415 }
  416 
  417 /*static*/ string SessionEditorDlgImpl::getBaseName(const string& strSessFile)
  418 {
  419     CB_ASSERT (endsWith(strSessFile, SESS_EXT));
  420     return strSessFile.substr(0, strSessFile.size() - SESS_EXT_LEN);
  421 }
  422 
  423 /*static*/ string SessionEditorDlgImpl::getTitleName(const string& strSessFile)
  424 {
  425     CB_ASSERT (endsWith(strSessFile, SESS_EXT));
  426 
  427     string::size_type n (strSessFile.rfind(getPathSep()));
  428     return strSessFile.substr(n + 1, strSessFile.size() - n - SESS_EXT_LEN - 1);
  429 }
  430 
  431 
  432  // removes all files associated with a session: .ini, .mp3ds, .log, .dat, _trace.txt, _step1.txt, _step2.txt
  433 /*static*/ void SessionEditorDlgImpl::removeSession(const string& strSessFile)
  434 {
  435     eraseFiles(strSessFile.substr(0, strSessFile.size() - SESS_EXT_LEN));
  436 }
  437 
  438 
  439 /*static*/ const char* const SessionEditorDlgImpl::SESS_EXT (".ini"); //ttt0 perhaps switch to .mp3ds (keep in mind that there may be many folders with .ini in them now); the point is to be able to double-click on a .mp3ds file
  440 /*static*/ int SessionEditorDlgImpl::SESS_EXT_LEN (strlen(SessionEditorDlgImpl::SESS_EXT));
  441 
  442 
  443 void SessionEditorDlgImpl::on_m_pOpenSessionsB_clicked()
  444 {
  445     m_strSessFile = "*";
  446     accept();
  447 }
  448 
  449 
  450 void SessionEditorDlgImpl::on_m_pTranslationCbB_currentIndexChanged(int)
  451 {
  452     const vector<string>& vstrTranslations (TranslatorHandler::getGlobalTranslator().getTranslations());
  453     m_strTranslation = vstrTranslations[m_pTranslationCbB->currentIndex()];
  454 
  455     TranslatorHandler::getGlobalTranslator().setTranslation(m_strTranslation);
  456     retranslateUi(this);
  457     setWindowTitle();
  458 }
  459 
  460 
  461 void SessionEditorDlgImpl::onHelp()
  462 {
  463     openHelp("110_first_run.html"); //ttt2 not quite right, since there are 2 "modes"
  464 }
  465 
  466 
  467 //================================================================================================================================================
  468 //================================================================================================================================================
  469 //================================================================================================================================================
  470 
  471 //ttt2 see about dereferenced symlinks
  472 
  473