knotes Library API Documentation

knotesapp.cpp

00001 /*******************************************************************
00002  KNotes -- Notes for the KDE project
00003 
00004  Copyright (c) 1997-2002, The KNotes Developers
00005 
00006  This program is free software; you can redistribute it and/or
00007  modify it under the terms of the GNU General Public License
00008  as published by the Free Software Foundation; either version 2
00009  of the License, or (at your option) any later version.
00010 
00011  This program is distributed in the hope that it will be useful,
00012  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  GNU General Public License for more details.
00015 
00016  You should have received a copy of the GNU General Public License
00017  along with this program; if not, write to the Free Software
00018  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00019 *******************************************************************/
00020 
00021 #include <qclipboard.h>
00022 
00023 #include <kwin.h>
00024 #include <klocale.h>
00025 #include <kiconloader.h>
00026 #include <kstandarddirs.h>
00027 #include <kpopupmenu.h>
00028 #include <khelpmenu.h>
00029 #include <kkeydialog.h>
00030 #include <kglobalaccel.h>
00031 #include <kmessagebox.h>
00032 #include <kdebug.h>
00033 #include <ksimpleconfig.h>
00034 #include <kio/netaccess.h>
00035 
00036 #include <kaction.h>
00037 #include <kxmlgui.h>
00038 
00039 #include <unistd.h>
00040 
00041 #include "knotesapp.h"
00042 #include "knote.h"
00043 #include "knoteconfigdlg.h"
00044 
00045 
00046 KNotesApp::KNotesApp()
00047     : QLabel( 0, 0, WType_TopLevel ), DCOPObject("KNotesIface"),
00048       KXMLGUIBuilder( this )
00049 {
00050     m_noteActions.setAutoDelete( true );
00051     m_noteList.setAutoDelete( true );
00052 
00053     // create the dock widget...
00054     KWin::setSystemTrayWindowFor( winId(), qt_xrootwin() );
00055     setBackgroundMode( X11ParentRelative );
00056     setPixmap( KGlobal::iconLoader()->loadIcon( "knotes", KIcon::Small ) );
00057 
00058  
00059     // create the GUI...
00060     new KAction( i18n("New Note"), "filenew", 0, this, SLOT(slotNewNote()), actionCollection(), "new_note" );
00061     new KAction( i18n("New Note from Clipboard"), "editpaste", 0, this, SLOT(slotNewNoteFromClipboard()), actionCollection(), "new_note_clipboard" );
00062     new KHelpMenu( this, kapp->aboutData(), false, actionCollection() );
00063     
00064     KStdAction::preferences( this, SLOT(slotPreferences()), actionCollection() );
00065     KStdAction::keyBindings( this, SLOT(slotConfigureAccels()), actionCollection() );
00066     KStdAction::quit( this, SLOT(slotQuit()), actionCollection() )->setShortcut( 0 );
00067 
00068     setXMLFile( QString( instance()->instanceName() + "ui.rc" ) );
00069     factory = new KXMLGUIFactory( this, this, "guifactory" );
00070     factory->addClient( this );
00071 
00072     m_context_menu = static_cast<KPopupMenu*>(factory->container( "knotes_context", this ));
00073     m_note_menu = static_cast<KPopupMenu*>(factory->container( "notes_menu", this ));
00074     
00075     // create accels for global shortcuts
00076     globalAccel = new KGlobalAccel( this, "global accel" );
00077     globalAccel->insert( "global_new_note", i18n("New Note"), "",
00078                          ALT+SHIFT+Key_N, ALT+SHIFT+Key_N , 
00079                          this, SLOT(slotNewNote()), true, true );
00080     globalAccel->insert( "global_new_note_clipboard", i18n("New Note from Clipboard"), "",
00081                          ALT+SHIFT+Key_C, ALT+SHIFT+Key_C, 
00082                          this, SLOT(slotNewNoteFromClipboard()), true, true );
00083 
00084     globalAccel->readSettings();
00085 
00086     KConfig *config = KGlobal::config();
00087     config->setGroup( "Global Keybindings" );
00088     globalAccel->setEnabled( config->readBoolEntry( "Enabled", true ) );
00089 
00090     updateGlobalAccels();
00091 
00092 
00093     // remove old (KDE 1.x) local config file if it still exists
00094     QString configfile = KGlobal::dirs()->findResource( "config", "knotesrc" );
00095     KSimpleConfig *test = new KSimpleConfig( configfile, true );
00096     test->setGroup( "General" );
00097     if ( test->readDoubleNumEntry( "version", 1 ) == 1 )
00098     {
00099         delete test;
00100         if ( !( checkAccess( configfile, W_OK ) &&
00101                 KIO::NetAccess::del( KURL(configfile) ) ) )
00102         {
00103             kdError(5500) << "Could not delete old config file!!" << endl;
00104             // TODO
00105         }
00106     } else
00107         delete test;
00108 
00109 
00110     QDir noteDir( KGlobal::dirs()->saveLocation( "appdata", "notes/" ) );
00111 
00112     // clean up note names (pre KNotes 2.1)
00113     QStringList notes = noteDir.entryList( QDir::Files, QDir::Name );   // this doesn't list the hidden data files
00114     for ( QStringList::Iterator n = notes.begin(); n != notes.end(); n++ )
00115     {
00116         bool number;
00117         (*n).mid( 6 ).toInt( &number );
00118         if ( !((*n).startsWith( "KNote " ) && number) )
00119         {
00120             QString newName;
00121             for ( int i = 1; ; i++ )
00122             {
00123                 newName = QString( "KNote %1" ).arg(i);
00124                 if ( !noteDir.exists( newName ) )
00125                     break;
00126             }
00127             noteDir.rename( *n, newName, false );
00128             noteDir.rename( "." + (*n) + "_data", "." + newName + "_data", false );
00129             kdDebug(5500) << "Note " << *n << " renamed to " << newName << endl;
00130         }
00131     }
00132 
00133     // now read the notes
00134     notes = noteDir.entryList( QDir::Files, QDir::Name );   // this doesn't list the hidden data files
00135     for ( QStringList::Iterator i = notes.begin(); i != notes.end(); i++ )
00136     {
00137         KNote* newNote = new KNote( this, domDocument(), *i, true );
00138 
00139         connect( newNote, SIGNAL( sigRenamed(const QString&, const QString&) ),
00140                  this,    SLOT( slotNoteRenamed(const QString&, const QString&) ) );
00141         connect( newNote, SIGNAL( sigNewNote() ),
00142                  this,    SLOT( slotNewNote() ) );
00143         connect( newNote, SIGNAL( sigKilled(const QString&) ),
00144                  this,    SLOT( slotNoteKilled(const QString&) ) );
00145         connect( newNote, SIGNAL( sigConfigChanged() ),
00146                  this,    SLOT( updateNoteActions() ) );
00147 
00148         m_noteList.insert( newNote->name(), newNote );
00149     }
00150     updateNoteActions();
00151 
00152     connect( kapp, SIGNAL( lastWindowClosed() ), kapp, SLOT( quit() ) );
00153     
00154     kapp->installEventFilter( this );
00155     
00156     if ( m_noteList.count() == 0 && !kapp->isRestored() )
00157         slotNewNote();
00158 }
00159 
00160 KNotesApp::~KNotesApp()
00161 {
00162 kdDebug(5500) << k_funcinfo << endl;
00163     saveNotes( false );
00164     blockSignals(true);
00165     m_noteList.clear();
00166     blockSignals(false);
00167 
00168     delete factory;
00169 }
00170 
00171 bool KNotesApp::saveState( QSessionManager& )
00172 {
00173 kdDebug(5500) << k_funcinfo << endl;
00174     saveNotes( false );
00175     return true;
00176 }
00177 
00178 bool KNotesApp::commitData( QSessionManager& )
00179 {
00180 kdDebug(5500) << k_funcinfo << endl;
00181     saveNotes( true );
00182     return true;
00183 }
00184 
00185 
00186 // -------------------- public DCOP interface -------------------- //
00187 
00188 int KNotesApp::newNote( QString name, const QString& text )
00189 {
00190     if ( !name.isNull() && m_noteList[name] )
00191     {
00192         kdError(5500) << "A note with this name already exists!" << endl;
00193         return -1;
00194     }
00195 
00196     // must be done here to check if !m_noteList[name]
00197     QDir noteDir( KGlobal::dirs()->saveLocation( "appdata", "notes/" ) );
00198     if ( name.isEmpty() )
00199     {
00200         for ( int i = 1; ; i++ )
00201         {
00202             name = QString( "KNote %1" ).arg(i);
00203             if ( !m_noteList[name] && !noteDir.exists( name ) )
00204                 break;
00205         }
00206         
00207 //      New Notes have the current date as title
00208 /*      
00209         name = KGlobal::locale()->formatDateTime(QDateTime::currentDateTime());
00210         if ( m_noteList[name] || noteDir.exists( name ) )
00211         {
00212             name += "   -%1-";
00213             for ( int i =2; ; i++ )
00214             {
00215                 QString n = name.arg(i);
00216                 if ( !m_noteList[n] && !noteDir.exists( n ) )
00217                 {
00218                     name=n;
00219                     break;
00220                 }
00221             }
00222         }
00223 */
00224     }
00225 
00226     KNote* newNote = new KNote( this, domDocument(), name );
00227     newNote->setText( text );
00228 
00229     connect( newNote, SIGNAL( sigRenamed(const QString&, const QString&) ),
00230              this,    SLOT( slotNoteRenamed(const QString&, const QString&) ) );
00231     connect( newNote, SIGNAL( sigNewNote() ),
00232              this,    SLOT( slotNewNote() ) );
00233     connect( newNote, SIGNAL( sigKilled(const QString&) ),
00234              this,    SLOT( slotNoteKilled(const QString&) ) );
00235     connect( newNote, SIGNAL( sigConfigChanged() ),
00236              this,    SLOT( updateNoteActions() ) );
00237 
00238     m_noteList.insert( newNote->name(), newNote );
00239     updateNoteActions();
00240     showNote( newNote );
00241 
00242     return newNote->noteId();
00243 }
00244 
00245 int KNotesApp::newNoteFromClipboard( QString name )
00246 {
00247     const QString& text = KApplication::clipboard()->text();
00248     return newNote( name, text );
00249 }
00250 
00251 void KNotesApp::showNote( const QString& name ) const
00252 {
00253     KNote* note = m_noteList[name];
00254 
00255     if ( !note )
00256     {
00257         kdWarning(5500) << "No note named " << name << endl;
00258         return;
00259     }
00260 
00261     showNote( note );
00262 }
00263 
00264 void KNotesApp::showNote( int noteId ) const
00265 {
00266     KNote* note = noteById( noteId );
00267 
00268     if ( !note )
00269     {
00270         kdWarning(5500) << "No note with id " << noteId << endl;
00271         return;
00272     }
00273 
00274     showNote( note );
00275 }
00276 
00277 void KNotesApp::hideNote( const QString& name ) const
00278 {
00279     KNote* note = m_noteList[name];
00280 
00281     if ( !note )
00282     {
00283         kdWarning(5500) << "No note named " << name << endl;
00284         return;
00285     }
00286 
00287     note->hide();
00288 }
00289 
00290 void KNotesApp::hideNote( int noteId ) const
00291 {
00292     KNote* note = noteById( noteId );
00293     
00294     if ( !note )
00295     {
00296         kdWarning(5500) << "No note with id " << noteId << endl;
00297         return;
00298     }
00299 
00300     note->hide();
00301 }
00302 
00303 void KNotesApp::killNote( const QString& name )
00304 {
00305     KNote* note = m_noteList[name];
00306     if ( note )
00307         note->slotKill();
00308 }
00309 
00310 void KNotesApp::killNote( int noteId )
00311 {
00312     KNote* note = noteById( noteId );
00313     if ( note )
00314         note->slotKill();
00315 }
00316 
00317 QMap<int,QString> KNotesApp::notes() const
00318 {
00319     QMap<int,QString> notes;
00320     QDictIterator<KNote> it( m_noteList );
00321 
00322     for ( ; it.current(); ++it )
00323         notes.insert( it.current()->noteId(), it.current()->name() );
00324 
00325     return notes;
00326 }
00327 
00328 QString KNotesApp::text( const QString& name ) const
00329 {
00330     KNote* note = m_noteList[name];
00331 
00332     if ( note )
00333         return note->text();
00334     else
00335         return QString::null;
00336 }
00337 
00338 QString KNotesApp::text( int noteId ) const
00339 {
00340     KNote* note = noteById( noteId );
00341 
00342     if ( note )
00343         return note->text();
00344     else
00345         return QString::null;
00346 }
00347 
00348 void KNotesApp::setName( const QString& oldName, const QString& newName )
00349 {
00350     slotNoteRenamed( oldName, newName );
00351 }
00352 
00353 void KNotesApp::setName( int noteId, const QString& newName )
00354 {
00355     KNote* note = noteById( noteId );
00356     if ( note )
00357         slotNoteRenamed( note->name(), newName );
00358 }
00359 
00360 void KNotesApp::setText( const QString& name, const QString& newText )
00361 {
00362     KNote* note = m_noteList[name];
00363     if ( note )
00364         note->setText( newText );
00365 }
00366 
00367 void KNotesApp::setText( int noteId, const QString& newText )
00368 {
00369     KNote* note = noteById( noteId );
00370     if ( note )
00371         note->setText( newText );
00372 }
00373 
00374 void KNotesApp::sync( const QString& app )
00375 {
00376     QDictIterator<KNote> it( m_noteList );
00377 
00378     for ( ; it.current(); ++it )
00379         it.current()->sync( app );
00380 }
00381 
00382 bool KNotesApp::isNew( const QString& app, const QString& name ) const
00383 {
00384     KNote* note = m_noteList[name];
00385 
00386     if ( note )
00387         return note->isNew( app );
00388     else
00389         return false;
00390 }
00391 
00392 bool KNotesApp::isNew( const QString& app, int noteId ) const
00393 {
00394     KNote* note = noteById( noteId );
00395 
00396     if ( note )
00397         return note->isNew( app );
00398     else
00399         return false;
00400 }
00401 
00402 bool KNotesApp::isModified( const QString& app, const QString& name ) const
00403 {
00404     KNote* note = m_noteList[name];
00405 
00406     if ( note )
00407         return note->isModified( app );
00408     else
00409         return false;
00410 }
00411 
00412 bool KNotesApp::isModified( const QString& app, int noteId ) const
00413 {
00414     KNote* note = noteById( noteId );
00415 
00416     if ( note )
00417         return note->isModified( app );
00418     else
00419         return false;
00420 }
00421 
00422 
00423 // ------------------- protected methods ------------------- //
00424 
00425 void KNotesApp::mousePressEvent( QMouseEvent* e )
00426 {
00427     if ( !rect().contains( e->pos() ) )
00428         return;
00429 
00430     switch ( e->button() )
00431     {
00432     case LeftButton:
00433         if ( m_noteList.count() == 1 )
00434         {
00435             QDictIterator<KNote> it( m_noteList );
00436             showNote( it.toFirst() );
00437         }
00438         else if ( m_note_menu->count() > 0 )
00439             m_note_menu->popup( e->globalPos() );
00440         break;
00441     case MidButton:
00442         newNote();
00443         break;
00444     case RightButton:
00445         m_context_menu->popup( e->globalPos() );
00446     default: break;
00447     }
00448 }
00449 
00450 bool KNotesApp::eventFilter( QObject* o, QEvent* ev )
00451 {
00452     if ( ev->type() == QEvent::KeyPress )
00453     {
00454         QKeyEvent* ke = (QKeyEvent*)ev;
00455 
00456         if ( ke->key() == Key_BackTab )         // Shift+Tab
00457         {
00458             // show next note
00459             QDictIterator<KNote> it( m_noteList );
00460             KNote* first = it.current();
00461             for ( ; it.current(); ++it )
00462                 if ( it.current()->hasFocus() ) {
00463                     if ( ++it )
00464                         showNote( it.current() );
00465                     else
00466                         showNote( first );
00467                     break;
00468                 }
00469 
00470             ke->accept();
00471             return true;
00472         }
00473         else
00474             ke->ignore();
00475     }
00476 
00477     return QLabel::eventFilter( o, ev );
00478 }
00479 
00480 
00481 // -------------------- protected slots -------------------- //
00482 
00483 void KNotesApp::slotNewNote()
00484 {
00485     newNote();
00486 }
00487 
00488 void KNotesApp::slotNewNoteFromClipboard()
00489 {
00490     newNoteFromClipboard();
00491 }
00492 
00493 void KNotesApp::slotShowNote()
00494 {
00495     //tell the WM to give this note focus
00496     QString name = QString::fromUtf8( sender()->name() );
00497     showNote( name );
00498 }
00499 
00500 void KNotesApp::slotNoteRenamed( const QString& oldname, const QString& newname )
00501 {
00502     if ( m_noteList[newname] )
00503     {
00504         KMessageBox::sorry( this, i18n("There is already a note with that name") );
00505         return;
00506     }
00507 
00508     KNote *note = m_noteList.take( oldname );
00509     if ( note )
00510     {
00511         m_noteList.insert( newname, note );
00512         note->setName( newname );
00513 
00514         updateNoteActions();
00515     }
00516     else
00517         kdError(5500) << "There is no note named: " << oldname << endl;
00518 }
00519 
00520 void KNotesApp::slotNoteKilled( const QString& name )
00521 {
00522 kdDebug(5500) << k_funcinfo << endl;
00523     m_noteList.take( name );
00524     updateNoteActions();
00525 }
00526 
00527 void KNotesApp::slotPreferences() const
00528 {
00529     //launch preferences dialog...
00530     KNoteConfigDlg config( "knotesrc", i18n("KNotes Defaults"), true );
00531     config.exec();
00532 }
00533 
00534 void KNotesApp::slotConfigureAccels()
00535 {
00536     KKeyDialog::configure(globalAccel,this,false);
00537     globalAccel->writeSettings();
00538     updateGlobalAccels();
00539 }
00540 
00541 void KNotesApp::slotQuit()
00542 {
00543     saveNotes( true );
00544     kapp->quit();
00545 }
00546 
00547 // -------------------- private methods -------------------- //
00548 
00549 KNote* KNotesApp::noteById( int noteId ) const
00550 {
00551     QDictIterator<KNote> it( m_noteList );
00552 
00553     for ( ; it.current(); ++it )
00554         if ( it.current()->noteId() == noteId )
00555             return it.current();
00556 
00557     return 0L;
00558 }
00559 
00560 void KNotesApp::showNote( KNote* note ) const
00561 {
00562     if ( !note->isHidden() )
00563     {
00564         // if it's already showing, we need to change to its desktop
00565         // and give it focus
00566         KWin::setCurrentDesktop( KWin::info( note->winId() ).desktop );
00567         KWin::setActiveWindow( note->winId() );
00568         note->setFocus();
00569     }
00570     else
00571     {
00572         // if not, show note on the current desktop
00573         note->show();
00574         note->slotToDesktop( KWin::currentDesktop() );
00575         KWin::setActiveWindow( note->winId() );
00576         note->setFocus();
00577     }
00578 }
00579 
00580 void KNotesApp::saveNotes( bool display ) const
00581 {
00582 kdDebug(5500) << k_funcinfo << endl;
00583     // save all the notes...
00584     QDictIterator<KNote> it( m_noteList );
00585     for ( ; it.current(); ++it )
00586     {
00587         it.current()->saveData();
00588         it.current()->saveConfig();
00589         if ( display )
00590             it.current()->saveDisplayConfig();
00591     }
00592 }
00593 
00594 void KNotesApp::updateNoteActions()
00595 {
00596     unplugActionList( "notes" );
00597     m_noteActions.clear();
00598 
00599     for ( QDictIterator<KNote> it( m_noteList ); it.current(); ++it )
00600     {
00601         KAction *action = new KAction( it.currentKey().replace( "&", "&&"), 0, 0, it.currentKey().utf8() );
00602         QPixmap pix( 16, 16 );
00603         pix.fill( it.current()->paletteBackgroundColor() );
00604         action->setIconSet( pix );
00605         connect( action, SIGNAL( activated() ), this, SLOT( slotShowNote() ) );
00606         m_noteActions.append( action );
00607     }
00608 
00609     if ( m_noteActions.isEmpty() )
00610     {
00611         KAction *action = new KAction( i18n("No Notes") );
00612         m_noteActions.append( action );
00613     }
00614 
00615     plugActionList( "notes", m_noteActions );
00616 }
00617 
00618 void KNotesApp::updateGlobalAccels()
00619 {
00620     if ( globalAccel->isEnabled() )
00621     {
00622         KAction *action = actionCollection()->action( "new_note" );
00623         if ( action )
00624             action->setShortcut( globalAccel->shortcut( "global_new_note" ) );
00625         action = actionCollection()->action( "new_note_clipboard" );
00626         if ( action )
00627             action->setShortcut( globalAccel->shortcut( "global_new_note_clipboard" ) );
00628 
00629         globalAccel->updateConnections();
00630     }
00631     else
00632     {        
00633         KAction *action = actionCollection()->action( "new_note" );
00634         if ( action )
00635             action->setShortcut( 0 );
00636         action = actionCollection()->action( "new_note_clipboard" );
00637         if ( action )
00638             action->setShortcut( 0 );
00639     }
00640 }
00641 
00642 #include "knotesapp.moc"
KDE Logo
This file is part of the documentation for kdelibs Version 3.1.5.
Documentation copyright © 1996-2002 the KDE developers.
Generated on Sun Feb 15 11:40:19 2004 by doxygen 1.3.5 written by Dimitri van Heesch, © 1997-2001