knotes Library API Documentation

knote.cpp

00001 /*******************************************************************
00002  KNotes -- Notes for the KDE project
00003 
00004  Copyright (c) 1997-2002, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
00019 *******************************************************************/
00020 
00021 #include <qlabel.h>
00022 #include <qsizegrip.h>
00023 #include <qbitmap.h>
00024 #include <qcursor.h>
00025 #include <qpaintdevicemetrics.h>
00026 #include <qsimplerichtext.h>
00027 
00028 #include <kapplication.h>
00029 #include <kaction.h>
00030 #include <kxmlgui.h>
00031 #include <kprinter.h>
00032 #include <klocale.h>
00033 #include <kstandarddirs.h>
00034 #include <ksimpleconfig.h>
00035 #include <kdebug.h>
00036 #include <kiconloader.h>
00037 #include <kmessagebox.h>
00038 #include <kprocess.h>
00039 #include <klineeditdlg.h>
00040 #include <kpopupmenu.h>
00041 #include <kmdcodec.h>
00042 #include <kio/netaccess.h>
00043 #include <kglobalsettings.h>
00044 
00045 #include "knote.h"
00046 #include "knotebutton.h"
00047 #include "knoteedit.h"
00048 #include "knoteconfigdlg.h"
00049 #include "version.h"
00050 
00051 #include <kwin.h>
00052 #include <netwm.h>
00053 
00054 // fscking X headers
00055 #ifdef FocusIn
00056 #undef FocusIn
00057 #endif
00058 #ifdef FocusOut
00059 #undef FocusOut
00060 #endif
00061 
00062 extern Atom qt_sm_client_id;
00063 
00064 
00065 // -------------------- Initialisation -------------------- //
00066 KNote::KNote( KXMLGUIBuilder* builder, QDomDocument buildDoc, const QString& file,
00067               bool load, QWidget* parent, const char* name )
00068   : QFrame( parent, name, WStyle_Customize | WStyle_NoBorder | WDestructiveClose ),
00069     m_noteDir( KGlobal::dirs()->saveLocation( "appdata", "notes/" ) ),
00070     m_configFile( file )
00071 {
00072     XChangeProperty( x11Display(), winId(), qt_sm_client_id, XA_STRING, 8, 
00073         PropModeReplace, 0, 0 );
00074 
00075     // create the menu items for the note - not the editor...
00076     // rename, mail, print, insert date, close, delete, new note
00077     new KAction( i18n("New"), "filenew", 0, this, SLOT(slotNewNote()), actionCollection(), "new_note" );
00078     new KAction( i18n("Rename..."), "text", 0, this, SLOT(slotRename()), actionCollection(), "rename_note" );
00079     new KAction( i18n("Hide"), "fileclose" , 0, this, SLOT(slotClose()), actionCollection(), "hide_note" );
00080     new KAction( i18n("Delete"), "knotesdelete", 0, this, SLOT(slotKill()), actionCollection(), "delete_note" );
00081 
00082     new KAction( i18n("Insert Date"), "knotesdate", 0 , this, SLOT(slotInsDate()), actionCollection(), "insert_date" );
00083     new KAction( i18n("Mail..."), "mail_send", 0, this, SLOT(slotMail()), actionCollection(), "mail_note" );
00084     new KAction( i18n("Print..."), "fileprint", 0, this, SLOT(slotPrint()), actionCollection(), "print_note" );
00085     new KAction( i18n("Preferences..."), "configure", 0, this, SLOT(slotPreferences()), actionCollection(), "configure_note" );
00086 
00087     m_alwaysOnTop = new KToggleAction( i18n("Always on Top"), "attach", 0, this, SLOT(slotToggleAlwaysOnTop()), actionCollection(), "always_on_top" );
00088     connect( m_alwaysOnTop, SIGNAL(toggled(bool)), m_alwaysOnTop, SLOT(setChecked(bool)) );
00089     m_toDesktop = new KListAction( i18n("To Desktop"), 0, this, SLOT(slotToDesktop(int)), actionCollection(), "to_desktop" );
00090     connect( m_toDesktop->popupMenu(), SIGNAL(aboutToShow()), this, SLOT(slotUpdateDesktopActions()) );
00091 
00092     // create the note header, button and label...
00093     m_button = new KNoteButton( this );
00094     m_button->setPixmap( BarIcon( "knotesclose" ) );
00095     connect( m_button, SIGNAL( clicked() ), this, SLOT( slotClose() ) );
00096 
00097     m_label = new QLabel( this );
00098     m_label->setAlignment( AlignHCenter );
00099     m_label->installEventFilter( this );  // recieve events (for dragging & action menu)
00100 
00101     // create the note editor
00102     m_editor = new KNoteEdit( this );
00103     m_editor->installEventFilter( this ); // recieve events (for modified)
00104     m_editor->viewport()->installEventFilter( this );
00105 
00106     setDOMDocument( buildDoc );
00107     factory = new KXMLGUIFactory( builder, this, "guifactory" );
00108     factory->addClient( this );
00109 
00110     m_menu = static_cast<KPopupMenu*>(factory->container( "note_context", this ));
00111     m_edit_menu = static_cast<KPopupMenu*>(factory->container( "note_edit", this ));
00112 
00113     setFocusProxy( m_editor );
00114     
00115     // create the resize handle
00116     m_editor->setCornerWidget( new QSizeGrip( this ) );
00117     int width = m_editor->cornerWidget()->width();
00118     int height = m_editor->cornerWidget()->height();
00119     QBitmap mask;
00120     mask.resize( width, height );
00121     mask.fill( color0 );
00122     QPointArray array;
00123     array.setPoints( 3, 0, height, width, height, width, 0 );
00124     QPainter p;
00125     p.begin( &mask );
00126     p.setBrush( color1 );
00127     p.drawPolygon( array );
00128     p.end();
00129     m_editor->cornerWidget()->setMask( mask );
00130 
00131     // set up the look&feel of the note
00132     setMinimumSize( 20, 20 );
00133     setFrameStyle( WinPanel | Raised );
00134     setLineWidth( 1 );
00135 
00136     m_editor->setMargin( 5 );
00137     m_editor->setFrameStyle( NoFrame );
00138     m_editor->setBackgroundMode( PaletteBase );
00139 
00140     // now create or load the data and configuration
00141     bool oldconfig = false;
00142     // WARNING: if the config file doesn't exist a new note will be created!
00143     if ( load && m_noteDir.exists( m_configFile ) )
00144     {
00145         QString path = m_noteDir.absFilePath( m_configFile );
00146         KSimpleConfig* test = new KSimpleConfig( path, true );
00147         test->setGroup( "General" );
00148         oldconfig = ( test->readDoubleNumEntry( "version", 1 ) < 2 );
00149         delete test;
00150     }
00151     else
00152     {
00153         m_label->setText( m_configFile );
00154 
00155         // set the new configfile's name...
00156         for ( int i = 1; ; i++ )
00157         {
00158             m_configFile = QString( "KNote %1" ).arg(i);
00159             if ( !m_noteDir.exists( m_configFile ) )
00160                 break;
00161         }
00162 
00163         // ...and "fill" it with the default config
00164         KIO::NetAccess::copy( KURL( KGlobal::dirs()->findResource( "config", "knotesrc" ) ),
00165                               KURL( m_noteDir.absFilePath( m_configFile ) ) );
00166     }
00167 
00168     if ( oldconfig )
00169     {
00170         //read and convert the old configuration
00171         convertOldConfig();
00172     }
00173     else
00174     {
00175         // load the display configuration of the note
00176         KSimpleConfig config( m_noteDir.absFilePath( m_configFile ) );
00177         config.setGroup( "Display" );
00178         uint width  = config.readUnsignedNumEntry( "width", 200 );
00179         uint height = config.readUnsignedNumEntry( "height", 200 );
00180         resize( width, height );
00181 
00182         config.setGroup( "WindowDisplay" );
00183         int note_desktop = config.readNumEntry( "desktop", KWin::currentDesktop() );
00184         ulong note_state = config.readUnsignedLongNumEntry( "state", NET::SkipTaskbar );
00185         QPoint default_position = QPoint( -1, -1 );
00186         QPoint position  = config.readPointEntry( "position", &default_position );
00187 
00188         KWin::setState( winId(), note_state );
00189         if ( note_state & NET::StaysOnTop )
00190             m_alwaysOnTop->setChecked( true );
00191 
00192         // let KWin do the placement if the position is illegal
00193         if ( position != default_position &&
00194                kapp->desktop()->rect().contains( position.x()+width, position.y()+height ) )
00195             move( position );           // do before calling show() to avoid flicker
00196 
00197         // read configuration settings...
00198         slotApplyConfig();
00199 
00200         // show the note if desired
00201         if ( note_desktop != 0 && !isVisible() )
00202         {
00203             // HACK HACK
00204             if( note_desktop != NETWinInfo::OnAllDesktops )
00205             {
00206                 // to avoid flicker, call this before show()
00207                 slotToDesktop( note_desktop );
00208                 show();
00209             } else {
00210                 show();
00211                 // if this is called before show(),
00212                 // it won't work for sticky notes!!!
00213                 slotToDesktop( note_desktop );
00214             }
00215         }
00216 
00217         // load the saved text and put it in m_editor...
00218         QString datafile = "." + m_configFile + "_data";
00219         if ( m_noteDir.exists( datafile ) )
00220         {
00221             QString absfile = m_noteDir.absFilePath( datafile );
00222             m_editor->readFile( absfile );
00223         }
00224     }
00225 }
00226 
00227 KNote::~KNote()
00228 {
00229 kdDebug(5500) << k_funcinfo << endl;
00230 
00231     emit sigKilled( m_label->text() );
00232 
00233 }
00234 
00235 
00236 // -------------------- public member functions -------------------- //
00237 
00238 void KNote::saveData() const
00239 {
00240 kdDebug(5500) << k_funcinfo << endl;
00241 
00242     QString datafile = m_noteDir.absFilePath( "." + m_configFile + "_data" );
00243     m_editor->dumpToFile( datafile );
00244     m_editor->setModified( false );
00245 }
00246 
00247 void KNote::saveConfig() const
00248 {
00249 kdDebug(5500) << k_funcinfo << endl;
00250 
00251     // all that needs to get saved here is the size and name
00252     // everything else would have been saved by the preferences dialog
00253     KSimpleConfig config( m_noteDir.absFilePath( m_configFile ) );
00254 
00255     // store config settings...
00256     // need to save the new size to KSimpleConfig object
00257     config.setGroup( "Display" );
00258     config.writeEntry( "width", width() );
00259     config.writeEntry( "height", height() );
00260 
00261     // save name....
00262     config.setGroup( "Data" );
00263     config.writeEntry( "name", m_label->text() );
00264 }
00265 
00266 void KNote::saveDisplayConfig() const
00267 {
00268 kdDebug(5500) << k_funcinfo << endl;
00269 
00270     KSimpleConfig config( m_noteDir.absFilePath( m_configFile ) );
00271     NETWinInfo wm_client( qt_xdisplay(), winId(), qt_xrootwin(), NET::WMDesktop | NET::WMState );
00272 
00273     config.setGroup( "WindowDisplay" );
00274     config.writeEntry( "desktop", wm_client.desktop() );
00275     config.writeEntry( "state", wm_client.state() );
00276     config.writeEntry( "position", pos() );
00277 }
00278 
00279 int KNote::noteId() const
00280 {
00281     return m_configFile.mid( 6 ).toInt();
00282 }
00283 
00284 QString KNote::name() const
00285 {
00286     return m_label->text();
00287 }
00288 
00289 QString KNote::text() const
00290 {
00291     return m_editor->text();
00292 }
00293 
00294 void KNote::setName( const QString& name )
00295 {
00296     m_label->setText( name );
00297 
00298     saveConfig();
00299 }
00300 
00301 void KNote::setText( const QString& text )
00302 {
00303     m_editor->setText( text );
00304 }
00305 
00306 void KNote::sync( const QString& app )
00307 {
00308     QByteArray sep( 1 );
00309     sep[0] = '\0';
00310 
00311     KMD5 hash;
00312     QCString result;
00313 
00314     hash.update( m_label->text().utf8() );
00315     hash.update( sep );
00316     hash.update( m_editor->text().utf8() );
00317     hash.hexDigest( result );
00318 
00319     KSimpleConfig config( m_noteDir.absFilePath( m_configFile ) );
00320 
00321     config.setGroup( "Synchronisation" );
00322     config.writeEntry( app, result.data() );
00323 }
00324 
00325 bool KNote::isNew( const QString& app ) const
00326 {
00327     KSimpleConfig config( m_noteDir.absFilePath( m_configFile ) );
00328 
00329     config.setGroup( "Synchronisation" );
00330     QString hash = config.readEntry( app );
00331     return hash.isEmpty();
00332 }
00333 
00334 bool KNote::isModified( const QString& app ) const
00335 {
00336     QByteArray sep( 1 );
00337     sep[0] = '\0';
00338 
00339     KMD5 hash;
00340     hash.update( m_label->text().utf8() );
00341     hash.update( sep );
00342     hash.update( m_editor->text().utf8() );
00343     hash.hexDigest();
00344 
00345     KSimpleConfig config( m_noteDir.absFilePath( m_configFile ) );
00346     config.setGroup( "Synchronisation" );
00347     QString orig = config.readEntry( app );
00348 
00349     if ( hash.verify( orig.utf8() ) )   // returns false on error!
00350         return false;
00351     else
00352         return true;
00353 }
00354 
00355 
00356 // -------------------- public slots -------------------- //
00357 
00358 void KNote::slotNewNote()
00359 {
00360     emit sigNewNote();
00361 }
00362 
00363 void KNote::slotRename()
00364 {
00365     //pop up dialog to get the new name
00366     bool ok;
00367     QString newname = KLineEditDlg::getText( i18n("Please enter the new name:"),
00368                                              m_label->text(), &ok, this );
00369     if ( !ok ) // handle cancel
00370         return;
00371 
00372     if ( newname.isEmpty() ) {
00373         KMessageBox::sorry( this, i18n("A name must have at least one character") );
00374         return;
00375     }
00376 
00377     emit sigRenamed( m_label->text(), newname );
00378 }
00379 
00380 void KNote::slotClose()
00381 {
00382 kdDebug(5500) << k_funcinfo << endl;
00383     m_editor->clearFocus();
00384     hide(); //just hide the note so it's still available from the dock window
00385 }
00386 
00387 void KNote::slotKill()
00388 {
00389     if ( KMessageBox::warningYesNo( this,
00390          i18n("Do you really want to delete this note?"),
00391          i18n("Delete \"%1\"").arg( m_label->text() ) ) == KMessageBox::Yes )
00392     {
00393         if ( !m_noteDir.remove( m_configFile ) )
00394             kdWarning(5500) << "could not remove conf file for note " << m_label->text() << endl;
00395 
00396         if ( !m_noteDir.remove( "." + m_configFile + "_data" ) )
00397             kdWarning(5500) << "could not remove data file for note " << m_label->text() << endl;
00398 
00399         delete this;
00400     }
00401 }
00402 
00403 void KNote::slotInsDate()
00404 {
00405     m_editor->insert( KGlobal::locale()->formatDateTime(QDateTime::currentDateTime()) );
00406 }
00407 
00408 void KNote::slotPreferences()
00409 {
00410     saveConfig();
00411 
00412     // launch preferences dialog...
00413     KNoteConfigDlg configDlg( m_noteDir.absFilePath( m_configFile ),
00414                               i18n("Local Settings"), false );
00415     connect( &configDlg, SIGNAL( updateConfig() ), this, SLOT( slotApplyConfig() ) );
00416     configDlg.exec();
00417 }
00418 
00419 void KNote::slotToggleAlwaysOnTop()
00420 {
00421     if ( KWin::info(winId()).state & NET::StaysOnTop )
00422         KWin::clearState( winId(), NET::StaysOnTop );
00423     else
00424         KWin::setState( winId(), KWin::info(winId()).state | NET::StaysOnTop );
00425 }
00426 
00427 void KNote::slotToDesktop( int id )
00428 {
00429     if ( id == 0 || id == NETWinInfo::OnAllDesktops )
00430         KWin::setOnAllDesktops( winId(), true );
00431     else
00432         KWin::setOnDesktop( winId(), id );
00433 }
00434 
00435 void KNote::slotUpdateDesktopActions()
00436 {
00437     NETRootInfo wm_root( qt_xdisplay(), NET::NumberOfDesktops | NET::DesktopNames );
00438     NETWinInfo wm_client( qt_xdisplay(), winId(), qt_xrootwin(), NET::WMDesktop );
00439 
00440     QStringList desktops;
00441     desktops.append( i18n("&All Desktops") );
00442     desktops.append( QString::null );           // Separator
00443 
00444     int count = wm_root.numberOfDesktops();
00445     for ( int n = 1; n <= count; n++ )
00446         desktops.append( QString("&%1 %2").arg( n ).arg( QString::fromUtf8(wm_root.desktopName( n )) ) );
00447 
00448     m_toDesktop->setItems( desktops );
00449 
00450     if ( wm_client.desktop() == NETWinInfo::OnAllDesktops )
00451         m_toDesktop->setCurrentItem( 0 );
00452     else
00453         m_toDesktop->setCurrentItem( wm_client.desktop() );
00454 }
00455 
00456 void KNote::slotMail() //const
00457 {
00458     saveData();
00459     KSimpleConfig config( m_noteDir.absFilePath( m_configFile ), true );
00460 
00461     //sync up the data on note and the data file
00462     QString msg_body = m_noteDir.absFilePath( "." + m_configFile + "_data" );
00463 
00464     //get the mail action command
00465     config.setGroup( "Actions" );
00466     QString mail_cmd = config.readEntry( "mail", "kmail --msg %f" );
00467     QStringList cmd_list = QStringList::split( QChar(' '), mail_cmd );
00468 
00469     KProcess mail;
00470     for ( QStringList::Iterator it = cmd_list.begin();
00471         it != cmd_list.end(); ++it )
00472     {
00473         if ( *it == "%f" )
00474             mail << msg_body.local8Bit();
00475         else if ( *it == "%t" )
00476             mail << m_label->text().local8Bit();
00477         else
00478             mail << (*it).local8Bit();
00479     }
00480 
00481     if ( !mail.start( KProcess::DontCare ) )
00482     {
00483         KMessageBox::sorry( this, i18n("Unable to start the mail process.") );
00484     }
00485 }
00486 
00487 void KNote::slotPrint() const
00488 {
00489     saveData();
00490 
00491     KPrinter printer;
00492     printer.setFullPage( true );
00493 
00494     if ( printer.setup() )
00495     {
00496         KSimpleConfig config( m_noteDir.absFilePath( m_configFile ), true );
00497         config.setGroup( "Editor" );
00498 
00499         QFont font( KGlobalSettings::generalFont() );
00500         font = config.readFontEntry( "font", &font );
00501 
00502         QPainter painter;
00503         painter.begin( &printer );
00504         
00505         const int margin = 40;  // pt
00506 
00507         QPaintDeviceMetrics metrics( painter.device() );
00508         int marginX = margin * metrics.logicalDpiX() / 72;
00509         int marginY = margin * metrics.logicalDpiY() / 72;
00510 
00511         QRect body( marginX, marginY,
00512                     metrics.width() - marginX * 2,
00513                     metrics.height() - marginY * 2 );
00514 
00515         QString content;
00516         if ( m_editor->textFormat() == PlainText )
00517             content = QStyleSheet::convertFromPlainText( m_editor->text() );
00518         else
00519             content = m_editor->text();
00520 
00521         QSimpleRichText text( content, font, m_editor->context(),
00522                               m_editor->styleSheet(), m_editor->mimeSourceFactory(),
00523                               body.height() /*, linkColor, linkUnderline? */ );
00524 
00525         text.setWidth( &painter, body.width() );
00526         QRect view( body );
00527 
00528         int page = 1;
00529 
00530         for (;;) {
00531             text.draw( &painter, body.left(), body.top(), view, colorGroup() );
00532             view.moveBy( 0, body.height() );
00533             painter.translate( 0, -body.height() );
00534 
00535             // page numbers
00536             painter.setFont( font );
00537             painter.drawText(
00538                 view.right() - painter.fontMetrics().width( QString::number( page ) ),
00539                 view.bottom() + painter.fontMetrics().ascent() + 5, QString::number( page )
00540             );
00541 
00542             if ( view.top() >= text.height() )
00543                 break;
00544 
00545             printer.newPage();
00546             page++;
00547         }
00548 
00549         painter.end();
00550     }
00551 }
00552 
00553 
00554 // -------------------- private slots -------------------- //
00555 
00556 void KNote::slotApplyConfig()
00557 {
00558     KSimpleConfig config( m_noteDir.absFilePath( m_configFile ) );
00559 
00560     //do the Editor group: tabsize, autoindent, textformat, font, fontsize, fontstyle
00561     config.setGroup( "Editor" );
00562 
00563     bool richtext = config.readBoolEntry( "richtext", false );
00564     if ( richtext )
00565         m_editor->setTextFormat( RichText );
00566     else
00567     {
00568         m_editor->setTextFormat( PlainText );
00569         m_editor->setText( m_editor->text() );
00570     }
00571 
00572     QFont def( KGlobalSettings::generalFont() );
00573     def = config.readFontEntry( "font", &def );
00574     m_editor->setTextFont( def );
00575 
00576     def = config.readFontEntry( "titlefont", &def );
00577     m_label->setFont( def );
00578 
00579     uint tab_size = config.readUnsignedNumEntry( "tabsize", 4 );
00580     m_editor->setTabStop( tab_size );
00581 
00582     bool indent = config.readBoolEntry( "autoindent", true );
00583     m_editor->setAutoIndentMode( indent );
00584 
00585     //do the Data Group- name, data
00586     config.setGroup( "Data" );
00587 
00588     // TODO
00589     if ( m_label->text().isEmpty() )
00590     {
00591         QString notename = config.readEntry( "name", m_configFile );
00592         m_label->setText( notename );
00593     }
00594 
00595     // do Display group - bgcolor, fgcolor, transparent
00596     config.setGroup( "Display" );
00597 
00598     // create a pallete...
00599     QColor bg = config.readColorEntry( "bgcolor", &(Qt::yellow) );
00600     QColor fg = config.readColorEntry( "fgcolor", &(Qt::black) );
00601 
00602     setColor( fg, bg );
00603     
00604     emit sigConfigChanged();
00605 }
00606 
00607 
00608 // -------------------- private methods -------------------- //
00609 
00610 void KNote::convertOldConfig()
00611 {
00612     QFile infile( m_noteDir.absFilePath( m_configFile ) );
00613 
00614     if ( infile.open( IO_ReadOnly ) )
00615     {
00616         QTextStream input( &infile );
00617 
00618         // get the name
00619         m_label->setText( input.readLine() );
00620 
00621         // get the geometry
00622         QString geo = input.readLine();
00623 
00624         int pos, data[13];
00625         int n = 0;
00626 
00627         while ( (pos = geo.find('+')) != -1 )
00628         {
00629             if( n < 13 )
00630                 data[n++] = geo.left(pos).toInt();
00631             geo.remove( 0, pos + 1 );
00632         }
00633         if ( n < 13 )
00634             data[n++] = geo.toInt();
00635 
00636         int note_desktop = data[0];
00637         if ( data[11] == 1 )
00638             note_desktop = NETWinInfo::OnAllDesktops;
00639 
00640         resize( data[3], data[4] );
00641         if ( data[1] >= 0 && data[2] >= 0 )   // just to be sure...
00642             move( data[1], data[2] );
00643 
00644         if ( data[12] & 2048 )
00645         {
00646             KWin::setState( winId(), NET::StaysOnTop | NET::SkipTaskbar );
00647             m_alwaysOnTop->setChecked( true );
00648         }
00649         else
00650             KWin::setState( winId(), NET::SkipTaskbar );
00651 
00652         // get the foreground color
00653         uint red = input.readLine().toUInt();
00654         uint green = input.readLine().toUInt();
00655         uint blue = input.readLine().toUInt();
00656         QColor bg = QColor( red, green, blue );
00657 
00658         // get the background color
00659         red = input.readLine().toUInt();
00660         green = input.readLine().toUInt();
00661         blue = input.readLine().toUInt();
00662         QColor fg = QColor( red, green, blue );
00663 
00664         setColor( fg, bg );
00665         
00666         // get the font
00667         QString fontfamily = input.readLine();
00668         if ( fontfamily.isEmpty() )
00669             fontfamily = QString( "helvetica" );
00670         uint size = input.readLine().toUInt();
00671         size = QMAX( size, 4 );
00672         uint weight = input.readLine().toUInt();
00673         bool italic = ( input.readLine().toUInt() == 1 );
00674 
00675         QFont font( fontfamily, size, weight, italic );
00676         m_label->setFont( font );
00677         m_editor->setTextFont( font );
00678 
00679         // 3d frame? Not supported yet!
00680         input.readLine();
00681 
00682         // autoindent
00683         bool indent = ( input.readLine().toUInt() == 1 );
00684         m_editor->setAutoIndentMode( indent );
00685         m_editor->setTabStop( 4 );
00686 
00687         // richtext
00688         m_editor->setTextFormat( Qt::PlainText );
00689 
00690         // hidden
00691         bool hidden = ( input.readLine().toUInt() == 1 );
00692 
00693         // show the note
00694         if ( !hidden && !isVisible() )
00695         {
00696             // HACK HACK
00697             if ( note_desktop != NETWinInfo::OnAllDesktops )
00698             {
00699                 // to avoid flicker, call this before show()
00700                 slotToDesktop( note_desktop );
00701                 show();
00702             } else {
00703                 show();
00704                 // if this is called before show(), it won't work for sticky notes!!!
00705                 slotToDesktop( note_desktop );
00706             }
00707         }
00708 
00709         // get the text
00710         while ( !input.atEnd() )
00711             m_editor->insertParagraph( input.readLine(), -1 );
00712 
00713         infile.close();
00714         infile.remove();     // TODO: success?
00715 
00716         // set the new configfile's name...
00717         for ( int i = 1; ; i++ )
00718         {
00719             m_configFile = QString( "KNote %1" ).arg(i);
00720             if ( !m_noteDir.exists( m_configFile ) )
00721                 break;
00722         }
00723 
00724         // write the new configuration
00725         KIO::NetAccess::copy(
00726             KURL( KGlobal::dirs()->findResource( "config", "knotesrc" ) ),
00727             KURL( m_noteDir.absFilePath( m_configFile ) )
00728         );
00729 
00730         saveData();
00731         saveConfig();
00732         saveDisplayConfig();
00733 
00734         // TODO: Needed? What about KConfig? This deletes everything else?
00735         KSimpleConfig config( m_noteDir.absFilePath( m_configFile ) );
00736         config.setGroup( "General" );
00737         config.writeEntry( "version", KNOTES_VERSION );
00738 
00739         config.setGroup( "Display" );
00740         config.writeEntry( "fgcolor", fg );
00741         config.writeEntry( "bgcolor", bg );
00742 
00743         config.setGroup( "Actions" );      // use the new default for this group
00744         config.writeEntry( "mail", "kmail --msg %f" );
00745 
00746         config.setGroup( "Editor" );
00747         config.writeEntry( "autoindent", indent );
00748         config.writeEntry( "richtext", false );
00749         config.writeEntry( "titlefont", font );
00750         config.writeEntry( "font", font );
00751         config.writeEntry( "tabsize", 4 );
00752         config.sync();
00753     } else
00754         kdDebug(5500) << "could not open input file" << endl;
00755 }
00756 
00757 void KNote::setColor( const QColor &fg, const QColor &bg )
00758 {
00759     QPalette newpalette = palette();
00760     newpalette.setColor( QColorGroup::Background, bg );
00761     newpalette.setColor( QColorGroup::Foreground, fg );
00762     newpalette.setColor( QColorGroup::Base,       bg ); // text background
00763     newpalette.setColor( QColorGroup::Text,       fg ); // text color
00764 
00765     // the shadow
00766     newpalette.setColor( QColorGroup::Midlight, bg.light(110) );
00767     newpalette.setColor( QColorGroup::Shadow, bg.dark(116) );
00768     newpalette.setColor( QColorGroup::Light, bg.light(180) );
00769     newpalette.setColor( QColorGroup::Dark, bg.dark(108) );
00770     setPalette( newpalette );
00771 
00772     // set the text color
00773     m_editor->setTextColor( fg );
00774 
00775     // set darker values for the label and button...
00776     m_button->setBackgroundColor( palette().active().shadow() );
00777     
00778     // to set the color of the title
00779     updateFocus();
00780 }
00781 
00782 void KNote::updateFocus()
00783 {
00784     if ( hasFocus() )
00785     {
00786         m_label->setBackgroundColor( palette().active().shadow() );
00787         m_button->show();
00788         m_editor->cornerWidget()->show();
00789     }
00790     else
00791     {
00792         m_label->setBackgroundColor( palette().active().background() );
00793         m_button->hide();
00794         m_editor->cornerWidget()->hide();
00795     }
00796 }
00797 
00798 void KNote::updateLayout()
00799 {
00800     // DAMN, Qt 3.1 still has no support for widgets with a fixed aspect ratio :-(
00801     // So we have to write our own layout manager...
00802 
00803     int headerHeight = m_label->sizeHint().height();
00804     int margin = m_editor->margin();
00805 
00806     m_button->setGeometry( 
00807                 frameRect().width() - headerHeight - 2,
00808                 frameRect().y() + 2, 
00809                 headerHeight, 
00810                 headerHeight 
00811              );
00812 
00813     m_label->setGeometry( 
00814                 frameRect().x() + 2, 
00815                 frameRect().y() + 2,
00816                 frameRect().width() - (m_button->isHidden()?0:headerHeight) - 4,
00817                 headerHeight 
00818              );
00819               
00820     m_editor->setGeometry( 
00821                 contentsRect().x(), 
00822                 contentsRect().y() + headerHeight + 2,
00823                 contentsRect().width(),
00824                 contentsRect().height() - headerHeight - 4
00825              );
00826 
00827     setMinimumSize( m_editor->cornerWidget()->width() + margin*2 + 4,
00828                     headerHeight + m_editor->cornerWidget()->height() + margin*2 + 4 );
00829 }
00830 
00831 // -------------------- protected methods -------------------- //
00832 
00833 void KNote::resizeEvent( QResizeEvent* qre )
00834 {
00835     QFrame::resizeEvent( qre );
00836     updateLayout();
00837 }
00838 
00839 void KNote::closeEvent( QCloseEvent* /*e*/ )
00840 {
00841 kdDebug(5500) << k_funcinfo << endl;
00842     slotClose();
00843 }
00844 
00845 void KNote::keyPressEvent( QKeyEvent* e )
00846 {
00847     if ( e->key() == Key_Escape )
00848         slotClose();
00849     else
00850         e->ignore();
00851 }
00852 
00853 bool KNote::event( QEvent* ev )
00854 {
00855     if ( ev->type() == QEvent::LayoutHint )
00856     {
00857         updateLayout();
00858         return true;
00859     }
00860     else
00861         return QFrame::event( ev );
00862 }
00863 
00864 bool KNote::eventFilter( QObject* o, QEvent* ev )
00865 {
00866     if ( o == m_label )
00867     {
00868         QMouseEvent* e = (QMouseEvent*)ev;
00869 
00870         if ( ev->type() == QEvent::MouseButtonDblClick )
00871             slotRename();
00872 
00873         if ( ev->type() == QEvent::MouseButtonRelease && 
00874              (e->button() == LeftButton || e->button() == MidButton) )
00875         {
00876             m_dragging = false;
00877             m_label->releaseMouse();
00878             return true;
00879         }
00880 
00881         if ( ev->type() == QEvent::MouseButtonPress &&
00882              (e->button() == LeftButton || e->button() == MidButton)) 
00883         {
00884             m_pointerOffset = e->pos();
00885             m_label->grabMouse( sizeAllCursor );
00886             
00887             e->button() == LeftButton ? raise() : lower();
00888                 
00889             return true;
00890         }
00891 
00892         if ( ev->type() == QEvent::MouseMove && m_label == mouseGrabber() )
00893         {
00894             if ( m_dragging )
00895                 move( QCursor::pos() - m_pointerOffset );
00896             else
00897             {
00898                 m_dragging = (
00899                     (e->pos().x() - m_pointerOffset.x()) *
00900                     (e->pos().x() - m_pointerOffset.x())
00901                     +
00902                     (e->pos().y() - m_pointerOffset.y()) *
00903                     (e->pos().y() - m_pointerOffset.y())   >= 9 
00904                 );
00905             }
00906             return true;
00907         }
00908 
00909         if ( m_menu && ( ev->type() == QEvent::MouseButtonPress )
00910             && ( e->button() == RightButton ) )
00911         {
00912             m_menu->popup( QCursor::pos() );
00913             return true;
00914         }
00915 
00916         return false;
00917     }
00918     
00919     if ( o == m_editor )
00920     {
00921         if ( ev->type() == QEvent::FocusOut )
00922         {
00923             if ( static_cast<QFocusEvent*>(ev)->reason() != QFocusEvent::Popup )
00924                 updateFocus();
00925             if ( m_editor->isModified() )
00926                 saveData();
00927         }
00928         else if ( ev->type() == QEvent::FocusIn )
00929             updateFocus();
00930 
00931         return false;
00932     }
00933     
00934     if ( o == m_editor->viewport() )
00935     {
00936         if ( ev->type() == QEvent::MouseButtonPress )
00937             if ( m_edit_menu && ((QMouseEvent*)ev)->button() == RightButton )
00938             {
00939                 m_edit_menu->popup( QCursor::pos() );
00940                 return true;
00941             }
00942     }
00943 
00944     return false;
00945 }
00946 
00947 #include "knote.moc"
00948 #include "knotebutton.moc"
KDE Logo
This file is part of the documentation for kdelibs Version 3.1.5.
Documentation copyright © 1996-2002 the KDE developers.
Generated on Sun Feb 15 11:40:19 2004 by doxygen 1.3.5 written by Dimitri van Heesch, © 1997-2001