Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Utilities
Kate
Commits
54865897
Commit
54865897
authored
Mar 15, 2021
by
Waqar Ahmed
Browse files
Show lines add/remove in diff
parent
92a224f1
Changes
7
Hide whitespace changes
Inline
Side-by-side
addons/project/comarebranchesview.cpp
View file @
54865897
...
...
@@ -2,32 +2,131 @@
#include "kateprojectpluginview.h"
#include "kateprojectworker.h"
#include <QPainter>
#include <QProcess>
#include <QStyledItemDelegate>
#include <QVBoxLayout>
#include <KLocalizedString>
#include <QProcess>
static
QVariantMap
createMap
(
const
QStringList
&
files
)
#include <QDebug>
class
DiffStyleDelegate
:
public
QStyledItemDelegate
{
QVariantMap
cnf
,
filesMap
;
filesMap
[
QStringLiteral
(
"list"
)]
=
(
files
);
cnf
[
QStringLiteral
(
"name"
)]
=
QStringLiteral
(
"ComparingBranches"
);
cnf
[
QStringLiteral
(
"files"
)]
=
(
QVariantList
()
<<
filesMap
);
return
cnf
;
public:
DiffStyleDelegate
(
QObject
*
parent
)
:
QStyledItemDelegate
(
parent
)
{
}
void
paint
(
QPainter
*
painter
,
const
QStyleOptionViewItem
&
option
,
const
QModelIndex
&
index
)
const
override
{
if
(
index
.
data
(
KateProjectItem
::
TypeRole
).
toInt
()
==
KateProjectItem
::
Directory
)
{
QStyledItemDelegate
::
paint
(
painter
,
option
,
index
);
return
;
}
QStyleOptionViewItem
options
=
option
;
initStyleOption
(
&
options
,
index
);
painter
->
save
();
// paint background
if
(
option
.
state
&
QStyle
::
State_Selected
)
{
painter
->
fillRect
(
option
.
rect
,
option
.
palette
.
highlight
());
}
else
{
painter
->
fillRect
(
option
.
rect
,
option
.
palette
.
base
());
}
int
add
=
index
.
data
(
Qt
::
UserRole
+
2
).
toInt
();
int
sub
=
index
.
data
(
Qt
::
UserRole
+
3
).
toInt
();
QString
adds
=
QString
(
QStringLiteral
(
"+"
)
+
QString
::
number
(
add
));
QString
subs
=
QString
(
QStringLiteral
(
" -"
)
+
QString
::
number
(
sub
));
QString
file
=
options
.
text
;
options
.
text
=
QString
();
// clear old text
options
.
widget
->
style
()
->
drawControl
(
QStyle
::
CE_ItemViewItem
,
&
options
,
painter
,
options
.
widget
);
QRect
r
=
options
.
rect
;
// don't draw over icon
r
.
setX
(
r
.
x
()
+
option
.
decorationSize
.
width
()
+
5
);
auto
&
fm
=
options
.
fontMetrics
;
// adds width
int
aw
=
fm
.
horizontalAdvance
(
adds
);
// subs width
int
sw
=
fm
.
horizontalAdvance
(
subs
);
// subtract this from total width of rect
int
totalw
=
r
.
width
();
totalw
=
totalw
-
(
aw
+
sw
);
// get file name, elide if necessary
QString
filename
=
fm
.
elidedText
(
file
,
Qt
::
ElideRight
,
totalw
);
painter
->
drawText
(
r
,
Qt
::
AlignVCenter
,
filename
);
static
constexpr
auto
red
=
QColor
(
237
,
21
,
21
);
// Breeze Danger Red
static
constexpr
auto
green
=
QColor
(
17
,
209
,
27
);
// Breeze Verdant Green
r
.
setX
(
r
.
x
()
+
totalw
);
painter
->
setPen
(
green
);
painter
->
drawText
(
r
,
Qt
::
AlignVCenter
,
adds
);
painter
->
setPen
(
red
);
r
.
setX
(
r
.
x
()
+
aw
);
painter
->
drawText
(
r
,
Qt
::
AlignVCenter
,
subs
);
painter
->
restore
();
}
};
static
void
createFileTree
(
QStandardItem
*
parent
,
const
QString
&
basePath
,
const
QVector
<
GitUtils
::
StatusItem
>
&
files
)
{
QDir
dir
(
basePath
);
const
QString
dirPath
=
dir
.
path
()
+
QLatin1Char
(
'/'
);
QHash
<
QString
,
QStandardItem
*>
dir2Item
;
dir2Item
[
QString
()]
=
parent
;
for
(
const
auto
&
file
:
qAsConst
(
files
))
{
const
QString
filePath
=
QString
::
fromUtf8
(
file
.
file
);
/**
* cheap file name computation
* we do this A LOT, QFileInfo is very expensive just for this operation
*/
const
int
slashIndex
=
filePath
.
lastIndexOf
(
QLatin1Char
(
'/'
));
const
QString
fileName
=
(
slashIndex
<
0
)
?
filePath
:
filePath
.
mid
(
slashIndex
+
1
);
const
QString
filePathName
=
(
slashIndex
<
0
)
?
QString
()
:
filePath
.
left
(
slashIndex
);
const
QString
fullFilePath
=
dirPath
+
filePath
;
/**
* construct the item with right directory prefix
* already hang in directories in tree
*/
KateProjectItem
*
fileItem
=
new
KateProjectItem
(
KateProjectItem
::
File
,
fileName
);
fileItem
->
setData
(
fullFilePath
,
Qt
::
UserRole
);
fileItem
->
setData
(
file
.
statusChar
,
Qt
::
UserRole
+
1
);
fileItem
->
setData
(
file
.
linesAdded
,
Qt
::
UserRole
+
2
);
fileItem
->
setData
(
file
.
linesRemoved
,
Qt
::
UserRole
+
3
);
// put in our item to the right directory parent
KateProjectWorker
::
directoryParent
(
dir
,
dir2Item
,
filePathName
)
->
appendRow
(
fileItem
);
}
}
CompareBranchesView
::
CompareBranchesView
(
QWidget
*
parent
,
const
QString
&
gitPath
,
const
QString
fromB
,
const
QString
&
toBr
,
Q
StringList
file
s
)
CompareBranchesView
::
CompareBranchesView
(
QWidget
*
parent
,
const
QString
&
gitPath
,
const
QString
fromB
,
const
QString
&
toBr
,
Q
Vector
<
GitUtils
::
StatusItem
>
item
s
)
:
QWidget
(
parent
)
,
m_files
(
std
::
move
(
files
))
,
m_gitDir
(
gitPath
)
,
m_fromBr
(
fromB
)
,
m_toBr
(
toBr
)
{
setLayout
(
new
QVBoxLayout
);
KateProjectWorker
*
w
=
new
KateProjectWorker
(
m_gitDir
,
QString
(),
createMap
(
m_files
),
true
);
connect
(
w
,
&
KateProjectWorker
::
loadDone
,
this
,
&
CompareBranchesView
::
loadFilesDone
,
Qt
::
QueuedConnection
);
w
->
run
();
QStandardItem
*
root
=
new
QStandardItem
;
createFileTree
(
root
,
m_gitDir
,
items
);
m_model
.
clear
();
m_model
.
invisibleRootItem
()
->
appendColumn
(
root
->
takeColumn
(
0
));
m_backBtn
.
setText
(
i18n
(
"Back"
));
m_backBtn
.
setIcon
(
QIcon
::
fromTheme
(
QStringLiteral
(
"draw-arrow-back.svg"
)));
...
...
@@ -38,17 +137,12 @@ CompareBranchesView::CompareBranchesView(QWidget *parent, const QString &gitPath
layout
()
->
addWidget
(
&
m_tree
);
m_tree
.
setHeaderHidden
(
true
);
m_tree
.
setItemDelegate
(
new
DiffStyleDelegate
(
this
));
m_tree
.
expandAll
();
connect
(
&
m_tree
,
&
QTreeView
::
clicked
,
this
,
&
CompareBranchesView
::
showDiff
);
}
void
CompareBranchesView
::
loadFilesDone
(
const
KateProjectSharedQStandardItem
&
topLevel
,
KateProjectSharedQHashStringItem
)
{
m_model
.
clear
();
m_model
.
invisibleRootItem
()
->
appendColumn
(
topLevel
->
takeColumn
(
0
));
m_tree
.
expandAll
();
}
void
CompareBranchesView
::
showDiff
(
const
QModelIndex
&
idx
)
{
auto
file
=
idx
.
data
(
Qt
::
UserRole
).
toString
().
remove
(
m_gitDir
+
QLatin1Char
(
'/'
));
...
...
addons/project/comarebranchesview.h
View file @
54865897
...
...
@@ -6,14 +6,14 @@
#include <QTreeView>
#include <QWidget>
#include
<kateproject
.h
>
#include
"git/gitstatus
.h
"
class
KateProjectPluginView
;
class
CompareBranchesView
:
public
QWidget
{
Q_OBJECT
public:
explicit
CompareBranchesView
(
QWidget
*
parent
,
const
QString
&
gitPath
,
const
QString
fromB
,
const
QString
&
toBr
,
Q
StringList
file
s
);
explicit
CompareBranchesView
(
QWidget
*
parent
,
const
QString
&
gitPath
,
const
QString
fromB
,
const
QString
&
toBr
,
Q
Vector
<
GitUtils
::
StatusItem
>
item
s
);
void
setPluginView
(
KateProjectPluginView
*
pv
)
{
m_pluginView
=
pv
;
...
...
@@ -22,13 +22,11 @@ public:
Q_SIGNAL
void
backClicked
();
private
Q_SLOTS
:
void
loadFilesDone
(
const
KateProjectSharedQStandardItem
&
topLevel
,
KateProjectSharedQHashStringItem
file2Item
);
void
showDiff
(
const
QModelIndex
&
idx
);
private:
QPushButton
m_backBtn
;
QTreeView
m_tree
;
QStringList
m_files
;
QStandardItemModel
m_model
;
QString
m_gitDir
;
QString
m_fromBr
;
...
...
addons/project/git/gitstatus.cpp
View file @
54865897
...
...
@@ -167,3 +167,23 @@ void GitUtils::parseDiffNumStat(QVector<GitUtils::StatusItem> &items, const QByt
addNumStat
(
items
,
add
,
sub
,
file
);
}
}
QVector
<
GitUtils
::
StatusItem
>
GitUtils
::
parseDiffNameStatus
(
const
QByteArray
&
raw
)
{
const
auto
lines
=
raw
.
split
(
'\n'
);
QVector
<
GitUtils
::
StatusItem
>
out
;
out
.
reserve
(
lines
.
size
());
for
(
const
auto
&
l
:
lines
)
{
const
auto
cols
=
l
.
split
(
'\t'
);
if
(
cols
.
size
()
<
2
)
{
continue
;
}
GitUtils
::
StatusItem
i
;
i
.
statusChar
=
cols
[
0
][
0
];
i
.
file
=
cols
[
1
];
out
.
append
(
i
);
}
return
out
;
}
addons/project/git/gitstatus.h
View file @
54865897
...
...
@@ -68,6 +68,8 @@ GitParsedStatus parseStatus(const QByteArray &raw);
void
parseDiffNumStat
(
QVector
<
GitUtils
::
StatusItem
>
&
items
,
const
QByteArray
&
raw
);
QVector
<
StatusItem
>
parseDiffNameStatus
(
const
QByteArray
&
raw
);
QString
statusString
(
GitStatus
s
);
}
...
...
addons/project/gitwidget.cpp
View file @
54865897
...
...
@@ -738,7 +738,7 @@ void GitWidget::numStatForStatus(QVector<GitUtils::StatusItem> &list, bool modif
void
GitWidget
::
branchCompareFiles
(
const
QString
&
from
,
const
QString
&
to
)
{
// git diff br...br2 --name-only -z
const
auto
args
=
QStringList
{
QStringLiteral
(
"diff"
),
QStringLiteral
(
"%1...%2"
).
arg
(
from
).
arg
(
to
),
QStringLiteral
(
"--name-
only"
),
QStringLiteral
(
"-z
"
)};
auto
args
=
QStringList
{
QStringLiteral
(
"diff"
),
QStringLiteral
(
"%1...%2"
).
arg
(
from
).
arg
(
to
),
QStringLiteral
(
"--name-
status
"
)};
QProcess
git
;
git
.
setWorkingDirectory
(
m_gitPath
);
...
...
@@ -748,13 +748,27 @@ void GitWidget::branchCompareFiles(const QString &from, const QString &to)
return
;
}
}
QList
<
QByteArray
>
files
=
git
.
readAllStandardOutput
().
split
(
0x00
);
QStringList
filesList
;
std
::
transform
(
files
.
cbegin
(),
files
.
cend
(),
std
::
back_inserter
(
filesList
),
[](
const
QByteArray
&
a
)
{
return
QString
::
fromUtf8
(
a
);
});
CompareBranchesView
*
w
=
new
CompareBranchesView
(
this
,
m_gitPath
,
from
,
to
,
filesList
);
auto
filesWithNameStatus
=
GitUtils
::
parseDiffNameStatus
(
git
.
readAllStandardOutput
());
if
(
filesWithNameStatus
.
isEmpty
())
{
sendMessage
(
i18n
(
"Failed to compare %1...%2"
,
from
,
to
),
true
);
return
;
}
// get --num-stat
args
=
QStringList
{
QStringLiteral
(
"diff"
),
QStringLiteral
(
"%1...%2"
).
arg
(
from
).
arg
(
to
),
QStringLiteral
(
"--numstat"
),
QStringLiteral
(
"-z"
)};
git
.
setArguments
(
args
);
git
.
start
(
QStringLiteral
(
"git"
),
args
,
QProcess
::
ReadOnly
);
if
(
git
.
waitForStarted
()
&&
git
.
waitForFinished
(
-
1
))
{
if
(
git
.
exitStatus
()
!=
QProcess
::
NormalExit
||
git
.
exitCode
()
!=
0
)
{
sendMessage
(
i18n
(
"Failed to get numstat when diffing %1...%2"
,
from
,
to
),
true
);
return
;
}
}
GitUtils
::
parseDiffNumStat
(
filesWithNameStatus
,
git
.
readAllStandardOutput
());
CompareBranchesView
*
w
=
new
CompareBranchesView
(
this
,
m_gitPath
,
from
,
to
,
filesWithNameStatus
);
w
->
setPluginView
(
m_pluginView
);
connect
(
w
,
&
CompareBranchesView
::
backClicked
,
this
,
[
this
]
{
auto
x
=
m_stackWid
->
currentWidget
();
...
...
addons/project/kateprojectworker.cpp
View file @
54865897
...
...
@@ -130,7 +130,7 @@ void KateProjectWorker::loadProject(QStandardItem *parent, const QVariantMap &pr
* @param path current path we need item for
* @return correct parent item for given path, will reuse existing ones
*/
static
QStandardItem
*
directoryParent
(
const
QDir
&
base
,
QHash
<
QString
,
QStandardItem
*>
&
dir2Item
,
QString
path
)
QStandardItem
*
KateProjectWorker
::
directoryParent
(
const
QDir
&
base
,
QHash
<
QString
,
QStandardItem
*>
&
dir2Item
,
QString
path
)
{
/**
* throw away simple /
...
...
addons/project/kateprojectworker.h
View file @
54865897
...
...
@@ -35,6 +35,8 @@ public:
void
run
()
override
;
static
QStandardItem
*
directoryParent
(
const
QDir
&
base
,
QHash
<
QString
,
QStandardItem
*>
&
dir2Item
,
QString
path
);
Q_SIGNALS:
void
loadDone
(
KateProjectSharedQStandardItem
topLevel
,
KateProjectSharedQHashStringItem
file2Item
);
void
loadIndexDone
(
KateProjectSharedProjectIndex
index
);
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment