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 #include <qtooltip.h>
00024 
00025 #include <kdebug.h>
00026 #include <kaction.h>
00027 #include <kxmlguifactory.h>
00028 #include <kxmlguibuilder.h>
00029 #include <ksystemtray.h>
00030 #include <klocale.h>
00031 #include <kiconeffect.h>
00032 #include <kstandarddirs.h>
00033 #include <kpopupmenu.h>
00034 #include <khelpmenu.h>
00035 #include <kkeydialog.h>
00036 #include <kglobalaccel.h>
00037 #include <ksimpleconfig.h>
00038 #include <kwin.h>
00039 #include <kextsock.h>
00040 
00041 #include <libkcal/journal.h>
00042 #include <libkcal/calendarlocal.h>
00043 
00044 #include "knotesapp.h"
00045 #include "knote.h"
00046 #include "knoteconfigdlg.h"
00047 #include "knotesglobalconfig.h"
00048 #include "knoteslegacy.h"
00049 #include "knotesnetrecv.h"
00050 
00051 #include "knotes/resourcemanager.h"
00052 
00053 
00054 class KNotesKeyDialog : public KDialogBase
00055 {
00056 public:
00057     KNotesKeyDialog( KGlobalAccel *globals, QWidget *parent, const char* name = 0 )
00058         : KDialogBase( parent, name, true, QString::null, Default|Ok|Cancel, Ok )
00059 //        : KDialogBase( parent, name, true, i18n("Configure Shortcuts"), Default|Ok|Cancel, Ok )
00060     {
00061         m_keyChooser = new KKeyChooser( globals, this );
00062         setMainWidget( m_keyChooser );
00063         connect( this, SIGNAL(defaultClicked()), m_keyChooser, SLOT(allDefault()) );
00064     }
00065 
00066     void insert( KActionCollection *actions )
00067     {
00068         //m_keyChooser->insert( actions, i18n("Note Actions") );
00069         m_keyChooser->insert( actions );
00070     }
00071 
00072     void configure()
00073     {
00074         if ( exec() == Accepted )
00075             m_keyChooser->save();
00076     }
00077 
00078 private:
00079     KKeyChooser *m_keyChooser;
00080 };
00081 
00082 
00083 int KNotesApp::KNoteActionList::compareItems( QPtrCollection::Item s1, QPtrCollection::Item s2 )
00084 {
00085     if ( ((KAction*)s1)->text() == ((KAction*)s2)->text() )
00086         return 0;
00087     return ( ((KAction*)s1)->text() < ((KAction*)s2)->text() ? -1 : 1 );
00088 }
00089 
00090 
00091 KNotesApp::KNotesApp()
00092     : DCOPObject("KNotesIface"), QLabel( 0, 0, WType_TopLevel ),
00093       m_listener( 0 )
00094 {
00095     connect( kapp, SIGNAL(lastWindowClosed()), kapp, SLOT(quit()) );
00096 
00097     m_noteList.setAutoDelete( true );
00098     m_noteActions.setAutoDelete( true );
00099 
00100     // create the dock widget...
00101     KWin::setSystemTrayWindowFor( winId(), qt_xrootwin() );
00102     QToolTip::add( this, i18n( "KNotes: Sticky notes for KDE" ) );
00103     setBackgroundMode( X11ParentRelative );
00104     setPixmap( KSystemTray::loadIcon( "knotes" ) );
00105 
00106     // create the GUI...
00107     new KAction( i18n("New Note"), "filenew", 0,
00108         this, SLOT(newNote()), actionCollection(), "new_note" );
00109     new KAction( i18n("New Note From Clipboard"), "editpaste", 0,
00110         this, SLOT(newNoteFromClipboard()), actionCollection(), "new_note_clipboard" );
00111 //    new KAction( i18n("Show All Notes"), "knotes", 0,
00112 //        this, SLOT(showAllNotes()), actionCollection(), "show_all_notes" );
00113 //    new KAction( i18n("Hide All Notes"), "fileclose", 0,
00114 //        this, SLOT(hideAllNotes()), actionCollection(), "hide_all_notes" );
00115     new KHelpMenu( this, kapp->aboutData(), false, actionCollection() );
00116 
00117     KStdAction::preferences( this, SLOT(slotPreferences()), actionCollection() );
00118     KStdAction::keyBindings( this, SLOT(slotConfigureAccels()), actionCollection() );
00119     KStdAction::quit( this, SLOT(slotQuit()), actionCollection() )->setShortcut( 0 );
00120 
00121     setXMLFile( instance()->instanceName() + "appui.rc" );
00122 
00123     m_guiBuilder = new KXMLGUIBuilder( this );
00124     m_guiFactory = new KXMLGUIFactory( m_guiBuilder, this );
00125     m_guiFactory->addClient( this );
00126 
00127     m_context_menu = static_cast<KPopupMenu*>(m_guiFactory->container( "knotes_context", this ));
00128     m_note_menu = static_cast<KPopupMenu*>(m_guiFactory->container( "notes_menu", this ));
00129 
00130     m_noteGUI.setContent(
00131         KXMLGUIFactory::readConfigFile( instance()->instanceName() + "ui.rc", instance() )
00132     );
00133 
00134     // create accels for global shortcuts
00135     m_globalAccel = new KGlobalAccel( this, "global accel" );
00136     m_globalAccel->insert( "global_new_note", i18n("New Note"), "",
00137                            ALT+SHIFT+Key_N, ALT+SHIFT+Key_N ,
00138                            this, SLOT(newNote()), true, true );
00139     m_globalAccel->insert( "global_new_note_clipboard", i18n("New Note From Clipboard"), "",
00140                            ALT+SHIFT+Key_C, ALT+SHIFT+Key_C,
00141                            this, SLOT(newNoteFromClipboard()), true, true );
00142 //    m_globalAccel->insert( "global_hide_all_notes", i18n("Hide All Notes"), "",
00143 //                           ALT+SHIFT+Key_H, ALT+SHIFT+Key_H ,
00144 //                           this, SLOT(hideAllNotes()), true, true );
00145 //    m_globalAccel->insert( "global_show_all_notes", i18n("Show All Notes"), "",
00146 //                           ALT+SHIFT+Key_S, ALT+SHIFT+Key_S,
00147 //                           this, SLOT(showAllNotes()), true, true );
00148 
00149     m_globalAccel->readSettings();
00150 
00151     KConfig *config = KGlobal::config();
00152     config->setGroup( "Global Keybindings" );
00153     m_globalAccel->setEnabled( config->readBoolEntry( "Enabled", true ) );
00154 
00155     updateGlobalAccels();
00156 
00157     // clean up old config files
00158     KNotesLegacy::cleanUp();
00159 
00160     // create the resource manager
00161     m_manager = new KNotesResourceManager();
00162     connect( m_manager, SIGNAL(sigRegisteredNote( KCal::Journal * )),
00163              this,      SLOT(createNote( KCal::Journal * )) );
00164     connect( m_manager, SIGNAL(sigDeregisteredNote( KCal::Journal * )),
00165              this,      SLOT(killNote( KCal::Journal * )) );
00166 
00167     // read the notes
00168     m_manager->load();
00169 
00170     // read the old config files, convert and add them
00171     KCal::CalendarLocal calendar;
00172     if ( KNotesLegacy::convert( &calendar ) )
00173     {
00174         KCal::Journal::List notes = calendar.journals();
00175         KCal::Journal::List::ConstIterator it;
00176         for ( it = notes.begin(); it != notes.end(); ++it )
00177             m_manager->addNewNote( *it );
00178 
00179         m_manager->save();
00180     }
00181 
00182     // create the socket and possibly start listening for connections
00183     m_listener = new KExtendedSocket();
00184     m_listener->setSocketFlags( KExtendedSocket::passiveSocket | KExtendedSocket::inetSocket );
00185     connect( m_listener, SIGNAL(readyAccept()), SLOT(acceptConnection()) );
00186     updateNetworkListener();
00187 
00188     if ( m_noteList.count() == 0 && !kapp->isRestored() )
00189         newNote();
00190 
00191     updateNoteActions();  // in case there is no note yet
00192 }
00193 
00194 KNotesApp::~KNotesApp()
00195 {
00196     saveNotes();
00197 
00198     blockSignals( true );
00199     m_noteList.clear();
00200     blockSignals( false );
00201 
00202     delete m_listener;
00203     delete m_manager;
00204     delete m_guiBuilder;
00205 }
00206 
00207 bool KNotesApp::commitData( QSessionManager& )
00208 {
00209     saveConfigs();
00210     return true;
00211 }
00212 
00213 // -------------------- public DCOP interface -------------------- //
00214 
00215 QString KNotesApp::newNote( const QString& name, const QString& text )
00216 {
00217     // create the new note
00218     KCal::Journal *journal = new KCal::Journal();
00219 
00220     // new notes have the current date/time as title if none was given
00221     if ( !name.isEmpty() )
00222         journal->setSummary( name );
00223     else
00224         journal->setSummary( KGlobal::locale()->formatDateTime( QDateTime::currentDateTime() ) );
00225 
00226     // the body of the note
00227     journal->setDescription( text );
00228 
00229     m_manager->addNewNote( journal );
00230 
00231     showNote( journal->uid() );
00232 
00233     return journal->uid();
00234 }
00235 
00236 QString KNotesApp::newNoteFromClipboard( const QString& name )
00237 {
00238     const QString& text = KApplication::clipboard()->text();
00239     return newNote( name, text );
00240 }
00241 
00242 void KNotesApp::hideAllNotes() const
00243 {
00244     QDictIterator<KNote> it( m_noteList );
00245     for ( ; *it; ++it )
00246         (*it)->close();
00247 }
00248 
00249 void KNotesApp::showAllNotes() const
00250 {
00251     QDictIterator<KNote> it( m_noteList );
00252     for ( ; *it; ++it )
00253     {
00254         (*it)->show();
00255         (*it)->setFocus();
00256     }
00257 }
00258 
00259 void KNotesApp::showNote( const QString& id ) const
00260 {
00261     KNote* note = m_noteList[id];
00262     if ( note )
00263         showNote( note );
00264     else
00265         kdWarning(5500) << "showNote: no note with id: " << id << endl;
00266 }
00267 
00268 void KNotesApp::hideNote( const QString& id ) const
00269 {
00270     KNote* note = m_noteList[id];
00271     if ( note )
00272         note->hide();
00273     else
00274         kdWarning(5500) << "hideNote: no note with id: " << id << endl;
00275 }
00276 
00277 void KNotesApp::killNote( const QString& id, bool force )
00278 {
00279     KNote* note = m_noteList[id];
00280     if ( note )
00281         note->slotKill( force );
00282     else
00283         kdWarning(5500) << "killNote: no note with id: " << id << endl;
00284 }
00285 
00286 // "bool force = false" doesn't work with dcop
00287 void KNotesApp::killNote( const QString& id )
00288 {
00289     killNote( id, false );
00290 }
00291 
00292 QMap<QString,QString> KNotesApp::notes() const
00293 {
00294     QMap<QString,QString> notes;
00295     QDictIterator<KNote> it( m_noteList );
00296 
00297     for ( ; it.current(); ++it )
00298         notes.insert( it.current()->noteId(), it.current()->name() );
00299 
00300     return notes;
00301 }
00302 
00303 QString KNotesApp::name( const QString& id ) const
00304 {
00305     KNote* note = m_noteList[id];
00306     if ( note )
00307         return note->name();
00308     else
00309         return QString::null;
00310 }
00311 
00312 QString KNotesApp::text( const QString& id ) const
00313 {
00314     KNote* note = m_noteList[id];
00315     if ( note )
00316         return note->text();
00317     else
00318         return QString::null;
00319 }
00320 
00321 void KNotesApp::setName( const QString& id, const QString& newName )
00322 {
00323     KNote* note = m_noteList[id];
00324     if ( note )
00325         note->setName( newName );
00326     else
00327         kdWarning(5500) << "setName: no note with id: " << id << endl;
00328 }
00329 
00330 void KNotesApp::setText( const QString& id, const QString& newText )
00331 {
00332     KNote* note = m_noteList[id];
00333     if ( note )
00334         note->setText( newText );
00335     else
00336         kdWarning(5500) << "setText: no note with id: " << id << endl;
00337 }
00338 
00339 void KNotesApp::sync( const QString& app )
00340 {
00341     QDictIterator<KNote> it( m_noteList );
00342 
00343     for ( ; it.current(); ++it )
00344         it.current()->sync( app );
00345 }
00346 
00347 bool KNotesApp::isNew( const QString& app, const QString& id ) const
00348 {
00349     KNote* note = m_noteList[id];
00350     if ( note )
00351         return note->isNew( app );
00352     else
00353         return false;
00354 }
00355 
00356 bool KNotesApp::isModified( const QString& app, const QString& id ) const
00357 {
00358     KNote* note = m_noteList[id];
00359     if ( note )
00360         return note->isModified( app );
00361     else
00362         return false;
00363 }
00364 
00365 
00366 // ------------------- protected methods ------------------- //
00367 
00368 void KNotesApp::mousePressEvent( QMouseEvent* e )
00369 {
00370     if ( !rect().contains( e->pos() ) )
00371         return;
00372 
00373     switch ( e->button() )
00374     {
00375     case LeftButton:
00376         if ( m_noteList.count() == 1 )
00377         {
00378             QDictIterator<KNote> it( m_noteList );
00379             showNote( it.toFirst() );
00380         }
00381         else if ( m_note_menu->count() > 0 )
00382             m_note_menu->popup( e->globalPos() );
00383         break;
00384     case MidButton:
00385         newNote();
00386         break;
00387     case RightButton:
00388         m_context_menu->popup( e->globalPos() );
00389     default: break;
00390     }
00391 }
00392 
00393 // -------------------- protected slots -------------------- //
00394 
00395 void KNotesApp::slotShowNote()
00396 {
00397     // tell the WM to give this note focus
00398     showNote( QString::fromUtf8( sender()->name() ) );
00399 }
00400 
00401 void KNotesApp::slotWalkThroughNotes()
00402 {
00403     // show next note
00404     QDictIterator<KNote> it( m_noteList );
00405     KNote *first = it.toFirst();
00406     for ( ; *it; ++it )
00407         if ( (*it)->hasFocus() )
00408         {
00409             if ( ++it )
00410                 showNote( *it );
00411             else
00412                 showNote( first );
00413             break;
00414         }
00415 }
00416 
00417 void KNotesApp::slotPreferences()
00418 {
00419     // reuse the dialog if possible
00420     if ( KNoteConfigDlg::showDialog( "KNotes Default Settings" ) )
00421         return;
00422 
00423     // create a new preferences dialog...
00424     KNoteConfigDlg *dialog = new KNoteConfigDlg( 0, i18n("Settings"), this,
00425                                                  "KNotes Settings" );
00426     connect( dialog, SIGNAL(settingsChanged()), this, SLOT(updateNetworkListener()) );
00427     dialog->show();
00428 }
00429 
00430 void KNotesApp::slotConfigureAccels()
00431 {
00432     KNotesKeyDialog keys( m_globalAccel, this );
00433     QDictIterator<KNote> notes( m_noteList );
00434     if ( !m_noteList.isEmpty() )
00435         keys.insert( (*notes)->actionCollection() );
00436     keys.configure();
00437 
00438     m_globalAccel->writeSettings();
00439     updateGlobalAccels();
00440 
00441     // update GUI doc for new notes
00442     m_noteGUI.setContent(
00443         KXMLGUIFactory::readConfigFile( instance()->instanceName() + "ui.rc", instance() )
00444     );
00445 
00446     if ( m_noteList.isEmpty() )
00447         return;
00448 
00449     notes.toFirst();
00450     QValueList<KAction *> list = (*notes)->actionCollection()->actions();
00451     for ( QValueList<KAction *>::iterator it = list.begin(); it != list.end(); ++it )
00452     {
00453         notes.toFirst();
00454         for ( ++notes; *notes; ++notes )
00455         {
00456             KAction *toChange = (*notes)->actionCollection()->action( (*it)->name() );
00457             if ( toChange->shortcut() != (*it)->shortcut() )
00458                 toChange->setShortcut( (*it)->shortcut() );
00459         }
00460     }
00461 }
00462 
00463 void KNotesApp::slotNoteKilled( KCal::Journal *journal )
00464 {
00465     m_manager->deleteNote( journal );
00466 
00467     saveNotes();
00468     updateNoteActions();
00469 }
00470 
00471 void KNotesApp::slotQuit()
00472 {
00473     QDictIterator<KNote> it( m_noteList );
00474 
00475     for ( ; *it; ++it )
00476         if ( (*it)->isModified() )
00477             (*it)->saveData();
00478 
00479     saveConfigs();
00480     kapp->quit();
00481 }
00482 
00483 
00484 // -------------------- private methods -------------------- //
00485 
00486 void KNotesApp::showNote( KNote* note ) const
00487 {
00488     note->show();
00489     KWin::setCurrentDesktop( KWin::windowInfo( note->winId() ).desktop() );
00490     KWin::forceActiveWindow( note->winId() );
00491     note->setFocus();
00492 }
00493 
00494 void KNotesApp::createNote( KCal::Journal *journal )
00495 {
00496     KNote *newNote = new KNote( m_noteGUI, journal, 0, journal->uid().utf8() );
00497     m_noteList.insert( newNote->noteId(), newNote );
00498 
00499     connect( newNote, SIGNAL(sigRequestNewNote()), SLOT(newNote()) );
00500     connect( newNote, SIGNAL(sigShowNextNote()), SLOT(slotWalkThroughNotes()) );
00501     connect( newNote, SIGNAL(sigKillNote( KCal::Journal* )),
00502                         SLOT(slotNoteKilled( KCal::Journal* )) );
00503     connect( newNote, SIGNAL(sigNameChanged()), SLOT(updateNoteActions()) );
00504     connect( newNote, SIGNAL(sigDataChanged()), SLOT(saveNotes()) );
00505     connect( newNote, SIGNAL(sigColorChanged()), SLOT(updateNoteActions()) );
00506 
00507     updateNoteActions();
00508 }
00509 
00510 void KNotesApp::killNote( KCal::Journal *journal )
00511 {
00512     // this kills the KNote object
00513     m_noteList.remove( journal->uid() );
00514     updateNoteActions();
00515 }
00516 
00517 void KNotesApp::acceptConnection()
00518 {
00519     // Accept the connection and make KNotesNetworkReceiver do the job
00520     KExtendedSocket *s;
00521     m_listener->accept( s );
00522     KNotesNetworkReceiver *recv = new KNotesNetworkReceiver( s );
00523     connect( recv, SIGNAL(sigNoteReceived( const QString &, const QString & )),
00524              this, SLOT(newNote( const QString &, const QString & )) );
00525 }
00526 
00527 void KNotesApp::saveNotes()
00528 {
00529     m_manager->save();
00530 }
00531 
00532 void KNotesApp::saveConfigs()
00533 {
00534     QDictIterator<KNote> it( m_noteList );
00535     for ( ; it.current(); ++it )
00536         it.current()->saveConfig();
00537 }
00538 
00539 void KNotesApp::updateNoteActions()
00540 {
00541     unplugActionList( "notes" );
00542     m_noteActions.clear();
00543 
00544     for ( QDictIterator<KNote> it( m_noteList ); it.current(); ++it )
00545     {
00546         KAction *action = new KAction( it.current()->name().replace("&", "&&"),
00547                                        KShortcut(), this, SLOT(slotShowNote()),
00548                                        (QObject *)0,
00549                                        it.current()->noteId().utf8() );
00550         KIconEffect effect;
00551         QPixmap icon = effect.apply( kapp->miniIcon(), KIconEffect::Colorize, 1,
00552                                      it.current()->paletteBackgroundColor(), false );
00553         action->setIconSet( icon );
00554         m_noteActions.append( action );
00555     }
00556 
00557     m_noteActions.sort();
00558 
00559     if ( m_noteActions.isEmpty() )
00560     {
00561         KAction *action = new KAction( i18n("No Notes") );
00562         m_noteActions.append( action );
00563     }
00564 
00565     plugActionList( "notes", m_noteActions );
00566 }
00567 
00568 void KNotesApp::updateGlobalAccels()
00569 {
00570     if ( m_globalAccel->isEnabled() )
00571     {
00572         KAction *action = actionCollection()->action( "new_note" );
00573         if ( action )
00574             action->setShortcut( m_globalAccel->shortcut( "global_new_note" ) );
00575         action = actionCollection()->action( "new_note_clipboard" );
00576         if ( action )
00577             action->setShortcut( m_globalAccel->shortcut( "global_new_note_clipboard" ) );
00578         action = actionCollection()->action( "hide_all_notes" );
00579         if ( action )
00580             action->setShortcut( m_globalAccel->shortcut( "global_hide_all_notes" ) );
00581         action = actionCollection()->action( "show_all_notes" );
00582         if ( action )
00583             action->setShortcut( m_globalAccel->shortcut( "global_show_all_notes" ) );
00584 
00585         m_globalAccel->updateConnections();
00586     }
00587     else
00588     {
00589         KAction *action = actionCollection()->action( "new_note" );
00590         if ( action )
00591             action->setShortcut( 0 );
00592         action = actionCollection()->action( "new_note_clipboard" );
00593         if ( action )
00594             action->setShortcut( 0 );
00595         action = actionCollection()->action( "hide_all_notes" );
00596         if ( action )
00597             action->setShortcut( 0 );
00598         action = actionCollection()->action( "show_all_notes" );
00599         if ( action )
00600             action->setShortcut( 0 );
00601     }
00602 }
00603 
00604 void KNotesApp::updateNetworkListener()
00605 {
00606     m_listener->reset();
00607 
00608     if ( KNotesGlobalConfig::receiveNotes() )
00609     {
00610         m_listener->setPort( KNotesGlobalConfig::port() );
00611         m_listener->listen();
00612     }
00613 }
00614 
00615 #include "knotesapp.moc"
KDE Logo
This file is part of the documentation for knotes Library Version 3.3.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Wed Jan 31 15:53:19 2007 by doxygen 1.4.2 written by Dimitri van Heesch, © 1997-2003