summaryrefslogtreecommitdiff
path: root/kodereviewer/models
diff options
context:
space:
mode:
Diffstat (limited to 'kodereviewer/models')
-rw-r--r--kodereviewer/models/__init__.py9
-rw-r--r--kodereviewer/models/comments.py89
-rw-r--r--kodereviewer/models/project.py92
-rw-r--r--kodereviewer/models/pull_request.py75
4 files changed, 265 insertions, 0 deletions
diff --git a/kodereviewer/models/__init__.py b/kodereviewer/models/__init__.py
new file mode 100644
index 0000000..853b618
--- /dev/null
+++ b/kodereviewer/models/__init__.py
@@ -0,0 +1,9 @@
+from kodereviewer.models.comments import CommentModel
+from kodereviewer.models.project import ProjectModel
+from kodereviewer.models.pull_request import PullRequestModel
+
+__all__ = [
+ 'CommentModel',
+ 'ProjectModel',
+ 'PullRequestModel',
+]
diff --git a/kodereviewer/models/comments.py b/kodereviewer/models/comments.py
new file mode 100644
index 0000000..06de3d7
--- /dev/null
+++ b/kodereviewer/models/comments.py
@@ -0,0 +1,89 @@
+from enum import auto, IntEnum
+from typing import Optional
+
+from PySide6.QtCore import QAbstractListModel, QByteArray, QModelIndex, QObject, QPersistentModelIndex, QStandardPaths, QUrl, Qt, Signal, Slot, Property
+from PySide6.QtQml import QmlElement
+
+from kodereviewer.data import Comment, PullRequest
+
+QML_IMPORT_NAME = "org.deprecated.kodereviewer"
+QML_IMPORT_MAJOR_VERSION = 1
+
+
+@QmlElement
+class CommentModel(QAbstractListModel):
+
+ _pull_request: Optional[PullRequest]
+
+ class Roles(IntEnum):
+ Body = Qt.ItemDataRole.UserRole + 1
+ CreatedAt = auto()
+ UpdatedAt = auto()
+ Username = auto()
+ AvatarUrl = auto()
+
+
+ def __init__(self):
+ super().__init__()
+ self._pull_request = None
+
+ def get_pull_request(self) -> Optional[PullRequest]:
+ return self._pull_request
+
+ def set_pull_request(self, pull_request: Optional[PullRequest]) -> None:
+ if pull_request is None:
+ return
+
+ if self._pull_request is not None and self._pull_request == pull_request:
+ return
+
+ print(f"Setting up pull request to {pull_request}")
+ self.beginResetModel()
+ self._pull_request = pull_request
+ self._pull_request.commentsLoaded.connect(self._reset_model)
+ self.endResetModel()
+ self.pullRequestChanged.emit()
+
+ pullRequestChanged = Signal()
+ pullRequest = Property(PullRequest, fget=get_pull_request, fset=set_pull_request,
+ notify=pullRequestChanged)
+
+ def _reset_model(self) -> None:
+ self.beginResetModel()
+ self.endResetModel()
+
+ def data(self,
+ index: QModelIndex | QPersistentModelIndex,
+ role: int = Qt.ItemDataRole.DisplayRole) -> object:
+ if self._pull_request is None:
+ return None
+
+ comment: Comment = self._pull_request._comments[index.row()]
+
+ if role == self.Roles.Body:
+ return comment.body
+ if role == self.Roles.CreatedAt:
+ return comment.created_at.strftime("%Y-%M-%d %H:%m")
+ if role == self.Roles.UpdatedAt:
+ return comment.updated_at.strftime("%Y-%M-%d %H:%m")
+ if role == self.Roles.Username:
+ return comment.user.username
+ if role == self.Roles.AvatarUrl:
+ return comment.user.avatar_url
+ if role == Qt.ItemDataRole.DisplayRole:
+ return comment.body
+ return None
+
+ def rowCount(self, parent: QModelIndex | QPersistentModelIndex = QModelIndex()) -> int:
+ if self._pull_request is None:
+ return 0
+ return len(self._pull_request._comments)
+
+ def roleNames(self) -> dict[int, QByteArray]:
+ return {
+ self.Roles.Body: QByteArray(b'body'),
+ self.Roles.CreatedAt: QByteArray(b'createdAt'),
+ self.Roles.UpdatedAt: QByteArray(b'updatedAt'),
+ self.Roles.Username: QByteArray(b'username'),
+ self.Roles.AvatarUrl: QByteArray(b'avatarUrl'),
+ }
diff --git a/kodereviewer/models/project.py b/kodereviewer/models/project.py
new file mode 100644
index 0000000..c676157
--- /dev/null
+++ b/kodereviewer/models/project.py
@@ -0,0 +1,92 @@
+import json
+from os import path
+from typing import Any
+
+from PySide6.QtCore import QAbstractListModel, QByteArray, QModelIndex, QObject, QPersistentModelIndex, QStandardPaths, QUrl, Qt, Signal, Slot, Property
+from PySide6.QtQml import QmlElement
+
+from kodereviewer.project import Project
+
+QML_IMPORT_NAME = "org.deprecated.kodereviewer"
+QML_IMPORT_MAJOR_VERSION = 1
+
+
+@QmlElement
+class ProjectModel(QAbstractListModel):
+ """Projects list!"""
+
+ projects: list[Project]
+
+ NameRole = Qt.ItemDataRole.UserRole + 1
+ OwnerRole = NameRole + 1
+ UrlRole = OwnerRole + 1
+
+ def __init__(self):
+ super().__init__()
+ self.projects = []
+
+ project_config = self._project_file()
+ try:
+ with open(project_config) as fp:
+ data = json.load(fp)
+ if isinstance(data, list):
+ self._load_projects(data)
+ except OSError as e:
+ pass
+
+ def _project_file(self) -> str:
+ app_data = QStandardPaths.writableLocation(QStandardPaths.AppDataLocation)
+ project_config = path.join(app_data, 'projects.json')
+ return project_config
+
+ def data(self,
+ index: QModelIndex | QPersistentModelIndex,
+ role: int = Qt.ItemDataRole.DisplayRole) -> object:
+ project = self.projects[index.row()]
+
+ if role == Qt.ItemDataRole.DisplayRole:
+ return project.name
+ if role == self.NameRole:
+ return project.name
+ if role == self.OwnerRole:
+ return project.owner
+ if role == self.UrlRole:
+ return project.url
+
+ return None
+
+ def rowCount(self, parent: QModelIndex | QPersistentModelIndex = QModelIndex()) -> int:
+ return len(self.projects)
+
+ def roleNames(self) -> dict[int, QByteArray]:
+ return {
+ self.NameRole: QByteArray(b"name"),
+ self.OwnerRole: QByteArray(b"owner"),
+ self.UrlRole: QByteArray(b"url")
+ }
+
+ @Slot(int, result=Project)
+ def get(self, index: int) -> Project:
+ return self.projects[index]
+
+ def _load_projects(self, data: list[dict[str, Any]]) -> None:
+ for project in data:
+ self.projects.append(Project(
+ project['name'],
+ project['owner'],
+ project['url']
+ ))
+
+ def _save_projects(self):
+ project_config = self._project_file()
+ data = [{'name': project.name, 'owner': project.owner, 'url': project.url} for project in self.projects]
+
+ with open(self._project_file(), 'w') as fp:
+ json.dump(data, fp)
+
+ @Slot(str, str, str)
+ def add(self, name: str, owner: str, url: str) -> None:
+ self.beginInsertRows(QModelIndex(), self.rowCount(), self.rowCount())
+ self.projects.append(Project(name, owner, url))
+ self._save_projects()
+ self.endInsertRows()
diff --git a/kodereviewer/models/pull_request.py b/kodereviewer/models/pull_request.py
new file mode 100644
index 0000000..7d08efa
--- /dev/null
+++ b/kodereviewer/models/pull_request.py
@@ -0,0 +1,75 @@
+import json
+from os import path
+from typing import Any, Optional
+
+from PySide6.QtCore import QAbstractListModel, QByteArray, QModelIndex, QObject, QPersistentModelIndex, QStandardPaths, QUrl, Qt, Signal, Slot, Property
+from PySide6.QtQml import QmlElement
+
+from kodereviewer.project import Project
+from kodereviewer.data import PullRequest
+
+QML_IMPORT_NAME = "org.deprecated.kodereviewer"
+QML_IMPORT_MAJOR_VERSION = 1
+
+@QmlElement
+class PullRequestModel(QAbstractListModel):
+
+ _project: Optional[Project]
+
+ NumberRole = Qt.ItemDataRole.UserRole + 1
+ TitleRole = NumberRole + 1
+
+ def __init__(self):
+ super().__init__()
+
+ def data(self,
+ index: QModelIndex | QPersistentModelIndex,
+ role: int = Qt.ItemDataRole.DisplayRole) -> object:
+ if self._project is None:
+ return None
+
+ pull_request = self._project.pullRequests[index.row()]
+ if role == self.NumberRole:
+ return pull_request.number
+ if role == self.TitleRole:
+ return pull_request.title
+ if role == Qt.ItemDataRole.DisplayRole:
+ return f'{pull_request.number} - {pull_request.title}'
+ return None
+
+ def rowCount(self, parent: QModelIndex | QPersistentModelIndex = QModelIndex()) -> int:
+ if self._project is not None:
+ return len(self._project.pullRequests)
+ return 0
+
+ def roleNames(self) -> dict[int, QByteArray]:
+ return {
+ self.NumberRole: QByteArray(b"number"),
+ self.TitleRole: QByteArray(b"title"),
+ }
+
+ def get_project(self) -> Optional[Project]:
+ return self._project
+
+ def set_project(self, project: Optional[Project])-> None:
+ if project is None:
+ return
+
+ self._project = project
+ assert self._project is not None
+
+ self._project.pullRequestsChanged.connect(self._reset_model)
+
+ project = Property(Project, fget=get_project, fset=set_project)
+
+ @Slot(int, result=PullRequest)
+ def get(self, index: int) -> Optional[PullRequest]:
+ if self._project is not None:
+ return self._project.pullRequests[index]
+ return None
+
+
+ def _reset_model(self) -> None:
+ print("Reseting pull request model")
+ self.beginResetModel()
+ self.endResetModel()