You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tde-style-baghira/sidebar/dndlistbox.cpp

677 lines
22 KiB

#include <dcopclient.h>
#include <tqdragobject.h>
#include <kurl.h>
#include <tqstrlist.h>
#include <tqtimer.h>
#include <tdeapplication.h>
#include <tdelocale.h>
#include <tdefileitem.h>
#include <tdepopupmenu.h>
#include <kicondialog.h>
#include <kiconloader.h>
#include <klineedit.h>
#include <kprocess.h>
#include <kurlrequester.h>
#include <kstandarddirs.h>
#include <twin.h>
#include <tqclipboard.h>
#include "listboxlink.h"
#include "linkconfig.h"
#include "dndlistbox.h"
#include "baghiralinkdrag.h"
#include "dndlistbox.moc"
#define ID 0
#define NAME 1
#define LABEL 2
#define USER_LABEL 3
#define MOUNTABLE 4
#define DEVICE_NODE 5
#define MOUNT_POINT 6
#define FS_TYPE 7
#define MOUNTED 8
#define BASE_URL 9
#define MIME_TYPE 10
#define ICON_NAME 11
#define MEDIA_PROPS 12
#define MEDIALIST_PROPS 13
ResizingLinkBox::ResizingLinkBox( TQWidget * parent, const char * name, WFlags f ) : TDEListBox( parent, name, f)
{
TDEConfig config(TQDir::homeDirPath() + "/.qt/baghirarc");
config.setGroup("Sidebar");
size_ = config.readNumEntry (TQString(name) + "_IconSize", 48);
popupMenu = new TDEPopupMenu;
popupMenu->insertTitle (i18n("Icon Size"),122,122);
popupMenu->insertItem("16x16", this, TQ_SLOT(setIconSize(int)),0,16,123);
popupMenu->insertItem("22x22", this, TQ_SLOT(setIconSize(int)),0,22,124);
popupMenu->insertItem("32x32", this, TQ_SLOT(setIconSize(int)),0,32,125);
popupMenu->insertItem("48x48", this, TQ_SLOT(setIconSize(int)),0,48,126);
popupMenu->insertItem("64x64", this, TQ_SLOT(setIconSize(int)),0,64,127);
popupMenu->insertItem("128x128", this, TQ_SLOT(setIconSize(int)),0,128,128);
}
void ResizingLinkBox::insertItem( const TQListBoxItem *lbi, int index )
{
TDEListBox::insertItem( lbi, index );
if (height() <= numRows()*itemHeight())
emit itemNumberChanged(TRUE);
}
void ResizingLinkBox::insertItem( const TQListBoxItem *lbi, const TQListBoxItem *after )
{
TDEListBox::insertItem( lbi, after );
if (height() <= numRows()*itemHeight())
emit itemNumberChanged(TRUE);
}
void ResizingLinkBox::insertItem( const TQString & icon, const TQString & title, const TQString & url )
{
insertItem( new ListBoxLink(icon, size_, title, url ) );
}
void ResizingLinkBox::removeItem( int index )
{
blockSignals ( true );
TDEListBox::removeItem(index);
blockSignals ( false );
emit itemNumberChanged(FALSE);
}
void ResizingLinkBox::setIconSize(int size)
{
size_ = size;
TDEConfig *config = new TDEConfig(TQDir::homeDirPath() + "/.qt/baghirarc");
config->setGroup("Sidebar");
config->writeEntry (TQString(name()) + "_IconSize", size);
config->sync();
ListBoxLink *runner;
ListBoxDevice *current;
blockSignals ( true );
for (uint i = 0; i < count(); i++)
{
runner = (ListBoxLink*)item(i);
if (dynamic_cast<ListBoxDevice*>(runner))
{
current = (ListBoxDevice*)runner;
insertItem( new ListBoxDevice(current->icon(), size, current->text(), current->URL(), current->name(), current->mountPoint(), current->mounted(), current->ejectable(), current->removable(), current->id()), i );
}
else
{
insertItem( new ListBoxLink(runner->icon(), size, runner->text(), runner->URL()), i );
}
TDEListBox::removeItem(i+1);
}
blockSignals ( false );
}
void ResizingLinkBox::mousePressEvent ( TQMouseEvent *mpe )
{
TDEListBox::mousePressEvent( mpe );
}
void ResizingLinkBox::mouseReleaseEvent ( TQMouseEvent *mpe )
{
if (mpe->button() == TQt::LeftButton)
{
ListBoxLink *link = (ListBoxLink*)itemAt(mpe->pos());
if (isSelected(link)) emit clicked(link);
TDEListBox::mousePressEvent( mpe );
return;
}
TDEListBox::mouseReleaseEvent( mpe );
}
void ResizingLinkBox::contentsWheelEvent ( TQWheelEvent * we )
{
if (we->state() == TQt::ControlButton)
TDEListBox::contentsWheelEvent ( we );
else
emit scrolled(0, -we->delta());
}
MediaListBox::MediaListBox( TQWidget * parent, const char * name, WFlags f ) : ResizingLinkBox(parent, name, f), DCOPObject("BaghiraSidebarIface")
{
TDEConfig config(TQDir::homeDirPath() + "/.qt/baghirarc");
config.setGroup("Sidebar");
hiddenDevices = config.readListEntry("HiddenDevices");
currentFloppy = 0L;
devicePopup = new TDEPopupMenu(this);
devicePopup->setCheckable ( true );
popupMenu->insertItem(i18n("Device List"), devicePopup, 1, 0);
popupMenu->insertSeparator( 0 );
insertItem(new ListBoxDevice("system", size_, i18n("My Computer"), "system:/", "", "", TRUE, FALSE, FALSE));
insertItem(new ListBoxDevice("network", size_, i18n("Network"), "remote:/", "", "", TRUE, FALSE, FALSE));
insertItem(new ListBoxDevice("hdd-mounted", size_, i18n("Startvolume"), TQDir::rootDirPath(), "", "", TRUE, FALSE, FALSE));
client = TDEApplication::dcopClient();
client->connectDCOPSignal("kded", "mediamanager", "mediumAdded(TQString)", "BaghiraSidebarIface", "mediumAdded(TQString)", FALSE);
client->connectDCOPSignal("kded", "mediamanager", "mediumRemoved(TQString)", "BaghiraSidebarIface", "mediumRemoved(const TQString)", FALSE);
client->connectDCOPSignal("kded", "mediamanager", "mediumChanged(TQString)", "BaghiraSidebarIface", "mediumChanged(TQString)", FALSE);
/* Get the media info - huhhh ;) */
TQByteArray data, replyData;
TQCString replyType;
TQDataStream arg(data, IO_WriteOnly);
arg << ""; // ask for the full list
if (!client->call("kded", "mediamanager", "fullList()", data, replyType, replyData))
tqDebug("there was some error using DCOP.");
else
{
TQDataStream reply(replyData, IO_ReadOnly);
if (replyType == "TQStringList")
{
TQStringList result;
reply >> result;
blockSignals ( true );
for (uint i = 0; i < result.size()/MEDIALIST_PROPS; i++)
{
if (result[MEDIALIST_PROPS*i+MIME_TYPE] != "media/hdd_mounted" &&
result[MEDIALIST_PROPS*i+MIME_TYPE] != "media/hdd_unmounted" &&
result[MEDIALIST_PROPS*i+MIME_TYPE] != "media/nfs_mounted" &&
result[MEDIALIST_PROPS*i+MIME_TYPE] != "media/nfs_unmounted" &&
result[MEDIALIST_PROPS*i+MIME_TYPE] != "media/smb_mounted" &&
result[MEDIALIST_PROPS*i+MIME_TYPE] != "media/smb_unmounted")
{
ListBoxDevice *dev = createListBoxDevice(result, i);
if (hiddenDevices.contains(dev->name()))
{
deviceList.append(dev);
devicePopup->setItemChecked(dev->id(),false);
}
else
{
insertItem(dev);
devicePopup->setItemChecked(dev->id(),true);
}
}
}
blockSignals ( false );
}
else
tqWarning("fullList() returned an unexpected type of reply!");
}
// setCurrentItem( 0 );
}
MediaListBox::~MediaListBox()
{
hiddenDevices.clear();
ListBoxDevice *runner;
for ( runner = deviceList.first(); runner; runner = deviceList.next() )
hiddenDevices.append(runner->name());
TDEConfig config(TQDir::homeDirPath() + "/.qt/baghirarc");
config.setGroup("Sidebar");
config.writeEntry("HiddenDevices", hiddenDevices);
}
void MediaListBox::removeItem( int index )
{
devicePopup->removeItem(((ListBoxDevice*)item( index ))->id());
ResizingLinkBox::removeItem(index);
}
void MediaListBox::kfloppy()
{
if (currentFloppy)
{
TDEProcess proc;
proc << "kfloppy" << currentFloppy->mountPoint();
proc.start(TDEProcess::DontCare);
proc.detach();
currentFloppy = 0L;
}
return;
}
void MediaListBox::toggleDevice(int id)
{
ListBoxDevice *runner;
if (devicePopup->isItemChecked(id)) // remove the device!
{
devicePopup->setItemChecked(id, false);
for (uint i = 0; i < count(); i++)
{
runner = (ListBoxDevice*)item(i);
if (runner->id() == id)
{
deviceList.append(runner);
blockSignals ( true );
takeItem(runner);
blockSignals ( false );
break;
}
}
}
else // add the device!
{
devicePopup->setItemChecked(id, true);
for ( runner = deviceList.first(); runner; runner = deviceList.next() )
if (runner->id() == id)
{
insertItem(deviceList.take());
break;
}
}
}
ListBoxDevice *MediaListBox::createListBoxDevice(TQStringList & deviceProperties, uint n)
{
TQString icon;
icon = deviceProperties[MEDIALIST_PROPS*n+ICON_NAME];
if (icon.isNull())
{
icon = deviceProperties[MEDIALIST_PROPS*n+MIME_TYPE];
icon = icon.section( '/', -1 );
icon.truncate( icon.length()-2 );
if (icon.contains("floppy")) icon.prepend("3");
}
TQString label;
label = deviceProperties[MEDIALIST_PROPS*n+USER_LABEL];
if (label.isNull())
{
label = deviceProperties[MEDIALIST_PROPS*n+LABEL];
label = i18n(label.section( " (", 0, 0 ).utf8());
}
return new ListBoxDevice( icon, size_, label, "system:/media/"+deviceProperties[MEDIALIST_PROPS*n+NAME], deviceProperties[MEDIALIST_PROPS*n+NAME], deviceProperties[MEDIALIST_PROPS*n+DEVICE_NODE], deviceProperties[MEDIALIST_PROPS*n+MOUNTED] == "true", icon.contains("dvd") || icon.contains("cdrom") || icon.contains("cdwriter"),icon.contains("floppy"), devicePopup->insertItem(deviceProperties[MEDIALIST_PROPS*n+NAME], this, TQ_SLOT(toggleDevice(int))));
}
int MediaListBox::index (const TQString & name )
{
ListBoxDevice *device;
for (uint i = 0; i < count(); i++)
{
device = (ListBoxDevice*)item(i);
if (device && device->name() == name) return i;
}
return -1;
}
void MediaListBox::mediumAdded(const TQString &name)
{
TQByteArray data, replyData;
TQCString replyType;
TQDataStream arg(data, IO_WriteOnly);
arg << name; // ask for this item only
if (!client->call("kded", "mediamanager", "properties(TQString)", data, replyType, replyData))
tqDebug("there was some error using DCOP.");
else
{
TQDataStream reply(replyData, IO_ReadOnly);
if (replyType == "TQStringList")
{
TQStringList result;
reply >> result;
ListBoxDevice *dev = createListBoxDevice(result);
if (hiddenDevices.contains(dev->name()))
{
deviceList.append(dev);
devicePopup->setItemChecked(dev->id(),false);
}
else
{
insertItem(dev);
devicePopup->setItemChecked(dev->id(),true);
}
}
else
tqWarning("properties() returned an unexpected type of reply!");
}
}
void MediaListBox::mediumRemoved(const TQString &name)
{
TQByteArray data, replyData;
TQCString replyType;
TQDataStream arg(data, IO_WriteOnly);
arg << name; // ask for this item only
if (!client->call("kded", "mediamanager", "properties(TQString)", data, replyType, replyData))
tqDebug("there was some error using DCOP.");
else
{
TQDataStream reply(replyData, IO_ReadOnly);
if (replyType == "TQStringList")
{
TQStringList result;
reply >> result;
int i = index(name);
if (i<0)
return;
if (i == currentItem()) setCurrentItem(0);
removeItem(i);
}
else
tqWarning("properties() returned an unexpected type of reply!");
}
}
void MediaListBox::mediumChanged(const TQString &name)
{
TQByteArray data, replyData;
TQCString replyType;
TQDataStream arg(data, IO_WriteOnly);
arg << name; // ask for this item only
if (!client->call("kded", "mediamanager", "properties(TQString)", data, replyType, replyData))
tqDebug("there was some error using DCOP.");
else
{
TQDataStream reply(replyData, IO_ReadOnly);
if (replyType == "TQStringList")
{
TQStringList result;
reply >> result;
int i = index(name);
if (i<0)
return;
ListBoxDevice *device = createListBoxDevice(result);
if (hiddenDevices.contains(device->name()))
{
deviceList.append(device);
devicePopup->setItemChecked(device->id(),false);
return;
}
devicePopup->setItemChecked(device->id(),true);
blockSignals(true);
if (i == currentItem()) // changing current item - take some care of updating stuff
{
if (((ListBoxDevice*)item(i))->mounted() && !device->mounted()) // unmounted the device - we certainly do not wanna select it anymore
{
setCurrentItem(0);
removeItem(i);
insertItem(device, i);
}
else // we're selected and wanna keep selection
{
removeItem(i);
insertItem(device, i);
setSelected( i, true );
}
}
else // ordinary change
{
removeItem(i);
insertItem(device, i);
}
blockSignals(false);
}
else
tqWarning("properties() returned an unexpected type of reply!");
}
}
#define _FLOPPYID_ 0
#define _FLOPPYINDEX_ 0
void MediaListBox::mousePressEvent ( TQMouseEvent *mpe )
{
if (mpe->button() == TQt::RightButton)
{
popupMenu->removeItem(_FLOPPYID_);
ListBoxDevice *device = (ListBoxDevice*)itemAt(mpe->pos());
if (device && device->name().contains("fd"))
{
currentFloppy = device;
popupMenu->insertItem(i18n("Format disk..."), this, TQ_SLOT(kfloppy()),0,_FLOPPYID_,_FLOPPYINDEX_);
}
popupMenu->popup(mpe->globalPos());
return;
}
if (mpe->button() == TQt::LeftButton && mpe->x() > width()-22)
{
ListBoxDevice *device = (ListBoxDevice*)itemAt(mpe->pos());
int dy = itemRect(device).y();
if ((device->removable() || device->ejectable()) && device->mounted() && mpe->y() > dy+11 && mpe->y() < dy+33)
{
TDEProcess proc;
device->ejectable()?
proc << "kdeeject" /*<< "-q"*/ << device->mountPoint():
proc << "umount" << device->mountPoint(); // umount?
proc.start(TDEProcess::DontCare);
proc.detach();
return;
}
}
ResizingLinkBox::mousePressEvent( mpe );
}
void MediaListBox::resizeEvent ( TQResizeEvent * re)
{
if (width() != re->oldSize().width())
{
for (uint i = 0; i < count(); i++)
if (((ListBoxDevice*)item(i))->ejectable() && ((ListBoxDevice*)item(i))->mounted() && !isSelected(i)) updateItem(i);
}
ResizingLinkBox::resizeEvent(re);
}
DnDListBox::DnDListBox( TQWidget * parent, const char * name, WFlags f ):
ResizingLinkBox( parent, name, f), _poof(0), _poofIndex(0), _poofAnimPix(0), _poofPix(0)
{
setAcceptDrops(true);
dialog = new LinkConfig();
connect(dialog->buttonOk, TQ_SIGNAL(clicked()), this, TQ_SLOT(updateLink()));
setCursor(TQt::PointingHandCursor);
}
DnDListBox::~DnDListBox()
{
}
void DnDListBox::poof(ListBoxLink *link)
{
_poofIndex = 0;
_poofPix = new TQPixmap(locateLocal("data", "baghira/poof.png"), "png");
_poofAnimPix = new TQPixmap(_poofPix->width(), _poofPix->width());
if (!_poof)
_poof = new TQWidget(0,0, TQt::WType_TopLevel | TQt::WStyle_NoBorder | TQt::WStyle_StaysOnTop | TQt::WX11BypassWM);
KWin::setShadowSize(_poof->winId(), 0);
_poof->setFixedSize(_poofPix->width(), _poofPix->width());
int x = TQCursor::pos().x() - _poof->width()/2;
int y = TQCursor::pos().y() - _poof->height()/2;
TQPixmap bgPix = TQPixmap::grabWindow( tqt_xrootwin(), x, y, _poofPix->width(), _poofPix->width());
_poof->move(x,y);
_poof->show();
_poof->setBackgroundOrigin(TQWidget::WidgetOrigin);
_poof->setPaletteBackgroundPixmap( bgPix );
runPoof();
removeItem ( index(link) );
}
void DnDListBox::runPoof()
{
if (_poofIndex > 4)
{
_poof->hide();
delete _poofPix;
_poofPix = 0L;
// delete _poof;
// _poof = 0L;
delete _poofAnimPix;
_poofAnimPix = 0L;
_poofIndex = 0;
return;
}
_poof->erase();
bitBlt(_poof, 0 ,0, _poofPix, 0, _poofIndex * _poofPix->width(), _poofPix->width(), _poofPix->width(), TQt::AndROP);
++_poofIndex;
TQTimer::singleShot ( 70, this, TQ_SLOT(runPoof()) ); // around 15 fps
}
void DnDListBox::dragEnterEvent ( TQDragEnterEvent *dee )
{
// dragging_ = true;
if (TQUriDrag::canDecode(dee) || BaghiraLinkDrag::canDecode(dee) || TQTextDrag::canDecode(dee))
dee->accept(true);
}
void DnDListBox::dropEvent ( TQDropEvent *de )
{
TQStrList list;
TQString title;
TQString command;
TQString icon;
int oldIndex;
TQCString subtype;
if (BaghiraLinkDrag::decode(de, &title, &command, &icon, &oldIndex)) // internal move
{
BaghiraLinkDrag::setAccepted();
TQListBoxItem *after = itemAt(de->pos());
int newIndex = index(after);
if (!dragging_ || oldIndex < 0 || oldIndex > count()-2)
insertItem (new ListBoxLink(icon, size_, title, command), after?newIndex:count());
else if (oldIndex != newIndex)
{
insertItem (new ListBoxLink(*((ListBoxLink*)item(oldIndex))), after?newIndex:count());
removeItem ( (newIndex < 0 || oldIndex < newIndex) ? oldIndex : oldIndex + 1 );
}
}
else if ( TQUriDrag::decode(de, list) )
{
char *uri;
KURL url;
TQListBoxItem *after = itemAt(de->pos());
for ( uri = list.first(); uri; uri = list.next() )
{
url = KURL(uri);
if (url.protocol() == "http")
insertItem(new ListBoxLink("html", size_, url.host()+(url.path()=="/"?TQString(""):url.path()), uri), after?index(after):count());
else
{
KFileItem item = KFileItem(KFileItem::Unknown, KFileItem::Unknown, url, true);
insertItem(new ListBoxLink(item.iconName(), size_, url.fileName().isEmpty()?url.prettyURL():url.fileName(), uri), after?index(after):count());
}
}
}
else if (TQTextDrag::decode(de, command, subtype))
{
KURL url(command);
if (url.isValid())
{
TQListBoxItem *after = itemAt(de->pos());
if (url.protocol() == "http")
insertItem(new ListBoxLink("html", size_, url.host()+(url.path()=="/"?TQString(""):url.path()), command), after?index(after):count());
else
{
KFileItem item = KFileItem(KFileItem::Unknown, KFileItem::Unknown, url, true);
insertItem(new ListBoxLink(item.iconName(), size_, url.fileName().isEmpty()?url.prettyURL():url.fileName(), command), after?index(after):count());
}
}
else if (command.contains('@'))
{
TQListBoxItem *after = itemAt(de->pos());
command.replace(" ","");
insertItem(new ListBoxLink("kmail", size_, command, "mailto:"+command), after?index(after):count());
}
else if (command.contains("'at'")) //last chance for anti-spam addy
{
TQListBoxItem *after = itemAt(de->pos());
command.replace(" ","");
command.replace("'at'","@");
insertItem(new ListBoxLink("kmail", size_, command, "mailto:"+command), after?index(after):count());
}
}
}
void DnDListBox::mousePressEvent ( TQMouseEvent *mpe )
{
if (mpe->button() == TQt::RightButton)
{
currentItem = 0;
popupMenu->removeItem(0);
ListBoxDevice *device = (ListBoxDevice*)itemAt(mpe->pos());
if (device)
{
currentItem = device;
popupMenu->insertItem("Edit link...", this, TQ_SLOT(configureLink()),0,0,0);
}
popupMenu->popup(mpe->globalPos());
return;
}
if (mpe->button() == TQt::MidButton)
{
pasteURL(TQClipboard::Selection, itemAt(mpe->pos()));
return;
}
ResizingLinkBox::mousePressEvent( mpe );
}
void DnDListBox::mouseReleaseEvent ( TQMouseEvent *mre )
{
if (!dragging_) ResizingLinkBox::mouseReleaseEvent( mre );
}
void DnDListBox::mouseMoveEvent ( TQMouseEvent * mme )
{
if (mme->state() & TQt::LeftButton)
{
if (!dragging_)
{
ListBoxLink *link = (ListBoxLink*)itemAt(mme->pos());
if (link)
{
dragging_ = true;
BaghiraLinkDrag *d = new BaghiraLinkDrag( link->text(), link->URL(), link->icon(), index(link), this );
d->setPixmap(*link->pixmap(),TQPoint(22,22));
d->drag();
if (mme->state() & TQt::ControlButton || BaghiraLinkDrag::accepted())
return;
poof(link);
// do NOT delete d.
}
}
}
else // ensure to release from drag
dragging_ = false;
}
void DnDListBox::pasteURL(int mode, TQListBoxItem *after)
{
TQString string = tqApp->clipboard()->text( (TQClipboard::Mode)mode );
KURL url(string);
if (url.isValid())
{
if (url.protocol() == "http")
insertItem(new ListBoxLink("html", size_, url.host()+(url.path()=="/"?TQString(""):url.path()), string), after?index(after):count());
else
{
KFileItem item = KFileItem(KFileItem::Unknown, KFileItem::Unknown, url, true);
insertItem(new ListBoxLink(item.iconName(),size_, url.fileName().isEmpty()?url.prettyURL():url.fileName(), string), after?index(after):count());
}
}
else if (string.contains('@'))
{
string.replace(" ","");
insertItem(new ListBoxLink("kmail", size_, string, "mailto:"+string), after?index(after):count());
}
else if (string.contains("'at'")) //last chance for anti-spam addy
{
string.replace(" ","");
string.replace("'at'","@");
insertItem(new ListBoxLink("kmail", size_, string, "mailto:"+string), after?index(after):count());
}
}
void DnDListBox::configureLink()
{
if (currentItem == 0L)
return;
dialog->title->setText(currentItem->text());
dialog->url->setURL(currentItem->URL());
dialog->icon->setIcon(currentItem->icon());
dialog->show();
}
void DnDListBox::updateLink()
{
if (currentItem)
{
int index_ = index(currentItem);
bool wasSelected = isSelected(index_);
insertItem( new ListBoxLink(dialog->icon->icon(), size_, dialog->title->text(),dialog->url->url()), index_ +1);
removeItem( index_ );
setSelected(index_, wasSelected);
}
}