// 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); }
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))); } } }