knotes Library API Documentation

knote.cpp

00001 /*******************************************************************
00002  KNotes -- Notes for the KDE project
00003 
00004  Copyright (c) 1997-2003, 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00019 *******************************************************************/
00020 
00021 #include <qlabel.h>
00022 #include <qsizegrip.h>
00023 #include <qbitmap.h>
00024 #include <qcursor.h>
00025 #include <qpointarray.h>
00026 #include <qpainter.h>
00027 #include <qpaintdevicemetrics.h>
00028 #include <qsimplerichtext.h>
00029 
00030 #include <kapplication.h>
00031 #include <kdebug.h>
00032 #include <kaction.h>
00033 #include <kxmlguifactory.h>
00034 #include <kprinter.h>
00035 #include <klocale.h>
00036 #include <kstandarddirs.h>
00037 #include <ksimpleconfig.h>
00038 #include <kiconloader.h>
00039 #include <kmessagebox.h>
00040 #include <kprocess.h>
00041 #include <kinputdialog.h>
00042 #include <kpopupmenu.h>
00043 #include <kmdcodec.h>
00044 #include <kglobalsettings.h>
00045 
00046 #include "libkcal/journal.h"
00047 
00048 #include "knote.h"
00049 #include "knotebutton.h"
00050 #include "knoteedit.h"
00051 #include "knoteconfigdlg.h"
00052 #include "version.h"
00053 
00054 #include <kwin.h>
00055 #include <netwm.h>
00056 
00057 // fscking X headers
00058 #ifdef FocusIn
00059 #undef FocusIn
00060 #endif
00061 #ifdef FocusOut
00062 #undef FocusOut
00063 #endif
00064 
00065 extern Atom qt_sm_client_id;
00066 
00067 using namespace KCal;
00068 
00069 
00070 KNote::KNote( KXMLGUIBuilder* builder, QDomDocument buildDoc, Journal *j,
00071               QWidget* parent, const char* name )
00072   : QFrame( parent, name, WStyle_Customize | WStyle_NoBorder | WDestructiveClose ),
00073     m_label( 0 ), m_button( 0 ), m_editor( 0 ), m_tool( 0 ), 
00074     m_journal( j )
00075 {
00076     // to disable kwin's session management (ie. saving positions of windows) we need to
00077     // remove the session id from all note windows
00078     XChangeProperty( x11Display(), winId(), qt_sm_client_id, XA_STRING, 8,
00079         PropModeReplace, 0, 0 );
00080 
00081     // create the menu items for the note - not the editor...
00082     // rename, mail, print, insert date, close, delete, new note
00083     new KAction( i18n("New"), "filenew", 0, 
00084         this, SLOT(slotNewNote()), actionCollection(), "new_note" );
00085     new KAction( i18n("Rename..."), "text", 0, 
00086         this, SLOT(slotRename()), actionCollection(), "rename_note" );
00087     new KAction( i18n("Hide"), "fileclose" , 0, 
00088         this, SLOT(slotClose()), actionCollection(), "hide_note" );
00089     new KAction( i18n("Delete"), "knotes_delete", 0, 
00090         this, SLOT(slotKill()), actionCollection(), "delete_note" );
00091 
00092     new KAction( i18n("Insert Date"), "knotes_date", 0 , 
00093         this, SLOT(slotInsDate()), actionCollection(), "insert_date" );
00094     new KAction( i18n("Mail..."), "mail_send", 0, 
00095         this, SLOT(slotMail()), actionCollection(), "mail_note" );
00096     new KAction( i18n("Print..."), "fileprint", 0, 
00097         this, SLOT(slotPrint()), actionCollection(), "print_note" );
00098     new KAction( i18n("Preferences..."), "configure", 0, 
00099         this, SLOT(slotPreferences()), actionCollection(), "configure_note" );
00100 
00101     m_alwaysOnTop = new KToggleAction( i18n("Always on Top"), "attach", 0, 
00102         this, SLOT(slotToggleAlwaysOnTop()), actionCollection(), "always_on_top" );
00103     connect( m_alwaysOnTop, SIGNAL(toggled(bool)), m_alwaysOnTop, SLOT(setChecked(bool)) );
00104 
00105     m_toDesktop = new KListAction( i18n("To Desktop"), 0, 
00106         this, SLOT(slotPopupActionToDesktop(int)), actionCollection(), "to_desktop" );
00107     connect( m_toDesktop->popupMenu(), SIGNAL(aboutToShow()), this, SLOT(slotUpdateDesktopActions()) );
00108 
00109     // create the note header, button and label...
00110     m_button = new KNoteButton( "knotes_close", this );
00111     connect( m_button, SIGNAL(clicked()), this, SLOT(slotClose()) );
00112 
00113     m_label = new QLabel( this );
00114     m_label->installEventFilter( this );  // receive events (for dragging & action menu)
00115     setName( m_journal->summary() );      // don't worry, no signals are connected at this stage yet
00116 
00117     // create the toolbar
00118     m_tool = new QWidget( this, "toolbar" );
00119     m_tool->hide();
00120 
00121     // create the note editor
00122     m_editor = new KNoteEdit( m_tool, this );
00123     m_editor->installEventFilter( this ); // receive events (for modified)
00124     m_editor->viewport()->installEventFilter( this );
00125 
00126     setDOMDocument( buildDoc );
00127     factory = new KXMLGUIFactory( builder, this, "guifactory" );
00128     factory->addClient( this );
00129 
00130     m_menu = static_cast<KPopupMenu*>(factory->container( "note_context", this ));
00131     m_edit_menu = static_cast<KPopupMenu*>(factory->container( "note_edit", this ));
00132 
00133     setFocusProxy( m_editor );
00134 
00135     // create the resize handle
00136     m_editor->setCornerWidget( new QSizeGrip( this ) );
00137     uint width = m_editor->cornerWidget()->width();
00138     uint height = m_editor->cornerWidget()->height();
00139     QBitmap mask;
00140     mask.resize( width, height );
00141     mask.fill( color0 );
00142     QPointArray array;
00143     array.setPoints( 3, 0, height, width, height, width, 0 );
00144     QPainter p;
00145     p.begin( &mask );
00146     p.setBrush( color1 );
00147     p.drawPolygon( array );
00148     p.end();
00149     m_editor->cornerWidget()->setMask( mask );
00150 
00151     // set up the look&feel of the note
00152     setMinimumSize( 20, 20 );
00153     setFrameStyle( WinPanel | Raised );
00154     setLineWidth( 1 );
00155 
00156     m_editor->setMargin( 5 );
00157     m_editor->setFrameStyle( NoFrame );
00158     m_editor->setBackgroundMode( PaletteBase );
00159 
00160     // get the config attachment
00161     m_configFile = m_journal->attachments(CONFIG_MIME).first()->uri();
00162 
00163     // load the display configuration of the note
00164     KSimpleConfig config( m_configFile );
00165     config.setGroup( "Display" );
00166     width  = config.readUnsignedNumEntry( "width", 200 );
00167     height = config.readUnsignedNumEntry( "height", 200 );
00168     resize( width, height );
00169 
00170     config.setGroup( "WindowDisplay" );
00171     int note_desktop = config.readNumEntry( "desktop", KWin::currentDesktop() );
00172     ulong note_state = config.readUnsignedLongNumEntry( "state", NET::SkipTaskbar );
00173     QPoint default_position = QPoint( -1000, -1000 );
00174     QPoint position  = config.readPointEntry( "position", &default_position );
00175 
00176     KWin::setState( winId(), note_state );
00177     if ( note_state & NET::StaysOnTop )
00178         m_alwaysOnTop->setChecked( true );
00179 
00180     // let KWin do the placement if the position is illegal
00181     if ( position != default_position &&
00182             kapp->desktop()->rect().intersects( QRect( position, size() ) ) )
00183         move( position );           // do before calling show() to avoid flicker
00184 
00185     // read configuration settings...
00186     slotApplyConfig();
00187 
00188     // show the note if desired
00189     if ( note_desktop != 0 && !isVisible() )
00190     {
00191         // HACK HACK
00192         if( note_desktop != NETWinInfo::OnAllDesktops )
00193         {
00194             // to avoid flicker, call this before show()
00195             toDesktop( note_desktop );
00196             show();
00197         } else {
00198             show();
00199             // if this is called before show(),
00200             // it won't work for sticky notes!!!
00201             toDesktop( note_desktop );
00202         }
00203     }
00204 
00205     m_editor->setText( m_journal->description() );
00206     m_editor->setModified( false );
00207 }
00208 
00209 KNote::~KNote()
00210 {
00211 }
00212 
00213 
00214 // -------------------- public member functions -------------------- //
00215 
00216 void KNote::saveData()
00217 {
00218     m_journal->setSummary( m_label->text() );
00219     m_journal->setDescription( m_editor->text() );
00220     m_editor->setModified( false );
00221 
00222     // TODO: call m_calendar.update( this ) in knotesapp?
00223     emit sigSaveData();
00224 }
00225 
00226 void KNote::saveConfig() const
00227 {
00228     // all that needs to get saved here is the size and name
00229     // everything else would have been saved by the preferences dialog
00230     KSimpleConfig config( m_configFile );
00231 
00232     // need to save the new size to KSimpleConfig object
00233     // but don't save the height of the toolbar
00234     config.setGroup( "Display" );
00235     config.writeEntry( "width", width() );
00236     config.writeEntry( "height", height() - (m_tool->isHidden() ? 0:m_tool->height()) );
00237 
00238     NETWinInfo wm_client( qt_xdisplay(), winId(), qt_xrootwin(), NET::WMDesktop | NET::WMState );
00239     config.setGroup( "WindowDisplay" );
00240     config.writeEntry( "desktop", wm_client.desktop() );
00241 
00242     if ( isHidden() && m_alwaysOnTop->isChecked() )
00243         config.writeEntry( "state", wm_client.state() | NET::StaysOnTop );
00244     else
00245         config.writeEntry( "state", wm_client.state() );
00246 
00247     // TODO: move to group Display
00248     config.writeEntry( "position", pos() );
00249 }
00250 
00251 QString KNote::noteId() const
00252 {
00253     return m_journal->uid();
00254 }
00255 
00256 QString KNote::name() const
00257 {
00258     return m_label->text();
00259 }
00260 
00261 QString KNote::text() const
00262 {
00263     return m_editor->text();
00264 }
00265 
00266 void KNote::setName( const QString& name )
00267 {
00268     m_label->setText( name );
00269     updateLabelAlignment();
00270 
00271     if ( m_editor )    // not called from CTOR?
00272         saveData();
00273 
00274     // set the window's name for the taskbar entry to be more helpful (#58338)
00275     NETWinInfo note_win( qt_xdisplay(), winId(), qt_xrootwin(), NET::WMDesktop );
00276     note_win.setName( name.utf8() );
00277 
00278     emit sigNameChanged();
00279 }
00280 
00281 void KNote::setText( const QString& text )
00282 {
00283     m_editor->setText( text );
00284     saveData();
00285 }
00286 
00287 void KNote::sync( const QString& app )
00288 {
00289     QByteArray sep( 1 );
00290     sep[0] = '\0';
00291 
00292     KMD5 hash;
00293     QCString result;
00294 
00295     hash.update( m_label->text().utf8() );
00296     hash.update( sep );
00297     hash.update( m_editor->text().utf8() );
00298     hash.hexDigest( result );
00299 
00300     KSimpleConfig config( m_configFile );
00301 
00302     config.setGroup( "Synchronisation" );
00303     config.writeEntry( app, result.data() );
00304 }
00305 
00306 bool KNote::isNew( const QString& app ) const
00307 {
00308     KSimpleConfig config( m_configFile );
00309 
00310     config.setGroup( "Synchronisation" );
00311     QString hash = config.readEntry( app );
00312     return hash.isEmpty();
00313 }
00314 
00315 bool KNote::isModified( const QString& app ) const
00316 {
00317     QByteArray sep( 1 );
00318     sep[0] = '\0';
00319 
00320     KMD5 hash;
00321     hash.update( m_label->text().utf8() );
00322     hash.update( sep );
00323     hash.update( m_editor->text().utf8() );
00324     hash.hexDigest();
00325 
00326     KSimpleConfig config( m_configFile );
00327     config.setGroup( "Synchronisation" );
00328     QString orig = config.readEntry( app );
00329 
00330     if ( hash.verify( orig.utf8() ) )   // returns false on error!
00331         return false;
00332     else
00333         return true;
00334 }
00335 
00336 
00337 // -------------------- public slots -------------------- //
00338 
00339 void KNote::slotNewNote()
00340 {
00341     emit sigNewNote();
00342 }
00343 
00344 void KNote::slotRename()
00345 {
00346     // pop up dialog to get the new name
00347     bool ok;
00348     QString newName = KInputDialog::getText( QString::null,
00349         i18n("Please enter the new name:"), m_label->text(), &ok, this );
00350     if ( !ok ) // handle cancel
00351         return;
00352 
00353     setName( newName );
00354 }
00355 
00356 void KNote::slotClose()
00357 {
00358     m_editor->clearFocus();
00359     hide(); //just hide the note so it's still available from the dock window
00360 }
00361 
00362 void KNote::slotKill( bool force )
00363 {
00364     if ( !force )
00365     if ( KMessageBox::warningYesNo( this,
00366          i18n("<qt>Do you really want to delete note <b>%1</b>?</qt>").arg( m_label->text() ),
00367          i18n("Confirm Delete") ) != KMessageBox::Yes ) return;
00368     emit sigKillNote( m_journal );
00369 }
00370 
00371 void KNote::slotInsDate()
00372 {
00373     m_editor->insert( KGlobal::locale()->formatDateTime(QDateTime::currentDateTime()) );
00374 }
00375 
00376 void KNote::slotPreferences()
00377 {
00378     // launch preferences dialog...
00379     KNoteConfigDlg configDlg( m_configFile, i18n("Local Settings"), false, this );
00380     connect( &configDlg, SIGNAL(updateConfig()), this, SLOT(slotApplyConfig()) );
00381     connect( &configDlg, SIGNAL(skipTaskbar(bool)), this, SLOT(slotSkipTaskbar(bool)) );
00382     configDlg.exec();
00383 }
00384 
00385 void KNote::slotToggleAlwaysOnTop()
00386 {
00387     if ( KWin::info(winId()).state & NET::StaysOnTop )
00388         KWin::clearState( winId(), NET::StaysOnTop );
00389     else
00390         KWin::setState( winId(), KWin::info(winId()).state | NET::StaysOnTop );
00391 }
00392 
00393 void KNote::slotPopupActionToDesktop( int id )
00394 {
00395     if( id > 1 )
00396       --id;      // compensate for the menu separator
00397     toDesktop( id );
00398 }
00399 
00400 void KNote::toDesktop( int desktop )
00401 {
00402     if ( desktop == 0 || desktop == NETWinInfo::OnAllDesktops )
00403         KWin::setOnAllDesktops( winId(), true );
00404     else
00405         KWin::setOnDesktop( winId(), desktop );
00406 }
00407 
00408 void KNote::slotUpdateDesktopActions()
00409 {
00410     NETRootInfo wm_root( qt_xdisplay(), NET::NumberOfDesktops | NET::DesktopNames );
00411     NETWinInfo wm_client( qt_xdisplay(), winId(), qt_xrootwin(), NET::WMDesktop );
00412 
00413     QStringList desktops;
00414     desktops.append( i18n("&All Desktops") );
00415     desktops.append( QString::null );           // Separator
00416 
00417     int count = wm_root.numberOfDesktops();
00418     for ( int n = 1; n <= count; n++ )
00419         desktops.append( QString("&%1 %2").arg( n ).arg( QString::fromUtf8(wm_root.desktopName( n )) ) );
00420 
00421     m_toDesktop->setItems( desktops );
00422 
00423     kdDebug() << "updateDesktopActions:" << wm_client.desktop() << endl;
00424     if ( wm_client.desktop() == NETWinInfo::OnAllDesktops )
00425         m_toDesktop->setCurrentItem( 0 );
00426     else
00427         m_toDesktop->setCurrentItem( wm_client.desktop() + 1 ); // compensate for separator (+1)
00428 }
00429 
00430 void KNote::slotMail() //const
00431 {
00432     saveData();
00433     KSimpleConfig config( m_configFile, true );
00434 
00435     // TODO: convert to plain text
00436     QString msg_body = m_editor->text();
00437 
00438     //get the mail action command
00439     config.setGroup( "Actions" );
00440     QString mail_cmd = config.readPathEntry( "mail", "kmail --msg %f" );
00441     QStringList cmd_list = QStringList::split( QChar(' '), mail_cmd );
00442 
00443     KProcess mail;
00444     for ( QStringList::Iterator it = cmd_list.begin();
00445         it != cmd_list.end(); ++it )
00446     {
00447         if ( *it == "%f" )
00448             mail << msg_body.local8Bit();
00449         else if ( *it == "%t" )
00450             mail << m_label->text().local8Bit();
00451         else
00452             mail << (*it).local8Bit();
00453     }
00454 
00455     if ( !mail.start( KProcess::DontCare ) )
00456     {
00457         KMessageBox::sorry( this, i18n("Unable to start the mail process.") );
00458     }
00459 }
00460 
00461 void KNote::slotPrint()
00462 {
00463     saveData();
00464 
00465     KPrinter printer;
00466     printer.setFullPage( true );
00467 
00468     if ( printer.setup(0L, i18n("Print %1").arg(name())) )
00469     {
00470         KSimpleConfig config( m_configFile, true );
00471         config.setGroup( "Editor" );
00472 
00473         QFont font( KGlobalSettings::generalFont() );
00474         font = config.readFontEntry( "font", &font );
00475 
00476         QPainter painter;
00477         painter.begin( &printer );
00478 
00479         const int margin = 40;  // pt
00480 
00481         QPaintDeviceMetrics metrics( painter.device() );
00482         int marginX = margin * metrics.logicalDpiX() / 72;
00483         int marginY = margin * metrics.logicalDpiY() / 72;
00484 
00485         QRect body( marginX, marginY,
00486                     metrics.width() - marginX * 2,
00487                     metrics.height() - marginY * 2 );
00488 
00489         QString content;
00490         if ( m_editor->textFormat() == PlainText )
00491             content = QStyleSheet::convertFromPlainText( m_editor->text() );
00492         else
00493             content = m_editor->text();
00494 
00495         QSimpleRichText text( content, font, m_editor->context(),
00496                               m_editor->styleSheet(), m_editor->mimeSourceFactory(),
00497                               body.height() /*, linkColor, linkUnderline? */ );
00498 
00499         text.setWidth( &painter, body.width() );
00500         QRect view( body );
00501 
00502         int page = 1;
00503 
00504         for (;;) 
00505         {
00506             text.draw( &painter, body.left(), body.top(), view, colorGroup() );
00507             view.moveBy( 0, body.height() );
00508             painter.translate( 0, -body.height() );
00509 
00510             // page numbers
00511             painter.setFont( font );
00512             painter.drawText(
00513                 view.right() - painter.fontMetrics().width( QString::number( page ) ),
00514                 view.bottom() + painter.fontMetrics().ascent() + 5, QString::number( page )
00515             );
00516 
00517             if ( view.top() >= text.height() )
00518                 break;
00519 
00520             printer.newPage();
00521             page++;
00522         }
00523 
00524         painter.end();
00525     }
00526 }
00527 
00528 
00529 // -------------------- private slots -------------------- //
00530 
00531 void KNote::slotApplyConfig()
00532 {
00533     KSimpleConfig config( m_configFile );
00534 
00535     // do the Editor group - tabsize, autoindent, textformat, font, fontsize, fontstyle
00536     config.setGroup( "Editor" );
00537 
00538     bool richtext = config.readBoolEntry( "richtext", false );
00539     if ( richtext )
00540         m_editor->setTextFormat( RichText );
00541     else
00542     {
00543         m_editor->setTextFormat( PlainText );
00544         m_editor->setText( m_editor->text() );
00545     }
00546 
00547     QFont def( KGlobalSettings::generalFont() );
00548     def = config.readFontEntry( "font", &def );
00549     m_editor->setTextFont( def );
00550 
00551     // TODO remove this!
00552     def = config.readFontEntry( "titlefont", &def );
00553     m_label->setFont( def );
00554     updateLabelAlignment();
00555 
00556     uint tab_size = config.readUnsignedNumEntry( "tabsize", 4 );
00557     m_editor->setTabStop( tab_size );
00558 
00559     bool indent = config.readBoolEntry( "autoindent", true );
00560     m_editor->setAutoIndentMode( indent );
00561 
00562     // do Display group - bgcolor, fgcolor, transparent
00563     config.setGroup( "Display" );
00564 
00565     // create a pallete...
00566     QColor bg = config.readColorEntry( "bgcolor", &(Qt::yellow) );
00567     QColor fg = config.readColorEntry( "fgcolor", &(Qt::black) );
00568 
00569     setColor( fg, bg );
00570 }
00571 
00572 void KNote::slotSkipTaskbar( bool skip )
00573 {
00574     if ( skip )
00575         KWin::setState( winId(), KWin::info(winId()).state | NET::SkipTaskbar );
00576     else
00577         KWin::clearState( winId(), NET::SkipTaskbar );
00578 }
00579 
00580 // -------------------- private methods -------------------- //
00581 
00582 void KNote::setColor( const QColor &fg, const QColor &bg )
00583 {
00584     QPalette newpalette = palette();
00585     newpalette.setColor( QColorGroup::Background, bg );
00586     newpalette.setColor( QColorGroup::Foreground, fg );
00587     newpalette.setColor( QColorGroup::Base,       bg ); // text background
00588     newpalette.setColor( QColorGroup::Text,       fg ); // text color
00589     newpalette.setColor( QColorGroup::Button,     bg );
00590 
00591     // the shadow
00592     newpalette.setColor( QColorGroup::Midlight, bg.light(110) );
00593     newpalette.setColor( QColorGroup::Shadow, bg.dark(116) );
00594     newpalette.setColor( QColorGroup::Light, bg.light(180) );
00595     newpalette.setColor( QColorGroup::Dark, bg.dark(108) );
00596     setPalette( newpalette );
00597 
00598     // set the text color
00599     m_editor->setTextColor( fg );
00600 
00601     // set darker value for the hide button...
00602     QPalette darker = palette();
00603     darker.setColor( QColorGroup::Button, bg.dark(116) );
00604     m_button->setPalette( darker );
00605 
00606     // to set the color of the title
00607     updateFocus();
00608 }
00609 
00610 void KNote::updateLabelAlignment()
00611 {
00612     // if the name is too long to fit, left-align it, otherwise center it (#59028)
00613     QString labelText = m_label->text();
00614     if ( m_label->fontMetrics().boundingRect( labelText ).width() > m_label->width() )
00615         m_label->setAlignment( AlignLeft );
00616     else
00617         m_label->setAlignment( AlignHCenter );
00618 }
00619 
00620 void KNote::updateFocus()
00621 {
00622     if ( hasFocus() )
00623     {
00624         m_label->setBackgroundColor( palette().active().shadow() );
00625         m_button->show();
00626         m_editor->cornerWidget()->show();
00627 
00628         if ( m_tool->isHidden() && m_editor->textFormat() == QTextEdit::RichText )
00629         {
00630             m_tool->show();
00631             setGeometry( x(), y(), width(), height() + m_tool->height() );
00632         }
00633     }
00634     else
00635     {
00636         m_label->setBackgroundColor( palette().active().background() );
00637         m_button->hide();
00638         m_editor->cornerWidget()->hide();
00639 
00640         if ( !m_tool->isHidden() )
00641         {
00642             m_tool->hide();
00643             updateLayout();     // to update the minimum height
00644             setGeometry( x(), y(), width(), height() - m_tool->height() );
00645         }
00646     }
00647 }
00648 
00649 void KNote::updateLayout()
00650 {
00651     // DAMN, Qt 3.1 still has no support for widgets with a fixed aspect ratio :-(
00652     // So we have to write our own layout manager...
00653 
00654     int headerHeight = m_label->sizeHint().height();
00655     int margin = m_editor->margin();
00656 
00657     m_button->setGeometry(
00658                 frameRect().width() - headerHeight - 2,
00659                 frameRect().y() + 2,
00660                 headerHeight,
00661                 headerHeight
00662              );
00663 
00664     m_label->setGeometry(
00665                 frameRect().x() + 2,
00666                 frameRect().y() + 2,
00667                 frameRect().width() - (m_button->isHidden()?0:headerHeight) - 4,
00668                 headerHeight
00669              );
00670     updateLabelAlignment();
00671 
00672     m_tool->setGeometry(
00673                 contentsRect().x(),
00674                 contentsRect().y() + headerHeight + 2,
00675                 contentsRect().width(),
00676                 16
00677                 //m_tool->minimumSizeHint().height()
00678              );
00679 
00680     int toolHeight = m_tool->isHidden() ? 0 : m_tool->height();
00681 
00682     m_editor->setGeometry(
00683                 contentsRect().x(),
00684                 contentsRect().y() + headerHeight + toolHeight + 2,
00685                 contentsRect().width(),
00686                 contentsRect().height() - headerHeight - toolHeight - 4
00687              );
00688 
00689     setMinimumSize( m_editor->cornerWidget()->width() + margin*2 + 4,
00690                     headerHeight + toolHeight + m_editor->cornerWidget()->height() + margin*2 + 4 );
00691 }
00692 
00693 // -------------------- protected methods -------------------- //
00694 
00695 void KNote::resizeEvent( QResizeEvent* qre )
00696 {
00697     QFrame::resizeEvent( qre );
00698     updateLayout();
00699 }
00700 
00701 void KNote::closeEvent( QCloseEvent* /*e*/ )
00702 {
00703     slotClose();
00704 }
00705 
00706 void KNote::keyPressEvent( QKeyEvent* e )
00707 {
00708     if ( e->key() == Key_Escape )
00709         slotClose();
00710     else
00711         e->ignore();
00712 }
00713 
00714 bool KNote::event( QEvent* ev )
00715 {
00716     if ( ev->type() == QEvent::LayoutHint )
00717     {
00718         updateLayout();
00719         return true;
00720     }
00721     else
00722         return QFrame::event( ev );
00723 }
00724 
00725 bool KNote::eventFilter( QObject* o, QEvent* ev )
00726 {
00727     if ( o == m_label )
00728     {
00729         QMouseEvent* e = (QMouseEvent*)ev;
00730 
00731         if ( ev->type() == QEvent::MouseButtonDblClick )
00732             slotRename();
00733 
00734         if ( ev->type() == QEvent::MouseButtonRelease &&
00735              (e->button() == LeftButton || e->button() == MidButton) )
00736         {
00737             m_dragging = false;
00738             m_label->releaseMouse();
00739             return true;
00740         }
00741 
00742         if ( ev->type() == QEvent::MouseButtonPress &&
00743              (e->button() == LeftButton || e->button() == MidButton))
00744         {
00745             m_pointerOffset = e->pos();
00746             m_label->grabMouse( sizeAllCursor );
00747 
00748             e->button() == LeftButton ? raise() : lower();
00749 
00750             return true;
00751         }
00752 
00753         if ( ev->type() == QEvent::MouseMove && m_label == mouseGrabber() )
00754         {
00755             if ( m_dragging )
00756                 move( QCursor::pos() - m_pointerOffset );
00757             else
00758             {
00759                 m_dragging = (
00760                     (e->pos().x() - m_pointerOffset.x()) *
00761                     (e->pos().x() - m_pointerOffset.x())
00762                     +
00763                     (e->pos().y() - m_pointerOffset.y()) *
00764                     (e->pos().y() - m_pointerOffset.y())   >= 9
00765                 );
00766             }
00767             return true;
00768         }
00769 
00770         if ( m_menu && ( ev->type() == QEvent::MouseButtonPress )
00771             && ( e->button() == RightButton ) )
00772         {
00773             m_menu->popup( QCursor::pos() );
00774             return true;
00775         }
00776 
00777         return false;
00778     }
00779 
00780     if ( o == m_editor )
00781     {
00782         if ( ev->type() == QEvent::FocusOut )
00783         {
00784             if ( static_cast<QFocusEvent*>(ev)->reason() != QFocusEvent::Popup )
00785                 updateFocus();
00786             if ( m_editor->isModified() )
00787                 saveData();
00788         }
00789         else if ( ev->type() == QEvent::FocusIn )
00790             updateFocus();
00791 
00792         return false;
00793     }
00794 
00795     if ( o == m_editor->viewport() )
00796     {
00797         if ( ev->type() == QEvent::MouseButtonPress )
00798             if ( m_edit_menu && ((QMouseEvent*)ev)->button() == RightButton )
00799             {
00800                 m_edit_menu->popup( QCursor::pos() );
00801                 return true;
00802             }
00803     }
00804 
00805     return false;
00806 }
00807 
00808 #include "knote.moc"
00809 #include "knotebutton.moc"
KDE Logo
This file is part of the documentation for knotes Library Version 3.2.1.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sat Mar 6 17:18:05 2004 by doxygen 1.3.6-20040222 written by Dimitri van Heesch, © 1997-2003