knotes Library API Documentation

knote.cpp

00001 /******************************************************************* 00002 KNotes -- Notes for the KDE project 00003 00004 Copyright (c) 1997-2004, 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 <qsize.h> 00023 #include <qsizegrip.h> 00024 #include <qbitmap.h> 00025 #include <qcursor.h> 00026 #include <qpainter.h> 00027 #include <qpaintdevicemetrics.h> 00028 #include <qsimplerichtext.h> 00029 #include <qobjectlist.h> 00030 00031 #include <kapplication.h> 00032 #include <kdebug.h> 00033 #include <kaction.h> 00034 #include <kstdaction.h> 00035 #include <kcombobox.h> 00036 #include <ktoolbar.h> 00037 #include <kpopupmenu.h> 00038 #include <kxmlguifactory.h> 00039 #include <kprinter.h> 00040 #include <klocale.h> 00041 #include <kstandarddirs.h> 00042 #include <ksimpleconfig.h> 00043 #include <kiconloader.h> 00044 #include <kmessagebox.h> 00045 #include <kprocess.h> 00046 #include <kinputdialog.h> 00047 #include <kmdcodec.h> 00048 #include <kglobalsettings.h> 00049 #include <kio/netaccess.h> 00050 00051 #include <libkcal/journal.h> 00052 00053 #include "knote.h" 00054 #include "knotebutton.h" 00055 #include "knoteedit.h" 00056 #include "knoteconfig.h" 00057 #include "knoteconfigdlg.h" 00058 #include "version.h" 00059 00060 #include <kwin.h> 00061 #include <netwm.h> 00062 00063 #include <fixx11h.h> 00064 00065 using namespace KCal; 00066 00067 00068 KNote::KNote( KXMLGUIBuilder* builder, QDomDocument buildDoc, Journal *j, 00069 QWidget* parent, const char* name ) 00070 : QFrame( parent, name, WStyle_Customize | WStyle_NoBorder | WDestructiveClose ), 00071 m_label( 0 ), m_button( 0 ), m_tool( 0 ), m_editor( 0 ), 00072 m_config( 0 ), m_journal( j ) 00073 { 00074 //actionCollection()->setWidget( this ); 00075 00076 // if there is no title yet, use the start date if valid 00077 // (KOrganizer's journals don't have titles but a valid start date) 00078 if ( m_journal->summary().isNull() && m_journal->dtStart().isValid() ) 00079 { 00080 QString s = KGlobal::locale()->formatDateTime( m_journal->dtStart() ); 00081 m_journal->setSummary( s ); 00082 } 00083 00084 // create the menu items for the note - not the editor... 00085 // rename, mail, print, insert date, close, delete, new note 00086 new KAction( i18n("New"), "filenew", 0, 00087 this, SIGNAL(sigRequestNewNote()), actionCollection(), "new_note" ); 00088 new KAction( i18n("Rename..."), "text", 0, 00089 this, SLOT(slotRename()), actionCollection(), "rename_note" ); 00090 new KAction( i18n("Hide"), "fileclose" , 0, 00091 this, SLOT(slotClose()), actionCollection(), "hide_note" ); 00092 new KAction( i18n("Delete"), "knotes_delete", 0, 00093 this, SLOT(slotKill()), actionCollection(), "delete_note" ); 00094 00095 new KAction( i18n("Insert Date"), "knotes_date", 0 , 00096 this, SLOT(slotInsDate()), actionCollection(), "insert_date" ); 00097 new KAction( i18n("Mail..."), "mail_send", 0, 00098 this, SLOT(slotMail()), actionCollection(), "mail_note" ); 00099 KStdAction::print( this, SLOT(slotPrint()), actionCollection(), "print_note" ); 00100 new KAction( i18n("Preferences..."), "configure", 0, 00101 this, SLOT(slotPreferences()), actionCollection(), "configure_note" ); 00102 00103 m_keepAbove = new KToggleAction( i18n("Always on Top"), "up", 0, 00104 this, SLOT(slotUpdateKeepAboveBelow()), actionCollection(), "keep_above" ); 00105 m_keepAbove->setExclusiveGroup( "keepAB" ); 00106 00107 // string freeze 00108 m_keepBelow = new KToggleAction( /*i18n("Keep Below Others")*/"", "down", 0, 00109 this, SLOT(slotUpdateKeepAboveBelow()), actionCollection(), "keep_below" ); 00110 m_keepBelow->setExclusiveGroup( "keepAB" ); 00111 00112 m_toDesktop = new KListAction( i18n("To Desktop"), 0, 00113 this, SLOT(slotPopupActionToDesktop(int)), actionCollection(), "to_desktop" ); 00114 connect( m_toDesktop->popupMenu(), SIGNAL(aboutToShow()), this, SLOT(slotUpdateDesktopActions()) ); 00115 00116 // create the note header, button and label... 00117 m_button = new KNoteButton( "knotes_close", this ); 00118 connect( m_button, SIGNAL(clicked()), this, SLOT(slotClose()) ); 00119 00120 m_label = new QLabel( this ); 00121 m_label->installEventFilter( this ); // receive events (for dragging & action menu) 00122 setName( m_journal->summary() ); // don't worry, no signals are connected at this stage yet 00123 00124 // create the note editor 00125 m_editor = new KNoteEdit( this ); 00126 m_editor->installEventFilter( this ); // receive events (for modified) 00127 m_editor->viewport()->installEventFilter( this ); 00128 00129 setDOMDocument( buildDoc ); 00130 KXMLGUIFactory factory( builder, this, "guifactory" ); 00131 factory.addClient( this ); 00132 00133 m_menu = static_cast<KPopupMenu*>(factory.container( "note_context", this )); 00134 m_edit_menu = static_cast<KPopupMenu*>(factory.container( "note_edit", this )); 00135 m_tool = static_cast<KToolBar*>(factory.container( "note_tool", this )); 00136 m_tool->reparent( this, QPoint( 0, 0 ) ); 00137 m_tool->hide(); 00138 00139 setFocusProxy( m_editor ); 00140 00141 // create the resize handle 00142 m_editor->setCornerWidget( new QSizeGrip( this ) ); 00143 uint width = m_editor->cornerWidget()->width(); 00144 uint height = m_editor->cornerWidget()->height(); 00145 QBitmap mask; 00146 mask.resize( width, height ); 00147 mask.fill( color0 ); 00148 QPointArray array; 00149 array.setPoints( 3, 0, height, width, height, width, 0 ); 00150 QPainter p; 00151 p.begin( &mask ); 00152 p.setBrush( color1 ); 00153 p.drawPolygon( array ); 00154 p.end(); 00155 m_editor->cornerWidget()->setMask( mask ); 00156 00157 // set up the look&feel of the note 00158 setMinimumSize( 20, 20 ); 00159 setFrameStyle( WinPanel | Raised ); 00160 setLineWidth( 1 ); 00161 00162 m_editor->setMargin( 5 ); 00163 m_editor->setFrameStyle( NoFrame ); 00164 m_editor->setBackgroundMode( PaletteBase ); 00165 00166 // the config file location 00167 QString configFile = KGlobal::dirs()->saveLocation( "appdata", "notes/" ); 00168 configFile += m_journal->uid(); 00169 KURL dst( configFile ); 00170 00171 // no config file yet? -> use the default display config if available 00172 // we want to write to configFile, so use "false" 00173 if ( !KIO::NetAccess::exists( dst, false, 0 ) ) 00174 { 00175 // use saveLocation since it's the user's default and not the 00176 // system's default (i.e., KNotes has to have write permission) 00177 KURL src( KGlobal::dirs()->saveLocation( "config" ) + "knotesrc" ); 00178 00179 // "fill" the config file with the default config 00180 if ( KIO::NetAccess::exists( src, true, 0 ) ) 00181 KIO::NetAccess::file_copy( src, dst, -1, true, false, 0 ); 00182 } 00183 00184 m_config = new KNoteConfig( KSharedConfig::openConfig( configFile, false, false ) ); 00185 m_config->readConfig(); 00186 m_config->setVersion( KNOTES_VERSION ); 00187 00188 // load the display configuration of the note 00189 width = m_config->width(); 00190 height = m_config->height(); 00191 resize( width, height ); 00192 00193 if ( m_config->keepAbove() ) 00194 m_keepAbove->setChecked( true ); 00195 else if ( m_config->keepBelow() ) 00196 m_keepBelow->setChecked( true ); 00197 else 00198 { 00199 m_keepAbove->setChecked( false ); 00200 m_keepBelow->setChecked( false ); 00201 } 00202 00203 // let KWin do the placement if the position is illegal 00204 const QPoint& position = m_config->position(); 00205 if ( kapp->desktop()->rect().intersects( QRect( position, QSize( width, height ) ) ) ) 00206 move( position ); // do before calling show() to avoid flicker 00207 00208 // read configuration settings... 00209 slotApplyConfig(); 00210 00211 // if this is a new note put on current desktop - we can't use defaults 00212 // in KConfig XT since only _changes_ will be stored in the config file 00213 int desktop = m_config->desktop(); 00214 if ( desktop < 0 && desktop != NETWinInfo::OnAllDesktops ) 00215 desktop = KWin::currentDesktop(); 00216 00217 // show the note if desired 00218 if ( desktop != 0 && !isVisible() ) 00219 { 00220 // HACK HACK 00221 if ( desktop != NETWinInfo::OnAllDesktops ) 00222 { 00223 // to avoid flicker, call this before show() 00224 toDesktop( desktop ); 00225 show(); 00226 } 00227 else 00228 { 00229 show(); 00230 // if this is called before show(), 00231 // it won't work for sticky notes!!! 00232 toDesktop( desktop ); 00233 } 00234 } 00235 00236 m_editor->setText( m_journal->description() ); 00237 m_editor->setModified( false ); 00238 } 00239 00240 KNote::~KNote() 00241 { 00242 delete m_config; 00243 } 00244 00245 00246 // -------------------- public slots -------------------- // 00247 00248 void KNote::slotKill( bool force ) 00249 { 00250 if ( !force && 00251 KMessageBox::warningYesNo( this, 00252 i18n("<qt>Do you really want to delete note <b>%1</b>?</qt>") 00253 .arg( m_label->text() ), 00254 i18n("Confirm Delete") ) 00255 != KMessageBox::Yes ) 00256 { 00257 return; 00258 } 00259 00260 // delete the configuration first, then the corresponding file 00261 delete m_config; 00262 m_config = 0; 00263 00264 QString configFile = KGlobal::dirs()->saveLocation( "appdata", "notes/" ); 00265 configFile += m_journal->uid(); 00266 00267 if ( !KIO::NetAccess::del( KURL(configFile), this ) ) 00268 kdError(5500) << "Can't remove the note config: " << configFile << endl; 00269 00270 emit sigKillNote( m_journal ); 00271 } 00272 00273 00274 // -------------------- public member functions -------------------- // 00275 00276 void KNote::saveData() 00277 { 00278 m_journal->setSummary( m_label->text() ); 00279 m_journal->setDescription( m_editor->text() ); 00280 00281 emit sigDataChanged(); 00282 m_editor->setModified( false ); 00283 } 00284 00285 void KNote::saveConfig() const 00286 { 00287 m_config->setWidth( width() ); 00288 m_config->setHeight( height() - (m_tool->isHidden() ? 0 : m_tool->height()) ); 00289 m_config->setPosition( pos() ); 00290 00291 NETWinInfo wm_client( qt_xdisplay(), winId(), qt_xrootwin(), NET::WMDesktop | NET::WMState ); 00292 m_config->setDesktop( wm_client.desktop() ); 00293 00294 // actually store the config on disk 00295 m_config->writeConfig(); 00296 } 00297 00298 QString KNote::noteId() const 00299 { 00300 return m_journal->uid(); 00301 } 00302 00303 QString KNote::name() const 00304 { 00305 return m_label->text(); 00306 } 00307 00308 QString KNote::text() const 00309 { 00310 return m_editor->text(); 00311 } 00312 00313 void KNote::setName( const QString& name ) 00314 { 00315 m_label->setText( name ); 00316 updateLabelAlignment(); 00317 00318 if ( m_editor ) // not called from CTOR? 00319 saveData(); 00320 00321 // set the window's name for the taskbar entry to be more helpful (#58338) 00322 NETWinInfo note_win( qt_xdisplay(), winId(), qt_xrootwin(), NET::WMDesktop ); 00323 note_win.setName( name.utf8() ); 00324 00325 emit sigNameChanged(); 00326 } 00327 00328 void KNote::setText( const QString& text ) 00329 { 00330 m_editor->setText( text ); 00331 saveData(); 00332 } 00333 00334 // FIXME KDE 4.0: remove sync(), isNew() and isModified() 00335 void KNote::sync( const QString& app ) 00336 { 00337 QByteArray sep( 1 ); 00338 sep[0] = '\0'; 00339 00340 KMD5 hash; 00341 QCString result; 00342 00343 hash.update( m_label->text().utf8() ); 00344 hash.update( sep ); 00345 hash.update( m_editor->text().utf8() ); 00346 hash.hexDigest( result ); 00347 00348 // hacky... not possible with KConfig XT 00349 KConfig *config = m_config->config(); 00350 config->setGroup( "Synchronisation" ); 00351 config->writeEntry( app, result.data() ); 00352 } 00353 00354 bool KNote::isNew( const QString& app ) const 00355 { 00356 KConfig *config = m_config->config(); 00357 config->setGroup( "Synchronisation" ); 00358 QString hash = config->readEntry( app ); 00359 return hash.isEmpty(); 00360 } 00361 00362 bool KNote::isModified( const QString& app ) const 00363 { 00364 QByteArray sep( 1 ); 00365 sep[0] = '\0'; 00366 00367 KMD5 hash; 00368 hash.update( m_label->text().utf8() ); 00369 hash.update( sep ); 00370 hash.update( m_editor->text().utf8() ); 00371 hash.hexDigest(); 00372 00373 KConfig *config = m_config->config(); 00374 config->setGroup( "Synchronisation" ); 00375 QString orig = config->readEntry( app ); 00376 00377 if ( hash.verify( orig.utf8() ) ) // returns false on error! 00378 return false; 00379 else 00380 return true; 00381 } 00382 00383 void KNote::toDesktop( int desktop ) 00384 { 00385 if ( desktop == 0 || desktop == NETWinInfo::OnAllDesktops ) 00386 KWin::setOnAllDesktops( winId(), true ); 00387 else 00388 KWin::setOnDesktop( winId(), desktop ); 00389 } 00390 00391 00392 // ------------------ private slots (menu actions) ------------------ // 00393 00394 void KNote::slotRename() 00395 { 00396 // pop up dialog to get the new name 00397 bool ok; 00398 QString newName = KInputDialog::getText( QString::null, 00399 i18n("Please enter the new name:"), m_label->text(), &ok, this ); 00400 if ( !ok ) // handle cancel 00401 return; 00402 00403 setName( newName ); 00404 } 00405 00406 void KNote::slotClose() 00407 { 00408 m_editor->clearFocus(); 00409 hide(); //just hide the note so it's still available from the dock window 00410 } 00411 00412 void KNote::slotInsDate() 00413 { 00414 m_editor->insert( KGlobal::locale()->formatDateTime(QDateTime::currentDateTime()) ); 00415 } 00416 00417 void KNote::slotPreferences() 00418 { 00419 // reuse if possible 00420 if ( KNoteConfigDlg::showDialog( noteId().utf8() ) ) 00421 return; 00422 00423 // create a new preferences dialog... 00424 KNoteConfigDlg *dialog = new KNoteConfigDlg( m_config, name(), false, this, 00425 noteId().utf8() ); 00426 connect( dialog, SIGNAL(settingsChanged()), this, SLOT(slotApplyConfig()) ); 00427 connect( this, SIGNAL(sigNameChanged()), dialog, SLOT(slotUpdateCaption()) ); 00428 dialog->show(); 00429 } 00430 00431 void KNote::slotMail() 00432 { 00433 saveData(); 00434 00435 QString msg_body = m_editor->text(); 00436 00437 // convert rich text to plain text first 00438 if ( m_editor->textFormat() == RichText ) 00439 { 00440 QTextEdit conv; 00441 conv.setTextFormat( RichText ); 00442 conv.setText( msg_body ); 00443 conv.setTextFormat( PlainText ); 00444 msg_body = conv.text(); 00445 } 00446 00447 // get the mail action command 00448 QStringList cmd_list = QStringList::split( QChar(' '), m_config->mailAction() ); 00449 00450 KProcess mail; 00451 for ( QStringList::Iterator it = cmd_list.begin(); 00452 it != cmd_list.end(); ++it ) 00453 { 00454 if ( *it == "%f" ) 00455 mail << msg_body.local8Bit(); 00456 else if ( *it == "%t" ) 00457 mail << m_label->text().local8Bit(); 00458 else 00459 mail << (*it).local8Bit(); 00460 } 00461 00462 if ( !mail.start( KProcess::DontCare ) ) 00463 KMessageBox::sorry( this, i18n("Unable to start the mail process.") ); 00464 } 00465 00466 void KNote::slotPrint() 00467 { 00468 saveData(); 00469 00470 KPrinter printer; 00471 printer.setFullPage( true ); 00472 00473 if ( printer.setup(0L, i18n("Print %1").arg(name())) ) 00474 { 00475 QPainter painter; 00476 painter.begin( &printer ); 00477 00478 const int margin = 40; // pt 00479 00480 QPaintDeviceMetrics metrics( painter.device() ); 00481 int marginX = margin * metrics.logicalDpiX() / 72; 00482 int marginY = margin * metrics.logicalDpiY() / 72; 00483 00484 QRect body( marginX, marginY, 00485 metrics.width() - marginX * 2, 00486 metrics.height() - marginY * 2 ); 00487 00488 QString content; 00489 if ( m_editor->textFormat() == PlainText ) 00490 content = QStyleSheet::convertFromPlainText( m_editor->text() ); 00491 else 00492 content = m_editor->text(); 00493 00494 QSimpleRichText text( content, m_config->font(), m_editor->context(), 00495 m_editor->styleSheet(), m_editor->mimeSourceFactory(), 00496 body.height() /*, linkColor, linkUnderline? */ ); 00497 00498 text.setWidth( &painter, body.width() ); 00499 QRect view( body ); 00500 00501 int page = 1; 00502 00503 for (;;) 00504 { 00505 text.draw( &painter, body.left(), body.top(), view, colorGroup() ); 00506 view.moveBy( 0, body.height() ); 00507 painter.translate( 0, -body.height() ); 00508 00509 // page numbers 00510 painter.setFont( m_config->font() ); 00511 painter.drawText( 00512 view.right() - painter.fontMetrics().width( QString::number( page ) ), 00513 view.bottom() + painter.fontMetrics().ascent() + 5, QString::number( page ) 00514 ); 00515 00516 if ( view.top() >= text.height() ) 00517 break; 00518 00519 printer.newPage(); 00520 page++; 00521 } 00522 00523 painter.end(); 00524 } 00525 } 00526 00527 void KNote::slotPopupActionToDesktop( int id ) 00528 { 00529 if( id > 1 ) 00530 --id; // compensate for the menu separator 00531 toDesktop( id ); 00532 } 00533 00534 00535 // ------------------ private slots (configuration) ------------------ // 00536 00537 void KNote::slotApplyConfig() 00538 { 00539 if ( m_config->richText() ) 00540 m_editor->setTextFormat( RichText ); 00541 else 00542 m_editor->setTextFormat( PlainText ); 00543 00544 m_label->setFont( m_config->titleFont() ); 00545 m_editor->setTextFont( m_config->font() ); 00546 m_editor->setTabStop( m_config->tabSize() ); 00547 m_editor->setAutoIndentMode( m_config->autoIndent() ); 00548 00549 // if called as a slot, save the text, we might have changed the 00550 // text format - otherwise the journal will not be updated 00551 if ( sender() ) 00552 saveData(); 00553 00554 setColor( m_config->fgColor(), m_config->bgColor() ); 00555 00556 updateLabelAlignment(); 00557 slotUpdateShowInTaskbar(); 00558 } 00559 00560 void KNote::slotUpdateKeepAboveBelow() 00561 { 00562 KWin::WindowInfo info( KWin::windowInfo( winId() ) ); 00563 00564 if ( m_keepAbove->isChecked() ) 00565 { 00566 m_config->setKeepAbove( true ); 00567 m_config->setKeepBelow( false ); 00568 KWin::setState( winId(), info.state() | NET::KeepAbove ); 00569 } 00570 else if ( m_keepBelow->isChecked() ) 00571 { 00572 m_config->setKeepAbove( false ); 00573 m_config->setKeepBelow( true ); 00574 KWin::setState( winId(), info.state() | NET::KeepBelow ); 00575 } 00576 else 00577 { 00578 m_config->setKeepAbove( false ); 00579 KWin::clearState( winId(), NET::KeepAbove ); 00580 00581 m_config->setKeepBelow( false ); 00582 KWin::clearState( winId(), NET::KeepBelow ); 00583 } 00584 } 00585 00586 void KNote::slotUpdateShowInTaskbar() 00587 { 00588 if ( !m_config->showInTaskbar() ) 00589 KWin::setState( winId(), KWin::windowInfo(winId()).state() | NET::SkipTaskbar ); 00590 else 00591 KWin::clearState( winId(), NET::SkipTaskbar ); 00592 } 00593 00594 void KNote::slotUpdateDesktopActions() 00595 { 00596 NETRootInfo wm_root( qt_xdisplay(), NET::NumberOfDesktops | NET::DesktopNames ); 00597 NETWinInfo wm_client( qt_xdisplay(), winId(), qt_xrootwin(), NET::WMDesktop ); 00598 00599 QStringList desktops; 00600 desktops.append( i18n("&All Desktops") ); 00601 desktops.append( QString::null ); // Separator 00602 00603 int count = wm_root.numberOfDesktops(); 00604 for ( int n = 1; n <= count; n++ ) 00605 desktops.append( QString("&%1 %2").arg( n ).arg( QString::fromUtf8(wm_root.desktopName( n )) ) ); 00606 00607 m_toDesktop->setItems( desktops ); 00608 00609 if ( wm_client.desktop() == NETWinInfo::OnAllDesktops ) 00610 m_toDesktop->setCurrentItem( 0 ); 00611 else 00612 m_toDesktop->setCurrentItem( wm_client.desktop() + 1 ); // compensate for separator (+1) 00613 } 00614 00615 00616 // -------------------- private methods -------------------- // 00617 00618 void KNote::setColor( const QColor &fg, const QColor &bg ) 00619 { 00620 QPalette newpalette = palette(); 00621 newpalette.setColor( QColorGroup::Background, bg ); 00622 newpalette.setColor( QColorGroup::Foreground, fg ); 00623 newpalette.setColor( QColorGroup::Base, bg ); // text background 00624 newpalette.setColor( QColorGroup::Text, fg ); // text color 00625 newpalette.setColor( QColorGroup::Button, bg ); 00626 00627 // the shadow 00628 newpalette.setColor( QColorGroup::Midlight, bg.light(110) ); 00629 newpalette.setColor( QColorGroup::Shadow, bg.dark(116) ); // 132 ? 00630 newpalette.setColor( QColorGroup::Light, bg.light(180) ); 00631 newpalette.setColor( QColorGroup::Dark, bg.dark(108) ); 00632 setPalette( newpalette ); 00633 00634 // set the text color 00635 m_editor->setTextColor( fg ); 00636 00637 // set darker value for the hide button... 00638 QPalette darker = palette(); 00639 darker.setColor( QColorGroup::Button, bg.dark(116) ); 00640 m_button->setPalette( darker ); 00641 00642 // to set the color of the title 00643 updateFocus(); 00644 emit sigColorChanged(); 00645 } 00646 00647 void KNote::updateLabelAlignment() 00648 { 00649 // if the name is too long to fit, left-align it, otherwise center it (#59028) 00650 QString labelText = m_label->text(); 00651 if ( m_label->fontMetrics().boundingRect( labelText ).width() > m_label->width() ) 00652 m_label->setAlignment( AlignLeft ); 00653 else 00654 m_label->setAlignment( AlignHCenter ); 00655 } 00656 00657 void KNote::updateFocus() 00658 { 00659 if ( hasFocus() ) 00660 { 00661 m_label->setBackgroundColor( palette().active().shadow() ); 00662 m_button->show(); 00663 m_editor->cornerWidget()->show(); 00664 00665 if ( m_tool->isHidden() && m_editor->textFormat() == QTextEdit::RichText ) 00666 { 00667 m_tool->show(); 00668 setGeometry( x(), y(), width(), height() + m_tool->height() ); 00669 } 00670 } 00671 else 00672 { 00673 m_label->setBackgroundColor( palette().active().background() ); 00674 m_button->hide(); 00675 m_editor->cornerWidget()->hide(); 00676 00677 if ( !m_tool->isHidden() ) 00678 { 00679 m_tool->hide(); 00680 setGeometry( x(), y(), width(), height() - m_tool->height() ); 00681 updateLayout(); // to update the minimum height 00682 } 00683 } 00684 } 00685 00686 void KNote::updateLayout() 00687 { 00688 // DAMN, Qt still has no support for widgets with a fixed aspect ratio :-( 00689 // So we have to write our own layout manager... 00690 00691 const int headerHeight = m_label->sizeHint().height(); 00692 const int toolHeight = m_tool->isHidden() ? 0 : 16; 00693 const int margin = m_editor->margin(); 00694 static const int border = 2; 00695 bool closeLeft = false; 00696 00697 m_button->setGeometry( 00698 closeLeft ? frameRect().x() + border 00699 : frameRect().width() - headerHeight - border, 00700 frameRect().y() + border, 00701 headerHeight, 00702 headerHeight 00703 ); 00704 00705 m_label->setGeometry( 00706 frameRect().x() + border + (closeLeft && !m_button->isHidden() ? headerHeight : 0), 00707 frameRect().y() + border, 00708 frameRect().width() - (m_button->isHidden() ? 0 : headerHeight) - border*2, 00709 headerHeight 00710 ); 00711 00712 m_editor->setGeometry( 00713 contentsRect().x(), 00714 contentsRect().y() + headerHeight + border, 00715 contentsRect().width(), 00716 contentsRect().height() - headerHeight - toolHeight - border*2 00717 ); 00718 00719 m_tool->setGeometry( 00720 contentsRect().x(), 00721 contentsRect().height() - 16, 00722 contentsRect().width(), 00723 16 00724 ); 00725 m_tool->setIconSize( 10 ); 00726 00727 // if there was just a way of making KComboBox adhere the toolbar height... 00728 QObjectList *list = m_tool->queryList( "KComboBox" ); 00729 QObjectListIt it( *list ); 00730 while ( it.current() != 0 && toolHeight ) 00731 { 00732 KComboBox *combo = (KComboBox *)it.current(); 00733 QFont font = combo->font(); 00734 font.setPointSize( 7 ); 00735 combo->setFont( font ); 00736 combo->setFixedHeight( m_tool->height() - 2 ); 00737 ++it; 00738 } 00739 delete list; 00740 00741 setMinimumSize( 00742 m_editor->cornerWidget()->width() + margin*2 + border*2, 00743 headerHeight + toolHeight + 00744 m_editor->cornerWidget()->height() + margin*2 + border*2 00745 ); 00746 00747 updateLabelAlignment(); 00748 } 00749 00750 // -------------------- protected methods -------------------- // 00751 00752 void KNote::showEvent( QShowEvent * ) 00753 { 00754 // KWin does not preserve these properties for hidden windows 00755 slotUpdateKeepAboveBelow(); 00756 slotUpdateShowInTaskbar(); 00757 } 00758 00759 void KNote::resizeEvent( QResizeEvent *qre ) 00760 { 00761 QFrame::resizeEvent( qre ); 00762 updateLayout(); 00763 } 00764 00765 void KNote::closeEvent( QCloseEvent * ) 00766 { 00767 slotClose(); 00768 } 00769 00770 void KNote::keyPressEvent( QKeyEvent *e ) 00771 { 00772 if ( e->key() == Key_Escape ) 00773 slotClose(); 00774 else 00775 e->ignore(); 00776 } 00777 00778 bool KNote::focusNextPrevChild( bool ) 00779 { 00780 return true; 00781 } 00782 00783 bool KNote::event( QEvent *ev ) 00784 { 00785 if ( ev->type() == QEvent::LayoutHint ) 00786 { 00787 updateLayout(); 00788 return true; 00789 } 00790 else 00791 return QFrame::event( ev ); 00792 } 00793 00794 bool KNote::eventFilter( QObject *o, QEvent *ev ) 00795 { 00796 if ( o == m_label ) 00797 { 00798 QMouseEvent *e = (QMouseEvent *)ev; 00799 00800 if ( ev->type() == QEvent::MouseButtonDblClick ) 00801 slotRename(); 00802 00803 if ( ev->type() == QEvent::MouseButtonRelease && 00804 (e->button() == LeftButton || e->button() == MidButton) ) 00805 { 00806 m_dragging = false; 00807 m_label->releaseMouse(); 00808 return true; 00809 } 00810 00811 if ( ev->type() == QEvent::MouseButtonPress && 00812 (e->button() == LeftButton || e->button() == MidButton)) 00813 { 00814 m_pointerOffset = e->pos(); 00815 m_label->grabMouse( sizeAllCursor ); 00816 00817 e->button() == LeftButton ? KWin::raiseWindow( winId() ) 00818 : KWin::lowerWindow( winId() ); 00819 00820 return true; 00821 } 00822 00823 if ( ev->type() == QEvent::MouseMove && m_label == mouseGrabber() ) 00824 { 00825 if ( m_dragging ) 00826 move( QCursor::pos() - m_pointerOffset ); 00827 else 00828 { 00829 m_dragging = ( 00830 (e->pos().x() - m_pointerOffset.x()) * 00831 (e->pos().x() - m_pointerOffset.x()) 00832 + 00833 (e->pos().y() - m_pointerOffset.y()) * 00834 (e->pos().y() - m_pointerOffset.y()) >= 9 00835 ); 00836 } 00837 return true; 00838 } 00839 00840 if ( m_menu && ( ev->type() == QEvent::MouseButtonPress ) 00841 && ( e->button() == RightButton ) ) 00842 { 00843 m_menu->popup( QCursor::pos() ); 00844 return true; 00845 } 00846 00847 return false; 00848 } 00849 00850 if ( o == m_editor ) 00851 { 00852 if ( ev->type() == QEvent::FocusOut ) 00853 { 00854 QFocusEvent *fe = static_cast<QFocusEvent *>(ev); 00855 if ( fe->reason() != QFocusEvent::Popup && fe->reason() != QFocusEvent::Mouse ) 00856 { 00857 updateFocus(); 00858 if ( m_editor->isModified() ) 00859 saveData(); 00860 } 00861 } 00862 else if ( ev->type() == QEvent::FocusIn ) 00863 updateFocus(); 00864 00865 return false; 00866 } 00867 00868 if ( o == m_editor->viewport() ) 00869 { 00870 if ( m_edit_menu && 00871 ev->type() == QEvent::MouseButtonPress && 00872 ((QMouseEvent *)ev)->button() == RightButton ) 00873 { 00874 m_edit_menu->popup( QCursor::pos() ); 00875 return true; 00876 } 00877 } 00878 00879 return false; 00880 } 00881 00882 #include "knote.moc" 00883 #include "knotebutton.moc"
KDE Logo
This file is part of the documentation for knotes Library Version 3.2.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Wed Jul 28 23:57:45 2004 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003