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
#include <qptrlist.h>
00023
#include <qtooltip.h>
00024
00025
#include <kdebug.h>
00026
#include <kaction.h>
00027
#include <kxmlguifactory.h>
00028
#include <ksystemtray.h>
00029
#include <klocale.h>
00030
#include <kiconeffect.h>
00031
#include <kstandarddirs.h>
00032
#include <kpopupmenu.h>
00033
#include <khelpmenu.h>
00034
#include <kkeydialog.h>
00035
#include <kglobalaccel.h>
00036
#include <ksimpleconfig.h>
00037
#include <kwin.h>
00038
#include <kextsock.h>
00039
00040
#include <libkcal/journal.h>
00041
00042
#include "knotesapp.h"
00043
#include "knote.h"
00044
#include "knoteconfig.h"
00045
#include "knoteconfigdlg.h"
00046
#include "knotesglobalconfig.h"
00047
#include "knoteslegacy.h"
00048
#include "knotesnetrecv.h"
00049
00050
#include "knotes/resourcemanager.h"
00051
00052
00053
int KNotesApp::KNoteActionList::compareItems( QPtrCollection::Item s1, QPtrCollection::Item s2 )
00054 {
00055
if ( ((KAction*)s1)->text() == ((KAction*)s2)->text() )
00056
return 0;
00057
return ( ((KAction*)s1)->text() < ((KAction*)s2)->text() ? -1 : 1 );
00058 }
00059
00060
00061 KNotesApp::KNotesApp()
00062 : DCOPObject("KNotesIface"),
QLabel( 0, 0, WType_TopLevel ),
00063 KXMLGUIBuilder( this ),
00064 m_listener( 0 )
00065 {
00066 connect( kapp, SIGNAL(lastWindowClosed()), kapp, SLOT(quit()) );
00067
00068 m_noteList.setAutoDelete(
true );
00069 m_noteActions.setAutoDelete(
true );
00070
00071
00072 KWin::setSystemTrayWindowFor( winId(), qt_xrootwin() );
00073 QToolTip::add(
this, i18n(
"KNotes: Sticky notes for KDE" ) );
00074 setBackgroundMode( X11ParentRelative );
00075 setPixmap( KSystemTray::loadIcon(
"knotes" ) );
00076
00077
00078
new KAction( i18n(
"New Note"),
"filenew", 0,
00079
this, SLOT(newNote()), actionCollection(),
"new_note" );
00080
new KAction( i18n(
"New Note From Clipboard"),
"editpaste", 0,
00081
this, SLOT(newNoteFromClipboard()), actionCollection(),
"new_note_clipboard" );
00082
new KHelpMenu(
this, kapp->aboutData(),
false, actionCollection() );
00083
00084 KStdAction::preferences(
this, SLOT(slotPreferences()), actionCollection() );
00085 KStdAction::keyBindings(
this, SLOT(slotConfigureAccels()), actionCollection() );
00086 KStdAction::quit(
this, SLOT(slotQuit()), actionCollection() )->setShortcut( 0 );
00087
00088 setXMLFile(
QString( instance()->instanceName() +
"ui.rc" ) );
00089
00090 m_guiFactory =
new KXMLGUIFactory(
this,
this,
"guifactory" );
00091 m_guiFactory->addClient(
this );
00092
00093 m_context_menu = static_cast<KPopupMenu*>(m_guiFactory->container(
"knotes_context",
this ));
00094 m_note_menu = static_cast<KPopupMenu*>(m_guiFactory->container(
"notes_menu",
this ));
00095
00096
00097 m_globalAccel =
new KGlobalAccel(
this,
"global accel" );
00098 m_globalAccel->insert(
"global_new_note", i18n(
"New Note"),
"",
00099 ALT+SHIFT+Key_N, ALT+SHIFT+Key_N ,
00100
this, SLOT(newNote()),
true,
true );
00101 m_globalAccel->insert(
"global_new_note_clipboard", i18n(
"New Note From Clipboard"),
"",
00102 ALT+SHIFT+Key_C, ALT+SHIFT+Key_C,
00103
this, SLOT(newNoteFromClipboard()),
true,
true );
00104
00105 m_globalAccel->readSettings();
00106
00107 KConfig *config = KGlobal::config();
00108 config->setGroup(
"Global Keybindings" );
00109 m_globalAccel->setEnabled( config->readBoolEntry(
"Enabled",
true ) );
00110
00111 updateGlobalAccels();
00112
00113
00114 KNotesLegacy::cleanUp();
00115
00116
00117 m_manager =
new KNotesResourceManager();
00118 connect( m_manager, SIGNAL(sigRegisteredNote( KCal::Journal * )),
00119
this, SLOT(createNote( KCal::Journal * )) );
00120 connect( m_manager, SIGNAL(sigDeregisteredNote( KCal::Journal * )),
00121
this, SLOT(killNote( KCal::Journal * )) );
00122
00123
00124 m_manager->load();
00125
00126 kapp->installEventFilter(
this );
00127
00128
00129 m_listener =
new KExtendedSocket();
00130 m_listener->setSocketFlags( KExtendedSocket::passiveSocket | KExtendedSocket::inetSocket );
00131 connect( m_listener, SIGNAL(readyAccept()), SLOT(acceptConnection()) );
00132 updateNetworkListener();
00133
00134
if ( m_noteList.count() == 0 && !kapp->isRestored() )
00135 newNote();
00136 }
00137
00138 KNotesApp::~KNotesApp()
00139 {
00140 saveNotes();
00141
00142 blockSignals(
true );
00143 m_noteList.clear();
00144 blockSignals(
false );
00145
00146
delete m_listener;
00147
delete m_manager;
00148 }
00149
00150
bool KNotesApp::commitData(
QSessionManager& )
00151 {
00152 saveConfigs();
00153
return true;
00154 }
00155
00156
00157
00158
QString KNotesApp::newNote(
const QString& name,
const QString& text )
00159 {
00160
00161 KCal::Journal *journal =
new KCal::Journal();
00162
00163
00164
if ( !name.isEmpty() )
00165 journal->setSummary( name );
00166
else
00167 journal->setSummary( KGlobal::locale()->formatDateTime( QDateTime::currentDateTime() ) );
00168
00169
00170 journal->setDescription( text );
00171
00172 m_manager->addNewNote( journal );
00173
00174 showNote( journal->uid() );
00175
00176
return journal->uid();
00177 }
00178
00179
QString KNotesApp::newNoteFromClipboard(
const QString& name )
00180 {
00181
const QString& text = KApplication::clipboard()->text();
00182
return newNote( name, text );
00183 }
00184
00185
void KNotesApp::showNote(
const QString&
id )
const
00186
{
00187 KNote* note = m_noteList[
id];
00188
if ( note )
00189 showNote( note );
00190
else
00191 kdWarning(5500) <<
"showNote: no note with id: " <<
id << endl;
00192 }
00193
00194
void KNotesApp::hideNote(
const QString&
id )
const
00195
{
00196 KNote* note = m_noteList[
id];
00197
if ( note )
00198 note->hide();
00199
else
00200 kdWarning(5500) <<
"hideNote: no note with id: " <<
id << endl;
00201 }
00202
00203
void KNotesApp::killNote(
const QString&
id,
bool force )
00204 {
00205 KNote* note = m_noteList[
id];
00206
if ( note )
00207 note->slotKill( force );
00208
else
00209 kdWarning(5500) <<
"killNote: no note with id: " <<
id << endl;
00210 }
00211
00212
00213
void KNotesApp::killNote(
const QString&
id )
00214 {
00215 killNote(
id,
false );
00216 }
00217
00218
QMap<QString,QString> KNotesApp::notes()
const
00219
{
00220
QMap<QString,QString> notes;
00221
QDictIterator<KNote> it( m_noteList );
00222
00223
for ( ; it.current(); ++it )
00224 notes.insert( it.current()->noteId(), it.current()->name() );
00225
00226
return notes;
00227 }
00228
00229
QString KNotesApp::name(
const QString&
id )
const
00230
{
00231 KNote* note = m_noteList[
id];
00232
if ( note )
00233
return note->name();
00234
else
00235
return QString::null;
00236 }
00237
00238
QString KNotesApp::text(
const QString&
id )
const
00239
{
00240 KNote* note = m_noteList[
id];
00241
if ( note )
00242
return note->text();
00243
else
00244
return QString::null;
00245 }
00246
00247
void KNotesApp::setName(
const QString&
id,
const QString& newName )
00248 {
00249 KNote* note = m_noteList[
id];
00250
if ( note )
00251 note->setName( newName );
00252
else
00253 kdWarning(5500) <<
"setName: no note with id: " <<
id << endl;
00254 }
00255
00256
void KNotesApp::setText(
const QString&
id,
const QString& newText )
00257 {
00258 KNote* note = m_noteList[
id];
00259
if ( note )
00260 note->setText( newText );
00261
else
00262 kdWarning(5500) <<
"setText: no note with id: " <<
id << endl;
00263 }
00264
00265
void KNotesApp::sync(
const QString& app )
00266 {
00267
QDictIterator<KNote> it( m_noteList );
00268
00269
for ( ; it.current(); ++it )
00270 it.current()->sync( app );
00271 }
00272
00273
bool KNotesApp::isNew(
const QString& app,
const QString&
id )
const
00274
{
00275 KNote* note = m_noteList[
id];
00276
if ( note )
00277
return note->isNew( app );
00278
else
00279
return false;
00280 }
00281
00282
bool KNotesApp::isModified(
const QString& app,
const QString&
id )
const
00283
{
00284 KNote* note = m_noteList[
id];
00285
if ( note )
00286
return note->isModified( app );
00287
else
00288
return false;
00289 }
00290
00291
00292
00293
00294
void KNotesApp::mousePressEvent(
QMouseEvent* e )
00295 {
00296
if ( !rect().contains( e->pos() ) )
00297
return;
00298
00299
switch ( e->button() )
00300 {
00301
case LeftButton:
00302
if ( m_noteList.count() == 1 )
00303 {
00304
QDictIterator<KNote> it( m_noteList );
00305 showNote( it.toFirst() );
00306 }
00307
else if ( m_note_menu->count() > 0 )
00308 m_note_menu->popup( e->globalPos() );
00309
break;
00310
case MidButton:
00311 newNote();
00312
break;
00313
case RightButton:
00314 m_context_menu->popup( e->globalPos() );
00315
default:
break;
00316 }
00317 }
00318
00319
bool KNotesApp::eventFilter(
QObject* o,
QEvent* ev )
00320 {
00321
if ( ev->type() == QEvent::KeyPress )
00322 {
00323
QKeyEvent* ke = (
QKeyEvent*)ev;
00324
00325
if ( ke->key() == Key_BackTab )
00326 {
00327
00328
QDictIterator<KNote> it( m_noteList );
00329 KNote *first = it.toFirst();
00330
for ( ; it.current(); ++it )
00331
if ( it.current()->hasFocus() )
00332 {
00333
if ( ++it )
00334 showNote( it.current() );
00335
else
00336 showNote( first );
00337
break;
00338 }
00339
00340 ke->accept();
00341
return true;
00342 }
00343
else
00344 ke->ignore();
00345 }
00346
00347
return QLabel::eventFilter( o, ev );
00348 }
00349
00350
00351
00352
00353
void KNotesApp::slotShowNote()
00354 {
00355
00356 showNote( QString::fromUtf8( sender()->name() ) );
00357 }
00358
00359
void KNotesApp::slotPreferences()
00360 {
00361
00362
if ( KNoteConfigDlg::showDialog(
"KNotes Default Settings" ) )
00363
return;
00364
00365
00366 KNoteConfigDlg *dialog =
new KNoteConfigDlg( 0, i18n(
"Settings"),
this,
00367
"KNotes Settings" );
00368 connect( dialog, SIGNAL(settingsChanged()),
this, SLOT(updateNetworkListener()) );
00369 dialog->show();
00370 }
00371
00372
void KNotesApp::slotConfigureAccels()
00373 {
00374 KKeyDialog keys(
false,
this );
00375 keys.insert( actionCollection() );
00376
QDictIterator<KNote> notes( m_noteList );
00377
if ( !m_noteList.isEmpty() )
00378 keys.insert( notes.current()->actionCollection() );
00379 keys.configure();
00380
00381 notes.toFirst();
00382
for( ; notes.current(); ++notes )
00383 notes.current()->reloadXML();
00384
00385 m_globalAccel->writeSettings();
00386 updateGlobalAccels();
00387 }
00388
00389
void KNotesApp::slotNoteKilled( KCal::Journal *journal )
00390 {
00391
00392 m_noteList.remove( journal->uid() );
00393 m_manager->deleteNote( journal );
00394
00395 saveNotes();
00396 updateNoteActions();
00397 }
00398
00399
void KNotesApp::slotQuit()
00400 {
00401 saveConfigs();
00402 kapp->quit();
00403 }
00404
00405
00406
00407
00408
void KNotesApp::showNote( KNote* note )
const
00409
{
00410
if ( !note->isHidden() )
00411 {
00412
00413
00414 KWin::setCurrentDesktop( KWin::windowInfo( note->winId() ).desktop() );
00415 KWin::forceActiveWindow( note->winId() );
00416 note->setFocus();
00417 }
00418
else
00419 {
00420
00421 note->show();
00422 note->toDesktop( KWin::currentDesktop() );
00423 KWin::forceActiveWindow( note->winId() );
00424 note->setFocus();
00425 }
00426 }
00427
00428
void KNotesApp::createNote( KCal::Journal *journal )
00429 {
00430 KNote *newNote =
new KNote(
this, domDocument(), journal,
00431 0, journal->uid().utf8() );
00432 m_noteList.insert( newNote->noteId(), newNote );
00433
00434 connect( newNote, SIGNAL(sigRequestNewNote()), SLOT(newNote()) );
00435 connect( newNote, SIGNAL(sigKillNote( KCal::Journal* )),
00436 SLOT(slotNoteKilled( KCal::Journal* )) );
00437 connect( newNote, SIGNAL(sigNameChanged()), SLOT(updateNoteActions()) );
00438 connect( newNote, SIGNAL(sigDataChanged()), SLOT(saveNotes()) );
00439 connect( newNote, SIGNAL(sigColorChanged()), SLOT(updateNoteActions()) );
00440
00441 updateNoteActions();
00442 }
00443
00444
void KNotesApp::killNote( KCal::Journal *journal )
00445 {
00446
00447 m_noteList.remove( journal->uid() );
00448 updateNoteActions();
00449 }
00450
00451
void KNotesApp::acceptConnection()
00452 {
00453
00454 KExtendedSocket *s;
00455 m_listener->accept( s );
00456 KNotesNetworkReceiver *recv =
new KNotesNetworkReceiver( s );
00457 connect( recv, SIGNAL(sigNoteReceived(
const QString &,
const QString & )),
00458
this, SLOT(newNote(
const QString &,
const QString & )) );
00459 }
00460
00461
void KNotesApp::saveNotes()
00462 {
00463 m_manager->save();
00464 }
00465
00466
void KNotesApp::saveConfigs()
00467 {
00468
QDictIterator<KNote> it( m_noteList );
00469
for ( ; it.current(); ++it )
00470 it.current()->saveConfig();
00471 }
00472
00473
void KNotesApp::updateNoteActions()
00474 {
00475 unplugActionList(
"notes" );
00476 m_noteActions.clear();
00477
00478
for (
QDictIterator<KNote> it( m_noteList ); it.current(); ++it )
00479 {
00480 KAction *action =
new KAction( it.current()->name().replace(
"&",
"&&"),
00481 KShortcut(),
this, SLOT(slotShowNote()),
00482 (
QObject *)0,
00483 it.current()->noteId().utf8() );
00484 KIconEffect effect;
00485
QPixmap icon = effect.apply( kapp->miniIcon(), KIconEffect::Colorize, 1,
00486 it.current()->paletteBackgroundColor(),
false );
00487 action->setIconSet( icon );
00488 m_noteActions.append( action );
00489 }
00490
00491 m_noteActions.sort();
00492
00493
if ( m_noteActions.isEmpty() )
00494 {
00495 KAction *action =
new KAction( i18n(
"No Notes") );
00496 m_noteActions.append( action );
00497 }
00498
00499 plugActionList(
"notes", m_noteActions );
00500 }
00501
00502
void KNotesApp::updateGlobalAccels()
00503 {
00504
if ( m_globalAccel->isEnabled() )
00505 {
00506 KAction *action = actionCollection()->action(
"new_note" );
00507
if ( action )
00508 action->setShortcut( m_globalAccel->shortcut(
"global_new_note" ) );
00509 action = actionCollection()->action(
"new_note_clipboard" );
00510
if ( action )
00511 action->setShortcut( m_globalAccel->shortcut(
"global_new_note_clipboard" ) );
00512
00513 m_globalAccel->updateConnections();
00514 }
00515
else
00516 {
00517 KAction *action = actionCollection()->action(
"new_note" );
00518
if ( action )
00519 action->setShortcut( 0 );
00520 action = actionCollection()->action(
"new_note_clipboard" );
00521
if ( action )
00522 action->setShortcut( 0 );
00523 }
00524 }
00525
00526
void KNotesApp::updateNetworkListener()
00527 {
00528 m_listener->reset();
00529
00530
if ( KNotesGlobalConfig::receiveNotes() )
00531 {
00532 m_listener->setPort( KNotesGlobalConfig::port() );
00533 m_listener->listen();
00534 }
00535 }
00536
00537
#include "knotesapp.moc"