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