|
|
|
//Author: Max Howell <max.howell@methylblue.com>, (C) 2003-4
|
|
|
|
//Copyright: See COPYING file that comes with this distribution
|
|
|
|
|
|
|
|
#include "fileTree.h"
|
|
|
|
#include "radialMap.h" //class Segment
|
|
|
|
#include "widget.h"
|
|
|
|
|
|
|
|
#include <cmath> //::segmentAt()
|
|
|
|
#include <kcursor.h> //::mouseMoveEvent()
|
|
|
|
#include <kiconeffect.h> //::mousePressEvent()
|
|
|
|
#include <kiconloader.h> //::mousePressEvent()
|
|
|
|
#include <tdeio/job.h> //::mousePressEvent()
|
|
|
|
#include <tdelocale.h>
|
|
|
|
#include <tdemessagebox.h> //::mousePressEvent()
|
|
|
|
#include <tdepopupmenu.h> //::mousePressEvent()
|
|
|
|
#include <krun.h> //::mousePressEvent()
|
|
|
|
#include <kurldrag.h>
|
|
|
|
#include <tqapplication.h>//TQApplication::setOverrideCursor()
|
|
|
|
#include <tqclipboard.h>
|
|
|
|
#include <tqpainter.h>
|
|
|
|
#include <tqtimer.h> //::resizeEvent()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
RadialMap::Widget::resizeEvent( TQResizeEvent* )
|
|
|
|
{
|
|
|
|
if( m_map.resize( rect() ) )
|
|
|
|
m_timer.start( 500, true ); //will cause signature to rebuild for new size
|
|
|
|
|
|
|
|
//always do these as they need to be initialised on creation
|
|
|
|
m_offset.rx() = (width() - m_map.width()) / 2;
|
|
|
|
m_offset.ry() = (height() - m_map.height()) / 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
RadialMap::Widget::paintEvent( TQPaintEvent* )
|
|
|
|
{
|
|
|
|
//bltBit for some TQt setups will bitBlt _after_ the labels are painted. Which buggers things up!
|
|
|
|
//shame as bitBlt is faster, possibly TQt bug? Should report the bug? - seems to be race condition
|
|
|
|
//bitBlt( this, m_offset, &m_map );
|
|
|
|
|
|
|
|
TQPainter paint( this );
|
|
|
|
|
|
|
|
paint.drawPixmap( m_offset, m_map );
|
|
|
|
|
|
|
|
//vertical strips
|
|
|
|
if( m_map.width() < width() )
|
|
|
|
{
|
|
|
|
paint.eraseRect( 0, 0, m_offset.x(), height() );
|
|
|
|
paint.eraseRect( m_map.width() + m_offset.x(), 0, m_offset.x() + 1, height() );
|
|
|
|
}
|
|
|
|
//horizontal strips
|
|
|
|
if( m_map.height() < height() )
|
|
|
|
{
|
|
|
|
paint.eraseRect( 0, 0, width(), m_offset.y() );
|
|
|
|
paint.eraseRect( 0, m_map.height() + m_offset.y(), width(), m_offset.y() + 1 );
|
|
|
|
}
|
|
|
|
|
|
|
|
//exploded labels
|
|
|
|
if( !m_map.isNull() && !m_timer.isActive() )
|
|
|
|
paintExplodedLabels( paint );
|
|
|
|
}
|
|
|
|
|
|
|
|
const RadialMap::Segment*
|
|
|
|
RadialMap::Widget::segmentAt( TQPoint &e ) const
|
|
|
|
{
|
|
|
|
//determine which segment TQPoint e is above
|
|
|
|
|
|
|
|
e -= m_offset;
|
|
|
|
|
|
|
|
if( !m_map.m_signature )
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if( e.x() <= m_map.width() && e.y() <= m_map.height() )
|
|
|
|
{
|
|
|
|
//transform to cartesian coords
|
|
|
|
e.rx() -= m_map.width() / 2; //should be an int
|
|
|
|
e.ry() = m_map.height() / 2 - e.y();
|
|
|
|
|
|
|
|
double length = hypot( e.x(), e.y() );
|
|
|
|
|
|
|
|
if( length >= m_map.m_innerRadius ) //not hovering over inner circle
|
|
|
|
{
|
|
|
|
uint depth = ((int)length - m_map.m_innerRadius) / m_map.m_ringBreadth;
|
|
|
|
|
|
|
|
if( depth <= m_map.m_visibleDepth ) //**** do earlier since you can //** check not outside of range
|
|
|
|
{
|
|
|
|
//vector calculation, reduces to simple trigonometry
|
|
|
|
//cos angle = (aibi + ajbj) / albl
|
|
|
|
//ai = x, bi=1, aj=y, bj=0
|
|
|
|
//cos angle = x / (length)
|
|
|
|
|
|
|
|
uint a = (uint)(acos( (double)e.x() / length ) * 916.736); //916.7324722 = #radians in circle * 16
|
|
|
|
|
|
|
|
//acos only understands 0-180 degrees
|
|
|
|
if( e.y() < 0 ) a = 5760 - a;
|
|
|
|
|
|
|
|
#define ring (m_map.m_signature + depth)
|
|
|
|
for( ConstIterator<Segment> it = ring->constIterator(); it != ring->end(); ++it )
|
|
|
|
if( (*it)->intersects( a ) )
|
|
|
|
return *it;
|
|
|
|
#undef ring
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else return m_rootSegment; //hovering over inner circle
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
RadialMap::Widget::mouseMoveEvent( TQMouseEvent *e )
|
|
|
|
{
|
|
|
|
//set m_focus to what we hover over, update UI if it's a new segment
|
|
|
|
|
|
|
|
Segment const * const oldFocus = m_focus;
|
|
|
|
TQPoint p = e->pos();
|
|
|
|
|
|
|
|
m_focus = segmentAt( p ); //NOTE p is passed by non-const reference
|
|
|
|
|
|
|
|
if( m_focus && m_focus->file() != m_tree )
|
|
|
|
{
|
|
|
|
if( m_focus != oldFocus ) //if not same as last time
|
|
|
|
{
|
|
|
|
setCursor( KCursor::handCursor() );
|
|
|
|
m_tip->updateTip( m_focus->file(), m_tree );
|
|
|
|
emit mouseHover( m_focus->file()->fullPath() );
|
|
|
|
|
|
|
|
//repaint required to update labels now before transparency is generated
|
|
|
|
repaint( false );
|
|
|
|
}
|
|
|
|
|
|
|
|
m_tip->moveTo( e->globalPos(), *this, ( p.y() < 0 ) ); //updates tooltip psuedo-tranparent background
|
|
|
|
}
|
|
|
|
else if( oldFocus && oldFocus->file() != m_tree )
|
|
|
|
{
|
|
|
|
unsetCursor();
|
|
|
|
m_tip->hide();
|
|
|
|
update();
|
|
|
|
|
|
|
|
emit mouseHover( TQString() );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
RadialMap::Widget::mousePressEvent( TQMouseEvent *e )
|
|
|
|
{
|
|
|
|
//m_tip is hidden already by event filter
|
|
|
|
//m_focus is set correctly (I've been strict, I assure you it is correct!)
|
|
|
|
|
|
|
|
enum { Konqueror, Konsole, Center, Open, Copy, Delete };
|
|
|
|
|
|
|
|
if (m_focus && !m_focus->isFake())
|
|
|
|
{
|
|
|
|
const KURL url = Widget::url( m_focus->file() );
|
|
|
|
const bool isDir = m_focus->file()->isDirectory();
|
|
|
|
|
|
|
|
if( e->button() == TQt::RightButton )
|
|
|
|
{
|
|
|
|
TDEPopupMenu popup;
|
|
|
|
popup.insertTitle( m_focus->file()->fullPath( m_tree ) );
|
|
|
|
|
|
|
|
if (isDir) {
|
|
|
|
popup.insertItem( SmallIconSet( "konqueror" ), i18n( "Open &Konqueror Here" ), Konqueror );
|
|
|
|
|
|
|
|
if( url.protocol() == "file" )
|
|
|
|
popup.insertItem( SmallIconSet( "konsole" ), i18n( "Open &Konsole Here" ), Konsole );
|
|
|
|
|
|
|
|
if (m_focus->file() != m_tree) {
|
|
|
|
popup.insertSeparator();
|
|
|
|
popup.insertItem( SmallIconSet( "viewmag" ), i18n( "&Center Map Here" ), Center );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
Bring filenew, fileopen, fileprint, filequickprint, filesave, filesaveas, fileclose, editclear, editcopy, editcut, editdelete, editpaste, folder_new, and gohome icons into XDG compliance
10 years ago
|
|
|
popup.insertItem( SmallIconSet( "document-open" ), i18n( "&Open" ), Open );
|
|
|
|
|
|
|
|
popup.insertSeparator();
|
Bring filenew, fileopen, fileprint, filequickprint, filesave, filesaveas, fileclose, editclear, editcopy, editcut, editdelete, editpaste, folder_new, and gohome icons into XDG compliance
10 years ago
|
|
|
popup.insertItem( SmallIconSet( "edit-copy" ), i18n( "&Copy to clipboard" ), Copy );
|
|
|
|
|
|
|
|
popup.insertSeparator();
|
Bring filenew, fileopen, fileprint, filequickprint, filesave, filesaveas, fileclose, editclear, editcopy, editcut, editdelete, editpaste, folder_new, and gohome icons into XDG compliance
10 years ago
|
|
|
popup.insertItem( SmallIconSet( "edit-delete" ), i18n( "&Delete" ), Delete );
|
|
|
|
|
|
|
|
switch (popup.exec( e->globalPos(), 1 )) {
|
|
|
|
case Konqueror:
|
|
|
|
//KRun::runCommand will show an error message if there was trouble
|
|
|
|
KRun::runCommand( TQString( "kfmclient openURL \"%1\"" ).arg( url.url() ) );
|
|
|
|
break;
|
|
|
|
|
|
|
|
case Konsole:
|
|
|
|
// --workdir only works for local file paths
|
|
|
|
KRun::runCommand( TQString( "konsole --workdir \"%1\"" ).arg( url.path() ) );
|
|
|
|
break;
|
|
|
|
|
|
|
|
case Center:
|
|
|
|
case Open:
|
|
|
|
goto section_two;
|
|
|
|
|
|
|
|
case Copy:
|
|
|
|
TQApplication::clipboard()->setData( new KURLDrag( KURL::List( url ) ) );
|
|
|
|
break;
|
|
|
|
|
|
|
|
case Delete:
|
|
|
|
{
|
|
|
|
const KURL url = Widget::url( m_focus->file() );
|
|
|
|
const TQString message = m_focus->file()->isDirectory()
|
|
|
|
? i18n( "<qt>The directory at <i>'%1'</i> will be <b>recursively</b> and <b>permanently</b> deleted." )
|
|
|
|
: i18n( "<qt><i>'%1'</i> will be <b>permanently</b> deleted." );
|
|
|
|
const int userIntention = KMessageBox::warningContinueCancel(
|
|
|
|
this, message.arg( url.prettyURL() ),
|
Bring filenew, fileopen, fileprint, filequickprint, filesave, filesaveas, fileclose, editclear, editcopy, editcut, editdelete, editpaste, folder_new, and gohome icons into XDG compliance
10 years ago
|
|
|
TQString(), KGuiItem( i18n("&Delete"), "edit-delete" ) );
|
|
|
|
|
|
|
|
if (userIntention == KMessageBox::Continue) {
|
|
|
|
TDEIO::Job *job = TDEIO::del( url );
|
|
|
|
job->setWindow( this );
|
|
|
|
connect( job, TQ_SIGNAL(result( TDEIO::Job* )), TQ_SLOT(deleteJobFinished( TDEIO::Job* )) );
|
|
|
|
TQApplication::setOverrideCursor( KCursor::workingCursor() );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
|
|
|
//ensure m_focus is set for new mouse position
|
|
|
|
sendFakeMouseEvent();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else { // not right mouse button
|
|
|
|
|
|
|
|
section_two:
|
|
|
|
const TQRect rect( e->x() - 20, e->y() - 20, 40, 40 );
|
|
|
|
|
|
|
|
m_tip->hide(); // user expects this
|
|
|
|
|
|
|
|
if (!isDir || e->button() == TQt::MidButton) {
|
|
|
|
TDEIconEffect::visualActivate( this, rect );
|
|
|
|
new KRun( url, this, true ); //FIXME see above
|
|
|
|
}
|
|
|
|
else if (m_focus->file() != m_tree) { // is left click
|
|
|
|
TDEIconEffect::visualActivate( this, rect );
|
|
|
|
emit activated( url ); //activate first, this will cause UI to prepare itself
|
|
|
|
createFromCache( (Directory *)m_focus->file() );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
emit giveMeTreeFor( url.upURL() );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
RadialMap::Widget::deleteJobFinished( TDEIO::Job *job )
|
|
|
|
{
|
|
|
|
TQApplication::restoreOverrideCursor();
|
|
|
|
if( !job->error() )
|
|
|
|
invalidate();
|
|
|
|
else
|
|
|
|
job->showErrorDialog( this );
|
|
|
|
}
|
|
|
|
|
|
|
|
#include "debug.h"
|
|
|
|
void
|
|
|
|
RadialMap::Widget::dropEvent( TQDropEvent *e )
|
|
|
|
{
|
|
|
|
DEBUG_ANNOUNCE
|
|
|
|
|
|
|
|
KURL::List urls;
|
|
|
|
if (KURLDrag::decode( e, urls ) && urls.count())
|
|
|
|
emit giveMeTreeFor( urls.first() );
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
RadialMap::Widget::dragEnterEvent( TQDragEnterEvent *e )
|
|
|
|
{
|
|
|
|
DEBUG_ANNOUNCE
|
|
|
|
|
|
|
|
e->accept( KURLDrag::canDecode( e ) );
|
|
|
|
}
|