summaryrefslogtreecommitdiffstats
path: root/kcontrol/kcontrol/toplevel.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kcontrol/kcontrol/toplevel.cpp')
-rw-r--r--kcontrol/kcontrol/toplevel.cpp526
1 files changed, 526 insertions, 0 deletions
diff --git a/kcontrol/kcontrol/toplevel.cpp b/kcontrol/kcontrol/toplevel.cpp
new file mode 100644
index 000000000..c7a47e372
--- /dev/null
+++ b/kcontrol/kcontrol/toplevel.cpp
@@ -0,0 +1,526 @@
+/*
+ Copyright (c) 1999 Matthias Hoelzer-Kluepfel <hoelzer@kde.org>
+ Copyright (c) 2000 Matthias Elter <elter@kde.org>
+
+ 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 <kapplication.h>
+#include <kstandarddirs.h>
+#include <kconfig.h>
+#include <kbugreport.h>
+#include <kaboutapplication.h>
+#include <kmessagebox.h>
+#include <kinstance.h>
+#include <kaction.h>
+#include <kwin.h>
+#include <kiconloader.h>
+#include <klineedit.h>
+
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qpushbutton.h>
+#include <qtabwidget.h>
+#include <qtooltip.h>
+#include <qwhatsthis.h>
+
+#include "indexwidget.h"
+#include "searchwidget.h"
+#include "helpwidget.h"
+#include "aboutwidget.h"
+#include "proxywidget.h"
+#include "moduletreeview.h"
+#include <stdio.h>
+
+#include "toplevel.h"
+#include "toplevel.moc"
+
+TopLevel::TopLevel(const char* name)
+ : KMainWindow( 0, name, WStyle_ContextHelp )
+ , _active(0), dummyAbout(0)
+{
+ setCaption(QString::null);
+
+ report_bug = 0;
+
+ // read settings
+ KConfig *config = KGlobal::config();
+ config->setGroup("Index");
+ QString viewmode = config->readEntry("ViewMode", "Tree");
+
+ if (viewmode == "Tree")
+ KCGlobal::setViewMode(Tree);
+ else
+ KCGlobal::setViewMode(Icon);
+
+ QString size = config->readEntry("IconSize", "Medium");
+ if (size == "Small")
+ KCGlobal::setIconSize(KIcon::SizeSmall);
+ else if (size == "Large")
+ KCGlobal::setIconSize(KIcon::SizeLarge);
+ else if (size == "Huge")
+ KCGlobal::setIconSize(KIcon::SizeHuge);
+ else
+ KCGlobal::setIconSize(KIcon::SizeMedium);
+
+ // initialize the entries
+ _modules = new ConfigModuleList();
+ _modules->readDesktopEntries();
+
+ for ( ConfigModule* m = _modules->first(); m; m = _modules->next() ) {
+ connect( m, SIGNAL( handbookRequest() ), this, SLOT( slotHandbookRequest() ) );
+ connect( m, SIGNAL( helpRequest() ), this, SLOT( slotHelpRequest() ) );
+ }
+
+ // create the layout box
+ _splitter = new QSplitter( QSplitter::Horizontal, this );
+
+ QFrame* leftFrame = new QFrame ( _splitter );
+ QBoxLayout *leftFrameLayout = new QVBoxLayout( leftFrame );
+
+ QFrame* mSearchFrame = new QFrame( leftFrame );
+ leftFrameLayout->addWidget( mSearchFrame );
+
+ QBoxLayout *searchLayout = new QHBoxLayout( mSearchFrame );
+ searchLayout->setSpacing( KDialog::spacingHint() );
+ searchLayout->setMargin( 6 );
+
+ QPushButton *clearButton = new QPushButton( mSearchFrame );
+ clearButton->setIconSet( KApplication::reverseLayout() ?
+ SmallIconSet( "clear_left" ) : SmallIconSet("locationbar_erase") );
+ searchLayout->addWidget( clearButton );
+ QToolTip::add( clearButton, i18n("Clear search") );
+
+ QLabel *label = new QLabel(i18n("Search:"), mSearchFrame );
+ searchLayout->addWidget( label );
+
+ KLineEdit *searchEdit = new KLineEdit( mSearchFrame );
+ clearButton->setFixedHeight( searchEdit->height() );
+ connect( clearButton, SIGNAL( clicked() ), searchEdit, SLOT( clear() ) );
+ label->setBuddy( searchEdit );
+ searchLayout->addWidget( searchEdit );
+ connect( searchEdit, SIGNAL( textChanged( const QString & ) ),
+ SLOT( slotSearchChanged(const QString &) ) );
+
+ // create the left hand side under search
+ _stack = new QWidgetStack( leftFrame );
+ leftFrameLayout->addWidget( _stack );
+
+ // index tab
+ _index = new IndexWidget(_modules, this);
+ connect(_index, SIGNAL(moduleActivated(ConfigModule*)),
+ this, SLOT(activateModule(ConfigModule*)));
+ _stack->addWidget( _index );
+
+ connect(_index, SIGNAL(categorySelected(QListViewItem*)),
+ this, SLOT(categorySelected(QListViewItem*)));
+
+ // search tab
+ _search = new SearchWidget(this);
+ _search->populateKeywordList(_modules);
+ connect(_search, SIGNAL(moduleSelected(ConfigModule *)),
+ this, SLOT(activateModule(ConfigModule *)));
+
+ _stack->addWidget( _search );
+
+ // set up the right hand side (the docking area)
+ _dock = new DockContainer( _splitter );
+
+ // help widget
+ _help = new HelpWidget(_dock);
+
+ _stack->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ) );
+
+ // Restore sizes
+ config->setGroup("General");
+ QValueList<int> sizes = config->readIntListEntry( "SplitterSizes" );
+ if (!sizes.isEmpty())
+ _splitter->setSizes(sizes);
+
+ // That one does the trick ...
+ _splitter->setResizeMode( leftFrame, QSplitter::KeepSize );
+
+ connect(_dock, SIGNAL(newModule(const QString&, const QString&, const QString&)),
+ this, SLOT(newModule(const QString&, const QString&, const QString&)));
+ connect(_dock, SIGNAL(changedModule(ConfigModule*)),
+ SLOT(changedModule(ConfigModule*)));
+
+ // set the main view
+ setCentralWidget( _splitter );
+
+ // initialize the GUI actions
+ setupActions();
+
+ // activate defaults
+ if (KCGlobal::viewMode() == Tree) {
+ activateTreeView();
+ tree_view->setChecked(true);
+ }
+ else {
+ activateIconView();
+ icon_view->setChecked(true);
+ }
+
+ // insert the about widget
+ if (KCGlobal::isInfoCenter())
+ {
+ AboutWidget *aw = new AboutWidget( this, 0, _index->firstTreeViewItem());
+ connect( aw, SIGNAL( moduleSelected( ConfigModule * ) ),
+ SLOT( activateModule( ConfigModule * ) ) );
+ _dock->setBaseWidget( aw );
+ KWin::setIcons( winId(),
+ KGlobal::iconLoader()->loadIcon("hwinfo", KIcon::NoGroup, 32 ),
+ KGlobal::iconLoader()->loadIcon("hwinfo", KIcon::NoGroup, 16 ) );
+ }
+ else
+ {
+ AboutWidget *aw = new AboutWidget(this);
+ connect( aw, SIGNAL( moduleSelected( ConfigModule * ) ),
+ SLOT( activateModule( ConfigModule * ) ) );
+ _dock->setBaseWidget(aw);
+ }
+}
+
+TopLevel::~TopLevel()
+{
+ KConfig *config = KGlobal::config();
+ config->setGroup("Index");
+ if (KCGlobal::viewMode() == Tree)
+ config->writeEntry("ViewMode", "Tree");
+ else
+ config->writeEntry("ViewMode", "Icon");
+
+ switch (KCGlobal::iconSize())
+ {
+ case KIcon::SizeSmall:
+ config->writeEntry("IconSize", "Small");
+ break;
+ case KIcon::SizeLarge:
+ config->writeEntry("IconSize", "Large");
+ break;
+ case KIcon::SizeHuge:
+ config->writeEntry("IconSize", "Huge");
+ break;
+ default:
+ config->writeEntry("IconSize", "Medium");
+ break;
+ }
+
+ config->setGroup("General");
+ config->writeEntry("SplitterSizes", _splitter->sizes());
+
+ config->sync();
+
+ delete _modules;
+}
+
+bool TopLevel::queryClose()
+{
+ return _dock->dockModule(0);
+}
+
+void TopLevel::setupActions()
+{
+ KStdAction::quit(this, SLOT(close()), actionCollection());
+ KStdAction::keyBindings(guiFactory(), SLOT(configureShortcuts()),
+actionCollection());
+ icon_view = new KRadioAction
+ (i18n("&Icon View"), 0, this, SLOT(activateIconView()),
+ actionCollection(), "activate_iconview");
+ icon_view->setExclusiveGroup( "viewmode" );
+
+ tree_view = new KRadioAction
+ (i18n("&Tree View"), 0, this, SLOT(activateTreeView()),
+ actionCollection(), "activate_treeview");
+ tree_view->setExclusiveGroup( "viewmode" );
+
+ icon_small = new KRadioAction
+ (i18n("&Small"), 0, this, SLOT(activateSmallIcons()),
+ actionCollection(), "activate_smallicons");
+ icon_small->setExclusiveGroup( "iconsize" );
+
+ icon_medium = new KRadioAction
+ (i18n("&Medium"), 0, this, SLOT(activateMediumIcons()),
+ actionCollection(), "activate_mediumicons");
+ icon_medium->setExclusiveGroup( "iconsize" );
+
+ icon_large = new KRadioAction
+ (i18n("&Large"), 0, this, SLOT(activateLargeIcons()),
+ actionCollection(), "activate_largeicons");
+ icon_large->setExclusiveGroup( "iconsize" );
+
+ icon_huge = new KRadioAction
+ (i18n("&Huge"), 0, this, SLOT(activateHugeIcons()),
+ actionCollection(), "activate_hugeicons");
+ icon_huge->setExclusiveGroup( "iconsize" );
+
+ about_module = new KAction(i18n("About Current Module"), 0, this, SLOT(aboutModule()), actionCollection(), "help_about_module");
+ about_module->setEnabled(false);
+
+ // I need to add this so that each module can get a bug reported,
+ // and not just KControl
+ if (KCGlobal::isInfoCenter())
+ createGUI("kinfocenterui.rc");
+ else
+ createGUI("kcontrolui.rc");
+
+ report_bug = actionCollection()->action("help_report_bug");
+ report_bug->setText(i18n("&Report Bug..."));
+ report_bug->disconnect();
+ connect(report_bug, SIGNAL(activated()), SLOT(reportBug()));
+}
+
+void TopLevel::activateIconView()
+{
+ KCGlobal::setViewMode(Icon);
+ _index->activateView(Icon);
+
+ icon_small->setEnabled(true);
+ icon_medium->setEnabled(true);
+ icon_large->setEnabled(true);
+ icon_huge->setEnabled(true);
+
+ switch(KCGlobal::iconSize())
+ {
+ case KIcon::SizeSmall:
+ icon_small->setChecked(true);
+ break;
+ case KIcon::SizeLarge:
+ icon_large->setChecked(true);
+ break;
+ case KIcon::SizeHuge:
+ icon_huge->setChecked(true);
+ break;
+ default:
+ icon_medium->setChecked(true);
+ break;
+ }
+}
+
+void TopLevel::activateTreeView()
+{
+ KCGlobal::setViewMode(Tree);
+ _index->activateView(Tree);
+
+ icon_small->setEnabled(false);
+ icon_medium->setEnabled(false);
+ icon_large->setEnabled(false);
+ icon_huge->setEnabled(false);
+}
+
+void TopLevel::activateSmallIcons()
+{
+ KCGlobal::setIconSize(KIcon::SizeSmall);
+ _index->reload();
+}
+
+void TopLevel::activateMediumIcons()
+{
+ KCGlobal::setIconSize(KIcon::SizeMedium);
+ _index->reload();
+}
+
+void TopLevel::activateLargeIcons()
+{
+ KCGlobal::setIconSize(KIcon::SizeLarge);
+ _index->reload();
+}
+
+void TopLevel::activateHugeIcons()
+{
+ KCGlobal::setIconSize(KIcon::SizeHuge);
+ _index->reload();
+}
+
+void TopLevel::newModule(const QString &name, const QString& docPath, const QString &quickhelp)
+{
+ setCaption(name, false);
+
+ _help->setText( docPath, quickhelp );
+
+ if (!report_bug) return;
+
+ if(name.isEmpty())
+ report_bug->setText(i18n("&Report Bug..."));
+ else
+ report_bug->setText(i18n("Report Bug on Module %1...").arg( handleAmpersand( name)));
+}
+
+void TopLevel::changedModule(ConfigModule *changed)
+{
+ if (!changed)
+ return;
+ setCaption(changed->moduleName(), changed->isChanged() );
+}
+
+void TopLevel::categorySelected(QListViewItem *category)
+{
+ if (_active)
+ {
+ if (_active->isChanged())
+ {
+ int res = KMessageBox::warningYesNoCancel(this, _active ?
+ i18n("There are unsaved changes in the active module.\n"
+ "Do you want to apply the changes before running "
+ "the new module or discard the changes?") :
+ i18n("There are unsaved changes in the active module.\n"
+ "Do you want to apply the changes before exiting "
+ "the Control Center or discard the changes?"),
+ i18n("Unsaved Changes"),
+ KStdGuiItem::apply(),
+ KStdGuiItem::discard());
+ if (res == KMessageBox::Yes)
+ _active->module()->applyClicked();
+ else if (res == KMessageBox::Cancel)
+ return;
+ }
+ }
+ _dock->removeModule();
+ about_module->setText( i18n( "About Current Module" ) );
+ about_module->setIconSet( QIconSet() );
+ about_module->setEnabled( false );
+
+ // insert the about widget
+ QListViewItem *firstItem = category->firstChild();
+ QString caption = static_cast<ModuleTreeItem*>(category)->caption();
+ QString icon = static_cast<ModuleTreeItem*>(category)->icon();
+ if( _dock->baseWidget()->isA( "AboutWidget" ) )
+ {
+ static_cast<AboutWidget *>( _dock->baseWidget() )->setCategory( firstItem, icon, caption);
+ }
+ else
+ {
+ AboutWidget *aw = new AboutWidget( this, 0, firstItem, caption );
+ connect( aw, SIGNAL( moduleSelected( ConfigModule * ) ),
+ SLOT( activateModule( ConfigModule * ) ) );
+ _dock->setBaseWidget( aw );
+ }
+}
+
+
+void TopLevel::activateModule(ConfigModule *mod)
+{
+ if ( _dock->module() == mod )
+ return;
+
+ // tell the index to display the module
+ _index->makeVisible(mod);
+
+ // tell the index to mark this module as loaded
+ _index->makeSelected(mod);
+
+ // dock it
+ if (!_dock->dockModule(mod))
+ {
+ if ( _dock->module() )
+ {
+ _index->makeVisible(_active);
+ _index->makeSelected(_active);
+ }
+ return;
+ }
+
+ _active=mod;
+
+ if (mod->aboutData())
+ {
+ about_module->setText(i18n("Help menu->about <modulename>", "About %1").arg(
+ handleAmpersand( mod->moduleName())));
+ about_module->setIcon(mod->icon());
+ about_module->setEnabled(true);
+ }
+ else
+ {
+ about_module->setText(i18n("About Current Module"));
+ about_module->setIconSet(QIconSet());
+ about_module->setEnabled(false);
+ }
+}
+
+void TopLevel::deleteDummyAbout()
+{
+ delete dummyAbout;
+ dummyAbout = 0;
+}
+
+void TopLevel::slotSearchChanged(const QString& search)
+{
+ if (search.isEmpty())
+ _stack->raiseWidget(_index);
+ else
+ {
+ _stack->raiseWidget(_search);
+ _search->searchTextChanged(search);
+ }
+}
+
+void TopLevel::slotHelpRequest()
+{
+ _help->display(_help->text(), QCursor::pos ( ), _dock);
+}
+
+void TopLevel::slotHandbookRequest()
+{
+ _help->handbookRequest();
+}
+
+void TopLevel::reportBug()
+{
+ // this assumes the user only opens one bug report at a time
+ static char buffer[128];
+
+ dummyAbout = 0;
+ bool deleteit = false;
+
+ if (!_active) // report against kcontrol
+ dummyAbout = const_cast<KAboutData*>(KGlobal::instance()->aboutData());
+ else
+ {
+ if (_active->aboutData())
+ dummyAbout = const_cast<KAboutData*>(_active->aboutData());
+ else
+ {
+ snprintf(buffer, sizeof(buffer), "kcm%s", _active->library().latin1());
+ dummyAbout = new KAboutData(buffer, _active->moduleName().utf8(), "2.0");
+ deleteit = true;
+ }
+ }
+ KBugReport *br = new KBugReport(this, false, dummyAbout);
+ if (deleteit)
+ connect(br, SIGNAL(finished()), SLOT(deleteDummyAbout()));
+ else
+ dummyAbout = 0;
+ br->show();
+}
+
+void TopLevel::aboutModule()
+{
+ KAboutApplication dlg(_active->aboutData());
+ dlg.exec();
+}
+
+QString TopLevel::handleAmpersand( QString modulename ) const
+{
+ if( modulename.contains( '&' )) // double it
+ {
+ for( int i = modulename.length();
+ i >= 0;
+ --i )
+ if( modulename[ i ] == '&' )
+ modulename.insert( i, "&" );
+ }
+ return modulename;
+}