Changeset 11871:be57aa910cf9 in orange


Ignore:
Timestamp:
02/26/14 17:54:46 (7 weeks ago)
Author:
Ales Erjavec <ales.erjavec@…>
Branch:
default
Message:

Changed image scaling (zoom).

The final shown image size is based on the pixmap's original size
(before it was based on a 'fixed' tile size).

File:
1 edited

Legend:

Unmodified
Added
Removed
  • Orange/OrangeWidgets/Data/OWImageViewer.py

    r11867 r11871  
    44from collections import namedtuple 
    55from functools import partial 
     6from itertools import izip_longest 
    67 
    78from PyQt4.QtCore import pyqtSignal as Signal 
     
    3637        self.setCacheMode(QGraphicsItem.ItemCoordinateCache) 
    3738        self._pixmap = pixmap 
    38         self._pixmapSize = QSizeF(50, 50) 
     39        self._pixmapSize = QSizeF() 
    3940        self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) 
    4041 
     
    5354 
    5455    def pixmapSize(self): 
    55         return QSizeF(self._pixmapSize) 
     56        if self._pixmapSize.isValid(): 
     57            return QSizeF(self._pixmapSize) 
     58        else: 
     59            return QSizeF(self._pixmap.size()) 
    5660 
    5761    def sizeHint(self, which, constraint=QSizeF()): 
    5862        if which == Qt.PreferredSize: 
    59             return QSizeF(self._pixmapSize) 
     63            return self.pixmapSize() 
    6064        else: 
    6165            return QGraphicsWidget.sizeHint(self, which, constraint) 
     
    6670 
    6771        rect = self.contentsRect() 
    68         pixsize = self._pixmapSize 
     72 
     73        pixsize = self.pixmapSize() 
    6974        pixrect = QRectF(QPointF(0, 0), pixsize) 
    7075        pixrect.moveCenter(rect.center()) 
     
    112117 
    113118        self._title = None 
    114         self._size = None 
     119        self._size = QSizeF() 
    115120 
    116121        layout = QGraphicsLinearLayout(Qt.Vertical, self) 
     
    135140        self.setTitle(title) 
    136141        self.setTitleWidth(100) 
    137         self.setThumbnailSize(QSizeF(100, 100)) 
    138142 
    139143    def setPixmap(self, pixmap): 
     
    177181    def _updatePixmapSize(self): 
    178182        pixmap = self.pixmap() 
    179         if not pixmap.isNull(): 
     183        if not pixmap.isNull() and self._size.isValid(): 
    180184            pixsize = QSizeF(self.pixmap().size()) 
    181185            pixsize.scale(self._size, Qt.KeepAspectRatio) 
     
    196200        self.setLayout(layout) 
    197201 
    198         self._thumbSize = QSizeF(50, 50) 
    199  
    200     def setThumbnailSize(self, size): 
    201         if self._thumbSize != size: 
    202             self._thumbSize = QSizeF(size) 
    203             self.reflow() 
    204  
    205     def reflow(self, width=None): 
    206         if width is None: 
    207             width = self.size().width() 
     202    def setGeometry(self, geom): 
     203        super(ThumbnailWidget, self).setGeometry(geom) 
     204        self.reflow(self.size().width()) 
     205 
     206    def reflow(self, width): 
     207        if not self.layout(): 
     208            return 
    208209 
    209210        left, right, _, _ = self.getContentsMargins() 
    210211        layout = self.layout() 
    211212        width -= left + right 
    212         # thumbnail size + margins 
    213         thumbwidth = max(100, self._thumbSize.width()) + 2 * 5 
    214         spacing = layout.horizontalSpacing() 
    215  
    216         ncol = (width + spacing) // (thumbwidth + spacing) 
    217         ncol = max(ncol, 1) 
     213 
     214        hints = self._hints(Qt.PreferredSize) 
     215        widths = [max(24, h.width()) for h in hints] 
     216        ncol = self._fitncols(widths, layout.horizontalSpacing(), width) 
    218217 
    219218        if ncol == layout.columnCount(): 
     
    228227        for i, item in enumerate(items): 
    229228            layout.addItem(item, i // ncol, i % ncol) 
     229 
     230    def items(self): 
     231        layout = self.layout() 
     232        if layout: 
     233            return [layout.itemAt(i) for i in range(layout.count())] 
     234        else: 
     235            return [] 
     236 
     237    def _hints(self, which): 
     238        return [item.effectiveSizeHint(which) for item in self.items()] 
     239 
     240    def _fitncols(self, widths, spacing, constraint): 
     241        def sliced(seq, ncol): 
     242            return [seq[i:i + ncol] for i in range(0, len(seq), ncol)] 
     243 
     244        def flow_width(widths, spacing, ncol): 
     245            W = sliced(widths, ncol) 
     246            col_widths = map(max, izip_longest(*W, fillvalue=0)) 
     247            return sum(col_widths) + (ncol - 1) * spacing 
     248 
     249        ncol_best = 1 
     250        for ncol in range(2, len(widths)): 
     251            w = flow_width(widths, spacing, ncol) 
     252            if w <= constraint: 
     253                ncol_best = ncol 
     254            else: 
     255                break 
     256 
     257        return ncol_best 
    230258 
    231259 
     
    414442 
    415443    def setupScene(self): 
    416         thumbnailSize = self.pixmapSize() 
    417         thumbnailSize = QSizeF(thumbnailSize, thumbnailSize) 
    418444        self.information(0) 
    419445        self.error(0) 
     
    424450                         if not inst[attr].isSpecial()] 
    425451            widget = ThumbnailWidget() 
    426             widget.setThumbnailSize(thumbnailSize) 
    427  
    428452            layout = widget.layout() 
    429453 
     
    439463 
    440464                thumbnail.setToolTip(unicode(url.toString())) 
    441                 thumbnail.setThumbnailSize(thumbnailSize) 
    442465                thumbnail.instance = inst 
    443466                layout.addItem(thumbnail, i / 5, i % 5) 
     
    457480                        else: 
    458481                            pixmap = QPixmap.fromImage(future.result()) 
     482 
    459483                        thumb.setPixmap(pixmap) 
     484                        if not pixmap.isNull(): 
     485                            thumb.setThumbnailSize(self.pixmapSize(pixmap)) 
    460486 
    461487                        self._updateStatus(future) 
     
    466492                self.items.append(_ImageItem(thumbnail, url, future)) 
    467493 
    468             widget.setThumbnailSize(thumbnailSize) 
    469494            widget.show() 
    470495            widget.geometryChanged.connect(self._updateSceneRect) 
     496 
     497            self.info.setText("Retrieving...\n") 
    471498            self.thumbnailWidget = widget 
    472  
    473             self.info.setText("Retrieving...\n") 
    474499            self.sceneLayout = layout 
    475500 
     
    478503                     self.sceneView.verticalScrollBar().width()) 
    479504            self.thumbnailWidget.reflow(width) 
     505            self.thumbnailWidget.setPreferredWidth(width) 
    480506            self.sceneLayout.activate() 
    481507 
     
    507533        return url 
    508534 
    509     def pixmapSize(self): 
     535    def pixmapSize(self, pixmap): 
    510536        """ 
    511537        Return the preferred pixmap size based on the current `zoom` value. 
    512538        """ 
    513         return (111.0 / 11.0) * (self.zoom - 1) + 25.0 
     539        scale = 2 * self.zoom / 100.0 
     540        size = QSizeF(pixmap.size()) * scale 
     541        return size.expandedTo(QSizeF(16, 16)) 
    514542 
    515543    def clearScene(self): 
     
    531559 
    532560    def updateZoom(self): 
    533         size = self.pixmapSize() 
    534         size = QSizeF(size, size) 
    535561        for item in self.thumbnailItems(): 
    536             item.setThumbnailSize(size) 
     562            item.setThumbnailSize(self.pixmapSize(item.pixmap())) 
    537563 
    538564        if self.thumbnailWidget: 
    539             self.thumbnailWidget.setThumbnailSize(size) 
    540  
    541             width = self.sceneView.width() 
    542             width -= self.sceneView.verticalScrollBar().width() 
     565            width = (self.sceneView.width() - 
     566                     self.sceneView.verticalScrollBar().width()) 
    543567 
    544568            self.thumbnailWidget.reflow(width) 
     569            self.thumbnailWidget.setPreferredWidth(width) 
    545570 
    546571        if self.sceneLayout: 
     
    624649 
    625650    def eventFilter(self, receiver, event): 
    626         if receiver == self.sceneView and event.type() == QEvent.Resize \ 
     651        if receiver is self.sceneView and event.type() == QEvent.Resize \ 
    627652                and self.thumbnailWidget: 
    628653            width = (self.sceneView.width() - 
    629654                     self.sceneView.verticalScrollBar().width()) 
     655 
    630656            self.thumbnailWidget.reflow(width) 
     657            self.thumbnailWidget.setPreferredWidth(width) 
    631658 
    632659        return super(OWImageViewer, self).eventFilter(receiver, event) 
Note: See TracChangeset for help on using the changeset viewer.