diff options
Diffstat (limited to 'src/projectfilesdlg.cpp')
-rw-r--r-- | src/projectfilesdlg.cpp | 439 |
1 files changed, 439 insertions, 0 deletions
diff --git a/src/projectfilesdlg.cpp b/src/projectfilesdlg.cpp new file mode 100644 index 0000000..de84417 --- /dev/null +++ b/src/projectfilesdlg.cpp @@ -0,0 +1,439 @@ +/*************************************************************************** + * + * 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 <qpushbutton.h> +#include <qlistview.h> +#include <qlineedit.h> +#include <qregexp.h> +#include <klocale.h> +#include <kmessagebox.h> +#include <kfiledialog.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, QWidget* 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(QListView::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, SIGNAL(clicked()), this, + SLOT(slotAddFiles())); + connect(m_pAddDirButton, SIGNAL(clicked()), this, SLOT(slotAddDir())); + connect(m_pAddTreeButton, SIGNAL(clicked()), this, SLOT(slotAddTree())); + + // Remove selected files/directory/tree when the appropriate button is + // clicked + connect(m_pRemSelButton, SIGNAL(clicked()), this, SLOT(slotRemSel())); + connect(m_pRemDirButton, SIGNAL(clicked()), this, SLOT(slotRemDir())); + connect(m_pRemTreeButton, SIGNAL(clicked()), this, SLOT(slotRemTree())); + + // Hide/show files according to filter + connect(m_pFilterButton, SIGNAL(clicked()), this, SLOT(slotFilter())); + connect(m_pShowAllButton, SIGNAL(clicked()), this, SLOT(slotShowAll())); + + // Close the dialog when OK/Cancel are clicked + connect(m_pOKButton, SIGNAL(clicked()), this, SLOT(accept())); + connect(m_pCancelButton, SIGNAL(clicked()), this, 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 QString& sFilePath) +{ + QListViewItem* pItem; + + pItem = new QListViewItem(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(QString& 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(QString& 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(QCustomEvent* pEvent) +{ + DirScanEvent* pDSE; + QString 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, SIGNAL(cancelled()), this, + 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?"), + pDSE->m_nFiles); + if (KMessageBox::questionYesNo(0, sMsg) == KMessageBox::No) + return; + + // Add the files to the list + const QStringList& slFiles = m_pScanner->getFiles(); + QStringList::const_iterator itr; + + for (itr = slFiles.begin(); itr != slFiles.end(); ++itr) + addItem(*itr); +} + +/** + * Removes a single item from the file list. + */ +void ProjectFilesDlg::removeItem(QListViewItem* 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() +{ + QStringList slFiles; + QStringList::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() +{ + QString sDir; + QStringList slFiles; + QStringList::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() +{ + QString sDir; + QStringList slFiles; + QStringList::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() +{ + QListViewItem* 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() +{ + QString sDir, sFilePath; + QListViewItem* 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() +{ + QString sDir, sFilePath; + QListViewItem* 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() +{ + QString sFilter; + QListViewItem* pItem; + + // Get the user's filter string + sFilter = m_pFilterEdit->text().stripWhiteSpace(); + if (sFilter.isEmpty()) + return; + + // Create the regular expression + QRegExp 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() +{ + QListViewItem* 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" |