File indexing completed on 2024-04-21 16:22:52
0001 /* 0002 * SPDX-FileCopyrightText: 2009 Ben Cooksley <bcooksley@kde.org> 0003 * 0004 * SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "IconMode.h" 0008 #include "CategorizedView.h" 0009 #include "CategoryDrawer.h" 0010 0011 #include "MenuItem.h" 0012 #include "MenuModel.h" 0013 #include "MenuProxyModel.h" 0014 #include "ModuleView.h" 0015 0016 #include <QStackedWidget> 0017 0018 #include <KAboutData> 0019 #include <KFileItemDelegate> 0020 #include <KLocalizedString> 0021 #include <KPluginFactory> 0022 #include <KStandardAction> 0023 #include <QAction> 0024 0025 K_PLUGIN_CLASS_WITH_JSON(IconMode, "settings-icon-view.json") 0026 0027 class IconMode::Private 0028 { 0029 public: 0030 Private() 0031 { 0032 } 0033 0034 virtual ~Private() 0035 { 0036 delete aboutIcon; 0037 } 0038 0039 KCategoryDrawer *categoryDrawer = nullptr; 0040 KCategorizedView *categoryView = nullptr; 0041 QStackedWidget *mainWidget = nullptr; 0042 MenuModel *model = nullptr; 0043 MenuProxyModel *proxyModel = nullptr; 0044 KAboutData *aboutIcon = nullptr; 0045 ModuleView *moduleView = nullptr; 0046 QAction *backAction = nullptr; 0047 }; 0048 0049 IconMode::IconMode(QObject *parent, const QVariantList &args) 0050 : BaseMode(parent, args) 0051 , d(new Private()) 0052 { 0053 d->aboutIcon = new KAboutData(QStringLiteral("IconView"), 0054 i18n("Icon View"), 0055 QStringLiteral("1.0"), 0056 i18n("Provides a categorized icons view of control modules."), 0057 KAboutLicense::GPL, 0058 i18n("(c) 2009, Ben Cooksley")); 0059 d->aboutIcon->addAuthor(i18n("Ben Cooksley"), i18n("Author"), QStringLiteral("bcooksley@kde.org")); 0060 d->aboutIcon->addAuthor(i18n("Mathias Soeken"), i18n("Developer"), QStringLiteral("msoeken@informatik.uni-bremen.de")); 0061 0062 d->backAction = KStandardAction::back(this, SLOT(backToOverview()), this); 0063 d->backAction->setText(i18n("All Settings")); 0064 d->backAction->setToolTip(i18n("Keyboard Shortcut: %1", d->backAction->shortcut().toString(QKeySequence::NativeText))); 0065 d->backAction->setEnabled(false); 0066 actionsList() << d->backAction; 0067 } 0068 0069 IconMode::~IconMode() 0070 { 0071 delete d; 0072 } 0073 0074 KAboutData *IconMode::aboutData() 0075 { 0076 return d->aboutIcon; 0077 } 0078 0079 ModuleView *IconMode::moduleView() const 0080 { 0081 return d->moduleView; 0082 } 0083 0084 QWidget *IconMode::mainWidget() 0085 { 0086 if (!d->categoryView) { 0087 initWidget(); 0088 } 0089 return d->mainWidget; 0090 } 0091 0092 QList<QAbstractItemView *> IconMode::views() const 0093 { 0094 QList<QAbstractItemView *> list; 0095 list.append(d->categoryView); 0096 return list; 0097 } 0098 0099 void IconMode::initEvent() 0100 { 0101 d->model = new MenuModel(rootItem(), this); 0102 foreach (MenuItem *child, rootItem()->children()) { 0103 d->model->addException(child); 0104 } 0105 0106 d->proxyModel = new MenuProxyModel(this); 0107 d->proxyModel->setCategorizedModel(true); 0108 d->proxyModel->setSourceModel(d->model); 0109 d->proxyModel->sort(0); 0110 0111 d->mainWidget = new QStackedWidget(); 0112 d->moduleView = new ModuleView(d->mainWidget); 0113 connect(d->moduleView, &ModuleView::moduleChanged, this, &IconMode::moduleLoaded); 0114 connect(d->moduleView, &ModuleView::closeRequest, this, &IconMode::backToOverview); 0115 d->categoryView = nullptr; 0116 } 0117 0118 void IconMode::searchChanged(const QString &text) 0119 { 0120 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) 0121 d->proxyModel->setFilterRegExp(text); 0122 #else 0123 d->proxyModel->setFilterRegularExpression(text); 0124 #endif 0125 if (d->categoryView) { 0126 QAbstractItemModel *model = d->categoryView->model(); 0127 const int column = d->categoryView->modelColumn(); 0128 const QModelIndex root = d->categoryView->rootIndex(); 0129 for (int i = 0; i < model->rowCount(); ++i) { 0130 const QModelIndex index = model->index(i, column, root); 0131 if (model->flags(index) & Qt::ItemIsEnabled) { 0132 d->categoryView->scrollTo(index); 0133 break; 0134 } 0135 } 0136 } 0137 } 0138 0139 void IconMode::changeModule(const QModelIndex &activeModule) 0140 { 0141 // Already loaded? 0142 MenuItem *item = activeModule.data(Qt::UserRole).value<MenuItem *>(); 0143 if (d->moduleView->activeModuleName() == item->name()) 0144 return; 0145 0146 changeModuleWithArgs(activeModule, QStringList()); 0147 } 0148 0149 void IconMode::changeModuleWithArgs(const QModelIndex &activeModule, const QStringList &args) 0150 { 0151 // Always reopen because args might have changed 0152 d->moduleView->closeModules(); 0153 d->mainWidget->setCurrentWidget(d->moduleView); 0154 0155 const QModelIndex categoryIndex = activeModule.parent(); 0156 const bool hasCategory = categoryIndex.isValid(); 0157 const bool hasChildren = d->categoryView->model()->rowCount(activeModule) > 1; 0158 0159 // We have no children or any other items in the category, so we load a single KCM 0160 if (!hasCategory && !hasChildren) { 0161 d->moduleView->setFaceType(KPageView::Plain); 0162 d->moduleView->loadModule(activeModule, args); 0163 return; 0164 } 0165 0166 d->moduleView->setFaceType(KPageView::List); 0167 0168 // In the case of Appearance -> GlobalTheme we will load its children items 0169 // Otherwise, load the modules that belong into that category 0170 const QModelIndex rootIndex = hasCategory ? categoryIndex : activeModule; 0171 0172 for (int row = 0; row < d->categoryView->model()->rowCount(rootIndex); row++) { 0173 const QModelIndex subpageItem = d->categoryView->model()->index(row, 0, rootIndex); 0174 const QStringList &effectiveArgs = activeModule.row() == row ? args : QStringList(); // Only set args for the active module 0175 0176 d->moduleView->loadModule(subpageItem, effectiveArgs); 0177 } 0178 0179 MenuItem *item = activeModule.data(Qt::UserRole).value<MenuItem *>(); 0180 if (item) { 0181 d->moduleView->setActiveModule(item->name()); 0182 } 0183 } 0184 0185 void IconMode::moduleLoaded() 0186 { 0187 d->backAction->setEnabled(true); 0188 Q_EMIT changeToolBarItems(BaseMode::NoItems); 0189 } 0190 0191 void IconMode::backToOverview() 0192 { 0193 if (d->moduleView->resolveChanges()) { 0194 d->mainWidget->setCurrentWidget(d->categoryView); 0195 d->moduleView->closeModules(); 0196 d->backAction->setEnabled(false); 0197 Q_EMIT changeToolBarItems(BaseMode::Search | BaseMode::Configure | BaseMode::Quit); 0198 Q_EMIT viewChanged(false); 0199 } 0200 } 0201 0202 void IconMode::initWidget() 0203 { 0204 // Create the widget 0205 d->categoryView = new CategorizedView(d->mainWidget); 0206 d->categoryDrawer = new CategoryDrawer(d->categoryView); 0207 0208 d->categoryView->setSelectionMode(QAbstractItemView::SingleSelection); 0209 // PORT QT5 d->categoryView->setSpacing( KDialog::spacingHint() ); 0210 d->categoryView->setCategoryDrawer(d->categoryDrawer); 0211 d->categoryView->setViewMode(QListView::IconMode); 0212 d->categoryView->setMouseTracking(true); 0213 d->categoryView->viewport()->setAttribute(Qt::WA_Hover); 0214 0215 KFileItemDelegate *delegate = new KFileItemDelegate(d->categoryView); 0216 delegate->setWrapMode(QTextOption::WordWrap); 0217 d->categoryView->setItemDelegate(delegate); 0218 0219 d->categoryView->setFrameShape(QFrame::NoFrame); 0220 d->categoryView->setModel(d->proxyModel); 0221 connect(d->categoryView, &QAbstractItemView::activated, this, &IconMode::changeModule); 0222 0223 d->mainWidget->addWidget(d->categoryView); 0224 d->mainWidget->addWidget(d->moduleView); 0225 d->mainWidget->setCurrentWidget(d->categoryView); 0226 Q_EMIT changeToolBarItems(BaseMode::Search | BaseMode::Configure | BaseMode::Quit); 0227 d->mainWidget->installEventFilter(this); 0228 0229 if (!startupModule().isEmpty()) { 0230 MenuItem *item = rootItem()->descendantForModule(startupModule()); 0231 if (item) { 0232 changeModuleWithArgs(d->proxyModel->mapFromSource(d->model->indexForItem(item)), startupModuleArgs()); 0233 } 0234 } 0235 } 0236 0237 void IconMode::reloadStartupModule() 0238 { 0239 if (!startupModule().isEmpty()) { 0240 MenuItem *item = rootItem()->descendantForModule(startupModule()); 0241 if (item) { 0242 changeModuleWithArgs(d->proxyModel->mapFromSource(d->model->indexForItem(item)), startupModuleArgs()); 0243 } 0244 } 0245 } 0246 0247 bool IconMode::eventFilter(QObject *watched, QEvent *event) 0248 { 0249 if (watched == d->mainWidget && event->type() == QEvent::Show) { 0250 Q_EMIT changeToolBarItems(BaseMode::Search | BaseMode::Configure | BaseMode::Quit); 0251 } 0252 return BaseMode::eventFilter(watched, event); 0253 } 0254 0255 void IconMode::leaveModuleView() 0256 { 0257 d->moduleView->closeModules(); // We have to force it here 0258 backToOverview(); 0259 } 0260 0261 void IconMode::giveFocus() 0262 { 0263 d->categoryView->setFocus(); 0264 } 0265 0266 #include "IconMode.moc"