File indexing completed on 2024-04-28 05:49:04

0001 /*
0002     SPDX-FileCopyrightText: 2021 Waqar Ahmed <waqar.17a@gmail.com>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 #include "branchesdialog.h"
0007 #include "branchesdialogmodel.h"
0008 #include "gitprocess.h"
0009 #include "ktexteditor_utils.h"
0010 
0011 #include <QPainter>
0012 #include <QTreeView>
0013 #include <QWidget>
0014 
0015 #include <KFuzzyMatcher>
0016 #include <KLocalizedString>
0017 #include <KTextEditor/Message>
0018 #include <KTextEditor/View>
0019 
0020 #include <drawing_utils.h>
0021 
0022 class StyleDelegate : public HUDStyleDelegate
0023 {
0024 public:
0025     using HUDStyleDelegate::HUDStyleDelegate;
0026 
0027     void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override
0028     {
0029         QStyleOptionViewItem options = option;
0030         initStyleOption(&options, index);
0031 
0032         auto name = index.data().toString();
0033 
0034         QList<QTextLayout::FormatRange> formats;
0035         QTextCharFormat fmt;
0036         fmt.setForeground(options.palette.link());
0037         fmt.setFontWeight(QFont::Bold);
0038 
0039         const auto itemType = (BranchesDialogModel::ItemType)index.data(BranchesDialogModel::ItemTypeRole).toInt();
0040         const bool branchItem = itemType == BranchesDialogModel::BranchItem;
0041         const int offset = branchItem ? 0 : 2;
0042 
0043         const auto ranges = KFuzzyMatcher::matchedRanges(m_filterString, name);
0044         std::transform(ranges.begin(), ranges.end(), std::back_inserter(formats), [offset, fmt](const KFuzzyMatcher::Range &fr) {
0045             return QTextLayout::FormatRange{fr.start + offset, fr.length, fmt};
0046         });
0047 
0048         if (!branchItem) {
0049             name = QStringLiteral("+ ") + name;
0050         }
0051 
0052         const int nameLen = name.length();
0053         int len = 6;
0054         if (branchItem) {
0055             const auto refType = (GitUtils::RefType)index.data(BranchesDialogModel::RefType).toInt();
0056             using RefType = GitUtils::RefType;
0057             if (refType == RefType::Head) {
0058                 name.append(QStringLiteral(" local"));
0059             } else if (refType == RefType::Remote) {
0060                 name.append(QStringLiteral(" remote"));
0061                 len = 7;
0062             }
0063         }
0064         QTextCharFormat lf;
0065         lf.setFontItalic(true);
0066         lf.setForeground(Qt::gray);
0067         formats.append({nameLen, len, lf});
0068 
0069         painter->save();
0070 
0071         auto *style = options.widget->style();
0072         options.text = QString(); // clear old text
0073         style->drawControl(QStyle::CE_ItemViewItem, &options, painter, options.widget);
0074 
0075         // leave space for icon
0076         const int hMargin = style->pixelMetric(QStyle::PM_FocusFrameHMargin, &option, option.widget);
0077         const int iconWidth = option.decorationSize.width() + (hMargin * 2);
0078         if (itemType == BranchesDialogModel::BranchItem) {
0079             options.rect.adjust(iconWidth, 0, 0, 0);
0080         } else {
0081             options.rect.adjust((hMargin * 2), 0, 0, 0);
0082         }
0083         Utils::paintItemViewText(painter, name, options, formats);
0084 
0085         painter->restore();
0086     }
0087 };
0088 
0089 BranchesDialog::BranchesDialog(QWidget *window, QString projectPath)
0090     : HUDDialog(nullptr, window)
0091     , m_model(new BranchesDialogModel(this))
0092     , m_projectPath(projectPath)
0093 {
0094     setModel(m_model, FilterType::ScoredFuzzy, 0, Qt::DisplayRole, BranchesDialogModel::FuzzyScore);
0095     setDelegate(new StyleDelegate(this));
0096 }
0097 
0098 void BranchesDialog::openDialog(GitUtils::RefType r)
0099 {
0100     m_lineEdit.setPlaceholderText(i18n("Select Branch..."));
0101 
0102     QList<GitUtils::Branch> branches = GitUtils::getAllBranchesAndTags(m_projectPath, r);
0103     m_model->refresh(branches);
0104 
0105     reselectFirst();
0106     exec();
0107 }
0108 
0109 void BranchesDialog::slotReturnPressed(const QModelIndex &index)
0110 {
0111     if (index.isValid()) {
0112         const auto branch = index.data().toString();
0113         const auto itemType = (BranchesDialogModel::ItemType)index.data(BranchesDialogModel::ItemTypeRole).toInt();
0114         Q_ASSERT(itemType == BranchesDialogModel::BranchItem);
0115 
0116         m_branch = branch;
0117         Q_EMIT branchSelected(branch);
0118     }
0119 
0120     clearLineEdit();
0121     hide();
0122 }
0123 
0124 void BranchesDialog::sendMessage(const QString &plainText, bool warn)
0125 {
0126     Utils::showMessage(plainText, gitIcon(), i18n("Git"), warn ? MessageType::Error : MessageType::Info);
0127 }
0128 
0129 #include "moc_branchesdialog.cpp"