File filelist.cpp of Package fcmake

/***************************************************************************
 *   Copyright (C) 2008 Brno University of Technology,                     *
 *   Faculty of Information Technology                                     *
 *   Author(s): Marek Vavrusa    <xvavru00 AT stud.fit.vutbr.cz>           *
 *              Zdenek Vasicek   <vasicek  AT fit.vutbr.cz>                *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU Library 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 Library General Public     *
 *   License along with this program; if not, write to the                 *
 *   Free Software Foundation, Inc.,                                       *
 *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.         *
 ***************************************************************************/

#include <QFile>
#include <QTextStream>
#include <QDateTime>
#include <QDomElement>
#include <QDomNode>

#include <utime.h>
#include "filelist.h"

namespace FCMake
{

class FileList::Private
{
   public:
      Private(const QDir& root) : root(root) {}
      QDir root;
      QString xmlFilePath;
};

FileList::FileList(const QDir& root, bool refreshNow) : d(new Private(root))
{
   //if xmlFilePath not empty, read the list
   if (refreshNow)
      refresh();
}

FileList::~FileList()
{
   delete d;
}

const QDir& FileList::root()
{
   return d->root;
}

void FileList::refresh()
{
   clear();
   list(d->root);
}

void FileList::list(const QDir &dir)
{
   QString filePath;
   bool buildDir;
   QStringList filter;
   FileListItem item;

   //include the following files only
   filter << "*.c" << "*.h" << "*.vhd" << "*.vhdl" << "*.xml" << "*.inc" << "*.bin" << "*.hex" << "*.a";
   //is build directory?
   buildDir = dir.dirName() == "build";

   //append files
   foreach (QFileInfo entry, dir.entryInfoList(filter, QDir::NoDotAndDotDot | QDir::Files | QDir::Readable, QDir::Name))
   {
      filePath = entry.absoluteFilePath();
      if ((buildDir) && !(filePath.endsWith(".bin") || filePath.endsWith(".hex") || filePath.endsWith(".a"))) 
         continue;

      item.filePath = d->root.relativeFilePath(filePath);
      item.type = File;
      item.size = entry.size();
      item.mtime = entry.lastModified().toTime_t();
      append(item);
   }

   if (buildDir)
      return;

   //append directories
   foreach (QFileInfo entry, dir.entryInfoList(QDir::NoDotAndDotDot | QDir::Dirs | QDir::Readable, QDir::Name))
   {
      filePath = entry.absoluteFilePath();

      item.filePath = d->root.relativeFilePath(filePath);
      item.type = Dir;
      item.size = 0;
      item.mtime = entry.lastModified().toTime_t();
      append(item);

      list(QDir(filePath));
   }
}

QFileListMap* FileList::map() 
{
   QFileListMap* map = new QFileListMap();
   for (iterator item = begin(); item != end(); item++)
   {
      map->insert(item->filePath, &(*item));
//      map->insert(item->filePath, item-begin());
   }
   return map;
}

void FileList::filterChanges(FileList& oldList)
{
  if (oldList.root() != d->root)
  {
     qDebug("Can't compare - different root directories given");
     return;
  }

  QFileList newList;
  QFileListMap* map = oldList.map();
  FileListItem* itm;
  for (iterator item = begin(); item != end(); item++)
  {
     itm = map->value(item->filePath, 0);
     if ((itm == 0) || //new file
         (itm->mtime != item->mtime) //updated file
        )
     {
        newList.append(*item);
     }
  }

  clear();
  for (iterator item = newList.begin(); item != newList.end(); item++)
  {
     append(*item);
  }
}

//Write list to XML file
bool FileList::writeToXML(const QString& filePath)
{
   QFile xmlFile(d->root.absoluteFilePath(filePath));
   if (!xmlFile.open(QIODevice::WriteOnly))
      return false;
   
   QTextStream stream(&xmlFile);
   stream << "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<itemlist>\n";
   for (iterator item = begin(); item != end(); item++)
   {
      stream << "  <item type=\"" << ((item->type == Dir) ? "dir\" " : "file\"") << " ";
      stream << "name=\"" << item->filePath.toUtf8() << "\" ";
      if (item->type == File)
         stream << "size=\"" << item->size << "\" ";
      stream << "mtime=\"" << item->mtime <<"\" ";
      stream << "/>\n";
   }
   stream << "</itemlist>\n";
   xmlFile.close();

   return true;
}

//Load list from XML file
bool FileList::loadFromXML(const QString& filePath)
{
   clear();

   QFile xmlFile(d->root.absoluteFilePath(filePath));
   QDomDocument doc;
   FileListItem item;

   // Load document
   if (!doc.setContent(&xmlFile, true))
   {
      qDebug("Unable to parse XML file");
      return false;
   }

   // Parse header
   QDomElement root = doc.documentElement();
   if(root.tagName() != "itemlist")
      return false;

   for (QDomElement n = root.firstChildElement(); !n.isNull(); n = n.nextSiblingElement())
   {
      if (n.tagName() != "item")
      {
         qDebug("Unknown element %s", n.tagName().toStdString().c_str());
         return false;
      }

      item.type = File;
      item.filePath = n.attribute("name","");
      if (item.filePath.isEmpty()) 
         continue;

      if ((n.attribute("type") != "file") && (n.attribute("type") != "dir"))
      {
         qDebug("Unknown item type %s", n.attribute("type").toStdString().c_str());
         return false;
      }

      if (n.attribute("type") == "dir")
         item.type = Dir;

      item.size = n.attribute("size","0").toInt();
      item.mtime = n.attribute("mtime","0").toInt();

      append(item);
   }   
   // Parse data

   return true;
}

//nastavi u soboru co jsou v seznamu list stejne mtime jako ma soubor v list
void FileList::setMtimeFrom(FileList& list)
{
  struct utimbuf utb;
  FileListItem* itm;
  QString path;
  QFileListMap* map = list.map();

  for (iterator item = begin(); item != end(); item++)
  {
     itm = map->value(item->filePath, 0);
     if (itm != 0) //file item is in list, change mtime
     {
        path = QDir::toNativeSeparators(d->root.absoluteFilePath(item->filePath));
        utb.actime = itm->mtime;
        utb.modtime = itm->mtime;
        qDebug("Set mtime: %s to: %d",path.toStdString().c_str(), itm->mtime);

        if (utime(path.toStdString().c_str(), &utb) < 0)
           qDebug("Can't set mtime: %s", path.toStdString().c_str());
     }
  }

}
};
openSUSE Build Service is sponsored by