Logo Search packages:      
Sourcecode: katalog version File versions  Download package

katalog.cpp

/***************************************************************************
 *   Copyright (C) 2004 by Stefano Salvador                                *
 *   salva_ste@tin.it                                                      *
 *                                                                         *
 *   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.             *
 ***************************************************************************/

#include <qdatetime.h>
#include <qdom.h>
#include <qmap.h>

#include <kmimetype.h>
#include <ktempfile.h>
#include <kdebug.h>
#include <kio/job.h>
#include <kfileitem.h>
#include <kio/netaccess.h>
#include <kfilterdev.h>
#include <klocale.h>
#include <kglobal.h>
#include <kstandarddirs.h>
#include <kinstance.h>

#include "katalog.h"

#define DOC_TYPE "KDEKatalog"
#define ROOT "KATALOG"
#define CATALOG "CATALOG"
#define ITEM "ITEM"
#define META "META"
#define GROUP "GROUP"

using namespace KIO;
  
KatalogJobItem::KatalogJobItem()
{}

KatalogJobItem::KatalogJobItem(KURL& _u, QStringList& _p){
  u = _u;
  p = _p;
}
  
KURL KatalogJobItem::url() const
{
  return u;
}
  
QStringList KatalogJobItem::path() const
{
  return p;
}
  
bool KatalogJobItem::isEmpty()
{
  return u.isEmpty() || p.isEmpty();
}
  
bool KatalogJobItem::operator==( const KatalogJobItem & kji ) const
{
  return u == kji.url() && p == kji.path();
}

Katalog::Katalog()
{
  m_changed = false;
}

Katalog::~Katalog()
{}

bool Katalog::isChanged()
{
  return m_changed;
}

KatalogJobItem Katalog::find(const KURL& url) const
{
  QValueListConstIterator<KatalogJobItem> it;
  for ( it = m_jobs.begin(); it != m_jobs.end(); ++it )
  {
    if((*it).url() == url)
      return *it;        
  }
  return KatalogJobItem();
}

00100 int Katalog::initDocument(const KURL& url)
{
  QString tmpfile;
  QIODevice * dev = 0L;
  bool newFile = FALSE;
  if( !url.isEmpty() && NetAccess::download( url, tmpfile ) )
  {
    dev = KFilterDev::deviceForFile( tmpfile, "application/x-gzip");
    if(!dev->open( IO_ReadOnly ))
      return UNREADABLE_URL;
  }
  else
    newFile = TRUE;
  
  m_document = QDomDocument();
  if(newFile)
  {
    QDomImplementation implementation;
    m_document = implementation.createDocument(
                   QString::null,
                   ROOT, 
                   implementation.createDocumentType(DOC_TYPE, QString::null, QString::null));
    m_rootElement = m_document.firstChild().toElement();
  }
  else
  {
    int Line;
    int Col;
    QString str;
    if ( !dev || 
         !m_document.setContent( dev, true, &str, &Line, &Col ) ||
         m_document.doctype().name().compare(DOC_TYPE))
    {
      dev->close();
      NetAccess::removeTempFile( tmpfile );
      return NOT_KATALOG;
    }
      
    dev->close();
    NetAccess::removeTempFile( tmpfile );
      
    QDomNode node = m_document.firstChild();
    
    if(node.isNull() || node.nodeName() != ROOT)
      return UNCOMPLETE;
    
    m_rootElement = node.toElement();
  }
  
  m_changed = false;

  return SUCCESS;
}

00154 bool Katalog::rename(QStringList& path, QString& newName)
{
  if(newName.isEmpty())
    return FALSE;
  
  QDomNode srcNode = findNode(path);

  if(srcNode.isNull())
    return FALSE;
  
  srcNode.toElement().removeAttribute("name");
  
  srcNode.toElement().setAttribute("name", newName);
  
  m_changed = true;

  return TRUE;
}

00173 void Katalog::del(QStringList& path)
{
  QDomNode srcNode = findNode(path);
  
  if(srcNode.isNull())
    return;
  
  QDomNode parentNode = srcNode.parentNode();
  parentNode.removeChild(srcNode);
  m_changed = true;
}

00185 bool Katalog::saveDocument(const KURL& url, const char *format)
{
  
  KURL file = KURL(url);
  
  if(!file.isValid())
    return FALSE;
    
  QString tmpName;
  QIODevice *dev;
  if(!file.isLocalFile())
  {
    KTempFile tmpFile;
    tmpName = tmpFile.name();
    dev = KFilterDev::deviceForFile( tmpName, format );
  }
  else
    dev = KFilterDev::deviceForFile( file.path(), format );
  
  if(!dev->open( IO_WriteOnly ))
    return FALSE;
  
  QTextStream ds( dev );
  ds << m_document.toString(2);
  dev->close();
  delete dev;
  
  if(!file.isLocalFile())
    NetAccess::upload( tmpName, file );
  
  m_changed = false;
  
  return TRUE;
}
  
/** Returns the Meta Info of the specified file */
00221 QString Katalog::readInfo(QStringList& path) const
{
  QDomNode node = findNode(path);
  QDomDocument doc;
  
  if(!node.isNull() && node.nodeName().compare(ROOT) == 0 )
  {
    QDomElement metaEl = doc.createElement(META);
    QDomElement groupEl = doc.createElement(GROUP);
    groupEl.setAttribute("name", "Katalog");
    QDomElement itemEl1 = doc.createElement(ITEM);
    itemEl1.setAttribute("key", i18n("Total Catalogs"));
    itemEl1.setAttribute("int_value", totalCatalogs() );
    groupEl.appendChild(itemEl1);
    QDomElement itemEl2 = doc.createElement(ITEM);
    itemEl2.setAttribute("key", i18n("Total Items"));
    itemEl2.setAttribute("int_value", totalItems());
    groupEl.appendChild(itemEl2);
    metaEl.appendChild(groupEl);
    doc.appendChild(metaEl);
    return doc.toString(2);
  }
  
  if(!node.isNull() && node.nodeName().compare(CATALOG) == 0 )
  {
    QDomElement metaEl = doc.createElement(META);
    QDomElement groupEl = doc.createElement(GROUP);
    groupEl.setAttribute("name", "Katalog");
    QDomElement itemEl1 = doc.createElement(ITEM);
    itemEl1.setAttribute("key", i18n("Total Items"));
    itemEl1.setAttribute("int_value", itemsInNode(node));
    groupEl.appendChild(itemEl1);
    QDomElement itemEl2 = doc.createElement(ITEM);
    itemEl2.setAttribute("key", i18n("Original Medium"));
    itemEl2.setAttribute("string_value", sourceURL(path).prettyURL());
    groupEl.appendChild(itemEl2);
    metaEl.appendChild(groupEl);
    doc.appendChild(metaEl);
    return doc.toString(2);
  }
  
  QDomNode metaNode = node.firstChild();
  QDomElement groupElI = doc.createElement(GROUP);
  
  if(!node.isNull() && node.nodeName().compare(ITEM) == 0 )
  {
    groupElI.setAttribute("name", "Katalog");
    QDomElement itemEl = doc.createElement(ITEM);
    itemEl.setAttribute("key", i18n("Mimetype"));
    itemEl.setAttribute("string_value", node.toElement().attribute("mimetype") );
    groupElI.appendChild(itemEl);    
  }
  
  if(!metaNode.isNull() && metaNode.nodeName().compare(META) == 0 )
  {
    if(groupElI.hasChildNodes())
      metaNode.appendChild(groupElI);
    doc.appendChild(metaNode);
    return doc.toString(2);
  }
  return "";
}
 
00284 int Katalog::addItems(const KURL& mount, QString name, bool exploreArchives, bool getMetaInfo)
{
  m_exploreArchives = exploreArchives;
  m_getMetaInfo = getMetaInfo;
  
  if(name.isNull() || name.isEmpty())
    return NAME_EMPTY;
    
  QDateTime date(QDate::currentDate(), QTime::currentTime());
    
  ListJob *job = listRecursive( mount, false );
  m_currentUrl = mount.path();
  QStringList list(name);
  QDomNode node = findNode(list);
  QDomElement el;
  if(node.isNull())
  {
    el = m_document.createElement(CATALOG);
    el.setAttribute("name", name);
    el.setAttribute("type", E_DIR);
    el.setAttribute("mimetype", "inode/directory");
    el.setAttribute("time", date.toTime_t());
    el.setAttribute("mount", mount.url());
    m_rootElement.appendChild(el);
  }
  else
    el = node.toElement();
  
  KURL u = job->url();
  QStringList l(name);
  m_jobs.append( KatalogJobItem(u, l));
  
  connect( job, SIGNAL( entries( KIO::Job *, const KIO::UDSEntryList & ) ),
           this, SLOT( slotEntries( KIO::Job *, const KIO::UDSEntryList & ) ) );
  connect( job, SIGNAL( result( KIO::Job * ) ),
           this, SLOT( slotResult( KIO::Job * ) ) );
  connect( job, SIGNAL( redirection( KIO::Job *, const KURL& ) ),
           this, SLOT( slotRedirection( KIO::Job *, const KURL& ) ) );
  
  m_changed = true;

  return SUCCESS;
}

00328 KURL Katalog::sourceURL(QStringList& path) const
{
  KURL url;
  QString catalog = *(path.begin());
  QStringList catalogList;
  catalogList.append(catalog);
  QDomNode catalogNode = findNode(catalogList);
  if(catalogNode.isNull())
    return url;
  
  QString baseURL = catalogNode.toElement().attribute("mount");
  if(baseURL.isEmpty())
    return url;
    
  path.remove(path.begin());
  QString pathURL = path.join("/");
  
  return KURL(baseURL + "/" + pathURL);
}

00348 KatalogUDSEntry Katalog::findEntry(QStringList& path) const
{
  QDomNode node = findNode(path);
  if(node == m_rootElement)
  {
    KatalogUDSEntry entry;
    KatalogUDSAtom atom;
    atom.m_uds = UDS_FILE_TYPE;
    atom.m_long = S_IFDIR;
    entry.append( atom );
    return entry;
  }
  
  if(node.isNull()){
    KatalogUDSEntry entry;
    entry.clear();
    return entry;
  }
  
  return createUDSEntry(node.toElement());
}

00370 KatalogUDSEntryList Katalog::getNodeContent(QStringList& path) const
{
  KatalogUDSEntryList l;
  QDomNode parentNode = findNode(path);
  QDomNode node = parentNode.firstChild();
  while ( !node.isNull() )
  {
    if(!node.isElement())
      continue;
    l.append( createUDSEntry(node.toElement()) );
    node = node.nextSibling();
  }
  return l;
}

00385 QDomNode Katalog::findNode(QStringList& path) const
{
  // Search logic:
  // path[0] <---> it is the catalog, find corresponding node walking through children of root node
  // no more path? ==> return node
  // path[1] <---> find corresponding node walking through children of previously find node
  // no more path? ==> return node
  // ...
  
  QStringList::Iterator it;
  
  QDomNode node = m_rootElement;
  
  for(it = path.begin(); it != path.end(); it++ )
  {
    node = node.firstChild();
    // find the correct children, if not found node.isNull() == true
    while ( !node.isNull())
    {
      if ( (node.nodeName() == CATALOG || node.nodeName() == ITEM ) &&
           node.isElement() &&
           node.toElement().attribute( "name" ).compare( *it ) == 0)
        break;
      // nothing this run try another
      node = node.nextSibling();
    }
    if(node.isNull())
    {
      // path item not found, useless to continue :-(
      node = QDomNode();
      break;
    }
  }
  
  return node;
}

void Katalog::slotEntries(Job *job, const UDSEntryList &entries)
{
  KURL url = static_cast<ListJob *>(job)->url();
  
  KatalogJobItem item = find(url);
  if(item.isEmpty())
    return;
    
  QStringList path = item.path();
  
  UDSEntryListConstIterator it = entries.begin();
  UDSEntryListConstIterator end = entries.end();
  for ( ; it != end; ++it )
  {
    QString name;

    UDSEntry::ConstIterator entit = (*it).begin();
    for( ; entit != (*it).end(); ++entit )
      if ( (*entit).m_uds == UDS_NAME )
      {
        name = (*entit).m_str;
        break;
      }

    if ( name.isEmpty() || name == "." || name == "..")
      continue;
    
    KFileItem item( *it, url, false, true );
    
    QStringList tmpPath = path + QStringList::split("/", name);
    QString nameEl = tmpPath.last();
    tmpPath.pop_back();
    QDomElement childNode = m_document.createElement(ITEM);
    
    QDateTime date;
    date.setTime_t( item.time( UDS_MODIFICATION_TIME ));
    childNode.setAttribute("name", nameEl);
    if(item.isDir())
      childNode.setAttribute("type", E_DIR);
    else if(item.isFile())
      childNode.setAttribute("type", E_FILE);
    else if(item.isLink())
      childNode.setAttribute("type", E_LINK);
    childNode.setAttribute("mimetype", item.mimetype()); 
    childNode.setAttribute("time", date.toTime_t());
    childNode.setAttribute("size", number( item.size() ));
    childNode.setAttribute("user", item.user());
    childNode.setAttribute("group", item.group());
    childNode.setAttribute("permissions", item.permissions());
    
    if(m_getMetaInfo)
    {
      KFileMetaInfo minfo = item.metaInfo();
    
      if(minfo.isValid() && !minfo.isEmpty())
      {
        QDomElement metaNode = m_document.createElement(META);
        QStringList groupKeyList = minfo.supportedGroups();
        for ( QStringList::Iterator it = groupKeyList.begin(); it != groupKeyList.end(); ++it )
        {
          KFileMetaInfoGroup group = minfo.group(*it);
          if(!group.isEmpty())
          {
            QDomElement groupNode = m_document.createElement(GROUP);
            groupNode.setAttribute("name", group.name());
            uint attributes = group.attributes() & KFileMimeTypeInfo::MultiLine;
            if(attributes != 0)
              groupNode.setAttribute("attributes", attributes);
            QStringList itemKeyList = group.supportedKeys();
            for ( QStringList::Iterator it = itemKeyList.begin(); it != itemKeyList.end(); ++it )
            {
              KFileMetaInfoItem minfoitem = minfo.item(*it);
              QDomElement itemNode = m_document.createElement(ITEM);
              itemNode.setAttribute("key", minfoitem.translatedKey());
              QVariant v = minfoitem.value();
              bool addFlag = true;
              switch(v.type())
              {
                case QVariant::Int :
                  itemNode.setAttribute("int_value", v.asInt());
                  break;
                case QVariant::Bool :
                  itemNode.setAttribute("bool_value", v.asBool());
                  break;
                case QVariant::Date :
                  itemNode.setAttribute("date_value", v.asDate().toString());
                  break;
                case QVariant::DateTime :
                  itemNode.setAttribute("datetime_value", v.asDateTime().toTime_t());
                  break;
                case QVariant::Double :
                  itemNode.setAttribute("double_value", v.asDouble());
                  break;
                case QVariant::LongLong :
                  itemNode.setAttribute("long_value", (long int)v.asLongLong());
                  break;
                case QVariant::String :
                default :
                  QString str = v.asString();
                  if(str.isEmpty())
                    addFlag = false;
                  itemNode.setAttribute("string_value", v.asString());
                  break;
              }
              uint unit = minfoitem.unit();
              if(unit != KFileMimeTypeInfo::NoUnit)
                itemNode.setAttribute("unit", unit);
              uint attributes = minfoitem.attributes() & KFileMimeTypeInfo::MultiLine;
              if(attributes != 0)
                itemNode.setAttribute("attributes", attributes);
              uint hint = minfoitem.hint();
              if(hint != KFileMimeTypeInfo::NoHint)
                itemNode.setAttribute("hint", hint);
              if(addFlag)
                groupNode.appendChild(itemNode);     
            }
            metaNode.appendChild(groupNode);
          }
        }
        childNode.appendChild(metaNode);
      }
    }
    
    QDomNode node = findNode(tmpPath);
    if(!node.isNull())
      node.appendChild(childNode);
    else
      continue;
      
    bool supportedProtocol = false;
    KURL subUrl;
    if(item.mimetype() == "application/x-tgz" || 
       item.mimetype() == "application/x-tbz" || 
       item.mimetype() == "application/x-tar") {
      subUrl.setProtocol("tar");
      supportedProtocol = true;
    } else if(item.mimetype() == "application/x-zip") {
      subUrl.setProtocol("zip");
      supportedProtocol = true;
    }
    
    if(supportedProtocol && m_exploreArchives){
      subUrl.setPath( item.url().path());
      tmpPath.append( nameEl );
      KatalogJobItem kji( subUrl, tmpPath );
      m_jobs.append(kji);
    }
  }
}

void Katalog::slotResult(Job *job)
{ 
  KatalogJobItem item = find(static_cast<ListJob *>(job)->url());
  m_jobs.remove(item);
  
  if(m_jobs.isEmpty()){
    emit finished(m_currentUrl);
  }
  else
  {
    item = *(m_jobs.begin());
    KURL subUrl = item.url();
    ListJob *subjob = listRecursive( (KURL)subUrl, false );
    connect( subjob, SIGNAL( entries( KIO::Job *, const KIO::UDSEntryList & ) ),
             this, SLOT( slotEntries( KIO::Job *, const KIO::UDSEntryList & ) ) );
    connect( subjob, SIGNAL( result( KIO::Job * ) ),
             this, SLOT( slotResult( KIO::Job * ) ) );
    connect( subjob, SIGNAL( redirection( KIO::Job *, const KURL& ) ),
             this, SLOT( slotRedirection( KIO::Job *, const KURL& ) ) );
  }
}

void Katalog::slotRedirection(Job *job, const KURL& newUrl)
{ 
  KatalogJobItem item = find(static_cast<ListJob *>(job)->url());
  
  if(item.isEmpty())
    return;
    
  KURL u(newUrl);
  QStringList l(item.path());
  
  KatalogJobItem newItem(u, l);
  m_jobs.remove(item);
  m_jobs.append(item);
}

KatalogUDSEntry Katalog::createUDSEntry(QDomElement node) const
{
  KatalogUDSEntry entry;
  entry.clear();
  int type = node.toElement().attribute( "type" ).toInt();
  if(!node.firstChild().isNull() && node.firstChild().nodeName().compare(META) )
    type = E_DIR;
   
  KatalogUDSAtom atom;
  atom.m_uds = UDS_NAME;
  atom.m_str = node.toElement().attribute("name");
  entry.append( atom );
  
  atom.m_uds = UDS_FILE_TYPE;
  switch(type)
  {
    case E_FILE:
      atom.m_long = S_IFREG;
      break;
    case E_DIR:
      atom.m_long = S_IFDIR;
      break;
    case E_LINK:
      atom.m_long = S_IFLNK;
      break;
  }
  entry.append( atom );
  
  atom.m_uds = UDS_MODIFICATION_TIME;
  atom.m_long = node.toElement().attribute( "time" ).toInt();
  entry.append( atom );
  
  atom.m_uds = UDS_SIZE;
  atom.m_long = node.toElement().attribute( "size" ).toInt();
  entry.append( atom );
  
  atom.m_uds = UDS_MIME_TYPE;
  if(type == E_DIR)
    atom.m_str = "inode/katalog-directory";
  else
    atom.m_str = "application/x-katalogitem";
  entry.append( atom );
  
  if(!node.toElement().attribute( "user" ).isNull())
  {
    atom.m_uds = UDS_USER;
    atom.m_str = node.toElement().attribute( "user" );
    entry.append( atom );
  }
  
  if(!node.toElement().attribute( "group" ).isNull())
  {
    atom.m_uds = UDS_GROUP;
    atom.m_str = node.toElement().attribute( "group" );
    entry.append( atom );
  }
  
  if(!node.toElement().attribute( "permissions" ).isNull())
  {
    atom.m_uds = UDS_ACCESS;
    atom.m_long = node.toElement().attribute( "permissions" ).toInt();
    entry.append( atom );
  }
  
  return entry;
}

int totItems;

int Katalog::totalItems() const
{
  int totItems = 0;
  QDomNode n = m_rootElement.firstChild();
  while ( !n.isNull() ) {
    if ( !n.nodeName().compare(CATALOG)) {
      totItems += itemsInNode(n);
    }
    n = n.nextSibling();
  }  
  return totItems;
}

int Katalog::itemsInNode(QDomNode& node) const
{
  int totItems = 0;
  QDomNode n = node.firstChild();
  while ( !n.isNull() ) {
    if ( !n.nodeName().compare(ITEM)) {
      totItems++;
      if(!n.firstChild().isNull())
        totItems += itemsInNode(n);
    }
    n = n.nextSibling();
  }
  return totItems;
}
  
int Katalog::totalCatalogs() const
{
  int tot = 0;
  QDomNode n = m_rootElement.firstChild();
  while ( !n.isNull() ) {
    if ( !n.nodeName().compare(CATALOG)) {
      tot ++;
    }
    n = n.nextSibling();
  }
  return tot;
}     

#include "katalog.moc"

Generated by  Doxygen 1.6.0   Back to index