| 1 | #include <IssueItem.h> |
| 2 | |
| 3 | #include <ButtonLink.hpp> |
| 4 | #include <PullRequest.h> |
| 5 | |
| 6 | #include <QDir> |
| 7 | #include <QFile> |
| 8 | #include <QUrl> |
| 9 | #include <QGridLayout> |
| 10 | #include <QDesktopServices> |
| 11 | #include <QLocale> |
| 12 | |
| 13 | using namespace GitServer; |
| 14 | |
| 15 | IssueItem::IssueItem(const Issue &issueData, QWidget *parent) |
| 16 | : QFrame(parent) |
| 17 | , mComments(new QLabel()) |
| 18 | { |
| 19 | setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Maximum); |
| 20 | |
| 21 | fillWidget(issueData); |
| 22 | |
| 23 | mComments->setText(QString::number(issueData.commentsCount)); |
| 24 | } |
| 25 | |
| 26 | IssueItem::IssueItem(const PullRequest &issueData, QWidget *parent) |
| 27 | : QFrame(parent) |
| 28 | , mComments(new QLabel()) |
| 29 | { |
| 30 | fillWidget(issueData); |
| 31 | |
| 32 | mComments->setText(QString::number(issueData.commentsCount + issueData.reviewCommentsCount)); |
| 33 | } |
| 34 | |
| 35 | void IssueItem::fillWidget(const Issue &issueData) |
| 36 | { |
| 37 | const auto title = new ButtonLink(QString("#%1 - %2" ).arg(issueData.number).arg(issueData.title)); |
| 38 | title->setWordWrap(true); |
| 39 | title->setObjectName("IssueTitle" ); |
| 40 | connect(title, &ButtonLink::clicked, this, [this, issueNum = issueData.number]() { emit selected(issueNum); }); |
| 41 | |
| 42 | const auto titleLayout = new QHBoxLayout(); |
| 43 | titleLayout->setContentsMargins(QMargins()); |
| 44 | titleLayout->setSpacing(0); |
| 45 | titleLayout->addWidget(title); |
| 46 | |
| 47 | const auto creationLayout = new QHBoxLayout(); |
| 48 | creationLayout->setContentsMargins(QMargins()); |
| 49 | creationLayout->setSpacing(0); |
| 50 | creationLayout->addWidget(new QLabel(tr("<i>Created by </i>" ))); |
| 51 | const auto creator = new ButtonLink(QString("<i><b>%1</b></i>" ).arg(issueData.creator.name)); |
| 52 | creator->setObjectName("CreatorLink" ); |
| 53 | connect(creator, &ButtonLink::clicked, [url = issueData.url]() { QDesktopServices::openUrl(url); }); |
| 54 | |
| 55 | creationLayout->addWidget(creator); |
| 56 | |
| 57 | const auto days = issueData.creation.daysTo(QDateTime::currentDateTime()); |
| 58 | const auto whenText = days <= 30 |
| 59 | ? tr("<i> %1 days ago</i>" ).arg(days) |
| 60 | : tr("<i> on %1</i>" ).arg(issueData.creation.date().toString(QLocale().dateFormat(QLocale::ShortFormat))); |
| 61 | |
| 62 | const auto whenLabel = new QLabel(whenText); |
| 63 | whenLabel->setToolTip(issueData.creation.toString(QLocale().dateFormat(QLocale::ShortFormat))); |
| 64 | |
| 65 | creationLayout->addWidget(whenLabel); |
| 66 | creationLayout->addStretch(); |
| 67 | |
| 68 | const auto layout = new QVBoxLayout(); |
| 69 | layout->setContentsMargins(QMargins()); |
| 70 | layout->setSpacing(5); |
| 71 | layout->addLayout(titleLayout); |
| 72 | layout->addLayout(creationLayout); |
| 73 | |
| 74 | if (!issueData.assignees.isEmpty()) |
| 75 | { |
| 76 | const auto assigneeLayout = new QHBoxLayout(); |
| 77 | assigneeLayout->setContentsMargins(QMargins()); |
| 78 | assigneeLayout->setSpacing(0); |
| 79 | assigneeLayout->addWidget(new QLabel(tr("Assigned to " ))); |
| 80 | |
| 81 | auto count = 0; |
| 82 | const auto totalAssignees = issueData.assignees.count(); |
| 83 | for (auto &assignee : issueData.assignees) |
| 84 | { |
| 85 | const auto assigneLabel = new ButtonLink(QString("<b>%1</b>" ).arg(assignee.name)); |
| 86 | assigneLabel->setObjectName("CreatorLink" ); |
| 87 | connect(assigneLabel, &ButtonLink::clicked, [url = assignee.url]() { QDesktopServices::openUrl(url); }); |
| 88 | assigneeLayout->addWidget(assigneLabel); |
| 89 | |
| 90 | if (count++ < totalAssignees - 1) |
| 91 | assigneeLayout->addWidget(new QLabel(", " )); |
| 92 | } |
| 93 | assigneeLayout->addStretch(); |
| 94 | |
| 95 | layout->addLayout(assigneeLayout); |
| 96 | } |
| 97 | |
| 98 | if (!issueData.labels.isEmpty()) |
| 99 | { |
| 100 | const auto labelsLayout = new QHBoxLayout(); |
| 101 | labelsLayout->setContentsMargins(QMargins()); |
| 102 | labelsLayout->setSpacing(10); |
| 103 | |
| 104 | QStringList labelsList; |
| 105 | |
| 106 | for (auto &label : issueData.labels) |
| 107 | { |
| 108 | auto labelWidget = new QLabel(); |
| 109 | labelWidget->setStyleSheet(QString("QLabel {" |
| 110 | "background-color: #%1;" |
| 111 | "border-radius: 7px;" |
| 112 | "min-height: 15px;" |
| 113 | "max-height: 15px;" |
| 114 | "min-width: 15px;" |
| 115 | "max-width: 15px;}" ) |
| 116 | .arg(label.colorHex)); |
| 117 | labelWidget->setToolTip(label.name); |
| 118 | labelsLayout->addWidget(labelWidget); |
| 119 | } |
| 120 | |
| 121 | const auto milestone = new QLabel(QString("%1" ).arg(issueData.milestone.title)); |
| 122 | milestone->setObjectName("IssueLabel" ); |
| 123 | labelsLayout->addWidget(milestone); |
| 124 | labelsLayout->addStretch(); |
| 125 | layout->addLayout(labelsLayout); |
| 126 | } |
| 127 | |
| 128 | QPixmap pic(":/icons/comment" ); |
| 129 | pic = pic.scaled(15, 15, Qt::KeepAspectRatio, Qt::SmoothTransformation); |
| 130 | |
| 131 | const auto icon = new QLabel(); |
| 132 | icon->setPixmap(pic); |
| 133 | |
| 134 | const auto = new QGridLayout(); |
| 135 | commentsLayout->addWidget(mComments, 0, 0); |
| 136 | commentsLayout->addWidget(icon, 0, 1); |
| 137 | commentsLayout->addItem(new QSpacerItem(1, 1, QSizePolicy::Fixed, QSizePolicy::Expanding), 1, 0, 1, 2); |
| 138 | |
| 139 | const auto mainLayout = new QHBoxLayout(this); |
| 140 | mainLayout->setContentsMargins(10, 10, 10, 10); |
| 141 | mainLayout->addLayout(layout); |
| 142 | mainLayout->addLayout(commentsLayout); |
| 143 | } |
| 144 | |