00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <qlabel.h>
00022 #include <qdrawutil.h>
00023 #include <qsize.h>
00024 #include <qsizegrip.h>
00025 #include <qbitmap.h>
00026 #include <qcursor.h>
00027 #include <qpainter.h>
00028 #include <qpaintdevicemetrics.h>
00029 #include <qsimplerichtext.h>
00030 #include <qobjectlist.h>
00031 #include <qfile.h>
00032 #include <qcheckbox.h>
00033
00034 #include <kapplication.h>
00035 #include <kdebug.h>
00036 #include <kaction.h>
00037 #include <kstdaction.h>
00038 #include <kcombobox.h>
00039 #include <ktoolbar.h>
00040 #include <kpopupmenu.h>
00041 #include <kxmlguibuilder.h>
00042 #include <kxmlguifactory.h>
00043 #include <kcolordrag.h>
00044 #include <kiconeffect.h>
00045 #include <klocale.h>
00046 #include <kstandarddirs.h>
00047 #include <kmessagebox.h>
00048 #include <kfind.h>
00049 #include <kprocess.h>
00050 #include <kinputdialog.h>
00051 #include <kmdcodec.h>
00052 #include <kglobalsettings.h>
00053 #include <kfiledialog.h>
00054 #include <kio/netaccess.h>
00055
00056 #include <libkcal/journal.h>
00057
00058 #include "knote.h"
00059 #include "knotebutton.h"
00060 #include "knoteedit.h"
00061 #include "knoteconfig.h"
00062 #include "knotesglobalconfig.h"
00063 #include "knoteconfigdlg.h"
00064 #include "knotealarmdlg.h"
00065 #include "knotehostdlg.h"
00066 #include "knotesnetsend.h"
00067 #include "knoteprinter.h"
00068 #include "version.h"
00069
00070 #include "pushpin.xpm"
00071
00072 #include <kwin.h>
00073 #include <netwm.h>
00074
00075 #include <fixx11h.h>
00076
00077 using namespace KCal;
00078
00079 extern Time qt_x_time;
00080
00081 int KNote::s_ppOffset = 0;
00082
00083 KNote::KNote( QDomDocument buildDoc, Journal *j, QWidget *parent, const char *name )
00084 : QFrame( parent, name, WStyle_Customize | WStyle_NoBorder | WDestructiveClose ),
00085 m_label( 0 ), m_pushpin( 0 ), m_fold( 0 ), m_button( 0 ), m_tool( 0 ), m_editor( 0 ),
00086 m_config( 0 ), m_journal( j ), m_find( 0 ),
00087 m_kwinConf( KSharedConfig::openConfig( "kwinrc", true ) ),
00088 m_busy( 0 ), m_deleteWhenIdle( false )
00089 {
00090 setAcceptDrops( true );
00091 actionCollection()->setWidget( this );
00092
00093 setDOMDocument( buildDoc );
00094
00095
00096 setXMLFile( instance()->instanceName() + "ui.rc", false, false );
00097
00098
00099
00100 if ( m_journal->summary().isNull() && m_journal->dtStart().isValid() )
00101 {
00102 QString s = KGlobal::locale()->formatDateTime( m_journal->dtStart() );
00103 m_journal->setSummary( s );
00104 }
00105
00106
00107
00108 new KAction( i18n("New"), "filenew", 0,
00109 this, SIGNAL(sigRequestNewNote()), actionCollection(), "new_note" );
00110 new KAction( i18n("Rename..."), "text", 0,
00111 this, SLOT(slotRename()), actionCollection(), "rename_note" );
00112 m_readOnly = new KToggleAction( i18n("Lock"), "lock" , 0,
00113 this, SLOT(slotUpdateReadOnly()), actionCollection(), "lock_note" );
00114 m_readOnly->setCheckedState( KGuiItem( i18n("Unlock"), "unlock" ) );
00115 new KAction( i18n("Hide"), "fileclose" , Key_Escape,
00116 this, SLOT(slotClose()), actionCollection(), "hide_note" );
00117 new KAction( i18n("Delete"), "knotes_delete", 0,
00118 this, SLOT(slotKill()), actionCollection(), "delete_note" );
00119
00120 new KAction( i18n("Insert Date"), "knotes_date", 0 ,
00121 this, SLOT(slotInsDate()), actionCollection(), "insert_date" );
00122 new KAction( i18n("Set Alarm..."), "knotes_alarm", 0 ,
00123 this, SLOT(slotSetAlarm()), actionCollection(), "set_alarm" );
00124
00125 new KAction( i18n("Send..."), "network", 0,
00126 this, SLOT(slotSend()), actionCollection(), "send_note" );
00127 new KAction( i18n("Mail..."), "mail_send", 0,
00128 this, SLOT(slotMail()), actionCollection(), "mail_note" );
00129 new KAction( i18n("Save As..."), "filesaveas", 0,
00130 this, SLOT(slotSaveAs()), actionCollection(), "save_note" );
00131 KStdAction::print( this, SLOT(slotPrint()), actionCollection(), "print_note" );
00132 new KAction( i18n("Preferences..."), "configure", 0,
00133 this, SLOT(slotPreferences()), actionCollection(), "configure_note" );
00134
00135 m_keepAbove = new KToggleAction( i18n("Keep Above Others"), "up", 0,
00136 this, SLOT(slotUpdateKeepAboveBelow()), actionCollection(), "keep_above" );
00137 m_keepAbove->setExclusiveGroup( "keepAB" );
00138
00139 m_keepBelow = new KToggleAction( i18n("Keep Below Others"), "down", 0,
00140 this, SLOT(slotUpdateKeepAboveBelow()), actionCollection(), "keep_below" );
00141 m_keepBelow->setExclusiveGroup( "keepAB" );
00142
00143 m_toDesktop = new KListAction( i18n("To Desktop"), 0,
00144 this, SLOT(slotPopupActionToDesktop(int)), actionCollection(), "to_desktop" );
00145 connect( m_toDesktop->popupMenu(), SIGNAL(aboutToShow()), this, SLOT(slotUpdateDesktopActions()) );
00146
00147
00148 new KAction( i18n("Walk Through Notes"), 0, SHIFT+Key_BackTab,
00149 this, SIGNAL(sigShowNextNote()), actionCollection(), "walk_notes" );
00150
00151
00152 m_label = new QLabel( this );
00153 m_label->setFrameStyle( NoFrame );
00154 m_label->setLineWidth( 0 );
00155 m_label->installEventFilter( this );
00156 setName( m_journal->summary() );
00157
00158 m_button = new KNoteButton( "knotes_close", this );
00159 connect( m_button, SIGNAL(clicked()), this, SLOT(slotClose()) );
00160
00161
00162 m_editor = new KNoteEdit( actionCollection(), this );
00163 m_editor->installEventFilter( this );
00164 m_editor->viewport()->installEventFilter( this );
00165 connect( m_editor, SIGNAL(contentsMoving( int, int )), this, SLOT(slotUpdateViewport( int, int )));
00166
00167 KXMLGUIBuilder builder( this );
00168 KXMLGUIFactory factory( &builder, this );
00169 factory.addClient( this );
00170
00171 m_menu = dynamic_cast<KPopupMenu*>(factory.container( "note_context", this ));
00172 m_edit_menu = dynamic_cast<KPopupMenu*>(factory.container( "note_edit", this ));
00173 m_tool = dynamic_cast<KToolBar*>(factory.container( "note_tool", this ));
00174
00175 if ( m_tool ) {
00176 m_tool->setIconSize( 10 );
00177 m_tool->setFixedHeight( 16 );
00178 m_tool->setIconText( KToolBar::IconOnly );
00179
00180
00181 QObjectList *list = m_tool->queryList( "KComboBox" );
00182 QObjectListIt it( *list );
00183 while ( it.current() != 0 )
00184 {
00185 KComboBox *combo = (KComboBox *)it.current();
00186 QFont font = combo->font();
00187 font.setPointSize( 7 );
00188 combo->setFont( font );
00189 combo->setFixedHeight( 14 );
00190 ++it;
00191 }
00192 delete list;
00193
00194 m_tool->hide();
00195 }
00196
00197 setFocusProxy( m_editor );
00198
00199
00200 m_editor->setCornerWidget( new QSizeGrip( this ) );
00201 uint width = m_editor->cornerWidget()->width();
00202 uint height = m_editor->cornerWidget()->height();
00203 QBitmap mask;
00204 mask.resize( width, height );
00205 mask.fill( color0 );
00206 QPointArray array;
00207 array.setPoints( 3, 0, height, width, height, width, 0 );
00208 QPainter p;
00209 p.begin( &mask );
00210 p.setBrush( color1 );
00211 p.drawPolygon( array );
00212 p.end();
00213 m_editor->cornerWidget()->setMask( mask );
00214 m_editor->cornerWidget()->setBackgroundMode( PaletteBase );
00215
00216
00217 QString configFile = KGlobal::dirs()->saveLocation( "appdata", "notes/" );
00218 configFile += m_journal->uid();
00219
00220
00221
00222 bool newNote = !KIO::NetAccess::exists( KURL::fromPathOrURL( configFile ), false, 0 );
00223
00224 m_config = new KNoteConfig( KSharedConfig::openConfig( configFile, false, false ) );
00225 m_config->readConfig();
00226 m_config->setVersion( KNOTES_VERSION );
00227
00228 if ( newNote )
00229 {
00230
00231 KNotesGlobalConfig *globalConfig = KNotesGlobalConfig::self();
00232 m_config->setBgColor( globalConfig->bgColor() );
00233 m_config->setFgColor( globalConfig->fgColor() );
00234 m_config->setWidth( globalConfig->width() );
00235 m_config->setHeight( globalConfig->height() );
00236
00237 m_config->setFont( globalConfig->font() );
00238 m_config->setTitleFont( globalConfig->titleFont() );
00239 m_config->setAutoIndent( globalConfig->autoIndent() );
00240 m_config->setRichText( globalConfig->richText() );
00241 m_config->setTabSize( globalConfig->tabSize() );
00242 m_config->setReadOnly( globalConfig->readOnly() );
00243
00244 m_config->setDesktop( globalConfig->desktop() );
00245 m_config->setHideNote( globalConfig->hideNote() );
00246 m_config->setPosition( globalConfig->position() );
00247 m_config->setShowInTaskbar( globalConfig->showInTaskbar() );
00248 m_config->setKeepAbove( globalConfig->keepAbove() );
00249 m_config->setKeepBelow( globalConfig->keepBelow() );
00250
00251 m_config->writeConfig();
00252 }
00253
00254
00255 setMinimumSize( 20, 20 );
00256 setLineWidth( 1 );
00257 setMargin( 0 );
00258
00259 m_editor->setMargin( 0 );
00260 m_editor->setFrameStyle( NoFrame );
00261 m_editor->setBackgroundOrigin( WindowOrigin );
00262
00263
00264 bool closeLeft = false;
00265 m_kwinConf->setGroup( "Style" );
00266 if ( m_kwinConf->readBoolEntry( "CustomButtonPositions" ) )
00267 closeLeft = m_kwinConf->readEntry( "ButtonsOnLeft" ).find( 'X' ) > -1;
00268
00269 QPixmap pushpin_pix;
00270 if ( closeLeft )
00271 pushpin_pix = QPixmap( QPixmap( pushpin_xpm ).convertToImage().mirror( true, false ) );
00272 else
00273 pushpin_pix = QPixmap( pushpin_xpm );
00274
00275
00276 m_pushpin = new QLabel( this );
00277 m_pushpin->setScaledContents( true );
00278 m_pushpin->setBackgroundMode( NoBackground );
00279 m_pushpin->setPixmap( pushpin_pix );
00280 m_pushpin->resize( pushpin_pix.size() );
00281
00282
00283 m_fold = new QLabel( this );
00284 m_fold->setScaledContents( true );
00285 m_fold->setBackgroundMode( NoBackground );
00286
00287
00288 width = m_config->width();
00289 height = m_config->height();
00290 resize( width, height );
00291
00292
00293
00294 const QPoint& position = m_config->position();
00295 QRect desk = kapp->desktop()->rect();
00296 desk.addCoords( 10, 10, -10, -10 );
00297 if ( desk.intersects( QRect( position, QSize( width, height ) ) ) )
00298 move( position );
00299
00300
00301 QString property = m_journal->customProperty( "KNotes", "FgColor" );
00302 if ( !property.isNull() )
00303 m_config->setFgColor( QColor( property ) );
00304 else
00305 m_journal->setCustomProperty( "KNotes", "FgColor", m_config->fgColor().name() );
00306
00307 property = m_journal->customProperty( "KNotes", "BgColor" );
00308 if ( !property.isNull() )
00309 m_config->setBgColor( QColor( property ) );
00310 else
00311 m_journal->setCustomProperty( "KNotes", "BgColor", m_config->bgColor().name() );
00312
00313 property = m_journal->customProperty( "KNotes", "RichText" );
00314 if ( !property.isNull() )
00315 m_config->setRichText( property == "true" ? true : false );
00316 else
00317 m_journal->setCustomProperty( "KNotes", "RichText", m_config->richText() ? "true" : "false" );
00318
00319
00320 slotApplyConfig();
00321
00322
00323
00324 m_fold->setMask( QRegion( m_fold->pixmap()->createHeuristicMask() ) );
00325
00326
00327
00328 int desktop = m_config->desktop();
00329 if ( desktop < 0 && desktop != NETWinInfo::OnAllDesktops )
00330 desktop = KWin::currentDesktop();
00331
00332
00333 if ( desktop != 0 && !m_config->hideNote() )
00334 {
00335
00336 toDesktop( desktop );
00337 show();
00338
00339
00340 if ( desktop == NETWinInfo::OnAllDesktops )
00341 toDesktop( desktop );
00342 }
00343
00344 m_editor->setText( m_journal->description() );
00345 m_editor->setModified( false );
00346
00347 m_readOnly->setChecked( m_config->readOnly() );
00348 slotUpdateReadOnly();
00349
00350 if ( m_config->keepAbove() )
00351 m_keepAbove->setChecked( true );
00352 else if ( m_config->keepBelow() )
00353 m_keepBelow->setChecked( true );
00354 else
00355 {
00356 m_keepAbove->setChecked( false );
00357 m_keepBelow->setChecked( false );
00358 }
00359 slotUpdateKeepAboveBelow();
00360
00361
00362 KIconEffect effect;
00363 QPixmap icon = effect.apply( kapp->icon(), KIconEffect::Colorize, 1, m_config->bgColor(), false );
00364 QPixmap miniIcon = effect.apply( kapp->miniIcon(), KIconEffect::Colorize, 1, m_config->bgColor(), false );
00365 KWin::setIcons( winId(), icon, miniIcon );
00366 }
00367
00368 KNote::~KNote()
00369 {
00370 delete m_config;
00371 }
00372
00373
00374
00375
00376 void KNote::slotKill( bool force )
00377 {
00378 if ( !force &&
00379 KMessageBox::warningContinueCancel( this,
00380 i18n("<qt>Do you really want to delete note <b>%1</b>?</qt>").arg( m_label->text() ),
00381 i18n("Confirm Delete"), KGuiItem( i18n("&Delete"), "editdelete" ),
00382 "ConfirmDeleteNote"
00383 )
00384 != KMessageBox::Continue )
00385 {
00386 return;
00387 }
00388
00389
00390 delete m_config;
00391 m_config = 0;
00392
00393 QString configFile = KGlobal::dirs()->saveLocation( "appdata", "notes/" );
00394 configFile += m_journal->uid();
00395
00396 if ( !KIO::NetAccess::del( KURL::fromPathOrURL( configFile ), this ) )
00397 kdError(5500) << "Can't remove the note config: " << configFile << endl;
00398
00399 emit sigKillNote( m_journal );
00400 }
00401
00402
00403
00404
00405 void KNote::saveData()
00406 {
00407 m_journal->setSummary( m_label->text() );
00408 m_journal->setDescription( m_editor->text() );
00409 m_journal->setCustomProperty( "KNotes", "FgColor", m_config->fgColor().name() );
00410 m_journal->setCustomProperty( "KNotes", "BgColor", m_config->bgColor().name() );
00411 m_journal->setCustomProperty( "KNotes", "RichText", m_config->richText() ? "true" : "false" );
00412
00413 emit sigDataChanged();
00414 m_editor->setModified( false );
00415 }
00416
00417 void KNote::saveConfig() const
00418 {
00419 m_config->setWidth( width() );
00420 if ( m_tool )
00421 m_config->setHeight( height() - (m_tool->isHidden() ? 0 : m_tool->height()) );
00422 else
00423 m_config->setHeight( 0 );
00424 m_config->setPosition( pos() );
00425
00426 NETWinInfo wm_client( qt_xdisplay(), winId(), qt_xrootwin(), NET::WMDesktop );
00427 if ( wm_client.desktop() == NETWinInfo::OnAllDesktops || wm_client.desktop() > 0 )
00428 m_config->setDesktop( wm_client.desktop() );
00429
00430
00431 m_config->writeConfig();
00432 }
00433
00434 QString KNote::noteId() const
00435 {
00436 return m_journal->uid();
00437 }
00438
00439 QString KNote::name() const
00440 {
00441 return m_label->text();
00442 }
00443
00444 QString KNote::text() const
00445 {
00446 return m_editor->text();
00447 }
00448
00449 QString KNote::plainText() const
00450 {
00451 if ( m_editor->textFormat() == RichText )
00452 {
00453 QTextEdit conv;
00454 conv.setTextFormat( RichText );
00455 conv.setText( m_editor->text() );
00456 conv.setTextFormat( PlainText );
00457 return conv.text();
00458 }
00459 else
00460 return m_editor->text();
00461 }
00462
00463 void KNote::setName( const QString& name )
00464 {
00465 m_label->setText( name );
00466 updateLabelAlignment();
00467
00468 if ( m_editor )
00469 saveData();
00470
00471
00472 NETWinInfo note_win( qt_xdisplay(), winId(), qt_xrootwin(), NET::WMDesktop );
00473 note_win.setName( name.utf8() );
00474
00475 emit sigNameChanged();
00476 }
00477
00478 void KNote::setText( const QString& text )
00479 {
00480 m_editor->setText( text );
00481 saveData();
00482 }
00483
00484 QColor KNote::fgColor() const
00485 {
00486 return m_config->fgColor();
00487 }
00488
00489 QColor KNote::bgColor() const
00490 {
00491 return m_config->bgColor();
00492 }
00493
00494 void KNote::setColor( const QColor& fg, const QColor& bg )
00495 {
00496 m_journal->setCustomProperty( "KNotes", "FgColor", fg.name() );
00497 m_journal->setCustomProperty( "KNotes", "BgColor", bg.name() );
00498 m_config->setFgColor( fg );
00499 m_config->setBgColor( bg );
00500
00501 m_journal->updated();
00502 emit sigDataChanged();
00503 m_config->writeConfig();
00504
00505 QPalette newpalette = palette();
00506 newpalette.setColor( QColorGroup::Background, bg );
00507 newpalette.setColor( QColorGroup::Foreground, fg );
00508 newpalette.setColor( QColorGroup::Base, bg );
00509 newpalette.setColor( QColorGroup::Text, fg );
00510 newpalette.setColor( QColorGroup::Button, bg );
00511 newpalette.setColor( QColorGroup::ButtonText, fg );
00512
00513
00514
00515
00516
00517 newpalette.setColor( QColorGroup::Midlight, bg.light(150) );
00518 newpalette.setColor( QColorGroup::Shadow, bg.dark(116) );
00519 newpalette.setColor( QColorGroup::Light, bg.light(180) );
00520 if ( s_ppOffset )
00521 newpalette.setColor( QColorGroup::Dark, bg.dark(200) );
00522 else
00523 newpalette.setColor( QColorGroup::Dark, bg.dark(108) );
00524 setPalette( newpalette );
00525
00526
00527 m_editor->setTextColor( fg );
00528
00529
00530 updateBackground();
00531
00532
00533 QPalette darker = palette();
00534 darker.setColor( QColorGroup::Button, bg.dark(116) );
00535 m_button->setPalette( darker );
00536
00537
00538 KIconEffect effect;
00539 QPixmap icon = effect.apply( kapp->icon(), KIconEffect::Colorize, 1, bg, false );
00540 QPixmap miniIcon = effect.apply( kapp->miniIcon(), KIconEffect::Colorize, 1, bg, false );
00541 KWin::setIcons( winId(), icon, miniIcon );
00542
00543
00544 QColor sel = palette().color( QPalette::Active, QColorGroup::Base ).dark();
00545 if ( sel == Qt::black )
00546 sel = palette().color( QPalette::Active, QColorGroup::Base ).light();
00547
00548 m_editor->setSelectionAttributes( 1, sel, true );
00549
00550
00551 createFold();
00552
00553
00554 updateFocus();
00555 emit sigColorChanged();
00556 }
00557
00558 void KNote::find( const QString& pattern, long options )
00559 {
00560 delete m_find;
00561 m_find = new KFind( pattern, options, this );
00562
00563 connect( m_find, SIGNAL(highlight( const QString &, int, int )),
00564 this, SLOT(slotHighlight( const QString &, int, int )) );
00565 connect( m_find, SIGNAL(findNext()), this, SLOT(slotFindNext()) );
00566
00567 m_find->setData( plainText() );
00568 slotFindNext();
00569 }
00570
00571 void KNote::slotFindNext()
00572 {
00573
00574
00575
00576
00577 KFind::Result res = m_find->find();
00578
00579 if ( res == KFind::NoMatch )
00580 {
00581 m_editor->removeSelection( 1 );
00582 emit sigFindFinished();
00583 delete m_find;
00584 m_find = 0;
00585 }
00586 else
00587 {
00588 show();
00589 KWin::setCurrentDesktop( KWin::windowInfo( winId() ).desktop() );
00590 }
00591 }
00592
00593 void KNote::slotHighlight( const QString& str, int idx, int len )
00594 {
00595 int paraFrom = 0, idxFrom = 0, p = 0;
00596 for ( ; p < idx; ++p )
00597 if ( str[p] == '\n' )
00598 {
00599 ++paraFrom;
00600 idxFrom = 0;
00601 }
00602 else
00603 ++idxFrom;
00604
00605 int paraTo = paraFrom, idxTo = idxFrom;
00606
00607 for ( ; p < idx + len; ++p )
00608 {
00609 if ( str[p] == '\n' )
00610 {
00611 ++paraTo;
00612 idxTo = 0;
00613 }
00614 else
00615 ++idxTo;
00616 }
00617
00618 m_editor->setSelection( paraFrom, idxFrom, paraTo, idxTo, 1 );
00619 }
00620
00621 bool KNote::isModified() const
00622 {
00623 return m_editor->isModified();
00624 }
00625
00626
00627 void KNote::sync( const QString& app )
00628 {
00629 QByteArray sep( 1 );
00630 sep[0] = '\0';
00631
00632 KMD5 hash;
00633 QCString result;
00634
00635 hash.update( m_label->text().utf8() );
00636 hash.update( sep );
00637 hash.update( m_editor->text().utf8() );
00638 hash.hexDigest( result );
00639
00640
00641 KConfig *config = m_config->config();
00642 config->setGroup( "Synchronisation" );
00643 config->writeEntry( app, result.data() );
00644 }
00645
00646 bool KNote::isNew( const QString& app ) const
00647 {
00648 KConfig *config = m_config->config();
00649 config->setGroup( "Synchronisation" );
00650 QString hash = config->readEntry( app );
00651 return hash.isEmpty();
00652 }
00653
00654 bool KNote::isModified( const QString& app ) const
00655 {
00656 QByteArray sep( 1 );
00657 sep[0] = '\0';
00658
00659 KMD5 hash;
00660 hash.update( m_label->text().utf8() );
00661 hash.update( sep );
00662 hash.update( m_editor->text().utf8() );
00663 hash.hexDigest();
00664
00665 KConfig *config = m_config->config();
00666 config->setGroup( "Synchronisation" );
00667 QString orig = config->readEntry( app );
00668
00669 if ( hash.verify( orig.utf8() ) )
00670 return false;
00671 else
00672 return true;
00673 }
00674
00675 void KNote::setStyle( int style )
00676 {
00677 if ( style == KNotesGlobalConfig::EnumStyle::Plain )
00678 s_ppOffset = 0;
00679 else
00680 s_ppOffset = 12;
00681 }
00682
00683
00684
00685
00686 void KNote::slotRename()
00687 {
00688
00689 bool ok;
00690 aboutToEnterEventLoop();
00691 QString oldName = m_label->text();
00692 QString newName = KInputDialog::getText( QString::null,
00693 i18n("Please enter the new name:"), m_label->text(), &ok, this );
00694 eventLoopLeft();
00695 if ( !ok || ( oldName == newName) )
00696 return;
00697
00698 setName( newName );
00699 }
00700
00701 void KNote::slotUpdateReadOnly()
00702 {
00703 const bool readOnly = m_readOnly->isChecked();
00704
00705 m_editor->setReadOnly( readOnly );
00706 m_config->setReadOnly( readOnly );
00707
00708
00709 actionCollection()->action( "configure_note" )->setEnabled( !readOnly );
00710 actionCollection()->action( "insert_date" )->setEnabled( !readOnly );
00711 actionCollection()->action( "delete_note" )->setEnabled( !readOnly );
00712
00713 actionCollection()->action( "edit_undo" )->setEnabled( !readOnly && m_editor->isUndoAvailable() );
00714 actionCollection()->action( "edit_redo" )->setEnabled( !readOnly && m_editor->isRedoAvailable() );
00715 actionCollection()->action( "edit_cut" )->setEnabled( !readOnly && m_editor->hasSelectedText() );
00716 actionCollection()->action( "edit_paste" )->setEnabled( !readOnly );
00717 actionCollection()->action( "edit_clear" )->setEnabled( !readOnly );
00718 actionCollection()->action( "rename_note" )->setEnabled( !readOnly );
00719
00720 actionCollection()->action( "format_bold" )->setEnabled( !readOnly );
00721 actionCollection()->action( "format_italic" )->setEnabled( !readOnly );
00722 actionCollection()->action( "format_underline" )->setEnabled( !readOnly );
00723 actionCollection()->action( "format_strikeout" )->setEnabled( !readOnly );
00724 actionCollection()->action( "format_alignleft" )->setEnabled( !readOnly );
00725 actionCollection()->action( "format_aligncenter" )->setEnabled( !readOnly );
00726 actionCollection()->action( "format_alignright" )->setEnabled( !readOnly );
00727 actionCollection()->action( "format_alignblock" )->setEnabled( !readOnly );
00728 actionCollection()->action( "format_list" )->setEnabled( !readOnly );
00729 actionCollection()->action( "format_super" )->setEnabled( !readOnly );
00730 actionCollection()->action( "format_sub" )->setEnabled( !readOnly );
00731 actionCollection()->action( "format_size" )->setEnabled( !readOnly );
00732 actionCollection()->action( "format_color" )->setEnabled( !readOnly );
00733
00734 updateFocus();
00735 }
00736
00737 void KNote::slotClose()
00738 {
00739 NETWinInfo wm_client( qt_xdisplay(), winId(), qt_xrootwin(), NET::WMDesktop );
00740 if ( wm_client.desktop() == NETWinInfo::OnAllDesktops || wm_client.desktop() > 0 )
00741 m_config->setDesktop( wm_client.desktop() );
00742
00743 m_editor->clearFocus();
00744 m_config->setHideNote( true );
00745 m_config->setPosition( pos() );
00746
00747
00748 hide();
00749 }
00750
00751 void KNote::slotInsDate()
00752 {
00753 m_editor->insert( KGlobal::locale()->formatDateTime(QDateTime::currentDateTime()) );
00754 }
00755
00756 void KNote::slotSetAlarm()
00757 {
00758 KNoteAlarmDlg dlg( name(), this );
00759 dlg.setIncidence( m_journal );
00760
00761 aboutToEnterEventLoop();
00762 if ( dlg.exec() == QDialog::Accepted )
00763 emit sigDataChanged();
00764 eventLoopLeft();
00765 }
00766
00767 void KNote::slotPreferences()
00768 {
00769
00770 if ( KNoteConfigDlg::showDialog( noteId().utf8() ) )
00771 return;
00772
00773
00774 KNoteConfigDlg *dialog = new KNoteConfigDlg( m_config, name(), this, noteId().utf8() );
00775 connect( dialog, SIGNAL(settingsChanged()), this, SLOT(slotApplyConfig()) );
00776 connect( this, SIGNAL(sigNameChanged()), dialog, SLOT(slotUpdateCaption()) );
00777 dialog->show();
00778 }
00779
00780 void KNote::slotSend()
00781 {
00782
00783 KNoteHostDlg hostDlg( i18n("Send \"%1\"").arg( name() ), this );
00784 aboutToEnterEventLoop();
00785 bool ok = (hostDlg.exec() == QDialog::Accepted);
00786 eventLoopLeft();
00787 if ( !ok )
00788 return;
00789 QString host = hostDlg.host();
00790
00791 if ( host.isEmpty() )
00792 {
00793 KMessageBox::sorry( this, i18n("The host cannot be empty.") );
00794 return;
00795 }
00796
00797
00798 KNotesNetworkSender *sender = new KNotesNetworkSender( host, KNotesGlobalConfig::port() );
00799 sender->setSenderId( KNotesGlobalConfig::senderID() );
00800 sender->setNote( name(), text() );
00801 sender->connect();
00802 }
00803
00804 void KNote::slotMail()
00805 {
00806
00807 const QStringList cmd_list = QStringList::split( QChar(' '), KNotesGlobalConfig::mailAction() );
00808
00809 KProcess mail;
00810 for ( QStringList::ConstIterator it = cmd_list.constBegin();
00811 it != cmd_list.constEnd(); ++it )
00812 {
00813 if ( *it == "%f" )
00814 mail << plainText().local8Bit();
00815 else if ( *it == "%t" )
00816 mail << m_label->text().local8Bit();
00817 else
00818 mail << (*it).local8Bit();
00819 }
00820
00821 if ( !mail.start( KProcess::DontCare ) )
00822 KMessageBox::sorry( this, i18n("Unable to start the mail process.") );
00823 }
00824
00825 void KNote::slotPrint()
00826 {
00827 saveData();
00828
00829 QString content;
00830 if ( m_editor->textFormat() == PlainText )
00831 content = QStyleSheet::convertFromPlainText( m_editor->text() );
00832 else
00833 content = m_editor->text();
00834
00835 KNotePrinter printer;
00836 printer.setMimeSourceFactory( m_editor->mimeSourceFactory() );
00837 printer.setFont( m_config->font() );
00838 printer.setContext( m_editor->context() );
00839 printer.setStyleSheet( m_editor->styleSheet() );
00840 printer.setColorGroup( colorGroup() );
00841 printer.printNote( QString(), content );
00842 }
00843
00844 void KNote::slotSaveAs()
00845 {
00846 QCheckBox *convert = 0;
00847
00848 if ( m_editor->textFormat() == RichText )
00849 {
00850 convert = new QCheckBox( 0 );
00851 convert->setText( i18n("Save note as plain text") );
00852 }
00853
00854 KFileDialog dlg( QString::null, QString::null, this, "filedialog", true, convert );
00855 dlg.setOperationMode( KFileDialog::Saving );
00856 dlg.setCaption( i18n("Save As") );
00857 aboutToEnterEventLoop();
00858 dlg.exec();
00859 eventLoopLeft();
00860
00861 QString fileName = dlg.selectedFile();
00862 if ( fileName.isEmpty() )
00863 return;
00864
00865 QFile file( fileName );
00866
00867 if ( file.exists() &&
00868 KMessageBox::warningContinueCancel( this, i18n("<qt>A file named <b>%1</b> already exists.<br>"
00869 "Are you sure you want to overwrite it?</qt>").arg( QFileInfo(file).fileName() ) )
00870 != KMessageBox::Continue )
00871 {
00872 return;
00873 }
00874
00875 if ( file.open( IO_WriteOnly ) )
00876 {
00877 QTextStream stream( &file );
00878
00879 if ( convert && convert->isChecked() )
00880 stream << plainText();
00881 else
00882 stream << text();
00883 }
00884 }
00885
00886 void KNote::slotPopupActionToDesktop( int id )
00887 {
00888 toDesktop( id - 1 );
00889 }
00890
00891
00892
00893
00894 void KNote::slotApplyConfig()
00895 {
00896 if ( m_config->richText() )
00897 m_editor->setTextFormat( RichText );
00898 else
00899 m_editor->setTextFormat( PlainText );
00900
00901 m_label->setFont( m_config->titleFont() );
00902 m_editor->setTextFont( m_config->font() );
00903 m_editor->setTabStop( m_config->tabSize() );
00904 m_editor->setAutoIndentMode( m_config->autoIndent() );
00905
00906
00907
00908 if ( sender() )
00909 saveData();
00910
00911 setColor( m_config->fgColor(), m_config->bgColor() );
00912
00913 updateLabelAlignment();
00914 slotUpdateShowInTaskbar();
00915 }
00916
00917 void KNote::slotUpdateKeepAboveBelow()
00918 {
00919 KWin::WindowInfo info( KWin::windowInfo( winId() ) );
00920
00921 if ( m_keepAbove->isChecked() )
00922 {
00923 m_config->setKeepAbove( true );
00924 m_config->setKeepBelow( false );
00925 KWin::setState( winId(), info.state() | NET::KeepAbove );
00926 }
00927 else if ( m_keepBelow->isChecked() )
00928 {
00929 m_config->setKeepAbove( false );
00930 m_config->setKeepBelow( true );
00931 KWin::setState( winId(), info.state() | NET::KeepBelow );
00932 }
00933 else
00934 {
00935 m_config->setKeepAbove( false );
00936 KWin::clearState( winId(), NET::KeepAbove );
00937
00938 m_config->setKeepBelow( false );
00939 KWin::clearState( winId(), NET::KeepBelow );
00940 }
00941 }
00942
00943 void KNote::slotUpdateShowInTaskbar()
00944 {
00945 if ( !m_config->showInTaskbar() )
00946 KWin::setState( winId(), KWin::windowInfo(winId()).state() | NET::SkipTaskbar );
00947 else
00948 KWin::clearState( winId(), NET::SkipTaskbar );
00949 }
00950
00951 void KNote::slotUpdateDesktopActions()
00952 {
00953 NETRootInfo wm_root( qt_xdisplay(), NET::NumberOfDesktops | NET::DesktopNames );
00954 NETWinInfo wm_client( qt_xdisplay(), winId(), qt_xrootwin(), NET::WMDesktop );
00955
00956 QStringList desktops;
00957 desktops.append( i18n("&All Desktops") );
00958 desktops.append( QString::null );
00959
00960 int count = wm_root.numberOfDesktops();
00961 for ( int n = 1; n <= count; n++ )
00962 desktops.append( QString("&%1 %2").arg( n ).arg( QString::fromUtf8(wm_root.desktopName( n )) ) );
00963
00964 m_toDesktop->setItems( desktops );
00965
00966 if ( wm_client.desktop() == NETWinInfo::OnAllDesktops )
00967 m_toDesktop->setCurrentItem( 0 );
00968 else
00969 m_toDesktop->setCurrentItem( wm_client.desktop() + 1 );
00970 }
00971
00972 void KNote::slotUpdateViewport( int , int y )
00973 {
00974 if ( s_ppOffset )
00975 updateBackground( y );
00976 }
00977
00978
00979
00980 void KNote::toDesktop( int desktop )
00981 {
00982 if ( desktop == 0 )
00983 return;
00984
00985 if ( desktop == NETWinInfo::OnAllDesktops )
00986 KWin::setOnAllDesktops( winId(), true );
00987 else
00988 KWin::setOnDesktop( winId(), desktop );
00989 }
00990
00991 void KNote::createFold()
00992 {
00993 QPixmap fold( 15, 15 );
00994 QPainter foldp( &fold );
00995 foldp.setPen( Qt::NoPen );
00996 foldp.setBrush( palette().active().dark() );
00997 QPointArray foldpoints( 3 );
00998 foldpoints.putPoints( 0, 3, 0, 0, 14, 0, 0, 14 );
00999 foldp.drawPolygon( foldpoints );
01000 foldp.end();
01001 m_fold->setPixmap( fold );
01002 }
01003
01004 void KNote::updateLabelAlignment()
01005 {
01006
01007 QString labelText = m_label->text();
01008 if ( m_label->fontMetrics().boundingRect( labelText ).width() > m_label->width() )
01009 m_label->setAlignment( AlignLeft );
01010 else
01011 m_label->setAlignment( AlignHCenter );
01012 }
01013
01014 void KNote::updateFocus()
01015 {
01016 if ( hasFocus() )
01017 {
01018 m_label->setBackgroundColor( palette().active().shadow() );
01019 m_button->show();
01020 m_editor->cornerWidget()->show();
01021
01022 if ( !m_editor->isReadOnly() )
01023 {
01024 if ( m_tool && m_tool->isHidden() && m_editor->textFormat() == QTextEdit::RichText )
01025 {
01026 m_tool->show();
01027 setGeometry( x(), y(), width(), height() + m_tool->height() );
01028 }
01029 }
01030 else if ( m_tool && !m_tool->isHidden() )
01031 {
01032 m_tool->hide();
01033 setGeometry( x(), y(), width(), height() - m_tool->height() );
01034 updateLayout();
01035 }
01036
01037 m_fold->hide();
01038 }
01039 else
01040 {
01041 m_button->hide();
01042 m_editor->cornerWidget()->hide();
01043
01044 if ( m_tool && !m_tool->isHidden() )
01045 {
01046 m_tool->hide();
01047 setGeometry( x(), y(), width(), height() - m_tool->height() );
01048 updateLayout();
01049 }
01050
01051 if ( s_ppOffset )
01052 {
01053 m_label->setBackgroundColor( palette().active().midlight() );
01054 m_fold->show();
01055 }
01056 else
01057 m_label->setBackgroundColor( palette().active().background() );
01058 }
01059 }
01060
01061 void KNote::updateMask()
01062 {
01063 if ( !s_ppOffset )
01064 {
01065 clearMask();
01066 return;
01067 }
01068
01069 int w = width();
01070 int h = height();
01071 QRegion reg( 0, s_ppOffset, w, h - s_ppOffset );
01072
01073 const QBitmap *pushpin_bitmap = m_pushpin->pixmap()->mask();
01074 QRegion pushpin_reg( *pushpin_bitmap );
01075 m_pushpin->setMask( pushpin_reg );
01076 pushpin_reg.translate( m_pushpin->x(), m_pushpin->y() );
01077
01078 if ( !hasFocus() )
01079 {
01080 QPointArray foldpoints( 3 );
01081 foldpoints.putPoints( 0, 3, w-15, h, w, h-15, w, h );
01082 QRegion fold( foldpoints, false );
01083 setMask( reg.unite( pushpin_reg ).subtract( fold ) );
01084 }
01085 else
01086 setMask( reg.unite( pushpin_reg ) );
01087 }
01088
01089 void KNote::updateBackground( int y_offset )
01090 {
01091 if ( !s_ppOffset )
01092 {
01093 m_editor->setPaper( QBrush( colorGroup().background() ) );
01094 return;
01095 }
01096
01097 int w = m_editor->visibleWidth();
01098 int h = m_editor->visibleHeight();
01099
01100
01101
01102
01103 if ( y_offset == -1 )
01104 y_offset = m_editor->contentsY();
01105
01106 y_offset = y_offset % h;
01107
01108 QImage grad_img( w, h, 32 );
01109 QRgb rgbcol;
01110 QColor bg = palette().active().background();
01111
01112 for ( int i = 0; i < h; ++i )
01113 {
01114
01115
01116
01117
01118
01119
01120
01121 int i_1 = 150 - 75 * ((i - y_offset + h) % h) / h;
01122 rgbcol = bg.light( i_1 ).rgb();
01123 for ( int j = 0; j < w; ++j )
01124 grad_img.setPixel( j, i, rgbcol );
01125 }
01126
01127
01128 m_editor->setPaper( QBrush( Qt::black, QPixmap( grad_img ) ) );
01129 }
01130
01131 void KNote::updateLayout()
01132 {
01133 const int headerHeight = m_label->sizeHint().height();
01134 const int margin = m_editor->margin();
01135 bool closeLeft = false;
01136
01137 m_kwinConf->setGroup( "Style" );
01138 if ( m_kwinConf->readBoolEntry( "CustomButtonPositions" ) )
01139 closeLeft = m_kwinConf->readEntry( "ButtonsOnLeft" ).find( 'X' ) > -1;
01140
01141 if ( s_ppOffset )
01142 {
01143 if ( !m_editor->paper().pixmap() )
01144 setColor( palette().active().foreground(), palette().active().background() );
01145
01146 m_pushpin->show();
01147 setFrameStyle( Panel | Raised );
01148
01149 if ( closeLeft )
01150 m_pushpin->move( width() - m_pushpin->width(), 0 );
01151 else
01152 m_pushpin->move( 0, 0 );
01153 }
01154 else
01155 {
01156 if ( m_editor->paper().pixmap() )
01157 setColor( palette().active().foreground(), palette().active().background() );
01158
01159 setFrameStyle( WinPanel | Raised );
01160 m_pushpin->hide();
01161 m_fold->hide();
01162 }
01163
01164 m_button->setGeometry(
01165 closeLeft ? contentsRect().x() : contentsRect().width() - headerHeight,
01166 contentsRect().y() + s_ppOffset,
01167 headerHeight,
01168 headerHeight
01169 );
01170
01171 m_label->setGeometry(
01172 contentsRect().x(), contentsRect().y() + s_ppOffset,
01173 contentsRect().width(), headerHeight
01174 );
01175
01176 m_editor->setGeometry( QRect(
01177 QPoint( contentsRect().x(),
01178 contentsRect().y() + headerHeight + s_ppOffset ),
01179 QPoint( contentsRect().right(),
01180 contentsRect().bottom() - ( m_tool ? (m_tool->isHidden() ? 0 : m_tool->height()) : 0 ) )
01181 ) );
01182
01183 if( m_tool ) {
01184 m_tool->setGeometry(
01185 contentsRect().x(),
01186 contentsRect().bottom() - m_tool->height() + 1,
01187 contentsRect().width(),
01188 m_tool->height()
01189 );
01190 }
01191
01192 if ( s_ppOffset )
01193 m_fold->move( width() - 15, height() - 15 );
01194
01195 setMinimumSize(
01196 m_editor->cornerWidget()->width() + margin*2,
01197 headerHeight + s_ppOffset + ( m_tool ? (m_tool->isHidden() ? 0 : m_tool->height() ) : 0 ) +
01198 m_editor->cornerWidget()->height() + margin*2
01199 );
01200
01201 updateLabelAlignment();
01202 updateMask();
01203 updateBackground();
01204 }
01205
01206
01207
01208 void KNote::drawFrame( QPainter *p )
01209 {
01210 QRect r = frameRect();
01211 r.setTop( s_ppOffset );
01212 if ( s_ppOffset )
01213 qDrawShadePanel( p, r, colorGroup(), false, lineWidth() );
01214 else
01215 qDrawWinPanel( p, r, colorGroup(), false );
01216 }
01217
01218 void KNote::showEvent( QShowEvent * )
01219 {
01220 if ( m_config->hideNote() )
01221 {
01222
01223 slotUpdateKeepAboveBelow();
01224 slotUpdateShowInTaskbar();
01225 toDesktop( m_config->desktop() );
01226 move( m_config->position() );
01227 m_config->setHideNote( false );
01228 }
01229 }
01230
01231 void KNote::resizeEvent( QResizeEvent *qre )
01232 {
01233 QFrame::resizeEvent( qre );
01234 updateLayout();
01235 }
01236
01237 void KNote::closeEvent( QCloseEvent * )
01238 {
01239 slotClose();
01240 }
01241
01242 void KNote::dragEnterEvent( QDragEnterEvent *e )
01243 {
01244 if ( !m_config->readOnly() )
01245 e->accept( KColorDrag::canDecode( e ) );
01246 }
01247
01248 void KNote::dropEvent( QDropEvent *e )
01249 {
01250 if ( m_config->readOnly() )
01251 return;
01252
01253 QColor bg;
01254 if ( KColorDrag::decode( e, bg ) )
01255 setColor( paletteForegroundColor(), bg );
01256 }
01257
01258 bool KNote::focusNextPrevChild( bool )
01259 {
01260 return true;
01261 }
01262
01263 bool KNote::event( QEvent *ev )
01264 {
01265 if ( ev->type() == QEvent::LayoutHint )
01266 {
01267 updateLayout();
01268 return true;
01269 }
01270 else
01271 return QFrame::event( ev );
01272 }
01273
01274 bool KNote::eventFilter( QObject *o, QEvent *ev )
01275 {
01276 if ( ev->type() == QEvent::DragEnter &&
01277 KColorDrag::canDecode( static_cast<QDragEnterEvent *>(ev) ) )
01278 {
01279 dragEnterEvent( static_cast<QDragEnterEvent *>(ev) );
01280 return true;
01281 }
01282
01283 if ( ev->type() == QEvent::Drop &&
01284 KColorDrag::canDecode( static_cast<QDropEvent *>(ev) ) )
01285 {
01286 dropEvent( static_cast<QDropEvent *>(ev) );
01287 return true;
01288 }
01289
01290 if ( o == m_label )
01291 {
01292 QMouseEvent *e = (QMouseEvent *)ev;
01293
01294 if ( ev->type() == QEvent::MouseButtonDblClick )
01295 {
01296 if( !m_editor->isReadOnly())
01297 slotRename();
01298 }
01299 if ( ev->type() == QEvent::MouseButtonPress &&
01300 (e->button() == LeftButton || e->button() == MidButton))
01301 {
01302 e->button() == LeftButton ? KWin::raiseWindow( winId() )
01303 : KWin::lowerWindow( winId() );
01304
01305 XUngrabPointer( qt_xdisplay(), qt_x_time );
01306 NETRootInfo wm_root( qt_xdisplay(), NET::WMMoveResize );
01307 wm_root.moveResizeRequest( winId(), e->globalX(), e->globalY(), NET::Move );
01308 return true;
01309 }
01310
01311 #if KDE_IS_VERSION( 3, 5, 1 )
01312 if ( ev->type() == QEvent::MouseButtonRelease )
01313 {
01314 NETRootInfo wm_root( qt_xdisplay(), NET::WMMoveResize );
01315 wm_root.moveResizeRequest( winId(), e->globalX(), e->globalY(), NET::MoveResizeCancel );
01316 return false;
01317 }
01318 #endif
01319
01320 if ( m_menu && ( ev->type() == QEvent::MouseButtonPress )
01321 && ( e->button() == RightButton ) )
01322 {
01323 m_menu->popup( QCursor::pos() );
01324 return true;
01325 }
01326
01327 return false;
01328 }
01329
01330 if ( o == m_editor )
01331 {
01332 if ( ev->type() == QEvent::FocusOut )
01333 {
01334 QFocusEvent *fe = static_cast<QFocusEvent *>(ev);
01335 if ( fe->reason() != QFocusEvent::Popup &&
01336 fe->reason() != QFocusEvent::Mouse )
01337 {
01338 updateFocus();
01339 if ( m_editor->isModified() )
01340 saveData();
01341 }
01342 }
01343 else if ( ev->type() == QEvent::FocusIn )
01344 updateFocus();
01345
01346 return false;
01347 }
01348
01349 if ( o == m_editor->viewport() )
01350 {
01351 if ( m_edit_menu &&
01352 ev->type() == QEvent::MouseButtonPress &&
01353 ((QMouseEvent *)ev)->button() == RightButton )
01354 {
01355 m_edit_menu->popup( QCursor::pos() );
01356 return true;
01357 }
01358 }
01359
01360 return false;
01361 }
01362
01363 void KNote::deleteWhenIdle()
01364 {
01365 if ( m_busy <= 0 )
01366 deleteLater();
01367 else
01368 m_deleteWhenIdle = true;
01369 }
01370
01371 void KNote::aboutToEnterEventLoop()
01372 {
01373 ++m_busy;
01374 }
01375
01376 void KNote::eventLoopLeft()
01377 {
01378 --m_busy;
01379 if ( m_busy <= 0 && m_deleteWhenIdle )
01380 deleteLater();
01381 }
01382
01383
01384 #include "knote.moc"
01385 #include "knotebutton.moc"