summaryrefslogtreecommitdiffstats
path: root/quanta/treeviews
diff options
context:
space:
mode:
authortoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
committertoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
commite9ae80694875f869892f13f4fcaf1170a00dea41 (patch)
treeaa2f8d8a217e2d376224c8d46b7397b68d35de2d /quanta/treeviews
downloadtdewebdev-e9ae80694875f869892f13f4fcaf1170a00dea41.tar.gz
tdewebdev-e9ae80694875f869892f13f4fcaf1170a00dea41.zip
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923 git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdewebdev@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'quanta/treeviews')
-rw-r--r--quanta/treeviews/Makefile.am24
-rw-r--r--quanta/treeviews/basetreeview.cpp1233
-rw-r--r--quanta/treeviews/basetreeview.h362
-rw-r--r--quanta/treeviews/docfolder.cpp126
-rw-r--r--quanta/treeviews/docfolder.h50
-rw-r--r--quanta/treeviews/docitem.cpp52
-rw-r--r--quanta/treeviews/docitem.h45
-rw-r--r--quanta/treeviews/doctreeview.cpp194
-rw-r--r--quanta/treeviews/doctreeview.h71
-rw-r--r--quanta/treeviews/fileinfodlg.ui94
-rw-r--r--quanta/treeviews/filestreeview.cpp334
-rw-r--r--quanta/treeviews/filestreeview.h81
-rw-r--r--quanta/treeviews/newtemplatedirdlg.cpp29
-rw-r--r--quanta/treeviews/newtemplatedirdlg.h33
-rw-r--r--quanta/treeviews/projecttreeview.cpp674
-rw-r--r--quanta/treeviews/projecttreeview.h176
-rw-r--r--quanta/treeviews/quantapropertiespage.ui247
-rw-r--r--quanta/treeviews/scripttreeview.cpp425
-rw-r--r--quanta/treeviews/scripttreeview.h220
-rw-r--r--quanta/treeviews/servertreeview.cpp195
-rw-r--r--quanta/treeviews/servertreeview.h92
-rw-r--r--quanta/treeviews/structtreetag.cpp217
-rw-r--r--quanta/treeviews/structtreetag.h45
-rw-r--r--quanta/treeviews/structtreeview.cpp1071
-rw-r--r--quanta/treeviews/structtreeview.h176
-rw-r--r--quanta/treeviews/tagattributeitems.cpp538
-rw-r--r--quanta/treeviews/tagattributeitems.h178
-rw-r--r--quanta/treeviews/tagattributetree.cpp659
-rw-r--r--quanta/treeviews/tagattributetree.h143
-rw-r--r--quanta/treeviews/templatedirform.ui170
-rw-r--r--quanta/treeviews/templatestreeview.cpp1079
-rw-r--r--quanta/treeviews/templatestreeview.h162
-rw-r--r--quanta/treeviews/uploadtreefile.cpp89
-rw-r--r--quanta/treeviews/uploadtreefile.h53
-rw-r--r--quanta/treeviews/uploadtreefolder.cpp116
-rw-r--r--quanta/treeviews/uploadtreefolder.h57
-rw-r--r--quanta/treeviews/uploadtreeview.cpp451
-rw-r--r--quanta/treeviews/uploadtreeview.h60
38 files changed, 10021 insertions, 0 deletions
diff --git a/quanta/treeviews/Makefile.am b/quanta/treeviews/Makefile.am
new file mode 100644
index 00000000..c32c617d
--- /dev/null
+++ b/quanta/treeviews/Makefile.am
@@ -0,0 +1,24 @@
+noinst_LTLIBRARIES = libtreeviews.la
+
+METASOURCES = AUTO
+
+libtreeviews_la_SOURCES = uploadtreeview.cpp uploadtreefolder.cpp uploadtreefile.cpp fileinfodlg.ui quantapropertiespage.ui newtemplatedirdlg.cpp templatedirform.ui templatestreeview.cpp projecttreeview.cpp structtreeview.cpp doctreeview.cpp docitem.cpp docfolder.cpp structtreetag.cpp filestreeview.cpp tagattributetree.cpp tagattributeitems.cpp scripttreeview.cpp basetreeview.cpp servertreeview.cpp
+
+if include_cvsservice
+CVSSERVICE_INCLUDE = -I$(top_srcdir)/quanta/components/cvsservice
+endif
+
+AM_CPPFLAGS = -I$(top_srcdir)/quanta/utility \
+ -I$(top_srcdir)/quanta/parsers \
+ -I$(top_srcdir)/quanta/src \
+ -I$(top_srcdir)/quanta/project \
+ -I$(top_srcdir)/quanta/dialogs/tagdialogs \
+ -I$(top_srcdir)/quanta/dialogs \
+ -I$(top_srcdir)/quanta/messages \
+ -I$(top_srcdir)/quanta/parts/kafka \
+ -I$(top_srcdir)/quanta/components/csseditor \
+ -I$(top_srcdir)/lib \
+ -I$(top_builddir)/quanta/dialogs/tagdialogs \
+ -I$(top_builddir)/quanta/components/csseditor \
+ -I$(top_srcdir)/quanta/plugins \
+ $(KMDI_INCLUDES) $(CVSSERVICE_INCLUDE) $(LIBXML_CFLAGS) $(LIBXSLT_CFLAGS) $(all_includes)
diff --git a/quanta/treeviews/basetreeview.cpp b/quanta/treeviews/basetreeview.cpp
new file mode 100644
index 00000000..8d8fad11
--- /dev/null
+++ b/quanta/treeviews/basetreeview.cpp
@@ -0,0 +1,1233 @@
+/***************************************************************************
+ 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 <qeventloop.h>
+#include <qlayout.h>
+#include <qfileinfo.h>
+#include <qlabel.h>
+#include <qimage.h>
+#include <qregexp.h>
+#include <qclipboard.h>
+#include <qpoint.h>
+#include <qregexp.h>
+#include <qlineedit.h>
+#include <qfont.h>
+#include <qpainter.h>
+#include <qtooltip.h>
+#include <qptrstack.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 QToolTip
+{
+public:
+ BaseTreeViewToolTip( QWidget *parent, BaseTreeView *lv );
+
+ void maybeTip( const QPoint &pos );
+
+private:
+ BaseTreeView *m_view;
+
+};
+
+BaseTreeViewToolTip::BaseTreeViewToolTip( QWidget *parent, BaseTreeView *lv )
+ : QToolTip( parent ), m_view( lv )
+{
+}
+
+void BaseTreeViewToolTip::maybeTip( const QPoint &pos )
+{
+ if ( !parentWidget() || !m_view || !m_view->showToolTips() )
+ return;
+
+ QListViewItem *item = m_view->itemAt(pos);
+ if (!item)
+ return;
+ QString text;
+ KFileTreeViewItem * kftvi = dynamic_cast<BaseTreeViewItem *> (item);
+ if (kftvi) {
+ QString 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)
+{
+}
+
+QString 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(QListViewItem *i, int col,
+ bool ascending) const
+{
+ return key(col, ascending).compare(i->key(col, ascending));
+}
+
+void BaseTreeViewItem::paintCell(QPainter *p, const QColorGroup &cg,
+ int column, int width, int align)
+{
+ QColorGroup _cg( cg );
+ if (column == 0)
+ {
+ QFont 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(QColorGroup::Text, QColor(h, s, v, QColor::Hsv));
+ };
+ KFileTreeViewItem::paintCell( p, _cg, column, width, align );
+}
+
+void BaseTreeViewItem::refreshIcon()
+{
+ fileItem()->refreshMimeType();
+}
+
+
+//BaseTreeBranch implementation
+BaseTreeBranch::BaseTreeBranch(KFileTreeView *parent, const KURL& url,
+ const QString& name, const QPixmap& 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(QStringList* 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 (QStringList::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(QEventLoop::ExcludeUserInput | QEventLoop::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(QWidget *parent, const char *name)
+: KFileTreeView(parent, name), fileInfoDlg(0), m_saveOpenFolder(false), m_openWithMenu(0L), m_openWithMenuId(-1)
+{
+ m_parent = parent;
+ QToolTip::remove(viewport()); // remove the tooltip from QListView
+ m_tooltip = new BaseTreeViewToolTip(viewport(), this);
+ setFrameStyle( Panel | Sunken );
+ setRootIsDecorated(true);
+ setSorting(0);
+ setLineWidth(2);
+ setFullWidth(true);
+ setShowSortIndicator(true);
+ setFocusPolicy(QWidget::ClickFocus);
+ setShowFolderOpenPixmap(false);
+
+ connect(this, SIGNAL(returnPressed(QListViewItem *)),
+ this, SLOT(slotReturnPressed(QListViewItem *)));
+
+ connect(this, SIGNAL(dropped(QWidget *, QDropEvent *, KURL::List&, KURL&)),
+ this, SLOT(slotDropped(QWidget *, QDropEvent *, KURL::List&, KURL&)));
+
+ connect(this, SIGNAL(itemRenamed(QListViewItem*, const QString &, int )),
+ this, SLOT(slotRenameItem(QListViewItem*, const QString &, int )));
+
+ connect(this, SIGNAL(executed(QListViewItem *)),
+ this, SLOT(slotSelectFile(QListViewItem *)));
+
+ connect(this, SIGNAL(openFile(const KURL &)),
+ quantaApp, SLOT(slotFileOpen(const KURL &)));
+
+ connect(this, SIGNAL(openImage(const KURL &)),
+ quantaApp, SLOT(slotImageOpen(const KURL &)));
+
+ connect(this, SIGNAL(closeFile(const KURL &)),
+ quantaApp, SLOT(slotFileClose(const KURL &)));
+
+ connect(this, SIGNAL(insertTag(const KURL &, DirInfo)),
+ quantaApp, SLOT(slotInsertTag(const KURL &, DirInfo)));
+}
+
+
+BaseTreeView::~BaseTreeView()
+{
+ QToolTip::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(QListViewItem *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;
+
+ QString 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() )
+ {
+
+ QFrame *quantaFilePage = propDlg->addPage(i18n("Quanta File Info"));
+ QVBoxLayout *topLayout = new QVBoxLayout( quantaFilePage);
+ quantaFileProperties = new FileInfoDlg( quantaFilePage, i18n("Quanta") );
+
+ 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
+ {
+ QString nameForInfo = u.path();
+ QString path =u.directory(0,0); //extract path for images
+ QString sourcename=u.fileName(0);
+
+ QFile qfile(nameForInfo);
+ fsize=qfile.size(); //html file size
+
+ QString mimetype = KMimeType::findByFileContent(nameForInfo)->name();
+ if (mimetype.contains("text"))
+ {
+ qfile.open(IO_ReadOnly);
+ QString imgname,imgpath;
+ QTextStream stream(&qfile);
+ stream.setEncoding(QTextStream::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,Qt::ExactMatch)) //check if image was already counted
+ {
+ KURL v(KURL::fromPathOrURL( path ),imgname);
+ imgpath=v.path();
+ QFile 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
+ QImage imagefile=QImage(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()
+{
+ QListViewItem *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(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();
+ QString mimeType = KMimeType::findByURL(urlToOpen, 0, true, true)->name();
+ KTrader::OfferList offers = KTrader::self()->query(mimeType, "Type == 'Application'");
+ QDict<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, QFile::encodeName((*it)->desktopEntryPath()).data());
+ connect(action, SIGNAL(activated()), this, SLOT(slotOpenWithApplication()));
+ action->plug(m_openWithMenu);
+ m_openWithActions.append(action);
+ }
+ m_openWithMenu->insertSeparator();
+ }
+ if (plugins.count() > 0)
+ {
+ m_openWithMenu->insertTitle(i18n("Plugins"));
+ QDictIterator<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, SIGNAL(activated(int)), SLOT(slotOpenWithActivated(int)));
+ m_openWithMenu->insertSeparator();
+ }
+ m_openWithMenu->insertItem(i18n("&Other..."), this, SLOT(slotOpenWith()));
+ m_openWithMenuId = menu->insertItem(i18n("Open &With"), m_openWithMenu, -1, position);
+ } else
+ m_openWithMenuId = menu->insertItem(i18n("Open &With..."), this, 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())
+ {
+ QClipboard *cb = QApplication::clipboard();
+ cb->setText( currentURL().prettyURL() );
+ }
+}
+
+
+void BaseTreeView::slotPaste()
+{
+ if (currentItem())
+ {
+ QClipboard *cb = QApplication::clipboard();
+ KURL::List list( QStringList::split( QChar('\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 {
+ QString 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, SIGNAL( applied() ), this, 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?
+ QString 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()
+{
+ QPtrStack<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
+ QStringList 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(QListViewItem *item)
+{
+ emit executed(item);
+}
+
+
+bool BaseTreeView::acceptDrag(QDropEvent* e ) const
+{
+ QPoint p (contentsToViewport(e->pos()));
+ QListViewItem *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 (QWidget *, QDropEvent * /*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
+ QPopupMenu 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( QCursor::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, SIGNAL( result(KIO::Job *) ),
+ this, SLOT( slotJobFinished(KIO::Job *) ) );
+ progressBar->setTotalSteps(100);
+ connect(job, SIGNAL(percent( KIO::Job *, unsigned long)),
+ this, SLOT(slotPercent( KIO::Job *, unsigned long)));
+}
+
+
+void BaseTreeView::findDrop(const QPoint &pos, QListViewItem *&parent, QListViewItem *&after)
+{
+ QPoint p (contentsToViewport(pos));
+ QListViewItem *atpos = itemAt(p);
+// if (atpos && atpos->parent()) {
+// after = atpos;
+// parent = atpos->parent();
+// } else {
+ after = atpos;
+ parent = atpos;
+// }
+}
+
+
+void BaseTreeView::slotNewProjectLoaded(const QString &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()
+{
+ QClipboard *cb = QApplication::clipboard();
+ KURL::List list( QStringList::split( QChar('\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();
+ }
+ }
+/* QListViewItemIterator 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(QListViewItem* item, const QString & 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 QString & newName)
+{
+ if (! kftvi)
+ return;
+
+ KURL oldURL = kftvi->url();
+ KURL newURL = oldURL;
+
+ if (kftvi->isDir())
+ {
+ newURL.setPath(QFileInfo(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 QString &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;
+ QStringList folderList;
+ // remember the root url so that I find the branch on restore
+ folderList.append(btb->rootUrl().url());
+ btb->addOpenFolder(&folderList);
+ config->writePathEntry("OpenFolderList" + QString::number(i), folderList);
+ }
+ }
+ config->writeEntry("NumOpenFolderList", i);
+}
+
+
+void BaseTreeView::restoreLayout(KConfig *config, const QString &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)
+ {
+ QStringList folderList = QuantaCommon::readPathListEntry(config, "OpenFolderList" + QString::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()
+{
+ QString 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("/"))
+ {
+ QFile f((*it).path());
+ if (f.open(IO_ReadOnly))
+ {
+ QByteArray 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;
+ QString 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;
+ QString 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"
diff --git a/quanta/treeviews/basetreeview.h b/quanta/treeviews/basetreeview.h
new file mode 100644
index 00000000..345b5a79
--- /dev/null
+++ b/quanta/treeviews/basetreeview.h
@@ -0,0 +1,362 @@
+/***************************************************************************
+ BaseTreeView.h - 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 <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. *
+ * *
+ ***************************************************************************/
+
+#ifndef BASETREEVIEW_H
+#define BASETREEVIEW_H
+
+//qt includes
+#include <qvaluelist.h>
+
+//kde includes
+#include <kfiletreebranch.h>
+#include <kfiletreeview.h>
+#include <kfiletreeviewitem.h>
+
+// quanta includes
+#include "quantacommon.h"
+
+//foward declarations
+class QListViewItem;
+class QString;
+class QPixmap;
+class QPoint;
+class QRegExp;
+class QCloseEvent;
+
+class KAction;
+class KFileItem;
+class KPopupMenu;
+class KPropertiesDialog;
+class KURL;
+class FileInfoDlg;
+class BaseTreeViewToolTip;
+class QuantaPlugin;
+
+/**
+ * @short a KFileTreeViewItem with some specials.
+ *
+ * @author Jens Herden <jens@kdewebdev.org>
+ */
+class BaseTreeViewItem : public KFileTreeViewItem {
+
+public:
+ BaseTreeViewItem( KFileTreeViewItem *parent, KFileItem* item, KFileTreeBranch *brnch );
+
+ /**
+ sorts folders separate from files
+ */
+ QString key (int column, bool ascending) const;
+
+ /**
+ makes compare independent from locale
+ */
+ int compare( QListViewItem *i, int col, bool ascending ) const;
+
+ /**
+ makes open files bold and the second column lighter
+ */
+ void paintCell(QPainter *p, const QColorGroup &cg, int column, int width, int align);
+
+ /**
+ refresh icon
+ */
+ void refreshIcon();
+};
+
+/**
+ * @short a KFileTreeBranch that uses @ref BaseTreeViewItem and does some special filtering.
+ *
+ * @author Jens Herden <jens@kdewebdev.org>
+ */
+class BaseTreeBranch : public KFileTreeBranch {
+ Q_OBJECT
+
+public:
+ BaseTreeBranch(KFileTreeView *parent, const KURL& url,
+ const QString& name, const QPixmap& pix,
+ bool showHidden = false, KFileTreeViewItem *branchRoot = 0);
+ /**
+ get the BaseTreeViewItem
+ */
+ virtual KFileTreeViewItem* createTreeViewItem( KFileTreeViewItem *parent,
+ KFileItem *fileItem );
+ /**
+ does custom filtering
+ */
+ bool matchesFilter(const KFileItem *item) const;
+
+ /**
+ files matching to this will not be shown
+ */
+ QRegExp excludeFilterRx;
+
+ /**
+ adds the current open folders of the branch to a stringslist.
+ Attention: no check for double entries is done
+
+ @param openFolder the list where to add the URL strings
+ */
+ void addOpenFolder(QStringList *openFolder);
+
+ /** opens the next folder in @ref folderToOpen */
+ void reopenFolder();
+
+ /** list of folders to open */
+ QStringList folderToOpen;
+
+ /** inform the dirwatcher to update all open folders */
+ void updateOpenFolder();
+
+};
+
+
+/**
+ * @short the base class for many of Quantas treeviews
+ *
+ * @ref FilesTreeView, @ref ScriptTreeView, @ref ProjectTreeView and
+ * @ref TemplatesTreeView use this class.
+ *
+ */
+class BaseTreeView : public KFileTreeView {
+ Q_OBJECT
+
+public:
+ BaseTreeView(QWidget *parent = 0L, const char *name = 0L);
+ virtual ~BaseTreeView();
+
+ /**
+ * Saves the list view's layout (column widtsh, column order, sort column)
+ * to a KConfig group. Reimplemented to save the open folders.
+ *
+ * @param config the KConfig object to write to
+ * @param group the config group to use
+ */
+ void saveLayout(KConfig *config, const QString &group);
+
+ /**
+ * Reads the list view's layout from a KConfig group as stored with
+ * saveLayout. Reimplemented to load the open folders.
+ *
+ * @param config the KConfig object to read from
+ * @param group the config group to use
+ */
+ void restoreLayout(KConfig *config, const QString &group);
+
+ /**
+ * en/disable saving a list of open folders in @ref saveLayout and
+ * restoring the tree status in @ref restoreLayout
+ */
+ void setSaveOpenFolder(bool b = true) { m_saveOpenFolder = b; };
+
+ /** reads property @ref setSaveOpenFolder */
+ bool saveOpenFolder() { return m_saveOpenFolder; };
+
+public slots:
+ /**
+ sets new project information
+ */
+ void slotNewProjectLoaded(const QString &, const KURL &, const KURL &);
+ /**
+ repaints all treeview items
+ */
+ void slotDocumentClosed(const KURL& url);
+
+protected slots:
+
+ void slotCopy();
+ void slotPaste();
+ void slotDelete();
+ virtual void slotJobFinished( KIO::Job *job);
+ void slotInsertInProject();
+ void slotInsertDirInProject();
+ virtual void slotReturnPressed(QListViewItem *item);
+ virtual void slotDropped (QWidget *, QDropEvent *, KURL::List&, KURL&);
+ /**
+ sends value from KIO::Job to progressbar
+ */
+ virtual void slotPercent(KIO::Job *job, unsigned long value);
+
+ void slotPopulateFinished(KFileTreeViewItem *item);
+ /**
+ shows open with dialog for the current item
+ */
+ void slotOpenWith();
+
+ /** Opens the current item with the selected associated application */
+ void slotOpenWithApplication();
+ /**
+ Called for: double click, return, Open
+
+ emits a signal (@ref openFile or @ref openImage)
+ or expands an archiv (@ref expandArchiv) in the tree
+ */
+ virtual void slotSelectFile(QListViewItem *item);
+ /**
+ emits the signal @ref insertTag
+ */
+ void slotInsertTag();
+ /**
+ reloads the current branch
+ */
+ void slotReload();
+ /**
+ reloads all branches
+ */
+ virtual void slotReloadAllTrees();
+ /**
+ reloads one branche
+ */
+ virtual void reload(BaseTreeBranch *btb);
+ /**
+ opens the properties dialog
+ */
+ void slotProperties();
+ /**
+ applies changed properties
+ */
+ virtual void slotPropertiesApplied();
+ /**
+ emits the signal @ref open
+ */
+ void slotOpen();
+ /**
+ emits the signal @ref closeFile
+ */
+ void slotClose();
+
+ /**
+ starts the inline rename of the current item
+ */
+ void slotStartRename();
+
+ /**
+ connect signal itemRenamed to this slot to handle inline rename
+ */
+ virtual void slotRenameItem(QListViewItem* kvtvi, const QString & newText, int col);
+ /**
+ create a site template tarball from the selected directory
+ */
+ virtual void slotCreateSiteTemplate();
+ /**
+ Creates a folder under the current item
+ */
+ virtual void slotCreateFolder();
+ /**
+ Creates a file under the current item
+ */
+ virtual void slotCreateFile();
+
+ virtual void slotOpenWithActivated(int id);
+
+protected:
+ /**
+ implement this to create a branch and add this branch to the treeview
+ @param url the root of the branch
+ @return the new branch
+ */
+ virtual KFileTreeBranch* newBranch(const KURL& url) = 0;
+
+ /**
+ called when an item was renamed in the properties dialog
+ the default implementation emits the signal @ref renamed
+ */
+ virtual void itemRenamed(const KURL& , const KURL& );
+
+ /**
+ called when the description of an item was changed,
+ the default implementation does nothing
+ @param item the treeview item
+ @param newDesc the new description of item
+ */
+ virtual void itemDescChanged(KFileTreeViewItem* item, const QString& newDesc)
+ {
+ Q_UNUSED(item);
+ Q_UNUSED(newDesc);
+ };
+ /**
+ @return true if the clipboard contains one or more valid path
+ */
+ bool isPathInClipboard();
+
+ /**
+ adds the Quanta fileinfopage to the properties dialog
+ @param propDlg the dialog where to add the page
+ @return pointer to to just added page
+ */
+ virtual FileInfoDlg* addFileInfoPage(KPropertiesDialog *propDlg);
+
+ /**
+ expands an archiv inside of the tree
+ @return true if expanding was possible
+ */
+ bool expandArchiv (KFileTreeViewItem *item);
+ bool acceptDrag(QDropEvent* e ) const;
+ void findDrop(const QPoint &pos, QListViewItem *&parent, QListViewItem *&after);
+
+ /**
+ this is for project and template tree to reduce includes there
+ */
+ bool isFileOpen(const KURL &url);
+
+ /** Inserts an Open With submenu into @param menu which lists
+ the possible applications that can open the current item and an
+ "Other" entry to bring up the Open With dialog. If no application
+ is associated with the type of the current item, the menu will bring up the Open With dialog immediately.
+ @param menu the menu where the Open With submenu should be inserted
+ @param position the position in this menu
+ */
+ void insertOpenWithMenu(KPopupMenu *menu, int position);
+ KPropertiesDialog *propDlg;
+ QString m_projectName;
+ KURL m_projectBaseURL;
+ FileInfoDlg* fileInfoDlg;
+ /** the parent of the treeview
+ the passwords are cached there
+ */
+ QWidget * m_parent;
+
+ BaseTreeViewToolTip * m_tooltip;
+ // some stuff for renaming
+ void doRename(KFileTreeViewItem* kvtvi, const QString & newName);
+ /** reimplemented to reset renameable */
+ void cancelRename(int col);
+
+signals:
+ void openFile(const KURL&);
+ void openImage(const KURL&);
+ void open(QListViewItem *name);
+ void insertDirInProject(const KURL&);
+ void insertFileInProject(const KURL&);
+ void insertTag(const KURL &, DirInfo);
+ /**
+ file or folder has been renamed
+ */
+ void renamed(const KURL &, const KURL &);
+ /**
+ close the file in Quanta
+ */
+ void closeFile( const KURL& );
+
+private:
+ bool m_saveOpenFolder;
+ KPopupMenu *m_openWithMenu;
+ int m_openWithMenuId;
+ QValueList<KAction *> m_openWithActions;
+ QMap<int, QuantaPlugin*> m_pluginIds;
+};
+
+#endif
diff --git a/quanta/treeviews/docfolder.cpp b/quanta/treeviews/docfolder.cpp
new file mode 100644
index 00000000..02669a1e
--- /dev/null
+++ b/quanta/treeviews/docfolder.cpp
@@ -0,0 +1,126 @@
+/***************************************************************************
+ docfolder.cpp - description
+ -------------------
+ begin : Fri Mar 3 2000
+ copyright : (C) 2000 by Yacovlev Alexander & Dmitry Poplavsky <pdima@mail.univ.kiev.ua>
+ (C) 2002 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. *
+ * *
+ ***************************************************************************/
+
+// QT includes
+#include <qstrlist.h>
+#include <qpixmap.h>
+
+// KDE includes
+#include <kconfig.h>
+#include <kstandarddirs.h>
+#include <kiconloader.h>
+
+// app includes
+#include "docfolder.h"
+#include "docitem.h"
+
+DocFolder::DocFolder(QListViewItem *parent, const QString &_name, KConfig *config, const QString &basePath)
+ : KListViewItem(parent)
+{
+ name = _name;
+ topLevel = false;
+ url = "";
+
+ QStrList list;
+
+ config->readListEntry( name, list );
+
+ char *item;
+
+ for ( list.last(); ( item = list.current() ) ; list.prev() ) {
+ if ( item[0] != '#' ) {
+ QString url = config->readEntry( item );
+ DocItem *el = new DocItem( this, QString(item), basePath+url);
+ el->setPixmap( 0, SmallIcon("info") );
+ } else
+ if ( item[0] == '#' ) { // current item is folder
+ item++; // remove leading #
+ QString l_url = config->readEntry( QString("folder_")+item, "" );
+ DocFolder *el = new DocFolder(this, QString(item), config, basePath);
+ if ( ! l_url.isEmpty() )
+ el->url = basePath+l_url;
+ el->setPixmap( 0, UserIcon("mini-book1") );
+ el->setOpen( false );
+ }
+ }
+}
+
+DocFolder::DocFolder(QListView *parent, const QString &_name, KConfig *config, const QString &basePath)
+ : KListViewItem(parent)
+{
+ name = _name;
+ topLevel = false;
+ url = "";
+ QStrList list;
+
+ config->readListEntry( name, list );
+
+ char *item;
+
+ for ( list.last(); ( item = list.current() ) ; list.prev() ) {
+ if ( item[0] != '#' ) {
+ QString url = config->readEntry( item );
+ DocItem *el = new DocItem( this, QString(item), basePath+url);
+ el->setPixmap( 0, SmallIcon("info") );
+ } else
+ if ( item[0] == '#' ) { // current item is folder
+ item++; // remove leading #
+ QString l_url = config->readEntry( QString("folder_")+item, "" );
+ DocFolder *el = new DocFolder(this, QString(item), config, basePath);
+ if ( ! l_url.isEmpty() )
+ el->url = basePath+l_url;
+ el->setPixmap( 0, UserIcon("mini-book1") );
+ el->setOpen( false );
+ }
+ }
+}
+
+
+
+DocFolder::~DocFolder(){
+}
+
+
+QString DocFolder::text( int i) const
+{
+ if (i == 0)
+ return name;
+ else
+ return "";
+}
+
+void DocFolder::setup()
+{
+ setExpandable( true );
+ QListViewItem::setup();
+}
+/** */
+void DocFolder::setOpen( bool o)
+{
+ QListViewItem::setOpen( o );
+ if ( !topLevel ) {
+ if (o)
+ setPixmap( 0, UserIcon("mini-book2") );
+ else
+ setPixmap( 0, UserIcon("mini-book1") );
+ } else {
+ if (o)
+ setPixmap( 0, SmallIcon("folder_open") );
+ else
+ setPixmap( 0, SmallIcon("folder") );
+ }
+}
diff --git a/quanta/treeviews/docfolder.h b/quanta/treeviews/docfolder.h
new file mode 100644
index 00000000..6b6668e1
--- /dev/null
+++ b/quanta/treeviews/docfolder.h
@@ -0,0 +1,50 @@
+/***************************************************************************
+ docfolder.h - description
+ -------------------
+ begin : Fri Mar 3 2000
+ copyright : (C) 2000 by Yacovlev Alexander & Dmitry Poplavsky <pdima@mail.univ.kiev.ua>
+ (C) 2002 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. *
+ * *
+ ***************************************************************************/
+
+#ifndef DOCFOLDER_H
+#define DOCFOLDER_H
+
+#include <qwidget.h>
+
+#include <klistview.h>
+
+/**
+Class for forlder for
+Doc tree
+
+ *@author Yacovlev Alexander & Dmitry Poplavsky
+ */
+
+class KConfig;
+
+class DocFolder : public KListViewItem {
+public:
+ DocFolder(QListViewItem *parent, const QString &_name, KConfig *config, const QString &basePath);
+ DocFolder(QListView *parent, const QString &_name, KConfig *config, const QString &basePath);
+ ~DocFolder();
+ QString text( int column ) const;
+ void setup();
+ /** */
+ void setOpen( bool o);
+
+public:
+ QString url;
+ QString name;
+ bool topLevel;
+};
+
+#endif
diff --git a/quanta/treeviews/docitem.cpp b/quanta/treeviews/docitem.cpp
new file mode 100644
index 00000000..7c9efa83
--- /dev/null
+++ b/quanta/treeviews/docitem.cpp
@@ -0,0 +1,52 @@
+/***************************************************************************
+ docitem.cpp - description
+ -------------------
+ begin : Fri Mar 3 2000
+ copyright : (C) 2000 by Yacovlev Alexander & Dmitry Poplavsky <pdima@mail.univ.kiev.ua>
+ (C) 2002 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. *
+ * *
+ ***************************************************************************/
+
+#include <qstrlist.h>
+
+#include <kconfig.h>
+
+#include "docitem.h"
+
+DocItem::DocItem(QListViewItem *parent, const QString &_name, const QString &_url)
+ : KListViewItem(parent)
+{
+ url = _url;
+ name = _name;
+}
+
+DocItem::DocItem(QListView *parent, const QString &_name, const QString &_url)
+ : KListViewItem(parent)
+{
+ url = _url;
+ name = _name;
+}
+
+
+DocItem::~DocItem()
+{
+}
+
+
+QString DocItem::text( int i) const
+{
+ if (i == 0)
+ return name;
+ else
+ return "";
+}
+//#include "docitem.moc"
+
diff --git a/quanta/treeviews/docitem.h b/quanta/treeviews/docitem.h
new file mode 100644
index 00000000..94fff375
--- /dev/null
+++ b/quanta/treeviews/docitem.h
@@ -0,0 +1,45 @@
+/***************************************************************************
+ docitem.h - description
+ -------------------
+ begin : Fri Mar 3 2000
+ copyright : (C) 2000 by Yacovlev Alexander & Dmitry Poplavsky <pdima@mail.univ.kiev.ua>
+ (C) 2002 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. *
+ * *
+ ***************************************************************************/
+
+#ifndef DOCITEM_H
+#define DOCITEM_H
+
+#include <qwidget.h>
+
+#include <klistview.h>
+
+class KConfig;
+
+/**
+ *@author Yacovlev Alexander & Dmitry Poplavsky
+ */
+
+class DocItem : public KListViewItem {
+
+public:
+ DocItem(QListViewItem *parent, const QString &_name, const QString &_url);
+ DocItem(QListView *parent, const QString &_name, const QString &_url);
+ ~DocItem();
+ QString text( int column ) const;
+
+public: // Public attributes
+ QString url;
+ QString name;
+
+};
+
+#endif
diff --git a/quanta/treeviews/doctreeview.cpp b/quanta/treeviews/doctreeview.cpp
new file mode 100644
index 00000000..fd9abf65
--- /dev/null
+++ b/quanta/treeviews/doctreeview.cpp
@@ -0,0 +1,194 @@
+/***************************************************************************
+ doctreeview.cpp - description
+ -------------------
+ begin : Sat Mar 4 2000
+ copyright : (C) 2000 by Yacovlev Alexander & Dmitry Poplavsky <pdima@mail.univ.kiev.ua>
+ (C) 2002, 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. *
+ * *
+ ***************************************************************************/
+
+// QT clases
+#include <qstrlist.h>
+#include <qheader.h>
+#include <qpixmap.h>
+#include <qdir.h>
+
+// KDE clases
+#include <kconfig.h>
+#include <kapplication.h>
+#include <klocale.h>
+#include <kpopupmenu.h>
+#include <kstandarddirs.h>
+#include <kiconloader.h>
+#include <kurl.h>
+
+// application clases
+#include "doctreeview.h"
+#include "docfolder.h"
+#include "docitem.h"
+
+DocTreeView::DocTreeView(QWidget *parent, const char *name )
+ : KListView(parent,name)
+{
+
+ contextHelpDict = new QDict<QString>( 101, false );
+
+ setRootIsDecorated( true );
+ header()->hide();
+ setSorting(-1,false);
+
+ setFrameStyle( Panel | Sunken );
+ setLineWidth( 2 );
+ addColumn(i18n("Name"), -1);
+ addColumn("");
+ setFullWidth(true);
+
+ projectDocFolder = new KListViewItem(this, i18n("Project Documentation"));
+ projectDocFolder->setOpen(true);
+ slotRefreshTree();
+ setFocusPolicy(QWidget::ClickFocus);
+
+ connect(this, SIGNAL(executed(QListViewItem *)), SLOT(clickItem(QListViewItem *)) );
+ connect(this, SIGNAL(returnPressed(QListViewItem *)), SLOT(clickItem(QListViewItem *)));
+ connect(this, SIGNAL(doubleClicked(QListViewItem *)), SLOT(slotDoubleClicked(QListViewItem *)));
+
+ m_contextMenu = new KPopupMenu(this);
+ m_menuReload = m_contextMenu->insertItem(i18n("&Reload"), this, SLOT(slotReloadProjectDocs()));
+ m_contextMenu->insertItem(SmallIcon("network"), i18n("&Download Documentation..."), this, SIGNAL(downloadDoc()));
+ connect(this, SIGNAL(contextMenu(KListView*, QListViewItem*, const QPoint&)),
+ this, SLOT(slotMenu(KListView*, QListViewItem*, const QPoint&)));
+}
+
+
+DocTreeView::~DocTreeView(){
+ contextHelpDict->setAutoDelete(true);
+ delete contextHelpDict;
+}
+
+void DocTreeView::slotRefreshTree()
+{
+ for (QValueList<DocFolder *>::Iterator it = m_folderList.begin(); it != m_folderList.end(); ++it)
+ {
+ delete *it;
+ }
+ m_folderList.clear();
+ QStringList docDirs = KGlobal::instance()->dirs()->findDirs("appdata", "doc");
+
+ for ( QStringList::Iterator it = docDirs.begin(); it != docDirs.end(); ++it )
+ {
+ QString docDir = *it;
+ QDir dir(docDir, "*.docrc");
+ QStringList files = dir.entryList();
+
+ for ( QStringList::Iterator it_f = files.begin(); it_f != files.end(); ++it_f )
+ {
+ KConfig config( docDir + *it_f );
+ config.setGroup("Tree");
+
+ QString relDocDir = config.readEntry("Doc dir");
+ QString name = config.readEntry("Name").lower();
+
+ DocFolder *folder = new DocFolder(this, config.readEntry("Top Element"), &config , QDir::cleanDirPath(docDir+relDocDir)+"/");
+ folder->setPixmap( 0, SmallIcon("folder_open") );
+ folder->topLevel = true;
+ folder->setOpen(true);
+ m_folderList.append(folder);
+
+ config.setGroup("Context");
+ QStrList list;
+ config.readListEntry("ContextList", list );
+
+ for ( unsigned int i=0; i<list.count(); i++ )
+ {
+ QString keyword = list.at(i);
+ QString *url = new QString(QDir::cleanDirPath(docDir + relDocDir + "/" + config.readEntry( list.at(i) )));
+ contextHelpDict->insert( name + "|" + keyword, url );
+ }
+ }
+ }
+
+}
+
+void DocTreeView::clickItem( QListViewItem *)
+{
+ QListViewItem *it = currentItem();
+ if ( !it )
+ return;
+ DocItem *dit = dynamic_cast< DocItem *>(it);
+ if ( dit )
+ if ( ! dit->url.isEmpty() )
+ emit openURL( dit->url);
+
+ DocFolder *dfol = dynamic_cast< DocFolder *>(it);
+ if ( dfol )
+ if ( ! dfol->url.isEmpty() )
+ emit openURL( dfol->url );
+ //else
+ // emit openURL( locate("appdata","doc/documentation.html") );
+}
+
+
+QString * DocTreeView::contextHelp(const QString &keyword)
+{
+ QString word = keyword.mid(keyword.find("|"));
+ if (contextHelpDict->find(keyword))
+ return contextHelpDict->find(keyword);
+ else
+ return contextHelpDict->find(word); //to support old documentation packages
+}
+
+void DocTreeView::slotDoubleClicked(QListViewItem *item )
+{
+ if (item)
+ {
+ item->setOpen(!item->isOpen());
+ }
+}
+
+void DocTreeView::slotAddProjectDoc(const KURL& url)
+{
+ QString path = url.path();
+ int pos = path.find("/doc/");
+ path = path.mid(pos + 5);
+ new DocItem(projectDocFolder, path, url.url());
+}
+
+void DocTreeView::slotMenu(KListView *, QListViewItem *item, const QPoint &point)
+{
+ m_contextMenu->setItemVisible(m_menuReload, false);
+ if (item)
+ {
+ setSelected(item, true);
+ if (currentItem() == projectDocFolder)
+ {
+ m_contextMenu->setItemVisible(m_menuReload, true);
+ }
+ }
+ m_contextMenu->popup(point);
+}
+
+void DocTreeView::slotNewProjectLoaded(const QString &, const KURL &, const KURL &)
+{
+ slotReloadProjectDocs();
+}
+
+void DocTreeView::slotReloadProjectDocs()
+{
+ QListViewItem *child = projectDocFolder->firstChild();
+ while (child) {
+ QListViewItem *c = child;
+ child = child->nextSibling();
+ delete c;
+ }
+ emit reloadProjectDocs();
+}
+
+#include "doctreeview.moc"
diff --git a/quanta/treeviews/doctreeview.h b/quanta/treeviews/doctreeview.h
new file mode 100644
index 00000000..8061085d
--- /dev/null
+++ b/quanta/treeviews/doctreeview.h
@@ -0,0 +1,71 @@
+/***************************************************************************
+ doctreeview.h - description
+ -------------------
+ begin : Sat Mar 4 2000
+ copyright : (C) 2000 by Yacovlev Alexander & Dmitry Poplavsky <pdima@mail.univ.kiev.ua>
+ (C) 2002, 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. *
+ * *
+ ***************************************************************************/
+
+#ifndef DOCTREEVIEW_H
+#define DOCTREEVIEW_H
+
+//qt includes
+#include <qdict.h>
+#include <qvaluelist.h>
+
+//kde includes
+#include <klistview.h>
+
+class DocFolder;
+class KPopupMenu;
+
+
+/**
+ *@author Yacovlev Alexander & Dmitry Poplavsky
+ */
+
+class DocTreeView : public KListView {
+ Q_OBJECT
+public:
+ DocTreeView(QWidget *parent=0, const char *name=0);
+ ~DocTreeView();
+
+ QString *contextHelp(const QString &keyword);
+
+public slots:
+ void slotNewProjectLoaded(const QString &, const KURL &, const KURL &);
+ void slotReloadProjectDocs();
+ void slotAddProjectDoc(const KURL& url);
+ /** Re-reads the documentation directories. */
+ void slotRefreshTree();
+
+signals:
+ void openURL(const QString& );
+ void reloadProjectDocs();
+ void downloadDoc();
+
+private slots:
+ void clickItem( QListViewItem *);
+ void slotDoubleClicked(QListViewItem *);
+ void slotMenu(KListView *, QListViewItem *item, const QPoint &point);
+
+
+private:
+
+ QDict<QString> *contextHelpDict;
+ QValueList<DocFolder *> m_folderList;
+ KListViewItem *projectDocFolder;
+ KPopupMenu *m_contextMenu;
+ int m_menuReload;
+};
+
+#endif
diff --git a/quanta/treeviews/fileinfodlg.ui b/quanta/treeviews/fileinfodlg.ui
new file mode 100644
index 00000000..f2fbd5fa
--- /dev/null
+++ b/quanta/treeviews/fileinfodlg.ui
@@ -0,0 +1,94 @@
+<!DOCTYPE UI><UI version="3.1" stdsetdef="1">
+<class>FileInfoDlg</class>
+<comment>/***************************************************************************
+ * *
+ * 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; version 2 of the License. *
+ * *
+ ***************************************************************************/
+</comment>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>FileInfoDlg</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>349</width>
+ <height>266</height>
+ </rect>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>lineNum</cstring>
+ </property>
+ <property name="text">
+ <string>Number of lines:</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="1" column="0">
+ <property name="name">
+ <cstring>imageNum</cstring>
+ </property>
+ <property name="text">
+ <string>Number of images included:</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="2" column="0">
+ <property name="name">
+ <cstring>imageSize</cstring>
+ </property>
+ <property name="text">
+ <string>Size of the included images:</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="3" column="0">
+ <property name="name">
+ <cstring>totalSize</cstring>
+ </property>
+ <property name="text">
+ <string>Total file size:</string>
+ </property>
+ </widget>
+ <widget class="QListBox" row="5" column="0">
+ <property name="name">
+ <cstring>imageList</cstring>
+ </property>
+ <property name="selectionMode">
+ <enum>NoSelection</enum>
+ </property>
+ </widget>
+ <widget class="QLabel" row="4" column="0">
+ <property name="name">
+ <cstring>includedLabel</cstring>
+ </property>
+ <property name="text">
+ <string>Included images:</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="6" column="0">
+ <property name="name">
+ <cstring>fileDescLbl</cstring>
+ </property>
+ <property name="text">
+ <string>Description:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>fileDesc</cstring>
+ </property>
+ </widget>
+ <widget class="QLineEdit" row="7" column="0">
+ <property name="name">
+ <cstring>fileDesc</cstring>
+ </property>
+ </widget>
+ </grid>
+</widget>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/quanta/treeviews/filestreeview.cpp b/quanta/treeviews/filestreeview.cpp
new file mode 100644
index 00000000..be4c6a7e
--- /dev/null
+++ b/quanta/treeviews/filestreeview.cpp
@@ -0,0 +1,334 @@
+/***************************************************************************
+ filestreeview.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. *
+ * *
+ ***************************************************************************/
+
+
+// KDE includes
+#include <kdebug.h>
+#include <klocale.h>
+#include <kiconloader.h>
+#include <kinputdialog.h>
+#include <kopenwith.h>
+#include <kmessagebox.h>
+#include <kpopupmenu.h>
+#include <kfiledialog.h>
+#include <kprogress.h>
+#include <kurl.h>
+
+// app includes
+#include "filestreeview.h"
+#include "resource.h"
+#include "project.h"
+#ifdef ENABLE_CVSSERVICE
+#include "cvsservice.h"
+#endif
+#include "qextfileinfo.h"
+
+
+//FilesTreeView implementation
+
+FilesTreeView::FilesTreeView(KConfig *config, QWidget *parent, const char *name)
+ : BaseTreeView(parent, name)
+{
+ setAcceptDrops(true);
+ setDragEnabled(true);
+ setSaveOpenFolder(true);
+
+ m_config = config;
+ m_config->setGroup("General Options");
+ // I must read this here because quanta_init has not done it yet
+ qConfig.showHiddenFiles = m_config->readBoolEntry("Show Hidden Files", true);
+ qConfig.saveTrees = m_config->readBoolEntry("Save Local Trees", true);
+ QStringList topStrList = QuantaCommon::readPathListEntry(m_config, "Top folders");
+ QStringList topStrAliasList = QuantaCommon::readPathListEntry(m_config, "Top folder aliases");
+ KURL url;
+ for (uint i = 0; i < topStrList.count(); i++)
+ {
+ url = KURL();
+ QuantaCommon::setUrl(url, topStrList[i]);
+ if (!topURLList.contains(url))
+ {
+ topURLList.append(url);
+ if (i < topStrAliasList.count())
+ topURLAliases.insert(url.url(), topStrAliasList[i]);
+ else
+ topURLAliases.insert(url.url(), url.fileName());
+ }
+ }
+
+ m_config->setGroup("General Options");
+ if (m_config->readBoolEntry("Home-Root Folder On", true))
+ {
+ url = KURL();
+ url.setPath("/");
+ if (!topURLList.contains(url))
+ topURLList.append(url);
+ url = KURL();
+ url.setPath(QExtFileInfo::homeDirPath() + "/");
+ if (!topURLList.contains(url))
+ topURLList.append(url);
+ }
+
+ m_fileMenu = new KPopupMenu(this);
+
+ m_fileMenu->insertItem(SmallIcon("fileopen"), i18n("&Open"), this ,SLOT(slotOpen()));
+ m_fileMenu->insertItem(i18n("Insert &Tag"), this, SLOT(slotInsertTag()));
+ m_menuClose = m_fileMenu->insertItem(SmallIcon("fileclose"), i18n("Clos&e"), this, SLOT(slotClose()));
+ m_fileMenu->insertSeparator();
+ m_insertFileInProject = m_fileMenu->insertItem(i18n("&Insert in Project..."), this, SLOT(slotInsertInProject()));
+ m_fileMenu->insertItem(SmallIcon("editcopy"), i18n("&Copy"), this, SLOT(slotCopy()));
+ m_fileMenu->insertItem(i18n("Re&name"), this, SLOT(slotStartRename()));
+ m_fileMenu->insertItem(SmallIcon("editdelete"), i18n("&Delete"), this, SLOT(slotDelete()));
+ m_fileMenu->insertSeparator();
+ m_fileMenu->insertItem(SmallIcon("info"), i18n("&Properties"), this, SLOT(slotProperties()));
+
+ KPopupMenu *createNewMenu = new KPopupMenu(this);
+ createNewMenu->insertItem(SmallIcon("folder_new"), i18n("F&older..."), this, SLOT(slotCreateFolder()));
+ createNewMenu->insertItem(SmallIcon("document"), i18n("&File..."), this, SLOT(slotCreateFile()));
+
+ m_folderMenu = new KPopupMenu();
+
+ m_folderMenu->insertItem(SmallIcon("folder_new"), i18n("New Top &Folder..."), this, SLOT(slotNewTopFolder()));
+ m_menuTop = m_folderMenu->insertItem(i18n("&Add Folder to Top"), this, SLOT(slotAddToTop()));
+ m_folderMenu->insertItem(i18n("Create Site &Template..."), this, SLOT(slotCreateSiteTemplate()));
+ m_folderMenu->insertItem(SmallIcon("empty"), i18n("&Create New"), createNewMenu);
+ m_folderMenu->insertSeparator();
+ m_insertFolderInProject = m_folderMenu->insertItem(i18n("&Insert in Project..."), this, SLOT(slotInsertDirInProject()));
+ m_folderMenu->insertItem(SmallIcon("editcopy"), i18n("&Copy"), this, SLOT(slotCopy()));
+ m_menuPasteFolder = m_folderMenu->insertItem(SmallIcon("editpaste"), i18n("&Paste"), this, SLOT(slotPaste()));
+ m_menuChangeAlias = m_folderMenu->insertItem(i18n("&Change Alias..."), this, SLOT(slotChangeAlias()));
+ m_menuFolderRename = m_folderMenu->insertItem(i18n("Re&name"), this, SLOT(slotStartRename()));
+ m_menuDel = m_folderMenu->insertItem( SmallIcon("editdelete"), i18n("&Delete"), this, SLOT(slotDelete()));
+ m_folderMenu->insertSeparator();
+ m_folderMenu->insertItem(SmallIcon("info"), i18n("&Properties"), this, SLOT(slotProperties()));
+ m_reloadMenuId = m_folderMenu->insertItem(SmallIcon("revert"), i18n("&Reload"), this, SLOT(slotReload()));
+
+ m_emptyMenu = new KPopupMenu();
+
+ m_emptyMenu->insertItem(i18n("New Top &Folder..."), this, SLOT(slotNewTopFolder()), 0, -1 , 0);
+
+ addColumn(i18n("Files Tree"), -1);
+ addColumn("");
+
+ connect(this, SIGNAL(open(QListViewItem *)),
+ this, SLOT(slotSelectFile(QListViewItem *)));
+ connect(this, SIGNAL(contextMenu(KListView*, QListViewItem*, const QPoint&)),
+ this, SLOT(slotMenu(KListView*, QListViewItem*, const QPoint&)));
+
+ // generate top list of directories
+ for (uint i = 0; i < topURLList.count(); i++)
+ {
+ KURL url = topURLList[i];
+ newBranch(url);
+ }
+ restoreLayout(m_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);
+}
+
+FilesTreeView::~FilesTreeView()
+{
+}
+
+KFileTreeBranch* FilesTreeView::newBranch(const KURL& url)
+{
+ BaseTreeBranch* newBrnch = 0;
+ KFileItem fileItem(KFileItem::Unknown, KFileItem::Unknown, url);
+ if (url.isLocalFile() && url.path() == "/")
+ {
+ newBrnch = new BaseTreeBranch(this, url, i18n("Root Folder"), SmallIcon(fileItem.iconName()), true);
+ } else
+ {
+ if (url.isLocalFile() && url.equals(KURL(QExtFileInfo::homeDirPath() + "/"), true))
+ {
+ newBrnch = new BaseTreeBranch(this, url, i18n("Home Folder"), SmallIcon(fileItem.iconName()), true);
+ } else
+ {
+ QString s = url.fileName();
+ if (s.isEmpty())
+ s = "/";
+ if (topURLAliases.contains(url.url()))
+ s = topURLAliases[url.url()];
+ s += " [" + url.prettyURL() + "]";
+ newBrnch = new BaseTreeBranch(this, url, s, SmallIcon(fileItem.iconName()), true);
+ }
+ }
+ newBrnch->setShowingDotFiles(qConfig.showHiddenFiles);
+ addBranch(newBrnch);
+ return newBrnch;
+}
+
+
+
+/** RMB pressed, bring up the menu */
+void FilesTreeView::slotMenu(KListView* listView, QListViewItem *item, const QPoint &point)
+{
+ Q_UNUSED(listView);
+#ifdef ENABLE_CVSSERVICE
+ KURL url = currentURL();
+ if (Project::ref()->contains(url))
+ CVSService::ref()->setRepository(Project::ref()->projectBaseURL().path());
+ else
+ CVSService::ref()->setRepository(url.directory());
+ if (url.isLocalFile())
+ {
+ CVSService::ref()->setCurrentFile(url.path());
+ }
+ else
+ CVSService::ref()->setCurrentFile("");
+#endif
+ if (item)
+ {
+ bool hasProject = !m_projectName.isNull();
+ m_folderMenu->setItemVisible(m_menuChangeAlias, false);
+ m_folderMenu->setItemVisible(m_menuFolderRename, true);
+ m_folderMenu->setItemVisible(m_insertFolderInProject, hasProject);
+ m_fileMenu->setItemVisible(m_insertFileInProject, hasProject);
+ setSelected(item, true);
+ KFileTreeViewItem *curItem = currentKFileTreeViewItem();
+ if ( !curItem->isDir() )
+ {
+ m_fileMenu->setItemVisible(m_menuClose, isFileOpen(currentURL()));
+ insertOpenWithMenu(m_fileMenu, 1);
+ m_fileMenu->popup( point);
+ } else {
+ m_folderMenu->setItemVisible( m_menuDel, true );
+ m_folderMenu->setItemVisible( m_menuTop, true );
+ m_folderMenu->setItemVisible(m_menuPasteFolder, isPathInClipboard());
+ KURL url = curItem->url();
+ if ( curItem == curItem->branch()->root() )
+ {
+ m_folderMenu->setItemVisible(m_menuDel, false);
+ m_folderMenu->changeItem(m_menuTop, i18n("Remove From &Top"));
+ m_folderMenu->setItemVisible(m_menuChangeAlias, true);
+ m_folderMenu->setItemVisible(m_menuFolderRename, false);
+
+ m_config->setGroup("General Options");
+ if ((url == KURL("file:/") || url == KURL("file:" + QExtFileInfo::homeDirPath() + "/")) &&
+ m_config->readBoolEntry("Home-Root Folder On", true) )
+ m_folderMenu ->setItemVisible(m_menuTop, false);
+ m_folderMenu ->setItemVisible(m_reloadMenuId, true);
+ }
+ else
+ {
+ m_folderMenu->changeItem( m_menuTop, i18n("&Add Folder to Top"));
+ url.adjustPath(+1);
+ m_folderMenu->setItemVisible(m_menuTop, (topURLList.findIndex(url) == -1));
+ m_folderMenu->setItemVisible(m_reloadMenuId, false);
+ }
+ m_folderMenu->popup( point);
+ }
+ } else {
+ m_emptyMenu->popup( point );
+ }
+}
+
+
+
+/** Add or remove folders to/from the top list */
+void FilesTreeView::slotAddToTop()
+{
+ KFileTreeViewItem *curItem = currentKFileTreeViewItem();
+ if ( !curItem ) return;
+
+ if ( curItem->isDir() )
+ {
+ KURL url(currentURL().url());
+ url.adjustPath(+1);
+ if ( curItem != curItem->branch()->root() ) //it is not a top folder
+ { // add
+ if (topURLList.findIndex(url) == -1)
+ {
+ topURLList.append(url);
+ bool ok;
+ QString aliasName = KInputDialog::getText(i18n("Set Alias"), i18n("Alternative folder name:"), url.fileName(), &ok, this);
+ if (!ok)
+ aliasName = url.fileName();
+ topURLAliases.insert(url.url(), aliasName);
+ newBranch(url);
+ } else {
+ KMessageBox::information(this, i18n("<qt><b>%1</b> is already a toplevel entry.</qt>").arg(url.url()));
+ }
+ } else
+ { // remove
+ topURLList.remove(url);
+ topURLAliases.remove(url.url());
+ removeBranch(curItem->branch());
+ }
+ }
+}
+
+void FilesTreeView::slotNewTopFolder()
+{
+ KURL url = KFileDialog::getExistingURL(QString::null, this, i18n("Choose Local or Remote Folder"));
+ if (url.isEmpty()) return;
+ url.adjustPath(+1);
+ if (topURLList.findIndex(url) == -1)
+ {
+ bool ok;
+ QString aliasName = KInputDialog::getText(i18n("Set Alias"), i18n("Alternative folder name:"), url.fileName(), &ok, this);
+ if (!ok)
+ aliasName = url.fileName();
+ topURLAliases.insert(url.url(), aliasName);
+ newBranch(url);
+ topURLList.append(url);
+ } else {
+ KMessageBox::information(this, i18n("<qt><b>%1</b> is already a toplevel entry.</qt>").arg(url.url()));
+ }
+}
+
+
+void FilesTreeView::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());
+#endif
+}
+
+void FilesTreeView::slotChangeAlias()
+{
+ KFileTreeViewItem *curItem = currentKFileTreeViewItem();
+ if ( !curItem ) return;
+
+ if ( curItem->isDir() )
+ {
+ KURL url(currentURL().url());
+ url.adjustPath(+1);
+ if ( curItem == curItem->branch()->root() ) //it is not a top folder
+ {
+ if (topURLList.findIndex(url) != -1)
+ {
+ bool ok;
+ QString aliasName = KInputDialog::getText(i18n("Change Alias"), i18n("Alternative folder name:"), topURLAliases[url.url()], &ok, this);
+ if (ok)
+ {
+ topURLAliases.replace(url.url(), aliasName);
+ removeBranch(curItem->branch());
+ newBranch(url);
+ }
+ } else {
+ KMessageBox::information(this, i18n("<qt><b>%1</b> is already a toplevel entry.</qt>").arg(url.url()));
+ }
+ }
+ }
+}
+
+
+#include "filestreeview.moc"
diff --git a/quanta/treeviews/filestreeview.h b/quanta/treeviews/filestreeview.h
new file mode 100644
index 00000000..a77ba3de
--- /dev/null
+++ b/quanta/treeviews/filestreeview.h
@@ -0,0 +1,81 @@
+/***************************************************************************
+ filestreeview.h - 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 <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. *
+ * *
+ ***************************************************************************/
+
+#ifndef FILESTREEVIEW_H
+#define FILESTREEVIEW_H
+
+//qt includes
+#include <qmap.h>
+
+// quanta includes
+#include "basetreeview.h"
+
+//foward declarations
+class QListViewItem;
+class QPoint;
+class KPopupMenu;
+class KURL;
+
+
+class FilesTreeView : public BaseTreeView {
+ Q_OBJECT
+
+public:
+ FilesTreeView(KConfig *config, QWidget *parent, const char *name = 0L);
+ virtual ~FilesTreeView();
+ KURL::List topURLList;
+ QMap<QString, QString> topURLAliases;
+ void plugCVSMenu();
+
+protected slots:
+ /**
+ opens dialog to choose a url for a new branch
+ */
+ void slotNewTopFolder();
+
+ virtual void slotMenu(KListView *listView, QListViewItem *item, const QPoint &point);
+ /**
+ creates a new branch from the current url
+ */
+ void slotAddToTop();
+ /**
+ Changes the alias (alternative name) for a top folder
+ */
+ void slotChangeAlias();
+
+protected:
+ virtual KFileTreeBranch* newBranch(const KURL& url);
+
+ KPopupMenu *m_fileMenu;
+ KPopupMenu *m_folderMenu;
+ KPopupMenu *m_emptyMenu;
+ int m_menuClose; ///< remembers the menu entry
+ int m_menuPasteFolder; ///< remembers the menu entry
+ int m_insertFileInProject;
+ int m_insertFolderInProject;
+ // config
+ KConfig *m_config;
+
+private:
+ int m_menuTop;
+ int m_menuChangeAlias;
+ int m_menuFolderRename;
+ int m_menuDel;
+ int m_reloadMenuId;
+};
+
+#endif
diff --git a/quanta/treeviews/newtemplatedirdlg.cpp b/quanta/treeviews/newtemplatedirdlg.cpp
new file mode 100644
index 00000000..bdf6d87f
--- /dev/null
+++ b/quanta/treeviews/newtemplatedirdlg.cpp
@@ -0,0 +1,29 @@
+/***************************************************************************
+ newtemplatedirdlg.cpp - description
+ -------------------
+ begin : Fri Jun 21 2002
+ copyright : (C) 2002 by 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; version 2 of the License. *
+ * *
+ ***************************************************************************/
+
+#include <qpushbutton.h>
+#include "newtemplatedirdlg.h"
+#include "newtemplatedirdlg.moc"
+
+NewTemplateDirDlg::NewTemplateDirDlg(QWidget *parent, const char *name ) : TemplateDirForm(parent,name)
+{
+ setCaption(name);
+ connect( buttonOk, SIGNAL(clicked()), SLOT(accept()) );
+ connect( buttonCancel, SIGNAL(clicked()), SLOT(reject()) );
+}
+
+NewTemplateDirDlg::~NewTemplateDirDlg()
+{
+}
diff --git a/quanta/treeviews/newtemplatedirdlg.h b/quanta/treeviews/newtemplatedirdlg.h
new file mode 100644
index 00000000..daa6864a
--- /dev/null
+++ b/quanta/treeviews/newtemplatedirdlg.h
@@ -0,0 +1,33 @@
+/***************************************************************************
+ newtemplatedirdlg.h - description
+ -------------------
+ begin : Fri Jun 21 2002
+ copyright : (C) 2002 by 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; version 2 of the License. *
+ * *
+ ***************************************************************************/
+
+#ifndef NEWTEMPLATEDIRDLG_H
+#define NEWTEMPLATEDIRDLG_H
+
+#include <qwidget.h>
+#include <templatedirform.h>
+
+/**
+ *@author Andras Mantia
+ */
+
+class NewTemplateDirDlg : public TemplateDirForm {
+ Q_OBJECT
+public:
+ NewTemplateDirDlg(QWidget *parent=0, const char *name=0);
+ ~NewTemplateDirDlg();
+};
+
+#endif
diff --git a/quanta/treeviews/projecttreeview.cpp b/quanta/treeviews/projecttreeview.cpp
new file mode 100644
index 00000000..dc8744aa
--- /dev/null
+++ b/quanta/treeviews/projecttreeview.cpp
@@ -0,0 +1,674 @@
+/***************************************************************************
+ 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. *
+ * *
+ ***************************************************************************/
+
+// QT includes
+#include <qpainter.h>
+#include <qlabel.h>
+#include <qlineedit.h>
+#include <qdict.h>
+
+// KDE includes
+#include <klocale.h>
+#include <kiconloader.h>
+#include <kinputdialog.h>
+#include <kmessagebox.h>
+#include <kdebug.h>
+#include <kpopupmenu.h>
+#include <kpropertiesdialog.h>
+#include <ktempfile.h>
+#include <kapplication.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(QPainter *p, const QColorGroup &cg,
+ int column, int width, int align)
+{
+ QFont 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 QString& name, const QPixmap& 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(QWidget *parent, const char *name )
+ : BaseTreeView(parent,name), m_projectFiles(0)
+{
+ //setSelectionModeExt(KListView::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 KPopupMenu(this);
+ m_alwaysUploadId = m_uploadStatusMenu->insertItem(i18n("&When Modified"), this, SLOT(slotAlwaysUpload()));
+ m_neverUploadId = m_uploadStatusMenu->insertItem(i18n("&Never"), this, SLOT(slotNeverUpload()));
+ m_confirmUploadId = m_uploadStatusMenu->insertItem(i18n("&Confirm"), this, SLOT(slotConfirmUpload()));
+ connect(m_uploadStatusMenu, SIGNAL(aboutToShow()), this, SLOT(slotUploadMenuAboutToShow()));
+
+ m_fileMenu = new KPopupMenu(this);
+
+ m_fileMenu->insertItem(SmallIcon("fileopen"), i18n("&Open"), this, SLOT(slotOpen()));
+ m_openInQuantaId = m_fileMenu->insertItem(i18n("Load Toolbar"), this, SLOT(slotLoadToolbar()));
+ m_fileMenu->insertItem(i18n("Insert &Tag"), this, SLOT(slotInsertTag()));
+ m_menuClose = m_fileMenu->insertItem(SmallIcon("fileclose"), i18n("Clos&e"), this, SLOT(slotClose()));
+ m_fileMenu->insertSeparator();
+ m_fileMenu->insertItem(SmallIcon("up"), i18n("&Upload File..."), this, SLOT(slotUploadSingleURL()));
+ m_fileMenu->insertItem(SmallIcon("up"), i18n("&Quick File Upload"), this, SLOT(slotQuickUploadURL()));
+ m_fileMenu->insertItem(i18n("Re&name"), this, SLOT(slotStartRename()));
+ m_fileMenu->insertItem( i18n("&Remove From Project"), this, SLOT(slotRemoveFromProject(int)));
+ m_fileMenu->insertItem(SmallIcon("editdelete"), i18n("&Delete"), this, SLOT(slotDelete()));
+ m_fileMenu->insertSeparator();
+ m_fileMenu->insertItem(i18n("Upload &Status"), m_uploadStatusMenu);
+ m_fileMenu->insertItem(SmallIcon("info"), i18n("&Properties"), this, SLOT(slotProperties()));
+
+ KPopupMenu *createNewMenu = new KPopupMenu(this);
+ createNewMenu->insertItem(SmallIcon("folder_new"), i18n("F&older..."), this, SLOT(slotCreateFolder()));
+ createNewMenu->insertItem(SmallIcon("document"), i18n("&File..."), this, SLOT(slotCreateFile()));
+
+ m_folderMenu = new KPopupMenu(this);
+
+ m_folderMenu->insertItem(SmallIconSet("filenew"), i18n("&Create New"), createNewMenu);
+ m_folderMenu->insertSeparator();
+ m_folderMenu->insertItem(SmallIcon("up"), i18n("&Upload Folder..."), this, SLOT(slotUploadSingleURL()));
+ m_folderMenu->insertItem(SmallIcon("up"), i18n("&Quick Folder Upload"), this, SLOT(slotQuickUploadURL()));
+ m_folderMenu->insertItem(i18n("Create Site &Template..."), this, SLOT(slotCreateSiteTemplate()));
+ m_folderMenu->insertItem(i18n("Re&name"), this, SLOT(slotStartRename()));
+ m_folderMenu->insertItem(i18n("&Remove From Project"), this, SLOT(slotRemoveFromProject(int)));
+ m_folderMenu->insertItem(SmallIcon("editdelete"), i18n("&Delete"), this, SLOT(slotDelete()));
+ m_folderMenu->insertSeparator();
+ m_setDocumentRootId = m_folderMenu->insertItem(i18n("Document-&Base Folder"), this, SLOT(slotChangeDocumentFolderStatus()));
+ m_folderMenu->insertItem(i18n("Upload &Status"), m_uploadStatusMenu);
+ m_folderMenu->insertItem(SmallIcon("info"), i18n("&Properties"), this, SLOT(slotProperties()));
+
+ m_projectMenu = new KPopupMenu(this);
+ m_projectMenu->insertItem(SmallIconSet("filenew"), i18n("&Create New"), createNewMenu);
+ m_projectMenu->insertSeparator();
+ m_projectMenu->insertItem(SmallIcon("up"), i18n("&Upload Project..."), this, SLOT(slotUploadProject()));
+ m_projectMenu->insertItem(SmallIcon("reload"), i18n("Re&scan Project Folder..."), this, SLOT(slotRescan()));
+ m_projectMenu->insertItem(SmallIcon("configure"), i18n("Project &Properties"), this, SLOT(slotOptions()));
+ m_projectMenu->insertItem(SmallIcon("revert"), i18n("&Reload"), this, SLOT(slotReload()));
+ m_projectMenu->insertSeparator();
+ m_projectMenu->insertItem(i18n("Upload &Status"), m_uploadStatusMenu);
+
+
+ connect(this, SIGNAL(contextMenu(KListView*, QListViewItem*, const QPoint&)),
+ this, SLOT(slotMenu(KListView*, QListViewItem*, const QPoint&)));
+
+ connect(this, SIGNAL(open(QListViewItem *)),
+ this, SLOT(slotSelectFile(QListViewItem *)));
+
+ 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)
+{
+ QString m_projectNameStr = m_projectName+" ";
+ if (m_projectName)
+ {
+ 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, SIGNAL(populateFinished(KFileTreeViewItem*)),
+ this, SLOT(slotPopulateFinished(KFileTreeViewItem*)));
+ addBranch(m_projectDir);
+ m_projectDir->urlList = m_projectFiles; // set list for filter
+ if (m_projectName)
+ 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(KListView *listView, QListViewItem *item, const QPoint& point)
+{
+ Q_UNUSED(listView);
+ KURL url = currentURL();
+#ifdef ENABLE_CVSSERVICE
+ CVSService::ref()->setRepository(m_projectBaseURL.path());
+ if (url.isLocalFile())
+ {
+ QString 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 QString &name, const KURL &baseURL, const KURL &templateURL)
+{
+ BaseTreeView::slotNewProjectLoaded(name, baseURL, templateURL); // set m_projectName and m_projectBaseURL
+ if (!m_projectName.isNull())
+ {
+ QString 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 QStringList &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;
+ QListViewItemIterator 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;
+ QString 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;
+ QString 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)
+{
+ QListViewItem *item = currentItem();
+ if (item)
+ {
+ KURL url = currentURL();
+ QString 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
+ QString 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 QString& 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(QListViewItem* kftvi, const QString& 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"
diff --git a/quanta/treeviews/projecttreeview.h b/quanta/treeviews/projecttreeview.h
new file mode 100644
index 00000000..3bd7548d
--- /dev/null
+++ b/quanta/treeviews/projecttreeview.h
@@ -0,0 +1,176 @@
+/***************************************************************************
+ projecttreeview.h - 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. *
+ * *
+ ***************************************************************************/
+
+#ifndef PROJECTTREEVIEW_H
+#define PROJECTTREEVIEW_H
+
+//own includes
+#include "basetreeview.h"
+//#include "projecturl.h"
+
+class KIO::Job;
+class FileInfoDlg;
+class ProjectList;
+
+class ProjectTreeViewItem : public BaseTreeViewItem {
+
+public:
+ ProjectTreeViewItem( KFileTreeViewItem *parent, KFileItem* item, KFileTreeBranch *brnch );
+ /** makes document root italics */
+ void paintCell(QPainter *p, const QColorGroup &cg, int column, int width, int align);
+};
+
+class ProjectTreeBranch : public BaseTreeBranch {
+
+public:
+ ProjectTreeBranch(KFileTreeView *parent, const KURL& url,
+ const QString& name, const QPixmap& pix,
+ bool showHidden = false, KFileTreeViewItem *branchRoot = 0L);
+
+ /** check for CVS and visible*/
+ virtual KFileTreeViewItem* createTreeViewItem(KFileTreeViewItem *parent,
+ KFileItem *fileItem );
+
+ /** only files in list will be shown */
+ ProjectList *urlList;
+};
+
+
+
+class ProjectTreeView : public BaseTreeView {
+ Q_OBJECT
+
+public:
+ /**
+ * since this class is a singleton you must use this function to access it
+ *
+ * the parameters are only used at the first call to create the class
+ *
+ */
+ static ProjectTreeView* const ref(QWidget *parent = 0L, const char *name = 0L)
+ {
+ static ProjectTreeView *m_ref;
+ if (!m_ref) m_ref = new ProjectTreeView(parent, name);
+ return m_ref;
+ }
+
+ virtual ~ProjectTreeView();
+ bool isDocumentFolder(const KURL &url);
+ ProjectTreeBranch* rootBranch() {return m_projectDir;}
+ void plugCVSMenu();
+
+public slots: // Public slots
+ void slotOpen();
+ void slotLoadToolbar();
+ void slotReloadTree(ProjectList *a_fileList, bool buildNewtree, const QStringList &folderToOpen);
+ /** Sets new project information */
+ void slotNewProjectLoaded(const QString &, const KURL &, const KURL &);
+ void slotPopulateFinished(KFileTreeViewItem* );
+ /** makes the url visible in the tree */
+ void slotViewActivated(const KURL&);
+ /** fills the list with the url's of the open folder */
+ void slotGetTreeStatus(QStringList *folderToOpen)
+ {
+ m_projectDir->addOpenFolder(folderToOpen);
+ }
+
+
+
+protected slots:
+ void slotMenu(KListView *listView, QListViewItem *item, const QPoint &point);
+ void slotRenameItem(QListViewItem* kvtvi, const QString & newText, int col);
+ virtual void slotCreateFolder();
+ virtual void slotCreateFile();
+
+signals: // Signals
+ void removeFromProject( const KURL& );
+ /** No descriptions */
+ void rescanProjectDir();
+ /** No descriptions */
+ void showProjectOptions();
+ void insertToProject(const KURL&);
+ void uploadSingleURL(const KURL&, const QString&, bool, bool);
+ void loadToolbarFile(const KURL&);
+ void uploadProject();
+ void changeFileDescription(const KURL& url, const QString& desc);
+ void changeUploadStatus(const KURL& url, int status);
+ void changeDocumentFolderStatus(const KURL& url, bool status);
+ void reloadProject();
+
+private:
+ /** The constructor is privat because we use singleton patter.
+ * If you need the class use ProjectTreeView::ref() for
+ * construction and reference
+ */
+ ProjectTreeView(QWidget *parent, const char *name);
+
+ ProjectTreeBranch *m_projectDir;
+ KPopupMenu *m_fileMenu;
+ KPopupMenu *m_folderMenu;
+ KPopupMenu *m_projectMenu;
+ KURL m_documentRootURL;
+ ProjectTreeViewItem *m_documentRootItem;
+ KURL::List m_documentFolderList;
+ KPopupMenu *m_uploadStatusMenu;
+ ProjectList *m_projectFiles;
+ int m_menuClose; ///< remembers the menu entry
+
+ int m_openInQuantaId; ///< remembers the menu entry
+ int m_setDocumentRootId;
+ int m_alwaysUploadId;
+ int m_neverUploadId;
+ int m_confirmUploadId;
+
+protected:
+ /**
+ creates a branch and adds this branch to the treeview
+ @param url the root of the branch
+ @return the new branch
+ */
+ virtual KFileTreeBranch* newBranch(const KURL& url);
+ /**
+ called when the description of an item was changed,
+ @param item the treeview item
+ @param newDesc the new description of item
+ */
+ void itemDescChanged(KFileTreeViewItem* item, const QString& newDesc);
+ /**
+ adds the Quanta fileinfopage to the properties dialog
+ overwritten to enable the file description
+ @param propDlg the dialog where to add the page
+ @return pointer to to just added page
+ */
+ virtual FileInfoDlg* addFileInfoPage(KPropertiesDialog *propDlg);
+
+private slots: // Private slots
+ /** No descriptions */
+ void slotUploadProject();
+ /** Bring up the project options dialog */
+ void slotOptions();
+ /** No descriptions */
+ void slotRescan();
+ void slotRemoveFromProject(int askForRemove = 1);
+ void slotUploadSingleURL();
+ void slotQuickUploadURL();
+ void slotAlwaysUpload();
+ void slotNeverUpload();
+ void slotConfirmUpload();
+ void slotUploadMenuAboutToShow();
+ void slotChangeDocumentFolderStatus();
+};
+
+#endif
diff --git a/quanta/treeviews/quantapropertiespage.ui b/quanta/treeviews/quantapropertiespage.ui
new file mode 100644
index 00000000..5c7a9096
--- /dev/null
+++ b/quanta/treeviews/quantapropertiespage.ui
@@ -0,0 +1,247 @@
+<!DOCTYPE UI><UI version="3.2" stdsetdef="1">
+<class>QuantaPropertiesPage</class>
+<comment>/***************************************************************************
+ * *
+ * 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; version 2 of the License. *
+ * *
+ ***************************************************************************/
+</comment>
+<author>(C) 2002 Andras Mantia &lt;amantia@kde.org&gt;</author>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>QuantaPropertiesPage</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>343</width>
+ <height>443</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>300</width>
+ <height>400</height>
+ </size>
+ </property>
+ <property name="caption">
+ <string>Quanta Properties</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QWidgetStack" row="0" column="0">
+ <property name="name">
+ <cstring>typeStack</cstring>
+ </property>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>WStackPage</cstring>
+ </property>
+ <attribute name="id">
+ <number>0</number>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QCheckBox" row="1" column="0" rowspan="1" colspan="4">
+ <property name="name">
+ <cstring>parentAttr</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Inherit type from parent (nothing)</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>TextLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Type:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>typesCombo</cstring>
+ </property>
+ </widget>
+ <spacer row="0" column="3">
+ <property name="name">
+ <cstring>Spacer2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>92</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="KComboBox" row="0" column="2">
+ <property name="name">
+ <cstring>typesCombo</cstring>
+ </property>
+ </widget>
+ <widget class="QButtonGroup" row="2" column="0" rowspan="1" colspan="4">
+ <property name="name">
+ <cstring>prePostGroup</cstring>
+ </property>
+ <property name="title">
+ <string></string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QCheckBox" row="0" column="0">
+ <property name="name">
+ <cstring>usePrePostText</cstring>
+ </property>
+ <property name="text">
+ <string>Use &amp;pre/post text</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="1" column="0">
+ <property name="name">
+ <cstring>TextLabel1_2</cstring>
+ </property>
+ <property name="text">
+ <string>Pre-text:</string>
+ </property>
+ </widget>
+ <widget class="QTextEdit" row="2" column="0">
+ <property name="name">
+ <cstring>preTextEdit</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ </widget>
+ <widget class="QLabel" row="3" column="0">
+ <property name="name">
+ <cstring>TextLabel2</cstring>
+ </property>
+ <property name="text">
+ <string>Post-text:</string>
+ </property>
+ </widget>
+ <widget class="QTextEdit" row="4" column="0">
+ <property name="name">
+ <cstring>postTextEdit</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <spacer row="0" column="1">
+ <property name="name">
+ <cstring>Spacer1</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>93</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </grid>
+ </widget>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>WStackPage</cstring>
+ </property>
+ <attribute name="id">
+ <number>1</number>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>filteringLabel</cstring>
+ </property>
+ <property name="text">
+ <string>Filtering &amp;action:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>actionCombo</cstring>
+ </property>
+ </widget>
+ <widget class="KComboBox" row="0" column="1">
+ <property name="name">
+ <cstring>actionCombo</cstring>
+ </property>
+ </widget>
+ <spacer row="1" column="1">
+ <property name="name">
+ <cstring>spacer3</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </grid>
+ </widget>
+ </widget>
+ </grid>
+</widget>
+<connections>
+ <connection>
+ <sender>parentAttr</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>typesCombo</receiver>
+ <slot>setDisabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>usePrePostText</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>preTextEdit</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>usePrePostText</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>postTextEdit</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+</connections>
+<tabstops>
+ <tabstop>typesCombo</tabstop>
+ <tabstop>parentAttr</tabstop>
+</tabstops>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/quanta/treeviews/scripttreeview.cpp b/quanta/treeviews/scripttreeview.cpp
new file mode 100644
index 00000000..191be51c
--- /dev/null
+++ b/quanta/treeviews/scripttreeview.cpp
@@ -0,0 +1,425 @@
+/***************************************************************************
+ scripttreeview.cpp - description
+ -------------------
+ begin : Thu Sep 16 2003
+ copyright : (C) 2003-2004 by 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; version 2 of the License. *
+ * *
+ ***************************************************************************/
+//kde includes
+#include <kapplication.h>
+#include <kiconloader.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kpopupmenu.h>
+#include <kprocess.h>
+#include <krun.h>
+#include <kstandarddirs.h>
+#include <ktar.h>
+#include <ktempdir.h>
+#include <ktempfile.h>
+#include <kurl.h>
+#include <kdebug.h>
+
+//qt includes
+#include <qdir.h>
+#include <qdom.h>
+#include <qfile.h>
+#include <qfileinfo.h>
+#include <qlabel.h>
+#include <qlineedit.h>
+#include <qregexp.h>
+#include <qstringlist.h>
+#include <qtextedit.h>
+
+//other includes
+#include <libxml/xmlmemory.h>
+#include <libxml/debugXML.h>
+#include <libxml/HTMLtree.h>
+#include <libxml/xmlIO.h>
+#include <libxml/DOCBparser.h>
+#include <libxml/xinclude.h>
+#include <libxml/catalog.h>
+#include <libxslt/xslt.h>
+#include <libxslt/xsltInternals.h>
+#include <libxslt/transform.h>
+#include <libxslt/xsltutils.h>
+
+//app includes
+#include "scripttreeview.h"
+#include "resource.h"
+#include "quantacommon.h"
+#include "tagmaildlg.h"
+
+extern int xmlLoadExtDtdDefaultValue;
+
+ScriptTreeView::ScriptTreeView(QWidget *parent, const char *name )
+ : BaseTreeView(parent,name)
+{
+ setSaveOpenFolder(true);
+ addColumn(i18n("Scripts"), -1);
+ addColumn("");
+
+ KURL url;
+ url.setPath(qConfig.globalDataDir + resourceDir + "scripts/");
+
+ BaseTreeBranch *m_globalDir;
+ m_globalDir = new BaseTreeBranch(this, url, i18n("Global Scripts"), SmallIcon("run"), true);
+ addBranch(m_globalDir);
+
+ url.setPath(locateLocal("data", resourceDir + "scripts/"));
+
+ BaseTreeBranch *m_localDir;
+ m_localDir = new BaseTreeBranch(this, url, i18n("Local Scripts"), SmallIcon("run"), true);
+ addBranch(m_localDir);
+
+ // here you define which files should not be visible for the users
+ const QString excludeString = ".*\\.info$|.*\\.css$|.*\\.xsl$";
+ m_globalDir->excludeFilterRx.setPattern(excludeString);
+ m_localDir->excludeFilterRx.setPattern(excludeString);
+
+ m_fileMenu = new KPopupMenu(this);
+ m_fileMenu->insertItem(SmallIcon("info"), i18n("&Description"), this, SLOT(slotProperties()));
+ m_fileMenu->insertItem(SmallIcon("run"), i18n("&Run Script"), this, SLOT(slotRun()));
+ m_fileMenu->insertSeparator();
+ m_fileMenu->insertItem(i18n("&Edit Script"), this, SLOT(slotEditScript()));
+ m_fileMenu->insertItem(i18n("Edit in &Quanta"), this, SLOT(slotEditInQuanta()));
+ m_fileMenu->insertItem(i18n("Edi&t Description"), this, SLOT(slotEditDescription()));
+ m_fileMenu->insertSeparator();
+ m_fileMenu->insertItem(UserIcon("ball"), i18n("&Assign Action"), this, SLOT(slotAssignAction()));
+ m_fileMenu->insertItem(SmallIcon("mail_send"), i18n("&Send in Email..."), this, SLOT(slotSendScriptInMail()));
+ m_fileMenu->insertItem(SmallIcon("network"), i18n("&Upload Script..."), this, SLOT(slotUploadScript()));
+
+ m_folderMenu = new KPopupMenu(this);
+ m_downloadMenuId = m_folderMenu->insertItem(SmallIcon("network"), i18n("&Download Script..."), this, SIGNAL(downloadScript()));
+
+
+ connect(this, SIGNAL(contextMenu(KListView*, QListViewItem*, const QPoint&)),
+ this, SLOT(slotMenu(KListView*, QListViewItem*, const QPoint&)));
+
+ 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);
+}
+
+ScriptTreeView::~ScriptTreeView()
+{
+}
+
+void ScriptTreeView::slotMenu(KListView *, QListViewItem *item, const QPoint &point)
+{
+ if (!item)
+ {
+ m_folderMenu->setItemVisible(m_downloadMenuId, true);
+ m_folderMenu->popup(point);
+ return;
+ }
+ setSelected(item, true);
+
+ KFileTreeViewItem *curItem = currentKFileTreeViewItem();
+ if (!curItem->isDir())
+ {
+ m_fileMenu->popup(point);
+ } else
+ {
+ if (curItem == curItem->branch()->root())
+ {
+ m_folderMenu->setItemVisible(m_downloadMenuId, true);
+ } else
+ {
+ m_folderMenu->setItemVisible(m_downloadMenuId, false);
+ }
+ m_folderMenu->popup(point);
+ }
+}
+
+void ScriptTreeView::slotSelectFile(QListViewItem *item)
+{
+ if (item) {
+ if ( !currentKFileTreeViewItem()->isDir() )
+ {
+ KURL urlToOpen = infoFile(currentURL(), true);
+ emit openFileInPreview(urlToOpen);
+ }
+ }
+}
+
+void ScriptTreeView::slotEditDescription()
+{
+ if ( !currentKFileTreeViewItem()->isDir() )
+ {
+ KURL urlToOpen = infoFile(currentURL());
+ emit showPreviewWidget(false);
+ emit openFile(urlToOpen);
+ }
+}
+
+void ScriptTreeView::slotEditScript()
+{
+ if ( !currentKFileTreeViewItem()->isDir() )
+ {
+ emit showPreviewWidget(false);
+ KURL urlToOpen = currentURL();
+ KURL infoUrl = infoFile(urlToOpen);
+ QString editApp = infoOptionValue(infoUrl, "editor");
+ if (editApp.isEmpty())
+ emit openFile(urlToOpen);
+ else
+ {
+ KProcess *proc = new KProcess();
+ *proc << editApp << urlToOpen.path();
+ proc->start(KProcess::DontCare);
+ }
+ }
+}
+
+
+void ScriptTreeView::slotRun()
+{
+ if ( !currentKFileTreeViewItem()->isDir() )
+ {
+ KURL urlToOpen = currentURL();
+ KURL infoUrl = infoFile(urlToOpen);
+ QString execApp = infoOptionValue(infoUrl, "interpreter");
+ if (execApp.isEmpty())
+ {
+ KURL::List list;
+ list.append(urlToOpen);
+ KRun::displayOpenWithDialog(list);
+ }
+ else
+ {
+ KProcess *proc = new KProcess();
+ QStringList argsList = QStringList::split(' ', execApp);
+ *proc << argsList;
+ *proc << urlToOpen.path();
+ proc->start(KProcess::DontCare);
+ }
+ }
+}
+
+
+void ScriptTreeView::slotEditInQuanta()
+{
+ if ( !currentKFileTreeViewItem()->isDir() )
+ {
+ KURL urlToOpen = currentURL();
+ emit showPreviewWidget(false);
+ emit openFile(urlToOpen);
+ }
+}
+
+void ScriptTreeView::slotAssignAction()
+{
+ if ( !currentKFileTreeViewItem()->isDir() )
+ {
+ KURL url = currentURL();
+ KURL infoURL = infoFile(url);
+ QString execApp = infoOptionValue(infoURL, "interpreter");
+ if (execApp.isEmpty())
+ execApp = "sh";
+ url.setPath(url.path().replace(locateLocal("data", resourceDir + "scripts/"), "%scriptdir/"));
+ url.setPath(url.path().replace(qConfig.globalDataDir + resourceDir + "scripts/", "%scriptdir/"));
+ emit assignActionToScript(url, execApp);
+ }
+}
+
+QString ScriptTreeView::createScriptTarball()
+{
+ KURL url = currentURL();
+ KURL infoURL = infoFile(url);
+
+ KTempDir* tempDir = new KTempDir(tmpDir);
+ tempDir->setAutoDelete(true);
+ tempDirList.append(tempDir);
+ QString tempFileName=tempDir->name() + url.fileName() + ".tgz";
+
+ //pack the .tag files and the description.rc into a .tgz file
+ KTar tar(tempFileName, "application/x-gzip");
+ tar.open(IO_WriteOnly);
+
+ KURL::List files;
+ files.append(url);
+ files.append(infoURL);
+ files.append(KURL().fromPathOrURL(qConfig.globalDataDir + resourceDir + "scripts/info.xsl"));
+ for ( KURL::List::Iterator it_f = files.begin(); it_f != files.end(); ++it_f )
+ {
+ QFile file((*it_f).path());
+ file.open(IO_ReadOnly);
+ QByteArray bArray = file.readAll();
+ tar.writeFile((*it_f).fileName(), "user", "group", bArray.size(), bArray.data());
+ file.close();
+ }
+ tar.close();
+
+ return tempFileName;
+}
+
+void ScriptTreeView::slotSendScriptInMail()
+{
+ if ( !currentKFileTreeViewItem()->isDir() )
+ {
+
+ QStringList attachmentFile;
+ attachmentFile += createScriptTarball();
+
+ TagMailDlg *mailDlg = new TagMailDlg( this, i18n("Send script in email"));
+ QString toStr;
+ QString message = i18n("Hi,\n This is a Quanta Plus [http://quanta.kdewebdev.org] script tarball.\n\nHave fun.\n");
+ QString titleStr;
+ QString subjectStr;
+
+ mailDlg->TitleLabel->setText(i18n("Content:"));
+/* mailDlg->titleEdit->setFixedHeight(60);
+ mailDlg->titleEdit->setVScrollBarMode(QTextEdit::Auto);
+ mailDlg->titleEdit->setHScrollBarMode(QTextEdit::Auto);*/
+ if ( mailDlg->exec() )
+ {
+ if ( !mailDlg->lineEmail->text().isEmpty())
+ {
+ toStr = mailDlg->lineEmail->text();
+ subjectStr = (mailDlg->lineSubject->text().isEmpty())?i18n("Quanta Plus Script"):mailDlg->lineSubject->text();
+ if ( !mailDlg->titleEdit->text().isEmpty())
+ message = mailDlg->titleEdit->text();
+ } else
+ {
+ KMessageBox::error(this,i18n("No destination address was specified.\n Sending is aborted."),i18n("Error Sending Email"));
+ delete mailDlg;
+ return;
+ }
+ kapp->invokeMailer(toStr, QString::null, QString::null, subjectStr, message, QString::null, attachmentFile);
+ }
+ delete mailDlg;
+
+ }
+}
+
+void ScriptTreeView::slotUploadScript()
+{
+ if ( !currentKFileTreeViewItem()->isDir() )
+ {
+ QString fileName = createScriptTarball();
+ emit uploadScript(fileName);
+ }
+}
+
+KURL ScriptTreeView::infoFile(const KURL& url, bool htmlVersion)
+{
+ KURL returnUrl = url;
+ QString fileName = returnUrl.fileName();
+ //fileName.truncate(fileName.length() - QFileInfo(fileName).extension().length() - 1);
+ fileName.append(".info");
+ returnUrl.setFileName(fileName);
+ if (!QFileInfo(returnUrl.path()).exists())
+ {
+ QFile f(returnUrl.path());
+ if (f.open(IO_WriteOnly))
+ {
+ QTextStream str(&f);
+ str.setEncoding(QTextStream::UnicodeUTF8);
+ str << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << endl;
+ str << "<?xml-stylesheet type=\"text/xsl\" href=\"info.xsl\" ?>" << endl;
+ str << "<!DOCTYPE QuantaScriptInfo>" << endl;
+ str << "<INFO>" << endl;
+ str << " <options editor=\"\" interpreter=\"\" />" << endl;
+ str << " <name>" << url.fileName() << "</name>" << endl;
+ str << " <author></author>" << endl;
+ str << " <email></email>" << endl;
+ str << " <website></website>" << endl;
+ str << " <version></version>" << endl;
+ str << " <license></license>" << endl;
+ str << " <about></about>" << endl;
+ str << "</INFO>" << endl;
+ f.close();
+ }
+ }
+
+ if (htmlVersion)
+ {
+ KTempFile *tempInfoFile = 0L;
+ if (!QFileInfo(returnUrl.path()).exists())
+ {
+ tempInfoFile = new KTempFile(tmpDir);
+ tempInfoFile->setAutoDelete(true);
+ returnUrl = KURL::fromPathOrURL(tempInfoFile->name());
+ QTextStream str(tempInfoFile->file());
+ str.setEncoding(QTextStream::UnicodeUTF8);
+ str << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << endl;
+ str << "<?xml-stylesheet type=\"text/xsl\" href=\"info.xsl\" ?>" << endl;
+ str << "<!DOCTYPE QuantaScriptInfo>" << endl;
+ str << "<INFO>" << endl;
+ str << " <options editor=\"\" interpreter=\"\" />" << endl;
+ str << " <name>" << url.fileName() << "</name>" << endl;
+ str << " <author></author>" << endl;
+ str << " <email></email>" << endl;
+ str << " <website></website>" << endl;
+ str << " <version></version>" << endl;
+ str << " <license></license>" << endl;
+ str << " <about></about>" << endl;
+ str << "</INFO>" << endl;
+ tempInfoFile->close();
+ tempFileList.append(tempInfoFile);
+ }
+ KTempFile *tempFile = new KTempFile(tmpDir);
+ tempFile->setAutoDelete(true);
+ //apply the stylesheet
+ xsltStylesheetPtr cur = NULL;
+ xmlDocPtr doc, res;
+ xmlSubstituteEntitiesDefault(1);
+ xmlLoadExtDtdDefaultValue = 1;
+ QString xslFile = qConfig.globalDataDir + resourceDir + "scripts/info.xsl";
+ cur = xsltParseStylesheetFile(xmlCharStrndup(xslFile.utf8(), xslFile.utf8().length()));
+ doc = xmlParseFile(returnUrl.path().utf8());
+ res = xsltApplyStylesheet(cur, doc, 0);
+ xsltSaveResultToFile(tempFile->fstream(), res, cur);
+
+ xsltFreeStylesheet(cur);
+ xmlFreeDoc(res);
+ xmlFreeDoc(doc);
+
+ xsltCleanupGlobals();
+ xmlCleanupParser();
+ tempFile->close();
+
+ tempFileList.append(tempFile);
+ return KURL().fromPathOrURL(tempFile->name());
+ } else
+ return returnUrl;
+}
+
+QString ScriptTreeView::infoOptionValue(const KURL& infoURL, const QString& optionName)
+{
+ QString value;
+ QFile f(infoURL.path());
+ if (f.open(IO_ReadOnly))
+ {
+ QDomDocument doc;
+ doc.setContent(&f);
+ f.close();
+ QDomNodeList nodes = doc.elementsByTagName("options");
+ if (nodes.count() > 0)
+ {
+ QDomElement el = nodes.item(0).toElement();
+ value = el.attribute(optionName);
+ }
+ }
+ return value;
+}
+
+
+void ScriptTreeView::slotProperties()
+{
+ KFileTreeViewItem *item = currentKFileTreeViewItem();
+ if (item)
+ slotSelectFile(item);
+}
+
+
+#include "scripttreeview.moc"
diff --git a/quanta/treeviews/scripttreeview.h b/quanta/treeviews/scripttreeview.h
new file mode 100644
index 00000000..7cf2b145
--- /dev/null
+++ b/quanta/treeviews/scripttreeview.h
@@ -0,0 +1,220 @@
+/***************************************************************************
+ scripttreeview.h - description
+ -------------------
+ begin : Thu Sep 16 2003
+ copyright : (C) 2003-2004 by 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; version 2 of the License. *
+ * *
+ ***************************************************************************/
+#ifndef SCRIPTTREEVIEW_H
+#define SCRIPTTREEVIEW_H
+
+//own includes
+#include "basetreeview.h"
+
+/**
+ * @short treeview with all in Quanta available scripts.
+ *
+ * You can manage and excecute scripts from here.
+ *
+ * There are local and global scripts in different branches.
+ *
+ * For every script should exist an .info file!
+ *
+ * The .info file is an xhtml file with the extention .info and
+ * must be in one folder together with the script.
+ *
+ * Inside of your .info file should be an options tag like this
+ * example:
+ *
+ * <options editor="kmdr-editor" interpreter="kmdr-executor" />
+ *
+ * Here is defined which program is used for editing and executing the script.
+ *
+ * @author Andras Mantia <amantia@kde.org>
+ */
+class ScriptTreeView : public BaseTreeView {
+ Q_OBJECT
+
+
+public:
+ ScriptTreeView(QWidget *parent, const char *name = 0L);
+ ~ScriptTreeView();
+
+protected slots:
+
+ /**
+ * displays the RBM
+ *
+ *
+ * @param listView KListView where the event comes from
+ *
+ * @param item QListViewItem where the mousepointer is hovering
+ *
+ * @param point QPoint coordinates of the event
+ *
+ */
+ virtual void slotMenu(KListView *listView, QListViewItem *item, const QPoint &point);
+
+ /**
+ * slot of QListView
+ *
+ * shows the .info file for the script
+ *
+ * @param item the selected QListViewItem
+ */
+ virtual void slotSelectFile(QListViewItem *item);
+
+ /**
+ * slot for the RBM
+ *
+ * invokes the editor for a script
+ */
+ void slotEditScript();
+
+ /**
+ * slot for the RBM
+ *
+ * opens the script in Quanta
+ *
+ * if @ref infoOptionValue can not find the definition of the editor
+ * in the .info file the script will be opened in Quanta
+ */
+ void slotEditInQuanta();
+
+ /**
+ * slot for the RBM
+ *
+ * opens the .info file of the script in Quanta
+ */
+ void slotEditDescription();
+
+ /**
+ * slot for the RBM
+ *
+ * excecutes the script
+ *
+ * If @ref infoOptionValue can not find the definition of the interpreter
+ * in the .info file you will get a open-with dialog to choose a program.
+ */
+ void slotRun();
+
+ /**
+ * slot for the RBM
+ *
+ * opens an dialog to assign an action to this script
+ */
+ void slotAssignAction();
+
+ /**
+ * slot for the RBM
+ *
+ * packs and sends the script as attachment to an email
+ */
+ void slotSendScriptInMail();
+
+ /**
+ * slot for the RBM
+ *
+ * packs and uploads the script to the main server
+ */
+ void slotUploadScript();
+
+ /**
+ * slot for the RBM
+ *
+ * shows .info file for the script
+ *
+ * calls @ref slotSelectFile
+ */
+ void slotProperties();
+
+protected:
+
+ /**
+ * don't need this in the class but it is abstract in the base class
+ * so I need to implement it
+ */
+ virtual KFileTreeBranch* newBranch(const KURL& url)
+ {
+ Q_UNUSED(url)
+ return 0l;
+ };
+
+signals:
+
+ /**
+ * emited from @ref slotSelectFile to display the .info file
+ */
+ void openFileInPreview(const KURL&);
+
+ /**
+ * emited from @ref slotAssignAction to open the assignment dialog
+ */
+ void assignActionToScript(const KURL&, const QString&);
+
+ /**
+ * emited to make the script describtion visible
+ */
+ void showPreviewWidget(bool);
+
+ /**
+ * emitted to request downloading of a script from the main server
+ */
+ void downloadScript();
+
+ /**
+ * request to upload the @ref fileName script tarball
+ */
+ void uploadScript(const QString& fileName);
+
+private:
+ /**
+ * make the default constructor private to force the use of the other one
+ */
+ ScriptTreeView() { };
+
+ /**
+ * creates the URL of the .info file
+ *
+ * @param url URL of the script file
+ * @param htmlVersion if true returns the HTML version of the file
+ *
+ * @return URL of the matching .info file (no check is done if the file exists)
+ */
+ KURL infoFile(const KURL& url, bool htmlVersion = false);
+
+ /**
+ * query options from the .info file
+ *
+ * inside of your .info file only the first options tag is located
+ *
+ * @param infoURL URL of the .info file
+ *
+ * @param optionName name of the option you want to query
+ *
+ * @return the value of the option
+ */
+ QString infoOptionValue(const KURL& infoURL, const QString& optionName);
+
+ /** Create a script tarball which can be uploaded or sent in email. Returns
+ * the name of the created file or QString::null if creation has failed.
+ */
+ QString createScriptTarball();
+
+ /**
+ * remember the menu for manipulation
+ */
+ KPopupMenu *m_fileMenu;
+ KPopupMenu *m_folderMenu;
+
+ int m_downloadMenuId;
+};
+
+#endif
diff --git a/quanta/treeviews/servertreeview.cpp b/quanta/treeviews/servertreeview.cpp
new file mode 100644
index 00000000..024e31d5
--- /dev/null
+++ b/quanta/treeviews/servertreeview.cpp
@@ -0,0 +1,195 @@
+/***************************************************************************
+ filestreeview.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 <qpainter.h>
+
+// KDE includes
+#include <kdebug.h>
+#include <klocale.h>
+#include <kiconloader.h>
+#include <kopenwith.h>
+#include <kmessagebox.h>
+#include <kpopupmenu.h>
+#include <kfiledialog.h>
+#include <kprogress.h>
+#include <kurl.h>
+
+// app includes
+#include "servertreeview.h"
+#include "resource.h"
+#include "project.h"
+#include "qextfileinfo.h"
+
+
+ServerTreeViewItem::ServerTreeViewItem( KFileTreeViewItem *parent, KFileItem* item, KFileTreeBranch *brnch )
+: BaseTreeViewItem( parent, item, brnch)
+{
+}
+
+void ServerTreeViewItem::paintCell(QPainter *p, const QColorGroup &cg,
+ int column, int width, int align)
+{
+ QColorGroup _cg( cg );
+ KURL baseURL = Project::ref()->projectBaseURL();
+ KURL relURL = baseURL;
+ relURL.setPath(QExtFileInfo::toRelative(url(), branch()->url()).path());
+ KURL url = QExtFileInfo::toAbsolute(relURL, baseURL);
+ if ( !Project::ref()->contains(url) )
+ {
+ QFont f = p->font();
+ f.setItalic(true);
+ p->setFont(f);
+ int h, s, v;
+ p->pen().color().getHsv(&h, &s, &v);
+ v = (v < 155 ? v + 100 : 255);
+ _cg.setColor(QColorGroup::Text, QColor(h, s, v, QColor::Hsv));
+ };
+ BaseTreeViewItem::paintCell( p, _cg, column, width, align );
+}
+
+//ServerTreeBranch implementation
+ServerTreeBranch::ServerTreeBranch(KFileTreeView *parent, const KURL& url,
+ const QString& name, const QPixmap& pix,
+ bool showHidden, KFileTreeViewItem *branchRoot)
+ : BaseTreeBranch(parent, url, name, pix, showHidden, branchRoot)
+{
+}
+
+KFileTreeViewItem* ServerTreeBranch::createTreeViewItem(KFileTreeViewItem *parent, KFileItem *fileItem )
+{
+ BaseTreeViewItem *tvi = 0;
+ if( parent && fileItem )
+ {
+ tvi = new ServerTreeViewItem( parent, fileItem, this );
+ }
+ else
+ kdDebug(24000) << "ServerTreeBranch::createTreeViewItem: Have no parent" << endl;
+ return tvi;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////
+//
+// ServerTreeView implementation
+//
+//
+ServerTreeView::ServerTreeView(KConfig *config, QWidget *parent, const KURL &url, const char *name)
+ : BaseTreeView(parent, name)
+{
+ setAcceptDrops(true);
+ setDragEnabled(true);
+
+ m_config = config;
+ m_config->setGroup("General Options");
+ // I must read this here because quanta_init has not done it yet
+ qConfig.showHiddenFiles = m_config->readBoolEntry("Show Hidden Files", true);
+
+ m_fileMenu = new KPopupMenu();
+
+ m_fileMenu->insertItem(SmallIcon("fileopen"), i18n("&Open"), this ,SLOT(slotOpen()));
+ m_fileMenu->insertItem(i18n("Open &With..."), this, SLOT(slotOpenWith()));
+ m_menuClose = m_fileMenu->insertItem(SmallIcon("fileclose"), i18n("Clos&e"), this, SLOT(slotClose()));
+ m_fileMenu->insertSeparator();
+// m_insertFileInProject = m_fileMenu->insertItem(i18n("&Insert in Project..."), this, SLOT(slotInsertInProject()));
+ m_fileMenu->insertItem(SmallIcon("editcopy"), i18n("&Copy"), this, SLOT(slotCopy()));
+ m_fileMenu->insertItem(SmallIcon("editdelete"), i18n("&Delete"), this, SLOT(slotDelete()));
+ m_fileMenu->insertItem(i18n("Re&name"), this, SLOT(slotStartRename()));
+ m_fileMenu->insertSeparator();
+ m_fileMenu->insertItem(SmallIcon("info"), i18n("&Properties"), this, SLOT(slotProperties()));
+
+ m_folderMenu = new KPopupMenu();
+
+// m_insertFolderInProject = m_folderMenu->insertItem(i18n("&Insert in Project..."), this, SLOT(slotInsertDirInProject()));
+ m_folderMenu->insertItem(SmallIcon("editcopy"), i18n("&Copy"), this, SLOT(slotCopy()));
+ m_menuPasteFolder = m_folderMenu->insertItem(SmallIcon("editpaste"), i18n("&Paste"), this, SLOT(slotPaste()));
+ m_menuDel = m_folderMenu->insertItem( SmallIcon("editdelete"), i18n("&Delete"), this, SLOT(slotDelete()));
+ m_renameId = m_folderMenu->insertItem(i18n("Re&name"), this, SLOT(slotStartRename()));
+ m_folderMenu->insertSeparator();
+ m_folderMenu->insertItem(SmallIcon("info"), i18n("&Properties"), this, SLOT(slotProperties()));
+ m_reloadMenuId = m_folderMenu->insertItem(SmallIcon("revert"), i18n("&Reload"), this, SLOT(slotReload()));
+
+ addColumn(i18n("Upload Tree"), -1);
+ addColumn("");
+
+ connect(this, SIGNAL(open(QListViewItem *)),
+ this, SLOT(slotSelectFile(QListViewItem *)));
+ connect(this, SIGNAL(contextMenu(KListView*, QListViewItem*, const QPoint&)),
+ this, SLOT(slotMenu(KListView*, QListViewItem*, const QPoint&)));
+ connect(Project::ref(), SIGNAL(reloadTree(ProjectList *, bool, const QStringList &)),
+ this, SLOT(slotReloadTree(ProjectList *, bool, const QStringList &)));
+
+ restoreLayout(m_config, "UploadTreeView"); // a fixed name only for the tooltip configuration
+ // 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);
+ newBranch(url);
+}
+
+ServerTreeView::~ServerTreeView()
+{
+}
+
+KFileTreeBranch* ServerTreeView::newBranch(const KURL& url)
+{
+ KURL branchURL = url;
+ branchURL.adjustPath(+1);
+ BaseTreeBranch* newBrnch = 0;
+ newBrnch = new ServerTreeBranch(this, branchURL, branchURL.prettyURL(), SmallIcon("up"), true);
+ newBrnch->setShowingDotFiles(qConfig.showHiddenFiles);
+ addBranch(newBrnch);
+ return newBrnch;
+}
+
+
+/** RMB pressed, bring up the menu */
+void ServerTreeView::slotMenu(KListView* listView, QListViewItem *item, const QPoint &point)
+{
+ Q_UNUSED(listView);
+ if (item)
+ {
+ setSelected(item, true);
+ KFileTreeViewItem *curItem = currentKFileTreeViewItem();
+ if ( !curItem->isDir() )
+ {
+ m_fileMenu->setItemVisible(m_menuClose, isFileOpen(currentURL()));
+ m_fileMenu->popup(point);
+ } else {
+ m_folderMenu->setItemVisible(m_menuPasteFolder, isPathInClipboard());
+ bool root = (curItem == curItem->branch()->root());
+ m_folderMenu->setItemVisible(m_menuDel, ! root);
+ m_folderMenu->setItemVisible(m_reloadMenuId, root);
+ m_folderMenu->setItemVisible(m_renameId, ! root);
+ m_folderMenu->popup(point);
+ }
+ }
+}
+
+
+void ServerTreeView::slotReloadTree( ProjectList *fileList, bool buildNewTree, const QStringList &folderToOpen)
+{
+ Q_UNUSED(fileList);
+ Q_UNUSED(buildNewTree);
+ Q_UNUSED(folderToOpen);
+
+ QListViewItemIterator iter(this);
+ for ( ; iter.current(); ++iter )
+ {
+ iter.current()->repaint();
+ }
+}
+
+#include "servertreeview.moc"
diff --git a/quanta/treeviews/servertreeview.h b/quanta/treeviews/servertreeview.h
new file mode 100644
index 00000000..c49b5a60
--- /dev/null
+++ b/quanta/treeviews/servertreeview.h
@@ -0,0 +1,92 @@
+/***************************************************************************
+ servertreeview.h - 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 <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. *
+ * *
+ ***************************************************************************/
+
+#ifndef SERVERTREEVIEW_H
+#define SERVERTREEVIEW_H
+
+// quanta includes
+#include "basetreeview.h"
+
+//foward declarations
+class QListViewItem;
+class QPoint;
+class KPopupMenu;
+class KURL;
+class ProjectList;
+
+/**
+ TreeViewItem with special painter
+*/
+
+class ServerTreeViewItem : public BaseTreeViewItem {
+
+public:
+ ServerTreeViewItem( KFileTreeViewItem *parent, KFileItem* item, KFileTreeBranch *brnch );
+ /** makes document not in project lighter */
+ void paintCell(QPainter *p, const QColorGroup &cg, int column, int width, int align);
+};
+
+/**
+ the branch for using @ref ServerTreeViewItem
+*/
+
+class ServerTreeBranch : public BaseTreeBranch {
+
+public:
+ ServerTreeBranch(KFileTreeView *parent, const KURL& url,
+ const QString& name, const QPixmap& pix,
+ bool showHidden = false, KFileTreeViewItem *branchRoot = 0L);
+
+ /** check for CVS and visible*/
+ virtual KFileTreeViewItem* createTreeViewItem(KFileTreeViewItem *parent,
+ KFileItem *fileItem );
+};
+
+
+class ServerTreeView : public BaseTreeView {
+ Q_OBJECT
+
+public:
+ ServerTreeView(KConfig *config, QWidget *parent, const KURL &url, const char *name = 0L);
+ virtual ~ServerTreeView();
+
+protected slots:
+
+ void slotMenu(KListView *listView, QListViewItem *item, const QPoint &point);
+
+ /** repaints the treeview items, because they might be added to or removed from the project*/
+ void slotReloadTree( ProjectList *fileList, bool buildNewTree, const QStringList &folderToOpen);
+
+protected:
+ KFileTreeBranch* newBranch(const KURL& url);
+
+ KPopupMenu *m_fileMenu;
+ KPopupMenu *m_folderMenu;
+ int m_menuClose; ///< remembers the menu entry
+ int m_menuPasteFolder; ///< remembers the menu entry
+ int m_insertFileInProject;
+ int m_insertFolderInProject;
+ // config
+ KConfig *m_config;
+
+private:
+ int m_menuDel;
+ int m_reloadMenuId;
+ int m_renameId;
+};
+
+#endif
diff --git a/quanta/treeviews/structtreetag.cpp b/quanta/treeviews/structtreetag.cpp
new file mode 100644
index 00000000..2742bcea
--- /dev/null
+++ b/quanta/treeviews/structtreetag.cpp
@@ -0,0 +1,217 @@
+/***************************************************************************
+ structtreetag.cpp - description
+ -------------------
+ begin : Sat Apr 29 2000
+ copyright : (C) 2000 by Yacovlev Alexander & Dmitry Poplavsky <pdima@mail.univ.kiev.ua>
+ (C) 2002, 2003 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. *
+ * *
+ ***************************************************************************/
+//qt include
+#include <qregexp.h>
+
+// KDE includes
+#include <kiconloader.h>
+#include <klocale.h>
+
+// app includes
+#include "structtreeview.h"
+#include "structtreetag.h"
+#include "messageoutput.h"
+#include "tag.h"
+#include "node.h"
+#include "quantacommon.h"
+#include "document.h"
+#include "resource.h"
+
+StructTreeTag::StructTreeTag(QListView *parent, QString a_title)
+ : KListViewItem(parent, a_title)
+{
+ node = 0L;
+ hasOpenFileMenu = false;
+ groupTag = 0L;
+ parentTree = static_cast<StructTreeView*>(parent);
+}
+
+StructTreeTag::StructTreeTag(StructTreeTag *parent, Node *a_node, const QString a_title,
+ QListViewItem *after )
+: KListViewItem(parent, after, a_title)
+{
+ parentTree = parent->parentTree;
+ hasOpenFileMenu = false;
+ groupTag = 0L;
+ static const QString space = " ";
+ static const QRegExp nbspRx("&nbsp;|\\n");
+ node = a_node;
+ if (node)
+ {
+ Tag *tag = node->tag;
+ QString title = tag->name.lower();
+ if (a_title.isEmpty())
+ {
+ switch (tag->type)
+ {
+ case Tag::XmlTag:
+ {
+ if (title == "font")
+ {
+ setPixmap( 0, UserIcon("tag_font_small") );
+ if ( tag->attrCount() )
+ title = space + tag->attribute(0) + "=" + tag->attributeValue(0);
+ else
+ title = "";
+ } else
+ if (title == "img")
+ {
+ setPixmap( 0, SmallIcon("image") );
+ title = space + tag->attributeValue("src");
+
+ } else
+ if (title == "a")
+ {
+ setPixmap( 0, SmallIcon("www") );
+ if ( tag->hasAttribute("href") )
+ title = space + "href "+ tag->attributeValue("href");
+ if ( tag->hasAttribute("name") )
+ title = space + "name "+ tag->attributeValue("name");
+ } else
+ if ( title == "br")
+ {
+ setPixmap( 0, UserIcon("tag_br_small") );
+ title = "";
+ } else
+ if ( title == "hr")
+ {
+ setPixmap( 0, UserIcon("tag_hr_small") );
+ title = "";
+ } else
+ if ( title == "li")
+ {
+ setPixmap( 0, UserIcon("ball") );
+ title = "";
+ } else
+ if ( title == "p")
+ {
+ setPixmap( 0, UserIcon("tag_p") );
+ title = "";
+ }
+
+ if (!typingInProgress)
+ {
+ QTag *parentQTag = 0L;
+ if (node->parent)
+ parentQTag = QuantaCommon::tagFromDTD(node->parent);
+ QString qTagName = node->tag->dtd()->caseSensitive ? node->tag->name : node->tag->name.upper();
+ int line, col;
+ node->tag->beginPos(line, col);
+ if (parentQTag && !parentQTag->childTags.contains(qTagName) &&
+ !parentQTag->childTags.isEmpty())
+ {
+ node->tag->write()->setErrorMark(line);
+ QString parentTagName = node->tag->dtd()->caseSensitive ? node->parent->tag->name : node->parent->tag->name.upper();
+ parentTree->showMessage(i18n("Line %1: %2 is not a possible child of %3.\n").arg(line + 1).arg(qTagName).arg(parentTagName));
+ }
+ QString nextTagName;
+ if (node->next)
+ {
+ nextTagName = node->tag->dtd()->caseSensitive ? node->next->tag->name : node->next->tag->name.upper();
+ }
+ parentQTag = QuantaCommon::tagFromDTD(node);
+ if (parentQTag && !parentQTag->isSingle() &&
+ !parentQTag->isOptional() &&
+ (!node->next || ( !node->getClosingNode())) )
+ {
+ node->tag->write()->setErrorMark(line);
+ parentTree->showMessage(i18n("Line %1, column %2: Closing tag for %3 is missing.").arg(line + 1).arg(col + 1).arg(qTagName));
+ } else
+ if (!parentQTag && node->tag->name.upper() != "!DOCTYPE")
+ {
+ node->tag->write()->setErrorMark(line);
+ parentTree->showMessage(i18n("Line %1, column %2: %3 is not part of %4.").arg(line + 1).arg(col + 1).arg(qTagName).arg(node->tag->dtd()->nickName));
+ }
+ }
+ break;
+ }
+ case Tag::Text:
+ {
+ title = tag->tagStr();
+ title = title.left(70).stripWhiteSpace();
+ title.replace( nbspRx," ");
+ break;
+ }
+ case Tag::Comment:
+ {
+ setPixmap( 0, UserIcon("tag_comm") );
+ title = tag->tagStr();
+ title = title.left(70).stripWhiteSpace();
+ title.replace( nbspRx," ");
+ break;
+ }
+ case Tag::ScriptTag:
+ {
+ title = tag->name;
+ break;
+ }
+ case Tag::Empty:
+ {
+ title = i18n("Empty tag");
+ break;
+ }
+ case Tag::ScriptStructureBegin:
+ {
+ title = tag->cleanStr.stripWhiteSpace();
+ break;
+ }
+ default:
+ {
+ if (!typingInProgress && node->tag->type == Tag::XmlTagEnd && !node->tag->name.isEmpty())
+ {
+ int line, col;
+ node->tag->beginPos(line, col);
+ QString qTagName = node->tag->dtd()->caseSensitive ? node->tag->name : node->tag->name.upper();
+ QString qPrevTagName;
+ if (node->prev)
+ qPrevTagName = node->tag->dtd()->caseSensitive ? node->prev->tag->name : node->prev->tag->name.upper();
+ if (!node->prev || qTagName != "/" + qPrevTagName)
+ {
+ node->tag->write()->setErrorMark(line);
+ parentTree->showMessage(i18n("Line %1, column %2: Opening tag for %3 is missing.").arg(line + 1).arg(col + 1).arg(qTagName));
+ }
+ }
+ title = tag->tagStr().left(70).stripWhiteSpace();
+ }
+
+
+ }
+ } else
+ {
+ title = a_title;
+ }
+
+ title.replace(newLineRx," ");
+ setText(0, title);
+ node->listItems.append(this);
+ }
+}
+
+StructTreeTag::StructTreeTag(StructTreeTag *parent, QString a_title )
+: KListViewItem(parent, a_title)
+{
+ node = 0L;
+ hasOpenFileMenu = false;
+ groupTag = 0L;
+ parentTree = parent->parentTree;
+}
+
+
+StructTreeTag::~StructTreeTag(){
+ if (node)
+ node->listItems.remove(node->listItems.find(this));
+}
diff --git a/quanta/treeviews/structtreetag.h b/quanta/treeviews/structtreetag.h
new file mode 100644
index 00000000..0b365b0c
--- /dev/null
+++ b/quanta/treeviews/structtreetag.h
@@ -0,0 +1,45 @@
+/***************************************************************************
+ structtreetag.h - description
+ -------------------
+ begin : Sat Apr 29 2000
+ copyright : (C) 2000 by Yacovlev Alexander & Dmitry Poplavsky <pdima@mail.univ.kiev.ua>
+ (C) 2002, 2003 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. *
+ * *
+ ***************************************************************************/
+
+#ifndef STRUCTTREETAG_H
+#define STRUCTTREETAG_H
+
+#include <klistview.h>
+
+class Tag;
+class Node;
+class StructTreeView;
+/**tag in structure widget
+ *@author Yacovlev Alexander & Dmitry Poplavsky & Andras Mantia
+ */
+
+class StructTreeTag : public KListViewItem {
+
+public:
+ StructTreeTag(QListView *parent, const QString a_title = QString::null );
+ StructTreeTag(StructTreeTag *parent, Node *a_node, const QString a_title = QString::null, QListViewItem *after = 0L);
+ StructTreeTag(StructTreeTag *parent, const QString a_title = QString::null );
+ ~StructTreeTag();
+
+ Node *node;
+ bool hasOpenFileMenu;
+ Tag* groupTag;
+ QRegExp fileNameRx;
+ StructTreeView *parentTree;
+};
+
+#endif
diff --git a/quanta/treeviews/structtreeview.cpp b/quanta/treeviews/structtreeview.cpp
new file mode 100644
index 00000000..f6f55b40
--- /dev/null
+++ b/quanta/treeviews/structtreeview.cpp
@@ -0,0 +1,1071 @@
+/***************************************************************************
+ structtreeview.cpp - description
+ -------------------
+ begin : Sat Apr 29 2000
+ copyright : (C) 2000 by Yacovlev Alexander & Dmitry Poplavsky <pdima@mail.univ.kiev.ua>
+ (C) 2002, 2003 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. *
+ * *
+ ***************************************************************************/
+
+// system headers
+#include <assert.h>
+
+// QT headers
+#include <qpixmap.h>
+#include <qheader.h>
+#include <qregexp.h>
+#include <qdatetime.h>
+#include <qdragobject.h>
+#include <qcursor.h>
+
+// KDE headers
+#include <kapplication.h>
+#include <kiconloader.h>
+#include <kpopupmenu.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kconfig.h>
+#include <kdebug.h>
+#include <ktexteditor/view.h>
+
+// app includes
+#include "messageoutput.h"
+#include "node.h"
+#include "qtag.h"
+#include "document.h"
+#include "resource.h"
+#include "qextfileinfo.h"
+#include "quantacommon.h"
+#include "dtds.h"
+#include "viewmanager.h"
+#include "kafkacommon.h"
+#include "cursors.h"
+#include "undoredo.h"
+#include "quantaview.h"
+#include "wkafkapart.h"
+
+#include "structtreetag.h"
+#include "structtreeview.h"
+#include "structtreeview.moc"
+extern GroupElementMapList globalGroupMap;
+
+StructTreeView::StructTreeView(QWidget *parent, const char *name )
+ : KListView(parent,name), m_marker(0), m_draggedItem(0)/*, m_thisWidget(0)*/
+{
+ for (int i = 0; i < 15; i++)
+ groupOpened.append(false);
+ top = 0L;
+ lastTag = 0L;
+ groupsCount = 0;
+ followCursorFlag = true;
+ config = kapp->config();
+
+ topOpened = true;
+ useOpenLevelSetting = true;
+
+ setRootIsDecorated( true );
+ header()->hide();
+ setSorting(-1,false);
+ setAcceptDrops(false); // disabled d&d is broken
+ setDropVisualizer(true);
+ setDragEnabled(false); // disabled d&d is broken
+// setSelectionModeExt(FileManager); disabled d&d is broken
+
+ setFrameStyle( Panel | Sunken );
+ setLineWidth( 2 );
+ addColumn( i18n("Name"), -1 );
+
+ setFocusPolicy(QWidget::ClickFocus);
+
+ dtdMenu = new KPopupMenu(this);
+
+ dtdMenu->insertItem(i18n("All Present DTEP"));
+ dtdMenu->insertSeparator();
+ dtdList = DTDs::ref()->nickNameList();
+ for(uint i = 0; i < dtdList.count(); i++ )
+ {
+ dtdMenu->insertItem(dtdList[i], i, -1);
+ }
+
+ connect(dtdMenu, SIGNAL(activated(int)), this, SLOT(slotDTDChanged(int)));
+
+ connect(this, SIGNAL(dropped(QDropEvent*, QListViewItem*, QListViewItem*)),
+ SLOT(slotDropped(QDropEvent*, QListViewItem*, QListViewItem*)));
+
+ emptyAreaMenu = new KPopupMenu(this);
+ emptyAreaMenu->insertItem(i18n("Show Groups For"), dtdMenu);
+ emptyAreaMenu->insertItem(SmallIcon("reload"), i18n("&Reparse"), this, SLOT(slotReparseMenuItem()));
+
+ popupMenu = new KPopupMenu(this);
+
+ popupMenu -> insertItem( i18n("Show Groups For"), dtdMenu);
+ popupMenu -> insertSeparator();
+ popupMenu -> insertItem( i18n("Select Tag Area"), this ,SLOT(slotSelectTag()));
+ popupMenu -> insertItem( i18n("Go to End of Tag"), this ,SLOT(slotGotoClosingTag()));
+ openFileMenuId = popupMenu -> insertItem( i18n("Open File"), this ,SLOT(slotOpenFile()));
+ popupMenu -> insertSeparator();
+ popupMenu -> insertItem( i18n("Open Subtrees"), this ,SLOT(slotOpenSubTree()));
+ popupMenu -> insertItem( i18n("Close Subtrees"),this ,SLOT(slotCloseSubTree()));
+ popupMenu -> insertSeparator();
+#if 0
+ popupMenu -> insertItem( i18n("Remove"),this ,SLOT(slotRemoveTags()));
+ popupMenu -> insertSeparator();
+#endif
+ popupMenu -> insertItem( SmallIcon("reload"), i18n("&Reparse"), this ,SLOT(slotReparseMenuItem()));
+ followCursorId = popupMenu -> insertItem( i18n("Follow Cursor"), this ,SLOT(changeFollowCursor()));
+
+ popupMenu -> setItemChecked ( followCursorId, followCursor() );
+
+
+ connect( this, SIGNAL(mouseButtonPressed(int, QListViewItem*, const QPoint&, int)),
+ this, SLOT (slotMouseClicked(int, QListViewItem*, const QPoint&, int)));
+
+ connect( this, SIGNAL(doubleClicked(QListViewItem *)), SLOT(slotDoubleClicked(QListViewItem *)));
+
+ connect(this, SIGNAL(expanded(QListViewItem *)), SLOT(slotExpanded(QListViewItem *)));
+ connect(this, SIGNAL(collapsed(QListViewItem *)), SLOT(slotCollapsed(QListViewItem *)));
+
+ write = 0L;
+ timer = new QTime();
+ timer->start();
+ m_dirty = true;
+}
+
+
+StructTreeView::~StructTreeView(){
+ delete timer;
+}
+
+/** builds the structure tree */
+void StructTreeView::buildTree(Node *baseNode, int openLevel, bool groupOnly)
+{
+#ifdef DEBUG_PARSER
+ kdDebug(24000) << "Starting to rebuild the structure tree. Grouponly = " << groupOnly << endl;
+#endif
+ if (!groupOnly)
+ {
+ top = new StructTreeTag( this, i18n("Document Structure") );
+ top->setOpen(topOpened);
+ emit clearProblemOutput();
+ }
+ Node *currentNode = baseNode;
+ StructTreeTag *currentItem = top; //after this
+ StructTreeTag *item = 0L;
+ StructTreeTag *parentItem = top; //under this
+ int level = 0;
+ QString title;
+ QString tagStr;
+ QString tmpStr;
+ int groupId = 0;
+ const DTDStruct* parsingDTD;
+ for (uint index = 0; index < m_parsingDTDList.count(); index++)
+ {
+ parsingDTD = m_parsingDTDList[index];
+ if (parsingDTD->family == Script)
+ {
+ StructTreeGroup group;
+ uint gCount = parsingDTD->structTreeGroups.count();
+ for (uint i = 0; i < gCount; i++)
+ {
+ group = parsingDTD->structTreeGroups[i];
+ StructTreeTag *groupTag = new StructTreeTag(this, i18n(group.name.utf8()) + " [" + parsingDTD->nickName+"]");
+ if (!group.icon.isEmpty())
+ {
+ groupTag->setPixmap(0, SmallIcon(group.icon));
+ }
+ groupTag->setOpen(groupOpened[groupId]);
+#ifdef DEBUG_PARSER
+ kdDebug(24001) << "Grouptag created: " << groupId << " " << groupTag->text(0) << " "<< groupTag << endl;
+#endif
+ groups.append(groupTag);
+ groupIds.insert(group.name + parsingDTD->name, groupId);
+ groupId++;
+ }
+ } else
+ {
+ QMap<QString, XMLStructGroup>::ConstIterator it;
+ for (it = parsingDTD->xmlStructTreeGroups.begin(); it != parsingDTD->xmlStructTreeGroups.end(); ++it)
+ {
+ XMLStructGroup group = it.data();
+ StructTreeTag *groupTag = new StructTreeTag(this, i18n(group.name.utf8()) + " [" + parsingDTD->nickName+"]");
+ if (!group.icon.isEmpty())
+ {
+ groupTag->setPixmap(0, SmallIcon(group.icon));
+ }
+ groupTag->setOpen(groupOpened[groupId]);
+#ifdef DEBUG_PARSER
+ kdDebug(24001) << "Grouptag created: " << groupId << " " << groupTag->text(0) << " "<< groupTag << endl;
+#endif
+ groups.append(groupTag);
+ groupIds.insert(group.name + parsingDTD->name, groupId);
+ groupId++;
+ }
+
+ }
+ }
+ groupsCount = groupId;
+ QMap<QString, QListViewItem*> lastItemInGroup;
+ QMap<QString, QListViewItem*> groupItems;
+ while (currentNode)
+ {
+ if (!groupOnly)
+ {
+ title = "";
+ item = new StructTreeTag(parentItem, currentNode, title, currentItem);
+ item->setOpen(level < openLevel);
+ currentNode->mainListItem = item;
+
+ if ( (!qConfig.showEmptyNodes && currentNode->tag->type == Tag::Empty) ||
+ (!qConfig.showClosingTags &&
+ (currentNode->tag->type == Tag::XmlTagEnd ||
+ currentNode->tag->type == Tag::ScriptStructureEnd) ) )
+ {
+ item->setVisible(false);
+ }
+ }
+ const DTDStruct *dtd = currentNode->tag->dtd();
+ //add all the group elements belonging to this node to the tree
+ for (QValueList<GroupElement*>::ConstIterator it = currentNode->m_groupElements.constBegin(); it != currentNode->m_groupElements.constEnd(); ++it)
+ {
+ GroupElement *groupElement = (*it);
+ if (!groupIds.contains(groupElement->group->name + dtd->name))
+ continue;
+ StructTreeTag *groupItem = groups[groupIds[groupElement->group->name + dtd->name]];
+ QListViewItem* insertAfter = 0L;
+ QListViewItem* insertUnder = groupItem;
+ if (groupItems.contains(groupElement->group->name + groupElement->tag->name))
+ insertUnder = groupItems[groupElement->group->name + groupElement->tag->name];
+ if (lastItemInGroup.contains(groupElement->group->name))
+ insertAfter = lastItemInGroup[groupElement->group->name];
+
+ StructTreeTag *item = new StructTreeTag(static_cast<StructTreeTag*>(insertUnder), currentNode, groupElement->tag->name, insertAfter);
+ item->groupTag = groupElement->tag;
+ if (insertUnder == groupItem)
+ {
+ groupItems[groupElement->group->name + groupElement->tag->name] = item;
+ lastItemInGroup[groupElement->group->name] = item;
+ }
+ item->hasOpenFileMenu = groupElement->group->hasFileName;
+ item->fileNameRx = groupElement->group->fileNameRx;
+#ifdef DEBUG_PARSER
+ kdDebug(24001) << "Tree element "<< groupElement->tag->tagStr() << "[" << groupElement->group->name<<"]"<< " inserted: " << item << " under " <<insertUnder << " after " << insertAfter << endl;
+#endif
+ }
+
+ //go to the child node, if it exists
+ if (currentNode->child)
+ {
+ currentNode = currentNode->child;
+ parentItem = item;
+ currentItem = 0L;
+ level++;
+ } else
+ {
+ //go to the next node if it exists
+ if (currentNode->next)
+ {
+ currentNode = currentNode->next;
+ currentItem = item;
+ } else
+ {
+ //go up some levels, to the parent, if the node has no child or next
+ while (currentNode)
+ {
+ level--;
+ //parentItem = dynamic_cast<StructTreeTag*>(parentItem->parent());
+ if (currentNode->parent && currentNode->parent->next)
+ {
+ currentNode = currentNode->parent->next;
+ break;
+ } else
+ {
+ currentNode = currentNode->parent;
+ }
+ }
+ if (!groupOnly && currentNode)
+ {
+ if (currentNode->prev)
+ currentItem = static_cast<StructTreeTag*>(currentNode->prev->mainListItem);
+ if (currentNode->parent)
+ {
+ parentItem = static_cast<StructTreeTag*>(currentNode->parent->mainListItem);
+ if (!parentItem)
+ {
+ parentItem = top;
+ }
+ }
+ else
+ {
+ parentItem = top;
+ }
+ }
+
+ }
+ }
+ }
+ //add the externally found items to the tree
+ QListViewItem *insertUnder;
+ QListViewItem *insertAfter;
+ QListViewItem *listItem;
+ GroupElementMapList::Iterator it;
+ IncludedGroupElementsMap::Iterator externalIt;
+ for (uint index = 0; index < m_parsingDTDList.count(); index++)
+ {
+ parsingDTD = m_parsingDTDList[index];
+ if (parsingDTD->family == Script)
+ {
+ StructTreeGroup group;
+ uint gCount = parsingDTD->structTreeGroups.count();
+ for (uint i = 0; i < gCount; i++)
+ {
+ group = parsingDTD->structTreeGroups[i];
+ groupId = groupIds[group.name + parsingDTD->name];
+ QString name = group.name+"|";
+ StructTreeTag *groupTag = groups[groupId];
+ for (externalIt = parser->includedMap.begin(); externalIt != parser->includedMap.end(); ++externalIt)
+ {
+ insertUnder = new StructTreeTag(static_cast<StructTreeTag*>(groupTag), 0L, externalIt.key(), groupTag);
+ insertAfter = insertUnder;
+ IncludedGroupElements elements = externalIt.data();
+ GroupElementMapList::Iterator elIt;
+ for (elIt = elements[group.name].begin(); elIt != elements[group.name].end(); ++elIt)
+ {
+ listItem = new StructTreeTag(static_cast<StructTreeTag*>(insertUnder), elIt.data()[0]->node, elIt.key(), insertAfter);
+ static_cast<StructTreeTag*>(listItem)->hasOpenFileMenu = group.hasFileName;
+ static_cast<StructTreeTag*>(listItem)->fileNameRx = group.fileNameRx;
+ insertAfter = listItem;
+ }
+ if (!insertUnder->firstChild())
+ delete insertUnder;
+ else
+ insertUnder->sortChildItems(0, true);
+ }
+ groupTag->sortChildItems(0, true);
+ }
+ }
+ }
+}
+
+/** Delete the items */
+void StructTreeView::deleteList(bool groupOnly)
+{
+ if (!groupOnly && top )
+ {
+ topOpened = top->isOpen();
+ delete top;
+ top = 0L;
+ }
+ for (uint i = 0; i < groupsCount; i++)
+ {
+ groupOpened.append(groups[i]->isOpen());
+#ifdef DEBUG_PARSER
+ kdDebug(24001) << "Grouptag deleted: " << i << " " << groups[i]->text(0) << endl;
+#endif
+ delete groups[i];
+ }
+ groups.clear();
+ groupIds.clear();
+ groupsCount = 0;
+}
+
+/** repaint document structure */
+void StructTreeView::slotReparse(Document *w, Node* node, int openLevel, bool groupOnly)
+{
+ timer->restart();
+ if (typingInProgress)
+ return;
+ deleteList(groupOnly);
+ if (!node)
+ return;
+ write = w;
+ if (write)
+ write->clearAnnotations();
+ write->clearErrorMarks();
+ buildTree(node, openLevel, groupOnly);
+
+ kdDebug(24000) << "StructTreeView building: " << timer->elapsed() << " ms\n";
+
+ const DTDStruct *parsingDTD;
+ int groupId = 0;
+ for (uint index = 0; index < m_parsingDTDList.count(); index++)
+ {
+ parsingDTD = m_parsingDTDList[index];
+ if (parsingDTD->family == Script)
+ {
+ uint gCount = parsingDTD->structTreeGroups.count();
+ for (uint i = 0; i < gCount; i++)
+ {
+ StructTreeTag *groupTag = groups[groupId];
+ if (groupTag->childCount() == 0)
+ {
+ if (qConfig.showEmptyNodes)
+ {
+ //kdDebug(24000) << "No elements in group: " << groupId << " " << groupTag->text(0) << endl;
+ groupTag->setText(0, i18n(parsingDTD->structTreeGroups[i].noName.utf8()) + " [" + parsingDTD->nickName+"]");
+ } else
+ {
+ groupTag->setVisible(false);
+ }
+ }
+ groupId++;
+ }
+ } else
+ {
+ QMap<QString, XMLStructGroup>::ConstIterator it;
+ uint i = 0;
+ for (it = parsingDTD->xmlStructTreeGroups.begin(); it != parsingDTD->xmlStructTreeGroups.end(); ++it)
+ {
+ StructTreeTag *groupTag = groups[groupId];
+ if (groupTag->childCount() == 0)
+ {
+ if (qConfig.showEmptyNodes)
+ {
+ //kdDebug(24000) << "No elements in group: " << groupId << " " << groupTag->text(0) << endl;
+ groupTag->setText(0, i18n(it.data().noName.utf8()) + " [" + parsingDTD->nickName+"]");
+ } else
+ {
+ groupTag->setVisible(false);
+ }
+ }
+ i++;
+ groupId++;
+ }
+ }
+ }
+ useOpenLevelSetting = false;
+ m_dirty = false;
+}
+
+void StructTreeView::slotGotoTag( QListViewItem *item )
+{
+ StructTreeTag *it = dynamic_cast<StructTreeTag*>(item);
+ if (!m_dirty && it && it->node && it->node->tag)
+ {
+ Tag *tag = new Tag(*it->node->tag);
+ int line, col;
+ tag->beginPos(line, col);
+ if (!it->node->fileName.isEmpty())
+ {
+ KURL url;
+ QuantaCommon::setUrl(url, it->node->fileName);
+ emit openFile(url);
+ }
+ int el, ec;
+ tag->endPos(el, ec);
+/*
+ kdDebug(24000) << "Node area: " << line << ", " << col << ", " << el << ", " << ec << endl;
+ kdDebug(24000) << "Node type: " << tag->type << endl;
+ kdDebug(24000) << "Node str: " << tag->tagStr() << endl;
+ kdDebug(24000) << "Node cleanstr: " << tag->cleanStr << endl;
+*/
+ if (tag->type == Tag::XmlTag || tag->type == Tag::XmlTagEnd)
+ col++; //position the cursor inside the tag
+ emit newCursorPosition(line, col);
+ Document *w = ViewManager::ref()->activeDocument();
+ if (w)
+ w->view()->setFocus();
+ delete tag;
+ }
+}
+
+
+void StructTreeView::slotMouseClicked(int button, QListViewItem *item, const QPoint& point, int dummy)
+{
+ if (item)
+ {
+ config->setGroup("Parser options");
+
+ QString handleMBM = config->readEntry("MBM", i18n("Select Tag Area"));
+ QString handleLBM = config->readEntry("LBM", i18n("Find tag"));
+ QString handleDoubleClick = config->readEntry("Double click", i18n("Select Tag Area"));
+
+ setSelected(item, true);
+
+ if (button == Qt::RightButton)
+ {
+ if (dynamic_cast<StructTreeTag*>(item))
+ {
+ popupMenu->setItemVisible(openFileMenuId, static_cast<StructTreeTag*>(item)->hasOpenFileMenu);
+ }
+ popupMenu->popup(point);
+ return;
+ }
+
+ if (button == Qt::LeftButton)
+ {
+ if (handleLBM == i18n("Find Tag && Open Tree"))
+ setOpen(item, !isOpen(item));
+ setSelected(item, true);
+
+ bool const ctrlPressed = KApplication::keyboardMouseState() & Qt::ControlButton;
+
+ if(ctrlPressed)
+ setContiguousSelectedItems();
+
+ if(ViewManager::ref()->activeView()->hadLastFocus() == QuantaView::VPLFocus)
+ slotMouseClickedVPL(button, item, point, dummy);
+ else
+ slotGotoTag(item);
+ }
+
+ if (button == Qt::MidButton)
+ {
+ if (handleMBM == i18n("nothing"))
+ return;
+
+ if (handleMBM == i18n("Find Tag && Open Tree"))
+ {
+ setOpen(item, !isOpen(item));
+ setSelected(item, true);
+ slotGotoTag(item);
+ }
+
+ if (handleMBM == i18n("Select Tag Area"))
+ slotSelectTag();
+
+ if (handleMBM == i18n("Go to End of Tag"))
+ slotGotoClosingTag();
+
+ setSelected(item, true);
+ }
+ } else
+ if (button == Qt::RightButton)
+ emptyAreaMenu->popup(point);
+}
+
+
+void StructTreeView::slotDoubleClicked( QListViewItem *item)
+{
+ config->setGroup("Parser options");
+
+ if ( config->readEntry("Double click") != i18n("nothing") )
+ {
+ slotSelectTag();
+ } else
+ {
+ item->setOpen(!item->isOpen());
+ }
+}
+
+
+
+void StructTreeView::slotReparseMenuItem()
+{
+ useOpenLevelSetting = true;
+ emit needReparse();
+}
+
+void StructTreeView::slotGotoClosingTag()
+{
+ QListViewItem *item = currentItem();
+ StructTreeTag *it = dynamic_cast<StructTreeTag*>(item);
+ if (!m_dirty && it && it->node)
+ {
+ int newLine, newCol;
+ Tag *tag = it->node->tag;
+ if (tag->single || !it->node->next)
+ {
+ tag->endPos(newLine, newCol);
+ } else
+ {
+ if (tag->closingMissing)
+ {
+ Node *node = it->node;
+ while (node->child) node = node->child;
+ node->tag->endPos(newLine, newCol);
+ } else
+ {
+ it->node->next->tag->endPos(newLine, newCol);
+ }
+ }
+
+ emit newCursorPosition( newLine, newCol + 1 );
+ }
+}
+
+void StructTreeView::slotSelectTag()
+{
+ bool newFileOpened = false;
+ QListViewItem *item = currentItem();
+ StructTreeTag *it = dynamic_cast<StructTreeTag*>(item);
+ if (!m_dirty && it && it->node)
+ {
+ int bLine, bCol, eLine, eCol;
+ if (it->node->fileName.isEmpty())
+ {
+ if (it->groupTag)
+ {
+ Tag *tag = it->groupTag;
+ tag->beginPos(bLine, bCol);
+ tag->endPos(eLine, eCol);
+ } else
+ {
+ Tag *tag = it->node->tag;
+ if (tag->single || !it->node->next)
+ {
+ tag->endPos(eLine, eCol);
+ } else
+ {
+ emit selectTagArea(it->node);
+ return;
+ }
+ tag->beginPos(bLine, bCol);
+ }
+ } else
+ {
+ KURL url;
+ QuantaCommon::setUrl(url, it->node->fileName);
+ it->node->tag->beginPos(bLine, bCol);
+ it->node->tag->endPos(eLine, eCol);
+ eCol--;
+ emit openFile(url);
+ newFileOpened = true;
+
+ }
+ emit selectArea( bLine, bCol, eLine, eCol + 1);
+
+ if (!newFileOpened)
+ {
+ setSelected(item, true);
+ it->node->tag->write()->view()->setFocus();
+ }
+ }
+}
+
+
+/** Do the recursive opening or closing of the trees */
+void StructTreeView::setOpenSubTree( QListViewItem *it, bool open)
+{
+ if (it)
+ {
+ it->setOpen(open);
+ setOpenSubTree( it->nextSibling(), open );
+ setOpenSubTree( it->firstChild(), open );
+ }
+}
+
+/** Recursively open the tree and all its subtrees */
+void StructTreeView::slotOpenSubTree()
+{
+ QListViewItem *item = currentItem();
+ if (item)
+ {
+ item->setOpen( true );
+ setOpenSubTree( item->firstChild(), true );
+ }
+}
+
+
+/** Recursively close the tree and all its subtrees */
+void StructTreeView::slotCloseSubTree()
+{
+ QListViewItem *item = currentItem();
+ if (item)
+ {
+ item->setOpen( false );
+ setOpenSubTree( item->firstChild(), false );
+ }
+}
+
+/** Show the element in tree according to cursor position (x,y) */
+void StructTreeView::showTagAtPos(Node *node)
+{
+ if (followCursorFlag)
+ {
+ if (node && node->mainListItem)
+ {
+ clearSelection();
+ ensureItemVisible(node->mainListItem);
+ setSelected(node->mainListItem, true);
+ }
+ } //if (followCursorFlag)
+}
+
+void StructTreeView::setFollowCursor(bool follow)
+{
+ followCursorFlag = follow;
+ popupMenu->setItemChecked(followCursorId, follow);
+}
+
+/** No descriptions */
+void StructTreeView::slotExpanded(QListViewItem *item)
+{
+ StructTreeTag *it = dynamic_cast<StructTreeTag*>(item);
+ if (!m_dirty && it && it->node)
+ it->node->opened = true;
+}
+
+/** No descriptions */
+void StructTreeView::slotCollapsed(QListViewItem *item)
+{
+ StructTreeTag *it = dynamic_cast<StructTreeTag*>(item);
+ if (!m_dirty && it && it->node)
+ it->node->opened = false;
+}
+/** Do a reparse before showing. */
+void StructTreeView::showEvent(QShowEvent* /*ev*/)
+{
+ slotReparseMenuItem();
+}
+
+/** Do a reparse before showing. */
+void StructTreeView::hideEvent(QHideEvent* /*ev*/)
+{
+ emit clearProblemOutput();
+}
+
+enum {
+ DRAG_COPY = 0,
+ DRAG_MOVE = 1,
+ DRAG_CANCEL = 2
+};
+
+void StructTreeView::setContiguousSelectedItems()
+{
+ kdDebug(25001) << "setContiguousSelectedItems" << endl;
+
+ QPtrList<QListViewItem> selected_items = selectedItems(false);
+
+ QListViewItem* first = selected_items.getFirst();
+ QListViewItem* last = selected_items.getLast();
+
+ QListViewItemIterator it(first);
+ while(it.current() && it.current() != last)
+ {
+ QListViewItem* item = it.current();
+ if(!item->isSelected())
+ item->setSelected(true);
+
+ ++it;
+ }
+}
+
+bool StructTreeView::acceptDrag(QDropEvent* e) const
+{
+ static int i = 0;
+ kdDebug(25001) << "acceptDrag: " << ++i << endl;
+
+ QPoint p = contentsToViewport(e->pos());
+ QListViewItem* current_item = itemAt(p);
+
+// assert(m_thisWidget);
+
+ static bool last_accept = false;
+
+ if(current_item == m_marker)
+ {
+ e->accept(last_accept);
+/* if(last_accept)
+ m_thisWidget->setCursor(Qt::ForbiddenCursor);
+ else
+ m_thisWidget->setCursor(Qt::ForbiddenCursor);*/
+ kdDebug(25001) << "Princ�io: " << last_accept << endl;
+
+ return last_accept;
+ }
+ else
+ m_marker = current_item;
+
+ if(current_item == m_draggedItem ||
+ !(e->provides("text/x-struct_tree_tag_item") || e->source() == (QWidget *)this) || !m_marker)
+ {
+ e->accept(false);
+ last_accept = false;
+/* if(last_accept)
+ m_thisWidget->setCursor(Qt::ForbiddenCursor);
+ else
+ m_thisWidget->setCursor(Qt::ForbiddenCursor);*/
+ kdDebug(25001) << "PROIBIDO! #1" << endl;
+ return false;
+ }
+
+ Node* dragged_node = (dynamic_cast<StructTreeTag*> (m_draggedItem))->node;
+ Node* after_node = (dynamic_cast<StructTreeTag*> (m_marker))->node;
+ if(!after_node)
+ {
+ e->accept(false);
+ last_accept = false;
+/* if(last_accept)
+ m_thisWidget->setCursor(Qt::ForbiddenCursor);
+ else
+ m_thisWidget->setCursor(Qt::ForbiddenCursor);*/
+ kdDebug(25001) << "PROIBIDO! #2" << endl;
+ return false;
+ }
+ QTag* nodeQTag = QuantaCommon::tagFromDTD(after_node->parent);
+ bool is_child = (nodeQTag && nodeQTag->isChild(dragged_node));
+
+ if(!is_child)
+ kdDebug(25001) << "PROIBIDO! #3" << endl;
+ else
+ kdDebug(25001) << "ACEITE!" << endl;
+
+ e->accept(is_child);
+ last_accept = is_child;
+// if(last_accept)
+// m_thisWidget->setCursor(Qt::ForbiddenCursor);
+// else
+// m_thisWidget->setCursor(Qt::ForbiddenCursor);
+
+ return is_child;
+}
+
+void StructTreeView::slotDropped(QDropEvent* e, QListViewItem* parent, QListViewItem* after)
+{
+ if(!e)
+ return;
+ if (e->source() != this)
+ return; // Only internal drags are supported atm
+
+ if(!QTextDrag::canDecode(e))
+ return;
+
+ KPopupMenu *menu = new KPopupMenu( this );
+ menu->insertItem( i18n("&Move Here"), DRAG_MOVE, 0 );
+ menu->insertItem( SmallIcon("editcopy"), i18n("&Copy Here"), DRAG_COPY, 1 );
+ menu->insertSeparator();
+ menu->insertItem( SmallIcon("cancel"), i18n("C&ancel"), DRAG_CANCEL, 3 );
+ int id = menu->exec(QCursor::pos(), 0);
+
+ switch(id) {
+ case DRAG_COPY:
+ copySelectedItems(parent, after);
+ break;
+ case DRAG_MOVE:
+ moveSelectedItems(parent, after);
+ break;
+ case DRAG_CANCEL: // cancelled by menuitem
+ break;
+ case -1: // cancelled by Esc
+ break;
+ default:
+ break;
+ }
+
+ m_draggedItem = 0;
+}
+
+void StructTreeView::startDrag()
+{
+ // This a dummy drag object. Decode is made by the objects selected on the tree.
+ QTextDrag* drag = new QTextDrag(this);
+// m_thisWidget = drag->source();
+ drag->setSubtype("x-struct_tree_tag_item");
+ drag->setPixmap(SmallIcon("node"));
+ drag->dragMove();
+
+}
+
+void StructTreeView::contentsMousePressEvent(QMouseEvent* e)
+{
+ if(e->button() == LeftButton)
+ {
+ QPoint p = contentsToViewport(e->pos());
+ m_draggedItem = itemAt(p);
+ m_marker = m_draggedItem;
+ }
+ KListView::contentsMousePressEvent(e);
+}
+
+void StructTreeView::copySelectedItems(QListViewItem* parent, QListViewItem* after)
+{
+ StructTreeTag* parent_item = dynamic_cast<StructTreeTag*> (parent);
+ StructTreeTag* after_item = dynamic_cast<StructTreeTag*> (after);
+ if(!parent_item/* || !after_item*/) // can happen if the element is inserted as the first child
+ return;
+
+ QPtrList<QListViewItem> selected_items = selectedItems(false);
+ QListViewItem* first_item = selected_items.getFirst();
+ QListViewItem* last_item = selected_items.getLast();
+
+ Node* start_node = (dynamic_cast<StructTreeTag*> (first_item))->node;
+ Node* end_node = (dynamic_cast<StructTreeTag*> (last_item))->node;
+ assert(start_node && end_node);
+
+ Node* start_node_subtree = 0;
+ if(start_node == end_node)
+ start_node_subtree = kafkaCommon::duplicateNodeSubtree(start_node, true);
+ else
+ start_node_subtree = kafkaCommon::getNodeSubtree(start_node, 0, end_node, end_node->tag->tagStr().length());
+
+ Node* parent_node = parent_item->node;
+ if(!parent_node)
+ return;
+ Node* next_node = 0;
+ if(after_item)
+ next_node = after_item->node->SNext();
+ else
+ next_node = parent_node->firstChild();
+
+ NodeSelection cursor_holder;
+ NodeModifsSet *modifs = new NodeModifsSet();
+
+ kafkaCommon::DTDInsertNodeSubtree(start_node_subtree, parent_node, next_node, cursor_holder, modifs);
+
+ write->docUndoRedo->addNewModifsSet(modifs, undoRedo::NodeTreeModif, 0, false);
+}
+
+void StructTreeView::moveSelectedItems(QListViewItem* parent, QListViewItem* after)
+{
+ StructTreeTag* parent_item = dynamic_cast<StructTreeTag*> (parent);
+ StructTreeTag* after_item = dynamic_cast<StructTreeTag*> (after);
+ if(!parent_item || !after_item)
+ return;
+
+ QPtrList<QListViewItem> selected_items = selectedItems(false);
+ QListViewItem* first_item = selected_items.getFirst();
+ QListViewItem* last_item = selected_items.getLast();
+
+ Node* start_node = (dynamic_cast<StructTreeTag*> (first_item))->node;
+ Node* end_node = (dynamic_cast<StructTreeTag*> (last_item))->node;
+ assert(start_node && end_node);
+
+ Node* cursor_node = 0;
+ long cursor_offset = 0;
+ NodeModifsSet *modifs = new NodeModifsSet();
+
+ Node* start_node_subtree = 0;
+ if(start_node == end_node)
+ start_node_subtree = kafkaCommon::extractNodeSubtreeAux(start_node, end_node, modifs);
+ else
+ start_node_subtree = kafkaCommon::DTDExtractNodeSubtree(start_node, 0, end_node, end_node->tag->tagStr().length(),
+ &cursor_node, cursor_offset, modifs);
+
+ Node* parent_node = parent_item->node;
+ if(!parent_node)
+ return;
+ Node* next_node = after_item->node->SNext();
+
+ NodeSelection cursor_holder(cursor_node, cursor_offset);
+
+ kafkaCommon::DTDInsertNodeSubtree(start_node_subtree, parent_node, next_node, cursor_holder, modifs);
+
+ write->docUndoRedo->addNewModifsSet(modifs, undoRedo::NodeTreeModif, &cursor_holder, false);
+}
+
+/** The treeview DTD has changed to id. */
+void StructTreeView::slotDTDChanged(int id)
+{
+ QString text = dtdMenu->text(id);
+ if (dtdMenu->indexOf(id) > 0)
+ {
+ QString dtdName = DTDs::ref()->getDTDNameFromNickName(text);
+ emit showGroupsForDTEP(dtdName, !dtdMenu->isItemChecked(id));
+ } else
+ emit showGroupsForDTEP("clear", true);
+}
+
+void StructTreeView::setParsingDTDs(const QStringList &parsingDTDList)
+{
+ m_parsingDTDList.clear();
+ for (uint i = 0; i < dtdList.count(); i++)
+ {
+ dtdMenu->setItemChecked(i, false);
+ }
+ QString dtdNickName;
+ for (QStringList::ConstIterator it = parsingDTDList.constBegin(); it != parsingDTDList.constEnd(); ++it)
+ {
+ dtdNickName = DTDs::ref()->getDTDNickNameFromName(*it);
+ for (uint i = 0; i < dtdList.count(); i++)
+ {
+ if (dtdList[i] == dtdNickName)
+ dtdMenu->setItemChecked(i, true);
+ }
+ m_parsingDTDList.append(DTDs::ref()->find(*it));
+ }
+}
+
+void StructTreeView::slotOpenFile()
+{
+ StructTreeTag *item = dynamic_cast<StructTreeTag*>(currentItem());
+ if (!m_dirty && item->node)
+ {
+ QString text = item->groupTag->name;
+ text.remove(item->fileNameRx);
+ KURL baseUrl = QExtFileInfo::path(write->url());
+ KURL url = baseUrl;
+ QuantaCommon::setUrl(url, text.stripWhiteSpace());
+ url = QExtFileInfo::toAbsolute(url, baseUrl);
+ if (QExtFileInfo::exists(url, true, this))
+ {
+ if (QuantaCommon::checkMimeGroup(url, "text" ))
+ {
+ emit openFile(url);
+ }
+ else if (QuantaCommon::checkMimeGroup(url," image" ))
+ {
+ emit openImage(url);
+ }
+ } else
+ KMessageBox::error(this, i18n("<qt>The file <b>%1</b> does not exist or is not a recognized mime type.</qt>").arg(url.prettyURL(0, KURL::StripFileProtocol)));
+ }
+}
+
+void StructTreeView::slotNodeTreeChanged()
+{
+ m_dirty = true;
+}
+
+void StructTreeView::showMessage(const QString& message)
+{
+ emit showProblemMessage(message);
+}
+
+void StructTreeView::slotMouseClickedVPL(int /*button*/, QListViewItem* item, const QPoint&, int)
+{
+ ViewManager::ref()->activeView()->setFocus();
+
+ QPtrList<QListViewItem> selected_items = selectedItems(true);
+ if(selected_items.count() == 1)
+ {
+ StructTreeTag* tag_item = dynamic_cast<StructTreeTag*> (item);
+ if(!tag_item)
+ return;
+ Node* node = tag_item->node;
+ if(!node)
+ return;
+ if(node->tag->type == Tag::Text || node->tag->type == Tag::Empty)
+ {
+ KafkaDocument::ref()->setCursor(node, 0);
+ }
+ }
+ else
+ {
+ Node* start_node = (dynamic_cast<StructTreeTag*> (selected_items.getFirst()))->node;
+ Node* end_node = (dynamic_cast<StructTreeTag*> (selected_items.getLast()))->node;
+
+ NodeSelectionInd selection(start_node, 0, end_node, 1/*end_node->tag->tagStr().length()*/);
+ KafkaDocument::ref()->setCursorAndSelection(&selection);
+ }
+}
+
+void StructTreeView::slotRemoveTags()
+{
+ QPtrList<QListViewItem> selected_items = selectedItems(true);
+
+ Node* start_node = (dynamic_cast<StructTreeTag*> (selected_items.getFirst()))->node;
+ Node* end_node = start_node;
+ if(selected_items.count() > 1)
+ end_node = (dynamic_cast<StructTreeTag*> (selected_items.getLast()))->node;
+
+ kafkaCommon::coutTree(start_node, 3);
+
+ Node* cursor_node = 0;
+ long cursor_offset = 0;
+
+ NodeModifsSet *modifs = new NodeModifsSet();
+ kafkaCommon::DTDExtractNodeSubtree(start_node, 0, end_node, end_node->tag->tagStr().length(), &cursor_node, cursor_offset, modifs);
+
+ NodeSelection* selection = new NodeSelection(cursor_node, cursor_offset);
+
+ write->docUndoRedo->addNewModifsSet(modifs, undoRedo::NodeTreeModif, selection, false);
+}
+
diff --git a/quanta/treeviews/structtreeview.h b/quanta/treeviews/structtreeview.h
new file mode 100644
index 00000000..4f59e7d3
--- /dev/null
+++ b/quanta/treeviews/structtreeview.h
@@ -0,0 +1,176 @@
+/***************************************************************************
+ structtreeview.h - description
+ -------------------
+ begin : Sat Apr 29 2000
+ copyright : (C) 2000 by Yacovlev Alexander & Dmitry Poplavsky <pdima@mail.univ.kiev.ua>
+ (C) 2002, 2003 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. *
+ * *
+ ***************************************************************************/
+
+#ifndef STRUCTTREEVIEW_H
+#define STRUCTTREEVIEW_H
+
+#include <qmap.h>
+#include <qvaluelist.h>
+
+#include <klistview.h>
+
+/**view class of document structure
+ *@author Andras Mantia & Paulo Moura Guedes & Yacovlev Alexander & Dmitry Poplavsky
+ */
+
+class KPopupMenu;
+class KConfig;
+class KURL;
+class QTime;
+
+class Node;
+class StructTreeTag;
+class Parser;
+class Document;
+struct DTDStruct;
+
+class StructTreeView : public KListView {
+ Q_OBJECT
+public:
+
+ /**
+ * since this class is a singleton you must use this function to access it
+ *
+ * the parameters are only used at the first call to create the class
+ *
+ */
+ static StructTreeView* const ref(QWidget *parent = 0L, const char *name = 0L)
+ {
+ static StructTreeView *m_ref;
+ if (!m_ref) m_ref = new StructTreeView (parent, name);
+ return m_ref;
+ }
+
+ ~StructTreeView();
+
+
+ void setFollowCursor(bool);
+ bool followCursor() { return followCursorFlag; }
+ /** Show the element in tree according to cursor position (x,y) */
+ void showTagAtPos(Node *node);
+ /** Delete the items */
+ void deleteList(bool groupOnly);
+ void setParsingDTDs(const QStringList &parsingDTDList);
+ void showMessage(const QString& message);
+
+
+ bool useOpenLevelSetting;
+
+public slots: // Public slots
+ /** repaint document structure */
+ void slotReparse(Document *w, Node* node, int openLevel = 3,bool groupOnly=false);
+ void slotMouseClicked(int button, QListViewItem*, const QPoint&, int);
+ void slotDoubleClicked( QListViewItem * );
+
+ // slots for RBM menu
+ void slotReparseMenuItem();
+ void slotSelectTag();
+ void slotGotoTag( QListViewItem *item );
+ void slotGotoClosingTag();
+ /** Recursively open the tree and all its subtrees */
+ void slotOpenSubTree();
+ /** Recursively close the tree and all its subtrees */
+ void slotCloseSubTree();
+ void changeFollowCursor() { setFollowCursor(!followCursorFlag); }
+ /** No descriptions */
+ void slotCollapsed(QListViewItem *item);
+ /** No descriptions */
+ void slotExpanded(QListViewItem *);
+ void slotOpenFile();
+ void slotNodeTreeChanged();
+ void slotRemoveTags();
+
+signals:
+ void newCursorPosition( int col, int row );
+ void selectTagArea(Node* node);
+ void selectArea(int col1, int row1, int col2, int row2 );
+ void needReparse();
+ void onTag( const QString &tag );
+ void showGroupsForDTEP(const QString& dtep, bool show);
+ void openFile(const KURL&);
+ void openImage(const KURL&);
+ void showProblemMessage(const QString&);
+ void clearProblemOutput();
+
+private:
+
+ /** The constructor is private because we use singleton pattern.
+ * If you need the class use StructTreeView::ref() for
+ * construction and reference
+ */
+ StructTreeView(QWidget *parent=0, const char *name=0);
+ /** builds the structure tree */
+ void buildTree(Node *baseNode, int openLevel, bool groupOnly);
+ /** Do the recursive opening or closing of the trees */
+ void setOpenSubTree(QListViewItem *it, bool open);
+
+ /** Make ctrl have the same behavior has shift */
+ void setContiguousSelectedItems();
+
+ void copySelectedItems(QListViewItem* parent, QListViewItem* after);
+ void moveSelectedItems(QListViewItem* parent, QListViewItem* after);
+
+private:
+
+ int followCursorId;
+ bool followCursorFlag;
+
+ KPopupMenu *popupMenu;
+ KPopupMenu *emptyAreaMenu;
+ KPopupMenu *dtdMenu;
+ StructTreeTag *lastTag;
+ KConfig *config;
+ QStringList dtdList;
+ QValueList<const DTDStruct*> m_parsingDTDList;
+ int openFileMenuId;
+ QMap<QString, uint> groupIds;
+ bool m_dirty;
+ StructTreeTag *top;
+ QValueList<StructTreeTag*> groups;
+ uint groupsCount;
+
+ bool topOpened;
+ QValueList<bool> groupOpened;
+
+ mutable QListViewItem* m_marker; //track that has the drag/drop marker under it
+ QListViewItem* m_draggedItem;
+// mutable QWidget* m_thisWidget; // non const this hack for acceptDrag
+
+protected: // Protected methods
+ /** Do a reparse before showing. */
+ virtual void showEvent(QShowEvent*);
+ /** Clear the problem output when hiding. */
+ virtual void hideEvent(QHideEvent*);
+
+ // drag functions
+ virtual bool acceptDrag(QDropEvent* e) const;
+ virtual void startDrag();
+ virtual void contentsMousePressEvent(QMouseEvent* e);
+
+protected slots: // Protected slots
+ /** The treeview DTD has changed to id. */
+ void slotDTDChanged(int id);
+
+ void slotMouseClickedVPL(int button, QListViewItem*, const QPoint&, int);
+ virtual void slotDropped(QDropEvent* e, QListViewItem* parent, QListViewItem* after);
+
+protected: // Protected attributes
+ Document *write;
+ QTime *timer;
+};
+
+#endif
diff --git a/quanta/treeviews/tagattributeitems.cpp b/quanta/treeviews/tagattributeitems.cpp
new file mode 100644
index 00000000..4b74217d
--- /dev/null
+++ b/quanta/treeviews/tagattributeitems.cpp
@@ -0,0 +1,538 @@
+/***************************************************************************
+ tagattributeitems.cpp
+ ---------------------
+ copyright : (C) 2003 by 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; version 2 of the License. *
+ * *
+ ***************************************************************************/
+
+//qt includes
+#include <qcombobox.h>
+#include <qheader.h>
+#include <qlineedit.h>
+#include <qlistbox.h>
+#include <qpainter.h>
+#include <qstyle.h>
+
+//kde includes
+#include <dcopref.h>
+#include <kapplication.h>
+#include <kcolorcombo.h>
+#include <klistview.h>
+#include <klocale.h>
+#include <kurlrequester.h>
+#include <kdebug.h>
+
+//app includes
+#include "tagattributeitems.h"
+#include "tagattributetree.h"
+#include "node.h"
+#include "tag.h"
+#include "qtag.h"
+#include "document.h"
+#include "quantacommon.h"
+#include "qextfileinfo.h"
+#include "styleeditor.h"
+
+TopLevelItem::TopLevelItem(KListView* parent, const QString &title)
+: KListViewItem(parent, title)
+{
+}
+
+TopLevelItem::TopLevelItem(KListView* parent, QListViewItem* after, const QString &title)
+: KListViewItem(parent, after, title)
+{
+}
+
+TopLevelItem::~TopLevelItem()
+{
+}
+
+
+void TopLevelItem::paintCell(QPainter *p, const QColorGroup &cg,
+ int column, int width, int align)
+{
+ if ( !p )
+ return;
+
+ // make toplevel item names bold
+ if (column == 0 && !parent())
+ {
+ QFont f = p->font();
+ f.setBold(true);
+ p->setFont(f);
+ }
+ KListViewItem::paintCell( p, cg, column, width, align );
+ if (column == 0)
+ {
+ p->setPen(QPen(QColor(0,0,0)));
+ p->drawLine( width - 1, 0, width - 1, height());
+ }
+}
+
+ParentItem::ParentItem(TagAttributeTree *listView, QListViewItem* parent)
+: KListViewItem(parent)
+{
+ m_listView = listView;
+ comboBox = new QComboBox(false, m_listView->viewport() );
+ QRect r = m_listView->itemRect( this );
+ if ( !r.size().isValid() )
+ {
+ m_listView->ensureItemVisible( this );
+ r = m_listView->itemRect( this );
+ }
+ r.setX( m_listView->header()->sectionPos( 0 ) + 20);
+ r.setWidth( m_listView->header()->sectionSize( 0 ) - 20);
+ r = QRect( m_listView->viewportToContents( r.topLeft() ), r.size() );
+ comboBox->resize( r.size() );
+ m_listView->moveChild( comboBox, r.x(), r.y() );
+}
+
+ParentItem::~ParentItem()
+{
+ delete comboBox;
+}
+
+
+void ParentItem::paintCell(QPainter *p, const QColorGroup &cg,
+ int column, int width, int align)
+{
+ if ( !p )
+ return;
+
+ KListViewItem::paintCell( p, cg, column, width, align );
+ if (column == 0)
+ {
+ p->setPen(QPen(QColor(0,0,0)));
+ p->drawLine( width - 1, 0, width - 1, height());
+ }
+}
+
+void ParentItem::addNode(Node *node)
+{
+ if (node)
+ {
+ m_nodeList.append(node);
+ comboBox->insertItem(node->tag->name);
+ }
+}
+
+Node* ParentItem::node(int index)
+{
+ return m_nodeList.at(index);
+}
+
+void ParentItem::showList(bool show)
+{
+ if (show)
+ {
+ comboBox->show();
+ QObject::connect(comboBox, SIGNAL(activated(int)), m_listView, SLOT(slotParentSelected(int)));
+ }
+ else
+ {
+ comboBox->hide();
+ QObject::disconnect(comboBox, SIGNAL(activated(int)), m_listView, SLOT(slotParentSelected(int)));
+ }
+}
+
+//Generic attribute item
+AttributeItem::AttributeItem(QListViewItem* parent, const QString &title, const QString& title2)
+: KListViewItem(parent, title, title2)
+{
+ lin = 0L;
+ lin2 = 0L;
+}
+
+AttributeItem::AttributeItem(EditableTree* listView, QListViewItem* parent, const QString &title, const QString& title2)
+: KListViewItem(parent, title, title2)
+{
+ m_listView = listView;
+ lin = new QLineEdit( m_listView->viewport() );
+ lin2 = new QLineEdit( m_listView->viewport() );
+ QObject::connect( lin, SIGNAL( returnPressed() ), m_listView, SLOT( editorContentChanged() ) );
+ lin->hide();
+ lin2->hide();
+}
+
+AttributeItem::AttributeItem(EditableTree *listView, const QString& title, const QString& title2)
+: KListViewItem(listView, title, title2)
+{
+ m_listView = listView;
+ lin = new QLineEdit( m_listView->viewport() );
+ lin2 = new QLineEdit( m_listView->viewport() );
+ lin2->setText(title);
+ lin->setText(title2);
+ QObject::connect( lin, SIGNAL( returnPressed() ), m_listView, SLOT( editorContentChanged() ) );
+ lin->hide();
+ lin2->hide();
+}
+
+AttributeItem::AttributeItem(EditableTree *listView, const QString& title, const QString& title2,
+ QListViewItem* after)
+: KListViewItem(listView, after, title, title2)
+{
+ m_listView = listView;
+ lin = new QLineEdit( m_listView->viewport() );
+ lin2 = new QLineEdit( m_listView->viewport() );
+ lin2->setText(title);
+ lin->setText(title2);
+ QObject::connect( lin, SIGNAL( returnPressed() ), m_listView, SLOT( editorContentChanged() ) );
+ lin->hide();
+ lin2->hide();
+}
+
+AttributeItem::~AttributeItem()
+{
+ delete lin;
+ delete lin2;
+}
+
+void AttributeItem::paintCell(QPainter *p, const QColorGroup &cg,
+ int column, int width, int align)
+{
+ if ( !p )
+ return;
+ KListViewItem::paintCell( p, cg, column, width, align );
+ if (column == 0)
+ {
+ p->setPen(QPen(QColor(0,0,0)));
+ p->drawLine( width - 1, 0, width - 1, height());
+ }
+}
+
+QString AttributeItem::editorText(int column)
+{
+ if(column == 1)
+ return lin->text();
+ else
+ return lin2->text();
+}
+
+void AttributeItem::replaceCurrentEditor()
+{
+ if(lin->isVisible())
+ {
+ placeEditor(lin, 1);
+ }
+ else if(lin2->isVisible())
+ {
+ placeEditor(lin, 0);
+ }
+}
+
+void AttributeItem::showEditor(int column)
+{
+ if(column == 1)
+ {
+ placeEditor(lin, column);
+ lin->show();
+ lin->setText(text(1));
+ lin->setFocus();
+ }
+ else
+ {
+ placeEditor(lin2, column);
+ lin2->show();
+ lin2->setText(text(0));
+ lin2->setFocus();
+ }
+}
+
+void AttributeItem::hideEditor(int column)
+{
+ m_listView->editorContentChanged();
+ if(column == 1 && lin->isVisible())
+ {
+ setText(1, lin->text());
+ lin->hide();
+ }
+ else if(column == 0 && lin2->isVisible())
+ {
+ setText(0, lin2->text());
+ lin2->hide();
+ }
+}
+
+void AttributeItem::placeEditor( QWidget *w, int column)
+{
+ QRect r = m_listView->itemRect( this );
+ if ( !r.size().isValid() )
+ {
+ m_listView->ensureItemVisible( this );
+ r = m_listView->itemRect( this );
+ }
+ if(column == 1)
+ {
+ r.setX( m_listView->header()->sectionPos( 1 ) );
+ r.setWidth( m_listView->header()->sectionSize( 1 ) - 1 );
+ }
+ else
+ {
+ r.setX( m_listView->header()->sectionPos( 0 ) );
+ r.setWidth( m_listView->header()->sectionSize( 0 ) - 1 );
+ }
+ r = QRect( m_listView->viewportToContents( r.topLeft() ), r.size() );
+ w->resize( r.size() );
+ m_listView->moveChild( w, r.x(), r.y() );
+}
+
+//Boolean attribute item
+AttributeBoolItem::AttributeBoolItem(TagAttributeTree* listView, QListViewItem* parent, const QString &title, const QString& title2)
+: AttributeItem(parent, title, title2)
+{
+ m_listView = listView;
+ combo = new QComboBox( m_listView->viewport() );
+ combo->insertItem((static_cast<TagAttributeTree *>(m_listView))->node()->tag->dtd()->booleanTrue);
+ combo->insertItem((static_cast<TagAttributeTree *>(m_listView))->node()->tag->dtd()->booleanFalse);
+ combo->hide();
+ QObject::connect( combo, SIGNAL( activated(int) ), m_listView, SLOT( editorContentChanged() ) );
+ }
+
+AttributeBoolItem::~AttributeBoolItem()
+{
+ delete combo;
+}
+
+QString AttributeBoolItem::editorText(int)
+{
+ return combo->currentText();
+}
+
+void AttributeBoolItem::showEditor(int)
+{
+ placeEditor(combo);
+ combo->show();
+ if (text(1) == (static_cast<TagAttributeTree *>(m_listView))->node()->tag->dtd()->booleanTrue)
+ combo->setCurrentItem(0);
+ else
+ combo->setCurrentItem(1);
+ combo->setFocus();
+}
+
+void AttributeBoolItem::hideEditor(int)
+{
+ m_listView->editorContentChanged();
+ setText(1, combo->currentText());
+ combo->hide();
+}
+
+//Boolean attribute item
+AttributeUrlItem::AttributeUrlItem(TagAttributeTree* listView, QListViewItem* parent, const QString &title, const QString& title2)
+: AttributeItem(parent, title, title2)
+{
+ m_listView = listView;
+ urlRequester = new KURLRequester( m_listView->viewport() );
+ urlRequester->setMode(KFile::File | KFile::ExistingOnly );
+ urlRequester->hide();
+ QObject::connect( urlRequester, SIGNAL( returnPressed() ), m_listView, SLOT( editorContentChanged() ) );
+ }
+
+AttributeUrlItem::~AttributeUrlItem()
+{
+ delete urlRequester;
+}
+
+QString AttributeUrlItem::editorText(int)
+{
+ KURL url, baseURL;
+ QuantaCommon::setUrl(url, urlRequester->url());
+ baseURL = (static_cast<TagAttributeTree *>(m_listView))->node()->tag->write()->url();
+ baseURL.setPath(baseURL.directory());
+ url = QExtFileInfo::toRelative(url, baseURL);
+ QString s = url.url();
+ if (url.protocol() == (static_cast<TagAttributeTree *>(m_listView))->node()->tag->write()->url().protocol())
+ s.remove(0, url.protocol().length() + 3);
+ return s;
+}
+
+void AttributeUrlItem::showEditor(int)
+{
+ placeEditor(urlRequester);
+ urlRequester->show();
+ KURL url, baseURL;
+ baseURL = (static_cast<TagAttributeTree *>(m_listView))->node()->tag->write()->url();
+ baseURL.setPath(baseURL.directory());
+ QuantaCommon::setUrl(url, text(1));
+ url= QExtFileInfo::toAbsolute(url, baseURL);
+ urlRequester->setURL(url.url());
+ urlRequester->setFocus();
+}
+
+void AttributeUrlItem::hideEditor(int)
+{
+ m_listView->editorContentChanged();
+ setText(1, editorText());
+ urlRequester->hide();
+}
+
+
+//editable listbox
+//Boolean attribute item
+AttributeListItem::AttributeListItem(EditableTree* listView, QListViewItem* parent, const QString &title, const QString& title2, Attribute *attr)
+: AttributeItem(parent, title, title2)
+{
+ m_listView = listView;
+ combo = new QComboBox( m_listView->viewport() );
+ Node *node = (static_cast<TagAttributeTree *>(m_listView))->node();
+ QTag *qTag = QuantaCommon::tagFromDTD(node);
+ if (qTag)
+ {
+ if (!attr)
+ attr = qTag->attribute(title);
+ if (attr)
+ {
+ combo->insertStringList(attr->values);
+ if (attr->source == "dcop") //fill the list with a result of a DCOP call
+ {
+ QString interface = "QuantaIf";
+ if (!attr->interface.isEmpty())
+ interface = attr->interface;
+ QString arguments = attr->arguments;
+ arguments.replace("%tagname%", node->tag->name);
+ DCOPReply reply = QuantaCommon::callDCOPMethod(interface, attr->method, arguments);
+ if (reply.isValid())
+ {
+ QStringList list = reply;
+ combo->insertStringList(list);
+ }
+ }
+
+ }
+ combo->insertItem("", 0);
+ combo->setEditable(true);
+ }
+ combo->hide();
+ QObject::connect( combo, SIGNAL( activated(int) ), m_listView, SLOT( editorContentChanged() ) );
+ }
+
+AttributeListItem::~AttributeListItem()
+{
+ delete combo;
+}
+
+QString AttributeListItem::editorText(int)
+{
+ return combo->currentText();
+}
+
+void AttributeListItem::showEditor(int)
+{
+ placeEditor(combo);
+ combo->show();
+ int index = -1;
+ Node *node = (static_cast<TagAttributeTree *>(m_listView))->node();
+ QTag *qTag = QuantaCommon::tagFromDTD(node);
+ if (qTag)
+ {
+ Attribute *attr = qTag->attribute(text(0));
+ if (attr)
+ {
+ index = attr->values.findIndex(text(1));
+ }
+ }
+ if (index != -1)
+ combo->setCurrentItem(index + 1);
+ else
+ {
+ combo->changeItem(text(1), 0);
+ combo->setCurrentItem(0);
+ }
+ combo->setFocus();
+}
+
+void AttributeListItem::hideEditor(int)
+{
+ m_listView->editorContentChanged();
+ setText(1, combo->currentText());
+ combo->hide();
+}
+
+//editable color combobox
+AttributeColorItem::AttributeColorItem(EditableTree* listView, QListViewItem* parent, const QString &title, const QString& title2)
+: AttributeItem(parent, title, title2)
+{
+ m_listView = listView;
+ combo = new KColorCombo( m_listView->viewport() );
+ combo->setEditable(true);
+ combo->hide();
+ QObject::connect( combo, SIGNAL( activated(int) ), m_listView, SLOT( editorContentChanged() ) );
+ }
+
+AttributeColorItem::~AttributeColorItem()
+{
+ delete combo;
+}
+
+QString AttributeColorItem::editorText(int)
+{
+ QString name = combo->color().name();
+ if (name == "#000000")
+ name = "";
+ combo->setCurrentText(name);
+ return name;
+}
+
+void AttributeColorItem::showEditor(int)
+{
+ placeEditor(combo);
+ combo->show();
+ combo->setColor(text(1));
+ combo->setCurrentText(text(1));
+ combo->setFocus();
+}
+
+void AttributeColorItem::hideEditor(int)
+{
+ m_listView->editorContentChanged();
+ QString name = combo->color().name();
+ if (name == "#000000")
+ name = "";
+ setText(1, name);
+ combo->hide();
+}
+
+//editable style combobox
+AttributeStyleItem::AttributeStyleItem(EditableTree* listView, QListViewItem* parent, const QString &title, const QString& title2)
+: AttributeItem(parent, title, title2)
+{
+ m_listView = listView;
+ m_se = new StyleEditor( m_listView->viewport() );
+ m_se->setButtonIcon(4,0);
+ //combo->setEditable(true);
+ m_se->hide();
+
+ QObject::connect( m_se->button(), SIGNAL( clicked() ), m_listView, SLOT( editorContentChanged() ) );
+ }
+
+AttributeStyleItem::~AttributeStyleItem()
+{
+ delete m_se;
+}
+
+QString AttributeStyleItem::editorText(int)
+{
+ return m_se->lineEdit()->text();
+}
+
+void AttributeStyleItem::showEditor(int)
+{
+ placeEditor(m_se);
+ m_se->show();
+ m_se->lineEdit()->setText(text(1));
+ m_se->setFocus();
+}
+
+void AttributeStyleItem::hideEditor(int)
+{
+ m_listView->editorContentChanged();
+ setText(1, m_se->lineEdit()->text());
+ m_se->hide();
+}
+
diff --git a/quanta/treeviews/tagattributeitems.h b/quanta/treeviews/tagattributeitems.h
new file mode 100644
index 00000000..8d603529
--- /dev/null
+++ b/quanta/treeviews/tagattributeitems.h
@@ -0,0 +1,178 @@
+/***************************************************************************
+ tagattributeitems.h
+ -------------------
+ copyright : (C) 2003 by 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; version 2 of the License. *
+ * *
+ ***************************************************************************/
+
+#ifndef TAGATTRIBUTEITEM_H
+#define TAGATTRIBUTEITEM_H
+
+#include <qptrlist.h>
+
+class KColorCombo;
+class KURLRequester;
+class KListView;
+class KListViewItem;
+class QListViewItem;
+class QLineEdit;
+class QComboBox;
+
+class Attribute;
+class EditableTree;
+class TagAttributeTree;
+class Node;
+class StyleEditor;
+
+class TopLevelItem : public KListViewItem
+{
+
+public:
+ TopLevelItem(KListView *parent, const QString& title);
+ TopLevelItem(KListView *parent, QListViewItem* after, const QString& title);
+
+ virtual ~TopLevelItem();
+
+protected:
+
+ void paintCell( QPainter *p, const QColorGroup &cg,
+ int column, int width, int align );
+};
+
+class ParentItem : public KListViewItem
+{
+
+public:
+ ParentItem(TagAttributeTree *listView, QListViewItem *parent);
+
+ virtual ~ParentItem();
+ Node *node(int index);
+ void addNode(Node *node);
+ void showList(bool show);
+
+protected:
+
+ void paintCell( QPainter *p, const QColorGroup &cg,
+ int column, int width, int align );
+
+private:
+ QPtrList<Node> m_nodeList;
+ QComboBox *comboBox;
+ TagAttributeTree *m_listView;
+};
+
+class AttributeItem : public KListViewItem
+{
+public:
+ AttributeItem(QListViewItem* parent, const QString& title, const QString& title2);
+ AttributeItem(EditableTree *listView, QListViewItem* parent, const QString& title, const QString& title2);
+ AttributeItem(EditableTree *listView, const QString& title, const QString& title2);
+ AttributeItem(EditableTree *listView, const QString& title, const QString& title2, QListViewItem* after);
+
+ virtual ~AttributeItem();
+ virtual void replaceCurrentEditor();
+ virtual void showEditor(int column = 1);
+ virtual void hideEditor(int column = 1);
+ virtual void placeEditor(QWidget *w, int column = 1);
+ virtual QString editorText(int column = 1);
+
+ //I'm not sane... lin is the right editor, lin2 is the left one.
+ QLineEdit *lin, *lin2;
+
+protected:
+
+ void paintCell( QPainter *p, const QColorGroup &cg,
+ int column, int width, int align );
+
+ EditableTree *m_listView;
+};
+
+class AttributeNameSpaceItem:public AttributeItem
+{
+public:
+ AttributeNameSpaceItem(QListViewItem* parent, const QString& title, const QString& title2): AttributeItem(parent, title, title2){};
+ AttributeNameSpaceItem(EditableTree *listView, QListViewItem* parent, const QString& title, const QString& title2):AttributeItem(listView, parent, title, title2){};
+ virtual ~AttributeNameSpaceItem(){};
+
+};
+
+class AttributeBoolItem : public AttributeItem
+{
+public:
+ AttributeBoolItem(TagAttributeTree *listView, QListViewItem* parent, const QString& title, const QString& title2);
+
+ virtual ~AttributeBoolItem();
+ virtual void showEditor(int column = 1);
+ virtual void hideEditor(int column = 1);
+ virtual QString editorText(int column = 1);
+
+private:
+ QComboBox* combo;
+};
+
+class AttributeUrlItem : public AttributeItem
+{
+public:
+ AttributeUrlItem(TagAttributeTree *listView, QListViewItem* parent, const QString& title, const QString& title2);
+
+ virtual ~AttributeUrlItem();
+ virtual void showEditor(int column = 1);
+ virtual void hideEditor(int column = 1);
+ virtual QString editorText(int column = 1);
+
+private:
+ KURLRequester* urlRequester;
+};
+
+class AttributeListItem : public AttributeItem
+{
+public:
+ AttributeListItem(EditableTree *listView, QListViewItem* parent, const QString& title, const QString& title2, Attribute *attr = 0L);
+
+ virtual ~AttributeListItem();
+ virtual void showEditor(int column = 1);
+ virtual void hideEditor(int column = 1);
+ virtual QString editorText(int column = 1);
+
+private:
+ QComboBox* combo;
+};
+
+class AttributeColorItem : public AttributeItem
+{
+public:
+ AttributeColorItem(EditableTree *listView, QListViewItem* parent, const QString& title, const QString& title2);
+
+ virtual ~AttributeColorItem();
+ virtual void showEditor(int column = 1);
+ virtual void hideEditor(int column = 1);
+ virtual QString editorText(int column = 1);
+
+private:
+ KColorCombo* combo;
+};
+
+class AttributeStyleItem : public AttributeItem
+{
+public:
+ AttributeStyleItem(EditableTree *listView, QListViewItem* parent, const QString& title, const QString& title2);
+
+ virtual ~AttributeStyleItem();
+ virtual void showEditor(int column = 1);
+ virtual void hideEditor(int column = 1);
+ virtual QString editorText(int column = 1);
+
+private:
+
+ StyleEditor *m_se;
+};
+
+
+#endif
diff --git a/quanta/treeviews/tagattributetree.cpp b/quanta/treeviews/tagattributetree.cpp
new file mode 100644
index 00000000..a8e4406b
--- /dev/null
+++ b/quanta/treeviews/tagattributetree.cpp
@@ -0,0 +1,659 @@
+/***************************************************************************
+ tagattributetree.cpp
+ ---------------------
+ copyright : (C) 2003 by 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; version 2 of the License. *
+ * *
+ ***************************************************************************/
+
+//qt includes
+#include <qfont.h>
+#include <qpainter.h>
+#include <qtimer.h>
+#include <qlineedit.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qtooltip.h>
+
+//kde includes
+#include <kaction.h>
+#include <klocale.h>
+#include <kpushbutton.h>
+#include <kstringhandler.h>
+#include <kdebug.h>
+#include <kiconloader.h>
+#include <khtmlview.h>
+#include <ktexteditor/editinterface.h>
+#include <ktexteditor/viewcursorinterface.h>
+#include <ktexteditor/view.h>
+#include <dom/dom_node.h>
+
+//app includes
+#include "tagattributetree.h"
+#include "tagattributeitems.h"
+#include "qtag.h"
+#include "node.h"
+#include "parser.h"
+#include "quantacommon.h"
+#include "document.h"
+#include "quantaview.h"
+#include "tag.h"
+#include "wkafkapart.h"
+#include "kafkacommon.h"
+#include "undoredo.h"
+
+#include "viewmanager.h"
+
+EditableTree::EditableTree(QWidget *parent, const char *name)
+: KListView(parent, name)
+{
+ m_editable = true;
+}
+
+EditableTree::~EditableTree()
+{
+
+}
+
+void EditableTree::setCurrentItem( QListViewItem *item)
+{
+ if ( item && m_editable)
+ {
+ QListViewItem *it = currentItem();
+ if ( dynamic_cast<AttributeItem*>(it) )
+ static_cast<AttributeItem*>(it)->hideEditor();
+
+ KListView::setCurrentItem(item);
+ it = currentItem();
+ if ( dynamic_cast<AttributeItem*>(it) )
+ static_cast<AttributeItem*>(it)->showEditor();
+ }
+}
+
+void EditableTree::editorContentChanged()
+{
+
+}
+
+void EditableTree::focusInEvent(QFocusEvent *)
+{
+ /**QListViewItem *it = currentItem();
+ if( dynamic_cast<AttributeItem*>(it))
+ {
+ static_cast<AttributeItem *>(it)->showEditor();
+ static_cast<AttributeItem *>(it)->lin->setFocus();
+ }*/
+}
+
+void EditableTree::focusOutEvent(QFocusEvent *)
+{
+ /**QListViewItem *it = currentItem();
+ if( dynamic_cast<AttributeItem*>(it))
+ {
+ static_cast<AttributeItem *>(it)->hideEditor();
+ }*/
+}
+
+DualEditableTree::DualEditableTree(QWidget *parent, const char *name)
+: EditableTree(parent, name)
+{
+ curCol = 0;
+ setFocusPolicy(QWidget::ClickFocus);
+ this->installEventFilter(this);
+ connect(this, SIGNAL(clicked(QListViewItem *, const QPoint &, int )),
+ this, SLOT(itemClicked(QListViewItem *, const QPoint &, int )));
+}
+
+DualEditableTree::~DualEditableTree()
+{
+
+}
+
+bool DualEditableTree::eventFilter(QObject *object, QEvent *event)
+{
+ AttributeItem *it = dynamic_cast<AttributeItem*>(currentItem());
+ AttributeItem *up = 0L, *down = 0L;
+ if(!it)
+ return KListView::eventFilter(object, event);
+ if(currentItem()->itemAbove())
+ up = dynamic_cast<AttributeItem*>(currentItem()->itemAbove());
+ if(currentItem()->itemBelow())
+ down = dynamic_cast<AttributeItem *>(currentItem()->itemBelow());
+
+ if(event->type() == QEvent::KeyPress && m_editable)
+ {
+ QKeyEvent *keyevent = static_cast<QKeyEvent *>(event);
+ switch(keyevent->key())
+ {
+ case Key_Left:
+ if(curCol == 1 && it->lin->cursorPosition() == 0 )
+ {
+ it->hideEditor(1);
+ it->showEditor(0);
+ it->lin2->setFocus();
+ curCol = 0;
+ }
+ break;
+
+ case Key_Right:
+ if(curCol == 0 && (unsigned)it->lin2->cursorPosition() == it->lin2->text().length())
+ {
+ it->hideEditor(0);
+ it->showEditor(1);
+ it->lin->setFocus();
+ curCol = 1;
+ }
+ break;
+
+ case Key_Up:
+ if(up)
+ {
+ it->hideEditor(curCol);
+ up->showEditor(curCol);
+ }
+ break;
+
+ case Key_Down:
+ if(down)
+ {
+ it->hideEditor(curCol);
+ down->showEditor(curCol);
+ }
+ break;
+ }
+ }
+ return KListView::eventFilter(object, event);;
+}
+
+void DualEditableTree::resizeEvent(QResizeEvent *ev)
+{
+ KListView::resizeEvent(ev);
+ if(!currentItem()) return;
+ AttributeItem *item = dynamic_cast<AttributeItem*>(currentItem());
+ if(item)
+ {
+ item->hideEditor(curCol);
+ item->showEditor(curCol);
+ }
+}
+
+void DualEditableTree::setCurrentItem(QListViewItem *item)
+{
+ if ( item && m_editable)
+ {
+ QListViewItem *it = currentItem();
+ if ( dynamic_cast<AttributeItem*>(it) )
+ {
+ static_cast<AttributeItem*>(it)->hideEditor(0);
+ static_cast<AttributeItem*>(it)->hideEditor(1);
+ }
+
+ KListView::setCurrentItem(item);
+ it = currentItem();
+ if ( dynamic_cast<AttributeItem*>(it) )
+ static_cast<AttributeItem*>(it)->showEditor(curCol);
+ }
+}
+
+void DualEditableTree::editorContentChanged()
+{
+ emit itemModified(dynamic_cast<AttributeItem*>(currentItem()));
+}
+
+void DualEditableTree::itemClicked(QListViewItem *item, const QPoint &, int column)
+{
+ if(item)
+ {
+ curCol = column;
+ if(item == currentItem())
+ setCurrentItem(item);
+ }
+}
+
+TagAttributeTree::TagAttributeTree(QWidget *parent, const char *name)
+: EditableTree(parent, name)
+{
+ setRootIsDecorated( true );
+ setSorting(-1);
+ setFrameStyle( Panel | Sunken );
+ setLineWidth( 2 );
+ setFocusPolicy(QWidget::ClickFocus);
+ addColumn(i18n("Attribute Name"));
+ addColumn(i18n("Value"));
+ setResizeMode(QListView::LastColumn);
+ m_node = 0L;
+ m_newNode = 0L;
+ m_parentItem = 0L;
+ rebuildEnabled = true;
+}
+
+TagAttributeTree::~TagAttributeTree()
+{
+}
+
+void TagAttributeTree::setCurrentNode(Node *node)
+{
+ if (m_node == node)
+ return;
+ m_node = node;
+ emit newNodeSelected(node);
+ if (!rebuildEnabled)
+ return;
+ clear();
+ m_parentItem = 0L;
+ //We don't want to be able to edit the text node but it's parent.
+ if (node && node->tag->type == Tag::Text)
+ m_node = node = node->parent;
+ if (!node)
+ return;
+#ifdef HEAVY_DEBUG
+ kafkaCommon::coutTree(baseNode, 2);
+ KafkaDocument::ref()->coutLinkTree(baseNode, 2);
+#endif
+ AttributeItem *item = 0L;
+ TopLevelItem *group = 0L;
+ QString attrName;
+ QTag *qTag = QuantaCommon::tagFromDTD(node);
+ Node *n = node->parent;
+ while (n)
+ {
+ if (n->tag->type == Tag::XmlTag)
+ {
+ if (!m_parentItem)
+ {
+ group = new TopLevelItem(this, 0L, i18n("Parent tags"));
+ m_parentItem = new ParentItem(this, group);
+ }
+ m_parentItem->addNode(n);
+ }
+ n = n->parent;
+ }
+
+ if (m_parentItem)
+ m_parentItem->showList(true);
+ if (group)
+ group->setOpen(true);
+// if (!node->tag->nameSpace.isEmpty())
+
+ if(node->tag->type == Tag::XmlTag || node->tag->type == Tag::XmlTagEnd)
+ {
+ QString nameSpace = node->tag->nameSpace;
+ if (node->tag->type == Tag::XmlTagEnd)
+ nameSpace.remove('/');
+ group = new TopLevelItem(this, group, i18n("Namespace"));
+ item = new AttributeNameSpaceItem(this, group, i18n("prefix"), nameSpace);
+ group->setOpen(true);
+ }
+ if (qTag)
+ {
+ group = new TopLevelItem(this, group, i18n("Attributes"));
+ QStringList list;
+ for (int i = 0; i < qTag->attributeCount(); i++)
+ {
+ list += qTag->attributeAt(i)->name;
+ }
+ list.sort();
+ QStringList::Iterator it = list.end();
+ --it;
+ while (it != list.end())
+ {
+ Attribute *attr = qTag->attribute(*it);
+ if (attr->type == "check")
+ {
+ item = new AttributeBoolItem(this, group, attr->name, node->tag->attributeValue(attr->name));
+ } else
+ if (attr->type == "url")
+ {
+ item = new AttributeUrlItem(this, group, attr->name, node->tag->attributeValue(attr->name));
+ } else
+ if (attr->type == "list")
+ {
+ item = new AttributeListItem(this, group, attr->name, node->tag->attributeValue(attr->name));
+ } else
+ if (attr->type == "color")
+ {
+ item = new AttributeColorItem(this, group, attr->name, node->tag->attributeValue(attr->name));
+ } else
+ {
+ item = new AttributeItem(this, group, attr->name, node->tag->attributeValue(attr->name));
+ }
+ item->setRenameEnabled(1, true);
+ if (it != list.begin())
+ --it;
+ else
+ break;
+ }
+ group->setOpen(true);
+ for (uint i = 0; i < qTag->commonGroups.count(); i++)
+ {
+ group = new TopLevelItem(this, group, i18n(qTag->commonGroups[i].utf8()));
+ AttributeList *groupAttrs = qTag->parentDTD->commonAttrs->find(qTag->commonGroups[i]);
+ for (uint j = 0; j < groupAttrs->count(); j++)
+ {
+ Attribute *attr = groupAttrs->at(j);
+ attrName = attr->name;
+ if (attr->type == "check")
+ {
+ item = new AttributeBoolItem(this, group, attrName, node->tag->attributeValue(attrName));
+ } else
+ if (attr->type == "url")
+ {
+ item = new AttributeUrlItem(this, group, attr->name, node->tag->attributeValue(attr->name));
+ } else
+ if (attr->type == "list")
+ {
+ item = new AttributeListItem(this, group, attr->name, node->tag->attributeValue(attr->name), attr);
+ } else
+ if (attr->type == "color")
+ {
+ item = new AttributeColorItem(this, group, attr->name, node->tag->attributeValue(attr->name));
+ } else
+ if (attr->type == "css-style")
+ {
+ item = new AttributeStyleItem(this, group, attr->name, node->tag->attributeValue(attr->name));
+ } else
+ {
+ item = new AttributeItem(this, group, attrName, node->tag->attributeValue(attrName));
+ }
+ item->setRenameEnabled(1, true);
+ }
+ group->setOpen(true);
+ }
+
+ }
+ connect(this, SIGNAL(collapsed(QListViewItem*)), SLOT(slotCollapsed(QListViewItem*)));
+ connect(this, SIGNAL(expanded(QListViewItem*)), SLOT(slotExpanded(QListViewItem*)));
+}
+
+void TagAttributeTree::editorContentChanged()
+{
+ AttributeItem *item = dynamic_cast<AttributeItem*>(currentItem());
+ if (m_node && item )
+ {
+ rebuildEnabled = false;
+ if (dynamic_cast<AttributeNameSpaceItem*>(item))
+ {
+ QString nameSpace = item->editorText();
+ m_node->tag->write()->changeTagNamespace(m_node->tag, nameSpace);
+ } else
+ {
+ if(ViewManager::ref()->activeView()->hadLastFocus() == QuantaView::SourceFocus)
+ {
+ m_node->tag->write()->changeTagAttribute(m_node->tag, item->text(0), item->editorText());
+ }
+ else
+ {
+ //edit the attribute
+ NodeModifsSet *modifs = new NodeModifsSet();
+ kafkaCommon::editNodeAttribute(m_node, item->text(0), item->editorText(), modifs);
+ ViewManager::ref()->activeDocument()->docUndoRedo->addNewModifsSet(modifs, undoRedo::NodeTreeModif);
+
+#ifdef HEAVY_DEBUG
+ kafkaCommon::coutTree(baseNode, 2);
+#endif
+ }
+ }
+ rebuildEnabled = true;
+ }
+}
+
+/**void TagAttributeTree::setCurrentItem( QListViewItem *item )
+{
+ if ( item )
+ {
+ QListViewItem *it = currentItem();
+ if ( dynamic_cast<AttributeItem*>(it) )
+ static_cast<AttributeItem*>(it)->hideEditor();
+
+ KListView::setCurrentItem(item);
+ it = currentItem();
+ if ( dynamic_cast<AttributeItem*>(it) )
+ static_cast<AttributeItem*>(it)->showEditor();
+ }
+}*/
+
+void TagAttributeTree::slotParentSelected(int index)
+{
+ if (m_parentItem)
+ {
+ m_newNode = m_parentItem->node(index);
+ QTimer::singleShot(0, this, SLOT(slotDelayedSetCurrentNode()));
+ }
+}
+
+void TagAttributeTree::slotCollapsed(QListViewItem *item)
+{
+ if (m_parentItem && item == m_parentItem->parent())
+ m_parentItem->showList(false);
+}
+
+void TagAttributeTree::slotExpanded(QListViewItem *item)
+{
+ if (m_parentItem && item == m_parentItem->parent())
+ m_parentItem->showList(true);
+}
+
+void TagAttributeTree::slotDelayedSetCurrentNode()
+{
+ setCurrentNode(m_newNode);
+ if (ViewManager::ref()->activeDocument())
+ {
+ if (ViewManager::ref()->activeView()->hadLastFocus() == QuantaView::SourceFocus)
+ ViewManager::ref()->activeDocument()->view()->setFocus();
+ else
+ KafkaDocument::ref()->getKafkaWidget()->view()->setFocus();
+ }
+}
+
+EnhancedTagAttributeTree::EnhancedTagAttributeTree(QWidget *parent, const char *name)
+: QWidget(parent, name)
+{
+
+ widgetLayout = new QGridLayout( this, 1, 1, 11, 6, "MainLayout");
+
+ attrTree = new TagAttributeTree(this, "TagAttributeTree");
+ attrTree->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::MinimumExpanding);
+ widgetLayout->addMultiCellWidget( attrTree, 1, 1, 0, 3 );
+
+ nodeName = new QLabel(this, i18n( "Node Name" ));
+ nodeName->setSizePolicy( QSizePolicy( QSizePolicy::MinimumExpanding, QSizePolicy::Fixed, 0, 0, nodeName->sizePolicy().hasHeightForWidth() ) );
+
+ widgetLayout->addWidget( nodeName, 0, 0 );
+ deleteTag = new KPushButton(this, i18n( "Delete Tag" ));
+ deleteTag->setPixmap(SmallIcon("editdelete"));
+ deleteTag->setMaximumHeight(32);
+ deleteTag->setMaximumWidth(32);
+ QToolTip::add(deleteTag, i18n("Delete the current tag only."));
+
+ deleteAll = new KPushButton(this, i18n( "Delete All" ));
+ deleteAll->setPixmap(SmallIcon("editdelete"));
+ deleteAll->setMaximumHeight(32);
+ deleteAll->setMaximumWidth(32);
+ QToolTip::add(deleteAll, i18n("Delete the current tag and all its children."));
+
+ widgetLayout->addWidget( deleteTag, 0, 2 );
+ widgetLayout->addWidget( deleteAll, 0, 3 );
+ clearWState( WState_Polished );
+
+ connect(attrTree, SIGNAL(newNodeSelected(Node *)), this, SLOT(NodeSelected(Node *)));
+ connect(deleteTag, SIGNAL(clicked()), this, SLOT(deleteNode()));
+ connect(deleteAll, SIGNAL(clicked()), this, SLOT(deleteSubTree()));
+}
+
+EnhancedTagAttributeTree::~EnhancedTagAttributeTree()
+{
+
+}
+
+void EnhancedTagAttributeTree::setCurrentNode(Node *node)
+{
+ curNode = node;
+ attrTree->setCurrentNode(node);
+ showCaption();
+}
+
+void EnhancedTagAttributeTree::NodeSelected(Node *node)
+{
+ curNode = node;
+ //We don't want to be able to edit the text node but it's parent.
+ if (node && node->tag->type == Tag::Text)
+ curNode = node = node->parent;
+ showCaption();
+ emit newNodeSelected(node);
+}
+
+void EnhancedTagAttributeTree::showCaption()
+{
+ if(curNode)
+ {
+ if(curNode->tag->type == Tag::XmlTag || curNode->tag->type == Tag::XmlTagEnd ||
+ curNode->tag->type == Tag::ScriptTag)
+ {
+ QString s = i18n("Current tag: <b>%1</b>").arg(curNode->tag->name);
+ nodeName->setText(KStringHandler::rPixelSqueeze(s, nodeName->fontMetrics(), attrTree->width()- 50));
+ }
+ else if(curNode->tag->type == Tag::Text)
+ nodeName->setText(i18n("Current tag: <b>text</b>"));
+ else if(curNode->tag->type == Tag::Comment)
+ nodeName->setText(i18n("Current tag: <b>comment</b>"));
+ else
+ nodeName->setText(i18n("Current tag:"));
+ }
+}
+
+void EnhancedTagAttributeTree::deleteSubTree()
+{
+ QuantaView *view = ViewManager::ref()->activeView();
+ if(!curNode || !view->document())
+ return;
+ Node *oldCurNode;
+ NodeModifsSet *modifs;
+ int curLine, curCol;
+ long offset;
+ DOM::Node domNode;
+ QValueList<int> loc;
+
+ //Save the cursor position in kafka/quanta
+ if(view->hadLastFocus() == QuantaView::SourceFocus)
+ curNode->tag->beginPos(curLine, curCol);
+ else
+ {
+ KafkaDocument::ref()->getKafkaWidget()->getCurrentNode(domNode, offset);
+ if(!domNode.previousSibling().isNull())
+ domNode = domNode.previousSibling();
+ else if(!domNode.parentNode().isNull())
+ domNode = domNode.parentNode();
+ else
+ domNode = KafkaDocument::ref()->getKafkaWidget()->document();
+ if(domNode.nodeType() == DOM::Node::TEXT_NODE)
+ offset = domNode.nodeValue().length();
+ else
+ offset = 0;
+ loc = kafkaCommon::getLocation(domNode);
+ }
+
+ //Remove the Nodes
+ oldCurNode = curNode;
+ curNode = 0L;
+ attrTree->setCurrentNode(curNode);
+
+ modifs = new NodeModifsSet();
+ kafkaCommon::extractAndDeleteNode(oldCurNode, modifs);
+
+ view->document()->docUndoRedo->addNewModifsSet(modifs, undoRedo::NodeTreeModif);
+
+ //set the cursor position in kafka/quanta
+ if(view->hadLastFocus() == QuantaView::SourceFocus)
+ view->document()->viewCursorIf->setCursorPositionReal((uint)curLine, (uint)curCol);
+ else
+ {
+ domNode = kafkaCommon::getNodeFromLocation(loc,
+ KafkaDocument::ref()->getKafkaWidget()->document());
+ KafkaDocument::ref()->getKafkaWidget()->setCurrentNode(domNode, offset);
+ }
+}
+
+void EnhancedTagAttributeTree::deleteNode()
+{
+ QuantaView *view = ViewManager::ref()->activeView();
+ if(!curNode || !view->document())
+ return;
+
+ Node *oldCurNode, *oldCurNodeParent, *child;
+ QTag *oldCurNodeParentQTag;
+ int curLine, curCol;
+ long offset;
+ DOM::Node domNode;
+ QValueList<int> loc;
+ NodeModifsSet *modifs;
+
+ //Save the cursor position in kafka/quanta
+ if(view->hadLastFocus() == QuantaView::SourceFocus)
+ curNode->tag->beginPos(curLine, curCol);
+ else
+ {
+ KafkaDocument::ref()->getKafkaWidget()->getCurrentNode(domNode, offset);
+ if(!domNode.previousSibling().isNull())
+ domNode = domNode.previousSibling();
+ else if(!domNode.parentNode().isNull())
+ domNode = domNode.parentNode();
+ else
+ domNode = KafkaDocument::ref()->getKafkaWidget()->document();
+ if(domNode.nodeType() == DOM::Node::TEXT_NODE)
+ offset = domNode.nodeValue().length();
+ else
+ offset = 0;
+ loc = kafkaCommon::getLocation(domNode);
+ }
+
+ //remove the Nodes
+ oldCurNode = curNode;
+ oldCurNodeParent = curNode->parent;
+ curNode = 0L;
+ attrTree->setCurrentNode(curNode);
+
+ modifs = new NodeModifsSet();
+ kafkaCommon::extractAndDeleteNode(oldCurNode, modifs, false);
+
+ //Then we see if the new parent - child relationships are valid, and if not, delete the child and restart
+ if(oldCurNodeParent)
+ {
+ oldCurNodeParentQTag = QuantaCommon::tagFromDTD(oldCurNodeParent);
+ if(oldCurNodeParentQTag)
+ {
+ child = oldCurNodeParent->child;
+ while(child)
+ {
+ if(!oldCurNodeParentQTag->isChild(child))
+ {
+ kafkaCommon::extractAndDeleteNode(child, modifs, false);
+ //too lazy to get the real next node ;-)
+ child = oldCurNodeParent->child;
+ }
+ else
+ child = child->next;
+ }
+ }
+ }
+
+ view->document()->docUndoRedo->addNewModifsSet(modifs, undoRedo::NodeTreeModif);
+
+ //set the cursor position in kafka/quanta
+ if(view->hadLastFocus() == QuantaView::SourceFocus)
+ view->document()->viewCursorIf->setCursorPositionReal((uint)curLine, (uint)curCol);
+ else
+ {
+ domNode = kafkaCommon::getNodeFromLocation(loc,
+ KafkaDocument::ref()->getKafkaWidget()->document());
+ KafkaDocument::ref()->getKafkaWidget()->setCurrentNode(domNode, offset);
+ }
+
+}
+
+#include "tagattributetree.moc"
diff --git a/quanta/treeviews/tagattributetree.h b/quanta/treeviews/tagattributetree.h
new file mode 100644
index 00000000..bae0f3ff
--- /dev/null
+++ b/quanta/treeviews/tagattributetree.h
@@ -0,0 +1,143 @@
+/***************************************************************************
+ tagattributetree.h
+ -------------------
+ copyright : (C) 2003 by 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; version 2 of the License. *
+ * *
+ ***************************************************************************/
+
+#ifndef TAGATTRIBUTETREE_H
+#define TAGATTRIBUTETREE_H
+
+//qt includes
+#include <qwidget.h>
+
+//kde includes
+#include <klistview.h>
+
+//app includes
+
+class KListView;
+class QListViewItem;
+class ParentItem;
+class Node;
+class QLabel;
+class KPushButton;
+class QGridLayout;
+
+class EditableTree : public KListView {
+Q_OBJECT
+
+public:
+ EditableTree(QWidget *parent = 0, const char *name = 0);
+ virtual ~EditableTree();
+
+ virtual void setCurrentItem( QListViewItem *i);
+ void setEditable(bool b) {m_editable = b;}
+ bool isEditable() {return m_editable;}
+
+public slots:
+ virtual void editorContentChanged();
+ virtual void focusInEvent(QFocusEvent *);
+ virtual void focusOutEvent(QFocusEvent *);
+
+protected:
+ bool m_editable;
+
+};
+
+class DualEditableTree : public EditableTree
+{
+ Q_OBJECT
+public:
+ DualEditableTree(QWidget *parent = 0, const char *name = 0);
+ virtual ~DualEditableTree();
+
+ virtual void setCurrentItem ( QListViewItem *i);
+ int currentColumn() {return curCol;}
+
+protected:
+ virtual bool eventFilter(QObject *object, QEvent *event);
+ virtual void resizeEvent(QResizeEvent *);
+
+signals:
+ void itemModified( QListViewItem *);
+
+public slots:
+ virtual void editorContentChanged();
+
+private slots:
+ void itemClicked(QListViewItem *i, const QPoint &point, int col);
+
+private:
+ int curCol;
+};
+
+class TagAttributeTree : public EditableTree {
+ Q_OBJECT
+
+public:
+ TagAttributeTree(QWidget *parent=0, const char *name=0);
+ virtual ~TagAttributeTree();
+
+ void setCurrentNode(Node *node);
+ //virtual void setCurrentItem( QListViewItem *i );
+ Node *node() const {return m_node;}
+
+public slots:
+ void slotDelayedSetCurrentNode();
+ void slotParentSelected(int index);
+ virtual void editorContentChanged();
+
+private slots:
+ void slotCollapsed(QListViewItem *item);
+ void slotExpanded(QListViewItem *item);
+
+signals:
+ void newNodeSelected(Node *node);
+
+private:
+ Node *m_node;
+ Node *m_newNode;
+ bool rebuildEnabled;
+ ParentItem *m_parentItem;
+};
+
+//An enhanced TagAttributeTree with the tag name and buttons to delete the tag.
+class EnhancedTagAttributeTree : public QWidget
+{
+Q_OBJECT
+public:
+ EnhancedTagAttributeTree(QWidget *parent = 0, const char *name = 0);
+ virtual ~EnhancedTagAttributeTree();
+
+ void setCurrentNode(Node *node);
+ Node *node() const {return attrTree->node();}
+
+signals:
+ void newNodeSelected(Node *node);
+
+private slots:
+ void NodeSelected(Node *node);
+ void deleteNode();
+ void deleteSubTree();
+
+private:
+ void showCaption();
+
+ QLabel *nodeName;
+ KPushButton* deleteAll;
+ KPushButton* deleteTag;
+ TagAttributeTree *attrTree;
+ QGridLayout *widgetLayout;
+ Node *curNode;
+};
+
+#endif
+
diff --git a/quanta/treeviews/templatedirform.ui b/quanta/treeviews/templatedirform.ui
new file mode 100644
index 00000000..4ab6d6c1
--- /dev/null
+++ b/quanta/treeviews/templatedirform.ui
@@ -0,0 +1,170 @@
+<!DOCTYPE UI><UI version="3.1" stdsetdef="1">
+<class>TemplateDirForm</class>
+<comment>/***************************************************************************
+ * *
+ * 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; version 2 of the License. *
+ * *
+ ***************************************************************************/
+
+</comment>
+<author>(C) 2002 by Andras Mantia &lt;amantia@kde.org&gt;</author>
+<widget class="QDialog">
+ <property name="name">
+ <cstring>TemplateDirForm</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>309</width>
+ <height>157</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>Create Template Folder</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel" row="1" column="0">
+ <property name="name">
+ <cstring>TextLabel2</cstring>
+ </property>
+ <property name="text">
+ <string>Type:</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>TextLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>Name:</string>
+ </property>
+ </widget>
+ <widget class="KComboBox" row="1" column="1">
+ <property name="name">
+ <cstring>typesCombo</cstring>
+ </property>
+ </widget>
+ <widget class="QLineEdit" row="0" column="1">
+ <property name="name">
+ <cstring>dirName</cstring>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="2" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>parentAttr</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Inherit parent attribute</string>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget" row="3" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>layout4</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <spacer>
+ <property name="name">
+ <cstring>spacer1</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>38</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>buttonOk</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;OK</string>
+ </property>
+ <property name="default">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer3</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>25</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>buttonCancel</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Cancel</string>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>38</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </hbox>
+ </widget>
+ </grid>
+</widget>
+<connections>
+ <connection>
+ <sender>parentAttr</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>typesCombo</receiver>
+ <slot>setDisabled(bool)</slot>
+ </connection>
+</connections>
+<tabstops>
+ <tabstop>dirName</tabstop>
+ <tabstop>typesCombo</tabstop>
+ <tabstop>parentAttr</tabstop>
+ <tabstop>buttonOk</tabstop>
+ <tabstop>buttonCancel</tabstop>
+</tabstops>
+<slots>
+ <slot>okBtn_clicked()</slot>
+</slots>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>kcombobox.h</includehint>
+</includehints>
+</UI>
diff --git a/quanta/treeviews/templatestreeview.cpp b/quanta/treeviews/templatestreeview.cpp
new file mode 100644
index 00000000..e87e2428
--- /dev/null
+++ b/quanta/treeviews/templatestreeview.cpp
@@ -0,0 +1,1079 @@
+/***************************************************************************
+ templatestreeview.cpp - description
+ -------------------
+ begin : Thu Dec 20 2001
+ copyright : (C) 2001-2004 by 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; version 2 of the License. *
+ * *
+ ***************************************************************************/
+
+#include <unistd.h>
+#include <grp.h>
+#include <pwd.h>
+#include <sys/types.h>
+
+// QT includes
+#include <qbuttongroup.h>
+#include <qcheckbox.h>
+#include <qclipboard.h>
+#include <qdir.h>
+#include <qpixmap.h>
+#include <qheader.h>
+#include <qpoint.h>
+#include <qlayout.h>
+#include <qtextedit.h>
+#include <qregexp.h>
+#include <qlabel.h>
+#include <qmap.h>
+#include <qwidgetstack.h>
+
+// KDE includes
+#include <kapplication.h>
+#include <klocale.h>
+#include <kiconloader.h>
+#include <kstandarddirs.h>
+#include <kmainwindow.h>
+#include <kmimetype.h>
+#include <kmessagebox.h>
+#include <kcombobox.h>
+#include <kpopupmenu.h>
+#include <kpropertiesdialog.h>
+#include <kurlrequester.h>
+#include <kurlrequesterdlg.h>
+#include <ktempdir.h>
+#include <ktempfile.h>
+#include <kio/netaccess.h>
+#include <kurldrag.h>
+#include <ktar.h>
+#include <kdebug.h>
+#include <kfile.h>
+
+
+#include "templatestreeview.h"
+#include "copyto.h"
+#include "newtemplatedirdlg.h"
+#include "qextfileinfo.h"
+#include "quantanetaccess.h"
+#include "quantapropertiespage.h"
+#include "resource.h"
+#include "tagaction.h"
+#include "tagmaildlg.h"
+
+#define EXCLUDE ".*\\.tmpl$"
+#define TMPL ".tmpl"
+#define NONE "None"
+
+
+const QString textMenu = I18N_NOOP("Insert as &Text");
+const QString binaryMenu = I18N_NOOP("Insert &Link to File");
+const QString docMenu = I18N_NOOP("&New Document Based on This");
+const QString siteMenu = I18N_NOOP("&Extract Site Template To...");
+QMap<QString, QString> typeToi18n;
+QMap<QString, QString> i18nToType;
+
+
+//TemplatesTreeBranch implementation
+TemplatesTreeBranch::TemplatesTreeBranch(KFileTreeView *parent, const KURL& url,
+ const QString& name, const QPixmap& pix,
+ bool showHidden,
+ KFileTreeViewItem *branchRoot)
+ : BaseTreeBranch(parent, url, name, pix, showHidden, branchRoot)
+{
+}
+
+KFileTreeViewItem* TemplatesTreeBranch::createTreeViewItem(KFileTreeViewItem *parent,
+ KFileItem *fileItem )
+{
+ BaseTreeViewItem *tvi = 0;
+ if( parent && fileItem )
+ {
+ KURL url = fileItem->url();
+ tvi = new BaseTreeViewItem( parent, fileItem, this );
+ if (tvi && fileItem->isDir())
+ {
+ if (url.isLocalFile())
+ {
+ QDir dir (url.path(), "", QDir::All);
+ tvi->setExpandable(dir.count() != 2); // . and .. are always there
+ } else {
+ tvi->setExpandable(true); // we assume there is something
+ }
+ } else
+ {
+ url = static_cast<BaseTreeViewItem*>(parent)->url();
+ }
+ QFileInfo dotFileInfo(url.path() + "/.dirinfo");
+ while ((!dotFileInfo.exists()) && (dotFileInfo.dirPath() != "/"))
+ {
+ dotFileInfo.setFile(QFileInfo(dotFileInfo.dirPath()).dirPath()+"/.dirinfo");
+ }
+ if (dotFileInfo.exists())
+ {
+ KConfig *config = new KConfig(dotFileInfo.filePath());
+ QString s = config->readEntry("Type");
+ tvi->setText(1, typeToi18n[s]);
+ delete config;
+ }
+
+ }
+ else
+ kdDebug(24000) << "TemplatesTreeBranch::createTreeViewItem: Have no parent" << endl;
+ return tvi;
+}
+
+
+
+TemplatesTreeView::TemplatesTreeView(KMainWindow *parent, const char *name )
+ : BaseTreeView(parent,name), m_projectDir(0), m_mainWindow(parent)
+{
+ typeToi18n["text/all"] = i18n("Text Snippet");
+ typeToi18n["file/all"] = i18n("Binary File");
+ typeToi18n["template/all"] = i18n("Document Template");
+ typeToi18n["site/all"] = i18n("Site Template");
+ i18nToType[i18n("Text Snippet")] = "text/all";
+ i18nToType[i18n("Binary File")] = "file/all";
+ i18nToType[i18n("Document Template")] = "template/all";
+ i18nToType[i18n("Site Template")] = "site/all";
+
+ m_fileMenu = new KPopupMenu(this);
+
+ m_openId = m_fileMenu->insertItem(i18n("Open"), this ,SLOT(slotInsert()));
+ m_fileMenu->insertItem(SmallIcon("fileopen"), i18n("&Open"), this ,SLOT(slotOpen()));
+ m_fileMenu->insertItem(SmallIcon("mail_send"), i18n("Send in E&mail..."), this, SLOT(slotSendInMail()));
+ m_fileMenu->insertItem(SmallIcon("network"), i18n("&Upload Template..."), this, SLOT(slotUploadTemplate()));
+ m_insertFileInProject = m_fileMenu->insertItem(i18n("&Insert in Project..."), this, SLOT(slotInsertInProject()));
+ m_menuClose = m_fileMenu->insertItem(SmallIcon("fileclose"), i18n("Clos&e"), this, SLOT(slotClose()));
+ m_fileMenu->insertSeparator();
+ m_fileMenu->insertItem(SmallIcon("editcopy"), i18n("&Copy"), this, SLOT(slotCopy()));
+ m_fileMenu->insertItem(SmallIcon("editdelete"), i18n("&Delete"), this, SLOT(slotDelete()));
+ m_fileMenu->insertSeparator();
+ m_fileMenu->insertItem(SmallIcon("info"), i18n("&Properties"), this, SLOT(slotProperties()));
+
+ m_folderMenu = new KPopupMenu(this);
+
+ m_folderMenu->insertItem(SmallIcon("folder_new"), i18n("&New Folder..."), this, SLOT(slotNewDir()));
+ m_folderMenu->insertItem(SmallIcon("mail_send"), i18n("Send in E&mail..."), this, SLOT(slotSendInMail()));
+ m_folderMenu->insertItem(SmallIcon("network"), i18n("&Upload Template..."), this, SLOT(slotUploadTemplate()));
+ m_downloadMenuId = m_folderMenu->insertItem(SmallIcon("network"), i18n("&Download Template..."), this, SIGNAL(downloadTemplate()));
+ m_insertFolderInProject = m_folderMenu->insertItem(i18n("&Insert in Project..."), this, SLOT(slotInsertDirInProject()));
+ m_folderMenu->insertSeparator();
+ m_folderMenu->insertItem(SmallIcon("editcopy"), i18n("&Copy"), this, SLOT(slotCopy()));
+ m_menuPasteFolder = m_folderMenu->insertItem(SmallIcon("editpaste"), i18n("&Paste"), this, SLOT(slotPaste()));
+ m_deleteMenuId = m_folderMenu->insertItem(SmallIcon("editdelete"), i18n("&Delete"), this, SLOT(slotDelete()));
+ m_folderMenu->insertSeparator();
+ m_folderMenu->insertItem(SmallIcon("info"), i18n("&Properties"), this, SLOT(slotProperties()));
+ m_reloadMenuId = m_folderMenu->insertItem(SmallIcon("revert"), i18n("&Reload"), this, SLOT(slotReload()));
+
+ m_emptyAreaMenu = new KPopupMenu(this);
+ m_emptyAreaMenu->insertItem(SmallIcon("network"), i18n("&Download Template..."), this, SIGNAL(downloadTemplate()));
+
+ addColumn(i18n("Templates"), -1);
+ addColumn(i18n("Group"), -1);
+
+ globalURL.setPath(qConfig.globalDataDir + resourceDir + "templates/");
+ newBranch(globalURL);
+
+ localURL.setPath(locateLocal("data", resourceDir + "templates/"));
+ newBranch(localURL);
+
+ connect(this, SIGNAL(contextMenu(KListView*, QListViewItem*, const QPoint&)),
+ this, SLOT(slotMenu(KListView*, QListViewItem*, const QPoint&)));
+
+ connect(this, SIGNAL(open(QListViewItem *)),
+ this, SLOT(slotSelectFile(QListViewItem *)));
+
+ setAcceptDrops(true);
+ setSelectionMode(QListView::Single);
+ setDragEnabled(true);
+ setSaveOpenFolder(true);
+ 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);
+}
+
+TemplatesTreeView::~TemplatesTreeView()
+{
+}
+
+
+KFileTreeBranch* TemplatesTreeView::newBranch(const KURL& url)
+{
+ BaseTreeBranch *newBrnch;
+ if (url == globalURL)
+ {
+ newBrnch = new TemplatesTreeBranch(this, url, i18n("Global Templates"), SmallIcon("ttab"));
+ } else
+ {
+ if (url == localURL)
+ newBrnch = new TemplatesTreeBranch(this, url, i18n("Local Templates"), SmallIcon("ttab"));
+ else
+ {
+ newBrnch = new TemplatesTreeBranch(this, url, i18n("Project Templates"), SmallIcon("ptab"));
+ m_projectDir = newBrnch;
+ }
+ }
+ newBrnch->excludeFilterRx.setPattern(EXCLUDE);
+ addBranch(newBrnch);
+ if (url.isLocalFile())
+ {
+ QDir dir (url.path(), "", QDir::All);
+ newBrnch->root()->setExpandable(dir.count() != 2); // . and .. are always there
+ } else {
+ newBrnch->root()->setExpandable(true); // we assume there is something
+ }
+
+ return newBrnch;
+}
+
+
+/** No descriptions */
+void TemplatesTreeView::slotInsertInDocument()
+{
+
+ KURL url = filterTemplate();
+ if (QuantaCommon::checkMimeGroup(url, "text"))
+ {
+ emit insertFile(url);
+ } else
+ {
+ if (QuantaCommon::denyBinaryInsert(this) == KMessageBox::Yes)
+ {
+ emit insertFile(url);
+ }
+ }
+
+}
+
+void TemplatesTreeView::slotMenu(KListView*, QListViewItem *item, const QPoint &point)
+{
+ if (!item)
+ {
+ m_emptyAreaMenu->popup(point);
+ return;
+ }
+ setSelected(item, true);
+ bool hasProject = m_projectName;
+ m_folderMenu->setItemVisible(m_insertFolderInProject, hasProject);
+ m_fileMenu->setItemVisible(m_insertFileInProject, hasProject);
+
+ KFileTreeViewItem *curItem = currentKFileTreeViewItem();
+ if ( curItem->isDir() )
+ {
+ m_folderMenu->setItemVisible(m_menuPasteFolder, isPathInClipboard());
+ if ( curItem == curItem->branch()->root())
+ {
+ m_folderMenu ->setItemVisible(m_deleteMenuId, false);
+ m_folderMenu ->setItemVisible(m_reloadMenuId, true);
+ m_folderMenu ->setItemVisible(m_downloadMenuId, true);
+ } else
+ {
+ m_folderMenu ->setItemVisible(m_deleteMenuId, true);
+ m_folderMenu ->setItemVisible(m_reloadMenuId, false);
+ m_folderMenu ->setItemVisible(m_downloadMenuId, false);
+ }
+ m_folderMenu ->popup(point);
+ } else
+ {
+ m_dirInfo = readDirInfo();
+
+ QString menuText = "";
+
+ if (m_dirInfo.mimeType.upper().contains("TEXT"))
+ menuText = i18n(textMenu.utf8());
+ else if (m_dirInfo.mimeType.upper().contains("FILE"))
+ menuText = i18n(binaryMenu.utf8());
+ else if (m_dirInfo.mimeType.upper().contains("TEMPLATE"))
+ menuText = i18n(docMenu.utf8());
+ else if (m_dirInfo.mimeType.upper().contains("SITE"))
+ menuText = i18n(siteMenu.utf8());
+
+ if (menuText.isEmpty())
+ {
+ m_fileMenu->setItemVisible(m_openId, false);
+ } else
+ {
+ m_fileMenu->setItemVisible(m_openId, true);
+ m_fileMenu->changeItem(m_openId, menuText);
+ }
+ m_fileMenu->setItemVisible(m_menuClose, isFileOpen(currentURL()));
+
+ m_fileMenu->popup( point);
+ }
+}
+/** No descriptions */
+void TemplatesTreeView::slotNewDocument()
+{
+ KURL url = filterTemplate();
+ if (QuantaCommon::checkMimeGroup(url, "text") || QuantaCommon::denyBinaryInsert(this) == KMessageBox::Yes)
+ {
+ QListViewItem *item = currentItem();
+ if (item )
+ {
+ if ( currentKFileTreeViewItem() != currentKFileTreeViewItem()->branch()->root())
+ {
+ emit openFile(KURL());
+ emit insertFile(url);
+ }
+ }
+ }
+}
+
+/** Insert the template as text, image, new document. */
+void TemplatesTreeView::slotInsert()
+{
+ QString menuText = m_fileMenu->text(m_openId);
+
+ if (menuText == i18n(textMenu.utf8()))
+ slotInsertInDocument();
+ else if (menuText == i18n(binaryMenu.utf8()))
+ slotInsertTag();
+ else if (menuText == i18n(docMenu.utf8()))
+ slotNewDocument();
+ if (menuText == i18n(siteMenu.utf8()))
+ slotExtractSiteTemplate();
+}
+
+void TemplatesTreeView::slotSelectFile(QListViewItem *item)
+{
+ if ( !item ) return;
+
+ KFileTreeViewItem *kftvItem = currentKFileTreeViewItem();
+ if ( !kftvItem ) return;
+
+ if ( !kftvItem->isDir() )
+ {
+ m_dirInfo = readDirInfo();
+/* if (m_dirInfo.mimeType.upper().contains("SITE"))
+ {
+ slotExtractSiteTemplate();
+ return;
+ }*/
+ if (expandArchiv(kftvItem)) return;
+ if (m_dirInfo.mimeType.upper().contains("TEXT"))
+ slotInsertInDocument();
+ else if (m_dirInfo.mimeType.upper().contains("FILE"))
+ slotInsertTag();
+ else if (m_dirInfo.mimeType.upper().contains("TEMPLATE"))
+ slotNewDocument();
+ }
+}
+
+void TemplatesTreeView::slotOpen()
+{
+ BaseTreeView::slotSelectFile(currentItem());
+}
+
+/** No descriptions */
+void TemplatesTreeView::slotNewDir()
+{
+ NewTemplateDirDlg *createDirDlg = new NewTemplateDirDlg(this,i18n("Create New Template Folder"));
+ createDirDlg->typesCombo->insertItem(typeToi18n["text/all"]);
+ createDirDlg->typesCombo->insertItem(typeToi18n["file/all"]);
+ createDirDlg->typesCombo->insertItem(typeToi18n["template/all"]);
+ createDirDlg->typesCombo->insertItem(typeToi18n["site/all"]);
+
+ m_dirInfo = readDirInfo();
+
+ if (m_dirInfo.mimeType.isEmpty())
+ {
+ createDirDlg->parentAttr->setText(i18n("&Inherit parent attribute (nothing)"));
+ } else
+ {
+ createDirDlg->parentAttr->setText(i18n("&Inherit parent attribute (%1)").arg(typeToi18n[m_dirInfo.mimeType]));
+ }
+ if (createDirDlg->exec())
+ {
+ QDir dir;
+
+ QString startDir = "";
+ if ( !currentKFileTreeViewItem()->isDir() )
+ {
+ startDir = currentURL().path();
+ } else
+ {
+ startDir = currentURL().path() + "/dummy_file";
+ }
+ startDir = QFileInfo(startDir).dirPath();
+ if (!dir.mkdir(startDir+"/"+createDirDlg->dirName->text()))
+ {
+ KMessageBox::error(this,i18n("Error while creating the new folder.\n \
+ Maybe you do not have permission to write in the %1 folder.").arg(startDir));
+ return;
+ }
+ if (! createDirDlg->parentAttr->isChecked())
+ {
+ m_dirInfo.mimeType = i18nToType[createDirDlg->typesCombo->currentText()];
+ m_dirInfo.preText = "";
+ m_dirInfo.postText = "";
+ writeDirInfo(startDir+"/"+createDirDlg->dirName->text()+"/.dirinfo");
+ }
+ }
+}
+/** No descriptions */
+
+QDragObject * TemplatesTreeView::dragObject ()
+{
+ // don't drag folders
+ if ( ! currentKFileTreeViewItem() || currentKFileTreeViewItem()->isDir() ) return 0;
+
+ m_dirInfo = readDirInfo();
+ if(!m_dirInfo.mimeType.isEmpty()) // only drag when the template type is specified
+ {
+ KURLDrag *drag = new KURLDrag(KURL::List(currentURL()), this);
+ return drag;
+ }
+ return 0;
+}
+
+/** No descriptions */
+void TemplatesTreeView::contentsDropEvent(QDropEvent *e)
+{
+ if (KURLDrag::canDecode(e))
+ {
+ // handles url drops
+ BaseTreeView::contentsDropEvent(e);
+ return;
+ }
+ if (QTextDrag::canDecode(e))
+ {
+ QListViewItem *item = itemAt(contentsToViewport(e->pos()));
+ if (item)
+ {
+ KURL dest;
+ if ( currentKFileTreeViewItem()->isDir() )
+ dest = currentURL();
+ else
+ dest = currentURL().directory(false);
+ dest.adjustPath(+1);
+ QString content;
+ QTextDrag::decode(e, content);
+ KURL url =KURLRequesterDlg::getURL( dest.path() + "template.txt",
+ this, i18n("Save selection as template file:"));
+ if ( !url.isEmpty() )
+ {
+ //now save the file
+ KTempFile* tempFile = new KTempFile(tmpDir);
+ tempFile->setAutoDelete(true);
+ tempFile->textStream()->setEncoding(QTextStream::UnicodeUTF8);
+ *(tempFile->textStream()) << content;
+ tempFile->close();
+ bool proceed = true;
+ if (QExtFileInfo::exists(url, false, this))
+ {
+ proceed = KMessageBox::warningContinueCancel(this, i18n("<qt>The file <b>%1</b> already exists.<br>Do you want to overwrite it?</qt>").arg(url.prettyURL(0, KURL::StripFileProtocol)),i18n("Overwrite"), i18n("Overwrite")) == KMessageBox::Continue;
+ }
+ if (proceed)
+ {
+ if (!QuantaNetAccess::upload(tempFile->name(), url, m_parent, false))
+ {
+ KMessageBox::error(this,i18n("<qt>Could not write to file <b>%1</b>.<br>Check if you have rights to write there or that your connection is working.</qt>").arg(url.prettyURL(0, KURL::StripFileProtocol)));
+ }
+ }
+ delete tempFile;
+ }
+ }
+ }
+ // must be done to reset timer etc.
+ BaseTreeView::contentsDropEvent(e);
+}
+
+/** Reads a .dirinfo file from the selected item's path */
+DirInfo TemplatesTreeView::readDirInfo(const QString& dir)
+{
+ DirInfo dirInfo;
+ QString startDir = dir;
+
+ if (startDir.isEmpty())
+ {
+ if (!currentKFileTreeViewItem()->isDir())
+ {
+ startDir = currentURL().path();
+ } else
+ {
+ startDir = currentURL().path() + "/dummy_file";
+ }
+ }
+
+ QFileInfo dotFileInfo(QFileInfo(startDir).dirPath()+"/.dirinfo");
+
+ while ((!dotFileInfo.exists()) && (dotFileInfo.dirPath() != "/"))
+ {
+ dotFileInfo.setFile(QFileInfo(dotFileInfo.dirPath()).dirPath()+"/.dirinfo");
+ }
+
+ KConfig *config = new KConfig(dotFileInfo.filePath());
+ dirInfo.mimeType = config->readEntry("Type");
+ dirInfo.preText = config->readEntry("PreText");
+ dirInfo.postText = config->readEntry("PostText");
+ dirInfo.usePrePostText = config->readBoolEntry("UsePrePostText", false);
+
+ delete config;
+ return dirInfo;
+}
+
+/** Writes a .dirinfo file from the selected item's path */
+bool TemplatesTreeView::writeDirInfo(const QString& m_dirInfoFile)
+{
+ QString startDir = "";
+
+ if (m_dirInfoFile.isEmpty())
+ {
+ if ( !currentKFileTreeViewItem()->isDir() )
+ {
+ startDir = currentURL().path();
+ } else
+ {
+ startDir = currentURL().path() + "/dummy_file";
+ }
+ } else
+ {
+ startDir = m_dirInfoFile;
+ }
+
+ QFileInfo dotFileInfo(QFileInfo(startDir).dirPath()+"/.dirinfo");
+
+ bool success = false;
+ KConfig *config = new KConfig(dotFileInfo.filePath());
+ if (!config->isReadOnly())
+ {
+ config->writeEntry("Type", m_dirInfo.mimeType);
+ config->writeEntry("PreText", m_dirInfo.preText);
+ config->writeEntry("PostText", m_dirInfo.postText);
+ config->writeEntry("UsePrePostText", m_dirInfo.usePrePostText);
+ config->sync();
+ success = true;
+ }
+ delete config;
+ return success;
+}
+
+void TemplatesTreeView::slotProperties()
+{
+ if ( !currentItem() ) return;
+ KURL url = currentURL();
+
+ KPropertiesDialog *propDlg = new KPropertiesDialog( url, this, 0L, false, false); //autodeletes itself
+
+//Always add the Quanta directory page
+ QFrame *quantaDirPage = propDlg->addPage(i18n("Quanta Template"));
+ QVBoxLayout *topLayout = new QVBoxLayout( quantaDirPage);
+ m_quantaProperties = new QuantaPropertiesPage( quantaDirPage, i18n("Quanta") );
+
+ m_quantaProperties->typesCombo->insertItem(typeToi18n["text/all"]);
+ m_quantaProperties->typesCombo->insertItem(typeToi18n["file/all"]);
+ m_quantaProperties->typesCombo->insertItem(typeToi18n["template/all"]);
+ m_quantaProperties->typesCombo->insertItem(typeToi18n["site/all"]);
+
+ m_dirInfo = readDirInfo();
+
+ m_quantaProperties->typesCombo->setCurrentItem(typeToi18n[m_dirInfo.mimeType]);
+
+ KIO::UDSEntry entry;
+ KIO::NetAccess::stat(url, entry, this);
+ KFileItem fItem(entry, url);
+ QString permissions = fItem.permissionsString();
+ QString userName;
+ struct passwd *user = getpwuid(getuid());
+ if (user)
+ userName = QString::fromLocal8Bit(user->pw_name);
+ QString groupName;
+ gid_t gid = getgid();
+ struct group *ge = getgrgid(gid);
+ if (ge)
+ {
+ groupName = QString::fromLocal8Bit(ge->gr_name);
+ if (groupName.isEmpty())
+ groupName.sprintf("%d", ge->gr_gid);
+ } else
+ groupName.sprintf("%d", gid);
+ bool writable = false;
+ if (permissions[8] == 'w' || (permissions[2] == 'w' && userName == fItem.user()) || (permissions[5] == 'w' && groupName == fItem.group()))
+ writable = true;
+
+ QString startDir = "";
+ if (!currentKFileTreeViewItem()->isDir())
+ {
+ startDir = url.path();
+ m_quantaProperties->typeStack->raiseWidget(1);
+ } else
+ {
+ startDir = url.path() + "/dummy_file";
+ m_quantaProperties->typeStack->raiseWidget(0);
+ }
+ m_quantaProperties->setEnabled(writable);
+ QFileInfo dotFileInfo(QFileInfo(startDir).dirPath()+"/.dirinfo");
+ m_parentDirInfo = readDirInfo(dotFileInfo.dirPath());
+ if (!dotFileInfo.exists() || m_dirInfo.mimeType == m_parentDirInfo.mimeType)
+ {
+ m_quantaProperties->parentAttr->setChecked(true);
+ }
+ if (m_parentDirInfo.mimeType.isEmpty())
+ {
+ m_quantaProperties->parentAttr->setText(i18n("&Inherit parent attribute (nothing)"));
+ } else
+ {
+ m_quantaProperties->parentAttr->setText(i18n("&Inherit parent attribute (%1)").arg(typeToi18n[m_parentDirInfo.mimeType]));
+ }
+ m_quantaProperties->preTextEdit->setText(m_dirInfo.preText);
+ m_quantaProperties->postTextEdit->setText(m_dirInfo.postText);
+ if (m_dirInfo.usePrePostText)
+ {
+ m_quantaProperties->usePrePostText->setChecked(true);
+ }
+
+ topLayout->addWidget( m_quantaProperties );
+ connect( propDlg, SIGNAL( applied() ), this , SLOT( slotPropertiesApplied()) );
+
+ QString name = url.path() + TMPL;
+ KConfig config(name);
+ config.setGroup("Filtering");
+ name = config.readEntry("Action", NONE);
+ if ( name == NONE )
+ name = i18n(NONE);
+ uint pos = 0;
+ uint j = 1;
+ m_quantaProperties->actionCombo->insertItem(i18n(NONE));
+ QString tmpStr;
+ KActionCollection *ac = m_mainWindow->actionCollection();
+ uint acCount = ac->count();
+ for (uint i = 0; i < acCount; i++)
+ {
+ TagAction *action = dynamic_cast<TagAction*>(ac->action(i));
+ if (action)
+ {
+ QDomElement el = action->data();
+ QString type = el.attribute("type", "tag");
+ if (type == "script")
+ {
+ tmpStr = action->text().replace(QRegExp("\\&(?!\\&)"),"");
+ m_quantaProperties->actionCombo->insertItem(tmpStr);
+ if (tmpStr == name)
+ pos = j;
+ j++;
+ }
+ }
+ }
+ m_quantaProperties->actionCombo->setCurrentItem(pos);
+
+//If the item is a file, add the Quanta file info page
+ addFileInfoPage(propDlg);
+ if (propDlg->exec() == QDialog::Accepted)
+ {
+//TODO: move to slotPropertiesApplied
+ if (url != propDlg->kurl())
+ {
+ itemRenamed(url, propDlg->kurl());
+ }
+ }
+}
+
+
+/** No descriptions */
+void TemplatesTreeView::slotPropertiesApplied()
+{
+ DirInfo m_localDirInfo;
+ QString typeString = "";
+
+ if (!m_quantaProperties->parentAttr->isChecked())
+ {
+ m_localDirInfo.mimeType = m_quantaProperties->typesCombo->currentText();
+ typeString = m_localDirInfo.mimeType;
+ m_localDirInfo.mimeType = i18nToType[m_localDirInfo.mimeType];
+
+ } else
+ {
+ if (m_dirInfo.mimeType != m_parentDirInfo.mimeType)
+ typeString = typeToi18n[m_parentDirInfo.mimeType];
+ m_localDirInfo.mimeType = m_parentDirInfo.mimeType;
+ }
+
+ m_localDirInfo.usePrePostText = m_quantaProperties->usePrePostText->isChecked();
+ m_localDirInfo.preText = m_quantaProperties->preTextEdit->text();
+ m_localDirInfo.postText = m_quantaProperties->postTextEdit->text();
+
+ if ( (m_dirInfo.mimeType != m_localDirInfo.mimeType) ||
+ (m_dirInfo.preText != m_localDirInfo.preText) ||
+ (m_dirInfo.postText != m_localDirInfo.postText))
+ {
+ m_dirInfo.mimeType = m_localDirInfo.mimeType;
+ m_dirInfo.preText = m_localDirInfo.preText;
+ m_dirInfo.postText = m_localDirInfo.postText;
+ m_dirInfo.usePrePostText = m_localDirInfo.usePrePostText;
+ bool result = writeDirInfo();
+ KFileTreeViewItem *item = currentKFileTreeViewItem();
+ if (item && !item->isDir())
+ item = static_cast<KFileTreeViewItem *>(item->parent());
+ if (result && item && !typeString.isEmpty())
+ {
+ if (item->parent() && item->isDir())
+ item->setText(1, typeString);
+ updateTypeDescription(item, typeString);
+ }
+ }
+
+ writeTemplateInfo();
+}
+
+void TemplatesTreeView::updateTypeDescription(KFileTreeViewItem *item, const QString &typeString)
+{
+ if (item->parent() && item->isDir())
+ item->setText(1, typeString);
+ KFileTreeViewItem *curItem = static_cast<KFileTreeViewItem *>(item->firstChild());
+ while (curItem && curItem != static_cast<KFileTreeViewItem *>(item->nextSibling()))
+ {
+ if (!curItem->isDir())
+ {
+ curItem->setText(1, typeString);
+ } else
+ {
+ QFileInfo dotFileInfo(curItem->url().path() + "/.dirinfo");
+ if (!dotFileInfo.exists())
+ updateTypeDescription(curItem, typeString);
+ }
+ curItem = static_cast<KFileTreeViewItem *>(curItem->nextSibling());
+ }
+}
+
+/** No descriptions */
+void TemplatesTreeView::slotInsertTag()
+{
+ if (currentItem())
+ {
+ m_dirInfo = readDirInfo();
+ KURL url = currentURL();
+ emit insertTag( url, m_dirInfo);
+ }
+}
+/*
+ Attention, this is called whenever a drop on a kate window happens!
+*/
+void TemplatesTreeView::slotDragInsert(QDropEvent *e)
+{
+ if (KURLDrag::canDecode(e))
+ {
+ KURL::List fileList;
+ KURLDrag::decode(e, fileList);
+
+ if(fileList.empty())
+ return;
+
+ KURL url = fileList.front();
+
+ QString localFileName;
+ if (url.isLocalFile())
+ {
+ localFileName = url.path();
+ m_dirInfo = readDirInfo(localFileName);
+ }
+ QString mimeType = KMimeType::findByURL(url)->name();
+
+ /* First, see if the type of the file is specified in the .dirinfo file */
+ if(m_dirInfo.mimeType.isEmpty())
+ {
+ // no .dirinfo file present, so we insert it as tag
+ emit insertTag(url, m_dirInfo);
+ } else
+ {
+ if(m_dirInfo.mimeType == "text/all") // default to inserting in document
+ {
+ if(!mimeType.contains("text", false) && QuantaCommon::denyBinaryInsert(this) != KMessageBox::Yes)
+ {
+ return;
+ }
+ emit insertFile(KURL::fromPathOrURL( localFileName ));
+ }
+
+ if(m_dirInfo.mimeType == "file/all")
+ {
+ // whatever this is, insert it with a tag (image or link or prefix/postfix)
+ emit insertTag(KURL::fromPathOrURL( localFileName ), m_dirInfo);
+ }
+ else
+ if(m_dirInfo.mimeType == "template/all")
+ {
+ if(!mimeType.contains("text", false) && QuantaCommon::denyBinaryInsert(this) != KMessageBox::Yes)
+ {
+ return;
+ }
+ emit openFile(KURL());
+ emit insertFile(KURL::fromPathOrURL( localFileName ));
+ }
+ }
+ } else
+ if (QTextDrag::canDecode(e))
+ {
+ QString s;
+ QTextDrag::decode(e, s);
+ KMessageBox::information(this,s, "Decode");
+ }
+}
+
+void TemplatesTreeView::slotNewProjectLoaded(const QString &projectName, const KURL &baseURL, const KURL &templateURL)
+{
+ BaseTreeView::slotNewProjectLoaded(projectName, baseURL, templateURL); // set m_projectName and m_projectBaseURL
+ if (m_projectDir)
+ removeBranch(m_projectDir);
+ if (!templateURL.isEmpty())
+ {
+ newBranch(templateURL);
+ }
+}
+
+
+/*!
+ \fn TemplatesTreeView::writeTemplateInfo()
+ */
+void TemplatesTreeView::writeTemplateInfo()
+{
+ QString fileName = currentURL().path() + TMPL;
+ KConfig config(fileName);
+ config.setGroup("Filtering");
+ if ( m_quantaProperties->actionCombo->currentText() == i18n(NONE) )
+ config.writeEntry("Action", NONE);
+ else
+ config.writeEntry("Action", m_quantaProperties->actionCombo->currentText());
+ config.sync();
+}
+
+void TemplatesTreeView::slotPaste()
+{
+ if (currentItem())
+ {
+ QClipboard *cb = QApplication::clipboard();
+ KURL::List list( QStringList::split( QChar('\n'), cb->text() ) );
+
+ KURL url;
+ uint j = list.count();
+ for (uint i = 0; i < j; i++)
+ {
+ url = list[i];
+ url.setFileName(url.fileName() + TMPL);
+ if (url.isLocalFile() && QFileInfo(url.path()).exists())
+ list += url;
+ }
+ url = currentURL();
+ if ( ! currentKFileTreeViewItem()->isDir() )
+ url.setFileName(""); // don't paste on files but in dirs
+ KIO::Job *job = KIO::copy( list, url);
+ connect( job, SIGNAL( result( KIO::Job *) ), this , SLOT( slotJobFinished( KIO::Job *) ) );
+ }
+}
+
+void TemplatesTreeView::slotDelete()
+{
+ if (currentItem())
+ {
+ KURL url = currentURL();
+ QString msg;
+ if ( currentKFileTreeViewItem()->isDir() )
+ msg = i18n("Do you really want to delete folder \n%1 ?\n").arg(url.path());
+ else
+ msg = i18n("Do you really want to delete file \n%1 ?\n").arg(url.path());
+
+ if ( KMessageBox::warningContinueCancel(this, msg, QString::null, KStdGuiItem::del()) == KMessageBox::Continue )
+ {
+ KIO::Job *job = KIO::del(url);
+ connect( job, SIGNAL( result( KIO::Job *) ), this , SLOT( slotJobFinished( KIO::Job *) ) );
+ url.setFileName(url.fileName()+ TMPL);
+ if ( QFileInfo(url.path()).exists() ) {
+ KIO::Job *job2 = KIO::del(url);
+ connect( job2, SIGNAL( result( KIO::Job *) ), this , SLOT( slotJobFinished( KIO::Job *) ) );
+ };
+ }
+ }
+}
+
+/** Filters the template through and action, and returns the modified/filtered
+template file */
+KURL TemplatesTreeView::filterTemplate()
+{
+ KURL url = currentURL();
+ QString name = url.path() + TMPL;
+ KConfig config(name);
+ config.setGroup("Filtering");
+ name = config.readEntry("Action", NONE);
+ TagAction *filterAction = 0L;
+ KActionCollection *ac = m_mainWindow->actionCollection();
+ uint acCount = ac->count();
+ QString tmpStr;
+ for (uint i = 0; i < acCount; i++)
+ {
+ TagAction *action = dynamic_cast<TagAction*>(ac->action(i));
+ if (action)
+ {
+ QDomElement el = action->data();
+ QString type = el.attribute("type", "tag");
+ tmpStr = action->text();
+ tmpStr.replace(QRegExp("\\&(?!\\&)"),"");
+ if (type == "script" && tmpStr == name)
+ {
+ filterAction = action;
+ }
+ }
+ }
+ if (filterAction)
+ {
+ KTempFile* tempFile = new KTempFile(tmpDir);
+ filterAction->setOutputFile(tempFile->file());
+ filterAction->setInputFileName(url.path());
+ filterAction->execute(true);
+ filterAction->setOutputFile(0L);
+ filterAction->setInputFileName(QString::null);
+ tempFile->close();
+ tempFileList.append(tempFile);
+ url.setPath(tempFile->name());
+ }
+ return url;
+}
+
+QString TemplatesTreeView::createTemplateTarball()
+{
+ KURL url = currentURL();
+ KURL dirURL (url);
+ if (!currentKFileTreeViewItem()->isDir())
+ dirURL.setPath(dirURL.directory(false));
+
+ KTempDir* tempDir = new KTempDir(tmpDir);
+ tempDir->setAutoDelete(true);
+ tempDirList.append(tempDir);
+ QString tempFileName=tempDir->name() + url.fileName() + ".tgz";
+ //pack the files into a .tgz file
+ KTar tar(tempFileName, "application/x-gzip");
+ tar.open(IO_WriteOnly);
+// tar.setOrigFileName("");
+
+ KURL::List files;
+ if ( ! currentKFileTreeViewItem()->isDir() )
+ files.append(url);
+ else {
+ files = QExtFileInfo::allFiles(dirURL, "*", this) ;
+ dirURL = dirURL.upURL();
+ }
+
+ for ( KURL::List::Iterator it_f = files.begin(); it_f != files.end(); ++it_f )
+ {
+ if (!(*it_f).fileName(false).isEmpty()) {
+ url = QExtFileInfo::toRelative( (*it_f), dirURL) ;
+
+ QFile file((*it_f).path());
+ file.open(IO_ReadOnly);
+ QByteArray bArray = file.readAll();
+ tar.writeFile(url.path(), "user", "group", bArray.size(), bArray.data());
+ file.close();
+ };
+ }
+ tar.close();
+
+ return tempFileName;
+}
+
+void TemplatesTreeView::slotSendInMail()
+{
+ if ( ! currentKFileTreeViewItem() ) return;
+
+
+ QStringList attachmentFile;
+ attachmentFile += createTemplateTarball();
+
+ TagMailDlg *mailDlg = new TagMailDlg( this, i18n("Send template in email"));
+ QString toStr;
+ QString message = i18n("Hi,\n This is a Quanta Plus [http://quanta.kdewebdev.org] template tarball.\n\nHave fun.\n");
+ QString titleStr;
+ QString subjectStr;
+
+ mailDlg->TitleLabel->setText(i18n("Content:"));
+/* mailDlg->titleEdit->setFixedHeight(60);
+ mailDlg->titleEdit->setVScrollBarMode(QTextEdit::Auto);
+ mailDlg->titleEdit->setHScrollBarMode(QTextEdit::Auto);*/
+ if ( mailDlg->exec() )
+ {
+ if ( !mailDlg->lineEmail->text().isEmpty())
+ {
+ toStr = mailDlg->lineEmail->text();
+ subjectStr = (mailDlg->lineSubject->text().isEmpty())?i18n("Quanta Plus Template"):mailDlg->lineSubject->text();
+ if ( !mailDlg->titleEdit->text().isEmpty())
+ message = mailDlg->titleEdit->text();
+ } else
+ {
+ KMessageBox::error(this,i18n("No destination address was specified.\n Sending is aborted."),i18n("Error Sending Email"));
+ delete mailDlg;
+ return;
+ }
+ kapp->invokeMailer(toStr, QString::null, QString::null, subjectStr, message, QString::null, attachmentFile);
+ }
+ delete mailDlg;
+}
+
+void TemplatesTreeView::slotUploadTemplate()
+{
+ if ( ! currentKFileTreeViewItem() ) return;
+ emit uploadTemplate(createTemplateTarball());
+}
+
+bool TemplatesTreeView::acceptDrag(QDropEvent* e ) const
+{
+ return (BaseTreeView::acceptDrag(e) || QTextDrag::canDecode(e));
+}
+
+void TemplatesTreeView::slotExtractSiteTemplate()
+{
+ QString startDir = m_projectBaseURL.url();
+ if (startDir.isEmpty())
+ startDir = QDir::homeDirPath();
+ bool error = false;
+ KURLRequesterDlg urlRequester(startDir, i18n("Target folder"), this, "req", true);
+ urlRequester.urlRequester()->setMode(KFile::Directory);
+ if (urlRequester.exec())
+ {
+ KURL targetURL = urlRequester.selectedURL();
+ KURL url = currentURL();
+ QString tempFile;
+ if (KIO::NetAccess::download(url, tempFile, this))
+ {
+ KTar tar(tempFile);
+ if (tar.open(IO_ReadOnly))
+ {
+ const KArchiveDirectory *directory = tar.directory();
+ if (targetURL.protocol() == "file")
+ directory->copyTo(targetURL.path(), true);
+ else
+ {
+ KTempDir* tempDir = new KTempDir(tmpDir);
+ tempDir->setAutoDelete(true);
+ QString tempDirName = tempDir->name();
+ directory->copyTo(tempDirName, true);
+ QStringList entries = directory->entries();
+ KURL::List fileList;
+ for (QStringList::Iterator it = entries.begin(); it != entries.end(); ++it)
+ fileList.append(KURL::fromPathOrURL(tempDirName + "/" + *it));
+ if (!KIO::NetAccess::dircopy(fileList, targetURL, this))
+ error = true;
+ KIO::NetAccess::del(KURL().fromPathOrURL(tempDirName), this);
+ delete tempDir;
+ }
+ tar.close();
+ } else
+ error = true;
+ KIO::NetAccess::removeTempFile(tempFile);
+ if (!m_projectBaseURL.isEmpty() && !QExtFileInfo::toRelative(targetURL, m_projectBaseURL).url().startsWith("."))
+ {
+ if (KMessageBox::questionYesNo(this, i18n("You have extracted the site template to a folder which is not under your main project folder.\nDo you want to copy the folder into the main project folder?"), QString::null, i18n("Copy Folder"), i18n("Do Not Copy")) == KMessageBox::Yes)
+ {
+ emit insertDirInProject(targetURL);
+ }
+ }
+ } else
+ error = true;
+ if (error)
+ KMessageBox::error(this, i18n("<qt>Some error happened while extracting the <i>%1</i> site template file.<br>Check that you have write permission for <i>%2</i> and that there is enough free space in your temporary folder.</qt>").arg(url.prettyURL(0, KURL::StripFileProtocol)).arg(targetURL.prettyURL(0, KURL::StripFileProtocol)));
+ }
+}
+
+#include "templatestreeview.moc"
diff --git a/quanta/treeviews/templatestreeview.h b/quanta/treeviews/templatestreeview.h
new file mode 100644
index 00000000..c0df69e5
--- /dev/null
+++ b/quanta/treeviews/templatestreeview.h
@@ -0,0 +1,162 @@
+/***************************************************************************
+ templatestreeview.h - description
+ -------------------
+ begin : Thu Dec 20 2001
+ copyright : (C) 2001-2004 by 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; version 2 of the License. *
+ * *
+ ***************************************************************************/
+
+#ifndef TEMPLATESTREEVIEW_H
+#define TEMPLATESTREEVIEW_H
+
+//own includes
+#include "basetreeview.h"
+#include "quantacommon.h"
+
+//forward declarations
+class QuantaPropertiesPage;
+class KMainWindow;
+
+class TemplatesTreeBranch : public BaseTreeBranch {
+
+public:
+ TemplatesTreeBranch(KFileTreeView *parent, const KURL& url,
+ const QString& name, const QPixmap& pix,
+ bool showHidden = false, KFileTreeViewItem *branchRoot = 0L);
+
+ /** read the mimetype */
+ virtual KFileTreeViewItem* createTreeViewItem(KFileTreeViewItem *parent,
+ KFileItem *fileItem );
+};
+
+
+class TemplatesTreeView : public BaseTreeView {
+ Q_OBJECT
+
+public:
+
+ /**
+ * since this class is a singleton you must use this function to access it
+ *
+ * the parameter are only used at the first call to create the class
+ *
+ */
+ static TemplatesTreeView* const ref(KMainWindow *parent = 0L, const char *name = 0L)
+ {
+ static TemplatesTreeView *m_ref;
+ if (!m_ref) m_ref = new TemplatesTreeView (parent, name);
+ return m_ref;
+ }
+
+ ~TemplatesTreeView();
+ /** Writes a .dirinfo file from the selected item's path */
+ bool writeDirInfo(const QString& dirInfoFile = QString::null);
+ /** Reads a .dirinfo file from the selected item's path */
+ DirInfo readDirInfo(const QString& dir = QString::null);
+
+
+public slots:
+
+ /** Inserts the content of the selected template into the
+ * activ document
+ */
+ void slotInsertInDocument();
+
+ /**
+ * displays the RBM
+ *
+ *
+ * @param listView KListView where the event comes from
+ *
+ * @param item QListViewItem where the mousepointer is hovering
+ *
+ * @param point QPoint coordinates of the event
+ *
+ */
+ void slotMenu(KListView *listView, QListViewItem *item, const QPoint &point);
+ /** Creates a new document based in the selected template. */
+ void slotNewDocument();
+ /** Insert the template as text, image, new document. */
+ void slotInsert();
+ /** Extracts the site template to an user specified directory */
+ void slotExtractSiteTemplate();
+ /** No descriptions */
+ void slotNewDir();
+ /** Handles dropping on the document from the template tree */
+ void slotDragInsert(QDropEvent *);
+
+ /**
+ * slot for the RBM
+ *
+ * packs and sends files or folders as attachment to an email
+ */
+ void slotSendInMail();
+ void slotUploadTemplate();
+ virtual void slotSelectFile(QListViewItem *item);
+ void slotOpen();
+ void slotPaste();
+ void slotDelete();
+ /** Properties dialog for template view */
+ virtual void slotProperties();
+ /** Property application for template view */
+ virtual void slotPropertiesApplied();
+ void slotInsertTag();
+
+ /** Sets the project template directory */
+ void slotNewProjectLoaded(const QString &, const KURL &, const KURL &);
+
+private:
+
+ /** The constructor is privat because we use singleton pattern.
+ * If you need the class use TemplatesTreeView::ref() for
+ * construction and reference
+ */
+ TemplatesTreeView(KMainWindow *parent, const char *name = 0L);
+ /** Filters the template through and action, and returns the modified/filtered
+ template file */
+ KURL filterTemplate();
+ void writeTemplateInfo();
+ void updateTypeDescription(KFileTreeViewItem *item, const QString &typeString);
+
+ BaseTreeBranch *m_projectDir;
+ int m_deleteMenuId;
+ int m_openId;
+ int m_reloadMenuId;
+ int m_downloadMenuId;
+ QuantaPropertiesPage *m_quantaProperties;
+ QString m_projectName;
+ KURL localURL;
+ KURL globalURL;
+ KPopupMenu *m_fileMenu;
+ KPopupMenu *m_folderMenu;
+ KPopupMenu *m_emptyAreaMenu;
+ KMainWindow *m_mainWindow;
+ DirInfo m_dirInfo;
+ DirInfo m_parentDirInfo;
+ int m_insertFileInProject;
+ int m_insertFolderInProject;
+ int m_menuClose; ///< remembers the menu entry
+ int m_menuPasteFolder; ///< remembers the menu entry
+
+signals: // Signals
+ void insertFile(const KURL &);
+ void downloadTemplate();
+ void uploadTemplate(const QString&);
+
+protected: // Protected methods
+ KFileTreeBranch* newBranch(const KURL& url);
+ virtual QDragObject * dragObject();
+// virtual void startDrag();
+ void contentsDropEvent(QDropEvent *event);
+ bool acceptDrag(QDropEvent* e ) const;
+ QString createTemplateTarball();
+};
+
+#endif
diff --git a/quanta/treeviews/uploadtreefile.cpp b/quanta/treeviews/uploadtreefile.cpp
new file mode 100644
index 00000000..2df61f3f
--- /dev/null
+++ b/quanta/treeviews/uploadtreefile.cpp
@@ -0,0 +1,89 @@
+/***************************************************************************
+ uploadtreefile.cpp - description
+ -------------------
+ begin : Sun Aug 25 2002
+ copyright : (C) 2002, 2003 by 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; version 2 of the License. *
+ * *
+ ***************************************************************************/
+
+// QT includes
+#include <qdir.h>
+#include <qpixmap.h>
+#include <qfileinfo.h>
+
+// KDE includes
+#include <kfileitem.h>
+#include <kiconloader.h>
+#include <kurl.h>
+
+// app includes
+#include "uploadtreefile.h"
+#include "resource.h"
+
+UploadTreeFile::UploadTreeFile( UploadTreeFolder *parent, const KURL &a_url, const KFileItem &a_fileItem)
+ : KListViewItem( parent, a_url.fileName(), "", QString("%1").arg( (long int)a_fileItem.size() ), a_fileItem.timeString())
+{
+ m_url = a_url;
+ isDir = false;
+ parentFolder = parent;
+ m_fileItem = new KFileItem(a_fileItem);
+ m_confirm = false;
+
+ setWhichPixmap("check_clear");
+ setText(0, m_url.fileName());
+}
+
+UploadTreeFile::UploadTreeFile( QListView *parent, const KURL &a_url, const KFileItem &a_fileItem)
+ : KListViewItem( parent, a_url.fileName(), "", QString("%1").arg( (long int)a_fileItem.size() ), a_fileItem.timeString())
+{
+ m_url = a_url;
+ isDir = false;
+ parentFolder = 0L;
+ m_fileItem = new KFileItem(a_fileItem);
+ m_confirm = false;
+
+ //setPixmap( 1, SmallIcon("check") );
+ setWhichPixmap("check_clear");
+ setText(0, m_url.fileName());
+}
+
+
+UploadTreeFile::~UploadTreeFile()
+{
+ delete m_fileItem;
+}
+
+int UploadTreeFile::permissions()
+{
+ if (m_fileItem)
+ return m_fileItem->permissions();
+ else
+ return -1;
+}
+
+/** used for sorting */
+QString UploadTreeFile::key ( int, bool ) const
+{
+ static QString key;
+ key = QString( "1" + text(0) );
+ return key;
+// return QFileInfo(key).extension()+key;
+}
+
+void UploadTreeFile::setWhichPixmap(const QString& pixmap )
+{
+ setPixmap( 1, SmallIcon(pixmap) );
+}
+
+/** No descriptions */
+KURL UploadTreeFile::url()
+{
+ return m_url;
+}
diff --git a/quanta/treeviews/uploadtreefile.h b/quanta/treeviews/uploadtreefile.h
new file mode 100644
index 00000000..54c8ce01
--- /dev/null
+++ b/quanta/treeviews/uploadtreefile.h
@@ -0,0 +1,53 @@
+/***************************************************************************
+ uploadtreefile.h - description
+ -------------------
+ begin : Sun Aug 25 2002
+ copyright : (C) 2002, 2003 by 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; version 2 of the License. *
+ * *
+ ***************************************************************************/
+
+#ifndef UPLOADTREEFILE_H
+#define UPLOADTREEFILE_H
+
+#include <klistview.h>
+
+#include "uploadtreefolder.h"
+
+/**
+ *@author George Vilches & Andras Mantia
+ */
+
+class KFileItem;
+
+class UploadTreeFile : public KListViewItem {
+public:
+ UploadTreeFile( UploadTreeFolder *parent, const KURL &a_url, const KFileItem &a_fileItem);
+ UploadTreeFile( QListView *parent, const KURL &a_url, const KFileItem &a_fileItem);
+ ~UploadTreeFile();
+
+ void setWhichPixmap(const QString& pixmap);
+ int permissions();
+
+ /** used for sorting */
+ virtual QString key ( int column, bool ascending ) const;
+ /** No descriptions */
+ KURL url();
+ void setConfirmUpload(bool confirm) {m_confirm = confirm;}
+ bool confirmUpload() {return m_confirm;}
+
+public:
+ UploadTreeFolder * parentFolder;
+ KURL m_url;
+ bool isDir;
+ bool m_confirm;
+ KFileItem *m_fileItem;
+};
+
+#endif
diff --git a/quanta/treeviews/uploadtreefolder.cpp b/quanta/treeviews/uploadtreefolder.cpp
new file mode 100644
index 00000000..f38e648c
--- /dev/null
+++ b/quanta/treeviews/uploadtreefolder.cpp
@@ -0,0 +1,116 @@
+/***************************************************************************
+ uploadtreefolder.cpp - description
+ -------------------
+ begin : Sun Aug 25 2002
+ copyright : (C) 2002 by 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; version 2 of the License. *
+ * *
+ ***************************************************************************/
+
+// QT includes
+#include <qdir.h>
+#include <qdragobject.h>
+#include <qevent.h>
+#include <qpixmap.h>
+
+// KDE includes
+#include <kiconloader.h>
+
+// app includes
+#include "uploadtreefolder.h"
+#include "uploadtreefile.h"
+#include "resource.h"
+
+UploadTreeFolder::UploadTreeFolder(const KURL &a_url, UploadTreeFolder * parent, const char * name )
+ : KListViewItem( parent, name, "", "", "" )
+{
+ parentFolder = parent;
+ m_url = a_url;
+ m_url.adjustPath(1);
+
+ setPixmap( 0, SmallIcon("folder") );
+ setPixmap( 1, SmallIcon("check") );
+ setText(0, m_url.fileName());
+
+}
+
+UploadTreeFolder::UploadTreeFolder(const KURL &a_url, QListView * parent, const char * name )
+ : KListViewItem( parent, name, "", "", "" )
+{
+ parentFolder = 0L;
+ m_url = a_url;
+ m_url.adjustPath(1);
+
+ setPixmap( 0, SmallIcon("folder") );
+ setPixmap( 1, SmallIcon("check") );
+ setText(0, m_url.fileName());
+}
+
+
+void UploadTreeFolder::setOpen( bool open )
+{
+ QListViewItem::setOpen( open );
+}
+
+/** retun full name of the folder */
+//TODO: This should go away. Use url() instead.
+QString UploadTreeFolder::fullName()
+{
+ QString s="";
+
+ if ( parentFolder )
+ {
+ s = parentFolder->fullName();
+ s += m_url.fileName()+"/";
+ }
+ else {
+ s = m_url.fileName();
+ }
+
+ return s;
+}
+
+/** setup */
+void UploadTreeFolder::setup()
+{
+ setExpandable( true );
+ QListViewItem::setup();
+}
+
+/** reload file list */
+void UploadTreeFolder::reloadList()
+{
+ setOpen( false );
+
+ QListViewItem *child;
+ while ( (child = firstChild()) )
+ removeItem( child );
+
+ setOpen( true );
+}
+
+/** need for sorting */
+QString UploadTreeFolder::key ( int, bool ) const
+{
+ static QString key;
+
+ key = QString("0") + text(0);
+
+ return key;
+}
+
+UploadTreeFolder::~UploadTreeFolder()
+{
+}
+
+void UploadTreeFolder::setWhichPixmap(const QString& pixmap )
+{
+ setPixmap( 1, SmallIcon(pixmap) );
+}
+
diff --git a/quanta/treeviews/uploadtreefolder.h b/quanta/treeviews/uploadtreefolder.h
new file mode 100644
index 00000000..1ef77279
--- /dev/null
+++ b/quanta/treeviews/uploadtreefolder.h
@@ -0,0 +1,57 @@
+/***************************************************************************
+ uploadtreefolder.h - description
+ -------------------
+ begin : Sun Aug 25 2002
+ copyright : (C) 2002 by 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; version 2 of the License. *
+ * *
+ ***************************************************************************/
+
+#ifndef UPLOADTREEFOLDER_H
+#define UPLOADTREEFOLDER_H
+
+#include <qfile.h>
+#include <qfileinfo.h>
+#include <qstring.h>
+#include <qstringlist.h>
+
+#include <klistview.h>
+#include <kurl.h>
+
+/**
+ *@author Andras Mantia
+ */
+
+class KURL;
+
+class UploadTreeFolder : public KListViewItem {
+public:
+ UploadTreeFolder( const KURL &a_url, QListView * parent, const char * name);
+ UploadTreeFolder( const KURL &a_url, UploadTreeFolder * parent, const char * name );
+ virtual ~UploadTreeFolder();
+
+ /** used for sorting */
+ virtual QString key ( int column, bool ascending ) const;
+ QString fullName();
+ KURL url() {return m_url;}
+
+ virtual void setOpen( bool );
+ void setup();
+ void setWhichPixmap(const QString& pixmap );
+
+public:
+ UploadTreeFolder * parentFolder;
+ KURL m_url;
+
+public slots: // Public slots
+ void reloadList();
+
+};
+
+#endif
diff --git a/quanta/treeviews/uploadtreeview.cpp b/quanta/treeviews/uploadtreeview.cpp
new file mode 100644
index 00000000..75d0fa0c
--- /dev/null
+++ b/quanta/treeviews/uploadtreeview.cpp
@@ -0,0 +1,451 @@
+/***************************************************************************
+ uploadtreeview.cpp - description
+ -------------------
+ begin : Sun Aug 25 2002
+ copyright : (C) 2002 by 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; version 2 of the License. *
+ * *
+ ***************************************************************************/
+
+#include <qregexp.h>
+
+#include <kcursor.h>
+#include <klocale.h>
+#include <kurl.h>
+#include <kfileitem.h>
+
+#include "uploadtreeview.h"
+#include "quantacommon.h"
+
+UploadTreeView::UploadTreeView( QWidget *parent, const char *name ) :
+ KListView(parent, name)
+{
+ setRootIsDecorated( true );
+ setSorting( 0 );
+ setMultiSelection(true);
+
+ setFrameStyle( Panel | Sunken );
+ setLineWidth( 2 );
+ addColumn( i18n("Name") );
+ addColumn( i18n("Upload") );
+ addColumn( i18n("Size") );
+ addColumn( i18n("Date") );
+
+ setFocusPolicy(QWidget::ClickFocus);
+
+ connect( this, SIGNAL(selectionChanged()), SLOT(slotSelectFile()));
+ connect( this, SIGNAL(selectionChanged(QListViewItem *)),
+ this, SLOT(slotSelectFile(QListViewItem *)));
+
+ connect(this, SIGNAL(doubleClicked(QListViewItem *, const QPoint &, int )), SLOT(slotDoubleClicked(QListViewItem *, const QPoint &, int )));
+}
+
+UploadTreeView::~UploadTreeView()
+{
+}
+
+int UploadTreeView::checkboxTree( QListViewItem *it )
+{
+ parentWidget()->setCursor(KCursor::workingCursor());
+
+ QListViewItem *itIter = it ? it->firstChild() : firstChild();
+
+ // bitFlag structure: (0/1)all children exist (0/1)no children exist.
+ // We don't need some children as a bit flag, because that's implied if the bits are "00".
+
+ int bitFlags = 3;
+ int retVal = 1;
+
+ if ( itIter != 0 )
+ {
+ for( ; itIter != 0; itIter = itIter->nextSibling() )
+ {
+ if ( dynamic_cast<UploadTreeFolder *>(itIter) )
+ {
+ int hadCheckFlags = checkboxTree( itIter );
+ bitFlags &= hadCheckFlags;
+ UploadTreeFolder *itF = static_cast<UploadTreeFolder *>(itIter);
+
+ if (hadCheckFlags == 2) {
+ // All children exist.
+ itF->setWhichPixmap( "check" );
+ itF->setSelected( true );
+ }
+ else if (hadCheckFlags == 1) {
+ // No children exist.
+ itF->setWhichPixmap( "check_clear" );
+ itF->setSelected( false );
+ }
+ else {
+ // Some children exist.
+ itF->setWhichPixmap( "check_grey" );
+ itF->setSelected( true );
+ }
+
+ }
+ else if ( dynamic_cast<UploadTreeFile *>(itIter) )
+ {
+ UploadTreeFile *itF = static_cast<UploadTreeFile *>(itIter);
+ if ( itF->isSelected() )
+ {
+ itF->setWhichPixmap("check");
+ // Turn off "no children"
+ if ( bitFlags % 2 == 1 ) bitFlags -= 1;
+ }
+ else
+ {
+ itF->setWhichPixmap("check_clear");
+ // Turn off "all children".
+ if (bitFlags >> 1 == 1) bitFlags -= 2;
+ }
+
+ }
+ }
+ retVal = bitFlags;
+ } else
+ {
+ if ( dynamic_cast<UploadTreeFolder *>(it) )
+ {
+ UploadTreeFolder *itF = static_cast<UploadTreeFolder *>(it);
+ if ( itF->isSelected() )
+ {
+ itF->setWhichPixmap("check");
+ retVal = 2;
+ }
+ else
+ {
+ itF->setWhichPixmap("check_clear");
+ retVal = 1;
+ }
+
+ }
+ }
+
+ parentWidget()->setCursor(KCursor::arrowCursor());
+
+ return retVal;
+}
+
+void UploadTreeView::selectAllUnderNode( QListViewItem* it, bool select )
+{
+ QListViewItem *itIter = 0;
+ if (it == 0) itIter = firstChild();
+ else itIter = it->firstChild();
+
+ for( ; itIter != 0; itIter = itIter->nextSibling() )
+ {
+ itIter->setSelected(select);
+ selectAllUnderNode(itIter, select);
+ if (itIter->isSelected() != select)
+ itIter->setSelected(select);
+ }
+}
+
+void UploadTreeView::slotSelectFile( QListViewItem *it )
+{
+ UploadTreeFolder *itF = dynamic_cast<UploadTreeFolder *>(it);
+ // This need a bit of special behavior for clicking on directories.
+ if ( itF )
+ {
+ itF->setSelected(it->isSelected());
+ selectAllUnderNode( it, it->isSelected() );
+ }
+
+//set the correct checkbox for this item, if it was a folder
+ int hadCheckFlags = checkboxTree(it);
+ if ( itF )
+ {
+ if (hadCheckFlags == 2) {
+ // All children exist.
+ itF->setWhichPixmap( "check" );
+ itF->setSelected( true );
+ }
+ else if (hadCheckFlags == 1) {
+ // No children exist.
+ itF->setWhichPixmap( "check_clear" );
+ itF->setSelected( false );
+ }
+ else {
+ // Some children exist.
+ itF->setWhichPixmap( "check_grey" );
+ itF->setSelected( true );
+ }
+
+ itF = itF->parentFolder;
+ }
+ else
+ {
+ UploadTreeFile *itFile = static_cast<UploadTreeFile*>(it);
+ if (it->isSelected())
+ {
+ itFile->setWhichPixmap("check");
+ itFile->setSelected(true);
+ } else
+ {
+ itFile->setWhichPixmap("check_clear");
+ itFile->setSelected(false);
+ }
+ itF = itFile->parentFolder;
+ }
+
+ //iterate through the item's parents and set the correct checkboxes for them
+ while (itF)
+ {
+ bool hasSelected = false;
+ bool allSelected = true;
+ //check if the item has any children's selected
+ QListViewItemIterator iter(itF->firstChild());
+ while ( iter.current() && iter.current() != itF->nextSibling())
+ {
+ if ( iter.current()->isSelected() )
+ {
+ hasSelected = true;
+ } else
+ {
+ allSelected = false;
+ }
+ ++iter;
+ }
+ if (hasSelected)
+ {
+ if (allSelected)
+ {
+ itF->setWhichPixmap( "check" );
+ } else
+ {
+ itF->setWhichPixmap( "check_grey" );
+ }
+ itF->setSelected( true );
+ } else
+ {
+ itF->setWhichPixmap( "check_clear" );
+ itF->setSelected( false );
+ }
+ itF = itF->parentFolder;
+ }
+}
+
+void UploadTreeView::slotSelectFile( )
+{
+ slotSelectFile(currentItem());
+}
+
+//TODO: This should search based on url's rather than on text(0)
+UploadTreeFolder* UploadTreeView::findFolder( UploadTreeFolder *it, const QString& folderName )
+{
+ QListViewItem *itIter = 0;
+ if (it == 0) itIter = firstChild();
+ else itIter = it->firstChild();
+
+ for( ; itIter != 0; itIter = itIter->nextSibling() )
+ {
+ if ( itIter->text(0) == folderName )
+ {
+ return (UploadTreeFolder *)itIter;
+ }
+ }
+ return 0;
+}
+
+UploadTreeFolder* UploadTreeView::printTree( UploadTreeFolder *it = 0,const QString& indent = QString::null )
+{
+ QListViewItem *itIter = 0;
+ if (it == 0) itIter = firstChild();
+ else itIter = it->firstChild();
+
+ for( ; itIter != 0; itIter = itIter->nextSibling() )
+ {
+// cout << indent << itIter->text(0) << endl;
+ if ( dynamic_cast<UploadTreeFolder *>(itIter) )
+ printTree( (UploadTreeFolder *)itIter, indent + " " );
+ }
+ return 0;
+}
+
+// :NOTE: AFAIK, safe to use only if you are sure the item searched for
+// is already in here. It might be safe otherwise, but use at your own
+// peril.
+QListViewItem* UploadTreeView::findItem(const QString& path )
+{
+ QString item = path;
+ UploadTreeFolder *it = 0;
+ int i;
+ while ( ( i = item.find('/') ) >= 0 )
+ {
+ it = findFolder( it, item.left(i) );
+ if ( it == 0 )
+ return 0;
+ item.remove(0,i+1);
+ }
+
+ QListViewItem *itIter = 0;
+ if ( it == 0 ) itIter = firstChild();
+ else itIter = it->firstChild();
+
+ for( ; itIter != 0; itIter = itIter->nextSibling() )
+ {
+ if ( itIter->text(0) == item )
+ {
+ return itIter;
+ }
+ }
+ return 0;
+}
+
+UploadTreeFile* UploadTreeView::addItem(const KURL &a_url, const KFileItem& a_fileItem)
+{
+ QString item = a_url.path(); //TODO: do with real KURL's
+ QString fname = item;
+ int i;
+ uint col = 0;
+ UploadTreeFolder *it = 0;
+ KURL u;
+ while ( ( i = item.find('/', col) ) >= 0 )
+ {
+ if ( i!=0 )
+ {
+ UploadTreeFolder *itTemp = findFolder(it, item.mid(col, i - col));
+ if ( itTemp == 0 )
+ {
+ u = a_url;
+ QuantaCommon::setUrl(u,item.left(i)+"/");
+ if ( it == 0 )
+ {
+ it = new UploadTreeFolder(u, this, "");
+ }
+ else {
+ it = new UploadTreeFolder(u, it, "");
+ }
+ }
+ else
+ {
+ it = itTemp;
+ }
+ }
+ col = i + 1;
+ }
+ UploadTreeFile *file = 0;
+ if ( col < item.length() )
+ {
+ if (it == 0)
+ {
+ file = new UploadTreeFile(this, a_url, a_fileItem);
+ }
+ else
+ {
+ file = new UploadTreeFile(it, a_url, a_fileItem);
+ }
+ }
+ return file;
+}
+
+void UploadTreeView::expandAll( QListViewItem *it )
+{
+ QListViewItem *itIter = it;
+ if (it == 0) itIter = firstChild();
+ else itIter = it->firstChild();
+
+ for( ; itIter != 0; itIter = itIter->nextSibling() )
+ {
+ if ( dynamic_cast<UploadTreeFolder *>(itIter) )
+ {
+ itIter->setOpen( true );
+ expandAll( itIter );
+ }
+ }
+}
+
+void UploadTreeView::collapseAll( QListViewItem *it )
+{
+ QListViewItem *itIter = it;
+ if (it == 0) itIter = firstChild();
+ else itIter = it->firstChild();
+
+ for( ; itIter != 0; itIter = itIter->nextSibling() )
+ {
+ if ( dynamic_cast<UploadTreeFolder *>(itIter) )
+ {
+ itIter->setOpen( false );
+ expandAll( itIter );
+ }
+ }
+}
+
+void UploadTreeView::invertAll( QListViewItem *it )
+{
+ QListViewItem *itIter = it;
+ if (it == 0) itIter = firstChild();
+ else itIter = it->firstChild();
+
+ for( ; itIter != 0; itIter = itIter->nextSibling() )
+ {
+ if ( dynamic_cast<UploadTreeFile *>(itIter) ||
+ ( dynamic_cast<UploadTreeFolder *>(itIter) &&
+ !itIter->firstChild()) )
+ {
+ itIter->setSelected( !itIter->isSelected() );
+ }
+ else
+ {
+ invertAll( itIter );
+ }
+ }
+}
+
+void UploadTreeView::selectAll( bool select )
+{
+ QListViewItemIterator it(this);
+
+ for ( ; it.current(); ++it )
+ {
+ if ( dynamic_cast<UploadTreeFile *>(it.current()) )
+ {
+ it.current()->setSelected( select);
+ } else
+ if ( dynamic_cast<UploadTreeFolder *>(it.current()) &&
+ !it.current()->firstChild() )
+ {
+ it.current()->setSelected( select);
+ }
+ }
+}
+
+
+/** No descriptions */
+QListViewItem* UploadTreeView::itemByUrl(const KURL& a_url)
+{
+ QListViewItemIterator it(this);
+ UploadTreeFile *fileItem;
+ UploadTreeFolder *folderItem;
+ KURL url;
+ for ( ; it.current(); ++it )
+ {
+ if ( (fileItem = dynamic_cast<UploadTreeFile *>(it.current()) ) !=0)
+ {
+ url = fileItem->m_url;
+ } else
+ {
+ folderItem = static_cast<UploadTreeFolder*>(it.current());
+ url = folderItem->m_url;
+ }
+ if (url == a_url)
+ {
+ return it.current();
+ }
+ }
+
+ return 0L;
+}
+
+void UploadTreeView::slotDoubleClicked(QListViewItem *item, const QPoint &, int )
+{
+ item->setOpen(!item->isOpen());
+}
+
+#include "uploadtreeview.moc"
diff --git a/quanta/treeviews/uploadtreeview.h b/quanta/treeviews/uploadtreeview.h
new file mode 100644
index 00000000..85676e41
--- /dev/null
+++ b/quanta/treeviews/uploadtreeview.h
@@ -0,0 +1,60 @@
+/***************************************************************************
+ uploadtreeview.h - description
+ -------------------
+ begin : Sun Aug 25 2002
+ copyright : (C) 2002, 2003 by 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; version 2 of the License. *
+ * *
+ ***************************************************************************/
+
+#ifndef UPLOADTREEVIEW_H
+#define UPLOADTREEVIEW_H
+
+#include <qdir.h>
+#include <qpixmap.h>
+#include <qheader.h>
+
+#include "uploadtreefolder.h"
+#include "uploadtreefile.h"
+
+class KFileItem;
+
+/**
+ *@author George Vilches & Andras Mantia
+ */
+
+class UploadTreeView : public KListView {
+ Q_OBJECT
+public:
+ UploadTreeView( QWidget *parent, const char *name=0L );
+ ~UploadTreeView();
+ UploadTreeFile* addItem( const KURL &a_url, const KFileItem &a_fileItem);
+ QListViewItem* findItem( const QString& );
+ int checkboxTree( QListViewItem *it = 0);
+ void expandAll( QListViewItem * = 0 );
+ void collapseAll( QListViewItem * = 0 );
+ void invertAll( QListViewItem * = 0 );
+ virtual void selectAll( bool select);
+ /** No descriptions */
+ QListViewItem* itemByUrl(const KURL& a_url);
+
+public slots:
+ void slotSelectFile( QListViewItem * );
+ void slotSelectFile( );
+ void selectAllUnderNode( QListViewItem *it, bool select );
+
+private slots:
+ void slotDoubleClicked(QListViewItem *, const QPoint &, int );
+
+private:
+ UploadTreeFolder* findFolder( UploadTreeFolder *, const QString&);
+ UploadTreeFolder* printTree( UploadTreeFolder *, const QString&);
+};
+
+#endif