- `kareer --db <path>` works for the GUI and every subcommand, before or after the subcommand name, and creates the file if missing. main() strips it from argv before CLI/GUI routing; every parser declares it so it shows in --help. - Path precedence: --db > KAREER_DB_PATH > the location chosen in the GUI (kareerrc [Database] Path, read at startup for GUI and CLI alike) > $XDG_DATA_HOME/kareer/kareer.sqlite. - First GUI run (nothing forced, no file yet, or the configured file has gone missing): DatabaseSetupDialog offers the default location, a folder of the user's choice, or an existing database used in place. Until then JobsDatabase opens nothing. - Preferences gains a Database section: Move to... (copies, leaves the original), Open Existing..., Use Default Location. Refuses foreign SQLite files and unwritable ones. - Models call JobsDatabase::reopenIfPathChanged() on refresh, so switching databases needs no restart. - Link KF6::ConfigCore; add a QuickDialogs2 configure-time guard; add kconfig to the Arch dependencies and a note to the Flatpak manifest. - README documents --db, the precedence, and the first-run choice, and gains Fedora 44 build dependencies; CONTRIBUTING gets a dev recipe. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_01BxDf7HqD1xPnsZP8wt3NTk
102 lines
3.2 KiB
C++
102 lines
3.2 KiB
C++
/*
|
|
SPDX-FileCopyrightText: 2026 ToServeTheKing <[email protected]>
|
|
|
|
SPDX-License-Identifier: GPL-3.0-or-later
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include "job.h"
|
|
|
|
#include <QList>
|
|
#include <QString>
|
|
#include <optional>
|
|
|
|
class QSqlDatabase;
|
|
|
|
/**
|
|
* SQLite-backed storage for job applications and their stage history.
|
|
*
|
|
* Every JobsDatabase instance owns its own named QSqlDatabase connection
|
|
* (Qt's SQL connections are identified by name, not by object identity),
|
|
* so multiple instances - e.g. in tests - never collide.
|
|
*/
|
|
class JobsDatabase
|
|
{
|
|
public:
|
|
JobsDatabase();
|
|
explicit JobsDatabase(const QString &path);
|
|
~JobsDatabase();
|
|
|
|
JobsDatabase(const JobsDatabase &) = delete;
|
|
JobsDatabase &operator=(const JobsDatabase &) = delete;
|
|
|
|
/// The database file a default-constructed instance opens. Resolved in
|
|
/// order: the --db override, the KAREER_DB_PATH environment variable
|
|
/// (used by autotests), the path configured in kareerrc, and finally
|
|
/// $XDG_DATA_HOME/kareer/kareer.sqlite.
|
|
static QString defaultPath();
|
|
|
|
/// $XDG_DATA_HOME/kareer/kareer.sqlite, ignoring every override.
|
|
static QString standardPath();
|
|
|
|
/// Set from the --db command-line option; wins over everything else.
|
|
static void setPathOverride(const QString &path);
|
|
|
|
/// The user's chosen location (kareerrc); empty means standardPath().
|
|
static void setConfiguredPath(const QString &path);
|
|
static QString configuredPath();
|
|
|
|
/// True when --db or KAREER_DB_PATH decides the path, so the configured
|
|
/// location has no effect.
|
|
static bool hasForcedPath();
|
|
|
|
/// While true (GUI first run, before the user has picked a location), a
|
|
/// default-constructed instance opens nothing and reports an error.
|
|
static void setSelectionPending(bool pending);
|
|
static bool selectionPending();
|
|
|
|
/// The file this instance opened, or empty if it opened nothing.
|
|
QString path() const;
|
|
|
|
/// Reopens against defaultPath() if that no longer matches path() (the
|
|
/// user picked another location). Returns true if it reopened.
|
|
bool reopenIfPathChanged();
|
|
|
|
/// Performs a harmless write (rewrites the header's user_version), so
|
|
/// callers can tell a read-only file apart from a usable one.
|
|
bool checkWritable();
|
|
|
|
bool isOpen() const;
|
|
QString lastError() const;
|
|
|
|
QList<Job> allJobs() const;
|
|
std::optional<Job> jobById(int id) const;
|
|
|
|
/// Inserts a new job. On success, job.id/createdAt/updatedAt are filled
|
|
/// in and an initial Start -> job.stage transition is recorded.
|
|
bool addJob(Job &job);
|
|
|
|
/// Updates every field except stage (use setStage for that, so every
|
|
/// stage change is captured in the history).
|
|
bool updateJob(const Job &job);
|
|
|
|
/// Moves a job to newStage, recording the transition. A no-op (but still
|
|
/// successful) if the job is already in newStage.
|
|
bool setStage(int id, const QString &newStage);
|
|
|
|
bool deleteJob(int id);
|
|
|
|
QList<StageTransition> stageTransitions() const;
|
|
|
|
private:
|
|
void init(const QString &path);
|
|
void close();
|
|
bool migrate();
|
|
Job jobFromQuery(class QSqlQuery &query) const;
|
|
|
|
QString m_connectionName;
|
|
QString m_path;
|
|
QString m_lastError;
|
|
};
|