From d344bf0d3d13e72b0ffce9383bc44d15df8a0f6e Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Wed, 23 Jun 2010 07:02:20 -0600 Subject: [PATCH 1/3] Cover browser: Set aspect ratio of covers to 3:4 instead of 2:3. Crop rather than distort covers whoose aspect ratio is different from this. Antialias the rendering of text in the central cover --- src/calibre/gui2/pictureflow/pictureflow.cpp | 88 ++++++-------------- src/calibre/gui2/pictureflow/pictureflow.h | 11 --- src/calibre/gui2/pictureflow/pictureflow.sip | 4 - 3 files changed, 27 insertions(+), 76 deletions(-) diff --git a/src/calibre/gui2/pictureflow/pictureflow.cpp b/src/calibre/gui2/pictureflow/pictureflow.cpp index d1434e763c..a100f60e75 100644 --- a/src/calibre/gui2/pictureflow/pictureflow.cpp +++ b/src/calibre/gui2/pictureflow/pictureflow.cpp @@ -75,10 +75,6 @@ #include -// uncomment this to enable bilinear filtering for texture mapping -// gives much better rendering, at the cost of memory space -// #define PICTUREFLOW_BILINEAR_FILTER - // for fixed-point arithmetic, we need minimum 32-bit long // long long (64-bit) might be useful for multiplication and division typedef long PFreal; @@ -376,7 +372,6 @@ private: int slideWidth; int slideHeight; int fontSize; - int zoom; int queueLength; int centerIndex; @@ -401,6 +396,7 @@ private: void recalc(int w, int h); QRect renderSlide(const SlideInfo &slide, int alpha=256, int col1=-1, int col=-1); + QRect renderCenterSlide(const SlideInfo &slide); QImage* surface(int slideIndex); void triggerRender(); void resetSlides(); @@ -414,7 +410,6 @@ PictureFlowPrivate::PictureFlowPrivate(PictureFlow* w, int queueLength_) slideWidth = 200; slideHeight = 200; fontSize = 10; - zoom = 100; centerIndex = 0; queueLength = queueLength_; @@ -464,21 +459,6 @@ void PictureFlowPrivate::setSlideSize(QSize size) triggerRender(); } -int PictureFlowPrivate::zoomFactor() const -{ - return zoom; -} - -void PictureFlowPrivate::setZoomFactor(int z) -{ - if(z <= 0) - return; - - zoom = z; - recalc(buffer.width(), buffer.height()); - triggerRender(); -} - QImage PictureFlowPrivate::slide(int index) const { return slideImages->image(index); @@ -554,7 +534,8 @@ void PictureFlowPrivate::resize(int w, int h) if (w < 10) w = 10; if (h < 10) h = 10; slideHeight = int(float(h)/REFLECTION_FACTOR); - slideWidth = int(float(slideHeight) * 2/3.); + slideWidth = int(float(slideHeight) * 3./4.); + //qDebug() << slideHeight << "x" << slideWidth; fontSize = MAX(int(h/15.), 12); recalc(w, h); resetSlides(); @@ -595,15 +576,12 @@ void PictureFlowPrivate::resetSlides() } } -#define BILINEAR_STRETCH_HOR 4 -#define BILINEAR_STRETCH_VER 4 - static QImage prepareSurface(QImage img, int w, int h) { Qt::TransformationMode mode = Qt::SmoothTransformation; - img = img.scaled(w, h, Qt::IgnoreAspectRatio, mode); + img = img.scaled(w, h, Qt::KeepAspectRatioByExpanding, mode); - // slightly larger, to accomodate for the reflection + // slightly larger, to accommodate for the reflection int hs = int(h * REFLECTION_FACTOR); int hofs = 0; @@ -633,12 +611,6 @@ static QImage prepareSurface(QImage img, int w, int h) result.setPixel(h+hofs+y, x, qRgb(r, g, b)); } -#ifdef PICTUREFLOW_BILINEAR_FILTER - int hh = BILINEAR_STRETCH_VER*hs; - int ww = BILINEAR_STRETCH_HOR*w; - result = result.scaled(hh, ww, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); -#endif - return result; } @@ -699,8 +671,12 @@ void PictureFlowPrivate::render() int nleft = leftSlides.count(); int nright = rightSlides.count(); + QRect r; - QRect r = renderSlide(centerSlide); + if (step == 0) + r = renderCenterSlide(centerSlide); + else + r = renderSlide(centerSlide); int c1 = r.left(); int c2 = r.right(); @@ -813,7 +789,23 @@ static inline uint BYTE_MUL_RGB16_32(uint x, uint a) { return t; } +QRect PictureFlowPrivate::renderCenterSlide(const SlideInfo &slide) { + QImage* src = surface(slide.slideIndex); + if(!src) + return QRect(); + int sw = src->height(); + int sh = src->width(); + int h = buffer.height(); + QRect rect(buffer.width()/2 - sw/2, 0, sw, h-1); + int left = rect.left(); + + for(int x = 0; x < sh-1; x++) + for(int y = 0; y < sw; y++) + buffer.setPixel(left + y, 1+x, src->pixel(x, y)); + + return rect; +} // Renders a slide to offscreen buffer. Returns a rect of the rendered area. // alpha=256 means normal, alpha=0 is fully black, alpha=128 half transparent // col1 and col2 limit the column for rendering. @@ -826,13 +818,8 @@ int col1, int col2) QRect rect(0, 0, 0, 0); -#ifdef PICTUREFLOW_BILINEAR_FILTER - int sw = src->height() / BILINEAR_STRETCH_HOR; - int sh = src->width() / BILINEAR_STRETCH_VER; -#else int sw = src->height(); int sh = src->width(); -#endif int h = buffer.height(); int w = buffer.width(); @@ -848,7 +835,7 @@ int col1, int col2) col1 = qMin(col1, w-1); col2 = qMin(col2, w-1); - int distance = h * 100 / zoom; + int distance = h; PFreal sdx = fcos(slide.angle); PFreal sdy = fsin(slide.angle); PFreal xs = slide.cx - slideWidth * sdx/2; @@ -878,15 +865,9 @@ int col1, int col2) PFreal hitx = fmul(dist, rays[x]); PFreal hitdist = fdiv(hitx - slide.cx, sdx); -#ifdef PICTUREFLOW_BILINEAR_FILTER - int column = sw*BILINEAR_STRETCH_HOR/2 + (hitdist*BILINEAR_STRETCH_HOR >> PFREAL_SHIFT); - if(column >= sw*BILINEAR_STRETCH_HOR) - break; -#else int column = sw/2 + (hitdist >> PFREAL_SHIFT); if(column >= sw) break; -#endif if(column < 0) continue; @@ -901,13 +882,8 @@ int col1, int col2) QRgb565* pixel2 = (QRgb565*)(buffer.scanLine(y2)) + x; int pixelstep = pixel2 - pixel1; -#ifdef PICTUREFLOW_BILINEAR_FILTER - int center = (sh*BILINEAR_STRETCH_VER/2); - int dy = dist*BILINEAR_STRETCH_VER / h; -#else int center = sh/2; int dy = dist / h; -#endif int p1 = center*PFREAL_ONE - dy/2; int p2 = center*PFREAL_ONE + dy/2; @@ -1155,16 +1131,6 @@ void PictureFlow::setSlideSize(QSize size) d->setSlideSize(size); } -int PictureFlow::zoomFactor() const -{ - return d->zoomFactor(); -} - -void PictureFlow::setZoomFactor(int z) -{ - d->setZoomFactor(z); -} - QImage PictureFlow::slide(int index) const { return d->slide(index); diff --git a/src/calibre/gui2/pictureflow/pictureflow.h b/src/calibre/gui2/pictureflow/pictureflow.h index 8cce025180..13477a8771 100644 --- a/src/calibre/gui2/pictureflow/pictureflow.h +++ b/src/calibre/gui2/pictureflow/pictureflow.h @@ -91,7 +91,6 @@ Q_OBJECT Q_PROPERTY(int currentSlide READ currentSlide WRITE setCurrentSlide) Q_PROPERTY(QSize slideSize READ slideSize WRITE setSlideSize) - Q_PROPERTY(int zoomFactor READ zoomFactor WRITE setZoomFactor) public: /*! @@ -120,16 +119,6 @@ public: */ void setSlideSize(QSize size); - /*! - Sets the zoom factor (in percent). - */ - void setZoomFactor(int zoom); - - /*! - Returns the zoom factor (in percent). - */ - int zoomFactor() const; - /*! Clears any caches held to free up memory */ diff --git a/src/calibre/gui2/pictureflow/pictureflow.sip b/src/calibre/gui2/pictureflow/pictureflow.sip index 9202dd8ad5..f7ba12cee7 100644 --- a/src/calibre/gui2/pictureflow/pictureflow.sip +++ b/src/calibre/gui2/pictureflow/pictureflow.sip @@ -40,10 +40,6 @@ public : void setSlideSize(QSize size); - void setZoomFactor(int zoom); - - int zoomFactor() const; - void clearCaches(); virtual QImage slide(int index) const; From 44be78af3d326e88ad22053191cebddff09a534e Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Wed, 23 Jun 2010 08:23:34 -0600 Subject: [PATCH 2/3] Allow calibredb ot set series index for series type custom columns --- src/calibre/gui2/library/models.py | 13 ++---------- src/calibre/library/caches.py | 8 +++---- src/calibre/library/cli.py | 30 +++++++++++++++++++++++---- src/calibre/library/custom_columns.py | 4 ++-- 4 files changed, 34 insertions(+), 21 deletions(-) diff --git a/src/calibre/gui2/library/models.py b/src/calibre/gui2/library/models.py index 435b5c4c07..debdaa4151 100644 --- a/src/calibre/gui2/library/models.py +++ b/src/calibre/gui2/library/models.py @@ -21,6 +21,7 @@ from calibre.utils.date import dt_factory, qt_to_dt, isoformat from calibre.ebooks.metadata.meta import set_metadata as _set_metadata from calibre.utils.search_query_parser import SearchQueryParser from calibre.library.caches import _match, CONTAINS_MATCH, EQUALS_MATCH, REGEXP_MATCH +from calibre.library.cli import parse_series_string from calibre import strftime, isbytestring, prepare_string_for_xml from calibre.constants import filesystem_encoding from calibre.gui2.library import DEFAULT_SORT @@ -708,17 +709,7 @@ class BooksModel(QAbstractTableModel): # {{{ return False val = qt_to_dt(val, as_utc=False) elif typ == 'series': - val = unicode(value.toString()).strip() - pat = re.compile(r'\[([.0-9]+)\]') - match = pat.search(val) - if match is not None: - val = pat.sub('', val).strip() - s_index = float(match.group(1)) - elif val: - if tweaks['series_index_auto_increment'] == 'next': - s_index = self.db.get_next_cc_series_num_for(val, label=label) - else: - s_index = 1.0 + val, s_index = parse_series_string(self.db, label, value.toString()) self.db.set_custom(self.db.id(row), val, extra=s_index, label=label, num=None, append=False, notify=True) return True diff --git a/src/calibre/library/caches.py b/src/calibre/library/caches.py index d4afaabcdc..06cf07bb67 100644 --- a/src/calibre/library/caches.py +++ b/src/calibre/library/caches.py @@ -620,6 +620,10 @@ class ResultCache(SearchQueryParser): elif field == 'title': field = 'sort' elif field == 'authors': field = 'author_sort' as_string = field not in ('size', 'rating', 'timestamp') + + if self.first_sort: + subsort = True + self.first_sort = False if self.field_metadata[field]['is_custom']: if self.field_metadata[field]['datatype'] == 'series': fcmp = functools.partial(self.seriescmp, @@ -638,10 +642,6 @@ class ResultCache(SearchQueryParser): else: fcmp = functools.partial(self.cmp, self.FIELD_MAP[field], subsort=subsort, asstr=as_string) - - if self.first_sort: - subsort = True - self.first_sort = False self._map.sort(cmp=fcmp, reverse=not ascending) self._map_filtered = [id for id in self._map if id in self._map_filtered] diff --git a/src/calibre/library/cli.py b/src/calibre/library/cli.py index 3f71c98238..058b879b55 100644 --- a/src/calibre/library/cli.py +++ b/src/calibre/library/cli.py @@ -7,11 +7,11 @@ __docformat__ = 'restructuredtext en' Command line interface to the calibre database. ''' -import sys, os, cStringIO +import sys, os, cStringIO, re from textwrap import TextWrapper from calibre import terminal_controller, preferred_encoding, prints -from calibre.utils.config import OptionParser, prefs +from calibre.utils.config import OptionParser, prefs, tweaks from calibre.ebooks.metadata.meta import get_metadata from calibre.library.database2 import LibraryDatabase2 from calibre.ebooks.metadata.opf2 import OPFCreator, OPF @@ -680,9 +680,31 @@ def command_catalog(args, dbpath): # end of GR additions +def parse_series_string(db, label, value): + val = unicode(value).strip() + s_index = None + pat = re.compile(r'\[([.0-9]+)\]') + match = pat.search(val) + if match is not None: + val = pat.sub('', val).strip() + s_index = float(match.group(1)) + elif val: + if tweaks['series_index_auto_increment'] == 'next': + s_index = db.get_next_cc_series_num_for(val, label=label) + else: + s_index = 1.0 + return val, s_index + def do_set_custom(db, col, id_, val, append): - db.set_custom(id_, val, label=col, append=append) - prints('Data set to: %r'%db.get_custom(id_, label=col, index_is_id=True)) + if db.custom_column_label_map[col]['datatype'] == 'series': + val, s_index = parse_series_string(db, col, val) + db.set_custom(id_, val, extra=s_index, label=col, append=append) + prints('Data set to: %r[%4.2f]'% + (db.get_custom(id_, label=col, index_is_id=True), + db.get_custom_extra(id_, label=col, index_is_id=True))) + else: + db.set_custom(id_, val, label=col, append=append) + prints('Data set to: %r'%db.get_custom(id_, label=col, index_is_id=True)) def set_custom_option_parser(): parser = get_parser(_( diff --git a/src/calibre/library/custom_columns.py b/src/calibre/library/custom_columns.py index 52084fcda1..e039f5a817 100644 --- a/src/calibre/library/custom_columns.py +++ b/src/calibre/library/custom_columns.py @@ -308,8 +308,8 @@ class CustomColumns(object): self.conn.commit() return changed - def set_custom(self, id_, val, extra=None, label=None, num=None, - append=False, notify=True): + def set_custom(self, id_, val, label=None, num=None, + append=False, notify=True, extra=None): if label is not None: data = self.custom_column_label_map[label] if num is not None: From d44154243e6e88082b70def653771c95459c8da4 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Wed, 23 Jun 2010 08:26:26 -0600 Subject: [PATCH 3/3] SONY driver: Handle mistaken upper casing of filed names when user specifies what fields to build colelctions from --- src/calibre/devices/prs505/driver.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/calibre/devices/prs505/driver.py b/src/calibre/devices/prs505/driver.py index 5860826778..023416bdf2 100644 --- a/src/calibre/devices/prs505/driver.py +++ b/src/calibre/devices/prs505/driver.py @@ -145,7 +145,7 @@ class PRS505(USBMS): blists[i] = booklists[i] opts = self.settings() if opts.extra_customization: - collections = [x.strip() for x in + collections = [x.lower().strip() for x in opts.extra_customization.split(',')] else: collections = []