diff --git a/app/SettingsBase.cpp b/app/SettingsBase.cpp index 3e04cee6..409663da 100644 --- a/app/SettingsBase.cpp +++ b/app/SettingsBase.cpp @@ -1,417 +1,417 @@ /*************************************************************************** * 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 "systemsettings_app_debug.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 = nullptr; aboutDialog = nullptr; configDialog = nullptr; lostFound = nullptr; // Prepare the view area stackedWidget = new QStackedWidget( this ); setWindowTitle(i18n("System Settings")); setWindowIcon(QIcon::fromTheme(QStringLiteral("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(QStringLiteral("SystemSettingsCategory")); modules = KServiceTypeTrader::self()->query(QStringLiteral("KCModule"), QStringLiteral("[X-KDE-System-Settings-Parent-Category] != ''")); modules += KServiceTypeTrader::self()->query(QStringLiteral("SystemSettingsExternalApp")); rootModule = new MenuItem( true, nullptr ); 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 ); qCDebug(SYSTEMSETTINGS_APP_LOG) << "Added " << entry->name(); } } // Prepare the Base Data BaseData::instance()->setMenuItem( rootModule ); // Load all possible views const KService::List pluginObjects = KServiceTypeTrader::self()->query( QStringLiteral("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 { qCWarning(SYSTEMSETTINGS_APP_LOG) << QStringLiteral("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, QStringLiteral("quit_action"), this, SLOT(close()) ); // Configure goes at the end configureAction = actionCollection()->addAction( KStandardAction::Preferences, QStringLiteral("configure"), this, SLOT(configShow()) ); actionCollection()->setDefaultShortcut(configureAction, QKeySequence(Qt::CTRL + Qt::Key_M)); configureAction->setText( i18n("Configure") ); // Help after it initHelpMenu(); configureAction->setIcon(QIcon::fromTheme(QStringLiteral("application-menu"))); // Then a spacer so the search line-edit is kept separate spacerAction = new QWidgetAction( this ); spacerAction->setDefaultWidget(spacerWidget); actionCollection()->addAction( QStringLiteral("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( QStringLiteral("searchText"), searchAction ); // Initialise the Window setupGUI(Save|Create,QString()); menuBar()->hide(); // Toolbar & Configuration helpActionMenu->setMenu( dynamic_cast( factory()->container(QStringLiteral("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(QStringLiteral("help-contents")), i18n("Help"), this ); helpActionMenu->setDelayed( false ); actionCollection()->addAction( QStringLiteral("help_toolbar_menu"), helpActionMenu ); // Add the custom actions aboutModuleAction = actionCollection()->addAction( KStandardAction::AboutApp, QStringLiteral("help_about_module"), this, SLOT(about()) ); - changeAboutMenu( 0, aboutModuleAction, i18n("About Active Module") ); + changeAboutMenu( nullptr, aboutModuleAction, i18n("About Active Module") ); aboutViewAction = actionCollection()->addAction( KStandardAction::AboutApp, QStringLiteral("help_about_view"), this, SLOT(about()) ); } void SettingsBase::initConfig() { // Prepare dialog first configDialog = new KConfigDialog( this, QStringLiteral("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(QStringLiteral("X-KDE-System-Settings-Parent-Category")).toString(); const QString parentCategory2 = entry->property(QStringLiteral("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() == QLatin1String("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(QStringLiteral("X-KDE-System-Settings-Parent-Category")).toString(); const QString category2 = entry->property(QStringLiteral("X-KDE-System-Settings-Parent-Category-V2")).toString(); 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); 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->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; + aboutDialog = nullptr; - const KAboutData * about = 0; + const KAboutData * about = nullptr; if( sender() == aboutViewAction ) { about = activeView->aboutData(); } else if( sender() == aboutModuleAction && activeView->moduleView() ) { about = activeView->moduleView()->aboutData(); } if( about ) { - aboutDialog = new KAboutApplicationDialog(*about, 0); + aboutDialog = new KAboutApplicationDialog(*about, nullptr); 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 ); } } activeView->setShowToolTips( BaseConfig::showToolTips() ); 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, QStringLiteral("viewActions") ); guiFactory()->plugActionList( this, QStringLiteral("viewActions"), activeView->actionsList() ); } void SettingsBase::changeToolBar( BaseMode::ToolBarItems toolbar ) { if( sender() != activeView ) { return; } guiFactory()->unplugActionList( this, QStringLiteral("configure") ); guiFactory()->unplugActionList( this, QStringLiteral("search") ); guiFactory()->unplugActionList( this, QStringLiteral("quit") ); if ( BaseMode::Search & toolbar ) { QList searchBarActions; searchBarActions << spacerAction << searchAction; guiFactory()->plugActionList( this, QStringLiteral("search"), searchBarActions ); } if ( BaseMode::Configure & toolbar ) { QList configureBarActions; configureBarActions << configureAction; guiFactory()->plugActionList( this, QStringLiteral("configure"), configureBarActions ); } if ( BaseMode::Quit & toolbar ) { QList quitBarActions; quitBarActions << quitAction; guiFactory()->plugActionList( this, QStringLiteral("quit"), quitBarActions ); } toolBar()->setVisible(toolbar != BaseMode::NoItems || (activeView && activeView->actionsList().count() > 0)); } 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); } } diff --git a/app/ToolTips/tooltipmanager.cpp b/app/ToolTips/tooltipmanager.cpp index 3fc5fba6..6097e062 100644 --- a/app/ToolTips/tooltipmanager.cpp +++ b/app/ToolTips/tooltipmanager.cpp @@ -1,213 +1,213 @@ /******************************************************************************* * Copyright (C) 2008 by Konstantin Heil * * * * 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 "tooltipmanager.h" #include "MenuItem.h" #include #include #include #include #include #include #include #include #include #include #include class ToolTipManager::Private { public: Private() : - tooltip(0), - view(0), - timer(0), + tooltip(nullptr), + view(nullptr), + timer(nullptr), delay(300) { } KToolTipWidget *tooltip; QAbstractItemView* view; QTimer* timer; QModelIndex item; QRect itemRect; int delay; }; ToolTipManager::ToolTipManager(QAbstractItemView* parent) : QObject(parent) , d(new ToolTipManager::Private) { d->view = parent; d->tooltip = new KToolTipWidget(d->view); d->tooltip->setHideDelay(0); connect(parent, &QAbstractItemView::viewportEntered, this, &ToolTipManager::hideToolTip); connect(parent, &QAbstractItemView::entered, this, &ToolTipManager::requestToolTip); d->timer = new QTimer(this); d->timer->setSingleShot(true); connect(d->timer, &QTimer::timeout, this, &ToolTipManager::prepareToolTip); // When the mousewheel is used, the items don't get a hovered indication // (Qt-issue #200665). To assure that the tooltip still gets hidden, // the scrollbars are observed. connect(parent->horizontalScrollBar(), &QAbstractSlider::valueChanged, this, &ToolTipManager::hideToolTip); connect(parent->verticalScrollBar(), &QAbstractSlider::valueChanged, this, &ToolTipManager::hideToolTip); d->view->viewport()->installEventFilter(this); } ToolTipManager::~ToolTipManager() { delete d; } bool ToolTipManager::eventFilter(QObject* watched, QEvent* event) { if (watched == d->view->viewport()) { switch (event->type()) { case QEvent::Leave: case QEvent::MouseButtonPress: hideToolTip(); break; default: break; } } return QObject::eventFilter(watched, event); } void ToolTipManager::requestToolTip(const QModelIndex& index) { // only request a tooltip for the name column and when no selection or // drag & drop operation is done (indicated by the left mouse button) if ( !(QApplication::mouseButtons() & Qt::LeftButton) ) { d->tooltip->hide(); d->itemRect = d->view->visualRect(index); const QPoint pos = d->view->viewport()->mapToGlobal(d->itemRect.topLeft()); d->itemRect.moveTo(pos); d->item = index; d->timer->start(d->delay); } else { hideToolTip(); } } void ToolTipManager::hideToolTip() { d->timer->stop(); d->tooltip->hideLater(); } void ToolTipManager::prepareToolTip() { showToolTip( d->item ); } void ToolTipManager::showToolTip( QModelIndex menuItem ) { if (QApplication::mouseButtons() & Qt::LeftButton) { return; } QWidget * tip = createTipContent( menuItem ); d->tooltip->showBelow(d->itemRect, tip, d->view->nativeParentWidget()->windowHandle()); connect(d->tooltip, &KToolTipWidget::hidden, tip, &QObject::deleteLater); } QWidget * ToolTipManager::createTipContent( QModelIndex item ) { const QSize dialogIconSize = QSize(IconSize(KIconLoader::Dialog), IconSize(KIconLoader::Dialog)); const QSize toolbarIconSize = QSize(IconSize(KIconLoader::MainToolbar), IconSize(KIconLoader::MainToolbar)); QWidget * tipContent = new QWidget(); QGridLayout* tipLayout = new QGridLayout(); tipLayout->setAlignment( Qt::AlignLeft ); QLayout * primaryLine = generateToolTipLine( &item, tipContent, dialogIconSize, true ); primaryLine->setAlignment( Qt::AlignLeft ); tipLayout->addLayout( primaryLine, 0, 0, Qt::AlignLeft ); for ( int done = 0; d->view->model()->rowCount( item ) > done; done = 1 + done ) { QModelIndex childItem = d->view->model()->index( done, 0, item ); QLayout * subLine = generateToolTipLine( &childItem, tipContent, toolbarIconSize, false ); subLine->setAlignment( Qt::AlignLeft ); tipLayout->addLayout( subLine, done + 2, 0, Qt::AlignLeft ); } tipLayout->setVerticalSpacing( tipContent->fontMetrics().height() / 3 ); tipContent->setLayout( tipLayout ); if( d->view->model()->rowCount( item ) > 0 ) { QFrame * separatorLine = new QFrame( tipContent ); separatorLine->setFrameStyle( QFrame::HLine ); tipLayout->addWidget( separatorLine, 1, 0 ); } return tipContent; } QLayout * ToolTipManager::generateToolTipLine( QModelIndex * item, QWidget * toolTip, QSize iconSize, bool comment ) { // Get MenuItem MenuItem * menuItem = d->view->model()->data( *item, Qt::UserRole ).value(); QString text = menuItem->name(); if ( comment ) { text = QStringLiteral( "%1" ).arg( menuItem->name() ); } // Generate text if ( comment ) { text += QStringLiteral("
"); if ( !menuItem->service()->comment().isEmpty() ) { text += menuItem->service()->comment(); } else { int childCount = d->view->model()->rowCount( *item ); text += i18np( "Contains 1 item", "Contains %1 items", childCount ); } } QLabel * textLabel = new QLabel( toolTip ); textLabel->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed ); textLabel->setForegroundRole(QPalette::ToolTipText); textLabel->setText( text ); // Get icon QLabel * iconLabel = new QLabel( toolTip ); iconLabel->setPixmap( QIcon::fromTheme(menuItem->service()->icon()).pixmap(iconSize) ); iconLabel->setMaximumSize( iconSize ); // Generate layout QHBoxLayout * layout = new QHBoxLayout(); layout->setSpacing( textLabel->fontMetrics().height() / 3 ); layout->setAlignment( Qt::AlignLeft ); layout->addWidget( iconLabel, Qt::AlignLeft ); layout->addWidget( textLabel, Qt::AlignLeft ); return layout; } diff --git a/classic/ClassicMode.cpp b/classic/ClassicMode.cpp index 069e8714..4a8932bf 100644 --- a/classic/ClassicMode.cpp +++ b/classic/ClassicMode.cpp @@ -1,276 +1,276 @@ /************************************************************************** * Copyright (C) 2009 Ben Cooksley * * Copyright (C) 2008 Mathias Soeken * * * * 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 "ClassicMode.h" #include "ui_configClassic.h" #include #include #include #include #include #include #include #include #include #include "MenuItem.h" #include "MenuModel.h" #include "ModuleView.h" #include "CategoryList.h" #include "MenuProxyModel.h" K_PLUGIN_FACTORY(ClassicModeFactory, registerPlugin();) class ClassicMode::Private { public: Private() {} virtual ~Private() { delete aboutClassic; } QSplitter * classicWidget = nullptr; QTreeView * classicTree = nullptr; Ui::ConfigClassic classicConfig; CategoryList * classicCategory = nullptr; QStackedWidget * stackedWidget = nullptr; ModuleView * moduleView = nullptr; QModelIndex currentItem; MenuProxyModel * proxyModel = nullptr; MenuModel * model = nullptr; KAboutData * aboutClassic = nullptr; }; ClassicMode::ClassicMode( QObject * parent, const QVariantList& ) : BaseMode( parent ), d( new Private() ) { d->aboutClassic = new KAboutData(QStringLiteral("TreeView"), i18n("Tree View"), QStringLiteral("1.0"), i18n("Provides a classic tree-based view of control modules."), KAboutLicense::GPL, i18n("(c) 2009, Ben Cooksley")); d->aboutClassic->addAuthor(i18n("Ben Cooksley"), i18n("Author"), QStringLiteral("bcooksley@kde.org")); d->aboutClassic->addAuthor(i18n("Mathias Soeken"), i18n("Developer"), QStringLiteral("msoeken@informatik.uni-bremen.de")); d->aboutClassic->setProgramIconName(QStringLiteral("view-list-tree")); } ClassicMode::~ClassicMode() { if( !d->classicTree ) { delete d->classicWidget; } delete d; } void ClassicMode::initEvent() { // Create the model d->model = new MenuModel( rootItem(), this ); // Move items that are the sole child of a category up.... moveUp( rootItem() ); // Create the proxy model d->proxyModel = new MenuProxyModel( this ); d->proxyModel->setSourceModel( d->model ); d->proxyModel->sort( 0 ); - d->classicWidget = new QSplitter( Qt::Horizontal, 0 ); + d->classicWidget = new QSplitter( Qt::Horizontal, nullptr ); d->classicWidget->setChildrenCollapsible( false ); d->moduleView = new ModuleView( d->classicWidget ); d->classicTree = nullptr; } QWidget * ClassicMode::mainWidget() { if( !d->classicTree ) { initWidget(); } return d->classicWidget; } KAboutData * ClassicMode::aboutData() { return d->aboutClassic; } ModuleView * ClassicMode::moduleView() const { return d->moduleView; } QList ClassicMode::views() const { QList theViews; theViews << d->classicTree; return theViews; } void ClassicMode::saveState() { config().writeEntry( "viewLayout", d->classicWidget->sizes() ); config().sync(); } void ClassicMode::expandColumns() { d->classicTree->resizeColumnToContents(0); } void ClassicMode::searchChanged( const QString& text ) { d->proxyModel->setFilterRegExp(text); if( d->classicTree ) { d->classicCategory->changeModule( d->classicTree->currentIndex() ); } } void ClassicMode::selectModule( const QModelIndex& selectedModule ) { d->classicTree->setCurrentIndex( selectedModule ); if( d->proxyModel->rowCount(selectedModule) > 0 ) { d->classicTree->setExpanded(selectedModule, true); } changeModule( selectedModule ); } void ClassicMode::changeModule( const QModelIndex& activeModule ) { if( activeModule == d->currentItem ) { return; } if( !d->moduleView->resolveChanges() ) { return; } d->moduleView->closeModules(); d->currentItem = activeModule; if( d->proxyModel->rowCount(activeModule) > 0 ) { d->stackedWidget->setCurrentWidget( d->classicCategory ); d->classicCategory->changeModule(activeModule); emit viewChanged( false ); } else { d->moduleView->loadModule( activeModule ); } } void ClassicMode::moduleLoaded() { d->stackedWidget->setCurrentWidget( d->moduleView ); } void ClassicMode::initWidget() { // Create the widget d->classicTree = new QTreeView( d->classicWidget ); d->classicCategory = new CategoryList( d->classicWidget, d->proxyModel ); d->stackedWidget = new QStackedWidget( d->classicWidget ); d->stackedWidget->layout()->setMargin(0); d->stackedWidget->addWidget( d->classicCategory ); d->stackedWidget->addWidget( d->moduleView ); d->classicWidget->addWidget( d->classicTree ); d->classicWidget->addWidget( d->stackedWidget ); d->classicTree->setModel( d->proxyModel ); d->classicTree->setHeaderHidden( true ); d->classicTree->setIconSize( QSize( 24, 24 ) ); d->classicTree->setSortingEnabled( true ); d->classicTree->setMouseTracking( true ); d->classicTree->setMinimumWidth( 200 ); d->classicTree->setSelectionMode( QAbstractItemView::SingleSelection ); d->classicTree->sortByColumn( 0, Qt::AscendingOrder ); d->classicCategory->changeModule( d->classicTree->rootIndex() ); connect( d->classicCategory, &CategoryList::moduleSelected, this, &ClassicMode::selectModule ); connect( d->classicTree, &QAbstractItemView::activated, this, &ClassicMode::changeModule ); connect( d->classicTree, &QTreeView::collapsed, this, &ClassicMode::expandColumns ); connect( d->classicTree, &QTreeView::expanded, this, &ClassicMode::expandColumns ); connect( d->moduleView, &ModuleView::moduleChanged, this, &ClassicMode::moduleLoaded ); if( !qApp->style()->styleHint(QStyle::SH_ItemView_ActivateItemOnSingleClick) ) { // Needed because otherwise activated() is not fired with single click, which is apparently expected for tree views connect( d->classicTree, &QAbstractItemView::clicked, this, &ClassicMode::changeModule ); } if( config().readEntry( "autoExpandOneLevel", false ) ) { for( int processed = 0; d->proxyModel->rowCount() > processed; processed++ ) { d->classicTree->setExpanded( d->proxyModel->index( processed, 0 ), true ); } } expandColumns(); QList defaultSizes; defaultSizes << 250 << 500; d->classicWidget->setSizes( config().readEntry( "viewLayout", defaultSizes ) ); emit changeToolBarItems( BaseMode::Search | BaseMode::Configure | BaseMode::Quit ); d->classicWidget->installEventFilter(this); } bool ClassicMode::eventFilter(QObject* watched, QEvent* event) { if (watched == d->classicWidget && event->type() == QEvent::Show) { emit changeToolBarItems( BaseMode::Search | BaseMode::Configure | BaseMode::Quit ); } return BaseMode::eventFilter(watched, event); } void ClassicMode::leaveModuleView() { d->moduleView->closeModules(); d->stackedWidget->setCurrentWidget( d->classicCategory ); } void ClassicMode::giveFocus() { d->classicTree->setFocus(); } void ClassicMode::addConfiguration( KConfigDialog * config ) { QWidget * configWidget = new QWidget( config ); d->classicConfig.setupUi( configWidget ); config->addPage( configWidget, i18n("Tree View"), aboutData()->programIconName() ); } void ClassicMode::loadConfiguration() { d->classicConfig.CbExpand->setChecked( config().readEntry( "autoExpandOneLevel", false ) ); } void ClassicMode::saveConfiguration() { config().writeEntry("autoExpandOneLevel", d->classicConfig.CbExpand->isChecked()); } void ClassicMode::moveUp( MenuItem * item ) { foreach( MenuItem * child, item->children() ) { if( child->children().count() == 1 ) { d->model->addException( child ); } moveUp( child ); } } #include "ClassicMode.moc" diff --git a/core/ExternalAppModule.h b/core/ExternalAppModule.h index 9be29315..e613fff9 100644 --- a/core/ExternalAppModule.h +++ b/core/ExternalAppModule.h @@ -1,50 +1,50 @@ /*************************************************************************** * Copyright (C) 2009 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 * ***************************************************************************/ #ifndef EXTERNALAPPMODULE_H #define EXTERNALAPPMODULE_H #include #include "ui_externalModule.h" class QShowEvent; class KCModuleInfo; class ExternalAppModule : public QWidget { Q_OBJECT public: - explicit ExternalAppModule(QWidget * parent = 0, KCModuleInfo * module = 0); + explicit ExternalAppModule(QWidget * parent = nullptr, KCModuleInfo * module = nullptr); ~ExternalAppModule() override; protected: void showEvent(QShowEvent * event) override; private Q_SLOTS: void runExternal(); private: KCModuleInfo * moduleInfo; Ui::ExternalModule externalModule; bool firstShow; }; #endif diff --git a/core/MenuModel.cpp b/core/MenuModel.cpp index 45a5a020..e8a3889f 100644 --- a/core/MenuModel.cpp +++ b/core/MenuModel.cpp @@ -1,204 +1,204 @@ /************************************************************************** * Copyright (C) 2009 Ben Cooksley * * Copyright (C) 2007 Will Stephenson * * * * 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 "MenuModel.h" #include #include #include "MenuItem.h" const int MenuModel::UserFilterRole = 0x015D1AE6; const int MenuModel::UserSortRole = 0x03A8CC00; class MenuModel::Private { public: Private() {} MenuItem *rootItem = nullptr; QList exceptions; }; MenuModel::MenuModel( MenuItem * menuRoot, QObject *parent ) : QAbstractItemModel( parent ) , d( new Private() ) { d->rootItem = menuRoot; } MenuModel::~MenuModel() { d->exceptions.clear(); delete d; } int MenuModel::columnCount( const QModelIndex &parent ) const { Q_UNUSED( parent ); return 1; } int MenuModel::rowCount( const QModelIndex &parent ) const { MenuItem * mi; if ( parent.isValid() ) { mi = static_cast( parent.internalPointer() ); } else { mi = d->rootItem; } return childrenList(mi).count(); } QVariant MenuModel::data( const QModelIndex &index, int role ) const { MenuItem * mi = nullptr; QVariant theData; if ( !index.isValid() ) { return QVariant(); } mi = static_cast( index.internalPointer() ); switch ( role ) { case Qt::DisplayRole: theData.setValue( mi->name() ); break; case Qt::ToolTipRole: theData.setValue( mi->service()->comment() ); break; case Qt::DecorationRole: theData = QVariant( QIcon::fromTheme( mi->service()->icon() ) ); break; case KCategorizedSortFilterProxyModel::CategorySortRole: if ( mi->parent() ) { theData.setValue( QStringLiteral("%1%2").arg( QString::number(mi->parent()->weight()), 5, QLatin1Char('0') ).arg( mi->parent()->name() ) ); } break; case KCategorizedSortFilterProxyModel::CategoryDisplayRole: if ( mi->parent() ) { theData.setValue( mi->parent()->name() ); } break; case Qt::UserRole: theData.setValue( mi ); break; case MenuModel::UserFilterRole: theData.setValue( mi->keywords().join( QString() ) ); break; case MenuModel::UserSortRole: theData.setValue( QStringLiteral("%1").arg( QString::number(mi->weight()), 5, QLatin1Char('0') ) ); break; default: break; } return theData; } Qt::ItemFlags MenuModel::flags( const QModelIndex &index ) const { if ( !index.isValid() ) { - return 0; + return nullptr; } return Qt::ItemIsEnabled | Qt::ItemIsSelectable; } QModelIndex MenuModel::index( int row, int column, const QModelIndex &parent ) const { if ( !hasIndex(row, column, parent) ) { return QModelIndex(); } MenuItem *parentItem; if ( !parent.isValid() ) { parentItem = d->rootItem; } else { parentItem = static_cast( parent.internalPointer() ); } MenuItem *childItem = childrenList(parentItem).value(row); if ( childItem ) { return createIndex( row, column, childItem ); } else { return QModelIndex(); } } QModelIndex MenuModel::parent( const QModelIndex &index ) const { MenuItem *childItem = static_cast( index.internalPointer() ); if( !childItem ) { return QModelIndex(); } MenuItem * parent = parentItem(childItem); MenuItem * grandParent = parentItem(parent); int childRow = 0; if( grandParent ) { childRow = childrenList( grandParent ).indexOf( parent ); } if ( parent == d->rootItem ) { return QModelIndex(); } return createIndex( childRow, 0, parent ); } QList MenuModel::childrenList( MenuItem * parent ) const { QList children = parent->children(); foreach( MenuItem * child, children ) { if( d->exceptions.contains( child ) ) { children.removeOne(child); children.append(child->children()); } } return children; } MenuItem * MenuModel::parentItem( MenuItem * child ) const { MenuItem * parent = child->parent(); if( d->exceptions.contains(parent) ) { parent = parentItem(parent); } return parent; } MenuItem * MenuModel::rootItem() const { return d->rootItem; } void MenuModel::addException( MenuItem * exception ) { if( exception == d->rootItem ) { return; } d->exceptions.append(exception); } void MenuModel::removeException( MenuItem * exception ) { d->exceptions.removeAll(exception); } diff --git a/core/MenuModel.h b/core/MenuModel.h index 434e04d1..2ba70090 100644 --- a/core/MenuModel.h +++ b/core/MenuModel.h @@ -1,172 +1,172 @@ /************************************************************************** * Copyright (C) 2009 Ben Cooksley * * Copyright (C) 2007 Will Stephenson * * * * 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. * ***************************************************************************/ #ifndef MENUMODEL_H #define MENUMODEL_H #include #include "systemsettingsview_export.h" class MenuItem; /** * @brief Provides a menu of the MenuItem objects * * Provides a standardised model to be used with views to display the list of modules in a variety of ways.\n * It is recommended to also use this with the MenuProxyModel to provide searching * and correct ordering of modules. * * @author Ben Cooksley * @author Will Stephenson */ class SYSTEMSETTINGSVIEW_EXPORT MenuModel : public QAbstractItemModel { Q_OBJECT public: /** * Creates a MenuModel using the MenuItem specified. The MenuItem must always be valid * throughout the life of the MenuModel, otherwise it will cause crashes. * * @param menuRoot The MenuItem to use as the basis for providing information. * @param parent The QObject to use as a parent of the MenuModel. */ - explicit MenuModel( MenuItem * menuRoot, QObject *parent = 0 ); + explicit MenuModel( MenuItem * menuRoot, QObject *parent = nullptr ); /** * Destroys the MenuModel. The menuRoot will not be destroyed. */ ~MenuModel() override; /** * Please see Qt QAbstractItemModel documentation for more details.\n * Provides the name, tooltip, icon, category, keywords and the internal MenuItem to views. * * @param index The QModelIndex you want information about. * @param role The information role you want information about. * @returns The data requested for the role provided from the QModelIndex provided. */ QVariant data( const QModelIndex &index, int role ) const override; /** * Please see Qt QAbstractItemModel documentation for more details.\n * Provides the status flags for the QModelIndex specified. * The item always has selectable and enabled for its status unless invalid. * * @returns The flags for the QModelIndex provided. */ Qt::ItemFlags flags( const QModelIndex &index ) const override; /** * Please see Qt QAbstractItemModel documentation for more details.\n * Provides a QModelIndex at the row and column specified who belongs to the parent specified. * * @param row Vertical position in the grid of children. * @param column Horizontal position in the grid of children. * @param parent The parent of the requested child. * @returns The QModelIndex for the item requested. */ QModelIndex index( int row, int column, const QModelIndex &parent = QModelIndex() ) const override; /** * Please see Qt QAbstractItemModel documentation for more details.\n * Provides the parent QModelIndex for the child specified. * * @param index The child of the parent. * @returns A QModelIndex for the parent. */ QModelIndex parent( const QModelIndex &index ) const override; /** * Please see Qt QAbstractItemModel documentation for more details.\n * Provides the number of MenuItems ( categories or modules ) that the specified parent has. * * @param parent The QModelIndex the count is performed on. * @returns The number of rows ( children ) in the parent. */ int rowCount( const QModelIndex &parent = QModelIndex() ) const override; /** * Please see Qt QAbstractItemModel documentation for more details.\n * Returns 1, the number of columns of information about a row. * * @param parent This is ignored, as the count is always 1. * @returns The number of columns ( 1 ) in the parent. */ int columnCount( const QModelIndex &parent = QModelIndex() ) const override; /** * Makes the MenuItem specified be hidden from the list, while still showing its children.\n * Children of exceptions consider their grand parents as their parent. * Parents of exceptions consider the exceptions children as theirs. * * @param exception The MenuItem to give an exception to. */ void addException( MenuItem * exception ); /** * Revokes the exception granted above. After this, the MenuItem's parents will return their children * as normal and the grand children will return their true parents, restoring normal operation. * It has no effect if the MenuItem does not have an exception. * * @param exception The MenuItem to revoke an exception from. */ void removeException( MenuItem * exception ); /** * Role used to request the keywords to filter the items when searching. */ static const int UserFilterRole; /** * Role used to request the weight of a module, used to sort the items. */ static const int UserSortRole; protected: /** * Provides the MenuItem which is used internally to provide information. * * @returns The MenuItem used internally. */ MenuItem* rootItem() const; /** * Provides a list of children of an item which has been altered by the exceptions list * * @param parent The parent of the children desired * @returns The list of children for the item specified */ QList childrenList( MenuItem * parent ) const; /** * Provides the parent of the child specified altered by the exceptions list * * @param child The child of the parent * @returns The exceptions list affected parent of the child */ MenuItem* parentItem( MenuItem * child ) const; private: class Private; Private *const d; }; #endif diff --git a/core/MenuProxyModel.h b/core/MenuProxyModel.h index 47623e68..b03a7daa 100644 --- a/core/MenuProxyModel.h +++ b/core/MenuProxyModel.h @@ -1,125 +1,125 @@ /************************************************************************** * Copyright (C) 2009 Ben Cooksley * * Copyright (C) 2007 Will Stephenson * * * * 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. * ***************************************************************************/ #ifndef MENUPROXYMODEL_H #define MENUPROXYMODEL_H #include #include "systemsettingsview_export.h" /** * @brief Provides a filter model for MenuModel * * Provides a standardised model to be used with views to filter a MenuModel.\n * It automatically sorts the items appropriately depending on if it is categorised * or not. * Call setFilterRegExp(QString) with the desired text to filter to perform searching. * Items that do not match the search parameters will be disabled, not hidden. * * @author Will Stephenson * @author Ben Cooksley */ class SYSTEMSETTINGSVIEW_EXPORT MenuProxyModel : public KCategorizedSortFilterProxyModel { Q_OBJECT Q_PROPERTY(QString filterRegExp READ filterRegExp WRITE setFilterRegExp NOTIFY filterRegExpChanged) public: /** * Constructs a MenuProxyModel with the specified parent. * * @param parent The QObject to use as a parent. */ - MenuProxyModel( QObject *parent = 0 ); + MenuProxyModel( QObject *parent = nullptr ); QHash roleNames() const override; /** * Please see the Qt QSortFilterProxyModel documentation for further information.\n * Provides information on whether or not the QModelIndex specified by left is below right. * * @param left the QModelIndex that is being used for comparing. * @param right the QModelIndex to compare aganist. * @returns true if the left is below the right. */ bool lessThan( const QModelIndex &left, const QModelIndex &right ) const override; /** * Please see the KDE KCategorizedSortFilterProxyModel documentation for futher information.\n * Provides information on whether or not the QModelIndex specified by left is below right. * * @param left the QModelIndex that is being used for comparing. * @param right the QModelIndex to compare aganist. * @returns true if the left is below the right. */ bool subSortLessThan( const QModelIndex &left, const QModelIndex &right ) const override; /** * Please see the Qt QSortFilterProxyModel documentation for futher information.\n * Provides additional filtering of the MenuModel to only show categories which contain modules. * * @param source_column Please see QSortFilterProxyModel documentation. * @param source_parent Please see QSortFilterProxyModel documentation. * @returns true if the row should be displayed, false if it should not. */ bool filterAcceptsRow( int source_column, const QModelIndex &source_parent ) const override; /** * Please see Qt QAbstractItemModel documentation for more details.\n * Provides the status flags for the QModelIndex specified. * The item will be selectable and enabled for its status unless invalid or filtered by search terms. * * @returns The flags for the QModelIndex provided. */ Qt::ItemFlags flags( const QModelIndex &index ) const override; /** * Please see Qt QAbstractItemModel documentation for more details.\n * Reimplemented for internal reasons. */ void setFilterRegExp ( const QRegExp & regExp ); /** * Please see Qt QAbstractItemModel documentation for more details.\n * Reimplemented for internal reasons. */ void setFilterRegExp ( const QString & pattern ); QString filterRegExp() const; /** * makes the filter highlight matching entries instead of hiding them */ void setFilterHighlightsEntries (bool highlight ); /** * @returns the filter highlight matching entries instead of hiding them, default true */ bool filterHighlightsEntries() const; Q_SIGNALS: void filterRegExpChanged(); private: bool m_filterHighlightsEntries : 1; }; #endif diff --git a/core/ModuleView.h b/core/ModuleView.h index 4daa0ba3..b6ddc884 100644 --- a/core/ModuleView.h +++ b/core/ModuleView.h @@ -1,160 +1,160 @@ /***************************************************************************** * Copyright (C) 2009 Ben Cooksley * * Copyright (C) 2009 by Mathias Soeken * * * * 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 * *****************************************************************************/ #ifndef MODULE_VIEW_H #define MODULE_VIEW_H #include #include #include #include "systemsettingsview_export.h" class KAboutData; class KCModuleInfo; class KCModuleProxy; class KPageWidgetItem; /** * @brief Provides a convienent way to display modules * * Provides a standardised interface for displaying multiple modules simultaneously * and provides facilities to access the current module, and to load its help, restore * default settings, save new settings and revert changes to settings * * It also provides checking for when a module has changed its configuration, and will prompt * if the user tries to change module or view if BaseMode is reimplemented correctly * * It also provides signals for active module changes, configuration changes and for when it has * been requested to close by button press * * @author Mathias Soeken * @author Ben Cooksley */ class SYSTEMSETTINGSVIEW_EXPORT ModuleView : public QWidget { Q_OBJECT public: /** * Constructs a ModuleView, with the parent specified. */ - explicit ModuleView(QWidget * parent = 0); + explicit ModuleView(QWidget * parent = nullptr); /** * Destroys the module view, along with all modules loaded, and any changes present in them. * * @warning The user will not be prompted to save changes if any exist.\n */ ~ModuleView() override; /** * Provides the module information, which is used to set the caption of the window when either the * active module or configuration changes. */ KCModuleInfo * activeModule() const; /** * Provides the about data of the active module, used for the about dialog. */ const KAboutData * aboutData() const; /** * Resolves any changes in the currently active module by prompting the user if they exist. * * @returns true if the user saved or discarded changes, or there were no changes at all. * @returns false if the user canceled the module change. */ bool resolveChanges(); /** * Closes all active modules, after checking there are no active changes. * * @warning This forces all modules to be destroyed regardless of if changes exist or not * If possible, always check with resolveChanges() first. */ void closeModules(); void setFaceType(KPageView::FaceType type); KPageView::FaceType faceType() const; public Q_SLOTS: /** * Loads the module specified by menuItem.\n * If the module has children, they will all be loaded instead of the module. * * @param menuItem the QModelIndex that you want to load. Must be sourced from either MenuModel or MenuProxyModel */ void loadModule(const QModelIndex &menuItem ); /** * Will open KHelpCenter, and load the help for the active module. */ void moduleHelp(); /** * Causes the active module to reload its configuration, reverting all changes. */ void moduleLoad(); /** * Causes the active module to save its configuration, applying all changes. */ bool moduleSave(); /** * Causes the active module to revert all changes to the configuration, and return to defaults. */ void moduleDefaults(); /** * Reimplemented for internal reasons.\n */ void keyPressEvent( QKeyEvent * event ) override; private: bool resolveChanges( KCModuleProxy *currentProxy ); void addModule( KCModuleInfo *module ); bool moduleSave( KCModuleProxy *module ); void updatePageIconHeader( KPageWidgetItem * page, bool light = false ); private Q_SLOTS: void activeModuleChanged( KPageWidgetItem* current, KPageWidgetItem* previous); void updateButtons(); void stateChanged(); Q_SIGNALS: /** * Emitted when the currently active module is changed. This occurs whenever the active module or * its configuration changes. This causes the window caption to update. */ void moduleChanged( bool state ); /** * Emitted when the ModuleView is asked to close.\n */ void closeRequest(); private: class Private; Private *const d; }; #endif diff --git a/icons/CategorizedView.h b/icons/CategorizedView.h index da483690..c72c3ee6 100644 --- a/icons/CategorizedView.h +++ b/icons/CategorizedView.h @@ -1,35 +1,35 @@ /*************************************************************************** * Copyright (C) 2009 by Rafael Fernández López * * * * 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 * ***************************************************************************/ #ifndef CATEGORIZEDVIEW_H #define CATEGORIZEDVIEW_H #include class CategorizedView : public KCategorizedView { public: - CategorizedView( QWidget *parent = 0 ); + CategorizedView( QWidget *parent = nullptr ); void setModel( QAbstractItemModel *model ) override; protected: void wheelEvent(QWheelEvent *) override; }; #endif diff --git a/icons/IconMode.cpp b/icons/IconMode.cpp index 97541cf6..d1e247b0 100644 --- a/icons/IconMode.cpp +++ b/icons/IconMode.cpp @@ -1,211 +1,211 @@ /************************************************************************** * 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 "IconMode.h" #include "CategoryDrawer.h" #include "CategorizedView.h" #include "MenuItem.h" #include "MenuModel.h" #include "ModuleView.h" #include "MenuProxyModel.h" #include #include #include #include #include #include K_PLUGIN_FACTORY( IconModeFactory, registerPlugin(); ) class IconMode::Private { public: - Private() : categoryDrawer( 0 ), categoryView( 0 ), moduleView( 0 ) {} + Private() : categoryDrawer( nullptr ), categoryView( nullptr ), moduleView( nullptr ) {} virtual ~Private() { delete aboutIcon; } KCategoryDrawer * categoryDrawer; KCategorizedView * categoryView; QStackedWidget * mainWidget; MenuProxyModel * proxyModel; KAboutData * aboutIcon; ModuleView * moduleView; QAction * backAction; }; IconMode::IconMode( QObject *parent, const QVariantList& ) : BaseMode( parent ) , d( new Private() ) { d->aboutIcon = new KAboutData( QStringLiteral("IconView"), i18n( "Icon View" ), QStringLiteral("1.0"), i18n( "Provides a categorized icons view of control modules." ), KAboutLicense::GPL, i18n( "(c) 2009, Ben Cooksley" ) ); d->aboutIcon->addAuthor( i18n( "Ben Cooksley" ), i18n( "Author" ), QStringLiteral("bcooksley@kde.org") ); d->aboutIcon->addAuthor( i18n( "Mathias Soeken" ), i18n( "Developer" ), QStringLiteral("msoeken@informatik.uni-bremen.de") ); d->aboutIcon->setProgramIconName( QStringLiteral("view-list-icons") ); d->backAction = KStandardAction::back( this, SLOT(backToOverview()), this ); d->backAction->setText( i18n( "All Settings" ) ); d->backAction->setToolTip( i18n("Keyboard Shortcut: %1", d->backAction->shortcut().toString( QKeySequence::NativeText )) ); d->backAction->setEnabled( false ); actionsList() << d->backAction; } IconMode::~IconMode() { delete d; } KAboutData * IconMode::aboutData() { return d->aboutIcon; } ModuleView * IconMode::moduleView() const { return d->moduleView; } QWidget * IconMode::mainWidget() { if( !d->categoryView ) { initWidget(); } return d->mainWidget; } QList IconMode::views() const { QList list; list.append( d->categoryView ); return list; } void IconMode::initEvent() { MenuModel * model = new MenuModel( rootItem(), this ); foreach( MenuItem * child, rootItem()->children() ) { model->addException( child ); } d->proxyModel = new MenuProxyModel( this ); d->proxyModel->setCategorizedModel( true ); d->proxyModel->setSourceModel( model ); d->proxyModel->sort( 0 ); d->mainWidget = new QStackedWidget(); d->moduleView = new ModuleView( d->mainWidget ); connect( d->moduleView, &ModuleView::moduleChanged, this, &IconMode::moduleLoaded ); connect( d->moduleView, &ModuleView::closeRequest, this, &IconMode::backToOverview ); - d->categoryView = 0; + d->categoryView = nullptr; } void IconMode::searchChanged( const QString& text ) { d->proxyModel->setFilterRegExp( text ); if ( d->categoryView ) { QAbstractItemModel *model = d->categoryView->model(); const int column = d->categoryView->modelColumn(); const QModelIndex root = d->categoryView->rootIndex(); for ( int i = 0; i < model->rowCount(); ++i ) { const QModelIndex index = model->index( i, column, root ); if ( model->flags( index ) & Qt::ItemIsEnabled ) { d->categoryView->scrollTo( index ); break; } } } } void IconMode::changeModule( const QModelIndex& activeModule ) { d->moduleView->closeModules(); d->mainWidget->setCurrentWidget( d->moduleView ); d->moduleView->loadModule( activeModule ); } void IconMode::moduleLoaded() { d->backAction->setEnabled( true ); emit changeToolBarItems(BaseMode::NoItems); } void IconMode::backToOverview() { if( d->moduleView->resolveChanges() ) { d->mainWidget->setCurrentWidget( d->categoryView ); d->moduleView->closeModules(); d->backAction->setEnabled( false ); emit changeToolBarItems( BaseMode::Search | BaseMode::Configure | BaseMode::Quit ); emit viewChanged( false ); } } void IconMode::initWidget() { // Create the widget d->categoryView = new CategorizedView( d->mainWidget ); d->categoryDrawer = new CategoryDrawer(d->categoryView); d->categoryView->setSelectionMode( QAbstractItemView::SingleSelection ); //PORT QT5 d->categoryView->setSpacing( KDialog::spacingHint() ); d->categoryView->setCategoryDrawer( d->categoryDrawer ); d->categoryView->setViewMode( QListView::IconMode ); d->categoryView->setMouseTracking( true ); d->categoryView->viewport()->setAttribute( Qt::WA_Hover ); KFileItemDelegate *delegate = new KFileItemDelegate( d->categoryView ); delegate->setWrapMode( QTextOption::WordWrap ); d->categoryView->setItemDelegate( delegate ); d->categoryView->setFrameShape( QFrame::NoFrame ); d->categoryView->setModel( d->proxyModel ); connect( d->categoryView, &QAbstractItemView::activated, this, &IconMode::changeModule ); d->mainWidget->addWidget( d->categoryView ); d->mainWidget->addWidget( d->moduleView ); d->mainWidget->setCurrentWidget( d->categoryView ); emit changeToolBarItems( BaseMode::Search | BaseMode::Configure | BaseMode::Quit ); d->mainWidget->installEventFilter(this); } bool IconMode::eventFilter(QObject* watched, QEvent* event) { if (watched == d->mainWidget && event->type() == QEvent::Show) { emit changeToolBarItems( BaseMode::Search | BaseMode::Configure | BaseMode::Quit ); } return BaseMode::eventFilter(watched, event); } void IconMode::leaveModuleView() { d->moduleView->closeModules(); // We have to force it here backToOverview(); } void IconMode::giveFocus() { d->categoryView->setFocus(); } #include "IconMode.moc" diff --git a/sidebar/CategorizedView.h b/sidebar/CategorizedView.h index da483690..c72c3ee6 100644 --- a/sidebar/CategorizedView.h +++ b/sidebar/CategorizedView.h @@ -1,35 +1,35 @@ /*************************************************************************** * Copyright (C) 2009 by Rafael Fernández López * * * * 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 * ***************************************************************************/ #ifndef CATEGORIZEDVIEW_H #define CATEGORIZEDVIEW_H #include class CategorizedView : public KCategorizedView { public: - CategorizedView( QWidget *parent = 0 ); + CategorizedView( QWidget *parent = nullptr ); void setModel( QAbstractItemModel *model ) override; protected: void wheelEvent(QWheelEvent *) override; }; #endif diff --git a/sidebar/SidebarMode.cpp b/sidebar/SidebarMode.cpp index 18aa7575..7641a1d9 100644 --- a/sidebar/SidebarMode.cpp +++ b/sidebar/SidebarMode.cpp @@ -1,557 +1,557 @@ /************************************************************************** * 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 "SidebarMode.h" #include "CategoryDrawer.h" #include "CategorizedView.h" #include "MenuItem.h" #include "MenuModel.h" #include "ModuleView.h" #include "MenuProxyModel.h" #include "BaseData.h" #include "SidebarDelegate.h" #include "ToolTips/tooltipmanager.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace KAStats = KActivities::Stats; using namespace KAStats; using namespace KAStats::Terms; K_PLUGIN_FACTORY( SidebarModeFactory, registerPlugin(); ) FocusHackWidget::FocusHackWidget(QWidget *parent) : QWidget(parent) {} FocusHackWidget::~FocusHackWidget() {} void FocusHackWidget::focusNext() { focusNextChild(); } void FocusHackWidget::focusPrevious() { focusNextPrevChild(false); } class SubcategoryModel : public QStandardItemModel { public: explicit SubcategoryModel(QAbstractItemModel *parentModel, QObject *parent = nullptr) : QStandardItemModel(parent), m_parentModel(parentModel) {} void setParentIndex(const QModelIndex &activeModule) { blockSignals(true); //make the view receive a single signal when the new subcategory is loaded, //never make the view believe there are zero items if this is not the final count //this avoids the brief flash it had clear(); const int subRows = m_parentModel->rowCount(activeModule); if ( subRows > 1) { for (int i = 0; i < subRows; ++i) { const QModelIndex& index = m_parentModel->index(i, 0, activeModule); QStandardItem *item = new QStandardItem(m_parentModel->data(index, Qt::DecorationRole).value(), m_parentModel->data(index, Qt::DisplayRole).toString()); item->setData(index.data(Qt::UserRole), Qt::UserRole); appendRow(item); } } blockSignals(false); beginResetModel(); endResetModel(); } private: QAbstractItemModel *m_parentModel; }; class MostUsedModel : public QSortFilterProxyModel { public: explicit MostUsedModel(QObject *parent = nullptr) : QSortFilterProxyModel (parent) { sort(0, Qt::DescendingOrder); setSortRole(ResultModel::ScoreRole); setDynamicSortFilter(true); //prepare default items m_defaultModel = new QStandardItemModel(this); QStandardItem *item = new QStandardItem(); item->setData(QUrl(QStringLiteral("kcm:kcm_lookandfeel.desktop")), ResultModel::ResourceRole); m_defaultModel->appendRow(item); item = new QStandardItem(); item->setData(QUrl(QStringLiteral("kcm:user_manager.desktop")), ResultModel::ResourceRole); m_defaultModel->appendRow(item); item = new QStandardItem(); item->setData(QUrl(QStringLiteral("kcm:screenlocker.desktop")), ResultModel::ResourceRole); m_defaultModel->appendRow(item); item = new QStandardItem(); item->setData(QUrl(QStringLiteral("kcm:powerdevilprofilesconfig.desktop")), ResultModel::ResourceRole); m_defaultModel->appendRow(item); item = new QStandardItem(); item->setData(QUrl(QStringLiteral("kcm:kcm_kscreen.desktop")), ResultModel::ResourceRole); m_defaultModel->appendRow(item); } void setResultModel(ResultModel *model) { if (m_resultModel == model) { return; } auto updateModel = [this]() { if (m_resultModel->rowCount() >= 5) { setSourceModel(m_resultModel); } else { setSourceModel(m_defaultModel); } }; m_resultModel = model; connect(m_resultModel, &QAbstractItemModel::rowsInserted, this, updateModel); connect(m_resultModel, &QAbstractItemModel::rowsRemoved, this, updateModel); updateModel(); } QHash roleNames() const override { QHash roleNames; roleNames.insert(Qt::DisplayRole, "display"); roleNames.insert(Qt::DecorationRole, "decoration"); roleNames.insert(ResultModel::ScoreRole, "score"); return roleNames; } QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override { MenuItem *mi; const QString desktopName = QSortFilterProxyModel::data(index, ResultModel::ResourceRole).toUrl().path(); if (m_menuItems.contains(desktopName)) { mi = m_menuItems.value(desktopName); } else { mi = new MenuItem(false, nullptr); const_cast(this)->m_menuItems.insert(desktopName, mi); KService::Ptr service = KService::serviceByStorageId(desktopName); if (!service || !service->isValid()) { return QVariant(); } mi->setService(service); } switch (role) { case Qt::UserRole: return QVariant::fromValue(mi); case Qt::DisplayRole: if (mi->service() && mi->service()->isValid()) { return mi->service()->name(); } else { return QVariant(); } case Qt::DecorationRole: if (mi->service() && mi->service()->isValid()) { return mi->service()->icon(); } else { return QVariant(); } case ResultModel::ScoreRole: return QSortFilterProxyModel::data(index, ResultModel::ScoreRole).toInt(); default: return QVariant(); } } private: QHash m_menuItems; QStandardItemModel *m_defaultModel; ResultModel *m_resultModel; }; class SidebarMode::Private { public: Private() : quickWidget( nullptr ), moduleView( nullptr ), collection( nullptr ), activeCategory( -1 ), activeSubCategory( -1 ) {} virtual ~Private() { delete aboutIcon; } ToolTipManager *toolTipManager = nullptr; QQuickWidget * quickWidget = nullptr; KPackage::Package package; SubcategoryModel * subCategoryModel = nullptr; MostUsedModel * mostUsedModel = nullptr; FocusHackWidget * mainWidget = nullptr; QQuickWidget * placeHolderWidget = nullptr; QHBoxLayout * mainLayout = nullptr; KDeclarative::KDeclarative kdeclarative; MenuProxyModel * categorizedModel = nullptr; MenuProxyModel * searchModel = nullptr; KAboutData * aboutIcon = nullptr; ModuleView * moduleView = nullptr; KActionCollection *collection = nullptr; QPersistentModelIndex activeCategoryIndex; int activeCategory; int activeSubCategory; }; SidebarMode::SidebarMode( QObject *parent, const QVariantList& ) : BaseMode( parent ) , d( new Private() ) { qApp->setAttribute(Qt::AA_DontCreateNativeWidgetSiblings); d->aboutIcon = new KAboutData( QStringLiteral("SidebarView"), i18n( "Sidebar View" ), QStringLiteral("1.0"), i18n( "Provides a categorized sidebar for control modules." ), KAboutLicense::GPL, i18n( "(c) 2017, Marco Martin" ) ); d->aboutIcon->addAuthor( i18n( "Marco Martin" ), i18n( "Author" ), QStringLiteral("mart@kde.org") ); d->aboutIcon->addAuthor( i18n( "Ben Cooksley" ), i18n( "Author" ), QStringLiteral("bcooksley@kde.org") ); d->aboutIcon->addAuthor( i18n( "Mathias Soeken" ), i18n( "Developer" ), QStringLiteral("msoeken@informatik.uni-bremen.de") ); d->aboutIcon->setProgramIconName( QStringLiteral("view-sidetree") ); qmlRegisterType(); } SidebarMode::~SidebarMode() { delete d; } KAboutData * SidebarMode::aboutData() { return d->aboutIcon; } ModuleView * SidebarMode::moduleView() const { return d->moduleView; } QWidget * SidebarMode::mainWidget() { if( !d->quickWidget ) { initWidget(); } return d->mainWidget; } QAbstractItemModel * SidebarMode::categoryModel() const { return d->searchModel; } QAbstractItemModel * SidebarMode::subCategoryModel() const { return d->subCategoryModel; } QAbstractItemModel * SidebarMode::mostUsedModel() const { return d->mostUsedModel; } QList SidebarMode::views() const { QList list; //list.append( d->categoryView ); return list; } void SidebarMode::initEvent() { MenuModel * model = new MenuModel( rootItem(), this ); foreach( MenuItem * child, rootItem()->children() ) { model->addException( child ); } d->categorizedModel = new MenuProxyModel( this ); d->categorizedModel->setCategorizedModel( true ); d->categorizedModel->setSourceModel( model ); d->categorizedModel->sort( 0 ); d->categorizedModel->setFilterHighlightsEntries( false ); d->searchModel = new MenuProxyModel( this ); d->searchModel->setFilterHighlightsEntries( false ); d->searchModel->setSourceModel( d->categorizedModel ); connect( d->searchModel, &MenuProxyModel::filterRegExpChanged, this, [this] () { if (d->activeCategoryIndex.isValid() && d->activeCategoryIndex.row() >= 0) { d->subCategoryModel->setParentIndex( d->activeCategoryIndex ); emit activeCategoryChanged(); } }); d->mostUsedModel = new MostUsedModel( this ); d->subCategoryModel = new SubcategoryModel( d->searchModel, this ); d->mainWidget = new FocusHackWidget(); d->mainWidget->installEventFilter(this); d->mainLayout = new QHBoxLayout(d->mainWidget); d->mainLayout->setContentsMargins(0, 0, 0, 0); d->moduleView = new ModuleView( d->mainWidget ); connect( d->moduleView, &ModuleView::moduleChanged, this, &SidebarMode::moduleLoaded ); - d->quickWidget = 0; + d->quickWidget = nullptr; moduleView()->setFaceType(KPageView::Plain); } QAction *SidebarMode::action(const QString &name) const { if (!d->collection) { return nullptr; } return d->collection->action(name); } QString SidebarMode::actionIconName(const QString &name) const { if (QAction *a = action(name)) { return a->icon().name(); } return QString(); } void SidebarMode::requestToolTip(int index, const QRectF &rect) { if (showToolTips()) { d->toolTipManager->requestToolTip(d->searchModel->index(index, 0), rect.toRect()); } } void SidebarMode::hideToolTip() { d->toolTipManager->hideToolTip(); } void SidebarMode::loadMostUsed(int index) { const QModelIndex idx = d->mostUsedModel->index(index, 0); d->moduleView->closeModules(); d->moduleView->loadModule( idx ); } void SidebarMode::changeModule( const QModelIndex& activeModule ) { d->moduleView->closeModules(); const int subRows = d->searchModel->rowCount(activeModule); if ( subRows < 2) { d->moduleView->loadModule( activeModule ); } else { d->moduleView->loadModule( d->searchModel->index(0, 0, activeModule) ); } d->subCategoryModel->setParentIndex( activeModule ); } void SidebarMode::moduleLoaded() { d->placeHolderWidget->hide(); d->moduleView->show(); } int SidebarMode::activeCategory() const { return d->searchModel->mapFromSource(d->searchModel->sourceModel()->index(d->activeCategory, 0)).row(); } void SidebarMode::setActiveCategory(int cat) { const QModelIndex idx = d->searchModel->index(cat, 0); d->activeCategoryIndex = idx; const int newCategoryRow = d->searchModel->mapToSource(idx).row(); if (d->activeCategory ==newCategoryRow) { return; } d->activeCategoryIndex = idx; d->activeCategory = newCategoryRow; changeModule(idx); d->activeSubCategory = 0; emit activeCategoryChanged(); emit activeSubCategoryChanged(); } int SidebarMode::activeSubCategory() const { return d->activeSubCategory; } void SidebarMode::setActiveSubCategory(int cat) { if (d->activeSubCategory == cat) { return; } d->activeSubCategory = cat; d->moduleView->closeModules(); d->moduleView->loadModule( d->subCategoryModel->index(cat, 0) ); emit activeSubCategoryChanged(); } int SidebarMode::width() const { return d->mainWidget->width(); } void SidebarMode::initWidget() { // Create the widgets if (!KMainWindow::memberList().isEmpty()) { KXmlGuiWindow *mainWindow = qobject_cast(KMainWindow::memberList().first()); if (mainWindow) { d->collection = mainWindow->actionCollection(); } } d->quickWidget = new QQuickWidget(d->mainWidget); d->quickWidget->quickWindow()->setTitle(i18n("Sidebar")); d->quickWidget->setResizeMode(QQuickWidget::SizeRootObjectToView); d->quickWidget->engine()->rootContext()->setContextProperty(QStringLiteral("systemsettings"), this); d->package = KPackage::PackageLoader::self()->loadPackage(QStringLiteral("KPackage/GenericQML")); d->package.setPath(QStringLiteral("org.kde.systemsettings.sidebar")); d->kdeclarative.setDeclarativeEngine(d->quickWidget->engine()); d->kdeclarative.setupBindings(); d->quickWidget->setSource(QUrl::fromLocalFile(d->package.filePath("mainscript"))); const int rootImplicitWidth = d->quickWidget->rootObject()->property("implicitWidth").toInt(); if (rootImplicitWidth != 0) { d->quickWidget->setFixedWidth(rootImplicitWidth); } else { d->quickWidget->setFixedWidth(240); } connect(d->quickWidget->rootObject(), &QQuickItem::implicitWidthChanged, this, [this]() { const int rootImplicitWidth = d->quickWidget->rootObject()->property("implicitWidth").toInt(); if (rootImplicitWidth != 0) { d->quickWidget->setFixedWidth(rootImplicitWidth); } else { d->quickWidget->setFixedWidth(240); } }); connect(d->quickWidget->rootObject(), SIGNAL(focusNextRequest()), d->mainWidget, SLOT(focusNext())); connect(d->quickWidget->rootObject(), SIGNAL(focusPreviousRequest()), d->mainWidget, SLOT(focusPrevious())); d->quickWidget->installEventFilter(this); d->toolTipManager = new ToolTipManager(d->searchModel, d->quickWidget); d->placeHolderWidget = new QQuickWidget(d->mainWidget); d->placeHolderWidget->quickWindow()->setTitle(i18n("Most Used")); d->placeHolderWidget->setResizeMode(QQuickWidget::SizeRootObjectToView); d->placeHolderWidget->engine()->rootContext()->setContextObject(new KLocalizedContext(d->placeHolderWidget)); d->placeHolderWidget->engine()->rootContext()->setContextProperty(QStringLiteral("systemsettings"), this); d->placeHolderWidget->setSource(QUrl::fromLocalFile(d->package.filePath("ui", QStringLiteral("introPage.qml")))); connect(d->placeHolderWidget->rootObject(), SIGNAL(focusNextRequest()), d->mainWidget, SLOT(focusNext())); connect(d->placeHolderWidget->rootObject(), SIGNAL(focusPreviousRequest()), d->mainWidget, SLOT(focusPrevious())); d->placeHolderWidget->installEventFilter(this); d->mainLayout->addWidget( d->quickWidget ); d->moduleView->hide(); d->mainLayout->addWidget( d->moduleView ); d->mainLayout->addWidget( d->placeHolderWidget ); emit changeToolBarItems(BaseMode::NoItems); d->mostUsedModel->setResultModel(new ResultModel( AllResources | Agent(QStringLiteral("org.kde.systemsettings")) | HighScoredFirst | Limit(5), this)); } bool SidebarMode::eventFilter(QObject* watched, QEvent* event) { //FIXME: those are all workarounds around the QQuickWidget brokeness if ((watched == d->quickWidget || watched == d->placeHolderWidget) && event->type() == QEvent::KeyPress) { //allow tab navigation inside the qquickwidget QKeyEvent *ke = static_cast(event); QQuickWidget *qqw = static_cast(watched); if (ke->key() == Qt::Key_Tab || ke->key() == Qt::Key_Backtab) { QCoreApplication::sendEvent(qqw->quickWindow(), event); return true; } } else if ((watched == d->quickWidget || watched == d->placeHolderWidget) && event->type() == QEvent::FocusIn) { QFocusEvent *fe = static_cast(event); QQuickWidget *qqw = static_cast(watched); if (qqw && qqw->rootObject()) { if (fe->reason() == Qt::TabFocusReason) { QMetaObject::invokeMethod(qqw->rootObject(), "focusFirstChild"); } else if (fe->reason() == Qt::BacktabFocusReason) { QMetaObject::invokeMethod(qqw->rootObject(), "focusLastChild"); } } } else if (watched == d->quickWidget && event->type() == QEvent::Leave) { QCoreApplication::sendEvent(d->quickWidget->quickWindow(), event); } else if (watched == d->mainWidget && event->type() == QEvent::Resize) { emit widthChanged(); } else if (watched == d->mainWidget && event->type() == QEvent::Show) { emit changeToolBarItems(BaseMode::NoItems); } return BaseMode::eventFilter(watched, event); } void SidebarMode::giveFocus() { d->quickWidget->setFocus(); } #include "SidebarMode.moc" diff --git a/sidebar/ToolTips/tooltipmanager.cpp b/sidebar/ToolTips/tooltipmanager.cpp index 3e28f4b6..33fd72a4 100644 --- a/sidebar/ToolTips/tooltipmanager.cpp +++ b/sidebar/ToolTips/tooltipmanager.cpp @@ -1,216 +1,216 @@ /******************************************************************************* * Copyright (C) 2008 by Konstantin Heil * * * * 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 "tooltipmanager.h" #include "MenuItem.h" #include #include #include #include #include #include #include #include #include #include #include #include class ToolTipManager::Private { public: Private() : - tooltip(0), - view(0), - timer(0), + tooltip(nullptr), + view(nullptr), + timer(nullptr), delay(300) { } KToolTipWidget *tooltip; QWidget* view; QAbstractItemModel *model; QTimer* timer; QModelIndex item; QRect itemRect; int delay; }; ToolTipManager::ToolTipManager(QAbstractItemModel *model, QWidget* parent) : QObject(parent) , d(new ToolTipManager::Private) { d->view = parent; d->model = model; d->tooltip = new KToolTipWidget(d->view); d->tooltip->setHideDelay(0); d->timer = new QTimer(this); d->timer->setSingleShot(true); connect(d->timer, &QTimer::timeout, this, &ToolTipManager::prepareToolTip); d->view->installEventFilter(this); } ToolTipManager::~ToolTipManager() { delete d; } bool ToolTipManager::eventFilter(QObject* watched, QEvent* event) { if (watched == d->view) { switch (event->type()) { case QEvent::Leave: case QEvent::MouseButtonPress: hideToolTip(); break; default: break; } } return QObject::eventFilter(watched, event); } void ToolTipManager::requestToolTip(const QModelIndex& index, const QRect &rect) { // only request a tooltip for the name column and when no selection or // drag & drop operation is done (indicated by the left mouse button) if ( !(QApplication::mouseButtons() & Qt::LeftButton) ) { d->tooltip->hide(); d->itemRect = rect; const QPoint pos = d->view->mapToGlobal(d->itemRect.topLeft()); d->itemRect.moveTo(pos); d->item = index; d->timer->start(d->delay); } else { hideToolTip(); } } void ToolTipManager::hideToolTip() { d->timer->stop(); d->tooltip->hideLater(); } void ToolTipManager::prepareToolTip() { // item may have gone away since we're triggered by a timer MenuItem * menuItem = d->model->data( d->item, Qt::UserRole ).value(); if (menuItem) { showToolTip( d->item ); } } void ToolTipManager::showToolTip( QModelIndex menuItem ) { if (QApplication::mouseButtons() & Qt::LeftButton) { return; } QWidget * tip = createTipContent( menuItem ); if (qApp->isRightToLeft()) { d->tooltip->showAt(d->itemRect.topLeft() - QPoint(d->tooltip->width(), 0), tip, d->view->nativeParentWidget()->windowHandle()); } else { d->tooltip->showAt(d->itemRect.topRight(), tip, d->view->nativeParentWidget()->windowHandle()); } connect(d->tooltip, &KToolTipWidget::hidden, tip, &QObject::deleteLater); } QWidget * ToolTipManager::createTipContent( QModelIndex item ) { const QSize dialogIconSize = QSize(IconSize(KIconLoader::Dialog), IconSize(KIconLoader::Dialog)); const QSize toolbarIconSize = QSize(IconSize(KIconLoader::MainToolbar), IconSize(KIconLoader::MainToolbar)); QWidget * tipContent = new QWidget(); QGridLayout* tipLayout = new QGridLayout(); tipLayout->setAlignment( Qt::AlignLeft ); QLayout * primaryLine = generateToolTipLine( &item, tipContent, dialogIconSize, true ); primaryLine->setAlignment( Qt::AlignLeft ); tipLayout->addLayout( primaryLine, 0, 0, Qt::AlignLeft ); for ( int done = 0; d->model->rowCount( item ) > done; done = 1 + done ) { QModelIndex childItem = d->model->index( done, 0, item ); QLayout * subLine = generateToolTipLine( &childItem, tipContent, toolbarIconSize, false ); subLine->setAlignment( Qt::AlignLeft ); tipLayout->addLayout( subLine, done + 2, 0, Qt::AlignLeft ); } tipLayout->setVerticalSpacing( tipContent->fontMetrics().height() / 3 ); tipContent->setLayout( tipLayout ); if( d->model->rowCount( item ) > 0 ) { QFrame * separatorLine = new QFrame( tipContent ); separatorLine->setFrameStyle( QFrame::HLine ); tipLayout->addWidget( separatorLine, 1, 0 ); } return tipContent; } QLayout * ToolTipManager::generateToolTipLine( QModelIndex * item, QWidget * toolTip, QSize iconSize, bool comment ) { // Get MenuItem MenuItem * menuItem = d->model->data( *item, Qt::UserRole ).value(); QString text = menuItem->name(); if ( comment ) { text = QStringLiteral( "%1" ).arg( menuItem->name() ); } // Generate text if ( comment ) { text += QStringLiteral("
"); if ( !menuItem->service()->comment().isEmpty() ) { text += menuItem->service()->comment(); } else { int childCount = d->model->rowCount( *item ); text += i18np( "Contains 1 item", "Contains %1 items", childCount ); } } QLabel * textLabel = new QLabel( toolTip ); textLabel->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed ); textLabel->setForegroundRole(QPalette::ToolTipText); textLabel->setText( text ); // Get icon QLabel * iconLabel = new QLabel( toolTip ); iconLabel->setPixmap( QIcon::fromTheme(menuItem->service()->icon()).pixmap(iconSize) ); iconLabel->setMaximumSize( iconSize ); // Generate layout QHBoxLayout * layout = new QHBoxLayout(); layout->setSpacing( textLabel->fontMetrics().height() / 3 ); layout->setAlignment( Qt::AlignLeft ); layout->addWidget( iconLabel, Qt::AlignLeft ); layout->addWidget( textLabel, Qt::AlignLeft ); return layout; }