Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "overwritepopup.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// Tnz6 includes
Toshihiro Shimizu 890ddd
#include "tapp.h"
Toshihiro Shimizu 890ddd
#include "tsystem.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzQt includes
Toshihiro Shimizu 890ddd
#include "toonzqt/checkbox.h"
Toshihiro Shimizu 890ddd
#include "toonzqt/dvdialog.h"
Toshihiro Shimizu 890ddd
#include "toonzqt/lineedit.h"
Toshihiro Shimizu 890ddd
#include "toonzqt/gutil.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzLib includes
Toshihiro Shimizu 890ddd
#include "toonz/toonzscene.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzCore includes
Toshihiro Shimizu 890ddd
#include "tfilepath.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// Qt includes
Toshihiro Shimizu 890ddd
#include <qlabel></qlabel>
Toshihiro Shimizu 890ddd
#include <qpushbutton></qpushbutton>
Toshihiro Shimizu 890ddd
#include <qradiobutton></qradiobutton>
Toshihiro Shimizu 890ddd
#include <qbuttongroup></qbuttongroup>
Toshihiro Shimizu 890ddd
#include <qapplication></qapplication>
Toshihiro Shimizu 890ddd
#include <qmainwindow></qmainwindow>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//************************************************************************************
Toshihiro Shimizu 890ddd
//    OverwriteDialog::ExistsFunc  implementation
Toshihiro Shimizu 890ddd
//************************************************************************************
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
QString OverwriteDialog::DecodeFileExistsFunc::conflictString(
Shinya Kitaoka 120a6e
    const TFilePath &fp) const {
Shinya Kitaoka 120a6e
  return OverwriteDialog::tr(
Shinya Kitaoka 120a6e
             "File \"%1\" already exists.\nWhat do you want to do?")
Shinya Kitaoka 120a6e
      .arg(toQString(fp));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool OverwriteDialog::DecodeFileExistsFunc::operator()(
Shinya Kitaoka 120a6e
    const TFilePath &fp) const {
Shinya Kitaoka 120a6e
  return TSystem::doesExistFileOrLevel(m_scene->decodeFilePath(fp));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//************************************************************************************
Toshihiro Shimizu 890ddd
//    OverwriteDialog  implementation
Toshihiro Shimizu 890ddd
//************************************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
OverwriteDialog::OverwriteDialog()
Shinya Kitaoka 120a6e
    : DVGui::Dialog(TApp::instance()->getMainWindow(), true) {
Shinya Kitaoka 120a6e
  setModal(true);
Shinya Kitaoka 120a6e
  setWindowTitle(tr("Warning!"));
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  QButtonGroup *buttonGroup = new QButtonGroup(this);
Shinya Kitaoka 120a6e
  buttonGroup->setExclusive(true);
Shinya Kitaoka 120a6e
  bool ret = connect(buttonGroup, SIGNAL(buttonClicked(int)), this,
Shinya Kitaoka 120a6e
                     SLOT(onButtonClicked(int)));
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  beginVLayout();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_label = new QLabel(this);
Shinya Kitaoka 120a6e
  addWidget(m_label);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_keep = new QRadioButton(tr("Keep existing file"), this);
Shinya Kitaoka 120a6e
  buttonGroup->addButton(m_keep);
Shinya Kitaoka 120a6e
  addWidget(m_keep);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_overwrite = new QRadioButton(
Shinya Kitaoka 120a6e
      tr("Overwrite the existing file with the new one"), this);
Shinya Kitaoka 120a6e
  buttonGroup->addButton(m_overwrite);
Shinya Kitaoka 120a6e
  addWidget(m_overwrite);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_rename =
Shinya Kitaoka 120a6e
      new QRadioButton(tr("Rename the new file adding the suffix"), this);
Shinya Kitaoka 120a6e
  buttonGroup->addButton(m_rename);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_suffix = new DVGui::LineEdit("_1", this);
Shinya Kitaoka 120a6e
  m_suffix->setFixedWidth(25);
Shinya Kitaoka 120a6e
  m_suffix->setEnabled(false);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  QHBoxLayout *boxLayout = new QHBoxLayout();
Shinya Kitaoka 120a6e
  boxLayout->setMargin(0);
Shinya Kitaoka 120a6e
  boxLayout->setSpacing(0);
Shinya Kitaoka 120a6e
  boxLayout->addWidget(m_rename);
Shinya Kitaoka 120a6e
  boxLayout->addWidget(m_suffix);
Shinya Kitaoka 120a6e
  boxLayout->setAlignment(m_rename, Qt::AlignLeft);
Shinya Kitaoka 120a6e
  boxLayout->setAlignment(m_suffix, Qt::AlignLeft);
Shinya Kitaoka 120a6e
  addLayout(boxLayout);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  endVLayout();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_okBtn = new QPushButton(QString(tr("Apply")), this);
Shinya Kitaoka 120a6e
  ret     = ret && connect(m_okBtn, SIGNAL(clicked()), this, SLOT(accept()));
Shinya Kitaoka 120a6e
  addButtonBarWidget(m_okBtn);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_okToAllBtn = new QPushButton(QString(tr("Apply to All")), this);
Shinya Kitaoka 120a6e
  ret =
Shinya Kitaoka 120a6e
      ret && connect(m_okToAllBtn, SIGNAL(clicked()), this, SLOT(applyToAll()));
Shinya Kitaoka 120a6e
  addButtonBarWidget(m_okToAllBtn);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_cancelBtn = new QPushButton(QString(tr("Cancel")), this);
Shinya Kitaoka 120a6e
  ret = ret && connect(m_cancelBtn, SIGNAL(clicked()), this, SLOT(cancel()));
Shinya Kitaoka 120a6e
  addButtonBarWidget(m_cancelBtn);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  assert(ret);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  reset();
Shinya Kitaoka 120a6e
  m_keep->setChecked(true);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void OverwriteDialog::reset() {
Shinya Kitaoka 120a6e
  m_choice        = KEEP_OLD;
Shinya Kitaoka 120a6e
  m_applyToAll    = false;
Shinya Kitaoka 120a6e
  m_cancelPressed = false;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
std::wstring OverwriteDialog::getSuffix() {
Shinya Kitaoka 120a6e
  return m_suffix->text().toStdWString();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void OverwriteDialog::applyToAll() {
Shinya Kitaoka 120a6e
  m_applyToAll = true;
Shinya Kitaoka 120a6e
  accept();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void OverwriteDialog::cancel() {
Shinya Kitaoka 120a6e
  m_cancelPressed = true;
Shinya Kitaoka 120a6e
  reject();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void OverwriteDialog::onButtonClicked(int) {
Shinya Kitaoka 120a6e
  m_suffix->setEnabled(m_rename->isChecked());
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TFilePath OverwriteDialog::addSuffix(const TFilePath &src) const {
Shinya Kitaoka 120a6e
  return src.withName(src.getWideName() + m_suffix->text().toStdWString());
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
OverwriteDialog::Resolution OverwriteDialog::execute(TFilePath &filePath,
Shinya Kitaoka 120a6e
                                                     const ExistsFunc &exists,
Shinya Kitaoka 120a6e
                                                     Resolution acceptedRes,
Shinya Kitaoka 120a6e
                                                     Flags flags) {
Shinya Kitaoka 120a6e
  typedef QRadioButton *OverwriteDialog::*RadioRes;
Shinya Kitaoka 120a6e
  static const RadioRes radios[3] = {&OverwriteDialog::m_keep,
Shinya Kitaoka 120a6e
                                     &OverwriteDialog::m_overwrite,
Shinya Kitaoka 120a6e
                                     &OverwriteDialog::m_rename};
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  struct locals {
Shinya Kitaoka 120a6e
    static inline int idx(Resolution res) {
Shinya Kitaoka 120a6e
      int r = 0;
Shinya Kitaoka 120a6e
      while (r < 3 && !(res & (1 << r))) ++r;
Shinya Kitaoka 120a6e
      return r;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  };
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TFilePath writePath = filePath;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Deal with the case where "Apply To All" was already clicked
Shinya Kitaoka 120a6e
  if (m_applyToAll && (m_choice & acceptedRes)) {
Shinya Kitaoka 120a6e
    if (m_choice == RENAME) writePath = addSuffix(writePath);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (m_choice != RENAME || !exists(writePath))
Shinya Kitaoka 120a6e
      return filePath = writePath, m_choice;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  reset();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Find a compatible suffix to be displayed
Shinya Kitaoka 120a6e
  if (acceptedRes & RENAME)
Shinya Kitaoka 120a6e
    for (int i = 1; exists(addSuffix(filePath)); ++i)
Shinya Kitaoka 120a6e
      m_suffix->setText("_" + QString::number(i));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Show the various dialog components as specified
Shinya Kitaoka 120a6e
  m_overwrite->setVisible(acceptedRes & OVERWRITE);
Shinya Kitaoka 120a6e
  m_keep->setVisible(acceptedRes & KEEP_OLD);
Shinya Kitaoka 120a6e
  m_rename->setVisible(acceptedRes & RENAME);
Shinya Kitaoka 120a6e
  m_suffix->setVisible(acceptedRes & RENAME);
Shinya Kitaoka 120a6e
  m_okToAllBtn->setVisible(flags & APPLY_TO_ALL_FLAG);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Ensure that there is a checked button among the accepted resolutions
Shinya Kitaoka 120a6e
  for (int r = 0; r < 3; ++r)
Shinya Kitaoka 120a6e
    if ((this->*radios[r])->isChecked()) {
Shinya Kitaoka 120a6e
      if (!(acceptedRes & (1 << r)))
Shinya Kitaoka 120a6e
        (this->*radios[locals::idx(acceptedRes)])->setChecked(true);
Shinya Kitaoka 120a6e
      break;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Prompt the dialog to let the user decide resolution
Shinya Kitaoka 120a6e
  while (true) {
Shinya Kitaoka 120a6e
    // Build text to be displayed
Shinya Kitaoka 120a6e
    m_label->setText(exists.conflictString(writePath));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // Execute dialog
Shinya Kitaoka 120a6e
    int retCode = exec();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    m_choice = (retCode == QDialog::Rejected)
Shinya Kitaoka 120a6e
                   ? CANCELED
Shinya Kitaoka 120a6e
                   : m_overwrite->isChecked()
Shinya Kitaoka 120a6e
                         ? OVERWRITE
Shinya Kitaoka 120a6e
                         : m_rename->isChecked() ? RENAME : KEEP_OLD;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (m_choice == RENAME) {
Shinya Kitaoka 120a6e
      if (exists(writePath = addSuffix(filePath))) continue;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  return filePath = writePath, m_choice;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
std::wstring OverwriteDialog::execute(ToonzScene *scene,
Shinya Kitaoka 120a6e
                                      const TFilePath &srcLevelPath,
Shinya Kitaoka 120a6e
                                      bool multiload) {
Shinya Kitaoka 120a6e
  TFilePath levelPath       = srcLevelPath;
Shinya Kitaoka 120a6e
  TFilePath actualLevelPath = scene->decodeFilePath(levelPath);
Shinya Kitaoka 120a6e
  if (!TSystem::doesExistFileOrLevel(actualLevelPath))
Shinya Kitaoka 120a6e
    return levelPath.getWideName();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (m_applyToAll && m_choice == RENAME) {
Shinya Kitaoka 120a6e
    levelPath       = addSuffix(levelPath);
Shinya Kitaoka 120a6e
    actualLevelPath = scene->decodeFilePath(levelPath);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  if (m_applyToAll) {
Shinya Kitaoka 120a6e
    if (m_choice != RENAME || !TSystem::doesExistFileOrLevel(actualLevelPath))
Shinya Kitaoka 120a6e
      return levelPath.getWideName();
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  m_label->setText(tr("File %1 already exists.\nWhat do you want to do?")
Shinya Kitaoka 120a6e
                       .arg(toQString(levelPath)));
Shinya Kitaoka 120a6e
  // find a compatible suffix
Shinya Kitaoka 120a6e
  if (TSystem::doesExistFileOrLevel(actualLevelPath)) {
Shinya Kitaoka 120a6e
    int i = 0;
Shinya Kitaoka 120a6e
    while (TSystem::doesExistFileOrLevel(
Shinya Kitaoka 120a6e
        scene->decodeFilePath(addSuffix(srcLevelPath)))) {
Shinya Kitaoka 120a6e
      m_suffix->setText("_" + QString::number(++i));
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (multiload)
Shinya Kitaoka 120a6e
    m_okToAllBtn->show();
Shinya Kitaoka 120a6e
  else
Shinya Kitaoka 120a6e
    m_okToAllBtn->hide();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // there could be a WaitCursor cursor
Shinya Kitaoka 120a6e
  QApplication::setOverrideCursor(QCursor(Qt::ArrowCursor));
Shinya Kitaoka 120a6e
  raise();
Shinya Kitaoka 120a6e
  exec();
Shinya Kitaoka 120a6e
  QApplication::restoreOverrideCursor();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (m_rename->isChecked()) {
Shinya Kitaoka 120a6e
    if (m_suffix->text() == "") {
Shinya Kitaoka 120a6e
      DVGui::warning(tr("The suffix field is empty. Please specify a suffix."));
Shinya Kitaoka 120a6e
      return execute(scene, srcLevelPath, multiload);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    levelPath       = addSuffix(srcLevelPath);
Shinya Kitaoka 120a6e
    actualLevelPath = scene->decodeFilePath(levelPath);
Shinya Kitaoka 120a6e
    if (TSystem::doesExistFileOrLevel(actualLevelPath)) {
Shinya Kitaoka 120a6e
      DVGui::warning(
Shinya Kitaoka 120a6e
          tr("File %1 exists as well; please choose a different suffix.")
Shinya Kitaoka 120a6e
              .arg(toQString(levelPath)));
Shinya Kitaoka 120a6e
      return execute(scene, srcLevelPath, multiload);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    m_choice = RENAME;
Shinya Kitaoka 120a6e
  } else if (m_overwrite->isChecked())
Shinya Kitaoka 120a6e
    m_choice = OVERWRITE;
Shinya Kitaoka 120a6e
  else {
Shinya Kitaoka 120a6e
    assert(m_keep->isChecked());
Shinya Kitaoka 120a6e
    m_choice = KEEP_OLD;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  return levelPath.getWideName();
Toshihiro Shimizu 890ddd
}