/* * File name: kdirstatapp.cpp * Summary: The KDirStat application - menu bar, tool bar, ... * License: GPL - See file COPYING for details. * * Author: Stefan Hundhammer * Parts auto-generated by KDevelop * * Updated: 2004-12-06 */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "kdirstatapp.h" #include "kcleanupcollection.h" #include "kdirtree.h" #include "kpacman.h" #include "ktreemapview.h" #include "ktreemaptile.h" #include "kcleanupcollection.h" #include "kactivitytracker.h" #include "kdirtreeview.h" #include "kdirstatsettings.h" #define USER_CLEANUPS 10 // Number of user cleanup actions #define ID_STATUS_MSG 1 #define ID_PACMAN 42 #define PACMAN_WIDTH 350 #define PACMAN_INTERVAL 75 // millisec #define INITIAL_FEEDBACK_REMINDER 2000L #define FEEDBACK_REMINDER_INTERVAL 1000L using namespace KDirStat; KDirStatApp::KDirStatApp( TQWidget* , const char* name ) : TDEMainWindow( 0, name ) { // Simple inits _activityTracker = 0; // Might or might not be needed // Those will be created delayed, only when needed _settingsDialog = 0; _feedbackDialog = 0; _treemapView = 0; _pacMan = 0; _pacManDelimiter = 0; // Set up internal (mainWin -> mainWin) connections connect( this, TQT_SIGNAL( readConfig ( void ) ), this, TQT_SLOT ( readMainWinConfig( void ) ) ); connect( this, TQT_SIGNAL( saveConfig ( void ) ), this, TQT_SLOT ( saveMainWinConfig( void ) ) ); // Create main window _splitter = new TQSplitter( Qt::Vertical, this ); setCentralWidget( _splitter ); _treeView = new KDirTreeView( _splitter ); connect( _treeView, TQT_SIGNAL( progressInfo( const TQString & ) ), this, TQT_SLOT ( statusMsg ( const TQString & ) ) ); connect( _treeView, TQT_SIGNAL( selectionChanged( KFileInfo * ) ), this, TQT_SLOT ( selectionChanged( KFileInfo * ) ) ); connect( _treeView, TQT_SIGNAL( contextMenu( KDirTreeViewItem *, const TQPoint & ) ), this, TQT_SLOT ( contextMenu( KDirTreeViewItem *, const TQPoint & ) ) ); connect( this, TQT_SIGNAL( readConfig() ), _treeView, TQT_SLOT ( readConfig() ) ); connect( this, TQT_SIGNAL( saveConfig() ), _treeView, TQT_SLOT ( saveConfig() ) ); connect( _treeView, TQT_SIGNAL( finished() ), TQT_TQOBJECT(this), TQT_SLOT( createTreemapView() ) ); connect( _treeView, TQT_SIGNAL( aborted() ), TQT_TQOBJECT(this), TQT_SLOT( createTreemapView() ) ); connect( _treeView, TQT_SIGNAL( startingReading() ), TQT_TQOBJECT(this), TQT_SLOT( deleteTreemapView() ) ); connect( _treeView, TQT_SIGNAL( startingReading() ), TQT_TQOBJECT(this), TQT_SLOT( updateActions() ) ); connect( _treeView, TQT_SIGNAL( finished() ), TQT_TQOBJECT(this), TQT_SLOT( updateActions() ) ); connect( _treeView, TQT_SIGNAL( aborted() ), TQT_TQOBJECT(this), TQT_SLOT( updateActions() ) ); // Call inits to invoke all other construction parts initStatusBar(); initActions(); initCleanups(); createGUI(); initActivityTracker(); _treeViewContextMenu = (TQPopupMenu *) factory()->container( "treeViewContextMenu", this ); _treemapContextMenu = (TQPopupMenu *) factory()->container( "treemapContextMenu", this ); readMainWinConfig(); // Disable certain actions at startup _editCopy->setEnabled( false ); _reportMailToOwner->setEnabled( false ); _fileRefreshAll->setEnabled( false ); _fileRefreshSelected->setEnabled( false ); updateActions(); } KDirStatApp::~KDirStatApp() { delete _cleanupCollection; } void KDirStatApp::initActions() { _fileAskOpenDir = KStdAction::open ( TQT_TQOBJECT(this), TQT_SLOT( fileAskOpenDir() ), actionCollection() ); _fileAskOpenUrl = new TDEAction( i18n( "Open &URL..." ), "konqueror", 0, TQT_TQOBJECT(this), TQT_SLOT( fileAskOpenUrl() ), actionCollection(), "file_open_url" ); _fileOpenRecent = KStdAction::openRecent ( TQT_TQOBJECT(this), TQT_SLOT( fileOpenRecent( const KURL& ) ), actionCollection() ); _fileCloseDir = KStdAction::close ( TQT_TQOBJECT(this), TQT_SLOT( fileCloseDir() ), actionCollection() ); _fileRefreshAll = new TDEAction( i18n( "Refresh &All" ), "reload", 0, TQT_TQOBJECT(this), TQT_SLOT( refreshAll() ), actionCollection(), "file_refresh_all" ); _fileRefreshSelected = new TDEAction( i18n( "Refresh &Selected" ), 0, TQT_TQOBJECT(this), TQT_SLOT( refreshSelected() ), actionCollection(), "file_refresh_selected" ); _fileContinueReadingAtMountPoint = new TDEAction( i18n( "Continue Reading at &Mount Point" ), "drive-harddisk-mounted", 0, TQT_TQOBJECT(this), TQT_SLOT( refreshSelected() ), actionCollection(), "file_continue_reading_at_mount_point" ); _fileStopReading = new TDEAction( i18n( "Stop Rea&ding" ), "process-stop", 0, TQT_TQOBJECT(this), TQT_SLOT( stopReading() ), actionCollection(), "file_stop_reading" ); _fileQuit = KStdAction::quit ( TQT_TQOBJECT(kapp), TQT_SLOT( quit() ), actionCollection() ); _editCopy = KStdAction::copy ( TQT_TQOBJECT(this), TQT_SLOT( editCopy() ), actionCollection() ); _showToolBar = KStdAction::showToolbar ( TQT_TQOBJECT(this), TQT_SLOT( toggleToolBar() ), actionCollection() ); _showStatusBar = KStdAction::showStatusbar ( TQT_TQOBJECT(this), TQT_SLOT( toggleStatusBar() ), actionCollection() ); _cleanupOpenWith = new TDEAction( i18n( "Open With" ), 0, TQT_TQOBJECT(this), TQT_SLOT( cleanupOpenWith() ), actionCollection(), "cleanup_open_with" ); _treemapZoomIn = new TDEAction( i18n( "Zoom in" ), "zoom-in", Key_Plus, TQT_TQOBJECT(this), TQT_SLOT( treemapZoomIn() ), actionCollection(), "treemap_zoom_in" ); _treemapZoomOut = new TDEAction( i18n( "Zoom out" ), "zoom-out", Key_Minus, TQT_TQOBJECT(this), TQT_SLOT( treemapZoomOut() ), actionCollection(), "treemap_zoom_out" ); _treemapSelectParent= new TDEAction( i18n( "Select Parent" ), "go-up", Key_Asterisk, TQT_TQOBJECT(this), TQT_SLOT( treemapSelectParent() ), actionCollection(), "treemap_select_parent" ); _treemapRebuild = new TDEAction( i18n( "Rebuild Treemap" ), 0, TQT_TQOBJECT(this), TQT_SLOT( treemapRebuild() ), actionCollection(), "treemap_rebuild" ); _showTreemapView = new TDEToggleAction( i18n( "Show Treemap" ), Key_F9, TQT_TQOBJECT(this), TQT_SLOT( toggleTreemapView() ), actionCollection(), "options_show_treemap" ); new TDEAction( i18n( "Help about Treemaps" ), "help", 0, TQT_TQOBJECT(this), TQT_SLOT( treemapHelp() ), actionCollection(), "treemap_help" ); TDEAction * pref = KStdAction::preferences( TQT_TQOBJECT(this), TQT_SLOT( preferences() ), actionCollection() ); _reportMailToOwner = new TDEAction( i18n( "Send &Mail to Owner" ), "mail_generic", 0, TQT_TQOBJECT(_treeView), TQT_SLOT( sendMailToOwner() ), actionCollection(), "report_mail_to_owner" ); _helpSendFeedbackMail = new TDEAction( i18n( "Send &Feedback Mail..." ), 0, TQT_TQOBJECT(this), TQT_SLOT( sendFeedbackMail() ), actionCollection(), "help_send_feedback_mail" ); _fileAskOpenDir->setStatusText ( i18n( "Opens a directory" ) ); _fileAskOpenUrl->setStatusText ( i18n( "Opens a (possibly remote) directory" ) ); _fileOpenRecent->setStatusText ( i18n( "Opens a recently used directory" ) ); _fileCloseDir->setStatusText ( i18n( "Closes the current directory" ) ); _fileRefreshAll->setStatusText ( i18n( "Re-reads the entire directory tree" ) ); _fileRefreshSelected->setStatusText ( i18n( "Re-reads the selected subtree" ) ); _fileContinueReadingAtMountPoint->setStatusText( i18n( "Scan mounted file systems" ) ); _fileStopReading->setStatusText ( i18n( "Stops directory reading" ) ); _fileQuit->setStatusText ( i18n( "Quits the application" ) ); _editCopy->setStatusText ( i18n( "Copies the URL of the selected item to the clipboard" ) ); _showToolBar->setStatusText ( i18n( "Enables/disables the toolbar" ) ); _showStatusBar->setStatusText ( i18n( "Enables/disables the statusbar" ) ); _cleanupOpenWith->setStatusText ( i18n( "Open file or directory with arbitrary application" ) ); _showTreemapView->setStatusText ( i18n( "Enables/disables the treemap view" ) ); _treemapZoomIn->setStatusText ( i18n( "Zoom treemap in" ) ); _treemapZoomOut->setStatusText ( i18n( "Zoom treemap out" ) ); _treemapSelectParent->setStatusText ( i18n( "Select parent" ) ); _treemapRebuild->setStatusText ( i18n( "Rebuild treemap to fit into available space" ) ); pref->setStatusText ( i18n( "Opens the preferences dialog" ) ); _reportMailToOwner->setStatusText ( i18n( "Sends a mail to the owner of the selected subtree" ) ); } void KDirStatApp::initCleanups() { _cleanupCollection = new KCleanupCollection( actionCollection() ); TQ_CHECK_PTR( _cleanupCollection ); _cleanupCollection->addStdCleanups(); _cleanupCollection->addUserCleanups( USER_CLEANUPS ); _cleanupCollection->slotReadConfig(); connect( _treeView, TQT_SIGNAL( selectionChanged( KFileInfo * ) ), _cleanupCollection, TQT_SIGNAL( selectionChanged( KFileInfo * ) ) ); connect( this, TQT_SIGNAL( readConfig( void ) ), _cleanupCollection, TQT_SIGNAL( readConfig( void ) ) ); connect( this, TQT_SIGNAL( saveConfig( void ) ), _cleanupCollection, TQT_SIGNAL( saveConfig( void ) ) ); } void KDirStatApp::revertCleanupsToDefaults() { KCleanupCollection defaultCollection; defaultCollection.addStdCleanups(); defaultCollection.addUserCleanups( USER_CLEANUPS ); *_cleanupCollection = defaultCollection; } void KDirStatApp::initPacMan( bool enablePacMan ) { if ( enablePacMan ) { if ( ! _pacMan ) { _pacMan = new KPacMan( toolBar(), 16, false, "tde toolbar widget" ); _pacMan->setInterval( PACMAN_INTERVAL ); // millisec int id = ID_PACMAN; toolBar()->insertWidget( id, PACMAN_WIDTH, _pacMan ); toolBar()->setItemAutoSized( id, false ); _pacManDelimiter = new TQWidget( toolBar() ); toolBar()->insertWidget( ++id, 1, _pacManDelimiter ); connect( _treeView, TQT_SIGNAL( startingReading() ), _pacMan, TQT_SLOT( start() ) ); connect( _treeView, TQT_SIGNAL( finished() ), _pacMan, TQT_SLOT( stop () ) ); connect( _treeView, TQT_SIGNAL( aborted() ), _pacMan, TQT_SLOT( stop () ) ); } } else { if ( _pacMan ) { delete _pacMan; _pacMan = 0; } if ( _pacManDelimiter ) { delete _pacManDelimiter; _pacManDelimiter = 0; } } } void KDirStatApp::initStatusBar() { statusBar()->insertItem( i18n( "Ready." ), ID_STATUS_MSG ); } void KDirStatApp::initActivityTracker() { if ( ! doFeedbackReminder() ) return; _activityTracker = new KActivityTracker( TQT_TQOBJECT(this), "Feedback", INITIAL_FEEDBACK_REMINDER ); connect( _activityTracker, TQT_SIGNAL( thresholdReached() ), this, TQT_SLOT ( askForFeedback() ) ); connect( _treeView, TQT_SIGNAL( userActivity( int ) ), _activityTracker, TQT_SLOT ( trackActivity( int ) ) ); connect( _cleanupCollection, TQT_SIGNAL( userActivity( int ) ), _activityTracker, TQT_SLOT ( trackActivity( int ) ) ); } void KDirStatApp::openURL( const KURL& url ) { statusMsg( i18n( "Opening directory..." ) ); _treeView->openURL( url ); _fileOpenRecent->addURL( url ); _fileRefreshAll->setEnabled( true ); setCaption( url.fileName(), false ); statusMsg( i18n( "Ready." ) ); } void KDirStatApp::readMainWinConfig() { TDEConfig * config = kapp->config(); config->setGroup( "General Options" ); // Status settings of the various bars and views _showToolBar->setChecked( config->readBoolEntry( "Show Toolbar", true ) ); toggleToolBar(); _showStatusBar->setChecked( config->readBoolEntry( "Show Statusbar", true ) ); toggleStatusBar(); _showTreemapView->setChecked( config->readBoolEntry( "Show Treemap", true ) ); toggleTreemapView(); // Position settings of the various bars TDEToolBar::BarPosition toolBarPos; toolBarPos = ( TDEToolBar::BarPosition ) config->readNumEntry( "ToolBarPos", TDEToolBar::Top ); toolBar( "mainToolBar" )->setBarPos( toolBarPos ); _treemapViewHeight = config->readNumEntry( "TreemapViewHeight", 250 ); // initialize the recent file list _fileOpenRecent->loadEntries( config,"Recent Files" ); TQSize size = config->readSizeEntry( "Geometry" ); if( ! size.isEmpty() ) resize( size ); config->setGroup( "Animation" ); initPacMan( config->readBoolEntry( "ToolbarPacMan", true ) ); _treeView->enablePacManAnimation( config->readBoolEntry( "DirTreePacMan", false ) ); } void KDirStatApp::saveMainWinConfig() { TDEConfig * config = kapp->config(); config->setGroup( "General Options" ); config->writeEntry( "Geometry", size() ); config->writeEntry( "Show Toolbar", _showToolBar->isChecked() ); config->writeEntry( "Show Statusbar", _showStatusBar->isChecked() ); config->writeEntry( "Show Treemap", _showTreemapView->isChecked() ); config->writeEntry( "ToolBarPos", (int) toolBar( "mainToolBar" )->barPos() ); if ( _treemapView ) config->writeEntry( "TreemapViewHeight", _treemapView->height() ); _fileOpenRecent->saveEntries( config,"Recent Files" ); } void KDirStatApp::saveProperties( TDEConfig *config ) { (void) config; // TODO } void KDirStatApp::readProperties( TDEConfig *config ) { (void) config; // TODO } bool KDirStatApp::queryClose() { return true; } bool KDirStatApp::queryExit() { emit saveConfig(); return true; } //============================================================================ // Slots //============================================================================ void KDirStatApp::fileAskOpenDir() { statusMsg( i18n( "Opening directory..." ) ); KURL url = KFileDialog::getExistingDirectory( TQString(), this, i18n( "Open Directory..." ) ); if( ! url.isEmpty() ) openURL( fixedUrl( url.url() ) ); statusMsg( i18n( "Ready." ) ); } void KDirStatApp::fileAskOpenUrl() { statusMsg( i18n( "Opening URL..." ) ); KURL url = KURLRequesterDlg::getURL( TQString(), // startDir this, i18n( "Open URL..." ) ); if( ! url.isEmpty() ) openURL( fixedUrl( url.url() ) ); statusMsg( i18n( "Ready." ) ); } void KDirStatApp::fileOpenRecent( const KURL& url ) { statusMsg( i18n( "Opening directory..." ) ); if( ! url.isEmpty() ) openURL( fixedUrl( url.url() ) ); statusMsg( i18n( "Ready." ) ); } void KDirStatApp::fileCloseDir() { statusMsg( i18n( "Closing directory..." ) ); _treeView->clear(); _fileRefreshAll->setEnabled( false ); close(); statusMsg( i18n( "Ready." ) ); } void KDirStatApp::refreshAll() { statusMsg( i18n( "Refreshing directory tree..." ) ); _treeView->refreshAll(); statusMsg( i18n( "Ready." ) ); } void KDirStatApp::refreshSelected() { if ( ! _treeView->selection() ) return; statusMsg( i18n( "Refreshing selected subtree..." ) ); _treeView->refreshSelected(); statusMsg( i18n( "Ready." ) ); } void KDirStatApp::stopReading() { _treeView->abortReading(); } void KDirStatApp::editCopy() { if ( _treeView->selection() ) kapp->clipboard()->setText( TQString::fromLocal8Bit(_treeView->selection()->orig()->url()) ); #if 0 #warning debug if ( _activityTracker ) _activityTracker->trackActivity( 800 ); #endif } void KDirStatApp::cleanupOpenWith() { if ( ! _treeView->selection() ) return; KFileInfo * sel = _treeView->selection()->orig(); if ( sel->isDotEntry() ) return; KURL::List urlList( KURL( sel->url() ) ); KRun::displayOpenWithDialog( urlList, false ); } void KDirStatApp::selectionChanged( KFileInfo *selection ) { if ( selection ) { _editCopy->setEnabled( true ); _reportMailToOwner->setEnabled( true ); _fileRefreshSelected->setEnabled( ! selection->isDotEntry() ); _cleanupOpenWith->setEnabled( ! selection->isDotEntry() ); if ( selection->isMountPoint() && selection->readState() == KDirOnRequestOnly ) { _fileContinueReadingAtMountPoint->setEnabled( true ); } else _fileContinueReadingAtMountPoint->setEnabled( false ); statusMsg( TQString::fromLocal8Bit(selection->url()) ); } else { _editCopy->setEnabled( false ); _reportMailToOwner->setEnabled( false ); _fileRefreshSelected->setEnabled( false ); _fileContinueReadingAtMountPoint->setEnabled( false ); _cleanupOpenWith->setEnabled( false ); statusMsg( "" ); } updateActions(); } void KDirStatApp::updateActions() { _treemapZoomIn->setEnabled ( _treemapView && _treemapView->canZoomIn() ); _treemapZoomOut->setEnabled( _treemapView && _treemapView->canZoomOut() ); _treemapRebuild->setEnabled( _treemapView && _treemapView->rootTile() ); _treemapSelectParent->setEnabled( _treemapView && _treemapView->canSelectParent() ); if ( _treeView->tree() && _treeView->tree()->isBusy() ) _fileStopReading->setEnabled( true ); else _fileStopReading->setEnabled( false ); } void KDirStatApp::treemapZoomIn() { if ( _treemapView ) { _treemapView->zoomIn(); updateActions(); } } void KDirStatApp::treemapZoomOut() { if ( _treemapView ) { _treemapView->zoomOut(); updateActions(); } } void KDirStatApp::treemapSelectParent() { if ( _treemapView ) { _treemapView->selectParent(); updateActions(); } } void KDirStatApp::treemapRebuild() { if ( _treemapView ) { _treemapView->rebuildTreemap(); updateActions(); } } void KDirStatApp::treemapHelp() { kapp->invokeHelp( "treemap_intro" ); } void KDirStatApp::toggleToolBar() { if ( _showToolBar->isChecked() ) toolBar( "mainToolBar" )->show(); else toolBar( "mainToolBar" )->hide(); } void KDirStatApp::toggleStatusBar() { if ( _showStatusBar->isChecked() ) statusBar()->show(); else statusBar()->hide(); } void KDirStatApp::toggleTreemapView() { if ( _showTreemapView->isChecked() ) { if ( ! _treemapView ) createTreemapView(); } else { if ( _treemapView ) deleteTreemapView(); } } void KDirStatApp::preferences() { if ( ! _settingsDialog ) { _settingsDialog = new KDirStat::KSettingsDialog( this ); TQ_CHECK_PTR( _settingsDialog ); } if ( ! _settingsDialog->isVisible() ) _settingsDialog->show(); } void KDirStatApp::askForFeedback() { if ( ! doFeedbackReminder() ) return; TDEConfig * config = kapp->config(); switch ( KMessageBox::warningYesNoCancel( this, i18n( "Now that you know this program for some time,\n" "wouldn't you like to tell the authors your opinion about it?\n" "\n" "Open Source software depends on user feedback.\n" "Your opinion can help us make the software better." ), i18n( "Please tell us your opinion!" ), // caption i18n( "Open &Feedback Form..." ), // yesButton i18n( "&No, and don't ask again!" ) // noButton ) ) { case KMessageBox::Yes: sendFeedbackMail(); break; case KMessageBox::No: // ...and don't ask again config->setGroup( "Feedback" ); config->writeEntry( "dontAsk", true ); config->sync(); // make sure this doesn't get lost even if the app is killed or crashes break; case KMessageBox::Cancel: break; } config->setGroup( "Feedback" ); int remindersCount = config->readNumEntry ( "remindersCount", 0 ); config->writeEntry( "remindersCount", ++remindersCount ); if ( _activityTracker ) { _activityTracker->setThreshold( _activityTracker->threshold() + FEEDBACK_REMINDER_INTERVAL ); } } void KDirStatApp::feedbackMailSent() { TDEConfig * config = kapp->config(); config->setGroup( "Feedback" ); config->writeEntry( "mailSent", true ); config->sync(); } bool KDirStatApp::doFeedbackReminder() { TDEConfig * config = kapp->config(); config->setGroup( "Feedback" ); bool mailSent = config->readBoolEntry( "mailSent", false ); bool dontAsk = config->readBoolEntry( "dontAsk", false ); int remindersCount = config->readNumEntry ( "remindersCount", 0 ); return !mailSent && !dontAsk && remindersCount < 5; } void KDirStatApp::statusMsg( const TQString &text ) { // Change status message permanently statusBar()->clear(); statusBar()->changeItem( text, ID_STATUS_MSG ); } void KDirStatApp::contextMenu( KDirTreeViewItem * item, const TQPoint &pos ) { NOT_USED( item ); if ( _treeViewContextMenu ) _treeViewContextMenu->popup( pos ); } void KDirStatApp::contextMenu( KTreemapTile * tile, const TQPoint &pos ) { NOT_USED( tile ); if ( _treemapContextMenu ) _treemapContextMenu->popup( pos ); } void KDirStatApp::createTreemapView() { if ( ! _showTreemapView->isChecked() || ! _treeView->tree() ) return; if ( _treemapView ) delete _treemapView; _treemapView = new KTreemapView( _treeView->tree(), _splitter, TQSize( _splitter->width(), _treemapViewHeight ) ); TQ_CHECK_PTR( _treemapView ); connect( _treemapView, TQT_SIGNAL( contextMenu( KTreemapTile *, const TQPoint & ) ), this, TQT_SLOT ( contextMenu( KTreemapTile *, const TQPoint & ) ) ); connect( _treemapView, TQT_SIGNAL( treemapChanged() ), this, TQT_SLOT ( updateActions() ) ); connect( _treemapView, TQT_SIGNAL( selectionChanged( KFileInfo * ) ), this, TQT_SLOT ( selectionChanged( KFileInfo * ) ) ); if ( _activityTracker ) { connect( _treemapView, TQT_SIGNAL( userActivity ( int ) ), _activityTracker, TQT_SLOT ( trackActivity( int ) ) ); } _treemapView->show(); // TQSplitter needs explicit show() for new children updateActions(); } void KDirStatApp::deleteTreemapView() { if ( _treemapView ) { _treemapViewHeight = _treemapView->height(); delete _treemapView; } _treemapView = 0; updateActions(); } #include "kdirstatapp.moc" // EOF