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.
443 lines
12 KiB
443 lines
12 KiB
/***************************************************************************
|
|
*
|
|
* Copyright (C) 2007 Elad Lahav (elad_lahav@users.sourceforge.net)
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
*
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AS IS'' AND ANY EXPRESS OR
|
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*
|
|
***************************************************************************/
|
|
|
|
#include <unistd.h>
|
|
#include <fcntl.h>
|
|
#include <errno.h>
|
|
#include <tdemessagebox.h>
|
|
#include <tdelocale.h>
|
|
#include "project.h"
|
|
#include "kscopeconfig.h"
|
|
#include "cscopefrontend.h"
|
|
|
|
#define PROJECT_CONFIG_VER 2
|
|
|
|
inline void flListFromStringList(FileLocationList& fll, const TQStringList& sl)
|
|
{
|
|
TQStringList::ConstIterator itr;
|
|
TQString sPath;
|
|
uint nLine, nCol;
|
|
|
|
// Transform the string into a list of file locations
|
|
for (itr = sl.begin(); itr != sl.end(); ++itr) {
|
|
sPath = (*itr).section(':', 0, 0);
|
|
nLine = (*itr).section(':', 1, 1).toUInt();
|
|
nCol = (*itr).section(':', 2, 2).toUInt();
|
|
fll.append(new FileLocation(sPath, nLine, nCol));
|
|
}
|
|
}
|
|
|
|
inline void stringListFromFlList(TQStringList& sl, const FileLocationList& fll)
|
|
{
|
|
FileLocationList* pList;
|
|
FileLocation* pLoc;
|
|
TQString sLoc;
|
|
|
|
// Nasty...
|
|
pList = (FileLocationList*)&fll;
|
|
sl.clear();
|
|
|
|
// Turn the object list into a string list, so that it can be written in
|
|
// the configuration file
|
|
for (pLoc = pList->first(); pLoc != NULL; pLoc = pList->next()) {
|
|
sLoc = "";
|
|
TQTextOStream(&sLoc) << pLoc->m_sPath << ":" << pLoc->m_nLine << ":"
|
|
<< pLoc->m_nCol;
|
|
sl.append(sLoc);
|
|
}
|
|
}
|
|
|
|
/**
|
|
*/
|
|
Project::Project() : ProjectBase(),
|
|
m_pConf(NULL)
|
|
{
|
|
}
|
|
|
|
/**
|
|
*/
|
|
Project::~Project()
|
|
{
|
|
close();
|
|
}
|
|
|
|
/**
|
|
*/
|
|
bool Project::open(const TQString& sPath)
|
|
{
|
|
TQString sConfFile;
|
|
Options opt;
|
|
|
|
// Associate the object with the project directory
|
|
m_dir.setPath(sPath);
|
|
if (!m_dir.exists()) {
|
|
KMessageBox::error(0, i18n("Project directory does not exist"));
|
|
return false;
|
|
}
|
|
|
|
// Initialise the file-list file object
|
|
m_fiFileList.setName(sPath + "/cscope.files");
|
|
|
|
// Open the configuration files
|
|
m_pConf = new TDEConfig(sPath + "/cscope.proj");
|
|
|
|
// Verify the configuration file's version is compatible
|
|
m_pConf->setGroup("");
|
|
if (m_pConf->readUnsignedNumEntry("Version", 0) != PROJECT_CONFIG_VER) {
|
|
KMessageBox::error(0, i18n("Your project is not compatible with this "
|
|
"version of KScope.\nPlease re-create the project."));
|
|
return false;
|
|
}
|
|
|
|
// Get the project name
|
|
m_pConf->setGroup("Project");
|
|
m_sName = m_pConf->readEntry("Name");
|
|
if (m_sName == TQString::null) {
|
|
KMessageBox::error(0, i18n("Cannot read project name"));
|
|
return false;
|
|
}
|
|
|
|
// Get stored options
|
|
initOptions();
|
|
|
|
// Set default make values for new projects (overriden in loadSession(),
|
|
// which is not called for new projects)
|
|
m_sMakeRoot = getSourceRoot();
|
|
m_sMakeCmd = "make";
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
*/
|
|
void Project::close()
|
|
{
|
|
if (m_pConf)
|
|
delete m_pConf;
|
|
|
|
m_fiFileList.close();
|
|
}
|
|
|
|
/**
|
|
* Returns a semi-colon separated list of the file types included in the
|
|
* current project.
|
|
*/
|
|
TQString Project::getFileTypes() const
|
|
{
|
|
TQString sTypes;
|
|
|
|
m_pConf->setGroup("Project");
|
|
return m_pConf->readEntry("FileTypes");
|
|
}
|
|
|
|
/**
|
|
* Reads the project's options from the configuration file.
|
|
* @param opt A structure to fill with the read options
|
|
*/
|
|
void Project::getOptions(Options& opt) const
|
|
{
|
|
// Get project properties
|
|
m_pConf->setGroup("Project");
|
|
opt.sSrcRootPath = m_pConf->readEntry("RootPath", "/");
|
|
opt.slFileTypes = m_pConf->readListEntry("FileTypes", ' ');
|
|
opt.bKernel = m_pConf->readBoolEntry("Kernel", DEF_IS_KERNEL);
|
|
opt.bInvIndex = m_pConf->readBoolEntry("InvIndex", DEF_INV_INDEX);
|
|
opt.bNoCompress = m_pConf->readBoolEntry("NoCompress", DEF_NO_COMPRESS);
|
|
opt.bSlowPathDef = m_pConf->readBoolEntry("SlowPathDef", DEF_SLOW_PATH);
|
|
opt.nAutoRebuildTime = m_pConf->readNumEntry("AutoRebuildTime");
|
|
opt.nTabWidth = m_pConf->readUnsignedNumEntry("TabWidth");
|
|
opt.sCtagsCmd = m_pConf->readEntry("CtagsCommand", DEF_CTAGS_COMMAND);
|
|
|
|
// Get auto-completion options
|
|
m_pConf->setGroup("AutoCompletion");
|
|
opt.bACEnabled = m_pConf->readBoolEntry("Enabled");
|
|
opt.nACMinChars = m_pConf->readUnsignedNumEntry("MinChars",
|
|
DEF_AC_MIN_CHARS);
|
|
opt.nACDelay = m_pConf->readUnsignedNumEntry("Delay", DEF_AC_DELAY);
|
|
opt.nACMaxEntries = m_pConf->readUnsignedNumEntry("MaxEntries",
|
|
DEF_AC_MAX_ENTRIES);
|
|
}
|
|
|
|
/**
|
|
* Sets project options.
|
|
* @param opt A structure containing the new parameters to set
|
|
*/
|
|
void Project::setOptions(const Options& opt)
|
|
{
|
|
// Write the options to the configuration nfile
|
|
writeOptions(m_pConf, opt);
|
|
|
|
// Update project parameters
|
|
initOptions();
|
|
}
|
|
|
|
/**
|
|
*/
|
|
void Project::loadSession(Session& sess)
|
|
{
|
|
TQStringList slEntry;
|
|
|
|
m_pConf->setGroup("Session");
|
|
|
|
// Read the list of open file locations
|
|
slEntry = m_pConf->readListEntry("OpenFiles");
|
|
flListFromStringList(sess.fllOpenFiles, slEntry);
|
|
|
|
// Get the path of the last viewed file
|
|
sess.sLastFile = m_pConf->readEntry("LastOpenFile");
|
|
|
|
// Read the lists of locked query files and call-tree/graph files
|
|
sess.slQueryFiles = m_pConf->readListEntry("QueryFiles");
|
|
sess.slCallTreeFiles = m_pConf->readListEntry("CallTreeFiles");
|
|
|
|
// Read the list of bookmarks
|
|
slEntry = m_pConf->readListEntry("Bookmarks");
|
|
flListFromStringList(sess.fllBookmarks, slEntry);
|
|
|
|
// Read make-related information
|
|
sess.sMakeCmd = m_pConf->readEntry("MakeCommand", "make");
|
|
sess.sMakeRoot = m_pConf->readEntry("MakeRoot", getSourceRoot());
|
|
|
|
// Cache make values
|
|
m_sMakeCmd = sess.sMakeCmd;
|
|
m_sMakeRoot = sess.sMakeRoot;
|
|
}
|
|
|
|
/**
|
|
* Saves session-related information in the project's configuration file.
|
|
* @param sess Session parameters
|
|
*/
|
|
void Project::storeSession(const Session& sess)
|
|
{
|
|
TQStringList slEntry;
|
|
|
|
m_pConf->setGroup("Session");
|
|
|
|
// Write the list of open file locations
|
|
stringListFromFlList(slEntry, sess.fllOpenFiles);
|
|
m_pConf->writeEntry("OpenFiles", slEntry);
|
|
|
|
// Write the path of the last viewed file
|
|
m_pConf->writeEntry("LastOpenFile", sess.sLastFile);
|
|
|
|
// Write the lists of locked query files and call-tree/graph files
|
|
m_pConf->writeEntry("QueryFiles", sess.slQueryFiles);
|
|
m_pConf->writeEntry("CallTreeFiles", sess.slCallTreeFiles);
|
|
|
|
// Write the list of bookmarks
|
|
stringListFromFlList(slEntry, sess.fllBookmarks);
|
|
m_pConf->writeEntry("Bookmarks", slEntry);
|
|
|
|
// Write make-related information
|
|
// Be careful not to write empty strings, as they may occur if the make
|
|
// dialogue was not invoked during this session
|
|
if (!sess.sMakeCmd.isEmpty())
|
|
m_pConf->writeEntry("MakeCommand", sess.sMakeCmd);
|
|
if (!sess.sMakeRoot.isEmpty())
|
|
m_pConf->writeEntry("MakeRoot", sess.sMakeRoot);
|
|
}
|
|
|
|
/**
|
|
* Fills a list object with all files in the project.
|
|
* List items are created by reading and parsing all file name entries from
|
|
* the project's 'cscope.files' file.
|
|
* Note that the file may contain option lines, beginning with a dash. These
|
|
* should be ignored.
|
|
* @param pList Pointer to the object to fill
|
|
*/
|
|
bool Project::loadFileList(FileListTarget* pList)
|
|
{
|
|
TQString sFilePath;
|
|
|
|
// Open the 'cscope.files' file
|
|
if (!m_fiFileList.open(IO_ReadOnly))
|
|
return false;
|
|
|
|
// Read all file names from the file
|
|
TQTextStream str(&m_fiFileList);
|
|
while ((sFilePath = str.readLine()) != TQString::null) {
|
|
// Skip option lines
|
|
if (sFilePath.at(0) == '-')
|
|
continue;
|
|
|
|
// Set the new list item
|
|
pList->addItem(sFilePath);
|
|
}
|
|
|
|
m_fiFileList.close();
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Writes all file entries in a list view widget to the project's
|
|
* 'cscope.files' file (replacing current file contents.)
|
|
* @param pList Pointer to the object from which to take the new entries
|
|
*/
|
|
bool Project::storeFileList(FileListSource* pList)
|
|
{
|
|
TQString sFilePath;
|
|
|
|
// Open the 'cscope.files' file
|
|
if (!m_fiFileList.open(IO_WriteOnly | IO_Truncate))
|
|
return false;
|
|
|
|
TQTextStream str(&m_fiFileList);
|
|
|
|
// Write all file names
|
|
if (pList->firstItem(sFilePath)) {
|
|
do {
|
|
str << sFilePath << "\n";
|
|
} while (pList->nextItem(sFilePath));
|
|
}
|
|
|
|
m_fiFileList.close();
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Adds a single file to the file list.
|
|
* @param sPath The path of the file to add
|
|
* @return true if successful, false otherwise
|
|
*/
|
|
bool Project::addFile(const TQString& sPath)
|
|
{
|
|
// Open the 'cscope.files' file
|
|
if (!m_fiFileList.open(IO_WriteOnly | IO_Append))
|
|
return false;
|
|
|
|
// Write the file path
|
|
TQTextStream str(&m_fiFileList);
|
|
str << sPath << "\n";
|
|
|
|
m_fiFileList.close();
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Determines whether the project includes any files.
|
|
* Reads the 'cscope.files' file and looks for any file names in it. If none
|
|
* is present, then the project is considered empty.
|
|
* Note that the file may contain option lines, beginning with a dash. These
|
|
* should be ignored.
|
|
* @return true if no files are included in the project, false otherwise
|
|
*/
|
|
bool Project::isEmpty()
|
|
{
|
|
TQString sPath, sFileName;
|
|
bool bResult = true;
|
|
|
|
// Open the 'cscope.files' file
|
|
if (!m_fiFileList.open(IO_ReadOnly))
|
|
return true;
|
|
|
|
// Find at least one file name entry in the file
|
|
TQTextStream str(&m_fiFileList);
|
|
while ((sPath = str.readLine()) != TQString::null) {
|
|
if (sPath.at(0) != '-') {
|
|
bResult = false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
m_fiFileList.close();
|
|
return bResult;
|
|
}
|
|
|
|
/**
|
|
* Copies the list of previously queried symbols to the target object.
|
|
* @param slSymHistory The list object to copy into
|
|
*/
|
|
void Project::getSymHistory(TQStringList& slSymHistory) const
|
|
{
|
|
slSymHistory = m_slSymHistory;
|
|
}
|
|
|
|
/**
|
|
* Copies the list of previously queried symbols from the target object.
|
|
* @param slSymHistory The list object to copy from
|
|
*/
|
|
void Project::setSymHistory(TQStringList& slSymHistory)
|
|
{
|
|
m_slSymHistory = slSymHistory;
|
|
}
|
|
|
|
void Project::getMakeParams(TQString& sCmd, TQString& sDir) const
|
|
{
|
|
sCmd = m_sMakeCmd;
|
|
sDir = m_sMakeRoot;
|
|
}
|
|
|
|
/**
|
|
* Creates a project by writing a configuration file inside the given
|
|
* directory.
|
|
* @param sName The project's name
|
|
* @param sPath The full path of the project's directory
|
|
* @param opt Project options
|
|
*/
|
|
bool Project::create(const TQString& sName, const TQString& sPath,
|
|
const Options& opt)
|
|
{
|
|
// Prepare the project's files
|
|
TDEConfig conf(sPath + "/cscope.proj");
|
|
|
|
// Write the configuration file version
|
|
conf.setGroup("");
|
|
conf.writeEntry("Version", PROJECT_CONFIG_VER);
|
|
|
|
// Write project properties in the configuration file
|
|
conf.setGroup("Project");
|
|
conf.writeEntry("Name", sName);
|
|
writeOptions(&conf, opt);
|
|
|
|
// Flush the config file data, so the project is created even if KScope
|
|
// crashes...
|
|
conf.sync();
|
|
|
|
return true;
|
|
}
|
|
|
|
void Project::writeOptions(TDEConfig* pConf, const Options& opt)
|
|
{
|
|
pConf->setGroup("Project");
|
|
pConf->writeEntry("RootPath", opt.sSrcRootPath);
|
|
pConf->writeEntry("FileTypes", opt.slFileTypes.join(" "));
|
|
pConf->writeEntry("Kernel", opt.bKernel);
|
|
pConf->writeEntry("InvIndex", opt.bInvIndex);
|
|
pConf->writeEntry("NoCompress", opt.bNoCompress);
|
|
pConf->writeEntry("SlowPathDef", opt.bSlowPathDef);
|
|
pConf->writeEntry("AutoRebuildTime", opt.nAutoRebuildTime);
|
|
pConf->writeEntry("TabWidth", opt.nTabWidth);
|
|
pConf->writeEntry("CtagsCommand", opt.sCtagsCmd);
|
|
|
|
// Set auto-completion options
|
|
pConf->setGroup("AutoCompletion");
|
|
pConf->writeEntry("Enabled", opt.bACEnabled);
|
|
pConf->writeEntry("MinChars", opt.nACMinChars);
|
|
pConf->writeEntry("Delay", opt.nACDelay);
|
|
pConf->writeEntry("MaxEntries", opt.nACMaxEntries);
|
|
}
|