diff options
Diffstat (limited to 'src/sidebar')
27 files changed, 5015 insertions, 0 deletions
diff --git a/src/sidebar/CMakeLists.txt b/src/sidebar/CMakeLists.txt new file mode 100644 index 0000000..8e555c2 --- /dev/null +++ b/src/sidebar/CMakeLists.txt @@ -0,0 +1,14 @@ +include_directories( + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_BINARY_DIR} +) + + +##### sidebar library (static) + +tde_add_library( sidebar STATIC_PIC AUTOMOC + SOURCES + sq_mountviewitem.cpp sq_mountview.cpp sq_imagebasket.cpp sq_directorybasket.cpp + sq_categorybrowsermenu.cpp sq_categoriesview.cpp sq_treeviewmenu.cpp sq_previewwidget.cpp + sq_storagefile.cpp sq_treeviewitem.cpp sq_threaddirlister.cpp sq_treeview.cpp sq_multibar.cpp +) diff --git a/src/sidebar/sq_categoriesview.cpp b/src/sidebar/sq_categoriesview.cpp new file mode 100644 index 0000000..0508e8d --- /dev/null +++ b/src/sidebar/sq_categoriesview.cpp @@ -0,0 +1,318 @@ +/*************************************************************************** + sq_categoriesview.cpp - description + ------------------- + begin : ??? June 3 2006 + copyright : (C) 2006 by Baryshev Dmitry + email : ksquirrel.iv@gmail.com + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <tqfile.h> +#include <tqheader.h> + +#include <tdeio/job.h> +#include <tdetoolbar.h> +#include <kicontheme.h> +#include <tdelocale.h> +#include <kmimetype.h> +#include <tdefileitem.h> +#include <kurldrag.h> +#include <kinputdialog.h> +#include <kpropertiesdialog.h> +#include <tdefiletreeviewitem.h> +#include <tdemessagebox.h> + +#include "ksquirrel.h" +#include "sq_dir.h" +#include "sq_iconloader.h" +#include "sq_categoriesview.h" +#include "sq_libraryhandler.h" +#include "sq_externaltool.h" +#include "sq_widgetstack.h" +#include "sq_categorybrowsermenu.h" +#include "sq_storagefile.h" +#include "sq_widgetstack.h" +#include "sq_diroperator.h" +#include "sq_treeviewmenu.h" + +SQ_CategoriesBox * SQ_CategoriesBox::sing = 0; + +/* *************************************************************************************** */ + +SQ_CategoriesViewBranch::SQ_CategoriesViewBranch(KFileTreeView *parent, const KURL &url, const TQString &name, const TQPixmap &pix) + : KFileTreeBranch(parent, url, name, pix) +{} + +SQ_CategoriesViewBranch::~SQ_CategoriesViewBranch() +{} + +KFileTreeViewItem* SQ_CategoriesViewBranch::createTreeViewItem(KFileTreeViewItem *parent, KFileItem *fileItem) +{ + KFileTreeViewItem *i = KFileTreeBranch::createTreeViewItem(parent, fileItem); + + /* + * In storage there are files with MD5 sum appended to their names. + * We should cut off MD5. + */ + if(i) + { + TQString n = i->fileItem()->name(); + int ind = n.findRev('.'); + + // OOPS + if(ind != -1) + n.truncate(ind); + + i->setText(0, n); + } + + return i; +} + +/* *************************************************************************************** */ + +SQ_CategoriesView::SQ_CategoriesView(TQWidget *parent, const char *name) : KFileTreeView(parent, name) +{ + setAcceptDrops(true); + + m_dir = new SQ_Dir(SQ_Dir::Categories); + + // create custom branch + root = new SQ_CategoriesViewBranch(this, m_dir->root(), i18n("Categories"), + SQ_IconLoader::instance()->loadIcon("bookmark", TDEIcon::Desktop, TDEIcon::SizeSmall)); + + addBranch(root); + + header()->hide(); + addColumn(i18n("File")); + setDirOnlyMode(root, false); + setRootIsDecorated(true); + setCurrentItem(root->root()); + root->setChildRecurse(true); + root->setOpen(true); + + menu = new SQ_TreeViewMenu(this); + + connect(this, TQ_SIGNAL(spacePressed(TQListViewItem*)), this, TQ_SIGNAL(executed(TQListViewItem*))); + connect(this, TQ_SIGNAL(returnPressed(TQListViewItem*)), this, TQ_SIGNAL(executed(TQListViewItem*))); + connect(this, TQ_SIGNAL(executed(TQListViewItem*)), this, TQ_SLOT(slotItemExecuted(TQListViewItem*))); + connect(this, TQ_SIGNAL(contextMenu(TDEListView*, TQListViewItem*, const TQPoint&)), this, TQ_SLOT(slotContextMenu(TDEListView*, TQListViewItem*, const TQPoint&))); +} + +SQ_CategoriesView::~SQ_CategoriesView() +{ + delete m_dir; +} + +void SQ_CategoriesView::slotContextMenu(TDEListView *, TQListViewItem *item, const TQPoint &p) +{ + if(item) + { + KFileTreeViewItem *kfi = static_cast<KFileTreeViewItem*>(item); + menu->updateDirActions(kfi->isDir(), (item == root->root())); + menu->setURL(kfi->url()); + menu->exec(p); + } +} + +void SQ_CategoriesView::slotItemExecuted(TQListViewItem *item) +{ + if(!item) return; + + if(item == root->root()) + { + root->setOpen(true); + return; + } + + KFileTreeViewItem *cur = static_cast<KFileTreeViewItem *>(item); + + // file item + if(cur && !cur->isDir()) + { + KURL inpath = SQ_StorageFile::readStorageFile(cur->path()); + + KFileItem fi(KFileItem::Unknown, KFileItem::Unknown, inpath); + SQ_WidgetStack::instance()->diroperator()->execute(&fi); + } +} + +/* ************************************************************** */ + +SQ_CategoriesBox::SQ_CategoriesBox(TQWidget *parent, const char *name) : TQVBox(parent, name) +{ + sing = this; + + lastdir = i18n("New Category"); + + view = new SQ_CategoriesView(this); + toolbar = new TDEToolBar(this); + + connect(view, TQ_SIGNAL(dropped(TQDropEvent*, TQListViewItem*, TQListViewItem*)), this, TQ_SLOT(slotDropped(TQDropEvent*, TQListViewItem*, TQListViewItem*))); + + menu = new SQ_CategoryBrowserMenu(view->dir()->root(), 0, "Categories menu"); + + toolbar->setIconSize(TDEIcon::SizeSmall); + + toolbar->insertButton("folder-new", 0, TQ_SIGNAL(clicked()), this, TQ_SLOT(slotNewCategory()), true, i18n("New category")); + toolbar->insertButton("edittrash", 0, TQ_SIGNAL(clicked()), this, TQ_SLOT(slotDeleteItem()), true, i18n("Delete")); + toolbar->insertButton("application-vnd.tde.info", 0, TQ_SIGNAL(clicked()), this, TQ_SLOT(slotItemProperties()), true, i18n("Properties")); + toolbar->insertButton("bookmark_add", 0, TQ_SIGNAL(clicked()), this, TQ_SLOT(slotDefaultCategories()), true, i18n("Create default categories")); + + view->popupMenu()->reconnect(SQ_TreeViewMenu::New, this, TQ_SLOT(slotNewCategory())); + view->popupMenu()->reconnect(SQ_TreeViewMenu::Delete, this, TQ_SLOT(slotDeleteItem())); + view->popupMenu()->reconnect(SQ_TreeViewMenu::Properties, this, TQ_SLOT(slotItemProperties())); +} + +SQ_CategoriesBox::~SQ_CategoriesBox() +{} + +void SQ_CategoriesBox::addToCategory(const TQString &path) +{ + KFileItemList *selected = const_cast<KFileItemList *>(SQ_WidgetStack::instance()->selectedItems()); + + if(!selected) return; + + KFileItem *item; + + item = selected->first(); + + while(item) + { + if(item->isFile()) + SQ_StorageFile::writeStorageFile(path + TQDir::separator() + item->name(), item->url().path()); + + item = selected->next(); + } +} + +void SQ_CategoriesBox::slotDefaultCategories() +{ + if(KMessageBox::questionYesNo(KSquirrel::app(), + i18n("This will create default categories: Concerts, Pets, Home, Friends, Free time, Travelling and Nature. Continue?"), + i18n("Create default categories")) == KMessageBox::Yes) + { + TQStringList list; + + list << "Concerts" << "Pets" << "Home" << "Friends" << "Free time" << "Traveling" << "Nature"; + + for(TQStringList::iterator it = list.begin();it != list.end();++it) + view->dir()->mkdir(*it); + } +} + +void SQ_CategoriesBox::slotNewCategory() +{ + bool ok; + + KFileTreeViewItem *cur = view->currentKFileTreeViewItem(); + + if(!cur) return; + + if(!cur->isDir()) + cur = static_cast<KFileTreeViewItem *>(cur->parent()); + + if(!cur) return; + + TQString tmp = KInputDialog::getText(i18n("New Category"), i18n("Create new category:"), + lastdir, &ok, this); + if(ok) + { + lastdir = tmp; + TDEIO::mkdir(cur->path() + TQDir::separator() + lastdir); + } +} + +void SQ_CategoriesBox::slotDropped(TQDropEvent *e, TQListViewItem *parent, TQListViewItem *item) +{ + if(!item) item = parent; + + KFileTreeViewItem *cur = static_cast<KFileTreeViewItem *>(item); + + if(!cur) return; + + KURL::List list; + KURLDrag::decode(e, list); + TQString path = cur->path(); + + if(list.first().path().startsWith(view->dir()->root())) + TDEIO::move(list, cur->url()); + else + { + KURL::List::iterator itEnd = list.end(); + TQString mimeDet; + + for(KURL::List::iterator it = list.begin(); it != itEnd;++it) + { + mimeDet = KMimeType::findByURL(*it)->name(); + + if(mimeDet != "inode/directory") + SQ_StorageFile::writeStorageFile(path + TQDir::separator() + (*it).fileName(), (*it)); + } + } +} + +void SQ_CategoriesBox::slotDeleteItem() +{ + KFileTreeViewItem *cur = view->currentKFileTreeViewItem(); + + if(!cur) return; + + KURL root; + root.setPath(view->dir()->root()); + + if(cur->url().equals(root, true)) + return; + + TQListViewItem *next = cur->itemBelow(); + if(!next) next = cur->itemAbove(); + + if(next) + { + view->setCurrentItem(next); + view->setSelected(next, true); + } + + TQString tmp = cur->path(); + + // remove this item manually + delete cur; + cur = 0; + + // physically remove file from storage + TDEIO::del(tmp, false, false); +} + +void SQ_CategoriesBox::slotItemProperties() +{ + KFileTreeViewItem *cur = view->currentKFileTreeViewItem(); + + if(!cur) return; + + // directory - just show its properties + if(cur->isDir()) + (void)new KPropertiesDialog(cur->url(), KSquirrel::app()); + + // link to real file + else + { + KURL inpath = SQ_StorageFile::readStorageFile(cur->path()); + + if(!inpath.isEmpty()) + (void)new KPropertiesDialog(inpath, KSquirrel::app()); + } +} + +#include "sq_categoriesview.moc" diff --git a/src/sidebar/sq_categoriesview.h b/src/sidebar/sq_categoriesview.h new file mode 100644 index 0000000..4fba48a --- /dev/null +++ b/src/sidebar/sq_categoriesview.h @@ -0,0 +1,131 @@ +/*************************************************************************** + sq_categoriesview.h - description + ------------------- + begin : ??? June 3 2006 + copyright : (C) 2006 by Baryshev Dmitry + email : ksquirrel.iv@gmail.com + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 SQ_CATEGORIESVIEW_H +#define SQ_CATEGORIESVIEW_H + +#include <tqvbox.h> + +#include <tdefiletreeview.h> +#include <tdefiletreebranch.h> + +class TDEToolBar; + +class SQ_CategoryBrowserMenu; +class SQ_TreeViewMenu; +class SQ_Dir; + +/** + *@author Baryshev Dmitry + */ + +/* *************************************************** */ + +class SQ_CategoriesViewBranch : public KFileTreeBranch +{ + public: + SQ_CategoriesViewBranch(KFileTreeView*, const KURL &url, const TQString &name, const TQPixmap &pix); + ~SQ_CategoriesViewBranch(); + + protected: + virtual KFileTreeViewItem *createTreeViewItem(KFileTreeViewItem *parent, KFileItem *fileItem); +}; + +/* *************************************************** */ + +class SQ_CategoriesView : public KFileTreeView +{ + TQ_OBJECT + + + public: + SQ_CategoriesView(TQWidget *parent = 0, const char *name = 0); + ~SQ_CategoriesView(); + + SQ_TreeViewMenu *popupMenu() const; + + SQ_Dir* dir(); + + private slots: + void slotItemExecuted(TQListViewItem *item); + void slotContextMenu(TDEListView *, TQListViewItem *i, const TQPoint &p); + + private: + KFileTreeBranch *root; + SQ_TreeViewMenu *menu; + + SQ_Dir *m_dir; +}; + +inline +SQ_TreeViewMenu* SQ_CategoriesView::popupMenu() const +{ + return menu; +} + +inline +SQ_Dir* SQ_CategoriesView::dir() +{ + return m_dir; +} + +/* *************************************************** */ + +class SQ_CategoriesBox : public TQVBox +{ + TQ_OBJECT + + + public: + SQ_CategoriesBox(TQWidget *parent = 0, const char *name = 0); + ~SQ_CategoriesBox(); + + /* + * Get current popup menu. + */ + SQ_CategoryBrowserMenu* popupMenu() const; + + /* + * Add selected files to some category + */ + void addToCategory(const TQString &); + + static SQ_CategoriesBox* instance() { return sing; }; + + private slots: + void slotNewCategory(); + void slotDefaultCategories(); + void slotDeleteItem(); + void slotItemProperties(); + void slotDropped(TQDropEvent *, TQListViewItem *, TQListViewItem *); + + private: + SQ_CategoriesView *view; + TDEToolBar *toolbar; + TQString lastdir, copypath; + SQ_CategoryBrowserMenu *menu; + + static SQ_CategoriesBox *sing; +}; + +inline +SQ_CategoryBrowserMenu* SQ_CategoriesBox::popupMenu() const +{ + return menu; +} + +#endif diff --git a/src/sidebar/sq_categorybrowsermenu.cpp b/src/sidebar/sq_categorybrowsermenu.cpp new file mode 100644 index 0000000..9b74c1d --- /dev/null +++ b/src/sidebar/sq_categorybrowsermenu.cpp @@ -0,0 +1,521 @@ +/* + * Copyright (C) 2006 Baryshev Dmitry, KSquirrel project + * + * Originally based on browser_mnu.cpp by (C) Matthias Elter + * from kde-3.2.3 + */ + +/***************************************************************** + +Copyright (c) 2001 Matthias Elter <elter@kde.org> + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +******************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <tqpixmap.h> +#include <tqdir.h> + +#include <tdeglobal.h> +#include <tdeconfig.h> +#include <tdelocale.h> +#include <tdeapplication.h> +#include <tdeprocess.h> +#include <kiconloader.h> +#include <tdesimpleconfig.h> +#include <tdedesktopfile.h> +#include <kmimetype.h> +#include <tdeglobalsettings.h> +#include <tdeio/global.h> +#include <krun.h> +#include <konq_operations.h> +#include <tdefileitem.h> +#include <kdirwatch.h> +#include <kstringhandler.h> +#include <kurldrag.h> + +#include "sq_dir.h" +#include "sq_categoriesview.h" +#include "sq_categorybrowsermenu.h" + +#define CICON(a) (*_icons)[a] + +TQMap<TQString, TQPixmap> *SQ_CategoryBrowserMenu::_icons = 0; + +SQ_CategoryBrowserMenu::SQ_CategoryBrowserMenu(TQString path, TQWidget *parent, const char *name, int startid) + : KPanelMenu(path, parent, name) + , _mimecheckTimer(0) + , _startid(startid) + , _dirty(false) +{ + _subMenus.setAutoDelete(true); + _lastpress = TQPoint(-1, -1); + setAcceptDrops(true); // Should depend on permissions of path. + + // we are not interested for dirty events on files inside the + // directory (see slotClearIfNeeded) + connect( &_dirWatch, TQ_SIGNAL(dirty(const TQString&)), + this, TQ_SLOT(slotClearIfNeeded(const TQString&)) ); + connect( &_dirWatch, TQ_SIGNAL(created(const TQString&)), + this, TQ_SLOT(slotClear()) ); + connect( &_dirWatch, TQ_SIGNAL(deleted(const TQString&)), + this, TQ_SLOT(slotClear()) ); +} + +SQ_CategoryBrowserMenu::~SQ_CategoryBrowserMenu() +{} + +void SQ_CategoryBrowserMenu::slotClearIfNeeded(const TQString& p) +{ + if (p == path()) + slotClear(); +} + + +void SQ_CategoryBrowserMenu::initialize() +{ + _lastpress = TQPoint(-1, -1); + + // don't change menu if already visible + if (isVisible()) + return; + + if (_dirty) { + // directory content changed while menu was visible + slotClear(); + setInitialized(false); + _dirty = false; + } + + if (initialized()) return; + setInitialized(true); + + // start watching if not already done + if (!_dirWatch.contains(path())) + _dirWatch.addDir( path() ); + + // setup icon map + initIconMap(); + + // read configuration + TDEConfig *c = TDEGlobal::config(); + c->setGroup("menus"); + _showhidden = c->readBoolEntry("ShowHiddenFiles", false); + _maxentries = c->readNumEntry("MaxEntries2", 30); + + // clear maps + _filemap.clear(); + _mimemap.clear(); + + int filter = TQDir::Dirs | TQDir::Files; + if(_showhidden) + filter |= TQDir::Hidden; + + TQDir dir(path(), TQString(), TQDir::DirsFirst | TQDir::Name | TQDir::IgnoreCase, filter); + + // does the directory exist? + if (!dir.exists()) { + insertItem(i18n("Failed to Read Folder")); + return; + } + + // get entry list + const TQFileInfoList *list = dir.entryInfoList(); + + // no list -> read error + if (!list) { + insertItem(i18n("Failed to Read Folder")); + return; + } + + KURL url; + url.setPath(path()); + if (!tdeApp->authorizeURLAction("list", KURL(), url)) + { + insertItem(i18n("Not Authorized to Read Folder")); + return; + } + + // insert file manager and terminal entries + // only the first part menu got them + if(_startid == 0) + { + SQ_Dir dir(SQ_Dir::Categories); + + if(dir.root() != path()) + { + insertTitle(path().right(path().length() - dir.root().length())); + insertItem(CICON("bookmark_add"), i18n("Add here"), this, TQ_SLOT(slotAddToCategory())); + } + } + + bool first_entry = true; + bool dirfile_separator = false; + int item_count = 0; + int run_id = _startid; + + // get list iterator + TQFileInfoListIterator it(*list); + + // jump to startid + it += _startid; + + // iterate over entry list + for (; it.current(); ++it) + { + // bump id + run_id++; + + TQFileInfo *fi = it.current(); + // handle directories + if (fi->isDir()) + { + TQString name = fi->fileName(); + + // ignore . and .. entries + if (name == "." || name == "..") continue; + + TQPixmap icon; + TQString path = fi->absFilePath(); + + // parse .directory if it does exist + if (TQFile::exists(path + "/.directory")) { + + TDESimpleConfig c(path + "/.directory", true); + c.setDesktopGroup(); + icon = TDEGlobal::iconLoader()->loadIcon(c.readEntry("Icon"), + TDEIcon::Small, TDEIcon::SizeSmall, + TDEIcon::DefaultState, 0, true); + if(icon.isNull()) + icon = CICON("folder"); + name = c.readEntry("Name", name); + } + + // use cached folder icon for directories without special icon + if (icon.isNull()) + icon = CICON("folder"); + + // insert separator if we are the first menu entry + if(first_entry) { + if (_startid == 0) + insertSeparator(); + first_entry = false; + } + + // append menu entry + append(icon, KStringHandler::cEmSqueeze( name, fontMetrics(), 20 ), + new SQ_CategoryBrowserMenu(path, this)); + + // bump item count + item_count++; + + dirfile_separator = true; + } +/* + // handle files + else if(fi->isFile()) + { + TQString name = fi->fileName(); + TQString title = TDEIO::decodeFileName(name); + + // ignore .directory and .order files + if (name == ".directory" || name == ".order") continue; + + TQPixmap icon; + TQString path = fi->absFilePath(); + + bool mimecheck = false; + + // .desktop files + if(TDEDesktopFile::isDesktopFile(path)) + { + TDESimpleConfig c(path, true); + c.setDesktopGroup(); + title = c.readEntry("Name", title); + + TQString s = c.readEntry("Icon"); + if(!_icons->contains(s)) { + icon = TDEGlobal::iconLoader()->loadIcon(s, TDEIcon::Small, TDEIcon::SizeSmall, + TDEIcon::DefaultState, 0, true); + + if(icon.isNull()) { + TQString type = c.readEntry("Type", "Application"); + if (type == "Directory") + icon = CICON("folder"); + else if (type == "Mimetype") + icon = CICON("txt"); + else if (type == "FSDevice") + icon = CICON("chardevice"); + else + icon = CICON("exec"); + } + else + _icons->insert(s, icon); + } + else + icon = CICON(s); + } + else { + // set unknown icon + icon = CICON("unknown"); + + // mark for delayed mimetime check + mimecheck = true; + } + + // insert separator if we are the first menu entry + if(first_entry) { + if(_startid == 0) + insertSeparator(); + first_entry = false; + } + + // insert separator if we we first file after at least one directory + if (dirfile_separator) { + insertSeparator(); + dirfile_separator = false; + } + + // append file entry + append(icon, title, name, mimecheck); + + // bump item count + item_count++; + } +*/ + if(item_count == _maxentries) { + // Only insert a "More..." item if there are actually more items. + ++it; + if( it.current() ) { + insertSeparator(); + append(CICON("folder_open"), i18n("More..."), new SQ_CategoryBrowserMenu(path(), this, 0, run_id)); + } + break; + } + } + +#if 0 + // WABA: tear off handles don't work together with dynamically updated + // menus. We can't update the menu while torn off, and we don't know + // when it is torn off. + if(TDEGlobalSettings::insertTearOffHandle() && item_count > 0) + insertTearOffHandle(); +#endif + + adjustSize(); + + TQString dirname = path(); + + int maxlen = contentsRect().width() - 40; + if(item_count == 0) + maxlen = fontMetrics().width(dirname); + + if (fontMetrics().width(dirname) > maxlen) { + while ((!dirname.isEmpty()) && (fontMetrics().width(dirname) > (maxlen - fontMetrics().width("...")))) + dirname = dirname.remove(0, 1); + dirname.prepend("..."); + } + setCaption(dirname); + + // setup and start delayed mimetype check timer + if(_mimemap.count() > 0) { + + if(!_mimecheckTimer) + _mimecheckTimer = new TQTimer(this); + + connect(_mimecheckTimer, TQ_SIGNAL(timeout()), TQ_SLOT(slotMimeCheck())); + _mimecheckTimer->start(0); + } +} + +void SQ_CategoryBrowserMenu::append(const TQPixmap &pixmap, const TQString &title, const TQString &file, bool mimecheck) +{ + // avoid &'s being converted to accelerators + TQString newTitle = title; + newTitle.replace("&", "&&"); + newTitle = KStringHandler::cEmSqueeze( newTitle, fontMetrics(), 20 ); + + // insert menu item + int id = insertItem(pixmap, newTitle); + + // insert into file map + _filemap.insert(id, file); + + // insert into mimetype check map + if(mimecheck) + _mimemap.insert(id, true); +} + +void SQ_CategoryBrowserMenu::append(const TQPixmap &pixmap, const TQString &title, SQ_CategoryBrowserMenu *subMenu) +{ + // avoid &'s being converted to accelerators + TQString newTitle = title; + newTitle.replace("&", "&&"); + newTitle = KStringHandler::cEmSqueeze( newTitle, fontMetrics(), 20 ); + + // insert submenu + insertItem(pixmap, newTitle, subMenu); + // remember submenu for later deletion + _subMenus.append(subMenu); +} + +void SQ_CategoryBrowserMenu::mousePressEvent(TQMouseEvent *e) +{ + TQPopupMenu::mousePressEvent(e); + _lastpress = e->pos(); +} + +void SQ_CategoryBrowserMenu::mouseMoveEvent(TQMouseEvent *e) +{ + TQPopupMenu::mouseMoveEvent(e); + + if (!(e->state() & TQt::LeftButton)) return; + if(_lastpress == TQPoint(-1, -1)) return; + + // DND delay + if((_lastpress - e->pos()).manhattanLength() < 12) return; + + // get id + int id = idAt(_lastpress); + if(!_filemap.contains(id)) return; + + // reset _lastpress + _lastpress = TQPoint(-1, -1); + + // start drag + KURL url; + url.setPath(path() + '/' + _filemap[id]); + KURL::List files(url); + KURLDrag *d = new KURLDrag(files, this); + d->setPixmap(iconSet(id)->pixmap()); + d->drag(); +} + +void SQ_CategoryBrowserMenu::dragEnterEvent( TQDragEnterEvent *ev ) +{ + if (KURLDrag::canDecode(ev)) + ev->accept(rect()); + KPanelMenu::dragEnterEvent(ev); +} + +void SQ_CategoryBrowserMenu::dropEvent( TQDropEvent *ev ) +{ + KFileItem item( path(), TQString::fromLatin1( "inode/directory" ), KFileItem::Unknown ); + KonqOperations::doDrop( &item, path(), ev, this ); + KPanelMenu::dropEvent(ev); + // ### TODO: Update list +} + +void SQ_CategoryBrowserMenu::slotExec(int id) +{ + tdeApp->propagateSessionManager(); + + if(!_filemap.contains(id)) return; + + KURL url; + url.setPath(path() + '/' + _filemap[id]); + new KRun(url, 0, true); // will delete itself + _lastpress = TQPoint(-1, -1); +} + +void SQ_CategoryBrowserMenu::slotAddToCategory() +{ + SQ_CategoriesBox::instance()->addToCategory(path()); +} + +void SQ_CategoryBrowserMenu::slotMimeCheck() +{ + // get the first map entry + TQMap<int, bool>::Iterator it = _mimemap.begin(); + + // no mime types left to check -> stop timer + if(it == _mimemap.end()) { + _mimecheckTimer->stop(); + return; + } + + int id = it.key(); + TQString file = _filemap[id]; + + _mimemap.remove(it); + + KURL url; + url.setPath( path() + '/' + file ); + +// KMimeType::Ptr mt = KMimeType::findByURL(url, 0, true, false); +// TQString icon(mt->icon(url, true)); + TQString icon = KMimeType::iconForURL( url ); +// kdDebug() << url.url() << ": " << icon << endl; + + file = KStringHandler::cEmSqueeze( file, fontMetrics(), 20 ); + + file.replace("&", "&&"); + if(!_icons->contains(icon)) { + TQPixmap pm = SmallIcon(icon); + if( pm.height() > 16 ) + { + TQPixmap cropped( 16, 16 ); + copyBlt( &cropped, 0, 0, &pm, 0, 0, 16, 16 ); + pm = cropped; + } + _icons->insert(icon, pm); + changeItem(id, pm, file); + } + else + changeItem(id, CICON(icon), file); +} + +void SQ_CategoryBrowserMenu::slotClear() +{ + // no need to watch any further + if (_dirWatch.contains(path())) + _dirWatch.removeDir( path() ); + + // don't change menu if already visible + if (isVisible()) { + _dirty = true; + return; + } + KPanelMenu::slotClear(); + _subMenus.clear(); // deletes submenus +} + +void SQ_CategoryBrowserMenu::initIconMap() +{ + if(_icons) return; + +// kdDebug() << "SQ_CategoryBrowserMenu::initIconMap" << endl; + + _icons = new TQMap<TQString, TQPixmap>; + + _icons->insert("folder", SmallIcon("folder")); + _icons->insert("unknown", SmallIcon("unknown")); + _icons->insert("folder_open", SmallIcon("folder_open")); + _icons->insert("kdisknav", SmallIcon("kdisknav")); + _icons->insert("kfm", SmallIcon("kfm")); + _icons->insert("terminal", SmallIcon("terminal")); + _icons->insert("txt", SmallIcon("text-plain")); + _icons->insert("exec", SmallIcon("application-x-executable")); + _icons->insert("chardevice", SmallIcon("chardevice")); +} + +#include "sq_categorybrowsermenu.moc" diff --git a/src/sidebar/sq_categorybrowsermenu.h b/src/sidebar/sq_categorybrowsermenu.h new file mode 100644 index 0000000..c2e0b77 --- /dev/null +++ b/src/sidebar/sq_categorybrowsermenu.h @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2006 Baryshev Dmitry, KSquirrel project + * + * Originally based on browser_mnu.h by (C) Matthias Elter + * from kde-3.2.3 + */ + +/***************************************************************** + +Copyright (c) 2001 Matthias Elter <elter@kde.org> + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +******************************************************************/ + +#ifndef __browser_mnu_h__ +#define __browser_mnu_h__ + +#include <tqmap.h> +#include <tqptrlist.h> +#include <kpanelmenu.h> +#include <kdirwatch.h> + +class SQ_CategoryBrowserMenu : public KPanelMenu +{ + TQ_OBJECT + + + public: + SQ_CategoryBrowserMenu(TQString path, TQWidget *parent = 0, const char *name = 0, int startid = 0); + ~SQ_CategoryBrowserMenu(); + + void append(const TQPixmap &pixmap, const TQString &title, const TQString &filename, bool mimecheck); + void append(const TQPixmap &pixmap, const TQString &title, SQ_CategoryBrowserMenu *subMenu); + + public slots: + void initialize(); + + protected slots: + void slotExec(int id); + void slotAddToCategory(); + void slotMimeCheck(); + void slotClearIfNeeded(const TQString&); + void slotClear(); + + protected: + void mousePressEvent(TQMouseEvent *); + void mouseMoveEvent(TQMouseEvent *); + void dropEvent(TQDropEvent *ev); + void dragEnterEvent(TQDragEnterEvent *ev); + void initIconMap(); + + TQPoint _lastpress; + TQMap<int, TQString> _filemap; + TQMap<int, bool> _mimemap; + TQTimer *_mimecheckTimer; + KDirWatch _dirWatch; + TQPtrList<SQ_CategoryBrowserMenu> _subMenus; + + int _startid; + bool _showhidden; + int _maxentries; + bool _dirty; + + static TQMap<TQString, TQPixmap> *_icons; +}; + +#endif diff --git a/src/sidebar/sq_directorybasket.cpp b/src/sidebar/sq_directorybasket.cpp new file mode 100644 index 0000000..74ba7e2 --- /dev/null +++ b/src/sidebar/sq_directorybasket.cpp @@ -0,0 +1,520 @@ +/*************************************************************************** + sq_directorybasket.cpp - description + ------------------- + begin : ??? Sep 29 2007 + copyright : (C) 2007 by Baryshev Dmitry + email : ksquirrel.iv@gmail.com + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 <tqvaluevector.h> +#include <tqstringlist.h> +#include <tqheader.h> +#include <tqcursor.h> +#include <tqtimer.h> + +#include <tdeglobal.h> +#include <tdelocale.h> +#include <kurldrag.h> +#include <kmimetype.h> +#include <tdefiledialog.h> +#include <kinputdialog.h> +#include <kicondialog.h> +#include <kiconloader.h> +#include <tdeio/netaccess.h> +#include <tdeio/job.h> +#include <kprogress.h> +#include <tdeglobalsettings.h> + +#include "ksquirrel.h" +#include "sq_directorybasket.h" +#include "sq_storagefile.h" +#include "sq_iconloader.h" +#include "sq_treeviewmenu.h" +#include "sq_widgetstack.h" +#include "sq_diroperator.h" +#include "sq_navigatordropmenu.h" +#include "sq_dir.h" + +SQ_DirectoryBasket * SQ_DirectoryBasket::m_inst = 0; + +/* ******************************************************************************* */ + +SQ_DBMenu::SQ_DBMenu(TQWidget *parent, const char *name) : SQ_TreeViewMenu(parent, name), item(0) +{ + insertSeparator(); + id_icon = insertItem(i18n("Change icon"), this, TQ_SLOT(slotChangeIcon())); +} + +SQ_DBMenu::~SQ_DBMenu() +{} + +void SQ_DBMenu::slotChangeIcon() +{ + TDEIconDialog dialog(TDEGlobal::iconLoader()); + dialog.setup(TDEIcon::Desktop, TDEIcon::MimeType, true, TDEIcon::SizeSmall); + TQString result = dialog.openDialog(); + + if(!result.isEmpty() && item) + { + item->setIcon(result); + item->setPixmap(0, SQ_IconLoader::instance()->loadIcon(result, TDEIcon::Desktop, TDEIcon::SizeSmall)); + } +} + +void SQ_DBMenu::updateDirActions(bool, bool isroot) +{ + setItemEnabled(id_new, isroot); + setItemEnabled(id_clear, isroot); + setItemEnabled(id_prop, !isroot); + + setItemEnabled(id_delete, !isroot); + setItemEnabled(id_rename, !isroot); + setItemEnabled(id_icon, !isroot); +} + +void SQ_DBMenu::slotDirectoryRename() +{ + if(item) + { + TQString renameSrc = item->text(0); + bool ok; + + TQString mNewFilename = KInputDialog::getText(i18n("Rename Folder"), + i18n("<p>Rename item <b>%1</b> to:</p>").arg(renameSrc), + renameSrc, &ok, KSquirrel::app()); + + if(ok) + { + item->setName(mNewFilename); + item->setText(0, mNewFilename); + } + } +} + +void SQ_DBMenu::slotDirectoryResult(TDEIO::Job *job) +{ + if(job && job->error()) + job->showErrorDialog(KSquirrel::app()); +} + +void SQ_DBMenu::slotDirectoryDelete() +{ + if(item) + { + TDEIO::Job *job = TDEIO::del(item->KFileTreeViewItem::url()); + + connect(job, TQ_SIGNAL(result(TDEIO::Job*)), this, TQ_SLOT(slotDirectoryResult(TDEIO::Job *))); + } +} + +/* ******************************************************************************* */ + +SQ_DirectoryItem::SQ_DirectoryItem(KFileTreeViewItem *parentItem, KFileItem *fileItem, KFileTreeBranch *parentBranch) + : KFileTreeViewItem(parentItem, fileItem, parentBranch), m_index(0) +{} + +SQ_DirectoryItem::SQ_DirectoryItem(KFileTreeView *parent, KFileItem *fileItem, KFileTreeBranch *parentBranch) + : KFileTreeViewItem(parent, fileItem, parentBranch), m_index(0) +{} + +SQ_DirectoryItem::~SQ_DirectoryItem() +{} + +/* ******************************************************************************* */ + +SQ_DirectoryBasketBranch::SQ_DirectoryBasketBranch(KFileTreeView *parent, const KURL &url, const TQString &name, const TQPixmap &pix) + : KFileTreeBranch(parent, url, name, pix) +{} + +SQ_DirectoryBasketBranch::~SQ_DirectoryBasketBranch() +{} + +KFileTreeViewItem* SQ_DirectoryBasketBranch::createTreeViewItem(KFileTreeViewItem *parent, KFileItem *fileItem) +{ + if(!parent || !fileItem) + return 0; + + // hehe... + fileItem->setMimeType("inode/directory"); + + SQ_DirectoryItem *i = new SQ_DirectoryItem(parent, fileItem, this); + + if(i) + { + // inpath = "<URL><name><index>" + TQStringList list = TQStringList::split(TQChar('\n'), SQ_StorageFile::readStorageFileAsString(i->path()), true); + + if(list.count() < 4) + return i; + + TQStringList::iterator it = list.begin(); + + bool ok; + TQString name, icon; + + // get url + KURL inpath = KURL::fromPathOrURL(*it); + ++it; + + // get name + name = *it; + ++it; + + // get icon + icon = *it; + ++it; + + // get index + int index = (*it).toInt(&ok); + + i->setURL(inpath); + + if(name.isEmpty()) + i->setText(0, inpath.isLocalFile() ? inpath.path() : inpath.prettyURL()); + else + { + i->setText(0, name); + i->setName(name); + } + + if(!icon.isEmpty()) + { + i->setIcon(icon); + i->setPixmap(0, SQ_IconLoader::instance()->loadIcon(icon, TDEIcon::Desktop, TDEIcon::SizeSmall)); + } + + if(ok) i->setIndex(index); + } + + return i; +} + +/* ******************************************************************************* */ + +SQ_DirectoryBasket::SQ_DirectoryBasket(TQWidget *parent, const char *name) : KFileTreeView(parent, name) +{ + m_inst = this; + + progressAdd = new KProgress(0, "progress add", TQt::WStyle_StaysOnTop | TQt::WStyle_Customize | TQt::WStyle_NoBorder | TQt::WX11BypassWM); + + menu = new SQ_DBMenu(this); + + timer = new TQTimer(this); + connect(timer, TQ_SIGNAL(timeout()), this, TQ_SLOT(slotSortReal())); + + timerAdd = new TQTimer(this); + connect(timerAdd, TQ_SIGNAL(timeout()), this, TQ_SLOT(slotDelayedShowAdd())); + + setSorting(-1); + setAcceptDrops(true); + + dir = new SQ_Dir(SQ_Dir::DirectoryBasket); + + // create custom branch + root = new SQ_DirectoryBasketBranch(this, dir->root(), TQString(), + SQ_IconLoader::instance()->loadIcon("folder", TDEIcon::Desktop, TDEIcon::SizeSmall)); + + // some hacks to create our SQ_TreeViewItem as root item + SQ_DirectoryItem *ritem = new SQ_DirectoryItem(this, + new KFileItem(dir->root(), + "inode/directory", S_IFDIR), + root); + + ritem->setText(0, i18n("Folders")); + ritem->setExpandable(true); + ritem->setURL(dir->root()); + delete root->root(); + root->setRoot(ritem); + + addBranch(root); + + disconnect(root, TQ_SIGNAL(refreshItems(const KFileItemList &)), 0, 0); + + header()->hide(); + addColumn(i18n("File")); + setDirOnlyMode(root, false); + setCurrentItem(root->root()); + root->setOpen(true); + setRootIsDecorated(false); + + menu->reconnect(SQ_TreeViewMenu::New, this, TQ_SLOT(slotNewDirectory())); + + connect(this, TQ_SIGNAL(spacePressed(TQListViewItem*)), this, TQ_SIGNAL(executed(TQListViewItem*))); + connect(this, TQ_SIGNAL(returnPressed(TQListViewItem*)), this, TQ_SIGNAL(executed(TQListViewItem*))); + connect(this, TQ_SIGNAL(executed(TQListViewItem*)), this, TQ_SLOT(slotItemExecuted(TQListViewItem*))); + connect(this, TQ_SIGNAL(contextMenu(TDEListView*, TQListViewItem*, const TQPoint&)), this, TQ_SLOT(slotContextMenu(TDEListView*, TQListViewItem*, const TQPoint&))); + connect(this, TQ_SIGNAL(dropped(TQDropEvent*, TQListViewItem*, TQListViewItem*)), this, TQ_SLOT(slotDropped(TQDropEvent*, TQListViewItem*, TQListViewItem*))); + connect(this, TQ_SIGNAL(itemRenamed(TQListViewItem *, int, const TQString &)), this, TQ_SLOT(slotItemRenamedMy(TQListViewItem *, int, const TQString &))); + connect(this, TQ_SIGNAL(itemAdded(TQListViewItem *)), this, TQ_SLOT(slotSort())); + connect(this, TQ_SIGNAL(moved()), this, TQ_SLOT(slotReindex())); +} + +SQ_DirectoryBasket::~SQ_DirectoryBasket() +{ + SQ_DirectoryItem *item = static_cast<SQ_DirectoryItem *>(root->root()->firstChild()); + + static const TQString &nl = TDEGlobal::staticQString("\n"); + + if(item) + { + TQString url; + int index = 0; + + do + { + url = item->url().prettyURL() + nl + item->name() + nl + item->icon() + nl + TQString::number(index); + + SQ_StorageFile::writeStorageFileAsString( + dir->root() + TQDir::separator() + item->url().fileName(), + item->url(), url); + + ++index; + } + while((item = static_cast<SQ_DirectoryItem *>(item->nextSibling()))); + } + + delete dir; + delete progressAdd; +} + +void SQ_DirectoryBasket::slotNewDirectory() +{ + static const TQString &nl = TDEGlobal::staticQString("\n"); + + KURL url = KFileDialog::getExistingURL(TQString(), KSquirrel::app()); + + if(url.isEmpty()) + return; + + SQ_StorageFile::writeStorageFileAsString( + dir->root() + TQDir::separator() + url.fileName(), + url, + (url.prettyURL() + nl + nl + nl + TQString::number(root->root()->childCount()))); +} + +void SQ_DirectoryBasket::slotDropped(TQDropEvent *e, TQListViewItem *_parent, TQListViewItem *_item) +{ + if(!_parent) return; + if(!_item) _item = _parent; + + SQ_DirectoryItem *item = static_cast<SQ_DirectoryItem *>(_item); + SQ_DirectoryItem *parent = static_cast<SQ_DirectoryItem *>(_parent); + + KURL::List list; + KURLDrag::decode(e, list); + + // drag'n'drop inside basket + if(e->source() == this) + { + SQ_DirectoryItem *tomove = static_cast<SQ_DirectoryItem *>(root->findTVIByURL(list.first())); + + if(!tomove || tomove == root->root()) return; + + SQ_DirectoryItem *it; + + if(item->index() < tomove->index() && item != root->root()) + it = static_cast<SQ_DirectoryItem *>(item->itemAbove()); + else + it = static_cast<SQ_DirectoryItem *>(item); + + if(it) + { + if(it != root->root()) + moveItem(tomove, parent, it); + else + moveItem(tomove, parent, 0); + + emit moved(); + + setCurrentItem(tomove); + setSelected(tomove, true); + } + } + else if(item == root->root()) // some files were dropped from another source + { + KURL::List::iterator itEnd = list.end(); + KFileItemList flist; + TDEIO::UDSEntry entry; + + progressAdd->setTotalSteps(list.count()); + timerAdd->start(1000, true); + + for(KURL::List::iterator it = list.begin();it != itEnd;++it) + { + if(TDEIO::NetAccess::stat(*it, entry, KSquirrel::app())) + flist.append(new KFileItem(entry, *it)); + + progressAdd->advance(1); + } + + timerAdd->stop(); + progressAdd->hide(); + + add(flist); + flist.setAutoDelete(true); + } + else + { + SQ_NavigatorDropMenu::instance()->setupFiles(list, item->url()); + SQ_NavigatorDropMenu::instance()->exec(TQCursor::pos(), true); + } +} + +void SQ_DirectoryBasket::slotItemExecuted(TQListViewItem *item) +{ + if(!item) return; + + if(item == root->root()) + { + root->setOpen(true); + return; + } + + KFileTreeViewItem *cur = static_cast<KFileTreeViewItem *>(item); + + if(cur && !cur->isDir()) + { + KURL inpath = SQ_StorageFile::readStorageFile(cur->path()); + SQ_WidgetStack::instance()->diroperator()->setURL(inpath, true); + } +} + +void SQ_DirectoryBasket::slotContextMenu(TDEListView *, TQListViewItem *item, const TQPoint &p) +{ + if(item) + { + SQ_DirectoryItem *kfi = static_cast<SQ_DirectoryItem *>(item); + + if(kfi) + { + menu->updateDirActions(true, item == root->root()); + menu->setURL(kfi->url()); + menu->setItem(kfi); + menu->exec(p); + } + } +} + +void SQ_DirectoryBasket::add(const KFileItemList &list) +{ + static const TQString &nl = TDEGlobal::staticQString("\n"); + + KFileItemListIterator it(list); + KFileItem *fi; + TQString url; + + while((fi = it.current())) + { + if(fi->isDir()) + { + url = fi->url().prettyURL() + nl + nl + nl + TQString::number(root->root()->childCount()); + + SQ_StorageFile::writeStorageFileAsString( + dir->root() + TQDir::separator() + fi->url().fileName(), + fi->url(), + url); + } + + ++it; + } +} + +void SQ_DirectoryBasket::slotSort() +{ + timer->start(100, true); +} + +void SQ_DirectoryBasket::slotSortReal() +{ + sort(); +} + +struct SortableItem +{ + SortableItem(TQListViewItem *i, int ind) : item(i), index(ind) + {} + + SortableItem() : item(0), index(0) + {} + + bool operator< (const SortableItem &i) + { + return index > i.index; + } + + TQListViewItem *item; + int index; +}; + +void SQ_DirectoryBasket::sort() +{ + TQListViewItemIterator it(this); + SQ_DirectoryItem *item; + + TQValueVector<SortableItem> items; + int i = 0; + ++it; + + while((item = static_cast<SQ_DirectoryItem *>(it.current()))) + { + items.append(SortableItem(item, item->index())); + ++it; + } + + const int nChildren = items.count(); + + for(i = 0;i < nChildren;i++) + root->root()->takeItem(items[i].item); + + qHeapSort(items); + + blockSignals(true); + for(i = 0;i < nChildren;i++) + root->root()->insertItem(items[i].item); + blockSignals(false); +} + +void SQ_DirectoryBasket::slotReindex() +{ + SQ_DirectoryItem *item = static_cast<SQ_DirectoryItem *>(root->root()->firstChild()); + + if(item) + { + int index = 0; + + do + { + item->setIndex(index++); + } + while((item = static_cast<SQ_DirectoryItem *>(item->nextSibling()))); + } +} + +void SQ_DirectoryBasket::slotItemRenamedMy(TQListViewItem *_item, int, const TQString &name) +{ + SQ_DirectoryItem *item = static_cast<SQ_DirectoryItem *>(_item); + + if(item) + item->setName(name); +} + +void SQ_DirectoryBasket::slotDelayedShowAdd() +{ + int w = 200, h = 32; + + TQRect rc = TDEGlobalSettings::splashScreenDesktopGeometry(); + + progressAdd->setGeometry(rc.center().x() - w/2, rc.center().y() - h/2, w, h); + progressAdd->show(); +} + +#include "sq_directorybasket.moc" diff --git a/src/sidebar/sq_directorybasket.h b/src/sidebar/sq_directorybasket.h new file mode 100644 index 0000000..6f2858d --- /dev/null +++ b/src/sidebar/sq_directorybasket.h @@ -0,0 +1,195 @@ +/*************************************************************************** + sq_directorybasket.h - description + ------------------- + begin : ??? Sep 29 2007 + copyright : (C) 2007 by Baryshev Dmitry + email : ksquirrel.iv@gmail.com + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 SQ_DIRECTORYBASKET_H +#define SQ_DIRECTORYBASKET_H + +#include <tdefiletreeview.h> +#include <tdefiletreebranch.h> + +#include "sq_treeviewmenu.h" + +class TQTimer; + +class KProgress; + +namespace TDEIO { class Job; } + +class SQ_DirectoryItem; +class SQ_Dir; + +class SQ_DBMenu : public SQ_TreeViewMenu +{ + TQ_OBJECT + + + public: + SQ_DBMenu(TQWidget *parent = 0, const char *name = 0); + ~SQ_DBMenu(); + + virtual void updateDirActions(bool, bool isroot = false); + + void setItem(SQ_DirectoryItem *); + + private slots: + void slotChangeIcon(); + void slotDirectoryRename(); + void slotDirectoryDelete(); + void slotDirectoryResult(TDEIO::Job *job); + + private: + SQ_DirectoryItem *item; + int id_icon; +}; + +inline +void SQ_DBMenu::setItem(SQ_DirectoryItem *i) +{ + item = i; +} + +class SQ_DirectoryItem : public KFileTreeViewItem +{ + public: + SQ_DirectoryItem(KFileTreeViewItem *parentItem, KFileItem *fileItem, KFileTreeBranch *parentBranch); + SQ_DirectoryItem(KFileTreeView *parent, KFileItem *fileItem, KFileTreeBranch *parentBranch); + ~SQ_DirectoryItem(); + + int index() const; + void setIndex(int ind); + + KURL url() const; + void setURL(const KURL &u); + + TQString name() const; + void setName(const TQString &n); + + TQString icon() const; + void setIcon(const TQString &n); + + bool hasName() const; + + private: + int m_index; + TQString m_name, m_icon; + KURL m_url; +}; + +inline +KURL SQ_DirectoryItem::url() const +{ + return m_url; +} + +inline +void SQ_DirectoryItem::setURL(const KURL &u) +{ + m_url = u; +} + +inline +int SQ_DirectoryItem::index() const +{ + return m_index; +} + +inline +void SQ_DirectoryItem::setIndex(int ind) +{ + m_index = ind; +} + +inline +TQString SQ_DirectoryItem::name() const +{ + return m_name; +} + +inline +void SQ_DirectoryItem::setName(const TQString &n) +{ + m_name = n; +} + +inline +TQString SQ_DirectoryItem::icon() const +{ + return m_icon; +} + +inline +void SQ_DirectoryItem::setIcon(const TQString &n) +{ + m_icon = n; +} + +inline +bool SQ_DirectoryItem::hasName() const +{ + return !m_name.isEmpty(); +} + +/* ****************************************************************** */ + +class SQ_DirectoryBasketBranch : public KFileTreeBranch +{ + public: + SQ_DirectoryBasketBranch(KFileTreeView*, const KURL &url, const TQString &name, const TQPixmap &pix); + ~SQ_DirectoryBasketBranch(); + + protected: + virtual KFileTreeViewItem *createTreeViewItem(KFileTreeViewItem *parent, KFileItem *fileItem); +}; + +class SQ_DirectoryBasket : public KFileTreeView +{ + TQ_OBJECT + + + public: + SQ_DirectoryBasket(TQWidget *parent = 0, const char *name = 0); + ~SQ_DirectoryBasket(); + + void add(const KFileItemList &list); + + static SQ_DirectoryBasket* instance() { return m_inst; } + + private: + void sort(); + + private slots: + void slotDropped(TQDropEvent *, TQListViewItem *, TQListViewItem *); + void slotItemExecuted(TQListViewItem *item); + void slotContextMenu(TDEListView *, TQListViewItem *item, const TQPoint &p); + void slotNewDirectory(); + void slotSortReal(); + void slotSort(); + void slotReindex(); + void slotItemRenamedMy(TQListViewItem *, int, const TQString &); + void slotDelayedShowAdd(); + + private: + KFileTreeBranch *root; + SQ_Dir *dir; + TQTimer *timer, *timerAdd; + SQ_DBMenu *menu; + KProgress *progressAdd; + + static SQ_DirectoryBasket *m_inst; +}; + +#endif diff --git a/src/sidebar/sq_imagebasket.cpp b/src/sidebar/sq_imagebasket.cpp new file mode 100644 index 0000000..eeba95c --- /dev/null +++ b/src/sidebar/sq_imagebasket.cpp @@ -0,0 +1,291 @@ +/*************************************************************************** + sq_imagebasket.cpp - description + ------------------- + begin : ??? Feb 24 2007 + copyright : (C) 2004 by Baryshev Dmitry + email : ksquirrel.iv@gmail.com + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 <tqfile.h> + +#include <kmdcodec.h> +#include <tdefileview.h> +#include <tdelocale.h> +#include <tdeglobal.h> +#include <tdepopupmenu.h> +#include <tdefileiconview.h> +#include <kpropertiesdialog.h> +#include <tdeio/netaccess.h> +#include <tdeapplication.h> +#include <kmimetype.h> + +#include "ksquirrel.h" +#include "sq_config.h" +#include "sq_imagebasket.h" +#include "sq_storagefile.h" +#include "sq_dir.h" +#include "sq_widgetstack.h" +#include "sq_diroperator.h" + +SQ_ImageBasket * SQ_ImageBasket::m_inst; + +SQ_ImageBasket::SQ_ImageBasket(TQWidget *parent, const char *name) : KDirOperator((dir = new SQ_Dir(SQ_Dir::Basket))->root(), parent, name) +{ + m_inst = this; + + connect(this, TQ_SIGNAL(dropped(const KFileItem *, TQDropEvent*, const KURL::List&)), + this, TQ_SLOT(slotDropped(const KFileItem *, TQDropEvent*, const KURL::List&))); + + disconnect(dirLister(), TQ_SIGNAL(refreshItems(const KFileItemList &)), 0, 0); + + // redirect "Properties" dialog + disconnect(actionCollection()->action("properties"), 0, 0, 0); + connect(actionCollection()->action("properties"), TQ_SIGNAL(activated()), this, TQ_SLOT(slotBasketProperties())); + + disconnect(dirLister(), TQ_SIGNAL(newItems(const KFileItemList &)), 0, 0); + connect(dirLister(), TQ_SIGNAL(newItems(const KFileItemList &)), this, TQ_SLOT(insertNewFiles(const KFileItemList &))); + + connect(this, TQ_SIGNAL(viewChanged(KFileView *)), this, TQ_SLOT(slotViewChanged(KFileView *))); + connect(this, TQ_SIGNAL(fileSelected(const KFileItem *)), this, TQ_SLOT(slotExecuted(const KFileItem *))); + + setView(KFile::Simple); + setMode(KFile::Files); + + setAcceptDrops(true); + + SQ_Config::instance()->setGroup("Fileview"); + int sorting = 0; + + if(SQ_Config::instance()->readBoolEntry("basket_sorting_name", true)) sorting |= TQDir::Name; + if(SQ_Config::instance()->readBoolEntry("basket_sorting_time", false)) sorting |= TQDir::Time; + if(SQ_Config::instance()->readBoolEntry("basket_sorting_size", false)) sorting |= TQDir::Size; + if(SQ_Config::instance()->readBoolEntry("basket_sorting_dirs", true)) sorting |= TQDir::DirsFirst; + if(SQ_Config::instance()->readBoolEntry("basket_sorting_reverse", false)) sorting |= TQDir::Reversed; + if(SQ_Config::instance()->readBoolEntry("basket_sorting_ignore", false)) sorting |= TQDir::IgnoreCase; + + setSorting(static_cast<TQDir::SortSpec>(sorting)); +} + +SQ_ImageBasket::~SQ_ImageBasket() +{ + delete dir; +} + +void SQ_ImageBasket::insertNewFiles(const KFileItemList &list) +{ + TQString n; + int ind; + KFileItemListIterator it(list); + KFileItem *tmp; + + for(; (tmp = it.current()); ++it) + { + n = tmp->name(); + ind = n.findRev('.'); + + // OOPS + if(ind != -1) + n.truncate(ind); + + // force determining mimetype + (void)tmp->mimetype(); + tmp->setName(n); + + TQStringList list = TQStringList::split(TQChar('\n'), SQ_StorageFile::readStorageFileAsString(tmp->url().path()), true); + TQStringList::iterator it = list.begin(); + + if(list.count() > 1) + { + ++it; // skip url + tmp->setMimeType(*it); + } + else + { + KURL url = KURL::fromPathOrURL(*it); + TQString mime = KMimeType::findByURL(url)->name(); + tmp->setMimeType(mime); + + static const TQString &nl = TDEGlobal::staticQString("\n"); + + TQString inurl = url.prettyURL() + nl + mime; + + SQ_StorageFile::writeStorageFileAsString( + dir->root() + TQDir::separator() + url.fileName(), + url, inurl); + } + } + + view()->addItemList(list); +} + +void SQ_ImageBasket::add(const KFileItemList &list) +{ + KFileItem *tmp; + static const TQString &nl = TDEGlobal::staticQString("\n"); + + for(KFileItemListIterator it(list); (tmp = it.current()); ++it) + { + if(tmp->isFile()) + { + TQString inurl = tmp->url().prettyURL() + nl + tmp->mimetype(); + + SQ_StorageFile::writeStorageFileAsString( + dir->root() + TQDir::separator() + tmp->name(), + tmp->url(), inurl); + } + } +} + +void SQ_ImageBasket::slotDropped(const KFileItem *, TQDropEvent*, const KURL::List &list) +{ + TQString name; + KURL::List::const_iterator itEnd = list.end(); + static const TQString &nl = TDEGlobal::staticQString("\n"); + + for(KURL::List::const_iterator it = list.begin();it != itEnd;++it) + { + TQString inurl = (*it).prettyURL() + nl + KMimeType::findByURL(*it)->name(); + + SQ_StorageFile::writeStorageFileAsString( + dir->root() + TQDir::separator() + (*it).fileName(), + *it, inurl); + } +} + +void SQ_ImageBasket::slotBasketProperties() +{ + KFileView *fileView = view(); + + if(fileView) + { + KFileItemList newlist; + KFileItem *item = 0; + + newlist.setAutoDelete(true); + + for((item = fileView->firstFileItem()); item; item = fileView->nextItem(item)) + { + if(fileView->isSelected(item)) + { + KFileItem *realFile = new KFileItem(KFileItem::Unknown, KFileItem::Unknown, + SQ_StorageFile::readStorageFile(item->url().path())); + + newlist.append(realFile); + } + } + + if (!newlist.isEmpty()) + (void)new KPropertiesDialog(newlist, KSquirrel::app(), "props dlg", true); + } +} + +KFileItemList SQ_ImageBasket::realItems() const +{ + KFileView *fileView = view(); + KFileItemList newlist; + + newlist.setAutoDelete(true); + + if(fileView) + { + KFileItem *item = 0; + + for((item = fileView->firstFileItem()); item; item = fileView->nextItem(item)) + { + KFileItem *realFile = new KFileItem(KFileItem::Unknown, KFileItem::Unknown, + SQ_StorageFile::readStorageFile(item->url().path())); + + newlist.append(realFile); + } + } + + return newlist; +} + +void SQ_ImageBasket::slotSync() +{ + KFileView *fileView = view(); + + if(fileView) + { + KFileItem *item = 0; + KURL path; + TDEIO::UDSEntry entry; + + for((item = fileView->firstFileItem()); item; item = fileView->nextItem(item)) + { + path = SQ_StorageFile::readStorageFile(item->url().path()); + + if(!TDEIO::NetAccess::stat(path, entry, KSquirrel::app())) + TQFile::remove(item->url().path()); + } + } +} + +void SQ_ImageBasket::slotViewChanged(KFileView *v) +{ + KFileIconView *iv = dynamic_cast<KFileIconView *>(v); + + if(iv) + { + TDEAction *a; + + a = iv->actionCollection()->action("zoomIn"); + if(a) a->setShortcut(0); + + a = iv->actionCollection()->action("zoomOut"); + if(a) a->setShortcut(0); + + a = iv->actionCollection()->action("show previews"); + if(a) a->setShortcut(0); + } +} + +void SQ_ImageBasket::slotExecuted(const KFileItem *fi) +{ + if(!fi) + return; + + KURL inpath = SQ_StorageFile::readStorageFile(fi->url().path()); + + KFileItem f(KFileItem::Unknown, KFileItem::Unknown, inpath); + + SQ_WidgetStack::instance()->diroperator()->execute(&f); +} + +void SQ_ImageBasket::activatedMenu(const KFileItem *, const TQPoint &pos) +{ + setupMenu(KDirOperator::AllActions ^ KDirOperator::NavActions ^ KDirOperator::ViewActions); + updateSelectionDependentActions(); + + TDEActionMenu *pADirOperatorMenu = dynamic_cast<TDEActionMenu *>(actionCollection()->action("popupMenu")); + pADirOperatorMenu->popupMenu()->insertItem(i18n("Synchronize"), this, TQ_SLOT(slotSync()), 0, -1, 0); + pADirOperatorMenu->popupMenu()->insertSeparator(1); + + pADirOperatorMenu->popup(pos); +} + +void SQ_ImageBasket::saveConfig() +{ + TQDir::SortSpec sort = sorting(); + + SQ_Config::instance()->writeEntry("basket_sorting_name", KFile::isSortByName(sort)); + SQ_Config::instance()->writeEntry("basket_sorting_time", KFile::isSortByDate(sort)); + SQ_Config::instance()->writeEntry("basket_sorting_size", KFile::isSortBySize(sort)); + SQ_Config::instance()->writeEntry("basket_sorting_dirs", KFile::isSortDirsFirst(sort)); + SQ_Config::instance()->writeEntry("basket_sorting_reverse", (sort & TQDir::Reversed) == TQDir::Reversed); + SQ_Config::instance()->writeEntry("basket_sorting_ignore", KFile::isSortCaseInsensitive(sort)); + + SQ_Config::instance()->writeEntry("show hidden", showHiddenFiles()); +} + +#include "sq_imagebasket.moc" diff --git a/src/sidebar/sq_imagebasket.h b/src/sidebar/sq_imagebasket.h new file mode 100644 index 0000000..406b3c4 --- /dev/null +++ b/src/sidebar/sq_imagebasket.h @@ -0,0 +1,62 @@ +/*************************************************************************** + sq_imagebasket.h - description + ------------------- + begin : ??? Feb 24 2007 + copyright : (C) 2007 by Baryshev Dmitry + email : ksquirrel.iv@gmail.com + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 SQ_IMAGEBASKET_H +#define SQ_IMAGEBASKET_H + +#include <tdediroperator.h> + +class SQ_Dir; + +/** + *@author Baryshev Dmitry + */ + +class SQ_ImageBasket : public KDirOperator +{ + TQ_OBJECT + + + public: + SQ_ImageBasket(TQWidget *parent = 0, const char *name = 0); + ~SQ_ImageBasket(); + + void add(const KFileItemList &); + + KFileItemList realItems() const; + + void saveConfig(); + + static SQ_ImageBasket* instance() { return m_inst; } + + private slots: + // coming from KDirOperator + void insertNewFiles(const KFileItemList &); + void slotDropped(const KFileItem *, TQDropEvent*, const KURL::List&); + void slotBasketProperties(); + void slotSync(); + void slotViewChanged(KFileView *); + void slotExecuted(const KFileItem *fi); + + void activatedMenu(const KFileItem *, const TQPoint &pos); + + private: + SQ_Dir *dir; + static SQ_ImageBasket *m_inst; +}; + +#endif diff --git a/src/sidebar/sq_mountview.cpp b/src/sidebar/sq_mountview.cpp new file mode 100644 index 0000000..c52b199 --- /dev/null +++ b/src/sidebar/sq_mountview.cpp @@ -0,0 +1,247 @@ +/*************************************************************************** + sq_mountview.cpp - description + ------------------- + begin : ??? Nov 29 2005 + copyright : (C) 2005 by Baryshev Dmitry + email : ksquirrel.iv@gmail.com + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <tdemessagebox.h> +#include <kmountpoint.h> +#include <tdeglobal.h> +#include <tdelocale.h> +#include <kautomount.h> +#include <tdepopupmenu.h> + +#include "ksquirrel.h" +#include "sq_mountview.h" +#include "sq_mountviewitem.h" +#include "sq_iconloader.h" +#include "sq_config.h" + +SQ_MountView * SQ_MountView::m_inst = 0; + +SQ_MountView::SQ_MountView(TQWidget *parent, const char *name) : TDEListView(parent, name), m_columns(-1) +{ + m_inst = this; + + popup = new TDEPopupMenu; + id_mount = popup->insertItem(SQ_IconLoader::instance()->loadIcon("drive-harddisk-mounted", TDEIcon::Desktop, TDEIcon::SizeSmall), + i18n("Mount"), this, TQ_SLOT(slotMount())); + id_unmount = popup->insertItem(SQ_IconLoader::instance()->loadIcon("drive-harddisk-unmounted", TDEIcon::Desktop, TDEIcon::SizeSmall), + i18n("Unmount"), this, TQ_SLOT(slotUnmount())); + popup->insertItem(SQ_IconLoader::instance()->loadIcon("reload", TDEIcon::Desktop, TDEIcon::SizeSmall), + i18n("Refresh"), this, TQ_SLOT(slotRefresh())); + popup->insertSeparator(); + popup->insertItem(i18n("Cancel")); + + connect(this, TQ_SIGNAL(contextMenu(TDEListView *, TQListViewItem *, const TQPoint &)), + this, TQ_SLOT(slotContextMenu(TDEListView *, TQListViewItem *, const TQPoint &))); + setAcceptDrops(false); + + connect(this, TQ_SIGNAL(returnPressed(TQListViewItem*)), this, TQ_SLOT(slotExecuted(TQListViewItem *))); + connect(this, TQ_SIGNAL(clicked(TQListViewItem*)), this, TQ_SLOT(slotExecuted(TQListViewItem *))); + + setShowSortIndicator(true); + setAllColumnsShowFocus(true); + setSelectionMode(TQListView::Single); + setItemsMovable(false); + + // "Name" column will always exist + addColumn(i18n("Name")); + + setupColumns(); +} + +SQ_MountView::~SQ_MountView() +{} + +void SQ_MountView::slotExecuted(TQListViewItem *i) +{ + SQ_MountViewItem *mvi = static_cast<SQ_MountViewItem *>(i); + + if(!mvi) + return; + + if(mvi->mounted()) + emit path(mvi->text(0)); + else + { + mountItem = mvi; + KAutoMount *mounter = new KAutoMount(false, TQString(), mvi->device(), TQString(), TQString(), false); + connect(mounter, TQ_SIGNAL(finished()), this, TQ_SLOT(slotMountFinished())); + } +} + +void SQ_MountView::slotMountFinished() +{ + mountItem->setMounted(true); + emit path(mountItem->text(0)); +} + +void SQ_MountView::slotMountError() +{ + mountItem->setMounted(false); +} + +void SQ_MountView::reload(bool current) +{ + // get currently mounted filesystems + KMountPoint::List mt = current ? + KMountPoint::currentMountPoints(KMountPoint::NeedMountOptions | KMountPoint::NeedRealDeviceName) + : KMountPoint::possibleMountPoints(KMountPoint::NeedMountOptions | KMountPoint::NeedRealDeviceName); + + SQ_MountViewItem *fi; + int colum; + + for(KMountPoint::List::iterator it = mt.begin();it != mt.end();++it) + { + colum = 1; + + if(mounted.find((*it)->mountPoint()) == mounted.end()) + { + mounted.append((*it)->mountPoint()); + + // filter out /proc, swap etc. + if(!(*it)->mountedFrom().startsWith(TQChar('/')) || !(*it)->mountPoint().startsWith(TQChar('/'))) + continue; + + fi = new SQ_MountViewItem(this, (*it)->mountPoint()); + fi->setMounted(current); + fi->setDevice((*it)->realDeviceName()); + + if(m_columns & OPT_COL_DEVICE) + fi->setText(colum++, (*it)->realDeviceName()); + + if(m_columns & OPT_COL_FSTYPE) + fi->setText(colum++, (*it)->mountType()); + + if(m_columns & OPT_COL_OPTIONS) + fi->setText(colum, (*it)->mountOptions().join(TQString::fromLatin1(", "))); + } + } +} + +bool SQ_MountView::exists(const TQString &name) +{ + TQListViewItemIterator it(this); + + while(it.current()) + { + SQ_MountViewItem *mvi = static_cast<SQ_MountViewItem *>(it.current()); + + if(mvi && mvi->text(0) == name) + return true; + + ++it; + } + + return false; +} + +void SQ_MountView::setColumns(int cols) +{ + if(m_columns == cols) + return; + + m_columns = cols; + + int cur = columns() - 1; + + // remove old columns, 0 is always "Name" + for(int i = 0;i < cur;i++) + removeColumn(1); + + // add new + if(m_columns & OPT_COL_DEVICE) + addColumn(i18n("Device")); + + if(m_columns & OPT_COL_FSTYPE) + addColumn(i18n("FS Type")); + + if(m_columns & OPT_COL_OPTIONS) + addColumn(i18n("Options")); + + slotRefresh(); +} + +void SQ_MountView::setupColumns() +{ + SQ_Config::instance()->setGroup("Sidebar"); + int p = 0; + + if(SQ_Config::instance()->readBoolEntry("mount_options", false)) + p |= SQ_MountView::OPT_COL_OPTIONS; + + if(SQ_Config::instance()->readBoolEntry("mount_fstype", true)) + p |= SQ_MountView::OPT_COL_FSTYPE; + + if(SQ_Config::instance()->readBoolEntry("mount_device", false)) + p |= SQ_MountView::OPT_COL_DEVICE; + + setColumns(p); +} + +void SQ_MountView::slotContextMenu(TDEListView *, TQListViewItem *i, const TQPoint &p) +{ + SQ_MountViewItem *mvi = static_cast<SQ_MountViewItem *>(i); + + citem = mvi; + + popup->setItemEnabled(id_mount, !!mvi); + popup->setItemEnabled(id_unmount, !!mvi); + + popup->exec(p); +} + +void SQ_MountView::slotUnmount() +{ + if(citem) + { + KAutoUnmount *mounter = new KAutoUnmount(citem->text(0), TQString()); + connect(mounter, TQ_SIGNAL(finished()), this, TQ_SLOT(slotUnmountFinished())); + } +} + +void SQ_MountView::slotMount() +{ + if(citem) + { + KAutoMount *mounter = new KAutoMount(false, TQString(), citem->device(), TQString(), TQString(), false); + connect(mounter, TQ_SIGNAL(finished()), this, TQ_SLOT(slotMountFinished2())); +// connect(mounter, TQ_SIGNAL(error()), this, TQ_SLOT(slotMountError())); + } +} + +void SQ_MountView::slotUnmountFinished() +{ + citem->setMounted(false); +} + +void SQ_MountView::slotMountFinished2() +{ + citem->setMounted(true); +} + +void SQ_MountView::slotRefresh() +{ + clear(); + mounted.clear(); + reload(); + reload(false); +} + +#include "sq_mountview.moc" diff --git a/src/sidebar/sq_mountview.h b/src/sidebar/sq_mountview.h new file mode 100644 index 0000000..d14aa13 --- /dev/null +++ b/src/sidebar/sq_mountview.h @@ -0,0 +1,84 @@ +/*************************************************************************** + sq_mountview.h - description + ------------------- + begin : ??? Nov 29 2005 + copyright : (C) 2005 by Baryshev Dmitry + email : ksquirrel.iv@gmail.com + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 SQ_MOUNTVIEW_H +#define SQ_MOUNTVIEW_H + +#include <tqstringlist.h> + +#include <tdelistview.h> + +class TDEPopupMenu; + +class SQ_MountViewItem; + +/* + * SQ_MountView is an detailed view representing mount points. + */ + +class SQ_MountView : public TDEListView +{ + TQ_OBJECT + + + public: + SQ_MountView(TQWidget *parent = 0, const char *name = 0); + ~SQ_MountView(); + + enum { OPT_COL_MOUNTPOINT = 1, OPT_COL_DEVICE = 2, OPT_COL_FSTYPE = 4, OPT_COL_OPTIONS = 8 }; + + static SQ_MountView* instance() { return m_inst; } + + void setupColumns(); + + void reload(bool current = true); + + private: + void setColumns(int cols); + bool exists(const TQString &); + + private slots: + + void slotContextMenu(TDEListView *, TQListViewItem *i, const TQPoint &p); + /* + * Item executed. We should emit path() signal. + */ + void slotExecuted(TQListViewItem *i); + + // for context menu + void slotRefresh(); + void slotMount(); + void slotUnmount(); + void slotUnmountFinished(); + void slotMountFinished(); + void slotMountFinished2(); + void slotMountError(); + + signals: + void path(const TQString &); + + private: + int m_columns; + SQ_MountViewItem *mountItem, *citem; + TQStringList mounted; + TDEPopupMenu *popup; + int id_mount, id_unmount; + + static SQ_MountView *m_inst; +}; + +#endif diff --git a/src/sidebar/sq_mountviewitem.cpp b/src/sidebar/sq_mountviewitem.cpp new file mode 100644 index 0000000..532c0c8 --- /dev/null +++ b/src/sidebar/sq_mountviewitem.cpp @@ -0,0 +1,44 @@ +/*************************************************************************** + sq_mountviewitem.cpp - description + ------------------- + begin : ??? Feb 24 2007 + copyright : (C) 2007 by Baryshev Dmitry + email : ksquirrel.iv@gmail.com + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <tqfileinfo.h> + +#include "sq_mountviewitem.h" +#include "sq_iconloader.h" + +SQ_MountViewItem::SQ_MountViewItem(TDEListView *parent, const TQString &mpoint) + : TDEListViewItem(parent, mpoint), m_mounted(false) +{} + +SQ_MountViewItem::~SQ_MountViewItem() +{} + +void SQ_MountViewItem::setMounted(bool b) +{ + m_mounted = b; + TQFileInfo inf(text(0)); + + if(m_mounted) + setPixmap(0, inf.isReadable() ? SQ_IconLoader::instance()->loadIcon("folder", TDEIcon::Desktop, TDEIcon::SizeMedium) + : SQ_IconLoader::instance()->loadIcon("folder_locked", TDEIcon::Desktop, TDEIcon::SizeMedium)); + else + setPixmap(0, SQ_IconLoader::instance()->loadIcon("folder_red", TDEIcon::Desktop, TDEIcon::SizeMedium)); +} diff --git a/src/sidebar/sq_mountviewitem.h b/src/sidebar/sq_mountviewitem.h new file mode 100644 index 0000000..7056c39 --- /dev/null +++ b/src/sidebar/sq_mountviewitem.h @@ -0,0 +1,58 @@ +/*************************************************************************** + sq_mountviewitem.h - description + ------------------- + begin : ??? Feb 24 2007 + copyright : (C) 2007 by Baryshev Dmitry + email : ksquirrel.iv@gmail.com + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 SQ_MOUNTVIEWITEM_H +#define SQ_MOUNTVIEWITEM_H + +#include <tdelistview.h> + +class SQ_MountViewItem : public TDEListViewItem +{ + public: + SQ_MountViewItem(TDEListView *parent, const TQString &mpoint); + ~SQ_MountViewItem(); + + bool mounted() const; + void setMounted(bool b); + + TQString device() const; + void setDevice(const TQString &dev); + + private: + bool m_mounted; + TQString m_device; +}; + +inline +bool SQ_MountViewItem::mounted() const +{ + return m_mounted; +} + +inline +TQString SQ_MountViewItem::device() const +{ + return m_device; +} + +inline +void SQ_MountViewItem::setDevice(const TQString &dev) +{ + m_device = dev; +} + +#endif diff --git a/src/sidebar/sq_multibar.cpp b/src/sidebar/sq_multibar.cpp new file mode 100644 index 0000000..399929d --- /dev/null +++ b/src/sidebar/sq_multibar.cpp @@ -0,0 +1,133 @@ +/*************************************************************************** + sq_multibar.cpp - description + ------------------- + begin : ??? Nov 28 2005 + copyright : (C) 2005 by Baryshev Dmitry + email : ksquirrel.iv@gmail.com + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <tqwidgetstack.h> +#include <tqsignalmapper.h> +#include <tqsplitter.h> + +#include <tdemultitabbar.h> +#include <tdeglobal.h> +#include <kiconloader.h> + +#include "ksquirrel.h" +#include "sq_previewwidget.h" +#include "sq_multibar.h" +#include "sq_config.h" + +SQ_MultiBar * SQ_MultiBar::m_inst = 0; + +SQ_MultiBar::SQ_MultiBar(TQWidget *parent, const char *name) : TQHBox(parent, name) +{ + m_inst = this; + m_id = 0; + m_selected = -1; + + SQ_Config::instance()->setGroup("Interface"); + m_width = SQ_Config::instance()->readNumEntry("splitter", 220); + + mapper = new TQSignalMapper(this); + + connect(mapper, TQ_SIGNAL(mapped(int)), this, TQ_SLOT(raiseWidget(int))); + + mt = new KMultiTabBar(KMultiTabBar::Vertical, this); + + // setup multibar: style = VSNET, show text labels on the left side + mt->setStyle(KMultiTabBar::VSNET); + mt->setPosition(KMultiTabBar::Left); + mt->showActiveTabTexts(true); + + setSpacing(0); + + TQSplitter *ts = new TQSplitter(TQt::Vertical, this); + ts->setOpaqueResize(false); + + // TQWigdetStack will contain all widgets + stack = new TQWidgetStack(ts); + + new SQ_PreviewWidget(ts); + + TQValueList<int> sz; + sz.append(5500); + sz.append(4500); + ts->setSizes(sz); +} + +SQ_MultiBar::~SQ_MultiBar() +{} + +void SQ_MultiBar::addWidget(TQWidget *new_w, const TQString &text, const TQString &icon) +{ + // add widget to stack + stack->addWidget(new_w, m_id); + + // add button + mt->appendTab(TDEGlobal::iconLoader()->loadIcon(icon, TDEIcon::Desktop, 22), m_id, text); + + // since we cann't determine which tab was clicked, + // we should use TQSignalMapper to determine it. + mapper->setMapping(mt->tab(m_id), m_id); + + connect(mt->tab(m_id), TQ_SIGNAL(clicked()), mapper, TQ_SLOT(map())); + + m_id++; +} + +void SQ_MultiBar::raiseWidget(int id) +{ + if(m_selected != -1) + mt->setTab(m_selected, false); + + if(mt->isTabRaised(id)) + { + if(m_selected != -1) + m_width = stack->width(); + + m_selected = id; + + setMinimumSize(TQSize(0, 0)); + setMaximumSize(TQSize(10000, 10000)); + stack->raiseWidget(id); + stack->resize(m_width, stack->height()); + stack->show(); + + SQ_PreviewWidget::instance()->ignore(false); + SQ_PreviewWidget::instance()->loadPending(); + } + else + { + SQ_PreviewWidget::instance()->ignore(true); + + KSquirrel::app()->saveLayout(); + + m_selected = -1; + m_width = stack->width(); + stack->hide(); + setFixedWidth(mt->width()); + } +} + +void SQ_MultiBar::updateLayout() +{ + setFixedWidth(mt->sizeHint().width()); + stack->hide(); +} + +#include "sq_multibar.moc" diff --git a/src/sidebar/sq_multibar.h b/src/sidebar/sq_multibar.h new file mode 100644 index 0000000..12ce455 --- /dev/null +++ b/src/sidebar/sq_multibar.h @@ -0,0 +1,111 @@ +/*************************************************************************** + sq_multibar.h - description + ------------------- + begin : ??? Nov 28 2005 + copyright : (C) 2005 by Baryshev Dmitry + email : ksquirrel.iv@gmail.com + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 SQ_MULTIBAR_H +#define SQ_MULTIBAR_H + +#include <tqhbox.h> + +class KMultiTabBar; + +class TQWidgetStack; +class TQSignalMapper; + +/* + * Konqueror-like sidebar. + * + * +----------------------------------> KMultiTabBar, only contains buttons + * | +-----------------+ + * | | | + * | | | + * +------------------------+ | + * | 1 | | +----> TQWidgetStack, contains all widgets + * |---| | + * | 2 | | + * |---| | + * | 3 | | + * |---| | + * | | visible page | + * | | | + * | 4 | N4 | + * | | | + * | | | + * |---| | + * | | | + * | | | + * | | | + * | | | + * +------------------------+ + * + */ + +class SQ_MultiBar : public TQHBox +{ + TQ_OBJECT + + + public: + SQ_MultiBar(TQWidget *parent = 0, const char *name = 0); + ~SQ_MultiBar(); + + /* + * Add new widget with text label 'text' and icon 'icon'. SQ_MultiBar + * will use SQ_IconLoader to load given icon. + */ + void addWidget(TQWidget *new_w, const TQString &text, const TQString &icon); + + /* + * Current page index. 0 means first page. + */ + int currentPage(); + + void updateLayout(); + + KMultiTabBar* multiBar() const; + + static SQ_MultiBar* instance() { return m_inst; } + + public slots: + + /* + * Hide current widget and show a widget with + * id 'id'. + */ + void raiseWidget(int id); + + private: + KMultiTabBar *mt; + TQWidgetStack *stack; + int m_id, m_selected, m_width; + TQSignalMapper *mapper; + + static SQ_MultiBar *m_inst; +}; + +inline +int SQ_MultiBar::currentPage() +{ + return m_selected; +} + +inline +KMultiTabBar* SQ_MultiBar::multiBar() const +{ + return mt; +} + +#endif diff --git a/src/sidebar/sq_previewwidget.cpp b/src/sidebar/sq_previewwidget.cpp new file mode 100644 index 0000000..ca9f668 --- /dev/null +++ b/src/sidebar/sq_previewwidget.cpp @@ -0,0 +1,364 @@ +/*************************************************************************** + sq_previewwidget.cpp - description + ------------------- + begin : ??? Mar 13 2007 + copyright : (C) 2007 by Baryshev Dmitry + email : ksquirrel.iv@gmail.com + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <tqsize.h> +#include <tqimage.h> +#include <tqpainter.h> + +#include <tdelocale.h> +#include <tdefileitem.h> +#include <tdepopupmenu.h> +#include <kcolordialog.h> +#include <tdeio/global.h> + +#include <ksquirrel-libs/fmt_defs.h> + +#include "ksquirrel.h" +#include "sq_previewwidget.h" +#include "sq_iconloader.h" +#include "sq_imageloader.h" +#include "sq_libraryhandler.h" +#include "sq_config.h" +#include "sq_downloader.h" +#include "sq_utils.h" + +#ifdef SQ_HAVE_KEXIF +#include <libkexif/kexifdata.h> +#include <algorithm> +#include "sq_utils.h" +#endif + +SQ_PreviewWidget * SQ_PreviewWidget::m_inst = 0; + +SQ_PreviewWidget::SQ_PreviewWidget(TQWidget *parent, const char *name) + : TQWidget(parent, name, TQt::WNoAutoErase), all(0), small(0), m_ignore(true) +{ + m_inst = this; + + rereadColor(); + + down = new SQ_Downloader(this); + connect(down, TQ_SIGNAL(result(const KURL &)), this, TQ_SLOT(slotDownloadResult(const KURL &))); + connect(down, TQ_SIGNAL(percents(int)), this, TQ_SLOT(slotDownloadPercents(int))); + + popup = new TDEPopupMenu; + popup->insertItem(i18n("Background color..."), this, TQ_SLOT(slotBackground())); + popup->insertItem(i18n("Text color..."), this, TQ_SLOT(slotText())); + popup->insertSeparator(); + popup->insertItem(i18n("Go to first image")+"\tHome", this, TQ_SIGNAL(first())); + popup->insertItem(i18n("Next image")+"\tSpace", this, TQ_SIGNAL(next())); + popup->insertItem(i18n("Previous image")+"\tBackSpace", this, TQ_SIGNAL(previous())); + popup->insertItem(i18n("Go to last image")+"\tEnd", this, TQ_SIGNAL(last())); + popup->insertSeparator(); + popup->insertItem(i18n("Execute")+"\tEnter", this, TQ_SIGNAL(execute())); + + multi_pix = SQ_IconLoader::instance()->loadIcon("application-vnd.tde.tdemultiple", TDEIcon::Desktop, TDEIcon::SizeSmall); + + setMinimumHeight(20); + setFocusPolicy(TQWidget::WheelFocus); +} + +SQ_PreviewWidget::~SQ_PreviewWidget() +{ + delete popup; + delete small; + delete all; +} + +void SQ_PreviewWidget::load(const KURL &_url) +{ + if(SQ_LibraryHandler::instance()->maybeSupported(_url) == SQ_LibraryHandler::No) + return; + + if(!percentString.isEmpty()) + { + percentString = TQString(); + update(); + } + + down->kill(); + + if(m_forceignore || m_ignore) + { + pending = m_url = _url; + return; + } + else + pending = KURL(); + + m_url = _url; + + if(m_url.isLocalFile()) + slotDownloadResult(m_url); + else + { + KFileItem fi(KFileItem::Unknown, KFileItem::Unknown, m_url); + down->start(&fi); + } +} + +void SQ_PreviewWidget::fitAndConvert() +{ + if(!m_ignore && fit()) + pixmap.convertFromImage(small?*small:*all); +} + +void SQ_PreviewWidget::resizeEvent(TQResizeEvent *) +{ + fitAndConvert(); +} + +void SQ_PreviewWidget::paintEvent(TQPaintEvent *) +{ + TQPainter p(this); + + p.fillRect(rect(), color); + + int x = 4; + + if(!percentString.isEmpty()) + { + TQFont fnt = p.font(); + fnt.setBold(true); + p.setFont(fnt); + p.setPen(colorText); + p.drawText(x, 4, width(), height(), TQt::AlignLeft, percentString); + } + + if(!m_ignore && !pixmap.isNull()) + { + p.drawPixmap((width() - pixmap.width()) / 2, (height() - pixmap.height()) / 2, pixmap); + + if(multi) + { + x = x + multi_pix.width() + 4; + p.drawPixmap(4, 4, multi_pix); + } + + if(dim) + { + TQFont fnt = p.font(); + fnt.setBold(true); + p.setFont(fnt); + p.setPen(colorText); + p.drawText(x, 4, width(), height(), TQt::AlignLeft, dimstring); + } + } +} + +bool SQ_PreviewWidget::fit() +{ + if(!all) + return false; + + // image is bigger than preview widget - + // scale it down + if(width() < 2 || height() < 2) + return false; + + delete small; + small = 0; + + if(all->width() > width() || all->height() > height()) + { + small = new TQImage(); + + *small = SQ_Utils::scale(*all, width(), height(), SQ_Utils::SMOOTH_FAST, TQImage::ScaleMin); + } + + return true; +} + +void SQ_PreviewWidget::saveValues() +{ + SQ_Config::instance()->setGroup("Sidebar"); + SQ_Config::instance()->writeEntry("preview_background", color.name()); + SQ_Config::instance()->writeEntry("preview_text", colorText.name()); +} + +void SQ_PreviewWidget::rereadColor() +{ + SQ_Config::instance()->setGroup("Sidebar"); + bool b = SQ_Config::instance()->readBoolEntry("preview", true); + m_forceignore = !b; + setShown(b); + color.setNamedColor(SQ_Config::instance()->readEntry("preview_background", "#4e4e4e")); + dim = SQ_Config::instance()->readBoolEntry("preview_text_enable", true); + colorText.setNamedColor(SQ_Config::instance()->readEntry("preview_text", "#ffffff")); + m_delay = SQ_Config::instance()->readNumEntry("preview_delay", 400); + m_cancel = SQ_Config::instance()->readBoolEntry("preview_dont", true); + + if(m_delay < 50 || m_delay > 2000) + m_delay = 400; +} + + +void SQ_PreviewWidget::slotBackground() +{ + KColorDialog dlg(KSquirrel::app(), 0, true); + + dlg.setColor(color); + + if(dlg.exec() == TQDialog::Accepted) + { + color = dlg.color(); + saveValues(); + update(); + } +} + +void SQ_PreviewWidget::slotText() +{ + KColorDialog dlg(KSquirrel::app(), 0, true); + + dlg.setColor(colorText); + + if(dlg.exec() == TQDialog::Accepted) + { + colorText = dlg.color(); + saveValues(); + update(); + } +} + +void SQ_PreviewWidget::mousePressEvent(TQMouseEvent *e) +{ + e->accept(); + + if(e->button() == TQt::RightButton) + popup->exec(e->globalPos()); +} + +void SQ_PreviewWidget::loadPending() +{ + if(pending.isValid()) + { + KURL tmp = pending; + load(tmp); + } +} + +void SQ_PreviewWidget::slotDownloadResult(const KURL &url) +{ + percentString = TQString(); + TQString path = url.path(); + fmt_info *finfo; + RGBA *bits; + + // load first page + bool b = SQ_ImageLoader::instance()->loadImage(path, SQ_CodecSettings::ImageViewer, true, 2); + + finfo = SQ_ImageLoader::instance()->info(); + bits = SQ_ImageLoader::instance()->bits(); + + // memory allocation failed in SQ_ImageLoader::loadImage() + if(!b || !bits || !finfo->image.size()) + return; + + delete small; + delete all; + all = small = 0; + pixmap = TQPixmap(); + + int w = finfo->image[0].w; + int h = finfo->image[0].h; + dimstring = TQString::fromLatin1("%1x%2").arg(w).arg(h); + + const int wh = w * h; + unsigned char t; + + for(int i = 0;i < wh;i++) + { + t = (bits+i)->r; + (bits+i)->r = (bits+i)->b; + (bits+i)->b = t; + } + + all = new TQImage((uchar *)bits, w, h, 32, 0, 0, TQImage::LittleEndian); + all->setAlphaBuffer(true); + +#ifdef SQ_HAVE_KEXIF + KExifData data; + data.readFromFile(path); + int O = data.getImageQt::Orientation(); + + if(O != KExifData::UNSPECIFIED && O != KExifData::NORMAL) + { + // copy original image + TQImage img = *all; + + // rotate image + SQ_Utils::exifRotate(TQString(), img, O); + + // transfer back + *all = img; + } + else +#endif + *all = all->copy(); + + multi = finfo->image.size() > 1; + + SQ_ImageLoader::instance()->cleanup(); + + fitAndConvert(); + update(); +} + +void SQ_PreviewWidget::keyPressEvent(TQKeyEvent *e) +{ + e->accept(); + + int key = e->key(); + + if(key == TQt::Key_PageDown || key == TQt::Key_Space) + emit next(); + else if(key == TQt::Key_PageUp || key == TQt::Key_BackSpace) + emit previous(); + else if(key == TQt::Key_Return || key == TQt::Key_Enter) + emit execute(); + else if(key == TQt::Key_Home) + emit first(); + else if(key == TQt::Key_End) + emit last(); +} + +void SQ_PreviewWidget::wheelEvent(TQWheelEvent *e) +{ + if(e->delta() < 0) + emit next(); + else + emit previous(); +} + +void SQ_PreviewWidget::mouseDoubleClickEvent(TQMouseEvent *e) +{ + e->accept(); + emit execute(); +} + +void SQ_PreviewWidget::slotDownloadPercents(int p) +{ + percentString = i18n("Downloading...") + ' ' + TDEIO::convertSize(p); + update(); +} + +#include "sq_previewwidget.moc" diff --git a/src/sidebar/sq_previewwidget.h b/src/sidebar/sq_previewwidget.h new file mode 100644 index 0000000..25e8c37 --- /dev/null +++ b/src/sidebar/sq_previewwidget.h @@ -0,0 +1,132 @@ +/*************************************************************************** + sq_previewwidget.h - description + ------------------- + begin : ??? Mar 13 2007 + copyright : (C) 2007 by Baryshev Dmitry + email : ksquirrel.iv@gmail.com + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 SQ_PREVIEWWIDGET_H +#define SQ_PREVIEWWIDGET_H + +#include <tqwidget.h> +#include <tqpixmap.h> +#include <tqcolor.h> +#include <tqwmatrix.h> +#include <tqimage.h> + +#include <kurl.h> + +class TDEPopupMenu; + +class SQ_Downloader; + +/** + *@author Baryshev Dmitry + */ + +class SQ_PreviewWidget : public TQWidget +{ + TQ_OBJECT + + + public: + SQ_PreviewWidget(TQWidget *parent = 0, const char *name = 0); + ~SQ_PreviewWidget(); + + void rereadColor(); + + void load(const KURL &url); + + void ignore(bool ign); + + void loadPending(); + + static SQ_PreviewWidget* instance() { return m_inst; } + + int delay() const; + + bool cancel() const; + + KURL url() const; + + private: + void saveValues(); + + signals: + void next(); + void previous(); + void execute(); + void first(); + void last(); + + private slots: + void slotBackground(); + void slotText(); + void slotDownloadResult(const KURL &); + void slotDownloadPercents(int); + + protected: + virtual void resizeEvent(TQResizeEvent *); + virtual void paintEvent(TQPaintEvent *); + virtual void mousePressEvent(TQMouseEvent *e); + virtual void keyPressEvent(TQKeyEvent *e); + virtual void wheelEvent(TQWheelEvent *e); + virtual void mouseDoubleClickEvent(TQMouseEvent *e); + + private: + bool fit(); + void fitAndConvert(); + + private: + TQImage *all, *small; + TQPixmap pixmap; + bool m_ignore, m_forceignore, m_cancel; + TQColor color, colorText; + TDEPopupMenu *popup; + KURL pending, m_url; + int m_delay; + TQWMatrix matrix; + SQ_Downloader *down; + bool multi; + TQPixmap multi_pix; + TQString dimstring, percentString; + bool dim; + + static SQ_PreviewWidget *m_inst; +}; + +inline +void SQ_PreviewWidget::ignore(bool ign) +{ + m_ignore = ign; +} + +inline +int SQ_PreviewWidget::delay() const +{ + return m_delay; +} + +inline +bool SQ_PreviewWidget::cancel() const +{ + return m_cancel; +} + +inline +KURL SQ_PreviewWidget::url() const +{ + return m_url; +} + +#endif diff --git a/src/sidebar/sq_storagefile.cpp b/src/sidebar/sq_storagefile.cpp new file mode 100644 index 0000000..cf41122 --- /dev/null +++ b/src/sidebar/sq_storagefile.cpp @@ -0,0 +1,76 @@ +/*************************************************************************** + sq_storagefile.cpp - description + ------------------- + begin : Sat Mar 3 2007 + copyright : (C) 2007 by Baryshev Dmitry + email : ksquirrel.iv@gmail.com + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 <tqfile.h> +#include <tqcstring.h> +#include <tqstring.h> + +#include <kmdcodec.h> + +#include "sq_storagefile.h" + +void SQ_StorageFile::writeStorageFile(const TQString &path, const KURL &inpath, KURL w) +{ + SQ_StorageFile::writeStorageFileAsString(path, inpath, w.prettyURL()); +} + +void SQ_StorageFile::writeStorageFileAsString(const TQString &path, const KURL &inpath, TQString content) +{ + if(content.isEmpty()) + content = inpath.prettyURL(); + + KMD5 md5(TQFile::encodeName(inpath.prettyURL()).data()); + TQFile file(path + TQString::fromLatin1(".") + TQString(md5.hexDigest())); + + if(file.open(IO_WriteOnly)) + { + TQCString k = content.local8Bit(); + file.writeBlock(k, k.length()); + file.close(); + } +} + +KURL SQ_StorageFile::readStorageFile(const TQString &path) +{ + TQString n = SQ_StorageFile::readStorageFileAsString(path); + + int ind = n.find('\n'); + + if(ind != -1) + n.truncate(ind); + + return KURL::fromPathOrURL(n); +} + +TQString SQ_StorageFile::readStorageFileAsString(const TQString &path) +{ + TQFile file(path); + TQString str; + + if(file.open(IO_ReadOnly)) + { + TQByteArray ba = file.readAll(); + if(file.status() == IO_Ok) + { + str.append(ba); + } + } + + file.close(); + + return str; +} diff --git a/src/sidebar/sq_storagefile.h b/src/sidebar/sq_storagefile.h new file mode 100644 index 0000000..6e0b8c4 --- /dev/null +++ b/src/sidebar/sq_storagefile.h @@ -0,0 +1,34 @@ +/*************************************************************************** + sq_storagefile.h - description + ------------------- + begin : Sat Mar 3 2007 + copyright : (C) 2007 by Baryshev Dmitry + email : ksquirrel.iv@gmail.com + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 SQ_STORAGEFILE_H +#define SQ_STORAGEFILE_H + +#include <tqstring.h> + +#include <kurl.h> + +namespace SQ_StorageFile +{ + void writeStorageFile(const TQString &path, const KURL &inpath, KURL w = KURL()); + void writeStorageFileAsString(const TQString &path, const KURL &inpath, TQString content = TQString()); + + KURL readStorageFile(const TQString &path); + TQString readStorageFileAsString(const TQString &path); +}; + +#endif diff --git a/src/sidebar/sq_threaddirlister.cpp b/src/sidebar/sq_threaddirlister.cpp new file mode 100644 index 0000000..9c6610f --- /dev/null +++ b/src/sidebar/sq_threaddirlister.cpp @@ -0,0 +1,145 @@ +/*************************************************************************** + sq_threaddirlister.cpp - description + ------------------- + begin : Feb 10 2007 + copyright : (C) 2007 by Baryshev Dmitry + email : ksquirrel.iv@gmail.com + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <tqfile.h> +#include <tqdir.h> +#include <tqobject.h> +#include <tqfileinfo.h> +#include <tqdatetime.h> +#include <tqapplication.h> + +#include <tdeconfig.h> +#include <tdeglobal.h> + +#include "sq_threaddirlister.h" + +SQ_ThreadDirLister::SQ_ThreadDirLister(TQObject *o) + : TQThread(), obj(o) +{ + cache = new TDEConfig("ksquirrel-tree-cache"); + dir = 0; +} + +SQ_ThreadDirLister::~SQ_ThreadDirLister() +{ + // sync() & delete + delete cache; +} + +void SQ_ThreadDirLister::run() +{ + KURL url; + TQString path, name, filepath; + dirent *file; + int count_files, count_dirs; + TQDateTime dt, dt_def; + TQFileInfo fi; + bool b_read; + + static const TQString &dot = TDEGlobal::staticQString("."); + static const TQString &dotdot = TDEGlobal::staticQString(".."); + + while(true) + { + waitMutex(); + count_files = todo.count(); + unlock(); + + if(!count_files) break; + + waitMutex(); + url = todo.first(); + unlock(); + + path = url.path(); + count_files = count_dirs = 0; + b_read = true; + fi.setFile(path); + + if(cache->hasGroup(path)) + { + cache->setGroup(path); + dt = cache->readDateTimeEntry("modified", &dt_def); + + // compare cached time and real time + if(dt.isValid() && fi.lastModified() == dt) + { + count_files = cache->readNumEntry("count_files", 0); + count_dirs = cache->readNumEntry("count_dirs", 0); + b_read = false; + } + } + + if(b_read) + { + dir = opendir(TQFile::encodeName(path)); + dt = fi.lastModified(); // save directory last modified time + + if(dir) + { + while((file = readdir(dir))) + { + name = TQFile::decodeName(file->d_name); + + if(name != dot && name != dotdot) + { + filepath = path + TQDir::separator() + name; + + fi.setFile(filepath); + + if(fi.isDir()) + count_dirs++; + else + count_files++; + } + } + + closeDir(); + } + else // opendir() failed, this value won't be cached + b_read = false; + } + + waitMutex(); + todo.pop_front(); + unlock(); + + // cache only new values + if(b_read) + { + cache->setGroup(path); + cache->writeEntry("modified", dt); + cache->writeEntry("count_files", count_files); + cache->writeEntry("count_dirs", count_dirs); + } + + TQApplication::postEvent(obj, new SQ_ItemsEvent(url, count_files, count_dirs)); + }// while +} + +void SQ_ThreadDirLister::closeDir() +{ + if(dir) + { + closedir(dir); + dir = 0; + } +} diff --git a/src/sidebar/sq_threaddirlister.h b/src/sidebar/sq_threaddirlister.h new file mode 100644 index 0000000..7aa58fc --- /dev/null +++ b/src/sidebar/sq_threaddirlister.h @@ -0,0 +1,153 @@ +/*************************************************************************** + sq_threaddirlister.h - description + ------------------- + begin : Feb 10 2007 + copyright : (C) 2007 by Baryshev Dmitry + email : ksquirrel.iv@gmail.com + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 SQ_THREADDIRLISTER_H +#define SQ_THREADDIRLISTER_H + +#include <tqthread.h> +#include <tqevent.h> +#include <tqmutex.h> + +#include <kurl.h> + +#include <sys/types.h> +#include <dirent.h> + +class TQObject; + +class TDEConfig; + +/********************************************************/ + +#define SQ_ItemsEventId (TQEvent::User + 1) + +class SQ_ItemsEvent : public TQCustomEvent +{ + public: + SQ_ItemsEvent(const KURL &parent, int c1, int c2) + : TQCustomEvent(SQ_ItemsEventId), m_files(c1), m_dirs(c2), m_url(parent) + {} + + int files() const; + int dirs() const; + + KURL url() const; + + private: + int m_files, m_dirs; + KURL m_url; +}; + +inline +KURL SQ_ItemsEvent::url() const +{ + return m_url; +} + +inline +int SQ_ItemsEvent::files() const +{ + return m_files; +} + +inline +int SQ_ItemsEvent::dirs() const +{ + return m_dirs; +} + +/********************************************************/ + +/* + * This thread will read directory and determine + * number of files in it. Finally + * it will post an event to main thread with + * calculated count. This function is threaded + * due to perfomance reason. + */ +class SQ_ThreadDirLister : public TQThread +{ + public: + SQ_ThreadDirLister(TQObject *o); + ~SQ_ThreadDirLister(); + + void appendURL(const KURL &url); + + bool hasURL(const KURL &url); + bool isCurrent(const KURL &url); + + void lock(); + void unlock(); + + void closeDir(); + + protected: + virtual void run(); + + private: + void waitMutex(); + + private: + // urls to read + KURL::List todo; + + // this object will recieve our events + TQObject *obj; + TQMutex mutex; + TDEConfig *cache; + DIR *dir; +}; + +inline +void SQ_ThreadDirLister::appendURL(const KURL &url) +{ + todo.append(url); +} + +inline +bool SQ_ThreadDirLister::hasURL(const KURL &url) +{ + return todo.find(url) != todo.end(); +} + +inline +bool SQ_ThreadDirLister::isCurrent(const KURL &url) +{ + return todo.first().equals(url, true); +} + +inline +void SQ_ThreadDirLister::lock() +{ + mutex.lock(); +} + +inline +void SQ_ThreadDirLister::unlock() +{ + mutex.unlock(); +} + +inline +void SQ_ThreadDirLister::waitMutex() +{ + while(!mutex.tryLock()) + TQThread::msleep(1); +} + +#endif diff --git a/src/sidebar/sq_treeview.cpp b/src/sidebar/sq_treeview.cpp new file mode 100644 index 0000000..22207a9 --- /dev/null +++ b/src/sidebar/sq_treeview.cpp @@ -0,0 +1,678 @@ +/*************************************************************************** + sq_treeview.cpp - description + ------------------- + begin : Mon Mar 15 2004 + copyright : (C) 2004 by Baryshev Dmitry + email : ksquirrel.iv@gmail.com + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <tqdir.h> +#include <tqheader.h> +#include <tqtimer.h> +#include <tqcursor.h> + +#include <tdelocale.h> +#include <kurldrag.h> +#include <kurl.h> +#include <kdirwatch.h> + +#include "ksquirrel.h" +#include "sq_iconloader.h" +#include "sq_widgetstack.h" +#include "sq_filethumbview.h" +#include "sq_config.h" +#include "sq_treeview.h" +#include "sq_treeviewitem.h" +#include "sq_threaddirlister.h" +#include "sq_navigatordropmenu.h" +#include "sq_treeviewmenu.h" +#include "sq_hloptions.h" + +#include "sq_directorybasket.h" + +SQ_TreeView * SQ_TreeView::m_instance = 0; + +SQ_FileTreeViewBranch::SQ_FileTreeViewBranch(KFileTreeView *parent, const KURL &url, + const TQString &name, const TQPixmap &pix) : KFileTreeBranch(parent, url, name, pix) +{} + +SQ_FileTreeViewBranch::~SQ_FileTreeViewBranch() +{} + +KFileTreeViewItem* SQ_FileTreeViewBranch::createTreeViewItem(KFileTreeViewItem *parent, KFileItem *fileItem) +{ + KFileTreeViewItem *tvi = 0; + + if(parent && fileItem) + tvi = new SQ_TreeViewItem(parent, fileItem, this); + + return tvi; +} + +/******************************************************************************************************/ + +SQ_TreeView::SQ_TreeView(TQWidget *parent, const char *name) : KFileTreeView(parent, name) +{ + m_instance = this; + + itemToBeOpened = 0; + m_animTimer = new TQTimer(this); + scanTimer = new TQTimer(this); + m_ignoreClick = false; + + connect(m_animTimer, TQ_SIGNAL(timeout()), this, TQ_SLOT(slotAnimation())); + connect(scanTimer, TQ_SIGNAL(timeout()), this, TQ_SLOT(slotDelayedScan())); + + dw = 0; + m_recurs = No; + lister = new SQ_ThreadDirLister(this); + setupRecursion(); + + setFrameShape(TQFrame::NoFrame); + addColumn("Name"); + addColumn("Check"); + + header()->hide(); + header()->moveSection(1, 0); + setColumnWidthMode(1, TQListView::Manual); + setColumnWidth(1, 18); + + root = new SQ_FileTreeViewBranch(this, TQDir::rootDirPath(), TQString(), + SQ_IconLoader::instance()->loadIcon("folder_red", TDEIcon::Desktop, TDEIcon::SizeSmall)); + + // some hacks to create our SQ_TreeViewItem as root item + SQ_TreeViewItem *ritem = new SQ_TreeViewItem(this, + new KFileItem(TQDir::rootDirPath(), + "inode/directory", S_IFDIR), + root); + + ritem->setText(0, i18n("root")); + ritem->setExpandable(true); + + // oops :) + delete root->root(); + + // set new root + root->setRoot(ritem); + + addBranch(root); + + // don't show files + setDirOnlyMode(root, true); + + // show '+' + setRootIsDecorated(true); + + // connect signals + + // Space and Return will open item + connect(this, TQ_SIGNAL(spacePressed(TQListViewItem*)), this, TQ_SIGNAL(executed(TQListViewItem*))); + connect(this, TQ_SIGNAL(returnPressed(TQListViewItem*)), this, TQ_SIGNAL(executed(TQListViewItem*))); + connect(this, TQ_SIGNAL(currentChanged(TQListViewItem *)), this, TQ_SLOT(slotCurrentChanged(TQListViewItem*))); + + connect(this, TQ_SIGNAL(executed(TQListViewItem*)), this, TQ_SLOT(slotItemExecuted(TQListViewItem*))); + connect(this, TQ_SIGNAL(newURL(const KURL&)), this, TQ_SLOT(slotNewURL(const KURL&))); + connect(root, TQ_SIGNAL(populateFinished(KFileTreeViewItem *)), this, TQ_SLOT(slotOpened(KFileTreeViewItem *))); + connect(root, TQ_SIGNAL(deleteItem(KFileItem *)), this, TQ_SLOT(slotDeleteItemMy(KFileItem *))); + + setCurrentItem(root->root()); + root->setChildRecurse(false); + + SQ_Config::instance()->setGroup("Fileview"); + int sync_type = SQ_Config::instance()->readNumEntry("sync type", 0); + + // load url, if needed + if(sync_type != 1) + emitNewURL(SQ_WidgetStack::instance()->url()); + + setAcceptDrops(true); + + connect(this, TQ_SIGNAL(dropped(TQDropEvent *, TQListViewItem *, TQListViewItem *)), + this, TQ_SLOT(slotDropped(TQDropEvent *, TQListViewItem *, TQListViewItem *))); + + connect(this, TQ_SIGNAL(contextMenu(TDEListView *, TQListViewItem *, const TQPoint &)), + this, TQ_SLOT(slotContextMenu(TDEListView *, TQListViewItem *, const TQPoint &))); + + menu = new SQ_TreeViewMenu(this); + + if(SQ_HLOptions::instance()->have_directorybasket) + { + menu->insertSeparator(); + menu->insertItem(i18n("Add to Folder Basket"), this, TQ_SLOT(slotAddToFolderBasket())); + } +} + +SQ_TreeView::~SQ_TreeView() +{ + lister->terminate(); + lister->wait(); + + delete lister; +} + +void SQ_TreeView::slotCurrentChanged(TQListViewItem *item) +{ + SQ_TreeViewItem *tvi = static_cast<SQ_TreeViewItem *>(item); + + if(tvi) cURL = tvi->url(); +} + +void SQ_TreeView::setRecursion(int b) +{ + // avoid duplicate calls + if(m_recurs == b) + return; + + TQListViewItemIterator it(this); + SQ_TreeViewItem *tvi; + + // ignore root item + ++it; + + // turn recursion on + if(m_recurs == No && b) + { + dw = new KDirWatch(this); + connect(dw, TQ_SIGNAL(dirty(const TQString &)), this, TQ_SLOT(slotDirty(const TQString &))); + + dw->blockSignals(true); + lister->lock(); + while(it.current()) + { + tvi = static_cast<SQ_TreeViewItem *>(it.current()); + + if(tvi) + { + tvi->setParams((m_recurs == Files || m_recurs == FilesDirs), + (m_recurs == Dirs || m_recurs == FilesDirs)); + + lister->appendURL(tvi->url()); + dw->addDir(tvi->path()); + } + + ++it; + } + lister->unlock(); + dw->blockSignals(false); + + m_recurs = b; + + if(!lister->running()) + scanTimer->start(1, true); + } + // turn recursion off + else + { + delete dw; + dw = 0; + + m_recurs = b; + while(it.current()) + { + tvi = static_cast<SQ_TreeViewItem *>(it.current()); + + // reset item names + if(tvi) + { + tvi->setParams((m_recurs == Files || m_recurs == FilesDirs), + (m_recurs == Dirs || m_recurs == FilesDirs)); + tvi->setCount(tvi->files(), tvi->dirs()); + } + + ++it; + } + } +} + +void SQ_TreeView::slotClearChecked() +{ + TQListViewItemIterator it(this); + SQ_TreeViewItem *tvi; + + while(it.current()) + { + tvi = static_cast<SQ_TreeViewItem *>(it.current()); + + if(tvi && tvi->checked()) + tvi->setChecked(false); + + ++it; + } +} + +/* + * Item executed. Let's pass its url to SQ_WidgetStack (if needed). + */ +void SQ_TreeView::slotItemExecuted(TQListViewItem *item) +{ + if(!item) return; + + item->setOpen(true); + + SQ_Config::instance()->setGroup("Fileview"); + int sync_type = SQ_Config::instance()->readNumEntry("sync type", 0); + + // current sychronization type doesn't require + // passing url to SQ_WidgetStack - return + if(sync_type == 1) + return; + + KFileTreeViewItem *cur = static_cast<KFileTreeViewItem*>(item); + KURL Curl = cur->url(); + + // pass url to SQ_WidgetStack + SQ_WidgetStack::instance()->setURLForCurrent(Curl, false); +} + +void SQ_TreeView::emitNewURL(const KURL &url) +{ + // already selected? + if(!url.isLocalFile() || url.equals(currentURL(), true) || url.equals(cURL, true)) + return; + + cURL = url; + + // tree is invisible. + // save url for future use + if(!isVisible()) + { + pendingURL = url; + pendingURL.adjustPath(1); + return; + } + else + pendingURL = KURL(); + + emit newURL(url); +} + +/* + * Set given item visible, current, and populate it. + */ +void SQ_TreeView::populateItem(KFileTreeViewItem *item) +{ + if(item->url().equals(cURL, true)) + { + setSelected(item, true); + setCurrentItem(item); + + // 1/5 of height give above items + // 4/5 of height give below items + setContentsPos(contentsX(), itemPos(item)-visibleHeight()/5); + } + + itemToBeOpened = item; + item->setOpen(true); +} + +/* + * Load url. + */ +void SQ_TreeView::slotNewURL(const KURL &url) +{ + KURL k(url); + k.adjustPath(1); + + KURL last = k; + + TQString s; + + // divide url to paths. + // for example, "/home/krasu/1/2" will be divided to + // + // "/home/krasu/1/2" + // "/home/krasu/1" + // "/home/krasu" + // "/home" + // "/" + // + while(true) + { + s = k.path(); // remove "/" + s.remove(0, 1); + + paths.prepend(s); + k = k.upURL(); + + if(k.equals(last, true)) + break; + + last = k; + } + + while(doSearch()) + {} +} + +/* + * New item is opened. Try to continue loading url. + */ +void SQ_TreeView::slotOpened(KFileTreeViewItem *item) +{ + if(!item) return; + + // continue searhing... + if(item == itemToBeOpened) + doSearch(); +} + +/* + * Search first available url in variable 'paths'. Open found item. + * If item was found return true. + */ +bool SQ_TreeView::doSearch() +{ + // all items are opened + if(paths.empty()) + { + itemToBeOpened = 0; + return false; + } + + TQStringList::iterator it = paths.begin(); + + KFileTreeViewItem *found = findItem(root, *it); + + // item not found. It means that + // + // * we loaded all subpaths - nothing to do + // * item we needed is not loaded yet. populateItem() _now_ is trying to open + // new subpath, and we will continue searching in slotOpened(). + // + if(!found) + return false; + + // ok, item is found + // + // remove first entry from 'paths' + // and try to open item + paths.erase(it); + populateItem(found); + + // done, but subpaths are pending... + return true; +} + +/* + * On show event load saved url, if any. See emitNewURL(). + */ +void SQ_TreeView::showEvent(TQShowEvent *) +{ + // if pending url is valid + if(!pendingURL.isEmpty()) + { + // set pending url to current url + KURL url = pendingURL; + + // reset pending url + pendingURL = KURL(); + + // finally, load url + emit newURL(url); + } +} + +void SQ_TreeView::slotNewTreeViewItems(KFileTreeBranch *, const KFileTreeViewItemList &list) +{ + if(m_recurs == No) + return; + +// uuuuuuuggggggghhhhhhh :) + KFileTreeViewItemListIterator it(list); + KFileTreeViewItem *item; + + lister->lock(); + while((item = it.current())) + { + lister->appendURL(item->url()); + dw->addDir(item->path()); + ++it; + } + lister->unlock(); + + if(!lister->running()) + scanTimer->start(1, true); +} + +void SQ_TreeView::slotDelayedScan() +{ + if(!lister->running()) + lister->start(); +} + +void SQ_TreeView::customEvent(TQCustomEvent *e) +{ + if(!e || e->type() != SQ_ItemsEventId) + return; + + SQ_ItemsEvent *ie = static_cast<SQ_ItemsEvent *>(e); + + SQ_TreeViewItem *tvi = static_cast<SQ_TreeViewItem *>(root->findTVIByURL(ie->url())); + + if(tvi) + { + tvi->setParams((m_recurs == Files || m_recurs == FilesDirs), + (m_recurs == Dirs || m_recurs == FilesDirs)); + tvi->setCount(ie->files(), ie->dirs()); + } +} + +void SQ_TreeView::slotAnimation() +{ + KFileTreeViewItem *it = m_mapFolders.first(); + + for(;it;it = m_mapFolders.next()) + it->setPixmap(0, SmallIcon("clock")); +} + +void SQ_TreeView::startAnimation(KFileTreeViewItem *item, const char *, uint) +{ + if(!item) + return; + + m_mapFolders.append(item); + + if(!m_animTimer->isActive()) + m_animTimer->start(50, true); +} + +void SQ_TreeView::stopAnimation(KFileTreeViewItem *item) +{ + if(!item) + return; + + int f = m_mapFolders.find(item); + + if(f != -1) + { + item->setPixmap(0, itemIcon(item)); + m_mapFolders.remove(item); + } + + m_animTimer->stop(); +} + +void SQ_TreeView::viewportResizeEvent(TQResizeEvent *) +{ + setColumnWidth(0, viewport()->width() - columnWidth(1)); + triggerUpdate(); +} + +void SQ_TreeView::clearSelection() +{ + if(!m_ignoreClick) KFileTreeView::clearSelection(); +} + +void SQ_TreeView::setSelected(TQListViewItem *item, bool selected) +{ + if(!m_ignoreClick) KFileTreeView::setSelected(item, selected); +} + +void SQ_TreeView::setCurrentItem(TQListViewItem *item) +{ + if(!m_ignoreClick) KFileTreeView::setCurrentItem(item); +} + +void SQ_TreeView::setOpen(TQListViewItem *item, bool open) +{ + if(!m_ignoreClick) KFileTreeView::setOpen(item, open); +} + +void SQ_TreeView::contentsMousePressEvent(TQMouseEvent *e) +{ + TQListViewItem *item; + + TQPoint point = e->pos(); + point.setY(point.y() - contentsY()); + + if(header()->sectionAt(point.x()) && (item = itemAt(point))) + { + SQ_TreeViewItem *m = static_cast<SQ_TreeViewItem *>(item); + + if(m) + { + int state = e->state(); + + if(!state) + toggle(m, true); + else + { + TQListViewItemIterator it(this); + + // toggle parent item + if(state == TQt::ShiftButton) toggle(m, true); + else if(state == TQt::ControlButton) toggle(m, false, true); + else if(state == TQt::AltButton) toggle(m, false, false); + + SQ_TreeViewItem *tvi = static_cast<SQ_TreeViewItem *>(m->firstChild()); + + // toggle all child items + while(tvi) + { + if(state == TQt::ShiftButton) toggle(tvi, false, m->checked()); + else if(state == TQt::ControlButton) toggle(tvi, false, true); + else if(state == TQt::AltButton) toggle(tvi, false, false); + + tvi = static_cast<SQ_TreeViewItem *>(tvi->nextSibling()); + } + } + } + + m_ignoreClick = true; + } + + KFileTreeView::contentsMousePressEvent(e); + + m_ignoreClick = false; +} + +void SQ_TreeView::contentsMouseDoubleClickEvent(TQMouseEvent *e) +{ + if(header()->sectionAt(e->x())) + m_ignoreClick = true; + + KFileTreeView::contentsMouseDoubleClickEvent(e); + + m_ignoreClick = false; +} + +void SQ_TreeView::setupRecursion() +{ + SQ_Config::instance()->setGroup("Sidebar"); + + setRecursion(SQ_Config::instance()->readNumEntry("recursion_type", No)); +} + +void SQ_TreeView::toggle(SQ_TreeViewItem *item, bool togg, bool set) +{ + if(togg) + item->setChecked(!item->checked()); + else + item->setChecked(set); + + if(item->checked()) + emit urlAdded(item->url()); + else + emit urlRemoved(item->url()); +} + +void SQ_TreeView::slotDropped(TQDropEvent *e, TQListViewItem *parent, TQListViewItem *item) +{ + if(!item) item = parent; + + KFileTreeViewItem *cur = static_cast<KFileTreeViewItem *>(item); + + if(!cur) return; + + KURL::List list; + KURLDrag::decode(e, list); + + SQ_NavigatorDropMenu::instance()->setupFiles(list, cur->url()); + SQ_NavigatorDropMenu::instance()->exec(TQCursor::pos(), true); +} + +void SQ_TreeView::slotContextMenu(TDEListView *, TQListViewItem *item, const TQPoint &point) +{ + if(item) + { + KFileTreeViewItem *kfi = static_cast<KFileTreeViewItem*>(item); + menu->updateDirActions(kfi->isDir()); + menu->setURL(kfi->url()); + menu->exec(point); + } +} + +void SQ_TreeView::slotDirty(const TQString &path) +{ + KURL url; + url.setPath(path); + + lister->lock(); + + // we don't need update urls that are not yet updated + // by threaded lister + if(!lister->hasURL(url)) + lister->appendURL(url); + else if(lister->isCurrent(url)) + { + lister->terminate(); + lister->wait(); + lister->closeDir(); + } + + lister->unlock(); + + if(!lister->running()) + scanTimer->start(1000, true); +} + +void SQ_TreeView::slotDeleteItemMy(KFileItem *fi) +{ + if(m_recurs != No && fi) + dw->removeDir(fi->url().path()); +} + +void SQ_TreeView::slotAddToFolderBasket() +{ + KFileItem fi(KFileItem::Unknown, KFileItem::Unknown, menu->url()); + + KFileItemList list; + list.append(&fi); + + SQ_DirectoryBasket::instance()->add(list); +} + +#include "sq_treeview.moc" diff --git a/src/sidebar/sq_treeview.h b/src/sidebar/sq_treeview.h new file mode 100644 index 0000000..dd39480 --- /dev/null +++ b/src/sidebar/sq_treeview.h @@ -0,0 +1,174 @@ +/*************************************************************************** + sq_treeview.h - description + ------------------- + begin : Mon Mar 15 2004 + copyright : (C) 2004 by Baryshev Dmitry + email : ksquirrel.iv@gmail.com + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 SQ_TREEVIEW_H +#define SQ_TREEVIEW_H + +#include <tqstringlist.h> + +#include <tdefiletreeview.h> +#include <kurl.h> + +class KDirWatch; + +class SQ_TreeViewItem; +class SQ_ThreadDirLister; +class SQ_TreeViewMenu; + +/* + * We should subclass KFileTreeBranch to let us create + * our own items. See SQ_TreeViewitem. + */ +class SQ_FileTreeViewBranch : public KFileTreeBranch +{ + public: + SQ_FileTreeViewBranch(KFileTreeView*, const KURL &url, const TQString &name, const TQPixmap &pix); + ~SQ_FileTreeViewBranch(); + + protected: + virtual KFileTreeViewItem *createTreeViewItem(KFileTreeViewItem *parent, KFileItem *fileItem); +}; + +/* + * SQ_TreeView represents a file tree. + */ + +class SQ_TreeView : public KFileTreeView +{ + TQ_OBJECT + + + public: + SQ_TreeView(TQWidget *parent = 0, const char *name = 0); + ~SQ_TreeView(); + + enum Recursion { No = 0, Files, Dirs, FilesDirs }; + + /* + * Recursion settings. If recursion > 0, treeview will + * show a number of files/directories in the given directory. + * It will look like that: + * + * + mypictures [8] + * | + wallpapers [231] + * | + nature [12] + * | + pets [43] + * | + cats [22] + * | + dogs [32] + * + * This operation is threaded. + */ + void setupRecursion(); + + /* + * Load new url, if tree is visible. Save url and do nothing + * otherwise. + */ + void emitNewURL(const KURL &url); + + virtual void clearSelection(); + virtual void setSelected(TQListViewItem *item, bool selected); + virtual void setCurrentItem(TQListViewItem *item); + virtual void setOpen(TQListViewItem *item, bool open); + + static SQ_TreeView* instance() { return m_instance; } + + protected: + virtual void customEvent(TQCustomEvent *e); + virtual void startAnimation(KFileTreeViewItem* item, const char*, uint); + virtual void stopAnimation(KFileTreeViewItem* item); + virtual void viewportResizeEvent(TQResizeEvent *); + virtual void contentsMousePressEvent(TQMouseEvent *e); + virtual void contentsMouseDoubleClickEvent(TQMouseEvent *e); + + /* + * On show event load saved url, if any. See emitNewURL(). + */ + virtual void showEvent(TQShowEvent *); + + private: + void toggle(SQ_TreeViewItem *, bool, bool = false); + void setRecursion(int); + + /* + * Set given item visible, current, and populate it. + */ + void populateItem(KFileTreeViewItem *); + + /* + * Search first available url in variable 'paths'. Open found item. + * If item was found return true. + */ + bool doSearch(); + + private slots: + /* + * Load url. + */ + void slotNewURL(const KURL &url); + + void slotCurrentChanged(TQListViewItem *); + void slotAddToFolderBasket(); + void slotClearChecked(); + void slotDirty(const TQString &); + void slotDeleteItemMy(KFileItem *); + + /* + * Item executed. Let's pass its url to SQ_WidgetStack (if needed). + */ + void slotItemExecuted(TQListViewItem*); + + /* + * New item is opened. Try to continue loading url. + */ + void slotOpened(KFileTreeViewItem *); + + void slotNewTreeViewItems(KFileTreeBranch*, const KFileTreeViewItemList &); + void slotDelayedScan(); + void slotAnimation(); + + void slotDropped(TQDropEvent *, TQListViewItem *, TQListViewItem *); + void slotContextMenu(TDEListView *, TQListViewItem *, const TQPoint &); + + signals: + void newURL(const KURL &url); + + /* + * Since 0.7.0 our file manager supports multiple directories. + * These signals tell SQ_DirOperator to add or remove some + * urls. + */ + void urlAdded(const KURL &); + void urlRemoved(const KURL &); + + private: + SQ_FileTreeViewBranch *root; + TQStringList paths; + KURL pendingURL, cURL; + SQ_ThreadDirLister *lister; + KFileTreeViewItemList m_mapFolders; + TQTimer *m_animTimer, *scanTimer; + bool m_ignoreClick; + int m_recurs; + SQ_TreeViewMenu *menu; + KDirWatch *dw; + KFileTreeViewItem *itemToBeOpened; + + static SQ_TreeView *m_instance; +}; + +#endif diff --git a/src/sidebar/sq_treeviewitem.cpp b/src/sidebar/sq_treeviewitem.cpp new file mode 100644 index 0000000..cb3c1ab --- /dev/null +++ b/src/sidebar/sq_treeviewitem.cpp @@ -0,0 +1,107 @@ +/*************************************************************************** + sq_treeviewitem.cpp - description + ------------------- + begin : Feb 22 2007 + copyright : (C) 2007 by Baryshev Dmitry + email : ksquirrel.iv@gmail.com + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <tqpainter.h> + +#include "sq_treeviewitem.h" + +SQ_TreeViewItem::SQ_TreeViewItem(KFileTreeViewItem *parentItem, KFileItem *fileItem, KFileTreeBranch *parentBranch) + : KFileTreeViewItem(parentItem, fileItem, parentBranch), + m_checked(false), count_files(0), count_dirs(0), use_c1(false), use_c2(false) +{} + +SQ_TreeViewItem::SQ_TreeViewItem(KFileTreeView *parent, KFileItem *fileItem, KFileTreeBranch *parentBranch) + : KFileTreeViewItem(parent, fileItem, parentBranch), + m_checked(false), count_files(0), count_dirs(0), use_c1(false), use_c2(false) +{} + +SQ_TreeViewItem::~SQ_TreeViewItem() +{} + +void SQ_TreeViewItem::paintFocus(TQPainter *, const TQColorGroup &, const TQRect &) +{} + +void SQ_TreeViewItem::paintCell(TQPainter *p, const TQColorGroup &cg, int column, int width, int alignment) +{ + TDEListView *klv = static_cast<TDEListView *>(listView()); + + // mark item + if(column) + { + int h = height(); + int w = klv->columnWidth(1); + const int m = 6; + const int marg = 2; + + p->fillRect(0,0,w,h,cg.base()); + + p->setPen(black); + p->setBrush(cg.base()); + p->drawRect(marg, marg, w-marg*2, h-marg*2); + + if(m_checked) + p->fillRect((w-m)/2, (h-m)/2, m, m, cg.highlight()); + } + else // file name and pixmap + { + TQColorGroup cc = cg; + + if(m_checked) + { + if(klv->viewport()->backgroundMode() == TQt::FixedColor) + cc.setColor(TQColorGroup::Background, cg.highlight()); + else + cc.setColor(TQColorGroup::Base, cg.highlight()); + } + else if(isAlternate()) + { + if(klv->viewport()->backgroundMode() == TQt::FixedColor) + cc.setColor(TQColorGroup::Background, klv->alternateBackground()); + else + cc.setColor(TQColorGroup::Base, klv->alternateBackground()); + } + + TQListViewItem::paintCell(p, cc, column, width, alignment); + } +} + +void SQ_TreeViewItem::setCount(int c1, int c2) +{ + count_files = c1 < 0 ? 0 : c1; + count_dirs = c2 < 0 ? 0 : c2; + + setText(0, fileItem()->name()); +} + +void SQ_TreeViewItem::setText(int column, const TQString &text) +{ + TQString s; + + if(use_c1 && use_c2) // files + dirs: show these two values anyway + s = TQString::fromLatin1(" [%1/%2]").arg(count_dirs).arg(count_files); + else if(use_c1 && count_files) // files, file count is > 0 + s = TQString::fromLatin1(" [%1]").arg(count_files); + else if(use_c2 && count_dirs) // dirs, dir count is > 0 + s = TQString::fromLatin1(" [%1]").arg(count_dirs); + + KFileTreeViewItem::setText(column, text + s); +} + diff --git a/src/sidebar/sq_treeviewitem.h b/src/sidebar/sq_treeviewitem.h new file mode 100644 index 0000000..c51109c --- /dev/null +++ b/src/sidebar/sq_treeviewitem.h @@ -0,0 +1,85 @@ +/*************************************************************************** + sq_treeviewitem.h - description + ------------------- + begin : Feb 22 2007 + copyright : (C) 2007 by Baryshev Dmitry + email : ksquirrel.iv@gmail.com + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 SQ_TREEVIEWITEM_H +#define SQ_TREEVIEWITEM_H + +#include <tdefiletreeviewitem.h> + +class KFileTreeBranch; + +class SQ_TreeViewItem : public KFileTreeViewItem +{ + public: + SQ_TreeViewItem(KFileTreeViewItem *parentItem, KFileItem *fileItem, KFileTreeBranch *parentBranch); + SQ_TreeViewItem(KFileTreeView *parent, KFileItem *fileItem, KFileTreeBranch *parentBranch); + ~SQ_TreeViewItem(); + + bool checked() const; + void setChecked(bool c); + + int files() const; + int dirs() const; + + void setCount(int c1, int c2); + void setParams(bool _use_c1, bool _use_c2); + + virtual void paintFocus(TQPainter *, const TQColorGroup &, const TQRect &); + virtual void setText(int column, const TQString &text); + + protected: + virtual void paintCell(TQPainter *p, const TQColorGroup &cg, int column, int width, int alignment); + + private: + bool m_checked; + int count_files, count_dirs; + bool use_c1, use_c2; +}; + +inline +void SQ_TreeViewItem::setParams(bool _use_c1, bool _use_c2) +{ + use_c1 = _use_c1; + use_c2 = _use_c2; +} + +inline +bool SQ_TreeViewItem::checked() const +{ + return m_checked; +} + +inline +void SQ_TreeViewItem::setChecked(bool c) +{ + m_checked = c; + repaint(); +} + +inline +int SQ_TreeViewItem::files() const +{ + return count_files; +} + +inline +int SQ_TreeViewItem::dirs() const +{ + return count_dirs; +} + +#endif diff --git a/src/sidebar/sq_treeviewmenu.cpp b/src/sidebar/sq_treeviewmenu.cpp new file mode 100644 index 0000000..624c753 --- /dev/null +++ b/src/sidebar/sq_treeviewmenu.cpp @@ -0,0 +1,196 @@ +#include <tqpoint.h> +#include <tqwidget.h> +#include <tqstylesheet.h> + +#include <tdelocale.h> +#include <kurl.h> +#include <tdeio/job.h> +#include <kpropertiesdialog.h> +#include <kinputdialog.h> +#include <tdemessagebox.h> + +#include "sq_treeviewmenu.h" +#include "ksquirrel.h" +#include "sq_iconloader.h" + +SQ_TreeViewMenu::SQ_TreeViewMenu(TQWidget *parent, const char *name) : TDEPopupMenu(parent, name) +{ + id_new = insertItem(SQ_IconLoader::instance()->loadIcon("folder-new", TDEIcon::Desktop, TDEIcon::SizeSmall), i18n("New folder..."), this, TQ_SLOT(slotDirectoryNew())); + insertSeparator(); + id_rename = insertItem(i18n("Rename"), this, TQ_SLOT(slotDirectoryRename())); + id_clear = insertItem(i18n("Clear contents"), this, TQ_SLOT(slotDirectoryClear())); + id_delete = insertItem(SQ_IconLoader::instance()->loadIcon("edit-delete", TDEIcon::Desktop, TDEIcon::SizeSmall), i18n("Delete"), this, TQ_SLOT(slotDirectoryDelete())); + insertSeparator(); + id_prop = insertItem(i18n("Properties"), this, TQ_SLOT(slotDirectoryProperties())); +} + +SQ_TreeViewMenu::~SQ_TreeViewMenu() +{} + +void SQ_TreeViewMenu::reconnect(Element elem, TQObject *receiver, const char *member) +{ + int id; + + if(elem == SQ_TreeViewMenu::New) + id = id_new; + else if(elem == SQ_TreeViewMenu::Delete) + id = id_delete; + else if(elem == SQ_TreeViewMenu::Rename) + id = id_rename; + else if(elem == SQ_TreeViewMenu::Clear) + id = id_clear; + else + id = id_prop; + + disconnectItem(id, 0, 0); + connectItem(id, receiver, member); +} + +void SQ_TreeViewMenu::updateDirActions(bool isdir, bool isroot) +{ + setItemEnabled(id_new, isdir); + setItemEnabled(id_clear, isdir); + + setItemEnabled(id_delete, !isroot); + setItemEnabled(id_rename, isdir && !isroot); +} + +void SQ_TreeViewMenu::slotDirectoryNew() +{ + if(!m_url.isEmpty()) + { + bool ok; + + TQString mNewFilename = KInputDialog::getText(i18n("Create Subfolder"), + i18n("<p>Create new folder in <b>%1</b>:</p>").arg(TQStyleSheet::escape(m_url.filename())), + TQString(), &ok, KSquirrel::app()); + + if(ok) + { + KURL dstURL = m_url; + dstURL.addPath(mNewFilename); + TDEIO::Job *job = TDEIO::mkdir(dstURL); + + connect(job, TQ_SIGNAL(result(TDEIO::Job*)), this, TQ_SLOT(slotDirectoryResult(TDEIO::Job *))); + } + } +} + +void SQ_TreeViewMenu::slotDirectoryRename() +{ + if(!m_url.isEmpty()) + { + KURL renameSrcURL = m_url; + bool ok; + + TQString filename = TQStyleSheet::escape(renameSrcURL.filename()); + + TQString mNewFilename = KInputDialog::getText(i18n("Rename Folder"), + i18n("<p>Rename folder <b>%1</b> to:</p>").arg(filename), + renameSrcURL.filename(), &ok, KSquirrel::app()); + + if(ok) + { + KURL renameDstURL = renameSrcURL; + renameDstURL.setFileName(mNewFilename); + + TDEIO::Job *job = TDEIO::rename(renameSrcURL, renameDstURL, true); + + connect(job, TQ_SIGNAL(result(TDEIO::Job*)), this, TQ_SLOT(slotDirectoryResult(TDEIO::Job *))); + } + } +} + +void SQ_TreeViewMenu::slotDirectoryDelete() +{ + if(!m_url.isEmpty()) + { + TQString dir = TQStyleSheet::escape(m_url.path()); + + if(KMessageBox::questionYesNo(KSquirrel::app(), + "<qt>" + i18n("Are you sure you want to delete <b>%1</b>?").arg(dir) + "</qt>") == KMessageBox::No) + return; + + TDEIO::Job *job = TDEIO::del(m_url); + + connect(job, TQ_SIGNAL(result(TDEIO::Job*)), this, TQ_SLOT(slotDirectoryResult(TDEIO::Job *))); + } +} + +void SQ_TreeViewMenu::slotDirectoryClear() +{ + if(!m_url.isEmpty()) + { + urlstodel.clear(); + + if(KMessageBox::questionYesNo(KSquirrel::app(), + "<qt>" + i18n("Are you sure you want to delete contents of <b>%1</b>?").arg(m_url.path()) + "</qt>") == KMessageBox::No) + return; + + TDEIO::Job *job = TDEIO::listDir(m_url, false, true); + + connect(job, TQ_SIGNAL(entries(TDEIO::Job *, const TDEIO::UDSEntryList &)), this, TQ_SLOT(slotEntries(TDEIO::Job *, const TDEIO::UDSEntryList &))); + connect(job, TQ_SIGNAL(result(TDEIO::Job *)), this, TQ_SLOT(slotListResult(TDEIO::Job *))); + } +} + +void SQ_TreeViewMenu::slotEntries(TDEIO::Job *, const TDEIO::UDSEntryList &list) +{ + TDEIO::UDSEntryListConstIterator itEnd = list.end(); + TQString suff; + KURL u; + + static const TQString &dot = TDEGlobal::staticQString("."); + static const TQString &dotdot = TDEGlobal::staticQString(".."); + + // go through list of TDEIO::UDSEntrys + for(TDEIO::UDSEntryListConstIterator it = list.begin(); it != itEnd; ++it) + { + TDEIO::UDSEntry entry = *it; + TDEIO::UDSEntry::ConstIterator itEnd = entry.end(); + + for(TDEIO::UDSEntry::ConstIterator it = entry.begin(); it != itEnd; ++it) + { + if((*it).m_uds == TDEIO::UDS_NAME) + { + suff = (*it).m_str; + + if(suff != dot && suff != dotdot) + { + u = m_url; + u.addPath(suff); + urlstodel.append(u); + } + + break; + } + } + } +} + +void SQ_TreeViewMenu::slotListResult(TDEIO::Job *job) +{ + if(!job) return; + + if(job->error()) + job->showErrorDialog(KSquirrel::app()); + else if(!urlstodel.isEmpty()) + { + TDEIO::Job *job = TDEIO::del(urlstodel); + connect(job, TQ_SIGNAL(result(TDEIO::Job *)), this, TQ_SLOT(slotDirectoryResult(TDEIO::Job *))); + } +} + +void SQ_TreeViewMenu::slotDirectoryResult(TDEIO::Job *job) +{ + if(job && job->error()) + job->showErrorDialog(KSquirrel::app()); +} + +void SQ_TreeViewMenu::slotDirectoryProperties() +{ + if(!m_url.isEmpty()) + (void)new KPropertiesDialog(m_url, KSquirrel::app()); +} + +#include "sq_treeviewmenu.moc" diff --git a/src/sidebar/sq_treeviewmenu.h b/src/sidebar/sq_treeviewmenu.h new file mode 100644 index 0000000..72d900a --- /dev/null +++ b/src/sidebar/sq_treeviewmenu.h @@ -0,0 +1,59 @@ +#ifndef SQ_TREEVIEWMENU_H +#define SQ_TREEVIEWMENU_H + +#include <tdepopupmenu.h> +#include <kurl.h> + +class TQPoint; + +namespace TDEIO { class Job; } + +class SQ_TreeViewMenu : public TDEPopupMenu +{ + TQ_OBJECT + + + public: + SQ_TreeViewMenu(TQWidget *parent = 0, const char *name = 0); + virtual ~SQ_TreeViewMenu(); + + enum Element { New, Rename, Delete, Properties, Clear }; + + void setURL(const KURL &_url); + KURL url() const; + + void reconnect(Element, TQObject *receiver, const char *member); + virtual void updateDirActions(bool isdir, bool isroot = false); + + protected slots: + virtual void slotDirectoryNew(); + virtual void slotDirectoryRename(); + virtual void slotDirectoryDelete(); + virtual void slotDirectoryProperties(); + virtual void slotDirectoryResult(TDEIO::Job *job); + + void slotDirectoryClear(); + void slotEntries(TDEIO::Job *, const TDEIO::UDSEntryList &); + void slotListResult(TDEIO::Job *); + + protected: + int id_new, id_rename, id_delete, id_prop, id_clear; + + private: + KURL m_url; + KURL::List urlstodel; +}; + +inline +void SQ_TreeViewMenu::setURL(const KURL &_url) +{ + m_url = _url; +} + +inline +KURL SQ_TreeViewMenu::url() const +{ + return m_url; +} + +#endif |
