summaryrefslogtreecommitdiff
Side-by-side diff
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--noncore/settings/packagemanager/oipkg.cpp14
-rw-r--r--noncore/settings/packagemanager/oipkgconfigdlg.cpp7
2 files changed, 18 insertions, 3 deletions
diff --git a/noncore/settings/packagemanager/oipkg.cpp b/noncore/settings/packagemanager/oipkg.cpp
index 3d2c621..417ee95 100644
--- a/noncore/settings/packagemanager/oipkg.cpp
+++ b/noncore/settings/packagemanager/oipkg.cpp
@@ -1,794 +1,806 @@
/*
This file is part of the Opie Project
Copyright (c) 2003 Dan Williams <drw@handhelds.org>
=.
.=l.
.>+-=
_;:, .> :=|. This program is free software; you can
.> <`_, > . <= redistribute it and/or modify it under
:`=1 )Y*s>-.-- : the terms of the GNU Library General Public
.="- .-=="i, .._ License as published by the Free Software
- . .-<_> .<> Foundation; either version 2 of the License,
._= =} : or (at your option) any later version.
.%`+i> _;_.
.i_,=:_. -<s. 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
..}^=.= = ; Library General Public License for more
++= -. .` .: details.
: = ...= . :.=-
-. .:....=;==+<; You should have received a copy of the GNU
-_. . . )=. = Library General Public License along with
-- :-=` this library; see the file COPYING.LIB.
If not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
#include "oipkg.h"
#include <qdir.h>
#include <qfile.h>
#include <qtextstream.h>
#include <stdlib.h>
#include <unistd.h>
const QString IPKG_CONF = "/etc/ipkg.conf"; // Fully-qualified name of Ipkg primary configuration file
const QString IPKG_CONF_DIR = "/etc/ipkg"; // Directory of secondary Ipkg configuration files
const QString IPKG_PKG_PATH = "/usr/lib/ipkg/lists"; // Directory containing server package lists
const QString IPKG_STATUS_PATH = "usr/lib/ipkg/status"; // Destination status file location
const QString IPKG_INFO_PATH = "usr/lib/ipkg/info"; // Package file lists location
OIpkg *oipkg;
// Ipkg callback functions
int fsignalIpkgMessage( ipkg_conf_t *conf, message_level_t level, char *msg )
{
// Display message only if it is below the message level threshold
if ( conf && ( conf->verbosity < level ) )
return 0;
else
oipkg->ipkgMessage( msg );
return 0;
}
char *fIpkgResponse( char */*question*/ )
{
return 0l;
}
int fIpkgStatus( char */*name*/, int /*status*/, char *desc, void */*userdata*/ )
{
oipkg->ipkgStatus( desc );
return 0;
}
int fIpkgFiles( char */*name*/, char *desc, char */*version*/, pkg_state_status_t /*status*/,
void */*userdata*/ )
{
oipkg->ipkgList( desc );
return 0;
}
OIpkg::OIpkg( Config *config, QObject *parent, const char *name )
: QObject( parent, name )
, m_config( config )
, m_confInfo( NULL )
, m_ipkgExecOptions( 0 )
, m_ipkgExecVerbosity( 1 )
{
// Keep pointer to self for the Ipkg callback functions
oipkg = this;
// Initialize libipkg
ipkg_init( &fsignalIpkgMessage, &fIpkgResponse, &m_ipkgArgs );
// Default ipkg run-time arguments
m_ipkgArgs.noaction = false;
m_ipkgArgs.force_defaults = true;
}
OIpkg::~OIpkg()
{
// Upon destruction, ensure that items in config list are deleted with list
if ( m_confInfo )
m_confInfo->setAutoDelete( true );
// Free up libipkg resources
ipkg_deinit( &m_ipkgArgs );
}
OConfItemList *OIpkg::configItems()
{
// Retrieve all configuration items
return filterConfItems();
}
OConfItemList *OIpkg::servers()
{
// Retrieve only servers
return filterConfItems( OConfItem::Source );
}
OConfItemList *OIpkg::destinations()
{
// Retrieve only destinations
return filterConfItems( OConfItem::Destination );
}
OConfItemList *OIpkg::options()
{
// Retrieve only destinations
return filterConfItems( OConfItem::Option );
}
void OIpkg::setConfigItems( OConfItemList *configList )
{
if ( m_confInfo )
delete m_confInfo;
m_confInfo = configList;
// Write out new /etc/ipkg.conf
QFile confFile( IPKG_CONF );
if ( confFile.open( IO_WriteOnly ) )
{
QTextStream confStream( &confFile );
confStream << "# Generated by Opie Package Manager\n\n";
OConfItemListIterator it( *m_confInfo );
for ( ; it.current(); ++it )
{
OConfItem *item = it.current();
// Only write out valid conf items
if ( item->type() != OConfItem::NotDefined )
{
QString confLine;
QString name = item->name();
if ( !item->active() )
confLine = "#";
switch ( item->type() )
{
case OConfItem::Source :
{
if ( item->features().contains( "Compressed" ) )
confLine.append( "src/gz" );
else
confLine.append( "src" );
}
break;
case OConfItem::Destination : confLine.append( "dest" ); break;
case OConfItem::Option : confLine.append( "option" ); break;
case OConfItem::Arch : confLine.append( "arch" ); break;
case OConfItem::Other :
{
// For options w/type = Other, the mapping is as follows:
// name = typeStr (e.g. "lists_dir")
// value = value
// features = name (from configuration file)
confLine.append( item->name() );
name = item->features();
}
break;
default : break;
};
confStream << confLine << " " << name << " " << item->value() << "\n";
}
}
confFile.close();
}
else
{
// Problem writing to /etc/ipkg.conf, exit before removing other conf files
return;
}
// Delete /etc/ipkg/*.conf files (/etc/ipkg.conf should now have all settings
QStringList confFiles;
QDir confDir( IPKG_CONF_DIR );
if ( confDir.exists() )
{
confDir.setNameFilter( "*.conf" );
confDir.setFilter( QDir::Files );
confFiles = confDir.entryList( "*.conf", QDir::Files );
QStringList::Iterator lastFile = confFiles.end();
for ( QStringList::Iterator it = confFiles.begin(); it != lastFile; ++it )
{
// Create absolute file path if necessary
QString absFile = (*it);
if ( !absFile.startsWith( "/" ) )
absFile.prepend( QString( IPKG_CONF_DIR ) + "/" );
// Delete file
QFile::remove( absFile );
}
}
// Reinitialize libipkg to pick up new configuration
ipkg_deinit( &m_ipkgArgs );
ipkg_init( &fsignalIpkgMessage, &fIpkgResponse, &m_ipkgArgs );
m_ipkgArgs.noaction = false;
m_ipkgArgs.force_defaults = true;
}
void OIpkg::saveSettings()
{
// Save Ipkg execution options to application configuration file
if ( m_config )
{
m_config->setGroup( "Ipkg" );
m_config->writeEntry( "ExecOptions", m_ipkgExecOptions );
m_config->writeEntry( "Verbosity", m_ipkgExecVerbosity );
}
}
OPackageList *OIpkg::availablePackages( const QString &server )
{
// Load Ipkg configuration info if not already cached
if ( !m_confInfo )
loadConfiguration();
// Build new server list (caller is responsible for deleting)
OPackageList *pl = new OPackageList;
+ // Get directory where server lists are located
+ QString listsDir;
+ OConfItem *confItem = findConfItem( OConfItem::Other, "lists_dir" );
+ if ( confItem )
+ listsDir = confItem->value();
+ else
+ listsDir = IPKG_PKG_PATH;
+
// Open package list file
- QFile f( IPKG_PKG_PATH + "/" + server );
+ QFile f( listsDir + "/" + server );
if ( !f.open( IO_ReadOnly ) )
return NULL;
QTextStream t( &f );
// Process all information in package list file
OPackage *package = NULL;
QString line = t.readLine();
while ( !t.eof() )
{
// Determine key/value pair
int pos = line.find( ':', 0 );
QString key;
if ( pos > -1 )
key = line.mid( 0, pos );
else
key = QString::null;
QString value = line.mid( pos+2, line.length()-pos );
// Allocate new package and insert into list
if ( package == NULL && !key.isEmpty() )
{
package = new OPackage( value );
package->setSource( server );
pl->append( package );
}
// Update package data
if ( key == "Package" )
package->setName( value );
else if ( key == "Version" )
package->setVersion( value );
else if ( key == "Section" )
package->setCategory( value );
//DataManager::setAvailableCategories( value );
else if ( key.isEmpty() && value.isEmpty() )
package = NULL;
// Skip past all description lines
if ( key == "Description" )
{
line = t.readLine();
while ( !line.isEmpty() && line.find( ':', 0 ) == -1 && !t.eof() )
line = t.readLine();
}
else
line = t.readLine();
}
f.close();
return pl;
}
OPackageList *OIpkg::installedPackages( const QString &destName, const QString &destPath )
{
// Load Ipkg configuration info if not already cached
if ( !m_confInfo )
loadConfiguration();
// Build new server list (caller is responsible for deleting)
OPackageList *pl = new OPackageList;
// Open status file
QString path = destPath;
if ( path.right( 1 ) != "/" )
path.append( "/" );
path.append( IPKG_STATUS_PATH );
QFile f( path );
if ( !f.open( IO_ReadOnly ) )
return NULL;
QTextStream t( &f );
// Process all information in status file
bool newPackage = false;
QString line = t.readLine();
QString name;
QString version;
QString status;
while ( !t.eof() )
{
// Determine key/value pair
int pos = line.find( ':', 0 );
QString key;
if ( pos > -1 )
key = line.mid( 0, pos );
else
key = QString::null;
QString value = line.mid( pos+2, line.length()-pos );
// Allocate new package and insert into list
if ( newPackage && !key.isEmpty() )
{
// Add to list only if it has a valid name and is installed
if ( !name.isNull() && status.contains( " installed" ) )
{
pl->append( new OPackage( name, QString::null, version, QString::null, destName ) );
name = QString::null;
version = QString::null;
status = QString::null;
newPackage = false;
}
}
// Update package data
if ( key == "Package" )
name = value;
else if ( key == "Version" )
version = value;
else if ( key == "Status" )
status = value;
else if ( key.isEmpty() && value.isEmpty() )
newPackage = true;
// Skip past all description lines
if ( key == "Description" )
{
line = t.readLine();
while ( !line.isEmpty() && line.find( ':', 0 ) == -1 && !t.eof() )
line = t.readLine();
}
else
line = t.readLine();
}
f.close();
// Make sure to add to list last entry
if ( !name.isNull() && status.contains( " installed" ) )
pl->append( new OPackage( name, QString::null, version, QString::null, destName ) );
return pl;
}
OConfItem *OIpkg::findConfItem( OConfItem::Type type, const QString &name )
{
// Find configuration item in list
OConfItemListIterator configIt( *m_confInfo );
OConfItem *config = 0l;
for ( ; configIt.current(); ++configIt )
{
config = configIt.current();
if ( config->type() == type && config->name() == name )
break;
}
if ( config && config->type() == type && config->name() == name )
return config;
return 0l;
}
bool OIpkg::executeCommand( OPackage::Command command, const QStringList &parameters, const QString &destination,
const QObject *receiver, const char *slotOutput, bool rawOutput )
{
if ( command == OPackage::NotDefined )
return false;
// Set ipkg run-time options/arguments
m_ipkgArgs.force_depends = ( m_ipkgExecOptions & FORCE_DEPENDS );
m_ipkgArgs.force_reinstall = ( m_ipkgExecOptions & FORCE_REINSTALL );
// TODO m_ipkgArgs.force_remove = ( m_ipkgExecOptions & FORCE_REMOVE );
m_ipkgArgs.force_overwrite = ( m_ipkgExecOptions & FORCE_OVERWRITE );
m_ipkgArgs.verbosity = m_ipkgExecVerbosity;
if ( m_ipkgArgs.dest )
free( m_ipkgArgs.dest );
if ( !destination.isNull() )
{
int len = destination.length() + 1;
m_ipkgArgs.dest = (char *)malloc( len );
strncpy( m_ipkgArgs.dest, destination, destination.length() );
m_ipkgArgs.dest[ len - 1 ] = '\0';
}
else
m_ipkgArgs.dest = 0l;
// Connect output signal to widget
if ( !rawOutput )
{
// TODO - connect to local slot and parse output before emitting signalIpkgMessage
}
switch( command )
{
case OPackage::Update : {
connect( this, SIGNAL(signalIpkgMessage(const QString &)), receiver, slotOutput );
ipkg_lists_update( &m_ipkgArgs );
};
break;
case OPackage::Upgrade : {
connect( this, SIGNAL(signalIpkgMessage(const QString &)), receiver, slotOutput );
ipkg_packages_upgrade( &m_ipkgArgs );
// Re-link non-root destinations to make sure everything is in sync
OConfItemList *destList = destinations();
OConfItemListIterator it( *destList );
for ( ; it.current(); ++it )
{
OConfItem *dest = it.current();
if ( dest->name() != "root" )
linkPackageDir( dest->name() );
}
delete destList;
};
break;
case OPackage::Install : {
connect( this, SIGNAL(signalIpkgMessage(const QString &)), receiver, slotOutput );
for ( QStringList::ConstIterator it = parameters.begin(); it != parameters.end(); ++it )
{
ipkg_packages_install( &m_ipkgArgs, (*it) );
}
if ( destination != "root" )
linkPackageDir( destination );
};
break;
case OPackage::Remove : {
connect( this, SIGNAL(signalIpkgMessage(const QString &)), receiver, slotOutput );
// Get list of destinations for unlinking of packages not installed to root
OConfItemList *destList = destinations();
for ( QStringList::ConstIterator it = parameters.begin(); it != parameters.end(); ++it )
{
unlinkPackage( (*it), destList );
ipkg_packages_remove( &m_ipkgArgs, (*it), true );
}
delete destList;
};
break;
case OPackage::Download : {
connect( this, SIGNAL(signalIpkgMessage(const QString &)), receiver, slotOutput );
for ( QStringList::ConstIterator it = parameters.begin(); it != parameters.end(); ++it )
{
ipkg_packages_download( &m_ipkgArgs, (*it) );
}
};
break;
case OPackage::Info : {
connect( this, SIGNAL(signalIpkgStatus(const QString &)), receiver, slotOutput );
ipkg_packages_info( &m_ipkgArgs, (*parameters.begin()), &fIpkgStatus, 0l );
};
break;
case OPackage::Files : {
connect( this, SIGNAL(signalIpkgList(const QString &)), receiver, slotOutput );
ipkg_package_files( &m_ipkgArgs, (*parameters.begin()), &fIpkgFiles, 0l );
};
break;
default : break;
};
return true;
}
void OIpkg::ipkgMessage( char *msg )
{
emit signalIpkgMessage( msg );
}
void OIpkg::ipkgStatus( char *status )
{
emit signalIpkgStatus( status );
}
void OIpkg::ipkgList( char *filelist )
{
emit signalIpkgList( filelist );
}
void OIpkg::loadConfiguration()
{
if ( m_confInfo )
delete m_confInfo;
// Load configuration item list
m_confInfo = new OConfItemList();
QStringList confFiles;
QDir confDir( IPKG_CONF_DIR );
if ( confDir.exists() )
{
confDir.setNameFilter( "*.conf" );
confDir.setFilter( QDir::Files );
confFiles = confDir.entryList( "*.conf", QDir::Files );
}
confFiles << IPKG_CONF;
QStringList::Iterator lastFile = confFiles.end();
for ( QStringList::Iterator it = confFiles.begin(); it != lastFile; ++it )
{
// Create absolute file path if necessary
QString absFile = (*it);
if ( !absFile.startsWith( "/" ) )
absFile.prepend( QString( IPKG_CONF_DIR ) + "/" );
// Read in file
QFile f( absFile );
if ( f.open( IO_ReadOnly ) )
{
QTextStream s( &f );
while ( !s.eof() )
{
QString line = s.readLine().simplifyWhiteSpace();
// Parse line and save info to the conf options list
if ( !line.isEmpty() )
{
// Strip leading comment marker if exists
bool comment = false;
if ( line.startsWith( "#" ) )
{
line.remove( 0, 1 );
line = line.simplifyWhiteSpace();
comment = true;
}
bool recognizedOption = true;
int pos = line.find( ' ', 1 ) + 1;
int endpos = line.find( ' ', pos );
// Name
QString name = line.mid( pos, endpos - pos );
// Value
QString value = "";
if ( endpos > -1 )
value = line.right( line.length() - endpos - 1 );
// Active
bool active = !comment;
// Type
// For options w/type = Other, the mapping is as follows:
// name = typeStr (e.g. "lists_dir")
// value = value
// features = name (from configuration file)
QString typeStr = line.left( pos - 1 );
OConfItem::Type type;
QString features;
if ( typeStr == "src" )
type = OConfItem::Source;
else if ( typeStr == "src/gz" )
{
type = OConfItem::Source;
features = "Compressed";
}
else if ( typeStr == "dest" )
type = OConfItem::Destination;
else if ( typeStr == "option" )
type = OConfItem::Option;
else if ( typeStr == "arch" )
type = OConfItem::Arch;
else if ( typeStr == "lists_dir" )
{
type = OConfItem::Other;
features = name;
name = typeStr;
+
+ // Default value when not defined
+ if ( value == QString::null || value == "" )
+ value = IPKG_PKG_PATH;
}
else
recognizedOption = false;
// Add to list
if ( recognizedOption )
m_confInfo->append( new OConfItem( type, name, value, features, active ) );
}
}
f.close();
}
}
// Load Ipkg execution options from application configuration file
if ( m_config )
{
m_config->setGroup( "Ipkg" );
m_ipkgExecOptions = m_config->readNumEntry( "ExecOptions", m_ipkgExecOptions );
m_ipkgExecVerbosity = m_config->readNumEntry( "Verbosity", m_ipkgExecVerbosity );
}
}
OConfItemList *OIpkg::filterConfItems( OConfItem::Type typefilter )
{
// Load Ipkg configuration info if not already cached
if ( !m_confInfo )
loadConfiguration();
// Build new server list (caller is responsible for deleting)
OConfItemList *sl = new OConfItemList;
// If typefilter is empty, retrieve all items
bool retrieveAll = ( typefilter == OConfItem::NotDefined );
// Parse configuration info for servers
OConfItemListIterator it( *m_confInfo );
for ( ; it.current(); ++it )
{
OConfItem *item = it.current();
if ( retrieveAll || item->type() == typefilter )
{
sl->append( item );
}
}
return sl;
}
const QString &OIpkg::rootPath()
{
if ( m_rootPath.isEmpty() )
{
OConfItem *rootDest = findConfItem( OConfItem::Destination, "root" );
rootDest ? m_rootPath = rootDest->value()
: m_rootPath = '/';
if ( m_rootPath.right( 1 ) == '/' )
m_rootPath.truncate( m_rootPath.length() - 1 );
}
return m_rootPath;
}
void OIpkg::linkPackageDir( const QString &dest )
{
if ( !dest.isNull() )
{
OConfItem *destConfItem = findConfItem( OConfItem::Destination, dest );
emit signalIpkgMessage( tr( "Linking packages installed in: %1" ).arg( dest ) );
// Set package destination directory
QString destDir = destConfItem->value();
QString destInfoDir = destDir;
if ( destInfoDir.right( 1 ) != '/' )
destInfoDir.append( '/' );
destInfoDir.append( IPKG_INFO_PATH );
// Get list of installed packages in destination
QDir packageDir( destInfoDir );
QStringList packageFiles;
if ( packageDir.exists() )
{
packageDir.setNameFilter( "*.list" );
packageDir.setFilter( QDir::Files );
packageFiles = packageDir.entryList( "*.list", QDir::Files );
}
// Link all files for every package installed in desination
QStringList::Iterator lastFile = packageFiles.end();
for ( QStringList::Iterator it = packageFiles.begin(); it != lastFile; ++it )
{
//emit signalIpkgMessage( QString( "Processing: %1/%2" ).arg( destInfoDir ).arg (*it) );
QString packageFileName = destInfoDir;
packageFileName.append( '/' );
packageFileName.append( (*it) );
QFile packageFile( packageFileName );
if ( packageFile.open( IO_ReadOnly ) )
{
QTextStream t( &packageFile );
QString linkFile;
while ( !t.eof() )
{
// Get the name of the file to link and build the sym link filename
linkFile = t.readLine();
QString linkDest( linkFile.right( linkFile.length() - destDir.length() ) );
linkDest.prepend( rootPath() );
// If file installed file is actually symbolic link, use actual file for linking
QFileInfo fileInfo( linkFile );
if ( fileInfo.isSymLink() && !fileInfo.readLink().isEmpty() )
linkFile = fileInfo.readLink();
// See if directory exists in 'root', if not, create
fileInfo.setFile( linkDest );
QString linkDestDirName = fileInfo.dirPath( true );
QDir linkDestDir( linkDestDirName );
if ( !linkDestDir.exists() )
{
linkDestDir.mkdir( linkDestDirName );
}
else
{
// Remove any previous link to make sure we will be pointing to the current version
if ( QFile::exists( linkDest ) )
QFile::remove( linkDest );
}
// Link the file
//emit signalIpkgMessage( QString( "Linking '%1' to '%2'" ).arg( linkFile ).arg( linkDest ) );
if ( symlink( linkFile, linkDest ) == -1 )
emit signalIpkgMessage( tr( "Error linkling '%1' to '%2'" )
.arg( linkFile )
.arg( linkDest ) );
}
packageFile.close();
}
}
}
}
void OIpkg::unlinkPackage( const QString &package, OConfItemList *destList )
{
if ( !package.isNull() )
{
// Find destination package is installed in
if ( destList )
{
OConfItemListIterator it( *destList );
for ( ; it.current(); ++it )
{
OConfItem *dest = it.current();
QString destInfoFileName = QString( "%1/%2/%3.list" ).arg( dest->value() )
.arg( IPKG_INFO_PATH )
.arg( package );
//emit signalIpkgMessage( QString( "Looking for '%1'" ).arg ( destInfoFileName ) );
// If found and destination is not 'root', remove symbolic links
if ( QFile::exists( destInfoFileName ) && dest->name() != "root" )
{
QFile destInfoFile( destInfoFileName );
if ( destInfoFile.open( IO_ReadOnly ) )
{
QTextStream t( &destInfoFile );
QString linkFile;
while ( !t.eof() )
{
// Get the name of the file to link and build the sym link filename
linkFile = t.readLine();
QString linkDest( linkFile.right( linkFile.length() -
dest->value().length() ) );
linkDest.prepend( rootPath() );
//emit signalIpkgMessage( QString( "Deleting: '%1'" ).arg( linkDest ) );
QFile::remove( linkDest );
}
destInfoFile.close();
}
emit signalIpkgMessage( tr( "Links removed for: %1" ).arg( package ) );
return;
}
}
}
}
}
diff --git a/noncore/settings/packagemanager/oipkgconfigdlg.cpp b/noncore/settings/packagemanager/oipkgconfigdlg.cpp
index d234251..0ad1c82 100644
--- a/noncore/settings/packagemanager/oipkgconfigdlg.cpp
+++ b/noncore/settings/packagemanager/oipkgconfigdlg.cpp
@@ -1,648 +1,651 @@
/*
This file is part of the Opie Project
Copyright (c) 2003 Dan Williams <drw@handhelds.org>
=.
.=l.
.>+-=
_;:, .> :=|. This program is free software; you can
.> <`_, > . <= redistribute it and/or modify it under
:`=1 )Y*s>-.-- : the terms of the GNU Library General Public
.="- .-=="i, .._ License as published by the Free Software
- . .-<_> .<> Foundation; either version 2 of the License,
._= =} : or (at your option) any later version.
.%`+i> _;_.
.i_,=:_. -<s. 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
..}^=.= = ; Library General Public License for more
++= -. .` .: details.
: = ...= . :.=-
-. .:....=;==+<; You should have received a copy of the GNU
-_. . . )=. = Library General Public License along with
-- :-=` this library; see the file COPYING.LIB.
If not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
#include "oipkgconfigdlg.h"
#include <opie2/ofiledialog.h>
#include <qpe/qpeapplication.h>
#include <qpe/resource.h>
#include <qcheckbox.h>
#include <qcombobox.h>
#include <qgroupbox.h>
#include <qlabel.h>
#include <qlineedit.h>
#include <qlistbox.h>
#include <qpushbutton.h>
#include <qscrollview.h>
#include <qwhatsthis.h>
OIpkgConfigDlg::OIpkgConfigDlg( OIpkg *ipkg, bool installOptions, QWidget *parent )
: QDialog( parent, QString::null, true, WStyle_ContextHelp )
, m_ipkg( ipkg )
, m_configs( 0l )
, m_installOptions( installOptions )
, m_serverCurrent( -1 )
, m_destCurrent( -1 )
, m_layout( this, 2, 4 )
, m_tabWidget( this )
{
setCaption( tr( "Configuration" ) );
// Initialize configuration widgets
if ( !installOptions )
{
initServerWidget();
initDestinationWidget();
initProxyWidget();
}
initOptionsWidget();
// Load configuration information
initData();
// Setup tabs for all info
m_layout.addWidget( &m_tabWidget );
if ( !m_installOptions )
{
m_tabWidget.addTab( m_serverWidget, "packagemanager/servertab", tr( "Servers" ) );
m_tabWidget.addTab( m_destWidget, "packagemanager/desttab", tr( "Destinations" ) );
m_tabWidget.addTab( m_proxyWidget, "packagemanager/proxytab", tr( "Proxies" ) );
m_tabWidget.addTab( m_optionsWidget, "exec", tr( "Options" ) );
m_tabWidget.setCurrentTab( tr( "Servers" ) );
}
else
{
m_tabWidget.addTab( m_optionsWidget, "exec", tr( "Options" ) );
}
}
void OIpkgConfigDlg::accept()
{
// Save server, destination and proxy configuration
if ( !m_installOptions )
{
// Update proxy information before saving settings
OConfItem *confItem = m_ipkg->findConfItem( OConfItem::Option, "http_proxy" );
if ( confItem )
{
confItem->setValue( m_proxyHttpServer->text() );
confItem->setActive( m_proxyHttpActive->isChecked() );
}
else
m_configs->append( new OConfItem( OConfItem::Option, "http_proxy",
m_proxyHttpServer->text(), QString::null,
m_proxyHttpActive->isChecked() ) );
confItem = m_ipkg->findConfItem( OConfItem::Option, "ftp_proxy" );
if ( confItem )
{
confItem->setValue( m_proxyFtpServer->text() );
confItem->setActive( m_proxyFtpActive->isChecked() );
}
else
m_configs->append( new OConfItem( OConfItem::Option, "ftp_proxy",
m_proxyFtpServer->text(), QString::null,
m_proxyFtpActive->isChecked() ) );
confItem = m_ipkg->findConfItem( OConfItem::Option, "proxy_username" );
if ( confItem )
confItem->setValue( m_proxyUsername->text() );
else
m_configs->append( new OConfItem( OConfItem::Option, "proxy_username",
m_proxyUsername->text() ) );
confItem = m_ipkg->findConfItem( OConfItem::Option, "proxy_password" );
if ( confItem )
confItem->setValue( m_proxyPassword->text() );
else
m_configs->append( new OConfItem( OConfItem::Option, "proxy_password",
m_proxyPassword->text() ) );
+ QString listsDir = m_optSourceLists->text();
+ if ( listsDir == QString::null || listsDir == "" )
+ listsDir = "/usr/lib/ipkg/lists"; // TODO - use proper libipkg define
confItem = m_ipkg->findConfItem( OConfItem::Other, "lists_dir" );
if ( confItem )
- confItem->setValue( m_optSourceLists->text() );
+ confItem->setValue( listsDir );
else
m_configs->append( new OConfItem( OConfItem::Other, "lists_dir",
- m_optSourceLists->text(), "name" ) );
+ listsDir, "name" ) );
m_ipkg->setConfigItems( m_configs );
}
// Save options configuration
int options = 0;
if ( m_optForceDepends->isChecked() )
options |= FORCE_DEPENDS;
if ( m_optForceReinstall->isChecked() )
options |= FORCE_REINSTALL;
if ( m_optForceRemove->isChecked() )
options |= FORCE_REMOVE;
if ( m_optForceOverwrite->isChecked() )
options |= FORCE_OVERWRITE;
m_ipkg->setIpkgExecOptions( options );
m_ipkg->setIpkgExecVerbosity( m_optVerboseIpkg->currentItem() );
QDialog::accept();
}
void OIpkgConfigDlg::reject()
{
if ( m_configs )
delete m_configs;
}
void OIpkgConfigDlg::initServerWidget()
{
m_serverWidget = new QWidget( this );
// Initialize UI
QVBoxLayout *vb = new QVBoxLayout( m_serverWidget );
QScrollView *sv = new QScrollView( m_serverWidget );
vb->addWidget( sv, 0, 0 );
sv->setResizePolicy( QScrollView::AutoOneFit );
sv->setFrameStyle( QFrame::NoFrame );
QWidget *container = new QWidget( sv->viewport() );
sv->addChild( container );
QGridLayout *layout = new QGridLayout( container, 2, 3, 2, 4 );
m_serverList = new QListBox( container );
QWhatsThis::add( m_serverList, tr( "This is a list of all servers configured. Select one here to edit or delete, or add a new one below." ) );
m_serverList->setSizePolicy( QSizePolicy( QSizePolicy::Preferred, QSizePolicy::Preferred ) );
connect( m_serverList, SIGNAL(highlighted(int)), this, SLOT(slotServerSelected(int)) );
layout->addMultiCellWidget( m_serverList, 0, 0, 0, 2 );
QPixmap pic;
pic.convertFromImage( Resource::loadImage( "new" ).smoothScale( AppLnk::smallIconSize(), AppLnk::smallIconSize() ) );
QPushButton *btn = new QPushButton( pic, tr( "New" ), container );
btn->setMinimumHeight( AppLnk::smallIconSize() );
QWhatsThis::add( btn, tr( "Tap here to create a new entry. Fill in the fields below and then tap on Update." ) );
connect( btn, SIGNAL(clicked()), this, SLOT(slotServerNew()) );
layout->addWidget( btn, 1, 0 );
pic.convertFromImage( Resource::loadImage( "edit" ).smoothScale( AppLnk::smallIconSize(), AppLnk::smallIconSize() ) );
m_serverEditBtn = new QPushButton( pic, tr( "Edit" ), container );
m_serverEditBtn->setMinimumHeight( AppLnk::smallIconSize() );
m_serverEditBtn->setEnabled( false );
QWhatsThis::add( m_serverEditBtn, tr( "Tap here to edit the entry selected above." ) );
connect( m_serverEditBtn, SIGNAL(clicked()), this, SLOT(slotServerEdit()) );
layout->addWidget( m_serverEditBtn, 1, 1 );
pic.convertFromImage( Resource::loadImage( "trash" ).smoothScale( AppLnk::smallIconSize(), AppLnk::smallIconSize() ) );
m_serverDeleteBtn = new QPushButton( pic, tr( "Delete" ), container );
m_serverDeleteBtn->setMinimumHeight( AppLnk::smallIconSize() );
m_serverDeleteBtn->setEnabled( false );
QWhatsThis::add( m_serverDeleteBtn, tr( "Tap here to delete the entry selected above." ) );
connect( m_serverDeleteBtn, SIGNAL(clicked()), this, SLOT(slotServerDelete()) );
layout->addWidget( m_serverDeleteBtn, 1, 2 );
}
void OIpkgConfigDlg::initDestinationWidget()
{
m_destWidget = new QWidget( this );
// Initialize UI
QVBoxLayout *vb = new QVBoxLayout( m_destWidget );
QScrollView *sv = new QScrollView( m_destWidget );
vb->addWidget( sv, 0, 0 );
sv->setResizePolicy( QScrollView::AutoOneFit );
sv->setFrameStyle( QFrame::NoFrame );
QWidget *container = new QWidget( sv->viewport() );
sv->addChild( container );
QGridLayout *layout = new QGridLayout( container, 2, 3, 2, 4 );
m_destList = new QListBox( container );
QWhatsThis::add( m_destList, tr( "This is a list of all destinations configured for this device. Select one here to edit or delete, or add a new one below." ) );
m_destList->setSizePolicy( QSizePolicy( QSizePolicy::Preferred, QSizePolicy::Preferred ) );
connect( m_destList, SIGNAL(highlighted(int)), this, SLOT(slotDestSelected(int)) );
layout->addMultiCellWidget( m_destList, 0, 0, 0, 2 );
QPixmap pic;
pic.convertFromImage( Resource::loadImage( "new" ).smoothScale( AppLnk::smallIconSize(), AppLnk::smallIconSize() ) );
QPushButton *btn = new QPushButton( pic, tr( "New" ), container );
btn->setMinimumHeight( AppLnk::smallIconSize() );
QWhatsThis::add( btn, tr( "Tap here to create a new entry. Fill in the fields below and then tap on Update." ) );
connect( btn, SIGNAL(clicked()), this, SLOT(slotDestNew()) );
layout->addWidget( btn, 1, 0 );
pic.convertFromImage( Resource::loadImage( "edit" ).smoothScale( AppLnk::smallIconSize(), AppLnk::smallIconSize() ) );
m_destEditBtn = new QPushButton( pic, tr( "Edit" ), container );
m_destEditBtn->setMinimumHeight( AppLnk::smallIconSize() );
m_destEditBtn->setEnabled( false );
QWhatsThis::add( m_destEditBtn, tr( "Tap here to edit the entry selected above." ) );
connect( m_destEditBtn, SIGNAL(clicked()), this, SLOT(slotDestEdit()) );
layout->addWidget( m_destEditBtn, 1, 1 );
pic.convertFromImage( Resource::loadImage( "trash" ).smoothScale( AppLnk::smallIconSize(), AppLnk::smallIconSize() ) );
m_destDeleteBtn = new QPushButton( pic, tr( "Delete" ), container );
m_destDeleteBtn->setMinimumHeight( AppLnk::smallIconSize() );
m_destDeleteBtn->setEnabled( false );
QWhatsThis::add( m_destDeleteBtn, tr( "Tap here to delete the entry selected above." ) );
connect( m_destDeleteBtn, SIGNAL(clicked()), this, SLOT(slotDestDelete()) );
layout->addWidget( m_destDeleteBtn, 1, 2 );
}
void OIpkgConfigDlg::initProxyWidget()
{
m_proxyWidget = new QWidget( this );
// Initialize UI
QVBoxLayout *vb = new QVBoxLayout( m_proxyWidget );
QScrollView *sv = new QScrollView( m_proxyWidget );
vb->addWidget( sv, 0, 0 );
sv->setResizePolicy( QScrollView::AutoOneFit );
sv->setFrameStyle( QFrame::NoFrame );
QWidget *container = new QWidget( sv->viewport() );
sv->addChild( container );
QGridLayout *layout = new QGridLayout( container, 4, 2, 2, 4 );
// HTTP proxy server configuration
QGroupBox *grpbox = new QGroupBox( 0, Qt::Vertical, tr( "HTTP Proxy" ), container );
grpbox->layout()->setSpacing( 2 );
grpbox->layout()->setMargin( 4 );
layout->addMultiCellWidget( grpbox, 0, 0, 0, 1 );
QVBoxLayout *grplayout = new QVBoxLayout( grpbox->layout() );
m_proxyHttpServer = new QLineEdit( grpbox );
QWhatsThis::add( m_proxyHttpServer, tr( "Enter the URL address of the HTTP proxy server here." ) );
grplayout->addWidget( m_proxyHttpServer );
m_proxyHttpActive = new QCheckBox( tr( "Enabled" ), grpbox );
QWhatsThis::add( m_proxyHttpActive, tr( "Tap here to enable or disable the HTTP proxy server." ) );
grplayout->addWidget( m_proxyHttpActive );
// FTP proxy server configuration
grpbox = new QGroupBox( 0, Qt::Vertical, tr( "FTP Proxy" ), container );
grpbox->layout()->setSpacing( 2 );
grpbox->layout()->setMargin( 4 );
layout->addMultiCellWidget( grpbox, 1, 1, 0, 1 );
grplayout = new QVBoxLayout( grpbox->layout() );
m_proxyFtpServer = new QLineEdit( grpbox );
QWhatsThis::add( m_proxyFtpServer, tr( "Enter the URL address of the FTP proxy server here." ) );
grplayout->addWidget( m_proxyFtpServer );
m_proxyFtpActive = new QCheckBox( tr( "Enabled" ), grpbox );
QWhatsThis::add( m_proxyFtpActive, tr( "Tap here to enable or disable the FTP proxy server." ) );
grplayout->addWidget( m_proxyFtpActive );
// Proxy server username and password configuration
QLabel *label = new QLabel( tr( "Username:" ), container );
QWhatsThis::add( label, tr( "Enter the username for the proxy servers here." ) );
layout->addWidget( label, 2, 0 );
m_proxyUsername = new QLineEdit( container );
QWhatsThis::add( m_proxyUsername, tr( "Enter the username for the proxy servers here." ) );
layout->addWidget( m_proxyUsername, 2, 1 );
label = new QLabel( tr( "Password:" ), container );
QWhatsThis::add( label, tr( "Enter the password for the proxy servers here." ) );
layout->addWidget( label, 3, 0 );
m_proxyPassword = new QLineEdit( container );
QWhatsThis::add( m_proxyPassword, tr( "Enter the password for the proxy servers here." ) );
layout->addWidget( m_proxyPassword, 3, 1 );
}
void OIpkgConfigDlg::initOptionsWidget()
{
m_optionsWidget = new QWidget( this );
// Initialize UI
QVBoxLayout *vb = new QVBoxLayout( m_optionsWidget );
QScrollView *sv = new QScrollView( m_optionsWidget );
vb->addWidget( sv, 0, 0 );
sv->setResizePolicy( QScrollView::AutoOneFit );
sv->setFrameStyle( QFrame::NoFrame );
QWidget *container = new QWidget( sv->viewport() );
sv->addChild( container );
QGridLayout *layout = new QGridLayout( container, 8, 2, 2, 4 );
m_optForceDepends = new QCheckBox( tr( "Force Depends" ), container );
QWhatsThis::add( m_optForceDepends, tr( "Tap here to enable or disable the '-force-depends' option for Ipkg." ) );
layout->addMultiCellWidget( m_optForceDepends, 0, 0, 0, 1 );
m_optForceReinstall = new QCheckBox( tr( "Force Reinstall" ), container );
QWhatsThis::add( m_optForceReinstall, tr( "Tap here to enable or disable the '-force-reinstall' option for Ipkg." ) );
layout->addMultiCellWidget( m_optForceReinstall, 1, 1, 0, 1 );
m_optForceRemove = new QCheckBox( tr( "Force Remove" ), container );
QWhatsThis::add( m_optForceRemove, tr( "Tap here to enable or disable the '-force-removal-of-dependent-packages' option for Ipkg." ) );
layout->addMultiCellWidget( m_optForceRemove, 2, 2, 0, 1 );
m_optForceOverwrite = new QCheckBox( tr( "Force Overwrite" ), container );
QWhatsThis::add( m_optForceOverwrite, tr( "Tap here to enable or disable the '-force-overwrite' option for Ipkg." ) );
layout->addMultiCellWidget( m_optForceOverwrite, 3, 3, 0, 1 );
QLabel *l = new QLabel( tr( "Information level:" ), container );
QWhatsThis::add( l, tr( "Select information level for Ipkg." ) );
layout->addMultiCellWidget( l, 4, 4, 0, 1 );
m_optVerboseIpkg = new QComboBox( container );
QWhatsThis::add( m_optVerboseIpkg, tr( "Select information level for Ipkg." ) );
m_optVerboseIpkg->insertItem( tr( "Errors only" ) );
m_optVerboseIpkg->insertItem( tr( "Normal messages" ) );
m_optVerboseIpkg->insertItem( tr( "Informative messages" ) );
m_optVerboseIpkg->insertItem( tr( "Troubleshooting output" ) );
layout->addMultiCellWidget( m_optVerboseIpkg, 5, 5, 0, 1 );
l = new QLabel( tr( "Package source lists directory:" ), container );
QWhatsThis::add( l, tr( "Enter the directory where package source feed information is stored." ) );
layout->addMultiCellWidget( l, 6, 6, 0, 1 );
m_optSourceLists = new QLineEdit( container );
QWhatsThis::add( m_optSourceLists, tr( "Enter the directory where package source feed information is stored." ) );
layout->addWidget( m_optSourceLists, 7, 0 );
QPixmap pic;
pic.convertFromImage( Resource::loadImage( "folder" ).smoothScale( AppLnk::smallIconSize(), AppLnk::smallIconSize() ) );
QPushButton *btn = new QPushButton( pic, QString::null, container );
btn->setMaximumWidth( btn->height() );
QWhatsThis::add( btn, tr( "Tap here to select the directory where package source feed information is stored." ) );
connect( btn, SIGNAL(clicked()), this, SLOT(slotOptSelectSourceListsPath()) );
layout->addWidget( btn, 7, 1 );
layout->addItem( new QSpacerItem( 1, 1, QSizePolicy::Minimum, QSizePolicy::Expanding ) );
}
void OIpkgConfigDlg::initData()
{
// Read ipkg configuration (server/destination/proxy) information
if ( m_ipkg && !m_installOptions )
{
m_configs = m_ipkg->configItems();
if ( m_configs )
{
for ( OConfItemListIterator configIt( *m_configs ); configIt.current(); ++configIt )
{
OConfItem *config = configIt.current();
// Add configuration item to the appropriate dialog controls
if ( config )
{
switch ( config->type() )
{
case OConfItem::Source : m_serverList->insertItem( config->name() ); break;
case OConfItem::Destination : m_destList->insertItem( config->name() ); break;
case OConfItem::Option :
{
if ( config->name() == "http_proxy" )
{
m_proxyHttpServer->setText( config->value() );
m_proxyHttpActive->setChecked( config->active() );
}
else if ( config->name() == "ftp_proxy" )
{
m_proxyFtpServer->setText( config->value() );
m_proxyFtpActive->setChecked( config->active() );
}
else if ( config->name() == "proxy_username" )
{
m_proxyUsername->setText( config->value() );
}
else if ( config->name() == "proxy_password" )
{
m_proxyPassword->setText( config->value() );
}
}
break;
case OConfItem::Other :
{
if ( config->name() == "lists_dir" )
m_optSourceLists->setText( config->value() );
else // TODO - use proper libipkg define
m_optSourceLists->setText( "/usr/lib/ipkg/lists" );
}
break;
default : break;
};
}
}
}
}
// Get Ipkg execution options
int options = m_ipkg->ipkgExecOptions();
if ( options & FORCE_DEPENDS )
m_optForceDepends->setChecked( true );
if ( options & FORCE_REINSTALL )
m_optForceReinstall->setChecked( true );
if ( options & FORCE_REMOVE )
m_optForceRemove->setChecked( true );
if ( options & FORCE_OVERWRITE )
m_optForceOverwrite->setChecked( true );
m_optVerboseIpkg->setCurrentItem( m_ipkg->ipkgExecVerbosity() );
}
void OIpkgConfigDlg::slotServerSelected( int index )
{
m_serverCurrent = index;
// Enable Edit and Delete buttons
m_serverEditBtn->setEnabled( true );
m_serverDeleteBtn->setEnabled( true );
}
void OIpkgConfigDlg::slotServerNew()
{
OConfItem *server = new OConfItem( OConfItem::Source );
OIpkgServerDlg dlg( server, this );
if ( QPEApplication::execDialog( &dlg ) == QDialog::Accepted )
{
// Add to configuration option list
m_configs->append( server );
m_configs->sort();
// Add to server list
m_serverList->insertItem( server->name() );
m_serverList->setCurrentItem( m_serverList->count() );
}
else
delete server;
}
void OIpkgConfigDlg::slotServerEdit()
{
// Find selected server in list
OConfItem *server = m_ipkg->findConfItem( OConfItem::Source, m_serverList->currentText() );
// Edit server
if ( server )
{
QString origName = server->name();
OIpkgServerDlg dlg( server, this );
if ( QPEApplication::execDialog( &dlg ) == QDialog::Accepted )
{
// Check to see if name has changed, if so update the server list
if ( server->name() != origName )
m_serverList->changeItem( server->name(), m_serverCurrent );
}
}
}
void OIpkgConfigDlg::slotServerDelete()
{
// Find selected server in list
OConfItem *server = m_ipkg->findConfItem( OConfItem::Source, m_serverList->currentText() );
// Delete server
if ( server )
{
m_configs->removeRef( server );
m_serverList->removeItem( m_serverCurrent );
}
}
void OIpkgConfigDlg::slotDestSelected( int index )
{
m_destCurrent = index;
// Enable Edit and Delete buttons
m_destEditBtn->setEnabled( true );
m_destDeleteBtn->setEnabled( true );
}
void OIpkgConfigDlg::slotDestNew()
{
OConfItem *dest = new OConfItem( OConfItem::Destination );
OIpkgDestDlg dlg( dest, this );
if ( QPEApplication::execDialog( &dlg ) == QDialog::Accepted )
{
// Add to configuration option list
m_configs->append( dest );
m_configs->sort();
// Add to destination list
m_destList->insertItem( dest->name() );
m_destList->setCurrentItem( m_destList->count() );
}
else
delete dest;
}
void OIpkgConfigDlg::slotDestEdit()
{
// Find selected destination in list
OConfItem *dest = m_ipkg->findConfItem( OConfItem::Destination, m_destList->currentText() );
// Edit destination
if ( dest )
{
QString origName = dest->name();
OIpkgDestDlg dlg( dest, this );
if ( QPEApplication::execDialog( &dlg ) == QDialog::Accepted )
{
// Check to see if name has changed, if so update the dest list
if ( dest->name() != origName )
m_destList->changeItem( dest->name(), m_destCurrent );
}
}
}
void OIpkgConfigDlg::slotDestDelete()
{
// Find selected destination in list
OConfItem *destination = m_ipkg->findConfItem( OConfItem::Destination, m_destList->currentText() );
// Delete destination
if ( destination )
{
m_configs->removeRef( destination );
m_destList->removeItem( m_destCurrent );
}
}
void OIpkgConfigDlg::slotOptSelectSourceListsPath()
{
QString path = Opie::Ui::OFileDialog::getDirectory( 0, m_optSourceLists->text() );
if ( path.at( path.length() - 1 ) == '/' )
path.truncate( path.length() - 1 );
if ( !path.isNull() )
m_optSourceLists->setText( path );
}
OIpkgServerDlg::OIpkgServerDlg( OConfItem *server, QWidget *parent )
: QDialog( parent, QString::null, true, WStyle_ContextHelp )
, m_server( server )
{
setCaption( tr( "Edit Server" ) );
// Initialize UI
QVBoxLayout *layout = new QVBoxLayout( this, 2, 4 );
m_active = new QCheckBox( tr( "Active" ), this );
QWhatsThis::add( m_active, tr( "Tap here to indicate whether this entry is active or not." ) );
layout->addWidget( m_active );
layout->addStretch();
QLabel *label = new QLabel( tr( "Name:" ), this );
QWhatsThis::add( label, tr( "Enter the name of this entry here." ) );
layout->addWidget( label );
m_name = new QLineEdit( this );
QWhatsThis::add( m_name, tr( "Enter the name of this entry here." ) );
layout->addWidget( m_name );
layout->addStretch();
label = new QLabel( tr( "Address:" ), this );
QWhatsThis::add( label, tr( "Enter the URL address of this entry here." ) );
layout->addWidget( label );
m_location = new QLineEdit( this );
QWhatsThis::add( m_location, tr( "Enter the URL address of this entry here." ) );
layout->addWidget( m_location );
layout->addStretch();
m_compressed = new QCheckBox( tr( "Compressed server feed" ), this );
QWhatsThis::add( m_compressed, tr( "Tap here to indicate whether the server support compressed archives or not." ) );
layout->addWidget( m_compressed );
// Populate initial information
if ( m_server )
{
m_name->setText( m_server->name() );
m_location->setText( m_server->value() );
m_compressed->setChecked( m_server->features().contains( "Compressed" ) );
m_active->setChecked( m_server->active() );
}
}
void OIpkgServerDlg::accept()
{
// Save information entered
QString name = m_name->text();
name.replace( QRegExp( " " ), "_" );
m_server->setName( name );
m_server->setValue( m_location->text() );
m_compressed->isChecked() ? m_server->setFeatures( "Compressed" )
: m_server->setFeatures( QString::null );
m_server->setActive( m_active->isChecked() );
QDialog::accept();
}
OIpkgDestDlg::OIpkgDestDlg( OConfItem *dest, QWidget *parent )
: QDialog( parent, QString::null, true, WStyle_ContextHelp )
, m_dest( dest )
{
setCaption( tr( "Edit Destination" ) );
// Initialize UI
QVBoxLayout *layout = new QVBoxLayout( this, 2, 4 );
m_active = new QCheckBox( tr( "Active" ), this );
QWhatsThis::add( m_active, tr( "Tap here to indicate whether this entry is active or not." ) );
layout->addWidget( m_active );
layout->addStretch();
QLabel *label = new QLabel( tr( "Name:" ), this );
QWhatsThis::add( label, tr( "Enter the name of this entry here." ) );
layout->addWidget( label );
m_name = new QLineEdit( this );
QWhatsThis::add( m_name, tr( "Enter the name of this entry here." ) );