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
a10c4c7a
Commit
a10c4c7a
authored
Feb 11, 2022
by
Waqar Ahmed
Committed by
Christoph Cullmann
Feb 13, 2022
Browse files
Use a listview for the bar display
parent
d0f19b54
Changes
2
Hide whitespace changes
Inline
Side-by-side
kate/kateurlbar.cpp
View file @
a10c4c7a
...
...
@@ -11,6 +11,7 @@
#include
<QAbstractListModel>
#include
<QAction>
#include
<QApplication>
#include
<QDir>
#include
<QHBoxLayout>
#include
<QIcon>
...
...
@@ -18,7 +19,10 @@
#include
<QListView>
#include
<QMenu>
#include
<QMimeDatabase>
#include
<QPainter>
#include
<QScrollBar>
#include
<QStandardItemModel>
#include
<QStyledItemDelegate>
#include
<QToolButton>
#include
<QUrl>
...
...
@@ -62,6 +66,8 @@ public:
void
setDir
(
const
QDir
&
dir
)
{
m_fileInfos
.
clear
();
beginResetModel
();
const
auto
fileInfos
=
dir
.
entryInfoList
(
QDir
::
NoDotAndDotDot
|
QDir
::
Files
|
QDir
::
Dirs
|
QDir
::
Hidden
);
for
(
const
auto
&
fi
:
fileInfos
)
{
...
...
@@ -112,7 +118,7 @@ public:
const
auto
vScroll
=
m_list
.
verticalScrollBar
();
int
w
=
m_list
.
sizeHintForColumn
(
0
)
+
(
vScroll
?
vScroll
->
height
()
/
2
:
0
);
setFixedSize
(
qMin
(
w
,
3
00
),
qMin
(
h
,
600
));
setFixedSize
(
qMin
(
w
,
5
00
),
qMin
(
h
,
600
));
}
void
onClicked
(
const
QModelIndex
&
idx
)
...
...
@@ -138,16 +144,178 @@ private:
DirFilesModel
m_model
;
};
enum
BreadCrumbRole
{
PathRole
=
Qt
::
UserRole
+
1
,
IsFile
=
Qt
::
UserRole
+
2
,
};
class
BreadCrumbDelegate
:
public
QStyledItemDelegate
{
Q_OBJECT
public:
using
QStyledItemDelegate
::
QStyledItemDelegate
;
bool
isDir
(
const
QModelIndex
&
idx
)
const
{
return
!
idx
.
data
(
BreadCrumbRole
::
PathRole
).
toString
().
isEmpty
();
}
void
paint
(
QPainter
*
painter
,
const
QStyleOptionViewItem
&
opt
,
const
QModelIndex
&
index
)
const
override
{
auto
option
=
opt
;
if
(
isDir
(
index
)
&&
option
.
state
&
QStyle
::
State_MouseOver
)
{
painter
->
fillRect
(
opt
.
rect
,
option
.
palette
.
brush
(
QPalette
::
Inactive
,
QPalette
::
Highlight
));
}
QStyledItemDelegate
::
paint
(
painter
,
opt
,
index
);
}
QSize
sizeHint
(
const
QStyleOptionViewItem
&
opt
,
const
QModelIndex
&
idx
)
const
override
{
constexpr
int
hMargin
=
2
;
const
auto
str
=
idx
.
data
(
Qt
::
DisplayRole
).
toString
();
if
(
!
str
.
isEmpty
())
{
auto
size
=
QStyledItemDelegate
::
sizeHint
(
opt
,
idx
);
const
int
w
=
opt
.
fontMetrics
.
horizontalAdvance
(
str
)
+
8
;
size
.
rwidth
()
=
w
;
if
(
idx
.
data
(
BreadCrumbRole
::
IsFile
).
toBool
()
&&
!
idx
.
data
(
Qt
::
DecorationRole
).
isNull
())
{
size
.
rwidth
()
+=
16
+
hMargin
+
hMargin
;
}
return
size
;
}
else
if
(
!
idx
.
data
(
Qt
::
DecorationRole
).
isNull
())
{
QSize
s
(
16
,
16
);
s
=
s
.
grownBy
({
hMargin
,
0
,
hMargin
,
0
});
return
s
;
}
return
QStyledItemDelegate
::
sizeHint
(
opt
,
idx
);
}
};
class
BreadCrumbView
:
public
QListView
{
Q_OBJECT
public:
BreadCrumbView
(
QWidget
*
parent
=
nullptr
)
:
QListView
(
parent
)
{
setFlow
(
QListView
::
LeftToRight
);
setModel
(
&
m_model
);
setFrameStyle
(
QFrame
::
NoFrame
);
setSelectionMode
(
QAbstractItemView
::
NoSelection
);
setVerticalScrollBarPolicy
(
Qt
::
ScrollBarAlwaysOff
);
setHorizontalScrollBarPolicy
(
Qt
::
ScrollBarAlwaysOff
);
setItemDelegate
(
new
BreadCrumbDelegate
(
this
));
setEditTriggers
(
QAbstractItemView
::
NoEditTriggers
);
connect
(
qApp
,
&
QApplication
::
paletteChanged
,
this
,
&
BreadCrumbView
::
updatePalette
,
Qt
::
QueuedConnection
);
auto
font
=
this
->
font
();
font
.
setPointSize
(
font
.
pointSize
()
-
1
);
setFont
(
font
);
updatePalette
();
connect
(
this
,
&
QListView
::
clicked
,
this
,
&
BreadCrumbView
::
onClicked
);
}
void
updatePalette
()
{
auto
pal
=
palette
();
pal
.
setBrush
(
QPalette
::
Base
,
parentWidget
()
->
palette
().
window
());
setPalette
(
pal
);
}
void
setUrl
(
const
QUrl
&
url
)
{
if
(
url
.
isEmpty
())
{
return
;
}
const
QString
s
=
url
.
toString
(
QUrl
::
NormalizePathSegments
|
QUrl
::
PreferLocalFile
);
const
auto
res
=
splittedUrl
(
s
);
const
auto
&
file
=
res
.
first
;
const
auto
&
dirs
=
res
.
second
;
m_model
.
clear
();
for
(
const
auto
&
dir
:
dirs
)
{
auto
item
=
new
QStandardItem
(
dir
.
name
);
item
->
setData
(
dir
.
path
,
BreadCrumbRole
::
PathRole
);
m_model
.
appendRow
(
item
);
auto
sep
=
new
QStandardItem
(
QIcon
::
fromTheme
(
QStringLiteral
(
"arrow-right"
)),
{});
m_model
.
appendRow
(
sep
);
}
const
auto
icon
=
QIcon
::
fromTheme
(
QMimeDatabase
().
mimeTypeForFile
(
s
).
iconName
());
auto
fileRow
=
new
QStandardItem
(
icon
,
file
);
fileRow
->
setData
(
true
,
BreadCrumbRole
::
IsFile
);
m_model
.
appendRow
(
fileRow
);
}
void
onClicked
(
const
QModelIndex
&
idx
)
{
auto
path
=
idx
.
data
(
BreadCrumbRole
::
PathRole
).
toString
();
if
(
path
.
isEmpty
())
{
return
;
}
auto
pos
=
mapToGlobal
(
rectForIndex
(
idx
).
bottomLeft
());
QDir
d
(
path
);
DirFilesList
m
(
this
);
auto
par
=
static_cast
<
KateUrlBar
*>
(
parentWidget
());
connect
(
&
m
,
&
DirFilesList
::
openUrl
,
par
,
&
KateUrlBar
::
openUrlRequested
);
m
.
setDir
(
d
);
m
.
exec
(
pos
);
}
private:
struct
DirNamePath
{
QString
name
;
QString
path
;
};
std
::
pair
<
QString
,
QVector
<
DirNamePath
>>
splittedUrl
(
const
QString
&
s
)
{
const
int
slashIndex
=
s
.
lastIndexOf
(
QLatin1Char
(
'/'
));
if
(
slashIndex
==
-
1
)
{
return
{};
}
const
QString
fileName
=
s
.
mid
(
slashIndex
+
1
);
QDir
dir
(
s
);
QVector
<
DirNamePath
>
dirsList
;
while
(
dir
.
cdUp
())
{
if
(
dir
.
dirName
().
isEmpty
())
{
continue
;
}
DirNamePath
dnp
{
dir
.
dirName
(),
dir
.
absolutePath
()};
dirsList
.
push_back
(
dnp
);
}
std
::
reverse
(
dirsList
.
begin
(),
dirsList
.
end
());
return
{
fileName
,
dirsList
};
}
QStandardItemModel
m_model
;
};
KateUrlBar
::
KateUrlBar
(
KateViewSpace
*
parent
)
:
QWidget
(
parent
)
{
setFixedHeight
(
2
5
);
setFixedHeight
(
2
4
);
setContentsMargins
({});
m_layout
=
new
QHBoxLayout
(
this
);
m_layout
->
setContentsMargins
({});
m_layout
->
setSpacing
(
0
);
m_breadCrumbView
=
new
BreadCrumbView
(
this
);
m_layout
->
addWidget
(
m_breadCrumbView
);
auto
*
vm
=
parent
->
viewManger
();
connect
(
vm
,
&
KateViewManager
::
viewChanged
,
this
,
&
KateUrlBar
::
onViewChanged
);
...
...
@@ -172,119 +340,17 @@ void KateUrlBar::onViewChanged(KTextEditor::View *v)
if
(
vm
&&
!
vm
->
showUrlNavBar
())
{
return
;
}
m_paths
.
clear
();
QLayoutItem
*
l
;
while
((
l
=
m_layout
->
takeAt
(
0
))
!=
nullptr
)
{
delete
l
->
widget
();
delete
l
;
}
const
auto
url
=
v
->
document
()
->
url
();
if
(
url
.
isEmpty
())
{
if
(
url
.
isEmpty
()
||
!
url
.
isLocalFile
()
)
{
hide
();
return
;
}
auto
res
=
splittedUrl
(
url
);
const
auto
&
file
=
res
.
first
;
const
auto
&
dirs
=
res
.
second
;
if
(
dirs
.
isEmpty
()
||
file
.
isEmpty
())
{
hide
();
return
;
}
m_breadCrumbView
->
setUrl
(
v
->
document
()
->
url
());
for
(
const
auto
&
dir
:
dirs
)
{
m_layout
->
addWidget
(
dirButton
(
dir
.
name
,
dir
.
path
));
m_layout
->
addWidget
(
separatorLabel
());
}
m_layout
->
addWidget
(
fileLabel
(
file
));
m_layout
->
addStretch
();
if
(
isHidden
())
show
();
}
std
::
pair
<
QString
,
QVector
<
KateUrlBar
::
DirNamePath
>>
KateUrlBar
::
splittedUrl
(
const
QUrl
&
u
)
{
QString
s
=
u
.
toString
(
QUrl
::
NormalizePathSegments
|
QUrl
::
PreferLocalFile
);
const
int
slashIndex
=
s
.
lastIndexOf
(
QLatin1Char
(
'/'
));
if
(
slashIndex
==
-
1
)
{
return
{};
}
const
QString
fileName
=
s
.
mid
(
slashIndex
+
1
);
QDir
dir
(
s
);
QVector
<
DirNamePath
>
dirsList
;
while
(
dir
.
cdUp
())
{
if
(
dir
.
dirName
().
isEmpty
())
{
continue
;
}
DirNamePath
dnp
{
dir
.
dirName
(),
dir
.
absolutePath
()};
dirsList
.
push_back
(
dnp
);
}
std
::
reverse
(
dirsList
.
begin
(),
dirsList
.
end
());
return
{
fileName
,
dirsList
};
}
QLabel
*
KateUrlBar
::
separatorLabel
()
{
QLabel
*
sep
=
new
QLabel
(
this
);
sep
->
setPixmap
(
QIcon
::
fromTheme
(
QStringLiteral
(
"arrow-right"
)).
pixmap
(
QSize
(
16
,
16
)));
return
sep
;
}
QToolButton
*
KateUrlBar
::
dirButton
(
const
QString
&
dirName
,
const
QString
&
path
)
{
QToolButton
*
tb
=
new
QToolButton
(
this
);
tb
->
setText
(
dirName
);
tb
->
setArrowType
(
Qt
::
RightArrow
);
tb
->
setToolButtonStyle
(
Qt
::
ToolButtonTextOnly
);
tb
->
setAutoRaise
(
true
);
connect
(
tb
,
&
QToolButton
::
clicked
,
this
,
&
KateUrlBar
::
pathClicked
);
m_paths
.
push_back
({
tb
,
path
});
return
tb
;
}
QLabel
*
KateUrlBar
::
fileLabel
(
const
QString
&
file
)
{
auto
l
=
new
QLabel
(
file
);
auto
font
=
l
->
font
();
font
.
setPointSize
(
font
.
pointSize
()
-
1
);
l
->
setFont
(
font
);
l
->
setAlignment
(
Qt
::
AlignCenter
);
l
->
setContentsMargins
({
6
,
0
,
0
,
0
});
return
l
;
}
void
KateUrlBar
::
pathClicked
()
{
auto
button
=
sender
();
if
(
!
button
)
{
return
;
}
// Find the path that this toolbutton refers to
auto
it
=
std
::
find_if
(
m_paths
.
begin
(),
m_paths
.
end
(),
[
button
](
const
std
::
pair
<
QToolButton
*
,
QString
>
&
tbPath
)
{
return
tbPath
.
first
==
button
;
});
// not found?
if
(
it
==
m_paths
.
end
())
{
return
;
}
const
QToolButton
*
tb
=
it
->
first
;
const
QString
path
=
it
->
second
;
QDir
d
(
path
);
DirFilesList
m
(
this
);
connect
(
&
m
,
&
DirFilesList
::
openUrl
,
this
,
&
KateUrlBar
::
openUrlRequested
);
m
.
setDir
(
d
);
auto
pos
=
tb
->
mapToGlobal
(
tb
->
pos
())
-
tb
->
pos
();
pos
.
setY
(
pos
.
y
()
+
tb
->
height
());
m
.
exec
(
pos
);
}
#include
"kateurlbar.moc"
kate/kateurlbar.h
View file @
a10c4c7a
...
...
@@ -18,20 +18,9 @@ Q_SIGNALS:
void
openUrlRequested
(
const
QUrl
&
url
);
private:
// helper struct containing dir name and path
struct
DirNamePath
{
QString
name
;
QString
path
;
};
void
onViewChanged
(
KTextEditor
::
View
*
v
);
std
::
pair
<
QString
,
QVector
<
DirNamePath
>>
splittedUrl
(
const
QUrl
&
u
);
class
QLabel
*
separatorLabel
();
class
QToolButton
*
dirButton
(
const
QString
&
dirName
,
const
QString
&
path
);
class
QLabel
*
fileLabel
(
const
QString
&
file
);
class
QHBoxLayout
*
m_layout
;
void
pathClicked
();
QVector
<
std
::
pair
<
QToolButton
*
,
QString
>>
m_paths
;
class
BreadCrumbView
*
m_breadCrumbView
;
};
#endif
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