Stage history editor: - The edit form's Pipeline section is now the application's history: one row per step (stage + date), Add Step and Remove Step, kept in date order. The last step is the current stage and the first step's date the date applied, replacing the separate Stage and Date Applied fields. An application logged after the fact (applied, interviewed, rejected) keeps its whole path. - JobsDatabase::replaceStageHistory() rewrites a job's history in one transaction (sorted, repeats collapsed, stage and date applied kept in step); StageHistoryModel backs the section; JobsModel::addJob() now returns the new id so a new application's history can be saved. - `kareer history <id> [Stage=YYYY-MM-DD ...]` shows or replaces it. Auto-ghosting: - Applications still at Applied with no activity (the later of the date applied and the last stage change) for more than 30 days move to Ghosted, recorded like any stage change. Runs at startup for GUI and CLI, after switching databases, and shortly after the setting changes. - Preferences gains an Applications section: on/off and the number of days (kareerrc [AutoGhost]). The GUI shows a passive notification; the CLI notes it on stderr so --json output stays clean. Fixes: - The Add Application form pre-filled empty text fields with the word "undefined" (typing "a" gave "undefineda"): fields with no value reached QML as undefined. Every field now gets a typed default. - Embed the app icon as the window icon fallback, so the window and About page show it when running uninstalled. Tests: history replacement and the after-the-fact Allstate case, the ghosting rules (fresh/stale/logged-late/reopened/threshold), and empty new-form fields. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_01BxDf7HqD1xPnsZP8wt3NTk
71 lines
2.0 KiB
C++
71 lines
2.0 KiB
C++
/*
|
|
SPDX-FileCopyrightText: 2026 ToServeTheKing <[email protected]>
|
|
|
|
SPDX-License-Identifier: GPL-3.0-or-later
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include "job.h"
|
|
|
|
#include <QAbstractListModel>
|
|
#include <QQmlEngine>
|
|
|
|
/**
|
|
* The editable stage history of one application, as shown in the edit
|
|
* form's Pipeline section: one row per step (stage + date), kept in date
|
|
* order. The last step is the application's current stage, and the first
|
|
* step's date is its date applied. JobEditModel owns one and saves it with
|
|
* JobsDatabase::replaceStageHistory().
|
|
*/
|
|
class StageHistoryModel : public QAbstractListModel
|
|
{
|
|
Q_OBJECT
|
|
QML_ELEMENT
|
|
QML_UNCREATABLE("Owned by JobEditModel")
|
|
|
|
Q_PROPERTY(int count READ rowCount NOTIFY countChanged)
|
|
Q_PROPERTY(QStringList stages READ stages CONSTANT)
|
|
|
|
public:
|
|
enum Roles {
|
|
StageRole = Qt::UserRole + 1,
|
|
DateRole,
|
|
};
|
|
Q_ENUM(Roles)
|
|
|
|
explicit StageHistoryModel(QObject *parent = nullptr);
|
|
|
|
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
|
QVariant data(const QModelIndex &index, int role) const override;
|
|
QHash<int, QByteArray> roleNames() const override;
|
|
|
|
QStringList stages() const;
|
|
|
|
/// Replaces every step without marking the history as edited.
|
|
void load(const QList<StageStep> &steps);
|
|
QList<StageStep> steps() const;
|
|
bool isEdited() const;
|
|
|
|
Q_INVOKABLE void setStage(int row, const QString &stage);
|
|
/// Takes a JS Date from QML; only its (local) calendar date is kept.
|
|
Q_INVOKABLE void setDate(int row, const QDateTime &when);
|
|
/// Appends a step dated today, defaulting to the stage that usually
|
|
/// comes next.
|
|
Q_INVOKABLE void appendStep();
|
|
/// Removes a step; the last remaining step can't be removed.
|
|
Q_INVOKABLE void removeStep(int row);
|
|
|
|
Q_SIGNALS:
|
|
void countChanged();
|
|
/// Emitted after any change made through the invokables.
|
|
void edited();
|
|
|
|
private:
|
|
void sortByDate();
|
|
void markEdited();
|
|
|
|
QList<StageStep> m_steps;
|
|
bool m_edited = false;
|
|
};
|