Commit f8e5cc22 authored by Marco Martin's avatar Marco Martin

make possible for a module to represent a category

if a module owns a category, it will be opened when clicking on the category,
but won't show up in the sub category list
parent 35776800
......@@ -267,7 +267,12 @@ void SettingsBase::initMenuList(MenuItem * parent)
category2 = entry->property(QStringLiteral("X-KDE-System-Settings-Parent-Category-V2")).toString();
}
if( !parent->category().isEmpty() && (category == parent->category() || category2 == parent->category()) ) {
QString parentCategoryKcm = parent->service() ? parent->service()->property(QStringLiteral("X-KDE-System-Settings-Category-Module")).toString() : QString();
if (parentCategoryKcm == entry->library()) {
parent->setItem( KCModuleInfo(entry) );
removeList.append( modules.at(i) );
} else if( !parent->category().isEmpty() && (category == parent->category() || category2 == parent->category()) ) {
if (!entry->noDisplay() ) {
// Add the module info to the menu
MenuItem * infoItem = new MenuItem(false, parent);
......
......@@ -3,10 +3,10 @@ install( FILES systemsettingscategory.desktop DESTINATION ${KDE_INSTALL_KSERVIC
install( FILES
settings-appearance.desktop
settings-appearance-applicationstyle.desktop
settings-appearance-color.desktop
settings-appearance-font.desktop
settings-appearance-icons.desktop
settings-root-category.desktop
settings-workspace.desktop
settings-workspace-windowmanagement.desktop
......
[Desktop Entry]
Type=Service
X-KDE-ServiceTypes=SystemSettingsCategory
X-KDE-System-Settings-Category=applicationstyle
X-KDE-System-Settings-Parent-Category=appearance
Icon=preferences-desktop-theme-applications
X-KDE-Weight=30
Name=Application Style
Name[ar]=نمط التّطبيقات
Name[ast]=Estilu d'aplicaciones
Name[az]=Tətbiq Üslubu
Name[bg]=Изглед на програмите
Name[bs]=Stil programa
Name[ca]=Estil de l'aplicació
Name[ca@valencia]=Estil de l'aplicació
Name[cs]=Styl aplikací
Name[da]=Programstil
Name[de]=Anwendungs-Stil
Name[el]=Στιλ εφαρμογών
Name[en_GB]=Application Style
Name[es]=Estilo de las aplicaciones
Name[et]=Rakenduste stiil
Name[eu]=Aplikazioen estiloa
Name[fi]=Sovellusten tyyli
Name[fr]=Apparence des applications
Name[gl]=Estilo das aplicacións
Name[he]=מראה יישומים
Name[hu]=Alkalmazások megjelenése
Name[ia]=Apparentia de application
Name[id]=Gaya Aplikasi
Name[it]=Stile delle applicazioni
Name[ja]=アプリケーションスタイル
Name[ko]=프로그램 모양
Name[lt]=Programų stilius
Name[ml]=പ്രയോഗ ശൈലി
Name[nb]=Programstil
Name[nds]=Programmstil
Name[nl]=Stijl van toepassing
Name[nn]=Program­stil
Name[pa]=ਐਪਲੀਕੇਸ਼ਨ ਸਟਾਈਲ
Name[pl]=Wygląd programów
Name[pt]=Estilo das Aplicações
Name[pt_BR]=Estilo dos aplicativos
Name[ro]=Stil aplicații
Name[ru]=Оформление приложений
Name[sk]=Štýl aplikácií
Name[sl]=Slog programov
Name[sr]=Стил програма
Name[sr@ijekavian]=Стил програма
Name[sr@ijekavianlatin]=Stil programa
Name[sr@latin]=Stil programa
Name[sv]=Programstil
Name[tg]=Услуби барнома
Name[tr]=Uygulama Biçemi
Name[uk]=Стиль вікон програм
Name[vi]=Kiểu cách ứng dụng
Name[x-test]=xxApplication Stylexx
Name[zh_CN]=应用程序风格
Name[zh_TW]=應用程式樣式
......@@ -2,9 +2,11 @@
Type=Service
X-KDE-ServiceTypes=SystemSettingsCategory
X-KDE-System-Settings-Category=appearance
X-KDE-System-Settings-Parent-Category=
X-KDE-Weight=40
Icon=preferences-desktop-theme
X-KDE-System-Settings-Parent-Category=rootcategory
X-KDE-System-Settings-Category-Module=kcm_lookandfeel
X-KDE-Weight=1
Icon=preferences-desktop-theme-global
Name=Appearance
Name[ar]=المظهر
......
[Desktop Entry]
Type=Service
X-KDE-ServiceTypes=SystemSettingsCategory
X-KDE-System-Settings-Category=rootcategory
X-KDE-System-Settings-Parent-Category=
X-KDE-Weight=1
Name=Root
......@@ -95,3 +95,7 @@ Type=QString
# parent category identifier version 2
[PropertyDef::X-KDE-System-Settings-Parent-Category-V2]
Type=QString
# The category a module owns and represents
[PropertyDef::X-KDE-System-Settings-Category-Module]
Type=QString
......@@ -148,6 +148,12 @@ bool MenuItem::showDefaultIndicator() const
return d->showDefaultIndicator;
}
void MenuItem::setItem( const KCModuleInfo &item )
{
// d->name = item.moduleName();
d->item = item;
}
void MenuItem::updateDefaultIndicator()
{
d->showDefaultIndicator = !KCModuleLoader::isDefaults(d->item);
......
......@@ -153,6 +153,8 @@ public:
*/
void setService( const KService::Ptr& service );
void setItem( const KCModuleInfo &item );
MenuItem *descendantForModule(const QString &moduleName);
bool showDefaultIndicator() const;
......
......@@ -20,6 +20,8 @@
#include "MenuModel.h"
#include <KCModuleInfo>
#include <KPluginInfo>
#include <KCategorizedSortFilterProxyModel>
#include <QIcon>
#include "MenuItem.h"
......@@ -50,6 +52,7 @@ QHash<int, QByteArray> MenuModel::roleNames() const
QHash<int, QByteArray> names = QAbstractItemModel::roleNames();
names[DepthRole] = "DepthRole";
names[IsCategoryRole] = "IsCategoryRole";
names[IsKCMRole] = "IsKCMRole";
names[DefaultIndicatorRole] = "showDefaultIndicator";
return names;
}
......@@ -105,7 +108,10 @@ QVariant MenuModel::data( const QModelIndex &index, int role ) const
candidate = candidate->parent();
}
if (candidate) {
theData.setValue( candidate->name() );
// Children of this special root category don't have an user visible category
if (candidate->item().fileName() != QStringLiteral("settings-root-category.desktop")) {
theData.setValue( candidate->name() );
}
}
break;
}
......@@ -132,6 +138,9 @@ QVariant MenuModel::data( const QModelIndex &index, int role ) const
case MenuModel::IsCategoryRole:
theData.setValue( mi->menu() );
break;
case MenuModel::IsKCMRole:
theData.setValue( !mi->item().library().isEmpty() );
break;
case MenuModel::DefaultIndicatorRole:
theData.setValue(mi->showDefaultIndicator());
break;
......
......@@ -57,6 +57,8 @@ public:
IsCategoryRole,
IsKCMRole,
DefaultIndicatorRole
};
......
......@@ -223,12 +223,16 @@ void ModuleView::loadModule( const QModelIndex &menuItem, const QStringList &arg
}
QList<QModelIndex> indexes;
MenuItem *item = menuItem.data( Qt::UserRole ).value<MenuItem*>();
if (!item->item().library().isEmpty()) {
indexes << menuItem;
}
for ( int done = 0; menuItem.model()->rowCount( menuItem ) > done; done = 1 + done ) {
indexes << menuItem.model()->index( done, 0, menuItem );
}
if ( indexes.empty() ) {
indexes << menuItem;
}
foreach ( const QModelIndex &module, indexes ) {
MenuItem *newMenuItem = module.data( Qt::UserRole ).value<MenuItem*>();
......@@ -301,8 +305,10 @@ void ModuleView::updatePageIconHeader( KPageWidgetItem * page, bool light )
page->setIcon( QIcon::fromTheme( moduleInfo->icon() ) );
//HACK: no other ways to detect is a qml kcm
d->mCustomHeader->setText(moduleInfo->moduleName());
d->mCustomHeader->setVisible(!moduleProxy || !moduleProxy->realModule()->inherits("KCModuleQml"));
page->setHeaderVisible(false);
KCModuleProxy * currentProxy = d->mPages.value( d->mPageWidget->currentPage() );
d->mCustomHeader->setVisible(!currentProxy || !currentProxy->realModule()->inherits("KCModuleQml"));
if( light ) {
return;
......@@ -484,6 +490,10 @@ void ModuleView::stateChanged()
}
updatePageIconHeader( d->mPageWidget->currentPage() );
KCModuleProxy * moduleProxy = d->mPages.value( d->mPageWidget->currentPage() );
d->mCustomHeader->setVisible(!moduleProxy || !moduleProxy->realModule()->inherits("KCModuleQml"));
d->mApplyAuthorize->setAuthAction( moduleAction );
d->mDefault->setEnabled(!defaulted);
d->mDefault->setVisible(buttons & KCModule::Default);
......
......@@ -80,9 +80,10 @@ void FocusHackWidget::focusPrevious()
focusNextPrevChild(false);
}
SubcategoryModel::SubcategoryModel(QAbstractItemModel *parentModel, QObject *parent)
SubcategoryModel::SubcategoryModel(QAbstractItemModel *parentModel, SidebarMode *parent)
: KSelectionProxyModel(nullptr, parent),
m_parentModel(parentModel)
m_parentModel(parentModel),
m_sidebarMode(parent)
{
setSourceModel(parentModel);
setSelectionModel(new QItemSelectionModel(parentModel, this));
......@@ -91,16 +92,41 @@ SubcategoryModel::SubcategoryModel(QAbstractItemModel *parentModel, QObject *par
QString SubcategoryModel::title() const
{
return m_title;
MenuItem *mi = m_activeModuleIndex.data(MenuModel::MenuItemRole).value<MenuItem *>();
if (!mi) {
return QString();
}
return mi->item().moduleName();
}
QIcon SubcategoryModel::icon() const
{
return m_activeModuleIndex.data(Qt::DecorationRole).value<QIcon>();
}
bool SubcategoryModel::categoryOwnedByKCM() const
{
return m_activeModuleIndex.data(MenuModel::IsKCMRole).toBool();
}
void SubcategoryModel::setParentIndex(const QModelIndex &activeModule)
{
selectionModel()->select(activeModule, QItemSelectionModel::ClearAndSelect);
m_title = activeModule.data(Qt::DisplayRole).toString();
m_activeModuleIndex = QPersistentModelIndex(activeModule);
emit titleChanged();
emit iconChanged();
emit categoryOwnedByKCMChanged();
}
void SubcategoryModel::loadParentCategoryModule()
{
MenuItem *menuItem = m_activeModuleIndex.data(MenuModel::MenuItemRole).value<MenuItem *>();
if (!menuItem->item().library().isEmpty()) {
m_sidebarMode->loadModule(m_activeModuleIndex);
}
}
class MostUsedModel : public QSortFilterProxyModel
{
......@@ -466,23 +492,19 @@ void SidebarMode::loadModule( const QModelIndex& activeModule, const QStringList
setIntroPageVisible(false);
}
if ( mi->children().length() < 1) {
d->moduleView->loadModule( activeModule, args );
} else {
d->moduleView->loadModule( activeModule.model()->index(0, 0, activeModule), args );
}
d->moduleView->loadModule( activeModule, args );
if (activeModule.model() == d->categorizedModel) {
const int newCategoryRow = activeModule.row();
if (d->activeCategoryRow == newCategoryRow) {
return;
}
d->activeCategoryIndex = activeModule;
d->activeCategoryRow = newCategoryRow;
d->activeSubCategoryRow = 0;
if (mi->item().library().isEmpty()) {
d->activeSubCategoryRow = 0;
} else {
d->activeSubCategoryRow = -1;
}
d->subCategoryModel->setParentIndex( activeModule );
......@@ -490,7 +512,6 @@ void SidebarMode::loadModule( const QModelIndex& activeModule, const QStringList
d->activeSearchRow = -1;
emit activeSearchRowChanged();
}
emit activeCategoryRowChanged();
emit activeSubCategoryRowChanged();
......@@ -519,7 +540,7 @@ void SidebarMode::loadModule( const QModelIndex& activeModule, const QStringList
d->activeSubCategoryRow = -1;
}
d->subCategoryModel->setParentIndex( originalIndex.parent() );
d->subCategoryModel->setParentIndex( originalIndex.parent().isValid() ? originalIndex.parent() : originalIndex );
emit activeCategoryRowChanged();
emit activeSubCategoryRowChanged();
}
......@@ -550,12 +571,16 @@ void SidebarMode::loadModule( const QModelIndex& activeModule, const QStringList
QModelIndex idx = d->categorizedModel->mapFromSource(d->flatModel->mapToSource(flatIndex));
MenuItem *parentMi = idx.parent().data(MenuModel::MenuItemRole).value<MenuItem *>();
if (idx.isValid()) {
if (parentMi && parentMi->menu()) {
d->subCategoryModel->setParentIndex( idx.parent() );
d->activeCategoryRow = idx.parent().row();
d->activeSubCategoryRow = idx.row();
} else {
if (d->categorizedModel->rowCount(idx) > 0) {
d->subCategoryModel->setParentIndex( idx );
}
d->activeCategoryRow = idx.row();
d->activeSubCategoryRow = -1;
}
......@@ -583,8 +608,8 @@ void SidebarMode::updateDefaults()
QModelIndex categoryIdx = d->categorizedModel->index(d->activeCategoryRow, 0);
auto item = categoryIdx.data(Qt::UserRole).value<MenuItem*>();
Q_ASSERT(item);
// If subcategory exist update from subcategory
if (!item->children().isEmpty()) {
// If subcategory exist update from subcategory, unless this category is owned by a kcm
if (!item->children().isEmpty() && d->activeSubCategoryRow > -1) {
auto subCateogryIdx = d->subCategoryModel->index(d->activeSubCategoryRow, 0);
item = subCateogryIdx.data(Qt::UserRole).value<MenuItem*>();
}
......
......@@ -23,6 +23,7 @@
#include "BaseMode.h"
#include <QWidget>
#include <KSelectionProxyModel>
#include <QIcon>
class ModuleView;
class KAboutData;
......@@ -30,6 +31,7 @@ class QModelIndex;
class QAbstractItemView;
class QAbstractItemModel;
class QAction;
class SidebarMode;
class FocusHackWidget : public QWidget {
Q_OBJECT
......@@ -46,20 +48,29 @@ class SubcategoryModel : public KSelectionProxyModel
{
Q_OBJECT
Q_PROPERTY(QString title READ title NOTIFY titleChanged)
Q_PROPERTY(QIcon icon READ icon NOTIFY iconChanged)
Q_PROPERTY(bool categoryOwnedByKCM READ categoryOwnedByKCM NOTIFY categoryOwnedByKCMChanged)
public:
explicit SubcategoryModel(QAbstractItemModel *parentModel, QObject *parent = nullptr);
explicit SubcategoryModel(QAbstractItemModel *parentModel, SidebarMode *parent = nullptr);
QString title() const;
QIcon icon() const;
bool categoryOwnedByKCM() const;
void setParentIndex(const QModelIndex &activeModule);
Q_INVOKABLE void loadParentCategoryModule();
Q_SIGNALS:
void titleChanged();
void iconChanged();
void categoryOwnedByKCMChanged();
private:
SidebarMode *m_sidebarMode;
QAbstractItemModel *m_parentModel;
QString m_title;
QPersistentModelIndex m_activeModuleIndex;
};
class SidebarMode : public BaseMode
......
......@@ -145,13 +145,13 @@ Kirigami.ScrollablePage {
Accessible.role: Accessible.ListItem
Accessible.name: model.display
supportsMouseEvents: !model.IsCategoryRole || !mainColumn.searchMode
enabled: !model.IsCategoryRole || !mainColumn.searchMode
enabled: model.IsKCMRole || !mainColumn.searchMode
onClicked: {
if (model.IsCategoryRole && mainColumn.searchMode) {
if (!model.IsKCMRole && mainColumn.searchMode) {
return;
}
if (mainColumn.searchMode || systemsettings.activeCategoryRow !== index) {
if (model.IsKCMRole || mainColumn.searchMode || systemsettings.activeCategoryRow !== index) {
systemsettings.loadModule(categoryView.model.index(index, 0));
}
if (!mainColumn.searchMode && root.pageStack.depth > 1) {
......
......@@ -34,22 +34,16 @@ Kirigami.ScrollablePage {
rightPadding: Kirigami.Units.smallSpacing
preferredHeight: toolBarLayout.implicitHeight + topPadding + bottomPadding
background: MouseArea {
anchors.fill: parent
acceptedButtons: applicationWindow().wideScreen ? Qt.NoButton : Qt.LeftButton
onClicked: backButton.clicked()
}
contentItem: RowLayout {
id: toolBarLayout
anchors.fill: parent
spacing: Kirigami.Units.smallSpacing
spacing: 0
QQC2.ToolButton {
id: backButton
visible: !applicationWindow().wideScreen
icon.name: LayoutMirroring.enabled ? "go-next-symbolic" : "go-next-symbolic-rtl"
onClicked: root.pageStack.currentIndex = 0
onClicked: root.pageStack.currentIndex = 0;
Accessible.role: Accessible.Button
Accessible.name: i18n("Go back")
QQC2.ToolTip {
......@@ -57,16 +51,55 @@ Kirigami.ScrollablePage {
}
}
Kirigami.Heading {
MouseArea {
id: backToCategoryButton
implicitWidth: titleLayout.implicitWidth
implicitHeight: titleLayout.implicitHeight
Layout.fillWidth: true
Layout.fillHeight: true
// Don't be too short when the back button isn't visible
Layout.minimumHeight: backButton.implicitHeight
Layout.leftMargin: backButton.visible ? undefined : Kirigami.Units.largeSpacing
level: 3
text: subCategoryColumn.title
verticalAlignment: Text.AlignVCenter
elide: Text.ElideRight
Layout.leftMargin: Kirigami.Units.smallSpacing
enabled: systemsettings.subCategoryModel.categoryOwnedByKCM
hoverEnabled: true
activeFocusOnTab: true
Accessible.role: Accessible.Button
Accessible.name: subCategoryColumn.title
onClicked: {
focus = true;
systemsettings.subCategoryModel.loadParentCategoryModule();
}
Rectangle {
anchors {
fill: parent
leftMargin: -Kirigami.Units.smallSpacing
}
radius: Kirigami.Units.smallSpacing
color: Kirigami.Theme.highlightColor
opacity: parent.containsMouse ? (parent.pressed ? 0.4 : 0.2) : (parent.activeFocus ? 0.1 : 0)
Behavior on opacity {
OpacityAnimator {
duration: Kirigami.Units.shortDuration
easing.type: Easing.InOutQuad
}
}
}
RowLayout {
id: titleLayout
spacing: Kirigami.Units.smallSpacing
Kirigami.Icon {
visible: systemsettings.subCategoryModel.categoryOwnedByKCM
source: systemsettings.subCategoryModel.icon
Layout.preferredWidth: Kirigami.Units.iconSizes.smallMedium
}
Kirigami.Heading {
Layout.fillWidth: true
Layout.fillHeight: true
// Don't be too short when the back button isn't visible
Layout.minimumHeight: backButton.implicitHeight
level: 3
text: subCategoryColumn.title
verticalAlignment: Text.AlignVCenter
elide: Text.ElideRight
}
}
}
}
}
......@@ -110,11 +143,11 @@ Kirigami.ScrollablePage {
Connections {
target: systemsettings
onActiveSubCategoryRowChanged: {
if (systemsettings.activeSubCategoryRow < 0) {
root.pageStack.pop(mainColumn)
} else {
if (systemsettings.activeSubCategoryRow >= 0) {
root.pageStack.currentIndex = 1;
subCategoryView.forceActiveFocus();
} else {
backToCategoryButton.forceActiveFocus();
}
}
onIntroPageVisibleChanged: {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment