diff --git a/app/SettingsBase.cpp b/app/SettingsBase.cpp index a2f44f50..b8bcb0a9 100644 --- a/app/SettingsBase.cpp +++ b/app/SettingsBase.cpp @@ -1,409 +1,412 @@ /*************************************************************************** * Copyright (C) 2009 by Ben Cooksley * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA * ***************************************************************************/ #include "SettingsBase.h" #include "BaseConfig.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "BaseData.h" #include "ModuleView.h" SettingsBase::SettingsBase( QWidget * parent ) : KXmlGuiWindow(parent) { // Ensure delayed loading doesn't cause a crash activeView = 0; aboutDialog = 0; configDialog = 0; lostFound = 0; // Prepare the view area stackedWidget = new QStackedWidget( this ); setWindowTitle(i18n("System Settings")); setWindowIcon(QIcon::fromTheme("preferences-system")); setCentralWidget(stackedWidget); setWindowFlags( windowFlags() | Qt::WindowContextHelpButtonHint ); // Initialise search searchText = new KLineEdit( this ); searchText->setClearButtonShown( true ); searchText->setPlaceholderText( i18nc( "Search through a list of control modules", "Search" ) ); searchText->setCompletionMode( KCompletion::CompletionPopup ); spacerWidget = new QWidget( this ); spacerWidget->setSizePolicy( QSizePolicy::MinimumExpanding, QSizePolicy::Maximum ); // Initalise the window so we don't flicker initToolBar(); // We can now launch the delayed loading safely QTimer::singleShot(0, this, &SettingsBase::initApplication); } SettingsBase::~SettingsBase() { delete rootModule; } QSize SettingsBase::sizeHint() const { qreal factor = qBound(1., QGuiApplication::primaryScreen()->physicalDotsPerInch()/96., 3.); return QSize(720*factor, 600*factor); } void SettingsBase::initApplication() { // Prepare the menu of all modules categories = KServiceTypeTrader::self()->query("SystemSettingsCategory"); modules = KServiceTypeTrader::self()->query("KCModule", "[X-KDE-System-Settings-Parent-Category] != ''"); modules += KServiceTypeTrader::self()->query("SystemSettingsExternalApp"); rootModule = new MenuItem( true, 0 ); initMenuList(rootModule); // Handle lost+found modules... if (lostFound) { for (int i = 0; i < modules.size(); ++i) { const KService::Ptr entry = modules.at(i); MenuItem * infoItem = new MenuItem(false, lostFound); infoItem->setService( entry ); qDebug() << "Added " << entry->name(); } } // Prepare the Base Data BaseData::instance()->setMenuItem( rootModule ); // Load all possible views const KService::List pluginObjects = KServiceTypeTrader::self()->query( "SystemSettingsView" ); const int nbPlugins = pluginObjects.count(); for( int pluginsDone = 0; pluginsDone < nbPlugins ; ++pluginsDone ) { KService::Ptr activeService = pluginObjects.at( pluginsDone ); QString error; BaseMode * controller = activeService->createInstance(this, QVariantList(), &error); if( error.isEmpty() ) { possibleViews.insert( activeService->library(), controller ); controller->init( activeService ); connect(controller, &BaseMode::changeToolBarItems, this, &SettingsBase::changeToolBar); connect(controller, &BaseMode::actionsChanged, this, &SettingsBase::updateViewActions); connect(searchText, &KLineEdit::textChanged, controller, &BaseMode::searchChanged); connect(controller, &BaseMode::viewChanged, this, &SettingsBase::viewChange); } else { qWarning() << "View load error: " + error; } } searchText->completionObject()->setIgnoreCase( true ); searchText->completionObject()->setItems( BaseData::instance()->menuItem()->keywords() ); changePlugin(); activateWindow(); } void SettingsBase::initToolBar() { // Fill the toolbar with default actions // Exit is the very last action quitAction = actionCollection()->addAction( KStandardAction::Quit, "quit_action", this, SLOT(close()) ); // Configure goes at the end configureAction = actionCollection()->addAction( KStandardAction::Preferences, this, SLOT(configShow()) ); actionCollection()->setDefaultShortcut(configureAction, QKeySequence(Qt::CTRL + Qt::Key_M)); configureAction->setText( i18n("Configure") ); // Help after it initHelpMenu(); configureAction->setIcon(QIcon::fromTheme("application-menu")); // Then a spacer so the search line-edit is kept separate spacerAction = new QWidgetAction( this ); spacerAction->setDefaultWidget(spacerWidget); actionCollection()->addAction( "spacer", spacerAction ); // Finally the search line-edit searchAction = new QWidgetAction( this ); searchAction->setDefaultWidget(searchText); actionCollection()->setDefaultShortcut(searchAction, QKeySequence(Qt::CTRL + Qt::Key_F)); connect( searchAction, SIGNAL(triggered(bool)), searchText, SLOT(setFocus())); actionCollection()->addAction( "searchText", searchAction ); // Initialise the Window setupGUI(Save|Create,QString()); menuBar()->hide(); // Toolbar & Configuration helpActionMenu->setMenu( dynamic_cast( factory()->container("help", this) ) ); setMinimumSize(620,430); toolBar()->setMovable(false); // We don't allow any changes changeToolBar( BaseMode::Search | BaseMode::Configure ); } void SettingsBase::initHelpMenu() { helpActionMenu = new KActionMenu( QIcon::fromTheme("help-contents"), i18n("Help"), this ); helpActionMenu->setDelayed( false ); actionCollection()->addAction( "help_toolbar_menu", helpActionMenu ); // Add the custom actions aboutModuleAction = actionCollection()->addAction( KStandardAction::AboutApp, "help_about_module", this, SLOT(about()) ); changeAboutMenu( 0, aboutModuleAction, i18n("About Active Module") ); aboutViewAction = actionCollection()->addAction( KStandardAction::AboutApp, "help_about_view", this, SLOT(about()) ); } void SettingsBase::initConfig() { // Prepare dialog first configDialog = new KConfigDialog( this, "systemsettingsconfig", BaseConfig::self() ); configDialog->setStandardButtons(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); // Add our page QWidget * configPage = new QWidget( configDialog ); configWidget.setupUi(configPage); QString iconName = KAboutData::applicationData().programIconName(); configDialog->addPage( configPage, i18nc("General config for System Settings", "General"), iconName ); QVBoxLayout * configLayout = new QVBoxLayout; // Get the list of modules foreach( BaseMode * mode, possibleViews ) { mode->addConfiguration( configDialog ); QRadioButton * radioButton = new QRadioButton( mode->service()->name(), configWidget.GbViewStyle ); radioButton->setIcon( QIcon::fromTheme(mode->service()->icon()) ); configLayout->addWidget( radioButton ); viewSelection.addButton( radioButton, possibleViews.values().indexOf(mode) ); } configWidget.GbViewStyle->setLayout( configLayout ); KWindowConfig::restoreWindowSize(configDialog->windowHandle(), KSharedConfig::openConfig()->group("ConfigDialog")); connect(configDialog, &KConfigDialog::accepted, this, &SettingsBase::configUpdated); } void SettingsBase::initMenuList(MenuItem * parent) { // look for any categories inside this level, and recurse into them for (int i = 0; i < categories.size(); ++i) { const KService::Ptr entry = categories.at(i); const QString parentCategory = entry->property("X-KDE-System-Settings-Parent-Category").toString(); const QString parentCategory2 = entry->property("X-KDE-System-Settings-Parent-Category-V2").toString(); if ( parentCategory == parent->category() || // V2 entries must not be empty if they want to become a proper category. ( !parentCategory2.isEmpty() && parentCategory2 == parent->category() ) ) { MenuItem * menuItem = new MenuItem(true, parent); menuItem->setService( entry ); if( menuItem->category() == "lost-and-found" ) { lostFound = menuItem; continue; } initMenuList( menuItem ); } } KService::List removeList; // scan for any modules at this level and add them for (int i = 0; i < modules.size(); ++i) { const KService::Ptr entry = modules.at(i); const QString category = entry->property("X-KDE-System-Settings-Parent-Category").toString(); const QString category2 = entry->property("X-KDE-System-Settings-Parent-Category-V2").toString(); if( !parent->category().isEmpty() && (category == parent->category() || category2 == parent->category()) ) { - // Add the module info to the menu - MenuItem * infoItem = new MenuItem(false, parent); - infoItem->setService( entry ); + if (!entry->noDisplay() ) { + // Add the module info to the menu + MenuItem * infoItem = new MenuItem(false, parent); + infoItem->setService( entry ); + } + removeList.append( modules.at(i) ); } } for (int i = 0; i < removeList.size(); ++i) { modules.removeOne( removeList.at(i) ); } parent->sortChildrenByWeight(); } void SettingsBase::configUpdated() { KConfigGroup dialogConfig = KSharedConfig::openConfig()->group("ConfigDialog"); KWindowConfig::saveWindowSize(configDialog->windowHandle(), dialogConfig); BaseConfig::setActiveView( possibleViews.keys().at(viewSelection.checkedId()) ); BaseConfig::setShowToolTips( configWidget.ChTooltips->isChecked() ); activeView->saveConfiguration(); changePlugin(); } void SettingsBase::configShow() { // Initialise the configuration dialog if it hasn't already if( !configDialog ) { initConfig(); } if( activeView && activeView->moduleView() && !activeView->moduleView()->resolveChanges() ) { return; // It shouldn't be triggering anyway, since the action is disabled } activeView->loadConfiguration(); const QStringList pluginList = possibleViews.keys(); const int configIndex = pluginList.indexOf( BaseConfig::activeView() ); if( configIndex != -1 ) { viewSelection.button( configIndex )->setChecked(true); } configWidget.ChTooltips->setChecked( BaseConfig::showToolTips() ); if( pluginList.isEmpty() ) { KMessageBox::error(this, i18n("System Settings was unable to find any views, and hence nothing is available to configure."), i18n("No views found")); } else { configDialog->show(); } } bool SettingsBase::queryClose() { bool changes = true; if( activeView ) { activeView->saveState(); changes = activeView->moduleView()->resolveChanges(); } BaseConfig::self()->save(); return changes; } void SettingsBase::about() { delete aboutDialog; aboutDialog = 0; const KAboutData * about = 0; if( sender() == aboutViewAction ) { about = activeView->aboutData(); } else if( sender() == aboutModuleAction && activeView->moduleView() ) { about = activeView->moduleView()->aboutData(); } if( about ) { aboutDialog = new KAboutApplicationDialog(*about, 0); aboutDialog->show(); } } void SettingsBase::changePlugin() { if( possibleViews.count() == 0 ) { // We should ensure we have a plugin available to choose KMessageBox::error(this, i18n("System Settings was unable to find any views, and hence has nothing to display."), i18n("No views found")); close(); return; // Halt now! } if( activeView ) { activeView->saveState(); activeView->leaveModuleView(); } const QString viewToUse = BaseConfig::activeView(); if( possibleViews.keys().contains(viewToUse) ) { // First the configuration entry activeView = possibleViews.value(viewToUse); } else { // Otherwise we activate the failsafe activeView = possibleViews.begin().value(); } if( stackedWidget->indexOf(activeView->mainWidget()) == -1 ) { stackedWidget->addWidget(activeView->mainWidget()); } // Handle the tooltips qDeleteAll( tooltipManagers ); tooltipManagers.clear(); if ( BaseConfig::showToolTips() ) { QList theViews = activeView->views(); foreach ( QAbstractItemView* view, theViews ) { tooltipManagers << new ToolTipManager( view ); } } changeAboutMenu( activeView->aboutData(), aboutViewAction, i18n("About Active View") ); viewChange(false); stackedWidget->setCurrentWidget(activeView->mainWidget()); updateViewActions(); activeView->giveFocus(); } void SettingsBase::viewChange(bool state) { KCModuleInfo * moduleInfo = activeView->moduleView()->activeModule(); configureAction->setDisabled(state); if( moduleInfo ) { setCaption( moduleInfo->moduleName(), state ); } else { setCaption( QString(), state ); } changeAboutMenu( activeView->moduleView()->aboutData(), aboutModuleAction, i18n("About Active Module") ); } void SettingsBase::updateViewActions() { guiFactory()->unplugActionList( this, "viewActions" ); guiFactory()->plugActionList( this, "viewActions", activeView->actionsList() ); } void SettingsBase::changeToolBar( BaseMode::ToolBarItems toolbar ) { if( sender() != activeView ) { return; } guiFactory()->unplugActionList( this, "configure" ); guiFactory()->unplugActionList( this, "search" ); guiFactory()->unplugActionList( this, "quit" ); if ( BaseMode::Search & toolbar ) { QList searchBarActions; searchBarActions << spacerAction << searchAction; guiFactory()->plugActionList( this, "search", searchBarActions ); } if ( BaseMode::Configure & toolbar ) { QList configureBarActions; configureBarActions << configureAction; guiFactory()->plugActionList( this, "configure", configureBarActions ); } if ( BaseMode::Quit & toolbar ) { QList quitBarActions; quitBarActions << quitAction; guiFactory()->plugActionList( this, "quit", quitBarActions ); } } void SettingsBase::changeAboutMenu( const KAboutData * menuAbout, QAction * menuItem, QString fallback ) { if( !menuItem ) { return; } if( menuAbout ) { menuItem->setText( i18n( "About %1", menuAbout->displayName() ) ); menuItem->setIcon( QIcon::fromTheme( menuAbout->programIconName() ) ); menuItem->setEnabled(true); } else { menuItem->setText( fallback ); menuItem->setIcon( QIcon::fromTheme( KAboutData::applicationData().programIconName() ) ); menuItem->setEnabled(false); } }