gitignore, dialogues

This commit is contained in:
yzinchuk
2026-06-19 16:45:22 -04:00
parent 125a1354e0
commit 40a9f3dc5d
3 changed files with 285 additions and 0 deletions
+61
View File
@@ -0,0 +1,61 @@
# CMake build directory
build/
# Qt MOC files
moc_*.cpp
*.moc
# Qt resource compiler
qrc_*.cpp
# Qt UI files
ui_*.h
# Object files
*.o
*.obj
# Libraries
*.a
*.lib
# Executables
*.exe
*.out
*.app
screenshot-gallery
# Qt specific
*.autosave
*.qmlc
*.jsc
# IDE and editor files
.vscode/
.idea/
*.pro.user
*.pro.user.*
*~
.DS_Store
# Cache and temporary files
.cache/
*.swp
*.swo
*.tmp
# CMake files (if generated in source directory)
CMakeFiles/
CMakeCache.txt
cmake_install.cmake
Makefile
*.cmake
# Backup files
*.bak
*.backup
*~
# System files
.directory
Thumbs.db
+167
View File
@@ -0,0 +1,167 @@
#include "updatedatabasedialog.h"
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QScrollBar>
#include <QDateTime>
#include <QFileInfo>
#include <QTimer>
UpdateDatabaseDialog::UpdateDatabaseDialog(const QString &scriptPath,
const QString &dbPath,
const QString &screenshotsDir,
QWidget *parent)
: QDialog(parent)
, m_scriptPath(scriptPath)
, m_dbPath(dbPath)
, m_screenshotsDir(screenshotsDir)
, m_process(nullptr)
{
setWindowTitle(tr("Update Database"));
setMinimumSize(600, 400);
// Non-modal: caller uses show(), not exec()
setWindowModality(Qt::NonModal);
// ----- Layout -----
auto *mainLayout = new QVBoxLayout(this);
m_statusLabel = new QLabel(tr("Starting OCR process…"), this);
mainLayout->addWidget(m_statusLabel);
m_progressBar = new QProgressBar(this);
m_progressBar->setRange(0, 0); // indeterminate
mainLayout->addWidget(m_progressBar);
m_logView = new QTextEdit(this);
m_logView->setReadOnly(true);
m_logView->setFont(QFont("monospace", 9));
mainLayout->addWidget(m_logView);
auto *btnLayout = new QHBoxLayout();
btnLayout->addStretch();
m_cancelButton = new QPushButton(tr("Cancel"), this);
btnLayout->addWidget(m_cancelButton);
m_closeButton = new QPushButton(tr("Close"), this);
m_closeButton->setEnabled(false);
btnLayout->addWidget(m_closeButton);
mainLayout->addLayout(btnLayout);
connect(m_cancelButton, &QPushButton::clicked, this, &UpdateDatabaseDialog::onCancelClicked);
connect(m_closeButton, &QPushButton::clicked, this, &QDialog::accept);
startProcess();
}
UpdateDatabaseDialog::~UpdateDatabaseDialog()
{
if (m_process && m_process->state() != QProcess::NotRunning) {
m_process->kill();
m_process->waitForFinished(3000);
}
}
void UpdateDatabaseDialog::startProcess()
{
QFileInfo scriptInfo(m_scriptPath);
if (!scriptInfo.exists()) {
appendLog(tr("Error: script not found at %1").arg(m_scriptPath), true);
m_progressBar->setRange(0, 1);
m_progressBar->setValue(1);
m_statusLabel->setText(tr("Failed script not found."));
m_cancelButton->setEnabled(false);
m_closeButton->setEnabled(true);
return;
}
m_process = new QProcess(this);
m_process->setProcessChannelMode(QProcess::SeparateChannels);
connect(m_process, &QProcess::readyReadStandardOutput,
this, &UpdateDatabaseDialog::onReadyReadStdOut);
connect(m_process, &QProcess::readyReadStandardError,
this, &UpdateDatabaseDialog::onReadyReadStdErr);
connect(m_process,
QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
this, &UpdateDatabaseDialog::onProcessFinished);
const QStringList args = {
m_scriptPath,
"--db", m_dbPath,
"--screenshots-dir", m_screenshotsDir
};
appendLog(tr("Running: python3 %1").arg(args.join(' ')));
appendLog(QString());
m_process->start("python3", args);
}
void UpdateDatabaseDialog::onReadyReadStdOut()
{
const QString text = QString::fromUtf8(m_process->readAllStandardOutput());
for (const QString &line : text.split('\n', Qt::SkipEmptyParts))
appendLog(line);
}
void UpdateDatabaseDialog::onReadyReadStdErr()
{
const QString text = QString::fromUtf8(m_process->readAllStandardError());
for (const QString &line : text.split('\n', Qt::SkipEmptyParts))
appendLog(line, true);
}
void UpdateDatabaseDialog::onProcessFinished(int exitCode, QProcess::ExitStatus exitStatus)
{
m_progressBar->setRange(0, 1);
m_progressBar->setValue(1);
m_cancelButton->setEnabled(false);
m_closeButton->setEnabled(true);
if (exitStatus == QProcess::CrashExit || exitCode != 0) {
m_statusLabel->setText(tr("OCR process failed (exit code %1).").arg(exitCode));
appendLog(tr("\nProcess exited with code %1.").arg(exitCode), true);
} else {
m_statusLabel->setText(tr("OCR process completed successfully."));
appendLog(tr("\nDone."));
emit updateFinished();
}
}
void UpdateDatabaseDialog::onCancelClicked()
{
if (m_process && m_process->state() != QProcess::NotRunning) {
appendLog(tr("\nCancelling…"), true);
m_cancelButton->setEnabled(false);
m_statusLabel->setText(tr("Cancelling…"));
// SIGTERM Python script's signal handler will clean up and exit
m_process->terminate();
// If it hasn't exited after 3 s, send SIGKILL
QTimer::singleShot(3000, this, [this]() {
if (m_process && m_process->state() != QProcess::NotRunning) {
appendLog(tr("Force-killing process…"), true);
m_process->kill();
}
});
} else {
reject();
}
}
void UpdateDatabaseDialog::appendLog(const QString &text, bool isError)
{
if (isError)
m_logView->setTextColor(QColor("#cc3333"));
else
m_logView->setTextColor(m_logView->palette().color(QPalette::Text));
m_logView->append(text);
// Auto-scroll to bottom
QScrollBar *sb = m_logView->verticalScrollBar();
sb->setValue(sb->maximum());
}
+57
View File
@@ -0,0 +1,57 @@
#ifndef UPDATEDATABASEDIALOG_H
#define UPDATEDATABASEDIALOG_H
#include <QDialog>
#include <QTextEdit>
#include <QProgressBar>
#include <QLabel>
#include <QPushButton>
#include <QProcess>
#include <QString>
/**
* @brief Non-modal dialog that runs the OCR update script and streams its output.
*
* The dialog stays open after the process finishes so the user can read the log.
* It emits updateFinished() when the script exits successfully so the caller can
* reload the gallery.
*/
class UpdateDatabaseDialog : public QDialog
{
Q_OBJECT
public:
explicit UpdateDatabaseDialog(const QString &scriptPath,
const QString &dbPath,
const QString &screenshotsDir,
QWidget *parent = nullptr);
~UpdateDatabaseDialog();
signals:
/** Emitted when the OCR script exits with code 0. */
void updateFinished();
private slots:
void onReadyReadStdOut();
void onReadyReadStdErr();
void onProcessFinished(int exitCode, QProcess::ExitStatus exitStatus);
void onCancelClicked();
private:
void startProcess();
void appendLog(const QString &text, bool isError = false);
QString m_scriptPath;
QString m_dbPath;
QString m_screenshotsDir;
QLabel *m_statusLabel;
QTextEdit *m_logView;
QProgressBar*m_progressBar;
QPushButton *m_cancelButton;
QPushButton *m_closeButton;
QProcess *m_process;
};
#endif // UPDATEDATABASEDIALOG_H