knotes

knote.cpp
1/*******************************************************************
2 KNotes -- Notes for the KDE project
3
4 Copyright (c) 1997-2006, The KNotes Developers
5
6 This program is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License
8 as published by the Free Software Foundation; either version 2
9 of the License, or (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19*******************************************************************/
20
21#include <tqlabel.h>
22#include <tqdrawutil.h>
23#include <tqsize.h>
24#include <tqsizegrip.h>
25#include <tqbitmap.h>
26#include <tqcursor.h>
27#include <tqpainter.h>
28#include <tqpaintdevicemetrics.h>
29#include <tqsimplerichtext.h>
30#include <tqobjectlist.h>
31#include <tqfile.h>
32#include <tqcheckbox.h>
33#include <tqtimer.h>
34
35#include <tdeapplication.h>
36#include <kdebug.h>
37#include <tdeaction.h>
38#include <kstdaction.h>
39#include <kcombobox.h>
40#include <tdetoolbar.h>
41#include <tdepopupmenu.h>
42#include <kxmlguibuilder.h>
43#include <kxmlguifactory.h>
44#include <kcolordrag.h>
45#include <kiconeffect.h>
46#include <tdelocale.h>
47#include <tdestandarddirs.h>
48#include <tdemessagebox.h>
49#include <kfind.h>
50#include <tdeprocess.h>
51#include <kinputdialog.h>
52#include <kmdcodec.h>
53#include <tdeglobalsettings.h>
54#include <tdefiledialog.h>
55#include <tdeio/netaccess.h>
56
57#include <libkcal/journal.h>
58
59#include "knote.h"
60#include "knotebutton.h"
61#include "knoteedit.h"
62#include "knoteconfig.h"
63#include "knotesglobalconfig.h"
64#include "knoteconfigdlg.h"
65#include "knotealarmdlg.h"
66#include "knotehostdlg.h"
67#include "knotesnetsend.h"
68#include "knoteprinter.h"
69#include "version.h"
70
71#include "pushpin.xpm"
72
73#include <twin.h>
74#include <netwm.h>
75
76#include <fixx11h.h>
77
78using namespace KCal;
79
80int KNote::s_ppOffset = 0;
81
82KNote::KNote( TQDomDocument buildDoc, Journal *j, TQWidget *parent, const char *name )
83 : TQFrame( parent, name, WStyle_Customize | WStyle_NoBorder | WDestructiveClose ),
84 m_label( 0 ), m_pushpin( 0 ), m_fold( 0 ), m_button( 0 ), m_tool( 0 ), m_editor( 0 ),
85 m_config( 0 ), m_journal( j ), m_find( 0 ),
86 m_twinConf( TDESharedConfig::openConfig( "twinrc", true ) ),
87 m_busy( 0 ), m_deleteWhenIdle( false ), m_blockEmitDataChanged( false )
88{
89 setAcceptDrops( true );
90 actionCollection()->setWidget( this );
91
92 setDOMDocument( buildDoc );
93
94 // just set the name of the file to save the actions to, do NOT reparse it
95 setXMLFile( instance()->instanceName() + "ui.rc", false, false );
96
97 // if there is no title yet, use the start date if valid
98 // (KOrganizer's journals don't have titles but a valid start date)
99 if ( m_journal->summary().isNull() && m_journal->dtStart().isValid() )
100 {
101 TQString s = TDEGlobal::locale()->formatDateTime( m_journal->dtStart() );
102 m_journal->setSummary( s );
103 }
104
105 // create the menu items for the note - not the editor...
106 // rename, mail, print, save as, insert date, alarm, close, delete, new note
107 new TDEAction( i18n("New"), "document-new", 0,
108 this,TQ_SLOT(slotRequestNewNote()) , actionCollection(), "new_note" );
109 new TDEAction( i18n("Rename..."), "text", 0,
110 this, TQ_SLOT(slotRename()), actionCollection(), "rename_note" );
111 m_readOnly = new TDEToggleAction( i18n("Lock"), "system-lock-screen" , 0,
112 this, TQ_SLOT(slotUpdateReadOnly()), actionCollection(), "lock_note" );
113 m_readOnly->setCheckedState( KGuiItem( i18n("Unlock"), "unlock" ) );
114 new TDEAction( i18n("Hide"), "window-close" , Key_Escape,
115 this, TQ_SLOT(slotClose()), actionCollection(), "hide_note" );
116 new TDEAction( i18n("Delete"), "knotes_delete", 0,
117 this, TQ_SLOT(slotKill()), actionCollection(), "delete_note" );
118
119 new TDEAction( i18n("Insert Date"), "knotes_date", 0 ,
120 this, TQ_SLOT(slotInsDate()), actionCollection(), "insert_date" );
121 new TDEAction( i18n("Set Alarm..."), "knotes_alarm", 0 ,
122 this, TQ_SLOT(slotSetAlarm()), actionCollection(), "set_alarm" );
123
124 new TDEAction( i18n("Send..."), "network", 0,
125 this, TQ_SLOT(slotSend()), actionCollection(), "send_note" );
126 new TDEAction( i18n("Mail..."), "mail-send", 0,
127 this, TQ_SLOT(slotMail()), actionCollection(), "mail_note" );
128 new TDEAction( i18n("Save As..."), "document-save-as", 0,
129 this, TQ_SLOT(slotSaveAs()), actionCollection(), "save_note" );
130 KStdAction::print( this, TQ_SLOT(slotPrint()), actionCollection(), "print_note" );
131 new TDEAction( i18n("Preferences..."), "configure", 0,
132 this, TQ_SLOT(slotPreferences()), actionCollection(), "configure_note" );
133
134 m_keepAbove = new TDEToggleAction( i18n("Keep Above Others"), "go-up", 0,
135 this, TQ_SLOT(slotUpdateKeepAboveBelow()), actionCollection(), "keep_above" );
136 m_keepAbove->setExclusiveGroup( "keepAB" );
137
138 m_keepBelow = new TDEToggleAction( i18n("Keep Below Others"), "go-down", 0,
139 this, TQ_SLOT(slotUpdateKeepAboveBelow()), actionCollection(), "keep_below" );
140 m_keepBelow->setExclusiveGroup( "keepAB" );
141
142 m_toDesktop = new TDEListAction( i18n("To Desktop"), 0,
143 this, TQ_SLOT(slotPopupActionToDesktop(int)), actionCollection(), "to_desktop" );
144 connect( m_toDesktop->popupMenu(), TQ_SIGNAL(aboutToShow()), this, TQ_SLOT(slotUpdateDesktopActions()) );
145
146 // invisible action to walk through the notes to make this configurable
147 new TDEAction( i18n("Walk Through Notes"), 0, SHIFT+Key_BackTab,
148 this, TQ_SIGNAL(sigShowNextNote()), actionCollection(), "walk_notes" );
149
150 // create the note header, button and label...
151 m_label = new TQLabel( this );
152 m_label->setFrameStyle( NoFrame );
153 m_label->setLineWidth( 0 );
154 m_label->installEventFilter( this ); // receive events (for dragging & action menu)
155 setName( m_journal->summary() ); // don't worry, no signals are connected at this stage yet
156
157 m_button = new KNoteButton( "knotes_close", this );
158 connect( m_button, TQ_SIGNAL(clicked()), this, TQ_SLOT(slotClose()) );
159
160 // create the note editor
161 m_editor = new KNoteEdit( actionCollection(), this );
162 m_editor->setNote( this );
163 m_editor->installEventFilter( this ); // receive events (for modified)
164 m_editor->viewport()->installEventFilter( this );
165 connect( m_editor, TQ_SIGNAL(contentsMoving( int, int )), this, TQ_SLOT(slotUpdateViewport( int, int )));
166
167 KXMLGUIBuilder builder( this );
168 KXMLGUIFactory factory( &builder, this );
169 factory.addClient( this );
170
171 m_menu = dynamic_cast<TDEPopupMenu*>(factory.container( "note_context", this ));
172 m_edit_menu = dynamic_cast<TDEPopupMenu*>(factory.container( "note_edit", this ));
173 m_tool = dynamic_cast<TDEToolBar*>(factory.container( "note_tool", this ));
174
175 if ( m_tool ) {
176 m_tool->setIconSize( 10 );
177 m_tool->setFixedHeight( 16 );
178 m_tool->setIconText( TDEToolBar::IconOnly );
179
180 // if there was just a way of making KComboBox adhere the toolbar height...
181 TQObjectList *list = m_tool->queryList( "KComboBox" );
182 TQObjectListIt it( *list );
183 while ( it.current() != 0 )
184 {
185 KComboBox *combo = (KComboBox *)it.current();
186 TQFont font = combo->font();
187 font.setPointSize( 7 );
188 combo->setFont( font );
189 combo->setFixedHeight( 14 );
190 ++it;
191 }
192 delete list;
193
194 m_tool->hide();
195 }
196
197 setFocusProxy( m_editor );
198
199 // create the resize handle
200 m_editor->setCornerWidget( new TQSizeGrip( this ) );
201 uint width = m_editor->cornerWidget()->width();
202 uint height = m_editor->cornerWidget()->height();
203 TQBitmap mask;
204 mask.resize( width, height );
205 mask.fill( color0 );
206 TQPointArray array;
207 array.setPoints( 3, 0, height, width, height, width, 0 );
208 TQPainter p;
209 p.begin( &mask );
210 p.setBrush( color1 );
211 p.drawPolygon( array );
212 p.end();
213 m_editor->cornerWidget()->setMask( mask );
214 m_editor->cornerWidget()->setBackgroundMode( PaletteBase );
215
216 // the config file location
217 TQString configFile = TDEGlobal::dirs()->saveLocation( "appdata", "notes/" );
218 configFile += m_journal->uid();
219
220 // no config file yet? -> use the default display config if available
221 // we want to write to configFile, so use "false"
222 bool newNote = !TDEIO::NetAccess::exists( KURL::fromPathOrURL( configFile ), false, 0 );
223
224 m_config = new KNoteConfig( TDESharedConfig::openConfig( configFile, false, false ) );
225 m_config->readConfig();
226 m_config->setVersion( KNOTES_VERSION );
227
228 if ( newNote )
229 {
230 // until tdelibs provides copying of TDEConfigSkeletons (KDE 3.4)
231 KNotesGlobalConfig *globalConfig = KNotesGlobalConfig::self();
232 m_config->setBgColor( globalConfig->bgColor() );
233 m_config->setFgColor( globalConfig->fgColor() );
234 m_config->setWidth( globalConfig->width() );
235 m_config->setHeight( globalConfig->height() );
236
237 m_config->setFont( globalConfig->font() );
238 m_config->setTitleFont( globalConfig->titleFont() );
239 m_config->setAutoIndent( globalConfig->autoIndent() );
240 m_config->setRichText( globalConfig->richText() );
241 m_config->setTabSize( globalConfig->tabSize() );
242 m_config->setReadOnly( globalConfig->readOnly() );
243
244 m_config->setDesktop( globalConfig->desktop() );
245 m_config->setHideNote( globalConfig->hideNote() );
246 m_config->setPosition( globalConfig->position() );
247 m_config->setShowInTaskbar( globalConfig->showInTaskbar() );
248 m_config->setKeepAbove( globalConfig->keepAbove() );
249 m_config->setKeepBelow( globalConfig->keepBelow() );
250
251 m_config->writeConfig();
252 }
253
254 // set up the look&feel of the note
255 setMinimumSize( 20, 20 );
256 setLineWidth( 1 );
257 setMargin( 0 );
258
259 m_editor->setMargin( 0 );
260 m_editor->setFrameStyle( NoFrame );
261 m_editor->setBackgroundOrigin( WindowOrigin );
262
263 // can be done here since this doesn't pick up changes while KNotes is running anyway
264 bool closeLeft = false;
265 m_twinConf->setGroup( "Style" );
266 if ( m_twinConf->readBoolEntry( "CustomButtonPositions" ) )
267 closeLeft = m_twinConf->readEntry( "ButtonsOnLeft" ).find( 'X' ) > -1;
268
269 TQPixmap pushpin_pix;
270 if ( closeLeft )
271 pushpin_pix = TQPixmap( TQPixmap( pushpin_xpm ).convertToImage().mirror( true, false ) );
272 else
273 pushpin_pix = TQPixmap( pushpin_xpm );
274
275 // the pushpin label at the top left or right corner
276 m_pushpin = new TQLabel( this );
277 m_pushpin->setScaledContents( true );
278 m_pushpin->setBackgroundMode( NoBackground );
279 m_pushpin->setPixmap( pushpin_pix );
280 m_pushpin->resize( pushpin_pix.size() );
281
282 // fold label at bottom right corner
283 m_fold = new TQLabel( this );
284 m_fold->setScaledContents( true );
285 m_fold->setBackgroundMode( NoBackground );
286
287 // load the display configuration of the note
288 width = m_config->width();
289 height = m_config->height();
290 resize( width, height );
291
292 // let KWin do the placement if the position is illegal--at least 10 pixels
293 // of a note need to be visible
294 const TQPoint& position = m_config->position();
295 TQRect desk = tdeApp->desktop()->rect();
296 desk.addCoords( 10, 10, -10, -10 );
297 if ( desk.intersects( TQRect( position, TQSize( width, height ) ) ) )
298 move( position ); // do before calling show() to avoid flicker
299
300 // config items in the journal have priority
301 TQString property = m_journal->customProperty( "KNotes", "FgColor" );
302 if ( !property.isNull() )
303 m_config->setFgColor( TQColor( property ) );
304 else
305 m_journal->setCustomProperty( "KNotes", "FgColor", m_config->fgColor().name() );
306
307 property = m_journal->customProperty( "KNotes", "BgColor" );
308 if ( !property.isNull() )
309 m_config->setBgColor( TQColor( property ) );
310 else
311 m_journal->setCustomProperty( "KNotes", "BgColor", m_config->bgColor().name() );
312
313 property = m_journal->customProperty( "KNotes", "RichText" );
314 if ( !property.isNull() )
315 m_config->setRichText( property == "true" ? true : false );
316 else
317 m_journal->setCustomProperty( "KNotes", "RichText", m_config->richText() ? "true" : "false" );
318
319 // read configuration settings...
320 slotApplyConfig();
321
322 // create the mask for the fold---to be done after slotApplyConfig(),
323 // which calls createFold()
324 m_fold->setMask( TQRegion( m_fold->pixmap()->createHeuristicMask() ) );
325
326 // if this is a new note put on current desktop - we can't use defaults
327 // in TDEConfig XT since only _changes_ will be stored in the config file
328 int desktop = m_config->desktop();
329 if ( desktop < 0 && desktop != NETWinInfo::OnAllDesktops )
330 desktop = KWin::currentDesktop();
331
332 // show the note if desired
333 if ( desktop != 0 && !m_config->hideNote() )
334 {
335 // to avoid flicker, call this before show()
336 toDesktop( desktop );
337 show();
338
339 // because KWin forgets about that for hidden windows
340 if ( desktop == NETWinInfo::OnAllDesktops )
341 toDesktop( desktop );
342 }
343
344 m_editor->setText( m_journal->description() );
345 m_editor->setModified( false );
346
347 m_readOnly->setChecked( m_config->readOnly() );
348 slotUpdateReadOnly();
349
350 if ( m_config->keepAbove() )
351 m_keepAbove->setChecked( true );
352 else if ( m_config->keepBelow() )
353 m_keepBelow->setChecked( true );
354 else
355 {
356 m_keepAbove->setChecked( false );
357 m_keepBelow->setChecked( false );
358 }
359 slotUpdateKeepAboveBelow();
360
361 // HACK: update the icon color - again after showing the note, to make kicker aware of the new colors
362 TDEIconEffect effect;
363 TQPixmap icon = effect.apply( tdeApp->icon(), TDEIconEffect::Colorize, 1, m_config->bgColor(), false );
364 TQPixmap miniIcon = effect.apply( tdeApp->miniIcon(), TDEIconEffect::Colorize, 1, m_config->bgColor(), false );
365 KWin::setIcons( winId(), icon, miniIcon );
366}
367
368KNote::~KNote()
369{
370 delete m_config;
371}
372
373void KNote::slotRequestNewNote()
374{
375 //Be sure to save before to request a new note
376 saveConfig();
377 saveData();
378 emit sigRequestNewNote();
379}
380
381void KNote::changeJournal(KCal::Journal *journal)
382{
383 m_journal = journal;
384 m_editor->setText( m_journal->description() );
385 m_label->setText( m_journal->summary() );
386 updateLabelAlignment();
387}
388
389// -------------------- public slots -------------------- //
390
391void KNote::slotKill( bool force )
392{
393 m_blockEmitDataChanged = true;
394 if ( !force &&
395 KMessageBox::warningContinueCancel( this,
396 i18n("<qt>Do you really want to delete note <b>%1</b>?</qt>").arg( m_label->text() ),
397 i18n("Confirm Delete"), KGuiItem( i18n("&Delete"), "edit-delete" ),
398 "ConfirmDeleteNote"
399 )
400 != KMessageBox::Continue )
401 {
402 m_blockEmitDataChanged = false;
403 return;
404 }
405 aboutToEnterEventLoop();
406 // delete the configuration first, then the corresponding file
407 delete m_config;
408 m_config = 0;
409
410 TQString configFile = TDEGlobal::dirs()->saveLocation( "appdata", "notes/" );
411 configFile += m_journal->uid();
412
413 if ( !TDEIO::NetAccess::del( KURL::fromPathOrURL( configFile ), this ) )
414 kdError(5500) << "Can't remove the note config: " << configFile << endl;
415
416 emit sigKillNote( m_journal );
417 eventLoopLeft();
418
419}
420
421
422// -------------------- public member functions -------------------- //
423
424void KNote::saveData(bool update)
425{
426 m_journal->setSummary( m_label->text() );
427 m_journal->setDescription( m_editor->text() );
428 m_journal->setCustomProperty( "KNotes", "FgColor", m_config->fgColor().name() );
429 m_journal->setCustomProperty( "KNotes", "BgColor", m_config->bgColor().name() );
430 m_journal->setCustomProperty( "KNotes", "RichText", m_config->richText() ? "true" : "false" );
431 if(update) {
432 emit sigDataChanged( noteId() );
433 m_editor->setModified( false );
434 }
435}
436
437void KNote::saveConfig() const
438{
439 m_config->setWidth( width() );
440 m_config->setHeight( height() );
441 m_config->setPosition( pos() );
442
443 NETWinInfo wm_client( tqt_xdisplay(), winId(), tqt_xrootwin(), NET::WMDesktop );
444 if ( wm_client.desktop() == NETWinInfo::OnAllDesktops || wm_client.desktop() > 0 )
445 m_config->setDesktop( wm_client.desktop() );
446
447 // actually store the config on disk
448 m_config->writeConfig();
449}
450
451TQString KNote::noteId() const
452{
453 return m_journal->uid();
454}
455
456TQDateTime KNote::getLastModified() const
457{
458 return m_journal->lastModified();
459}
460
461TQString KNote::name() const
462{
463 return m_label->text();
464}
465
466TQString KNote::text() const
467{
468 return m_editor->text();
469}
470
471TQString KNote::plainText() const
472{
473 if ( m_editor->textFormat() == RichText )
474 {
475 TQTextEdit conv;
476 conv.setTextFormat( RichText );
477 conv.setText( m_editor->text() );
478 conv.setTextFormat( PlainText );
479 return conv.text();
480 }
481 else
482 return m_editor->text();
483}
484
485void KNote::setName( const TQString& name )
486{
487 m_label->setText( name );
488 updateLabelAlignment();
489
490 if ( m_editor ) // not called from CTOR?
491 saveData();
492
493 // set the window's name for the taskbar entry to be more helpful (#58338)
494 NETWinInfo note_win( tqt_xdisplay(), winId(), tqt_xrootwin(), NET::WMDesktop );
495 note_win.setName( name.utf8() );
496
497 emit sigNameChanged();
498}
499
500void KNote::setText( const TQString& text )
501{
502 m_editor->setText( text );
503 saveData();
504}
505
506TQColor KNote::fgColor() const
507{
508 return m_config->fgColor();
509}
510
511TQColor KNote::bgColor() const
512{
513 return m_config->bgColor();
514}
515
516void KNote::setColor( const TQColor& fg, const TQColor& bg )
517{
518 bool updateJournal = false;
519 TQString journalFg = m_journal->customProperty( "KNotes", "FgColor" );
520 if ( journalFg.isEmpty() || journalFg != fg.name() )
521 {
522 m_journal->setCustomProperty( "KNotes", "FgColor", fg.name() );
523 updateJournal = true;
524 }
525 TQString journalbg = m_journal->customProperty( "KNotes", "BgColor" );
526 if ( journalbg.isEmpty() || journalbg != bg.name() )
527 {
528 m_journal->setCustomProperty( "KNotes", "BgColor", bg.name() );
529 updateJournal = true;
530 }
531
532 m_config->setFgColor( fg );
533 m_config->setBgColor( bg );
534
535 if (updateJournal)
536 {
537 // Only update the journal if new configuration was really used.
538 // This is necessary because setColor() is called also when loading a note from an .ics
539 // file and we do not want to inadvertantly update the last modified field each time.
540 m_journal->updated(); // because setCustomProperty() doesn't call it!!
541 emit sigDataChanged(noteId());
542 }
543 m_config->writeConfig();
544
545 TQPalette newpalette = palette();
546 newpalette.setColor( TQColorGroup::Background, bg );
547 newpalette.setColor( TQColorGroup::Foreground, fg );
548 newpalette.setColor( TQColorGroup::Base, bg ); // text background
549 newpalette.setColor( TQColorGroup::Text, fg ); // text color
550 newpalette.setColor( TQColorGroup::Button, bg );
551 newpalette.setColor( TQColorGroup::ButtonText, fg );
552
553// newpalette.setColor( TQColorGroup::Highlight, bg );
554// newpalette.setColor( TQColorGroup::HighlightedText, fg );
555
556 // the shadow
557 newpalette.setColor( TQColorGroup::Midlight, bg.light(150) );
558 newpalette.setColor( TQColorGroup::Shadow, bg.dark(116) );
559 newpalette.setColor( TQColorGroup::Light, bg.light(180) );
560 if ( s_ppOffset )
561 newpalette.setColor( TQColorGroup::Dark, bg.dark(200) );
562 else
563 newpalette.setColor( TQColorGroup::Dark, bg.dark(108) );
564 setPalette( newpalette );
565
566 // set the text color
567 m_editor->setTextColor( fg );
568
569 // set the background color or gradient
570 updateBackground();
571
572 // set darker value for the hide button...
573 TQPalette darker = palette();
574 darker.setColor( TQColorGroup::Button, bg.dark(116) );
575 m_button->setPalette( darker );
576
577 // update the icon color
578 TDEIconEffect effect;
579 TQPixmap icon = effect.apply( tdeApp->icon(), TDEIconEffect::Colorize, 1, bg, false );
580 TQPixmap miniIcon = effect.apply( tdeApp->miniIcon(), TDEIconEffect::Colorize, 1, bg, false );
581 KWin::setIcons( winId(), icon, miniIcon );
582
583 // set the color for the selection used to highlight the find stuff
584 TQColor sel = palette().color( TQPalette::Active, TQColorGroup::Base ).dark();
585 if ( sel == TQt::black )
586 sel = palette().color( TQPalette::Active, TQColorGroup::Base ).light();
587
588 m_editor->setSelectionAttributes( 1, sel, true );
589
590 // update the color of the fold
591 createFold();
592
593 // update the color of the title
594 updateFocus();
595 emit sigColorChanged();
596}
597
598void KNote::find( const TQString& pattern, long options )
599{
600 delete m_find;
601 m_find = new KFind( pattern, options, this );
602
603 connect( m_find, TQ_SIGNAL(highlight( const TQString &, int, int )),
604 this, TQ_SLOT(slotHighlight( const TQString &, int, int )) );
605 connect( m_find, TQ_SIGNAL(findNext()), this, TQ_SLOT(slotFindNext()) );
606
607 m_find->setData( plainText() );
608 slotFindNext();
609}
610
611void KNote::slotFindNext()
612{
613 // TODO: honor FindBackwards
614 // TODO: dialogClosed() -> delete m_find
615
616 // Let KFind inspect the text fragment, and display a dialog if a match is found
617 KFind::Result res = m_find->find();
618
619 if ( res == KFind::NoMatch ) // i.e. at end-pos
620 {
621 m_editor->removeSelection( 1 );
622 emit sigFindFinished();
623 delete m_find;
624 m_find = 0;
625 }
626 else
627 {
628 show();
629 KWin::setCurrentDesktop( KWin::windowInfo( winId() ).desktop() );
630 }
631}
632
633void KNote::slotHighlight( const TQString& str, int idx, int len )
634{
635 int paraFrom = 0, idxFrom = 0, p = 0;
636 for ( ; p < idx; ++p )
637 if ( str[p] == '\n' )
638 {
639 ++paraFrom;
640 idxFrom = 0;
641 }
642 else
643 ++idxFrom;
644
645 int paraTo = paraFrom, idxTo = idxFrom;
646
647 for ( ; p < idx + len; ++p )
648 {
649 if ( str[p] == '\n' )
650 {
651 ++paraTo;
652 idxTo = 0;
653 }
654 else
655 ++idxTo;
656 }
657
658 m_editor->setSelection( paraFrom, idxFrom, paraTo, idxTo, 1 );
659}
660
661bool KNote::isModified() const
662{
663 return m_editor->isModified();
664}
665
666// FIXME KDE 4.0: remove sync(), isNew() and isModified()
667void KNote::sync( const TQString& app )
668{
669 TQByteArray sep( 1 );
670 sep[0] = '\0';
671
672 KMD5 hash;
673 TQCString result;
674
675 hash.update( m_label->text().utf8() );
676 hash.update( sep );
677 hash.update( m_editor->text().utf8() );
678 hash.hexDigest( result );
679
680 // hacky... not possible with TDEConfig XT
681 TDEConfig *config = m_config->config();
682 config->setGroup( "Synchronisation" );
683 config->writeEntry( app, result.data() );
684}
685
686bool KNote::isNew( const TQString& app ) const
687{
688 TDEConfig *config = m_config->config();
689 config->setGroup( "Synchronisation" );
690 TQString hash = config->readEntry( app );
691 return hash.isEmpty();
692}
693
694bool KNote::isModified( const TQString& app ) const
695{
696 TQByteArray sep( 1 );
697 sep[0] = '\0';
698
699 KMD5 hash;
700 hash.update( m_label->text().utf8() );
701 hash.update( sep );
702 hash.update( m_editor->text().utf8() );
703 hash.hexDigest();
704
705 TDEConfig *config = m_config->config();
706 config->setGroup( "Synchronisation" );
707 TQString orig = config->readEntry( app );
708
709 if ( hash.verify( orig.utf8() ) ) // returns false on error!
710 return false;
711 else
712 return true;
713}
714
715void KNote::setStyle( int style )
716{
717 if ( style == KNotesGlobalConfig::EnumStyle::Plain )
718 s_ppOffset = 0;
719 else
720 s_ppOffset = 12;
721}
722
723
724// ------------------ private slots (menu actions) ------------------ //
725
726void KNote::slotRename()
727{
728 m_blockEmitDataChanged = true;
729 // pop up dialog to get the new name
730 bool ok;
731 aboutToEnterEventLoop();
732 TQString oldName = m_label->text();
733 TQString newName = KInputDialog::getText( TQString(),
734 i18n("Please enter the new name:"), m_label->text(), &ok, this );
735 eventLoopLeft();
736 m_blockEmitDataChanged = false;
737 if ( !ok || ( oldName == newName) ) // handle cancel
738 return;
739
740 setName( newName );
741}
742
743void KNote::slotUpdateReadOnly()
744{
745 const bool readOnly = m_readOnly->isChecked();
746
747 m_editor->setReadOnly( readOnly );
748 m_config->setReadOnly( readOnly );
749
750 // Enable/disable actions accordingly
751 actionCollection()->action( "configure_note" )->setEnabled( !readOnly );
752 actionCollection()->action( "insert_date" )->setEnabled( !readOnly );
753 actionCollection()->action( "delete_note" )->setEnabled( !readOnly );
754
755 actionCollection()->action( "edit_undo" )->setEnabled( !readOnly && m_editor->isUndoAvailable() );
756 actionCollection()->action( "edit_redo" )->setEnabled( !readOnly && m_editor->isRedoAvailable() );
757 actionCollection()->action( "edit_cut" )->setEnabled( !readOnly && m_editor->hasSelectedText() );
758 actionCollection()->action( "edit_paste" )->setEnabled( !readOnly );
759 actionCollection()->action( "edit_clear" )->setEnabled( !readOnly );
760 actionCollection()->action( "rename_note" )->setEnabled( !readOnly );
761
762 actionCollection()->action( "format_bold" )->setEnabled( !readOnly );
763 actionCollection()->action( "format_italic" )->setEnabled( !readOnly );
764 actionCollection()->action( "format_underline" )->setEnabled( !readOnly );
765 actionCollection()->action( "format_strikeout" )->setEnabled( !readOnly );
766 actionCollection()->action( "format_alignleft" )->setEnabled( !readOnly );
767 actionCollection()->action( "format_aligncenter" )->setEnabled( !readOnly );
768 actionCollection()->action( "format_alignright" )->setEnabled( !readOnly );
769 actionCollection()->action( "format_alignblock" )->setEnabled( !readOnly );
770 actionCollection()->action( "format_list" )->setEnabled( !readOnly );
771 actionCollection()->action( "format_super" )->setEnabled( !readOnly );
772 actionCollection()->action( "format_sub" )->setEnabled( !readOnly );
773 actionCollection()->action( "format_size" )->setEnabled( !readOnly );
774 actionCollection()->action( "format_color" )->setEnabled( !readOnly );
775
776 updateFocus();
777}
778
779void KNote::slotClose()
780{
781 NETWinInfo wm_client( tqt_xdisplay(), winId(), tqt_xrootwin(), NET::WMDesktop );
782 if ( wm_client.desktop() == NETWinInfo::OnAllDesktops || wm_client.desktop() > 0 )
783 m_config->setDesktop( wm_client.desktop() );
784
785 m_editor->clearFocus();
786 m_config->setHideNote( true );
787 m_config->setPosition( pos() );
788
789 // just hide the note so it's still available from the dock window
790 hide();
791}
792
793void KNote::slotInsDate()
794{
795 m_editor->insert( TDEGlobal::locale()->formatDateTime(TQDateTime::currentDateTime()) );
796}
797
798void KNote::slotSetAlarm()
799{
800 m_blockEmitDataChanged = true;
801 KNoteAlarmDlg dlg( name(), this );
802 dlg.setIncidence( m_journal );
803
804 aboutToEnterEventLoop();
805 if ( dlg.exec() == TQDialog::Accepted )
806 emit sigDataChanged(noteId());
807 eventLoopLeft();
808 m_blockEmitDataChanged = false;
809}
810
811void KNote::slotPreferences()
812{
813 // reuse if possible
814 if ( KNoteConfigDlg::showDialog( noteId().utf8() ) )
815 return;
816
817 // create a new preferences dialog...
818 KNoteConfigDlg *dialog = new KNoteConfigDlg( m_config, name(), this, noteId().utf8() );
819 connect( dialog, TQ_SIGNAL(settingsChanged()), this, TQ_SLOT(slotApplyConfig()) );
820 connect( this, TQ_SIGNAL(sigNameChanged()), dialog, TQ_SLOT(slotUpdateCaption()) );
821 dialog->show();
822}
823
824void KNote::slotSend()
825{
826 // pop up dialog to get the IP
827 KNoteHostDlg hostDlg( i18n("Send \"%1\"").arg( name() ), this );
828 aboutToEnterEventLoop();
829 bool ok = (hostDlg.exec() == TQDialog::Accepted);
830 eventLoopLeft();
831 if ( !ok ) // handle cancel
832 return;
833 TQString host = hostDlg.host();
834
835 if ( host.isEmpty() )
836 {
837 KMessageBox::sorry( this, i18n("The host cannot be empty.") );
838 return;
839 }
840
841 // Send the note
842 KNotesNetworkSender *sender = new KNotesNetworkSender( host, KNotesGlobalConfig::port() );
843 sender->setSenderId( KNotesGlobalConfig::senderID() );
844 sender->setNote( name(), text() );
845 sender->connect();
846}
847
848void KNote::slotMail()
849{
850 // get the mail action command
851 const TQStringList cmd_list = TQStringList::split( TQChar(' '), KNotesGlobalConfig::mailAction() );
852
853 TDEProcess mail;
854 for ( TQStringList::ConstIterator it = cmd_list.constBegin();
855 it != cmd_list.constEnd(); ++it )
856 {
857 if ( *it == "%f" )
858 mail << plainText().local8Bit(); // convert rich text to plain text
859 else if ( *it == "%t" )
860 mail << m_label->text().local8Bit();
861 else
862 mail << (*it).local8Bit();
863 }
864
865 if ( !mail.start( TDEProcess::DontCare ) )
866 KMessageBox::sorry( this, i18n("Unable to start the mail process.") );
867}
868
869void KNote::slotPrint()
870{
871 TQString content;
872 if ( m_editor->textFormat() == PlainText )
873 content = TQStyleSheet::convertFromPlainText( m_editor->text() );
874 else
875 content = m_editor->text();
876
877 KNotePrinter printer;
878 printer.setMimeSourceFactory( m_editor->mimeSourceFactory() );
879 printer.setFont( m_config->font() );
880 printer.setContext( m_editor->context() );
881 printer.setStyleSheet( m_editor->styleSheet() );
882 printer.setColorGroup( colorGroup() );
883 printer.printNote( TQString(), content );
884}
885
886void KNote::slotSaveAs()
887{
888 m_blockEmitDataChanged = true;
889 TQCheckBox *convert = 0;
890
891 if ( m_editor->textFormat() == RichText )
892 {
893 convert = new TQCheckBox( 0 );
894 convert->setText( i18n("Save note as plain text") );
895 }
896
897 KFileDialog dlg( TQString(), TQString(), this, "filedialog", true, convert );
898 dlg.setOperationMode( KFileDialog::Saving );
899 dlg.setCaption( i18n("Save As") );
900 aboutToEnterEventLoop();
901 dlg.exec();
902 eventLoopLeft();
903
904 TQString fileName = dlg.selectedFile();
905 if ( fileName.isEmpty() )
906 {
907 m_blockEmitDataChanged = false;
908 return;
909 }
910 TQFile file( fileName );
911
912 if ( file.exists() &&
913 KMessageBox::warningContinueCancel( this, i18n("<qt>A file named <b>%1</b> already exists.<br>"
914 "Are you sure you want to overwrite it?</qt>").arg( TQFileInfo(file).fileName() ) )
915 != KMessageBox::Continue )
916 {
917 m_blockEmitDataChanged = false;
918 return;
919 }
920
921 if ( file.open( IO_WriteOnly ) )
922 {
923 TQTextStream stream( &file );
924 // convert rich text to plain text first
925 if ( convert && convert->isChecked() )
926 stream << plainText();
927 else
928 stream << text();
929 }
930 m_blockEmitDataChanged = false;
931}
932
933void KNote::slotPopupActionToDesktop( int id )
934{
935 toDesktop( id - 1 ); // compensate for the menu separator, -1 == all desktops
936}
937
938
939// ------------------ private slots (configuration) ------------------ //
940
941void KNote::slotApplyConfig()
942{
943 if ( m_config->richText() )
944 m_editor->setTextFormat( RichText );
945 else
946 m_editor->setTextFormat( PlainText );
947
948 m_label->setFont( m_config->titleFont() );
949 m_editor->setTextFont( m_config->font() );
950 m_editor->setTabStop( m_config->tabSize() );
951 m_editor->setAutoIndentMode( m_config->autoIndent() );
952
953 // if called as a slot, save the text, we might have changed the
954 // text format - otherwise the journal will not be updated
955 if ( sender() )
956 saveData();
957
958 setColor( m_config->fgColor(), m_config->bgColor() );
959
960 updateLabelAlignment();
961 slotUpdateShowInTaskbar();
962}
963
964void KNote::slotUpdateKeepAboveBelow()
965{
966 KWin::WindowInfo info( KWin::windowInfo( winId() ) );
967
968 if ( m_keepAbove->isChecked() )
969 {
970 m_config->setKeepAbove( true );
971 m_config->setKeepBelow( false );
972 KWin::setState( winId(), info.state() | NET::KeepAbove );
973 }
974 else if ( m_keepBelow->isChecked() )
975 {
976 m_config->setKeepAbove( false );
977 m_config->setKeepBelow( true );
978 KWin::setState( winId(), info.state() | NET::KeepBelow );
979 }
980 else
981 {
982 m_config->setKeepAbove( false );
983 KWin::clearState( winId(), NET::KeepAbove );
984
985 m_config->setKeepBelow( false );
986 KWin::clearState( winId(), NET::KeepBelow );
987 }
988}
989
990void KNote::slotUpdateShowInTaskbar()
991{
992 if ( !m_config->showInTaskbar() )
993 KWin::setState( winId(), KWin::windowInfo(winId()).state() | NET::SkipTaskbar );
994 else
995 KWin::clearState( winId(), NET::SkipTaskbar );
996}
997
998void KNote::slotUpdateDesktopActions()
999{
1000 NETRootInfo wm_root( tqt_xdisplay(), NET::NumberOfDesktops | NET::DesktopNames );
1001 NETWinInfo wm_client( tqt_xdisplay(), winId(), tqt_xrootwin(), NET::WMDesktop );
1002
1003 TQStringList desktops;
1004 desktops.append( i18n("&All Desktops") );
1005 desktops.append( TQString() ); // Separator
1006
1007 int count = wm_root.numberOfDesktops();
1008 for ( int n = 1; n <= count; n++ )
1009 desktops.append( TQString("&%1 %2").arg( n ).arg( TQString::fromUtf8(wm_root.desktopName( n )) ) );
1010
1011 m_toDesktop->setItems( desktops );
1012
1013 if ( wm_client.desktop() == NETWinInfo::OnAllDesktops )
1014 m_toDesktop->setCurrentItem( 0 );
1015 else
1016 m_toDesktop->setCurrentItem( wm_client.desktop() + 1 ); // compensate for separator (+1)
1017}
1018
1019void KNote::slotUpdateViewport( int /*x*/, int y )
1020{
1021 if ( s_ppOffset )
1022 updateBackground( y );
1023}
1024
1025// -------------------- private methods -------------------- //
1026
1027void KNote::toDesktop( int desktop )
1028{
1029 if ( desktop == 0 )
1030 return;
1031
1032 if ( desktop == NETWinInfo::OnAllDesktops )
1033 KWin::setOnAllDesktops( winId(), true );
1034 else
1035 KWin::setOnDesktop( winId(), desktop );
1036}
1037
1038void KNote::createFold()
1039{
1040 TQPixmap fold( 15, 15 );
1041 TQPainter foldp( &fold );
1042 foldp.setPen( TQt::NoPen );
1043 foldp.setBrush( palette().active().dark() );
1044 TQPointArray foldpoints( 3 );
1045 foldpoints.putPoints( 0, 3, 0, 0, 14, 0, 0, 14 );
1046 foldp.drawPolygon( foldpoints );
1047 foldp.end();
1048 m_fold->setPixmap( fold );
1049}
1050
1051void KNote::updateLabelAlignment()
1052{
1053 // if the name is too long to fit, left-align it, otherwise center it (#59028)
1054 TQString labelText = m_label->text();
1055 if ( m_label->fontMetrics().boundingRect( labelText ).width() > m_label->width() )
1056 m_label->setAlignment( AlignLeft );
1057 else
1058 m_label->setAlignment( AlignHCenter );
1059}
1060
1061void KNote::updateFocus()
1062{
1063 if ( hasFocus() )
1064 {
1065 m_label->setBackgroundColor( palette().active().shadow() );
1066 m_button->show();
1067
1068 if ( !m_editor->isReadOnly() )
1069 {
1070 if ( m_tool && m_tool->isHidden() && m_editor->textFormat() == TQTextEdit::RichText )
1071 {
1072 m_tool->show();
1073 updateLayout(); // to update the editor height
1074 }
1075 m_editor->cornerWidget()->show();
1076 }
1077 else
1078 {
1079 if ( m_tool && !m_tool->isHidden() )
1080 {
1081 m_tool->hide();
1082 updateLayout(); // to update the minimum height
1083 }
1084 m_editor->cornerWidget()->hide();
1085 }
1086
1087 m_fold->hide();
1088 }
1089 else
1090 {
1091 m_button->hide();
1092 m_editor->cornerWidget()->hide();
1093
1094 if ( m_tool && !m_tool->isHidden() )
1095 {
1096 m_tool->hide();
1097 updateLayout(); // to update the minimum height
1098 }
1099
1100 if ( s_ppOffset )
1101 {
1102 m_label->setBackgroundColor( palette().active().midlight() );
1103 m_fold->show();
1104 }
1105 else
1106 m_label->setBackgroundColor( palette().active().background() );
1107 }
1108}
1109
1110void KNote::updateMask()
1111{
1112 if ( !s_ppOffset )
1113 {
1114 clearMask();
1115 return;
1116 }
1117
1118 int w = width();
1119 int h = height();
1120 TQRegion reg( 0, s_ppOffset, w, h - s_ppOffset );
1121
1122 const TQBitmap *pushpin_bitmap = m_pushpin->pixmap()->mask();
1123 TQRegion pushpin_reg( *pushpin_bitmap );
1124 m_pushpin->setMask( pushpin_reg );
1125 pushpin_reg.translate( m_pushpin->x(), m_pushpin->y() );
1126
1127 if ( !hasFocus() )
1128 {
1129 TQPointArray foldpoints( 3 );
1130 foldpoints.putPoints( 0, 3, w-15, h, w, h-15, w, h );
1131 TQRegion fold( foldpoints, false );
1132 setMask( reg.unite( pushpin_reg ).subtract( fold ) );
1133 }
1134 else
1135 setMask( reg.unite( pushpin_reg ) );
1136}
1137
1138void KNote::updateBackground( int y_offset )
1139{
1140 if ( !s_ppOffset )
1141 {
1142 m_editor->setPaper( TQBrush( colorGroup().background() ) );
1143 return;
1144 }
1145
1146 int w = m_editor->visibleWidth();
1147 int h = m_editor->visibleHeight();
1148
1149 // in case y_offset is not set, calculate y_offset as the content
1150 // y-coordinate of the top-left point of the viewport - which is essentially
1151 // the vertical scroll amount
1152 if ( y_offset == -1 )
1153 y_offset = m_editor->contentsY();
1154
1155 y_offset = y_offset % h;
1156
1157 TQImage grad_img( w, h, 32 );
1158 TQRgb rgbcol;
1159 TQColor bg = palette().active().background();
1160
1161 for ( int i = 0; i < h; ++i )
1162 {
1163 // if the scrollbar has moved, then adjust the gradient by the amount the
1164 // scrollbar moved -- so that the background gradient looks ok when tiled
1165
1166 // the lightness is calculated as follows:
1167 // if i >= y, then lightness = 150 - (i-y)*75/h;
1168 // if i < y, then lightness = 150 - (i+h-y)*75/h
1169
1170 int i_1 = 150 - 75 * ((i - y_offset + h) % h) / h;
1171 rgbcol = bg.light( i_1 ).rgb();
1172 for ( int j = 0; j < w; ++j )
1173 grad_img.setPixel( j, i, rgbcol );
1174 }
1175
1176 // setPaletteBackgroundPixmap makes TQTextEdit::color() stop working!!
1177 m_editor->setPaper( TQBrush( TQt::black, TQPixmap( grad_img ) ) );
1178}
1179
1180void KNote::updateLayout()
1181{
1182 const int headerHeight = m_label->sizeHint().height();
1183 const int margin = m_editor->margin();
1184 bool closeLeft = false;
1185
1186 m_twinConf->setGroup( "Style" );
1187 if ( m_twinConf->readBoolEntry( "CustomButtonPositions" ) )
1188 closeLeft = m_twinConf->readEntry( "ButtonsOnLeft" ).find( 'X' ) > -1;
1189
1190 if ( s_ppOffset )
1191 {
1192 if ( !m_editor->paper().pixmap() ) // just changed the style
1193 setColor( palette().active().foreground(), palette().active().background() );
1194
1195 m_pushpin->show();
1196 setFrameStyle( Panel | Raised );
1197
1198 if ( closeLeft )
1199 m_pushpin->move( width() - m_pushpin->width(), 0 );
1200 else
1201 m_pushpin->move( 0, 0 );
1202 }
1203 else
1204 {
1205 if ( m_editor->paper().pixmap() ) // just changed the style
1206 setColor( palette().active().foreground(), palette().active().background() );
1207
1208 setFrameStyle( WinPanel | Raised );
1209 m_pushpin->hide();
1210 m_fold->hide();
1211 }
1212
1213 m_button->setGeometry(
1214 closeLeft ? contentsRect().x() : contentsRect().width() - headerHeight,
1215 contentsRect().y() + s_ppOffset,
1216 headerHeight,
1217 headerHeight
1218 );
1219
1220 m_label->setGeometry(
1221 contentsRect().x(), contentsRect().y() + s_ppOffset,
1222 contentsRect().width(), headerHeight
1223 );
1224
1225 m_editor->setGeometry( TQRect(
1226 TQPoint( contentsRect().x(),
1227 contentsRect().y() + headerHeight + s_ppOffset ),
1228 TQPoint( contentsRect().right(),
1229 contentsRect().bottom() - ( m_tool ? (m_tool->isHidden() ? 0 : m_tool->height()) : 0 ) )
1230 ) );
1231
1232 if( m_tool ) {
1233 m_tool->setGeometry(
1234 contentsRect().x(),
1235 contentsRect().bottom() - m_tool->height() + 1,
1236 contentsRect().width(),
1237 m_tool->height()
1238 );
1239 }
1240
1241 if ( s_ppOffset )
1242 m_fold->move( width() - 15, height() - 15 );
1243
1244 setMinimumSize(
1245 m_editor->cornerWidget()->width() + margin*2,
1246 headerHeight + s_ppOffset + ( m_tool ? m_tool->height() : 0 ) +
1247 m_editor->cornerWidget()->height() + margin*2
1248 );
1249
1250 updateLabelAlignment();
1251 updateMask();
1252 updateBackground();
1253}
1254
1255// -------------------- protected methods -------------------- //
1256
1257void KNote::drawFrame( TQPainter *p )
1258{
1259 TQRect r = frameRect();
1260 r.setTop( s_ppOffset );
1261 if ( s_ppOffset )
1262 qDrawShadePanel( p, r, colorGroup(), false, lineWidth() );
1263 else
1264 qDrawWinPanel( p, r, colorGroup(), false );
1265}
1266
1267void KNote::showEvent( TQShowEvent * )
1268{
1269 if ( m_config->hideNote() )
1270 {
1271 // KWin does not preserve these properties for hidden windows
1272 slotUpdateKeepAboveBelow();
1273 slotUpdateShowInTaskbar();
1274 toDesktop( m_config->desktop() );
1275 move( m_config->position() );
1276 m_config->setHideNote( false );
1277 }
1278}
1279
1280void KNote::resizeEvent( TQResizeEvent *qre )
1281{
1282 TQFrame::resizeEvent( qre );
1283 updateLayout();
1284}
1285
1286void KNote::closeEvent( TQCloseEvent *event )
1287{
1288 if(tdeApp->sessionSaving())
1289 return;
1290 event->ignore(); //We don't want to close (and delete the widget). Just hide it
1291 slotClose();
1292}
1293
1294void KNote::dragEnterEvent( TQDragEnterEvent *e )
1295{
1296 if ( !m_config->readOnly() )
1297 e->accept( KColorDrag::canDecode( e ) );
1298}
1299
1300void KNote::dropEvent( TQDropEvent *e )
1301{
1302 if ( m_config->readOnly() )
1303 return;
1304
1305 TQColor bg;
1306 if ( KColorDrag::decode( e, bg ) )
1307 setColor( paletteForegroundColor(), bg );
1308}
1309
1310bool KNote::focusNextPrevChild( bool )
1311{
1312 return true;
1313}
1314
1315bool KNote::event( TQEvent *ev )
1316{
1317 if ( ev->type() == TQEvent::LayoutHint )
1318 {
1319 updateLayout();
1320 return true;
1321 }
1322 else
1323 return TQFrame::event( ev );
1324}
1325
1326bool KNote::eventFilter( TQObject *o, TQEvent *ev )
1327{
1328 if ( ev->type() == TQEvent::DragEnter &&
1329 KColorDrag::canDecode( static_cast<TQDragEnterEvent *>(ev) ) )
1330 {
1331 dragEnterEvent( static_cast<TQDragEnterEvent *>(ev) );
1332 return true;
1333 }
1334
1335 if ( ev->type() == TQEvent::Drop &&
1336 KColorDrag::canDecode( static_cast<TQDropEvent *>(ev) ) )
1337 {
1338 dropEvent( static_cast<TQDropEvent *>(ev) );
1339 return true;
1340 }
1341
1342 if ( o == m_label )
1343 {
1344 TQMouseEvent *e = (TQMouseEvent *)ev;
1345
1346 if ( ev->type() == TQEvent::MouseButtonDblClick )
1347 {
1348 if( !m_editor->isReadOnly())
1349 slotRename();
1350 }
1351 if ( ev->type() == TQEvent::MouseButtonPress &&
1352 (e->button() == TQt::LeftButton || e->button() == TQt::MidButton))
1353 {
1354 e->button() == TQt::LeftButton ? KWin::raiseWindow( winId() )
1355 : KWin::lowerWindow( winId() );
1356
1357 XUngrabPointer( tqt_xdisplay(), get_tqt_x_time() );
1358 NETRootInfo wm_root( tqt_xdisplay(), NET::WMMoveResize );
1359 wm_root.moveResizeRequest( winId(), e->globalX(), e->globalY(), NET::Move );
1360 return true;
1361 }
1362
1363#if KDE_IS_VERSION( 3, 5, 1 )
1364 if ( ev->type() == TQEvent::MouseButtonRelease )
1365 {
1366 NETRootInfo wm_root( tqt_xdisplay(), NET::WMMoveResize );
1367 wm_root.moveResizeRequest( winId(), e->globalX(), e->globalY(), NET::MoveResizeCancel );
1368 return false;
1369 }
1370#endif
1371
1372 if ( m_menu && ( ev->type() == TQEvent::MouseButtonPress )
1373 && ( e->button() == TQt::RightButton ) )
1374 {
1375 m_menu->popup( TQCursor::pos() );
1376 return true;
1377 }
1378
1379 return false;
1380 }
1381
1382 if ( o == m_editor ) {
1383 if ( ev->type() == TQEvent::FocusOut ) {
1384 TQFocusEvent *fe = static_cast<TQFocusEvent*>(ev);
1385 if ( fe->reason() != TQFocusEvent::Popup &&
1386 fe->reason() != TQFocusEvent::Mouse ) {
1387 updateFocus();
1388 if ( isModified() ) {
1389 saveConfig();
1390 if ( !m_blockEmitDataChanged )
1391 saveData();
1392 }
1393 }
1394 } else if ( ev->type() == TQEvent::FocusIn ) {
1395 updateFocus();
1396 }
1397
1398 return false;
1399 }
1400
1401 if ( o == m_editor->viewport() )
1402 {
1403 if ( m_edit_menu &&
1404 ev->type() == TQEvent::MouseButtonPress &&
1405 ((TQMouseEvent *)ev)->button() == TQt::RightButton )
1406 {
1407 m_edit_menu->popup( TQCursor::pos() );
1408 return true;
1409 }
1410 }
1411
1412 return false;
1413}
1414
1415void KNote::slotSaveData()
1416{
1417 saveData();
1418}
1419
1420void KNote::deleteWhenIdle()
1421{
1422 if ( m_busy <= 0 )
1423 deleteLater();
1424 else
1425 m_deleteWhenIdle = true;
1426}
1427
1428void KNote::aboutToEnterEventLoop()
1429{
1430 ++m_busy;
1431}
1432
1433void KNote::eventLoopLeft()
1434{
1435 --m_busy;
1436 if ( m_busy <= 0 && m_deleteWhenIdle )
1437 deleteLater();
1438}
1439
1440
1441#include "knote.moc"
1442#include "knotebutton.moc"
A dialog to request a hostname or IP address.
Definition: knotehostdlg.h:45