Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
LEFEBVREJP email
radix
Commits
7cbe577d
Commit
7cbe577d
authored
Aug 02, 2018
by
LEFEBVREJP email
Browse files
WIP: Starting on navigationmodel to integration navigationwidget and navigationitem together.
parent
8aa41aea
Pipeline
#14510
passed with stages
in 7 minutes and 29 seconds
Changes
7
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
radixwidgets/CMakeLists.txt
View file @
7cbe577d
...
...
@@ -45,18 +45,22 @@ ELSE()
SET
(
HEADERS
${
HEADERS
}
numberpadwidget.hh
navigation
item
.hh
navigation
model
.hh
navigationwidget.hh
)
SET
(
SOURCES
${
SOURCES
}
numberpadwidget.cc
navigationitem.cc
navigationmodel.cc
navigationwidget.cc
)
QT5_WRAP_CPP
(
MOC_FILES
${
HEADERS
}
)
SET
(
HEADERS
${
HEADERS
}
navigationitem.hh
)
#
# Process qt resource files
#QT5_ADD_RESOURCES(RESOURCE_RESULT
...
...
radixwidgets/navigationitem.cc
View file @
7cbe577d
#include "radixwidgets/navigationitem.hh"
#include "radixbug/bug.hh"
#include <QDir>
#include <QDirIterator>
#include <QFileInfo>
#include <QMenu>
#include <QSignalMapper>
#include <QList>
namespace
radix
{
class
NavigationItem
::
PImpl
:
public
QObject
class
NavigationItem
::
PImpl
{
public:
NavigationItem
*
parent
=
nullptr
;
QList
<
NavigationItem
*>
children
;
QList
<
QVariant
>
data
;
~
PImpl
();
};
NavigationItem
::
NavigationItem
()
:
QObject
()
,
QStandardItem
()
,
p
(
new
PImpl
(),
[](
PImpl
*
impl
)
{
delete
impl
;
})
NavigationItem
::
PImpl
::~
PImpl
()
{
qDeleteAll
(
children
);
if
(
parent
)
delete
parent
;
}
void
NavigationItem
::
addActions
(
QMenu
&
m
)
const
{}
NavigationItem
::
NavigationItem
(
QVariant
data
,
NavigationItem
*
parentItem
)
:
p
(
new
PImpl
(),
[](
PImpl
*
impl
)
{
delete
impl
;
})
{
p
->
parent
=
parentItem
;
p
->
data
.
append
(
data
);
}
NavigationItem
::
NavigationItem
(
QList
<
QVariant
>
data
,
NavigationItem
*
parentItem
)
:
p
(
new
PImpl
(),
[](
PImpl
*
impl
)
{
delete
impl
;
})
{
p
->
parent
=
parentItem
;
p
->
data
=
data
;
}
NavigationItem
::
NavigationItem
(
NavigationItem
*
parentItem
)
:
p
(
new
PImpl
(),
[](
PImpl
*
impl
)
{
delete
impl
;
})
{
p
->
parent
=
parentItem
;
}
void
NavigationItem
::
addChild
(
NavigationItem
*
child
)
{
p
->
children
.
append
(
child
);
}
int
NavigationItem
::
childCount
()
const
{
return
p
->
children
.
size
();
}
int
NavigationItem
::
columnCount
()
const
{
return
p
->
data
.
size
();
}
QVariant
NavigationItem
::
data
(
int
column
)
const
{
radix_tagged_line
(
"data("
<<
column
<<
") data size ("
<<
p
->
data
.
size
()
<<
")"
);
if
(
column
>=
p
->
data
.
size
())
return
QVariant
();
p
->
data
.
value
(
column
);
}
void
NavigationItem
::
setData
(
int
column
,
QVariant
value
)
{
int
size
=
p
->
data
.
size
();
for
(
int
i
=
size
;
i
<=
column
;
++
i
)
{
p
->
data
.
append
(
QVariant
());
}
p
->
data
[
column
]
=
value
;
}
int
NavigationItem
::
row
()
const
{
if
(
p
->
parent
)
{
return
p
->
parent
->
p
->
children
.
indexOf
(
const_cast
<
NavigationItem
*>
(
this
));
}
}
NavigationItem
*
NavigationItem
::
parentItem
()
{
return
p
->
parent
;
}
NavigationItem
*
NavigationItem
::
child
(
int
row
)
{
return
p
->
children
.
value
(
row
);
}
}
// namespace radix
radixwidgets/navigationitem.hh
View file @
7cbe577d
#ifndef RADIX_RADIXWIDGETS_NAVIGATIONITEM_HH_
#define RADIX_RADIXWIDGETS_NAVIGATIONITEM_HH_
#include <QStandardItem>
#include <QVariant>
#include <memory>
QT_BEGIN_NAMESPACE
class
QAction
;
class
QMenu
;
QT_END_NAMESPACE
namespace
radix
{
class
NavigationItem
:
public
QObject
,
public
QStandardItem
class
NavigationItem
{
Q_OBJECT
public:
virtual
void
addActions
(
QMenu
&
m
)
const
;
public
slots
:
virtual
void
activate
()
{
/**empty*/
}
virtual
void
select
()
{
/**empty*/
}
protected:
NavigationItem
();
NavigationItem
(
QVariant
data
,
NavigationItem
*
parentItem
=
nullptr
);
NavigationItem
(
QList
<
QVariant
>
data
,
NavigationItem
*
parentItem
=
nullptr
);
NavigationItem
(
NavigationItem
*
parentItem
=
nullptr
);
void
addChild
(
NavigationItem
*
child
);
NavigationItem
*
child
(
int
row
);
int
childCount
()
const
;
int
columnCount
()
const
;
QVariant
data
(
int
column
)
const
;
void
setData
(
int
column
,
QVariant
value
);
int
row
()
const
;
NavigationItem
*
parentItem
();
private:
class
PImpl
;
...
...
radixwidgets/navigationmodel.cc
0 → 100644
View file @
7cbe577d
#include "radixwidgets/navigationmodel.hh"
#include "radixwidgets/navigationitem.hh"
#include "radixbug/bug.hh"
#include <QList>
namespace
radix
{
class
NavigationModel
::
PImpl
{
public:
NavigationItem
*
root
=
nullptr
;
~
PImpl
();
};
NavigationModel
::
PImpl
::~
PImpl
()
{
if
(
root
)
delete
root
;
}
NavigationModel
::
NavigationModel
(
QObject
*
parent
)
:
QAbstractItemModel
(
parent
)
,
p
(
new
PImpl
(),
[](
PImpl
*
impl
)
{
delete
impl
;
})
{
radix_tagged_line
(
"Navigation Model"
);
p
->
root
=
new
NavigationItem
();
p
->
root
->
addChild
(
new
NavigationItem
(
"Hello"
,
p
->
root
));
NavigationItem
*
world
=
new
NavigationItem
(
"World"
,
p
->
root
);
p
->
root
->
addChild
(
world
);
NavigationItem
*
child
=
new
NavigationItem
(
"My name is edward"
,
world
);
world
->
addChild
(
child
);
}
QVariant
NavigationModel
::
data
(
const
QModelIndex
&
index
,
int
role
)
const
{
radix_tagged_line
(
"data("
<<
index
.
row
()
<<
", "
<<
index
.
column
()
<<
")"
);
if
(
!
index
.
isValid
())
return
QVariant
();
if
(
role
!=
Qt
::
DisplayRole
)
return
QVariant
();
NavigationItem
*
item
=
static_cast
<
NavigationItem
*>
(
index
.
internalPointer
());
return
item
->
data
(
index
.
column
());
}
bool
NavigationModel
::
setData
(
const
QModelIndex
&
index
,
const
QVariant
&
value
,
int
role
)
{
return
false
;
}
Qt
::
ItemFlags
NavigationModel
::
flags
(
const
QModelIndex
&
index
)
const
{
if
(
!
index
.
isValid
())
return
QAbstractItemModel
::
flags
(
index
);
return
QAbstractItemModel
::
flags
(
index
);
}
QVariant
NavigationModel
::
headerData
(
int
section
,
Qt
::
Orientation
orientation
,
int
role
)
const
{
if
(
orientation
==
Qt
::
Horizontal
&&
role
==
Qt
::
DisplayRole
)
return
p
->
root
->
data
(
section
);
return
QVariant
();
}
QModelIndex
NavigationModel
::
index
(
int
row
,
int
column
,
const
QModelIndex
&
parent
)
const
{
radix_tagged_line
(
"index("
<<
row
<<
","
<<
column
<<
")"
);
if
(
!
hasIndex
(
row
,
column
,
parent
))
return
QModelIndex
();
NavigationItem
*
parentItem
;
if
(
!
parent
.
isValid
())
parentItem
=
p
->
root
;
else
parentItem
=
static_cast
<
NavigationItem
*>
(
parent
.
internalPointer
());
NavigationItem
*
childItem
=
parentItem
->
child
(
row
);
if
(
childItem
)
return
createIndex
(
row
,
column
,
childItem
);
else
return
QModelIndex
();
}
QModelIndex
NavigationModel
::
parent
(
const
QModelIndex
&
index
)
const
{
radix_tagged_line
(
"parent("
<<
index
.
row
()
<<
","
<<
index
.
column
()
<<
")"
);
if
(
!
index
.
isValid
())
return
QModelIndex
();
NavigationItem
*
childItem
=
static_cast
<
NavigationItem
*>
(
index
.
internalPointer
());
NavigationItem
*
parentItem
=
childItem
->
parentItem
();
if
(
parentItem
==
p
->
root
)
return
QModelIndex
();
return
createIndex
(
parentItem
->
row
(),
0
,
parentItem
);
}
int
NavigationModel
::
rowCount
(
const
QModelIndex
&
parent
)
const
{
radix_tagged_line
(
"rowCount("
<<
parent
.
row
()
<<
","
<<
parent
.
column
()
<<
")"
);
NavigationItem
*
parentItem
;
if
(
parent
.
column
()
>
0
)
return
0
;
if
(
!
parent
.
isValid
())
parentItem
=
p
->
root
;
else
parentItem
=
static_cast
<
NavigationItem
*>
(
parent
.
internalPointer
());
return
parentItem
->
childCount
();
}
int
NavigationModel
::
columnCount
(
const
QModelIndex
&
parent
)
const
{
radix_tagged_line
(
"columnCount("
<<
parent
.
row
()
<<
","
<<
parent
.
column
()
<<
")"
);
if
(
parent
.
isValid
())
return
static_cast
<
NavigationItem
*>
(
parent
.
internalPointer
())
->
columnCount
();
else
return
p
->
root
->
columnCount
();
}
}
// namespace radix
radixwidgets/navigationmodel.hh
0 → 100644
View file @
7cbe577d
#ifndef RADIX_RADIXWIDGETS_NAVIGATIONMODEL_HH_
#define RADIX_RADIXWIDGETS_NAVIGATIONMODEL_HH_
#include <QAbstractItemModel>
#include <QObject>
#include <memory>
namespace
radix
{
class
NavigationModel
:
public
QAbstractItemModel
{
Q_OBJECT
public:
NavigationModel
(
QObject
*
parent
=
nullptr
);
QVariant
data
(
const
QModelIndex
&
index
,
int
role
)
const
override
;
bool
setData
(
const
QModelIndex
&
index
,
const
QVariant
&
value
,
int
role
=
Qt
::
EditRole
)
override
;
Qt
::
ItemFlags
flags
(
const
QModelIndex
&
index
)
const
override
;
QVariant
headerData
(
int
section
,
Qt
::
Orientation
orientation
,
int
role
=
Qt
::
DisplayRole
)
const
override
;
QModelIndex
index
(
int
row
,
int
column
,
const
QModelIndex
&
parent
=
QModelIndex
())
const
override
;
QModelIndex
parent
(
const
QModelIndex
&
index
)
const
override
;
int
rowCount
(
const
QModelIndex
&
parent
=
QModelIndex
())
const
override
;
int
columnCount
(
const
QModelIndex
&
parent
=
QModelIndex
())
const
override
;
private:
class
PImpl
;
std
::
unique_ptr
<
PImpl
,
void
(
*
)(
PImpl
*
)
>
p
;
};
}
// namespace radix
#endif
radixwidgets/navigationwidget.cc
View file @
7cbe577d
#include "radixwidgets/navigationwidget.hh"
#include "radixbug/bug.hh"
#include "radixwidgets/navigationitem.hh"
#include "radixwidgets/navigationmodel.hh"
#include "radixbug/bug.hh"
#include <QClipboard>
#include <QEvent>
...
...
@@ -22,142 +24,12 @@
namespace
radix
{
ProNavDelegate
::
ProNavDelegate
(
QObject
*
parent
)
:
QStyledItemDelegate
(
parent
)
{
}
bool
ProNavDelegate
::
helpEvent
(
QHelpEvent
*
event
,
QAbstractItemView
*
view
,
const
QStyleOptionViewItem
&
option
,
const
QModelIndex
&
index
)
{
// event, view, and index must be valid
if
(
event
==
nullptr
||
view
==
nullptr
||
!
index
.
isValid
())
{
return
false
;
}
// determine what to do based on the event type
switch
(
event
->
type
())
{
// displaying/hiding a tooltip
case
QEvent
::
ToolTip
:
{
// index's visual rect, and view's size
auto
rect
=
view
->
visualRect
(
index
);
auto
size
=
view
->
size
();
// move rect and resize based on size hint
rect
.
moveTo
(
view
->
viewport
()
->
mapTo
(
view
,
rect
.
topLeft
()));
rect
.
setSize
(
sizeHint
(
option
,
index
));
// size hint rect is cut off by the view, show tooltip
if
(
rect
.
right
()
>
size
.
width
())
{
// item text is cut off, so start with the item text as the tooltip
auto
tooltip
=
index
.
data
(
Qt
::
DisplayRole
).
toString
();
// get specified tooltip
auto
original
=
index
.
data
(
Qt
::
ToolTipRole
);
// tooltip specified, tack it on the end
if
(
original
.
isValid
())
{
tooltip
.
append
(
QString
(
" (%1)"
).
arg
(
original
.
toString
()));
}
QToolTip
::
showText
(
event
->
globalPos
(),
tooltip
,
view
);
return
true
;
}
// full item is visible, so call base implementation
if
(
QStyledItemDelegate
::
helpEvent
(
event
,
view
,
option
,
index
))
{
return
true
;
}
QToolTip
::
hideText
();
return
false
;
}
default:
break
;
}
return
QStyledItemDelegate
::
helpEvent
(
event
,
view
,
option
,
index
);
}
void
ProNavDelegate
::
paint
(
QPainter
*
painter
,
const
QStyleOptionViewItem
&
option
,
const
QModelIndex
&
index
)
const
{
// default implementation
QStyledItemDelegate
::
paint
(
painter
,
option
,
index
);
}
QSize
ProNavDelegate
::
sizeHint
(
const
QStyleOptionViewItem
&
option
,
const
QModelIndex
&
index
)
const
{
// default size
auto
s
=
QStyledItemDelegate
::
sizeHint
(
option
,
index
);
return
s
;
}
class
NavigationItemSortFilterProxyModel
::
PImpl
{
public:
QHash
<
QModelIndex
,
bool
>
seen
;
};
NavigationItemSortFilterProxyModel
::
NavigationItemSortFilterProxyModel
(
QObject
*
parent
)
:
QSortFilterProxyModel
(
parent
)
,
p
(
new
PImpl
(),
[](
PImpl
*
impl
)
{
delete
impl
;
})
{
}
bool
NavigationItemSortFilterProxyModel
::
accepts
(
const
QModelIndex
&
index
)
const
{
const
QString
&
text
=
index
.
data
().
toString
();
const
QRegExp
&
regex
=
filterRegExp
();
bool
accept
=
text
.
contains
(
regex
);
for
(
int
i
=
0
,
ie
=
sourceModel
()
->
rowCount
(
index
);
i
<
ie
;
i
++
)
{
if
(
accepts
(
sourceModel
()
->
index
(
i
,
0
,
index
)))
{
accept
=
true
;
break
;
}
}
p
->
seen
[
index
]
=
accept
;
return
accept
;
}
void
NavigationItemSortFilterProxyModel
::
clearCache
()
{
p
->
seen
.
clear
();
}
bool
NavigationItemSortFilterProxyModel
::
filterAcceptsRow
(
int
source_row
,
const
QModelIndex
&
source_parent
)
const
{
const
QModelIndex
&
index
=
sourceModel
()
->
index
(
source_row
,
0
,
source_parent
);
if
(
p
->
seen
.
contains
(
index
))
{
return
p
->
seen
.
value
(
index
);
}
return
accepts
(
index
);
}
class
NavigationWidget
::
PImpl
{
public:
QLineEdit
*
filter
;
QStandardItemModel
*
navModel
;
QTreeView
*
navTree
;
NavigationItemSortFilterProxyModel
*
proxyModel
;
NavigationModel
*
model
;
QTreeView
*
view
;
};
NavigationWidget
::
NavigationWidget
(
QWidget
*
parent
)
...
...
@@ -168,159 +40,35 @@ NavigationWidget::NavigationWidget(QWidget* parent)
initLayout
();
}
void
NavigationWidget
::
activateItem
()
{
// selected indices
const
auto
&
selected
=
p
->
navTree
->
selectionModel
()
->
selectedIndexes
();
// selected at least one index
if
(
selected
.
isEmpty
())
{
return
;
}
// properly map selected items
}
void
NavigationWidget
::
addItem
(
QStandardItem
*
item
)
{
// perform linear search to determine where to insert the item (alphabetized)
for
(
auto
i
=
0
,
ie
=
p
->
navModel
->
rowCount
();
i
<
ie
;
i
++
)
{
// current item and text comparison result
auto
si
=
p
->
navModel
->
item
(
i
);
auto
c
=
item
->
text
().
compare
(
si
->
text
(),
Qt
::
CaseInsensitive
);
// new item should be inserted before the current item
if
(
c
<
0
)
{
p
->
navModel
->
insertRow
(
i
,
item
);
return
;
}
}
// just append new item to model
p
->
navModel
->
appendRow
(
item
);
}
void
NavigationWidget
::
closeTriggered
()
{
// selected item
auto
ani
=
selectedRoot
();
radix_tagged_line
(
"closeTriggered"
);
}
void
NavigationWidget
::
collapse
(
QStandardItem
*
item
)
{
p
->
navTree
->
collapse
(
p
->
proxyModel
->
mapFromSource
(
item
->
index
()));
}
void
NavigationWidget
::
collapse
()
{
// selected item
auto
ani
=
selectedItem
();
// no-op
if
(
ani
==
nullptr
)
{
return
;
}
// item's index
const
auto
&
index
=
ani
->
index
();
const
auto
&
mapped
=
p
->
proxyModel
->
mapFromSource
(
index
);
// current index is expanded, so collapse it
if
(
p
->
navTree
->
isExpanded
(
mapped
))
{
p
->
navTree
->
collapse
(
mapped
);
}
// current index is collapsed (or a leaf), so move to its parent
else
{
p
->
navTree
->
selectionModel
()
->
setCurrentIndex
(
mapped
.
parent
(),
QItemSelectionModel
::
ClearAndSelect
);
}
}
bool
NavigationWidget
::
eventFilter
(
QObject
*
o
,
QEvent
*
e
)
{
radix_tagged_line
(
"eventFilter"
);
return
QWidget
::
eventFilter
(
o
,
e
);
}
void
NavigationWidget
::
expand
(
QStandardItem
*
item
)
{
p
->
navTree
->
expand
(
p
->
proxyModel
->
mapFromSource
(
item
->
index
()));
}
void
NavigationWidget
::
filterModel
(
const
QString
&
pattern
)
{
// regex used to filter the model
QRegExp
regex
(
pattern
,
Qt
::
CaseInsensitive
,
QRegExp
::
RegExp2
);
// update the model
p
->
proxyModel
->
clearCache
();
p
->
proxyModel
->
setFilterRegExp
(
regex
);
// update the tree
if
(
pattern
.
isEmpty
())
{
p
->
navTree
->
collapseAll
();
for
(
int
i
=
0
,
ie
=
p
->
navModel
->
rowCount
();
i
<
ie
;
i
++
)
{
p
->
navTree
->
expand
(
p
->
proxyModel
->
mapFromSource
(
p
->
navModel
->
index
(
i
,
0
)));
}
}
else
{
p
->
navTree
->
expandAll
();
}
}
void
NavigationWidget
::
filterSelectionChanged
()
{
radix_tagged_line
(
"filterSelectionChanged"
);
}