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 void KNote::find( const QString& pattern, long options )
00478 {
00479 delete m_find;
00480 m_find = new KFind( pattern, options, this );
00481
00482 connect( m_find, SIGNAL(highlight( const QString &, int, int )),
00483 this, SLOT(slotHighlight( const QString &, int, int )) );
00484 connect( m_find, SIGNAL(findNext()), this, SLOT(slotFindNext()) );
00485
00486 m_find->setData( plainText() );
00487 slotFindNext();
00488 }
00489
00490 void KNote::slotFindNext()
00491 {
00492
00493
00494
00495
00496 KFind::Result res = m_find->find();
00497
00498 if ( res == KFind::NoMatch )
00499 {
00500 m_editor->removeSelection( 1 );
00501 emit sigFindFinished();
00502 delete m_find;
00503 m_find = 0;
00504 }
00505 else
00506 {
00507 show();
00508 KWin::setCurrentDesktop( KWin::windowInfo( winId() ).desktop() );
00509 }
00510 }
00511
00512 void KNote::slotHighlight( const QString& str, int idx, int len )
00513 {
00514 int paraFrom = 0, idxFrom = 0, p = 0;
00515 for ( ; p < idx; ++p )
00516 if ( str[p] == '\n' )
00517 {
00518 ++paraFrom;
00519 idxFrom = 0;
00520 }
00521 else
00522 ++idxFrom;
00523
00524 int paraTo = paraFrom, idxTo = idxFrom;
00525
00526 for ( ; p < idx + len; ++p )
00527 {
00528 if ( str[p] == '\n' )
00529 {
00530 ++paraTo;
00531 idxTo = 0;
00532 }
00533 else
00534 ++idxTo;
00535 }
00536
00537 m_editor->setSelection( paraFrom, idxFrom, paraTo, idxTo, 1 );
00538 }
00539
00540 bool KNote::isModified() const
00541 {
00542 return m_editor->isModified();
00543 }
00544
00545
00546 void KNote::sync( const QString& app )
00547 {
00548 QByteArray sep( 1 );
00549 sep[0] = '\0';
00550
00551 KMD5 hash;
00552 QCString result;
00553
00554 hash.update( m_label->text().utf8() );
00555 hash.update( sep );
00556 hash.update( m_editor->text().utf8() );
00557 hash.hexDigest( result );
00558
00559
00560 KConfig *config = m_config->config();
00561 config->setGroup( "Synchronisation" );
00562 config->writeEntry( app, result.data() );
00563 }
00564
00565 bool KNote::isNew( const QString& app ) const
00566 {
00567 KConfig *config = m_config->config();
00568 config->setGroup( "Synchronisation" );
00569 QString hash = config->readEntry( app );
00570 return hash.isEmpty();
00571 }
00572
00573 bool KNote::isModified( const QString& app ) const
00574 {
00575 QByteArray sep( 1 );
00576 sep[0] = '\0';
00577
00578 KMD5 hash;
00579 hash.update( m_label->text().utf8() );
00580 hash.update( sep );
00581 hash.update( m_editor->text().utf8() );
00582 hash.hexDigest();
00583
00584 KConfig *config = m_config->config();
00585 config->setGroup( "Synchronisation" );
00586 QString orig = config->readEntry( app );
00587
00588 if ( hash.verify( orig.utf8() ) )
00589 return false;
00590 else
00591 return true;
00592 }
00593
00594 void KNote::setStyle( int style )
00595 {
00596 if ( style == KNotesGlobalConfig::EnumStyle::Plain )
00597 s_ppOffset = 0;
00598 else
00599 s_ppOffset = 12;
00600 }
00601
00602
00603
00604
00605 void KNote::slotRename()
00606 {
00607
00608 bool ok;
00609 QString newName = KInputDialog::getText( QString::null,
00610 i18n("Please enter the new name:"), m_label->text(), &ok, this );
00611 if ( !ok )
00612 return;
00613
00614 setName( newName );
00615 }
00616
00617 void KNote::slotUpdateReadOnly()
00618 {
00619 const bool readOnly = m_readOnly->isChecked();
00620
00621 m_editor->setReadOnly( readOnly );
00622 m_config->setReadOnly( readOnly );
00623
00624
00625 actionCollection()->action( "configure_note" )->setEnabled( !readOnly );
00626 actionCollection()->action( "insert_date" )->setEnabled( !readOnly );
00627 actionCollection()->action( "delete_note" )->setEnabled( !readOnly );
00628
00629 actionCollection()->action( "edit_undo" )->setEnabled( !readOnly && m_editor->isUndoAvailable() );
00630 actionCollection()->action( "edit_redo" )->setEnabled( !readOnly && m_editor->isRedoAvailable() );
00631 actionCollection()->action( "edit_cut" )->setEnabled( !readOnly && m_editor->hasSelectedText() );
00632 actionCollection()->action( "edit_paste" )->setEnabled( !readOnly );
00633 actionCollection()->action( "edit_clear" )->setEnabled( !readOnly );
00634
00635 updateFocus();
00636 }
00637
00638 void KNote::slotClose()
00639 {
00640 NETWinInfo wm_client( qt_xdisplay(), winId(), qt_xrootwin(), NET::WMDesktop );
00641 if ( wm_client.desktop() == NETWinInfo::OnAllDesktops || wm_client.desktop() > 0 )
00642 m_config->setDesktop( wm_client.desktop() );
00643
00644 m_editor->clearFocus();
00645 m_config->setHideNote( true );
00646 m_config->setPosition( pos() );
00647
00648
00649 hide();
00650 }
00651
00652 void KNote::slotInsDate()
00653 {
00654 m_editor->insert( KGlobal::locale()->formatDateTime(QDateTime::currentDateTime()) );
00655 }
00656
00657 void KNote::slotSetAlarm()
00658 {
00659 KNoteAlarmDlg dlg( name(), this );
00660 dlg.setIncidence( m_journal );
00661
00662 if ( dlg.exec() == QDialog::Accepted )
00663 emit sigDataChanged();
00664 }
00665
00666 void KNote::slotPreferences()
00667 {
00668
00669 if ( KNoteConfigDlg::showDialog( noteId().utf8() ) )
00670 return;
00671
00672
00673 KNoteConfigDlg *dialog = new KNoteConfigDlg( m_config, name(), this, noteId().utf8() );
00674 connect( dialog, SIGNAL(settingsChanged()), this, SLOT(slotApplyConfig()) );
00675 connect( this, SIGNAL(sigNameChanged()), dialog, SLOT(slotUpdateCaption()) );
00676 dialog->show();
00677 }
00678
00679 void KNote::slotSend()
00680 {
00681
00682 KNoteHostDlg hostDlg( i18n("Send \"%1\"").arg( name() ), this );
00683 bool ok = (hostDlg.exec() == QDialog::Accepted);
00684 QString host = hostDlg.host();
00685
00686 if ( !ok )
00687 return;
00688
00689 if ( host.isEmpty() )
00690 {
00691 KMessageBox::sorry( this, i18n("The host cannot be empty.") );
00692 return;
00693 }
00694
00695
00696 KNotesNetworkSender *sender = new KNotesNetworkSender( host, KNotesGlobalConfig::port() );
00697 sender->setSenderId( KNotesGlobalConfig::senderID() );
00698 sender->setNote( name(), text() );
00699 sender->connect();
00700 }
00701
00702 void KNote::slotMail()
00703 {
00704
00705 QStringList cmd_list = QStringList::split( QChar(' '), KNotesGlobalConfig::mailAction() );
00706
00707 KProcess mail;
00708 for ( QStringList::Iterator it = cmd_list.begin();
00709 it != cmd_list.end(); ++it )
00710 {
00711 if ( *it == "%f" )
00712 mail << plainText().local8Bit();
00713 else if ( *it == "%t" )
00714 mail << m_label->text().local8Bit();
00715 else
00716 mail << (*it).local8Bit();
00717 }
00718
00719 if ( !mail.start( KProcess::DontCare ) )
00720 KMessageBox::sorry( this, i18n("Unable to start the mail process.") );
00721 }
00722
00723 void KNote::slotPrint()
00724 {
00725 saveData();
00726
00727 KPrinter printer;
00728 printer.setFullPage( true );
00729
00730 if ( printer.setup( 0, i18n("Print %1").arg(name()) ) )
00731 {
00732 QPainter painter;
00733 painter.begin( &printer );
00734
00735 const int margin = 40;
00736
00737 QPaintDeviceMetrics metrics( painter.device() );
00738 int marginX = margin * metrics.logicalDpiX() / 72;
00739 int marginY = margin * metrics.logicalDpiY() / 72;
00740
00741 QRect body( marginX, marginY,
00742 metrics.width() - marginX * 2,
00743 metrics.height() - marginY * 2 );
00744
00745 QString content;
00746 if ( m_editor->textFormat() == PlainText )
00747 content = QStyleSheet::convertFromPlainText( m_editor->text() );
00748 else
00749 content = m_editor->text();
00750
00751 QSimpleRichText text( content, m_config->font(), m_editor->context(),
00752 m_editor->styleSheet(), m_editor->mimeSourceFactory(),
00753 body.height() );
00754
00755 text.setWidth( &painter, body.width() );
00756 QRect view( body );
00757
00758 int page = 1;
00759
00760 for (;;)
00761 {
00762 text.draw( &painter, body.left(), body.top(), view, colorGroup() );
00763 view.moveBy( 0, body.height() );
00764 painter.translate( 0, -body.height() );
00765
00766
00767 painter.setFont( m_config->font() );
00768 painter.drawText(
00769 view.right() - painter.fontMetrics().width( QString::number( page ) ),
00770 view.bottom() + painter.fontMetrics().ascent() + 5, QString::number( page )
00771 );
00772
00773 if ( view.top() >= text.height() )
00774 break;
00775
00776 printer.newPage();
00777 page++;
00778 }
00779
00780 painter.end();
00781 }
00782 }
00783
00784 void KNote::slotSaveAs()
00785 {
00786 QCheckBox *convert = 0;
00787
00788 if ( m_editor->textFormat() == RichText )
00789 {
00790 convert = new QCheckBox( 0 );
00791 convert->setText( i18n("Save note as plain text") );
00792 }
00793
00794 KFileDialog dlg( QString::null, QString::null, this, "filedialog", true, convert );
00795 dlg.setOperationMode( KFileDialog::Saving );
00796 dlg.setCaption( i18n("Save As") );
00797 dlg.exec();
00798
00799 QString fileName = dlg.selectedFile();
00800 if ( fileName.isEmpty() )
00801 return;
00802
00803 QFile file( fileName );
00804
00805 if ( file.exists() &&
00806 KMessageBox::warningContinueCancel( this, i18n("<qt>A file named <b>%1</b> already exists.<br>"
00807 "Are you sure you want to overwrite it?</qt>").arg( QFileInfo(file).fileName() ) )
00808 != KMessageBox::Continue )
00809 {
00810 return;
00811 }
00812
00813 if ( file.open( IO_WriteOnly ) )
00814 {
00815 QTextStream stream( &file );
00816
00817 if ( convert && convert->isChecked() )
00818 stream << plainText();
00819 else
00820 stream << text();
00821 }
00822 }
00823
00824 void KNote::slotPopupActionToDesktop( int id )
00825 {
00826 toDesktop( id - 1 );
00827 }
00828
00829
00830
00831
00832 void KNote::slotApplyConfig()
00833 {
00834 if ( m_config->richText() )
00835 m_editor->setTextFormat( RichText );
00836 else
00837 m_editor->setTextFormat( PlainText );
00838
00839 m_label->setFont( m_config->titleFont() );
00840 m_editor->setTextFont( m_config->font() );
00841 m_editor->setTabStop( m_config->tabSize() );
00842 m_editor->setAutoIndentMode( m_config->autoIndent() );
00843
00844
00845
00846 if ( sender() )
00847 saveData();
00848
00849 setColor( m_config->fgColor(), m_config->bgColor() );
00850
00851 updateLabelAlignment();
00852 slotUpdateShowInTaskbar();
00853 }
00854
00855 void KNote::slotUpdateKeepAboveBelow()
00856 {
00857 KWin::WindowInfo info( KWin::windowInfo( winId() ) );
00858
00859 if ( m_keepAbove->isChecked() )
00860 {
00861 m_config->setKeepAbove( true );
00862 m_config->setKeepBelow( false );
00863 KWin::setState( winId(), info.state() | NET::KeepAbove );
00864 }
00865 else if ( m_keepBelow->isChecked() )
00866 {
00867 m_config->setKeepAbove( false );
00868 m_config->setKeepBelow( true );
00869 KWin::setState( winId(), info.state() | NET::KeepBelow );
00870 }
00871 else
00872 {
00873 m_config->setKeepAbove( false );
00874 KWin::clearState( winId(), NET::KeepAbove );
00875
00876 m_config->setKeepBelow( false );
00877 KWin::clearState( winId(), NET::KeepBelow );
00878 }
00879 }
00880
00881 void KNote::slotUpdateShowInTaskbar()
00882 {
00883 if ( !m_config->showInTaskbar() )
00884 KWin::setState( winId(), KWin::windowInfo(winId()).state() | NET::SkipTaskbar );
00885 else
00886 KWin::clearState( winId(), NET::SkipTaskbar );
00887 }
00888
00889 void KNote::slotUpdateDesktopActions()
00890 {
00891 NETRootInfo wm_root( qt_xdisplay(), NET::NumberOfDesktops | NET::DesktopNames );
00892 NETWinInfo wm_client( qt_xdisplay(), winId(), qt_xrootwin(), NET::WMDesktop );
00893
00894 QStringList desktops;
00895 desktops.append( i18n("&All Desktops") );
00896 desktops.append( QString::null );
00897
00898 int count = wm_root.numberOfDesktops();
00899 for ( int n = 1; n <= count; n++ )
00900 desktops.append( QString("&%1 %2").arg( n ).arg( QString::fromUtf8(wm_root.desktopName( n )) ) );
00901
00902 m_toDesktop->setItems( desktops );
00903
00904 if ( wm_client.desktop() == NETWinInfo::OnAllDesktops )
00905 m_toDesktop->setCurrentItem( 0 );
00906 else
00907 m_toDesktop->setCurrentItem( wm_client.desktop() + 1 );
00908 }
00909
00910 void KNote::slotUpdateViewport( int , int y )
00911 {
00912 if ( s_ppOffset )
00913 updateBackground( y );
00914 }
00915
00916
00917
00918 void KNote::toDesktop( int desktop )
00919 {
00920 if ( desktop == 0 )
00921 return;
00922
00923 if ( desktop == NETWinInfo::OnAllDesktops )
00924 KWin::setOnAllDesktops( winId(), true );
00925 else
00926 KWin::setOnDesktop( winId(), desktop );
00927 }
00928
00929 void KNote::setColor( const QColor &fg, const QColor &bg )
00930 {
00931 QPalette newpalette = palette();
00932 newpalette.setColor( QColorGroup::Background, bg );
00933 newpalette.setColor( QColorGroup::Foreground, fg );
00934 newpalette.setColor( QColorGroup::Base, bg );
00935 newpalette.setColor( QColorGroup::Text, fg );
00936 newpalette.setColor( QColorGroup::Button, bg );
00937 newpalette.setColor( QColorGroup::ButtonText, fg );
00938
00939
00940
00941
00942
00943 newpalette.setColor( QColorGroup::Midlight, bg.light(150) );
00944 newpalette.setColor( QColorGroup::Shadow, bg.dark(116) );
00945 newpalette.setColor( QColorGroup::Light, bg.light(180) );
00946 if ( s_ppOffset )
00947 newpalette.setColor( QColorGroup::Dark, bg.dark(200) );
00948 else
00949 newpalette.setColor( QColorGroup::Dark, bg.dark(108) );
00950 setPalette( newpalette );
00951
00952
00953 m_editor->setTextColor( fg );
00954
00955
00956 updateBackground();
00957
00958
00959 QPalette darker = palette();
00960 darker.setColor( QColorGroup::Button, bg.dark(116) );
00961 m_button->setPalette( darker );
00962
00963
00964 KIconEffect effect;
00965 QPixmap icon = effect.apply( kapp->icon(), KIconEffect::Colorize, 1, bg, false );
00966 QPixmap miniIcon = effect.apply( kapp->miniIcon(), KIconEffect::Colorize, 1, bg, false );
00967 KWin::setIcons( winId(), icon, miniIcon );
00968
00969
00970 QColor sel = palette().color( QPalette::Active, QColorGroup::Base ).dark();
00971 if ( sel == Qt::black )
00972 sel = palette().color( QPalette::Active, QColorGroup::Base ).light();
00973
00974 m_editor->setSelectionAttributes( 1, sel, true );
00975
00976
00977 createFold();
00978
00979
00980 updateFocus();
00981 emit sigColorChanged();
00982 }
00983
00984 void KNote::createFold()
00985 {
00986 QPixmap fold( 15, 15 );
00987 QPainter foldp( &fold );
00988 foldp.setPen( Qt::NoPen );
00989 foldp.setBrush( palette().active().dark() );
00990 QPointArray foldpoints( 3 );
00991 foldpoints.putPoints( 0, 3, 0, 0, 14, 0, 0, 14 );
00992 foldp.drawPolygon( foldpoints );
00993 foldp.end();
00994 m_fold->setPixmap( fold );
00995 }
00996
00997 void KNote::updateLabelAlignment()
00998 {
00999
01000 QString labelText = m_label->text();
01001 if ( m_label->fontMetrics().boundingRect( labelText ).width() > m_label->width() )
01002 m_label->setAlignment( AlignLeft );
01003 else
01004 m_label->setAlignment( AlignHCenter );
01005 }
01006
01007 void KNote::updateFocus()
01008 {
01009 if ( hasFocus() )
01010 {
01011 m_label->setBackgroundColor( palette().active().shadow() );
01012 m_button->show();
01013 m_editor->cornerWidget()->show();
01014
01015 if ( !m_editor->isReadOnly() )
01016 {
01017 if ( m_tool->isHidden() && m_editor->textFormat() == QTextEdit::RichText )
01018 {
01019 m_tool->show();
01020 setGeometry( x(), y(), width(), height() + m_tool->height() );
01021 }
01022 }
01023 else if ( !m_tool->isHidden() )
01024 {
01025 m_tool->hide();
01026 setGeometry( x(), y(), width(), height() - m_tool->height() );
01027 updateLayout();
01028 }
01029
01030 m_fold->hide();
01031 }
01032 else
01033 {
01034 m_button->hide();
01035 m_editor->cornerWidget()->hide();
01036
01037 if ( !m_tool->isHidden() )
01038 {
01039 m_tool->hide();
01040 setGeometry( x(), y(), width(), height() - m_tool->height() );
01041 updateLayout();
01042 }
01043
01044 if ( s_ppOffset )
01045 {
01046 m_label->setBackgroundColor( palette().active().midlight() );
01047 m_fold->show();
01048 }
01049 else
01050 m_label->setBackgroundColor( palette().active().background() );
01051 }
01052 }
01053
01054 void KNote::updateMask()
01055 {
01056 if ( !s_ppOffset )
01057 {
01058 clearMask();
01059 return;
01060 }
01061
01062 int w = width();
01063 int h = height();
01064 QRegion reg( 0, s_ppOffset, w, h - s_ppOffset );
01065
01066 const QBitmap *pushpin_bitmap = m_pushpin->pixmap()->mask();
01067 QRegion pushpin_reg( *pushpin_bitmap );
01068 m_pushpin->setMask( pushpin_reg );
01069 pushpin_reg.translate( m_pushpin->x(), m_pushpin->y() );
01070
01071 if ( !hasFocus() )
01072 {
01073 QPointArray foldpoints( 3 );
01074 foldpoints.putPoints( 0, 3, w-15, h, w, h-15, w, h );
01075 QRegion fold( foldpoints, false );
01076 setMask( reg.unite( pushpin_reg ).subtract( fold ) );
01077 }
01078 else
01079 setMask( reg.unite( pushpin_reg ) );
01080 }
01081
01082 void KNote::updateBackground( int y_offset )
01083 {
01084 if ( !s_ppOffset )
01085 {
01086 m_editor->setPaper( QBrush( colorGroup().background() ) );
01087 return;
01088 }
01089
01090 int w = m_editor->visibleWidth();
01091 int h = m_editor->visibleHeight();
01092
01093
01094
01095
01096 if ( y_offset == -1 )
01097 y_offset = m_editor->contentsY();
01098
01099 y_offset = y_offset % h;
01100
01101 QImage grad_img( w, h, 32 );
01102 QRgb rgbcol;
01103 QColor bg = palette().active().background();
01104
01105 for ( int i = 0; i < h; ++i )
01106 {
01107
01108
01109
01110
01111
01112
01113
01114 int i_1 = 150 - 75 * ((i - y_offset + h) % h) / h;
01115 rgbcol = bg.light( i_1 ).rgb();
01116 for ( int j = 0; j < w; ++j )
01117 grad_img.setPixel( j, i, rgbcol );
01118 }
01119
01120
01121 m_editor->setPaper( QBrush( Qt::black, QPixmap( grad_img ) ) );
01122 }
01123
01124 void KNote::updateLayout()
01125 {
01126 const int headerHeight = m_label->sizeHint().height();
01127 const int margin = m_editor->margin();
01128 bool closeLeft = false;
01129
01130 m_kwinConf->setGroup( "Style" );
01131 if ( m_kwinConf->readBoolEntry( "CustomButtonPositions" ) )
01132 closeLeft = m_kwinConf->readEntry( "ButtonsOnLeft" ).find( 'X' ) > -1;
01133
01134 if ( s_ppOffset )
01135 {
01136 if ( !m_editor->paper().pixmap() )
01137 setColor( palette().active().foreground(), palette().active().background() );
01138
01139 m_pushpin->show();
01140 setFrameStyle( Panel | Raised );
01141
01142 if ( closeLeft )
01143 m_pushpin->move( width() - m_pushpin->width(), 0 );
01144 else
01145 m_pushpin->move( 0, 0 );
01146 }
01147 else
01148 {
01149 if ( m_editor->paper().pixmap() )
01150 setColor( palette().active().foreground(), palette().active().background() );
01151
01152 setFrameStyle( WinPanel | Raised );
01153 m_pushpin->hide();
01154 m_fold->hide();
01155 }
01156
01157 m_button->setGeometry(
01158 closeLeft ? contentsRect().x() : contentsRect().width() - headerHeight,
01159 contentsRect().y() + s_ppOffset,
01160 headerHeight,
01161 headerHeight
01162 );
01163
01164 m_label->setGeometry(
01165 contentsRect().x(), contentsRect().y() + s_ppOffset,
01166 contentsRect().width(), headerHeight
01167 );
01168
01169 m_editor->setGeometry( QRect(
01170 QPoint( contentsRect().x(),
01171 contentsRect().y() + headerHeight + s_ppOffset ),
01172 QPoint( contentsRect().right(),
01173 contentsRect().bottom() - (m_tool->isHidden() ? 0 : m_tool->height()) )
01174 ) );
01175
01176 m_tool->setGeometry(
01177 contentsRect().x(),
01178 contentsRect().bottom() - m_tool->height() + 1,
01179 contentsRect().width(),
01180 m_tool->height()
01181 );
01182
01183 if ( s_ppOffset )
01184 m_fold->move( width() - 15, height() - 15 );
01185
01186 setMinimumSize(
01187 m_editor->cornerWidget()->width() + margin*2,
01188 headerHeight + s_ppOffset + (m_tool->isHidden() ? 0 : m_tool->height()) +
01189 m_editor->cornerWidget()->height() + margin*2
01190 );
01191
01192 updateLabelAlignment();
01193 updateMask();
01194 updateBackground();
01195 }
01196
01197
01198
01199 void KNote::drawFrame( QPainter *p )
01200 {
01201 QRect r = frameRect();
01202 r.setTop( s_ppOffset );
01203 if ( s_ppOffset )
01204 qDrawShadePanel( p, r, colorGroup(), false, lineWidth() );
01205 else
01206 qDrawWinPanel( p, r, colorGroup(), false );
01207 }
01208
01209 void KNote::showEvent( QShowEvent * )
01210 {
01211 if ( m_config->hideNote() )
01212 {
01213
01214 slotUpdateKeepAboveBelow();
01215 slotUpdateShowInTaskbar();
01216 toDesktop( m_config->desktop() );
01217 move( m_config->position() );
01218 m_config->setHideNote( false );
01219 }
01220 }
01221
01222 void KNote::resizeEvent( QResizeEvent *qre )
01223 {
01224 QFrame::resizeEvent( qre );
01225 updateLayout();
01226 }
01227
01228 void KNote::closeEvent( QCloseEvent * )
01229 {
01230 slotClose();
01231 }
01232
01233 void KNote::dragEnterEvent( QDragEnterEvent *e )
01234 {
01235 if ( !m_config->readOnly() )
01236 e->accept( KColorDrag::canDecode( e ) );
01237 }
01238
01239 void KNote::dropEvent( QDropEvent *e )
01240 {
01241 if ( m_config->readOnly() )
01242 return;
01243
01244 QColor bg;
01245 if ( KColorDrag::decode( e, bg ) )
01246 {
01247 setColor( paletteForegroundColor(), bg );
01248 m_journal->setCustomProperty( "KNotes", "BgColor", bg.name() );
01249 m_config->setBgColor( bg );
01250 }
01251 }
01252
01253 bool KNote::focusNextPrevChild( bool )
01254 {
01255 return true;
01256 }
01257
01258 bool KNote::event( QEvent *ev )
01259 {
01260 if ( ev->type() == QEvent::LayoutHint )
01261 {
01262 updateLayout();
01263 return true;
01264 }
01265 else
01266 return QFrame::event( ev );
01267 }
01268
01269 bool KNote::eventFilter( QObject *o, QEvent *ev )
01270 {
01271 if ( ev->type() == QEvent::DragEnter &&
01272 KColorDrag::canDecode( static_cast<QDragEnterEvent *>(ev) ) )
01273 {
01274 dragEnterEvent( static_cast<QDragEnterEvent *>(ev) );
01275 return true;
01276 }
01277
01278 if ( ev->type() == QEvent::Drop &&
01279 KColorDrag::canDecode( static_cast<QDropEvent *>(ev) ) )
01280 {
01281 dropEvent( static_cast<QDropEvent *>(ev) );
01282 return true;
01283 }
01284
01285 if ( o == m_label )
01286 {
01287 QMouseEvent *e = (QMouseEvent *)ev;
01288
01289 if ( ev->type() == QEvent::MouseButtonDblClick )
01290 slotRename();
01291
01292 if ( ev->type() == QEvent::MouseButtonPress &&
01293 (e->button() == LeftButton || e->button() == MidButton))
01294 {
01295 e->button() == LeftButton ? KWin::raiseWindow( winId() )
01296 : KWin::lowerWindow( winId() );
01297
01298 XUngrabPointer( qt_xdisplay(), qt_x_time );
01299 NETRootInfo wm_root( qt_xdisplay(), NET::WMMoveResize );
01300 wm_root.moveResizeRequest( winId(), e->globalX(), e->globalY(), NET::Move );
01301 return true;
01302 }
01303
01304 #if KDE_IS_VERSION( 3, 5, 1 )
01305 if ( ev->type() == QEvent::MouseButtonRelease )
01306 {
01307 NETRootInfo wm_root( qt_xdisplay(), NET::WMMoveResize );
01308 wm_root.moveResizeRequest( winId(), e->globalX(), e->globalY(), NET::MoveResizeCancel );
01309 return false;
01310 }
01311 #endif
01312
01313 if ( m_menu && ( ev->type() == QEvent::MouseButtonPress )
01314 && ( e->button() == RightButton ) )
01315 {
01316 m_menu->popup( QCursor::pos() );
01317 return true;
01318 }
01319
01320 return false;
01321 }
01322
01323 if ( o == m_editor )
01324 {
01325 if ( ev->type() == QEvent::FocusOut )
01326 {
01327 QFocusEvent *fe = static_cast<QFocusEvent *>(ev);
01328 if ( fe->reason() != QFocusEvent::Popup &&
01329 fe->reason() != QFocusEvent::Mouse )
01330 {
01331 updateFocus();
01332 if ( m_editor->isModified() )
01333 saveData();
01334 }
01335 }
01336 else if ( ev->type() == QEvent::FocusIn )
01337 updateFocus();
01338
01339 return false;
01340 }
01341
01342 if ( o == m_editor->viewport() )
01343 {
01344 if ( m_edit_menu &&
01345 ev->type() == QEvent::MouseButtonPress &&
01346 ((QMouseEvent *)ev)->button() == RightButton )
01347 {
01348 m_edit_menu->popup( QCursor::pos() );
01349 return true;
01350 }
01351 }
01352
01353 return false;
01354 }
01355
01356
01357 #include "knote.moc"
01358 #include "knotebutton.moc"