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