#include "UnsavedDocumentsDialog.h" #include #include #include #include #include #include UnsavedDocumentsDialog::UnsavedDocumentsDialog(const QList> &docs, QWidget *parent) : QDialog(parent) , m_docs(docs) , m_list(new QListWidget(this)) { setWindowTitle(tr("Unsaved changes")); auto layout = new QVBoxLayout(this); layout->addWidget(new QLabel(tr("The following documents have unsaved changes. Select the documents to save or discard:"), this)); for (const auto &doc : m_docs) { QStringList windows; for (const QWidget *editor : doc->editors()) { QString title = editor->window()->windowTitle(); if (!windows.contains(title)) windows.append(title); } auto item = new QListWidgetItem(QString("%1 (%2)").arg(doc->fileName(), windows.join(", ")), m_list); item->setToolTip(doc->fileName()); item->setFlags(item->flags() | Qt::ItemIsUserCheckable); item->setCheckState(Qt::Checked); } layout->addWidget(m_list); auto buttons = new QDialogButtonBox(this); auto save_button = buttons->addButton(tr("Save selected"), QDialogButtonBox::AcceptRole); auto discard_button = buttons->addButton(tr("Discard selected"), QDialogButtonBox::DestructiveRole); buttons->addButton(QDialogButtonBox::Cancel); layout->addWidget(buttons); connect(save_button, &QPushButton::clicked, this, [this]() { m_choice = Choice::Save; accept(); }); connect(discard_button, &QPushButton::clicked, this, [this]() { m_choice = Choice::Discard; accept(); }); connect(buttons, &QDialogButtonBox::rejected, this, &QDialog::reject); } QList> UnsavedDocumentsDialog::checkedDocuments() const { QList> result; for (int i = 0; i < m_docs.size(); ++i) { if (m_list->item(i)->checkState() == Qt::Checked) result.append(m_docs[i]); } return result; } QList> UnsavedDocumentsDialog::uncheckedDocuments() const { QList> result; for (int i = 0; i < m_docs.size(); ++i) { if (m_list->item(i)->checkState() != Qt::Checked) result.append(m_docs[i]); } return result; } QList> documentsClosedWith(const QList> &docs, const std::function &isClosing) { QList> result; for (const auto &doc : docs) { const auto &editors = doc->editors(); if (!doc->isModified() || editors.isEmpty()) continue; bool all_closing = std::all_of(editors.begin(), editors.end(), [&isClosing](const QWidget *editor) { return isClosing(editor); }); if (all_closing) result.append(doc); } return result; } bool confirmClose(QWidget *parent, const QList> &docs) { auto remaining = docs; while (!remaining.isEmpty()) { UnsavedDocumentsDialog dlg(remaining, parent); if (dlg.exec() != QDialog::Accepted || dlg.choice() == UnsavedDocumentsDialog::Choice::Cancel) return false; bool save = dlg.choice() == UnsavedDocumentsDialog::Choice::Save; for (const auto &doc : dlg.checkedDocuments()) { if (save) { if (!doc->save(parent)) return false; } else { doc->setModified(false); } } // Show the dialog again for the documents the user did not select. remaining = dlg.uncheckedDocuments(); } return true; }