Commit 3ba7c536 authored by Enrico Ros's avatar Enrico Ros
Browse files

Fix preloading. It does real good now.

Fix cache deallocator. Hard avoids swapping memory or filling it up to the
limit (allocated pages are referenced in an internal add/remove FIFO).
Merged open and open_recent buttons as many users requested.
Using viewmag icon for find-as-you-type popup.
Disabled debug output. Updated todo with the roadmap to release.
- Need to audit the memory code and choose good default policies now.

svn path=/trunk/kdegraphics/kpdf/; revision=380494
parent e5d68bf1
TODO - branch version TODO - KPdf HEAD
Legend: Legend:
ADD - ADDed ADD - ADDed (new feature)
CHG - CHanGed CHG - CHanGed (existing behavior)
FIX - FIXed FIX - FIXed (bug or regression)
MRG - MeRGed from head MRG - MeRGed (code from a branch or a patch)
(*) - Some parts of this item are already done
Status:
-> 2005-01-20: Stable. Apart from a bad memory deallocation mechanism
the core is ready for a public release. Usability: needs testing.
next steps: empty the in-progress list and keep it empty until release.
In progress: In progress:
-> memory: check for alloc/dealloc dynamic loops
-> new word highlighting for searches / other highlights (on paper - enrico) -> new word highlighting for searches / other highlights (on paper - enrico)
-> mem: iterate from older pages to newest ones when freeing memory (not rand)
More items (first items will enter 'In progress list' first): More items (first items will enter 'In progress list' first):
-> display current page / total pages (with analog indicator too (progressbar/...))
maybe this can be done on a small widget at the top of the toolbox, displaying
'document' informations (pages, current pg, some metadata, etc..)
Tested a 16px ktoolbar in the left-bottom corner.. looks goos and can be used to
insert some actions that aren't so useful in the main (and bigger) toolbar
-> c00l: add scrollbar marks for bookmarks (like kate)
-> google search in the page
-> cleanup code and update README.png -> cleanup code and update README.png
-> find-as-you-type: use shortcut for 'find next' action (not the default one) -> find-as-you-type: use shortcut for 'find next' action (not the default one)
-> show Viewport in ThumbnailsList (blended/contour) -> show Viewport in ThumbnailsList (blended/contour)
...@@ -22,11 +32,6 @@ More items (first items will enter 'In progress list' first): ...@@ -22,11 +32,6 @@ More items (first items will enter 'In progress list' first):
-> move toolbar view actions in the PageView instead of the part. maybe.. or not... -> move toolbar view actions in the PageView instead of the part. maybe.. or not...
-> usability: layout 2PPV [1 2,3 4,5 6] -> [1,2 3,4 5]. add option for 'ebook' style alignment. (by Mikolaj) -> usability: layout 2PPV [1 2,3 4,5 6] -> [1,2 3,4 5]. add option for 'ebook' style alignment. (by Mikolaj)
-> usability: trigger redraw on 'filter text' on current page (by Mikolaj) -> usability: trigger redraw on 'filter text' on current page (by Mikolaj)
-> display current page / total pages (with analog indicator too (progressbar/...))
maybe this can be done on a small widget at the top of the toolbox, displaying
'document' informations (pages, current pg, some metadata, etc..).
Tested a 16px ktoolbar in the left-bottom corner.. looks goos and can be used to
insert some actions that aren't so useful in the main (and bigger) toolbar
-> abstract TextPage generation (the last xpdf dependant class!). then go dancing in the -> abstract TextPage generation (the last xpdf dependant class!). then go dancing in the
streets. streets.
-> better boomark rendering (tested a 'clip overlay' but looks bad actually) -> better boomark rendering (tested a 'clip overlay' but looks bad actually)
...@@ -50,7 +55,7 @@ More items (first items will enter 'In progress list' first): ...@@ -50,7 +55,7 @@ More items (first items will enter 'In progress list' first):
-> take care of TODOs in code -> take care of TODOs in code
-> ADD: click over image allows "save image" [60% done (activerect of type image)] -> ADD: click over image allows "save image" [60% done (activerect of type image)]
-> screen editing (annotations): framework (BR67300,BR62793) -> screen editing (annotations): framework (BR67300,BR62793)
-> screen editing (annotations): tools (BR67300) -> screen editing (annotations): tools (BR67300), yellow notes 'post-it' like
-> export all text in plain_text/html -> export all text in plain_text/html
-> extract(export?) images (have a look at ImageOutputDev.cc and pdfimages.cc from xpdf (not in our xpdf sources)) -> extract(export?) images (have a look at ImageOutputDev.cc and pdfimages.cc from xpdf (not in our xpdf sources))
-> text selection in wordprocessor style (very hard/impossible) -> text selection in wordprocessor style (very hard/impossible)
...@@ -61,6 +66,7 @@ More items (first items will enter 'In progress list' first): ...@@ -61,6 +66,7 @@ More items (first items will enter 'In progress list' first):
-> kttsd output with menu entries. speech{document/page/selection}. (patch available - enrico) -> kttsd output with menu entries. speech{document/page/selection}. (patch available - enrico)
-> kttsd alternative (1): autodetect "/dev/speech" (speechd/festival) and provide reading -> kttsd alternative (1): autodetect "/dev/speech" (speechd/festival) and provide reading
-> automatic online dictionaries / translators (BR80338) -> automatic online dictionaries / translators (BR80338)
-> core: pdf forms support
-> add OCR for building TextPages out of pure graphical (aka scanned) pages -> add OCR for building TextPages out of pure graphical (aka scanned) pages
-> rotate the whole document / individual pages -> rotate the whole document / individual pages
-> presentation: implement transitions (6/11 done) -> presentation: implement transitions (6/11 done)
...@@ -75,8 +81,13 @@ More items (first items will enter 'In progress list' first): ...@@ -75,8 +81,13 @@ More items (first items will enter 'In progress list' first):
-> use shortcuts for next and prev page even in presenatation mode (by Tobias Koenig) -> use shortcuts for next and prev page even in presenatation mode (by Tobias Koenig)
-> move some document related features from part to the document (see find, goto dialog, ...) -> move some document related features from part to the document (see find, goto dialog, ...)
-> Albert: Read pdf specification and see if paths with length = 1 are allowed, in case they are allowed see how to fix 97131 without skipping paths with length = 1 -> Albert: Read pdf specification and see if paths with length = 1 are allowed, in case they are allowed see how to fix 97131 without skipping paths with length = 1
-> tools: ruler, measure: distance, perimeter, ?area?, color picker
-> export: export to other formats keeping formatting (a dream.. except for PNG :-)
Done (newest features come first): Done (newest features come first):
-> FIX: memory unloading order and hard swap avoiding
-> CHG: open and open-recent buttons unified in Shell
-> CHG: lens icon for the find-ahead messages
-> ADD: page preloading -> ADD: page preloading
-> FIX: smarter memory management / prioritize queries -> FIX: smarter memory management / prioritize queries
-> ADD: type ahead search in pageview (type '/' then the word to search..) (JakubS) -> ADD: type ahead search in pageview (type '/' then the word to search..) (JakubS)
...@@ -150,10 +161,3 @@ Done (newest features come first): ...@@ -150,10 +161,3 @@ Done (newest features come first):
-> The branch 'kpdf_experiments' was created at this point. Code refactoring started. -> The branch 'kpdf_experiments' was created at this point. Code refactoring started.
-> ADD: Completely use xpdf code for rendering that solves most font problems (Albert) -> ADD: Completely use xpdf code for rendering that solves most font problems (Albert)
-> MRG: Replace xpdf version with lastest one (3.00) that supports PDF 1.5 (Albert) -> MRG: Replace xpdf version with lastest one (3.00) that supports PDF 1.5 (Albert)
Here comes a list of suggestions from a dot post http://dot.kde.org/1095261317 and IRC:
Tool: ruler, measure: distance, perimeter, ?area?
Tool: color picker
Annotations: yellow notes 'post-it' like
Export: export to other formats keeping formatting (a dream.. except for PNG :-)
PDF: <theICEBear> pdf forms support.... :D if at all possible
...@@ -90,7 +90,7 @@ ...@@ -90,7 +90,7 @@
<bool>false</bool> <bool>false</bool>
</property> </property>
<property name="text"> <property name="text">
<string>Link &amp;thumbnails list with the page</string> <string>Link the &amp;thumbnails with the page</string>
</property> </property>
</widget> </widget>
</grid> </grid>
......
...@@ -52,33 +52,35 @@ class KPDFDocumentPrivate ...@@ -52,33 +52,35 @@ class KPDFDocumentPrivate
QString xmlFileName; QString xmlFileName;
// observers / requests stuff // observers / requests stuff
QMap< int, class ObserverData* > observers; QMap< int, DocumentObserver * > observers;
QValueList< PixmapRequest * > pixmapRequestsStack; QValueList< PixmapRequest * > pixmapRequestsStack;
QValueList< class AllocatedPixmap * > allocatedPixmapsFifo;
int allocatedPixmapsTotalMemory;
// timers (memory checking / info saver) // timers (memory checking / info saver)
QTimer * memCheckTimer; QTimer * memCheckTimer;
QTimer * saveBookmarksTimer; QTimer * saveBookmarksTimer;
}; };
struct ObserverData struct AllocatedPixmap
{ {
// public data fields // owner of the page
DocumentObserver * instance; int id;
QMap< int, int > pageMemory; int page;
int totalMemory; int memory;
// public constructor: initialize data // public constructor: initialize data
ObserverData( DocumentObserver * obs ) : instance( obs ), totalMemory( 0 ) {}; AllocatedPixmap( int i, int p, int m ) : id( i ), page( p ), memory( m ) {};
}; };
#define foreachObserver( cmd ) {\ #define foreachObserver( cmd ) {\
QMap< int, ObserverData * >::iterator it = d->observers.begin(), end = d->observers.end();\ QMap< int, DocumentObserver * >::iterator it=d->observers.begin(), end=d->observers.end();\
for ( ; it != end ; ++ it ) { (*it)->instance-> cmd ; } } for ( ; it != end ; ++ it ) { (*it)-> cmd ; } }
KPDFDocument::KPDFDocument() KPDFDocument::KPDFDocument()
: generator( 0 ), d( new KPDFDocumentPrivate ) : generator( 0 ), d( new KPDFDocumentPrivate )
{ {
d->searchPage = -1; d->searchPage = -1;
d->allocatedPixmapsTotalMemory = 0;
d->memCheckTimer = new QTimer( this ); d->memCheckTimer = new QTimer( this );
connect( d->memCheckTimer, SIGNAL( timeout() ), this, SLOT( slotCheckMemory() ) ); connect( d->memCheckTimer, SIGNAL( timeout() ), this, SLOT( slotCheckMemory() ) );
d->saveBookmarksTimer = new QTimer( this ); d->saveBookmarksTimer = new QTimer( this );
...@@ -87,17 +89,10 @@ KPDFDocument::KPDFDocument() ...@@ -87,17 +89,10 @@ KPDFDocument::KPDFDocument()
KPDFDocument::~KPDFDocument() KPDFDocument::~KPDFDocument()
{ {
// delete generator, pages, and related stuff
closeDocument(); closeDocument();
ObserverData *o; // delete the private structure
QMap< int, ObserverData * >::iterator oIt;
while (d->observers.count() > 0)
{
oIt = d->observers.begin();
o = *oIt;
d->observers.remove(oIt);
delete o;
}
delete d; delete d;
} }
...@@ -189,29 +184,30 @@ void KPDFDocument::closeDocument() ...@@ -189,29 +184,30 @@ void KPDFDocument::closeDocument()
foreachObserver( notifySetup( QValueVector< KPDFPage * >(), true ) ); foreachObserver( notifySetup( QValueVector< KPDFPage * >(), true ) );
// delete pages and clear 'pages_vector' container // delete pages and clear 'pages_vector' container
for ( uint i = 0; i < pages_vector.count() ; i++ ) QValueVector< KPDFPage * >::iterator pIt = pages_vector.begin();
delete pages_vector[i]; QValueVector< KPDFPage * >::iterator pEnd = pages_vector.end();
for ( ; pIt != pEnd; ++pIt )
delete *pIt;
pages_vector.clear(); pages_vector.clear();
// clear memory management data // clear memory management data
QMap< int, ObserverData * >::iterator oIt = d->observers.begin(), oEnd = d->observers.end(); QValueList< AllocatedPixmap * >::iterator aIt = d->allocatedPixmapsFifo.begin();
for ( ; oIt != oEnd ; ++oIt ) QValueList< AllocatedPixmap * >::iterator aEnd = d->allocatedPixmapsFifo.end();
{ for ( ; aIt != aEnd; ++aIt )
ObserverData * observerData = *oIt; delete *aIt;
observerData->pageMemory.clear(); d->allocatedPixmapsFifo.clear();
observerData->totalMemory = 0;
}
// reset internal variables // reset internal variables
d->viewport = DocumentViewport(); d->viewport = DocumentViewport();
d->searchPage = -1; d->searchPage = -1;
d->allocatedPixmapsTotalMemory = 0;
} }
void KPDFDocument::addObserver( DocumentObserver * pObserver ) void KPDFDocument::addObserver( DocumentObserver * pObserver )
{ {
// keep the pointer to the observer in a map // keep the pointer to the observer in a map
d->observers[ pObserver->observerId() ] = new ObserverData( pObserver ); d->observers[ pObserver->observerId() ] = pObserver;
// if the observer is added while a document is already opened, tell it // if the observer is added while a document is already opened, tell it
if ( !pages_vector.isEmpty() ) if ( !pages_vector.isEmpty() )
...@@ -229,8 +225,7 @@ void KPDFDocument::removeObserver( DocumentObserver * pObserver ) ...@@ -229,8 +225,7 @@ void KPDFDocument::removeObserver( DocumentObserver * pObserver )
for ( ; it != end; ++it ) for ( ; it != end; ++it )
(*it)->deletePixmap( observerId ); (*it)->deletePixmap( observerId );
// delete observer storage info // delete observer entry from the map
delete d->observers[ observerId ];
d->observers.remove( observerId ); d->observers.remove( observerId );
} }
} }
...@@ -318,8 +313,6 @@ void KPDFDocument::requestPixmaps( const QValueList< PixmapRequest * > & request ...@@ -318,8 +313,6 @@ void KPDFDocument::requestPixmaps( const QValueList< PixmapRequest * > & request
// 2. [ADD TO STACK] add requests to stack // 2. [ADD TO STACK] add requests to stack
bool threadingDisabled = !Settings::enableThreading(); bool threadingDisabled = !Settings::enableThreading();
bool preloadDisabled = threadingDisabled ||
Settings::memoryLevel() == Settings::EnumMemoryLevel::Low;
QValueList< PixmapRequest * >::const_iterator rIt = requests.begin(), rEnd = requests.end(); QValueList< PixmapRequest * >::const_iterator rIt = requests.begin(), rEnd = requests.end();
for ( ; rIt != rEnd; ++rIt ) for ( ; rIt != rEnd; ++rIt )
{ {
...@@ -403,10 +396,29 @@ void KPDFDocument::setViewport( const DocumentViewport & viewport, int id ) ...@@ -403,10 +396,29 @@ void KPDFDocument::setViewport( const DocumentViewport & viewport, int id )
d->viewport = viewport; d->viewport = viewport;
// notify change to all other (different from id) viewports // notify change to all other (different from id) viewports
QMap< int, ObserverData * >::iterator it = d->observers.begin(), end = d->observers.end(); QMap< int, DocumentObserver * >::iterator it = d->observers.begin(), end = d->observers.end();
for ( ; it != end ; ++ it ) for ( ; it != end ; ++ it )
if ( it.key() != id ) if ( it.key() != id )
(*it)->instance->notifyViewportChanged(); (*it)->notifyViewportChanged();
/* [MEM] raise position of currently viewed page in allocation queue
if ( d->allocatedPixmapsFifo.count() > 1 )
{
QValueList< AllocatedPixmap * >::iterator aIt = d->allocatedPixmapsFifo.begin();
QValueList< AllocatedPixmap * >::iterator aLast = d->allocatedPixmapsFifo.end();
--aLast;
while ( aIt != aLast )
{
if ( (*aIt)->page == viewport.pageNumber )
{
d->allocatedPixmapsFifo.append( *aIt );
aIt = d->allocatedPixmapsFifo.remove( aIt );
p--rintf("%d raised prio of %d %d\n",d->allocatedPixmapsFifo.count(), (*aIt)->id, (*aIt)->page);
}
else
++aIt;
}
}*/
} }
bool KPDFDocument::findText( const QString & string, bool keepCase, bool findAhead ) bool KPDFDocument::findText( const QString & string, bool keepCase, bool findAhead )
...@@ -635,21 +647,42 @@ bool KPDFDocument::print( KPrinter &printer ) ...@@ -635,21 +647,42 @@ bool KPDFDocument::print( KPrinter &printer )
return generator ? generator->print( printer ) : false; return generator ? generator->print( printer ) : false;
} }
void KPDFDocument::requestDone( PixmapRequest * req ) //FIXME void KPDFDocument::requestDone( PixmapRequest * req )
{ {
// notify an observer that its pixmap changed
if ( d->observers.contains( req->id ) )
d->observers[ req->id ]->instance->notifyPageChanged( req->pageNumber, DocumentObserver::Pixmap );
// delete request
delete req;
// start a new generation
#ifndef NDEBUG #ifndef NDEBUG
if ( !generator->canGeneratePixmap() ) if ( !generator->canGeneratePixmap() )
kdDebug() << "requestDone with generator not in READY state." << endl; kdDebug() << "requestDone with generator not in READY state." << endl;
#endif #endif
sendGeneratorRequest();
// [MEM] 1.1 find and remove a previous entry for the same page and id
QValueList< AllocatedPixmap * >::iterator aIt = d->allocatedPixmapsFifo.begin();
QValueList< AllocatedPixmap * >::iterator aEnd = d->allocatedPixmapsFifo.end();
for ( ; aIt != aEnd; ++aIt )
if ( (*aIt)->page == req->pageNumber && (*aIt)->id == req->id )
{
AllocatedPixmap * p = *aIt;
d->allocatedPixmapsFifo.remove( 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() void KPDFDocument::sendGeneratorRequest()
...@@ -671,81 +704,74 @@ void KPDFDocument::sendGeneratorRequest() ...@@ -671,81 +704,74 @@ void KPDFDocument::sendGeneratorRequest()
if ( !request ) if ( !request )
return; return;
// FIXME CHECK PREALLOC // [MEM] preventive memory freeing
// MEM: calc memory that should be freed to allow the new generation int pixmapBytes = 4 * request->width * request->height;
int pixmapMemory = 4 * request->width * request->height / 1024; if ( pixmapBytes > (1024 * 1024) )
// MEM: update statistics counting this pixmap cleanupMemory( pixmapBytes );
ObserverData * obs = d->observers[ request->id ];
int pageNumber = request->pageNumber;
if ( obs->pageMemory.contains( pageNumber ) )
obs->totalMemory -= obs->pageMemory[ pageNumber ];
obs->pageMemory[ pageNumber ] = pixmapMemory;
obs->totalMemory += pixmapMemory;
// MEM: cleanup
mCleanupMemory( request->id );
// submit the request to the generator // submit the request to the generator
generator->generatePixmap( request ); generator->generatePixmap( request );
} }
void KPDFDocument::mCleanupMemory( int observerId ) void KPDFDocument::cleanupMemory( int /*freeOffset*/ )
{ {
// get observer data for given id
ObserverData * obs = d->observers[ observerId ];
// choose memory parameters based on configuration profile // choose memory parameters based on configuration profile
int clipValue = 0; int clipValue = -1;
int memoryToFree = 0; int memoryToFree = -1;
switch ( Settings::memoryLevel() ) switch ( Settings::memoryLevel() )
{ {
case Settings::EnumMemoryLevel::Low: case Settings::EnumMemoryLevel::Low:
memoryToFree = obs->totalMemory; memoryToFree = d->allocatedPixmapsTotalMemory;
break; break;
case Settings::EnumMemoryLevel::Normal: case Settings::EnumMemoryLevel::Normal:
clipValue = obs->totalMemory - mFreeMemory() / 3; memoryToFree = d->allocatedPixmapsTotalMemory - getTotalMemory() / 5;
if ( observerId == THUMBNAILS_ID ) clipValue = d->allocatedPixmapsTotalMemory - getFreeMemory() / 2;
memoryToFree = obs->totalMemory - mTotalMemory() / 20;
else
memoryToFree = obs->totalMemory - mTotalMemory() / 5;
break; break;
case Settings::EnumMemoryLevel::Aggressive: case Settings::EnumMemoryLevel::Aggressive:
clipValue = obs->totalMemory - mFreeMemory() / 2; clipValue = d->allocatedPixmapsTotalMemory - getFreeMemory() / 2;
break; break;
} }
// p--rintf("T:%d TT:%d FF:%d - c:%d m:%d\n", d->allocatedPixmapsTotalMemory, getTotalMemory(), getFreeMemory(), clipValue, memoryToFree);
if ( clipValue > memoryToFree ) if ( clipValue > memoryToFree )
memoryToFree = clipValue; memoryToFree = clipValue;
if ( memoryToFree <= 0 ) if ( memoryToFree > 0 )
return; freeMemory( memoryToFree );
}
// free memory. remove older data until we free enough memory void KPDFDocument::freeMemory( int bytesToFree )
int freed = 0; {
QMap< int, int >::iterator it = obs->pageMemory.begin(), end = obs->pageMemory.end(); //kdDebug() << "Freeing: " << bytesToFree << " bytes" << endl;
while ( (it != end) && (memoryToFree > 0) ) // [MEM] free memory starting from older pixmaps
int pagesFreed = 0;
QValueList< AllocatedPixmap * >::iterator pIt = d->allocatedPixmapsFifo.begin();
QValueList< AllocatedPixmap * >::iterator pEnd = d->allocatedPixmapsFifo.end();
while ( (pIt != pEnd) && (bytesToFree > 0) )
{ {
int pageNumber = it.key(); AllocatedPixmap * p = *pIt;
if ( obs->instance->canUnloadPixmap( pageNumber ) ) if ( d->observers[ p->id ]->canUnloadPixmap( p->page ) )
{ {
// copy iterator to avoid invalidation on map->remove( it ) // update internal variables
QMap< int, int >::iterator i( it ); pIt = d->allocatedPixmapsFifo.remove( pIt );
++it; d->allocatedPixmapsTotalMemory -= p->memory;
// update mem stats bytesToFree -= p->memory;
memoryToFree -= i.data(); pagesFreed++;
obs->totalMemory -= i.data();
obs->pageMemory.remove( i );
// delete pixmap // delete pixmap
pages_vector[ pageNumber ]->deletePixmap( observerId ); pages_vector[ p->page ]->deletePixmap( p->id );
freed++; // delete allocation descriptor
delete p;
} else } else
++it; ++pIt;
} }
//kdDebug() << "Id:" << observerId << " [" << obs->totalMemory << "kB] Removed " << freed << " pages. " << obs->pageMemory.count() << " pages kept in memory." << endl;
//kdDebug() << "items: " << d->allocatedPixmapsFifo.count() << " [" << (d->allocatedPixmapsTotalMemory/1000) << "] Removed " << pagesFreed << " pages. gap: " << bytesToFree << endl;
} }
int KPDFDocument::mTotalMemory() int KPDFDocument::getTotalMemory()
{ {
static int cachedValue = 0; static int cachedValue = 0;
if ( cachedValue ) if ( cachedValue )
...@@ -755,7 +781,7 @@ int KPDFDocument::mTotalMemory() ...@@ -755,7 +781,7 @@ int KPDFDocument::mTotalMemory()
// if /proc/meminfo doesn't exist, return 128MB // if /proc/meminfo doesn't exist, return 128MB
QFile memFile( "/proc/meminfo" ); QFile memFile( "/proc/meminfo" );
if ( !memFile.open( IO_ReadOnly ) ) if ( !memFile.open( IO_ReadOnly ) )
return (cachedValue = 131072); return (cachedValue = 134217728);
// read /proc/meminfo and sum up the contents of 'MemFree', 'Buffers' // read /proc/meminfo and sum up the contents of 'MemFree', 'Buffers'
// and 'Cached' fields. consider swapped memory as used memory. // and 'Cached' fields. consider swapped memory as used memory.
...@@ -764,13 +790,13 @@ int KPDFDocument::mTotalMemory() ...@@ -764,13 +790,13 @@ int KPDFDocument::mTotalMemory()
{ {
QString entry = readStream.readLine(); QString entry = readStream.readLine();
if ( entry.startsWith( "MemTotal:" ) ) if ( entry.startsWith( "MemTotal:" ) )
return (cachedValue = entry.section( ' ', -2, -2 ).toInt()); return (cachedValue = (1024 * entry.section( ' ', -2, -2 ).toInt()));
} }
#endif #endif
return (cachedValue = 131072); return (cachedValue = 134217728);
} }
int KPDFDocument::mFreeMemory() int KPDFDocument::getFreeMemory()
{ {
#ifdef __linux__ #ifdef __linux__
// if /proc/meminfo doesn't exist, return MEMORY FULL // if /proc/meminfo doesn't exist, return MEMORY FULL
...@@ -795,7 +821,7 @@ int KPDFDocument::mFreeMemory() ...@@ -795,7 +821,7 @@ int KPDFDocument::mFreeMemory()
memoryFree -= entry.section( ' ', -2, -2 ).toInt(); memoryFree -= entry.section( ' ', -2, -2 ).toInt();
} }
memFile.close(); memFile.close();
return memoryFree; return 1024 * memoryFree;
#else #else
// tell the memory is full.. will act as in LOW profile // tell the memory is full.. will act as in LOW profile
return 0; return 0;
...@@ -982,15 +1008,10 @@ void KPDFDocument::saveDocumentInfo() const ...@@ -982,15 +1008,10 @@ void KPDFDocument::saveDocumentInfo() const
void KPDFDocument::slotCheckMemory() void KPDFDocument::slotCheckMemory()
{ {
// perform the memory check for 'free mem dependant' profiles only // [MEM] clean memory (for 'free mem dependant' profiles only)
if ( Settings::memoryLevel() == Settings::EnumMemoryLevel::Low ) if ( Settings::memoryLevel() != Settings::EnumMemoryLevel::Low &&
return; d->allocatedPixmapsTotalMemory > 1024*1024 )
cleanupMemory();
// for each observer going over 1MB of memory, invoke the manager
QMap< int, ObserverData * >::iterator it = d->observers.begin(), end = d->observers.end();
for ( ; it != end ; ++ it )
if ( (*it)->totalMemory > 1024 )
mCleanupMemory( it.key() /*observerId*/ );
} }
......
...@@ -92,9 +92,10 @@ class KPDFDocument : public QObject // only for a private slot.. ...@@ -92,9 +92,10 @@ class KPDFDocument : public QObject // only for a private slot..
private: private:
void sendGeneratorRequest(); void sendGeneratorRequest();
// memory management related functions // memory management related functions
void mCleanupMemory( int observerId ); void cleanupMemory( int bytesOffset = 0 );
int mTotalMemory();