00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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
00054 KWin::setSystemTrayWindowFor( winId(), qt_xrootwin() );
00055 setBackgroundMode( X11ParentRelative );
00056 setPixmap( KGlobal::iconLoader()->loadIcon( "knotes", KIcon::Small ) );
00057
00058
00059
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
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
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
00105 }
00106 } else
00107 delete test;
00108
00109
00110 QDir noteDir( KGlobal::dirs()->saveLocation( "appdata", "notes/" ) );
00111
00112
00113 QStringList notes = noteDir.entryList( QDir::Files, QDir::Name );
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
00134 notes = noteDir.entryList( QDir::Files, QDir::Name );
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
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
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
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
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
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 )
00457 {
00458
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
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
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
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
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
00565
00566 KWin::setCurrentDesktop( KWin::info( note->winId() ).desktop );
00567 KWin::setActiveWindow( note->winId() );
00568 note->setFocus();
00569 }
00570 else
00571 {
00572
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
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"