message: implement discarding submodules
diff: @@ -189,11 +189,31 @@ FileContextMenu::FileContextMenu(RepoView *view, const QStringList &files,
  QStringList modified;
  QStringList untracked;
  if (diff.isValid()) {
  - foreach (const QString &file, files) {
  + // copied from DiffTreeModel.cpp
  + // handle submodules
  + auto s = repo.submodules();
  + QList<git::Submodule> submodules;
  + QStringList filePatches;
  + for (auto trackedPatch : files) {
  + bool is_submodule = false;
  + for (auto submodule : s) {
  + if (submodule.path() == trackedPatch) {
  + is_submodule = true;
  + submodules.append(submodule);
  + break;
  + }
  + }
  + if (!is_submodule)
  + filePatches.append(trackedPatch);
  + }
  +
  + // handle files not submodules
  + foreach (const QString &file, filePatches) {
  handlePath(repo, file, diff, modified, untracked);
  }
  - QAction *discard = addAction(tr("Discard Changes"), [view, modified] {
  + QAction *discard =
  + addAction(tr("Discard Changes"), [view, modified, submodules] {
  QMessageBox *dialog =
  new QMessageBox(QMessageBox::Warning, tr("Discard Changes?"),
  tr("Are you sure you want to discard changes in "
  @@ -201,7 +221,10 @@ FileContextMenu::FileContextMenu(RepoView *view, const QStringList &files,
  QMessageBox::Cancel, view);
  dialog->setAttribute(Qt::WA_DeleteOnClose);
  dialog->setInformativeText(tr("This action cannot be undone."));
  - dialog->setDetailedText(modified.join('\n'));
  + QString detailedText = modified.join('\n');
  + for (const auto s : submodules)
  + detailedText += s.path() + " " + tr("(Submodule)") + "\n";
  + dialog->setDetailedText(detailedText);
  // Expand the Show Details
  foreach (QAbstractButton *button, dialog->buttons()) {
  @@ -212,24 +235,27 @@ FileContextMenu::FileContextMenu(RepoView *view, const QStringList &files,
  }
  QString text = tr("Discard Changes");
  - QPushButton *discard = dialog->addButton(text, QMessageBox::AcceptRole);
  + QPushButton *discard =
  + dialog->addButton(text, QMessageBox::AcceptRole);
  discard->setObjectName("DiscardButton");
  - connect(discard, &QPushButton::clicked, [view, modified] {
  + connect(discard, &QPushButton::clicked, [view, modified, submodules] {
  git::Repository repo = view->repo();
  int strategy = GIT_CHECKOUT_FORCE;
  - if (!repo.checkout(git::Commit(), nullptr, modified, strategy)) {
  + if (modified.count() &&
  + !repo.checkout(git::Commit(), nullptr, modified, strategy)) {
  QString text = tr("%1 files").arg(modified.size());
  LogEntry *parent = view->addLogEntry(text, tr("Discard"));
  view->error(parent, tr("discard"), text);
  }
  + view->updateSubmodules(submodules, true, false, true);
  // FIXME: Work dir changed?
  - view->refresh();
  + view->refresh(); // TODO: check that refresh is called only once!
  });
  dialog->open();
  });
  - discard->setEnabled(!modified.isEmpty());
  + discard->setEnabled(!modified.isEmpty() || submodules.count());
  QAction *remove = addAction(tr("Remove Untracked Files"),
  [view, untracked] { view->clean(untracked); });
  