diff options
Diffstat (limited to 'src/project.cpp')
-rw-r--r-- | src/project.cpp | 442 |
1 files changed, 442 insertions, 0 deletions
diff --git a/src/project.cpp b/src/project.cpp new file mode 100644 index 0000000..06e1332 --- /dev/null +++ b/src/project.cpp @@ -0,0 +1,442 @@ +/*************************************************************************** + * + * 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 <kmessagebox.h> +#include <klocale.h> +#include "project.h" +#include "kscopeconfig.h" +#include "cscopefrontend.h" + +#define PROJECT_CONFIG_VER 2 + +inline void flListFromStringList(FileLocationList& fll, const QStringList& sl) +{ + QStringList::ConstIterator itr; + QString 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(QStringList& sl, const FileLocationList& fll) +{ + FileLocationList* pList; + FileLocation* pLoc; + QString 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 = ""; + QTextOStream(&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 QString& sPath) +{ + QString 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 KConfig(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 == QString::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. + */ +QString Project::getFileTypes() const +{ + QString 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) +{ + QStringList 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) +{ + QStringList 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) +{ + QString sFilePath; + + // Open the 'cscope.files' file + if (!m_fiFileList.open(IO_ReadOnly)) + return false; + + // Read all file names from the file + QTextStream str(&m_fiFileList); + while ((sFilePath = str.readLine()) != QString::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) +{ + QString sFilePath; + + // Open the 'cscope.files' file + if (!m_fiFileList.open(IO_WriteOnly | IO_Truncate)) + return false; + + QTextStream 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 QString& sPath) +{ + // Open the 'cscope.files' file + if (!m_fiFileList.open(IO_WriteOnly | IO_Append)) + return false; + + // Write the file path + QTextStream 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() +{ + QString 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 + QTextStream str(&m_fiFileList); + while ((sPath = str.readLine()) != QString::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(QStringList& 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(QStringList& slSymHistory) +{ + m_slSymHistory = slSymHistory; +} + +void Project::getMakeParams(QString& sCmd, QString& 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 QString& sName, const QString& sPath, + const Options& opt) +{ + // Prepare the project's files + KConfig 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(KConfig* 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); +} |