00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #define DEVELOPERS_VERSION
00013 #include "advancedfm.h"
00014
00015 #include <opie2/odebug.h>
00016 #include <opie2/oresource.h>
00017 #include <opie2/ostorageinfo.h>
00018
00019 #include <qpe/qpeapplication.h>
00020 #include <qpe/config.h>
00021 #include <qpe/mimetype.h>
00022 #include <qpe/applnk.h>
00023 #include <qpe/menubutton.h>
00024
00025 #include <qcombobox.h>
00026 #include <qpopupmenu.h>
00027 #include <qlistview.h>
00028 #include <qmessagebox.h>
00029 #include <qlineedit.h>
00030
00031
00032 #include <sys/stat.h>
00033 #include <time.h>
00034 #include <dirent.h>
00035 #include <fcntl.h>
00036 #include <sys/vfs.h>
00037 #include <mntent.h>
00038
00039 using namespace Opie::Ui;
00040
00041 AdvancedFm::AdvancedFm(QWidget *,const char*, WFlags )
00042 : QMainWindow( ) {
00043 init();
00044 renameBox = 0;
00045 whichTab = 1;
00046 unknownXpm = Opie::Core::OResource::loadImage("UnknownDocument", Opie::Core::OResource::SmallIcon);
00047
00048 initConnections();
00049 rePopulate();
00050 channel = new QCopChannel( "QPE/Application/advancedfm", this );
00051 connect(channel,SIGNAL(received(const QCString&,const QByteArray&)),this,SLOT(qcopReceive(const QCString&,const QByteArray&)));
00052 switchToLocalTab();
00053 }
00054
00055 AdvancedFm::~AdvancedFm() {
00056 }
00057
00058
00059 void AdvancedFm::cleanUp() {
00060 QString sfile=QDir::homeDirPath();
00061 if(sfile.right(1) != "/")
00062 sfile+="/._temp";
00063 else
00064 sfile+="._temp";
00065 QFile file( sfile);
00066 if(file.exists())
00067 file.remove();
00068 }
00069
00070 void AdvancedFm::tabChanged(QWidget *wd) {
00071 if(wd == tab) {
00072 whichTab = 1;
00073 viewMenu->setItemChecked(viewMenu->idAt(0), true);
00074 viewMenu->setItemChecked(viewMenu->idAt(1), false);
00075
00076 }
00077
00078 else if(wd == tab_2) {
00079 whichTab = 2;
00080 viewMenu->setItemChecked(viewMenu->idAt(0), false);
00081 viewMenu->setItemChecked(viewMenu->idAt(1), true);
00082
00083 }
00084 qApp->processEvents();
00085 QString path = CurrentDir()->canonicalPath();
00086
00087 chdir( path.latin1());
00088 currentPathCombo->lineEdit()->setText(path);
00089 }
00090
00091
00092 void AdvancedFm::populateView() {
00093
00094 QPixmap pm;
00095 QListView *thisView = CurrentView();
00096 QDir *thisDir = CurrentDir();
00097 QString path = thisDir->canonicalPath();
00098
00099 thisView->clear();
00100 thisDir->setSorting( QDir::DirsFirst);
00101 thisDir->setMatchAllDirs(TRUE);
00102 thisDir->setNameFilter(filterStr);
00103 QString fileL, fileS, fileDate;
00104
00105 QString fs = getFileSystemType((const QString &) path);
00106 setCaption(tr("AdvancedFm :: ")+fs+" :: "
00107 +checkDiskSpace((const QString &) path)+ tr(" kB free") );
00108 bool isDir = FALSE;
00109
00110 const QFileInfoList *list = thisDir->entryInfoList( );
00111 QFileInfoListIterator it(*list);
00112 QFileInfo *fi;
00113 while ( (fi=it.current()) ) {
00114 if (fi->isSymLink() ) {
00115 QString symLink = fi->readLink();
00116 QFileInfo sym( symLink);
00117 fileS.sprintf( "%10i", sym.size() );
00118 fileL = fi->fileName() +" -> " + sym.filePath().data();
00119 fileDate = sym.lastModified().toString();
00120 } else {
00121 fileS.sprintf( "%10i", fi->size() );
00122 fileL = fi->fileName();
00123 fileDate= fi->lastModified().toString();
00124 if( QDir(QDir::cleanDirPath( path +"/"+fileL)).exists() ) {
00125
00126 fileL += "/";
00127 isDir=TRUE;
00128 }
00129 }
00130 QFileInfo fileInfo( path + "/" + fileL);
00131
00132 if(fileL !="./" && fi->exists()) {
00133 item = new QListViewItem( thisView, fileL, fileS , fileDate);
00134
00135 if(isDir || fileL.find("/",0,TRUE) != -1) {
00136
00137 if( !QDir( fi->filePath() ).isReadable())
00138 pm = Opie::Core::OResource::loadPixmap( "lockedfolder", Opie::Core::OResource::SmallIcon );
00139 else
00140 pm = Opie::Core::OResource::loadPixmap( "folder", Opie::Core::OResource::SmallIcon );
00141 }
00142 else if ( fs == "vfat" && fileInfo.filePath().contains("/bin") ) {
00143 pm = Opie::Core::OResource::loadPixmap( "exec", Opie::Core::OResource::SmallIcon );
00144 }
00145 else if( (fileInfo.permission( QFileInfo::ExeUser)
00146 | fileInfo.permission( QFileInfo::ExeGroup)
00147 | fileInfo.permission( QFileInfo::ExeOther)) && fs != "vfat" ) {
00148 pm = Opie::Core::OResource::loadPixmap( "exec", Opie::Core::OResource::SmallIcon );
00149 }
00150 else if( !fi->isReadable() ) {
00151 pm = Opie::Core::OResource::loadPixmap( "locked", Opie::Core::OResource::SmallIcon );
00152 }
00153 else {
00154 MimeType mt(fi->filePath());
00155 pm=mt.pixmap();
00156 if(pm.isNull()) {
00157 pm = unknownXpm;
00158 }
00159 }
00160 if( fi->isSymLink() || fileL.find("->",0,TRUE) != -1) {
00161
00162 pm = Opie::Core::OResource::loadPixmap( "advancedfm/symlink", Opie::Core::OResource::SmallIcon );
00163 }
00164 item->setPixmap( 0, pm );
00165
00166 }
00167 isDir=FALSE;
00168 ++it;
00169 }
00170
00171 if( path.find("dev",0,TRUE) != -1) {
00172 struct stat buf;
00173 dev_t devT;
00174 DIR *dir;
00175 struct dirent *mydirent;
00176
00177 if((dir = opendir( path.latin1())) != NULL)
00178 while ((mydirent = readdir(dir)) != NULL) {
00179 lstat( mydirent->d_name, &buf);
00180
00181 fileL.sprintf("%s", mydirent->d_name);
00182 devT = buf.st_dev;
00183 fileS.sprintf("%d, %d", (int) ( devT >>8) &0xFF, (int)devT &0xFF);
00184 fileDate.sprintf("%s", ctime( &buf.st_mtime));
00185 if( fileL.find(".") == -1 ) {
00186 item= new QListViewItem( thisView, fileL, fileS, fileDate);
00187 pm = unknownXpm;
00188 item->setPixmap( 0,pm);
00189 }
00190 }
00191
00192 closedir(dir);
00193 }
00194
00195 thisView->setSorting( 3,FALSE);
00196 fillCombo( (const QString &) path );
00197 }
00198
00199 void AdvancedFm::rePopulate() {
00200
00201 populateView();
00202 setOtherTabCurrent();
00203 populateView();
00204 }
00205
00206 void AdvancedFm::ListClicked(QListViewItem *selectedItem) {
00207 if(selectedItem) {
00208 QString strItem=selectedItem->text(0);
00209
00210 QString strSize=selectedItem->text(1);
00211 strSize=strSize.stripWhiteSpace();
00212 bool isDirectory = false;
00213 QString strItem2;
00214
00215 if(strItem.find("@",0,TRUE) !=-1 || strItem.find("->",0,TRUE) !=-1 ) {
00216 strItem2 = dealWithSymName((const QString&)strItem);
00217 if(QDir(strItem2).exists() )
00218 strItem = strItem2;
00219 }
00220
00221 if( strItem.find(". .",0,TRUE) && strItem.find("/",0,TRUE)!=-1 ) {
00222
00223 if(QDir(strItem).exists())
00224 isDirectory = true;
00225 }
00226
00227 if( isDirectory ) {
00228 CurrentDir()->cd( strItem, TRUE);
00229 populateView();
00230 CurrentView()->ensureItemVisible( CurrentView()->firstChild());
00231 }
00232 chdir( strItem.latin1());
00233 }
00234 }
00235
00236 void AdvancedFm::ListPressed( int mouse, QListViewItem *item, const QPoint& , int ) {
00237 Q_UNUSED(item);
00238 switch (mouse) {
00239 case 1:
00240 {
00241 if(renameBox != 0 ) {
00242 cancelRename();
00243 }
00244 }
00245 break;
00246
00247
00248
00249 };
00250 }
00251
00252
00253 void AdvancedFm::refreshCurrentTab() {
00254 populateView();
00255
00256 }
00257
00258 void AdvancedFm::switchToLocalTab() {
00259 TabWidget->setCurrentWidget(tab);
00260 Local_View->setFocus();
00261
00262 }
00263
00264 void AdvancedFm::switchToRemoteTab() {
00265 TabWidget->setCurrentWidget(tab_2);
00266 Remote_View->setFocus();
00267
00268 }
00269
00270 void AdvancedFm::currentPathComboChanged() {
00271 QString pDir = currentPathCombo->lineEdit()->text();
00272 if(QDir(pDir).exists()) {
00273 CurrentDir()->setPath(pDir );
00274 populateView();
00275 } else {
00276 QMessageBox::message(tr("Note"),tr("<p>%1 does not exist</p>").arg(pDir));
00277 }
00278 }
00279
00280 void AdvancedFm::fillCombo(const QString ¤tPath) {
00281
00282 if ( TabWidget->currentWidget() == tab) {
00283
00284 currentPathCombo->lineEdit()->setText( currentPath);
00285 if( localDirPathStringList.grep( currentPath,TRUE).isEmpty() ) {
00286 currentPathCombo->clear();
00287 localDirPathStringList.prepend( currentPath );
00288 currentPathCombo->insertStringList( localDirPathStringList,-1);
00289 }
00290 } else {
00291 currentPathCombo->lineEdit()->setText( currentPath);
00292 if( remoteDirPathStringList.grep( currentPath,TRUE).isEmpty() ) {
00293 currentPathCombo->clear();
00294 remoteDirPathStringList.prepend( currentPath );
00295 currentPathCombo->insertStringList( remoteDirPathStringList,-1);
00296 }
00297 }
00298 }
00299
00300 QStringList AdvancedFm::getPath() {
00301 QStringList strList;
00302 QListView *thisView=CurrentView();
00303 QList<QListViewItem> * getSelectedItems( QListView * thisView );
00304 QListViewItemIterator it( thisView );
00305 for ( ; it.current(); ++it ) {
00306 if ( it.current()->isSelected() ) {
00307 strList << it.current()->text(0);
00308
00309 }
00310 }
00311 return strList;
00312 }
00313
00314 void AdvancedFm::changeTo(const QString &dir) {
00315 chdir( dir.latin1());
00316 CurrentDir()->cd(dir, TRUE);
00317 populateView();
00318 update();
00319 }
00320
00321 void AdvancedFm::homeButtonPushed() {
00322 changeTo(QDir::homeDirPath());
00323 }
00324
00325 void AdvancedFm::docButtonPushed() {
00326 changeTo(QPEApplication::documentDir());
00327 }
00328
00329 void AdvancedFm::SDButtonPushed() {
00330 Opie::Core::OStorageInfo info;
00331 if(StorageInfo::hasSd() ) {
00332 changeTo(info.sdPath());
00333 }
00334 else if(StorageInfo::hasMmc()) {
00335 changeTo(info.mmcPath());
00336 }
00337 }
00338
00339 void AdvancedFm::CFButtonPushed() {
00340 Opie::Core::OStorageInfo info;
00341 changeTo(info.cfPath());
00342 }
00343
00344 void AdvancedFm::QPEButtonPushed() {
00345 changeTo(QPEApplication::qpeDir());
00346 }
00347
00348 void AdvancedFm::doAbout() {
00349 QMessageBox::message("AdvancedFm",tr("<P>Advanced FileManager is copyright 2002-2003 by L.J.Potter<llornkcor@handhelds.org> and is licensed by the GPL</P>"));
00350 }
00351
00352 void AdvancedFm::keyPressEvent( QKeyEvent *e) {
00353 Q_UNUSED(e);
00354 }
00355
00356 void AdvancedFm::keyReleaseEvent( QKeyEvent *e) {
00357
00358
00359
00360 if( currentPathCombo->lineEdit()->hasFocus()) {
00361
00362 }
00363
00364 else if( e->key() == Key_Left )
00365 upDir();
00366 else if( e->key() == Key_Return || e->key() == Key_Enter)
00367 navigateToSelected();
00368 else if( e->key() == Key_Tab)
00369 setOtherTabCurrent();
00370 else if( e->key() == Key_Delete )
00371 del();
00372 else
00373 e->accept();
00374
00375 }
00376
00377
00378 void AdvancedFm::parsetab(const QString &fileName) {
00379
00380 fileSystemTypeList.clear();
00381 fsList.clear();
00382 struct mntent *me;
00383 FILE *mntfp = setmntent( fileName.latin1(), "r" );
00384 if ( mntfp ) {
00385 while ( (me = getmntent( mntfp )) != 0 ) {
00386 QString deviceName = me->mnt_fsname;
00387 QString filesystemType = me->mnt_type;
00388 QString mountDir = me->mnt_dir;
00389 if(deviceName != "none") {
00390 if( fsList.contains(filesystemType) == 0
00391 & filesystemType.find("proc",0,TRUE) == -1
00392 & filesystemType.find("cramfs",0,TRUE) == -1
00393 & filesystemType.find("auto",0,TRUE) == -1)
00394 fsList << filesystemType;
00395 fileSystemTypeList << mountDir+"::"+filesystemType;
00396 }
00397 }
00398 }
00399 endmntent( mntfp );
00400 }
00401
00402 QString AdvancedFm::getFileSystemType(const QString ¤tText) {
00403 parsetab("/etc/mtab");
00404 QString current = currentText;
00405 QString baseFs;
00406 for ( QStringList::Iterator it = fileSystemTypeList.begin(); it != fileSystemTypeList.end(); ++it ) {
00407 QString temp = (*it);
00408 QString path = temp.left(temp.find("::",0,TRUE) );
00409 path = path.right( path.length()-1);
00410 if(path.isEmpty()) baseFs = temp.right( temp.length() - temp.find("::",0,TRUE) - 2);
00411 if( current.find( path,0,TRUE) != -1 && !path.isEmpty()) {
00412 return temp.right( temp.length() - temp.find("::",0,TRUE) - 2);
00413 }
00414 }
00415 return baseFs;
00416 }
00417
00418 QString AdvancedFm::getDiskSpace( const QString &path) {
00419 struct statfs fss;
00420 if ( !statfs( path.latin1(), &fss ) ) {
00421 int blkSize = fss.f_bsize;
00422
00423 int availBlks = fss.f_bavail;
00424
00425 long mult = blkSize / 1024;
00426 long div = 1024 / blkSize;
00427 if ( !mult ) mult = 1;
00428 if ( !div ) div = 1;
00429
00430 return QString::number(availBlks * mult / div);
00431 }
00432 return "";
00433 }
00434
00435
00436 void AdvancedFm::showFileMenu() {
00437 QString curApp;
00438 curApp = CurrentView()->currentItem()->text(0);
00439
00440 MimeType mt(curApp);
00441 const AppLnk* app = mt.application();
00442 QFile fi(curApp);
00443 QPopupMenu *m = new QPopupMenu(0);
00444 QPopupMenu *n = new QPopupMenu(0);
00445
00446 m->insertItem(tr("Show Hidden Files"),this,SLOT(showHidden()));
00447
00448 if ( QFileInfo(fi).isDir()) {
00449 m->insertSeparator();
00450 m->insertItem(tr("Change Directory"),this,SLOT(doDirChange()));
00451 } else {
00452
00453 if (app)
00454 m->insertItem(app->pixmap(),tr("Open in " + app->name()),this,SLOT(runThis()));
00455 else if(QFileInfo(fi).isExecutable() )
00456 m->insertItem(tr("Execute"),this,SLOT(runThis()));
00457 m->insertItem( Opie::Core::OResource::loadPixmap( "txt", Opie::Core::OResource::SmallIcon ),
00458 tr("Open as text"),this,SLOT(runText()));
00459 }
00460
00461 m->insertItem(tr("Actions"),n);
00462 n->insertItem(tr("Make Directory"),this,SLOT(makeDir()));
00463
00464 n->insertItem(tr("Make Symlink"),this,SLOT(mkSym()));
00465
00466 n->insertSeparator();
00467 n->insertItem(tr("Rename"),this,SLOT(renameIt()));
00468
00469 n->insertItem(tr("Copy"),this,SLOT(copyTimer()));
00470 n->insertItem(tr("Copy As"),this,SLOT(copyAsTimer()));
00471 n->insertItem(tr("Copy Same Dir"),this,SLOT(copySameDirTimer()));
00472 n->insertItem(tr("Move"),this,SLOT(moveTimer()));
00473
00474 n->insertSeparator();
00475 n->insertItem(tr("Delete"),this,SLOT(doDelete()));
00476 m->insertItem(tr("Add To Documents"),this,SLOT(addToDocs()));
00477
00478 m->insertItem(tr("Run Command"),this,SLOT(runCommand()));
00479 m->insertItem(tr("File Info"),this,SLOT(fileStatus()));
00480
00481 m->insertSeparator();
00482 m->insertItem(tr("Set Permissions"),this,SLOT(filePerms()));
00483
00484 #if defined(QT_QWS_OPIE)
00485 m->insertItem(tr("Properties"),this,SLOT(doProperties()));
00486 #endif
00487 m->setCheckable(TRUE);
00488 if (!b)
00489 m->setItemChecked(m->idAt(0),TRUE);
00490 else
00491 m->setItemChecked(m->idAt(0),FALSE);
00492
00493 if(Ir::supported())
00494 m->insertItem(tr("Beam File"),this,SLOT(doBeam()));
00495 m->setFocus();
00496
00497 m->exec(QPoint(QCursor::pos().x(),QCursor::pos().y()));
00498
00499 if(m) delete m;
00500 }
00501
00502
00503 QString AdvancedFm::checkDiskSpace(const QString &path) {
00504 struct statfs fss;
00505 if ( !statfs( path.latin1(), &fss ) ) {
00506 int blkSize = fss.f_bsize;
00507
00508 int availBlks = fss.f_bavail;
00509
00510 long mult = blkSize / 1024;
00511 long div = 1024 / blkSize;
00512 if ( !mult ) mult = 1;
00513 if ( !div ) div = 1;
00514
00515
00516 return QString::number(availBlks * mult / div);
00517 }
00518 return "";
00519 }
00520
00521 void AdvancedFm::addToDocs() {
00522 QStringList strListPaths = getPath();
00523 QDir *thisDir = CurrentDir();
00524
00525 if( strListPaths.count() > 0) {
00526 QString curFile;
00527 for ( QStringList::Iterator it = strListPaths.begin(); it != strListPaths.end(); ++it ) {
00528 curFile = thisDir->canonicalPath()+"/"+(*it);
00529
00530 QFileInfo fi(curFile);
00531 DocLnk f;
00532
00533 f.setName(fi.baseName() );
00534 f.setFile( curFile);
00535 f.writeLink();
00536 }
00537 }
00538 }
00539
00540
00541 void AdvancedFm::customDirsToMenu() {
00542
00543 Config cfg("AdvancedFm");
00544 cfg.setGroup("Menu");
00545
00546 QStringList list = cfg.readListEntry( "CustomDir", ',');
00547 menuButton->insertItems(list );
00548
00549
00550
00551
00552
00553 }
00554
00555 void AdvancedFm::dirMenuSelected(int item) {
00556 switch(item)
00557 {
00558
00559 case -21:
00560 case 0:
00561 addCustomDir();
00562 break;
00563 case -22:
00564 case 1:
00565 removeCustomDir();
00566 break;
00567 default:
00568 {
00569
00570
00571 }
00572 break;
00573
00574 };
00575 }
00576
00577 void AdvancedFm::addCustomDir() {
00578 Config cfg("AdvancedFm");
00579 cfg.setGroup("Menu");
00580 QString dir;
00581 QStringList list = cfg.readListEntry( (const QString &)"CustomDir", (const QChar)',');
00582
00583 dir = CurrentDir()->canonicalPath();
00584
00585 bool addIt=true;
00586 for ( QStringList::Iterator it = list.begin(); it != list.end(); ++it ) {
00587 if( dir == (*it)) {
00588 addIt=false;
00589 }
00590 }
00591 if(addIt) {
00592 menuButton->insertItem(dir);
00593
00594 list << dir;
00595 }
00596
00597 cfg.writeEntry("CustomDir", list, ',');
00598 cfg.write();
00599 }
00600
00601 void AdvancedFm::removeCustomDir() {
00602
00603 Config cfg("AdvancedFm");
00604 cfg.setGroup("Menu");
00605 QString dir;
00606 QStringList list = cfg.readListEntry( (const QString &)"CustomDir", (const QChar)',');
00607 QStringList list2;
00608 dir = CurrentDir()->canonicalPath();
00609 int ramble=2;
00610
00611
00612 if(list.grep(dir,true).isEmpty()) {
00613 QMessageBox::message(tr( "AdvancedFm" ),
00614 tr("<p>Cannot remove current directory from bookmarks. It is not bookmarked!</p>"));
00615 } else {
00616 for ( QStringList::Iterator it = list.begin(); it != list.end(); ++it ) {
00617 if((*it) != dir) {
00618
00619 list2 <<(*it);
00620 } else {
00621
00622 menuButton->remove( ramble);
00623
00624 }
00625 ramble++;
00626
00627 }
00628
00629 cfg.writeEntry("CustomDir", list2, ',');
00630 cfg.write();
00631 }
00632
00633
00634 }
00635
00636 void AdvancedFm::gotoCustomDir(const QString &dir) {
00637
00638
00639
00640
00641
00642 if( dir == s_addBookmark) {
00643 addCustomDir();
00644 }
00645 if( dir == s_removeBookmark) {
00646 removeCustomDir( );
00647 } else {
00648 changeTo( dir);
00649
00650
00651
00652
00653
00654
00655
00656 }
00657 }
00658
00659 QDir *AdvancedFm::CurrentDir() {
00660 if ( whichTab == 1) {
00661
00662 return ¤tDir;
00663 } else {
00664
00665 return ¤tRemoteDir;
00666 }
00667 }
00668
00669 QDir *AdvancedFm::OtherDir() {
00670
00671 if ( whichTab == 1) {
00672 return ¤tRemoteDir;
00673 } else {
00674 return ¤tDir;
00675 }
00676 }
00677
00678 QListView * AdvancedFm::CurrentView() {
00679
00680 if ( whichTab == 1) {
00681
00682 return Local_View;
00683 } else {
00684
00685
00686 return Remote_View;
00687 }
00688 }
00689
00690 QListView * AdvancedFm::OtherView() {
00691 if ( whichTab == 1)
00692 return Remote_View;
00693 else
00694 return Local_View;
00695 }
00696
00697 void AdvancedFm::setOtherTabCurrent() {
00698
00699 if ( whichTab == 1) {
00700 TabWidget->setCurrentWidget(1);
00701 } else {
00702 TabWidget->setCurrentWidget(0);
00703 }
00704
00705 OtherView()->setSelected( CurrentView()->firstChild(), true);
00706 }
00707
00708 void AdvancedFm::qcopReceive(const QCString &msg, const QByteArray &data) {
00709
00710 QDataStream stream ( data, IO_ReadOnly );
00711 if ( msg == "openDirectory(QString)" ) {
00712
00713 QString file;
00714 stream >> file;
00715 changeTo( (const QString &) file);
00716 }
00717 }
00718
00719 void AdvancedFm::setDocument(const QString &file) {
00720 changeTo( file);
00721 }
00722
00723
00724 void AdvancedFm::slotSwitchMenu(int item) {
00725 if(item == -23) {
00726 switchToLocalTab();
00727 tabChanged( tab);
00728 }
00729
00730 if(item == -24) {
00731 switchToRemoteTab();
00732 tabChanged( tab_2);
00733 }
00734 }
00735
00736 void AdvancedFm::navigateToSelected() {
00737 if( !CurrentView()->currentItem()) return;
00738 doDirChange();
00739 }