khtml Library API Documentation

render_frames.cpp

00001 
00025 //#define DEBUG_LAYOUT
00026 
00027 #include "rendering/render_frames.h"
00028 #include "rendering/render_root.h"
00029 #include "html/html_baseimpl.h"
00030 #include "html/html_objectimpl.h"
00031 #include "html/htmltokenizer.h"
00032 #include "misc/htmlattrs.h"
00033 #include "xml/dom2_eventsimpl.h"
00034 #include "xml/dom_docimpl.h"
00035 #include "misc/htmltags.h"
00036 #include "khtmlview.h"
00037 #include "khtml_part.h"
00038 
00039 #include <kapplication.h>
00040 #include <kmessagebox.h>
00041 #include <kmimetype.h>
00042 #include <klocale.h>
00043 #include <kdebug.h>
00044 #include <qtimer.h>
00045 #include <qpainter.h>
00046 #include <qcursor.h>
00047 
00048 #include <assert.h>
00049 
00050 using namespace khtml;
00051 using namespace DOM;
00052 
00053 RenderFrameSet::RenderFrameSet( HTMLFrameSetElementImpl *frameSet)
00054     : RenderBox(frameSet)
00055 {
00056   // init RenderObject attributes
00057     setInline(false);
00058 
00059   for (int k = 0; k < 2; ++k) {
00060       m_gridLen[k] = -1;
00061       m_gridDelta[k] = 0;
00062       m_gridLayout[k] = 0;
00063   }
00064 
00065   m_resizing = m_clientresizing= false;
00066 
00067   m_cursor = Qt::ArrowCursor;
00068 
00069   m_hSplit = -1;
00070   m_vSplit = -1;
00071 
00072   m_hSplitVar = 0;
00073   m_vSplitVar = 0;
00074 }
00075 
00076 RenderFrameSet::~RenderFrameSet()
00077 {
00078     for (int k = 0; k < 2; ++k) {
00079         if (m_gridLayout[k]) delete [] m_gridLayout[k];
00080         if (m_gridDelta[k]) delete [] m_gridDelta[k];
00081     }
00082   if (m_hSplitVar)
00083       delete [] m_hSplitVar;
00084   if (m_vSplitVar)
00085       delete [] m_vSplitVar;
00086 }
00087 
00088 bool RenderFrameSet::nodeAtPoint(NodeInfo& info, int _x, int _y, int _tx, int _ty)
00089 {
00090     RenderBox::nodeAtPoint(info, _x, _y, _tx, _ty);
00091 
00092     bool inside = m_resizing || canResize(_x, _y);
00093 
00094     if ( inside && element() && !element()->noResize() && !info.readonly())
00095         info.setInnerNode(element());
00096 
00097     return inside || m_clientresizing;
00098 }
00099 
00100 void RenderFrameSet::layout( )
00101 {
00102     KHTMLAssert( !layouted() );
00103     KHTMLAssert( minMaxKnown() );
00104 
00105     if ( !parent()->isFrameSet() ) {
00106         KHTMLView* view = root()->view();
00107         m_width = view->visibleWidth();
00108         m_height = view->visibleHeight();
00109     }
00110 
00111 #ifdef DEBUG_LAYOUT
00112     kdDebug( 6040 ) << renderName() << "(FrameSet)::layout( ) width=" << width() << ", height=" << height() << endl;
00113 #endif
00114 
00115     int remainingLen[2];
00116     remainingLen[1] = m_width - (element()->totalCols()-1)*element()->border();
00117     if(remainingLen[1]<0) remainingLen[1]=0;
00118     remainingLen[0] = m_height - (element()->totalRows()-1)*element()->border();
00119     if(remainingLen[0]<0) remainingLen[0]=0;
00120 
00121     int availableLen[2];
00122     availableLen[0] = remainingLen[0];
00123     availableLen[1] = remainingLen[1];
00124 
00125     if (m_gridLen[0] != element()->totalRows() || m_gridLen[1] != element()->totalCols()) {
00126         // number of rows or cols changed
00127         // need to zero out the deltas
00128         m_gridLen[0] = element()->totalRows();
00129         m_gridLen[1] = element()->totalCols();
00130         for (int k = 0; k < 2; ++k) {
00131             if (m_gridDelta[k]) delete [] m_gridDelta[k];
00132             m_gridDelta[k] = new int[m_gridLen[k]];
00133             if (m_gridLayout[k]) delete [] m_gridLayout[k];
00134             m_gridLayout[k] = new int[m_gridLen[k]];
00135             for (int i = 0; i < m_gridLen[k]; ++i)
00136                 m_gridDelta[k][i] = 0;
00137         }
00138     }
00139 
00140     for (int k = 0; k < 2; ++k) {
00141         int totalRelative = 0;
00142         int totalFixed = 0;
00143         int totalPercent = 0;
00144         int countRelative = 0;
00145         int countPercent = 0;
00146         int gridLen = m_gridLen[k];
00147         int* gridDelta = m_gridDelta[k];
00148         khtml::Length* grid =  k ? element()->m_cols : element()->m_rows;
00149         int* gridLayout = m_gridLayout[k];
00150 
00151         if (grid) {
00152             // first distribute the available width for fixed rows, then handle the
00153             // percentage ones and distribute remaining over relative
00154             for(int i = 0; i< gridLen; ++i)
00155                 if (grid[i].isFixed()) {
00156                     gridLayout[i] = kMin(grid[i].value() > 0 ? grid[i].value() : 0, remainingLen[k]);
00157                     remainingLen[k] -= gridLayout[i];
00158                     totalFixed += gridLayout[i];
00159                 }
00160                 else if(grid[i].isRelative()) {
00161                     totalRelative += grid[i].value() > 1 ? grid[i].value() : 1;
00162                     countRelative++;
00163                 }
00164 
00165             for(int i = 0; i < gridLen; i++)
00166                 if(grid[i].isPercent()) {
00167                     gridLayout[i] = kMin(kMax(grid[i].width(availableLen[k]), 0), remainingLen[k]);
00168                     remainingLen[k] -= gridLayout[i];
00169                     totalPercent += grid[i].value();
00170                     countPercent++;
00171                 }
00172 
00173             assert(remainingLen[k] >= 0);
00174 
00175             if (countRelative) {
00176                 int remaining = remainingLen[k];
00177                 for (int i = 0; i < gridLen; ++i)
00178                     if (grid[i].isRelative()) {
00179                         gridLayout[i] = ((grid[i].value() > 1 ? grid[i].value() : 1) * remaining) / totalRelative;
00180                         remainingLen[k] -= gridLayout[i];
00181                     }
00182             }
00183 
00184             // distribute the rest
00185             if (remainingLen[k]) {
00186                 LengthType distributeType = countPercent ? Percent : Fixed;
00187                 int total = countPercent ? totalPercent : totalFixed;
00188                 if (!total) total = 1;
00189                 for (int i = 0; i < gridLen; ++i)
00190                     if (grid[i].type() == distributeType) {
00191                         int toAdd = (remainingLen[k] * grid[i].value()) / total;
00192                         gridLayout[i] += toAdd;
00193                     }
00194             }
00195 
00196             // now we have the final layout, distribute the delta over it
00197             bool worked = true;
00198             for (int i = 0; i < gridLen; ++i) {
00199                 if (gridLayout[i] && gridLayout[i] + gridDelta[i] <= 0)
00200                     worked = false;
00201                 gridLayout[i] += gridDelta[i];
00202             }
00203             // now the delta's broke something, undo it and reset deltas
00204             if (!worked)
00205                 for (int i = 0; i < gridLen; ++i) {
00206                     gridLayout[i] -= gridDelta[i];
00207                     gridDelta[i] = 0;
00208                 }
00209         }
00210         else
00211             gridLayout[0] = remainingLen[k];
00212     }
00213 
00214     positionFrames();
00215 
00216     RenderObject *child = firstChild();
00217     if ( !child )
00218       return;
00219 
00220     if(!m_hSplitVar && !m_vSplitVar)
00221     {
00222 #ifdef DEBUG_LAYOUT
00223         kdDebug( 6031 ) << "calculationg fixed Splitters" << endl;
00224 #endif
00225         if(!m_vSplitVar && element()->totalCols() > 1)
00226         {
00227             m_vSplitVar = new bool[element()->totalCols()];
00228             for(int i = 0; i < element()->totalCols(); i++) m_vSplitVar[i] = true;
00229         }
00230         if(!m_hSplitVar && element()->totalRows() > 1)
00231         {
00232             m_hSplitVar = new bool[element()->totalRows()];
00233             for(int i = 0; i < element()->totalRows(); i++) m_hSplitVar[i] = true;
00234         }
00235 
00236         for(int r = 0; r < element()->totalRows(); r++)
00237         {
00238             for(int c = 0; c < element()->totalCols(); c++)
00239             {
00240                 bool fixed = false;
00241 
00242                 if ( child->isFrameSet() )
00243                   fixed = static_cast<RenderFrameSet *>(child)->element()->noResize();
00244                 else
00245                   fixed = static_cast<RenderFrame *>(child)->element()->noResize();
00246 
00247                 if(fixed)
00248                 {
00249 #ifdef DEBUG_LAYOUT
00250                     kdDebug( 6031 ) << "found fixed cell " << r << "/" << c << "!" << endl;
00251 #endif
00252                     if( element()->totalCols() > 1)
00253                     {
00254                         if(c>0) m_vSplitVar[c-1] = false;
00255                         m_vSplitVar[c] = false;
00256                     }
00257                     if( element()->totalRows() > 1)
00258                     {
00259                         if(r>0) m_hSplitVar[r-1] = false;
00260                         m_hSplitVar[r] = false;
00261                     }
00262                     child = child->nextSibling();
00263                     if(!child) goto end2;
00264                 }
00265 #ifdef DEBUG_LAYOUT
00266                 else
00267                     kdDebug( 6031 ) << "not fixed: " << r << "/" << c << "!" << endl;
00268 #endif
00269             }
00270         }
00271 
00272     }
00273     RenderContainer::layout();
00274  end2:
00275     setLayouted();
00276 }
00277 
00278 void RenderFrameSet::positionFrames()
00279 {
00280   int r;
00281   int c;
00282 
00283   RenderObject *child = firstChild();
00284   if ( !child )
00285     return;
00286 
00287   //  NodeImpl *child = _first;
00288   //  if(!child) return;
00289 
00290   int yPos = 0;
00291 
00292   for(r = 0; r < element()->totalRows(); r++)
00293   {
00294     int xPos = 0;
00295     for(c = 0; c < element()->totalCols(); c++)
00296     {
00297       child->setPos( xPos, yPos );
00298 #ifdef DEBUG_LAYOUT
00299       kdDebug(6040) << "child frame at (" << xPos << "/" << yPos << ") size (" << m_gridLayout[1][c] << "/" << m_gridLayout[0][r] << ")" << endl;
00300 #endif
00301       // has to be resized and itself resize its contents
00302       if ((m_gridLayout[1][c] != child->width()) || (m_gridLayout[0][r] != child->height())) {
00303           child->setWidth( m_gridLayout[1][c] );
00304           child->setHeight( m_gridLayout[0][r] );
00305           child->setLayouted(false);
00306       child->layout();
00307       }
00308 
00309       xPos += m_gridLayout[1][c] + element()->border();
00310       child = child->nextSibling();
00311 
00312       if ( !child )
00313         return;
00314 
00315     }
00316 
00317     yPos += m_gridLayout[0][r] + element()->border();
00318   }
00319 
00320   // all the remaining frames are hidden to avoid ugly
00321   // spurious nonlayouted frames
00322   while ( child ) {
00323       child->setWidth( 0 );
00324       child->setHeight( 0 );
00325       child->setLayouted();
00326 
00327       child = child->nextSibling();
00328   }
00329 }
00330 
00331 bool RenderFrameSet::userResize( MouseEventImpl *evt )
00332 {
00333     if (!layouted()) return false;
00334 
00335   bool res = false;
00336   int _x = evt->clientX();
00337   int _y = evt->clientY();
00338 
00339   if ( !m_resizing && evt->id() == EventImpl::MOUSEMOVE_EVENT || evt->id() == EventImpl::MOUSEDOWN_EVENT )
00340   {
00341 #ifdef DEBUG_LAYOUT
00342     kdDebug( 6031 ) << "mouseEvent:check" << endl;
00343 #endif
00344 
00345     m_hSplit = -1;
00346     m_vSplit = -1;
00347     //bool resizePossible = true;
00348 
00349     // check if we're over a horizontal or vertical boundary
00350     int pos = m_gridLayout[1][0] + xPos();
00351     for(int c = 1; c < element()->totalCols(); c++)
00352     {
00353       if(_x >= pos && _x <= pos+element()->border())
00354       {
00355         if(m_vSplitVar && m_vSplitVar[c-1] == true) m_vSplit = c-1;
00356 #ifdef DEBUG_LAYOUT
00357         kdDebug( 6031 ) << "vsplit!" << endl;
00358 #endif
00359         res = true;
00360         break;
00361       }
00362       pos += m_gridLayout[1][c] + element()->border();
00363     }
00364 
00365     pos = m_gridLayout[0][0] + yPos();
00366     for(int r = 1; r < element()->totalRows(); r++)
00367     {
00368       if( _y >= pos && _y <= pos+element()->border())
00369       {
00370         if(m_hSplitVar && m_hSplitVar[r-1] == true) m_hSplit = r-1;
00371 #ifdef DEBUG_LAYOUT
00372         kdDebug( 6031 ) << "hsplitvar = " << m_hSplitVar << endl;
00373         kdDebug( 6031 ) << "hsplit!" << endl;
00374 #endif
00375         res = true;
00376         break;
00377       }
00378       pos += m_gridLayout[0][r] + element()->border();
00379     }
00380 #ifdef DEBUG_LAYOUT
00381     kdDebug( 6031 ) << m_hSplit << "/" << m_vSplit << endl;
00382 #endif
00383   }
00384 
00385 
00386   m_cursor = Qt::ArrowCursor;
00387   if(m_hSplit != -1 && m_vSplit != -1)
00388       m_cursor = Qt::SizeAllCursor;
00389   else if( m_vSplit != -1 )
00390       m_cursor = Qt::SizeHorCursor;
00391   else if( m_hSplit != -1 )
00392       m_cursor = Qt::SizeVerCursor;
00393 
00394   if(!m_resizing && evt->id() == EventImpl::MOUSEDOWN_EVENT)
00395   {
00396       setResizing(true);
00397       KApplication::setOverrideCursor(QCursor(m_cursor));
00398       m_vSplitPos = _x;
00399       m_hSplitPos = _y;
00400       m_oldpos = -1;
00401   }
00402 
00403   // ### check the resize is not going out of bounds.
00404   if(m_resizing && evt->id() == EventImpl::MOUSEUP_EVENT)
00405   {
00406     setResizing(false);
00407     KApplication::restoreOverrideCursor();
00408 
00409     if(m_vSplit != -1 )
00410     {
00411 #ifdef DEBUG_LAYOUT
00412       kdDebug( 6031 ) << "split xpos=" << _x << endl;
00413 #endif
00414       int delta = m_vSplitPos - _x;
00415       m_gridDelta[1][m_vSplit] -= delta;
00416       m_gridDelta[1][m_vSplit+1] += delta;
00417     }
00418     if(m_hSplit != -1 )
00419     {
00420 #ifdef DEBUG_LAYOUT
00421       kdDebug( 6031 ) << "split ypos=" << _y << endl;
00422 #endif
00423       int delta = m_hSplitPos - _y;
00424       m_gridDelta[0][m_hSplit] -= delta;
00425       m_gridDelta[0][m_hSplit+1] += delta;
00426     }
00427 
00428     // this just schedules the relayout
00429     // important, otherwise the moving indicator is not correctly erased
00430     setLayouted(false);
00431   }
00432 
00433   if (m_resizing || evt->id() == EventImpl::MOUSEUP_EVENT) {
00434       QPainter paint( root()->view() );
00435       paint.setPen( Qt::gray );
00436       paint.setBrush( Qt::gray );
00437       paint.setRasterOp( Qt::XorROP );
00438       QRect r(xPos(), yPos(), width(), height());
00439       const int rBord = 3;
00440       int sw = element()->border();
00441       int p = m_resizing ? (m_vSplit > -1 ? _x : _y) : -1;
00442       if (m_vSplit > -1) {
00443           if ( m_oldpos >= 0 )
00444               paint.drawRect( m_oldpos + sw/2 - rBord , r.y(),
00445                               2*rBord, r.height() );
00446           if ( p >= 0 )
00447               paint.drawRect( p  + sw/2 - rBord, r.y(), 2*rBord, r.height() );
00448       } else {
00449           if ( m_oldpos >= 0 )
00450               paint.drawRect( r.x(), m_oldpos + sw/2 - rBord,
00451                               r.width(), 2*rBord );
00452           if ( p >= 0 )
00453               paint.drawRect( r.x(), p + sw/2 - rBord, r.width(), 2*rBord );
00454       }
00455       m_oldpos = p;
00456   }
00457 
00458   return res;
00459 }
00460 
00461 void RenderFrameSet::setResizing(bool e)
00462 {
00463       m_resizing = e;
00464       for (RenderObject* p = parent(); p; p = p->parent())
00465           if (p->isFrameSet()) static_cast<RenderFrameSet*>(p)->m_clientresizing = m_resizing;
00466 }
00467 
00468 bool RenderFrameSet::canResize( int _x, int _y )
00469 {
00470     // if we're not layouted, the gridLayout doesn't contain useful data
00471     if (!layouted() || !m_gridLayout[0] || !m_gridLayout[1] ) return false;
00472 
00473     // check if we're over a horizontal or vertical boundary
00474     int pos = m_gridLayout[1][0];
00475     for(int c = 1; c < element()->totalCols(); c++)
00476         if(_x >= pos && _x <= pos+element()->border())
00477             return true;
00478 
00479     pos = m_gridLayout[0][0];
00480     for(int r = 1; r < element()->totalRows(); r++)
00481         if( _y >= pos && _y <= pos+element()->border())
00482             return true;
00483 
00484     return false;
00485 }
00486 
00487 #ifndef NDEBUG
00488 void RenderFrameSet::dump(QTextStream *stream, QString ind) const
00489 {
00490   *stream << " totalrows=" << element()->totalRows();
00491   *stream << " totalcols=" << element()->totalCols();
00492 
00493   uint i;
00494   for (i = 0; i < (uint)element()->totalRows(); i++)
00495     *stream << " hSplitvar(" << i << ")=" << m_hSplitVar[i];
00496 
00497   for (i = 0; i < (uint)element()->totalCols(); i++)
00498     *stream << " vSplitvar(" << i << ")=" << m_vSplitVar[i];
00499 
00500   RenderBox::dump(stream,ind);
00501 }
00502 #endif
00503 
00504 /**************************************************************************************/
00505 
00506 RenderPart::RenderPart(DOM::HTMLElementImpl* node)
00507     : RenderWidget(node)
00508 {
00509     // init RenderObject attributes
00510     setInline(false);
00511 }
00512 
00513 void RenderPart::setWidget( QWidget *widget )
00514 {
00515 #ifdef DEBUG_LAYOUT
00516     kdDebug(6031) << "RenderPart::setWidget()" << endl;
00517 #endif
00518     setQWidget( widget );
00519     widget->setFocusPolicy(QWidget::WheelFocus);
00520     if(widget->inherits("KHTMLView"))
00521         connect( widget, SIGNAL( cleared() ), this, SLOT( slotViewCleared() ) );
00522 
00523     setLayouted( false );
00524     setMinMaxKnown( false );
00525 
00526     // make sure the scrollbars are set correctly for restore
00527     // ### find better fix
00528     slotViewCleared();
00529 }
00530 
00531 bool RenderPart::partLoadingErrorNotify(khtml::ChildFrame *, const KURL& , const QString& )
00532 {
00533     return false;
00534 }
00535 
00536 short RenderPart::intrinsicWidth() const
00537 {
00538     return 300;
00539 }
00540 
00541 int RenderPart::intrinsicHeight() const
00542 {
00543     return 200;
00544 }
00545 
00546 void RenderPart::slotViewCleared()
00547 {
00548 }
00549 
00550 /***************************************************************************************/
00551 
00552 RenderFrame::RenderFrame( DOM::HTMLFrameElementImpl *frame )
00553     : RenderPart(frame)
00554 {
00555     setInline( false );
00556 }
00557 
00558 void RenderFrame::slotViewCleared()
00559 {
00560     if(m_widget->inherits("QScrollView")) {
00561 #ifdef DEBUG_LAYOUT
00562         kdDebug(6031) << "frame is a scrollview!" << endl;
00563 #endif
00564         QScrollView *view = static_cast<QScrollView *>(m_widget);
00565         if(!element()->frameBorder || !((static_cast<HTMLFrameSetElementImpl *>(element()->parentNode()))->frameBorder()))
00566             view->setFrameStyle(QFrame::NoFrame);
00567         view->setVScrollBarMode(element()->scrolling );
00568         view->setHScrollBarMode(element()->scrolling );
00569         if(view->inherits("KHTMLView")) {
00570 #ifdef DEBUG_LAYOUT
00571             kdDebug(6031) << "frame is a KHTMLview!" << endl;
00572 #endif
00573             KHTMLView *htmlView = static_cast<KHTMLView *>(view);
00574             if(element()->marginWidth != -1) htmlView->setMarginWidth(element()->marginWidth);
00575             if(element()->marginHeight != -1) htmlView->setMarginHeight(element()->marginHeight);
00576         }
00577     }
00578 }
00579 
00580 /****************************************************************************************/
00581 
00582 RenderPartObject::RenderPartObject( DOM::HTMLElementImpl* element )
00583     : RenderPart( element )
00584 {
00585     // init RenderObject attributes
00586     setInline(true);
00587 }
00588 
00589 void RenderPartObject::updateWidget()
00590 {
00591   QString url;
00592   QString serviceType;
00593   QStringList params;
00594   KHTMLPart *part = m_view->part();
00595 
00596   setMinMaxKnown(false);
00597   setLayouted(false);
00598 
00599   // ### this should be constant true - move iframe to somewhere else
00600   if (element()->id() == ID_OBJECT || element()->id() == ID_EMBED) {
00601 
00602       for (NodeImpl* child = element()->firstChild(); child; child=child->nextSibling()) {
00603           if ( child->id() == ID_PARAM ) {
00604               HTMLParamElementImpl *p = static_cast<HTMLParamElementImpl *>( child );
00605 
00606               QString aStr = p->name();
00607               aStr += QString::fromLatin1("=\"");
00608               aStr += p->value();
00609               aStr += QString::fromLatin1("\"");
00610               params.append(aStr);
00611           }
00612       }
00613       params.append( QString::fromLatin1("__KHTML__PLUGINEMBED=\"YES\"") );
00614       params.append( QString::fromLatin1("__KHTML__PLUGINBASEURL=\"%1\"").arg( part->url().url() ) );
00615   }
00616 
00617   if(element()->id() == ID_OBJECT) {
00618 
00619       // check for embed child object
00620       HTMLObjectElementImpl *o = static_cast<HTMLObjectElementImpl *>(element());
00621       HTMLEmbedElementImpl *embed = 0;
00622       for (NodeImpl *child = o->firstChild(); child; child = child->nextSibling())
00623           if ( child->id() == ID_EMBED ) {
00624               embed = static_cast<HTMLEmbedElementImpl *>( child );
00625               break;
00626           }
00627 
00628       params.append( QString::fromLatin1("__KHTML__CLASSID=\"%1\"").arg( o->classId ) );
00629       params.append( QString::fromLatin1("__KHTML__CODEBASE=\"%1\"").arg( o->getAttribute(ATTR_CODEBASE).string() ) );
00630       if (!o->getAttribute(ATTR_WIDTH).isEmpty())
00631           params.append( QString::fromLatin1("WIDTH=\"%1\"").arg( o->getAttribute(ATTR_WIDTH).string() ) );
00632       if (!o->getAttribute(ATTR_HEIGHT).isEmpty())
00633           params.append( QString::fromLatin1("HEIGHT=\"%1\"").arg( o->getAttribute(ATTR_HEIGHT).string() ) );
00634 
00635       if ( !embed )
00636       {
00637           url = o->url;
00638           serviceType = o->serviceType;
00639           if(serviceType.isEmpty() || serviceType.isNull()) {
00640               if(!o->classId.isEmpty()) {
00641                   // We have a clsid, means this is activex (Niko)
00642                   serviceType = "application/x-activex-handler";
00643                   url = "dummy"; // Not needed, but KHTMLPart aborts the request if empty
00644               }
00645 
00646               if(o->classId.contains(QString::fromLatin1("D27CDB6E-AE6D-11cf-96B8-444553540000"))) {
00647                   // It is ActiveX, but the nsplugin system handling
00648                   // should also work, that's why we don't override the
00649                   // serviceType with application/x-activex-handler
00650                   // but let the KTrader in khtmlpart::createPart() detect
00651                   // the user's preference: launch with activex viewer or
00652                   // with nspluginviewer (Niko)
00653                   serviceType = "application/x-shockwave-flash";
00654               }
00655               else if(o->classId.contains(QString::fromLatin1("CFCDAA03-8BE4-11cf-B84B-0020AFBBCCFA")))
00656                   serviceType = "audio/x-pn-realaudio-plugin";
00657 
00658               // TODO: add more plugins here
00659           }
00660 
00661           if((url.isEmpty() || url.isNull())) {
00662               // look for a SRC attribute in the params
00663               NodeImpl *child = o->firstChild();
00664               while ( child ) {
00665                   if ( child->id() == ID_PARAM ) {
00666                       HTMLParamElementImpl *p = static_cast<HTMLParamElementImpl *>( child );
00667 
00668                       if ( p->name().lower()==QString::fromLatin1("src") ||
00669                            p->name().lower()==QString::fromLatin1("movie") ||
00670                            p->name().lower()==QString::fromLatin1("code") )
00671                       {
00672                           url = p->value();
00673                           break;
00674                       }
00675                   }
00676                   child = child->nextSibling();
00677               }
00678           }
00679 
00680 
00681           if ( url.isEmpty() && serviceType.isEmpty() ) {
00682 #ifdef DEBUG_LAYOUT
00683               kdDebug() << "RenderPartObject::close - empty url and serverType" << endl;
00684 #endif
00685               return;
00686           }
00687           part->requestObject( this, url, serviceType, params );
00688       }
00689       else {
00690           // render embed object
00691           url = embed->url;
00692           serviceType = embed->serviceType;
00693 
00694           if ( url.isEmpty() && serviceType.isEmpty() ) {
00695 #ifdef DEBUG_LAYOUT
00696               kdDebug() << "RenderPartObject::close - empty url and serverType" << endl;
00697 #endif
00698               return;
00699           }
00700           part->requestObject( this, url, serviceType, params );
00701       }
00702       o->setLiveConnect(part->liveConnectExtension(this));
00703   }
00704   else if ( element()->id() == ID_EMBED ) {
00705 
00706       HTMLEmbedElementImpl *o = static_cast<HTMLEmbedElementImpl *>(element());
00707       url = o->url;
00708       serviceType = o->serviceType;
00709 
00710       if ( url.isEmpty() && serviceType.isEmpty() ) {
00711 #ifdef DEBUG_LAYOUT
00712           kdDebug() << "RenderPartObject::close - empty url and serverType" << endl;
00713 #endif
00714           return;
00715       }
00716       // add all attributes set on the embed object
00717       NamedAttrMapImpl* a = o->attributes();
00718       if (a) {
00719           for (unsigned long i = 0; i < a->length(); ++i) {
00720               AttributeImpl* it = a->attributeItem(i);
00721               params.append(o->getDocument()->attrName(it->id()).string() + "=\"" + it->value().string() + "\"");
00722           }
00723       }
00724       part->requestObject( this, url, serviceType, params );
00725   } else {
00726       assert(element()->id() == ID_IFRAME);
00727       HTMLIFrameElementImpl *o = static_cast<HTMLIFrameElementImpl *>(element());
00728       url = o->url.string();
00729       if( url.isEmpty()) return;
00730       KHTMLView *v = static_cast<KHTMLView *>(m_view);
00731       v->part()->requestFrame( this, url, o->name.string(), QStringList(), true );
00732   }
00733 }
00734 
00735 // ugly..
00736 void RenderPartObject::close()
00737 {
00738     if ( element()->id() == ID_OBJECT )
00739         updateWidget();
00740     RenderPart::close();
00741 }
00742 
00743 
00744 bool RenderPartObject::partLoadingErrorNotify( khtml::ChildFrame *childFrame, const KURL& url, const QString& serviceType )
00745 {
00746     KHTMLPart *part = static_cast<KHTMLView *>(m_view)->part();
00747     //kdDebug() << "RenderPartObject::partLoadingErrorNotify serviceType=" << serviceType << endl;
00748     // Check if we just tried with e.g. nsplugin
00749     // and fallback to the activexhandler if there is a classid
00750     // and a codebase, where we may download the ocx if it's missing
00751     if( serviceType != "application/x-activex-handler" && element()->id()==ID_OBJECT ) {
00752 
00753         // check for embed child object
00754         HTMLObjectElementImpl *o = static_cast<HTMLObjectElementImpl *>(element());
00755         HTMLEmbedElementImpl *embed = 0;
00756         NodeImpl *child = o->firstChild();
00757         while ( child ) {
00758             if ( child->id() == ID_EMBED )
00759                 embed = static_cast<HTMLEmbedElementImpl *>( child );
00760 
00761             child = child->nextSibling();
00762         }
00763         if( embed && !o->classId.isEmpty() &&
00764             !( static_cast<ElementImpl *>(o)->getAttribute(ATTR_CODEBASE).string() ).isEmpty() )
00765         {
00766             KParts::URLArgs args;
00767             args.serviceType = "application/x-activex-handler";
00768             if (part->requestObject( childFrame, url, args ))
00769                 return true; // success
00770         }
00771     }
00772     // Dissociate ourselves from the current event loop (to prevent crashes
00773     // due to the message box staying up)
00774     QTimer::singleShot( 0, this, SLOT( slotPartLoadingErrorNotify() ) );
00775 #if 0
00776     Tokenizer *tokenizer = static_cast<DOM::DocumentImpl *>(part->document().handle())->tokenizer();
00777     if (tokenizer) tokenizer->setOnHold( true );
00778     slotPartLoadingErrorNotify();
00779     if (tokenizer) tokenizer->setOnHold( false );
00780 #endif
00781     return false;
00782 }
00783 
00784 void RenderPartObject::slotPartLoadingErrorNotify()
00785 {
00786     // First we need to find out the servicetype - again - this code is too duplicated !
00787     HTMLEmbedElementImpl *embed = 0;
00788     QString serviceType;
00789     if( element()->id()==ID_OBJECT ) {
00790 
00791         // check for embed child object
00792         HTMLObjectElementImpl *o = static_cast<HTMLObjectElementImpl *>(element());
00793         serviceType = o->serviceType;
00794         NodeImpl *child = o->firstChild();
00795         while ( child ) {
00796             if ( child->id() == ID_EMBED )
00797                 embed = static_cast<HTMLEmbedElementImpl *>( child );
00798 
00799             child = child->nextSibling();
00800         }
00801 
00802     } else if( element()->id()==ID_EMBED ) {
00803         embed = static_cast<HTMLEmbedElementImpl *>(element());
00804     }
00805     if ( embed )
00806     serviceType = embed->serviceType;
00807 
00808     KHTMLPart *part = static_cast<KHTMLView *>(m_view)->part();
00809     KParts::BrowserExtension *ext = part->browserExtension();
00810     if( embed && !embed->pluginPage.isEmpty() && ext ) {
00811         // Prepare the mimetype to show in the question (comment if available, name as fallback)
00812         QString mimeName = serviceType;
00813         KMimeType::Ptr mime = KMimeType::mimeType(serviceType);
00814         if ( mime->name() != KMimeType::defaultMimeType() )
00815             mimeName = mime->comment();
00816 
00817         // Check if we already asked the user, for this page
00818         if (!mimeName.isEmpty() && part->docImpl() && !part->pluginPageQuestionAsked( serviceType ) )
00819         {
00820             part->setPluginPageQuestionAsked( serviceType );
00821             // Prepare the URL to show in the question (host only if http, to make it short)
00822             KURL pluginPageURL( embed->pluginPage );
00823             QString shortURL = pluginPageURL.protocol() == "http" ? pluginPageURL.host() : pluginPageURL.prettyURL();
00824             int res = KMessageBox::questionYesNo( m_view,
00825                                                   i18n("No plugin found for '%1'.\nDo you want to download one from %2?").arg(mimeName).arg(shortURL),
00826                                                   i18n("Missing Plugin"), QString::null, QString::null, QString("plugin-")+serviceType);
00827             if ( res == KMessageBox::Yes )
00828             {
00829                 // Display vendor download page
00830                 ext->createNewWindow( pluginPageURL );
00831                 return;
00832             }
00833         }
00834     }
00835 
00836     // didn't work, render alternative content.
00837  //   if ( element() && element()->id() == ID_OBJECT )
00838    //     static_cast<HTMLObjectElementImpl*>( element() )->renderAlternative();
00839 }
00840 
00841 void RenderPartObject::layout( )
00842 {
00843     KHTMLAssert( !layouted() );
00844     KHTMLAssert( minMaxKnown() );
00845 
00846     calcWidth();
00847     calcHeight();
00848 
00849     RenderPart::layout();
00850 
00851     setLayouted();
00852 }
00853 
00854 void RenderPartObject::slotViewCleared()
00855 {
00856   if(m_widget->inherits("QScrollView") ) {
00857 #ifdef DEBUG_LAYOUT
00858       kdDebug(6031) << "iframe is a scrollview!" << endl;
00859 #endif
00860       QScrollView *view = static_cast<QScrollView *>(m_widget);
00861       int frameStyle = QFrame::NoFrame;
00862       QScrollView::ScrollBarMode scroll = QScrollView::Auto;
00863       int marginw = 0;
00864       int marginh = 0;
00865       if ( element()->id() == ID_IFRAME) {
00866       HTMLIFrameElementImpl *frame = static_cast<HTMLIFrameElementImpl *>(element());
00867       if(frame->frameBorder)
00868           frameStyle = QFrame::Box;
00869       scroll = frame->scrolling;
00870       marginw = frame->marginWidth;
00871       marginh = frame->marginHeight;
00872       }
00873       view->setFrameStyle(frameStyle);
00874       view->setVScrollBarMode(scroll );
00875       view->setHScrollBarMode(scroll );
00876       if(view->inherits("KHTMLView")) {
00877 #ifdef DEBUG_LAYOUT
00878           kdDebug(6031) << "frame is a KHTMLview!" << endl;
00879 #endif
00880           KHTMLView *htmlView = static_cast<KHTMLView *>(view);
00881           htmlView->setIgnoreWheelEvents( element()->id() == ID_IFRAME );
00882           if(marginw != -1) htmlView->setMarginWidth(marginw);
00883           if(marginh != -1) htmlView->setMarginHeight(marginh);
00884         }
00885   }
00886 }
00887 
00888 #include "render_frames.moc"
KDE Logo
This file is part of the documentation for kdelibs Version 3.1.4.
Documentation copyright © 1996-2002 the KDE developers.
Generated on Sun Feb 27 22:16:39 2005 by doxygen 1.3.4 written by Dimitri van Heesch, © 1997-2001