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