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.
tdeadmin/kpackage/packageInfo.cpp

636 lines
14 KiB

/*
** Copyright (C) 1999,2000 Toivo Pedaste <toivo@ucs.uwa.edu.au>
**
// Author: Damyan Pepper
// Author: Toivo Pedaste
*/
/*
** 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 in a file called COPYING; if not, write to
** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
** MA 02110-1301, USA.
*/
/*
** Bug reports and questions can be sent to kde-devel@kde.org
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
// Standard headers
#include <stdlib.h>
#include <tqregexp.h>
#include <tqdir.h>
#include <ctype.h>
// KDE headers
#include <kglobal.h>
#include <klocale.h>
#include <kdebug.h>
// kpackage headers
#include "kpackage.h"
#include "kplview.h"
#include "packageInfo.h"
#include "pkgInterface.h"
#include "managementWidget.h"
#include "utils.h"
#include "options.h"
// Global pixmap for
TQPixmap *pict = NULL;
//////////////////////////////////////////////////////////////////////////////
// Constructor -- get the pixmap
packageInfo::packageInfo(TQMap<TQString, TQString> _info, pkgInterface *type)
{
interface = type;
info = _info;
item = NULL;
packageState = UNSET;
updated = FALSE;
url = TQString();
}
// Another constructor, for a packge with a url
packageInfo::packageInfo(TQMap<TQString, TQString> _info, const TQString &_url)
{
info = _info;
url = _url;
item = NULL;
}
packageInfo::~packageInfo()
{
}
// Return a property
TQString packageInfo::getProperty(const TQString &property)
{
TQString result = info[property];
if (result.isEmpty()) {
return TQString();
}
return result;
}
// Check for existance of a property
bool packageInfo::hasProperty(const TQString &property)
{
TQString s = info[property];
if (s.isEmpty())
return false;
else
return true;
}
// Initialize fields if missing
void packageInfo::fixup()
{
if (info["name"].isEmpty()) {
TQString q;
q.setNum((long)this);
info.insert("name", q);
}
if (info["group"].isEmpty()) {
info.insert("group", i18n("OTHER"));
kdDebug() << "Package " << info["name"] << " has no group set." << endl;
}
if (!info["version"]) {
info.insert("version", "");
}
}
// Set the file name
void packageInfo::setFilename(const TQString &f)
{
url = f;
}
// Get the url
TQString packageInfo::getUrl()
{
if (url.isEmpty()) {
if (hasProperty("base") && hasProperty("filename")) {
url = getProperty("base") + "/" + getProperty("filename");
}
}
return url;
}
TQString packageInfo::fetchFilename()
{
TQString f = getFilename();
if (!f.isEmpty()) {
return f;
} else {
TQString aurl = getUrl();
if (!aurl.isEmpty()) {
return kpackage->fetchNetFile(aurl);
} else {
return getProperty("name");
}
}
}
bool packageInfo::isFileLocal()
{
TQString aurl = getUrl();
if (!aurl.isEmpty()) {
return KPACKAGE::isFileLocal(aurl);
}
return false;
}
bool packageInfo::isInstallable()
{
if (packageState != packageInfo::INSTALLED &&
!getProperty("filename").isNull() )
return true;
else
return false;
}
bool packageInfo::isFetchable()
{
if (interface->noFetch || !getFilename().isEmpty() )
return true;
else
return false;
}
TQString packageInfo::getFilename()
{
TQString cn = "";
TQString aurl = getUrl();
if (!aurl.isEmpty()) {
return KPACKAGE::getFileName(aurl,cn);
} else {
return "";
}
}
int packageInfo::getDigElement(const TQString &str, int *pos)
// Extract the next element from the string
// All digits
{
TQString s = str;
if (*pos < 0)
return -1;
s = s.mid(*pos);
if (s.isEmpty())
return -1;
TQRegExp ndig("[^0-9]");
int nf = 0;
int val = 0;
if ((s[0] >= '0') && (s[0] <= '9')) {
nf = s.tqfind(ndig);
if (nf >= 0) {
val = s.left(nf).toInt();
} else {
val = s.toInt();
nf = s.length();
}
}
// printf("n=%s %d %d\n",s.mid(nf,999).data(),nf,val);
*pos += nf;
return val;
}
TQString packageInfo::getNdigElement(const TQString &string, int *pos)
// Extract the next element from the string
// All all non-digits
{
TQString s(string);
if (*pos < 0)
return TQString();
s = s.mid(*pos);
if (s.isEmpty())
return TQString();
TQString str;
int nf = 0;
TQRegExp idig("[0-9]");
if ((s[0] < '0') || (s[0] > '9') ) {
nf = s.tqfind(idig);
if (nf < 0)
nf = s.length();
str = s.left(nf);
for (unsigned int i = 0; i < str.length() ; i++) {
// Strange Debian package sorting magic
if (!str[i].isLetter()) {
char t = str[i].latin1();
t += 128;
str[i] = t;
}
}
}
*pos += nf;
return str;
}
int packageInfo::pnewer(const TQString &s, const TQString &sp)
{
int ns = 0, nsp = 0, vs, vsp;
// kdDebug() << "S=" << s << " SP=" << sp << "\n";
while (TRUE) {
vs = getDigElement(s,&ns);
vsp = getDigElement(sp,&nsp);
// kdDebug() << "s=" << ns << " " << vs << " sp=" << nsp << " " << vsp << "\n";
if (vs < 0 && vsp < 0)
return 0;
if (vs < 0 && vsp < 0)
return 1;
if (vs < 0 && vsp < 0)
return -1;
if (vsp > vs)
return 1;
else if (vs > vsp)
return -1;
TQString svs = getNdigElement(s,&ns);
TQString svsp = getNdigElement(sp,&nsp);
// kdDebug() << "vs=" << ns << " " << svs << " sp=" << nsp << " " << svsp << "\n";
if (svs.isEmpty() && svsp.isEmpty())
return 0;
if (svs.isEmpty() && !svsp.isEmpty())
return 1;
if (!svs.isEmpty() && svsp.isEmpty())
return -1;
if (svsp.isNull()) { // Allow for QT strangeness comparing null string
svsp = "";
}
if (svs.isNull()) {
svs = "";
}
int n = svsp.compare(svs);
// kdDebug() << "svsp=" << svsp << "=" << svsp.length() << " svs=" << svs << "=" <<svs.length() << " n=" << n << "\n";
if (n != 0)
return n;
}
}
static bool split(TQString orig, char seperator, TQString &first, TQString &second)
{
int pos = orig.tqfind(seperator);
if (pos > 0) {
first = orig.mid(0,pos);
second = orig.mid(pos+1);
return true;
}
return false;
}
int packageInfo::newer(packageInfo *p)
{
TQString mySerial; // Serial number of this package
TQString myVersion; // Version of this package
TQString myRelease; // Release of this package
// Version of this package
TQString s = getProperty("version");
(void) split(s, ':', mySerial, s);
if (!split(s, '-', myVersion, myRelease))
{
myVersion = s;
}
// Version of other package
TQString hisSerial; // Serial number of the other package
TQString hisVersion; // Version of the other package
TQString hisRelease; // Release of the other package
s = p->getProperty("version");
if (p->hasProperty("release")) {
s = s + "-" + p->getProperty("release");
}
if (p->hasProperty("serial")) {
s = p->getProperty("serial") + ":" + s;
}
(void) split(s, ':', hisSerial, s);
if (!split(s, '-', hisVersion, hisRelease))
{
hisVersion = s;
}
// kdDebug() << "mySerial=" << mySerial << " hisSerial=" << hisSerial <<"\n";
// kdDebug() << "myVersion=" << myVersion << " hisVersion=" << hisVersion <<"\n";
// kdDebug() << "myRelease=" << myRelease << " hisRelease=" << hisRelease <<"\n";
int n = pnewer(mySerial,hisSerial);
if (n)
return n;
else {
n = pnewer(myVersion,hisVersion);
if (n)
return n;
else
return pnewer(myRelease,hisRelease);
}
}
bool packageInfo::display(int treeType)
{
switch (treeType) {
case Opts::INSTALLED:
if (packageState == INSTALLED || packageState == BAD_INSTALL)
return TRUE;
break;
case Opts::UPDATED:
if (packageState == UPDATED)
return TRUE;
break;
case Opts::NEW:
if ((packageState == UPDATED) || (packageState == NEW))
return TRUE;
break;
case Opts::ALL:
return TRUE;
break;
};
return FALSE;
}
//////////////////////////////////////////////////////////////////////
// Place the package in a TQListView
KpTreeListItem *packageInfo::place(KpTreeList *tree, bool insertI)
{
KpTreeListItem *search = tree->firstChild(), *tqparent=NULL, *child=NULL;
TQString qtmp, tmp;
bool doit = FALSE;
doit = TRUE;
if (packageState == NOLIST || packageState == HIDDEN)
doit = FALSE;
if (doit) {
qtmp = interface->head;
qtmp += "/";
qtmp += getProperty("group");
int cnt = 0;
TQStringList list = TQStringList::split("/",qtmp);
for ( TQStringList::Iterator it = list.begin(); it != list.end(); ++it ) {
KpTreeListItem *group;
if( search && (group=findGroup(*it, search)) ) {
tqparent = group;
tqparent->setOpen(TRUE);
search = group->firstChild();
} else {
if (tqparent) {
group = new KpTreeListItem(tqparent, 0, interface->folder, *it);
} else {
group = new KpTreeListItem(tree, 0, interface->folder, *it);
}
tqparent = group;
tqparent->setOpen(TRUE);
search = NULL;
}
cnt++;
}
tmp = *info.tqfind("name");
if(item)
delete item;
TQString sz = "";
if (!info["size"].isEmpty()) {
sz = info["size"].stripWhiteSpace();
if (sz.length() > 3)
sz.truncate(sz.length() - 3);
else
sz = "0";
sz += "K";
} else if (!info["file-size"].isEmpty()) {
sz = info["file-size"].stripWhiteSpace();
if (sz.length() > 3)
sz.truncate(sz.length() - 3);
else
sz = "0";
sz += "k";
}
sz = sz.rightJustify(6,' ');
TQString ver = "";
if (!info["version"].isEmpty()) {
ver = info["version"];
}
TQString over = "";
if (!info["old-version"].isEmpty()) {
over = info["old-version"];
}
TQString summary = "";
if (!info["summary"].isEmpty()) {
summary = info["summary"];
}
TQPixmap pic;
if (packageState == BAD_INSTALL) {
pic = interface->bad_pict;
} else if (packageState == UPDATED) {
pic = interface->updated_pict;
} else if (packageState == NEW) {
pic = interface->new_pict;
} else if (packageState == INSTALLED) {
pic = interface->pict;
} else {
pic = interface->pict;
}
if (child) {
item = new KpTreeListItem(child, this, pic, tmp, "", summary, sz, ver, over);
} else {
item = new KpTreeListItem(tqparent, this, pic, tmp, "", summary, sz, ver, over);
}
if (insertI) {
tqparent->setOpen(TRUE);
} else {
tqparent->setOpen(FALSE);
}
return item;
} else {
return 0;
}
}
//////////////////////////////////////////////////////////////////////
// Get the TQListViewItem
KpTreeListItem *packageInfo::getItem()
{
return item;
}
//////////////////////////////////////////////////////////////////////////////
bool packageInfo::smerge( const TQString &exp) {
TQDict<packageInfo> *dirInfoPackages = kpackage->management->dirInfoPackages;
TQString pname = getProperty("name") + exp;
packageInfo *pi = dirInfoPackages->tqfind(pname);
if (pi) {
TQMap<TQString,TQString>::Iterator it;
for ( it = pi->info.begin(); it != pi->info.end(); ++it ) {
if (!(it.key() == "size" && !info["size"].isEmpty()) ||
!(it.key() == "file-size" && !info["file-size"].isEmpty())) {
info.insert(it.key(), it.data());
}
++it;
}
return TRUE;
}
return FALSE;
}
//////////////////////////////////////////////////////////////////////////////
void packageInfo::pkgFileIns(const TQString &fileName)
{
info.insert("filename", fileName);
info.insert("base", "/");
if (pkgInsert(kpackage->management->allPackages, interface->typeID, FALSE)) {
packageState = packageInfo::NEW;
place(kpackage->management->treeList,TRUE);
TQString pname = getProperty("name") + interface->typeID;
kpackage->management->dirUninstPackages->insert(pname,this);
}
}
//////////////////////////////////////////////////////////////////////////////
bool packageInfo::pkgInsert(TQPtrList<packageInfo> *pki, const TQString &exp,
bool installed, bool infoPackage)
{
TQDict<packageInfo> *dirInstPackages = kpackage->management->dirInstPackages;
TQDict<packageInfo> *dirUninstPackages = kpackage->management->dirUninstPackages;
TQDict<packageInfo> *dirInfoPackages = kpackage->management->dirInfoPackages;
TQString pname = getProperty("name") + exp;
// printf("U1=%s\n",pname.data());
bool shouldUpdate = TRUE;
bool hidden = FALSE;
packageInfo *pi = dirInstPackages->tqfind(pname);
if (pi) { // installed version exists
if ((pi->packageState != BAD_INSTALL)
&& (pi->packageState != NOLIST)) {
if (newer(pi) >= 0) {
hidden = TRUE;
}
}
}
packageInfo *pu = dirUninstPackages->tqfind(pname);
if (pu) { // available version exists
if ((pu->packageState != BAD_INSTALL)
&& (pu->packageState != NOLIST)) {
if (newer(pu) >= 0) {
shouldUpdate = FALSE;
} else if (!installed) { // If older available package exists, remove it
dirUninstPackages->remove(*(pu->info.tqfind("name")));
pki->remove(pu);
}
}
}
if (getProperty("version").isEmpty()) {
shouldUpdate = TRUE;
}
if (shouldUpdate) {
if (packageState != BAD_INSTALL) {
if (installed)
packageState = INSTALLED;
else if (pi) { // installed version exists
if (hidden) {
packageState = HIDDEN;
} else {
TQString version = pi->getProperty("version");
if (version.isEmpty()) {
if (pi->packageState == NOLIST)
packageState = NEW;
else
packageState = UPDATED;
} else {
packageState = UPDATED;
if (pi->hasProperty("old-version")) {
info.insert("old-version",
pi->getProperty("old-version"));
} else {
info.insert("old-version",version);
}
TQString group = getProperty("group");
if (group == "NEW") {
if (pi->hasProperty("group")) {
info.tqreplace("group",
pi->getProperty("group") );
}
}
}
}
} else
packageState = NEW;
}
pki->insert(0,this);
if (installed) {
if (infoPackage)
dirInfoPackages->insert(pname,this);
else
dirInstPackages->insert(pname,this);
} else
dirUninstPackages->insert(pname,this);
return TRUE;
} else {
return FALSE;
}
}
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////