113 lines
3.4 KiB
C++
113 lines
3.4 KiB
C++
|
|
#include "UnsavedDocumentsDialog.h"
|
||
|
|
#include <QDialogButtonBox>
|
||
|
|
#include <QListWidget>
|
||
|
|
#include <QPushButton>
|
||
|
|
#include <QVBoxLayout>
|
||
|
|
#include <QLabel>
|
||
|
|
#include <algorithm>
|
||
|
|
|
||
|
|
UnsavedDocumentsDialog::UnsavedDocumentsDialog(const QList<std::shared_ptr<SqlDocument>> &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<std::shared_ptr<SqlDocument>> UnsavedDocumentsDialog::checkedDocuments() const
|
||
|
|
{
|
||
|
|
QList<std::shared_ptr<SqlDocument>> 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<std::shared_ptr<SqlDocument>> UnsavedDocumentsDialog::uncheckedDocuments() const
|
||
|
|
{
|
||
|
|
QList<std::shared_ptr<SqlDocument>> 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<std::shared_ptr<SqlDocument>> documentsClosedWith(const QList<std::shared_ptr<SqlDocument>> &docs,
|
||
|
|
const std::function<bool(const QWidget*)> &isClosing)
|
||
|
|
{
|
||
|
|
QList<std::shared_ptr<SqlDocument>> 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<std::shared_ptr<SqlDocument>> &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;
|
||
|
|
}
|