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