Example #1
0
// set proper grid size for the QListView based on current view mode, icon size, and font size.
void FolderView::updateGridSize() {
  if(mode == DetailedListMode || !view)
    return;
  FolderViewListView* listView = static_cast<FolderViewListView*>(view);
  QSize icon = iconSize(mode); // size of the icon
  QFontMetrics fm = fontMetrics(); // size of current font
  QSize grid; // the final grid size
  switch(mode) {
    case IconMode:
    case ThumbnailMode: {
      // NOTE by PCMan about finding the optimal text label size:
      // The average filename length on my root filesystem is roughly 18-20 chars.
      // So, a reasonable size for the text label is about 10 chars each line since string of this length
      // can be shown in two lines. If you consider word wrap, then the result is around 10 chars per word.
      // In average, 10 char per line should be enough to display a "word" in the filename without breaking.
      // The values can be estimated with this command:
      // > find / | xargs  basename -a | sed -e s'/[_-]/ /g' | wc -mcw
      // However, this average only applies to English. For some Asian characters, such as Chinese chars,
      // each char actually takes doubled space. To be safe, we use 13 chars per line x average char width
      // to get a nearly optimal width for the text label. As most of the filenames have less than 40 chars
      // 13 chars x 3 lines should be enough to show the full filenames for most files.
      int textWidth = fm.averageCharWidth() * 13;
      int textHeight = fm.lineSpacing() * 3;
      grid.setWidth(qMax(icon.width(), textWidth) + 4); // a margin of 2 px for selection rects
      grid.setHeight(icon.height() + textHeight + 4); // a margin of 2 px for selection rects
      break;
    }
    default:
      ; // do not use grid size
  }
  if(mode == IconMode || mode == ThumbnailMode)
    listView->setGridSize(grid + QSize(6, 6)); // a margin of 6 px for every cell
  else
    listView->setGridSize(grid);
  FolderItemDelegate* delegate = static_cast<FolderItemDelegate*>(listView->itemDelegateForColumn(FolderModel::ColumnFileName));
  delegate->setGridSize(grid);
}
Example #2
0
void FolderView::setViewMode(ViewMode _mode) {
  if(_mode == mode) // if it's the same more, ignore
    return;
  // FIXME: retain old selection

  // since only detailed list mode uses QTreeView, and others 
  // all use QListView, it's wise to preserve QListView when possible.
  bool recreateView = false;
  if(view && (mode == DetailedListMode || _mode == DetailedListMode)) {
    delete view; // FIXME: no virtual dtor?
    view = NULL;
    recreateView = true;
  }
  mode = _mode;
  QSize iconSize = iconSize_[mode - FirstViewMode];

  if(mode == DetailedListMode) {
    FolderViewTreeView* treeView = new FolderViewTreeView(this);
    view = treeView;
    treeView->setItemsExpandable(false);
    treeView->setRootIsDecorated(false);
    treeView->setAllColumnsShowFocus(false);

    // set our own custom delegate
    FolderItemDelegate* delegate = new FolderItemDelegate(treeView);
    treeView->setItemDelegateForColumn(FolderModel::ColumnFileName, delegate);
  }
  else {
    FolderViewListView* listView;
    if(view)
      listView = static_cast<FolderViewListView*>(view);
    else {
      listView = new FolderViewListView(this);
      view = listView;
    }
    // set our own custom delegate
    FolderItemDelegate* delegate = new FolderItemDelegate(listView);
    listView->setItemDelegateForColumn(FolderModel::ColumnFileName, delegate);
    // FIXME: should we expose the delegate?
    listView->setMovement(QListView::Static);
    listView->setResizeMode(QListView::Adjust);
    listView->setWrapping(true);
    switch(mode) {
      case IconMode: {
        listView->setViewMode(QListView::IconMode);
        // listView->setGridSize(QSize(iconSize.width() * 1.6, iconSize.height() * 2));
        listView->setGridSize(QSize(90, 110));
        listView->setWordWrap(true);
        listView->setFlow(QListView::LeftToRight);
        break;
      }
      case CompactMode: {
        listView->setViewMode(QListView::ListMode);
        listView->setGridSize(QSize());
        listView->setWordWrap(false);
        listView->setFlow(QListView::QListView::TopToBottom);
        break;
      }
      case ThumbnailMode: {
        listView->setViewMode(QListView::IconMode);
        listView->setGridSize(QSize(160, 160));
        listView->setWordWrap(true);
        listView->setFlow(QListView::LeftToRight);
        break;
      }
      default:;
    }
    delegate->setGridSize(listView->gridSize());
  }
  if(view) {
    // we have to install the event filter on the viewport instead of the view itself.
    view->viewport()->installEventFilter(this);
    // we want the QEvent::HoverMove event for single click + auto-selection support
    view->viewport()->setAttribute(Qt::WA_Hover, true);
    connect(view, SIGNAL(activatedFiltered(QModelIndex)), SLOT(onItemActivated(QModelIndex)));
    view->setContextMenuPolicy(Qt::NoContextMenu); // defer the context menu handling to parent widgets
    view->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    view->setIconSize(iconSize);

    view->setSelectionMode(QAbstractItemView::ExtendedSelection);
    layout()->addWidget(view);

    // enable dnd
    view->setDragEnabled(true);
    view->setAcceptDrops(true);
    view->setDragDropMode(QAbstractItemView::DragDrop);
    view->setDropIndicatorShown(true);

    if(model_) {
      // FIXME: preserve selections
      model_->setThumbnailSize(iconSize.width());
      view->setModel(model_);
      if(recreateView)
        connect(view->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), SLOT(onSelectionChanged(QItemSelection,QItemSelection)));
    }
  }
}