📄 document.cpp.svn-base
字号:
{ // check if searchID is present in runningSearches if ( !d->searches.contains( searchID ) ) return; // get previous parameters for search RunningSearch * s = d->searches[ searchID ]; // unhighlight pages and inform observers about that QLinkedList< int >::iterator it = s->highlightedPages.begin(), end = s->highlightedPages.end(); for ( ; it != end; ++it ) { int pageNumber = *it; pages_vector[ pageNumber ]->deleteHighlights( searchID ); foreachObserver( notifyPageChanged( pageNumber, DocumentObserver::Highlights ) ); } // send the setup signal too (to update views that filter on matches) foreachObserver( notifySetup( pages_vector, false ) ); // remove serch from the runningSearches list and delete it d->searches.remove( searchID ); delete s;}bool KPDFDocument::continueLastSearch(){ return continueSearch( d->m_lastSearchID );}void KPDFDocument::toggleBookmark( int n ){ KPDFPage * page = ( n < (int)pages_vector.count() ) ? pages_vector[ n ] : 0; if ( page ) { page->setBookmark( !page->hasBookmark() ); foreachObserver( notifyPageChanged( n, DocumentObserver::Bookmark ) ); }}void KPDFDocument::processLink( const KPDFLink * link ){ if ( !link ) return; switch( link->linkType() ) { case KPDFLink::Goto: { const KPDFLinkGoto * go = static_cast< const KPDFLinkGoto * >( link ); d->nextDocumentViewport = go->destViewport(); // Explanation of why d->nextDocumentViewport is needed: // all openRelativeFile does is launch a signal telling we // want to open another URL, the problem is that when the file is // non local, the loading is done assynchronously so you can't // do a setViewport after the if as it was because you are doing the setViewport // on the old file and when the new arrives there is no setViewport for it and // it does not show anything // first open filename if link is pointing outside this document if ( go->isExternal() && !openRelativeFile( go->fileName() ) ) { kWarning() << "Link: Error opening '" << go->fileName() << "'." << endl; return; } else { // skip local links that point to nowhere (broken ones) if (d->nextDocumentViewport.pageNumber == -1) return; setViewport( d->nextDocumentViewport, -1, true ); d->nextDocumentViewport = DocumentViewport(); } } break; case KPDFLink::Execute: { const KPDFLinkExecute * exe = static_cast< const KPDFLinkExecute * >( link ); QString fileName = exe->fileName(); if ( fileName.endsWith( ".pdf" ) || fileName.endsWith( ".PDF" ) ) { openRelativeFile( fileName ); return; } // Albert: the only pdf i have that has that kind of link don't define // an application and use the fileName as the file to open fileName = giveAbsolutePath( fileName ); KMimeType::Ptr mime = KMimeType::findByPath( fileName ); // Check executables if ( KRun::isExecutableFile( fileName, mime->name() ) ) { // Don't have any pdf that uses this code path, just a guess on how it should work if ( !exe->parameters().isEmpty() ) { fileName = giveAbsolutePath( exe->parameters() ); mime = KMimeType::findByPath( fileName ); if ( KRun::isExecutableFile( fileName, mime->name() ) ) { // this case is a link pointing to an executable with a parameter // that also is an executable, possibly a hand-crafted pdf KMessageBox::information( 0, i18n("The pdf file is trying to execute an external application and for your safety okular does not allow that.") ); return; } } else { // this case is a link pointing to an executable with no parameters // core developers find unacceptable executing it even after asking the user KMessageBox::information( 0, i18n("The pdf file is trying to execute an external application and for your safety okular does not allow that.") ); return; } } KService::Ptr ptr = KMimeTypeTrader::self()->preferredService( mime->name(), "Application" ); if ( ptr ) { KUrl::List lst; lst.append( fileName ); KRun::run( *ptr, lst, 0 ); } else KMessageBox::information( 0, i18n( "No application found for opening file of mimetype %1.", mime->name() ) ); } break; case KPDFLink::Action: { const KPDFLinkAction * action = static_cast< const KPDFLinkAction * >( link ); switch( action->actionType() ) { case KPDFLinkAction::PageFirst: setViewportPage( 0 ); break; case KPDFLinkAction::PagePrev: if ( (*d->viewportIterator).pageNumber > 0 ) setViewportPage( (*d->viewportIterator).pageNumber - 1 ); break; case KPDFLinkAction::PageNext: if ( (*d->viewportIterator).pageNumber < (int)pages_vector.count() - 1 ) setViewportPage( (*d->viewportIterator).pageNumber + 1 ); break; case KPDFLinkAction::PageLast: setViewportPage( pages_vector.count() - 1 ); break; case KPDFLinkAction::HistoryBack: setPrevViewport(); break; case KPDFLinkAction::HistoryForward: setNextViewport(); break; case KPDFLinkAction::Quit: emit quit(); break; case KPDFLinkAction::Presentation: emit linkPresentation(); break; case KPDFLinkAction::EndPresentation: emit linkEndPresentation(); break; case KPDFLinkAction::Find: emit linkFind(); break; case KPDFLinkAction::GoToPage: emit linkGoToPage(); break; case KPDFLinkAction::Close: emit close(); break; } } break; case KPDFLink::Browse: { const KPDFLinkBrowse * browse = static_cast< const KPDFLinkBrowse * >( link ); // if the url is a mailto one, invoke mailer if ( browse->url().startsWith( "mailto:", Qt::CaseInsensitive ) ) KToolInvocation::invokeMailer( browse->url() ); else { QString url = browse->url(); // fix for #100366, documents with relative links that are the form of http:foo.pdf if (url.indexOf("http:") == 0 && url.indexOf("http://") == -1 && url.right(4) == ".pdf") { openRelativeFile(url.mid(5)); return; } // Albert: this is not a leak! // TODO: find a widget to pass as second parameter new KRun( KUrl(url), 0 ); } } break; case KPDFLink::Movie: //const KPDFLinkMovie * browse = static_cast< const KPDFLinkMovie * >( link ); // TODO this (Movie link) break; }}bool KPDFDocument::print( KPrinter &printer ){ return generator ? generator->print( printer ) : false;}void KPDFDocument::requestDone( PixmapRequest * req ){#ifndef NDEBUG if ( !generator->canGeneratePixmap( req->async ) ) kDebug() << "requestDone with generator not in READY state." << endl;#endif // [MEM] 1.1 find and remove a previous entry for the same page and id QLinkedList< AllocatedPixmap * >::iterator aIt = d->allocatedPixmapsFifo.begin(); QLinkedList< AllocatedPixmap * >::iterator aEnd = d->allocatedPixmapsFifo.end(); for ( ; aIt != aEnd; ++aIt ) if ( (*aIt)->page == req->pageNumber && (*aIt)->id == req->id ) { AllocatedPixmap * p = *aIt; d->allocatedPixmapsFifo.erase( aIt ); d->allocatedPixmapsTotalMemory -= p->memory; delete p; break; } // [MEM] 1.2 append memory allocation descriptor to the FIFO int memoryBytes = 4 * req->width * req->height; AllocatedPixmap * memoryPage = new AllocatedPixmap( req->id, req->pageNumber, memoryBytes ); d->allocatedPixmapsFifo.append( memoryPage ); d->allocatedPixmapsTotalMemory += memoryBytes; // 2. notify an observer that its pixmap changed if ( d->observers.contains( req->id ) ) d->observers[ req->id ]->notifyPageChanged( req->pageNumber, DocumentObserver::Pixmap ); // 3. delete request delete req; // 4. start a new generation if some is pending if ( !d->pixmapRequestsStack.isEmpty() ) sendGeneratorRequest();}void KPDFDocument::sendGeneratorRequest(){ // find a request PixmapRequest * request = 0; while ( !d->pixmapRequestsStack.isEmpty() && !request ) { PixmapRequest * r = d->pixmapRequestsStack.last(); if (!r) { d->pixmapRequestsStack.pop_back(); } // request only if page isn't already present or request has invalid id else if ( r->page->hasPixmap( r->id, r->width, r->height ) || r->id <= 0 || r->id >= MAX_OBSERVER_ID) { d->pixmapRequestsStack.pop_back(); delete r; } else if ( (long)r->width * (long)r->height > 20000000L ) { d->pixmapRequestsStack.pop_back(); if ( !d->warnedOutOfMemory ) { kWarning() << "Running out of memory on page " << r->pageNumber << " (" << r->width << "x" << r->height << " px);" << endl; kWarning() << "this message will be reported only once." << endl; d->warnedOutOfMemory = true; } delete r; } else request = r; } // if no request found (or already generated), return if ( !request ) return; // [MEM] preventive memory freeing int pixmapBytes = 4 * request->width * request->height; if ( pixmapBytes > (1024 * 1024) ) cleanupPixmapMemory( pixmapBytes ); // submit the request to the generator if ( generator->canGeneratePixmap( request->async ) ) { kWarning() << "sending request id=" << request->id << " " <<request->width << "x" << request->height << "@" << request->pageNumber << " async == " << request->async << endl; d->pixmapRequestsStack.removeAll ( request ); generator->generatePixmap ( request ); } else // pino (7/4/2006): set the polling interval from 10 to 30 QTimer::singleShot( 30, this, SLOT(sendGeneratorRequest()) );}void KPDFDocument::cleanupPixmapMemory( int /*sure? bytesOffset*/ ){ // [MEM] choose memory parameters based on configuration profile int clipValue = -1; int memoryToFree = -1; switch ( KpdfSettings::memoryLevel() ) { case KpdfSettings::EnumMemoryLevel::Low: memoryToFree = d->allocatedPixmapsTotalMemory; break; case KpdfSettings::EnumMemoryLevel::Normal: memoryToFree = d->allocatedPixmapsTotalMemory - getTotalMemory() / 3; clipValue = (d->allocatedPixmapsTotalMemory - getFreeMemory()) / 2; break; case KpdfSettings::EnumMemoryLevel::Aggressive: clipValue = (d->allocatedPixmapsTotalMemory - getFreeMemory()) / 2; break; } if ( clipValue > memoryToFree ) memoryToFree = clipValue; if ( memoryToFree > 0 ) { // [MEM] free memory starting from older pixmaps int pagesFreed = 0; QLinkedList< AllocatedPixmap * >::iterator pIt = d->allocatedPixmapsFifo.begin(); QLinkedList< AllocatedPixmap * >::iterator pEnd = d->allocatedPixmapsFifo.end(); while ( (pIt != pEnd) && (memoryToFree > 0) ) { AllocatedPixmap * p = *pIt; if ( d->observers[ p->id ]->canUnloadPixmap( p->page ) ) { // update internal variables pIt = d->allocatedPixmapsFifo.erase( pIt ); d->allocatedPixmapsTotalMemory -= p->memory; memoryToFree -= p->memory; pagesFreed++; // delete pixmap pages_vector[ p->page ]->deletePixmap( p->id ); // delete allocation descriptor delete p; } else ++pIt; } //p--rintf("freeMemory A:[%d -%d = %d] \n", d->allocatedPixmapsFifo.count() + pagesFreed, pagesFreed, d->allocatedPixmapsFifo.count() ); }}int KPDFDocument::getTotalMemory(){ static int cachedValue = 0; if ( cachedValue ) return cachedValue;#ifdef __linux__ // if /proc/meminfo doesn't exist, return 128MB QFile memFile( "/proc/meminfo" ); if ( !memFile.open( QIODevice::ReadOnly ) ) return (cachedValue = 134217728); // read /proc/meminfo and sum up the contents of 'MemFree', 'Buffers' // and 'Cached' fields. consider swapped memory as used memory. QTextStream readStream( &memFile ); while ( !readStream.atEnd() ) { QString entry = readStream.readLine(); if ( entry.startsWith( "MemTotal:" ) ) return (cachedValue = (1024 * entry.section( ' ', -2, -2 ).toInt())); }#endif return (cachedValue = 134217728);}int KPDFDocument::getFreeMemory(){#ifdef __linux__
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -