You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
4155 lines
156 KiB
4155 lines
156 KiB
/* -*- mode: C++; c-file-style: "gnu" -*- |
|
* kmail: KDE mail client |
|
* This file: Copyright (C) 2000 Espen Sand, espen@kde.org |
|
* Copyright (C) 2001-2003 Marc Mutz, mutz@kde.org |
|
* Contains code segments and ideas from earlier kmail dialog code. |
|
* |
|
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
|
* |
|
*/ |
|
|
|
// This must be first |
|
#include <config.h> |
|
|
|
// my headers: |
|
#include "configuredialog.h" |
|
#include "configuredialog_p.h" |
|
|
|
#include "globalsettings.h" |
|
|
|
// other KMail headers: |
|
#include "simplestringlisteditor.h" |
|
#include "accountdialog.h" |
|
#include "colorlistbox.h" |
|
#include "kmacctmgr.h" |
|
#include "kmacctseldlg.h" |
|
#include "kmsender.h" |
|
#include "kmtransport.h" |
|
#include "kmfoldermgr.h" |
|
#include <libkpimidentities/identitymanager.h> |
|
#include "identitylistview.h" |
|
#include "kcursorsaver.h" |
|
#include "kmkernel.h" |
|
#include <composercryptoconfiguration.h> |
|
#include <warningconfiguration.h> |
|
#include <smimeconfiguration.h> |
|
|
|
using KMail::IdentityListView; |
|
using KMail::IdentityListViewItem; |
|
#include "identitydialog.h" |
|
using KMail::IdentityDialog; |
|
|
|
// other kdenetwork headers: |
|
#include <libkpimidentities/identity.h> |
|
#include <kmime_util.h> |
|
using KMime::DateFormatter; |
|
#include <kleo/cryptoconfig.h> |
|
#include <kleo/cryptobackendfactory.h> |
|
#include <ui/backendconfigwidget.h> |
|
#include <ui/keyrequester.h> |
|
|
|
// other KDE headers: |
|
#include <klocale.h> |
|
#include <kapplication.h> |
|
#include <kcharsets.h> |
|
#include <kdebug.h> |
|
#include <knuminput.h> |
|
#include <kfontdialog.h> |
|
#include <kmessagebox.h> |
|
#include <kurlrequester.h> |
|
#include <kseparator.h> |
|
#include <kiconloader.h> |
|
#include <kstandarddirs.h> |
|
#include <kwin.h> |
|
#include <knotifydialog.h> |
|
#include <kconfig.h> |
|
#include <kactivelabel.h> |
|
#include <kcmultidialog.h> |
|
|
|
// Qt headers: |
|
#include <qvalidator.h> |
|
#include <qwhatsthis.h> |
|
#include <qvgroupbox.h> |
|
#include <qvbox.h> |
|
#include <qvbuttongroup.h> |
|
#include <qhbuttongroup.h> |
|
#include <qtooltip.h> |
|
#include <qlabel.h> |
|
#include <qtextcodec.h> |
|
#include <qheader.h> |
|
#include <qpopupmenu.h> |
|
#include <qradiobutton.h> |
|
#include <qlayout.h> |
|
#include <qcheckbox.h> |
|
|
|
// other headers: |
|
#include <assert.h> |
|
|
|
#ifndef _PATH_SENDMAIL |
|
#define _PATH_SENDMAIL "/usr/sbin/sendmail" |
|
#endif |
|
|
|
#ifdef DIM |
|
#undef DIM |
|
#endif |
|
#define DIM(x) sizeof(x) / sizeof(*x) |
|
|
|
namespace { |
|
|
|
struct EnumConfigEntryItem { |
|
const char * key; // config key value, as appears in config file |
|
const char * desc; // description, to be i18n()ized |
|
}; |
|
struct EnumConfigEntry { |
|
const char * group; |
|
const char * key; |
|
const char * desc; |
|
const EnumConfigEntryItem * items; |
|
int numItems; |
|
int defaultItem; |
|
}; |
|
struct BoolConfigEntry { |
|
const char * group; |
|
const char * key; |
|
const char * desc; |
|
bool defaultValue; |
|
}; |
|
|
|
static const char * lockedDownWarning = |
|
I18N_NOOP("<qt><p>This setting has been fixed by your administrator.</p>" |
|
"<p>If you think this is an error, please contact him.</p></qt>"); |
|
|
|
void checkLockDown( QWidget * w, const KConfigBase & c, const char * key ) { |
|
if ( c.entryIsImmutable( key ) ) { |
|
w->setEnabled( false ); |
|
QToolTip::add( w, i18n( lockedDownWarning ) ); |
|
} else { |
|
QToolTip::remove( w ); |
|
} |
|
} |
|
|
|
void populateButtonGroup( QButtonGroup * g, const EnumConfigEntry & e ) { |
|
g->setTitle( i18n( e.desc ) ); |
|
g->layout()->setSpacing( KDialog::spacingHint() ); |
|
for ( int i = 0 ; i < e.numItems ; ++i ) |
|
g->insert( new QRadioButton( i18n( e.items[i].desc ), g ), i ); |
|
} |
|
|
|
void populateCheckBox( QCheckBox * b, const BoolConfigEntry & e ) { |
|
b->setText( i18n( e.desc ) ); |
|
} |
|
|
|
void loadWidget( QCheckBox * b, const KConfigBase & c, const BoolConfigEntry & e ) { |
|
Q_ASSERT( c.group() == e.group ); |
|
checkLockDown( b, c, e.key ); |
|
b->setChecked( c.readBoolEntry( e.key, e.defaultValue ) ); |
|
} |
|
|
|
void loadWidget( QButtonGroup * g, const KConfigBase & c, const EnumConfigEntry & e ) { |
|
Q_ASSERT( c.group() == e.group ); |
|
Q_ASSERT( g->count() == e.numItems ); |
|
checkLockDown( g, c, e.key ); |
|
const QString s = c.readEntry( e.key, e.items[e.defaultItem].key ); |
|
for ( int i = 0 ; i < e.numItems ; ++i ) |
|
if ( s == e.items[i].key ) { |
|
g->setButton( i ); |
|
return; |
|
} |
|
g->setButton( e.defaultItem ); |
|
} |
|
|
|
void saveCheckBox( QCheckBox * b, KConfigBase & c, const BoolConfigEntry & e ) { |
|
Q_ASSERT( c.group() == e.group ); |
|
c.writeEntry( e.key, b->isChecked() ); |
|
} |
|
|
|
void saveButtonGroup( QButtonGroup * g, KConfigBase & c, const EnumConfigEntry & e ) { |
|
Q_ASSERT( c.group() == e.group ); |
|
Q_ASSERT( g->count() == e.numItems ); |
|
c.writeEntry( e.key, e.items[ g->id( g->selected() ) ].key ); |
|
} |
|
|
|
template <typename T_Widget, typename T_Entry> |
|
inline void loadProfile( T_Widget * g, const KConfigBase & c, const T_Entry & e ) { |
|
if ( c.hasKey( e.key ) ) |
|
loadWidget( g, c, e ); |
|
} |
|
} |
|
|
|
|
|
ConfigureDialog::ConfigureDialog( QWidget *parent, const char *name, bool modal ) |
|
: KCMultiDialog( KDialogBase::IconList, KGuiItem( i18n( "&Load Profile..." ) ), |
|
KGuiItem(), User2, i18n( "Configure" ), parent, name, modal ) |
|
, mProfileDialog( 0 ) |
|
{ |
|
KWin::setIcons( winId(), kapp->icon(), kapp->miniIcon() ); |
|
showButton( User1, true ); |
|
|
|
addModule ( "kmail_config_identity", false ); |
|
addModule ( "kmail_config_network", false ); |
|
addModule ( "kmail_config_appearance", false ); |
|
addModule ( "kmail_config_composer", false ); |
|
addModule ( "kmail_config_security", false ); |
|
addModule ( "kmail_config_misc", false ); |
|
|
|
// We store the size of the dialog on hide, because otherwise |
|
// the KCMultiDialog starts with the size of the first kcm, not |
|
// the largest one. This way at least after the first showing of |
|
// the largest kcm the size is kept. |
|
KConfigGroup geometry( KMKernel::config(), "Geometry" ); |
|
int width = geometry.readNumEntry( "ConfigureDialogWidth" ); |
|
int height = geometry.readNumEntry( "ConfigureDialogHeight" ); |
|
if ( width != 0 && height != 0 ) { |
|
setMinimumSize( width, height ); |
|
} |
|
|
|
} |
|
|
|
void ConfigureDialog::hideEvent( QHideEvent * ) { |
|
KConfigGroup geometry( KMKernel::config(), "Geometry" ); |
|
geometry.writeEntry( "ConfigureDialogWidth", width() ); |
|
geometry.writeEntry( "ConfigureDialogHeight",height() ); |
|
} |
|
|
|
ConfigureDialog::~ConfigureDialog() { |
|
} |
|
|
|
void ConfigureDialog::slotApply() { |
|
KCMultiDialog::slotApply(); |
|
GlobalSettings::writeConfig(); |
|
} |
|
|
|
void ConfigureDialog::slotOk() { |
|
KCMultiDialog::slotOk(); |
|
GlobalSettings::writeConfig(); |
|
} |
|
|
|
void ConfigureDialog::slotUser2() { |
|
if ( mProfileDialog ) { |
|
mProfileDialog->raise(); |
|
return; |
|
} |
|
mProfileDialog = new ProfileDialog( this, "mProfileDialog" ); |
|
connect( mProfileDialog, SIGNAL(profileSelected(KConfig*)), |
|
this, SIGNAL(installProfile(KConfig*)) ); |
|
mProfileDialog->show(); |
|
} |
|
|
|
// ************************************************************* |
|
// * * |
|
// * IdentityPage * |
|
// * * |
|
// ************************************************************* |
|
QString IdentityPage::helpAnchor() const { |
|
return QString::fromLatin1("configure-identity"); |
|
} |
|
|
|
IdentityPage::IdentityPage( QWidget * parent, const char * name ) |
|
: ConfigModule( parent, name ), |
|
mIdentityDialog( 0 ) |
|
{ |
|
QHBoxLayout * hlay = new QHBoxLayout( this, 0, KDialog::spacingHint() ); |
|
|
|
mIdentityList = new IdentityListView( this ); |
|
connect( mIdentityList, SIGNAL(selectionChanged()), |
|
SLOT(slotIdentitySelectionChanged()) ); |
|
connect( mIdentityList, SIGNAL(itemRenamed(QListViewItem*,const QString&,int)), |
|
SLOT(slotRenameIdentity(QListViewItem*,const QString&,int)) ); |
|
connect( mIdentityList, SIGNAL(doubleClicked(QListViewItem*,const QPoint&,int)), |
|
SLOT(slotModifyIdentity()) ); |
|
connect( mIdentityList, SIGNAL(contextMenu(KListView*,QListViewItem*,const QPoint&)), |
|
SLOT(slotContextMenu(KListView*,QListViewItem*,const QPoint&)) ); |
|
// ### connect dragged(...), ... |
|
|
|
hlay->addWidget( mIdentityList, 1 ); |
|
|
|
QVBoxLayout * vlay = new QVBoxLayout( hlay ); // inherits spacing |
|
|
|
QPushButton * button = new QPushButton( i18n("&New..."), this ); |
|
mModifyButton = new QPushButton( i18n("&Modify..."), this ); |
|
mRenameButton = new QPushButton( i18n("&Rename"), this ); |
|
mRemoveButton = new QPushButton( i18n("Remo&ve"), this ); |
|
mSetAsDefaultButton = new QPushButton( i18n("Set as &Default"), this ); |
|
button->setAutoDefault( false ); |
|
mModifyButton->setAutoDefault( false ); |
|
mModifyButton->setEnabled( false ); |
|
mRenameButton->setAutoDefault( false ); |
|
mRenameButton->setEnabled( false ); |
|
mRemoveButton->setAutoDefault( false ); |
|
mRemoveButton->setEnabled( false ); |
|
mSetAsDefaultButton->setAutoDefault( false ); |
|
mSetAsDefaultButton->setEnabled( false ); |
|
connect( button, SIGNAL(clicked()), |
|
this, SLOT(slotNewIdentity()) ); |
|
connect( mModifyButton, SIGNAL(clicked()), |
|
this, SLOT(slotModifyIdentity()) ); |
|
connect( mRenameButton, SIGNAL(clicked()), |
|
this, SLOT(slotRenameIdentity()) ); |
|
connect( mRemoveButton, SIGNAL(clicked()), |
|
this, SLOT(slotRemoveIdentity()) ); |
|
connect( mSetAsDefaultButton, SIGNAL(clicked()), |
|
this, SLOT(slotSetAsDefault()) ); |
|
vlay->addWidget( button ); |
|
vlay->addWidget( mModifyButton ); |
|
vlay->addWidget( mRenameButton ); |
|
vlay->addWidget( mRemoveButton ); |
|
vlay->addWidget( mSetAsDefaultButton ); |
|
vlay->addStretch( 1 ); |
|
load(); |
|
} |
|
|
|
void IdentityPage::load() |
|
{ |
|
KPIM::IdentityManager * im = kmkernel->identityManager(); |
|
mOldNumberOfIdentities = im->shadowIdentities().count(); |
|
// Fill the list: |
|
mIdentityList->clear(); |
|
// Don't use ConstIterator here - it iterates over the wrong list! |
|
QListViewItem * item = 0; |
|
for ( KPIM::IdentityManager::Iterator it = im->begin() ; it != im->end() ; ++it ) |
|
item = new IdentityListViewItem( mIdentityList, item, *it ); |
|
mIdentityList->setSelected( mIdentityList->currentItem(), true ); |
|
} |
|
|
|
void IdentityPage::save() { |
|
assert( !mIdentityDialog ); |
|
|
|
kmkernel->identityManager()->sort(); |
|
kmkernel->identityManager()->commit(); |
|
|
|
if( mOldNumberOfIdentities < 2 && mIdentityList->childCount() > 1 ) { |
|
// have more than one identity, so better show the combo in the |
|
// composer now: |
|
KConfigGroup composer( KMKernel::config(), "Composer" ); |
|
int showHeaders = composer.readNumEntry( "headers", HDR_STANDARD ); |
|
showHeaders |= HDR_IDENTITY; |
|
composer.writeEntry( "headers", showHeaders ); |
|
} |
|
// and now the reverse |
|
if( mOldNumberOfIdentities > 1 && mIdentityList->childCount() < 2 ) { |
|
// have only one identity, so remove the combo in the composer: |
|
KConfigGroup composer( KMKernel::config(), "Composer" ); |
|
int showHeaders = composer.readNumEntry( "headers", HDR_STANDARD ); |
|
showHeaders &= ~HDR_IDENTITY; |
|
composer.writeEntry( "headers", showHeaders ); |
|
} |
|
} |
|
|
|
void IdentityPage::slotNewIdentity() |
|
{ |
|
assert( !mIdentityDialog ); |
|
|
|
KPIM::IdentityManager * im = kmkernel->identityManager(); |
|
NewIdentityDialog dialog( im->shadowIdentities(), this, "new", true ); |
|
|
|
if( dialog.exec() == QDialog::Accepted ) { |
|
QString identityName = dialog.identityName().stripWhiteSpace(); |
|
assert( !identityName.isEmpty() ); |
|
|
|
// |
|
// Construct a new Identity: |
|
// |
|
switch ( dialog.duplicateMode() ) { |
|
case NewIdentityDialog::ExistingEntry: |
|
{ |
|
KPIM::Identity & dupThis = im->identityForName( dialog.duplicateIdentity() ); |
|
im->newFromExisting( dupThis, identityName ); |
|
break; |
|
} |
|
case NewIdentityDialog::ControlCenter: |
|
im->newFromControlCenter( identityName ); |
|
break; |
|
case NewIdentityDialog::Empty: |
|
im->newFromScratch( identityName ); |
|
default: ; |
|
} |
|
|
|
// |
|
// Insert into listview: |
|
// |
|
KPIM::Identity & newIdent = im->identityForName( identityName ); |
|
QListViewItem * item = mIdentityList->selectedItem(); |
|
if ( item ) |
|
item = item->itemAbove(); |
|
mIdentityList->setSelected( new IdentityListViewItem( mIdentityList, |
|
/*after*/ item, |
|
newIdent ), true ); |
|
slotModifyIdentity(); |
|
} |
|
} |
|
|
|
void IdentityPage::slotModifyIdentity() { |
|
assert( !mIdentityDialog ); |
|
|
|
IdentityListViewItem * item = |
|
dynamic_cast<IdentityListViewItem*>( mIdentityList->selectedItem() ); |
|
if ( !item ) return; |
|
|
|
mIdentityDialog = new IdentityDialog( this ); |
|
mIdentityDialog->setIdentity( item->identity() ); |
|
|
|
// Hmm, an unmodal dialog would be nicer, but a modal one is easier ;-) |
|
if ( mIdentityDialog->exec() == QDialog::Accepted ) { |
|
mIdentityDialog->updateIdentity( item->identity() ); |
|
item->redisplay(); |
|
emit changed(true); |
|
} |
|
|
|
delete mIdentityDialog; |
|
mIdentityDialog = 0; |
|
} |
|
|
|
void IdentityPage::slotRemoveIdentity() |
|
{ |
|
assert( !mIdentityDialog ); |
|
|
|
KPIM::IdentityManager * im = kmkernel->identityManager(); |
|
kdFatal( im->shadowIdentities().count() < 2 ) |
|
<< "Attempted to remove the last identity!" << endl; |
|
|
|
IdentityListViewItem * item = |
|
dynamic_cast<IdentityListViewItem*>( mIdentityList->selectedItem() ); |
|
if ( !item ) return; |
|
|
|
QString msg = i18n("<qt>Do you really want to remove the identity named " |
|
"<b>%1</b>?</qt>").arg( item->identity().identityName() ); |
|
if( KMessageBox::warningYesNo( this, msg ) == KMessageBox::Yes ) |
|
if ( im->removeIdentity( item->identity().identityName() ) ) { |
|
delete item; |
|
mIdentityList->setSelected( mIdentityList->currentItem(), true ); |
|
refreshList(); |
|
} |
|
} |
|
|
|
void IdentityPage::slotRenameIdentity() { |
|
assert( !mIdentityDialog ); |
|
|
|
QListViewItem * item = mIdentityList->selectedItem(); |
|
if ( !item ) return; |
|
|
|
mIdentityList->rename( item, 0 ); |
|
} |
|
|
|
void IdentityPage::slotRenameIdentity( QListViewItem * i, |
|
const QString & s, int col ) { |
|
assert( col == 0 ); |
|
Q_UNUSED( col ); |
|
|
|
IdentityListViewItem * item = dynamic_cast<IdentityListViewItem*>( i ); |
|
if ( !item ) return; |
|
|
|
QString newName = s.stripWhiteSpace(); |
|
if ( !newName.isEmpty() && |
|
!kmkernel->identityManager()->shadowIdentities().contains( newName ) ) { |
|
KPIM::Identity & ident = item->identity(); |
|
ident.setIdentityName( newName ); |
|
emit changed(true); |
|
} |
|
item->redisplay(); |
|
} |
|
|
|
void IdentityPage::slotContextMenu( KListView *, QListViewItem * i, |
|
const QPoint & pos ) { |
|
IdentityListViewItem * item = dynamic_cast<IdentityListViewItem*>( i ); |
|
|
|
QPopupMenu * menu = new QPopupMenu( this ); |
|
menu->insertItem( i18n("New..."), this, SLOT(slotNewIdentity()) ); |
|
if ( item ) { |
|
menu->insertItem( i18n("Modify..."), this, SLOT(slotModifyIdentity()) ); |
|
if ( mIdentityList->childCount() > 1 ) |
|
menu->insertItem( i18n("Remove"), this, SLOT(slotRemoveIdentity()) ); |
|
if ( !item->identity().isDefault() ) |
|
menu->insertItem( i18n("Set as Default"), this, SLOT(slotSetAsDefault()) ); |
|
} |
|
menu->exec( pos ); |
|
delete menu; |
|
} |
|
|
|
|
|
void IdentityPage::slotSetAsDefault() { |
|
assert( !mIdentityDialog ); |
|
|
|
IdentityListViewItem * item = |
|
dynamic_cast<IdentityListViewItem*>( mIdentityList->selectedItem() ); |
|
if ( !item ) return; |
|
|
|
KPIM::IdentityManager * im = kmkernel->identityManager(); |
|
im->setAsDefault( item->identity().identityName() ); |
|
refreshList(); |
|
} |
|
|
|
void IdentityPage::refreshList() { |
|
for ( QListViewItemIterator it( mIdentityList ) ; it.current() ; ++it ) { |
|
IdentityListViewItem * item = |
|
dynamic_cast<IdentityListViewItem*>(it.current()); |
|
if ( item ) |
|
item->redisplay(); |
|
} |
|
emit changed(true); |
|
} |
|
|
|
void IdentityPage::slotIdentitySelectionChanged() |
|
{ |
|
IdentityListViewItem *item = |
|
dynamic_cast<IdentityListViewItem*>( mIdentityList->selectedItem() ); |
|
|
|
mRemoveButton->setEnabled( item && mIdentityList->childCount() > 1 ); |
|
mModifyButton->setEnabled( item ); |
|
mRenameButton->setEnabled( item ); |
|
mSetAsDefaultButton->setEnabled( item && !item->identity().isDefault() ); |
|
} |
|
|
|
void IdentityPage::slotUpdateTransportCombo( const QStringList & sl ) |
|
{ |
|
if ( mIdentityDialog ) mIdentityDialog->slotUpdateTransportCombo( sl ); |
|
} |
|
|
|
|
|
|
|
// ************************************************************* |
|
// * * |
|
// * NetworkPage * |
|
// * * |
|
// ************************************************************* |
|
QString NetworkPage::helpAnchor() const { |
|
return QString::fromLatin1("configure-network"); |
|
} |
|
|
|
NetworkPage::NetworkPage( QWidget * parent, const char * name ) |
|
: ConfigModuleWithTabs( parent, name ) |
|
{ |
|
// |
|
// "Sending" tab: |
|
// |
|
mSendingTab = new SendingTab(); |
|
addTab( mSendingTab, i18n( "&Sending" ) ); |
|
connect( mSendingTab, SIGNAL(transportListChanged(const QStringList&)), |
|
this, SIGNAL(transportListChanged(const QStringList&)) ); |
|
|
|
// |
|
// "Receiving" tab: |
|
// |
|
mReceivingTab = new ReceivingTab(); |
|
addTab( mReceivingTab, i18n( "&Receiving" ) ); |
|
|
|
connect( mReceivingTab, SIGNAL(accountListChanged(const QStringList &)), |
|
this, SIGNAL(accountListChanged(const QStringList &)) ); |
|
load(); |
|
} |
|
|
|
|
|
QString NetworkPage::SendingTab::helpAnchor() const { |
|
return QString::fromLatin1("configure-network-sending"); |
|
} |
|
|
|
NetworkPageSendingTab::NetworkPageSendingTab( QWidget * parent, const char * name ) |
|
: ConfigModuleTab( parent, name ) |
|
{ |
|
mTransportInfoList.setAutoDelete( true ); |
|
// temp. vars: |
|
QVBoxLayout *vlay; |
|
QVBoxLayout *btn_vlay; |
|
QHBoxLayout *hlay; |
|
QGridLayout *glay; |
|
QPushButton *button; |
|
QGroupBox *group; |
|
|
|
vlay = new QVBoxLayout( this, KDialog::marginHint(), KDialog::spacingHint() ); |
|
// label: zero stretch ### FIXME more |
|
vlay->addWidget( new QLabel( i18n("Outgoing accounts (add at least one):"), this ) ); |
|
|
|
// hbox layout: stretch 10, spacing inherited from vlay |
|
hlay = new QHBoxLayout(); |
|
vlay->addLayout( hlay, 10 ); // high stretch b/c of the groupbox's sizeHint |
|
|
|
// transport list: left widget in hlay; stretch 1 |
|
// ### FIXME: allow inline renaming of the account: |
|
mTransportList = new ListView( this, "transportList", 5 ); |
|
mTransportList->addColumn( i18n("Name") ); |
|
mTransportList->addColumn( i18n("Type") ); |
|
mTransportList->setAllColumnsShowFocus( true ); |
|
mTransportList->setFrameStyle( QFrame::WinPanel + QFrame::Sunken ); |
|
mTransportList->setSorting( -1 ); |
|
connect( mTransportList, SIGNAL(selectionChanged()), |
|
this, SLOT(slotTransportSelected()) ); |
|
connect( mTransportList, SIGNAL(doubleClicked( QListViewItem *)), |
|
this, SLOT(slotModifySelectedTransport()) ); |
|
hlay->addWidget( mTransportList, 1 ); |
|
|
|
// a vbox layout for the buttons: zero stretch, spacing inherited from hlay |
|
btn_vlay = new QVBoxLayout( hlay ); |
|
|
|
// "add..." button: stretch 0 |
|
button = new QPushButton( i18n("A&dd..."), this ); |
|
button->setAutoDefault( false ); |
|
connect( button, SIGNAL(clicked()), |
|
this, SLOT(slotAddTransport()) ); |
|
btn_vlay->addWidget( button ); |
|
|
|
// "modify..." button: stretch 0 |
|
mModifyTransportButton = new QPushButton( i18n("&Modify..."), this ); |
|
mModifyTransportButton->setAutoDefault( false ); |
|
mModifyTransportButton->setEnabled( false ); // b/c no item is selected yet |
|
connect( mModifyTransportButton, SIGNAL(clicked()), |
|
this, SLOT(slotModifySelectedTransport()) ); |
|
btn_vlay->addWidget( mModifyTransportButton ); |
|
|
|
// "remove" button: stretch 0 |
|
mRemoveTransportButton = new QPushButton( i18n("R&emove"), this ); |
|
mRemoveTransportButton->setAutoDefault( false ); |
|
mRemoveTransportButton->setEnabled( false ); // b/c no item is selected yet |
|
connect( mRemoveTransportButton, SIGNAL(clicked()), |
|
this, SLOT(slotRemoveSelectedTransport()) ); |
|
btn_vlay->addWidget( mRemoveTransportButton ); |
|
|
|
// "up" button: stretch 0 |
|
// ### FIXME: shouldn't this be a QToolButton? |
|
mTransportUpButton = new QPushButton( QString::null, this ); |
|
mTransportUpButton->setIconSet( BarIconSet( "up", KIcon::SizeSmall ) ); |
|
// mTransportUpButton->setPixmap( BarIcon( "up", KIcon::SizeSmall ) ); |
|
mTransportUpButton->setAutoDefault( false ); |
|
mTransportUpButton->setEnabled( false ); // b/c no item is selected yet |
|
connect( mTransportUpButton, SIGNAL(clicked()), |
|
this, SLOT(slotTransportUp()) ); |
|
btn_vlay->addWidget( mTransportUpButton ); |
|
|
|
// "down" button: stretch 0 |
|
// ### FIXME: shouldn't this be a QToolButton? |
|
mTransportDownButton = new QPushButton( QString::null, this ); |
|
mTransportDownButton->setIconSet( BarIconSet( "down", KIcon::SizeSmall ) ); |
|
// mTransportDownButton->setPixmap( BarIcon( "down", KIcon::SizeSmall ) ); |
|
mTransportDownButton->setAutoDefault( false ); |
|
mTransportDownButton->setEnabled( false ); // b/c no item is selected yet |
|
connect( mTransportDownButton, SIGNAL(clicked()), |
|
this, SLOT(slotTransportDown()) ); |
|
btn_vlay->addWidget( mTransportDownButton ); |
|
btn_vlay->addStretch( 1 ); // spacer |
|
|
|
// "Common options" groupbox: |
|
group = new QGroupBox( 0, Qt::Vertical, |
|
i18n("Common Options"), this ); |
|
vlay->addWidget(group); |
|
|
|
// a grid layout for the contents of the "common options" group box |
|
glay = new QGridLayout( group->layout(), 5, 3, KDialog::spacingHint() ); |
|
glay->setColStretch( 2, 10 ); |
|
|
|
// "confirm before send" check box: |
|
mConfirmSendCheck = new QCheckBox( i18n("Confirm &before send"), group ); |
|
glay->addMultiCellWidget( mConfirmSendCheck, 0, 0, 0, 1 ); |
|
connect( mConfirmSendCheck, SIGNAL( stateChanged( int ) ), |
|
this, SLOT( slotEmitChanged( void ) ) ); |
|
|
|
// "send messages in outbox on check" check box: |
|
mSendOutboxCheck = |
|
new QCheckBox(i18n("Send messages in outbox &folder on check"), group ); |
|
glay->addMultiCellWidget( mSendOutboxCheck, 1, 1, 0, 1 ); |
|
connect( mSendOutboxCheck, SIGNAL( stateChanged( int ) ), |
|
this, SLOT( slotEmitChanged( void ) ) ); |
|
|
|
// "default send method" combo: |
|
mSendMethodCombo = new QComboBox( false, group ); |
|
mSendMethodCombo->insertStringList( QStringList() |
|
<< i18n("Send Now") |
|
<< i18n("Send Later") ); |
|
glay->addWidget( mSendMethodCombo, 2, 1 ); |
|
connect( mSendMethodCombo, SIGNAL( activated( int ) ), |
|
this, SLOT( slotEmitChanged( void ) ) ); |
|
|
|
|
|
// "message property" combo: |
|
// ### FIXME: remove completely? |
|
mMessagePropertyCombo = new QComboBox( false, group ); |
|
mMessagePropertyCombo->insertStringList( QStringList() |
|
<< i18n("Allow 8-bit") |
|
<< i18n("MIME Compliant (Quoted Printable)") ); |
|
glay->addWidget( mMessagePropertyCombo, 3, 1 ); |
|
connect( mMessagePropertyCombo, SIGNAL( activated( int ) ), |
|
this, SLOT( slotEmitChanged( void ) ) ); |
|
|
|
// "default domain" input field: |
|
mDefaultDomainEdit = new KLineEdit( group ); |
|
glay->addMultiCellWidget( mDefaultDomainEdit, 4, 4, 1, 2 ); |
|
connect( mDefaultDomainEdit, SIGNAL( textChanged( const QString& ) ), |
|
this, SLOT( slotEmitChanged( void ) ) ); |
|
|
|
// labels: |
|
glay->addWidget( new QLabel( mSendMethodCombo, /*buddy*/ |
|
i18n("Defa&ult send method:"), group ), 2, 0 ); |
|
glay->addWidget( new QLabel( mMessagePropertyCombo, /*buddy*/ |
|
i18n("Message &property:"), group ), 3, 0 ); |
|
QLabel *l = new QLabel( mDefaultDomainEdit, /*buddy*/ |
|
i18n("Defaul&t domain:"), group ); |
|
glay->addWidget( l, 4, 0 ); |
|
|
|
// and now: add QWhatsThis: |
|
QString msg = i18n( "<qt><p>The default domain is used to complete email " |
|
"addresses that only consist of the user's name." |
|
"</p></qt>" ); |
|
QWhatsThis::add( l, msg ); |
|
QWhatsThis::add( mDefaultDomainEdit, msg ); |
|
} |
|
|
|
|
|
void NetworkPage::SendingTab::slotTransportSelected() |
|
{ |
|
QListViewItem *cur = mTransportList->selectedItem(); |
|
mModifyTransportButton->setEnabled( cur ); |
|
mRemoveTransportButton->setEnabled( cur ); |
|
mTransportDownButton->setEnabled( cur && cur->itemBelow() ); |
|
mTransportUpButton->setEnabled( cur && cur->itemAbove() ); |
|
} |
|
|
|
// adds a number to @p name to make the name unique |
|
static inline QString uniqueName( const QStringList & list, |
|
const QString & name ) |
|
{ |
|
int suffix = 1; |
|
QString result = name; |
|
while ( list.find( result ) != list.end() ) { |
|
result = i18n("%1: name; %2: number appended to it to make it unique " |
|
"among a list of names", "%1 %2") |
|
.arg( name ).arg( suffix ); |
|
suffix++; |
|
} |
|
return result; |
|
} |
|
|
|
void NetworkPage::SendingTab::slotAddTransport() |
|
{ |
|
int transportType; |
|
|
|
{ // limit scope of selDialog |
|
KMTransportSelDlg selDialog( this ); |
|
if ( selDialog.exec() != QDialog::Accepted ) return; |
|
transportType = selDialog.selected(); |
|
} |
|
|
|
KMTransportInfo *transportInfo = new KMTransportInfo(); |
|
switch ( transportType ) { |
|
case 0: // smtp |
|
transportInfo->type = QString::fromLatin1("smtp"); |
|
break; |
|
case 1: // sendmail |
|
transportInfo->type = QString::fromLatin1("sendmail"); |
|
transportInfo->name = i18n("Sendmail"); |
|
transportInfo->host = _PATH_SENDMAIL; // ### FIXME: use const, not #define |
|
break; |
|
default: |
|
assert( 0 ); |
|
} |
|
|
|
KMTransportDialog dialog( i18n("Add Transport"), transportInfo, this ); |
|
|
|
// create list of names: |
|
// ### move behind dialog.exec()? |
|
QStringList transportNames; |
|
QPtrListIterator<KMTransportInfo> it( mTransportInfoList ); |
|
for ( it.toFirst() ; it.current() ; ++it ) |
|
transportNames << (*it)->name; |
|
|
|
if( dialog.exec() != QDialog::Accepted ) { |
|
delete transportInfo; |
|
return; |
|
} |
|
|
|
// disambiguate the name by appending a number: |
|
// ### FIXME: don't allow this error to happen in the first place! |
|
transportInfo->name = uniqueName( transportNames, transportInfo->name ); |
|
// append to names and transportinfo lists: |
|
transportNames << transportInfo->name; |
|
mTransportInfoList.append( transportInfo ); |
|
|
|
// append to listview: |
|
// ### FIXME: insert before the selected item, append on empty selection |
|
QListViewItem *lastItem = mTransportList->firstChild(); |
|
QString typeDisplayName; |
|
if ( lastItem ) |
|
while ( lastItem->nextSibling() ) |
|
lastItem = lastItem->nextSibling(); |
|
if ( lastItem ) |
|
typeDisplayName = transportInfo->type; |
|
else |
|
typeDisplayName = i18n("%1: type of transport. Result used in " |
|
"Configure->Network->Sending listview, \"type\" " |
|
"column, first row, to indicate that this is the " |
|
"default transport", "%1 (Default)") |
|
.arg( transportInfo->type ); |
|
(void) new QListViewItem( mTransportList, lastItem, transportInfo->name, |
|
typeDisplayName ); |
|
|
|
// notify anyone who cares: |
|
emit transportListChanged( transportNames ); |
|
emit changed( true ); |
|
} |
|
|
|
void NetworkPage::SendingTab::slotModifySelectedTransport() |
|
{ |
|
QListViewItem *item = mTransportList->selectedItem(); |
|
if ( !item ) return; |
|
|
|
QPtrListIterator<KMTransportInfo> it( mTransportInfoList ); |
|
for ( it.toFirst() ; it.current() ; ++it ) |
|
if ( (*it)->name == item->text(0) ) break; |
|
if ( !it.current() ) return; |
|
|
|
KMTransportDialog dialog( i18n("Modify Transport"), (*it), this ); |
|
|
|
if ( dialog.exec() != QDialog::Accepted ) return; |
|
|
|
// create the list of names of transports, but leave out the current |
|
// item: |
|
QStringList transportNames; |
|
QPtrListIterator<KMTransportInfo> jt( mTransportInfoList ); |
|
int entryLocation = -1; |
|
for ( jt.toFirst() ; jt.current() ; ++jt ) |
|
if ( jt != it ) |
|
transportNames << (*jt)->name; |
|
else |
|
entryLocation = transportNames.count(); |
|
assert( entryLocation >= 0 ); |
|
|
|
// make the new name unique by appending a high enough number: |
|
(*it)->name = uniqueName( transportNames, (*it)->name ); |
|
// change the list item to the new name |
|
item->setText( 0, (*it)->name ); |
|
// and insert the new name at the position of the old in the list of |
|
// strings; then broadcast the new list: |
|
transportNames.insert( transportNames.at( entryLocation ), (*it)->name ); |
|
emit transportListChanged( transportNames ); |
|
emit changed( true ); |
|
} |
|
|
|
|
|
void NetworkPage::SendingTab::slotRemoveSelectedTransport() |
|
{ |
|
QListViewItem *item = mTransportList->selectedItem(); |
|
if ( !item ) return; |
|
|
|
QPtrListIterator<KMTransportInfo> it( mTransportInfoList ); |
|
for ( it.toFirst() ; it.current() ; ++it ) |
|
if ( (*it)->name == item->text(0) ) break; |
|
if ( !it.current() ) return; |
|
|
|
QListViewItem *newCurrent = item->itemBelow(); |
|
if ( !newCurrent ) newCurrent = item->itemAbove(); |
|
//mTransportList->removeItem( item ); |
|
if ( newCurrent ) { |
|
mTransportList->setCurrentItem( newCurrent ); |
|
mTransportList->setSelected( newCurrent, true ); |
|
} |
|
|
|
delete item; |
|
mTransportInfoList.remove( it ); |
|
|
|
QStringList transportNames; |
|
for ( it.toFirst() ; it.current() ; ++it ) |
|
transportNames << (*it)->name; |
|
emit transportListChanged( transportNames ); |
|
emit changed( true ); |
|
} |
|
|
|
|
|
void NetworkPage::SendingTab::slotTransportUp() |
|
{ |
|
QListViewItem *item = mTransportList->selectedItem(); |
|
if ( !item ) return; |
|
QListViewItem *above = item->itemAbove(); |
|
if ( !above ) return; |
|
|
|
// swap in the transportInfo list: |
|
// ### FIXME: use value-based list. This is ugly. |
|
KMTransportInfo *ti, *ti2 = 0; |
|
int i = 0; |
|
for (ti = mTransportInfoList.first(); ti; |
|
ti2 = ti, ti = mTransportInfoList.next(), i++) |
|
if (ti->name == item->text(0)) break; |
|
if (!ti || !ti2) return; |
|
ti = mTransportInfoList.take(i); |
|
mTransportInfoList.insert(i-1, ti); |
|
|
|
// swap in the display |
|
item->setText(0, ti2->name); |
|
item->setText(1, ti2->type); |
|
above->setText(0, ti->name); |
|
if ( above->itemAbove() ) |
|
// not first: |
|
above->setText( 1, ti->type ); |
|
else |
|
// first: |
|
above->setText( 1, i18n("%1: type of transport. Result used in " |
|
"Configure->Network->Sending listview, \"type\" " |
|
"column, first row, to indicate that this is the " |
|
"default transport", "%1 (Default)") |
|
.arg( ti->type ) ); |
|
|
|
mTransportList->setCurrentItem( above ); |
|
mTransportList->setSelected( above, true ); |
|
emit changed( true ); |
|
} |
|
|
|
|
|
void NetworkPage::SendingTab::slotTransportDown() |
|
{ |
|
QListViewItem * item = mTransportList->selectedItem(); |
|
if ( !item ) return; |
|
QListViewItem * below = item->itemBelow(); |
|
if ( !below ) return; |
|
|
|
KMTransportInfo *ti, *ti2 = 0; |
|
int i = 0; |
|
for (ti = mTransportInfoList.first(); ti; |
|
ti = mTransportInfoList.next(), i++) |
|
if (ti->name == item->text(0)) break; |
|
ti2 = mTransportInfoList.next(); |
|
if (!ti || !ti2) return; |
|
ti = mTransportInfoList.take(i); |
|
mTransportInfoList.insert(i+1, ti); |
|
|
|
item->setText(0, ti2->name); |
|
below->setText(0, ti->name); |
|
below->setText(1, ti->type); |
|
if ( item->itemAbove() ) |
|
item->setText( 1, ti2->type ); |
|
else |
|
item->setText( 1, i18n("%1: type of transport. Result used in " |
|
"Configure->Network->Sending listview, \"type\" " |
|
"column, first row, to indicate that this is the " |
|
"default transport", "%1 (Default)") |
|
.arg( ti2->type ) ); |
|
|
|
|
|
mTransportList->setCurrentItem(below); |
|
mTransportList->setSelected(below, TRUE); |
|
emit changed( true ); |
|
} |
|
|
|
void NetworkPage::SendingTab::load() { |
|
KConfigGroup general( KMKernel::config(), "General"); |
|
KConfigGroup composer( KMKernel::config(), "Composer"); |
|
|
|
int numTransports = general.readNumEntry("transports", 0); |
|
|
|
QListViewItem *top = 0; |
|
mTransportInfoList.clear(); |
|
mTransportList->clear(); |
|
QStringList transportNames; |
|
for ( int i = 1 ; i <= numTransports ; i++ ) { |
|
KMTransportInfo *ti = new KMTransportInfo(); |
|
ti->readConfig(i); |
|
mTransportInfoList.append( ti ); |
|
transportNames << ti->name; |
|
top = new QListViewItem( mTransportList, top, ti->name, ti->type ); |
|
} |
|
emit transportListChanged( transportNames ); |
|
|
|
QListViewItem *listItem = mTransportList->firstChild(); |
|
if ( listItem ) { |
|
listItem->setText( 1, i18n("%1: type of transport. Result used in " |
|
"Configure->Network->Sending listview, " |
|
"\"type\" column, first row, to indicate " |
|
"that this is the default transport", |
|
"%1 (Default)").arg( listItem->text(1) ) ); |
|
mTransportList->setCurrentItem( listItem ); |
|
mTransportList->setSelected( listItem, true ); |
|
} |
|
|
|
mSendMethodCombo->setCurrentItem( |
|
kmkernel->msgSender()->sendImmediate() ? 0 : 1 ); |
|
mMessagePropertyCombo->setCurrentItem( |
|
kmkernel->msgSender()->sendQuotedPrintable() ? 1 : 0 ); |
|
mSendOutboxCheck->setChecked( general.readBoolEntry( "sendOnCheck", |
|
false ) ); |
|
|
|
mConfirmSendCheck->setChecked( composer.readBoolEntry( "confirm-before-send", |
|
false ) ); |
|
QString str = general.readEntry( "Default domain" ); |
|
if( str.isEmpty() ) |
|
{ |
|
//### FIXME: Use the global convenience function instead of the homebrewed |
|
// solution once we can rely on HEAD kdelibs. |
|
//str = KGlobal::hostname(); ??????? |
|
char buffer[256]; |
|
if ( !gethostname( buffer, 255 ) ) |
|
// buffer need not be NUL-terminated if it has full length |
|
buffer[255] = 0; |
|
else |
|
buffer[0] = 0; |
|
str = QString::fromLatin1( *buffer ? buffer : "localhost" ); |
|
} |
|
mDefaultDomainEdit->setText( str ); |
|
} |
|
|
|
|
|
void NetworkPage::SendingTab::save() { |
|
KConfigGroup general( KMKernel::config(), "General" ); |
|
KConfigGroup composer( KMKernel::config(), "Composer" ); |
|
|
|
// Save transports: |
|
general.writeEntry( "transports", mTransportInfoList.count() ); |
|
QPtrListIterator<KMTransportInfo> it( mTransportInfoList ); |
|
for ( int i = 1 ; it.current() ; ++it, ++i ) |
|
(*it)->writeConfig(i); |
|
|
|
// Save common options: |
|
general.writeEntry( "sendOnCheck", mSendOutboxCheck->isChecked() ); |
|
kmkernel->msgSender()->setSendImmediate( |
|
mSendMethodCombo->currentItem() == 0 ); |
|
kmkernel->msgSender()->setSendQuotedPrintable( |
|
mMessagePropertyCombo->currentItem() == 1 ); |
|
kmkernel->msgSender()->writeConfig( false ); // don't sync |
|
composer.writeEntry("confirm-before-send", mConfirmSendCheck->isChecked() ); |
|
general.writeEntry( "Default domain", mDefaultDomainEdit->text() ); |
|
} |
|
|
|
QString NetworkPage::ReceivingTab::helpAnchor() const { |
|
return QString::fromLatin1("configure-network-receiving"); |
|
} |
|
|
|
NetworkPageReceivingTab::NetworkPageReceivingTab( QWidget * parent, const char * name ) |
|
: ConfigModuleTab ( parent, name ) |
|
{ |
|
// temp. vars: |
|
QVBoxLayout *vlay; |
|
QVBoxLayout *btn_vlay; |
|
QHBoxLayout *hlay; |
|
QPushButton *button; |
|
QGroupBox *group; |
|
|
|
vlay = new QVBoxLayout( this, KDialog::marginHint(), KDialog::spacingHint() ); |
|
|
|
// label: zero stretch |
|
vlay->addWidget( new QLabel( i18n("Incoming accounts (add at least one):"), this ) ); |
|
|
|
// hbox layout: stretch 10, spacing inherited from vlay |
|
hlay = new QHBoxLayout(); |
|
vlay->addLayout( hlay, 10 ); // high stretch to suppress groupbox's growing |
|
|
|
// account list: left widget in hlay; stretch 1 |
|
mAccountList = new ListView( this, "accountList", 5 ); |
|
mAccountList->addColumn( i18n("Name") ); |
|
mAccountList->addColumn( i18n("Type") ); |
|
mAccountList->addColumn( i18n("Folder") ); |
|
mAccountList->setAllColumnsShowFocus( true ); |
|
mAccountList->setFrameStyle( QFrame::WinPanel + QFrame::Sunken ); |
|
mAccountList->setSorting( -1 ); |
|
connect( mAccountList, SIGNAL(selectionChanged()), |
|
this, SLOT(slotAccountSelected()) ); |
|
connect( mAccountList, SIGNAL(doubleClicked( QListViewItem *)), |
|
this, SLOT(slotModifySelectedAccount()) ); |
|
hlay->addWidget( mAccountList, 1 ); |
|
|
|
// a vbox layout for the buttons: zero stretch, spacing inherited from hlay |
|
btn_vlay = new QVBoxLayout( hlay ); |
|
|
|
// "add..." button: stretch 0 |
|
button = new QPushButton( i18n("A&dd..."), this ); |
|
button->setAutoDefault( false ); |
|
connect( button, SIGNAL(clicked()), |
|
this, SLOT(slotAddAccount()) ); |
|
btn_vlay->addWidget( button ); |
|
|
|
// "modify..." button: stretch 0 |
|
mModifyAccountButton = new QPushButton( i18n("&Modify..."), this ); |
|
mModifyAccountButton->setAutoDefault( false ); |
|
mModifyAccountButton->setEnabled( false ); // b/c no item is selected yet |
|
connect( mModifyAccountButton, SIGNAL(clicked()), |
|
this, SLOT(slotModifySelectedAccount()) ); |
|
btn_vlay->addWidget( mModifyAccountButton ); |
|
|
|
// "remove..." button: stretch 0 |
|
mRemoveAccountButton = new QPushButton( i18n("R&emove"), this ); |
|
mRemoveAccountButton->setAutoDefault( false ); |
|
mRemoveAccountButton->setEnabled( false ); // b/c no item is selected yet |
|
connect( mRemoveAccountButton, SIGNAL(clicked()), |
|
this, SLOT(slotRemoveSelectedAccount()) ); |
|
btn_vlay->addWidget( mRemoveAccountButton ); |
|
btn_vlay->addStretch( 1 ); // spacer |
|
|
|
mCheckmailStartupCheck = new QCheckBox( i18n("Chec&k mail on startup"), this ); |
|
vlay->addWidget( mCheckmailStartupCheck ); |
|
connect( mCheckmailStartupCheck, SIGNAL( stateChanged( int ) ), |
|
this, SLOT( slotEmitChanged( void ) ) ); |
|
|
|
// "New Mail Notification" group box: stretch 0 |
|
group = new QVGroupBox( i18n("New Mail Notification"), this ); |
|
vlay->addWidget( group ); |
|
group->layout()->setSpacing( KDialog::spacingHint() ); |
|
|
|
// "beep on new mail" check box: |
|
mBeepNewMailCheck = new QCheckBox(i18n("&Beep"), group ); |
|
mBeepNewMailCheck->setSizePolicy( QSizePolicy( QSizePolicy::MinimumExpanding, |
|
QSizePolicy::Fixed ) ); |
|
connect( mBeepNewMailCheck, SIGNAL( stateChanged( int ) ), |
|
this, SLOT( slotEmitChanged( void ) ) ); |
|
|
|
// "Detailed new mail notification" check box |
|
mVerboseNotificationCheck = |
|
new QCheckBox( i18n( "Deta&iled new mail notification" ), group ); |
|
mVerboseNotificationCheck->setSizePolicy( QSizePolicy( QSizePolicy::MinimumExpanding, |
|
QSizePolicy::Fixed ) ); |
|
QToolTip::add( mVerboseNotificationCheck, |
|
i18n( "Show for each folder the number of newly arrived " |
|
"messages" ) ); |
|
QWhatsThis::add( mVerboseNotificationCheck, |
|
GlobalSettings::self()->verboseNewMailNotificationItem()->whatsThis() ); |
|
connect( mVerboseNotificationCheck, SIGNAL( stateChanged( int ) ), |
|
this, SLOT( slotEmitChanged() ) ); |
|
|
|
// "Systray" notification check box |
|
mSystrayCheck = new QCheckBox( i18n("System &tray notification"), group ); |
|
connect( mSystrayCheck, SIGNAL( stateChanged( int ) ), |
|
this, SLOT( slotEmitChanged( void ) ) ); |
|
|
|
|
|
// System tray modes |
|
QButtonGroup *bgroup = new QButtonGroup(i18n("System Tray Modes"), group); |
|
bgroup->setColumnLayout(0, Qt::Horizontal); |
|
bgroup->layout()->setSpacing( 0 ); |
|
bgroup->layout()->setMargin( 0 ); |
|
QGridLayout *bgroupLayout = new QGridLayout( bgroup->layout() ); |
|
bgroupLayout->setAlignment( Qt::AlignTop ); |
|
bgroupLayout->setSpacing( 6 ); |
|
bgroupLayout->setMargin( 11 ); |
|
|
|
mBlinkingSystray = new QRadioButton( i18n("Alwa&ys show system tray"), bgroup); |
|
bgroupLayout->addWidget(mBlinkingSystray, 0, 0); |
|
connect( mBlinkingSystray, SIGNAL( stateChanged( int ) ), |
|
this, SLOT( slotEmitChanged( void ) ) ); |
|
|
|
mSystrayOnNew = new QRadioButton( i18n("Sho&w system tray on new mail"), bgroup); |
|
connect( mSystrayOnNew, SIGNAL( stateChanged( int ) ), |
|
this, SLOT( slotEmitChanged( void ) ) ); |
|
|
|
bgroupLayout->addWidget(mSystrayOnNew, 0, 1); |
|
|
|
bgroup->setEnabled( false ); // since !mSystrayCheck->isChecked() |
|
connect( mSystrayCheck, SIGNAL(toggled(bool)), |
|
bgroup, SLOT(setEnabled(bool)) ); |
|
|
|
// "display message box" check box: |
|
mOtherNewMailActionsButton = new QPushButton( i18n("Other Actio&ns"), group ); |
|
mOtherNewMailActionsButton->setSizePolicy( QSizePolicy( QSizePolicy::Fixed, |
|
QSizePolicy::Fixed ) ); |
|
connect( mOtherNewMailActionsButton, SIGNAL(clicked()), |
|
this, SLOT(slotEditNotifications()) ); |
|
} |
|
|
|
|
|
void NetworkPage::ReceivingTab::slotAccountSelected() |
|
{ |
|
QListViewItem * item = mAccountList->selectedItem(); |
|
mModifyAccountButton->setEnabled( item ); |
|
mRemoveAccountButton->setEnabled( item ); |
|
} |
|
|
|
QStringList NetworkPage::ReceivingTab::occupiedNames() |
|
{ |
|
QStringList accountNames = kmkernel->acctMgr()->getAccounts(); |
|
|
|
QValueList<ModifiedAccountsType*>::Iterator k; |
|
for (k = mModifiedAccounts.begin(); k != mModifiedAccounts.end(); ++k ) |
|
if ((*k)->oldAccount) |
|
accountNames.remove( (*k)->oldAccount->name() ); |
|
|
|
QValueList< QGuardedPtr<KMAccount> >::Iterator l; |
|
for (l = mAccountsToDelete.begin(); l != mAccountsToDelete.end(); ++l ) |
|
if (*l) |
|
accountNames.remove( (*l)->name() ); |
|
|
|
QValueList< QGuardedPtr<KMAccount> >::Iterator it; |
|
for (it = mNewAccounts.begin(); it != mNewAccounts.end(); ++it ) |
|
if (*it) |
|
accountNames += (*it)->name(); |
|
|
|
QValueList<ModifiedAccountsType*>::Iterator j; |
|
for (j = mModifiedAccounts.begin(); j != mModifiedAccounts.end(); ++j ) |
|
accountNames += (*j)->newAccount->name(); |
|
|
|
return accountNames; |
|
} |
|
|
|
void NetworkPage::ReceivingTab::slotAddAccount() { |
|
KMAcctSelDlg accountSelectorDialog( this ); |
|
if( accountSelectorDialog.exec() != QDialog::Accepted ) return; |
|
|
|
const char *accountType = 0; |
|
switch ( accountSelectorDialog.selected() ) { |
|
case 0: accountType = "local"; break; |
|
case 1: accountType = "pop"; break; |
|
case 2: accountType = "imap"; break; |
|
case 3: accountType = "cachedimap"; break; |
|
case 4: accountType = "maildir"; break; |
|
|
|
default: |
|
// ### FIXME: How should this happen??? |
|
// replace with assert. |
|
KMessageBox::sorry( this, i18n("Unknown account type selected") ); |
|
return; |
|
} |
|
|
|
KMAccount *account |
|
= kmkernel->acctMgr()->create( QString::fromLatin1( accountType ), |
|
i18n("Unnamed") ); |
|
if ( !account ) { |
|
// ### FIXME: Give the user more information. Is this error |
|
// recoverable? |
|
KMessageBox::sorry( this, i18n("Unable to create account") ); |
|
return; |
|
} |
|
|
|
account->init(); // fill the account fields with good default values |
|
|
|
AccountDialog dialog( i18n("Add account"), account, this ); |
|
|
|
QStringList accountNames = occupiedNames(); |
|
|
|
if( dialog.exec() != QDialog::Accepted ) { |
|
delete account; |
|
return; |
|
} |
|
|
|
account->setName( uniqueName( accountNames, account->name() ) ); |
|
|
|
QListViewItem *after = mAccountList->firstChild(); |
|
while ( after && after->nextSibling() ) |
|
after = after->nextSibling(); |
|
|
|
QListViewItem *listItem = |
|
new QListViewItem( mAccountList, after, account->name(), account->type() ); |
|
if( account->folder() ) |
|
listItem->setText( 2, account->folder()->label() ); |
|
|
|
mNewAccounts.append( account ); |
|
emit changed( true ); |
|
} |
|
|
|
|
|
|
|
void NetworkPage::ReceivingTab::slotModifySelectedAccount() |
|
{ |
|
QListViewItem *listItem = mAccountList->selectedItem(); |
|
if( !listItem ) return; |
|
|
|
KMAccount *account = 0; |
|
QValueList<ModifiedAccountsType*>::Iterator j; |
|
for (j = mModifiedAccounts.begin(); j != mModifiedAccounts.end(); ++j ) |
|
if ( (*j)->newAccount->name() == listItem->text(0) ) { |
|
account = (*j)->newAccount; |
|
break; |
|
} |
|
|
|
if ( !account ) { |
|
QValueList< QGuardedPtr<KMAccount> >::Iterator it; |
|
for ( it = mNewAccounts.begin() ; it != mNewAccounts.end() ; ++it ) |
|
if ( (*it)->name() == listItem->text(0) ) { |
|
account = *it; |
|
break; |
|
} |
|
|
|
if ( !account ) { |
|
account = kmkernel->acctMgr()->findByName( listItem->text(0) ); |
|
if( !account ) { |
|
// ### FIXME: How should this happen? See above. |
|
KMessageBox::sorry( this, i18n("Unable to locate account") ); |
|
return; |
|
} |
|
|
|
ModifiedAccountsType *mod = new ModifiedAccountsType; |
|
mod->oldAccount = account; |
|
mod->newAccount = kmkernel->acctMgr()->create( account->type(), |
|
account->name() ); |
|
mod->newAccount->pseudoAssign( account ); |
|
mModifiedAccounts.append( mod ); |
|
account = mod->newAccount; |
|
} |
|
|
|
if( !account ) { |
|
// ### FIXME: See above. |
|
KMessageBox::sorry( this, i18n("Unable to locate account") ); |
|
return; |
|
} |
|
} |
|
|
|
QStringList accountNames = occupiedNames(); |
|
accountNames.remove( account->name() ); |
|
|
|
AccountDialog dialog( i18n("Modify Account"), account, this ); |
|
|
|
if( dialog.exec() != QDialog::Accepted ) return; |
|
|
|
account->setName( uniqueName( accountNames, account->name() ) ); |
|
|
|
listItem->setText( 0, account->name() ); |
|
listItem->setText( 1, account->type() ); |
|
if( account->folder() ) |
|
listItem->setText( 2, account->folder()->label() ); |
|
|
|
emit changed( true ); |
|
} |
|
|
|
|
|
|
|
void NetworkPage::ReceivingTab::slotRemoveSelectedAccount() { |
|
QListViewItem *listItem = mAccountList->selectedItem(); |
|
if( !listItem ) return; |
|
|
|
KMAccount *acct = 0; |
|
QValueList<ModifiedAccountsType*>::Iterator j; |
|
for ( j = mModifiedAccounts.begin() ; j != mModifiedAccounts.end() ; ++j ) |
|
if ( (*j)->newAccount->name() == listItem->text(0) ) { |
|
acct = (*j)->oldAccount; |
|
mAccountsToDelete.append( acct ); |
|
mModifiedAccounts.remove( j ); |
|
break; |
|
} |
|
if ( !acct ) { |
|
QValueList< QGuardedPtr<KMAccount> >::Iterator it; |
|
for ( it = mNewAccounts.begin() ; it != mNewAccounts.end() ; ++it ) |
|
if ( (*it)->name() == listItem->text(0) ) { |
|
acct = *it; |
|
mNewAccounts.remove( it ); |
|
break; |
|
} |
|
} |
|
if ( !acct ) { |
|
acct = kmkernel->acctMgr()->findByName( listItem->text(0) ); |
|
if ( acct ) |
|
mAccountsToDelete.append( acct ); |
|
} |
|
if ( !acct ) { |
|
// ### FIXME: see above |
|
KMessageBox::sorry( this, i18n("<qt>Unable to locate account <b>%1</b>.</qt>") |
|
.arg(listItem->text(0)) ); |
|
return; |
|
} |
|
|
|
QListViewItem * item = listItem->itemBelow(); |
|
if ( !item ) item = listItem->itemAbove(); |
|
delete listItem; |
|
|
|
if ( item ) |
|
mAccountList->setSelected( item, true ); |
|
|
|
emit changed( true ); |
|
} |
|
|
|
void NetworkPage::ReceivingTab::slotEditNotifications() |
|
{ |
|
if(kmkernel->xmlGuiInstance()) |
|
KNotifyDialog::configure(this, 0, kmkernel->xmlGuiInstance()->aboutData()); |
|
else |
|
KNotifyDialog::configure(this); |
|
} |
|
|
|
void NetworkPage::ReceivingTab::load() { |
|
KConfigGroup general( KMKernel::config(), "General" ); |
|
|
|
mAccountList->clear(); |
|
QListViewItem *top = 0; |
|
for( KMAccount *a = kmkernel->acctMgr()->first(); a!=0; |
|
a = kmkernel->acctMgr()->next() ) { |
|
QListViewItem *listItem = |
|
new QListViewItem( mAccountList, top, a->name(), a->type() ); |
|
if( a->folder() ) |
|
listItem->setText( 2, a->folder()->label() ); |
|
top = listItem; |
|
} |
|
|
|
QListViewItem *listItem = mAccountList->firstChild(); |
|
if ( listItem ) { |
|
mAccountList->setCurrentItem( listItem ); |
|
mAccountList->setSelected( listItem, true ); |
|
} |
|
|
|
mBeepNewMailCheck->setChecked( general.readBoolEntry("beep-on-mail", false ) ); |
|
mVerboseNotificationCheck->setChecked( GlobalSettings::verboseNewMailNotification() ); |
|
mSystrayCheck->setChecked( general.readBoolEntry("systray-on-mail", false) ); |
|
mBlinkingSystray->setChecked( !general.readBoolEntry("systray-on-new", true) ); |
|
mSystrayOnNew->setChecked( general.readBoolEntry("systray-on-new", true) ); |
|
mCheckmailStartupCheck->setChecked( general.readBoolEntry("checkmail-startup", false) ); |
|
} |
|
|
|
void NetworkPage::ReceivingTab::save() { |
|
// Add accounts marked as new |
|
QValueList< QGuardedPtr<KMAccount> > newCachedImapAccounts; |
|
QValueList< QGuardedPtr<KMAccount> >::Iterator it; |
|
for (it = mNewAccounts.begin(); it != mNewAccounts.end(); ++it ) { |
|
kmkernel->acctMgr()->add( *it ); |
|
// remember new Disconnected IMAP accounts because they are needed again |
|
if( (*it)->isA( "KMAcctCachedImap" ) ) { |
|
newCachedImapAccounts.append( *it ); |
|
} |
|
} |
|
|
|
mNewAccounts.clear(); |
|
|
|
// Update accounts that have been modified |
|
QValueList<ModifiedAccountsType*>::Iterator j; |
|
for ( j = mModifiedAccounts.begin() ; j != mModifiedAccounts.end() ; ++j ) { |
|
(*j)->oldAccount->pseudoAssign( (*j)->newAccount ); |
|
delete (*j)->newAccount; |
|
delete (*j); |
|
} |
|
mModifiedAccounts.clear(); |
|
|
|
// Delete accounts marked for deletion |
|
for ( it = mAccountsToDelete.begin() ; |
|
it != mAccountsToDelete.end() ; ++it ) { |
|
kmkernel->acctMgr()->writeConfig( true ); |
|
if ( (*it) && !kmkernel->acctMgr()->remove(*it) ) |
|
KMessageBox::sorry( this, i18n("<qt>Unable to locate account <b>%1</b>.</qt>") |
|
.arg( (*it)->name() ) ); |
|
} |
|
mAccountsToDelete.clear(); |
|
|
|
// Incoming mail |
|
kmkernel->acctMgr()->writeConfig( false ); |
|
kmkernel->cleanupImapFolders(); |
|
|
|
// Save Mail notification settings |
|
KConfigGroup general( KMKernel::config(), "General" ); |
|
general.writeEntry( "beep-on-mail", mBeepNewMailCheck->isChecked() ); |
|
GlobalSettings::setVerboseNewMailNotification( mVerboseNotificationCheck->isChecked() ); |
|
general.writeEntry( "systray-on-mail", mSystrayCheck->isChecked() ); |
|
general.writeEntry( "systray-on-new", mSystrayOnNew->isChecked() ); |
|
|
|
general.writeEntry( "checkmail-startup", mCheckmailStartupCheck->isChecked() ); |
|
|
|
// Sync new IMAP accounts ASAP: |
|
for (it = newCachedImapAccounts.begin(); it != newCachedImapAccounts.end(); ++it ) { |
|
KMAccount *acc = (*it); |
|
if ( !acc->checkingMail() ) { |
|
acc->setCheckingMail( true ); |
|
acc->processNewMail(false); |
|
} |
|
} |
|
} |
|
|
|
// ************************************************************* |
|
// * * |
|
// * AppearancePage * |
|
// * * |
|
// ************************************************************* |
|
QString AppearancePage::helpAnchor() const { |
|
return QString::fromLatin1("configure-appearance"); |
|
} |
|
|
|
AppearancePage::AppearancePage( QWidget * parent, const char * name ) |
|
: ConfigModuleWithTabs( parent, name ) |
|
{ |
|
// |
|
// "Fonts" tab: |
|
// |
|
mFontsTab = new FontsTab(); |
|
addTab( mFontsTab, i18n("&Fonts") ); |
|
|
|
// |
|
// "Colors" tab: |
|
// |
|
mColorsTab = new ColorsTab(); |
|
addTab( mColorsTab, i18n("Color&s") ); |
|
|
|
// |
|
// "Layout" tab: |
|
// |
|
mLayoutTab = new LayoutTab(); |
|
addTab( mLayoutTab, i18n("La&yout") ); |
|
|
|
// |
|
// "Headers" tab: |
|
// |
|
mHeadersTab = new HeadersTab(); |
|
addTab( mHeadersTab, i18n("H&eaders") ); |
|
load(); |
|
} |
|
|
|
|
|
QString AppearancePage::FontsTab::helpAnchor() const { |
|
return QString::fromLatin1("configure-appearance-fonts"); |
|
} |
|
|
|
static const struct { |
|
const char * configName; |
|
const char * displayName; |
|
bool enableFamilyAndSize; |
|
bool onlyFixed; |
|
} fontNames[] = { |
|
{ "body-font", I18N_NOOP("Message Body"), true, false }, |
|
{ "list-font", I18N_NOOP("Message List"), true, false }, |
|
{ "list-date-font", I18N_NOOP("Message List - Date Field"), true, false }, |
|
{ "folder-font", I18N_NOOP("Folder List"), true, false }, |
|
{ "quote1-font", I18N_NOOP("Quoted Text - First Level"), false, false }, |
|
{ "quote2-font", I18N_NOOP("Quoted Text - Second Level"), false, false }, |
|
{ "quote3-font", I18N_NOOP("Quoted Text - Third Level"), false, false }, |
|
{ "fixed-font", I18N_NOOP("Fixed Width Font"), true, true }, |
|
{ "composer-font", I18N_NOOP("Composer"), true, false }, |
|
{ "print-font", I18N_NOOP("Printing Output"), true, false }, |
|
}; |
|
static const int numFontNames = sizeof fontNames / sizeof *fontNames; |
|
|
|
AppearancePageFontsTab::AppearancePageFontsTab( QWidget * parent, const char * name ) |
|
: ConfigModuleTab( parent, name ), mActiveFontIndex( -1 ) |
|
{ |
|
assert( numFontNames == sizeof mFont / sizeof *mFont ); |
|
// tmp. vars: |
|
QVBoxLayout *vlay; |
|
QHBoxLayout *hlay; |
|
QLabel *label; |
|
|
|
// "Use custom fonts" checkbox, followed by <hr> |
|
vlay = new QVBoxLayout( this, KDialog::marginHint(), KDialog::spacingHint() ); |
|
mCustomFontCheck = new QCheckBox( i18n("&Use custom fonts"), this ); |
|
vlay->addWidget( mCustomFontCheck ); |
|
vlay->addWidget( new KSeparator( KSeparator::HLine, this ) ); |
|
connect ( mCustomFontCheck, SIGNAL( stateChanged( int ) ), |
|
this, SLOT( slotEmitChanged( void ) ) ); |
|
|
|
// "font location" combo box and label: |
|
hlay = new QHBoxLayout( vlay ); // inherites spacing |
|
mFontLocationCombo = new QComboBox( false, this ); |
|
mFontLocationCombo->setEnabled( false ); // !mCustomFontCheck->isChecked() |
|
|
|
QStringList fontDescriptions; |
|
for ( int i = 0 ; i < numFontNames ; i++ ) |
|
fontDescriptions << i18n( fontNames[i].displayName ); |
|
mFontLocationCombo->insertStringList( fontDescriptions ); |
|
|
|
label = new QLabel( mFontLocationCombo, i18n("Apply &to:"), this ); |
|
label->setEnabled( false ); // since !mCustomFontCheck->isChecked() |
|
hlay->addWidget( label ); |
|
|
|
hlay->addWidget( mFontLocationCombo ); |
|
hlay->addStretch( 10 ); |
|
vlay->addSpacing( KDialog::spacingHint() ); |
|
mFontChooser = new KFontChooser( this, "font", false, QStringList(), |
|
false, 4 ); |
|
mFontChooser->setEnabled( false ); // since !mCustomFontCheck->isChecked() |
|
vlay->addWidget( mFontChooser ); |
|
connect ( mFontChooser, SIGNAL( fontSelected( const QFont& ) ), |
|
this, SLOT( slotEmitChanged( void ) ) ); |
|
|
|
|
|
// {en,dis}able widgets depending on the state of mCustomFontCheck: |
|
connect( mCustomFontCheck, SIGNAL(toggled(bool)), |
|
label, SLOT(setEnabled(bool)) ); |
|
connect( mCustomFontCheck, SIGNAL(toggled(bool)), |
|
mFontLocationCombo, SLOT(setEnabled(bool)) ); |
|
connect( mCustomFontCheck, SIGNAL(toggled(bool)), |
|
mFontChooser, SLOT(setEnabled(bool)) ); |
|
// load the right font settings into mFontChooser: |
|
connect( mFontLocationCombo, SIGNAL(activated(int) ), |
|
this, SLOT(slotFontSelectorChanged(int)) ); |
|
} |
|
|
|
|
|
void AppearancePage::FontsTab::slotFontSelectorChanged( int index ) |
|
{ |
|
kdDebug(5006) << "slotFontSelectorChanged() called" << endl; |
|
if( index < 0 || index >= mFontLocationCombo->count() ) |
|
return; // Should never happen, but it is better to check. |
|
|
|
// Save current fontselector setting before we install the new: |
|
if( mActiveFontIndex == 0 ) { |
|
mFont[0] = mFontChooser->font(); |
|
// hardcode the family and size of "message body" dependant fonts: |
|
for ( int i = 0 ; i < numFontNames ; i++ ) |
|
if ( !fontNames[i].enableFamilyAndSize ) { |
|
// ### shall we copy the font and set the save and re-set |
|
// {regular,italic,bold,bold italic} property or should we |
|
// copy only family and pointSize? |
|
mFont[i].setFamily( mFont[0].family() ); |
|
mFont[i].setPointSize/*Float?*/( mFont[0].pointSize/*Float?*/() ); |
|
} |
|
} else if ( mActiveFontIndex > 0 ) |
|
mFont[ mActiveFontIndex ] = mFontChooser->font(); |
|
mActiveFontIndex = index; |
|
|
|
// Disonnect so the "Apply" button is not activated by the change |
|
disconnect ( mFontChooser, SIGNAL( fontSelected( const QFont& ) ), |
|
this, SLOT( slotEmitChanged( void ) ) ); |
|
|
|
// Display the new setting: |
|
mFontChooser->setFont( mFont[index], fontNames[index].onlyFixed ); |
|
|
|
connect ( mFontChooser, SIGNAL( fontSelected( const QFont& ) ), |
|
this, SLOT( slotEmitChanged( void ) ) ); |
|
|
|
// Disable Family and Size list if we have selected a quote font: |
|
mFontChooser->enableColumn( KFontChooser::FamilyList|KFontChooser::SizeList, |
|
fontNames[ index ].enableFamilyAndSize ); |
|
} |
|
|
|
void AppearancePage::FontsTab::load() { |
|
KConfigGroup fonts( KMKernel::config(), "Fonts" ); |
|
|
|
mFont[0] = KGlobalSettings::generalFont(); |
|
QFont fixedFont = KGlobalSettings::fixedFont(); |
|
for ( int i = 0 ; i < numFontNames ; i++ ) |
|
mFont[i] = fonts.readFontEntry( fontNames[i].configName, |
|
(fontNames[i].onlyFixed) ? &fixedFont : &mFont[0] ); |
|
|
|
mCustomFontCheck->setChecked( !fonts.readBoolEntry( "defaultFonts", true ) ); |
|
mFontLocationCombo->setCurrentItem( 0 ); |
|
slotFontSelectorChanged( 0 ); |
|
} |
|
|
|
void AppearancePage::FontsTab::installProfile( KConfig * profile ) { |
|
KConfigGroup fonts( profile, "Fonts" ); |
|
|
|
// read fonts that are defined in the profile: |
|
bool needChange = false; |
|
for ( int i = 0 ; i < numFontNames ; i++ ) |
|
if ( fonts.hasKey( fontNames[i].configName ) ) { |
|
needChange = true; |
|
mFont[i] = fonts.readFontEntry( fontNames[i].configName ); |
|
kdDebug(5006) << "got font \"" << fontNames[i].configName |
|
<< "\" thusly: \"" << mFont[i].toString() << "\"" << endl; |
|
} |
|
if ( needChange && mFontLocationCombo->currentItem() > 0 ) |
|
mFontChooser->setFont( mFont[ mFontLocationCombo->currentItem() ], |
|
fontNames[ mFontLocationCombo->currentItem() ].onlyFixed ); |
|
|
|
if ( fonts.hasKey( "defaultFonts" ) ) |
|
mCustomFontCheck->setChecked( !fonts.readBoolEntry( "defaultFonts" ) ); |
|
} |
|
|
|
void AppearancePage::FontsTab::save() { |
|
KConfigGroup fonts( KMKernel::config(), "Fonts" ); |
|
|
|
// read the current font (might have been modified) |
|
if ( mActiveFontIndex >= 0 ) |
|
mFont[ mActiveFontIndex ] = mFontChooser->font(); |
|
|
|
bool customFonts = mCustomFontCheck->isChecked(); |
|
fonts.writeEntry( "defaultFonts", !customFonts ); |
|
for ( int i = 0 ; i < numFontNames ; i++ ) |
|
if ( customFonts || fonts.hasKey( fontNames[i].configName ) ) |
|
// Don't write font info when we use default fonts, but write |
|
// if it's already there: |
|
fonts.writeEntry( fontNames[i].configName, mFont[i] ); |
|
} |
|
|
|
QString AppearancePage::ColorsTab::helpAnchor() const { |
|
return QString::fromLatin1("configure-appearance-colors"); |
|
} |
|
|
|
|
|
static const struct { |
|
const char * configName; |
|
const char * displayName; |
|
} colorNames[] = { // adjust setup() if you change this: |
|
{ "BackgroundColor", I18N_NOOP("Composer background") }, |
|
{ "AltBackgroundColor", I18N_NOOP("Alternative background color") }, |
|
{ "ForegroundColor", I18N_NOOP("Normal text") }, |
|
{ "QuotedText1", I18N_NOOP("Quoted text - first level") }, |
|
{ "QuotedText2", I18N_NOOP("Quoted text - second level") }, |
|
{ "QuotedText3", I18N_NOOP("Quoted text - third level") }, |
|
{ "LinkColor", I18N_NOOP("Link") }, |
|
{ "FollowedColor", I18N_NOOP("Followed link") }, |
|
{ "MisspelledColor", I18N_NOOP("Misspelled words") }, |
|
{ "NewMessage", I18N_NOOP("New message") }, |
|
{ "UnreadMessage", I18N_NOOP("Unread message") }, |
|
{ "FlagMessage", I18N_NOOP("Important message") }, |
|
{ "PGPMessageEncr", I18N_NOOP("OpenPGP message - encrypted") }, |
|
{ "PGPMessageOkKeyOk", I18N_NOOP("OpenPGP message - valid signature with trusted key") }, |
|
{ "PGPMessageOkKeyBad", I18N_NOOP("OpenPGP message - valid signature with untrusted key") }, |
|
{ "PGPMessageWarn", I18N_NOOP("OpenPGP message - unchecked signature") }, |
|
{ "PGPMessageErr", I18N_NOOP("OpenPGP message - bad signature") }, |
|
{ "HTMLWarningColor", I18N_NOOP("Border around warning prepending HTML messages") }, |
|
{ "ColorbarBackgroundPlain", I18N_NOOP("HTML status bar background - No HTML message") }, |
|
{ "ColorbarForegroundPlain", I18N_NOOP("HTML status bar foreground - No HTML message") }, |
|
{ "ColorbarBackgroundHTML", I18N_NOOP("HTML status bar background - HTML message") }, |
|
{ "ColorbarForegroundHTML", I18N_NOOP("HTML status bar foreground - HTML message") }, |
|
}; |
|
static const int numColorNames = sizeof colorNames / sizeof *colorNames; |
|
|
|
AppearancePageColorsTab::AppearancePageColorsTab( QWidget * parent, const char * name ) |
|
: ConfigModuleTab( parent, name ) |
|
{ |
|
// tmp. vars: |
|
QVBoxLayout *vlay; |
|
|
|
// "use custom colors" check box |
|
vlay = new QVBoxLayout( this, KDialog::marginHint(), KDialog::spacingHint() ); |
|
mCustomColorCheck = new QCheckBox( i18n("&Use custom colors"), this ); |
|
vlay->addWidget( mCustomColorCheck ); |
|
connect( mCustomColorCheck, SIGNAL( stateChanged( int ) ), |
|
this, SLOT( slotEmitChanged( void ) ) ); |
|
|
|
// color list box: |
|
mColorList = new ColorListBox( this ); |
|
mColorList->setEnabled( false ); // since !mCustomColorCheck->isChecked() |
|
QStringList modeList; |
|
for ( int i = 0 ; i < numColorNames ; i++ ) |
|
mColorList->insertItem( new ColorListItem( i18n( colorNames[i].displayName ) ) ); |
|
vlay->addWidget( mColorList, 1 ); |
|
|
|
// "recycle colors" check box: |
|
mRecycleColorCheck = |
|
new QCheckBox( i18n("Recycle colors on deep "ing"), this ); |
|
mRecycleColorCheck->setEnabled( false ); |
|
vlay->addWidget( mRecycleColorCheck ); |
|
connect( mRecycleColorCheck, SIGNAL( stateChanged( int ) ), |
|
this, SLOT( slotEmitChanged( void ) ) ); |
|
|
|
// {en,dir}able widgets depending on the state of mCustomColorCheck: |
|
connect( mCustomColorCheck, SIGNAL(toggled(bool)), |
|
mColorList, SLOT(setEnabled(bool)) ); |
|
connect( mCustomColorCheck, SIGNAL(toggled(bool)), |
|
mRecycleColorCheck, SLOT(setEnabled(bool)) ); |
|
connect( mCustomColorCheck, SIGNAL( stateChanged( int ) ), |
|
this, SLOT( slotEmitChanged( void ) ) ); |
|
} |
|
|
|
void AppearancePage::ColorsTab::load() { |
|
KConfigGroup reader( KMKernel::config(), "Reader" ); |
|
|
|
mCustomColorCheck->setChecked( !reader.readBoolEntry( "defaultColors", true ) ); |
|
mRecycleColorCheck->setChecked( reader.readBoolEntry( "RecycleQuoteColors", false ) ); |
|
|
|
static const QColor defaultColor[ numColorNames ] = { |
|
kapp->palette().active().base(), // bg |
|
KGlobalSettings::alternateBackgroundColor(), // alt bg |
|
kapp->palette().active().text(), // fg |
|
QColor( 0x00, 0x80, 0x00 ), // quoted l1 |
|
QColor( 0x00, 0x70, 0x00 ), // quoted l2 |
|
QColor( 0x00, 0x60, 0x00 ), // quoted l3 |
|
KGlobalSettings::linkColor(), // link |
|
KGlobalSettings::visitedLinkColor(), // visited link |
|
Qt::red, // misspelled words |
|
Qt::red, // new msg |
|
Qt::blue, // unread mgs |
|
QColor( 0x00, 0x7F, 0x00 ), // important msg |
|
QColor( 0x00, 0x80, 0xFF ), // light blue // pgp encrypted |
|
QColor( 0x40, 0xFF, 0x40 ), // light green // pgp ok, trusted key |
|
QColor( 0xFF, 0xFF, 0x40 ), // light yellow // pgp ok, untrusted key |
|
QColor( 0xFF, 0xFF, 0x40 ), // light yellow // pgp unchk |
|
Qt::red, // pgp bad |
|
QColor( 0xFF, 0x40, 0x40 ), // warning text color: light red |
|
Qt::lightGray, // colorbar plain bg |
|
Qt::black, // colorbar plain fg |
|
Qt::black, // colorbar html bg |
|
Qt::white, // colorbar html fg |
|
}; |
|
|
|
for ( int i = 0 ; i < numColorNames ; i++ ) |
|
mColorList->setColor( i, |
|
reader.readColorEntry( colorNames[i].configName, &defaultColor[i] ) ); |
|
connect( mColorList, SIGNAL( changed( ) ), |
|
this, SLOT( slotEmitChanged( void ) ) ); |
|
} |
|
|
|
void AppearancePage::ColorsTab::installProfile( KConfig * profile ) { |
|
KConfigGroup reader( profile, "Reader" ); |
|
|
|
if ( reader.hasKey( "defaultColors" ) ) |
|
mCustomColorCheck->setChecked( !reader.readBoolEntry( "defaultColors" ) ); |
|
if ( reader.hasKey( "RecycleQuoteColors" ) ) |
|
mRecycleColorCheck->setChecked( reader.readBoolEntry( "RecycleQuoteColors" ) ); |
|
|
|
for ( int i = 0 ; i < numColorNames ; i++ ) |
|
if ( reader.hasKey( colorNames[i].configName ) ) |
|
mColorList->setColor( i, reader.readColorEntry( colorNames[i].configName ) ); |
|
} |
|
|
|
void AppearancePage::ColorsTab::save() { |
|
KConfigGroup reader( KMKernel::config(), "Reader" ); |
|
|
|
bool customColors = mCustomColorCheck->isChecked(); |
|
reader.writeEntry( "defaultColors", !customColors ); |
|
|
|
for ( int i = 0 ; i < numColorNames ; i++ ) |
|
// Don't write color info when we use default colors, but write |
|
// if it's already there: |
|
if ( customColors || reader.hasKey( colorNames[i].configName ) ) |
|
reader.writeEntry( colorNames[i].configName, mColorList->color(i) ); |
|
|
|
reader.writeEntry( "RecycleQuoteColors", mRecycleColorCheck->isChecked() ); |
|
} |
|
|
|
QString AppearancePage::LayoutTab::helpAnchor() const { |
|
return QString::fromLatin1("configure-appearance-layout"); |
|
} |
|
|
|
static const EnumConfigEntryItem folderListModes[] = { |
|
{ "long", I18N_NOOP("Lon&g folder list") }, |
|
{ "short", I18N_NOOP("Shor&t folder list" ) } |
|
}; |
|
static const EnumConfigEntry folderListMode = { |
|
"Geometry", "FolderList", I18N_NOOP("Folder List"), |
|
folderListModes, DIM(folderListModes), 0 |
|
}; |
|
|
|
|
|
static const EnumConfigEntryItem mimeTreeLocations[] = { |
|
{ "top", I18N_NOOP("Abo&ve the message pane") }, |
|
{ "bottom", I18N_NOOP("&Below the message pane") } |
|
}; |
|
static const EnumConfigEntry mimeTreeLocation = { |
|
"Reader", "MimeTreeLocation", I18N_NOOP("Message Structure Viewer Placement"), |
|
mimeTreeLocations, DIM(mimeTreeLocations), 1 |
|
}; |
|
|
|
static const EnumConfigEntryItem mimeTreeModes[] = { |
|
{ "never", I18N_NOOP("Show &never") }, |
|
{ "smart", I18N_NOOP("Show only for non-plaintext &messages") }, |
|
{ "always", I18N_NOOP("Show alway&s") } |
|
}; |
|
static const EnumConfigEntry mimeTreeMode = { |
|
"Reader", "MimeTreeMode", I18N_NOOP("Message Structure Viewer"), |
|
mimeTreeModes, DIM(mimeTreeModes), 1 |
|
}; |
|
|
|
|
|
static const EnumConfigEntryItem readerWindowModes[] = { |
|
{ "hide", I18N_NOOP("&Do not show a message preview pane") }, |
|
{ "below", I18N_NOOP("Show the message preview pane belo&w the message list") }, |
|
{ "right", I18N_NOOP("Show the message preview pane ne&xt to the message list") } |
|
}; |
|
static const EnumConfigEntry readerWindowMode = { |
|
"Geometry", "readerWindowMode", I18N_NOOP("Message Preview Pane"), |
|
readerWindowModes, DIM(readerWindowModes), 1 |
|
}; |
|
|
|
static const BoolConfigEntry showColorbarMode = { |
|
"Reader", "showColorbar", I18N_NOOP("Show HTML stat&us bar"), false |
|
}; |
|
|
|
AppearancePageLayoutTab::AppearancePageLayoutTab( QWidget * parent, const char * name ) |
|
: ConfigModuleTab( parent, name ) |
|
{ |
|
// tmp. vars: |
|
QVBoxLayout * vlay; |
|
|
|
vlay = new QVBoxLayout( this, KDialog::marginHint(), KDialog::spacingHint() ); |
|
|
|
// "show colorbar" check box: |
|
populateCheckBox( mShowColorbarCheck = new QCheckBox( this ), showColorbarMode ); |
|
vlay->addWidget( mShowColorbarCheck ); |
|
connect( mShowColorbarCheck, SIGNAL ( stateChanged( int ) ), |
|
this, SLOT( slotEmitChanged() ) ); |
|
|
|
// "folder list" radio buttons: |
|
populateButtonGroup( mFolderListGroup = new QHButtonGroup( this ), folderListMode ); |
|
vlay->addWidget( mFolderListGroup ); |
|
connect( mFolderListGroup, SIGNAL ( clicked( int ) ), |
|
this, SLOT( slotEmitChanged() ) ); |
|
|
|
// "show reader window" radio buttons: |
|
populateButtonGroup( mReaderWindowModeGroup = new QVButtonGroup( this ), readerWindowMode ); |
|
vlay->addWidget( mReaderWindowModeGroup ); |
|
connect( mReaderWindowModeGroup, SIGNAL ( clicked( int ) ), |
|
this, SLOT( slotEmitChanged() ) ); |
|
|
|
// "Show MIME Tree" radio buttons: |
|
populateButtonGroup( mMIMETreeModeGroup = new QVButtonGroup( this ), mimeTreeMode ); |
|
vlay->addWidget( mMIMETreeModeGroup ); |
|
connect( mMIMETreeModeGroup, SIGNAL ( clicked( int ) ), |
|
this, SLOT( slotEmitChanged() ) ); |
|
|
|
// "MIME Tree Location" radio buttons: |
|
populateButtonGroup( mMIMETreeLocationGroup = new QHButtonGroup( this ), mimeTreeLocation ); |
|
vlay->addWidget( mMIMETreeLocationGroup ); |
|
connect( mMIMETreeLocationGroup, SIGNAL ( clicked( int ) ), |
|
this, SLOT( slotEmitChanged() ) ); |
|
|
|
vlay->addStretch( 10 ); // spacer |
|
} |
|
|
|
void AppearancePage::LayoutTab::load() { |
|
const KConfigGroup reader( KMKernel::config(), "Reader" ); |
|
const KConfigGroup geometry( KMKernel::config(), "Geometry" ); |
|
|
|
loadWidget( mShowColorbarCheck, reader, showColorbarMode ); |
|
loadWidget( mFolderListGroup, geometry, folderListMode ); |
|
loadWidget( mMIMETreeLocationGroup, reader, mimeTreeLocation ); |
|
loadWidget( mMIMETreeModeGroup, reader, mimeTreeMode ); |
|
loadWidget( mReaderWindowModeGroup, geometry, readerWindowMode ); |
|
} |
|
|
|
void AppearancePage::LayoutTab::installProfile( KConfig * profile ) { |
|
const KConfigGroup reader( profile, "Reader" ); |
|
const KConfigGroup geometry( profile, "Geometry" ); |
|
|
|
loadProfile( mShowColorbarCheck, reader, showColorbarMode ); |
|
loadProfile( mFolderListGroup, geometry, folderListMode ); |
|
loadProfile( mMIMETreeLocationGroup, reader, mimeTreeLocation ); |
|
loadProfile( mMIMETreeModeGroup, reader, mimeTreeMode ); |
|
loadProfile( mReaderWindowModeGroup, geometry, readerWindowMode ); |
|
} |
|
|
|
void AppearancePage::LayoutTab::save() { |
|
KConfigGroup reader( KMKernel::config(), "Reader" ); |
|
KConfigGroup geometry( KMKernel::config(), "Geometry" ); |
|
|
|
saveCheckBox( mShowColorbarCheck, reader, showColorbarMode ); |
|
saveButtonGroup( mFolderListGroup, geometry, folderListMode ); |
|
saveButtonGroup( mMIMETreeLocationGroup, reader, mimeTreeLocation ); |
|
saveButtonGroup( mMIMETreeModeGroup, reader, mimeTreeMode ); |
|
saveButtonGroup( mReaderWindowModeGroup, geometry, readerWindowMode ); |
|
} |
|
|
|
QString AppearancePage::HeadersTab::helpAnchor() const { |
|
return QString::fromLatin1("configure-appearance-headers"); |
|
} |
|
|
|
static const struct { |
|
const char * displayName; |
|
DateFormatter::FormatType dateDisplay; |
|
} dateDisplayConfig[] = { |
|
{ I18N_NOOP("Sta&ndard format (%1)"), KMime::DateFormatter::CTime }, |
|
{ I18N_NOOP("Locali&zed format (%1)"), KMime::DateFormatter::Localized }, |
|
{ I18N_NOOP("Fancy for&mat (%1)"), KMime::DateFormatter::Fancy }, |
|
{ I18N_NOOP("C&ustom format (Shift+F1 for help)"), |
|
KMime::DateFormatter::Custom } |
|
}; |
|
static const int numDateDisplayConfig = |
|
sizeof dateDisplayConfig / sizeof *dateDisplayConfig; |
|
|
|
AppearancePageHeadersTab::AppearancePageHeadersTab( QWidget * parent, const char * name ) |
|
: ConfigModuleTab( parent, name ), |
|
mCustomDateFormatEdit( 0 ) |
|
{ |
|
// tmp. vars: |
|
QButtonGroup * group; |
|
QRadioButton * radio; |
|
|
|
QVBoxLayout * vlay = new QVBoxLayout( this, KDialog::marginHint(), KDialog::spacingHint() ); |
|
|
|
// "General Options" group: |
|
group = new QVButtonGroup( i18n( "General Options" ), this ); |
|
group->layout()->setSpacing( KDialog::spacingHint() ); |
|
|
|
mMessageSizeCheck = new QCheckBox( i18n("Display messa&ge sizes"), group ); |
|
|
|
mCryptoIconsCheck = new QCheckBox( i18n( "Show crypto &icons" ), group ); |
|
|
|
mAttachmentCheck = new QCheckBox( i18n("Show attachment icon"), group ); |
|
|
|
mNestedMessagesCheck = |
|
new QCheckBox( i18n("&Thread list of message headers"), group ); |
|
|
|
connect( mMessageSizeCheck, SIGNAL( stateChanged( int ) ), |
|
this, SLOT( slotEmitChanged( void ) ) ); |
|
connect( mAttachmentCheck, SIGNAL( stateChanged( int ) ), |
|
this, SLOT( slotEmitChanged( void ) ) ); |
|
connect( mCryptoIconsCheck, SIGNAL( stateChanged( int ) ), |
|
this, SLOT( slotEmitChanged( void ) ) ); |
|
connect( mNestedMessagesCheck, SIGNAL( stateChanged( int ) ), |
|
this, SLOT( slotEmitChanged( void ) ) ); |
|
|
|
|
|
vlay->addWidget( group ); |
|
|
|
// "Message Header Threading Options" group: |
|
mNestingPolicy = |
|
new QVButtonGroup( i18n("Message Header Threading Options"), this ); |
|
mNestingPolicy->layout()->setSpacing( KDialog::spacingHint() ); |
|
|
|
mNestingPolicy->insert( |
|
new QRadioButton( i18n("Always &keep threads open"), |
|
mNestingPolicy ), 0 ); |
|
mNestingPolicy->insert( |
|
new QRadioButton( i18n("Threads default to o&pen"), |
|
mNestingPolicy ), 1 ); |
|
mNestingPolicy->insert( |
|
new QRadioButton( i18n("Threads default to closed"), |
|
mNestingPolicy ), 2 ); |
|
mNestingPolicy->insert( |
|
new QRadioButton( i18n("Open threads that contain ne&w, unread " |
|
"or important messages and open watched threads."), |
|
mNestingPolicy ), 3 ); |
|
|
|
vlay->addWidget( mNestingPolicy ); |
|
|
|
connect( mNestingPolicy, SIGNAL( clicked( int ) ), |
|
this, SLOT( slotEmitChanged( void ) ) ); |
|
|
|
// "Date Display" group: |
|
mDateDisplay = new QVButtonGroup( i18n("Date Display"), this ); |
|
mDateDisplay->layout()->setSpacing( KDialog::spacingHint() ); |
|
|
|
for ( int i = 0 ; i < numDateDisplayConfig ; i++ ) { |
|
QString buttonLabel = i18n(dateDisplayConfig[i].displayName); |
|
if ( buttonLabel.contains("%1") ) |
|
buttonLabel = buttonLabel.arg( DateFormatter::formatCurrentDate( dateDisplayConfig[i].dateDisplay ) ); |
|
radio = new QRadioButton( buttonLabel, mDateDisplay ); |
|
mDateDisplay->insert( radio, i ); |
|
if ( dateDisplayConfig[i].dateDisplay == DateFormatter::Custom ) { |
|
mCustomDateFormatEdit = new KLineEdit( mDateDisplay ); |
|
mCustomDateFormatEdit->setEnabled( false ); |
|
connect( radio, SIGNAL(toggled(bool)), |
|
mCustomDateFormatEdit, SLOT(setEnabled(bool)) ); |
|
QString customDateWhatsThis = |
|
i18n("<qt><p><strong>These expressions may be used for the date:" |
|
"</strong></p>" |
|
"<ul>" |
|
"<li>d - the day as a number without a leading zero (1-31)</li>" |
|
"<li>dd - the day as a number with a leading zero (01-31)</li>" |
|
"<li>ddd - the abbreviated day name (Mon - Sun)</li>" |
|
"<li>dddd - the long day name (Monday - Sunday)</li>" |
|
"<li>M - the month as a number without a leading zero (1-12)</li>" |
|
"<li>MM - the month as a number with a leading zero (01-12)</li>" |
|
"<li>MMM - the abbreviated month name (Jan - Dec)</li>" |
|
"<li>MMMM - the long month name (January - December)</li>" |
|
"<li>yy - the year as a two digit number (00-99)</li>" |
|
"<li>yyyy - the year as a four digit number (0000-9999)</li>" |
|
"</ul>" |
|
"<p><strong>These expressions may be used for the time:" |
|
"</string></p> " |
|
"<ul>" |
|
"<li>h - the hour without a leading zero (0-23 or 1-12 if AM/PM display)</li>" |
|
"<li>hh - the hour with a leading zero (00-23 or 01-12 if AM/PM display)</li>" |
|
"<li>m - the minutes without a leading zero (0-59)</li>" |
|
"<li>mm - the minutes with a leading zero (00-59)</li>" |
|
"<li>s - the seconds without a leading zero (0-59)</li>" |
|
"<li>ss - the seconds with a leading zero (00-59)</li>" |
|
"<li>z - the milliseconds without leading zeroes (0-999)</li>" |
|
"<li>zzz - the milliseconds with leading zeroes (000-999)</li>" |
|
"<li>AP - switch to AM/PM display. AP will be replaced by either \"AM\" or \"PM\".</li>" |
|
"<li>ap - switch to AM/PM display. ap will be replaced by either \"am\" or \"pm\".</li>" |
|
"<li>Z - time zone in numeric form (-0500)</li>" |
|
"</ul>" |
|
"<p><strong>All other input characters will be ignored." |
|
"</strong></p></qt>"); |
|
QWhatsThis::add( mCustomDateFormatEdit, customDateWhatsThis ); |
|
QWhatsThis::add( radio, customDateWhatsThis ); |
|
} |
|
} // end for loop populating mDateDisplay |
|
|
|
vlay->addWidget( mDateDisplay ); |
|
connect( mDateDisplay, SIGNAL( clicked( int ) ), |
|
this, SLOT( slotEmitChanged( void ) ) ); |
|
|
|
|
|
vlay->addStretch( 10 ); // spacer |
|
} |
|
|
|
void AppearancePage::HeadersTab::load() { |
|
KConfigGroup general( KMKernel::config(), "General" ); |
|
KConfigGroup geometry( KMKernel::config(), "Geometry" ); |
|
|
|
// "General Options": |
|
mNestedMessagesCheck->setChecked( geometry.readBoolEntry( "nestedMessages", false ) ); |
|
mMessageSizeCheck->setChecked( general.readBoolEntry( "showMessageSize", false ) ); |
|
mCryptoIconsCheck->setChecked( general.readBoolEntry( "showCryptoIcons", false ) ); |
|
mAttachmentCheck->setChecked( general.readBoolEntry( "showAttachmentIcon", true ) ); |
|
|
|
// "Message Header Threading Options": |
|
int num = geometry.readNumEntry( "nestingPolicy", 3 ); |
|
if ( num < 0 || num > 3 ) num = 3; |
|
mNestingPolicy->setButton( num ); |
|
|
|
// "Date Display": |
|
setDateDisplay( general.readNumEntry( "dateFormat", DateFormatter::Fancy ), |
|
general.readEntry( "customDateFormat" ) ); |
|
} |
|
|
|
void AppearancePage::HeadersTab::setDateDisplay( int num, const QString & format ) { |
|
DateFormatter::FormatType dateDisplay = |
|
static_cast<DateFormatter::FormatType>( num ); |
|
|
|
// special case: needs text for the line edit: |
|
if ( dateDisplay == DateFormatter::Custom ) |
|
mCustomDateFormatEdit->setText( format ); |
|
|
|
for ( int i = 0 ; i < numDateDisplayConfig ; i++ ) |
|
if ( dateDisplay == dateDisplayConfig[i].dateDisplay ) { |
|
mDateDisplay->setButton( i ); |
|
return; |
|
} |
|
// fell through since none found: |
|
mDateDisplay->setButton( numDateDisplayConfig - 2 ); // default |
|
} |
|
|
|
void AppearancePage::HeadersTab::installProfile( KConfig * profile ) { |
|
KConfigGroup general( profile, "General" ); |
|
KConfigGroup geometry( profile, "Geometry" ); |
|
|
|
if ( geometry.hasKey( "nestedMessages" ) ) |
|
mNestedMessagesCheck->setChecked( geometry.readBoolEntry( "nestedMessages" ) ); |
|
if ( general.hasKey( "showMessageSize" ) ) |
|
mMessageSizeCheck->setChecked( general.readBoolEntry( "showMessageSize" ) ); |
|
|
|
if( general.hasKey( "showCryptoIcons" ) ) |
|
mCryptoIconsCheck->setChecked( general.readBoolEntry( "showCryptoIcons" ) ); |
|
if ( general.hasKey( "showAttachmentIcon" ) ) |
|
mAttachmentCheck->setChecked( general.readBoolEntry( "showAttachmentIcon" ) ); |
|
|
|
if ( geometry.hasKey( "nestingPolicy" ) ) { |
|
int num = geometry.readNumEntry( "nestingPolicy" ); |
|
if ( num < 0 || num > 3 ) num = 3; |
|
mNestingPolicy->setButton( num ); |
|
} |
|
|
|
if ( general.hasKey( "dateFormat" ) ) |
|
setDateDisplay( general.readNumEntry( "dateFormat" ), |
|
general.readEntry( "customDateFormat" ) ); |
|
} |
|
|
|
void AppearancePage::HeadersTab::save() { |
|
KConfigGroup general( KMKernel::config(), "General" ); |
|
KConfigGroup geometry( KMKernel::config(), "Geometry" ); |
|
|
|
if ( geometry.readBoolEntry( "nestedMessages", false ) |
|
!= mNestedMessagesCheck->isChecked() ) { |
|
int result = KMessageBox::warningContinueCancel( this, |
|
i18n("Changing the global threading setting will override " |
|
"all folder specific values."), |
|
QString::null, QString::null, "threadOverride" ); |
|
if ( result == KMessageBox::Continue ) { |
|
geometry.writeEntry( "nestedMessages", mNestedMessagesCheck->isChecked() ); |
|
// remove all threadMessagesOverride keys from all [Folder-*] groups: |
|
QStringList groups = KMKernel::config()->groupList().grep( QRegExp("^Folder-") ); |
|
kdDebug(5006) << "groups.count() == " << groups.count() << endl; |
|
for ( QStringList::const_iterator it = groups.begin() ; it != groups.end() ; ++it ) { |
|
KConfigGroup group( KMKernel::config(), *it ); |
|
group.deleteEntry( "threadMessagesOverride" ); |
|
} |
|
} |
|
} |
|
|
|
geometry.writeEntry( "nestingPolicy", |
|
mNestingPolicy->id( mNestingPolicy->selected() ) ); |
|
general.writeEntry( "showMessageSize", mMessageSizeCheck->isChecked() ); |
|
general.writeEntry( "showCryptoIcons", mCryptoIconsCheck->isChecked() ); |
|
general.writeEntry( "showAttachmentIcon", mAttachmentCheck->isChecked() ); |
|
|
|
int dateDisplayID = mDateDisplay->id( mDateDisplay->selected() ); |
|
// check bounds: |
|
assert( dateDisplayID >= 0 ); assert( dateDisplayID < numDateDisplayConfig ); |
|
general.writeEntry( "dateFormat", |
|
dateDisplayConfig[ dateDisplayID ].dateDisplay ); |
|
general.writeEntry( "customDateFormat", mCustomDateFormatEdit->text() ); |
|
} |
|
|
|
|
|
// ************************************************************* |
|
// * * |
|
// * ComposerPage * |
|
// * * |
|
// ************************************************************* |
|
|
|
QString ComposerPage::helpAnchor() const { |
|
return QString::fromLatin1("configure-composer"); |
|
} |
|
|
|
ComposerPage::ComposerPage( QWidget * parent, const char * name ) |
|
: ConfigModuleWithTabs( parent, name ) |
|
{ |
|
// |
|
// "General" tab: |
|
// |
|
mGeneralTab = new GeneralTab(); |
|
addTab( mGeneralTab, i18n("&General") ); |
|
|
|
// |
|
// "Phrases" tab: |
|
// |
|
mPhrasesTab = new PhrasesTab(); |
|
addTab( mPhrasesTab, i18n("&Phrases") ); |
|
|
|
// |
|
// "Subject" tab: |
|
// |
|
mSubjectTab = new SubjectTab(); |
|
addTab( mSubjectTab, i18n("&Subject") ); |
|
|
|
// |
|
// "Charset" tab: |
|
// |
|
mCharsetTab = new CharsetTab(); |
|
addTab( mCharsetTab, i18n("Cha&rset") ); |
|
|
|
// |
|
// "Headers" tab: |
|
// |
|
mHeadersTab = new HeadersTab(); |
|
addTab( mHeadersTab, i18n("H&eaders") ); |
|
|
|
// |
|
// "Attachments" tab: |
|
// |
|
mAttachmentsTab = new AttachmentsTab(); |
|
addTab( mAttachmentsTab, i18n("Config->Composer->Attachments", "A&ttachments") ); |
|
load(); |
|
} |
|
|
|
QString ComposerPage::GeneralTab::helpAnchor() const { |
|
return QString::fromLatin1("configure-composer-general"); |
|
} |
|
|
|
ComposerPageGeneralTab::ComposerPageGeneralTab( QWidget * parent, const char * name ) |
|
: ConfigModuleTab( parent, name ) |
|
{ |
|
// tmp. vars: |
|
QVBoxLayout *vlay; |
|
QHBoxLayout *hlay; |
|
QGroupBox *group; |
|
QLabel *label; |
|
QHBox *hbox; |
|
QString msg; |
|
|
|
vlay = new QVBoxLayout( this, KDialog::marginHint(), KDialog::spacingHint() ); |
|
|
|
// some check buttons... |
|
mAutoAppSignFileCheck = |
|
new QCheckBox( i18n("A&utomatically append signature"), this ); |
|
vlay->addWidget( mAutoAppSignFileCheck ); |
|
connect( mAutoAppSignFileCheck, SIGNAL( stateChanged(int) ), |
|
this, SLOT( slotEmitChanged( void ) ) ); |
|
|
|
mSmartQuoteCheck = new QCheckBox( i18n("Use smart "ing"), this ); |
|
vlay->addWidget( mSmartQuoteCheck ); |
|
connect( mSmartQuoteCheck, SIGNAL( stateChanged(int) ), |
|
this, SLOT( slotEmitChanged( void ) ) ); |
|
|
|
mAutoRequestMDNCheck = new QCheckBox( i18n("Automatically request &message disposition notifications"), this ); |
|
vlay->addWidget( mAutoRequestMDNCheck ); |
|
connect( mAutoRequestMDNCheck, SIGNAL( stateChanged(int) ), |
|
this, SLOT( slotEmitChanged( void ) ) ); |
|
|
|
// a checkbox for "word wrap" and a spinbox for the column in |
|
// which to wrap: |
|
hlay = new QHBoxLayout( vlay ); // inherits spacing |
|
mWordWrapCheck = new QCheckBox( i18n("Word &wrap at column:"), this ); |
|
hlay->addWidget( mWordWrapCheck ); |
|
connect( mWordWrapCheck, SIGNAL( stateChanged(int) ), |
|
this, SLOT( slotEmitChanged( void ) ) ); |
|
|
|
mWrapColumnSpin = new KIntSpinBox( 30/*min*/, 78/*max*/, 1/*step*/, |
|
78/*init*/, 10 /*base*/, this ); |
|
mWrapColumnSpin->setEnabled( false ); // since !mWordWrapCheck->isChecked() |
|
connect( mWrapColumnSpin, SIGNAL( valueChanged(int) ), |
|
this, SLOT( slotEmitChanged( void ) ) ); |
|
|
|
hlay->addWidget( mWrapColumnSpin ); |
|
hlay->addStretch( 1 ); |
|
// only enable the spinbox if the checkbox is checked: |
|
connect( mWordWrapCheck, SIGNAL(toggled(bool)), |
|
mWrapColumnSpin, SLOT(setEnabled(bool)) ); |
|
|
|
hlay = new QHBoxLayout( vlay ); // inherits spacing |
|
mAutoSave = new KIntSpinBox( 0, 60, 1, 1, 10, this ); |
|
label = new QLabel( mAutoSave, i18n("Autosave every:"), this ); |
|
hlay->addWidget( label ); |
|
hlay->addWidget( mAutoSave ); |
|
mAutoSave->setSpecialValueText( i18n("No autosave") ); |
|
mAutoSave->setSuffix( i18n(" min") ); |
|
hlay->addStretch( 1 ); |
|
connect( mAutoSave, SIGNAL( valueChanged(int) ), |
|
this, SLOT( slotEmitChanged( void ) ) ); |
|
|
|
msg = i18n("A backup copy of the text in the composer window can be created " |
|
"regularly. The interval used to create the backups is set here. " |
|
"You can disable autosaving by setting it to the value 0."); |
|
QWhatsThis::add( mAutoSave, msg ); |
|
QWhatsThis::add( label, msg ); |
|
|
|
// The "external editor" group: |
|
group = new QVGroupBox( i18n("External Editor"), this ); |
|
group->layout()->setSpacing( KDialog::spacingHint() ); |
|
|
|
mExternalEditorCheck = |
|
new QCheckBox( i18n("Use e&xternal editor instead of composer"), group ); |
|
connect( mExternalEditorCheck, SIGNAL( toggled( bool ) ), |
|
this, SLOT( slotEmitChanged( void ) ) ); |
|
|
|
hbox = new QHBox( group ); |
|
label = new QLabel( i18n("Specify e&ditor:"), hbox ); |
|
mEditorRequester = new KURLRequester( hbox ); |
|
connect( mEditorRequester, SIGNAL( urlSelected(const QString&) ), |
|
this, SLOT( slotEmitChanged( void ) ) ); |
|
|
|
hbox->setStretchFactor( mEditorRequester, 1 ); |
|
label->setBuddy( mEditorRequester ); |
|
label->setEnabled( false ); // since !mExternalEditorCheck->isChecked() |
|
// ### FIXME: allow only executables (x-bit when available..) |
|
mEditorRequester->setFilter( "application/x-executable " |
|
"application/x-shellscript " |
|
"application/x-desktop" ); |
|
mEditorRequester->setEnabled( false ); // !mExternalEditorCheck->isChecked() |
|
connect( mExternalEditorCheck, SIGNAL(toggled(bool)), |
|
label, SLOT(setEnabled(bool)) ); |
|
connect( mExternalEditorCheck, SIGNAL(toggled(bool)), |
|
mEditorRequester, SLOT(setEnabled(bool)) ); |
|
|
|
label = new QLabel( i18n("<b>%f</b> will be replaced with the " |
|
"filename to edit."), group ); |
|
label->setEnabled( false ); // see above |
|
connect( mExternalEditorCheck, SIGNAL(toggled(bool)), |
|
label, SLOT(setEnabled(bool)) ); |
|
|
|
vlay->addWidget( group ); |
|
vlay->addStretch( 100 ); |
|
|
|
msg = i18n("<qt><p>Enable this option if you want KMail to request " |
|
"Message Disposition Notifications (MDNs) for each of your " |
|
"outgoing messages.</p>" |
|
"<p>This option only affects the default; " |
|
"you can still enable or disable MDN requesting on a " |
|
"per-message basis in the composer, menu item " |
|
"<em>Options</em>->>" |
|
"<em>Request Disposition Notification</em>.</p></qt>"); |
|
QWhatsThis::add( mAutoRequestMDNCheck, msg ); |
|
} |
|
|
|
void ComposerPage::GeneralTab::load() { |
|
KConfigGroup composer( KMKernel::config(), "Composer" ); |
|
KConfigGroup general( KMKernel::config(), "General" ); |
|
|
|
// various check boxes: |
|
bool state = ( composer.readEntry("signature").lower() != "manual" ); |
|
mAutoAppSignFileCheck->setChecked( state ); |
|
mSmartQuoteCheck->setChecked( composer.readBoolEntry( "smart-quote", true ) ); |
|
mAutoRequestMDNCheck->setChecked( composer.readBoolEntry( "request-mdn", false ) ); |
|
mWordWrapCheck->setChecked( composer.readBoolEntry( "word-wrap", true ) ); |
|
|
|
mWrapColumnSpin->setValue( composer.readNumEntry( "break-at", 78 ) ); |
|
mAutoSave->setValue( composer.readNumEntry( "autosave", 2 ) ); |
|
|
|
// editor group: |
|
mExternalEditorCheck->setChecked( general.readBoolEntry( "use-external-editor", false ) ); |
|
mEditorRequester->setURL( general.readPathEntry( "external-editor" ) ); |
|
} |
|
|
|
void ComposerPageGeneralTab::defaults() |
|
{ |
|
mAutoAppSignFileCheck->setChecked( true ); |
|
mSmartQuoteCheck->setChecked( true ); |
|
mAutoRequestMDNCheck->setChecked( false ); |
|
mWordWrapCheck->setChecked( true ); |
|
|
|
mWrapColumnSpin->setValue( 78 ); |
|
mAutoSave->setValue( 2 ); |
|
|
|
mExternalEditorCheck->setChecked( false ); |
|
mEditorRequester->clear(); |
|
} |
|
|
|
void ComposerPage::GeneralTab::installProfile( KConfig * profile ) { |
|
KConfigGroup composer( profile, "Composer" ); |
|
KConfigGroup general( profile, "General" ); |
|
|
|
if ( composer.hasKey( "signature" ) ) { |
|
bool state = ( composer.readEntry("signature").lower() == "auto" ); |
|
mAutoAppSignFileCheck->setChecked( state ); |
|
} |
|
if ( composer.hasKey( "smart-quote" ) ) |
|
mSmartQuoteCheck->setChecked( composer.readBoolEntry( "smart-quote" ) ); |
|
if ( composer.hasKey( "request-mdn" ) ) |
|
mAutoRequestMDNCheck->setChecked( composer.readBoolEntry( "request-mdn" ) ); |
|
if ( composer.hasKey( "word-wrap" ) ) |
|
mWordWrapCheck->setChecked( composer.readBoolEntry( "word-wrap" ) ); |
|
if ( composer.hasKey( "break-at" ) ) |
|
mWrapColumnSpin->setValue( composer.readNumEntry( "break-at" ) ); |
|
if ( composer.hasKey( "autosave" ) ) |
|
mAutoSave->setValue( composer.readNumEntry( "autosave" ) ); |
|
|
|
if ( general.hasKey( "use-external-editor" ) |
|
&& general.hasKey( "external-editor" ) ) { |
|
mExternalEditorCheck->setChecked( general.readBoolEntry( "use-external-editor" ) ); |
|
mEditorRequester->setURL( general.readPathEntry( "external-editor" ) ); |
|
} |
|
} |
|
|
|
void ComposerPage::GeneralTab::save() { |
|
KConfigGroup general( KMKernel::config(), "General" ); |
|
KConfigGroup composer( KMKernel::config(), "Composer" ); |
|
|
|
general.writeEntry( "use-external-editor", mExternalEditorCheck->isChecked() |
|
&& !mEditorRequester->url().isEmpty() ); |
|
general.writePathEntry( "external-editor", mEditorRequester->url() ); |
|
|
|
bool autoSignature = mAutoAppSignFileCheck->isChecked(); |
|
composer.writeEntry( "signature", autoSignature ? "auto" : "manual" ); |
|
composer.writeEntry( "smart-quote", mSmartQuoteCheck->isChecked() ); |
|
composer.writeEntry( "request-mdn", mAutoRequestMDNCheck->isChecked() ); |
|
composer.writeEntry( "word-wrap", mWordWrapCheck->isChecked() ); |
|
composer.writeEntry( "break-at", mWrapColumnSpin->value() ); |
|
composer.writeEntry( "autosave", mAutoSave->value() ); |
|
} |
|
|
|
QString ComposerPage::PhrasesTab::helpAnchor() const { |
|
return QString::fromLatin1("configure-composer-phrases"); |
|
} |
|
|
|
ComposerPagePhrasesTab::ComposerPagePhrasesTab( QWidget * parent, const char * name ) |
|
: ConfigModuleTab( parent, name ) |
|
{ |
|
// tmp. vars: |
|
QGridLayout *glay; |
|
QPushButton *button; |
|
|
|
glay = new QGridLayout( this, 7, 3, KDialog::spacingHint() ); |
|
glay->setMargin( KDialog::marginHint() ); |
|
glay->setColStretch( 1, 1 ); |
|
glay->setColStretch( 2, 1 ); |
|
glay->setRowStretch( 7, 1 ); |
|
|
|
// row 0: help text |
|
glay->addMultiCellWidget( new QLabel( i18n("<qt>The following placeholders are " |
|
"supported in the reply phrases:<br>" |
|
"<b>%D</b>: date, <b>%S</b>: subject,<br>" |
|
"<b>%e</b>: sender's address, <b>%F</b>: sender's name, <b>%f</b>: sender's initials,<br>" |
|
"<b>%T</b>: recipient's name, <b>%t</b>: recipient's name and address,<br>" |
|
"<b>%C</b>: carbon copy names, <b>%c</b>: carbon copy names and addresses,<br>" |
|
"<b>%%</b>: percent sign, <b>%_</b>: space, " |
|
"<b>%L</b>: linebreak</qt>"), this ), |
|
0, 0, 0, 2 ); // row 0; cols 0..2 |
|
|
|
// row 1: label and language combo box: |
|
mPhraseLanguageCombo = new LanguageComboBox( false, this ); |
|
glay->addWidget( new QLabel( mPhraseLanguageCombo, |
|
i18n("Lang&uage:"), this ), 1, 0 ); |
|
glay->addMultiCellWidget( mPhraseLanguageCombo, 1, 1, 1, 2 ); |
|
connect( mPhraseLanguageCombo, SIGNAL(activated(const QString&)), |
|
this, SLOT(slotLanguageChanged(const QString&)) ); |
|
|
|
// row 2: "add..." and "remove" push buttons: |
|
button = new QPushButton( i18n("A&dd..."), this ); |
|
button->setAutoDefault( false ); |
|
glay->addWidget( button, 2, 1 ); |
|
mRemoveButton = new QPushButton( i18n("Re&move"), this ); |
|
mRemoveButton->setAutoDefault( false ); |
|
mRemoveButton->setEnabled( false ); // combo doesn't contain anything... |
|
glay->addWidget( mRemoveButton, 2, 2 ); |
|
connect( button, SIGNAL(clicked()), |
|
this, SLOT(slotNewLanguage()) ); |
|
connect( mRemoveButton, SIGNAL(clicked()), |
|
this, SLOT(slotRemoveLanguage()) ); |
|
|
|
// row 3: "reply to sender" line edit and label: |
|
mPhraseReplyEdit = new KLineEdit( this ); |
|
connect( mPhraseReplyEdit, SIGNAL( textChanged( const QString& ) ), |
|
this, SLOT( slotEmitChanged( void ) ) ); |
|
glay->addWidget( new QLabel( mPhraseReplyEdit, |
|
i18n("Reply to se&nder:"), this ), 3, 0 ); |
|
glay->addMultiCellWidget( mPhraseReplyEdit, 3, 3, 1, 2 ); // cols 1..2 |
|
|
|
// row 4: "reply to all" line edit and label: |
|
mPhraseReplyAllEdit = new KLineEdit( this ); |
|
connect( mPhraseReplyAllEdit, SIGNAL( textChanged( const QString& ) ), |
|
this, SLOT( slotEmitChanged( void ) ) ); |
|
glay->addWidget( new QLabel( mPhraseReplyAllEdit, |
|
i18n("Repl&y to all:"), this ), 4, 0 ); |
|
glay->addMultiCellWidget( mPhraseReplyAllEdit, 4, 4, 1, 2 ); // cols 1..2 |
|
|
|
// row 5: "forward" line edit and label: |
|
mPhraseForwardEdit = new KLineEdit( this ); |
|
connect( mPhraseForwardEdit, SIGNAL( textChanged( const QString& ) ), |
|
this, SLOT( slotEmitChanged( void ) ) ); |
|
glay->addWidget( new QLabel( mPhraseForwardEdit, |
|
i18n("&Forward:"), this ), 5, 0 ); |
|
glay->addMultiCellWidget( mPhraseForwardEdit, 5, 5, 1, 2 ); // cols 1..2 |
|
|
|
// row 6: "quote indicator" line edit and label: |
|
mPhraseIndentPrefixEdit = new KLineEdit( this ); |
|
connect( mPhraseIndentPrefixEdit, SIGNAL( textChanged( const QString& ) ), |
|
this, SLOT( slotEmitChanged( void ) ) ); |
|
glay->addWidget( new QLabel( mPhraseIndentPrefixEdit, |
|
i18n("&Quote indicator:"), this ), 6, 0 ); |
|
glay->addMultiCellWidget( mPhraseIndentPrefixEdit, 6, 6, 1, 2 ); |
|
|
|
// row 7: spacer |
|
} |
|
|
|
|
|
void ComposerPage::PhrasesTab::setLanguageItemInformation( int index ) { |
|
assert( 0 <= index && index < (int)mLanguageList.count() ); |
|
|
|
LanguageItem &l = *mLanguageList.at( index ); |
|
|
|
mPhraseReplyEdit->setText( l.mReply ); |
|
mPhraseReplyAllEdit->setText( l.mReplyAll ); |
|
mPhraseForwardEdit->setText( l.mForward ); |
|
mPhraseIndentPrefixEdit->setText( l.mIndentPrefix ); |
|
} |
|
|
|
void ComposerPage::PhrasesTab::saveActiveLanguageItem() { |
|
int index = mActiveLanguageItem; |
|
if (index == -1) return; |
|
assert( 0 <= index && index < (int)mLanguageList.count() ); |
|
|
|
LanguageItem &l = *mLanguageList.at( index ); |
|
|
|
l.mReply = mPhraseReplyEdit->text(); |
|
l.mReplyAll = mPhraseReplyAllEdit->text(); |
|
l.mForward = mPhraseForwardEdit->text(); |
|
l.mIndentPrefix = mPhraseIndentPrefixEdit->text(); |
|
} |
|
|
|
void ComposerPage::PhrasesTab::slotNewLanguage() |
|
{ |
|
NewLanguageDialog dialog( mLanguageList, parentWidget(), "New", true ); |
|
if ( dialog.exec() == QDialog::Accepted ) slotAddNewLanguage( dialog.language() ); |
|
} |
|
|
|
void ComposerPage::PhrasesTab::slotAddNewLanguage( const QString& lang ) |
|
{ |
|
mPhraseLanguageCombo->setCurrentItem( |
|
mPhraseLanguageCombo->insertLanguage( lang ) ); |
|
KLocale locale("kmail"); |
|
locale.setLanguage( lang ); |
|
mLanguageList.append( |
|
LanguageItem( lang, |
|
locale.translate("On %D, you wrote:"), |
|
locale.translate("On %D, %F wrote:"), |
|
locale.translate("Forwarded Message"), |
|
locale.translate(">%_") ) ); |
|
mRemoveButton->setEnabled( true ); |
|
slotLanguageChanged( QString::null ); |
|
} |
|
|
|
void ComposerPage::PhrasesTab::slotRemoveLanguage() |
|
{ |
|
assert( mPhraseLanguageCombo->count() > 1 ); |
|
int index = mPhraseLanguageCombo->currentItem(); |
|
assert( 0 <= index && index < (int)mLanguageList.count() ); |
|
|
|
// remove current item from internal list and combobox: |
|
mLanguageList.remove( mLanguageList.at( index ) ); |
|
mPhraseLanguageCombo->removeItem( index ); |
|
|
|
if ( index >= (int)mLanguageList.count() ) index--; |
|
|
|
mActiveLanguageItem = index; |
|
setLanguageItemInformation( index ); |
|
mRemoveButton->setEnabled( mLanguageList.count() > 1 ); |
|
emit changed( true ); |
|
} |
|
|
|
void ComposerPage::PhrasesTab::slotLanguageChanged( const QString& ) |
|
{ |
|
int index = mPhraseLanguageCombo->currentItem(); |
|
assert( index < (int)mLanguageList.count() ); |
|
saveActiveLanguageItem(); |
|
mActiveLanguageItem = index; |
|
setLanguageItemInformation( index ); |
|
emit changed( true ); |
|
} |
|
|
|
|
|
void ComposerPage::PhrasesTab::load() { |
|
KConfigGroup general( KMKernel::config(), "General" ); |
|
|
|
mLanguageList.clear(); |
|
mPhraseLanguageCombo->clear(); |
|
mActiveLanguageItem = -1; |
|
|
|
int num = general.readNumEntry( "reply-languages", 0 ); |
|
int currentNr = general.readNumEntry( "reply-current-language" ,0 ); |
|
|
|
// build mLanguageList and mPhraseLanguageCombo: |
|
for ( int i = 0 ; i < num ; i++ ) { |
|
KConfigGroup config( KMKernel::config(), |
|
QCString("KMMessage #") + QCString().setNum(i) ); |
|
QString lang = config.readEntry( "language" ); |
|
mLanguageList.append( |
|
LanguageItem( lang, |
|
config.readEntry( "phrase-reply" ), |
|
config.readEntry( "phrase-reply-all" ), |
|
config.readEntry( "phrase-forward" ), |
|
config.readEntry( "indent-prefix" ) ) ); |
|
mPhraseLanguageCombo->insertLanguage( lang ); |
|
} |
|
|
|
if ( num == 0 ) |
|
slotAddNewLanguage( KGlobal::locale()->language() ); |
|
|
|
if ( currentNr >= num || currentNr < 0 ) |
|
currentNr = 0; |
|
|
|
mPhraseLanguageCombo->setCurrentItem( currentNr ); |
|
mActiveLanguageItem = currentNr; |
|
setLanguageItemInformation( currentNr ); |
|
mRemoveButton->setEnabled( mLanguageList.count() > 1 ); |
|
} |
|
|
|
void ComposerPage::PhrasesTab::save() { |
|
KConfigGroup general( KMKernel::config(), "General" ); |
|
|
|
general.writeEntry( "reply-languages", mLanguageList.count() ); |
|
general.writeEntry( "reply-current-language", mPhraseLanguageCombo->currentItem() ); |
|
|
|
saveActiveLanguageItem(); |
|
LanguageItemList::Iterator it = mLanguageList.begin(); |
|
for ( int i = 0 ; it != mLanguageList.end() ; ++it, ++i ) { |
|
KConfigGroup config( KMKernel::config(), |
|
QCString("KMMessage #") + QCString().setNum(i) ); |
|
config.writeEntry( "language", (*it).mLanguage ); |
|
config.writeEntry( "phrase-reply", (*it).mReply ); |
|
config.writeEntry( "phrase-reply-all", (*it).mReplyAll ); |
|
config.writeEntry( "phrase-forward", (*it).mForward ); |
|
config.writeEntry( "indent-prefix", (*it).mIndentPrefix ); |
|
} |
|
} |
|
|
|
QString ComposerPage::SubjectTab::helpAnchor() const { |
|
return QString::fromLatin1("configure-composer-subject"); |
|
} |
|
|
|
ComposerPageSubjectTab::ComposerPageSubjectTab( QWidget * parent, const char * name ) |
|
: ConfigModuleTab( parent, name ) |
|
{ |
|
// tmp. vars: |
|
QVBoxLayout *vlay; |
|
QGroupBox *group; |
|
QLabel *label; |
|
|
|
|
|
vlay = new QVBoxLayout( this, KDialog::marginHint(), KDialog::spacingHint() ); |
|
|
|
group = new QVGroupBox( i18n("Repl&y Subject Prefixes"), this ); |
|
group->layout()->setSpacing( KDialog::spacingHint() ); |
|
|
|
// row 0: help text: |
|
label = new QLabel( i18n("Recognize any sequence of the following prefixes\n" |
|
"(entries are case-insensitive regular expressions):"), group ); |
|
label->setAlignment( AlignLeft|WordBreak ); |
|
|
|
// row 1, string list editor: |
|
SimpleStringListEditor::ButtonCode buttonCode = |
|
static_cast<SimpleStringListEditor::ButtonCode>( SimpleStringListEditor::Add | SimpleStringListEditor::Remove | SimpleStringListEditor::Modify ); |
|
mReplyListEditor = |
|
new SimpleStringListEditor( group, 0, buttonCode, |
|
i18n("A&dd..."), i18n("Re&move"), |
|
i18n("Mod&ify..."), |
|
i18n("Enter new reply prefix:") ); |
|
connect( mReplyListEditor, SIGNAL( changed( void ) ), |
|
this, SLOT( slotEmitChanged( void ) ) ); |
|
|
|
// row 2: "replace [...]" check box: |
|
mReplaceReplyPrefixCheck = |
|
new QCheckBox( i18n("Replace recognized prefi&x with \"Re:\""), group ); |
|
connect( mReplaceReplyPrefixCheck, SIGNAL( stateChanged( int ) ), |
|
this, SLOT( slotEmitChanged( void ) ) ); |
|
|
|
vlay->addWidget( group ); |
|
|
|
|
|
group = new QVGroupBox( i18n("For&ward Subject Prefixes"), this ); |
|
group->layout()->setSpacing( KDialog::marginHint() ); |
|
|
|
// row 0: help text: |
|
label= new QLabel( i18n("Recognize any sequence of the following prefixes\n" |
|
"(entries are case-insensitive regular expressions):"), group ); |
|
label->setAlignment( AlignLeft|WordBreak ); |
|
|
|
// row 1: string list editor |
|
mForwardListEditor = |
|
new SimpleStringListEditor( group, 0, buttonCode, |
|
i18n("Add..."), |
|
i18n("Remo&ve"), |
|
i18n("Modify..."), |
|
i18n("Enter new forward prefix:") ); |
|
connect( mForwardListEditor, SIGNAL( changed( void ) ), |
|
this, SLOT( slotEmitChanged( void ) ) ); |
|
|
|
// row 3: "replace [...]" check box: |
|
mReplaceForwardPrefixCheck = |
|
new QCheckBox( i18n("Replace recognized prefix with \"&Fwd:\""), group ); |
|
connect( mReplaceForwardPrefixCheck, SIGNAL( stateChanged( int ) ), |
|
this, SLOT( slotEmitChanged( void ) ) ); |
|
|
|
vlay->addWidget( group ); |
|
} |
|
|
|
void ComposerPage::SubjectTab::load() { |
|
KConfigGroup composer( KMKernel::config(), "Composer" ); |
|
|
|
QStringList prefixList = composer.readListEntry( "reply-prefixes", ',' ); |
|
if ( prefixList.isEmpty() ) |
|
prefixList << QString::fromLatin1("Re\\s*:") |
|
<< QString::fromLatin1("Re\\[\\d+\\]:") |
|
<< QString::fromLatin1("Re\\d+:"); |
|
mReplyListEditor->setStringList( prefixList ); |
|
|
|
mReplaceReplyPrefixCheck->setChecked( composer.readBoolEntry("replace-reply-prefix", true ) ); |
|
|
|
prefixList = composer.readListEntry( "forward-prefixes", ',' ); |
|
if ( prefixList.isEmpty() ) |
|
prefixList << QString::fromLatin1("Fwd:") |
|
<< QString::fromLatin1("FW:"); |
|
mForwardListEditor->setStringList( prefixList ); |
|
|
|
mReplaceForwardPrefixCheck->setChecked( composer.readBoolEntry( "replace-forward-prefix", true ) ); |
|
} |
|
|
|
void ComposerPage::SubjectTab::save() { |
|
KConfigGroup composer( KMKernel::config(), "Composer" ); |
|
|
|
|
|
composer.writeEntry( "reply-prefixes", mReplyListEditor->stringList() ); |
|
composer.writeEntry( "forward-prefixes", mForwardListEditor->stringList() ); |
|
composer.writeEntry( "replace-reply-prefix", |
|
mReplaceReplyPrefixCheck->isChecked() ); |
|
composer.writeEntry( "replace-forward-prefix", |
|
mReplaceForwardPrefixCheck->isChecked() ); |
|
} |
|
|
|
QString ComposerPage::CharsetTab::helpAnchor() const { |
|
return QString::fromLatin1("configure-composer-charset"); |
|
} |
|
|
|
ComposerPageCharsetTab::ComposerPageCharsetTab( QWidget * parent, const char * name ) |
|
: ConfigModuleTab( parent, name ) |
|
{ |
|
// tmp. vars: |
|
QVBoxLayout *vlay; |
|
QLabel *label; |
|
|
|
vlay = new QVBoxLayout( this, KDialog::marginHint(), KDialog::spacingHint() ); |
|
|
|
label = new QLabel( i18n("This list is checked for every outgoing message " |
|
"from the top to the bottom for a charset that " |
|
"contains all required characters."), this ); |
|
label->setAlignment( WordBreak); |
|
vlay->addWidget( label ); |
|
|
|
mCharsetListEditor = |
|
new SimpleStringListEditor( this, 0, SimpleStringListEditor::All, |
|
i18n("A&dd..."), i18n("Remo&ve"), |
|
i18n("&Modify"), i18n("Enter charset:") ); |
|
connect( mCharsetListEditor, SIGNAL( changed( void ) ), |
|
this, SLOT( slotEmitChanged( void ) ) ); |
|
|
|
vlay->addWidget( mCharsetListEditor, 1 ); |
|
|
|
mKeepReplyCharsetCheck = new QCheckBox( i18n("&Keep original charset when " |
|
"replying or forwarding (if " |
|
"possible)."), this ); |
|
connect( mKeepReplyCharsetCheck, SIGNAL ( stateChanged( int ) ), |
|
this, SLOT( slotEmitChanged( void ) ) ); |
|
vlay->addWidget( mKeepReplyCharsetCheck ); |
|
|
|
connect( mCharsetListEditor, SIGNAL(aboutToAdd(QString&)), |
|
this, SLOT(slotVerifyCharset(QString&)) ); |
|
} |
|
|
|
void ComposerPage::CharsetTab::slotVerifyCharset( QString & charset ) { |
|
if ( charset.isEmpty() ) return; |
|
|
|
// KCharsets::codecForName("us-ascii") returns "iso-8859-1" (cf. Bug #49812) |
|
// therefore we have to treat this case specially |
|
if ( charset.lower() == QString::fromLatin1("us-ascii") ) { |
|
charset = QString::fromLatin1("us-ascii"); |
|
return; |
|
} |
|
|
|
if ( charset.lower() == QString::fromLatin1("locale") ) { |
|
charset = QString::fromLatin1("%1 (locale)") |
|
.arg( QCString( kmkernel->networkCodec()->mimeName() ).lower() ); |
|
return; |
|
} |
|
|
|
bool ok = false; |
|
QTextCodec *codec = KGlobal::charsets()->codecForName( charset, ok ); |
|
if ( ok && codec ) { |
|
charset = QString::fromLatin1( codec->mimeName() ).lower(); |
|
return; |
|
} |
|
|
|
KMessageBox::sorry( this, i18n("This charset is not supported.") ); |
|
charset = QString::null; |
|
} |
|
|
|
void ComposerPage::CharsetTab::load() { |
|
KConfigGroup composer( KMKernel::config(), "Composer" ); |
|
|
|
QStringList charsets = composer.readListEntry( "pref-charsets" ); |
|
for ( QStringList::Iterator it = charsets.begin() ; |
|
it != charsets.end() ; ++it ) |
|
if ( (*it) == QString::fromLatin1("locale") ) |
|
(*it) = QString("%1 (locale)") |
|
.arg( QCString( kmkernel->networkCodec()->mimeName() ).lower() ); |
|
|
|
mCharsetListEditor->setStringList( charsets ); |
|
mKeepReplyCharsetCheck->setChecked( !composer.readBoolEntry( "force-reply-charset", false ) ); |
|
} |
|
|
|
void ComposerPage::CharsetTab::save() { |
|
KConfigGroup composer( KMKernel::config(), "Composer" ); |
|
|
|
QStringList charsetList = mCharsetListEditor->stringList(); |
|
QStringList::Iterator it = charsetList.begin(); |
|
for ( ; it != charsetList.end() ; ++it ) |
|
if ( (*it).endsWith("(locale)") ) |
|
(*it) = "locale"; |
|
composer.writeEntry( "pref-charsets", charsetList ); |
|
composer.writeEntry( "force-reply-charset", |
|
!mKeepReplyCharsetCheck->isChecked() ); |
|
} |
|
|
|
QString ComposerPage::HeadersTab::helpAnchor() const { |
|
return QString::fromLatin1("configure-composer-headers"); |
|
} |
|
|
|
ComposerPageHeadersTab::ComposerPageHeadersTab( QWidget * parent, const char * name ) |
|
: ConfigModuleTab( parent, name ) |
|
{ |
|
// tmp. vars: |
|
QVBoxLayout *vlay; |
|
QHBoxLayout *hlay; |
|
QGridLayout *glay; |
|
QLabel *label; |
|
QPushButton *button; |
|
|
|
vlay = new QVBoxLayout( this, KDialog::marginHint(), KDialog::spacingHint() ); |
|
|
|
// "Use custom Message-Id suffix" checkbox: |
|
mCreateOwnMessageIdCheck = |
|
new QCheckBox( i18n("&Use custom message-id suffix"), this ); |
|
connect( mCreateOwnMessageIdCheck, SIGNAL ( stateChanged( int ) ), |
|
this, SLOT( slotEmitChanged( void ) ) ); |
|
vlay->addWidget( mCreateOwnMessageIdCheck ); |
|
|
|
// "Message-Id suffix" line edit and label: |
|
hlay = new QHBoxLayout( vlay ); // inherits spacing |
|
mMessageIdSuffixEdit = new KLineEdit( this ); |
|
// only ASCII letters, digits, plus, minus and dots are allowed |
|
mMessageIdSuffixValidator = |
|
new QRegExpValidator( QRegExp( "[a-zA-Z0-9+-]+(?:\\.[a-zA-Z0-9+-]+)*" ), this ); |
|
mMessageIdSuffixEdit->setValidator( mMessageIdSuffixValidator ); |
|
label = new QLabel( mMessageIdSuffixEdit, |
|
i18n("Custom message-&id suffix:"), this ); |
|
label->setEnabled( false ); // since !mCreateOwnMessageIdCheck->isChecked() |
|
mMessageIdSuffixEdit->setEnabled( false ); |
|
hlay->addWidget( label ); |
|
hlay->addWidget( mMessageIdSuffixEdit, 1 ); |
|
connect( mCreateOwnMessageIdCheck, SIGNAL(toggled(bool) ), |
|
label, SLOT(setEnabled(bool)) ); |
|
connect( mCreateOwnMessageIdCheck, SIGNAL(toggled(bool) ), |
|
mMessageIdSuffixEdit, SLOT(setEnabled(bool)) ); |
|
connect( mMessageIdSuffixEdit, SIGNAL( textChanged( const QString& ) ), |
|
this, SLOT( slotEmitChanged( void ) ) ); |
|
|
|
// horizontal rule and "custom header fields" label: |
|
vlay->addWidget( new KSeparator( KSeparator::HLine, this ) ); |
|
vlay->addWidget( new QLabel( i18n("Define custom mime header fields:"), this) ); |
|
|
|
// "custom header fields" listbox: |
|
glay = new QGridLayout( vlay, 5, 3 ); // inherits spacing |
|
glay->setRowStretch( 2, 1 ); |
|
glay->setColStretch( 1, 1 ); |
|
mTagList = new ListView( this, "tagList" ); |
|
mTagList->addColumn( i18n("Name") ); |
|
mTagList->addColumn( i18n("Value") ); |
|
mTagList->setAllColumnsShowFocus( true ); |
|
mTagList->setFrameStyle( QFrame::WinPanel | QFrame::Sunken ); |
|
mTagList->setSorting( -1 ); |
|
connect( mTagList, SIGNAL(selectionChanged()), |
|
this, SLOT(slotMimeHeaderSelectionChanged()) ); |
|
glay->addMultiCellWidget( mTagList, 0, 2, 0, 1 ); |
|
|
|
// "new" and "remove" buttons: |
|
button = new QPushButton( i18n("Ne&w"), this ); |
|
connect( button, SIGNAL(clicked()), this, SLOT(slotNewMimeHeader()) ); |
|
button->setAutoDefault( false ); |
|
glay->addWidget( button, 0, 2 ); |
|
mRemoveHeaderButton = new QPushButton( i18n("Re&move"), this ); |
|
connect( mRemoveHeaderButton, SIGNAL(clicked()), |
|
this, SLOT(slotRemoveMimeHeader()) ); |
|
button->setAutoDefault( false ); |
|
glay->addWidget( mRemoveHeaderButton, 1, 2 ); |
|
|
|
// "name" and "value" line edits and labels: |
|
mTagNameEdit = new KLineEdit( this ); |
|
mTagNameEdit->setEnabled( false ); |
|
mTagNameLabel = new QLabel( mTagNameEdit, i18n("&Name:"), this ); |
|
mTagNameLabel->setEnabled( false ); |
|
glay->addWidget( mTagNameLabel, 3, 0 ); |
|
glay->addWidget( mTagNameEdit, 3, 1 ); |
|
connect( mTagNameEdit, SIGNAL(textChanged(const QString&)), |
|
this, SLOT(slotMimeHeaderNameChanged(const QString&)) ); |
|
|
|
mTagValueEdit = new KLineEdit( this ); |
|
mTagValueEdit->setEnabled( false ); |
|
mTagValueLabel = new QLabel( mTagValueEdit, i18n("&Value:"), this ); |
|
mTagValueLabel->setEnabled( false ); |
|
glay->addWidget( mTagValueLabel, 4, 0 ); |
|
glay->addWidget( mTagValueEdit, 4, 1 ); |
|
connect( mTagValueEdit, SIGNAL(textChanged(const QString&)), |
|
this, SLOT(slotMimeHeaderValueChanged(const QString&)) ); |
|
} |
|
|
|
void ComposerPage::HeadersTab::slotMimeHeaderSelectionChanged() |
|
{ |
|
QListViewItem * item = mTagList->selectedItem(); |
|
|
|
if ( item ) { |
|
mTagNameEdit->setText( item->text( 0 ) ); |
|
mTagValueEdit->setText( item->text( 1 ) ); |
|
} else { |
|
mTagNameEdit->clear(); |
|
mTagValueEdit->clear(); |
|
} |
|
mRemoveHeaderButton->setEnabled( item ); |
|
mTagNameEdit->setEnabled( item ); |
|
mTagValueEdit->setEnabled( item ); |
|
mTagNameLabel->setEnabled( item ); |
|
mTagValueLabel->setEnabled( item ); |
|
} |
|
|
|
|
|
void ComposerPage::HeadersTab::slotMimeHeaderNameChanged( const QString & text ) { |
|
// is called on ::setup(), when clearing the line edits. So be |
|
// prepared to not find a selection: |
|
QListViewItem * item = mTagList->selectedItem(); |
|
if ( item ) |
|
item->setText( 0, text ); |
|
emit changed( true ); |
|
} |
|
|
|
|
|
void ComposerPage::HeadersTab::slotMimeHeaderValueChanged( const QString & text ) { |
|
// is called on ::setup(), when clearing the line edits. So be |
|
// prepared to not find a selection: |
|
QListViewItem * item = mTagList->selectedItem(); |
|
if ( item ) |
|
item->setText( 1, text ); |
|
emit changed( true ); |
|
} |
|
|
|
|
|
void ComposerPage::HeadersTab::slotNewMimeHeader() |
|
{ |
|
QListViewItem *listItem = new QListViewItem( mTagList ); |
|
mTagList->setCurrentItem( listItem ); |
|
mTagList->setSelected( listItem, true ); |
|
emit changed( true ); |
|
} |
|
|
|
|
|
void ComposerPage::HeadersTab::slotRemoveMimeHeader() |
|
{ |
|
// calling this w/o selection is a programming error: |
|
QListViewItem * item = mTagList->selectedItem(); |
|
if ( !item ) { |
|
kdDebug(5006) << "==================================================\n" |
|
<< "Error: Remove button was pressed although no custom header was selected\n" |
|
<< "==================================================\n"; |
|
return; |
|
} |
|
|
|
QListViewItem * below = item->nextSibling(); |
|
delete item; |
|
|
|
if ( below ) |
|
mTagList->setSelected( below, true ); |
|
else if ( mTagList->lastItem() ) |
|
mTagList->setSelected( mTagList->lastItem(), true ); |
|
emit changed( true ); |
|
} |
|
|
|
void ComposerPage::HeadersTab::load() { |
|
KConfigGroup general( KMKernel::config(), "General" ); |
|
|
|
QString suffix = general.readEntry( "myMessageIdSuffix" ); |
|
mMessageIdSuffixEdit->setText( suffix ); |
|
bool state = ( !suffix.isEmpty() && |
|
general.readBoolEntry( "useCustomMessageIdSuffix", false ) ); |
|
mCreateOwnMessageIdCheck->setChecked( state ); |
|
|
|
mTagList->clear(); |
|
mTagNameEdit->clear(); |
|
mTagValueEdit->clear(); |
|
|
|
QListViewItem * item = 0; |
|
|
|
int count = general.readNumEntry( "mime-header-count", 0 ); |
|
for( int i = 0 ; i < count ; i++ ) { |
|
KConfigGroup config( KMKernel::config(), |
|
QCString("Mime #") + QCString().setNum(i) ); |
|
QString name = config.readEntry( "name" ); |
|
QString value = config.readEntry( "value" ); |
|
if( !name.isEmpty() ) |
|
item = new QListViewItem( mTagList, item, name, value ); |
|
} |
|
if ( mTagList->childCount() ) { |
|
mTagList->setCurrentItem( mTagList->firstChild() ); |
|
mTagList->setSelected( mTagList->firstChild(), true ); |
|
} |
|
else { |
|
// disable the "Remove" button |
|
mRemoveHeaderButton->setEnabled( false ); |
|
} |
|
} |
|
|
|
void ComposerPage::HeadersTab::save() { |
|
KConfigGroup general( KMKernel::config(), "General" ); |
|
|
|
general.writeEntry( "useCustomMessageIdSuffix", |
|
mCreateOwnMessageIdCheck->isChecked() ); |
|
general.writeEntry( "myMessageIdSuffix", |
|
mMessageIdSuffixEdit->text() ); |
|
|
|
int numValidEntries = 0; |
|
QListViewItem * item = mTagList->firstChild(); |
|
for ( ; item ; item = item->itemBelow() ) |
|
if( !item->text(0).isEmpty() ) { |
|
KConfigGroup config( KMKernel::config(), QCString("Mime #") |
|
+ QCString().setNum( numValidEntries ) ); |
|
config.writeEntry( "name", item->text( 0 ) ); |
|
config.writeEntry( "value", item->text( 1 ) ); |
|
numValidEntries++; |
|
} |
|
general.writeEntry( "mime-header-count", numValidEntries ); |
|
} |
|
|
|
QString ComposerPage::AttachmentsTab::helpAnchor() const { |
|
return QString::fromLatin1("configure-composer-attachments"); |
|
} |
|
|
|
ComposerPageAttachmentsTab::ComposerPageAttachmentsTab( QWidget * parent, |
|
const char * name ) |
|
: ConfigModuleTab( parent, name ) { |
|
// tmp. vars: |
|
QVBoxLayout *vlay; |
|
QLabel *label; |
|
|
|
vlay = new QVBoxLayout( this, KDialog::marginHint(), KDialog::spacingHint() ); |
|
|
|
// "Outlook compatible attachment naming" check box |
|
mOutlookCompatibleCheck = |
|
new QCheckBox( i18n( "Outlook-compatible attachment naming" ), this ); |
|
mOutlookCompatibleCheck->setChecked( false ); |
|
QToolTip::add( mOutlookCompatibleCheck, i18n( |
|
"Turn this option on to make Outlook(tm) understand attachment names " |
|
"containing non-English characters" ) ); |
|
connect( mOutlookCompatibleCheck, SIGNAL( stateChanged( int ) ), |
|
this, SLOT( slotEmitChanged( void ) ) ); |
|
connect( mOutlookCompatibleCheck, SIGNAL( stateChanged( int ) ), |
|
this, SLOT( slotOutlookCompatibleChanged( int ) ) ); |
|
vlay->addWidget( mOutlookCompatibleCheck ); |
|
vlay->addSpacing( 5 ); |
|
|
|
// "Enable detection of missing attachments" check box |
|
mMissingAttachmentDetectionCheck = |
|
new QCheckBox( i18n("E&nable detection of missing attachments"), this ); |
|
mMissingAttachmentDetectionCheck->setChecked( true ); |
|
connect( mMissingAttachmentDetectionCheck, SIGNAL( stateChanged( int ) ), |
|
this, SLOT( slotEmitChanged( void ) ) ); |
|
vlay->addWidget( mMissingAttachmentDetectionCheck ); |
|
|
|
// "Attachment key words" label and string list editor |
|
label = new QLabel( i18n("Recognize any of the following key words as " |
|
"intention to attach a file:"), this ); |
|
label->setAlignment( AlignLeft|WordBreak ); |
|
vlay->addWidget( label ); |
|
|
|
SimpleStringListEditor::ButtonCode buttonCode = |
|
static_cast<SimpleStringListEditor::ButtonCode>( SimpleStringListEditor::Add | SimpleStringListEditor::Remove | SimpleStringListEditor::Modify ); |
|
mAttachWordsListEditor = |
|
new SimpleStringListEditor( this, 0, buttonCode, |
|
i18n("A&dd..."), i18n("Re&move"), |
|
i18n("Mod&ify..."), |
|
i18n("Enter new key word:") ); |
|
connect( mAttachWordsListEditor, SIGNAL( changed( void ) ), |
|
this, SLOT( slotEmitChanged( void ) ) ); |
|
vlay->addWidget( mAttachWordsListEditor ); |
|
|
|
connect( mMissingAttachmentDetectionCheck, SIGNAL(toggled(bool) ), |
|
label, SLOT(setEnabled(bool)) ); |
|
connect( mMissingAttachmentDetectionCheck, SIGNAL(toggled(bool) ), |
|
mAttachWordsListEditor, SLOT(setEnabled(bool)) ); |
|
} |
|
|
|
void ComposerPage::AttachmentsTab::load() { |
|
KConfigGroup composer( KMKernel::config(), "Composer" ); |
|
|
|
mOutlookCompatibleCheck->setChecked( |
|
composer.readBoolEntry( "outlook-compatible-attachments", false ) ); |
|
mMissingAttachmentDetectionCheck->setChecked( |
|
composer.readBoolEntry( "showForgottenAttachmentWarning", true ) ); |
|
QStringList attachWordsList = |
|
composer.readListEntry( "attachment-keywords" ); |
|
if ( attachWordsList.isEmpty() ) { |
|
// default value |
|
attachWordsList << QString::fromLatin1("attachment") |
|
<< QString::fromLatin1("attached"); |
|
if ( QString::fromLatin1("attachment") != i18n("attachment") ) |
|
attachWordsList << i18n("attachment"); |
|
if ( QString::fromLatin1("attached") != i18n("attached") ) |
|
attachWordsList << i18n("attached"); |
|
} |
|
|
|
mAttachWordsListEditor->setStringList( attachWordsList ); |
|
} |
|
|
|
void ComposerPage::AttachmentsTab::save() { |
|
KConfigGroup composer( KMKernel::config(), "Composer" ); |
|
composer.writeEntry( "outlook-compatible-attachments", |
|
mOutlookCompatibleCheck->isChecked() ); |
|
composer.writeEntry( "showForgottenAttachmentWarning", |
|
mMissingAttachmentDetectionCheck->isChecked() ); |
|
composer.writeEntry( "attachment-keywords", |
|
mAttachWordsListEditor->stringList() ); |
|
} |
|
|
|
void ComposerPageAttachmentsTab::slotOutlookCompatibleChanged( int state ) |
|
{ |
|
if (state == QButton::On) { |
|
KMessageBox::information(0,i18n("You have choosen to " |
|
"encode attachment names containing non-English characters in a way that " |
|
"is understood by Outlook(tm) and other mail clients that do not " |
|
"support standard-compliant encoded attachment names.\n" |
|
"Note that KMail may create non-standard compliant messages, " |
|
"and consequently it is possible that your messages will not be " |
|
"understood by standard-compliant mail clients; so, unless you have no " |
|
"other choice, you should not enable this option." ) ); |
|
} |
|
} |
|
|
|
// ************************************************************* |
|
// * * |
|
// * SecurityPage * |
|
// * * |
|
// ************************************************************* |
|
QString SecurityPage::helpAnchor() const { |
|
return QString::fromLatin1("configure-security"); |
|
} |
|
|
|
SecurityPage::SecurityPage( QWidget * parent, const char * name ) |
|
: ConfigModuleWithTabs( parent, name ) |
|
{ |
|
// |
|
// "Reading" tab: |
|
// |
|
mGeneralTab = new GeneralTab(); // ## TODO rename |
|
addTab( mGeneralTab, i18n("&Reading") ); |
|
|
|
// |
|
// "Composing" tab: |
|
// |
|
mComposerCryptoTab = new ComposerCryptoTab(); |
|
addTab( mComposerCryptoTab, i18n("Composing") ); |
|
|
|
// |
|
// "Warnings" tab: |
|
// |
|
mWarningTab = new WarningTab(); |
|
addTab( mWarningTab, i18n("Warnings") ); |
|
|
|
// |
|
// "S/MIME Validation" tab: |
|
// |
|
mSMimeTab = new SMimeTab(); |
|
addTab( mSMimeTab, i18n("S/MIME &Validation") ); |
|
|
|
// |
|
// "Crypto Backends" tab: |
|
// |
|
mCryptPlugTab = new CryptPlugTab(); |
|
addTab( mCryptPlugTab, i18n("Crypto Backe&nds") ); |
|
load(); |
|
} |
|
|
|
|
|
void SecurityPage::installProfile( KConfig * profile ) { |
|
mGeneralTab->installProfile( profile ); |
|
mComposerCryptoTab->installProfile( profile ); |
|
mWarningTab->installProfile( profile ); |
|
mSMimeTab->installProfile( profile ); |
|
} |
|
|
|
QString SecurityPage::GeneralTab::helpAnchor() const { |
|
return QString::fromLatin1("configure-security-general"); |
|
} |
|
|
|
SecurityPageGeneralTab::SecurityPageGeneralTab( QWidget * parent, const char * name ) |
|
: ConfigModuleTab ( parent, name ) |
|
{ |
|
// tmp. vars: |
|
QVBoxLayout *vlay; |
|
QHBox *hbox; |
|
QGroupBox *group; |
|
QRadioButton *radio; |
|
KActiveLabel *label; |
|
QWidget *w; |
|
QString msg; |
|
|
|
vlay = new QVBoxLayout( this, KDialog::marginHint(), KDialog::spacingHint() ); |
|
|
|
// QWhat'sThis texts |
|
QString htmlWhatsThis = i18n( "<qt><p>Messages sometimes come in both formats. " |
|
"This option controls whether you want the HTML part or the plain " |
|
"text part to be displayed.</p>" |
|
"<p>Displaying the HTML part makes the message look better, " |
|
"but at the same time increases the risk of security holes " |
|
"being exploited.</p>" |
|
"<p>Displaying the plain text part loses much of the message's " |
|
"formatting, but makes it almost <em>impossible</em> " |
|
"to exploit security holes in the HTML renderer (Konqueror).</p>" |
|
"<p>The option below guards against one common misuse of HTML " |
|
"messages, but it cannot guard against security issues that were " |
|
"not known at the time this version of KMail was written.</p>" |
|
"<p>It is therefore advisable to <em>not</em> prefer HTML to " |
|
"plain text.</p>" |
|
"<p><b>Note:</b> You can set this option on a per-folder basis " |
|
"from the <i>Folder</i> menu of KMail's main window.</p></qt>" ); |
|
|
|
QString externalWhatsThis = i18n( "<qt><p>Some mail advertisements are in HTML " |
|
"and contain references to, for example, images that the advertisers" |
|
" employ to find out that you have read their message " |
|
"("web bugs").</p>" |
|
"<p>There is no valid reason to load images off the Internet like " |
|
"this, since the sender can always attach the required images " |
|
"directly to the message.</p>" |
|
"<p>To guard from such a misuse of the HTML displaying feature " |
|
"of KMail, this option is <em>disabled</em> by default.</p>" |
|
"<p>However, if you wish to, for example, view images in HTML " |
|
"messages that were not attached to it, you can enable this " |
|
"option, but you should be aware of the possible problem.</p></qt>" ); |
|
|
|
QString receiptWhatsThis = i18n( "<qt><h3>Message Disposition " |
|
"Notification Policy</h3>" |
|
"<p>MDNs are a generalization of what is commonly called <b>read " |
|
"receipt</b>. The message author requests a disposition " |
|
"notification to be sent and the receiver's mail program " |
|
"generates a reply from which the author can learn what " |
|
"happened to his message. Common disposition types include " |
|
"<b>displayed</b> (i.e. read), <b>deleted</b> and <b>dispatched</b> " |
|
"(e.g. forwarded).</p>" |
|
"<p>The following options are available to control KMail's " |
|
"sending of MDNs:</p>" |
|
"<ul>" |
|
"<li><em>Ignore</em>: Ignores any request for disposition " |
|
"notifications. No MDN will ever be sent automatically " |
|
"(recommended).</li>" |
|
"<li><em>Ask</em>: Answers requests only after asking the user " |
|
"for permission. This way, you can send MDNs for selected " |
|
"messages while denying or ignoring them for others.</li>" |
|
"<li><em>Deny</em>: Always sends a <b>denied</b> notification. This " |
|
"is only <em>slightly</em> better than always sending MDNs. " |
|
"The author will still know that the messages has been acted " |
|
"upon, he just cannot tell whether it was deleted or read etc.</li>" |
|
"<li><em>Always send</em>: Always sends the requested " |
|
"disposition notification. That means that the author of the " |
|
"message gets to know when the message was acted upon and, " |
|
"in addition, what happened to it (displayed, deleted, " |
|
"etc.). This option is strongly discouraged, but since it " |
|
"makes much sense e.g. for customer relationship management, " |
|
"it has been made available.</li>" |
|
"</ul></qt>" ); |
|
|
|
|
|
// "HTML Messages" group box: |
|
group = new QVGroupBox( i18n( "HTML Messages" ), this ); |
|
group->layout()->setSpacing( KDialog::spacingHint() ); |
|
|
|
mHtmlMailCheck = new QCheckBox( i18n("Prefer H&TML to plain text"), group ); |
|
QWhatsThis::add( mHtmlMailCheck, htmlWhatsThis ); |
|
connect( mHtmlMailCheck, SIGNAL( stateChanged( int ) ), |
|
this, SLOT( slotEmitChanged( void ) ) ); |
|
mExternalReferences = new QCheckBox( i18n("Allow messages to load e&xternal " |
|
"references from the Internet" ), group ); |
|
QWhatsThis::add( mExternalReferences, externalWhatsThis ); |
|
connect( mExternalReferences, SIGNAL( stateChanged( int ) ), |
|
this, SLOT( slotEmitChanged( void ) ) ); |
|
label = new KActiveLabel( i18n("<b>WARNING:</b> Allowing HTML in email may " |
|
"increase the risk that your system will be " |
|
"compromised by present and anticipated security " |
|
"exploits. <a href=\"whatsthis:%1\">More about " |
|
"HTML mails...</a> <a href=\"whatsthis:%2\">More " |
|
"about external references...</a>") |
|
.arg(htmlWhatsThis).arg(externalWhatsThis), |
|
group ); |
|
|
|
vlay->addWidget( group ); |
|
|
|
// "Message Disposition Notification" groupbox: |
|
group = new QVGroupBox( i18n("Message Disposition Notifications"), this ); |
|
group->layout()->setSpacing( KDialog::spacingHint() ); |
|
|
|
|
|
// "ignore", "ask", "deny", "always send" radiobutton line: |
|
mMDNGroup = new QButtonGroup( group ); |
|
mMDNGroup->hide(); |
|
connect( mMDNGroup, SIGNAL( clicked( int ) ), |
|
this, SLOT( slotEmitChanged( void ) ) ); |
|
hbox = new QHBox( group ); |
|
hbox->setSpacing( KDialog::spacingHint() ); |
|
|
|
(void)new QLabel( i18n("Send policy:"), hbox ); |
|
|
|
radio = new QRadioButton( i18n("&Ignore"), hbox ); |
|
mMDNGroup->insert( radio ); |
|
|
|
radio = new QRadioButton( i18n("As&k"), hbox ); |
|
mMDNGroup->insert( radio ); |
|
|
|
radio = new QRadioButton( i18n("&Deny"), hbox ); |
|
mMDNGroup->insert( radio ); |
|
|
|
radio = new QRadioButton( i18n("Al&ways send"), hbox ); |
|
mMDNGroup->insert( radio ); |
|
|
|
for ( int i = 0 ; i < mMDNGroup->count() ; ++i ) |
|
QWhatsThis::add( mMDNGroup->find( i ), receiptWhatsThis ); |
|
|
|
w = new QWidget( hbox ); // spacer |
|
hbox->setStretchFactor( w, 1 ); |
|
|
|
// "Original Message quote" radiobutton line: |
|
mOrigQuoteGroup = new QButtonGroup( group ); |
|
mOrigQuoteGroup->hide(); |
|
connect( mOrigQuoteGroup, SIGNAL( clicked( int ) ), |
|
this, SLOT( slotEmitChanged( void ) ) ); |
|
|
|
hbox = new QHBox( group ); |
|
hbox->setSpacing( KDialog::spacingHint() ); |
|
|
|
(void)new QLabel( i18n("Quote original message:"), hbox ); |
|
|
|
radio = new QRadioButton( i18n("Nothin&g"), hbox ); |
|
mOrigQuoteGroup->insert( radio ); |
|
|
|
radio = new QRadioButton( i18n("&Full message"), hbox ); |
|
mOrigQuoteGroup->insert( radio ); |
|
|
|
radio = new QRadioButton( i18n("Onl&y headers"), hbox ); |
|
mOrigQuoteGroup->insert( radio ); |
|
|
|
w = new QWidget( hbox ); |
|
hbox->setStretchFactor( w, 1 ); |
|
|
|
mNoMDNsWhenEncryptedCheck = new QCheckBox( i18n("Do not send MDNs in response to encrypted messages"), group ); |
|
connect( mNoMDNsWhenEncryptedCheck, SIGNAL(toggled(bool)), SLOT(slotEmitChanged()) ); |
|
|
|
// Warning label: |
|
label = new KActiveLabel( i18n("<b>WARNING:</b> Unconditionally returning " |
|
"confirmations undermines your privacy. " |
|
"<a href=\"whatsthis:%1\">More...</a>") |
|
.arg(receiptWhatsThis), |
|
group ); |
|
|
|
vlay->addWidget( group ); |
|
|
|
// "Attached keys" group box: |
|
group = new QVGroupBox( i18n( "Certificate && Key Bundle Attachments" ), this ); |
|
group->layout()->setSpacing( KDialog::spacingHint() ); |
|
|
|
mAutomaticallyImportAttachedKeysCheck = new QCheckBox( i18n("Automatically import keys and certificates"), group ); |
|
connect( mAutomaticallyImportAttachedKeysCheck, SIGNAL(toggled(bool)), SLOT(slotEmitChanged()) ); |
|
|
|
vlay->addWidget( group ); |
|
|
|
|
|
|
|
vlay->addStretch( 10 ); // spacer |
|
} |
|
|
|
void SecurityPage::GeneralTab::load() { |
|
const KConfigGroup reader( KMKernel::config(), "Reader" ); |
|
|
|
mHtmlMailCheck->setChecked( reader.readBoolEntry( "htmlMail", false ) ); |
|
mExternalReferences->setChecked( reader.readBoolEntry( "htmlLoadExternal", false ) ); |
|
mAutomaticallyImportAttachedKeysCheck->setChecked( reader.readBoolEntry( "AutoImportKeys", false ) ); |
|
|
|
const KConfigGroup mdn( KMKernel::config(), "MDN" ); |
|
|
|
int num = mdn.readNumEntry( "default-policy", 0 ); |
|
if ( num < 0 || num >= mMDNGroup->count() ) num = 0; |
|
mMDNGroup->setButton( num ); |
|
num = mdn.readNumEntry( "quote-message", 0 ); |
|
if ( num < 0 || num >= mOrigQuoteGroup->count() ) num = 0; |
|
mOrigQuoteGroup->setButton( num ); |
|
mNoMDNsWhenEncryptedCheck->setChecked(mdn.readBoolEntry( "not-send-when-encrypted", true )); |
|
} |
|
|
|
void SecurityPage::GeneralTab::installProfile( KConfig * profile ) { |
|
const KConfigGroup reader( profile, "Reader" ); |
|
const KConfigGroup mdn( profile, "MDN" ); |
|
|
|
if ( reader.hasKey( "htmlMail" ) ) |
|
mHtmlMailCheck->setChecked( reader.readBoolEntry( "htmlMail" ) ); |
|
if ( reader.hasKey( "htmlLoadExternal" ) ) |
|
mExternalReferences->setChecked( reader.readBoolEntry( "htmlLoadExternal" ) ); |
|
if ( reader.hasKey( "AutoImportKeys" ) ) |
|
mAutomaticallyImportAttachedKeysCheck->setChecked( reader.readBoolEntry( "AutoImportKeys" ) ); |
|
|
|
if ( mdn.hasKey( "default-policy" ) ) { |
|
int num = mdn.readNumEntry( "default-policy" ); |
|
if ( num < 0 || num >= mMDNGroup->count() ) num = 0; |
|
mMDNGroup->setButton( num ); |
|
} |
|
if ( mdn.hasKey( "quote-message" ) ) { |
|
int num = mdn.readNumEntry( "quote-message" ); |
|
if ( num < 0 || num >= mOrigQuoteGroup->count() ) num = 0; |
|
mOrigQuoteGroup->setButton( num ); |
|
} |
|
if ( mdn.hasKey( "not-send-when-encrypted" ) ) |
|
mNoMDNsWhenEncryptedCheck->setChecked(mdn.readBoolEntry( "not-send-when-encrypted" )); |
|
} |
|
|
|
void SecurityPage::GeneralTab::save() { |
|
KConfigGroup reader( KMKernel::config(), "Reader" ); |
|
KConfigGroup mdn( KMKernel::config(), "MDN" ); |
|
|
|
if (reader.readBoolEntry( "htmlMail", false ) != mHtmlMailCheck->isChecked()) |
|
{ |
|
if (KMessageBox::warningContinueCancel(this, i18n("Changing the global " |
|
"HTML setting will override all folder specific values."), QString::null, |
|
QString::null, "htmlMailOverride") == KMessageBox::Continue) |
|
{ |
|
reader.writeEntry( "htmlMail", mHtmlMailCheck->isChecked() ); |
|
QStringList names; |
|
QValueList<QGuardedPtr<KMFolder> > folders; |
|
kmkernel->folderMgr()->createFolderList(&names, &folders); |
|
kmkernel->imapFolderMgr()->createFolderList(&names, &folders); |
|
kmkernel->dimapFolderMgr()->createFolderList(&names, &folders); |
|
kmkernel->searchFolderMgr()->createFolderList(&names, &folders); |
|
for (QValueList<QGuardedPtr<KMFolder> >::iterator it = folders.begin(); |
|
it != folders.end(); ++it) |
|
{ |
|
if (*it) |
|
{ |
|
KConfigGroupSaver saver(KMKernel::config(), |
|
"Folder-" + (*it)->idString()); |
|
KMKernel::config()->writeEntry("htmlMailOverride", false); |
|
} |
|
} |
|
} |
|
} |
|
reader.writeEntry( "htmlLoadExternal", mExternalReferences->isChecked() ); |
|
reader.writeEntry( "AutoImportKeys", mAutomaticallyImportAttachedKeysCheck->isChecked() ); |
|
mdn.writeEntry( "default-policy", mMDNGroup->id( mMDNGroup->selected() ) ); |
|
mdn.writeEntry( "quote-message", mOrigQuoteGroup->id( mOrigQuoteGroup->selected() ) ); |
|
mdn.writeEntry( "not-send-when-encrypted", mNoMDNsWhenEncryptedCheck->isChecked() ); |
|
} |
|
|
|
|
|
QString SecurityPage::ComposerCryptoTab::helpAnchor() const { |
|
return QString::fromLatin1("configure-security-pgp"); // change... |
|
} |
|
|
|
SecurityPageComposerCryptoTab::SecurityPageComposerCryptoTab( QWidget * parent, const char * name ) |
|
: ConfigModuleTab ( parent, name ) |
|
{ |
|
// the margins are inside mWidget itself |
|
QVBoxLayout* vlay = new QVBoxLayout( this, 0, 0 ); |
|
|
|
mWidget = new ComposerCryptoConfiguration( this ); |
|
vlay->addWidget( mWidget ); |
|
} |
|
|
|
void SecurityPage::ComposerCryptoTab::load() { |
|
const KConfigGroup composer( KMKernel::config(), "Composer" ); |
|
|
|
// If you change default values, sync messagecomposer.cpp too |
|
|
|
mWidget->mAutoSignature->setChecked( composer.readBoolEntry( "pgp-auto-sign", false ) ); |
|
|
|
mWidget->mEncToSelf->setChecked( composer.readBoolEntry( "crypto-encrypt-to-self", true ) ); |
|
mWidget->mShowEncryptionResult->setChecked( false ); //composer.readBoolEntry( "crypto-show-encryption-result", true ) ); |
|
mWidget->mShowEncryptionResult->hide(); |
|
mWidget->mShowKeyApprovalDlg->setChecked( composer.readBoolEntry( "crypto-show-keys-for-approval", true ) ); |
|
|
|
mWidget->mAutoEncrypt->setChecked( composer.readBoolEntry( "pgp-auto-encrypt", false ) ); |
|
mWidget->mNeverEncryptWhenSavingInDrafts->setChecked( composer.readBoolEntry( "never-encrypt-drafts", true ) ); |
|
|
|
mWidget->mStoreEncrypted->setChecked( composer.readBoolEntry( "crypto-store-encrypted", true ) ); |
|
} |
|
|
|
void SecurityPage::ComposerCryptoTab::installProfile( KConfig * profile ) { |
|
const KConfigGroup composer( profile, "Composer" ); |
|
|
|
if ( composer.hasKey( "pgp-auto-sign" ) ) |
|
mWidget->mAutoSignature->setChecked( composer.readBoolEntry( "pgp-auto-sign" ) ); |
|
|
|
if ( composer.hasKey( "crypto-encrypt-to-self" ) ) |
|
mWidget->mEncToSelf->setChecked( composer.readBoolEntry( "crypto-encrypt-to-self" ) ); |
|
if ( composer.hasKey( "crypto-show-encryption-result" ) ) |
|
mWidget->mShowEncryptionResult->setChecked( composer.readBoolEntry( "crypto-show-encryption-result" ) ); |
|
if ( composer.hasKey( "crypto-show-keys-for-approval" ) ) |
|
mWidget->mShowKeyApprovalDlg->setChecked( composer.readBoolEntry( "crypto-show-keys-for-approval" ) ); |
|
if ( composer.hasKey( "pgp-auto-encrypt" ) ) |
|
mWidget->mAutoEncrypt->setChecked( composer.readBoolEntry( "pgp-auto-encrypt" ) ); |
|
if ( composer.hasKey( "never-encrypt-drafts" ) ) |
|
mWidget->mNeverEncryptWhenSavingInDrafts->setChecked( composer.readBoolEntry( "never-encrypt-drafts" ) ); |
|
|
|
if ( composer.hasKey( "crypto-store-encrypted" ) ) |
|
mWidget->mStoreEncrypted->setChecked( composer.readBoolEntry( "crypto-store-encrypted" ) ); |
|
} |
|
|
|
void SecurityPage::ComposerCryptoTab::save() { |
|
KConfigGroup composer( KMKernel::config(), "Composer" ); |
|
|
|
composer.writeEntry( "pgp-auto-sign", mWidget->mAutoSignature->isChecked() ); |
|
|
|
composer.writeEntry( "crypto-encrypt-to-self", mWidget->mEncToSelf->isChecked() ); |
|
composer.writeEntry( "crypto-show-encryption-result", mWidget->mShowEncryptionResult->isChecked() ); |
|
composer.writeEntry( "crypto-show-keys-for-approval", mWidget->mShowKeyApprovalDlg->isChecked() ); |
|
|
|
composer.writeEntry( "pgp-auto-encrypt", mWidget->mAutoEncrypt->isChecked() ); |
|
composer.writeEntry( "never-encrypt-drafts", mWidget->mNeverEncryptWhenSavingInDrafts->isChecked() ); |
|
|
|
composer.writeEntry( "crypto-store-encrypted", mWidget->mStoreEncrypted->isChecked() ); |
|
} |
|
|
|
QString SecurityPage::WarningTab::helpAnchor() const { |
|
return QString::fromLatin1("configure-security-pgp"); // to be updated |
|
} |
|
|
|
SecurityPageWarningTab::SecurityPageWarningTab( QWidget * parent, const char * name ) |
|
: ConfigModuleTab( parent, name ) |
|
{ |
|
// the margins are inside mWidget itself |
|
QVBoxLayout* vlay = new QVBoxLayout( this, 0, 0 ); |
|
|
|
mWidget = new WarningConfiguration( this ); |
|
vlay->addWidget( mWidget ); |
|
|
|
connect( mWidget->enableAllWarningsPB, SIGNAL(clicked()), |
|
SLOT(slotReenableAllWarningsClicked()) ); |
|
} |
|
|
|
void SecurityPage::WarningTab::load() { |
|
const KConfigGroup composer( KMKernel::config(), "Composer" ); |
|
|
|
mWidget->warnUnencryptedCB->setChecked( composer.readBoolEntry( "crypto-warning-unencrypted", false ) ); |
|
mWidget->mWarnUnsigned->setChecked( composer.readBoolEntry( "crypto-warning-unsigned", false ) ); |
|
mWidget->warnReceiverNotInCertificateCB->setChecked( composer.readBoolEntry( "crypto-warn-recv-not-in-cert", true ) ); |
|
|
|
mWidget->mWarnSignKeyExpiresSB->setValue( composer.readNumEntry( "crypto-warn-sign-key-near-expire-int", 14 ) ); |
|
mWidget->mWarnSignChainCertExpiresSB->setValue( composer.readNumEntry( "crypto-warn-sign-chaincert-near-expire-int", 14 ) ); |
|
mWidget->mWarnSignRootCertExpiresSB->setValue( composer.readNumEntry( "crypto-warn-sign-root-near-expire-int", 14 ) ); |
|
|
|
mWidget->mWarnEncrKeyExpiresSB->setValue( composer.readNumEntry( "crypto-warn-encr-key-near-expire-int", 14 ) ); |
|
mWidget->mWarnEncrChainCertExpiresSB->setValue( composer.readNumEntry( "crypto-warn-encr-chaincert-near-expire-int", 14 ) ); |
|
mWidget->mWarnEncrRootCertExpiresSB->setValue( composer.readNumEntry( "crypto-warn-encr-root-near-expire-int", 14 ) ); |
|
|
|
mWidget->enableAllWarningsPB->setEnabled( true ); |
|
} |
|
|
|
void SecurityPage::WarningTab::installProfile( KConfig * profile ) { |
|
const KConfigGroup composer( profile, "Composer" ); |
|
|
|
if ( composer.hasKey( "crypto-warning-unencrypted" ) ) |
|
mWidget->warnUnencryptedCB->setChecked( composer.readBoolEntry( "crypto-warning-unencrypted" ) ); |
|
if ( composer.hasKey( "crypto-warning-unsigned" ) ) |
|
mWidget->mWarnUnsigned->setChecked( composer.readBoolEntry( "crypto-warning-unsigned" ) ); |
|
if ( composer.hasKey( "crypto-warn-recv-not-in-cert" ) ) |
|
mWidget->warnReceiverNotInCertificateCB->setChecked( composer.readBoolEntry( "crypto-warn-recv-not-in-cert" ) ); |
|
|
|
if ( composer.hasKey( "crypto-warn-sign-key-near-expire-int" ) ) |
|
mWidget->mWarnSignKeyExpiresSB->setValue( composer.readBoolEntry( "crypto-warn-sign-key-near-expire-int" ) ); |
|
if ( composer.hasKey( "crypto-warn-sign-chaincert-near-expire-int" ) ) |
|
mWidget->mWarnSignChainCertExpiresSB->setValue( composer.readBoolEntry( "crypto-warn-sign-chaincert-near-expire-int" ) ); |
|
if ( composer.hasKey( "crypto-warn-sign-root-near-expire-int" ) ) |
|
mWidget->mWarnSignRootCertExpiresSB->setValue( composer.readBoolEntry( "crypto-warn-sign-root-near-expire-int" ) ); |
|
|
|
if ( composer.hasKey( "crypto-warn-encr-key-near-expire-int" ) ) |
|
mWidget->mWarnEncrKeyExpiresSB->setValue( composer.readNumEntry( "crypto-warn-encr-key-near-expire-int" ) ); |
|
if ( composer.hasKey( "crypto-warn-encr-chaincert-near-expire-int" ) ) |
|
mWidget->mWarnEncrChainCertExpiresSB->setValue( composer.readNumEntry( "crypto-warn-encr-chaincert-near-expire-int" ) ); |
|
if ( composer.hasKey( "crypto-warn-encr-root-near-expire-int" ) ) |
|
mWidget->mWarnEncrRootCertExpiresSB->setValue( composer.readNumEntry( "crypto-warn-encr-root-near-expire-int" ) ); |
|
} |
|
|
|
void SecurityPage::WarningTab::save() { |
|
KConfigGroup composer( KMKernel::config(), "Composer" ); |
|
|
|
composer.writeEntry( "crypto-warn-recv-not-in-cert", mWidget->warnReceiverNotInCertificateCB->isChecked() ); |
|
composer.writeEntry( "crypto-warning-unencrypted", mWidget->warnUnencryptedCB->isChecked() ); |
|
composer.writeEntry( "crypto-warning-unsigned", mWidget->mWarnUnsigned->isChecked() ); |
|
|
|
composer.writeEntry( "crypto-warn-sign-key-near-expire-int", |
|
mWidget->mWarnSignKeyExpiresSB->value() ); |
|
composer.writeEntry( "crypto-warn-sign-chaincert-near-expire-int", |
|
mWidget->mWarnSignChainCertExpiresSB->value() ); |
|
composer.writeEntry( "crypto-warn-sign-root-near-expire-int", |
|
mWidget->mWarnSignRootCertExpiresSB->value() ); |
|
|
|
composer.writeEntry( "crypto-warn-encr-key-near-expire-int", |
|
mWidget->mWarnEncrKeyExpiresSB->value() ); |
|
composer.writeEntry( "crypto-warn-encr-chaincert-near-expire-int", |
|
mWidget->mWarnEncrChainCertExpiresSB->value() ); |
|
composer.writeEntry( "crypto-warn-encr-root-near-expire-int", |
|
mWidget->mWarnEncrRootCertExpiresSB->value() ); |
|
} |
|
|
|
void SecurityPage::WarningTab::slotReenableAllWarningsClicked() { |
|
KMessageBox::enableAllMessages(); |
|
mWidget->enableAllWarningsPB->setEnabled( false ); |
|
} |
|
|
|
//// |
|
|
|
QString SecurityPage::SMimeTab::helpAnchor() const { |
|
return QString::fromLatin1("configure-security-pgp"); // to be updated |
|
} |
|
|
|
SecurityPageSMimeTab::SecurityPageSMimeTab( QWidget * parent, const char * name ) |
|
: ConfigModuleTab( parent, name ) |
|
{ |
|
// the margins are inside mWidget itself |
|
QVBoxLayout* vlay = new QVBoxLayout( this, 0, 0 ); |
|
|
|
mWidget = new SMimeConfiguration( this ); |
|
vlay->addWidget( mWidget ); |
|
|
|
// Button-group for exclusive radiobuttons |
|
QButtonGroup* bg = new QButtonGroup( mWidget ); |
|
bg->hide(); |
|
bg->insert( mWidget->CRLRB ); |
|
bg->insert( mWidget->OCSPRB ); |
|
|
|
// Settings for the keyrequester custom widget |
|
mWidget->OCSPResponderSignature->setAllowedKeys( Kleo::SigningKeyRequester::SMIME ); |
|
mWidget->OCSPResponderSignature->setMultipleKeysEnabled( false ); |
|
|
|
mConfig = Kleo::CryptoBackendFactory::instance()->config(); |
|
} |
|
|
|
void SecurityPage::SMimeTab::load() { |
|
if ( !mConfig ) { |
|
setEnabled( false ); |
|
return; |
|
} |
|
// Checkboxes |
|
mCheckUsingOCSPConfigEntry = configEntry( "gpgsm", "Security", "enable-ocsp", Kleo::CryptoConfigEntry::ArgType_None, false ); |
|
mEnableOCSPsendingConfigEntry = configEntry( "dirmngr", "OCSP", "allow-ocsp", Kleo::CryptoConfigEntry::ArgType_None, false ); |
|
mDoNotCheckCertPolicyConfigEntry = configEntry( "gpgsm", "Security", "disable-policy-checks", Kleo::CryptoConfigEntry::ArgType_None, false ); |
|
mNeverConsultConfigEntry = configEntry( "gpgsm", "Security", "disable-crl-checks", Kleo::CryptoConfigEntry::ArgType_None, false ); |
|
mFetchMissingConfigEntry = configEntry( "gpgsm", "Security", "auto-issuer-key-retrieve", Kleo::CryptoConfigEntry::ArgType_None, false ); |
|
// Other widgets |
|
mOCSPResponderURLConfigEntry = configEntry( "dirmngr", "OCSP", "ocsp-responder", Kleo::CryptoConfigEntry::ArgType_String, false ); |
|
mOCSPResponderSignature = configEntry( "dirmngr", "OCSP", "ocsp-signer", Kleo::CryptoConfigEntry::ArgType_String, false ); |
|
|
|
// Initialize GUI items from the config entries |
|
|
|
if ( mCheckUsingOCSPConfigEntry ) { |
|
bool b = mCheckUsingOCSPConfigEntry->boolValue(); |
|
mWidget->OCSPRB->setChecked( b ); |
|
mWidget->CRLRB->setChecked( !b ); |
|
mWidget->OCSPGroupBox->setEnabled( b ); |
|
} |
|
if ( mDoNotCheckCertPolicyConfigEntry ) |
|
mWidget->doNotCheckCertPolicyCB->setChecked( mDoNotCheckCertPolicyConfigEntry->boolValue() ); |
|
if ( mNeverConsultConfigEntry ) |
|
mWidget->neverConsultCB->setChecked( mNeverConsultConfigEntry->boolValue() ); |
|
if ( mFetchMissingConfigEntry ) |
|
mWidget->fetchMissingCB->setChecked( mFetchMissingConfigEntry->boolValue() ); |
|
|
|
if ( mOCSPResponderURLConfigEntry ) |
|
mWidget->OCSPResponderURL->setText( mOCSPResponderURLConfigEntry->stringValue() ); |
|
if ( mOCSPResponderSignature ) { |
|
mWidget->OCSPResponderSignature->setFingerprint( mOCSPResponderSignature->stringValue() ); |
|
} |
|
} |
|
|
|
void SecurityPage::SMimeTab::installProfile( KConfig * ) { |
|
} |
|
|
|
void SecurityPage::SMimeTab::save() { |
|
if ( !mConfig ) { |
|
return; |
|
} |
|
bool b = mWidget->OCSPRB->isChecked(); |
|
if ( mCheckUsingOCSPConfigEntry && mCheckUsingOCSPConfigEntry->boolValue() != b ) |
|
mCheckUsingOCSPConfigEntry->setBoolValue( b ); |
|
// Set allow-ocsp together with enable-ocsp |
|
if ( mEnableOCSPsendingConfigEntry && mEnableOCSPsendingConfigEntry->boolValue() != b ) |
|
mEnableOCSPsendingConfigEntry->setBoolValue( b ); |
|
|
|
b = mWidget->doNotCheckCertPolicyCB->isChecked(); |
|
if ( mDoNotCheckCertPolicyConfigEntry && mDoNotCheckCertPolicyConfigEntry->boolValue() != b ) |
|
mDoNotCheckCertPolicyConfigEntry->setBoolValue( b ); |
|
|
|
b = mWidget->neverConsultCB->isChecked(); |
|
if ( mNeverConsultConfigEntry && mNeverConsultConfigEntry->boolValue() != b ) |
|
mNeverConsultConfigEntry->setBoolValue( b ); |
|
|
|
b = mWidget->fetchMissingCB->isChecked(); |
|
if ( mFetchMissingConfigEntry && mFetchMissingConfigEntry->boolValue() != b ) |
|
mFetchMissingConfigEntry->setBoolValue( b ); |
|
|
|
QString txt = mWidget->OCSPResponderURL->text(); |
|
if ( mOCSPResponderURLConfigEntry && mOCSPResponderURLConfigEntry->stringValue() != txt ) |
|
mOCSPResponderURLConfigEntry->setStringValue( txt ); |
|
|
|
txt = mWidget->OCSPResponderSignature->fingerprint(); |
|
if ( mOCSPResponderSignature && mOCSPResponderSignature->stringValue() != txt ) { |
|
mOCSPResponderSignature->setStringValue( txt ); |
|
} |
|
mConfig->sync( true ); |
|
} |
|
|
|
Kleo::CryptoConfigEntry* SecurityPage::SMimeTab::configEntry( const char* componentName, |
|
const char* groupName, |
|
const char* entryName, |
|
int /*Kleo::CryptoConfigEntry::ArgType*/ argType, |
|
bool isList ) |
|
{ |
|
Kleo::CryptoConfigEntry* entry = mConfig->entry( componentName, groupName, entryName ); |
|
if ( !entry ) { |
|
KMessageBox::error( this, i18n( "Backend error: gpgconf doesn't seem to know the entry for %1/%2/%3" ).arg( componentName, groupName, entryName ) ); |
|
return 0; |
|
} |
|
if( entry->argType() != argType || entry->isList() != isList ) { |
|
KMessageBox::error( this, i18n( "Backend error: gpgconf has wrong type for %1/%2/%3: %4 %5" ).arg( componentName, groupName, entryName ).arg( entry->argType() ).arg( entry->isList() ) ); |
|
return 0; |
|
} |
|
return entry; |
|
} |
|
|
|
QString SecurityPage::CryptPlugTab::helpAnchor() const { |
|
return QString::null; |
|
} |
|
|
|
SecurityPageCryptPlugTab::SecurityPageCryptPlugTab( QWidget * parent, const char * name ) |
|
: ConfigModuleTab( parent, name ) |
|
{ |
|
QVBoxLayout * vlay = new QVBoxLayout( this, KDialog::marginHint(), KDialog::spacingHint() ); |
|
|
|
mBackendConfig = Kleo::CryptoBackendFactory::instance()->configWidget( this, "mBackendConfig" ); |
|
|
|
vlay->addWidget( mBackendConfig ); |
|
} |
|
|
|
SecurityPageCryptPlugTab::~SecurityPageCryptPlugTab() |
|
{ |
|
|
|
} |
|
|
|
void SecurityPage::CryptPlugTab::load() { |
|
mBackendConfig->load(); |
|
} |
|
|
|
void SecurityPage::CryptPlugTab::save() { |
|
mBackendConfig->save(); |
|
} |
|
|
|
// ************************************************************* |
|
// * * |
|
// * MiscPage * |
|
// * * |
|
// ************************************************************* |
|
QString MiscPage::helpAnchor() const { |
|
return QString::fromLatin1("configure-misc"); |
|
} |
|
|
|
MiscPage::MiscPage( QWidget * parent, const char * name ) |
|
: ConfigModuleWithTabs( parent, name ) |
|
{ |
|
mFolderTab = new FolderTab(); |
|
addTab( mFolderTab, i18n("&Folders") ); |
|
|
|
mGroupwareTab = new GroupwareTab(); |
|
addTab( mGroupwareTab, i18n("&Groupware") ); |
|
load(); |
|
} |
|
|
|
QString MiscPage::FolderTab::helpAnchor() const { |
|
return QString::fromLatin1("configure-misc-folders"); |
|
} |
|
|
|
MiscPageFolderTab::MiscPageFolderTab( QWidget * parent, const char * name ) |
|
: ConfigModuleTab( parent, name ) |
|
{ |
|
// temp. vars: |
|
QVBoxLayout *vlay; |
|
QHBoxLayout *hlay; |
|
QGroupBox *group; |
|
QLabel *label; |
|
|
|
vlay = new QVBoxLayout( this, KDialog::marginHint(), KDialog::spacingHint() ); |
|
|
|
// "confirm before emptying folder" check box: stretch 0 |
|
mEmptyFolderConfirmCheck = |
|
new QCheckBox( i18n("Corresponds to Folder->Move All Messages to Trash", |
|
"Ask for co&nfirmation before moving all messages to " |
|
"trash"), |
|
this ); |
|
vlay->addWidget( mEmptyFolderConfirmCheck ); |
|
connect( mEmptyFolderConfirmCheck, SIGNAL( stateChanged( int ) ), |
|
this, SLOT( slotEmitChanged( void ) ) ); |
|
mExcludeImportantFromExpiry = |
|
new QCheckBox( i18n("E&xclude important messages from expiry"), this ); |
|
vlay->addWidget( mExcludeImportantFromExpiry ); |
|
connect( mExcludeImportantFromExpiry, SIGNAL( stateChanged( int ) ), |
|
this, SLOT( slotEmitChanged( void ) ) ); |
|
|
|
// "when trying to find unread messages" combo + label: stretch 0 |
|
hlay = new QHBoxLayout( vlay ); // inherits spacing |
|
mLoopOnGotoUnread = new QComboBox( false, this ); |
|
label = new QLabel( mLoopOnGotoUnread, |
|
i18n("to be continued with \"do not loop\", \"loop in current folder\", " |
|
"and \"loop in all folders\".", |
|
"When trying to find unread messages:"), this ); |
|
mLoopOnGotoUnread->insertStringList( QStringList() |
|
<< i18n("continuation of \"When trying to find unread messages:\"", |
|
"Do not Loop") |
|
<< i18n("continuation of \"When trying to find unread messages:\"", |
|
"Loop in Current Folder") |
|
<< i18n("continuation of \"When trying to find unread messages:\"", |
|
"Loop in All Folders")); |
|
hlay->addWidget( label ); |
|
hlay->addWidget( mLoopOnGotoUnread, 1 ); |
|
connect( mLoopOnGotoUnread, SIGNAL( activated( int ) ), |
|
this, SLOT( slotEmitChanged( void ) ) ); |
|
|
|
mJumpToUnread = |
|
new QCheckBox( i18n("&Jump to first unread message when entering a " |
|
"folder"), this ); |
|
vlay->addWidget( mJumpToUnread ); |
|
connect( mJumpToUnread, SIGNAL( stateChanged( int ) ), |
|
this, SLOT( slotEmitChanged( void ) ) ); |
|
|
|
hlay = new QHBoxLayout( vlay ); // inherits spacing |
|
mDelayedMarkAsRead = new QCheckBox( i18n("Mar&k selected message as read after"), this ); |
|
hlay->addWidget( mDelayedMarkAsRead ); |
|
mDelayedMarkTime = new KIntSpinBox( 0 /*min*/, 60 /*max*/, 1/*step*/, |
|
0 /*init*/, 10 /*base*/, this); |
|
mDelayedMarkTime->setSuffix( i18n(" sec") ); |
|
mDelayedMarkTime->setEnabled( false ); // since mDelayedMarkAsREad is off |
|
hlay->addWidget( mDelayedMarkTime ); |
|
hlay->addStretch( 1 ); |
|
connect( mDelayedMarkTime, SIGNAL( valueChanged( int ) ), |
|
this, SLOT( slotEmitChanged( void ) ) ); |
|
connect( mDelayedMarkAsRead, SIGNAL(toggled(bool)), |
|
mDelayedMarkTime, SLOT(setEnabled(bool))); |
|
connect( mDelayedMarkAsRead, SIGNAL(toggled(bool)), |
|
this , SLOT(slotEmitChanged( void ))); |
|
|
|
// "show popup after Drag'n'Drop" checkbox: stretch 0 |
|
mShowPopupAfterDnD = |
|
new QCheckBox( i18n("Ask for action after &dragging messages to another folder"), this ); |
|
vlay->addWidget( mShowPopupAfterDnD ); |
|
connect( mShowPopupAfterDnD, SIGNAL( stateChanged( int ) ), |
|
this, SLOT( slotEmitChanged( void ) ) ); |
|
|
|
// "default mailbox format" combo + label: stretch 0 |
|
hlay = new QHBoxLayout( vlay ); // inherits spacing |
|
mMailboxPrefCombo = new QComboBox( false, this ); |
|
label = new QLabel( mMailboxPrefCombo, |
|
i18n("to be continued with \"flat files\" and " |
|
"\"directories\", resp.", |
|
"By default, &message folders on disk are:"), this ); |
|
mMailboxPrefCombo->insertStringList( QStringList() |
|
<< i18n("continuation of \"By default, &message folders on disk are\"", |
|
"Flat Files (\"mbox\" format)") |
|
<< i18n("continuation of \"By default, &message folders on disk are\"", |
|
"Directories (\"maildir\" format)") ); |
|
hlay->addWidget( label ); |
|
hlay->addWidget( mMailboxPrefCombo, 1 ); |
|
connect( mMailboxPrefCombo, SIGNAL( activated( int ) ), |
|
this, SLOT( slotEmitChanged( void ) ) ); |
|
|
|
// "On startup..." option: |
|
hlay = new QHBoxLayout( vlay ); // inherits spacing |
|
mOnStartupOpenFolder = new KMFolderComboBox( this ); |
|
label = new QLabel( mOnStartupOpenFolder, |
|
i18n("Open this folder on startup:"), this ); |
|
hlay->addWidget( label ); |
|
hlay->addWidget( mOnStartupOpenFolder, 1 ); |
|
connect( mOnStartupOpenFolder, SIGNAL( activated( int ) ), |
|
this, SLOT( slotEmitChanged( void ) ) ); |
|
|
|
// "On exit..." groupbox: |
|
group = new QVGroupBox( i18n("On Program Exit, " |
|
"Perform Following Tasks"), this ); |
|
group->layout()->setSpacing( KDialog::spacingHint() ); |
|
mCompactOnExitCheck = new QCheckBox( i18n("Com&pact all folders"), group ); |
|
mEmptyTrashCheck = new QCheckBox( i18n("Empty &trash"), group ); |
|
|
|
connect( mCompactOnExitCheck, SIGNAL( stateChanged( int ) ), |
|
this, SLOT( slotEmitChanged( void ) ) ); |
|
connect( mEmptyTrashCheck, SIGNAL( stateChanged( int ) ), |
|
this, SLOT( slotEmitChanged( void ) ) ); |
|
|
|
vlay->addWidget( group ); |
|
vlay->addStretch( 1 ); |
|
|
|
// and now: add QWhatsThis: |
|
QString msg = i18n( "what's this help", |
|
"<qt><p>This selects which mailbox format will be " |
|
"the default for local folders:</p>" |
|
"<p><b>mbox:</b> KMail's mail " |
|
"folders are represented by a single file each. " |
|
"Individual messages are separated from each other by a " |
|
"line starting with \"From \". This saves space on " |
|
"disk, but may be less robust, e.g. when moving messages " |
|
"between folders.</p>" |
|
"<p><b>maildir:</b> KMail's mail folders are " |
|
"represented by real folders on disk. Individual messages " |
|
"are separate files. This may waste a bit of space on " |
|
"disk, but should be more robust, e.g. when moving " |
|
"messages between folders.</p></qt>"); |
|
QWhatsThis::add( mMailboxPrefCombo, msg ); |
|
QWhatsThis::add( label, msg ); |
|
|
|
msg = i18n( "what's this help", |
|
"<qt><p>When jumping to the next unread message, it may occur " |
|
"that no more unread messages are below the current message.</p>" |
|
"<p><b>Do not loop:</b> The search will stop at the last message in " |
|
"the current folder.</p>" |
|
"<p><b>Loop in current folder:</b> The search will continue at the " |
|
"top of the message list, but not go to another folder.</p>" |
|
"<p><b>Loop in all folders:</b> The search will continue at the top of " |
|
"the message list. If no unread messages are found it will then continue " |
|
"to the next folder.</p>" |
|
"<p>Similarly, when searching for the previous unread message, " |
|
"the search will start from the bottom of the message list and continue to " |
|
"the previous folder depending on which option is selected.</p></qt>" ); |
|
QWhatsThis::add( mLoopOnGotoUnread, msg ); |
|
} |
|
|
|
void MiscPage::FolderTab::load() { |
|
KConfigGroup general( KMKernel::config(), "General" ); |
|
|
|
mEmptyTrashCheck->setChecked( general.readBoolEntry( "empty-trash-on-exit", true ) ); |
|
mExcludeImportantFromExpiry->setChecked( GlobalSettings::excludeImportantMailFromExpiry() ); |
|
mOnStartupOpenFolder->setFolder( general.readEntry( "startupFolder", |
|
kmkernel->inboxFolder()->idString() ) ); |
|
mCompactOnExitCheck->setChecked( general.readBoolEntry( "compact-all-on-exit", true ) ); |
|
mEmptyFolderConfirmCheck->setChecked( general.readBoolEntry( "confirm-before-empty", true ) ); |
|
// default = "Loop in current folder" |
|
|
|
mLoopOnGotoUnread->setCurrentItem( GlobalSettings::loopOnGotoUnread() ); |
|
mJumpToUnread->setChecked( GlobalSettings::jumpToUnread() ); |
|
mDelayedMarkAsRead->setChecked( GlobalSettings::delayedMarkAsRead() ); |
|
mDelayedMarkTime->setValue( GlobalSettings::delayedMarkTime() ); |
|
mShowPopupAfterDnD->setChecked( GlobalSettings::showPopupAfterDnD() ); |
|
|
|
int num = general.readNumEntry("default-mailbox-format", 1 ); |
|
if ( num < 0 || num > 1 ) num = 1; |
|
mMailboxPrefCombo->setCurrentItem( num ); |
|
} |
|
|
|
void MiscPage::FolderTab::save() { |
|
KConfigGroup general( KMKernel::config(), "General" ); |
|
|
|
general.writeEntry( "empty-trash-on-exit", mEmptyTrashCheck->isChecked() ); |
|
general.writeEntry( "compact-all-on-exit", mCompactOnExitCheck->isChecked() ); |
|
general.writeEntry( "confirm-before-empty", mEmptyFolderConfirmCheck->isChecked() ); |
|
general.writeEntry( "default-mailbox-format", mMailboxPrefCombo->currentItem() ); |
|
general.writeEntry( "startupFolder", mOnStartupOpenFolder->getFolder() ? |
|
mOnStartupOpenFolder->getFolder()->idString() : QString::null ); |
|
|
|
GlobalSettings::setDelayedMarkAsRead( mDelayedMarkAsRead->isChecked() ); |
|
GlobalSettings::setDelayedMarkTime( mDelayedMarkTime->value() ); |
|
GlobalSettings::setJumpToUnread( mJumpToUnread->isChecked() ); |
|
GlobalSettings::setLoopOnGotoUnread( mLoopOnGotoUnread->currentItem() ); |
|
GlobalSettings::setShowPopupAfterDnD( mShowPopupAfterDnD->isChecked() ); |
|
GlobalSettings::setExcludeImportantMailFromExpiry( |
|
mExcludeImportantFromExpiry->isChecked() ); |
|
} |
|
|
|
QString MiscPage::GroupwareTab::helpAnchor() const { |
|
return QString::fromLatin1("configure-misc-groupware"); |
|
} |
|
|
|
MiscPageGroupwareTab::MiscPageGroupwareTab( QWidget* parent, const char* name ) |
|
: ConfigModuleTab( parent, name ) |
|
{ |
|
QBoxLayout* vlay = new QVBoxLayout( this, KDialog::marginHint(), |
|
KDialog::spacingHint() ); |
|
vlay->setAutoAdd( true ); |
|
|
|
// IMAP resource setup |
|
QVGroupBox* b1 = new QVGroupBox( i18n("&IMAP Resource Folder Options"), |
|
this ); |
|
|
|
mEnableImapResCB = |
|
new QCheckBox( i18n("&Enable IMAP resource functionality"), b1 ); |
|
QToolTip::add( mEnableImapResCB, i18n( "This enables the IMAP storage for " |
|
"the Kontact applications" ) ); |
|
QWhatsThis::add( mEnableImapResCB, |
|
i18n( GlobalSettings::self()->theIMAPResourceEnabledItem()->whatsThis().utf8() ) ); |
|
connect( mEnableImapResCB, SIGNAL( stateChanged( int ) ), |
|
this, SLOT( slotEmitChanged( void ) ) ); |
|
|
|
mBox = new QWidget( b1 ); |
|
QGridLayout* grid = new QGridLayout( mBox, 3, 2, 0, KDialog::spacingHint() ); |
|
grid->setColStretch( 1, 1 ); |
|
connect( mEnableImapResCB, SIGNAL( toggled(bool) ), |
|
mBox, SLOT( setEnabled(bool) ) ); |
|
QLabel* languageLA = new QLabel( i18n("&Language of the groupware folders:"), |
|
mBox ); |
|
QString toolTip = i18n( "Set the language of the folder names" ); |
|
QString whatsThis = i18n( GlobalSettings::self() |
|
->theIMAPResourceFolderLanguageItem()->whatsThis().utf8() ); |
|
grid->addWidget( languageLA, 0, 0 ); |
|
QToolTip::add( languageLA, toolTip ); |
|
QWhatsThis::add( languageLA, whatsThis ); |
|
mLanguageCombo = new QComboBox( false, mBox ); |
|
languageLA->setBuddy( mLanguageCombo ); |
|
QStringList lst; |
|
lst << i18n("English") << i18n("German") << i18n("French") << i18n("Dutch"); |
|
mLanguageCombo->insertStringList( lst ); |
|
grid->addWidget( mLanguageCombo, 0, 1 ); |
|
QToolTip::add( mLanguageCombo, toolTip ); |
|
QWhatsThis::add( mLanguageCombo, whatsThis ); |
|
connect( mLanguageCombo, SIGNAL( activated( int ) ), |
|
this, SLOT( slotEmitChanged( void ) ) ); |
|
|
|
QLabel* subfolderLA = |
|
new QLabel( i18n("Resource folders are &subfolders of:"), mBox ); |
|
toolTip = i18n( "Set the parent of the resource folders" ); |
|
whatsThis = i18n( GlobalSettings::self()->theIMAPResourceFolderParentItem()->whatsThis().utf8() ); |
|
grid->addWidget( subfolderLA, 1, 0 ); |
|
QToolTip::add( subfolderLA, toolTip ); |
|
QWhatsThis::add( subfolderLA, whatsThis ); |
|
mFolderCombo = new KMFolderComboBox( mBox ); |
|
subfolderLA->setBuddy( mFolderCombo ); |
|
grid->addWidget( mFolderCombo, 1, 1 ); |
|
QToolTip::add( mFolderCombo, toolTip ); |
|
QWhatsThis::add( mFolderCombo, whatsThis ); |
|
connect( mFolderCombo, SIGNAL( activated( int ) ), |
|
this, SLOT( slotEmitChanged( void ) ) ); |
|
|
|
mHideGroupwareFolders = new QCheckBox( i18n( "&Hide groupware folders" ), |
|
mBox, "HideGroupwareFoldersBox" ); |
|
grid->addMultiCellWidget( mHideGroupwareFolders, 2, 2, 0, 1 ); |
|
QToolTip::add( mHideGroupwareFolders, |
|
i18n( "When this is checked, you will not see the IMAP " |
|
"resource folders in the folder tree." ) ); |
|
QWhatsThis::add( mHideGroupwareFolders, i18n( GlobalSettings::self() |
|
->hideGroupwareFoldersItem()->whatsThis().utf8() ) ); |
|
connect( mHideGroupwareFolders, SIGNAL( toggled( bool ) ), |
|
this, SLOT( slotEmitChanged() ) ); |
|
|
|
// Groupware functionality compatibility setup |
|
b1 = new QVGroupBox( i18n("Groupware Compatibility & Legacy Options"), this ); |
|
|
|
gBox = new QVBox( b1 ); |
|
#if 0 |
|
// Currently believed to be disused. |
|
mEnableGwCB = new QCheckBox( i18n("&Enable groupware functionality"), b1 ); |
|
gBox->setSpacing( KDialog::spacingHint() ); |
|
connect( mEnableGwCB, SIGNAL( toggled(bool) ), |
|
gBox, SLOT( setEnabled(bool) ) ); |
|
connect( mEnableGwCB, SIGNAL( stateChanged( int ) ), |
|
this, SLOT( slotEmitChanged( void ) ) ); |
|
#endif |
|
mEnableGwCB = 0; |
|
mLegacyMangleFromTo = new QCheckBox( i18n( "Legac&y mode: Mangle From:/To: headers in replies to invitations" ), gBox ); |
|
QToolTip::add( mLegacyMangleFromTo, i18n( "Turn this option on in order to make Outlook(tm) understand your answers to invitations" ) ); |
|
QWhatsThis::add( mLegacyMangleFromTo, i18n( GlobalSettings::self()-> |
|
groupwareLegacyMangleFromToHeadersItem()->whatsThis().utf8() ) ); |
|
connect( mLegacyMangleFromTo, SIGNAL( stateChanged( int ) ), |
|
this, SLOT( slotEmitChanged( void ) ) ); |
|
|
|
// Open space padding at the end |
|
new QLabel( this ); |
|
} |
|
|
|
void MiscPage::GroupwareTab::load() { |
|
// Read the groupware config |
|
if ( mEnableGwCB ) { |
|
mEnableGwCB->setChecked( GlobalSettings::groupwareEnabled() ); |
|
gBox->setEnabled( mEnableGwCB->isChecked() ); |
|
} |
|
mLegacyMangleFromTo->setChecked( GlobalSettings::groupwareLegacyMangleFromToHeaders() ); |
|
|
|
// Read the IMAP resource config |
|
mEnableImapResCB->setChecked( GlobalSettings::theIMAPResourceEnabled() ); |
|
mBox->setEnabled( mEnableImapResCB->isChecked() ); |
|
|
|
mHideGroupwareFolders->setChecked( GlobalSettings::hideGroupwareFolders() ); |
|
int i = GlobalSettings::theIMAPResourceFolderLanguage(); |
|
mLanguageCombo->setCurrentItem(i); |
|
|
|
QString folderId( GlobalSettings::theIMAPResourceFolderParent() ); |
|
if( !folderId.isNull() ) { |
|
mFolderCombo->setFolder( folderId ); |
|
} |
|
} |
|
|
|
void MiscPage::GroupwareTab::save() { |
|
// Write the groupware config |
|
if ( mEnableGwCB ) |
|
GlobalSettings::setGroupwareEnabled( mEnableGwCB->isChecked() ); |
|
GlobalSettings::setGroupwareLegacyMangleFromToHeaders( |
|
mLegacyMangleFromTo->isChecked() ); |
|
|
|
// Write the IMAP resource config |
|
GlobalSettings::setHideGroupwareFolders( mHideGroupwareFolders->isChecked() ); |
|
|
|
// If there is a leftover folder in the foldercombo, getFolder can |
|
// return 0. In that case we really don't have it enabled |
|
KMFolder *folder = mFolderCombo->getFolder(); |
|
bool enabled = mEnableImapResCB->isChecked() && folder; |
|
GlobalSettings::setTheIMAPResourceEnabled( enabled ); |
|
GlobalSettings::setTheIMAPResourceFolderLanguage( mLanguageCombo->currentItem() ); |
|
GlobalSettings::setTheIMAPResourceFolderParent( folder? folder->idString(): "" ); |
|
} |
|
|
|
|
|
#undef DIM |
|
|
|
//---------------------------- |
|
// KCM stuff |
|
//---------------------------- |
|
extern "C" |
|
{ |
|
KCModule *create_kmail_config_misc( QWidget *parent, const char * ) |
|
{ |
|
MiscPage *page = new MiscPage( parent, "kcmkmail_config_misc" ); |
|
return page; |
|
} |
|
} |
|
|
|
extern "C" |
|
{ |
|
KCModule *create_kmail_config_appearance( QWidget *parent, const char * ) |
|
{ |
|
AppearancePage *page = |
|
new AppearancePage( parent, "kcmkmail_config_appearance" ); |
|
return page; |
|
} |
|
} |
|
|
|
extern "C" |
|
{ |
|
KCModule *create_kmail_config_composer( QWidget *parent, const char * ) |
|
{ |
|
ComposerPage *page = new ComposerPage( parent, "kcmkmail_config_composer" ); |
|
return page; |
|
} |
|
} |
|
|
|
extern "C" |
|
{ |
|
KCModule *create_kmail_config_identity( QWidget *parent, const char * ) |
|
{ |
|
IdentityPage *page = new IdentityPage( parent, "kcmkmail_config_identity" ); |
|
return page; |
|
} |
|
} |
|
|
|
extern "C" |
|
{ |
|
KCModule *create_kmail_config_network( QWidget *parent, const char * ) |
|
{ |
|
NetworkPage *page = new NetworkPage( parent, "kcmkmail_config_network" ); |
|
return page; |
|
} |
|
} |
|
|
|
extern "C" |
|
{ |
|
KCModule *create_kmail_config_security( QWidget *parent, const char * ) |
|
{ |
|
SecurityPage *page = new SecurityPage( parent, "kcmkmail_config_security" ); |
|
return page; |
|
} |
|
} |
|
//---------------------------- |
|
#include "configuredialog.moc"
|
|
|