summaryrefslogtreecommitdiffstats
path: root/src/project.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/project.cpp')
-rw-r--r--src/project.cpp442
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);
+}