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.
kscope/src/projectfilesdlg.cpp

440 lines
12 KiB

/***************************************************************************
*
* Copyright (C) 2005 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 <tqpushbutton.h>
#include <tqlistview.h>
#include <tqlineedit.h>
#include <tqregexp.h>
#include <tdelocale.h>
#include <tdemessagebox.h>
#include <tdefiledialog.h>
#include "projectfilesdlg.h"
#include "dirscanner.h"
#include "scanprogressdlg.h"
#include "kscopeconfig.h"
/**
* Class constructor.
* @param pProjMgr Pointer the KScope's project manager object
* @param pParent The parent widget
* @param szName The widget's name
*/
ProjectFilesDlg::ProjectFilesDlg(Project* pProj, TQWidget* pParent,
const char* szName) :
ProjectFilesLayout(pParent, szName),
m_pProj(pProj),
m_pScanDlg(NULL),
m_pItrItem(NULL),
m_pLastItem(NULL)
{
// Create the scanner object
m_pScanner = new DirScanner(this, &m_dicFiles);
// Initialise the list view
m_pFileList->setSelectionMode(TQListView::Extended);
m_pFileList->addColumn("File Path");
// Sort only when asked to by the user
if (Config().getAutoSortFiles())
m_pFileList->setSortColumn(0);
else
m_pFileList->setSortColumn(m_pFileList->columns() + 1);
// Add file/directory/tree when the appropriate button is clicked
connect(m_pAddFilesButton, TQ_SIGNAL(clicked()), this,
TQ_SLOT(slotAddFiles()));
connect(m_pAddDirButton, TQ_SIGNAL(clicked()), this, TQ_SLOT(slotAddDir()));
connect(m_pAddTreeButton, TQ_SIGNAL(clicked()), this, TQ_SLOT(slotAddTree()));
// Remove selected files/directory/tree when the appropriate button is
// clicked
connect(m_pRemSelButton, TQ_SIGNAL(clicked()), this, TQ_SLOT(slotRemSel()));
connect(m_pRemDirButton, TQ_SIGNAL(clicked()), this, TQ_SLOT(slotRemDir()));
connect(m_pRemTreeButton, TQ_SIGNAL(clicked()), this, TQ_SLOT(slotRemTree()));
// Hide/show files according to filter
connect(m_pFilterButton, TQ_SIGNAL(clicked()), this, TQ_SLOT(slotFilter()));
connect(m_pShowAllButton, TQ_SIGNAL(clicked()), this, TQ_SLOT(slotShowAll()));
// Close the dialog when OK/Cancel are clicked
connect(m_pOKButton, TQ_SIGNAL(clicked()), this, TQ_SLOT(accept()));
connect(m_pCancelButton, TQ_SIGNAL(clicked()), this, TQ_SLOT(reject()));
// Fill the list with the project's files
m_pFileList->setUpdatesEnabled(false);
m_pProj->loadFileList(this);
m_pFileList->setUpdatesEnabled(true);
m_pFileList->triggerUpdate();
}
/**
* Class destructor.
*/
ProjectFilesDlg::~ProjectFilesDlg()
{
delete m_pScanner;
}
/**
* Adds a single entry to the file list.
* Implements the addItem() virtual method of the FileListTarget base
* class. When a ProjectFilesDlg object is given as a parameter to
* ProjectManager::fillList(), this method is called for each file included
* in the project. A new list item is created, containing the file's path,
* and is added to the list.
* @param sFilePath The full path of a source file
*/
void ProjectFilesDlg::addItem(const TQString& sFilePath)
{
TQListViewItem* pItem;
pItem = new TQListViewItem(m_pFileList, m_pLastItem);
pItem->setText(0, sFilePath);
m_pLastItem = pItem;
m_dicFiles.insert(sFilePath, pItem);
}
/**
* Retrieves the first file path in the list.
* Imlpements the firstItem() virtual method of the FileListSource base
* class.
* @param sFilePath Contains the file path, upon successful return
* @return bool true if successful, false if the list is empty
*/
bool ProjectFilesDlg::firstItem(TQString& sFilePath)
{
m_pItrItem = m_pFileList->firstChild();
return nextItem(sFilePath);
}
/**
* Retrieves the next file path in the list.
* Imlpements the nextItem() virtual method of the FileListSource base
* class. The function requires that firstItem() will be called to begin an
* iteration through the file paths.
* @param sFilePath Contains the file path, upon successful return
* @return bool true if successful, false if no more items are
* available
*/
bool ProjectFilesDlg::nextItem(TQString& sFilePath)
{
if (m_pItrItem == NULL)
return false;
sFilePath = m_pItrItem->text(0);
m_pItrItem = m_pItrItem->nextSibling();
return true;
}
/**
* Notifies the user on the progress of a directory scan (when adding a new
* directory), and, if finished, allows the user to add these files to the
* project.
* @param pEvent The event object
*/
void ProjectFilesDlg::customEvent(TQCustomEvent* pEvent)
{
DirScanEvent* pDSE;
TQString sMsg;
// Process only directory scan progress events
if (((uint)pEvent->type()) != DirScanEvent::EventId)
return;
pDSE = (DirScanEvent*)pEvent;
// Check if the scan has terminated
if (!pDSE->m_bFinished) {
// Create the scan progress dialog, if required
if (m_pScanDlg == NULL) {
m_pScanDlg = new ScanProgressDlg(this);
connect(m_pScanDlg, TQ_SIGNAL(cancelled()), this,
TQ_SLOT(slotCancelDirScan()));
}
// Set progress indication
m_pScanDlg->addFiles(pDSE->m_nFiles);
return;
}
// Destroy the scan progress dialog
delete m_pScanDlg;
m_pScanDlg = NULL;
// Verify the thread has terminated
m_pScanner->wait(500);
if (!m_pScanner->finished())
m_pScanner->terminate();
// Do nothing if the operation was cancelled
if (m_pScanner->wasCancelled())
return;
// Abort if no files were found
if (pDSE->m_nFiles == 0) {
KMessageBox::sorry(0, "No files were found");
return;
}
// Prompt the user for the files to add
sMsg.sprintf(i18n("Would you like to add %d files to your project?").utf8(),
pDSE->m_nFiles);
if (KMessageBox::questionYesNo(0, sMsg) == KMessageBox::No)
return;
// Add the files to the list
const TQStringList& slFiles = m_pScanner->getFiles();
TQStringList::const_iterator itr;
for (itr = slFiles.begin(); itr != slFiles.end(); ++itr)
addItem(*itr);
}
/**
* Removes a single item from the file list.
*/
void ProjectFilesDlg::removeItem(TQListViewItem* pItem)
{
m_dicFiles.remove(pItem->text(0));
delete pItem;
}
/**
* Adds a list of files to the project.
* Prompts the user for source files, and adds the selected files to the
* current project.
*/
void ProjectFilesDlg::slotAddFiles()
{
TQStringList slFiles;
TQStringList::const_iterator itr;
// Prompt the user
slFiles = KFileDialog::getOpenFileNames(m_pProj->getSourceRoot(),
m_pProj->getFileTypes());
// Add the selected files, skipping existing entries
for (itr = slFiles.begin(); itr != slFiles.end(); ++itr) {
if (m_dicFiles.find(*itr) == NULL)
addItem(*itr);
}
}
/**
* Adds all source files in a given directory to the project.
* Prompts the user for a directory, and adds all files matching the
* project's pattern to the current project.
* Note that only source files in the selected directory are added, i.e., the
* search does not descend to sub-directories.
*/
void ProjectFilesDlg::slotAddDir()
{
TQString sDir;
TQStringList slFiles;
TQStringList::const_iterator itr;
// Prompt the user for a directory
sDir = KFileDialog::getExistingDirectory(m_pProj->getSourceRoot());
if (sDir.isEmpty())
return;
// Search for source files in this directory
m_pScanner->start(sDir, m_pProj->getFileTypes(), false);
}
/**
* Adds all source files in a given file system tree to the project.
* Prompts the user for a directory, and adds all files matching the
* project's pattern to the current project.
* Note that source files are searched for in the given directory, as well as
* in any of its sub-directories.
*/
void ProjectFilesDlg::slotAddTree()
{
TQString sDir;
TQStringList slFiles;
TQStringList::const_iterator itr;
// Prompt the user for a directory
sDir = KFileDialog::getExistingDirectory(m_pProj->getSourceRoot());
if (sDir.isEmpty())
return;
// Search for source files in this directory
m_pScanner->start(sDir, m_pProj->getFileTypes(), true);
}
/**
* Removes the selected files from the project.
*/
void ProjectFilesDlg::slotRemSel()
{
TQListViewItem* pItem, * pPrevItem;
// Prompt the user before removing the files
if (KMessageBox::questionYesNo(0, i18n("Are you sure you want to remove "
"the selected files from the project?")) == KMessageBox::No) {
return;
}
// Remove the selected files
pItem = m_pFileList->firstChild();
while (pItem != NULL) {
pPrevItem = pItem;
pItem = pItem->nextSibling();
if (pPrevItem->isSelected())
removeItem(pPrevItem);
}
}
/**
* Removes all source files in a directory from the project.
*/
void ProjectFilesDlg::slotRemDir()
{
TQString sDir, sFilePath;
TQListViewItem* pItem, * pPrevItem;
// Prompt the user for a directory
sDir = KFileDialog::getExistingDirectory(m_pProj->getSourceRoot());
if (sDir.isEmpty())
return;
// Confirm the directory removal
if (KMessageBox::questionYesNo(0, i18n("Are you sure you want to remove "
"the selected directory from the project?")) == KMessageBox::No) {
return;
}
// Remove the files under the selected directory
pItem = m_pFileList->firstChild();
while (pItem != NULL) {
pPrevItem = pItem;
pItem = pItem->nextSibling();
// Check if the file is under the selected directory
sFilePath = pPrevItem->text(0);
if (sFilePath.left(sFilePath.findRev('/') + 1) == sDir)
removeItem(pPrevItem);
}
}
/**
* Removes all source files in a directory or any of its sub-directories from
* the project.
*/
void ProjectFilesDlg::slotRemTree()
{
TQString sDir, sFilePath;
TQListViewItem* pItem, * pPrevItem;
// Prompt the user for a directory
sDir = KFileDialog::getExistingDirectory(m_pProj->getSourceRoot());
if (sDir.isEmpty())
return;
// Confirm the directory removal
if (KMessageBox::questionYesNo(0, i18n("Are you sure you want to remove "
"all files in the selected tree from the project?")) ==
KMessageBox::No) {
return;
}
// Remove the files under the selected directory
pItem = m_pFileList->firstChild();
while (pItem != NULL) {
pPrevItem = pItem;
pItem = pItem->nextSibling();
// Check if the file is under the selected directory
sFilePath = pPrevItem->text(0);
if (sFilePath.startsWith(sDir))
removeItem(pPrevItem);
}
}
/**
* Filter files according to a pattern.
* Hides all entries in the file list, except for those that match a given
* pattern.
*/
void ProjectFilesDlg::slotFilter()
{
TQString sFilter;
TQListViewItem* pItem;
// Get the user's filter string
sFilter = m_pFilterEdit->text().stripWhiteSpace();
if (sFilter.isEmpty())
return;
// Create the regular expression
TQRegExp reFilter(sFilter);
reFilter.setWildcard(true);
// Iterate over the list entries, and hide all items not matching the
// filter string
pItem = m_pFileList->firstChild();
while (pItem != NULL) {
if (reFilter.search(pItem->text(0)) == -1) {
pItem->setVisible(false);
pItem->setSelectable(false);
}
pItem = pItem->nextSibling();
}
}
/**
* Shows all entries in the file list, after a filter has been applied.
*/
void ProjectFilesDlg::slotShowAll()
{
TQListViewItem* pItem;
// Iterate over the list entries, and make all items visible
pItem = m_pFileList->firstChild();
while (pItem != NULL) {
pItem->setVisible(true);
pItem->setSelectable(true);
pItem = pItem->nextSibling();
}
}
/**
* Stops a directory scan process.
* This slot is called when the user clicks on the "Cancel" button in the
* scan progress dialog.
*/
void ProjectFilesDlg::slotCancelDirScan()
{
m_pScanner->cancel();
}
#include "projectfilesdlg.moc"