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