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