knotes Library API Documentation

knotesapp.cpp

00001 /*******************************************************************
00002  KNotes -- Notes for the KDE project
00003 
00004  Copyright (c) 1997-2004, 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00019 *******************************************************************/
00020 
00021 #include <qclipboard.h>
00022 #include <qptrlist.h>
00023 
00024 #include <kdebug.h>
00025 #include <kaction.h>
00026 #include <kxmlguifactory.h>
00027 #include <ksystemtray.h>
00028 #include <klocale.h>
00029 #include <kiconloader.h>
00030 #include <kstandarddirs.h>
00031 #include <kpopupmenu.h>
00032 #include <khelpmenu.h>
00033 #include <kkeydialog.h>
00034 #include <kglobalaccel.h>
00035 #include <kmessagebox.h>
00036 #include <ksimpleconfig.h>
00037 #include <kio/netaccess.h>
00038 #include <kwin.h>
00039 
00040 #include <libkcal/journal.h>
00041 #include <libkcal/icalformat.h>
00042 
00043 #include "knotesapp.h"
00044 #include "knote.h"
00045 #include "knoteconfig.h"
00046 #include "knoteconfigdlg.h"
00047 #include "knoteslegacy.h"
00048 
00049 
00050 int KNotesApp::KNoteActionList::compareItems( QPtrCollection::Item s1, QPtrCollection::Item s2 )
00051 {
00052     if ( ((KAction*)s1)->text() == ((KAction*)s2)->text() )
00053         return 0;
00054     return ( ((KAction*)s1)->text() < ((KAction*)s2)->text() ? -1 : 1 );
00055 }
00056 
00057 
00058 KNotesApp::KNotesApp()
00059     : DCOPObject("KNotesIface"), QLabel( 0, 0, WType_TopLevel ),
00060       KXMLGUIBuilder( this ),
00061       m_defaultConfig( 0 )
00062 {
00063     connect( kapp, SIGNAL(lastWindowClosed()), kapp, SLOT(quit()) );
00064 
00065     m_noteList.setAutoDelete( true );
00066     m_noteActions.setAutoDelete( true );
00067 
00068     // create the dock widget...
00069     KWin::setSystemTrayWindowFor( winId(), qt_xrootwin() );
00070     setBackgroundMode( X11ParentRelative );
00071     setPixmap( KSystemTray::loadIcon( "knotes" ) );
00072 
00073     // create the GUI...
00074     new KAction( i18n("New Note"), "filenew", 0,
00075         this, SLOT(newNote()), actionCollection(), "new_note" );
00076     new KAction( i18n("New Note From Clipboard"), "editpaste", 0,
00077         this, SLOT(newNoteFromClipboard()), actionCollection(), "new_note_clipboard" );
00078     new KHelpMenu( this, kapp->aboutData(), false, actionCollection() );
00079 
00080     KStdAction::preferences( this, SLOT(slotPreferences()), actionCollection() );
00081     KStdAction::keyBindings( this, SLOT(slotConfigureAccels()), actionCollection() );
00082     KStdAction::quit( this, SLOT(slotQuit()), actionCollection() )->setShortcut( 0 );
00083 
00084     setXMLFile( QString( instance()->instanceName() + "ui.rc" ) );
00085 
00086     m_guiFactory = new KXMLGUIFactory( this, this, "guifactory" );
00087     m_guiFactory->addClient( this );
00088 
00089     m_context_menu = static_cast<KPopupMenu*>(m_guiFactory->container( "knotes_context", this ));
00090     m_note_menu = static_cast<KPopupMenu*>(m_guiFactory->container( "notes_menu", this ));
00091 
00092     // create accels for global shortcuts
00093     m_globalAccel = new KGlobalAccel( this, "global accel" );
00094     m_globalAccel->insert( "global_new_note", i18n("New Note"), "",
00095                            ALT+SHIFT+Key_N, ALT+SHIFT+Key_N ,
00096                            this, SLOT(newNote()), true, true );
00097     m_globalAccel->insert( "global_new_note_clipboard", i18n("New Note From Clipboard"), "",
00098                            ALT+SHIFT+Key_C, ALT+SHIFT+Key_C,
00099                            this, SLOT(newNoteFromClipboard()), true, true );
00100 
00101     m_globalAccel->readSettings();
00102 
00103     KConfig *config = KGlobal::config();
00104     config->setGroup( "Global Keybindings" );
00105     m_globalAccel->setEnabled( config->readBoolEntry( "Enabled", true ) );
00106 
00107     updateGlobalAccels();
00108 
00109     // clean up old config files
00110     KNotesLegacy::cleanUp();
00111 
00112     // read the notes
00113     m_calendar.load( KGlobal::dirs()->saveLocation( "appdata" ) + "notes.ics" );
00114 
00115     // TODO
00116     // initialize the Calendar
00117     //mCalendar.setOwner(..);
00118     //mCalendar.setEmail(..);
00119 
00120     // read the old config files into mCalendar and convert them
00121     if ( KNotesLegacy::convert( &m_calendar ) )
00122         saveNotes();
00123 
00124     // create the note widgets out of the journals
00125     KCal::Journal::List notes = m_calendar.journals();
00126     KCal::Journal::List::ConstIterator end = notes.end();
00127     for ( KCal::Journal::List::ConstIterator it = notes.begin(); it != end; ++it )
00128         createNote( *it );
00129 
00130     kapp->installEventFilter( this );
00131 
00132     if ( m_noteList.count() == 0 && !kapp->isRestored() )
00133         newNote();
00134 }
00135 
00136 KNotesApp::~KNotesApp()
00137 {
00138     saveNotes();
00139 
00140     blockSignals( true );
00141     m_noteList.clear();
00142     blockSignals( false );
00143 
00144     delete m_defaultConfig;
00145 }
00146 
00147 bool KNotesApp::commitData( QSessionManager& )
00148 {
00149     saveConfigs();
00150     return true;
00151 }
00152 
00153 // -------------------- public DCOP interface -------------------- //
00154 
00155 QString KNotesApp::newNote( const QString& name, const QString& text )
00156 {
00157     // create the new note
00158     KCal::Journal *note = new KCal::Journal();
00159 
00160     // new notes have the current date/time as title if none was given
00161     if ( !name.isEmpty() )
00162         note->setSummary( name );
00163     else
00164         note->setSummary( KGlobal::locale()->formatDateTime( QDateTime::currentDateTime() ) );
00165 
00166     // the body of the note
00167     note->setDescription( text );
00168 
00169     m_calendar.addJournal( note );
00170 
00171     createNote( note );
00172     showNote( note->uid() );
00173 
00174     return note->uid();
00175 }
00176 
00177 QString KNotesApp::newNoteFromClipboard( const QString& name )
00178 {
00179     const QString& text = KApplication::clipboard()->text();
00180     return newNote( name, text );
00181 }
00182 
00183 void KNotesApp::showNote( const QString& id ) const
00184 {
00185     KNote* note = m_noteList[id];
00186     if ( note )
00187         showNote( note );
00188     else
00189         kdWarning(5500) << "No note with id: " << id << endl;
00190 }
00191 
00192 void KNotesApp::hideNote( const QString& id ) const
00193 {
00194     KNote* note = m_noteList[id];
00195     if ( note )
00196         note->hide();
00197     else
00198         kdWarning(5500) << "No note with id: " << id << endl;
00199 }
00200 
00201 void KNotesApp::killNote( const QString& id, bool force )
00202 {
00203     KNote* note = m_noteList[id];
00204     if ( note )
00205         note->slotKill( force );
00206     else
00207         kdWarning(5500) << "No note with id: " << id << endl;
00208 }
00209 
00210 // "bool force = false" doesn't work with dcop
00211 void KNotesApp::killNote( const QString& id )
00212 {
00213     killNote( id, false );
00214 }
00215 
00216 QMap<QString,QString> KNotesApp::notes() const
00217 {
00218     QMap<QString,QString> notes;
00219     QDictIterator<KNote> it( m_noteList );
00220 
00221     for ( ; it.current(); ++it )
00222         notes.insert( it.current()->noteId(), it.current()->name() );
00223 
00224     return notes;
00225 }
00226 
00227 QString KNotesApp::name( const QString& id ) const
00228 {
00229     KNote* note = m_noteList[id];
00230     if ( note )
00231         return note->name();
00232     else
00233         return QString::null;
00234 }
00235 
00236 QString KNotesApp::text( const QString& id ) const
00237 {
00238     KNote* note = m_noteList[id];
00239     if ( note )
00240         return note->text();
00241     else
00242         return QString::null;
00243 }
00244 
00245 void KNotesApp::setName( const QString& id, const QString& newName )
00246 {
00247     KNote* note = m_noteList[id];
00248     if ( note )
00249         note->setName( newName );
00250     else
00251         kdWarning(5500) << "No note with id: " << id << endl;
00252 }
00253 
00254 void KNotesApp::setText( const QString& id, const QString& newText )
00255 {
00256     KNote* note = m_noteList[id];
00257     if ( note )
00258         note->setText( newText );
00259     else
00260         kdWarning(5500) << "No note with id: " << id << endl;
00261 }
00262 
00263 void KNotesApp::sync( const QString& app )
00264 {
00265     QDictIterator<KNote> it( m_noteList );
00266 
00267     for ( ; it.current(); ++it )
00268         it.current()->sync( app );
00269 }
00270 
00271 bool KNotesApp::isNew( const QString& app, const QString& id ) const
00272 {
00273     KNote* note = m_noteList[id];
00274     if ( note )
00275         return note->isNew( app );
00276     else
00277         return false;
00278 }
00279 
00280 bool KNotesApp::isModified( const QString& app, const QString& id ) const
00281 {
00282     KNote* note = m_noteList[id];
00283     if ( note )
00284         return note->isModified( app );
00285     else
00286         return false;
00287 }
00288 
00289 
00290 // ------------------- protected methods ------------------- //
00291 
00292 void KNotesApp::mousePressEvent( QMouseEvent* e )
00293 {
00294     if ( !rect().contains( e->pos() ) )
00295         return;
00296 
00297     switch ( e->button() )
00298     {
00299     case LeftButton:
00300         if ( m_noteList.count() == 1 )
00301         {
00302             QDictIterator<KNote> it( m_noteList );
00303             showNote( it.toFirst() );
00304         }
00305         else if ( m_note_menu->count() > 0 )
00306             m_note_menu->popup( e->globalPos() );
00307         break;
00308     case MidButton:
00309         newNote();
00310         break;
00311     case RightButton:
00312         m_context_menu->popup( e->globalPos() );
00313     default: break;
00314     }
00315 }
00316 
00317 bool KNotesApp::eventFilter( QObject* o, QEvent* ev )
00318 {
00319     if ( ev->type() == QEvent::KeyPress )
00320     {
00321         QKeyEvent* ke = (QKeyEvent*)ev;
00322 
00323         if ( ke->key() == Key_BackTab )         // Shift+Tab
00324         {
00325             // show next note
00326             QDictIterator<KNote> it( m_noteList );
00327             KNote *first = it.toFirst();
00328             for ( ; it.current(); ++it )
00329                 if ( it.current()->hasFocus() )
00330                 {
00331                     if ( ++it )
00332                         showNote( it.current() );
00333                     else
00334                         showNote( first );
00335                     break;
00336                 }
00337 
00338             ke->accept();
00339             return true;
00340         }
00341         else
00342             ke->ignore();
00343     }
00344 
00345     return QLabel::eventFilter( o, ev );
00346 }
00347 
00348 
00349 // -------------------- protected slots -------------------- //
00350 
00351 void KNotesApp::slotShowNote()
00352 {
00353     // tell the WM to give this note focus
00354     showNote( QString::fromUtf8( sender()->name() ) );
00355 }
00356 
00357 void KNotesApp::slotPreferences()
00358 {
00359     // reuse the dialog if possible
00360     if ( KNoteConfigDlg::showDialog( "KNotes Default Settings" ) )
00361         return;
00362 
00363     // create the KNoteConfig if needed
00364     if ( !m_defaultConfig )
00365     {
00366         QString configFile = KGlobal::dirs()->saveLocation( "config" ) + "knotesrc";
00367         KSharedConfig::Ptr config = KSharedConfig::openConfig( configFile, false, false );
00368         m_defaultConfig = new KNoteConfig( config );
00369     }
00370 
00371     // create a new preferences dialog...
00372     KNoteConfigDlg *dialog = new KNoteConfigDlg( m_defaultConfig,
00373             i18n("KNotes Defaults"), true, this, "KNotes Default Settings" );
00374     dialog->show();
00375 }
00376 
00377 void KNotesApp::slotConfigureAccels()
00378 {
00379     KKeyDialog::configure( m_globalAccel, this, false );
00380     m_globalAccel->writeSettings();
00381     updateGlobalAccels();
00382 }
00383 
00384 void KNotesApp::slotNoteKilled( KCal::Journal *journal )
00385 {
00386     // this kills the KNote object
00387     m_noteList.remove( journal->uid() );
00388     m_calendar.deleteJournal( journal );
00389 
00390     saveNotes();
00391     updateNoteActions();
00392 }
00393 
00394 void KNotesApp::slotQuit()
00395 {
00396     saveConfigs();
00397     kapp->quit();
00398 }
00399 
00400 
00401 // -------------------- private methods -------------------- //
00402 
00403 void KNotesApp::showNote( KNote* note ) const
00404 {
00405     if ( !note->isHidden() )
00406     {
00407         // if it's already showing, we need to change to its desktop
00408         // and give it focus
00409         KWin::setCurrentDesktop( KWin::windowInfo( note->winId() ).desktop() );
00410         KWin::forceActiveWindow( note->winId() );
00411         note->setFocus();
00412     }
00413     else
00414     {
00415         // if not, show note on the current desktop
00416         note->show();
00417         note->toDesktop( KWin::currentDesktop() );
00418         KWin::forceActiveWindow( note->winId() );
00419         note->setFocus();
00420     }
00421 }
00422 
00423 void KNotesApp::createNote( KCal::Journal *journal )
00424 {
00425     KNote *newNote = new KNote( this, domDocument(), journal,
00426                                 0, journal->uid().utf8() );
00427     m_noteList.insert( newNote->noteId(), newNote );
00428 
00429     connect( newNote, SIGNAL(sigRequestNewNote()), SLOT(newNote()) );
00430     connect( newNote, SIGNAL(sigKillNote( KCal::Journal* )),
00431                         SLOT(slotNoteKilled( KCal::Journal* )) );
00432     connect( newNote, SIGNAL(sigNameChanged()), SLOT(updateNoteActions()) );
00433     connect( newNote, SIGNAL(sigDataChanged()), SLOT(saveNotes()) );
00434     connect( newNote, SIGNAL(sigColorChanged()), SLOT(updateNoteActions()) );
00435 
00436     updateNoteActions();
00437 }
00438 
00439 void KNotesApp::saveNotes()
00440 {
00441     QString file = KGlobal::dirs()->saveLocation( "appdata" ) + "notes.ics";
00442     QString backup = file + "~";
00443 
00444     // if the backup fails don't even try to save the current notes
00445     // (might just destroy the file that's already there)
00446 
00447     if ( KIO::NetAccess::exists( KURL( file ), true, 0 ) &&
00448          !KIO::NetAccess::file_copy( KURL( file ), KURL( backup ), -1, true ) )
00449     {
00450         KMessageBox::error( 0,
00451                             i18n("<qt>Unable to save the notes backup to "
00452                                  "<b>%1</b>! Check that there is sufficient "
00453                                  "disk space!</qt>").arg( backup ) );
00454     }
00455     else if ( !m_calendar.save( file, new KCal::ICalFormat() ) )
00456     {
00457         KMessageBox::error( 0,
00458                             i18n("<qt>Unable to save the notes to <b>%1</b>! "
00459                                  "Check that there is sufficient disk space."
00460                                  "<br>There should be a backup in <b>%2</b> "
00461                                  "though.</qt>").arg( file ).arg( backup ) );
00462     }
00463 }
00464 
00465 void KNotesApp::saveConfigs()
00466 {
00467     QDictIterator<KNote> it( m_noteList );
00468     for ( ; it.current(); ++it )
00469         it.current()->saveConfig();
00470 }
00471 
00472 void KNotesApp::updateNoteActions()
00473 {
00474     unplugActionList( "notes" );
00475     m_noteActions.clear();
00476 
00477     for ( QDictIterator<KNote> it( m_noteList ); it.current(); ++it )
00478     {
00479         KAction *action = new KAction( it.current()->name().replace("&", "&&"),
00480                                        KShortcut(), this, SLOT(slotShowNote()),
00481                                        (QObject *)0,
00482                                        it.current()->noteId().utf8() );
00483         QPixmap pix( 16, 16 );
00484         pix.fill( it.current()->paletteBackgroundColor() );
00485         action->setIconSet( pix );
00486         m_noteActions.append( action );
00487     }
00488 
00489     m_noteActions.sort();
00490 
00491     if ( m_noteActions.isEmpty() )
00492     {
00493         KAction *action = new KAction( i18n("No Notes") );
00494         m_noteActions.append( action );
00495     }
00496 
00497     plugActionList( "notes", m_noteActions );
00498 }
00499 
00500 void KNotesApp::updateGlobalAccels()
00501 {
00502     if ( m_globalAccel->isEnabled() )
00503     {
00504         KAction *action = actionCollection()->action( "new_note" );
00505         if ( action )
00506             action->setShortcut( m_globalAccel->shortcut( "global_new_note" ) );
00507         action = actionCollection()->action( "new_note_clipboard" );
00508         if ( action )
00509             action->setShortcut( m_globalAccel->shortcut( "global_new_note_clipboard" ) );
00510 
00511         m_globalAccel->updateConnections();
00512     }
00513     else
00514     {
00515         KAction *action = actionCollection()->action( "new_note" );
00516         if ( action )
00517             action->setShortcut( 0 );
00518         action = actionCollection()->action( "new_note_clipboard" );
00519         if ( action )
00520             action->setShortcut( 0 );
00521     }
00522 }
00523 
00524 #include "knotesapp.moc"
KDE Logo
This file is part of the documentation for knotes Library Version 3.2.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sat May 1 11:36:55 2004 by doxygen 1.2.15 written by Dimitri van Heesch, © 1997-2003