aboutsummaryrefslogtreecommitdiffstats
path: root/llamachat/ui.py
diff options
context:
space:
mode:
Diffstat (limited to 'llamachat/ui.py')
-rw-r--r--llamachat/ui.py52
1 files changed, 51 insertions, 1 deletions
diff --git a/llamachat/ui.py b/llamachat/ui.py
index 7d5c4a2..6c26ca2 100644
--- a/llamachat/ui.py
+++ b/llamachat/ui.py
@@ -32,7 +32,7 @@ from PySide6.QtWidgets import (
QPushButton, QRadioButton, QSplitter, QTextBrowser, QVBoxLayout, QWidget,
)
-from . import backend, prompts
+from . import backend, models as models_mod, prompts
from .backend import Attachment, BackendError, SearchConfig
from .config import GLOBAL_PROMPT
@@ -133,6 +133,56 @@ def _short(count: int) -> str:
return str(count)
+def cost_text(spent: float, projected: float, billable: bool, priced: bool) -> str:
+ """The cost label beside the context meter.
+
+ Three states, deliberately distinct: a local model shows nothing, a
+ cloud model with no price entered shows '?', and a priced one shows
+ what it has cost plus what the composed draft would add. Blank and '?'
+ must not collapse into each other, or an unpriced cloud model reads as
+ free.
+ """
+ if not billable:
+ return ""
+ if not priced:
+ return "?"
+ text = models_mod.format_cost(spent)
+ if projected > 0:
+ text += f" +{models_mod.format_cost(projected)}"
+ return text
+
+
+class CostLabel(QLabel):
+ """A one-line money readout that hides itself when there is nothing to say."""
+
+ def __init__(self):
+ super().__init__("")
+ self.setToolTip("")
+
+ def set_cost(
+ self, spent: float, projected: float, billable: bool, priced: bool
+ ) -> None:
+ text = cost_text(spent, projected, billable, priced)
+ self.setText(text)
+ self.setVisible(bool(text))
+ if not billable:
+ self.setToolTip("")
+ elif not priced:
+ self.setToolTip(
+ "No prices set for this model.\n"
+ "Use Model settings to enter them."
+ )
+ else:
+ tip = f"{models_mod.format_cost(spent)} spent in this conversation"
+ if projected > 0:
+ tip += (
+ f"\n+{models_mod.format_cost(projected)} to send what is "
+ "composed now"
+ )
+ tip += "\nApproximate: based on the prices you entered."
+ self.setToolTip(tip)
+
+
class StreamWorker(QObject):
"""Runs one streaming request off the GUI thread."""