You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

246 lines
9.3 KiB

// databasesettingspage.cpp — Database maintenance page in settings
#include "databasesettingspage.h"
#include "../db/db_manager.h"
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QFormLayout>
#include <QLabel>
#include <QFrame>
#include <QFileInfo>
#include <QTimer>
DatabaseSettingsPage::DatabaseSettingsPage(DbManager* db, QWidget* parent)
: QWidget(parent)
, m_db(db)
{
auto* layout = new QVBoxLayout(this);
layout->setSpacing(10);
layout->setContentsMargins(0, 0, 0, 0);
auto* title = new QLabel("Database Maintenance", this);
title->setStyleSheet("font-weight: bold; font-size: 13px;");
layout->addWidget(title);
// --- DB info ---
auto* infoLayout = new QFormLayout();
infoLayout->setSpacing(4);
QString dbPath = "—";
QString dbSize = "—";
QString walSize = "—";
if (m_db && m_db->m_db) {
const char* fname = sqlite3_db_filename(m_db->m_db, "main");
if (fname && fname[0]) {
dbPath = QString::fromUtf8(fname);
QFileInfo fi(dbPath);
if (fi.exists()) {
qint64 sz = fi.size();
if (sz < 1024) dbSize = QString("%1 B").arg(sz);
else if (sz < 1024 * 1024) dbSize = QString("%1 KB").arg(sz / 1024);
else dbSize = QString("%1 MB").arg(sz / (1024.0 * 1024.0), 0, 'f', 2);
}
QFileInfo walFi(dbPath + "-wal");
if (walFi.exists()) {
qint64 wsz = walFi.size();
if (wsz < 1024) walSize = QString("%1 B").arg(wsz);
else if (wsz < 1024 * 1024) walSize = QString("%1 KB").arg(wsz / 1024);
else walSize = QString("%1 MB").arg(wsz / (1024.0 * 1024.0), 0, 'f', 2);
} else {
walSize = "n/a";
}
}
}
m_filePathLabel = new QLabel(dbPath, this);
m_filePathLabel->setStyleSheet("font-size: 11px; color: gray;");
m_filePathLabel->setTextInteractionFlags(Qt::TextSelectableByMouse);
infoLayout->addRow("File:", m_filePathLabel);
m_fileSizeLabel = new QLabel(dbSize, this);
m_fileSizeLabel->setStyleSheet("font-size: 11px;");
infoLayout->addRow("Size:", m_fileSizeLabel);
m_walSizeLabel = new QLabel(walSize, this);
m_walSizeLabel->setStyleSheet("font-size: 11px;");
infoLayout->addRow("WAL:", m_walSizeLabel);
layout->addLayout(infoLayout);
// --- Separator ---
auto* sep = new QFrame(this);
sep->setFrameShape(QFrame::HLine);
sep->setFrameShadow(QFrame::Sunken);
layout->addWidget(sep);
// --- Buttons ---
auto* btnLayout = new QVBoxLayout();
btnLayout->setSpacing(6);
auto* quickRow = new QHBoxLayout();
m_quickBtn = new QPushButton("Quick Check", this);
m_quickBtn->setStyleSheet(
"QPushButton { border: 1px solid palette(mid); border-radius: 4px;"
" padding: 5px 14px; font-size: 12px; background: palette(button); }"
"QPushButton:hover { background: palette(light); }");
connect(m_quickBtn, &QPushButton::clicked, this, &DatabaseSettingsPage::onQuickCheck);
quickRow->addWidget(m_quickBtn);
auto* quickDesc = new QLabel("Scans structure without verifying indexes (fast)", this);
quickDesc->setStyleSheet("color: gray; font-size: 11px;");
quickRow->addWidget(quickDesc, 1);
btnLayout->addLayout(quickRow);
auto* fullRow = new QHBoxLayout();
m_fullBtn = new QPushButton("Full Check", this);
m_fullBtn->setStyleSheet(m_quickBtn->styleSheet());
connect(m_fullBtn, &QPushButton::clicked, this, &DatabaseSettingsPage::onFullCheck);
fullRow->addWidget(m_fullBtn);
auto* fullDesc = new QLabel("Verifies all data structures and indexes (thorough)", this);
fullDesc->setStyleSheet("color: gray; font-size: 11px;");
fullRow->addWidget(fullDesc, 1);
btnLayout->addLayout(fullRow);
auto* optRow = new QHBoxLayout();
m_optimizeBtn = new QPushButton("Optimize", this);
m_optimizeBtn->setStyleSheet(m_quickBtn->styleSheet());
connect(m_optimizeBtn, &QPushButton::clicked, this, &DatabaseSettingsPage::onOptimize);
optRow->addWidget(m_optimizeBtn);
auto* optDesc = new QLabel("Update query planner statistics for better performance", this);
optDesc->setStyleSheet("color: gray; font-size: 11px;");
optRow->addWidget(optDesc, 1);
btnLayout->addLayout(optRow);
layout->addLayout(btnLayout);
// --- Status ---
m_statusLabel = new QLabel("", this);
m_statusLabel->setStyleSheet("font-size: 12px; margin-top: 4px;");
layout->addWidget(m_statusLabel);
// --- Results ---
m_resultText = new QPlainTextEdit(this);
m_resultText->setReadOnly(true);
m_resultText->setMaximumHeight(120);
m_resultText->setStyleSheet(
"QPlainTextEdit { font-family: monospace; font-size: 11px;"
" background: palette(base); border: 1px solid palette(mid); border-radius: 4px;"
" padding: 4px; }");
m_resultText->setPlaceholderText("Run a check to see results...");
layout->addWidget(m_resultText);
layout->addStretch();
if (!m_db || !m_db->m_db) {
m_statusLabel->setText("Database not connected");
m_statusLabel->setStyleSheet("font-size: 12px; font-weight: bold; color: red;");
m_quickBtn->setEnabled(false);
m_fullBtn->setEnabled(false);
m_optimizeBtn->setEnabled(false);
qWarning("DatabaseSettingsPage: DB not ready m_db=%p m_db->m_db=%p", (void*)m_db, m_db ? (void*)m_db->m_db : nullptr);
}
}
void DatabaseSettingsPage::refreshStatus() {
if (!m_db || !m_db->m_db) {
m_statusLabel->setText("Database not connected");
m_statusLabel->setStyleSheet("font-size: 12px; font-weight: bold; color: red;");
m_quickBtn->setEnabled(false);
m_fullBtn->setEnabled(false);
m_optimizeBtn->setEnabled(false);
return;
}
m_quickBtn->setEnabled(true);
m_fullBtn->setEnabled(true);
m_optimizeBtn->setEnabled(true);
const char* fname = sqlite3_db_filename(m_db->m_db, "main");
if (fname && fname[0]) {
QString dbPath = QString::fromUtf8(fname);
m_filePathLabel->setText(dbPath);
QFileInfo fi(dbPath);
if (fi.exists()) {
qint64 sz = fi.size();
if (sz < 1024) m_fileSizeLabel->setText(QString("%1 B").arg(sz));
else if (sz < 1024 * 1024) m_fileSizeLabel->setText(QString("%1 KB").arg(sz / 1024));
else m_fileSizeLabel->setText(QString("%1 MB").arg(sz / (1024.0 * 1024.0), 0, 'f', 2));
QFileInfo walFi(dbPath + "-wal");
if (walFi.exists()) {
qint64 wsz = walFi.size();
if (wsz < 1024) m_walSizeLabel->setText(QString("%1 B").arg(wsz));
else if (wsz < 1024 * 1024) m_walSizeLabel->setText(QString("%1 KB").arg(wsz / 1024));
else m_walSizeLabel->setText(QString("%1 MB").arg(wsz / (1024.0 * 1024.0), 0, 'f', 2));
} else { m_walSizeLabel->setText("n/a"); }
}
}
}
void DatabaseSettingsPage::setBusy(bool busy) {
m_quickBtn->setEnabled(!busy);
m_fullBtn->setEnabled(!busy);
m_optimizeBtn->setEnabled(!busy);
if (busy) {
m_statusLabel->setText("Checking...");
m_statusLabel->setStyleSheet("font-size: 12px; margin-top: 4px; color: gray;");
}
}
void DatabaseSettingsPage::onQuickCheck() {
if (!m_db || !m_db->m_db) {
m_statusLabel->setText("Database not open");
m_statusLabel->setStyleSheet("font-size: 12px; color: red;");
return;
}
setBusy(true);
QTimer::singleShot(50, this, [this]() {
IntegrityResult r = m_db->integrityCheckQuick();
showResult("Quick Check", r);
});
}
void DatabaseSettingsPage::onFullCheck() {
if (!m_db || !m_db->m_db) {
m_statusLabel->setText("Database not open");
m_statusLabel->setStyleSheet("font-size: 12px; color: red;");
return;
}
setBusy(true);
QTimer::singleShot(50, this, [this]() {
IntegrityResult r = m_db->integrityCheckFull();
showResult("Full Check", r);
});
}
void DatabaseSettingsPage::onOptimize() {
if (!m_db || !m_db->m_db) {
m_statusLabel->setText("Database not open");
m_statusLabel->setStyleSheet("font-size: 12px; color: red;");
return;
}
setBusy(true);
QTimer::singleShot(50, this, [this]() {
IntegrityResult r = m_db->integrityOptimize();
showResult("Optimize", r);
});
}
void DatabaseSettingsPage::showResult(const QString& checkName, const IntegrityResult& result) {
m_quickBtn->setEnabled(true);
m_fullBtn->setEnabled(true);
m_optimizeBtn->setEnabled(true);
if (result.ok) {
m_statusLabel->setText(QString("%1: OK (%2 ms)")
.arg(checkName).arg(result.elapsedMs));
m_statusLabel->setStyleSheet("font-size: 12px; font-weight: bold; color: green;");
} else {
m_statusLabel->setText(QString("%1: FAILED (%2 ms)")
.arg(checkName).arg(result.elapsedMs));
m_statusLabel->setStyleSheet("font-size: 12px; font-weight: bold; color: red;");
}
if (result.errors.isEmpty()) {
m_resultText->setPlainText(result.message.isEmpty() ? "ok" : result.message);
} else {
QStringList lines;
lines.append(result.message);
lines.append(result.errors);
m_resultText->setPlainText(lines.join('\n'));
}
}