// KDat - a tar-based DAT archiver // Copyright (C) 1998-2000 Sean Vyain, svyain@mail.tds.net // Copyright (C) 2001-2002 Lawrence Widman, kdat@cardiothink.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. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA #include #include #include #include #include #include #include #include #include "Archive.h" #include "BackupProfile.h" #include "BackupProfileManager.h" #include "ImageCache.h" #include "KDatMainWindow.h" #include "Node.h" #include "Range.h" #include "Tape.h" #include "TapeManager.h" #include #include "Node.moc" Node::Node( int type, const TQString & text, const TQPixmap& pixmap ) : KTreeViewItem( text, pixmap ), _type( type ) { } Node::~Node() { } void Node::insertNode( Node* child ) { static Node* lastParent = 0; static uint lastDirIndex = 0; if ( lastParent != this ) { // Recompute lastDirIndex. for ( lastDirIndex = 0; ( lastDirIndex < childCount() ) && ( ((Node*)childAt( lastDirIndex ))->getType() == TapeDirectoryNodeType ); lastDirIndex++ ); lastParent = this; } int min, mid, max, smin, smax; if ( ( child->getType() == TapeDirectoryNodeType ) || ( child->getType() == MountedTapeDirectoryNodeType ) ) { min = 0; max = lastDirIndex - 1; lastDirIndex++; } else { min = lastDirIndex; max = childCount() - 1; } if ( min > max ) min = max; smin = min; smax = max; //printf( "min = %d, max = %d\n", min, max ); mid = min; while ( min < max ) { mid = ( max - min ) / 2 + min; //mid = ( min + max ) / 2; if ( child->getText().compare( childAt( mid )->getText() ) < 0 ) { max = mid - 1; } else { min = mid + 1; } } if ( childCount() ) { // KLUDGE! mid -= 5; if ( mid < smin ) mid = smin; if ( ((Node*)childAt( mid ))->getType() != child->getType() ) mid++; for ( ; ( mid <= smax ) && ( child->getText().compare( childAt( mid )->getText() ) > 0 ); mid++ ); //printf( "index = %d, text = '%s'\n", mid, child->getText().data() ); insertChild( mid, child ); } else { //printf( "index = %d, text = '%s'\n", 0, child->getText().data() ); insertChild( 0, child ); } } int Node::getType() { return _type; } bool Node::isType( int type ) { return type == NodeType; } void Node::expanding( bool expand ) { expand = TRUE; } void Node::expanded() { } void Node::collapsed() { } void Node::selected() { KDatMainWindow::getInstance()->hideInfo(); } void Node::popupMenu( const TQPoint& ) { } TapeNode::TapeNode( Tape* tape ) : Node( TapeNodeType, tape->getName(), *ImageCache::instance()->getTape() ), _tape( tape ) { setDelayedExpanding( TRUE ); } Tape* TapeNode::getTape() { return _tape; } bool TapeNode::validate() { bool changed = _tape->getName() != getText(); if ( changed ) { setText( _tape->getName() ); } if ( ( childCount() == 0 ) && ( !isExpanded() ) ) { return changed; } // Add/update existing archives. TQPtrListIterator i( _tape->getChildren() ); ArchiveNode* n; for ( ; i.current(); ++i ) { n = findArchiveNode( i.current() ); if ( n ) { if ( n->validate() ) { bool select = ( owner->getCurrentItem() == n ); removeChild( n ); insertNode( n ); if ( select ) { owner->setCurrentItem( owner->itemRow( n ) ); } } } else { insertNode( new ArchiveNode( i.current() ) ); } } // Remove deleted archives. Archive* a; for ( uint j = 0; j < childCount(); ) { a = ((ArchiveNode*)childAt( j ))->getArchive(); for ( i.toFirst(); i.current(); ++i ) { if ( i.current() == a ) { break; } } if ( !i.current() ) { removeChild( childAt( j ) ); } else { j++; } } return changed; } bool TapeNode::isType( int type ) { if ( type == TapeNodeType ) { return TRUE; } else { return Node::isType( type ); } } void TapeNode::expanding( bool expand ) { expand = TRUE; if ( childCount() > 0 ) { // We already have the children added return; } TQPtrListIterator f( _tape->getChildren() ); for ( ; f.current(); ++f ) { insertNode( new ArchiveNode( f.current() ) ); } } void TapeNode::selected() { KDatMainWindow::getInstance()->showTapeInfo( _tape ); } void TapeNode::popupMenu( const TQPoint& p ) { KDatMainWindow::getInstance()->popupTapeMenu( p ); } ArchiveNode* TapeNode::findArchiveNode( Archive* archive ) { ArchiveNode* n = 0; for ( uint i = 0; i < childCount(); i++ ) { if ( ((ArchiveNode*)childAt( i ))->getArchive() == archive ) { n = (ArchiveNode*)childAt( i ); break; } } return n; } ArchiveNode::ArchiveNode( Archive* archive ) : Node( ArchiveNodeType, archive->getName(), *ImageCache::instance()->getArchive() ), _archive( archive ) { setDelayedExpanding( TRUE ); } Archive* ArchiveNode::getArchive() { return _archive; } bool ArchiveNode::validate() { bool changed = _archive->getName() != getText(); if ( changed ) { setText( _archive->getName() ); } return changed; } bool ArchiveNode::isType( int type ) { if ( type == ArchiveNodeType ) { return TRUE; } else { return Node::isType( type ); } } void ArchiveNode::expanding( bool expand ) { expand = TRUE; if ( childCount() > 0 ) { // We already have the children added. return; } TQPtrListIterator f( _archive->getChildren() ); for ( ; f.current(); ++f ) { if ( f.current()->getName()[f.current()->getName().length()-1] == '/' ) { insertNode( new TapeDirectoryNode( f.current() ) ); } else { insertNode( new TapeFileNode( f.current() ) ); } } } void ArchiveNode::selected() { KDatMainWindow::getInstance()->showArchiveInfo( _archive ); } void ArchiveNode::popupMenu( const TQPoint& p ) { KDatMainWindow::getInstance()->popupArchiveMenu( p ); } TapeDirectoryNode::TapeDirectoryNode( File* file ) : Node( TapeDirectoryNodeType, "", *ImageCache::instance()->getFolderClosed() ), _file( file ) { setDelayedExpanding( TRUE ); int len = _file->getName().length(); int idx1 = _file->getName().findRev( '/', len - 2 ); if ( idx1 < 0 ) { setText( _file->getName().left( len - 1 ) ); } else { setText( _file->getName().mid( idx1 + 1, len - idx1 - 2 ) ); } } File* TapeDirectoryNode::getFile() { return _file; } bool TapeDirectoryNode::isType( int type ) { if ( type == TapeDirectoryNodeType ) { return TRUE; } else { return Node::isType( type ); } } void TapeDirectoryNode::expanding( bool expand ) { expand = TRUE; if ( childCount() > 0 ) { // We already have the children added. return; } TQPtrListIterator f( _file->getChildren() ); for ( ; f.current(); ++f ) { if ( f.current()->getName()[f.current()->getName().length()-1] == '/' ) { insertNode( new TapeDirectoryNode( f.current() ) ); } else { insertNode( new TapeFileNode( f.current() ) ); } } } void TapeDirectoryNode::expanded() { setPixmap( *ImageCache::instance()->getFolderOpen() ); } void TapeDirectoryNode::collapsed() { setPixmap( *ImageCache::instance()->getFolderClosed() ); } void TapeDirectoryNode::selected() { KDatMainWindow::getInstance()->showTapeFileInfo( _file ); } TapeFileNode::TapeFileNode( File* file ) : Node( TapeFileNodeType, file->getName(), *ImageCache::instance()->getFile() ), _file( file ) { int len = _file->getName().length(); int idx1 = _file->getName().findRev( '/', len - 1 ); if ( idx1 < 0 ) { setText( _file->getName().left( len ) ); } else { setText( _file->getName().mid( idx1 + 1, len - idx1 - 1 ) ); } } File* TapeFileNode::getFile() { return _file; } bool TapeFileNode::isType( int type ) { if ( type == TapeFileNodeType ) { return TRUE; } else { return Node::isType( type ); } } void TapeFileNode::selected() { KDatMainWindow::getInstance()->showTapeFileInfo( _file ); } SelectableNode::SelectableNode( int type, const TQString & text, const TQPixmap& pixmap, int state ) : Node( type, text, pixmap ), _state( state ) { } void SelectableNode::doUpdateState() { bool oneSelected = FALSE; bool hasSelected = FALSE; bool allSelected = TRUE; for ( uint i = 0; i < childCount(); i++ ) { switch ( ((SelectableNode*)childAt( i ))->_state ) { case SelAll: oneSelected = TRUE; hasSelected = TRUE; break; case SelSome: hasSelected = TRUE; allSelected = FALSE; break; case SelNone: allSelected = FALSE; break; } } if ( allSelected ) { _state = SelAll; } else if ( oneSelected || hasSelected ) { _state = SelSome; } else { _state = SelNone; } if ( ( getParent() ) && ( getParent()->getParent() ) && ( ((Node*)getParent())->isType( SelectableNodeType ) ) ) { ((SelectableNode*)getParent())->doUpdateState(); } } void SelectableNode::doSetSelected( bool select ) { // All my children get the same selection state. for ( uint i = 0; i < childCount(); i++ ) { if ( select ) { if ( !((SelectableNode*)childAt( i ))->isSelected() ) { ((SelectableNode*)childAt( i ))->doSetSelected( TRUE ); } } else { if ( ((SelectableNode*)childAt( i ))->isSelected() || ((SelectableNode*)childAt( i ))->hasSelectedChildren() ) { ((SelectableNode*)childAt( i ))->doSetSelected( FALSE ); } } } if ( select ) { _state = SelAll; } else { _state = SelNone; } } const TQPixmap* SelectableNode::getSelectPixmap() const { switch ( _state ) { case SelAll: return ImageCache::instance()->getSelectAll(); case SelNone: return ImageCache::instance()->getSelectNone(); case SelSome: return ImageCache::instance()->getSelectSome(); default: return 0; } } bool SelectableNode::mousePressEvent( const TQPoint& point ) { if ( _selectRect.contains( point ) ) { switch ( _state ) { case SelAll: setSelected( FALSE ); break; case SelNone: setSelected( TRUE ); break; case SelSome: setSelected( TRUE ); break; } return TRUE; } else { return FALSE; } } void SelectableNode::paint( TQPainter* p, int indent, const TQColorGroup& cg, bool highlighted ) const { assert(getParent() != 0); /* can't paint root item */ p->save(); p->setPen(cg.text()); p->setBackgroundColor(cg.base()); int cellHeight = height(p->fontMetrics()); if (doTree) { paintTree(p, indent, cellHeight); } /* * If this item has at least one child and expand button drawing is * enabled, set the rect for the expand button for later mouse press * bounds checking, and draw the button. */ if (doExpandButton && (child || delayedExpanding)) { paintExpandButton(p, indent, cellHeight); } const TQPixmap* pm = getSelectPixmap(); p->drawPixmap( indent, ( height() - pm->height() ) / 2, *pm ); _selectRect.setRect( indent, ( height() - pm->height() ) / 2, 12, 12 ); // now draw the item pixmap and text, if applicable int pixmapX = indent + 4 + 12; int pixmapY = (cellHeight - pixmap.height()) / 2; p->drawPixmap(pixmapX, pixmapY, pixmap); if (doText) { paintText(p, indent, cellHeight, cg, highlighted); } p->restore(); } void SelectableNode::paintText( TQPainter* p, int indent, int cellHeight, const TQColorGroup& cg, bool highlighted ) const { int textX = indent + 12 + 4 + pixmap.width() + 4; int textY = cellHeight - ((cellHeight - p->fontMetrics().ascent() - p->fontMetrics().leading()) / 2); if (highlighted) { paintHighlight(p, indent, cg, owner->hasFocus(), (TQt::GUIStyle)owner->style().styleHint(TQStyle::SH_GUIStyle)); // TQt3 doesn't make this easy ;) p->setPen(cg.base()); p->setBackgroundColor(cg.text()); } else { p->setPen(cg.text()); p->setBackgroundColor(cg.base()); } p->drawText(textX, textY, text); } int SelectableNode::width( int indent, const TQFontMetrics& fm ) const { int maxWidth = pixmap.width(); maxWidth += (4 + 12 + 4 + fm.width(text)); return maxWidth == 0 ? -1 : indent + maxWidth + 3; } TQRect SelectableNode::textBoundingRect(int indent) const { const TQFontMetrics& fm = owner->fontMetrics(); int cellHeight = height(fm); int rectX = indent + 12 + 4 + pixmap.width() + 3; int rectY = (cellHeight - fm.ascent() - fm.leading()) / 2 + 2; int rectW = fm.width(text) + 1; int rectH = fm.ascent() + fm.leading(); return TQRect(rectX, rectY, rectW, rectH); } bool SelectableNode::isType( int type ) { if ( type == SelectableNodeType ) { return TRUE; } else { return Node::isType( type ); } } bool SelectableNode::isSelected() { return _state == SelAll; } bool SelectableNode::hasSelectedChildren() { return _state == SelAll || _state == SelSome; } void SelectableNode::setSelected( bool select ) { doSetSelected( select ); if ( ( getParent() ) && ( getParent()->getParent() ) && ( ((Node*)getParent())->isType( SelectableNodeType ) ) ) { ((SelectableNode*)getParent())->doUpdateState(); } owner->repaint(); KDatMainWindow::getInstance()->configureUI( TapeManager::instance()->getMountedTape() ); } RangeableNode::RangeableNode( int type, const TQString & text, const TQPixmap& pixmap, int state ) : SelectableNode( type, text, pixmap, state ) { } bool RangeableNode::isType( int type ) { if ( type == RangeableNodeType ) { return TRUE; } else { return SelectableNode::isType( type ); } } MountedArchiveNode::MountedArchiveNode( Archive* archive ) : RangeableNode( MountedArchiveNodeType, archive->getName(), *ImageCache::instance()->getArchive(), SelNone ), _archive( archive ) { setDelayedExpanding( TRUE ); } Archive* MountedArchiveNode::getArchive() { return _archive; } const TQPtrList& MountedArchiveNode::getRanges() { return _archive->getRanges(); } bool MountedArchiveNode::validate() { bool changed = _archive->getName() != getText(); if ( changed ) { setText( _archive->getName() ); } return changed; } void MountedArchiveNode::setSelected( bool select ) { if ( select ) { // Deselect all other archives. Node* parent = (Node*)getParent(); for ( int i = parent->childCount() - 1; i >= 0; i-- ) { if ( parent->childAt( i ) != this ) { ((SelectableNode*)parent->childAt( i ))->setSelected( FALSE ); } } } SelectableNode::setSelected( select ); } bool MountedArchiveNode::isType( int type ) { if ( type == MountedArchiveNodeType ) { return TRUE; } else { return RangeableNode::isType( type ); } } void MountedArchiveNode::expanding( bool expand ) { expand = TRUE; if ( childCount() > 0 ) { // We already have the children added. return; } TQPtrListIterator f( _archive->getChildren() ); for ( ; f.current(); ++f ) { if ( f.current()->getName()[f.current()->getName().length()-1] == '/' ) { insertNode( new MountedTapeDirectoryNode( f.current(), _state == SelSome ? SelNone : _state ) ); } else { insertNode( new MountedTapeFileNode( f.current(), _state == SelSome ? SelNone : _state ) ); } } } void MountedArchiveNode::selected() { KDatMainWindow::getInstance()->showArchiveInfo( _archive ); } void MountedArchiveNode::popupMenu( const TQPoint& p ) { KDatMainWindow::getInstance()->popupMountedArchiveMenu( p ); } MountedTapeDirectoryNode::MountedTapeDirectoryNode( File* file, int state ) : RangeableNode( MountedTapeDirectoryNodeType, "", *ImageCache::instance()->getFolderClosed(), state ), _file( file ) { assert( _file > (File*)0x1 ); setDelayedExpanding( TRUE ); int len = _file->getName().length(); int idx1 = _file->getName().findRev( '/', len - 2 ); if ( idx1 < 0 ) { setText( _file->getName().left( len - 1 ) ); } else { setText( _file->getName().mid( idx1 + 1, len - idx1 - 2 ) ); } } File* MountedTapeDirectoryNode::getFile() { return _file; } TQString MountedTapeDirectoryNode::getFullPath() { if ( _fullPath.length() == 0 ) { _fullPath = getText() + "/"; for ( Node* parent = (Node*)getParent(); !parent->isType( MountedArchiveNodeType ); parent = (Node*)parent->getParent() ) { _fullPath.prepend( "/" ); _fullPath.prepend( parent->getText() ); } } return _fullPath; } const TQPtrList& MountedTapeDirectoryNode::getRanges() { return _file->getRanges(); } void MountedTapeDirectoryNode::setSelected( bool select ) { if ( select ) { // Deselect all other archives. Node* parent = (Node*)getParent(); Node* arcNode = 0; while ( !parent->isType( TapeDriveNodeType ) ) { if ( parent->isType( MountedArchiveNodeType ) ) { arcNode = parent; } parent = (Node*)parent->getParent(); } for ( int i = parent->childCount() - 1; i >= 0; i-- ) { if ( parent->childAt( i ) != arcNode ) { ((SelectableNode*)parent->childAt( i ))->setSelected( FALSE ); } } } SelectableNode::setSelected( select ); } bool MountedTapeDirectoryNode::isType( int type ) { if ( type == MountedTapeDirectoryNodeType ) { return TRUE; } else { return RangeableNode::isType( type ); } } void MountedTapeDirectoryNode::expanding( bool expand ) { expand = TRUE; if ( childCount() > 0 ) { // We already have the children added. return; } TQPtrListIterator f( _file->getChildren() ); for ( ; f.current(); ++f ) { if ( f.current()->getName()[f.current()->getName().length()-1] == '/' ) { insertNode( new MountedTapeDirectoryNode( f.current(), _state == SelSome ? SelNone : _state ) ); } else { insertNode( new MountedTapeFileNode( f.current(), _state == SelSome ? SelNone : _state ) ); } } } void MountedTapeDirectoryNode::expanded() { setPixmap( *ImageCache::instance()->getFolderOpen() ); } void MountedTapeDirectoryNode::collapsed() { setPixmap( *ImageCache::instance()->getFolderClosed() ); } void MountedTapeDirectoryNode::selected() { KDatMainWindow::getInstance()->showTapeFileInfo( _file ); } void MountedTapeDirectoryNode::popupMenu( const TQPoint& p ) { KDatMainWindow::getInstance()->popupMountedTapeFileMenu( p ); } MountedTapeFileNode::MountedTapeFileNode( File* file, int state ) : RangeableNode( MountedTapeFileNodeType, file->getName(), *ImageCache::instance()->getFile(), state ), _file( file ) { int len = _file->getName().length(); int idx1 = _file->getName().findRev( '/', len - 1 ); if ( idx1 < 0 ) { setText( _file->getName().left( len ) ); } else { setText( _file->getName().mid( idx1 + 1, len - idx1 - 1 ) ); } } File* MountedTapeFileNode::getFile() { return _file; } TQString MountedTapeFileNode::getFullPath() { if ( _fullPath.length() == 0 ) { _fullPath = getText(); for ( Node* parent = (Node*)getParent(); !parent->isType( MountedArchiveNodeType ); parent = (Node*)parent->getParent() ) { _fullPath.prepend( "/" ); _fullPath.prepend( parent->getText() ); } } return _fullPath; } const TQPtrList& MountedTapeFileNode::getRanges() { return _file->getRanges(); } void MountedTapeFileNode::setSelected( bool select ) { if ( select ) { // Deselect all other archives. Node* parent = (Node*)getParent(); Node* arcNode = 0; while ( !parent->isType( TapeDriveNodeType ) ) { if ( parent->isType( MountedArchiveNodeType ) ) { arcNode = parent; } parent = (Node*)parent->getParent(); } for ( int i = parent->childCount() - 1; i >= 0; i-- ) { if ( parent->childAt( i ) != arcNode ) { ((SelectableNode*)parent->childAt( i ))->setSelected( FALSE ); } } } SelectableNode::setSelected( select ); } bool MountedTapeFileNode::isType( int type ) { if ( type == MountedTapeFileNodeType ) { return TRUE; } else { return RangeableNode::isType( type ); } } void MountedTapeFileNode::selected() { KDatMainWindow::getInstance()->showTapeFileInfo( _file ); } void MountedTapeFileNode::popupMenu( const TQPoint& p ) { KDatMainWindow::getInstance()->popupMountedTapeFileMenu( p ); } ArchiveableNode::ArchiveableNode( int type, const TQString & text, const TQPixmap& pixmap, int state ) : SelectableNode( type, text, pixmap, state ) { } bool ArchiveableNode::isType( int type ) { if ( type == ArchiveableNodeType ) { return TRUE; } else { return SelectableNode::isType( type ); } } RootNode::RootNode() : ArchiveableNode( RootNodeType, "/", *ImageCache::instance()->getFolderClosed(), SelNone ), _mtime( -1 ) { setDelayedExpanding( TRUE ); } TQString RootNode::getFullPath() { if ( _fullPath.length() == 0 ) { _fullPath = "/"; } return _fullPath; } bool RootNode::isType( int type ) { if ( type == RootNodeType ) { return TRUE; } else { return ArchiveableNode::isType( type ); } } void RootNode::expanding( bool expand ) { expand = TRUE; // If we already have some children, check to see if the directory has been modified. if ( childCount() > 0 ) { struct stat statinfo; if ( stat( "/", &statinfo ) < 0 ) { printf( "Can't stat '/'\n" ); expand = FALSE; return; } if ( statinfo.st_mtime == _mtime ) { // Directory has not been modified. return; } _mtime = statinfo.st_mtime; // Remove all the children. Node* n; while ( ( n = (Node*)getChild() ) ) { removeChild( n ); delete n; } } else { struct stat statinfo; if ( stat( "/", &statinfo ) < 0 ) { printf( "Can't stat '/'\n" ); expand = FALSE; return; } _mtime = statinfo.st_mtime; } TQDir dir( "/" ); if ( dir.exists() ) { // Make sure we can read the directory. if ( !dir.isReadable() ) { //KMsgBox::message( this, i18n( "KDat: Error" ), i18n( "The directory cannot be read." ), KMsgBox::EXCLAMATION ); return; } // Fill in the child's children. const TQFileInfoList* list = dir.entryInfoList( TQDir::Hidden | TQDir::Files | TQDir::Dirs, TQDir::Name | TQDir::DirsFirst ); if ( list ) { TQFileInfoListIterator it( *list ); for ( ; it.current(); ++it ) { if ( ( it.current()->fileName() != "." ) && ( it.current()->fileName() != ".." ) ) { if ( it.current()->isDir() ) { appendChild( new DirectoryNode( it.current()->fileName(), _state == SelSome ? SelNone : _state ) ); } else { appendChild( new FileNode( it.current()->fileName(), _state == SelSome ? SelNone : _state ) ); } } } } } } void RootNode::expanded() { setPixmap( *ImageCache::instance()->getFolderOpen() ); } void RootNode::collapsed() { setPixmap( *ImageCache::instance()->getFolderClosed() ); } void RootNode::selected() { KDatMainWindow::getInstance()->showFileInfo( "/" ); } void RootNode::popupMenu( const TQPoint& p ) { KDatMainWindow::getInstance()->popupLocalFileMenu( p ); } DirectoryNode::DirectoryNode( const TQString & text, int state ) : ArchiveableNode( DirectoryNodeType, text, *ImageCache::instance()->getFolderClosed(), state ), _mtime( -1 ) { setDelayedExpanding( TRUE ); } TQString DirectoryNode::getFullPath() { if ( _fullPath.isEmpty() ) { _fullPath = ((ArchiveableNode*)getParent())->getFullPath() + getText() + "/"; } return _fullPath; } bool DirectoryNode::isType( int type ) { if ( type == DirectoryNodeType ) { return TRUE; } else { return ArchiveableNode::isType( type ); } } void DirectoryNode::expanding( bool expand ) { expand = TRUE; // Construct the full path. TQString path; Node* n; for ( n = this; n->getType() != RootNodeType; n = (Node*)n->getParent() ) { path.prepend( "/" ); path.prepend( n->getText() ); } path.prepend( "/" ); // If we already have some children, check to see if the directory has been modified. if ( childCount() > 0 ) { struct stat statinfo; if ( stat( TQFile::encodeName(path), &statinfo ) < 0 ) { kdError() << "Can't stat " << path << endl; expand = FALSE; return; } if ( statinfo.st_mtime == _mtime ) { // Directory has not been modified. return; } _mtime = statinfo.st_mtime; // Remove all the children. Node* n; while ( ( n = (Node*)getChild() ) ) { removeChild( n ); delete n; } } else { struct stat statinfo; if ( stat( TQFile::encodeName(path), &statinfo ) < 0 ) { kdError() << "Can't stat " << path << endl; expand = FALSE; return; } _mtime = statinfo.st_mtime; } TQDir dir( path ); if ( dir.exists() ) { // Make sure we can read the directory. if ( !dir.isReadable() ) { //KMsgBox::message( this, i18n( "KDat: Error" ), i18n( "The directory cannot be read." ), KMsgBox::EXCLAMATION ); return; } // Fill in the child's children. const TQFileInfoList* list = dir.entryInfoList( TQDir::Hidden | TQDir::Files | TQDir::Dirs, TQDir::Name | TQDir::DirsFirst ); if ( list ) { TQFileInfoListIterator it( *list ); for ( ; it.current(); ++it ) { if ( ( it.current()->fileName() != "." ) && ( it.current()->fileName() != ".." ) ) { if ( it.current()->isDir() ) { appendChild( new DirectoryNode( it.current()->fileName(), _state == SelSome ? SelNone : _state ) ); } else { appendChild( new FileNode( it.current()->fileName(), _state == SelSome ? SelNone : _state ) ); } } } } } } void DirectoryNode::expanded() { setPixmap( *ImageCache::instance()->getFolderOpen() ); } void DirectoryNode::collapsed() { setPixmap( *ImageCache::instance()->getFolderClosed() ); } void DirectoryNode::selected() { // Construct the full path. TQString path; Node* n; for ( n = this; n->getType() != RootNodeType; n = (Node*)n->getParent() ) { path.prepend( "/" ); path.prepend( n->getText() ); } path.prepend( "/" ); path = path.left( path.length() - 1 ); KDatMainWindow::getInstance()->showFileInfo( path ); } void DirectoryNode::popupMenu( const TQPoint& p ) { KDatMainWindow::getInstance()->popupLocalFileMenu( p ); } FileNode::FileNode( const TQString & text, int state ) : ArchiveableNode( FileNodeType, text, *ImageCache::instance()->getFile(), state ) { } TQString FileNode::getFullPath() { if ( _fullPath.isEmpty() ) { _fullPath = ((ArchiveableNode*)getParent())->getFullPath() + getText(); } return _fullPath; } bool FileNode::isType( int type ) { if ( type == FileNodeType ) { return TRUE; } else { return ArchiveableNode::isType( type ); } } void FileNode::selected() { // Construct the full path. TQString path; Node* n; for ( n = this; n->getType() != RootNodeType; n = (Node*)n->getParent() ) { path.prepend( "/" ); path.prepend( n->getText() ); } path.prepend( "/" ); path = path.left( path.length() - 1 ); KDatMainWindow::getInstance()->showFileInfo( path ); } void FileNode::popupMenu( const TQPoint& p ) { KDatMainWindow::getInstance()->popupLocalFileMenu( p ); } TapeDriveNode::TapeDriveNode() : Node( TapeDriveNodeType, i18n( "" ), *ImageCache::instance()->getTapeUnmounted() ) { setDelayedExpanding( TRUE ); connect( TapeManager::instance(), TQT_SIGNAL( sigTapeMounted() ) , this, TQT_SLOT( slotTapeMounted() ) ); connect( TapeManager::instance(), TQT_SIGNAL( sigTapeUnmounted() ) , this, TQT_SLOT( slotTapeUnmounted() ) ); connect( TapeManager::instance(), TQT_SIGNAL( sigTapeModified( Tape* ) ), this, TQT_SLOT( slotTapeModified( Tape* ) ) ); } bool TapeDriveNode::isType( int type ) { if ( type == TapeDriveNodeType ) { return TRUE; } else { return Node::isType( type ); } } void TapeDriveNode::expanding( bool expand ) { if ( !TapeManager::instance()->getMountedTape() ) { expand = FALSE; return; } expand = TRUE; if ( childCount() > 0 ) { // We already have the children added return; } TQPtrListIterator f( TapeManager::instance()->getMountedTape()->getChildren() ); for ( ; f.current(); ++f ) { insertNode( new MountedArchiveNode( f.current() ) ); } } void TapeDriveNode::selected() { if ( TapeManager::instance()->getMountedTape() ) { KDatMainWindow::getInstance()->showTapeInfo( TapeManager::instance()->getMountedTape() ); } else { KDatMainWindow::getInstance()->hideInfo(); } } void TapeDriveNode::popupMenu( const TQPoint& p ) { KDatMainWindow::getInstance()->popupTapeDriveMenu( p ); } void TapeDriveNode::slotTapeMounted() { setPixmap( *ImageCache::instance()->getTapeMounted() ); setText( TapeManager::instance()->getMountedTape()->getName() ); if ( this == owner->getCurrentItem() ) { KDatMainWindow::getInstance()->showTapeInfo( TapeManager::instance()->getMountedTape() ); } if ( isExpanded() ) { bool dummy = TRUE; expanding( dummy ); } } void TapeDriveNode::slotTapeUnmounted() { setPixmap( *ImageCache::instance()->getTapeUnmounted() ); setText( i18n( "" ) ); // Remove all the children. Node* n; while ( ( n = (Node*)getChild() ) ) { Node::removeChild( n ); delete n; } if ( this == owner->getCurrentItem() ) { KDatMainWindow::getInstance()->hideInfo(); } } void TapeDriveNode::slotTapeModified( Tape* tape ) { if ( TapeManager::instance()->getMountedTape() != tape ) { return; } setText( tape->getName() ); if ( owner->getCurrentItem() == this ) { KDatMainWindow::getInstance()->showTapeInfo( TapeManager::instance()->getMountedTape() ); } if ( ( childCount() == 0 ) && ( !isExpanded() ) ) { return; } // Add/update existing archives. TQPtrListIterator i( tape->getChildren() ); MountedArchiveNode* n; for ( ; i.current(); ++i ) { n = findArchiveNode( i.current() ); if ( n ) { if ( n->validate() ) { bool select = ( owner->getCurrentItem() == n ); Node::removeChild( n ); insertNode( n ); if ( select ) { owner->setCurrentItem( owner->itemRow( n ) ); } } } else { insertNode( new MountedArchiveNode( i.current() ) ); } } // Remove deleted archives. Archive* a; for ( uint j = 0; j < childCount(); ) { a = ((MountedArchiveNode*)childAt( j ))->getArchive(); for ( i.toFirst(); i.current(); ++i ) { if ( i.current() == a ) { break; } } if ( !i.current() ) { Node::removeChild( childAt( j ) ); } else { j++; } } } MountedArchiveNode* TapeDriveNode::findArchiveNode( Archive* archive ) { MountedArchiveNode* n = 0; for ( uint i = 0; i < childCount(); i++ ) { if ( ((MountedArchiveNode*)childAt( i ))->getArchive() == archive ) { n = (MountedArchiveNode*)childAt( i ); break; } } return n; } TapeIndexRootNode::TapeIndexRootNode() : Node( TapeIndexRootNodeType, i18n( "Tape Indexes" ), *ImageCache::instance()->getFolderClosed() ) { setDelayedExpanding( TRUE ); connect( TapeManager::instance(), TQT_SIGNAL( sigTapeAdded( Tape* ) ) , this, TQT_SLOT( slotTapeAdded( Tape* ) ) ); connect( TapeManager::instance(), TQT_SIGNAL( sigTapeRemoved( Tape* ) ) , this, TQT_SLOT( slotTapeRemoved( Tape* ) ) ); connect( TapeManager::instance(), TQT_SIGNAL( sigTapeModified( Tape* ) ), this, TQT_SLOT( slotTapeModified( Tape* ) ) ); } bool TapeIndexRootNode::isType( int type ) { if ( type == TapeIndexRootNodeType ) { return TRUE; } else { return Node::isType( type ); } } void TapeIndexRootNode::expanding( bool expand ) { expand = TRUE; if ( childCount() > 0 ) { return; } TQStringList list = TapeManager::instance()->getTapeIDs(); TQStringList::Iterator i = list.begin(); for ( ; i != list.end(); ++i ) { Tape* tape = TapeManager::instance()->findTape( *i ); if ( tape ) { insertNode( new TapeNode( tape ) ); } } } void TapeIndexRootNode::expanded() { setPixmap( *ImageCache::instance()->getFolderOpen() ); } void TapeIndexRootNode::collapsed() { setPixmap( *ImageCache::instance()->getFolderClosed() ); } void TapeIndexRootNode::slotTapeAdded( Tape* tape ) { if ( ( childCount() > 0 ) || ( isExpanded() ) ) { insertNode( new TapeNode( tape ) ); } } void TapeIndexRootNode::slotTapeRemoved( Tape* tape ) { if ( ( childCount() > 0 ) || ( isExpanded() ) ) { Node* n = findTapeNode( tape ); if ( n ) { Node::removeChild( n ); delete n; } } } void TapeIndexRootNode::slotTapeModified( Tape* tape ) { TapeNode* n = findTapeNode( tape ); if ( !n ) { return; } if ( n->validate() ) { bool select = ( owner->getCurrentItem() == n ); Node::removeChild( n ); insertNode( n ); if ( select ) { owner->setCurrentItem( owner->itemRow( n ) ); } } } TapeNode* TapeIndexRootNode::findTapeNode( Tape* tape ) { TapeNode* n = 0; for ( uint i = 0; i < childCount(); i++ ) { n = (TapeNode*)childAt( i ); if ( n->getTape() == tape ) { return n; } } return 0; } BackupProfileNode::BackupProfileNode( BackupProfile* backupProfile ) : Node( BackupProfileNodeType, backupProfile->getName(), *ImageCache::instance()->getFile() ), _backupProfile( backupProfile ) { } BackupProfile* BackupProfileNode::getBackupProfile() { return _backupProfile; } bool BackupProfileNode::validate() { bool changed = _backupProfile->getName() != getText(); if ( changed ) { setText( _backupProfile->getName() ); } return changed; } bool BackupProfileNode::isType( int type ) { if ( type == BackupProfileNodeType ) { return TRUE; } else { return Node::isType( type ); } } void BackupProfileNode::selected() { KDatMainWindow::getInstance()->showBackupProfileInfo( _backupProfile ); } void BackupProfileNode::popupMenu( const TQPoint& p ) { KDatMainWindow::getInstance()->popupBackupProfileMenu( p ); } BackupProfileRootNode::BackupProfileRootNode() : Node( BackupProfileRootNodeType, i18n( "Backup Profiles" ), *ImageCache::instance()->getFolderClosed() ) { setDelayedExpanding( TRUE ); connect( BackupProfileManager::instance(), TQT_SIGNAL( sigBackupProfileAdded( BackupProfile* ) ) , this, TQT_SLOT( slotBackupProfileAdded( BackupProfile* ) ) ); connect( BackupProfileManager::instance(), TQT_SIGNAL( sigBackupProfileRemoved( BackupProfile* ) ) , this, TQT_SLOT( slotBackupProfileRemoved( BackupProfile* ) ) ); connect( BackupProfileManager::instance(), TQT_SIGNAL( sigBackupProfileModified( BackupProfile* ) ), this, TQT_SLOT( slotBackupProfileModified( BackupProfile* ) ) ); } void BackupProfileRootNode::setSelected( BackupProfile* pBackupProfile ) { setExpanded( TRUE ); bool dummy = TRUE; expanding( dummy ); expanded(); BackupProfileNode* pNode = findBackupProfileNode( pBackupProfile ); if ( pNode ) { owner->setCurrentItem( owner->itemRow( pNode ) ); pNode->selected(); } KDatMainWindow::getInstance()->configureUI( TapeManager::instance()->getMountedTape() ); } bool BackupProfileRootNode::isType( int type ) { if ( type == BackupProfileRootNodeType ) { return TRUE; } else { return Node::isType( type ); } } void BackupProfileRootNode::expanding( bool expand ) { expand = TRUE; if ( childCount() > 0 ) { return; } TQStringList list = BackupProfileManager::instance()->getBackupProfileNames(); TQStringList::Iterator i = list.begin(); for ( ; i != list.end(); ++i ) { BackupProfile* backupProfile = BackupProfileManager::instance()->findBackupProfile( *i ); if ( backupProfile ) { insertNode( new BackupProfileNode( backupProfile ) ); } } } void BackupProfileRootNode::expanded() { setPixmap( *ImageCache::instance()->getFolderOpen() ); } void BackupProfileRootNode::collapsed() { setPixmap( *ImageCache::instance()->getFolderClosed() ); } void BackupProfileRootNode::popupMenu( const TQPoint& p ) { KDatMainWindow::getInstance()->popupBackupProfileRootMenu( p ); } void BackupProfileRootNode::slotBackupProfileAdded( BackupProfile* backupProfile ) { if ( ( childCount() > 0 ) || ( isExpanded() ) ) { insertNode( new BackupProfileNode( backupProfile ) ); } } void BackupProfileRootNode::slotBackupProfileRemoved( BackupProfile* backupProfile ) { if ( ( childCount() > 0 ) || ( isExpanded() ) ) { Node* n = findBackupProfileNode( backupProfile ); assert( n ); Node::removeChild( n ); delete n; } } void BackupProfileRootNode::slotBackupProfileModified( BackupProfile* backupProfile ) { BackupProfileNode* n = findBackupProfileNode( backupProfile ); if ( !n ) { return; } if ( n->validate() ) { bool select = ( owner->getCurrentItem() == n ); Node::removeChild( n ); insertNode( n ); if ( select ) { owner->setCurrentItem( owner->itemRow( n ) ); } } } BackupProfileNode* BackupProfileRootNode::findBackupProfileNode( BackupProfile* backupProfile ) { BackupProfileNode* n = 0; for ( uint i = 0; i < childCount(); i++ ) { n = (BackupProfileNode*)childAt( i ); if ( n->getBackupProfile() == backupProfile ) { return n; } } return 0; }