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/basetreeview.cpp

1234 lines
34 KiB

/***************************************************************************
basetreeview.cpp - description
-------------------
begin : Thu Jun 1 2000
copyright : (C) 2000 by Dmitry Poplavsky & Alexander Yakovlev & Eric Laffoon <pdima@users.sourceforge.net,yshurik@linuxfan.com,sequitur@easystreet.com>
(C) 2001-2004 Andras Mantia <amantoa@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. *
* *
***************************************************************************/
// QT includes
#include <tqeventloop.h>
#include <tqlayout.h>
#include <tqfileinfo.h>
#include <tqlabel.h>
#include <tqimage.h>
#include <tqregexp.h>
#include <tqclipboard.h>
#include <tqpoint.h>
#include <tqregexp.h>
#include <tqlineedit.h>
#include <tqfont.h>
#include <tqpainter.h>
#include <tqtooltip.h>
#include <tqptrstack.h>
// KDE includes
#include <kaction.h>
#include <kdebug.h>
#include <krun.h>
#include <kinputdialog.h>
#include <klocale.h>
#include <kiconloader.h>
#include <kopenwith.h>
#include <kmessagebox.h>
#include <kpropertiesdialog.h>
#include <kfiledialog.h>
#include <kprogress.h>
#include <kstandarddirs.h>
#include <kurldrag.h>
#include <kurl.h>
#include <ktar.h>
#include <ktempfile.h>
#include <ktrader.h>
#include <kapplication.h>
#include <kcursor.h>
#include <kprotocolinfo.h>
// app includes
#include "basetreeview.h"
#include "fileinfodlg.h"
#include "project.h"
#include "resource.h"
#include "quanta.h"
#include "qextfileinfo.h"
#include "viewmanager.h"
#include "quantanetaccess.h"
#include "quantaplugininterface.h"
#include "quantaplugin.h"
#include <X11/Xlib.h>
class BaseTreeViewToolTip : public TQToolTip
{
public:
BaseTreeViewToolTip( TQWidget *parent, BaseTreeView *lv );
void maybeTip( const TQPoint &pos );
private:
BaseTreeView *m_view;
};
BaseTreeViewToolTip::BaseTreeViewToolTip( TQWidget *parent, BaseTreeView *lv )
: TQToolTip( parent ), m_view( lv )
{
}
void BaseTreeViewToolTip::maybeTip( const TQPoint &pos )
{
if ( !parentWidget() || !m_view || !m_view->showToolTips() )
return;
TQListViewItem *item = m_view->itemAt(pos);
if (!item)
return;
TQString text;
KFileTreeViewItem * kftvi = dynamic_cast<BaseTreeViewItem *> (item);
if (kftvi) {
TQString desc = kftvi->text(1);
text = kftvi->fileItem()->getToolTipText();
if ( !desc.isEmpty() )
text.prepend("&nbsp;<i>" + desc + "</i><br>");
} else
{ // show something for the branchroot
text = item->text(0);
if ( ! item->text(1).isEmpty() )
text.append( "<br>" + item->text(1));
}
if ( !text.isEmpty() )
tip(m_view->itemRect(item), text);
}
//BaseTreeViewItem implementation
BaseTreeViewItem::BaseTreeViewItem( KFileTreeViewItem *parent, KFileItem* item, KFileTreeBranch *brnch )
: KFileTreeViewItem( parent, item, brnch)
{
}
TQString BaseTreeViewItem::key(int column, bool ascending) const
{
if (ascending)
if (isDir())
return text(column).prepend(" ");
else
return text(column);
else
if (isDir())
return text(column);
else
return text(column).prepend(" ");
}
int BaseTreeViewItem::compare(TQListViewItem *i, int col,
bool ascending) const
{
return key(col, ascending).compare(i->key(col, ascending));
}
void BaseTreeViewItem::paintCell(TQPainter *p, const TQColorGroup &cg,
int column, int width, int align)
{
TQColorGroup _cg( cg );
if (column == 0)
{
TQFont f = p->font();
if (quantaApp)
f.setBold(ViewManager::ref()->isOpened(url()));
p->setFont(f);
} else
{
int h, s, v;
p->pen().color().getHsv(&h, &s, &v);
v = (v < 155 ? v + 100 : 255);
_cg.setColor(TQColorGroup::Text, TQColor(h, s, v, TQColor::Hsv));
};
KFileTreeViewItem::paintCell( p, _cg, column, width, align );
}
void BaseTreeViewItem::refreshIcon()
{
fileItem()->refreshMimeType();
}
//BaseTreeBranch implementation
BaseTreeBranch::BaseTreeBranch(KFileTreeView *parent, const KURL& url,
const TQString& name, const TQPixmap& pix,
bool showHidden ,
KFileTreeViewItem *branchRoot)
: KFileTreeBranch(parent, url, name, pix, showHidden, branchRoot)
{
bool localFile = url.isLocalFile();
setAutoUpdate(localFile);
setChildRecurse(false);
}
bool BaseTreeBranch::matchesFilter(const KFileItem *item) const
{
if (!excludeFilterRx.isEmpty())
if (excludeFilterRx.exactMatch(item->url().path()))
return false;
return KFileTreeBranch::matchesFilter(item);
}
KFileTreeViewItem* BaseTreeBranch::createTreeViewItem(KFileTreeViewItem *parent,
KFileItem *fileItem)
{
BaseTreeViewItem *tvi = 0;
if( parent && fileItem)
{
tvi = new BaseTreeViewItem(parent, fileItem, this);
// we assume there are childs
if (tvi)
{
tvi->setExpandable(tvi->isDir());
}
}
else
kdDebug(24000) << "createTreeViewItem: Have no parent" << endl;
return tvi;
}
void BaseTreeBranch::addOpenFolder(TQStringList* openFolder)
{
if (! openFolder) // just in case
return;
KFileTreeViewItem *newItem;
KFileTreeViewItem *item = root();
while (item) {
if (item->isDir() && item->isOpen()) {
openFolder->append( item->url().url() );
// dive into the tree first
newItem = dynamic_cast<KFileTreeViewItem *>(item->firstChild());
if (newItem) {
// found child go ahead
item = newItem;
continue;
};
};
// move up in the tree
while (item && item != root())
{
if (item->nextSibling())
{
item = dynamic_cast<KFileTreeViewItem *>(item->nextSibling());
break;
}
else
{
item = dynamic_cast<KFileTreeViewItem *>(item->parent());
}
}
if (item == root())
break;
};
}
void BaseTreeBranch::reopenFolder()
{
if (folderToOpen.isEmpty())
return;
KFileTreeViewItem *item;
for (TQStringList::Iterator it = folderToOpen.begin(); it != folderToOpen.end(); ++it) {
KURL url( (*it) );
item = findTVIByURL(url);
if (item) {
// erase the url in the list
(*it) = "";
// open the folder
item->setExpandable(true);
item->setOpen(true);
}
}
}
void BaseTreeBranch::updateOpenFolder()
{
KFileTreeViewItem *newItem;
KFileTreeViewItem *item = root();
while (item) {
if (item->isDir() && item->isOpen()) {
updateDirectory( item->url() );
kapp->processEvents(TQEventLoop::ExcludeUserInput | TQEventLoop::ExcludeSocketNotifiers);
// dive into the tree first
newItem = dynamic_cast<KFileTreeViewItem *>(item->firstChild());
if (newItem) {
// found child go ahead
item = newItem;
continue;
};
};
// go up if no sibling available
if (! item->nextSibling())
item = dynamic_cast<KFileTreeViewItem *>(item->parent());
if (item == root())
break;
if (item)
item = dynamic_cast<KFileTreeViewItem *>(item->nextSibling());
};
}
////////////////////////////////////////////////////////////////////////////////////
//
// BaseTreeView implementation
//
////////////////////////////////////////////////////////////////////////////////////
BaseTreeView::BaseTreeView(TQWidget *parent, const char *name)
: KFileTreeView(parent, name), fileInfoDlg(0), m_saveOpenFolder(false), m_openWithMenu(0L), m_openWithMenuId(-1)
{
m_parent = parent;
TQToolTip::remove(viewport()); // remove the tooltip from TQListView
m_tooltip = new BaseTreeViewToolTip(viewport(), this);
setFrameStyle( Panel | Sunken );
setRootIsDecorated(true);
setSorting(0);
setLineWidth(2);
setFullWidth(true);
setShowSortIndicator(true);
setFocusPolicy(TQ_ClickFocus);
setShowFolderOpenPixmap(false);
connect(this, TQT_SIGNAL(returnPressed(TQListViewItem *)),
this, TQT_SLOT(slotReturnPressed(TQListViewItem *)));
connect(this, TQT_SIGNAL(dropped(TQWidget *, TQDropEvent *, KURL::List&, KURL&)),
this, TQT_SLOT(slotDropped(TQWidget *, TQDropEvent *, KURL::List&, KURL&)));
connect(this, TQT_SIGNAL(itemRenamed(TQListViewItem*, const TQString &, int )),
this, TQT_SLOT(slotRenameItem(TQListViewItem*, const TQString &, int )));
connect(this, TQT_SIGNAL(executed(TQListViewItem *)),
this, TQT_SLOT(slotSelectFile(TQListViewItem *)));
connect(this, TQT_SIGNAL(openFile(const KURL &)),
quantaApp, TQT_SLOT(slotFileOpen(const KURL &)));
connect(this, TQT_SIGNAL(openImage(const KURL &)),
quantaApp, TQT_SLOT(slotImageOpen(const KURL &)));
connect(this, TQT_SIGNAL(closeFile(const KURL &)),
quantaApp, TQT_SLOT(slotFileClose(const KURL &)));
connect(this, TQT_SIGNAL(insertTag(const KURL &, DirInfo)),
quantaApp, TQT_SLOT(slotInsertTag(const KURL &, DirInfo)));
}
BaseTreeView::~BaseTreeView()
{
TQToolTip::remove(viewport());
delete m_tooltip;
}
void BaseTreeView::itemRenamed(const KURL& oldURL, const KURL& newURL)
{
KFileTreeViewItem *curItem = currentKFileTreeViewItem();
if (! curItem) return;
if (curItem->isDir())
{
KURL n = newURL;
n.adjustPath(1);
KURL o = oldURL;
o.adjustPath(1);
emit renamed(o, n);
}
else
{
emit renamed(oldURL, newURL);
}
}
/** Called for: double click, return, Open */
void BaseTreeView::slotSelectFile(TQListViewItem *item)
{
KFileTreeViewItem* kftvi = currentKFileTreeViewItem();
if (!kftvi || kftvi->isDir()) return;
KURL urlToOpen = kftvi->url();
if (!urlToOpen.isEmpty())
{
if ( QuantaCommon::checkMimeGroup(urlToOpen,"text") )
{
emit openFile(urlToOpen);
item->repaint();
}
else if ( QuantaCommon::checkMimeGroup(urlToOpen, "image") ) //it may be an image
{
emit openImage( urlToOpen);
}
else if ( expandArchiv(kftvi)) //it may be an archiv
{
}
else //it is an unknown type, maybe binary
{
if (QuantaCommon::denyBinaryInsert(this) == KMessageBox::Yes)
{
emit openFile(urlToOpen);
item->repaint();
}
}
}
}
/** expands an archiv, if possible */
bool BaseTreeView::expandArchiv (KFileTreeViewItem *item)
{
if (!item) return false;
KURL urlToOpen = item->url();
if ( ! urlToOpen.isLocalFile()) return false;
TQString mimeType = KMimeType::findByURL(urlToOpen)->name();
if ( mimeType == "application/x-tgz" ||
mimeType == "application/x-tbz" ||
mimeType == "application/x-tar" ) //it is an archiv
urlToOpen.setProtocol("tar");
else
if ( mimeType == "application/x-zip" ) //it is an archiv
urlToOpen.setProtocol("zip");
else
return false;
// change status if there is already a sub branch
if (item->isExpandable()) {
item->setOpen( ! item->isOpen());
return true;
};
KFileTreeBranch *kftb = new BaseTreeBranch(this, urlToOpen, item->text(0), *(item->pixmap(0)), true, item);
addBranch(kftb); // connecting some signals
kftb->populate(urlToOpen, item);
item->setExpandable(true);
item->setOpen(true);
return true;
}
/** Properties dialog addon*/
FileInfoDlg* BaseTreeView::addFileInfoPage(KPropertiesDialog* propDlg)
{
//If the item is a file, add the Quanta file info page
FileInfoDlg *quantaFileProperties = 0L;
if ( !currentKFileTreeViewItem()->isDir() )
{
TQFrame *quantaFilePage = propDlg->addPage(i18n("Quanta File Info"));
TQVBoxLayout *topLayout = new TQVBoxLayout( quantaFilePage);
quantaFileProperties = new FileInfoDlg( quantaFilePage, i18n("Quanta").ascii() );
int fsize,fimgsize=0;
int ct=0,imgct=0,position=0;
KURL u = currentURL();
if (u.isLocalFile()) //get the file info only for local file. TODO: for non-local ones
{
TQString nameForInfo = u.path();
TQString path =u.directory(0,0); //extract path for images
TQString sourcename=u.fileName(0);
TQFile qfile(nameForInfo);
fsize=qfile.size(); //html file size
TQString mimetype = KMimeType::findByFileContent(nameForInfo)->name();
if (mimetype.contains("text"))
{
qfile.open(IO_ReadOnly);
TQString imgname,imgpath;
TQTextStream stream(&qfile);
stream.setEncoding(TQTextStream::UnicodeUTF8);
while (!stream.atEnd()) //open & parse file
{
imgname = stream.readLine();
ct++;
position=imgname.find("<img",0,false); //check for images
if (position!=-1)
{
imgname.remove(0,position+4);
position=imgname.find("src=",0,false); //extract images names
imgname.remove(0,position+4);
if (imgname.startsWith("\"")) imgname.remove(0,1);
if (imgname.startsWith("'")) imgname.remove(0,1);
position=imgname.find(" ",0,false);
if (position!=-1) imgname=imgname.left(position);
position=imgname.find(">",0,false);
if (position!=-1) imgname=imgname.left(position);
position=imgname.find("\"",0,false);
if (position!=-1) imgname=imgname.left(position);
position=imgname.find("'",0,false);
if (position!=-1) imgname=imgname.left(position);
if (!quantaFileProperties->imageList->findItem(imgname,TQt::ExactMatch)) //check if image was already counted
{
KURL v(KURL::fromPathOrURL( path ),imgname);
imgpath=v.path();
TQFile qimage(imgpath);
if (qimage.exists() && v.isLocalFile())
{
fimgsize+=qimage.size();
quantaFileProperties->imageList->insertItem(imgname);
imgct++;
}
}
}
}
qfile.close();
quantaFileProperties->lineNum->setText(i18n("Number of lines: %1").arg(ct));
quantaFileProperties->imageNum->setText(i18n("Number of images included: %1").arg(imgct));
quantaFileProperties->imageSize->setText(i18n("Size of the included images: %1 bytes").arg(fimgsize));
quantaFileProperties->totalSize->setText(i18n("Total size with images: %1 bytes").arg(fsize+fimgsize));
}
else if (mimetype.contains("image"))
{ // assume it's an image file
TQImage imagefile=TQImage(nameForInfo);
quantaFileProperties->lineNum->setText(i18n("Image size: %1 x %2").arg(imagefile.width()).arg(imagefile.height()));
quantaFileProperties->imageNum->hide();
quantaFileProperties->imageSize->hide();
quantaFileProperties->totalSize->hide();
quantaFileProperties->includedLabel->hide();
quantaFileProperties->imageList->hide();
}
quantaFileProperties->fileDescLbl->setText(i18n("Description:"));
quantaFileProperties->fileDesc->setText(currentKFileTreeViewItem()->text(1));
// disable per default
quantaFileProperties->fileDescLbl->hide();
quantaFileProperties->fileDesc->hide();
topLayout->addWidget(quantaFileProperties);
} //if localfile
}
return quantaFileProperties;
}
void BaseTreeView::slotClose()
{
if (currentItem())
{
emit closeFile(currentURL());
}
}
void BaseTreeView::slotOpen()
{
TQListViewItem *item = currentItem();
if (item)
{
emit open(item);
item->repaint();
}
}
void BaseTreeView::slotOpenWith()
{
if (currentItem())
{
KURL::List list;
KURL urlToOpen = currentURL();
list.append( urlToOpen );
KRun::displayOpenWithDialog( list );
}
}
void BaseTreeView::slotOpenWithApplication()
{
KService::Ptr ptr = KService::serviceByDesktopPath(TQT_TQOBJECT(const_cast<TQT_BASE_OBJECT_NAME*>(sender()))->name());
if (ptr)
{
KURL::List list;
list << currentURL();
KRun::run(*ptr, list);
}
}
void BaseTreeView::slotOpenWithActivated(int id)
{
if (m_pluginIds.contains(id))
{
QuantaPlugin *plugin = m_pluginIds[id];
plugin->unload(true);
if (plugin->load())
{
int input = plugin->input();
plugin->setInput(-1); //disable input
plugin->run();
if (plugin->part())
plugin->part()->openURL(currentURL());
plugin->setInput(input);
}
}
}
void BaseTreeView::insertOpenWithMenu(KPopupMenu *menu, int position)
{
if (m_openWithMenuId != -1)
menu->removeItem(m_openWithMenuId);
for (uint i = 0; i < m_openWithActions.count(); i++)
{
KAction *action = m_openWithActions[i];
delete action;
}
m_openWithActions.clear();
KURL urlToOpen = currentURL();
TQString mimeType = KMimeType::findByURL(urlToOpen, 0, true, true)->name();
KTrader::OfferList offers = KTrader::self()->query(mimeType, "Type == 'Application'");
TQDict<QuantaPlugin> plugins = QuantaPluginInterface::ref()->plugins();
m_pluginIds.clear();
if (offers.count() > 0 || plugins.count() > 0)
{
m_openWithMenu = new KPopupMenu(this);
if (offers.count() > 0)
{
KTrader::OfferList::Iterator it;
for (it = offers.begin(); it != offers.end(); ++it)
{
KAction *action = new KAction((*it)->name(), (*it)->icon(), 0, 0, TQFile::encodeName((*it)->desktopEntryPath()).data());
connect(action, TQT_SIGNAL(activated()), this, TQT_SLOT(slotOpenWithApplication()));
action->plug(m_openWithMenu);
m_openWithActions.append(action);
}
m_openWithMenu->insertSeparator();
}
if (plugins.count() > 0)
{
m_openWithMenu->insertTitle(i18n("Plugins"));
TQDictIterator<QuantaPlugin> it2(plugins);
for(;it2.current();++it2)
{
int id = m_openWithMenu->insertItem(KGlobal::iconLoader()->loadIconSet(it2.current()->icon(),KIcon::Small), it2.current()->name());
m_pluginIds[id] = it2.current();
}
connect(m_openWithMenu, TQT_SIGNAL(activated(int)), TQT_SLOT(slotOpenWithActivated(int)));
m_openWithMenu->insertSeparator();
}
m_openWithMenu->insertItem(i18n("&Other..."), this, TQT_SLOT(slotOpenWith()));
m_openWithMenuId = menu->insertItem(i18n("Open &With"), m_openWithMenu, -1, position);
} else
m_openWithMenuId = menu->insertItem(i18n("Open &With..."), this, TQT_SLOT(slotOpenWith()), 0, -1, position);
}
void BaseTreeView::slotInsertTag()
{
if (currentItem() )
{
DirInfo dirInfo;
dirInfo.mimeType = "";
dirInfo.preText = "";
dirInfo.postText = "";
emit insertTag( currentURL(), dirInfo );
}
}
void BaseTreeView::slotCopy()
{
if (currentItem())
{
TQClipboard *cb = TQApplication::clipboard();
cb->setText( currentURL().prettyURL() );
}
}
void BaseTreeView::slotPaste()
{
if (currentItem())
{
TQClipboard *cb = TQApplication::clipboard();
KURL::List list( TQStringList::split( TQChar('\n'), cb->text() ) );
KURL url = currentURL();
if ( ! currentKFileTreeViewItem()->isDir() )
url.setFileName(""); // don't paste on files but in dirs
QuantaNetAccess::dircopy(list, url, m_parent, true);
}
}
void BaseTreeView::slotPercent(KIO::Job *job, unsigned long value)
{
Q_UNUSED(job);
progressBar->setProgress(value);
}
void BaseTreeView::slotDelete()
{
if (!currentKFileTreeViewItem()) return;
KURL url = currentURL();
if (currentKFileTreeViewItem()->isDir())
url.adjustPath(+1);
QuantaNetAccess::del(url, m_parent, true);
}
void BaseTreeView::slotPopulateFinished(KFileTreeViewItem *item)
{
progressBar->setTotalSteps(1);
progressBar->setProgress(-1);
progressBar->setTextEnabled(false);
if ( !item ) return;
if( item->isDir() )
stopAnimation( item );
if (item->childCount() == 0) {
item->setOpen(false);
item->setExpandable(false);
} else {
TQString url = item->url().url();
BaseTreeBranch *btb = dynamic_cast<BaseTreeBranch *>(item->branch());
if (btb && ! btb->folderToOpen.empty()) {
btb->reopenFolder();
}
}
}
void BaseTreeView::slotInsertInProject()
{
if (currentItem() )
{
emit insertFileInProject( currentURL());
}
}
void BaseTreeView::slotInsertDirInProject()
{
if ( currentItem() )
{
emit insertDirInProject( currentURL() );
}
}
/** Bring up the properites dialog, and extend it for files */
void BaseTreeView::slotProperties()
{
if (! currentKFileTreeViewItem())
return;
propDlg = new KPropertiesDialog(currentKFileTreeViewItem()->fileItem(), this, 0L, false, false); //autodeletes itself
fileInfoDlg = 0L;
if (!currentKFileTreeViewItem()->isDir())
{
fileInfoDlg = addFileInfoPage(propDlg);
}
connect(propDlg, TQT_SIGNAL( applied() ), this, TQT_SLOT( slotPropertiesApplied()) );
propDlg->exec();
}
void BaseTreeView::slotPropertiesApplied()
{
if (! propDlg) return;
// check if renamed
KURL url = currentURL();
if (url != propDlg->kurl())
{
itemRenamed(url, propDlg->kurl());
}
KFileTreeViewItem *kftvi = currentKFileTreeViewItem();
if (fileInfoDlg && kftvi)
{
// has description changed?
TQString newDesc = fileInfoDlg->fileDesc->text();
if (kftvi->text(1) != newDesc)
itemDescChanged(kftvi, newDesc);
}
BaseTreeViewItem * btvi = dynamic_cast<BaseTreeViewItem *> (kftvi);
if (btvi)
{
btvi->refreshIcon();
}
/* not working as expected
if (kftvi && kftvi->url().isLocalFile()) {
slotReloadAllTrees(); // refresh the icons for local url's, they might have changed
}*/
}
void BaseTreeView::slotReloadAllTrees()
{
TQPtrStack<BaseTreeBranch> stack;
BaseTreeBranch *btb;
KFileTreeBranchIterator it( branches() );
for ( ; it.current(); ++it)
{
btb = dynamic_cast<BaseTreeBranch *>( (*it) );
if (btb && btb->rootUrl().isLocalFile()) {
stack.push(btb);
}
}
while (! stack.isEmpty())
{
reload(stack.pop());
}
}
void BaseTreeView::slotReload()
{
KFileTreeViewItem *curItem = currentKFileTreeViewItem();
if (curItem)
reload(dynamic_cast<BaseTreeBranch *>(curItem->branch()));
}
void BaseTreeView::reload(BaseTreeBranch *btb)
{
// remember the old status
TQStringList folderToOpen;
btb->addOpenFolder(&folderToOpen);
KURL url = btb->rootUrl();
// remove and open again
removeBranch(btb);
btb = dynamic_cast<BaseTreeBranch *>(newBranch(url));
if (btb) {
btb->folderToOpen = folderToOpen;
btb->reopenFolder();
btb->updateOpenFolder();
}
}
void BaseTreeView::slotJobFinished(KIO::Job *job)
{
if ( job->error() )
job->showErrorDialog(this);
progressBar->setTotalSteps(1);
progressBar->setProgress(-1);
progressBar->setTextEnabled(false);
}
void BaseTreeView::slotReturnPressed(TQListViewItem *item)
{
emit executed(item);
}
bool BaseTreeView::acceptDrag(TQDropEvent* e ) const
{
TQPoint p (contentsToViewport(e->pos()));
TQListViewItem *atpos = itemAt(p);
KFileTreeViewItem *kftvi = dynamic_cast <KFileTreeViewItem *> (atpos);
if (kftvi)
return (KFileTreeView::acceptDrag(e) && kftvi->isDir()); // accept only on folders
else
return (KFileTreeView::acceptDrag(e));
}
void BaseTreeView::slotDropped (TQWidget *, TQDropEvent * /*e*/, KURL::List& fileList, KURL& dest)
{
if(fileList.empty())
return;
// Check what the destination can do
if (!KProtocolInfo::supportsWriting(dest))
return;
bool sLinking = KProtocolInfo::supportsLinking(dest);
// Check what the source can do
KURL url = fileList.first(); // we'll assume it's the same for all URLs (hack)
bool sReading = KProtocolInfo::supportsReading(url);
bool sDeleting = KProtocolInfo::supportsDeleting(url);
bool sMoving = KProtocolInfo::supportsMoving(url);
// Check the state of the modifiers key at the time of the drop
Window root;
Window child;
int root_x, root_y, win_x, win_y;
uint keybstate;
XQueryPointer( qt_xdisplay(), qt_xrootwin(), &root, &child,
&root_x, &root_y, &win_x, &win_y, &keybstate );
int result;
if (keybstate & ControlMask) {
result = 1; // copy
} else {
if (keybstate & ShiftMask) {
result = 2; // move
} else {
// create the popup menu
TQPopupMenu popup;
if (sMoving || (sReading && sDeleting))
popup.insertItem(SmallIconSet("goto"), i18n("&Move Here"), 2 );
if (sReading)
popup.insertItem(SmallIconSet("editcopy"), i18n("&Copy Here"), 1 );
if (sLinking)
popup.insertItem(SmallIconSet("www"), i18n("&Link Here"), 3 );
popup.insertSeparator();
popup.insertItem(SmallIconSet("cancel"), i18n("C&ancel"), 5);
result = popup.exec( TQCursor::pos() );
}
}
bool tooltip = showToolTips();
KIO::Job *job;
switch ( result ) {
case 1 : setShowToolTips(false);
setDragEnabled(false);
QuantaNetAccess::dircopy(fileList, dest, m_parent, true);
setDragEnabled(true);
setShowToolTips(tooltip);
return;
case 2 : setShowToolTips(false);
setDragEnabled(false);
QuantaNetAccess::move(fileList, dest, m_parent, true);
setDragEnabled(true);
setShowToolTips(tooltip);
return;
case 3 : job = KIO::link(fileList, dest);
break;
default : return ;
}
if (!job)
return;
connect(job, TQT_SIGNAL( result(KIO::Job *) ),
this, TQT_SLOT( slotJobFinished(KIO::Job *) ) );
progressBar->setTotalSteps(100);
connect(job, TQT_SIGNAL(percent( KIO::Job *, unsigned long)),
this, TQT_SLOT(slotPercent( KIO::Job *, unsigned long)));
}
void BaseTreeView::findDrop(const TQPoint &pos, TQListViewItem *&parent, TQListViewItem *&after)
{
TQPoint p (contentsToViewport(pos));
TQListViewItem *atpos = itemAt(p);
// if (atpos && atpos->parent()) {
// after = atpos;
// parent = atpos->parent();
// } else {
after = atpos;
parent = atpos;
// }
}
void BaseTreeView::slotNewProjectLoaded(const TQString &name, const KURL &baseURL, const KURL &)
{
m_projectName = name;
m_projectBaseURL = baseURL;
}
bool BaseTreeView::isFileOpen(const KURL &url)
{
return ViewManager::ref()->isOpened(url);
}
bool BaseTreeView::isPathInClipboard()
{
TQClipboard *cb = TQApplication::clipboard();
KURL::List list( TQStringList::split( TQChar('\n'), cb->text() ) );
for ( KURL::List::Iterator it = list.begin(); it != list.end(); ++it )
{
if ( !(*it).isValid() )
return false;
}
return true;
}
void BaseTreeView::slotDocumentClosed(const KURL& url)
{
KFileTreeViewItem * item;
KFileTreeBranchIterator it( branches() );
for ( ; it.current(); ++it)
{
item = (*it)->findTVIByURL(url);
if (item)
{
item->repaint();
}
}
/* TQListViewItemIterator iter(this);
for ( ; iter.current(); ++iter )
{
iter.current()->repaint();
}*/
}
void BaseTreeView::slotStartRename()
{
KFileTreeViewItem * item = currentKFileTreeViewItem();
if (item) {
setRenameable(0, true);
rename(item, 0);
};
}
void BaseTreeView::cancelRename(int col)
{
// reset the inline rename option for file/folder name
if (col == 0) {
setRenameable(0, false);
}
}
void BaseTreeView::slotRenameItem(TQListViewItem* item, const TQString & newText, int col)
{
if (!item)
return;
// reset the inline rename option for file/folder name
if (col == 0) {
setRenameable(0, false);
KFileTreeViewItem * kvtvi = dynamic_cast<KFileTreeViewItem *>(item);
if (kvtvi)
doRename(kvtvi, newText);
}
}
void BaseTreeView::doRename(KFileTreeViewItem* kftvi, const TQString & newName)
{
if (! kftvi)
return;
KURL oldURL = kftvi->url();
KURL newURL = oldURL;
if (kftvi->isDir())
{
newURL.setPath(TQFileInfo(oldURL.path(-1)).dirPath() + '/' + newName + '/');
oldURL.adjustPath(1);
} else
{
newURL.setFileName(newName);
}
if ( oldURL != newURL )
{
bool proceed = true;
if (QExtFileInfo::exists(newURL, false, this))
{
proceed = KMessageBox::warningContinueCancel(this, i18n("<qt>The file <b>%1</b> already exists.<br>Do you want to overwrite it?</qt>").arg(newURL.prettyURL(0, KURL::StripFileProtocol)),i18n("Overwrite"), i18n("Overwrite")) == KMessageBox::Continue;
}
if (proceed)
{
//start the rename job
oldURL.adjustPath(-1);
newURL.adjustPath(-1);
if (!QuantaNetAccess::file_move(oldURL, newURL, -1, true, false, m_parent, true))
{
kftvi->setText(0, kftvi->fileItem()->text()); // reset the text
}
} else
{
kftvi->setText(0, kftvi->fileItem()->text()); // reset the text
}
}
}
void BaseTreeView::saveLayout(KConfig *config, const TQString &group)
{
KListView::saveLayout(config, group);
if (! m_saveOpenFolder || ! qConfig.saveTrees)
return;
KConfigGroupSaver saver(config, group);
BaseTreeBranch *btb;
int i = 0;
KFileTreeBranchIterator it( branches() );
for ( ; it.current(); ++it)
{
btb = dynamic_cast<BaseTreeBranch *>( (*it) );
if (btb && btb->rootUrl().isLocalFile()) {
++i;
TQStringList folderList;
// remember the root url so that I find the branch on restore
folderList.append(btb->rootUrl().url());
btb->addOpenFolder(&folderList);
config->writePathEntry("OpenFolderList" + TQString::number(i), folderList);
}
}
config->writeEntry("NumOpenFolderList", i);
}
void BaseTreeView::restoreLayout(KConfig *config, const TQString &group)
{
KListView::restoreLayout(config, group);
KConfigGroupSaver saver(config, group);
setShowToolTips( config->readBoolEntry("ShowToolTips", true) );
if (! m_saveOpenFolder || ! qConfig.saveTrees)
return;
BaseTreeBranch *btb;
KFileTreeBranchIterator it( branches() );
int maxBranch = config->readNumEntry("NumOpenFolderList", 0);
for (int i = 1; i <= maxBranch; ++i)
{
TQStringList folderList = QuantaCommon::readPathListEntry(config, "OpenFolderList" + TQString::number(i));
if (folderList.count() > 1) {
KURL rootURL = (*folderList.begin());
folderList.remove(folderList.begin()); // remove the root URL
KFileTreeBranchIterator it( branches() );
for ( ; it.current(); ++it)
{
if ((*it)->rootUrl() == rootURL) {
btb = dynamic_cast<BaseTreeBranch *>( (*it) );
if (btb) {
btb->folderToOpen = folderList;
btb->reopenFolder();
break;
}
}
}
}
}
}
void BaseTreeView::slotCreateSiteTemplate()
{
TQString startDir;
if (Project::ref()->hasProject())
{
startDir = Project::ref()->templateURL().url();
} else
{
startDir = locateLocal("data", resourceDir + "templates/");
}
KURL targetURL;
bool valid;
do {
valid = false;
targetURL = KFileDialog::getSaveURL(startDir, "*.tgz", this, i18n("Create Site Template File"));
if (targetURL.isEmpty())
return;
if (targetURL.url().startsWith(KURL::fromPathOrURL(locateLocal("data", resourceDir + "templates/")).url()))
valid = true;
if (Project::ref()->hasProject() && targetURL.url().startsWith(Project::ref()->templateURL().url()))
valid = true;
if (!valid)
KMessageBox::error(this, i18n("Templates should be saved to the local or project template folder."));
}while (!valid);
KURL url = currentURL();
//TODO: Implement creation from remote folders as well. Requires downloading of the files to a
//temporary directory
if (url.protocol() != "file")
{
KMessageBox::sorry(this, i18n("Currently you can create site templates only from local folders."), i18n("Unsupported Feature"));
return;
}
KTempFile *tempFile = new KTempFile(tmpDir);
tempFile->setAutoDelete(true);
tempFile->close();
KTar tar(tempFile->name(), "application/x-gzip");
bool error = false;
if (tar.open(IO_WriteOnly))
{
KURL::List fileList = QExtFileInfo::allFiles(url, "*", this);
for (KURL::List::Iterator it = fileList.begin(); it != fileList.end(); ++it)
{
if (!(*it).path().endsWith("/"))
{
TQFile f((*it).path());
if (f.open(IO_ReadOnly))
{
TQByteArray buffer(f.readAll());
if (!tar.writeFile((*it).path().remove(url.path()), "user", "group", buffer.size(), buffer.data()))
{
error = true;
}
f.close();
} else
error = true;
}
}
tar.close();
} else
error = true;
if (!QuantaNetAccess::copy(KURL::fromPathOrURL(tempFile->name()), targetURL, m_parent, false))
error = true;
if (error)
KMessageBox::error(this, i18n("<qt>There was an error while creating the site template tarball.<br>Check that you can read the files from <i>%1</i>, you have write access to <i>%2</i> and that you have enough free space in your temporary folder.</qt>").arg(url.prettyURL(0, KURL::StripFileProtocol)).arg(targetURL.prettyURL(0, KURL::StripFileProtocol)), i18n("Template Creation Error"));
delete tempFile;
}
void BaseTreeView::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 +"/");
QuantaNetAccess::mkdir(url, this, -1);
}
}
void BaseTreeView::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 (QuantaNetAccess::copy(KURL::fromPathOrURL(tempFile->name()), url, this))
{
emit openFile(url);
}
delete tempFile;
}
}
#include "basetreeview.moc"