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
Plasma
Plasma Mobile
Commits
4e4cc5ab
Commit
4e4cc5ab
authored
Sep 17, 2019
by
Marco Martin
Browse files
port to kicker model
still not completely functional, but starts to
parent
93400faa
Changes
4
Hide whitespace changes
Inline
Side-by-side
containments/homescreen/applicationlistmodel.cpp
View file @
4e4cc5ab
...
...
@@ -39,13 +39,9 @@
ApplicationListModel
::
ApplicationListModel
(
HomeScreen
*
parent
)
:
Q
AbstractList
Model
(
parent
),
:
Q
SortFilterProxy
Model
(
parent
),
m_homeScreen
(
parent
)
{
//can't use the new syntax as this signal is overloaded
connect
(
KSycoca
::
self
(),
SIGNAL
(
databaseChanged
(
const
QStringList
&
)),
this
,
SLOT
(
sycocaDbChanged
(
const
QStringList
&
)));
loadSettings
();
}
...
...
@@ -64,128 +60,23 @@ void ApplicationListModel::loadSettings()
m_appPositions
[
app
]
=
i
;
++
i
;
}
loadApplications
();
}
QHash
<
int
,
QByteArray
>
ApplicationListModel
::
roleNames
()
const
{
QHash
<
int
,
QByteArray
>
roleNames
;
roleNames
[
ApplicationNameRole
]
=
"ApplicationNameRole"
;
roleNames
[
ApplicationIconRole
]
=
"ApplicationIconRole"
;
roleNames
[
ApplicationStorageIdRole
]
=
"ApplicationStorageIdRole"
;
roleNames
[
ApplicationEntryPathRole
]
=
"ApplicationEntryPathRole"
;
roleNames
[
ApplicationOriginalRowRole
]
=
"ApplicationOriginalRowRole"
;
roleNames
[
ApplicationStartupNotifyRole
]
=
"ApplicationStartupNotifyRole"
;
roleNames
[
ApplicationLocationRole
]
=
"ApplicationLocationRole"
;
return
roleNames
;
}
void
ApplicationListModel
::
sycocaDbChanged
(
const
QStringList
&
changes
)
{
if
(
!
changes
.
contains
(
"apps"
)
&&
!
changes
.
contains
(
"xdgdata-apps"
))
{
return
;
if
(
sourceModel
())
{
roleNames
=
sourceModel
()
->
roleNames
();
}
roleNames
[
SortKeyRole
]
=
"SortKeyRole"
;
roleNames
[
ApplicationLocationRole
]
=
"ApplicationLocationRole"
;
m_applicationList
.
clear
();
loadApplications
();
}
const_cast
<
ApplicationListModel
*>
(
this
)
->
m_urlRole
=
roleNames
.
key
(
"url"
);
bool
appNameLessThan
(
const
ApplicationData
&
a1
,
const
ApplicationData
&
a2
)
{
return
a1
.
name
.
toLower
()
<
a2
.
name
.
toLower
();
return
roleNames
;
}
void
ApplicationListModel
::
loadApplications
()
{
auto
cfg
=
KSharedConfig
::
openConfig
(
"applications-blacklistrc"
);
auto
blgroup
=
KConfigGroup
(
cfg
,
QStringLiteral
(
"Applications"
));
// This is only temporary to get a clue what those apps' desktop files are called
// I'll remove it once I've done a blacklist
QStringList
bl
;
QStringList
blacklist
=
blgroup
.
readEntry
(
"blacklist"
,
QStringList
());
beginResetModel
();
m_applicationList
.
clear
();
KServiceGroup
::
Ptr
group
=
KServiceGroup
::
root
();
if
(
!
group
||
!
group
->
isValid
())
return
;
KServiceGroup
::
List
subGroupList
=
group
->
entries
(
true
);
QMap
<
int
,
ApplicationData
>
orderedList
;
QList
<
ApplicationData
>
unorderedList
;
// Iterate over all entries in the group
while
(
!
subGroupList
.
isEmpty
())
{
KSycocaEntry
::
Ptr
groupEntry
=
subGroupList
.
first
();
subGroupList
.
pop_front
();
if
(
groupEntry
->
isType
(
KST_KServiceGroup
))
{
KServiceGroup
::
Ptr
serviceGroup
(
static_cast
<
KServiceGroup
*
>
(
groupEntry
.
data
()));
if
(
!
serviceGroup
->
noDisplay
())
{
KServiceGroup
::
List
entryGroupList
=
serviceGroup
->
entries
(
true
);
for
(
KServiceGroup
::
List
::
ConstIterator
it
=
entryGroupList
.
constBegin
();
it
!=
entryGroupList
.
constEnd
();
it
++
)
{
KSycocaEntry
::
Ptr
entry
=
(
*
it
);
if
(
entry
->
isType
(
KST_KServiceGroup
))
{
KServiceGroup
::
Ptr
serviceGroup
(
static_cast
<
KServiceGroup
*
>
(
entry
.
data
()));
subGroupList
<<
serviceGroup
;
}
else
if
(
entry
->
property
(
"Exec"
).
isValid
())
{
KService
::
Ptr
service
(
static_cast
<
KService
*
>
(
entry
.
data
()));
if
(
service
->
isApplication
()
&&
!
blacklist
.
contains
(
service
->
desktopEntryName
())
&&
service
->
showOnCurrentPlatform
()
&&
!
service
->
property
(
"Terminal"
,
QVariant
::
Bool
).
toBool
())
{
bl
<<
service
->
desktopEntryName
();
ApplicationData
data
;
data
.
name
=
service
->
name
();
data
.
icon
=
service
->
icon
();
data
.
storageId
=
service
->
storageId
();
data
.
entryPath
=
service
->
exec
();
data
.
startupNotify
=
service
->
property
(
"StartupNotify"
).
toBool
();
if
(
m_favorites
.
contains
(
data
.
storageId
))
{
data
.
location
=
Favorites
;
}
else
if
(
m_desktopItems
.
contains
(
data
.
storageId
))
{
data
.
location
=
Desktop
;
}
auto
it
=
m_appPositions
.
constFind
(
service
->
storageId
());
if
(
it
!=
m_appPositions
.
constEnd
())
{
orderedList
[
*
it
]
=
data
;
}
else
{
unorderedList
<<
data
;
}
}
}
}
}
}
}
blgroup
.
writeEntry
(
"allapps"
,
bl
);
blgroup
.
writeEntry
(
"blacklist"
,
blacklist
);
cfg
->
sync
();
std
::
sort
(
unorderedList
.
begin
(),
unorderedList
.
end
(),
appNameLessThan
);
m_applicationList
<<
orderedList
.
values
();
m_applicationList
<<
unorderedList
;
endResetModel
();
emit
countChanged
();
}
QVariant
ApplicationListModel
::
data
(
const
QModelIndex
&
index
,
int
role
)
const
{
...
...
@@ -194,127 +85,117 @@ QVariant ApplicationListModel::data(const QModelIndex &index, int role) const
}
switch
(
role
)
{
case
Qt
::
DisplayRole
:
case
ApplicationNameRole
:
return
m_applicationList
.
at
(
index
.
row
()).
name
;
case
ApplicationIconRole
:
return
m_applicationList
.
at
(
index
.
row
()).
icon
;
case
ApplicationStorageIdRole
:
return
m_applicationList
.
at
(
index
.
row
()).
storageId
;
case
ApplicationEntryPathRole
:
return
m_applicationList
.
at
(
index
.
row
()).
entryPath
;
case
ApplicationOriginalRowRole
:
return
index
.
row
();
case
ApplicationStartupNotifyRole
:
return
m_applicationList
.
at
(
index
.
row
()).
startupNotify
;
case
ApplicationLocationRole
:
return
m_applicationList
.
at
(
index
.
row
()).
location
;
case
SortKeyRole
:
{
const
QString
url
=
QSortFilterProxyModel
::
data
(
index
,
m_urlRole
).
toString
();
if
(
m_appOrder
.
contains
(
url
))
{
return
QString
::
number
(
m_appOrder
.
indexOf
(
url
))
+
QStringLiteral
(
"_"
)
+
QSortFilterProxyModel
::
data
(
index
,
Qt
::
DisplayRole
).
toString
();
}
else
{
return
QStringLiteral
(
"z_"
)
+
QSortFilterProxyModel
::
data
(
index
,
Qt
::
DisplayRole
).
toString
();
}
}
case
ApplicationLocationRole
:
{
const
QString
url
=
QSortFilterProxyModel
::
data
(
index
,
m_urlRole
).
toString
();
if
(
m_favorites
.
contains
(
url
))
{
return
Favorites
;
}
else
if
(
m_desktopItems
.
contains
(
url
))
{
return
Desktop
;
}
else
{
return
Grid
;
}
}
default:
return
Q
Variant
(
);
return
Q
SortFilterProxyModel
::
data
(
index
,
role
);
}
}
//TODO: remove?
Qt
::
ItemFlags
ApplicationListModel
::
flags
(
const
QModelIndex
&
index
)
const
{
if
(
!
index
.
isValid
())
return
nullptr
;
return
Qt
::
ItemIsDragEnabled
|
Q
AbstractItem
Model
::
flags
(
index
);
return
Qt
::
ItemIsDragEnabled
|
Q
SortFilterProxy
Model
::
flags
(
index
);
}
int
ApplicationListModel
::
rowCount
(
const
QModelIndex
&
parent
)
const
{
if
(
parent
.
isValid
())
{
return
0
;
}
return
m_applicationList
.
count
();
}
void
ApplicationListModel
::
moveRow
(
const
QModelIndex
&
/* sourceParent */
,
int
sourceRow
,
const
QModelIndex
&
/* destinationParent */
,
int
destinationChild
)
{
moveItem
(
sourceRow
,
destinationChild
);
}
void
ApplicationListModel
::
setLocation
(
int
row
,
LauncherLocation
location
)
{
if
(
row
<
0
||
row
>=
m_applicationList
.
length
())
{
if
(
row
<
0
||
row
>=
rowCount
())
{
return
;
}
ApplicationData
&
data
=
m_applicationList
[
row
];
if
(
data
.
location
==
location
)
{
const
QString
url
=
data
(
index
(
row
,
0
),
m_urlRole
).
toString
();
if
(
url
.
isEmpty
())
{
return
;
}
if
(
location
==
Favorites
)
{
qWarning
()
<<
"favoriting"
<<
row
<<
data
.
name
;
if
(
location
==
Favorites
&&
!
m_favorites
.
contains
(
url
))
{
qWarning
()
<<
"favoriting"
<<
row
;
// Deny favorites when full
if
(
row
>=
m_maxFavoriteCount
||
m_favorites
.
count
()
>=
m_maxFavoriteCount
)
{
return
;
}
m_favorites
.
insert
(
row
,
data
.
storageId
);
m_favorites
.
insert
(
row
,
url
);
m_homeScreen
->
config
().
writeEntry
(
"Favorites"
,
m_favorites
);
emit
favoriteCountChanged
();
// Out of favorites
}
else
if
(
data
.
location
==
Favorites
)
{
m_favorites
.
removeAll
(
data
.
storageId
);
}
else
if
(
m_favorites
.
contains
(
url
)
)
{
m_favorites
.
removeAll
(
url
);
m_homeScreen
->
config
().
writeEntry
(
"Favorites"
,
m_favorites
);
emit
favoriteCountChanged
();
}
// In Desktop
if
(
location
==
Desktop
)
{
m_desktopItems
.
insert
(
data
.
storageId
);
if
(
location
==
Desktop
&&
m_desktopItems
.
contains
(
url
)
)
{
m_desktopItems
.
insert
(
url
);
m_homeScreen
->
config
().
writeEntry
(
"DesktopItems"
,
m_desktopItems
.
toList
());
// Out of Desktop
}
else
if
(
data
.
location
==
Desktop
)
{
m_desktopItems
.
remove
(
data
.
storageId
);
}
else
if
(
m_desktopItems
.
contains
(
url
)
)
{
m_desktopItems
.
remove
(
url
);
m_homeScreen
->
config
().
writeEntry
(
"DesktopItems"
,
m_desktopItems
.
toList
());
}
data
.
location
=
location
;
emit
m_homeScreen
->
configNeedsSaving
();
emit
dataChanged
(
index
(
row
,
0
),
index
(
row
,
0
));
}
void
ApplicationListModel
::
moveItem
(
int
row
,
int
destination
)
{
if
(
row
<
0
||
destination
<
0
||
row
>=
m_applicationList
.
length
()
||
destination
>=
m_applicationList
.
length
()
||
row
==
destination
)
{
if
(
row
<
0
||
destination
<
0
||
row
>=
rowCount
()
||
destination
>=
rowCount
()
||
row
==
destination
)
{
return
;
}
if
(
destination
>
row
)
{
++
destination
;
}
beginMoveRows
(
QModelIndex
(),
row
,
row
,
QModelIndex
(),
destination
);
if
(
destination
>
row
)
{
ApplicationData
data
=
m_applicationList
.
at
(
row
);
m_applicationList
.
insert
(
destination
,
data
);
m_applicationList
.
takeAt
(
row
);
const
QString
url
=
data
(
index
(
row
,
0
),
m_urlRole
).
toString
();
}
else
{
ApplicationData
data
=
m_applicationList
.
takeAt
(
row
);
m_applicationList
.
insert
(
destination
,
data
);
if
(
url
.
isEmpty
())
{
return
;
}
if
(
m_appOrder
.
length
()
<
qMax
(
row
,
destination
))
{
for
(
int
i
=
m_appOrder
.
length
();
i
<=
qMax
(
row
,
destination
);
++
i
)
{
m_appOrder
<<
data
(
index
(
i
,
0
),
m_urlRole
).
toString
();
}
}
if
(
destination
>
row
)
{
m_appOrder
.
insert
(
destination
,
url
);
m_appOrder
.
takeAt
(
row
);
m_appOrder
.
clear
();
m_appPositions
.
clear
();
int
i
=
0
;
for
(
auto
app
:
m_applicationList
)
{
m_appOrder
<<
app
.
storageId
;
m_appPositions
[
app
.
storageId
]
=
i
;
++
i
;
}
else
{
m_appOrder
.
takeAt
(
row
);
m_appOrder
.
insert
(
destination
,
url
);
}
m_homeScreen
->
config
().
writeEntry
(
"AppOrder"
,
m_appOrder
);
endMoveRows
();
}
void
ApplicationListModel
::
runApplication
(
const
QString
&
storageId
)
...
...
@@ -344,7 +225,7 @@ void ApplicationListModel::setMaxFavoriteCount(int count)
m_favorites
.
pop_back
();
}
emit
favoriteCountChanged
();
/*TODO
int i = 0;
for (auto &app : m_applicationList) {
if (i >= count && app.location == Favorites) {
...
...
@@ -352,7 +233,7 @@ void ApplicationListModel::setMaxFavoriteCount(int count)
emit dataChanged(index(i, 0), index(i, 0));
}
++i;
}
}
*/
}
m_maxFavoriteCount
=
count
;
...
...
containments/homescreen/applicationlistmodel.h
View file @
4e4cc5ab
...
...
@@ -22,7 +22,7 @@
// Qt
#include
<QObject>
#include
<Q
AbstractList
Model>
#include
<Q
SortFilterProxy
Model>
#include
<QList>
#include
"homescreen.h"
...
...
@@ -31,16 +31,7 @@ class QString;
class
ApplicationListModel
;
struct
ApplicationData
{
QString
name
;
QString
icon
;
QString
storageId
;
QString
entryPath
;
int
location
=
0
;
//FIXME
bool
startupNotify
=
true
;
};
class
ApplicationListModel
:
public
QAbstractListModel
{
class
ApplicationListModel
:
public
QSortFilterProxyModel
{
Q_OBJECT
Q_PROPERTY
(
int
count
READ
count
NOTIFY
countChanged
)
...
...
@@ -56,12 +47,7 @@ public:
Q_ENUM
(
LauncherLocation
)
enum
Roles
{
ApplicationNameRole
=
Qt
::
UserRole
+
1
,
ApplicationIconRole
,
ApplicationStorageIdRole
,
ApplicationEntryPathRole
,
ApplicationOriginalRowRole
,
ApplicationStartupNotifyRole
,
SortKeyRole
=
Qt
::
UserRole
+
100
,
ApplicationLocationRole
};
...
...
@@ -70,11 +56,7 @@ public:
void
loadSettings
();
int
rowCount
(
const
QModelIndex
&
parent
=
QModelIndex
())
const
Q_DECL_OVERRIDE
;
void
moveRow
(
const
QModelIndex
&
sourceParent
,
int
sourceRow
,
const
QModelIndex
&
destinationParent
,
int
destinationChild
);
int
count
()
const
{
return
m_applicationList
.
count
();
}
int
count
()
const
{
return
rowCount
();
}
int
favoriteCount
()
const
{
return
m_favorites
.
count
();}
int
maxFavoriteCount
()
const
;
...
...
@@ -92,10 +74,7 @@ public:
Q_INVOKABLE
void
runApplication
(
const
QString
&
storageId
);
Q_INVOKABLE
void
loadApplications
();
public
Q_SLOTS
:
void
sycocaDbChanged
(
const
QStringList
&
change
);
Q_SIGNALS:
void
countChanged
();
...
...
@@ -103,10 +82,9 @@ Q_SIGNALS:
void
maxFavoriteCountChanged
();
private:
QList
<
ApplicationData
>
m_applicationList
;
HomeScreen
*
m_homeScreen
=
nullptr
;
int
m_maxFavoriteCount
=
0
;
int
m_urlRole
=
0
;
QStringList
m_appOrder
;
QStringList
m_favorites
;
QSet
<
QString
>
m_desktopItems
;
...
...
containments/homescreen/package/contents/ui/launcher/Delegate.qml
View file @
4e4cc5ab
...
...
@@ -47,7 +47,7 @@ ContainmentLayoutManager.ItemContainer {
opacity
:
dragActive
?
0.4
:
1
key
:
model
.
ApplicationStorageIdRole
key
:
model
.
url
property
real
dragCenterX
property
real
dragCenterY
...
...
@@ -93,8 +93,8 @@ ContainmentLayoutManager.ItemContainer {
onClicked
:
{
clickFedbackAnimation
.
target
=
delegate
;
clickFedbackAnimation
.
running
=
true
;
feedbackWindow
.
title
=
model
Data
.
ApplicationNameRole
;
feedbackWindow
.
icon
=
model
Data
.
ApplicationIconRole
;
feedbackWindow
.
title
=
model
.
display
;
feedbackWindow
.
icon
=
model
.
decoration
;
feedbackWindow
.
state
=
"
open
"
;
plasmoid
.
nativeInterface
.
applicationListModel
.
runApplication
(
modelData
.
ApplicationStorageIdRole
);
...
...
@@ -112,7 +112,7 @@ ContainmentLayoutManager.ItemContainer {
Layout.minimumHeight
:
parent
.
height
-
root
.
reservedSpaceForLabel
Layout.preferredHeight
:
Layout
.
minimumHeight
source
:
model
Data
?
modelData
.
ApplicationIconRole
:
""
source
:
model
.
decoration
Behavior
on
scale
{
NumberAnimation
{
duration
:
units
.
longDuration
...
...
@@ -133,7 +133,7 @@ ContainmentLayoutManager.ItemContainer {
maximumLineCount
:
2
elide
:
Text
.
ElideRight
text
:
model
.
ApplicationNameRole
text
:
model
.
display
font.pixelSize
:
theme
.
defaultFont
.
pixelSize
color
:
model
.
ApplicationLocationRole
==
ApplicationListModel
.
Desktop
?
"
white
"
:
theme
.
textColor
...
...
containments/homescreen/package/contents/ui/launcher/LauncherGrid.qml
View file @
4e4cc5ab
...
...
@@ -29,6 +29,8 @@ import org.kde.plasma.private.containmentlayoutmanager 1.0 as ContainmentLayoutM
import
org
.
kde
.
phone
.
homescreen
1.0
import
org
.
kde
.
plasma
.
private
.
kicker
0.1
as
Kicker
LauncherContainer
{
id
:
root
...
...
@@ -39,6 +41,28 @@ LauncherContainer {
frame.width
:
width
Kicker.RootModel
{
id
:
kickerRootModel
appNameFormat
:
0
autoPopulate
:
false
flat
:
true
sorted
:
true
showSeparators
:
false
appletInterface
:
plasmoid
paginate
:
false
showAllApps
:
true
showTopLevelItems
:
false
showRecentApps
:
false
showRecentDocs
:
false
showRecentContacts
:
false
recentOrdering
:
0
Component.onCompleted
:
{
kickerRootModel
.
refresh
();
plasmoid
.
nativeInterface
.
applicationListModel
.
sourceModel
=
kickerRootModel
.
modelForRow
(
0
);
}
}
Repeater
{
model
:
plasmoid
.
nativeInterface
.
applicationListModel
delegate
:
Delegate
{
...
...
Marco Martin
@mart
mentioned in commit
abc112ed
·
Sep 18, 2019
mentioned in commit
abc112ed
mentioned in commit abc112ed1cfc8230e244521d647fc158e63ecc51
Toggle commit list
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