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.
tdewebdev/quanta/treeviews/projecttreeview.cpp

679 lines
22 KiB

/***************************************************************************
projecttreeview.cpp - description
-------------------
begin : Tue Mar 14 2000
copyright : (C) 2000 by Yacovlev Alexander & Dmitry Poplavsky <pdima@mail.univ.kiev.ua>
(C) 2001-2004 Andras Mantia <amantia@kde.org>
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
// QT includes
#include <tqpainter.h>
#include <tqlabel.h>
#include <tqlineedit.h>
#include <tqdict.h>
// KDE includes
#include <tdelocale.h>
#include <kiconloader.h>
#include <kinputdialog.h>
#include <tdemessagebox.h>
#include <kdebug.h>
#include <tdepopupmenu.h>
#include <kpropertiesdialog.h>
#include <tdetempfile.h>
#include <tdeapplication.h>
#include <kstringhandler.h>
// app includes
#include "projecttreeview.h"
#include "projectlist.h"
#include "projecturl.h"
#include "quantacommon.h"
#include "qextfileinfo.h"
#include "resource.h"
#include "fileinfodlg.h"
#ifdef ENABLE_CVSSERVICE
#include "cvsservice.h"
#endif
//ProjectTreeViewItem implementation
ProjectTreeViewItem::ProjectTreeViewItem( KFileTreeViewItem *parent, KFileItem* item, KFileTreeBranch *brnch )
: BaseTreeViewItem( parent, item, brnch)
{
}
void ProjectTreeViewItem::paintCell(TQPainter *p, const TQColorGroup &cg,
int column, int width, int align)
{
TQFont f = p->font();
if (ProjectTreeView::ref()->isDocumentFolder(url()))
{
f.setItalic(true);
if (text(1).isEmpty())
setText(1, i18n("Document Base Folder"));
} else
{
if (text(1) == i18n("Document Base Folder"))
setText(1, "");
}
p->setFont(f);
BaseTreeViewItem::paintCell( p, cg, column, width, align );
}
//ProjectTreeBranch implementation
ProjectTreeBranch::ProjectTreeBranch(KFileTreeView *parent, const KURL& url,
const TQString& name, const TQPixmap& pix,
bool showHidden,
KFileTreeViewItem *branchRoot)
: BaseTreeBranch(parent, url, name, pix, showHidden, branchRoot)
{
}
KFileTreeViewItem* ProjectTreeBranch::createTreeViewItem(KFileTreeViewItem *parent,
KFileItem *fileItem )
{
BaseTreeViewItem *tvi = 0;
if( parent && fileItem )
{
tvi = new ProjectTreeViewItem( parent, fileItem, this );
if (tvi)
{
// we assume there are childs
tvi->setExpandable(tvi->isDir());
if (urlList) {
tvi->setVisible(urlList->contains(fileItem->url())); // only listelements
}
}
}
else
kdDebug(24000) << "ProjectTreeBranch::createTreeViewItem: Have no parent" << endl;
return tvi;
}
//ProjectTreeView implementation
ProjectTreeView::ProjectTreeView(TQWidget *parent, const char *name )
: BaseTreeView(parent,name), m_projectFiles(0)
{
//setSelectionModeExt(TDEListView::Extended);
setRootIsDecorated(false);
addColumn(i18n("Project Files"), -1);
addColumn(i18n("Description"), -1);
setDragEnabled(true);
setAcceptDrops(true);
setItemsRenameable(true);
setRenameable(0, false);
setRenameable(1, true);
m_projectBaseURL = KURL();
newBranch(m_projectBaseURL); // create an empty project branch
m_projectDir->root()->setEnabled(false);
m_uploadStatusMenu = new TDEPopupMenu(this);
m_alwaysUploadId = m_uploadStatusMenu->insertItem(i18n("&When Modified"), this, TQ_SLOT(slotAlwaysUpload()));
m_neverUploadId = m_uploadStatusMenu->insertItem(i18n("&Never"), this, TQ_SLOT(slotNeverUpload()));
m_confirmUploadId = m_uploadStatusMenu->insertItem(i18n("&Confirm"), this, TQ_SLOT(slotConfirmUpload()));
connect(m_uploadStatusMenu, TQ_SIGNAL(aboutToShow()), this, TQ_SLOT(slotUploadMenuAboutToShow()));
m_fileMenu = new TDEPopupMenu(this);
m_fileMenu->insertItem(SmallIcon("document-open"), i18n("&Open"), this, TQ_SLOT(slotOpen()));
m_openInQuantaId = m_fileMenu->insertItem(i18n("Load Toolbar"), this, TQ_SLOT(slotLoadToolbar()));
m_fileMenu->insertItem(i18n("Insert &Tag"), this, TQ_SLOT(slotInsertTag()));
m_menuClose = m_fileMenu->insertItem(SmallIcon("window-close"), i18n("Clos&e"), this, TQ_SLOT(slotClose()));
m_fileMenu->insertSeparator();
m_fileMenu->insertItem(SmallIcon("go-up"), i18n("&Upload File..."), this, TQ_SLOT(slotUploadSingleURL()));
m_fileMenu->insertItem(SmallIcon("go-up"), i18n("&Quick File Upload"), this, TQ_SLOT(slotQuickUploadURL()));
m_fileMenu->insertItem(i18n("Re&name"), this, TQ_SLOT(slotStartRename()));
m_fileMenu->insertItem( i18n("&Remove From Project"), this, TQ_SLOT(slotRemoveFromProject(int)));
m_fileMenu->insertItem(SmallIcon("edit-delete"), i18n("&Delete"), this, TQ_SLOT(slotDelete()));
m_fileMenu->insertSeparator();
m_fileMenu->insertItem(i18n("Upload &Status"), m_uploadStatusMenu);
m_fileMenu->insertItem(SmallIcon("application-vnd.tde.info"), i18n("&Properties"), this, TQ_SLOT(slotProperties()));
TDEPopupMenu *createNewMenu = new TDEPopupMenu(this);
createNewMenu->insertItem(SmallIcon("folder-new"), i18n("F&older..."), this, TQ_SLOT(slotCreateFolder()));
createNewMenu->insertItem(SmallIcon("text-x-generic"), i18n("&File..."), this, TQ_SLOT(slotCreateFile()));
m_folderMenu = new TDEPopupMenu(this);
m_folderMenu->insertItem(SmallIconSet("document-new"), i18n("&Create New"), createNewMenu);
m_folderMenu->insertSeparator();
m_folderMenu->insertItem(SmallIcon("go-up"), i18n("&Upload Folder..."), this, TQ_SLOT(slotUploadSingleURL()));
m_folderMenu->insertItem(SmallIcon("go-up"), i18n("&Quick Folder Upload"), this, TQ_SLOT(slotQuickUploadURL()));
m_folderMenu->insertItem(i18n("Create Site &Template..."), this, TQ_SLOT(slotCreateSiteTemplate()));
m_folderMenu->insertItem(i18n("Re&name"), this, TQ_SLOT(slotStartRename()));
m_folderMenu->insertItem(i18n("&Remove From Project"), this, TQ_SLOT(slotRemoveFromProject(int)));
m_folderMenu->insertItem(SmallIcon("edit-delete"), i18n("&Delete"), this, TQ_SLOT(slotDelete()));
m_folderMenu->insertSeparator();
m_setDocumentRootId = m_folderMenu->insertItem(i18n("Document-&Base Folder"), this, TQ_SLOT(slotChangeDocumentFolderStatus()));
m_folderMenu->insertItem(i18n("Upload &Status"), m_uploadStatusMenu);
m_folderMenu->insertItem(SmallIcon("application-vnd.tde.info"), i18n("&Properties"), this, TQ_SLOT(slotProperties()));
m_projectMenu = new TDEPopupMenu(this);
m_projectMenu->insertItem(SmallIconSet("document-new"), i18n("&Create New"), createNewMenu);
m_projectMenu->insertSeparator();
m_projectMenu->insertItem(SmallIcon("go-up"), i18n("&Upload Project..."), this, TQ_SLOT(slotUploadProject()));
m_projectMenu->insertItem(SmallIcon("reload"), i18n("Re&scan Project Folder..."), this, TQ_SLOT(slotRescan()));
m_projectMenu->insertItem(SmallIcon("configure"), i18n("Project &Properties"), this, TQ_SLOT(slotOptions()));
m_projectMenu->insertItem(SmallIcon("document-revert"), i18n("&Reload"), this, TQ_SLOT(slotReload()));
m_projectMenu->insertSeparator();
m_projectMenu->insertItem(i18n("Upload &Status"), m_uploadStatusMenu);
connect(this, TQ_SIGNAL(contextMenu(TDEListView*, TQListViewItem*, const TQPoint&)),
this, TQ_SLOT(slotMenu(TDEListView*, TQListViewItem*, const TQPoint&)));
connect(this, TQ_SIGNAL(open(TQListViewItem *)),
this, TQ_SLOT(slotSelectFile(TQListViewItem *)));
restoreLayout(kapp->config(), className());
// the restored size of the first column might be too large for the current content
// we set it to 10 and the listview will adjust it to the size of the largest entry
setColumnWidth(0, 10);
}
ProjectTreeView::~ProjectTreeView(){
}
KFileTreeBranch* ProjectTreeView::newBranch(const KURL& url)
{
TQString m_projectNameStr = m_projectName+" ";
if (!m_projectName.isEmpty())
{
if (url.protocol() == "file")
{
m_projectNameStr += i18n("[local disk]");
} else
{
m_projectNameStr += "[" + url.protocol() + "://" + url.user() + "@" + url.host() + "]";
}
m_projectDir = new ProjectTreeBranch( this, url, m_projectNameStr, SmallIcon("ptab"), true);
m_projectDir->root()->setText(1, url.prettyURL());
setDragEnabled(true);
setRootIsDecorated(true);
} else {
m_projectDir = new ProjectTreeBranch( this, url, i18n("No Project"), SmallIcon("ptab"), true);
m_projectDir->root()->setText(1, "");
setDragEnabled(false);
setRootIsDecorated(false);
}
connect(m_projectDir, TQ_SIGNAL(populateFinished(KFileTreeViewItem*)),
this, TQ_SLOT(slotPopulateFinished(KFileTreeViewItem*)));
addBranch(m_projectDir);
m_projectDir->urlList = m_projectFiles; // set list for filter
if (!m_projectName.isEmpty())
m_projectDir->populate(m_projectDir->rootUrl(), m_projectDir->root());
else
m_projectDir->root()->setEnabled(false);
return m_projectDir;
}
/** slot for context menu */
void ProjectTreeView::slotMenu(TDEListView *listView, TQListViewItem *item, const TQPoint& point)
{
Q_UNUSED(listView);
KURL url = currentURL();
#ifdef ENABLE_CVSSERVICE
CVSService::ref()->setRepository(m_projectBaseURL.path());
if (url.isLocalFile())
{
TQString path = url.path();
if (path == m_projectBaseURL.path())
path += "/.";
CVSService::ref()->setCurrentFile(path);
}
else
CVSService::ref()->setCurrentFile("");
#endif
ProjectTreeViewItem *curItem = static_cast<ProjectTreeViewItem *>(currentKFileTreeViewItem());
if (item && curItem)
{
setSelected(item, true);
if (curItem == curItem->branch()->root())
{
m_projectMenu->popup(point);
} else
{
if (!curItem->isDir())
{
if (url.fileName().endsWith(toolbarExtension))
{
m_fileMenu->setItemVisible(m_openInQuantaId, true);
} else
{
m_fileMenu->setItemVisible(m_openInQuantaId, false);
}
m_fileMenu->setItemVisible(m_menuClose, isFileOpen(url));
insertOpenWithMenu(m_fileMenu, 1);
m_fileMenu->popup(point);
} else
{
if (m_documentFolderList.contains(url))
m_folderMenu->setItemChecked(m_setDocumentRootId, true);
else
m_folderMenu->setItemChecked(m_setDocumentRootId, false);
m_folderMenu->popup(point);
}
}
} else
if (!m_projectName.isNull())
{
setSelected(firstChild(), true);
m_projectMenu->popup(point);
}
}
/** Sets the project template directory */
void ProjectTreeView::slotNewProjectLoaded(const TQString &name, const KURL &baseURL, const KURL &templateURL)
{
BaseTreeView::slotNewProjectLoaded(name, baseURL, templateURL); // set m_projectName and m_projectBaseURL
if (!m_projectName.isNull())
{
TQString projectNameStr = m_projectName+" ";
if (m_projectBaseURL.protocol() == "file")
{
projectNameStr += i18n("[local disk]");
} else
{
projectNameStr += "["+m_projectBaseURL.protocol()+"://"+m_projectBaseURL.user()+"@"+m_projectBaseURL.host()+"]";
}
m_projectDir->root()->setText(0, projectNameStr);
m_projectDir->root()->setText(1, m_projectBaseURL.prettyURL());
setDragEnabled(true);
}
else
{
m_projectDir->root()->setText(0, i18n("No Project"));
m_projectDir->root()->setText(1, "");
setDragEnabled(false);
}
m_documentFolderList.clear();
m_documentFolderList.append(m_projectBaseURL);
}
void ProjectTreeView::slotReloadTree( ProjectList *fileList, bool buildNewTree, const TQStringList &folderToOpen)
{
m_projectFiles = fileList;
m_documentFolderList.clear();
m_documentFolderList.append(m_projectBaseURL);
KURL url;
ProjectList::Iterator it( *m_projectFiles );
for ( ; it.current(); ++it) {
if (it.current()->documentFolder) {
url = *(it.current());
url.adjustPath(-1);
m_documentFolderList.append( url );
}
}
if (buildNewTree)
{
if (m_projectDir)
{
removeBranch(m_projectDir);
m_projectDir = 0L;
}
BaseTreeBranch *btb = dynamic_cast<BaseTreeBranch *>(newBranch(m_projectBaseURL));
if (btb && folderToOpen.count() > 0) {
btb->folderToOpen = folderToOpen;
btb->reopenFolder();
btb->updateOpenFolder();
}
} else
{
if (m_projectDir){
m_projectDir->urlList = m_projectFiles; // set list for filter
KFileTreeViewItem *item;
KFileTreeViewItem *rootItem = m_projectDir->root();
KURL url;
TQListViewItemIterator iter(this);
for ( ; iter.current(); ++iter )
{
item = dynamic_cast <KFileTreeViewItem*> (iter.current());
item->setVisible(m_projectFiles->contains(item->url()) || item == rootItem);
}
rootItem->setEnabled(true);
}
}
}
void ProjectTreeView::slotOpen()
{
BaseTreeView::slotSelectFile(currentItem());
}
void ProjectTreeView::slotLoadToolbar()
{
if (currentItem())
{
KURL urlToOpen = currentURL();
if (urlToOpen.fileName().endsWith(toolbarExtension))
{
emit loadToolbarFile(urlToOpen);
}
}
}
void ProjectTreeView::slotCreateFolder()
{
bool ok;
TQString folderName = KInputDialog::getText(i18n("Create New Folder"), i18n("Folder name:"), "", &ok, this);
if (ok)
{
KURL url = currentURL();
if (currentKFileTreeViewItem()->isDir())
url.setPath(url.path() + "/" + folderName + "/");
else
url.setPath(url.directory() + "/" + folderName +"/");
if (QExtFileInfo::createDir(url, this))
{
emit insertToProject(url);
}
}
}
void ProjectTreeView::slotCreateFile()
{
bool ok;
TQString fileName = KInputDialog::getText(i18n("Create New File"), i18n("File name:"), "", &ok, this);
if (ok)
{
KURL url = currentURL();
if (currentKFileTreeViewItem()->isDir())
url.setPath(url.path() + "/" + fileName);
else
url.setPath(url.directory() + "/" + fileName);
if (QExtFileInfo::exists(url, false, this))
{
KMessageBox::error(this, i18n("<qt>Cannot create file, because a file named <b>%1</b> already exists.</qt>").arg(fileName), i18n("Error Creating File"));
return;
}
KTempFile *tempFile = new KTempFile(tmpDir);
tempFile->setAutoDelete(true);
tempFile->close();
if (QExtFileInfo::copy(KURL::fromPathOrURL(tempFile->name()), url))
{
emit insertToProject(url);
emit openFile(url);
}
delete tempFile;
}
}
void ProjectTreeView::slotRemoveFromProject(int askForRemove)
{
TQListViewItem *item = currentItem();
if (item)
{
KURL url = currentURL();
TQString nice = QExtFileInfo::toRelative(url, m_projectBaseURL).path();
nice = KStringHandler::lsqueeze(nice, 60);
if ( !askForRemove ||
KMessageBox::warningContinueCancel(this,i18n("<qt>Do you really want to remove <br><b>%1</b><br> from the project?</qt>").arg(nice), i18n("Remove From Project"), KStdGuiItem::remove(), "RemoveFromProject") == KMessageBox::Continue )
{
if ( currentKFileTreeViewItem()->isDir() ) url.adjustPath(+1);
emit removeFromProject(url);
}
}
}
void ProjectTreeView::slotUploadSingleURL()
{
if (currentItem())
{
KURL url = currentURL();
if ( currentKFileTreeViewItem()->isDir() ) url.adjustPath(+1);
emit uploadSingleURL(url, "", false, false);
}
}
void ProjectTreeView::slotQuickUploadURL()
{
if (currentItem())
{
KURL url = currentURL();
if ( currentKFileTreeViewItem()->isDir() ) url.adjustPath(+1);
emit uploadSingleURL(url, "", true, false);
}
}
void ProjectTreeView::slotRescan()
{
emit rescanProjectDir();
if (!m_projectBaseURL.isLocalFile())
slotReload();
}
/** Bring up the project options dialog */
void ProjectTreeView::slotOptions()
{
emit showProjectOptions();
}
/** No descriptions */
void ProjectTreeView::slotUploadProject()
{
emit uploadProject();
}
void ProjectTreeView::slotPopulateFinished(KFileTreeViewItem* item)
{
BaseTreeView::slotPopulateFinished(item);
// populate descriptions
TQString desc;
KFileTreeViewItem* file_item;
ProjectList::Iterator it( *m_projectFiles );
for ( ; it.current(); ++it)
{
desc = it.current()->fileDesc;
if (! desc.isEmpty())
{
file_item = m_projectDir->findTVIByURL( *(it.current()) );
if (file_item)
file_item->setText(1, desc);
}
}
if ( m_projectFiles->isEmpty() )
m_projectDir->root()->setExpandable( false );
/* FIXME:
* The below code can cause infinite recursion, possibly over slow links.
* setOpen call KFileTreeBranch::openURL, that calls KDirListerCache::listDir,
* that calls KDirListerCache::stop, that emit the signal cancelled, that
* is connected to KFileTreeBranch::slotCanceled, that emit populateFinished
* and we are back in this same function with item being the same and
* everything starts over again. */
// else
// m_projectDir->setOpen( true );
}
void ProjectTreeView::itemDescChanged(KFileTreeViewItem* item, const TQString& newDesc)
{
if (item) {
item->setText(1, newDesc);
KURL url = item->url();
if (item->isDir())
url.adjustPath(1);
emit changeFileDescription(url, newDesc);
}
}
void ProjectTreeView::slotAlwaysUpload()
{
KFileTreeViewItem *kftvi = currentKFileTreeViewItem();
if (! kftvi)
return;
KURL url = currentURL();
if (kftvi->isDir())
url.adjustPath(+1);
if (m_projectFiles->contains(url) || url == m_projectBaseURL)
{
emit changeUploadStatus(url, ProjectURL::AlwaysUpload);
}
}
void ProjectTreeView::slotNeverUpload()
{
KFileTreeViewItem *kftvi = currentKFileTreeViewItem();
if (! kftvi)
return;
KURL url = currentURL();
if (kftvi->isDir())
url.adjustPath(+1);
if (m_projectFiles->contains(url) || url == m_projectBaseURL)
{
emit changeUploadStatus(url, ProjectURL::NeverUpload);
}
}
void ProjectTreeView::slotConfirmUpload()
{
KFileTreeViewItem *kftvi = currentKFileTreeViewItem();
if (! kftvi)
return;
KURL url = currentURL();
if (kftvi->isDir())
url.adjustPath(+1);
if (m_projectFiles->contains(url) || url == m_projectBaseURL)
{
emit changeUploadStatus(url, ProjectURL::ConfirmUpload);
}
}
void ProjectTreeView::slotUploadMenuAboutToShow()
{
m_uploadStatusMenu->setItemChecked(m_alwaysUploadId, false);
m_uploadStatusMenu->setItemChecked(m_neverUploadId, false);
m_uploadStatusMenu->setItemChecked(m_confirmUploadId, false);
KFileTreeViewItem *kftvi = currentKFileTreeViewItem();
if (! kftvi)
return;
KURL url = currentURL();
if (kftvi->isDir())
url.adjustPath(+1);
ProjectURL *proUrl = m_projectFiles->find( url );
if (proUrl)
{
switch (proUrl->uploadStatus)
{
case ProjectURL::NeverUpload:
{
m_uploadStatusMenu->setItemChecked(m_neverUploadId, true);
break;
}
case ProjectURL::ConfirmUpload:
{
m_uploadStatusMenu->setItemChecked(m_confirmUploadId, true);
break;
}
case ProjectURL::AlwaysUpload:
default:
{
m_uploadStatusMenu->setItemChecked(m_alwaysUploadId, true);
break;
}
}
}
}
void ProjectTreeView::slotChangeDocumentFolderStatus()
{
KFileTreeViewItem *kftvi = currentKFileTreeViewItem();
if (! kftvi)
return;
KURL url = currentURL();
if (kftvi->isDir())
url.adjustPath(+1);
if (!m_documentFolderList.contains(currentURL()))
{
m_documentFolderList.append(currentURL());
emit changeUploadStatus(url, ProjectURL::AlwaysUpload);
emit changeDocumentFolderStatus(url, true);
} else
{
m_documentFolderList.remove(currentURL());
emit changeUploadStatus(url, false);
}
currentItem()->repaint();
}
bool ProjectTreeView::isDocumentFolder(const KURL &url)
{
return (m_documentFolderList.contains(url) > 0);
}
void ProjectTreeView::slotRenameItem(TQListViewItem* kftvi, const TQString& newText, int col)
{
if (!kftvi)
return;
if (col == 1) {
itemDescChanged(dynamic_cast <KFileTreeViewItem*> (kftvi), newText);
} else {
BaseTreeView::slotRenameItem(kftvi, newText, col);
}
}
FileInfoDlg* ProjectTreeView::addFileInfoPage(KPropertiesDialog* propDlg)
{
FileInfoDlg* dlg = BaseTreeView::addFileInfoPage(propDlg);
if (dlg) {
dlg->fileDescLbl->show();
dlg->fileDesc->show();
}
return dlg;
}
void ProjectTreeView::plugCVSMenu()
{
#ifdef ENABLE_CVSSERVICE
m_fileMenu->insertSeparator();
m_fileMenu->insertItem(SmallIcon("cervisia"), i18n("C&VS"), CVSService::ref()->menu());
m_folderMenu->insertSeparator();
m_folderMenu->insertItem(SmallIcon("cervisia"), i18n("C&VS"), CVSService::ref()->menu());
m_projectMenu->insertSeparator();
m_projectMenu->insertItem(SmallIcon("cervisia"), i18n("C&VS"), CVSService::ref()->menu());
#endif
}
void ProjectTreeView::slotViewActivated(const KURL& url)
{
if (! m_projectDir) return;
KFileTreeViewItem* item = m_projectDir->findTVIByURL(url);
if (item){
ensureItemVisible(item);
setSelected(item, true);
}
}
#include "projecttreeview.moc"