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 <tdeapplication.h> 00036 #include <kdebug.h> 00037 #include <tdeaction.h> 00038 #include <kstdaction.h> 00039 #include <kcombobox.h> 00040 #include <tdetoolbar.h> 00041 #include <tdepopupmenu.h> 00042 #include <kxmlguibuilder.h> 00043 #include <kxmlguifactory.h> 00044 #include <kcolordrag.h> 00045 #include <kiconeffect.h> 00046 #include <tdelocale.h> 00047 #include <kstandarddirs.h> 00048 #include <tdemessagebox.h> 00049 #include <kfind.h> 00050 #include <kprocess.h> 00051 #include <kinputdialog.h> 00052 #include <kmdcodec.h> 00053 #include <tdeglobalsettings.h> 00054 #include <tdefiledialog.h> 00055 #include <tdeio/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 <twin.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_twinConf( TDESharedConfig::openConfig( "twinrc", 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 = TDEGlobal::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 TDEAction( i18n("New"), "document-new", 0, 00108 TQT_TQOBJECT(this),TQT_SLOT(slotRequestNewNote()) , actionCollection(), "new_note" ); 00109 new TDEAction( i18n("Rename..."), "text", 0, 00110 TQT_TQOBJECT(this), TQT_SLOT(slotRename()), actionCollection(), "rename_note" ); 00111 m_readOnly = new TDEToggleAction( i18n("Lock"), "system-lock-screen" , 0, 00112 TQT_TQOBJECT(this), TQT_SLOT(slotUpdateReadOnly()), actionCollection(), "lock_note" ); 00113 m_readOnly->setCheckedState( KGuiItem( i18n("Unlock"), "unlock" ) ); 00114 new TDEAction( i18n("Hide"), "window-close" , Key_Escape, 00115 TQT_TQOBJECT(this), TQT_SLOT(slotClose()), actionCollection(), "hide_note" ); 00116 new TDEAction( i18n("Delete"), "knotes_delete", 0, 00117 TQT_TQOBJECT(this), TQT_SLOT(slotKill()), actionCollection(), "delete_note" ); 00118 00119 new TDEAction( i18n("Insert Date"), "knotes_date", 0 , 00120 TQT_TQOBJECT(this), TQT_SLOT(slotInsDate()), actionCollection(), "insert_date" ); 00121 new TDEAction( i18n("Set Alarm..."), "knotes_alarm", 0 , 00122 TQT_TQOBJECT(this), TQT_SLOT(slotSetAlarm()), actionCollection(), "set_alarm" ); 00123 00124 new TDEAction( i18n("Send..."), "network", 0, 00125 TQT_TQOBJECT(this), TQT_SLOT(slotSend()), actionCollection(), "send_note" ); 00126 new TDEAction( i18n("Mail..."), "mail-send", 0, 00127 TQT_TQOBJECT(this), TQT_SLOT(slotMail()), actionCollection(), "mail_note" ); 00128 new TDEAction( i18n("Save As..."), "document-save-as", 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 TDEAction( i18n("Preferences..."), "configure", 0, 00132 TQT_TQOBJECT(this), TQT_SLOT(slotPreferences()), actionCollection(), "configure_note" ); 00133 00134 m_keepAbove = new TDEToggleAction( i18n("Keep Above Others"), "go-up", 0, 00135 TQT_TQOBJECT(this), TQT_SLOT(slotUpdateKeepAboveBelow()), actionCollection(), "keep_above" ); 00136 m_keepAbove->setExclusiveGroup( "keepAB" ); 00137 00138 m_keepBelow = new TDEToggleAction( i18n("Keep Below Others"), "go-down", 0, 00139 TQT_TQOBJECT(this), TQT_SLOT(slotUpdateKeepAboveBelow()), actionCollection(), "keep_below" ); 00140 m_keepBelow->setExclusiveGroup( "keepAB" ); 00141 00142 m_toDesktop = new TDEListAction( 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 TDEAction( 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<TDEPopupMenu*>(factory.container( "note_context", this )); 00172 m_edit_menu = dynamic_cast<TDEPopupMenu*>(factory.container( "note_edit", this )); 00173 m_tool = dynamic_cast<TDEToolBar*>(factory.container( "note_tool", this )); 00174 00175 if ( m_tool ) { 00176 m_tool->setIconSize( 10 ); 00177 m_tool->setFixedHeight( 16 ); 00178 m_tool->setIconText( TDEToolBar::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 = TDEGlobal::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 = !TDEIO::NetAccess::exists( KURL::fromPathOrURL( configFile ), false, 0 ); 00223 00224 m_config = new KNoteConfig( TDESharedConfig::openConfig( configFile, false, false ) ); 00225 m_config->readConfig(); 00226 m_config->setVersion( KNOTES_VERSION ); 00227 00228 if ( newNote ) 00229 { 00230 // until tdelibs provides copying of TDEConfigSkeletons (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_twinConf->setGroup( "Style" ); 00266 if ( m_twinConf->readBoolEntry( "CustomButtonPositions" ) ) 00267 closeLeft = m_twinConf->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 TDEConfig 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 TDEIconEffect effect; 00363 TQPixmap icon = effect.apply( kapp->icon(), TDEIconEffect::Colorize, 1, m_config->bgColor(), false ); 00364 TQPixmap miniIcon = effect.apply( kapp->miniIcon(), TDEIconEffect::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"), "edit-delete" ), 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 = TDEGlobal::dirs()->saveLocation( "appdata", "notes/" ); 00411 configFile += m_journal->uid(); 00412 00413 if ( !TDEIO::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( tqt_xdisplay(), winId(), tqt_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 TQDateTime KNote::getLastModified() const 00457 { 00458 return m_journal->lastModified(); 00459 } 00460 00461 TQString KNote::name() const 00462 { 00463 return m_label->text(); 00464 } 00465 00466 TQString KNote::text() const 00467 { 00468 return m_editor->text(); 00469 } 00470 00471 TQString KNote::plainText() const 00472 { 00473 if ( m_editor->textFormat() == RichText ) 00474 { 00475 TQTextEdit conv; 00476 conv.setTextFormat( RichText ); 00477 conv.setText( m_editor->text() ); 00478 conv.setTextFormat( PlainText ); 00479 return conv.text(); 00480 } 00481 else 00482 return m_editor->text(); 00483 } 00484 00485 void KNote::setName( const TQString& name ) 00486 { 00487 m_label->setText( name ); 00488 updateLabelAlignment(); 00489 00490 if ( m_editor ) // not called from CTOR? 00491 saveData(); 00492 00493 // set the window's name for the taskbar entry to be more helpful (#58338) 00494 NETWinInfo note_win( tqt_xdisplay(), winId(), tqt_xrootwin(), NET::WMDesktop ); 00495 note_win.setName( name.utf8() ); 00496 00497 emit sigNameChanged(); 00498 } 00499 00500 void KNote::setText( const TQString& text ) 00501 { 00502 m_editor->setText( text ); 00503 saveData(); 00504 } 00505 00506 TQColor KNote::fgColor() const 00507 { 00508 return m_config->fgColor(); 00509 } 00510 00511 TQColor KNote::bgColor() const 00512 { 00513 return m_config->bgColor(); 00514 } 00515 00516 void KNote::setColor( const TQColor& fg, const TQColor& bg ) 00517 { 00518 bool updateJournal = false; 00519 TQString journalFg = m_journal->customProperty( "KNotes", "FgColor" ); 00520 if ( journalFg.isEmpty() || journalFg != fg.name() ) 00521 { 00522 m_journal->setCustomProperty( "KNotes", "FgColor", fg.name() ); 00523 updateJournal = true; 00524 } 00525 TQString journalbg = m_journal->customProperty( "KNotes", "BgColor" ); 00526 if ( journalbg.isEmpty() || journalbg != bg.name() ) 00527 { 00528 m_journal->setCustomProperty( "KNotes", "BgColor", bg.name() ); 00529 updateJournal = true; 00530 } 00531 00532 m_config->setFgColor( fg ); 00533 m_config->setBgColor( bg ); 00534 00535 if (updateJournal) 00536 { 00537 // Only update the journal if new configuration was really used. 00538 // This is necessary because setColor() is called also when loading a note from an .ics 00539 // file and we do not want to inadvertantly update the last modified field each time. 00540 m_journal->updated(); // because setCustomProperty() doesn't call it!! 00541 emit sigDataChanged(noteId()); 00542 } 00543 m_config->writeConfig(); 00544 00545 TQPalette newpalette = palette(); 00546 newpalette.setColor( TQColorGroup::Background, bg ); 00547 newpalette.setColor( TQColorGroup::Foreground, fg ); 00548 newpalette.setColor( TQColorGroup::Base, bg ); // text background 00549 newpalette.setColor( TQColorGroup::Text, fg ); // text color 00550 newpalette.setColor( TQColorGroup::Button, bg ); 00551 newpalette.setColor( TQColorGroup::ButtonText, fg ); 00552 00553 // newpalette.setColor( TQColorGroup::Highlight, bg ); 00554 // newpalette.setColor( TQColorGroup::HighlightedText, fg ); 00555 00556 // the shadow 00557 newpalette.setColor( TQColorGroup::Midlight, bg.light(150) ); 00558 newpalette.setColor( TQColorGroup::Shadow, bg.dark(116) ); 00559 newpalette.setColor( TQColorGroup::Light, bg.light(180) ); 00560 if ( s_ppOffset ) 00561 newpalette.setColor( TQColorGroup::Dark, bg.dark(200) ); 00562 else 00563 newpalette.setColor( TQColorGroup::Dark, bg.dark(108) ); 00564 setPalette( newpalette ); 00565 00566 // set the text color 00567 m_editor->setTextColor( fg ); 00568 00569 // set the background color or gradient 00570 updateBackground(); 00571 00572 // set darker value for the hide button... 00573 TQPalette darker = palette(); 00574 darker.setColor( TQColorGroup::Button, bg.dark(116) ); 00575 m_button->setPalette( darker ); 00576 00577 // update the icon color 00578 TDEIconEffect effect; 00579 TQPixmap icon = effect.apply( kapp->icon(), TDEIconEffect::Colorize, 1, bg, false ); 00580 TQPixmap miniIcon = effect.apply( kapp->miniIcon(), TDEIconEffect::Colorize, 1, bg, false ); 00581 KWin::setIcons( winId(), icon, miniIcon ); 00582 00583 // set the color for the selection used to highlight the find stuff 00584 TQColor sel = palette().color( TQPalette::Active, TQColorGroup::Base ).dark(); 00585 if ( sel == TQt::black ) 00586 sel = palette().color( TQPalette::Active, TQColorGroup::Base ).light(); 00587 00588 m_editor->setSelectionAttributes( 1, sel, true ); 00589 00590 // update the color of the fold 00591 createFold(); 00592 00593 // update the color of the title 00594 updateFocus(); 00595 emit sigColorChanged(); 00596 } 00597 00598 void KNote::find( const TQString& pattern, long options ) 00599 { 00600 delete m_find; 00601 m_find = new KFind( pattern, options, this ); 00602 00603 connect( m_find, TQT_SIGNAL(highlight( const TQString &, int, int )), 00604 TQT_TQOBJECT(this), TQT_SLOT(slotHighlight( const TQString &, int, int )) ); 00605 connect( m_find, TQT_SIGNAL(findNext()), TQT_TQOBJECT(this), TQT_SLOT(slotFindNext()) ); 00606 00607 m_find->setData( plainText() ); 00608 slotFindNext(); 00609 } 00610 00611 void KNote::slotFindNext() 00612 { 00613 // TODO: honor FindBackwards 00614 // TODO: dialogClosed() -> delete m_find 00615 00616 // Let KFind inspect the text fragment, and display a dialog if a match is found 00617 KFind::Result res = m_find->find(); 00618 00619 if ( res == KFind::NoMatch ) // i.e. at end-pos 00620 { 00621 m_editor->removeSelection( 1 ); 00622 emit sigFindFinished(); 00623 delete m_find; 00624 m_find = 0; 00625 } 00626 else 00627 { 00628 show(); 00629 KWin::setCurrentDesktop( KWin::windowInfo( winId() ).desktop() ); 00630 } 00631 } 00632 00633 void KNote::slotHighlight( const TQString& str, int idx, int len ) 00634 { 00635 int paraFrom = 0, idxFrom = 0, p = 0; 00636 for ( ; p < idx; ++p ) 00637 if ( str[p] == '\n' ) 00638 { 00639 ++paraFrom; 00640 idxFrom = 0; 00641 } 00642 else 00643 ++idxFrom; 00644 00645 int paraTo = paraFrom, idxTo = idxFrom; 00646 00647 for ( ; p < idx + len; ++p ) 00648 { 00649 if ( str[p] == '\n' ) 00650 { 00651 ++paraTo; 00652 idxTo = 0; 00653 } 00654 else 00655 ++idxTo; 00656 } 00657 00658 m_editor->setSelection( paraFrom, idxFrom, paraTo, idxTo, 1 ); 00659 } 00660 00661 bool KNote::isModified() const 00662 { 00663 return m_editor->isModified(); 00664 } 00665 00666 // FIXME KDE 4.0: remove sync(), isNew() and isModified() 00667 void KNote::sync( const TQString& app ) 00668 { 00669 TQByteArray sep( 1 ); 00670 sep[0] = '\0'; 00671 00672 KMD5 hash; 00673 TQCString result; 00674 00675 hash.update( m_label->text().utf8() ); 00676 hash.update( sep ); 00677 hash.update( m_editor->text().utf8() ); 00678 hash.hexDigest( result ); 00679 00680 // hacky... not possible with TDEConfig XT 00681 TDEConfig *config = m_config->config(); 00682 config->setGroup( "Synchronisation" ); 00683 config->writeEntry( app, result.data() ); 00684 } 00685 00686 bool KNote::isNew( const TQString& app ) const 00687 { 00688 TDEConfig *config = m_config->config(); 00689 config->setGroup( "Synchronisation" ); 00690 TQString hash = config->readEntry( app ); 00691 return hash.isEmpty(); 00692 } 00693 00694 bool KNote::isModified( const TQString& app ) const 00695 { 00696 TQByteArray sep( 1 ); 00697 sep[0] = '\0'; 00698 00699 KMD5 hash; 00700 hash.update( m_label->text().utf8() ); 00701 hash.update( sep ); 00702 hash.update( m_editor->text().utf8() ); 00703 hash.hexDigest(); 00704 00705 TDEConfig *config = m_config->config(); 00706 config->setGroup( "Synchronisation" ); 00707 TQString orig = config->readEntry( app ); 00708 00709 if ( hash.verify( orig.utf8() ) ) // returns false on error! 00710 return false; 00711 else 00712 return true; 00713 } 00714 00715 void KNote::setStyle( int style ) 00716 { 00717 if ( style == KNotesGlobalConfig::EnumStyle::Plain ) 00718 s_ppOffset = 0; 00719 else 00720 s_ppOffset = 12; 00721 } 00722 00723 00724 // ------------------ private slots (menu actions) ------------------ // 00725 00726 void KNote::slotRename() 00727 { 00728 m_blockEmitDataChanged = true; 00729 // pop up dialog to get the new name 00730 bool ok; 00731 aboutToEnterEventLoop(); 00732 TQString oldName = m_label->text(); 00733 TQString newName = KInputDialog::getText( TQString(), 00734 i18n("Please enter the new name:"), m_label->text(), &ok, this ); 00735 eventLoopLeft(); 00736 m_blockEmitDataChanged = false; 00737 if ( !ok || ( oldName == newName) ) // handle cancel 00738 return; 00739 00740 setName( newName ); 00741 } 00742 00743 void KNote::slotUpdateReadOnly() 00744 { 00745 const bool readOnly = m_readOnly->isChecked(); 00746 00747 m_editor->setReadOnly( readOnly ); 00748 m_config->setReadOnly( readOnly ); 00749 00750 // Enable/disable actions accordingly 00751 actionCollection()->action( "configure_note" )->setEnabled( !readOnly ); 00752 actionCollection()->action( "insert_date" )->setEnabled( !readOnly ); 00753 actionCollection()->action( "delete_note" )->setEnabled( !readOnly ); 00754 00755 actionCollection()->action( "edit_undo" )->setEnabled( !readOnly && m_editor->isUndoAvailable() ); 00756 actionCollection()->action( "edit_redo" )->setEnabled( !readOnly && m_editor->isRedoAvailable() ); 00757 actionCollection()->action( "edit_cut" )->setEnabled( !readOnly && m_editor->hasSelectedText() ); 00758 actionCollection()->action( "edit_paste" )->setEnabled( !readOnly ); 00759 actionCollection()->action( "edit_clear" )->setEnabled( !readOnly ); 00760 actionCollection()->action( "rename_note" )->setEnabled( !readOnly ); 00761 00762 actionCollection()->action( "format_bold" )->setEnabled( !readOnly ); 00763 actionCollection()->action( "format_italic" )->setEnabled( !readOnly ); 00764 actionCollection()->action( "format_underline" )->setEnabled( !readOnly ); 00765 actionCollection()->action( "format_strikeout" )->setEnabled( !readOnly ); 00766 actionCollection()->action( "format_alignleft" )->setEnabled( !readOnly ); 00767 actionCollection()->action( "format_aligncenter" )->setEnabled( !readOnly ); 00768 actionCollection()->action( "format_alignright" )->setEnabled( !readOnly ); 00769 actionCollection()->action( "format_alignblock" )->setEnabled( !readOnly ); 00770 actionCollection()->action( "format_list" )->setEnabled( !readOnly ); 00771 actionCollection()->action( "format_super" )->setEnabled( !readOnly ); 00772 actionCollection()->action( "format_sub" )->setEnabled( !readOnly ); 00773 actionCollection()->action( "format_size" )->setEnabled( !readOnly ); 00774 actionCollection()->action( "format_color" )->setEnabled( !readOnly ); 00775 00776 updateFocus(); 00777 } 00778 00779 void KNote::slotClose() 00780 { 00781 NETWinInfo wm_client( tqt_xdisplay(), winId(), tqt_xrootwin(), NET::WMDesktop ); 00782 if ( wm_client.desktop() == NETWinInfo::OnAllDesktops || wm_client.desktop() > 0 ) 00783 m_config->setDesktop( wm_client.desktop() ); 00784 00785 m_editor->clearFocus(); 00786 m_config->setHideNote( true ); 00787 m_config->setPosition( pos() ); 00788 00789 // just hide the note so it's still available from the dock window 00790 hide(); 00791 } 00792 00793 void KNote::slotInsDate() 00794 { 00795 m_editor->insert( TDEGlobal::locale()->formatDateTime(TQDateTime::currentDateTime()) ); 00796 } 00797 00798 void KNote::slotSetAlarm() 00799 { 00800 m_blockEmitDataChanged = true; 00801 KNoteAlarmDlg dlg( name(), this ); 00802 dlg.setIncidence( m_journal ); 00803 00804 aboutToEnterEventLoop(); 00805 if ( dlg.exec() == TQDialog::Accepted ) 00806 emit sigDataChanged(noteId()); 00807 eventLoopLeft(); 00808 m_blockEmitDataChanged = false; 00809 } 00810 00811 void KNote::slotPreferences() 00812 { 00813 // reuse if possible 00814 if ( KNoteConfigDlg::showDialog( noteId().utf8() ) ) 00815 return; 00816 00817 // create a new preferences dialog... 00818 KNoteConfigDlg *dialog = new KNoteConfigDlg( m_config, name(), this, noteId().utf8() ); 00819 connect( dialog, TQT_SIGNAL(settingsChanged()), TQT_TQOBJECT(this), TQT_SLOT(slotApplyConfig()) ); 00820 connect( this, TQT_SIGNAL(sigNameChanged()), dialog, TQT_SLOT(slotUpdateCaption()) ); 00821 dialog->show(); 00822 } 00823 00824 void KNote::slotSend() 00825 { 00826 // pop up dialog to get the IP 00827 KNoteHostDlg hostDlg( i18n("Send \"%1\"").arg( name() ), this ); 00828 aboutToEnterEventLoop(); 00829 bool ok = (hostDlg.exec() == TQDialog::Accepted); 00830 eventLoopLeft(); 00831 if ( !ok ) // handle cancel 00832 return; 00833 TQString host = hostDlg.host(); 00834 00835 if ( host.isEmpty() ) 00836 { 00837 KMessageBox::sorry( this, i18n("The host cannot be empty.") ); 00838 return; 00839 } 00840 00841 // Send the note 00842 KNotesNetworkSender *sender = new KNotesNetworkSender( host, KNotesGlobalConfig::port() ); 00843 sender->setSenderId( KNotesGlobalConfig::senderID() ); 00844 sender->setNote( name(), text() ); 00845 sender->connect(); 00846 } 00847 00848 void KNote::slotMail() 00849 { 00850 // get the mail action command 00851 const TQStringList cmd_list = TQStringList::split( TQChar(' '), KNotesGlobalConfig::mailAction() ); 00852 00853 TDEProcess mail; 00854 for ( TQStringList::ConstIterator it = cmd_list.constBegin(); 00855 it != cmd_list.constEnd(); ++it ) 00856 { 00857 if ( *it == "%f" ) 00858 mail << plainText().local8Bit(); // convert rich text to plain text 00859 else if ( *it == "%t" ) 00860 mail << m_label->text().local8Bit(); 00861 else 00862 mail << (*it).local8Bit(); 00863 } 00864 00865 if ( !mail.start( TDEProcess::DontCare ) ) 00866 KMessageBox::sorry( this, i18n("Unable to start the mail process.") ); 00867 } 00868 00869 void KNote::slotPrint() 00870 { 00871 TQString content; 00872 if ( m_editor->textFormat() == PlainText ) 00873 content = TQStyleSheet::convertFromPlainText( m_editor->text() ); 00874 else 00875 content = m_editor->text(); 00876 00877 KNotePrinter printer; 00878 printer.setMimeSourceFactory( m_editor->mimeSourceFactory() ); 00879 printer.setFont( m_config->font() ); 00880 printer.setContext( m_editor->context() ); 00881 printer.setStyleSheet( m_editor->styleSheet() ); 00882 printer.setColorGroup( colorGroup() ); 00883 printer.printNote( TQString(), content ); 00884 } 00885 00886 void KNote::slotSaveAs() 00887 { 00888 m_blockEmitDataChanged = true; 00889 TQCheckBox *convert = 0; 00890 00891 if ( m_editor->textFormat() == RichText ) 00892 { 00893 convert = new TQCheckBox( 0 ); 00894 convert->setText( i18n("Save note as plain text") ); 00895 } 00896 00897 KFileDialog dlg( TQString(), TQString(), this, "filedialog", true, convert ); 00898 dlg.setOperationMode( KFileDialog::Saving ); 00899 dlg.setCaption( i18n("Save As") ); 00900 aboutToEnterEventLoop(); 00901 dlg.exec(); 00902 eventLoopLeft(); 00903 00904 TQString fileName = dlg.selectedFile(); 00905 if ( fileName.isEmpty() ) 00906 { 00907 m_blockEmitDataChanged = false; 00908 return; 00909 } 00910 TQFile file( fileName ); 00911 00912 if ( file.exists() && 00913 KMessageBox::warningContinueCancel( this, i18n("<qt>A file named <b>%1</b> already exists.<br>" 00914 "Are you sure you want to overwrite it?</qt>").arg( TQFileInfo(file).fileName() ) ) 00915 != KMessageBox::Continue ) 00916 { 00917 m_blockEmitDataChanged = false; 00918 return; 00919 } 00920 00921 if ( file.open( IO_WriteOnly ) ) 00922 { 00923 TQTextStream stream( &file ); 00924 // convert rich text to plain text first 00925 if ( convert && convert->isChecked() ) 00926 stream << plainText(); 00927 else 00928 stream << text(); 00929 } 00930 m_blockEmitDataChanged = false; 00931 } 00932 00933 void KNote::slotPopupActionToDesktop( int id ) 00934 { 00935 toDesktop( id - 1 ); // compensate for the menu separator, -1 == all desktops 00936 } 00937 00938 00939 // ------------------ private slots (configuration) ------------------ // 00940 00941 void KNote::slotApplyConfig() 00942 { 00943 if ( m_config->richText() ) 00944 m_editor->setTextFormat( RichText ); 00945 else 00946 m_editor->setTextFormat( PlainText ); 00947 00948 m_label->setFont( m_config->titleFont() ); 00949 m_editor->setTextFont( m_config->font() ); 00950 m_editor->setTabStop( m_config->tabSize() ); 00951 m_editor->setAutoIndentMode( m_config->autoIndent() ); 00952 00953 // if called as a slot, save the text, we might have changed the 00954 // text format - otherwise the journal will not be updated 00955 if ( sender() ) 00956 saveData(); 00957 00958 setColor( m_config->fgColor(), m_config->bgColor() ); 00959 00960 updateLabelAlignment(); 00961 slotUpdateShowInTaskbar(); 00962 } 00963 00964 void KNote::slotUpdateKeepAboveBelow() 00965 { 00966 KWin::WindowInfo info( KWin::windowInfo( winId() ) ); 00967 00968 if ( m_keepAbove->isChecked() ) 00969 { 00970 m_config->setKeepAbove( true ); 00971 m_config->setKeepBelow( false ); 00972 KWin::setState( winId(), info.state() | NET::KeepAbove ); 00973 } 00974 else if ( m_keepBelow->isChecked() ) 00975 { 00976 m_config->setKeepAbove( false ); 00977 m_config->setKeepBelow( true ); 00978 KWin::setState( winId(), info.state() | NET::KeepBelow ); 00979 } 00980 else 00981 { 00982 m_config->setKeepAbove( false ); 00983 KWin::clearState( winId(), NET::KeepAbove ); 00984 00985 m_config->setKeepBelow( false ); 00986 KWin::clearState( winId(), NET::KeepBelow ); 00987 } 00988 } 00989 00990 void KNote::slotUpdateShowInTaskbar() 00991 { 00992 if ( !m_config->showInTaskbar() ) 00993 KWin::setState( winId(), KWin::windowInfo(winId()).state() | NET::SkipTaskbar ); 00994 else 00995 KWin::clearState( winId(), NET::SkipTaskbar ); 00996 } 00997 00998 void KNote::slotUpdateDesktopActions() 00999 { 01000 NETRootInfo wm_root( tqt_xdisplay(), NET::NumberOfDesktops | NET::DesktopNames ); 01001 NETWinInfo wm_client( tqt_xdisplay(), winId(), tqt_xrootwin(), NET::WMDesktop ); 01002 01003 TQStringList desktops; 01004 desktops.append( i18n("&All Desktops") ); 01005 desktops.append( TQString() ); // Separator 01006 01007 int count = wm_root.numberOfDesktops(); 01008 for ( int n = 1; n <= count; n++ ) 01009 desktops.append( TQString("&%1 %2").arg( n ).arg( TQString::fromUtf8(wm_root.desktopName( n )) ) ); 01010 01011 m_toDesktop->setItems( desktops ); 01012 01013 if ( wm_client.desktop() == NETWinInfo::OnAllDesktops ) 01014 m_toDesktop->setCurrentItem( 0 ); 01015 else 01016 m_toDesktop->setCurrentItem( wm_client.desktop() + 1 ); // compensate for separator (+1) 01017 } 01018 01019 void KNote::slotUpdateViewport( int /*x*/, int y ) 01020 { 01021 if ( s_ppOffset ) 01022 updateBackground( y ); 01023 } 01024 01025 // -------------------- private methods -------------------- // 01026 01027 void KNote::toDesktop( int desktop ) 01028 { 01029 if ( desktop == 0 ) 01030 return; 01031 01032 if ( desktop == NETWinInfo::OnAllDesktops ) 01033 KWin::setOnAllDesktops( winId(), true ); 01034 else 01035 KWin::setOnDesktop( winId(), desktop ); 01036 } 01037 01038 void KNote::createFold() 01039 { 01040 TQPixmap fold( 15, 15 ); 01041 TQPainter foldp( &fold ); 01042 foldp.setPen( TQt::NoPen ); 01043 foldp.setBrush( palette().active().dark() ); 01044 TQPointArray foldpoints( 3 ); 01045 foldpoints.putPoints( 0, 3, 0, 0, 14, 0, 0, 14 ); 01046 foldp.drawPolygon( foldpoints ); 01047 foldp.end(); 01048 m_fold->setPixmap( fold ); 01049 } 01050 01051 void KNote::updateLabelAlignment() 01052 { 01053 // if the name is too long to fit, left-align it, otherwise center it (#59028) 01054 TQString labelText = m_label->text(); 01055 if ( m_label->fontMetrics().boundingRect( labelText ).width() > m_label->width() ) 01056 m_label->setAlignment( AlignLeft ); 01057 else 01058 m_label->setAlignment( AlignHCenter ); 01059 } 01060 01061 void KNote::updateFocus() 01062 { 01063 if ( hasFocus() ) 01064 { 01065 m_label->setBackgroundColor( palette().active().shadow() ); 01066 m_button->show(); 01067 01068 if ( !m_editor->isReadOnly() ) 01069 { 01070 if ( m_tool && m_tool->isHidden() && m_editor->textFormat() == TQTextEdit::RichText ) 01071 { 01072 m_tool->show(); 01073 updateLayout(); // to update the editor height 01074 } 01075 m_editor->cornerWidget()->show(); 01076 } 01077 else 01078 { 01079 if ( m_tool && !m_tool->isHidden() ) 01080 { 01081 m_tool->hide(); 01082 updateLayout(); // to update the minimum height 01083 } 01084 m_editor->cornerWidget()->hide(); 01085 } 01086 01087 m_fold->hide(); 01088 } 01089 else 01090 { 01091 m_button->hide(); 01092 m_editor->cornerWidget()->hide(); 01093 01094 if ( m_tool && !m_tool->isHidden() ) 01095 { 01096 m_tool->hide(); 01097 updateLayout(); // to update the minimum height 01098 } 01099 01100 if ( s_ppOffset ) 01101 { 01102 m_label->setBackgroundColor( palette().active().midlight() ); 01103 m_fold->show(); 01104 } 01105 else 01106 m_label->setBackgroundColor( palette().active().background() ); 01107 } 01108 } 01109 01110 void KNote::updateMask() 01111 { 01112 if ( !s_ppOffset ) 01113 { 01114 clearMask(); 01115 return; 01116 } 01117 01118 int w = width(); 01119 int h = height(); 01120 TQRegion reg( 0, s_ppOffset, w, h - s_ppOffset ); 01121 01122 const TQBitmap *pushpin_bitmap = m_pushpin->pixmap()->mask(); 01123 TQRegion pushpin_reg( *pushpin_bitmap ); 01124 m_pushpin->setMask( pushpin_reg ); 01125 pushpin_reg.translate( m_pushpin->x(), m_pushpin->y() ); 01126 01127 if ( !hasFocus() ) 01128 { 01129 TQPointArray foldpoints( 3 ); 01130 foldpoints.putPoints( 0, 3, w-15, h, w, h-15, w, h ); 01131 TQRegion fold( foldpoints, false ); 01132 setMask( reg.unite( pushpin_reg ).subtract( fold ) ); 01133 } 01134 else 01135 setMask( reg.unite( pushpin_reg ) ); 01136 } 01137 01138 void KNote::updateBackground( int y_offset ) 01139 { 01140 if ( !s_ppOffset ) 01141 { 01142 m_editor->setPaper( TQBrush( colorGroup().background() ) ); 01143 return; 01144 } 01145 01146 int w = m_editor->visibleWidth(); 01147 int h = m_editor->visibleHeight(); 01148 01149 // in case y_offset is not set, calculate y_offset as the content 01150 // y-coordinate of the top-left point of the viewport - which is essentially 01151 // the vertical scroll amount 01152 if ( y_offset == -1 ) 01153 y_offset = m_editor->contentsY(); 01154 01155 y_offset = y_offset % h; 01156 01157 TQImage grad_img( w, h, 32 ); 01158 TQRgb rgbcol; 01159 TQColor bg = palette().active().background(); 01160 01161 for ( int i = 0; i < h; ++i ) 01162 { 01163 // if the scrollbar has moved, then adjust the gradient by the amount the 01164 // scrollbar moved -- so that the background gradient looks ok when tiled 01165 01166 // the lightness is calculated as follows: 01167 // if i >= y, then lightness = 150 - (i-y)*75/h; 01168 // if i < y, then lightness = 150 - (i+h-y)*75/h 01169 01170 int i_1 = 150 - 75 * ((i - y_offset + h) % h) / h; 01171 rgbcol = bg.light( i_1 ).rgb(); 01172 for ( int j = 0; j < w; ++j ) 01173 grad_img.setPixel( j, i, rgbcol ); 01174 } 01175 01176 // setPaletteBackgroundPixmap makes TQTextEdit::color() stop working!! 01177 m_editor->setPaper( TQBrush( TQt::black, TQPixmap( grad_img ) ) ); 01178 } 01179 01180 void KNote::updateLayout() 01181 { 01182 const int headerHeight = m_label->sizeHint().height(); 01183 const int margin = m_editor->margin(); 01184 bool closeLeft = false; 01185 01186 m_twinConf->setGroup( "Style" ); 01187 if ( m_twinConf->readBoolEntry( "CustomButtonPositions" ) ) 01188 closeLeft = m_twinConf->readEntry( "ButtonsOnLeft" ).find( 'X' ) > -1; 01189 01190 if ( s_ppOffset ) 01191 { 01192 if ( !m_editor->paper().pixmap() ) // just changed the style 01193 setColor( palette().active().foreground(), palette().active().background() ); 01194 01195 m_pushpin->show(); 01196 setFrameStyle( Panel | Raised ); 01197 01198 if ( closeLeft ) 01199 m_pushpin->move( width() - m_pushpin->width(), 0 ); 01200 else 01201 m_pushpin->move( 0, 0 ); 01202 } 01203 else 01204 { 01205 if ( m_editor->paper().pixmap() ) // just changed the style 01206 setColor( palette().active().foreground(), palette().active().background() ); 01207 01208 setFrameStyle( WinPanel | Raised ); 01209 m_pushpin->hide(); 01210 m_fold->hide(); 01211 } 01212 01213 m_button->setGeometry( 01214 closeLeft ? contentsRect().x() : contentsRect().width() - headerHeight, 01215 contentsRect().y() + s_ppOffset, 01216 headerHeight, 01217 headerHeight 01218 ); 01219 01220 m_label->setGeometry( 01221 contentsRect().x(), contentsRect().y() + s_ppOffset, 01222 contentsRect().width(), headerHeight 01223 ); 01224 01225 m_editor->setGeometry( TQRect( 01226 TQPoint( contentsRect().x(), 01227 contentsRect().y() + headerHeight + s_ppOffset ), 01228 TQPoint( contentsRect().right(), 01229 contentsRect().bottom() - ( m_tool ? (m_tool->isHidden() ? 0 : m_tool->height()) : 0 ) ) 01230 ) ); 01231 01232 if( m_tool ) { 01233 m_tool->setGeometry( 01234 contentsRect().x(), 01235 contentsRect().bottom() - m_tool->height() + 1, 01236 contentsRect().width(), 01237 m_tool->height() 01238 ); 01239 } 01240 01241 if ( s_ppOffset ) 01242 m_fold->move( width() - 15, height() - 15 ); 01243 01244 setMinimumSize( 01245 m_editor->cornerWidget()->width() + margin*2, 01246 headerHeight + s_ppOffset + ( m_tool ? m_tool->height() : 0 ) + 01247 m_editor->cornerWidget()->height() + margin*2 01248 ); 01249 01250 updateLabelAlignment(); 01251 updateMask(); 01252 updateBackground(); 01253 } 01254 01255 // -------------------- protected methods -------------------- // 01256 01257 void KNote::drawFrame( TQPainter *p ) 01258 { 01259 TQRect r = frameRect(); 01260 r.setTop( s_ppOffset ); 01261 if ( s_ppOffset ) 01262 qDrawShadePanel( p, r, colorGroup(), false, lineWidth() ); 01263 else 01264 qDrawWinPanel( p, r, colorGroup(), false ); 01265 } 01266 01267 void KNote::showEvent( TQShowEvent * ) 01268 { 01269 if ( m_config->hideNote() ) 01270 { 01271 // KWin does not preserve these properties for hidden windows 01272 slotUpdateKeepAboveBelow(); 01273 slotUpdateShowInTaskbar(); 01274 toDesktop( m_config->desktop() ); 01275 move( m_config->position() ); 01276 m_config->setHideNote( false ); 01277 } 01278 } 01279 01280 void KNote::resizeEvent( TQResizeEvent *qre ) 01281 { 01282 TQFrame::resizeEvent( qre ); 01283 updateLayout(); 01284 } 01285 01286 void KNote::closeEvent( TQCloseEvent *event ) 01287 { 01288 if(kapp->sessionSaving()) 01289 return; 01290 event->ignore(); //We don't want to close (and delete the widget). Just hide it 01291 slotClose(); 01292 } 01293 01294 void KNote::dragEnterEvent( TQDragEnterEvent *e ) 01295 { 01296 if ( !m_config->readOnly() ) 01297 e->accept( KColorDrag::canDecode( e ) ); 01298 } 01299 01300 void KNote::dropEvent( TQDropEvent *e ) 01301 { 01302 if ( m_config->readOnly() ) 01303 return; 01304 01305 TQColor bg; 01306 if ( KColorDrag::decode( e, bg ) ) 01307 setColor( paletteForegroundColor(), bg ); 01308 } 01309 01310 bool KNote::focusNextPrevChild( bool ) 01311 { 01312 return true; 01313 } 01314 01315 bool KNote::event( TQEvent *ev ) 01316 { 01317 if ( ev->type() == TQEvent::LayoutHint ) 01318 { 01319 updateLayout(); 01320 return true; 01321 } 01322 else 01323 return TQFrame::event( ev ); 01324 } 01325 01326 bool KNote::eventFilter( TQObject *o, TQEvent *ev ) 01327 { 01328 if ( ev->type() == TQEvent::DragEnter && 01329 KColorDrag::canDecode( static_cast<TQDragEnterEvent *>(ev) ) ) 01330 { 01331 dragEnterEvent( static_cast<TQDragEnterEvent *>(ev) ); 01332 return true; 01333 } 01334 01335 if ( ev->type() == TQEvent::Drop && 01336 KColorDrag::canDecode( static_cast<TQDropEvent *>(ev) ) ) 01337 { 01338 dropEvent( static_cast<TQDropEvent *>(ev) ); 01339 return true; 01340 } 01341 01342 if ( TQT_BASE_OBJECT(o) == TQT_BASE_OBJECT(m_label) ) 01343 { 01344 TQMouseEvent *e = (TQMouseEvent *)ev; 01345 01346 if ( ev->type() == TQEvent::MouseButtonDblClick ) 01347 { 01348 if( !m_editor->isReadOnly()) 01349 slotRename(); 01350 } 01351 if ( ev->type() == TQEvent::MouseButtonPress && 01352 (e->button() == Qt::LeftButton || e->button() == Qt::MidButton)) 01353 { 01354 e->button() == Qt::LeftButton ? KWin::raiseWindow( winId() ) 01355 : KWin::lowerWindow( winId() ); 01356 01357 XUngrabPointer( tqt_xdisplay(), GET_QT_X_TIME() ); 01358 NETRootInfo wm_root( tqt_xdisplay(), NET::WMMoveResize ); 01359 wm_root.moveResizeRequest( winId(), e->globalX(), e->globalY(), NET::Move ); 01360 return true; 01361 } 01362 01363 #if KDE_IS_VERSION( 3, 5, 1 ) 01364 if ( ev->type() == TQEvent::MouseButtonRelease ) 01365 { 01366 NETRootInfo wm_root( tqt_xdisplay(), NET::WMMoveResize ); 01367 wm_root.moveResizeRequest( winId(), e->globalX(), e->globalY(), NET::MoveResizeCancel ); 01368 return false; 01369 } 01370 #endif 01371 01372 if ( m_menu && ( ev->type() == TQEvent::MouseButtonPress ) 01373 && ( e->button() == Qt::RightButton ) ) 01374 { 01375 m_menu->popup( TQCursor::pos() ); 01376 return true; 01377 } 01378 01379 return false; 01380 } 01381 01382 if ( TQT_BASE_OBJECT(o) == TQT_BASE_OBJECT(m_editor) ) { 01383 if ( ev->type() == TQEvent::FocusOut ) { 01384 TQFocusEvent *fe = TQT_TQFOCUSEVENT(ev); 01385 if ( fe->reason() != TQFocusEvent::Popup && 01386 fe->reason() != TQFocusEvent::Mouse ) { 01387 updateFocus(); 01388 if ( isModified() ) { 01389 saveConfig(); 01390 if ( !m_blockEmitDataChanged ) 01391 saveData(); 01392 } 01393 } 01394 } else if ( ev->type() == TQEvent::FocusIn ) { 01395 updateFocus(); 01396 } 01397 01398 return false; 01399 } 01400 01401 if ( TQT_BASE_OBJECT(o) == TQT_BASE_OBJECT(m_editor->viewport()) ) 01402 { 01403 if ( m_edit_menu && 01404 ev->type() == TQEvent::MouseButtonPress && 01405 ((TQMouseEvent *)ev)->button() == Qt::RightButton ) 01406 { 01407 m_edit_menu->popup( TQCursor::pos() ); 01408 return true; 01409 } 01410 } 01411 01412 return false; 01413 } 01414 01415 void KNote::slotSaveData() 01416 { 01417 saveData(); 01418 } 01419 01420 void KNote::deleteWhenIdle() 01421 { 01422 if ( m_busy <= 0 ) 01423 deleteLater(); 01424 else 01425 m_deleteWhenIdle = true; 01426 } 01427 01428 void KNote::aboutToEnterEventLoop() 01429 { 01430 ++m_busy; 01431 } 01432 01433 void KNote::eventLoopLeft() 01434 { 01435 --m_busy; 01436 if ( m_busy <= 0 && m_deleteWhenIdle ) 01437 deleteLater(); 01438 } 01439 01440 01441 #include "knote.moc" 01442 #include "knotebutton.moc"
