diff --git a/krusader/GUI/krstyleproxy.cpp b/krusader/GUI/krstyleproxy.cpp index 880ff6c6..a5af4ba9 100644 --- a/krusader/GUI/krstyleproxy.cpp +++ b/krusader/GUI/krstyleproxy.cpp @@ -1,66 +1,87 @@ /*************************************************************************** krstyleproxy.cpp ------------------- copyright : (C) 2008+ by Csaba Karai email : krusader@users.sourceforge.net web site : http://krusader.sourceforge.net --------------------------------------------------------------------------- Description *************************************************************************** A db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD S o u r c e F i l e *************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "krstyleproxy.h" // QtGui #include #include // QtWidgets #include +#include + +#include "../krglobal.h" + void KrStyleProxy::drawPrimitive(PrimitiveElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const { if (element == QStyle::PE_FrameFocusRect) { if (const QStyleOptionFocusRect *fropt = qstyleoption_cast(option)) { QColor bg = fropt->backgroundColor; QPen oldPen = painter->pen(); QPen newPen; if (bg.isValid()) { int h, s, v; bg.getHsv(&h, &s, &v); if (v >= 128) newPen.setColor(Qt::black); else newPen.setColor(Qt::white); } else { newPen.setColor(option->palette.foreground().color()); } newPen.setWidth(0); newPen.setStyle(Qt::DotLine); painter->setPen(newPen); QRect focusRect = option->rect /*.adjusted(1, 1, -1, -1) */; painter->drawRect(focusRect.adjusted(0, 0, -1, -1)); //draw pen inclusive painter->setPen(oldPen); } } else QProxyStyle::drawPrimitive(element, option, painter, widget); } + +int KrStyleProxy::styleHint(QStyle::StyleHint hint, const QStyleOption *option, + const QWidget *widget, QStyleHintReturn *returnData) const +{ + if (hint == QStyle::SH_ToolTip_WakeUpDelay) { + KConfigGroup group(krConfig, "Look&Feel"); + const int delay = group.readEntry("Panel Tooltip Delay", 1000); + return delay < 0 ? INT_MAX : delay; + } + + // disable instant consecutive tooltips + if (hint == QStyle::SH_ToolTip_FallAsleepDelay) { + return 0; + } + + return QProxyStyle::styleHint(hint, option, widget, returnData); +} diff --git a/krusader/GUI/krstyleproxy.h b/krusader/GUI/krstyleproxy.h index cd43a4a0..cd7609bc 100644 --- a/krusader/GUI/krstyleproxy.h +++ b/krusader/GUI/krstyleproxy.h @@ -1,44 +1,49 @@ /*************************************************************************** krstyleproxy.h ------------------- copyright : (C) 2008+ by Csaba Karai email : krusader@users.sourceforge.net web site : http://krusader.sourceforge.net --------------------------------------------------------------------------- Description *************************************************************************** A db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD H e a d e r F i l e *************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef KRSTYLEPROXY_H #define KRSTYLEPROXY_H // QtWidgets #include class KrStyleProxy: public QProxyStyle { public: void drawPrimitive(PrimitiveElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget = 0) const Q_DECL_OVERRIDE; + + int styleHint(StyleHint hint, + const QStyleOption *option, + const QWidget *widget, + QStyleHintReturn *returnData) const Q_DECL_OVERRIDE; }; #endif /* KRSTYLEPROXY_H */ diff --git a/krusader/Konfigurator/kgpanel.cpp b/krusader/Konfigurator/kgpanel.cpp index b238876b..a8a750ab 100644 --- a/krusader/Konfigurator/kgpanel.cpp +++ b/krusader/Konfigurator/kgpanel.cpp @@ -1,724 +1,738 @@ /*************************************************************************** kgpanel.cpp - description ------------------- copyright : (C) 2003 by Csaba Karai copyright : (C) 2010 by Jan Lepper e-mail : krusader@users.sourceforge.net web site : http://krusader.sourceforge.net --------------------------------------------------------------------------- Description *************************************************************************** A db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD S o u r c e F i l e *************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "kgpanel.h" #include "../defaults.h" #include "../Dialogs/krdialogs.h" // QtGui #include // QtWidgets #include #include #include #include #include #include #include #include "../GUI/krtreewidget.h" #include "../Panel/krsearchbar.h" #include "../Panel/krselectionmode.h" #include "../Panel/krview.h" #include "../Panel/krviewfactory.h" #include "../Panel/krlayoutfactory.h" enum { PAGE_MISC = 0, PAGE_VIEW, PAGE_PANELTOOLBAR, PAGE_MOUSE, PAGE_MEDIA_MENU, PAGE_LAYOUT }; KgPanel::KgPanel(bool first, QWidget* parent) : KonfiguratorPage(first, parent) { tabWidget = new QTabWidget(this); setWidget(tabWidget); setWidgetResizable(true); setupMiscTab(); setupPanelTab(); setupButtonsTab(); setupMouseModeTab(); setupMediaMenuTab(); setupLayoutTab(); } // --------------------------------------------------------------------------------------- // ---------------------------- Misc TAB ------------------------------------------------ // --------------------------------------------------------------------------------------- void KgPanel::setupMiscTab() { QScrollArea *scrollArea = new QScrollArea(tabWidget); QWidget *tab = new QWidget(scrollArea); scrollArea->setFrameStyle(QFrame::NoFrame); scrollArea->setWidget(tab); scrollArea->setWidgetResizable(true); tabWidget->addTab(scrollArea, i18n("General")); QVBoxLayout *miscLayout = new QVBoxLayout(tab); miscLayout->setSpacing(6); miscLayout->setContentsMargins(11, 11, 11, 11); // --------------------------------------------------------------------------------------- // ------------------------------- Navigator bar ------------------------------------- // --------------------------------------------------------------------------------------- QGroupBox *miscGrp = createFrame(i18n("Navigator bar"), tab); QGridLayout *miscGrid = createGridLayout(miscGrp); KONFIGURATOR_CHECKBOX_PARAM navigatorbar_settings[] = { // cfg_class, cfg_name, default, text, restart, tooltip {"Look&Feel", "Navigator Edit Mode", false, i18n("Edit Mode by default"), true, i18n("Show editable path in Navigator bar by default") }, {"Look&Feel", "Navigator Full Path", false, i18n("Show full path by default"), true, i18n("Always show full path in Navigator bar by default.") }, }; cbs = createCheckBoxGroup(2, 0, navigatorbar_settings, 2 /*count*/, miscGrp, PAGE_MISC); miscGrid->addWidget(cbs, 0, 0); miscLayout->addWidget(miscGrp); // --------------------------------------------------------------------------------------- // ------------------------------- Operation --------------------------------------------- // --------------------------------------------------------------------------------------- miscGrp = createFrame(i18n("Operation"), tab); miscGrid = createGridLayout(miscGrp); KONFIGURATOR_CHECKBOX_PARAM operation_settings[] = { // cfg_class, cfg_name, default, text, restart, tooltip {"Look&Feel", "Mark Dirs", _MarkDirs, i18n("Autoselect folders"), false, i18n("When matching the select criteria, not only files will be selected, but also folders.") }, {"Look&Feel", "Rename Selects Extension", true, i18n("Rename selects extension"), false, i18n("When renaming a file, the whole text is selected. If you want Total-Commander like renaming of just the name, without extension, uncheck this option.") }, {"Look&Feel", "UnselectBeforeOperation", _UnselectBeforeOperation, i18n("Unselect files before copy/move"), false, i18n("Unselect files, which are to be copied/moved, before the operation starts.") }, {"Look&Feel", "FilterDialogRemembersSettings", _FilterDialogRemembersSettings, i18n("Filter dialog remembers settings"), false, i18n("The filter dialog is opened with the last filter settings that where applied to the panel.") }, }; cbs = createCheckBoxGroup(2, 0, operation_settings, 4 /*count*/, miscGrp, PAGE_MISC); miscGrid->addWidget(cbs, 0, 0); miscLayout->addWidget(miscGrp); // --------------------------------------------------------------------------------------- // ------------------------------ Tabs --------------------------------------------------- // --------------------------------------------------------------------------------------- miscGrp = createFrame(i18n("Tabs"), tab); miscGrid = createGridLayout(miscGrp); KONFIGURATOR_CHECKBOX_PARAM tabbar_settings[] = { // cfg_class cfg_name default text restart tooltip {"Look&Feel", "Fullpath Tab Names", _FullPathTabNames, i18n("Use full path tab names"), true , i18n("Display the full path in the folder tabs. By default only the last part of the path is displayed.") }, {"Look&Feel", "Show Tab Buttons", true, i18n("Show new/close tab buttons"), true , i18n("Show the new/close tab buttons") }, }; KonfiguratorCheckBoxGroup *cbs = createCheckBoxGroup(2, 0, tabbar_settings, 2 /*count*/, miscGrp, PAGE_MISC); miscGrid->addWidget(cbs, 0, 0); // ----------------- Tab Bar position ---------------------------------- QHBoxLayout *hbox = new QHBoxLayout(); hbox->addWidget(new QLabel(i18n("Tab Bar position:"), miscGrp)); KONFIGURATOR_NAME_VALUE_PAIR positions[] = { { i18n("Top"), "top" }, { i18n("Bottom"), "bottom" } }; KonfiguratorComboBox *cmb = createComboBox("Look&Feel", "Tab Bar Position", "bottom", positions, 2, miscGrp, true, false, PAGE_MISC); hbox->addWidget(cmb); hbox->addWidget(createSpacer(miscGrp)); miscGrid->addLayout(hbox, 1, 0); miscLayout->addWidget(miscGrp); // --------------------------------------------------------------------------------------- // ----------------------------- Search bar -------------------------------------------- // --------------------------------------------------------------------------------------- miscGrp = createFrame(i18n("Search bar"), tab); miscGrid = createGridLayout(miscGrp); KONFIGURATOR_CHECKBOX_PARAM quicksearch[] = { // cfg_class cfg_name default text restart tooltip {"Look&Feel", "New Style Quicksearch", _NewStyleQuicksearch, i18n("Start by typing"), false, i18n("Open search bar and start searching by typing in panel.") }, {"Look&Feel", "Case Sensitive Quicksearch", _CaseSensitiveQuicksearch, i18n("Case sensitive"), false, i18n("Search must match case.") }, {"Look&Feel", "Up/Down Cancels Quicksearch", false, i18n("Up/Down cancels search"), false, i18n("Pressing the Up/Down buttons closes the search bar (only in search mode).") }, }; quicksearchCheckboxes = createCheckBoxGroup(2, 0, quicksearch, 3 /*count*/, miscGrp, PAGE_MISC); miscGrid->addWidget(quicksearchCheckboxes, 0, 0, 1, -1); connect(quicksearchCheckboxes->find("New Style Quicksearch"), SIGNAL(stateChanged(int)), this, SLOT(slotDisable())); slotDisable(); // -------------- Search bar position ----------------------- hbox = new QHBoxLayout(); hbox->addWidget(new QLabel(i18n("Position:"), miscGrp)); cmb = createComboBox("Look&Feel", "Quicksearch Position", "bottom", positions, 2, miscGrp, true, false, PAGE_MISC); hbox->addWidget(cmb); hbox->addWidget(createSpacer(miscGrp)); miscGrid->addLayout(hbox, 1, 0); miscLayout->addWidget(miscGrp); // -------------- Default search mode ----------------------- hbox = new QHBoxLayout(); hbox->addWidget(new QLabel(i18n("Default mode:"), miscGrp)); KONFIGURATOR_NAME_VALUE_PAIR modes[] = { { i18n("Search"), QString::number(KrSearchBar::MODE_SEARCH) }, { i18n("Select"), QString::number(KrSearchBar::MODE_SELECT) }, { i18n("Filter"), QString::number(KrSearchBar::MODE_FILTER) } }; cmb = createComboBox("Look&Feel", "Default Search Mode", QString::number(KrSearchBar::MODE_SEARCH), modes, 3, miscGrp, true, false, PAGE_MISC); cmb->setToolTip(i18n("Set the default mode on first usage")); hbox->addWidget(cmb); hbox->addWidget(createSpacer(miscGrp)); miscGrid->addLayout(hbox, 1, 1); miscLayout->addWidget(miscGrp); // -------------------------------------------------------------------------------------------- // ------------------------------- Status/Totalsbar settings ---------------------------------- // -------------------------------------------------------------------------------------------- miscGrp = createFrame(i18n("Status/Totalsbar"), tab); miscGrid = createGridLayout(miscGrp); KONFIGURATOR_CHECKBOX_PARAM barSettings[] = { {"Look&Feel", "Show Size In Bytes", false, i18n("Show size in bytes too"), true, i18n("Show size in bytes too") }, {"Look&Feel", "ShowSpaceInformation", true, i18n("Show space information"), true, i18n("Show free/total space on the device") }, }; KonfiguratorCheckBoxGroup *barSett = createCheckBoxGroup(2, 0, barSettings, 2 /*count*/, miscGrp, PAGE_MISC); miscGrid->addWidget(barSett, 1, 0, 1, 2); miscLayout->addWidget(miscGrp); } // -------------------------------------------------------------------------------------------- // ------------------------------------ Layout Tab -------------------------------------------- // -------------------------------------------------------------------------------------------- void KgPanel::setupLayoutTab() { QScrollArea *scrollArea = new QScrollArea(tabWidget); QWidget *tab = new QWidget(scrollArea); scrollArea->setFrameStyle(QFrame::NoFrame); scrollArea->setWidget(tab); scrollArea->setWidgetResizable(true); tabWidget->addTab(scrollArea, i18n("Layout")); QGridLayout *grid = createGridLayout(tab); QStringList layoutNames = KrLayoutFactory::layoutNames(); int numLayouts = layoutNames.count(); grid->addWidget(createSpacer(tab), 0, 2); QLabel *l = new QLabel(i18n("Layout:"), tab); l->setAlignment(Qt::AlignRight | Qt::AlignVCenter); grid->addWidget(l, 0, 0); KONFIGURATOR_NAME_VALUE_PAIR *layouts = new KONFIGURATOR_NAME_VALUE_PAIR[numLayouts]; for (int i = 0; i != numLayouts; i++) { layouts[ i ].text = KrLayoutFactory::layoutDescription(layoutNames[i]); layouts[ i ].value = layoutNames[i]; } KonfiguratorComboBox *cmb = createComboBox("PanelLayout", "Layout", "default", layouts, numLayouts, tab, true, false, PAGE_LAYOUT); grid->addWidget(cmb, 0, 1); delete [] layouts; l = new QLabel(i18n("Frame Color:"), tab); l->setAlignment(Qt::AlignRight | Qt::AlignVCenter); grid->addWidget(l, 1, 0); KONFIGURATOR_NAME_VALUE_PAIR frameColor[] = { { i18nc("Frame color", "Defined by Layout"), "default" }, { i18nc("Frame color", "None"), "none" }, { i18nc("Frame color", "Statusbar"), "Statusbar" } }; cmb = createComboBox("PanelLayout", "FrameColor", "default", frameColor, 3, tab, true, false, PAGE_LAYOUT); grid->addWidget(cmb, 1, 1); l = new QLabel(i18n("Frame Shape:"), tab); l->setAlignment(Qt::AlignRight | Qt::AlignVCenter); grid->addWidget(l, 2, 0); KONFIGURATOR_NAME_VALUE_PAIR frameShape[] = { { i18nc("Frame shape", "Defined by Layout"), "default" }, { i18nc("Frame shape", "None"), "NoFrame" }, { i18nc("Frame shape", "Box"), "Box" }, { i18nc("Frame shape", "Panel"), "Panel" }, }; cmb = createComboBox("PanelLayout", "FrameShape", "default", frameShape, 4, tab, true, false, PAGE_LAYOUT); grid->addWidget(cmb, 2, 1); l = new QLabel(i18n("Frame Shadow:"), tab); l->setAlignment(Qt::AlignRight | Qt::AlignVCenter); grid->addWidget(l, 3, 0); KONFIGURATOR_NAME_VALUE_PAIR frameShadow[] = { { i18nc("Frame shadow", "Defined by Layout"), "default" }, { i18nc("Frame shadow", "None"), "Plain" }, { i18nc("Frame shadow", "Raised"), "Raised" }, { i18nc("Frame shadow", "Sunken"), "Sunken" }, }; cmb = createComboBox("PanelLayout", "FrameShadow", "default", frameShadow, 4, tab, true, false, PAGE_LAYOUT); grid->addWidget(cmb, 3, 1); } void KgPanel::setupView(KrViewInstance *instance, QWidget *parent) { QGridLayout *grid = createGridLayout(parent); // -------------------- Filelist icon size ---------------------------------- QHBoxLayout *hbox = new QHBoxLayout(); hbox->addWidget(new QLabel(i18n("Default icon size:"), parent)); KONFIGURATOR_NAME_VALUE_PAIR *iconSizes = new KONFIGURATOR_NAME_VALUE_PAIR[KrView::iconSizes.count()]; for(int i = 0; i < KrView::iconSizes.count(); i++) iconSizes[i].text = iconSizes[i].value = QString::number(KrView::iconSizes[i]); KonfiguratorComboBox *cmb = createComboBox(instance->name(), "IconSize", _FilelistIconSize, iconSizes, KrView::iconSizes.count(), parent, true, true, PAGE_VIEW); delete [] iconSizes; cmb->lineEdit()->setValidator(new QRegExpValidator(QRegExp("[1-9]\\d{0,1}"), cmb)); hbox->addWidget(cmb); hbox->addWidget(createSpacer(parent)); grid->addLayout(hbox, 1, 0); //-------------------------------------------------------------------- KONFIGURATOR_CHECKBOX_PARAM iconSettings[] = // cfg_class cfg_name default text restart tooltip { {instance->name(), "With Icons", _WithIcons, i18n("Use icons in the filenames"), true, i18n("Show the icons for filenames and folders.") }, {instance->name(), "ShowPreviews", false, i18n("Show previews by default"), false, i18n("Show previews of files and folders.") }, }; KonfiguratorCheckBoxGroup *iconSett = createCheckBoxGroup(2, 0, iconSettings, 2 /*count*/, parent, PAGE_VIEW); grid->addWidget(iconSett, 2, 0, 1, 2); } // ---------------------------------------------------------------------------------- // ---------------------------- VIEW TAB ------------------------------------------- // ---------------------------------------------------------------------------------- void KgPanel::setupPanelTab() { QScrollArea *scrollArea = new QScrollArea(tabWidget); QWidget *tab_panel = new QWidget(scrollArea); scrollArea->setFrameStyle(QFrame::NoFrame); scrollArea->setWidget(tab_panel); scrollArea->setWidgetResizable(true); tabWidget->addTab(scrollArea, i18n("View")); QGridLayout *panelLayout = new QGridLayout(tab_panel); panelLayout->setSpacing(6); panelLayout->setContentsMargins(11, 11, 11, 11); QGroupBox *panelGrp = createFrame(i18n("General"), tab_panel); panelLayout->addWidget(panelGrp, 0, 0); QGridLayout *panelGrid = createGridLayout(panelGrp); // ---------------------------------------------------------------------------------- // ---------------------------- General settings ----------------------------------- // ---------------------------------------------------------------------------------- // -------------------- Panel Font ---------------------------------- QHBoxLayout *hbox = new QHBoxLayout(); - hbox->addWidget(new QLabel(i18n("View font:"), panelGrp)); - - KonfiguratorFontChooser * chsr = createFontChooser("Look&Feel", "Filelist Font", _FilelistFont, panelGrp, true, PAGE_VIEW); - hbox->addWidget(chsr); - - hbox->addWidget(createSpacer(panelGrp)); + QHBoxLayout *fontLayout = new QHBoxLayout(); + fontLayout->addWidget(new QLabel(i18n("View font:"), panelGrp)); + KonfiguratorFontChooser *chsr = + createFontChooser("Look&Feel", "Filelist Font", _FilelistFont, panelGrp, true, PAGE_VIEW); + fontLayout->addWidget(chsr); + fontLayout->addStretch(1); + hbox->addLayout(fontLayout, 1); + + // -------------------- Panel Tooltip ---------------------------------- + QHBoxLayout *tooltipLayout = new QHBoxLayout(); + QLabel *tooltipLabel = new QLabel(i18n("Tooltip delay (msec):")); + tooltipLabel->setWhatsThis(i18n("The duration after a tooltip is shown for a file item, in " + "milliseconds. Set a negative value to disable tooltips.")); + tooltipLayout->addWidget(tooltipLabel); + KonfiguratorSpinBox *tooltipSpinBox = createSpinBox("Look&Feel", "Panel Tooltip Delay", 1000, + -100, 5000, panelGrp, false, PAGE_VIEW); + tooltipSpinBox->setSingleStep(100); + tooltipLayout->addWidget(tooltipSpinBox); + tooltipLayout->addStretch(1); + hbox->addLayout(tooltipLayout, 1); panelGrid->addLayout(hbox, 1, 0); // -------------------- Misc options ---------------------------------- KONFIGURATOR_CHECKBOX_PARAM panelSettings[] = // cfg_class cfg_name default text restart tooltip { {"Look&Feel", "Human Readable Size", _HumanReadableSize, i18n("Use human-readable file size"), true , i18n("File sizes are displayed in B, KB, MB and GB, not just in bytes.") }, {"Look&Feel", "Show Hidden", _ShowHidden, i18n("Show hidden files"), false, i18n("Display files beginning with a dot.") }, {"Look&Feel", "Numeric permissions", _NumericPermissions, i18n("Numeric Permissions"), true, i18n("Show octal numbers (0755) instead of the standard permissions (rwxr-xr-x) in the permission column.") }, {"Look&Feel", "Load User Defined Folder Icons", _UserDefinedFolderIcons, i18n("Load the user defined folder icons"), true , i18n("Load the user defined folder icons (can cause decrease in performance).") }, }; KonfiguratorCheckBoxGroup *panelSett = createCheckBoxGroup(2, 0, panelSettings, 4 /*count*/, panelGrp, PAGE_VIEW); panelGrid->addWidget(panelSett, 3, 0, 1, 2); // ========================================================= panelGrid->addWidget(createLine(panelGrp), 4, 0); // ------------------------ Sort Method ---------------------------------- hbox = new QHBoxLayout(); hbox->addWidget(new QLabel(i18n("Sort method:"), panelGrp)); KONFIGURATOR_NAME_VALUE_PAIR sortMethods[] = {{ i18n("Alphabetical"), QString::number(KrViewProperties::Alphabetical) }, { i18n("Alphabetical and numbers"), QString::number(KrViewProperties::AlphabeticalNumbers) }, { i18n("Character code"), QString::number(KrViewProperties::CharacterCode) }, { i18n("Character code and numbers"), QString::number(KrViewProperties::CharacterCodeNumbers) }, { i18nc("Krusader sort", "Krusader"), QString::number(KrViewProperties::Krusader) } }; KonfiguratorComboBox *cmb = createComboBox("Look&Feel", "Sort method", QString::number(_DefaultSortMethod), sortMethods, 5, panelGrp, true, false, PAGE_VIEW); hbox->addWidget(cmb); hbox->addWidget(createSpacer(panelGrp)); panelGrid->addLayout(hbox, 5, 0); // ------------------------ Sort Options ---------------------------------- KONFIGURATOR_CHECKBOX_PARAM sortSettings[] = // cfg_class, cfg_name, default, text, restart, tooltip { {"Look&Feel", "Case Sensative Sort", _CaseSensativeSort, i18n("Case sensitive sorting"), true, i18n("All files beginning with capital letters appear before files beginning with non-capital letters (UNIX default).") }, {"Look&Feel", "Show Directories First", true, i18n("Show folders first"), true, 0 }, {"Look&Feel", "Always sort dirs by name", false, i18n("Always sort dirs by name"), true, i18n("Folders are sorted by name, regardless of the sort column.") }, {"Look&Feel", "Locale Aware Sort", true, i18n("Locale aware sorting"), true, i18n("The sorting is performed in a locale- and also platform-dependent manner. Can be slow.") }, }; KonfiguratorCheckBoxGroup *sortSett = createCheckBoxGroup(2, 0, sortSettings, 4 /*count*/, panelGrp, PAGE_VIEW); sortSett->find("Show Directories First")->addDep(sortSett->find("Always sort dirs by name")); panelGrid->addWidget(sortSett, 6, 0, 1, 2); // ---------------------------------------------------------------------------------- // ---------------------------- View modes ----------------------------------------- // ---------------------------------------------------------------------------------- panelGrp = createFrame(i18n("View modes"), tab_panel); panelLayout->addWidget(panelGrp, 1, 0); panelGrid = createGridLayout(panelGrp); // -------------------- Default Panel Type ---------------------------------- hbox = new QHBoxLayout(); hbox->addWidget(new QLabel(i18n("Default view mode:"), panelGrp)); QList views = KrViewFactory::registeredViews(); const int viewsSize = views.size(); KONFIGURATOR_NAME_VALUE_PAIR *panelTypes = new KONFIGURATOR_NAME_VALUE_PAIR[ viewsSize ]; QString defType = QString('0'); for (int i = 0; i != viewsSize; i++) { KrViewInstance * inst = views[ i ]; panelTypes[ i ].text = inst->description(); panelTypes[ i ].text.remove('&'); panelTypes[ i ].value = QString("%1").arg(inst->id()); if (inst->id() == KrViewFactory::defaultViewId()) defType = QString("%1").arg(inst->id()); } cmb = createComboBox("Look&Feel", "Default Panel Type", defType, panelTypes, viewsSize, panelGrp, false, false, PAGE_VIEW); hbox->addWidget(cmb); hbox->addWidget(createSpacer(panelGrp)); delete [] panelTypes; panelGrid->addLayout(hbox, 0, 0); // ----- Individual Settings Per View Type ------------------------ QTabWidget *tabs_view = new QTabWidget(panelGrp); panelGrid->addWidget(tabs_view, 11, 0); for(int i = 0; i < views.count(); i++) { QWidget *tab = new QWidget(tabs_view); tabs_view->addTab(tab, views[i]->description()); setupView(views[i], tab); } } // ----------------------------------------------------------------------------------- // -------------------------- Panel Toolbar TAB ---------------------------------- // ----------------------------------------------------------------------------------- void KgPanel::setupButtonsTab() { QScrollArea *scrollArea = new QScrollArea(tabWidget); QWidget *tab = new QWidget(scrollArea); scrollArea->setFrameStyle(QFrame::NoFrame); scrollArea->setWidget(tab); scrollArea->setWidgetResizable(true); tabWidget->addTab(scrollArea, i18n("Buttons")); QBoxLayout * tabLayout = new QVBoxLayout(tab); tabLayout->setSpacing(6); tabLayout->setContentsMargins(11, 11, 11, 11); KONFIGURATOR_CHECKBOX_PARAM buttonsParams[] = // cfg_class cfg_name default text restart tooltip { {"ListPanelButtons", "Icons", false, i18n("Toolbar buttons have icons"), true, "" }, {"Look&Feel", "Media Button Visible", true, i18n("Show Media Button"), true , i18n("The media button will be visible.") }, {"Look&Feel", "Back Button Visible", false, i18n("Show Back Button"), true , "Goes back in history." }, {"Look&Feel", "Forward Button Visible", false, i18n("Show Forward Button"), true , "Goes forward in history." }, {"Look&Feel", "History Button Visible", true, i18n("Show History Button"), true , i18n("The history button will be visible.") }, {"Look&Feel", "Bookmarks Button Visible", true, i18n("Show Bookmarks Button"), true , i18n("The bookmarks button will be visible.") }, {"Look&Feel", "Panel Toolbar visible", _PanelToolBar, i18n("Show Panel Toolbar"), true, i18n("The panel toolbar will be visible.") }, }; buttonsCheckboxes = createCheckBoxGroup(1, 0, buttonsParams, 7/*count*/, tab, PAGE_PANELTOOLBAR); connect(buttonsCheckboxes->find("Panel Toolbar visible"), SIGNAL(stateChanged(int)), this, SLOT(slotEnablePanelToolbar())); tabLayout->addWidget(buttonsCheckboxes, 0, 0); QGroupBox * panelToolbarGrp = createFrame(i18n("Visible Panel Toolbar buttons"), tab); QGridLayout * panelToolbarGrid = createGridLayout(panelToolbarGrp); KONFIGURATOR_CHECKBOX_PARAM panelToolbarButtonsParams[] = { // cfg_class cfg_name default text restart tooltip {"Look&Feel", "Equal Button Visible", _cdOther, i18n("Equal button (=)"), true , i18n("Changes the panel folder to the other panel folder.") }, {"Look&Feel", "Up Button Visible", _cdUp, i18n("Up button (..)"), true , i18n("Changes the panel folder to the parent folder.") }, {"Look&Feel", "Home Button Visible", _cdHome, i18n("Home button (~)"), true , i18n("Changes the panel folder to the home folder.") }, {"Look&Feel", "Root Button Visible", _cdRoot, i18n("Root button (/)"), true , i18n("Changes the panel folder to the root folder.") }, {"Look&Feel", "SyncBrowse Button Visible", _syncBrowseButton, i18n("Toggle-button for sync-browsing"), true , i18n("Each folder change in the panel is also performed in the other panel.") }, }; panelToolbarButtonsCheckboxes = createCheckBoxGroup(1, 0, panelToolbarButtonsParams, sizeof(panelToolbarButtonsParams) / sizeof(*panelToolbarButtonsParams), panelToolbarGrp, PAGE_PANELTOOLBAR); panelToolbarGrid->addWidget(panelToolbarButtonsCheckboxes, 0, 0); tabLayout->addWidget(panelToolbarGrp, 1, 0); // Enable panel toolbar checkboxes slotEnablePanelToolbar(); } // --------------------------------------------------------------------------- // -------------------------- Mouse TAB ---------------------------------- // --------------------------------------------------------------------------- void KgPanel::setupMouseModeTab() { QScrollArea *scrollArea = new QScrollArea(tabWidget); QWidget *tab_mouse = new QWidget(scrollArea); scrollArea->setFrameStyle(QFrame::NoFrame); scrollArea->setWidget(tab_mouse); scrollArea->setWidgetResizable(true); tabWidget->addTab(scrollArea, i18n("Selection Mode")); QGridLayout *mouseLayout = new QGridLayout(tab_mouse); mouseLayout->setSpacing(6); mouseLayout->setContentsMargins(11, 11, 11, 11); // -------------- General ----------------- QGroupBox *mouseGeneralGroup = createFrame(i18n("General"), tab_mouse); QGridLayout *mouseGeneralGrid = createGridLayout(mouseGeneralGroup); mouseGeneralGrid->setSpacing(0); mouseGeneralGrid->setContentsMargins(5, 5, 5, 5); KONFIGURATOR_NAME_VALUE_TIP mouseSelection[] = { // name value tooltip { i18n("Krusader Mode"), "0", i18n("Both keys allow selecting files. To select more than one file, hold the Ctrl key and click the left mouse button. Right-click menu is invoked using a short click on the right mouse button.") }, { i18n("Konqueror Mode"), "1", i18n("Pressing the left mouse button selects files - you can click and select multiple files. Right-click menu is invoked using a short click on the right mouse button.") }, { i18n("Total-Commander Mode"), "2", i18n("The left mouse button does not select, but sets the current file without affecting the current selection. The right mouse button selects multiple files and the right-click menu is invoked by pressing and holding the right mouse button.") }, { i18n("Ergonomic Mode"), "4", i18n("The left mouse button does not select, but sets the current file without affecting the current selection. The right mouse button invokes the context-menu. You can select with Ctrl key and the left button.") }, { i18n("Custom Selection Mode"), "3", i18n("Design your own selection mode.") } }; mouseRadio = createRadioButtonGroup("Look&Feel", "Mouse Selection", "0", 1, 5, mouseSelection, 5, mouseGeneralGroup, true, PAGE_MOUSE); mouseRadio->layout()->setContentsMargins(0, 0, 0, 0); mouseGeneralGrid->addWidget(mouseRadio, 0, 0); for (int i = 0; i != mouseRadio->count(); i++) connect(mouseRadio->find(i), SIGNAL(clicked()), SLOT(slotSelectionModeChanged())); mouseLayout->addWidget(mouseGeneralGroup, 0, 0); // -------------- Details ----------------- QGroupBox *mouseDetailGroup = createFrame(i18n("Details"), tab_mouse); QGridLayout *mouseDetailGrid = createGridLayout(mouseDetailGroup); mouseDetailGrid->setSpacing(0); mouseDetailGrid->setContentsMargins(5, 5, 5, 5); KONFIGURATOR_NAME_VALUE_TIP singleOrDoubleClick[] = { // name value tooltip { i18n("Double-click selects (classic)"), "0", i18n("A single click on a file will select and focus, a double click opens the file or steps into the folder.") }, { i18n("Obey global selection policy"), "1", i18n("

Use global setting:

Plasma System Settings -> Input Devices -> Mouse

") } }; KonfiguratorRadioButtons *clickRadio = createRadioButtonGroup("Look&Feel", "Single Click Selects", "0", 1, 0, singleOrDoubleClick, 2, mouseDetailGroup, true, PAGE_MOUSE); clickRadio->layout()->setContentsMargins(0, 0, 0, 0); mouseDetailGrid->addWidget(clickRadio, 0, 0); KONFIGURATOR_CHECKBOX_PARAM mouseCheckboxesParam[] = { // {cfg_class, cfg_name, default // text, restart, // tooltip } {"Custom Selection Mode", "QT Selection", _QtSelection, i18n("Based on KDE's selection mode"), true, i18n("If checked, use a mode based on KDE's style.") }, {"Custom Selection Mode", "Left Selects", _LeftSelects, i18n("Left mouse button selects"), true, i18n("If checked, left clicking an item will select it.") }, {"Custom Selection Mode", "Left Preserves", _LeftPreserves, i18n("Left mouse button preserves selection"), true, i18n("If checked, left clicking an item will select it, but will not unselect other, already selected items.") }, {"Custom Selection Mode", "ShiftCtrl Left Selects", _ShiftCtrlLeft, i18n("Shift/Ctrl-Left mouse button selects"), true, i18n("If checked, Shift/Ctrl left clicking will select items.\nNote: this is meaningless if 'Left Button Selects' is checked.") }, {"Custom Selection Mode", "Right Selects", _RightSelects, i18n("Right mouse button selects"), true, i18n("If checked, right clicking an item will select it.") }, {"Custom Selection Mode", "Right Preserves", _RightPreserves, i18n("Right mouse button preserves selection"), true, i18n("If checked, right clicking an item will select it, but will not unselect other, already selected items.") }, {"Custom Selection Mode", "ShiftCtrl Right Selects", _ShiftCtrlRight, i18n("Shift/Ctrl-Right mouse button selects"), true, i18n("If checked, Shift/Ctrl right clicking will select items.\nNote: this is meaningless if 'Right Button Selects' is checked.") }, {"Custom Selection Mode", "Space Moves Down", _SpaceMovesDown, i18n("Spacebar moves down"), true, i18n("If checked, pressing the spacebar will select the current item and move down.\nOtherwise, current item is selected, but remains the current item.") }, {"Custom Selection Mode", "Insert Moves Down", _InsertMovesDown, i18n("Insert moves down"), true, i18n("If checked, pressing Insert will select the current item, and move down to the next item.\nOtherwise, current item is not changed.") }, {"Custom Selection Mode", "Immediate Context Menu", _ImmediateContextMenu, i18n("Right clicking pops context menu immediately"), true, i18n("If checked, right clicking will result in an immediate showing of the context menu.\nOtherwise, user needs to click and hold the right mouse button for 500ms.") }, }; mouseCheckboxes = createCheckBoxGroup(1, 0, mouseCheckboxesParam, 10 /*count*/, mouseDetailGroup, PAGE_MOUSE); mouseDetailGrid->addWidget(mouseCheckboxes, 1, 0); for (int i = 0; i < mouseCheckboxes->count(); i++) connect(mouseCheckboxes->find(i), SIGNAL(clicked()), SLOT(slotMouseCheckBoxChanged())); mouseLayout->addWidget(mouseDetailGroup, 0, 1, 2, 1); // Disable the details-button if not in custom-mode slotSelectionModeChanged(); // -------------- Preview ----------------- QGroupBox *mousePreviewGroup = createFrame(i18n("Preview"), tab_mouse); QGridLayout *mousePreviewGrid = createGridLayout(mousePreviewGroup); // TODO preview mousePreview = new KrTreeWidget(mousePreviewGroup); mousePreviewGrid->addWidget(mousePreview, 0 , 0); mousePreviewGroup->setEnabled(false); // TODO re-enable once the preview is implemented // ------------------------------------------ mouseLayout->addWidget(mousePreviewGroup, 1, 0); } // --------------------------------------------------------------------------- // -------------------------- Media Menu TAB ---------------------------------- // --------------------------------------------------------------------------- void KgPanel::setupMediaMenuTab() { QScrollArea *scrollArea = new QScrollArea(tabWidget); QWidget *tab = new QWidget(scrollArea); scrollArea->setFrameStyle(QFrame::NoFrame); scrollArea->setWidget(tab); scrollArea->setWidgetResizable(true); tabWidget->addTab(scrollArea, i18n("Media Menu")); QBoxLayout * tabLayout = new QVBoxLayout(tab); tabLayout->setSpacing(6); tabLayout->setContentsMargins(11, 11, 11, 11); KONFIGURATOR_CHECKBOX_PARAM mediaMenuParams[] = { // cfg_class cfg_name default text restart tooltip {"MediaMenu", "ShowPath", true, i18n("Show Mount Path"), false, 0 }, {"MediaMenu", "ShowFSType", true, i18n("Show File System Type"), false, 0 }, }; KonfiguratorCheckBoxGroup *mediaMenuCheckBoxes = createCheckBoxGroup(1, 0, mediaMenuParams, sizeof(mediaMenuParams) / sizeof(*mediaMenuParams), tab, PAGE_MEDIA_MENU); tabLayout->addWidget(mediaMenuCheckBoxes, 0, 0); QHBoxLayout *showSizeHBox = new QHBoxLayout(); showSizeHBox->addWidget(new QLabel(i18n("Show Size:"), tab)); KONFIGURATOR_NAME_VALUE_PAIR showSizeValues[] = { { i18nc("setting 'show size'", "Always"), "Always" }, { i18nc("setting 'show size'", "When Device has no Label"), "WhenNoLabel" }, { i18nc("setting 'show size'", "Never"), "Never" }, }; KonfiguratorComboBox *showSizeCmb = createComboBox("MediaMenu", "ShowSize", "Always", showSizeValues, sizeof(showSizeValues) / sizeof(*showSizeValues), tab, false, false, PAGE_MEDIA_MENU); showSizeHBox->addWidget(showSizeCmb); showSizeHBox->addStretch(); tabLayout->addLayout(showSizeHBox); tabLayout->addStretch(); } void KgPanel::slotDisable() { bool isNewStyleQuickSearch = quicksearchCheckboxes->find("New Style Quicksearch")->isChecked(); quicksearchCheckboxes->find("Case Sensitive Quicksearch")->setEnabled(isNewStyleQuickSearch); } void KgPanel::slotEnablePanelToolbar() { bool enableTB = buttonsCheckboxes->find("Panel Toolbar visible")->isChecked(); panelToolbarButtonsCheckboxes->find("Root Button Visible")->setEnabled(enableTB); panelToolbarButtonsCheckboxes->find("Home Button Visible")->setEnabled(enableTB); panelToolbarButtonsCheckboxes->find("Up Button Visible")->setEnabled(enableTB); panelToolbarButtonsCheckboxes->find("Equal Button Visible")->setEnabled(enableTB); panelToolbarButtonsCheckboxes->find("SyncBrowse Button Visible")->setEnabled(enableTB); } void KgPanel::slotSelectionModeChanged() { KrSelectionMode *selectionMode = KrSelectionMode::getSelectionHandlerForMode(mouseRadio->selectedValue()); if (selectionMode == NULL) //User mode return; selectionMode->init(); mouseCheckboxes->find("QT Selection")->setChecked(selectionMode->useQTSelection()); mouseCheckboxes->find("Left Selects")->setChecked(selectionMode->leftButtonSelects()); mouseCheckboxes->find("Left Preserves")->setChecked(selectionMode->leftButtonPreservesSelection()); mouseCheckboxes->find("ShiftCtrl Left Selects")->setChecked(selectionMode->shiftCtrlLeftButtonSelects()); mouseCheckboxes->find("Right Selects")->setChecked(selectionMode->rightButtonSelects()); mouseCheckboxes->find("Right Preserves")->setChecked(selectionMode->rightButtonPreservesSelection()); mouseCheckboxes->find("ShiftCtrl Right Selects")->setChecked(selectionMode->shiftCtrlRightButtonSelects()); mouseCheckboxes->find("Space Moves Down")->setChecked(selectionMode->spaceMovesDown()); mouseCheckboxes->find("Insert Moves Down")->setChecked(selectionMode->insertMovesDown()); mouseCheckboxes->find("Immediate Context Menu")->setChecked(selectionMode->showContextMenu() == -1); } void KgPanel::slotMouseCheckBoxChanged() { mouseRadio->selectButton("3"); //custom selection mode } int KgPanel::activeSubPage() { return tabWidget->currentIndex(); } diff --git a/krusader/Panel/krinterbriefview.cpp b/krusader/Panel/krinterbriefview.cpp index b34a4a81..1beee8ec 100644 --- a/krusader/Panel/krinterbriefview.cpp +++ b/krusader/Panel/krinterbriefview.cpp @@ -1,716 +1,698 @@ /***************************************************************************** * Copyright (C) 2009 Csaba Karai * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This package is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this package; if not, write to the Free Software * * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ #include "krinterbriefview.h" // QtCore #include #include #include #include // QtGui #include #include #include // QtWidgets #include #include #include #include #include #include #include #include "krviewfactory.h" #include "krviewitemdelegate.h" #include "krviewitem.h" #include "krvfsmodel.h" #include "krmousehandler.h" #include "krcolorcache.h" #include "../FileSystem/krpermhandler.h" #include "../defaults.h" #include "../GUI/krstyleproxy.h" KrInterBriefView::KrInterBriefView(QWidget *parent, KrViewInstance &instance, KConfig *cfg) : QAbstractItemView(parent), KrInterView(instance, cfg, this), _header(0) { setWidget(this); setModel(_model); setSelectionMode(QAbstractItemView::NoSelection); setSelectionModel(new DummySelectionModel(_model, this)); KConfigGroup grpSvr(_config, "Look&Feel"); _viewFont = grpSvr.readEntry("Filelist Font", _FilelistFont); KrStyleProxy *style = new KrStyleProxy(); style->setParent(this); setStyle(style); + viewport()->setStyle(style); // for custom tooltip delay setItemDelegate(new KrViewItemDelegate()); setMouseTracking(true); setAcceptDrops(true); setDropIndicatorShown(true); connect(_mouseHandler, SIGNAL(renameCurrentItem()), SLOT(renameCurrentItem())); _model->setExtensionEnabled(false); _model->setAlternatingTable(true); connect(_model, SIGNAL(layoutChanged()), SLOT(updateGeometries())); } KrInterBriefView::~KrInterBriefView() { delete _properties; _properties = 0; delete _operator; _operator = 0; } void KrInterBriefView::doRestoreSettings(KConfigGroup group) { _properties->numberOfColumns = group.readEntry("Number Of Brief Columns", _NumberOfBriefColumns); if (_properties->numberOfColumns < 1) _properties->numberOfColumns = 1; else if (_properties->numberOfColumns > MAX_BRIEF_COLS) _properties->numberOfColumns = MAX_BRIEF_COLS; _numOfColumns = _properties->numberOfColumns; KrInterView::doRestoreSettings(group); updateGeometries(); } void KrInterBriefView::saveSettings(KConfigGroup grp, KrViewProperties::PropertyType properties) { KrInterView::saveSettings(grp, properties); if(properties & KrViewProperties::PropColumns) grp.writeEntry("Number Of Brief Columns", _numOfColumns); } int KrInterBriefView::itemsPerPage() { int height = getItemHeight(); if (height == 0) height ++; int numRows = viewport()->height() / height; return numRows; } void KrInterBriefView::updateView() { } void KrInterBriefView::setup() { _header = new QHeaderView(Qt::Horizontal, this); _header->setDefaultAlignment(Qt::AlignLeft | Qt::AlignVCenter); _header->setParent(this); _header->setModel(_model); _header->hideSection(KrViewProperties::Type); _header->hideSection(KrViewProperties::Permissions); _header->hideSection(KrViewProperties::KrPermissions); _header->hideSection(KrViewProperties::Owner); _header->hideSection(KrViewProperties::Group); _header->setStretchLastSection(true); _header->setSectionResizeMode(QHeaderView::Fixed); _header->setSectionsClickable(true); _header->setSortIndicatorShown(true); connect(_header, SIGNAL(sortIndicatorChanged(int,Qt::SortOrder)), _model, SLOT(sort(int,Qt::SortOrder))); _header->installEventFilter(this); _numOfColumns = _properties->numberOfColumns; setSortMode(_properties->sortColumn, (_properties->sortOptions & KrViewProperties::Descending)); } void KrInterBriefView::keyPressEvent(QKeyEvent *e) { if (!e || !_model->ready()) return ; // subclass bug if (handleKeyEvent(e)) return; QAbstractItemView::keyPressEvent(e); } bool KrInterBriefView::handleKeyEvent(QKeyEvent *e) { if ((e->key() != Qt::Key_Left && e->key() != Qt::Key_Right) && (KrView::handleKeyEvent(e))) // did the view class handled the event? return true; switch (e->key()) { case Qt::Key_Right : { if (e->modifiers() == Qt::ControlModifier) { // let the panel handle it e->ignore(); break; } KrViewItem *i = getCurrentKrViewItem(); KrViewItem *newCurrent = i; if (!i) break; int num = itemsPerPage() + 1; if (e->modifiers() & Qt::ShiftModifier) i->setSelected(!i->isSelected()); while (i && num > 0) { if (e->modifiers() & Qt::ShiftModifier) i->setSelected(!i->isSelected()); newCurrent = i; i = getNext(i); num--; } if (newCurrent) { setCurrentKrViewItem(newCurrent); makeCurrentVisible(); } if (e->modifiers() & Qt::ShiftModifier) op()->emitSelectionChanged(); return true; } case Qt::Key_Left : { if (e->modifiers() == Qt::ControlModifier) { // let the panel handle it e->ignore(); break; } KrViewItem *i = getCurrentKrViewItem(); KrViewItem *newCurrent = i; if (!i) break; int num = itemsPerPage() + 1; if (e->modifiers() & Qt::ShiftModifier) i->setSelected(!i->isSelected()); while (i && num > 0) { if (e->modifiers() & Qt::ShiftModifier) i->setSelected(!i->isSelected()); newCurrent = i; i = getPrev(i); num--; } if (newCurrent) { setCurrentKrViewItem(newCurrent); makeCurrentVisible(); } if (e->modifiers() & Qt::ShiftModifier) op()->emitSelectionChanged(); return true; } } return false; } void KrInterBriefView::wheelEvent(QWheelEvent *ev) { if (!_mouseHandler->wheelEvent(ev)) QApplication::sendEvent(horizontalScrollBar(), ev); } bool KrInterBriefView::eventFilter(QObject *object, QEvent *event) { if (object == _header) { if (event->type() == QEvent::ContextMenu) { QContextMenuEvent *me = (QContextMenuEvent *)event; showContextMenu(me->globalPos()); return true; } } return false; } void KrInterBriefView::showContextMenu(const QPoint & p) { QMenu popup(this); popup.setTitle(i18n("Columns")); int COL_ID = 14700; for (int i = 1; i <= MAX_BRIEF_COLS; i++) { QAction *act = popup.addAction(QString("%1").arg(i)); act->setData(QVariant(COL_ID + i)); act->setCheckable(true); act->setChecked(properties()->numberOfColumns == i); } QAction * res = popup.exec(p); int result = -1; if (res && res->data().canConvert()) result = res->data().toInt(); if (result > COL_ID && result <= COL_ID + MAX_BRIEF_COLS) { _properties->numberOfColumns = result - COL_ID; _numOfColumns = _properties->numberOfColumns; updateGeometries(); op()->settingsChanged(KrViewProperties::PropColumns); } } QRect KrInterBriefView::visualRect(const QModelIndex&ndx) const { int width = (viewport()->width()) / _numOfColumns; if ((viewport()->width()) % _numOfColumns) width++; int height = getItemHeight(); int numRows = viewport()->height() / height; if (numRows == 0) numRows++; int x = width * (ndx.row() / numRows); int y = height * (ndx.row() % numRows); return mapToViewport(QRect(x, y, width, height)); } void KrInterBriefView::scrollTo(const QModelIndex &ndx, QAbstractItemView::ScrollHint hint) { const QRect rect = visualRect(ndx); if (hint == EnsureVisible && viewport()->rect().contains(rect)) { setDirtyRegion(rect); return; } const QRect area = viewport()->rect(); const bool leftOf = rect.left() < area.left(); const bool rightOf = rect.right() > area.right(); int horizontalValue = horizontalScrollBar()->value(); if (leftOf) horizontalValue -= area.left() - rect.left(); else if (rightOf) horizontalValue += rect.right() - area.right(); horizontalScrollBar()->setValue(horizontalValue); } QModelIndex KrInterBriefView::indexAt(const QPoint& p) const { int x = p.x() + horizontalOffset(); int y = p.y() + verticalOffset(); int itemWidth = (viewport()->width()) / _numOfColumns; if ((viewport()->width()) % _numOfColumns) itemWidth++; int itemHeight = getItemHeight(); int numRows = viewport()->height() / itemHeight; if (numRows == 0) numRows++; int row = y / itemHeight; int col = x / itemWidth; int numColsTotal = _model->rowCount() / numRows; if(_model->rowCount() % numRows) numColsTotal++; if(row < numRows && col < numColsTotal) return _model->index((col * numRows) + row, 0); return QModelIndex(); } QModelIndex KrInterBriefView::moveCursor(QAbstractItemView::CursorAction cursorAction, Qt::KeyboardModifiers) { if (_model->rowCount() == 0) return QModelIndex(); QModelIndex current = currentIndex(); if (!current.isValid()) return _model->index(0, 0); switch (cursorAction) { case MoveLeft: case MovePageDown: { int newRow = current.row() - itemsPerPage(); if (newRow < 0) newRow = 0; return _model->index(newRow, 0); } case MoveRight: case MovePageUp: { int newRow = current.row() + itemsPerPage(); if (newRow >= _model->rowCount()) newRow = _model->rowCount() - 1; return _model->index(newRow, 0); } case MovePrevious: case MoveUp: { int newRow = current.row() - 1; if (newRow < 0) newRow = 0; return _model->index(newRow, 0); } case MoveNext: case MoveDown: { int newRow = current.row() + 1; if (newRow >= _model->rowCount()) newRow = _model->rowCount() - 1; return _model->index(newRow, 0); } case MoveHome: return _model->index(0, 0); case MoveEnd: return _model->index(_model->rowCount() - 1, 0); } return current; } int KrInterBriefView::horizontalOffset() const { return horizontalScrollBar()->value(); } int KrInterBriefView::verticalOffset() const { return 0; } bool KrInterBriefView::isIndexHidden(const QModelIndex&ndx) const { return ndx.column() != 0; } #if 0 QRegion KrInterBriefView::visualRegionForSelection(const QItemSelection &selection) const { if (selection.isEmpty()) return QRegion(); QRegion selectionRegion; for (int i = 0; i < selection.count(); ++i) { QItemSelectionRange range = selection.at(i); if (!range.isValid()) continue; QModelIndex leftIndex = range.topLeft(); if (!leftIndex.isValid()) continue; const QRect leftRect = visualRect(leftIndex); int top = leftRect.top(); QModelIndex rightIndex = range.bottomRight(); if (!rightIndex.isValid()) continue; const QRect rightRect = visualRect(rightIndex); int bottom = rightRect.bottom(); if (top > bottom) qSwap(top, bottom); int height = bottom - top + 1; QRect combined = leftRect | rightRect; combined.setX(range.left()); selectionRegion += combined; } return selectionRegion; } #endif void KrInterBriefView::paintEvent(QPaintEvent *e) { QStyleOptionViewItem option = viewOptions(); option.widget = this; option.decorationSize = QSize(_fileIconSize, _fileIconSize); option.decorationPosition = QStyleOptionViewItem::Left; QPainter painter(viewport()); QModelIndex curr = currentIndex(); QVector intersectVector; QRect area = e->rect(); area.adjust(horizontalOffset(), verticalOffset(), horizontalOffset(), verticalOffset()); intersectionSet(area, intersectVector); foreach(const QModelIndex &mndx, intersectVector) { option.state = QStyle::State_None; option.rect = visualRect(mndx); painter.save(); itemDelegate()->paint(&painter, option, mndx); // (always) draw dashed line border around current item row const bool isCurrent = curr.isValid() && curr.row() == mndx.row(); if (isCurrent) { QStyleOptionFocusRect o; o.QStyleOption::operator=(option); QPalette::ColorGroup cg = QPalette::Normal; o.backgroundColor = option.palette.color(cg, QPalette::Background); style()->drawPrimitive(QStyle::PE_FrameFocusRect, &o, &painter); } painter.restore(); } } int KrInterBriefView::getItemHeight() const { int textHeight = QFontMetrics(_viewFont).height(); int height = textHeight; int iconSize = 0; if (properties()->displayIcons) iconSize = _fileIconSize; if (iconSize > textHeight) height = iconSize; if (height == 0) height++; return height; } void KrInterBriefView::updateGeometries() { if (_header) { QSize hint = _header->sizeHint(); setViewportMargins(0, hint.height(), 0, 0); QRect vg = viewport()->geometry(); QRect geometryRect(vg.left(), vg.top() - hint.height(), vg.width(), hint.height()); _header->setGeometry(geometryRect); int items = 0; for (int i = 0; i != _header->count(); i++) if (!_header->isSectionHidden(i)) items++; if (items == 0) items++; int sectWidth = viewport()->width() / items; for (int i = 0; i != _header->count(); i++) if (!_header->isSectionHidden(i)) _header->resizeSection(i, sectWidth); QMetaObject::invokeMethod(_header, "updateGeometries"); } if (_model->rowCount() <= 0) horizontalScrollBar()->setRange(0, 0); else { int itemsPerColumn = viewport()->height() / getItemHeight(); if (itemsPerColumn <= 0) itemsPerColumn = 1; int columnWidth = (viewport()->width()) / _numOfColumns; if ((viewport()->width()) % _numOfColumns) columnWidth++; int maxWidth = _model->rowCount() / itemsPerColumn; if (_model->rowCount() % itemsPerColumn) maxWidth++; maxWidth *= columnWidth; if (maxWidth > viewport()->width()) { horizontalScrollBar()->setSingleStep(columnWidth); horizontalScrollBar()->setPageStep(columnWidth * _numOfColumns); horizontalScrollBar()->setRange(0, maxWidth - viewport()->width()); } else { horizontalScrollBar()->setRange(0, 0); } } QAbstractItemView::updateGeometries(); } void KrInterBriefView::setSortMode(KrViewProperties::ColumnType sortColumn, bool descending) { Qt::SortOrder sortDir = descending ? Qt::DescendingOrder : Qt::AscendingOrder; _header->setSortIndicator(sortColumn, sortDir); } int KrInterBriefView::elementWidth(const QModelIndex & index) { QString text = index.data(Qt::DisplayRole).toString(); int textWidth = QFontMetrics(_viewFont).width(text); const int textMargin = QApplication::style()->pixelMetric(QStyle::PM_FocusFrameHMargin) + 1; textWidth += 2 * textMargin; QVariant decor = index.data(Qt::DecorationRole); if (decor.isValid() && decor.type() == QVariant::Pixmap) { QPixmap p = decor.value(); textWidth += p.width() + 2 * textMargin; } return textWidth; } void KrInterBriefView::intersectionSet(const QRect &rect, QVector &ndxList) { int maxNdx = _model->rowCount(); int width = (viewport()->width()) / _numOfColumns; if ((viewport()->width()) % _numOfColumns) width++; int height = getItemHeight(); int items = viewport()->height() / height; if (items == 0) items++; int xmin = -1; int ymin = -1; int xmax = -1; int ymax = -1; xmin = rect.x() / width; ymin = rect.y() / height; xmax = (rect.x() + rect.width()) / width; if ((rect.x() + rect.width()) % width) xmax++; ymax = (rect.y() + rect.height()) / height; if ((rect.y() + rect.height()) % height) ymax++; for (int i = ymin; i < ymax; i++) for (int j = xmin; j < xmax; j++) { int ndx = j * items + i; if (ndx < maxNdx) ndxList.append(_model->index(ndx, 0)); } } QRect KrInterBriefView::itemRect(const FileItem *item) { return visualRect(_model->fileItemIndex(item)); } void KrInterBriefView::copySettingsFrom(KrView *other) { if(other->instance() == instance()) { // the other view is of the same type KrInterBriefView *v = static_cast(other); int column = v->_model->lastSortOrder(); Qt::SortOrder sortDir = v->_model->lastSortDir(); _header->setSortIndicator(column, sortDir); _model->sort(column, sortDir); setFileIconSize(v->fileIconSize()); } } void KrInterBriefView::setFileIconSize(int size) { KrView::setFileIconSize(size); setIconSize(QSize(fileIconSize(), fileIconSize())); updateGeometries(); } void KrInterBriefView::currentChanged(const QModelIndex & current, const QModelIndex & previous) { if (_model->ready()) { KrViewItem * item = getKrViewItem(currentIndex()); op()->emitCurrentChanged(item); } QAbstractItemView::currentChanged(current, previous); } void KrInterBriefView::renameCurrentItem() { QModelIndex cIndex = currentIndex(); QModelIndex nameIndex = _model->index(cIndex.row(), KrViewProperties::Name); edit(nameIndex); updateEditorData(); update(nameIndex); } bool KrInterBriefView::event(QEvent * e) { _mouseHandler->otherEvent(e); return QAbstractItemView::event(e); } void KrInterBriefView::mousePressEvent(QMouseEvent * ev) { if (!_mouseHandler->mousePressEvent(ev)) QAbstractItemView::mousePressEvent(ev); } void KrInterBriefView::mouseReleaseEvent(QMouseEvent * ev) { if (!_mouseHandler->mouseReleaseEvent(ev)) QAbstractItemView::mouseReleaseEvent(ev); } void KrInterBriefView::mouseDoubleClickEvent(QMouseEvent *ev) { if (!_mouseHandler->mouseDoubleClickEvent(ev)) QAbstractItemView::mouseDoubleClickEvent(ev); } void KrInterBriefView::mouseMoveEvent(QMouseEvent * ev) { if (!_mouseHandler->mouseMoveEvent(ev)) QAbstractItemView::mouseMoveEvent(ev); } void KrInterBriefView::dragEnterEvent(QDragEnterEvent *ev) { if (!_mouseHandler->dragEnterEvent(ev)) QAbstractItemView::dragEnterEvent(ev); } void KrInterBriefView::dragMoveEvent(QDragMoveEvent *ev) { QAbstractItemView::dragMoveEvent(ev); _mouseHandler->dragMoveEvent(ev); } void KrInterBriefView::dragLeaveEvent(QDragLeaveEvent *ev) { if (!_mouseHandler->dragLeaveEvent(ev)) QAbstractItemView::dragLeaveEvent(ev); } void KrInterBriefView::dropEvent(QDropEvent *ev) { if (!_mouseHandler->dropEvent(ev)) QAbstractItemView::dropEvent(ev); } -bool KrInterBriefView::viewportEvent(QEvent * event) -{ - if (event->type() == QEvent::ToolTip) { - QHelpEvent *he = static_cast(event); - const QModelIndex index = indexAt(he->pos()); - - if (index.isValid()) { - int width = visualRect(index).width(); - int textWidth = elementWidth(index); - - if (textWidth <= width) { - event->accept(); - return true; - } - } - } - return QAbstractItemView::viewportEvent(event); -} - QRect KrInterBriefView::mapToViewport(const QRect &rect) const { if (!rect.isValid()) return rect; QRect result = rect; int dx = -horizontalOffset(); int dy = -verticalOffset(); result.adjust(dx, dy, dx, dy); return result; } diff --git a/krusader/Panel/krinterbriefview.h b/krusader/Panel/krinterbriefview.h index 0e96e98f..88bc0230 100644 --- a/krusader/Panel/krinterbriefview.h +++ b/krusader/Panel/krinterbriefview.h @@ -1,120 +1,119 @@ /***************************************************************************** * Copyright (C) 2009 Csaba Karai * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This package is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this package; if not, write to the Free Software * * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ #ifndef KRINTERBRIEFVIEW_H #define KRINTERBRIEFVIEW_H // QtCore #include // QtGui #include // QtWidgets #include #include #include #include "krinterview.h" /** * @brief Compact view showing only icon and file name of view items */ class KrInterBriefView : public QAbstractItemView, public KrInterView { Q_OBJECT public: KrInterBriefView(QWidget *parent, KrViewInstance &instance, KConfig *cfg); virtual ~KrInterBriefView(); // ---- reimplemented from QAbstractItemView ---- QRect visualRect(const QModelIndex&) const Q_DECL_OVERRIDE; QModelIndex indexAt(const QPoint&) const Q_DECL_OVERRIDE; void scrollTo(const QModelIndex &, QAbstractItemView::ScrollHint = QAbstractItemView::EnsureVisible) Q_DECL_OVERRIDE; // ---- reimplemented from KrView ---- int itemsPerPage() Q_DECL_OVERRIDE; void updateView() Q_DECL_OVERRIDE; bool ensureVisibilityAfterSelect() Q_DECL_OVERRIDE { return false; } void setSortMode(KrViewProperties::ColumnType sortColumn, bool descending) Q_DECL_OVERRIDE; // ---- reimplemented from QAbstractItemView ---- // Don't do anything, selections are handled by the mouse handler void setSelection(const QRect &, QItemSelectionModel::SelectionFlags) Q_DECL_OVERRIDE {} void selectAll() Q_DECL_OVERRIDE {} // this shouldn't be called QRegion visualRegionForSelection(const QItemSelection&) const Q_DECL_OVERRIDE { return QRegion(); } // ---- reimplemented from KrView ---- void setFileIconSize(int size) Q_DECL_OVERRIDE; protected slots: // ---- reimplemented from QAbstractItemView ---- void updateGeometries() Q_DECL_OVERRIDE; // ---- reimplemented from KrView ---- void currentChanged(const QModelIndex & current, const QModelIndex & previous) Q_DECL_OVERRIDE; void renameCurrentItem() Q_DECL_OVERRIDE; protected: // ---- reimplemented from KrView ---- bool handleKeyEvent(QKeyEvent *e) Q_DECL_OVERRIDE; // ---- reimplemented from QAbstractItemView ---- bool eventFilter(QObject *object, QEvent *event) Q_DECL_OVERRIDE; void keyPressEvent(QKeyEvent *e) Q_DECL_OVERRIDE; void paintEvent(QPaintEvent *e) Q_DECL_OVERRIDE; QModelIndex moveCursor(QAbstractItemView::CursorAction, Qt::KeyboardModifiers) Q_DECL_OVERRIDE; int horizontalOffset() const Q_DECL_OVERRIDE; int verticalOffset() const Q_DECL_OVERRIDE; bool isIndexHidden(const QModelIndex&) const Q_DECL_OVERRIDE; // QRegion visualRegionForSelection(const QItemSelection&) const Q_DECL_OVERRIDE; bool event(QEvent * e) Q_DECL_OVERRIDE; void mousePressEvent(QMouseEvent *) Q_DECL_OVERRIDE; void mouseReleaseEvent(QMouseEvent *) Q_DECL_OVERRIDE; void mouseDoubleClickEvent(QMouseEvent *ev) Q_DECL_OVERRIDE; void mouseMoveEvent(QMouseEvent *) Q_DECL_OVERRIDE; void wheelEvent(QWheelEvent *) Q_DECL_OVERRIDE; void dragEnterEvent(QDragEnterEvent *e) Q_DECL_OVERRIDE; void dragMoveEvent(QDragMoveEvent *e) Q_DECL_OVERRIDE; void dragLeaveEvent(QDragLeaveEvent *e) Q_DECL_OVERRIDE; void dropEvent(QDropEvent *) Q_DECL_OVERRIDE; - bool viewportEvent(QEvent * event) Q_DECL_OVERRIDE; // ---- reimplemented from KrView ---- void setup() Q_DECL_OVERRIDE; void doRestoreSettings(KConfigGroup group) Q_DECL_OVERRIDE; void saveSettings(KConfigGroup grp, KrViewProperties::PropertyType properties) Q_DECL_OVERRIDE; void copySettingsFrom(KrView *other) Q_DECL_OVERRIDE; QRect itemRect(const FileItem *fileitem) Q_DECL_OVERRIDE; void showContextMenu(const QPoint & p) Q_DECL_OVERRIDE; QRect mapToViewport(const QRect &rect) const; int getItemHeight() const; int elementWidth(const QModelIndex & index); void intersectionSet(const QRect &, QVector &); private: QFont _viewFont; int _numOfColumns; QHeaderView * _header; }; #endif // KRINTERBRIEFVIEW_H diff --git a/krusader/Panel/krinterdetailedview.cpp b/krusader/Panel/krinterdetailedview.cpp index 7cdd17c9..16f1b2b3 100644 --- a/krusader/Panel/krinterdetailedview.cpp +++ b/krusader/Panel/krinterdetailedview.cpp @@ -1,421 +1,429 @@ /***************************************************************************** * Copyright (C) 2002 Shie Erlich * * Copyright (C) 2002 Rafi Yanai * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This package is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this package; if not, write to the Free Software * * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ #include "krinterdetailedview.h" // QtCore #include #include // QtWidgets +#include #include #include #include -#include +#include #include #include #include #include "krviewfactory.h" #include "krviewitemdelegate.h" #include "krviewitem.h" #include "krvfsmodel.h" #include "../FileSystem/krpermhandler.h" #include "../defaults.h" #include "../krglobal.h" #include "krmousehandler.h" #include "krcolorcache.h" #include "../GUI/krstyleproxy.h" KrInterDetailedView::KrInterDetailedView(QWidget *parent, KrViewInstance &instance, KConfig *cfg): QTreeView(parent), KrInterView(instance, cfg, this), _autoResizeColumns(true) { connect(_mouseHandler, SIGNAL(renameCurrentItem()), this, SLOT(renameCurrentItem())); setWidget(this); KConfigGroup grpSvr(_config, "Look&Feel"); _viewFont = grpSvr.readEntry("Filelist Font", _FilelistFont); setModel(_model); setRootIsDecorated(false); setItemsExpandable(false); setAllColumnsShowFocus(true); setUniformRowHeights(true); - KrStyleProxy *krstyle = new KrStyleProxy(); - krstyle->setParent(this); - setStyle(krstyle); - setItemDelegate(new KrViewItemDelegate(this)); setMouseTracking(true); setAcceptDrops(true); setDropIndicatorShown(true); setSelectionMode(QAbstractItemView::NoSelection); setSelectionModel(new DummySelectionModel(_model, this)); header()->installEventFilter(this); header()->setSectionResizeMode(QHeaderView::Interactive); header()->setStretchLastSection(false); + KrStyleProxy *style = new KrStyleProxy(); + style->setParent(this); + setStyle(style); + viewport()->setStyle(style); // for custom tooltip delay + + setItemDelegate(new KrViewItemDelegate(this)); + connect(header(), SIGNAL(sectionResized(int,int,int)), this, SLOT(sectionResized(int,int,int))); connect(header(), SIGNAL(sectionMoved(int,int,int)), this, SLOT(sectionMoved(int,int,int))); } KrInterDetailedView::~KrInterDetailedView() { delete _properties; _properties = 0; delete _operator; _operator = 0; } void KrInterDetailedView::currentChanged(const QModelIndex & current, const QModelIndex & previous) { if (_model->ready()) { KrViewItem * item = getKrViewItem(currentIndex()); op()->emitCurrentChanged(item); } QTreeView::currentChanged(current, previous); } void KrInterDetailedView::doRestoreSettings(KConfigGroup grp) { _autoResizeColumns = grp.readEntry("AutoResizeColumns", true); QByteArray savedState = grp.readEntry("Saved State", QByteArray()); if (savedState.isEmpty()) { hideColumn(KrViewProperties::Type); hideColumn(KrViewProperties::Permissions); hideColumn(KrViewProperties::Owner); hideColumn(KrViewProperties::Group); header()->resizeSection(KrViewProperties::Ext, QFontMetrics(_viewFont).width("tar.bz2 ")); header()->resizeSection(KrViewProperties::KrPermissions, QFontMetrics(_viewFont).width("rwx ")); header()->resizeSection(KrViewProperties::Size, QFontMetrics(_viewFont).width("9") * 10); QDateTime tmp(QDate(2099, 12, 29), QTime(23, 59)); QString desc = QLocale().toString(tmp, QLocale::ShortFormat) + " "; header()->resizeSection(KrViewProperties::Modified, QFontMetrics(_viewFont).width(desc)); } else { header()->restoreState(savedState); _model->setExtensionEnabled(!isColumnHidden(KrViewProperties::Ext)); } KrInterView::doRestoreSettings(grp); } void KrInterDetailedView::saveSettings(KConfigGroup grp, KrViewProperties::PropertyType properties) { KrInterView::saveSettings(grp, properties); grp.writeEntry("AutoResizeColumns", _autoResizeColumns); if(properties & KrViewProperties::PropColumns) { QByteArray state = header()->saveState(); grp.writeEntry("Saved State", state); } } int KrInterDetailedView::itemsPerPage() { QRect rect = visualRect(currentIndex()); if (!rect.isValid()) { for (int i = 0; i != _model->rowCount(); i++) { rect = visualRect(_model->index(i, 0)); if (rect.isValid()) break; } } if (!rect.isValid()) return 0; int size = (height() - header()->height()) / rect.height(); if (size < 0) size = 0; return size; } void KrInterDetailedView::updateView() { } void KrInterDetailedView::setup() { setSortMode(_properties->sortColumn, (_properties->sortOptions & KrViewProperties::Descending)); setSortingEnabled(true); } void KrInterDetailedView::keyPressEvent(QKeyEvent *e) { if (!e || !_model->ready()) return ; // subclass bug if (handleKeyEvent(e)) // did the view class handled the event? return; QTreeView::keyPressEvent(e); } void KrInterDetailedView::mousePressEvent(QMouseEvent * ev) { if (!_mouseHandler->mousePressEvent(ev)) QTreeView::mousePressEvent(ev); } void KrInterDetailedView::mouseReleaseEvent(QMouseEvent * ev) { if (!_mouseHandler->mouseReleaseEvent(ev)) QTreeView::mouseReleaseEvent(ev); } void KrInterDetailedView::mouseDoubleClickEvent(QMouseEvent *ev) { if (!_mouseHandler->mouseDoubleClickEvent(ev)) QTreeView::mouseDoubleClickEvent(ev); } void KrInterDetailedView::mouseMoveEvent(QMouseEvent * ev) { if (!_mouseHandler->mouseMoveEvent(ev)) QTreeView::mouseMoveEvent(ev); } void KrInterDetailedView::wheelEvent(QWheelEvent *ev) { if (!_mouseHandler->wheelEvent(ev)) QTreeView::wheelEvent(ev); } void KrInterDetailedView::dragEnterEvent(QDragEnterEvent *ev) { if (!_mouseHandler->dragEnterEvent(ev)) QTreeView::dragEnterEvent(ev); } void KrInterDetailedView::dragMoveEvent(QDragMoveEvent *ev) { QTreeView::dragMoveEvent(ev); _mouseHandler->dragMoveEvent(ev); } void KrInterDetailedView::dragLeaveEvent(QDragLeaveEvent *ev) { if (!_mouseHandler->dragLeaveEvent(ev)) QTreeView::dragLeaveEvent(ev); } void KrInterDetailedView::dropEvent(QDropEvent *ev) { if (!_mouseHandler->dropEvent(ev)) QTreeView::dropEvent(ev); } bool KrInterDetailedView::event(QEvent * e) { _mouseHandler->otherEvent(e); return QTreeView::event(e); } void KrInterDetailedView::renameCurrentItem() { QModelIndex cIndex = currentIndex(); QModelIndex nameIndex = _model->index(cIndex.row(), KrViewProperties::Name); edit(nameIndex); updateEditorData(); update(nameIndex); } bool KrInterDetailedView::eventFilter(QObject *object, QEvent *event) { if (object == header()) { if (event->type() == QEvent::ContextMenu) { QContextMenuEvent *me = (QContextMenuEvent *)event; showContextMenu(me->globalPos()); return true; } else if (event->type() == QEvent::Resize) { recalculateColumnSizes(); return false; } } return false; } void KrInterDetailedView::showContextMenu(const QPoint & p) { QMenu popup(this); popup.setTitle(i18n("Columns")); QVector actions; for(int i = KrViewProperties::Ext; i < KrViewProperties::MAX_COLUMNS; i++) { QString text = (_model->headerData(i, Qt::Horizontal)).toString(); QAction *act = popup.addAction(text); act->setCheckable(true); act->setChecked(!header()->isSectionHidden(i)); act->setData(i); actions.append(act); } popup.addSeparator(); QAction *actAutoResize = popup.addAction(i18n("Automatically Resize Columns")); actAutoResize->setCheckable(true); actAutoResize->setChecked(_autoResizeColumns); QAction *res = popup.exec(p); if (res == 0) return; if(res == actAutoResize) { _autoResizeColumns = actAutoResize->isChecked(); recalculateColumnSizes(); } else { int column = res->data().toInt(); if(header()->isSectionHidden(column)) header()->showSection(column); else header()->hideSection(column); if(KrViewProperties::Ext == column) _model->setExtensionEnabled(!header()->isSectionHidden(KrViewProperties::Ext)); } op()->settingsChanged(KrViewProperties::PropColumns); } void KrInterDetailedView::sectionResized(int /*column*/, int oldSize, int newSize) { // *** taken from dolphin *** // If the user changes the size of the headers, the autoresize feature should be // turned off. As there is no dedicated interface to find out whether the header // section has been resized by the user or by a resize event, another approach is used. // Attention: Take care when changing the if-condition to verify that there is no // regression in combination with bug 178630 (see fix in comment #8). if ((QApplication::mouseButtons() & Qt::LeftButton) && header()->underMouse()) { _autoResizeColumns = false; op()->settingsChanged(KrViewProperties::PropColumns); } if (oldSize == newSize || !_model->ready()) return; recalculateColumnSizes(); } void KrInterDetailedView::sectionMoved(int /*logicalIndex*/, int /*oldVisualIndex*/, int /*newVisualIndex*/) { op()->settingsChanged(KrViewProperties::PropColumns); } void KrInterDetailedView::recalculateColumnSizes() { if(!_autoResizeColumns) return; int sum = 0; for (int i = 0; i != _model->columnCount(); i++) { if (!isColumnHidden(i)) sum += header()->sectionSize(i); } if (sum != header()->width()) { int delta = sum - header()->width(); int nameSize = header()->sectionSize(KrViewProperties::Name); if (nameSize - delta > 20) header()->resizeSection(KrViewProperties::Name, nameSize - delta); } } bool KrInterDetailedView::viewportEvent(QEvent * event) { if (event->type() == QEvent::ToolTip) { + // only show tooltip if column is not wide enough to show all text. In this case the column + // data text is abbreviated and the full text is shown as tooltip, see KrVfsModel::data(). + QHelpEvent *he = static_cast(event); const QModelIndex index = indexAt(he->pos()); - - if (index.isValid()) { + // name column has a detailed tooltip + if (index.isValid() && index.column() != KrViewProperties::Name) { int width = header()->sectionSize(index.column()); QString text = index.data(Qt::DisplayRole).toString(); int textWidth = QFontMetrics(_viewFont).width(text); const int textMargin = QApplication::style()->pixelMetric(QStyle::PM_FocusFrameHMargin) + 1; textWidth += 2 * textMargin; QVariant decor = index.data(Qt::DecorationRole); if (decor.isValid() && decor.type() == QVariant::Pixmap) { QPixmap p = decor.value(); textWidth += p.width() + 2 * textMargin; } if (textWidth <= width) { + QToolTip::hideText(); event->accept(); return true; } } } return QTreeView::viewportEvent(event); } void KrInterDetailedView::drawRow(QPainter *painter, const QStyleOptionViewItem &options, const QModelIndex &index) const { QTreeView::drawRow(painter, options, index); // (always) draw dashed line border around current item row. This is done internally in // QTreeView::drawRow() only when panel is focused, we have to repeat it here. if (index == currentIndex()) { QStyleOptionFocusRect o; o.backgroundColor = options.palette.color(QPalette::Normal, QPalette::Background); const QRect focusRect(0, options.rect.y(), header()->length(), options.rect.height()); o.rect = style()->visualRect(layoutDirection(), viewport()->rect(), focusRect); style()->drawPrimitive(QStyle::PE_FrameFocusRect, &o, painter); } } void KrInterDetailedView::setSortMode(KrViewProperties::ColumnType sortColumn, bool descending) { Qt::SortOrder sortDir = descending ? Qt::DescendingOrder : Qt::AscendingOrder; sortByColumn(sortColumn, sortDir); } void KrInterDetailedView::setFileIconSize(int size) { KrView::setFileIconSize(size); setIconSize(QSize(fileIconSize(), fileIconSize())); } QRect KrInterDetailedView::itemRect(const FileItem *item) { QRect r = visualRect(_model->fileItemIndex(item)); r.setLeft(0); r.setWidth(header()->length()); return r; } void KrInterDetailedView::copySettingsFrom(KrView *other) { if(other->instance() == instance()) { // the other view is of the same type KrInterDetailedView *v = static_cast(other); _autoResizeColumns = v->_autoResizeColumns; header()->restoreState(v->header()->saveState()); _model->setExtensionEnabled(!isColumnHidden(KrViewProperties::Ext)); recalculateColumnSizes(); setFileIconSize(v->fileIconSize()); } } diff --git a/krusader/Panel/krsort.cpp b/krusader/Panel/krsort.cpp index 24b90d22..3a754b55 100644 --- a/krusader/Panel/krsort.cpp +++ b/krusader/Panel/krsort.cpp @@ -1,356 +1,344 @@ /***************************************************************************** * Copyright (C) 2002 Shie Erlich * * Copyright (C) 2002 Rafi Yanai * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This package is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this package; if not, write to the Free Software * * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ #include "krsort.h" -// QtCore -#include -#include - #include "krview.h" #include "../FileSystem/fileitem.h" -#include "../FileSystem/krpermhandler.h" namespace KrSort { void SortProps::init(FileItem *fileitem, int col, const KrViewProperties * props, bool isDummy, bool asc, int origNdx, QVariant customData) { _col = col; _prop = props; _isdummy = isDummy; _ascending = asc; _fileItem = fileitem; _index = origNdx; _name = fileitem->getName(); _customData = customData; if(_prop->sortOptions & KrViewProperties::IgnoreCase) _name = _name.toLower(); switch (_col) { case KrViewProperties::Ext: { if (fileitem->isDir()) { _ext = ""; } else { // check if the file has an extension const QString& fileitemName = fileitem->getName(); int loc = fileitemName.lastIndexOf('.'); if (loc > 0) { // avoid mishandling of .bashrc and friend // check if it has one of the predefined 'atomic extensions' for (QStringList::const_iterator i = props->atomicExtensions.begin(); i != props->atomicExtensions.end(); ++i) { if (fileitemName.endsWith(*i) && fileitemName != *i) { loc = fileitemName.length() - (*i).length(); break; } } _ext = _name.mid(loc); } else _ext = ""; } break; } case KrViewProperties::Type: { if (isDummy) _data = ""; else { - QMimeDatabase db; - QMimeType mt = db.mimeTypeForName(fileitem->getMime()); - if (mt.isValid()) - _data = mt.comment(); + _data = KrView::mimeTypeText(fileitem); } break; } case KrViewProperties::Permissions: { if (isDummy) _data = ""; else { - if (properties()->numericPermissions) { - QString perm; - _data = perm.sprintf("%.4o", fileitem->getMode() & PERM_BITMASK); - } else - _data = fileitem->getPerm(); + _data = KrView::permissionsText(properties(), fileitem); } break; } case KrViewProperties::KrPermissions: { if (isDummy) _data = ""; else { - _data = KrView::krPermissionString(fileitem); + _data = KrView::krPermissionText(fileitem); } break; } case KrViewProperties::Owner: { if (isDummy) _data = ""; else _data = fileitem->getOwner(); } case KrViewProperties::Group: { if (isDummy) _data = ""; else _data = fileitem->getGroup(); } default: break; } } // compares numbers within two strings int compareNumbers(QString& aS1, int& aPos1, QString& aS2, int& aPos2) { int res = 0; int start1 = aPos1; int start2 = aPos2; while (aPos1 < aS1.length() && aS1.at(aPos1).isDigit()) aPos1++; while (aPos2 < aS2.length() && aS2.at(aPos2).isDigit()) aPos2++; // the left-most difference determines what's bigger int i1 = aPos1 - 1; int i2 = aPos2 - 1; for (; i1 >= start1 || i2 >= start2; i1--, i2--) { int c1 = 0; int c2 = 0; if (i1 >= start1) c1 = aS1.at(i1).digitValue(); if (i2 >= start2) c2 = aS2.at(i2).digitValue(); if (c1 < c2) res = -1; else if (c1 > c2) res = 1; } return res; } bool compareTextsAlphabetical(QString& aS1, QString& aS2, const KrViewProperties * _viewProperties, bool aNumbers) { int lPositionS1 = 0; int lPositionS2 = 0; // sometimes, localeAwareCompare is not case sensitive. in that case, we need to fallback to a simple string compare (KDE bug #40131) bool lUseLocaleAware = ((_viewProperties->sortOptions & KrViewProperties::IgnoreCase) || _viewProperties->localeAwareCompareIsCaseSensitive) && (_viewProperties->sortOptions & KrViewProperties::LocaleAwareSort); int j = 0; QChar lchar1; QChar lchar2; while (true) { lchar1 = aS1[lPositionS1]; lchar2 = aS2[lPositionS2]; // detect numbers if (aNumbers && lchar1.isDigit() && lchar2.isDigit()) { int j = compareNumbers(aS1, lPositionS1, aS2, lPositionS2); if (j != 0) return j < 0; } else if (lUseLocaleAware && ((lchar1 >= 128 && ((lchar2 >= 'A' && lchar2 <= 'Z') || (lchar2 >= 'a' && lchar2 <= 'z') || lchar2 >= 128)) || (lchar2 >= 128 && ((lchar1 >= 'A' && lchar1 <= 'Z') || (lchar1 >= 'a' && lchar1 <= 'z') || lchar1 >= 128)) ) ) { // use localeAwareCompare when a unicode character is encountered j = QString::localeAwareCompare(lchar1, lchar2); if (j != 0) return j < 0; lPositionS1++; lPositionS2++; } else { // if characters are latin or localeAwareCompare is not case sensitive then use simple characters compare is enough if (lchar1 < lchar2) return true; if (lchar1 > lchar2) return false; lPositionS1++; lPositionS2++; } // at this point strings are equal, check if ends of strings are reached if (lPositionS1 == aS1.length() && lPositionS2 == aS2.length()) return false; if (lPositionS1 == aS1.length() && lPositionS2 < aS2.length()) return true; if (lPositionS1 < aS1.length() && lPositionS2 == aS2.length()) return false; } } bool compareTextsCharacterCode(QString& aS1, QString& aS2, const KrViewProperties * _viewProperties, bool aNumbers) { Q_UNUSED(_viewProperties); int lPositionS1 = 0; int lPositionS2 = 0; while (true) { // detect numbers if (aNumbers && aS1[lPositionS1].isDigit() && aS2[lPositionS2].isDigit()) { int j = compareNumbers(aS1, lPositionS1, aS2, lPositionS2); if (j != 0) return j < 0; } else { if (aS1[lPositionS1] < aS2[lPositionS2]) return true; if (aS1[lPositionS1] > aS2[lPositionS2]) return false; lPositionS1++; lPositionS2++; } // at this point strings are equal, check if ends of strings are reached if (lPositionS1 == aS1.length() && lPositionS2 == aS2.length()) return false; if (lPositionS1 == aS1.length() && lPositionS2 < aS2.length()) return true; if (lPositionS1 < aS1.length() && lPositionS2 == aS2.length()) return false; } } bool compareTextsKrusader(const QString &aS1, const QString &aS2, const KrViewProperties *_viewProperties) { // sometimes, localeAwareCompare is not case sensitive. in that case, we need to fallback to a simple string compare (KDE bug #40131) if (((_viewProperties->sortOptions & KrViewProperties::IgnoreCase) || _viewProperties->localeAwareCompareIsCaseSensitive) && (_viewProperties->sortOptions & KrViewProperties::LocaleAwareSort)) return QString::localeAwareCompare(aS1, aS2) < 0; else // if localeAwareCompare is not case sensitive then use simple compare is enough return QString::compare(aS1, aS2) < 0; } bool compareTexts(QString aS1, QString aS2, const KrViewProperties * _viewProperties, bool asc, bool isName) { //check empty strings if (aS1.length() == 0 && aS2.length() == 0) { return false; } else if (aS1.length() == 0) { return true; } else if (aS2.length() == 0) { return false; } if (isName) { if (aS1 == "..") { return !asc; } else { if (aS2 == "..") return asc; } } switch (_viewProperties->sortMethod) { case KrViewProperties::Alphabetical: return compareTextsAlphabetical(aS1, aS2, _viewProperties, false); case KrViewProperties::AlphabeticalNumbers: return compareTextsAlphabetical(aS1, aS2, _viewProperties, true); case KrViewProperties::CharacterCode: return compareTextsCharacterCode(aS1, aS2, _viewProperties, false); case KrViewProperties::CharacterCodeNumbers: return compareTextsCharacterCode(aS1, aS2, _viewProperties, true); case KrViewProperties::Krusader: default: return compareTextsKrusader(aS1, aS2, _viewProperties); } } bool itemLessThan(SortProps *sp, SortProps *sp2) { FileItem * file1 = sp->fileitem(); FileItem * file2 = sp2->fileitem(); bool isdir1 = file1->isDir(); bool isdir2 = file2->isDir(); bool dirsFirst = sp->properties()->sortOptions & KrViewProperties::DirsFirst; bool alwaysSortDirsByName = sp->properties()->sortOptions & KrViewProperties::AlwaysSortDirsByName && dirsFirst && isdir1 && isdir2; if(dirsFirst) { if (isdir1 && !isdir2) return sp->isAscending(); if (isdir2 && !isdir1) return !sp->isAscending(); } if (sp->isDummy()) return sp->isAscending(); if (sp2->isDummy()) return !sp->isAscending(); int column = sp->column(); if (dirsFirst && isdir1 && isdir2 && alwaysSortDirsByName) { alwaysSortDirsByName = !sp->isAscending(); column = KrViewProperties::Name; } switch (column) { case KrViewProperties::Name: return compareTexts(sp->name(), sp2->name(), sp->properties(), sp->isAscending(), true) ^ alwaysSortDirsByName; case KrViewProperties::Ext: if (sp->extension() == sp2->extension()) return compareTexts(sp->name(), sp2->name(), sp->properties(), sp->isAscending(), true); return compareTexts(sp->extension(), sp2->extension(), sp->properties(), sp->isAscending(), true); case KrViewProperties::Size: if (file1->getSize() == file2->getSize()) return compareTexts(sp->name(), sp2->name(), sp->properties(), sp->isAscending(), true); return file1->getSize() < file2->getSize(); case KrViewProperties::Modified: if (file1->getTime_t() == file2->getTime_t()) return compareTexts(sp->name(), sp2->name(), sp->properties(), sp->isAscending(), true); return file1->getTime_t() < file2->getTime_t(); case KrViewProperties::Type: case KrViewProperties::Permissions: case KrViewProperties::KrPermissions: case KrViewProperties::Owner: case KrViewProperties::Group: if (sp->data() == sp2->data()) return compareTexts(sp->name(), sp2->name(), sp->properties(), sp->isAscending(), true); return compareTexts(sp->data(), sp2->data(), sp->properties(), sp->isAscending(), true); } return sp->name() < sp2->name(); } bool itemGreaterThan(SortProps *sp, SortProps *sp2) { return !itemLessThan(sp, sp2); } Sorter::Sorter(int reserveItems, const KrViewProperties *viewProperties, LessThanFunc lessThanFunc, LessThanFunc greaterThanFunc) : _viewProperties(viewProperties), _lessThanFunc(lessThanFunc), _greaterThanFunc(greaterThanFunc) { _items.reserve(reserveItems); _itemStore.reserve(reserveItems); } void Sorter::addItem(FileItem *fileitem, bool isDummy, int idx, QVariant customData) { _itemStore << SortProps(fileitem, _viewProperties->sortColumn, _viewProperties, isDummy, !descending(), idx, customData); _items << &_itemStore.last(); } void Sorter::sort() { qStableSort(_items.begin(), _items.end(), descending() ? _greaterThanFunc : _lessThanFunc); } int Sorter::insertIndex(FileItem *fileitem, bool isDummy, QVariant customData) { SortProps props(fileitem, _viewProperties->sortColumn, _viewProperties, isDummy, !descending(), -1, customData); const QVector::iterator it = qLowerBound(_items.begin(), _items.end(), &props, descending() ? _greaterThanFunc : _lessThanFunc); if(it != _items.end()) return _items.indexOf((*it)); else return _items.count(); } bool Sorter::descending() const { return _viewProperties->sortOptions & KrViewProperties::Descending; } } // namespace KrSort diff --git a/krusader/Panel/krsort.h b/krusader/Panel/krsort.h index dc49d996..21d79d2c 100644 --- a/krusader/Panel/krsort.h +++ b/krusader/Panel/krsort.h @@ -1,125 +1,123 @@ /***************************************************************************** * Copyright (C) 2002 Shie Erlich * * Copyright (C) 2002 Rafi Yanai * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This package is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this package; if not, write to the Free Software * * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ #ifndef KRSORT_H #define KRSORT_H // QtCore #include #include #include -#define PERM_BITMASK (S_ISUID|S_ISGID|S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO) - class FileItem; class KrViewProperties; namespace KrSort { class SortProps { public: SortProps() {} SortProps(const SortProps& other) { init(other.fileitem(), other.column(), other.properties(), other.isDummy(), other.isAscending(), other.originalIndex(), other.customData()); } SortProps(FileItem *fileitem, int col, const KrViewProperties * props, bool isDummy, bool asc, int origNdx, QVariant customData) { init(fileitem, col, props, isDummy, asc, origNdx, customData); } inline int column() const { return _col; } inline const KrViewProperties * properties() const { return _prop; } inline bool isDummy() const { return _isdummy; } inline bool isAscending() const { return _ascending; } inline QString name() const { return _name; } inline QString extension() const { return _ext; } inline FileItem * fileitem() const { return _fileItem; } inline int originalIndex() const { return _index; } inline QString data() const { return _data; } inline const QVariant& customData() const { return _customData; } private: void init(FileItem *fileitem, int col, const KrViewProperties * props, bool isDummy, bool asc, int origNdx, QVariant customData); int _col; const KrViewProperties * _prop; bool _isdummy; FileItem * _fileItem; bool _ascending; QString _name; QString _ext; int _index; QString _data; QVariant _customData; }; bool compareTexts(QString aS1, QString aS2, const KrViewProperties * _viewProperties, bool asc, bool isName); bool itemLessThan(SortProps *sp, SortProps *sp2); bool itemGreaterThan(SortProps *sp, SortProps *sp2); typedef bool(*LessThanFunc)(SortProps*, SortProps*); class Sorter { public: Sorter(int reserveItems, const KrViewProperties *viewProperties, LessThanFunc lessThanFunc, LessThanFunc greaterThanFunc); Sorter(const Sorter &other); const QVector &items() const { return _items; } void sort(); void addItem(FileItem *fileitem, bool isDummy, int idx, QVariant customData); int insertIndex(FileItem *fileitem, bool isDummy, QVariant customData); private: bool descending() const; const KrViewProperties *_viewProperties; QVector _items; QVector _itemStore; LessThanFunc _lessThanFunc, _greaterThanFunc; }; } // namespace KrSort #endif // KRSORT_H diff --git a/krusader/Panel/krvfsmodel.cpp b/krusader/Panel/krvfsmodel.cpp index a90edc7e..f1cc4941 100644 --- a/krusader/Panel/krvfsmodel.cpp +++ b/krusader/Panel/krvfsmodel.cpp @@ -1,579 +1,597 @@ /***************************************************************************** * Copyright (C) 2002 Shie Erlich * * Copyright (C) 2002 Rafi Yanai * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This package is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this package; if not, write to the Free Software * * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ #include "krvfsmodel.h" #include "krcolorcache.h" #include "krinterview.h" #include "krpanel.h" #include "krview.h" #include "../defaults.h" #include "../krglobal.h" #include "../FileSystem/fileitem.h" -#include "../FileSystem/krpermhandler.h" - -// QtCore -#include -#include -#include -#include #include #include KrVfsModel::KrVfsModel(KrInterView * view): QAbstractListModel(0), _extensionEnabled(true), _view(view), _dummyFileItem(0), _ready(false), _justForSizeHint(false), _alternatingTable(false) { KConfigGroup grpSvr(krConfig, "Look&Feel"); _defaultFont = grpSvr.readEntry("Filelist Font", _FilelistFont); } void KrVfsModel::populate(const QList &files, FileItem *dummy) { _fileItems = files; _dummyFileItem = dummy; _ready = true; if(lastSortOrder() != KrViewProperties::NoColumn) sort(); else { emit layoutAboutToBeChanged(); for(int i = 0; i < _fileItems.count(); i++) { updateIndices(_fileItems[i], i); } emit layoutChanged(); } } KrVfsModel::~KrVfsModel() { } void KrVfsModel::clear(bool emitLayoutChanged) { if(!_fileItems.count()) return; emit layoutAboutToBeChanged(); // clear persistent indexes QModelIndexList oldPersistentList = persistentIndexList(); QModelIndexList newPersistentList; newPersistentList.reserve(oldPersistentList.size()); for (int i=0; i< oldPersistentList.size(); ++i) newPersistentList.append(QModelIndex()); changePersistentIndexList(oldPersistentList, newPersistentList); _fileItems.clear(); _fileItemNdx.clear(); _nameNdx.clear(); _urlNdx.clear(); _dummyFileItem = 0; if (emitLayoutChanged) emit layoutChanged(); } int KrVfsModel::rowCount(const QModelIndex& /*parent*/) const { return _fileItems.count(); } int KrVfsModel::columnCount(const QModelIndex& /*parent*/) const { return KrViewProperties::MAX_COLUMNS; } QVariant KrVfsModel::data(const QModelIndex& index, int role) const { if (!index.isValid() || index.row() >= rowCount()) return QVariant(); FileItem *fileitem = _fileItems.at(index.row()); if (fileitem == 0) return QVariant(); switch (role) { case Qt::FontRole: return _defaultFont; case Qt::EditRole: { if (index.column() == 0) { return fileitem->getName(); } return QVariant(); } case Qt::UserRole: { if (index.column() == 0) { return nameWithoutExtension(fileitem, false); } return QVariant(); } - case Qt::ToolTipRole: + case Qt::ToolTipRole: { + if (index.column() == KrViewProperties::Name) { + return fileitem == _dummyFileItem ? QVariant() : toolTipText(fileitem); + } + // breaktrough + } case Qt::DisplayRole: { switch (index.column()) { case KrViewProperties::Name: { return nameWithoutExtension(fileitem); } case KrViewProperties::Ext: { QString nameOnly = nameWithoutExtension(fileitem); const QString& fileitemName = fileitem->getName(); return fileitemName.mid(nameOnly.length() + 1); } case KrViewProperties::Size: { if (fileitem->isDir() && fileitem->getSize() <= 0) { //HACK add <> brackets AFTER translating - otherwise KUIT thinks it's a tag static QString label = QString("<") + i18nc("Show the string 'DIR' instead of file size in detailed view (for folders)", "DIR") + '>'; return label; } else - return KrView::sizeToString(properties(), fileitem->getSize()); + return KrView::sizeText(properties(), fileitem->getSize()); } case KrViewProperties::Type: { if (fileitem == _dummyFileItem) return QVariant(); - QMimeDatabase db; - QMimeType mt = db.mimeTypeForName(fileitem->getMime()); - if (mt.isValid()) - return mt.comment(); - return QVariant(); + const QString mimeType = KrView::mimeTypeText(fileitem); + return mimeType.isEmpty() ? QVariant() : mimeType; } case KrViewProperties::Modified: { if (fileitem == _dummyFileItem) return QVariant(); - time_t time = fileitem->getTime_t(); - struct tm* t = localtime((time_t *) & time); - - QDateTime tmp(QDate(t->tm_year + 1900, t->tm_mon + 1, t->tm_mday), QTime(t->tm_hour, t->tm_min)); - return QLocale().toString(tmp, QLocale::ShortFormat); + return dateText(fileitem->getTime_t()); } case KrViewProperties::Permissions: { if (fileitem == _dummyFileItem) return QVariant(); - if (properties()->numericPermissions) { - QString perm; - return perm.sprintf("%.4o", fileitem->getMode() & PERM_BITMASK); - } - return fileitem->getPerm(); + return KrView::permissionsText(properties(), fileitem); } case KrViewProperties::KrPermissions: { if (fileitem == _dummyFileItem) return QVariant(); - return KrView::krPermissionString(fileitem); + return KrView::krPermissionText(fileitem); } case KrViewProperties::Owner: { if (fileitem == _dummyFileItem) return QVariant(); return fileitem->getOwner(); } case KrViewProperties::Group: { if (fileitem == _dummyFileItem) return QVariant(); return fileitem->getGroup(); } default: return QString(); } return QVariant(); } case Qt::DecorationRole: { switch (index.column()) { case KrViewProperties::Name: { if (properties()->displayIcons) { if (_justForSizeHint) return QPixmap(_view->fileIconSize(), _view->fileIconSize()); return _view->getIcon(fileitem); } break; } default: break; } return QVariant(); } case Qt::TextAlignmentRole: { switch (index.column()) { case KrViewProperties::Size: return QVariant(Qt::AlignRight | Qt::AlignVCenter); default: return QVariant(Qt::AlignLeft | Qt::AlignVCenter); } return QVariant(); } case Qt::BackgroundRole: case Qt::ForegroundRole: { KrColorItemType colorItemType; colorItemType.m_activePanel = _view->isFocused(); int actRow = index.row(); if (_alternatingTable) { int itemNum = _view->itemsPerPage(); if (itemNum == 0) itemNum++; if ((itemNum & 1) == 0) actRow += (actRow / itemNum); } colorItemType.m_alternateBackgroundColor = (actRow & 1); colorItemType.m_currentItem = _view->getCurrentIndex().row() == index.row(); colorItemType.m_selectedItem = _view->isSelected(index); if (fileitem->isSymLink()) { if (fileitem->isBrokenLink()) colorItemType.m_fileType = KrColorItemType::InvalidSymlink; else colorItemType.m_fileType = KrColorItemType::Symlink; } else if (fileitem->isDir()) colorItemType.m_fileType = KrColorItemType::Directory; else if (fileitem->isExecutable()) colorItemType.m_fileType = KrColorItemType::Executable; else colorItemType.m_fileType = KrColorItemType::File; KrColorGroup cols; KrColorCache::getColorCache().getColors(cols, colorItemType); if (colorItemType.m_selectedItem) { if (role == Qt::ForegroundRole) return cols.highlightedText(); else return cols.highlight(); } if (role == Qt::ForegroundRole) return cols.text(); else return cols.background(); } default: return QVariant(); } } bool KrVfsModel::setData(const QModelIndex & index, const QVariant & value, int role) { if (role == Qt::EditRole && index.isValid()) { if (index.row() < rowCount() && index.row() >= 0) { FileItem *fileitem = _fileItems.at(index.row()); if (fileitem == 0) return false; _view->op()->emitRenameItem(fileitem->getName(), value.toString()); } } if (role == Qt::UserRole && index.isValid()) { _justForSizeHint = value.toBool(); } return QAbstractListModel::setData(index, value, role); } void KrVfsModel::sort(int column, Qt::SortOrder order) { _view->sortModeUpdated(column, order); if(lastSortOrder() == KrViewProperties::NoColumn) return; emit layoutAboutToBeChanged(); QModelIndexList oldPersistentList = persistentIndexList(); KrSort::Sorter sorter(createSorter()); sorter.sort(); _fileItems.clear(); _fileItemNdx.clear(); _nameNdx.clear(); _urlNdx.clear(); bool sortOrderChanged = false; QHash changeMap; for (int i = 0; i < sorter.items().count(); ++i) { const KrSort::SortProps *props = sorter.items()[i]; _fileItems.append(props->fileitem()); changeMap[ props->originalIndex() ] = i; if (i != props->originalIndex()) sortOrderChanged = true; updateIndices(props->fileitem(), i); } QModelIndexList newPersistentList; foreach(const QModelIndex &mndx, oldPersistentList) newPersistentList << index(changeMap[ mndx.row()], mndx.column()); changePersistentIndexList(oldPersistentList, newPersistentList); emit layoutChanged(); if (sortOrderChanged) _view->makeItemVisible(_view->getCurrentKrViewItem()); } QModelIndex KrVfsModel::addItem(FileItem *fileitem) { emit layoutAboutToBeChanged(); if(lastSortOrder() == KrViewProperties::NoColumn) { int idx = _fileItems.count(); _fileItems.append(fileitem); updateIndices(fileitem, idx); emit layoutChanged(); return index(idx, 0); } QModelIndexList oldPersistentList = persistentIndexList(); KrSort::Sorter sorter(createSorter()); int insertIndex = sorter.insertIndex(fileitem, fileitem == _dummyFileItem, customSortData(fileitem)); if (insertIndex != _fileItems.count()) _fileItems.insert(insertIndex, fileitem); else _fileItems.append(fileitem); for (int i = insertIndex; i < _fileItems.count(); ++i) { updateIndices(_fileItems[i], i); } QModelIndexList newPersistentList; foreach(const QModelIndex &mndx, oldPersistentList) { int newRow = mndx.row(); if (newRow >= insertIndex) newRow++; newPersistentList << index(newRow, mndx.column()); } changePersistentIndexList(oldPersistentList, newPersistentList); emit layoutChanged(); _view->makeItemVisible(_view->getCurrentKrViewItem()); return index(insertIndex, 0); } QModelIndex KrVfsModel::removeItem(FileItem *fileitem) { QModelIndex currIndex = _view->getCurrentIndex(); int removeIdx = _fileItems.indexOf(fileitem); if(removeIdx < 0) return currIndex; emit layoutAboutToBeChanged(); QModelIndexList oldPersistentList = persistentIndexList(); QModelIndexList newPersistentList; _fileItems.removeAt(removeIdx); if (currIndex.row() == removeIdx) { if (_fileItems.count() == 0) currIndex = QModelIndex(); else if (removeIdx >= _fileItems.count()) currIndex = index(_fileItems.count() - 1, 0); else currIndex = index(removeIdx, 0); } else if (currIndex.row() > removeIdx) { currIndex = index(currIndex.row() - 1, 0); } _fileItemNdx.remove(fileitem); _nameNdx.remove(fileitem->getName()); _urlNdx.remove(fileitem->getUrl()); // update indices for fileItems following fileitem for (int i = removeIdx; i < _fileItems.count(); i++) { updateIndices(_fileItems[i], i); } foreach(const QModelIndex &mndx, oldPersistentList) { int newRow = mndx.row(); if (newRow > removeIdx) newRow--; if (newRow != removeIdx) newPersistentList << index(newRow, mndx.column()); else newPersistentList << QModelIndex(); } changePersistentIndexList(oldPersistentList, newPersistentList); emit layoutChanged(); _view->makeItemVisible(_view->getCurrentKrViewItem()); return currIndex; } void KrVfsModel::updateItem(FileItem *fileitem) { QModelIndex oldModelIndex = fileItemIndex(fileitem); if (!oldModelIndex.isValid()) { addItem(fileitem); return; } if(lastSortOrder() == KrViewProperties::NoColumn) { _view->redrawItem(fileitem); return; } int oldIndex = oldModelIndex.row(); emit layoutAboutToBeChanged(); _fileItems.removeAt(oldIndex); KrSort::Sorter sorter(createSorter()); QModelIndexList oldPersistentList = persistentIndexList(); int newIndex = sorter.insertIndex(fileitem, fileitem == _dummyFileItem, customSortData(fileitem)); if (newIndex != _fileItems.count()) { if (newIndex > oldIndex) newIndex--; _fileItems.insert(newIndex, fileitem); } else _fileItems.append(fileitem); int i = newIndex; if (oldIndex < i) i = oldIndex; for (; i < _fileItems.count(); ++i) { updateIndices(_fileItems[i], i); } QModelIndexList newPersistentList; foreach(const QModelIndex &mndx, oldPersistentList) { int newRow = mndx.row(); if (newRow == oldIndex) newRow = newIndex; else { if (newRow >= oldIndex) newRow--; if (mndx.row() > newIndex) newRow++; } newPersistentList << index(newRow, mndx.column()); } changePersistentIndexList(oldPersistentList, newPersistentList); emit layoutChanged(); if (newIndex != oldIndex) _view->makeItemVisible(_view->getCurrentKrViewItem()); } QVariant KrVfsModel::headerData(int section, Qt::Orientation orientation, int role) const { // ignore anything that's not display, and not horizontal if (role != Qt::DisplayRole || orientation != Qt::Horizontal) return QVariant(); switch (section) { case KrViewProperties::Name: return i18nc("File property", "Name"); case KrViewProperties::Ext: return i18nc("File property", "Ext"); case KrViewProperties::Size: return i18nc("File property", "Size"); case KrViewProperties::Type: return i18nc("File property", "Type"); case KrViewProperties::Modified: return i18nc("File property", "Modified"); case KrViewProperties::Permissions: return i18nc("File property", "Perms"); case KrViewProperties::KrPermissions: return i18nc("File property", "rwx"); case KrViewProperties::Owner: return i18nc("File property", "Owner"); case KrViewProperties::Group: return i18nc("File property", "Group"); } return QString(); } const KrViewProperties *KrVfsModel::properties() const { return _view->properties(); } FileItem *KrVfsModel::fileItemAt(const QModelIndex &index) { if (!index.isValid() || index.row() < 0 || index.row() >= _fileItems.count()) return 0; return _fileItems[ index.row()]; } const QModelIndex & KrVfsModel::fileItemIndex(const FileItem *fileitem) { return _fileItemNdx[ (FileItem *) fileitem ]; } const QModelIndex & KrVfsModel::nameIndex(const QString & st) { return _nameNdx[ st ]; } Qt::ItemFlags KrVfsModel::flags(const QModelIndex & index) const { Qt::ItemFlags flags = QAbstractListModel::flags(index); if (!index.isValid()) return flags; if (index.row() >= rowCount()) return flags; FileItem *fileitem = _fileItems.at(index.row()); if (fileitem == _dummyFileItem) { flags = (flags & (~Qt::ItemIsSelectable)) | Qt::ItemIsDropEnabled; } else flags = flags | Qt::ItemIsEditable | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled; return flags; } Qt::SortOrder KrVfsModel::lastSortDir() const { return (properties()->sortOptions & KrViewProperties::Descending) ? Qt::DescendingOrder : Qt::AscendingOrder; } int KrVfsModel::lastSortOrder() const { return properties()->sortColumn; } QString KrVfsModel::nameWithoutExtension(const FileItem *fileItem, bool checkEnabled) const { if ((checkEnabled && !_extensionEnabled) || fileItem->isDir()) return fileItem->getName(); // check if the file has an extension const QString& fileItemName = fileItem->getName(); int loc = fileItemName.lastIndexOf('.'); // avoid mishandling of .bashrc and friend // and virtfs / search result names like "/dir/.file" which whould become "/dir/" if (loc > 0 && fileItemName.lastIndexOf('/') < loc) { // check if it has one of the predefined 'atomic extensions' for (QStringList::const_iterator i = properties()->atomicExtensions.begin(); i != properties()->atomicExtensions.end(); ++i) { if (fileItemName.endsWith(*i) && fileItemName != *i) { loc = fileItemName.length() - (*i).length(); break; } } } else return fileItemName; return fileItemName.left(loc); } const QModelIndex &KrVfsModel::indexFromUrl(const QUrl &url) { return _urlNdx[url]; } KrSort::Sorter KrVfsModel::createSorter() { KrSort::Sorter sorter(_fileItems.count(), properties(), lessThanFunc(), greaterThanFunc()); for(int i = 0; i < _fileItems.count(); i++) sorter.addItem(_fileItems[i], _fileItems[i] == _dummyFileItem, i, customSortData(_fileItems[i])); return sorter; } void KrVfsModel::updateIndices(FileItem *file, int i) { _fileItemNdx[file] = index(i, 0); _nameNdx[file->getName()] = index(i, 0); _urlNdx[file->getUrl()] = index(i, 0); } + +QString KrVfsModel::toolTipText(FileItem *fileItem) const +{ + //"

"; // disable automatic word-wrap + QString text = "" + fileItem->getName() + "


"; + if (!fileItem->isDir() || fileItem->getSize() != 0) { + const QString size = KrView::sizeText(properties(), fileItem->getSize()); + text += i18n("Size:") + " " + size + "
"; + } + text += i18nc("File property", "Type:") + " " + KrView::mimeTypeText(fileItem); + text += "
" + i18nc("File property", "Modified:") + " " + dateText(fileItem->getTime_t()); + text += "
" + i18nc("File property", "Permissions:") + " " + + KrView::permissionsText(properties(), fileItem); + text += "
" + i18nc("File property", "Owner:") + " " + fileItem->getOwner(); + text += "
" + i18nc("File property", "Group:") + " " + fileItem->getGroup(); + if (fileItem->isSymLink()) { + text += "
" + i18nc("File property", "Link to:") + " " + fileItem->getSymDest(); + if (fileItem->isBrokenLink()) + text += " - " + i18nc("File property; broken symbolic link", "(broken)"); + } + return text; +} + +QString KrVfsModel::dateText(time_t time) +{ + struct tm* t = localtime((time_t *) & time); + + const QDateTime dateTime(QDate(t->tm_year + 1900, t->tm_mon + 1, t->tm_mday), + QTime(t->tm_hour, t->tm_min)); + return QLocale().toString(dateTime, QLocale::ShortFormat); +} diff --git a/krusader/Panel/krvfsmodel.h b/krusader/Panel/krvfsmodel.h index 17c837a2..b15a17bb 100644 --- a/krusader/Panel/krvfsmodel.h +++ b/krusader/Panel/krvfsmodel.h @@ -1,119 +1,121 @@ /***************************************************************************** * Copyright (C) 2002 Shie Erlich * * Copyright (C) 2002 Rafi Yanai * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This package is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this package; if not, write to the Free Software * * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ #ifndef KRVFSMODEL_H #define KRVFSMODEL_H // QtCore #include // QtGui #include #include "krsort.h" class FileItem; class KrInterView; class KrViewProperties; /** * @brief The list model for all panel views. */ class KrVfsModel: public QAbstractListModel { Q_OBJECT public: explicit KrVfsModel(KrInterView *); virtual ~KrVfsModel(); inline bool ready() const { return _ready; } void populate(const QList &files, FileItem *dummy); QModelIndex addItem(FileItem *); QModelIndex removeItem(FileItem *); void updateItem(FileItem *fileitem); int rowCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE; int columnCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE; QVariant data(const QModelIndex &index, int role) const Q_DECL_OVERRIDE; bool setData(const QModelIndex & index, const QVariant & value, int role = Qt::EditRole) Q_DECL_OVERRIDE; QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const Q_DECL_OVERRIDE; void setExtensionEnabled(bool exten) { _extensionEnabled = exten; } const KrViewProperties * properties() const; void sort() { sort(lastSortOrder(), lastSortDir()); } void clear(bool emitLayoutChanged = true); QList fileItems() { return _fileItems; } FileItem * fileItemAt(const QModelIndex &index); FileItem *dummyFileItem() const { return _dummyFileItem; } const QModelIndex & fileItemIndex(const FileItem *); const QModelIndex & nameIndex(const QString &); const QModelIndex & indexFromUrl(const QUrl &url); virtual Qt::ItemFlags flags(const QModelIndex & index) const Q_DECL_OVERRIDE; void emitChanged() { emit layoutChanged(); } Qt::SortOrder lastSortDir() const; int lastSortOrder() const; void setAlternatingTable(bool altTable) { _alternatingTable = altTable; } public slots: virtual void sort(int column, Qt::SortOrder order = Qt::AscendingOrder) Q_DECL_OVERRIDE; protected: KrSort::LessThanFunc lessThanFunc() { return KrSort::itemLessThan; } KrSort::LessThanFunc greaterThanFunc() const { return KrSort::itemGreaterThan; } QVariant customSortData(FileItem *) const { return QVariant(); } KrSort::Sorter createSorter(); QString nameWithoutExtension(const FileItem * fileitem, bool checkEnabled = true) const; private: void updateIndices(FileItem *file, int index); + QString toolTipText(FileItem *fileItem) const; + static QString dateText(time_t time); QList _fileItems; QHash _fileItemNdx; QHash _nameNdx; QHash _urlNdx; bool _extensionEnabled; KrInterView * _view; FileItem * _dummyFileItem; bool _ready; QFont _defaultFont; bool _justForSizeHint; bool _alternatingTable; }; #endif // __krvfsmodel__ diff --git a/krusader/Panel/krview.cpp b/krusader/Panel/krview.cpp index 955ea8f6..a87483d4 100644 --- a/krusader/Panel/krview.cpp +++ b/krusader/Panel/krview.cpp @@ -1,1163 +1,1179 @@ /*************************************************************************** krview.cpp ------------------- copyright : (C) 2000-2002 by Shie Erlich & Rafi Yanai e-mail : krusader@users.sourceforge.net web site : http://krusader.sourceforge.net --------------------------------------------------------------------------- Description *************************************************************************** A db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD S o u r c e F i l e *************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "krview.h" #include "viewactions.h" #include "krviewfactory.h" #include "krviewitem.h" #include "krselectionmode.h" #include "krcolorcache.h" #include "krpreviews.h" #include "../kicons.h" #include "../krglobal.h" #include "../defaults.h" #include "../FileSystem/dirlisterinterface.h" #include "../FileSystem/fileitem.h" #include "../FileSystem/krpermhandler.h" #include "../Filter/filterdialog.h" // QtCore #include // QtGui #include #include #include #include // QtWidgets #include #include +#include +#include #include #include #include #include #define FILEITEM getFileItem() KrView *KrViewOperator::_changedView = 0; KrViewProperties::PropertyType KrViewOperator::_changedProperties = KrViewProperties::NoProperty; // ----------------------------- operator KrViewOperator::KrViewOperator(KrView *view, QWidget *widget) : _view(view), _widget(widget), _massSelectionUpdate(false) { _saveDefaultSettingsTimer.setSingleShot(true); connect(&_saveDefaultSettingsTimer, SIGNAL(timeout()), SLOT(saveDefaultSettings())); } KrViewOperator::~KrViewOperator() { if(_changedView == _view) saveDefaultSettings(); } void KrViewOperator::startUpdate() { _view->refresh(); } void KrViewOperator::cleared() { _view->clear(); } void KrViewOperator::fileAdded(FileItem *fileitem) { _view->addItem(fileitem); } void KrViewOperator::fileUpdated(FileItem *fileitem) { _view->updateItem(fileitem); } void KrViewOperator::startDrag() { QStringList items; _view->getSelectedItems(&items); if (items.empty()) return ; // don't drag an empty thing QPixmap px; if (items.count() > 1 || _view->getCurrentKrViewItem() == 0) px = FL_LOADICON("queue"); // how much are we dragging else px = _view->getCurrentKrViewItem() ->icon(); emit letsDrag(items, px); } bool KrViewOperator::searchItem(const QString &text, bool caseSensitive, int direction) { KrViewItem * item = _view->getCurrentKrViewItem(); if (!item) { return false; } QRegExp rx(text, caseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive, QRegExp::Wildcard); if (!direction) { if (rx.indexIn(item->name()) == 0) { return true; } direction = 1; } KrViewItem * startItem = item; while (true) { item = (direction > 0) ? _view->getNext(item) : _view->getPrev(item); if (!item) item = (direction > 0) ? _view->getFirst() : _view->getLast(); if (item == startItem) { return false; } if (rx.indexIn(item->name()) == 0) { _view->setCurrentKrViewItem(item); _view->makeItemVisible(item); return true; } } } bool KrViewOperator::filterSearch(const QString &text, bool caseSensitive) { _view->_quickFilterMask = QRegExp(text, caseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive, QRegExp::Wildcard); _view->refresh(); return _view->_count || !_view->_files->numFileItems(); } void KrViewOperator::setMassSelectionUpdate(bool upd) { _massSelectionUpdate = upd; if (!upd) { emit selectionChanged(); _view->redraw(); } } void KrViewOperator::settingsChanged(KrViewProperties::PropertyType properties) { if(!_view->_updateDefaultSettings || _view->_ignoreSettingsChange) return; if(_changedView != _view) saveDefaultSettings(); _changedView = _view; _changedProperties = static_cast(_changedProperties | properties); _saveDefaultSettingsTimer.start(100); } void KrViewOperator::saveDefaultSettings() { _saveDefaultSettingsTimer.stop(); if(_changedView) _changedView->saveDefaultSettings(_changedProperties); _changedProperties = KrViewProperties::NoProperty; _changedView = 0; } // ----------------------------- krview const KrView::IconSizes KrView::iconSizes; KrView::KrView(KrViewInstance &instance, KConfig *cfg) : _config(cfg), _properties(0), _focused(false), _fileIconSize(0), _instance(instance), _files(0), _mainWindow(0), _widget(0), _nameToMakeCurrent(QString()), _previews(0), _updateDefaultSettings(false), _ignoreSettingsChange(false), _count(0), _numDirs(0), _dummyFileItem(0) { } KrView::~KrView() { _instance.m_objects.removeOne(this); delete _previews; _previews = 0; delete _dummyFileItem; _dummyFileItem = 0; if (_properties) qFatal("A class inheriting KrView didn't delete _properties!"); if (_operator) qFatal("A class inheriting KrView didn't delete _operator!"); } void KrView::init(bool enableUpdateDefaultSettings) { // sanity checks: if (!_widget) qFatal("_widget must be set during construction of KrView inheritors"); // ok, continue initProperties(); _operator = createOperator(); setup(); restoreDefaultSettings(); _updateDefaultSettings = enableUpdateDefaultSettings && KConfigGroup(_config, "Startup").readEntry("Update Default Panel Settings", _RememberPos); _instance.m_objects.append(this); } void KrView::initProperties() { _properties = createViewProperties(); KConfigGroup grpSvr(_config, "Look&Feel"); KConfigGroup grpInstance(_config, _instance.name()); _properties->displayIcons = grpInstance.readEntry("With Icons", _WithIcons); _properties->numericPermissions = grpSvr.readEntry("Numeric permissions", _NumericPermissions); int sortOptions = _properties->sortOptions; if (grpSvr.readEntry("Show Directories First", true)) sortOptions |= KrViewProperties::DirsFirst; if(grpSvr.readEntry("Always sort dirs by name", false)) sortOptions |= KrViewProperties::AlwaysSortDirsByName; if (!grpSvr.readEntry("Case Sensative Sort", _CaseSensativeSort)) sortOptions |= KrViewProperties::IgnoreCase; if (grpSvr.readEntry("Locale Aware Sort", true)) sortOptions |= KrViewProperties::LocaleAwareSort; _properties->sortOptions = static_cast(sortOptions); _properties->sortMethod = static_cast( grpSvr.readEntry("Sort method", (int) _DefaultSortMethod)); _properties->humanReadableSize = grpSvr.readEntry("Human Readable Size", _HumanReadableSize); _properties->localeAwareCompareIsCaseSensitive = QString("a").localeAwareCompare("B") > 0; // see KDE bug #40131 QStringList defaultAtomicExtensions; defaultAtomicExtensions += ".tar.gz"; defaultAtomicExtensions += ".tar.bz2"; defaultAtomicExtensions += ".tar.lzma"; defaultAtomicExtensions += ".tar.xz"; defaultAtomicExtensions += ".moc.cpp"; QStringList atomicExtensions = grpSvr.readEntry("Atomic Extensions", defaultAtomicExtensions); for (QStringList::iterator i = atomicExtensions.begin(); i != atomicExtensions.end();) { QString & ext = *i; ext = ext.trimmed(); if (!ext.length()) { i = atomicExtensions.erase(i); continue; } if (!ext.startsWith('.')) ext.insert(0, '.'); ++i; } _properties->atomicExtensions = atomicExtensions; } void KrView::showPreviews(bool show) { if(show) { if(!_previews) { _previews = new KrPreviews(this); _previews->update(); } } else { delete _previews; _previews = 0; } redraw(); // op()->settingsChanged(KrViewProperties::PropShowPreviews); op()->emitRefreshActions(); } void KrView::updatePreviews() { if(_previews) _previews->update(); } QPixmap KrView::processIcon(const QPixmap &icon, bool dim, const QColor & dimColor, int dimFactor, bool symlink) { QPixmap pixmap = icon; if (symlink) { const QStringList overlays = QStringList() << QString() << "emblem-symbolic-link"; KIconLoader::global()->drawOverlays(overlays, pixmap, KIconLoader::Desktop); } if(!dim) return pixmap; QImage dimmed = pixmap.toImage(); QPainter p(&dimmed); p.setCompositionMode(QPainter::CompositionMode_SourceIn); p.fillRect(0, 0, icon.width(), icon.height(), dimColor); p.setCompositionMode(QPainter::CompositionMode_SourceOver); p.setOpacity((qreal)dimFactor / (qreal)100); p.drawPixmap(0, 0, icon.width(), icon.height(), pixmap); return QPixmap::fromImage(dimmed, Qt::ColorOnly | Qt::ThresholdDither | Qt::ThresholdAlphaDither | Qt::NoOpaqueDetection ); } QPixmap KrView::getIcon(FileItem *fileitem, bool active, int size/*, KRListItem::cmpColor color*/) { // KConfigGroup ag( krConfig, "Advanced"); ////////////////////////////// QPixmap icon; QString icon_name = fileitem->getIcon(); QString cacheName; if(!size) size = _FilelistIconSize.toInt(); QColor dimColor; int dimFactor; bool dim = !active && KrColorCache::getColorCache().getDimSettings(dimColor, dimFactor); if (icon_name.isNull()) icon_name = ""; cacheName.append(QString::number(size)); if(fileitem->isSymLink()) cacheName.append("LINK_"); if(dim) cacheName.append("DIM_"); cacheName.append(icon_name); //QPixmapCache::setCacheLimit( ag.readEntry("Icon Cache Size",_IconCacheSize) ); // first try the cache if (!QPixmapCache::find(cacheName, icon)) { icon = processIcon(krLoader->loadIcon(icon_name, KIconLoader::Desktop, size), dim, dimColor, dimFactor, fileitem->isSymLink()); // insert it into the cache QPixmapCache::insert(cacheName, icon); } return icon; } QPixmap KrView::getIcon(FileItem *fileitem) { if(_previews) { QPixmap icon; if(_previews->getPreview(fileitem, icon, _focused)) return icon; } return getIcon(fileitem, _focused, _fileIconSize); } /** * this function ADDs a list of selected item names into 'names'. * it assumes the list is ready and doesn't initialize it, or clears it */ void KrView::getItemsByMask(QString mask, QStringList* names, bool dirs, bool files) { for (KrViewItem * it = getFirst(); it != 0; it = getNext(it)) { if ((it->name() == "..") || !QDir::match(mask, it->name())) continue; // if we got here, than the item fits the mask if (it->getFileItem()->isDir() && !dirs) continue; // do we need to skip folders? if (!it->getFileItem()->isDir() && !files) continue; // do we need to skip files names->append(it->name()); } } /** * this function ADDs a list of selected item names into 'names'. * it assumes the list is ready and doesn't initialize it, or clears it */ void KrView::getSelectedItems(QStringList *names, bool ignoreJustFocused) { for (KrViewItem * it = getFirst(); it != 0; it = getNext(it)) if (it->isSelected() && (it->name() != "..")) names->append(it->name()); // if all else fails, take the current item if (!ignoreJustFocused) { QString item = getCurrentItem(); if (names->empty() && !item.isEmpty() && item != "..") { names->append(item); } } } void KrView::getSelectedKrViewItems(KrViewItemList *items) { for (KrViewItem * it = getFirst(); it != 0; it = getNext(it)) if (it->isSelected() && (it->name() != "..")) items->append(it); // if all else fails, take the current item QString item = getCurrentItem(); if (items->empty() && !item.isEmpty() && item != ".." && getCurrentKrViewItem() != 0) { items->append(getCurrentKrViewItem()); } } QString KrView::statistics() { KIO::filesize_t size = calcSize(); KIO::filesize_t selectedSize = calcSelectedSize(); QString tmp; KConfigGroup grp(_config, "Look&Feel"); if(grp.readEntry("Show Size In Bytes", false)) { tmp = i18nc("%1=number of selected items,%2=total number of items, \ %3=filesize of selected items,%4=filesize in Bytes, \ %5=filesize of all items in folder,%6=filesize in Bytes", "%1 out of %2, %3 (%4) out of %5 (%6)", numSelected(), _count, KIO::convertSize(selectedSize), KRpermHandler::parseSize(selectedSize), KIO::convertSize(size), KRpermHandler::parseSize(size)); } else { tmp = i18nc("%1=number of selected items,%2=total number of items, \ %3=filesize of selected items,%4=filesize of all items in folder", "%1 out of %2, %3 out of %4", numSelected(), _count, KIO::convertSize(selectedSize), KIO::convertSize(size)); } // notify if we're running a filtered view if (filter() != KrViewProperties::All) tmp = ">> [ " + filterMask().nameFilter() + " ] " + tmp; return tmp; } bool KrView::changeSelection(const KRQuery& filter, bool select) { KConfigGroup grpSvr(_config, "Look&Feel"); return changeSelection(filter, select, grpSvr.readEntry("Mark Dirs", _MarkDirs), true); } bool KrView::changeSelection(const KRQuery& filter, bool select, bool includeDirs, bool makeVisible) { if (op()) op()->setMassSelectionUpdate(true); KrViewItem *temp = getCurrentKrViewItem(); KrViewItem *firstMatch = 0; for (KrViewItem * it = getFirst(); it != 0; it = getNext(it)) { if (it->name() == "..") continue; if (it->getFileItem()->isDir() && !includeDirs) continue; FileItem * file = it->getMutableFileItem(); // filter::match calls getMimetype which isn't const if (file == 0) continue; if (filter.match(file)) { it->setSelected(select); if (!firstMatch) firstMatch = it; } } if (op()) op()->setMassSelectionUpdate(false); updateView(); if (ensureVisibilityAfterSelect() && temp != 0) { makeItemVisible(temp); } else if (makeVisible && firstMatch != 0) { // if no selected item is visible... KrViewItemList selectedItems; getSelectedKrViewItems(&selectedItems); bool anyVisible = false; for (KrViewItem *item : selectedItems) { if (isItemVisible(item)) { anyVisible = true; break; } } if (!anyVisible) { // ...scroll to fist selected item makeItemVisible(firstMatch); } } redraw(); return firstMatch != 0; // return if any file was selected } void KrView::invertSelection() { if (op()) op()->setMassSelectionUpdate(true); KConfigGroup grpSvr(_config, "Look&Feel"); bool markDirs = grpSvr.readEntry("Mark Dirs", _MarkDirs); KrViewItem *temp = getCurrentKrViewItem(); for (KrViewItem * it = getFirst(); it != 0; it = getNext(it)) { if (it->name() == "..") continue; if (it->getFileItem()->isDir() && !markDirs && !it->isSelected()) continue; it->setSelected(!it->isSelected()); } if (op()) op()->setMassSelectionUpdate(false); updateView(); if (ensureVisibilityAfterSelect() && temp != 0) makeItemVisible(temp); } QString KrView::firstUnmarkedBelowCurrent() { if (getCurrentKrViewItem() == 0) return QString(); KrViewItem * iterator = getNext(getCurrentKrViewItem()); while (iterator && iterator->isSelected()) iterator = getNext(iterator); if (!iterator) { iterator = getPrev(getCurrentKrViewItem()); while (iterator && iterator->isSelected()) iterator = getPrev(iterator); } if (!iterator) return QString(); return iterator->name(); } void KrView::delItem(const QString &name) { KrViewItem *it = findItemByName(name); if(!it) return; if(_previews) _previews->deletePreview(it); preDelItem(it); if (it->FILEITEM->isDir()) { --_numDirs; } --_count; delete it; op()->emitSelectionChanged(); } void KrView::addItem(FileItem *fileitem) { if (isFiltered(fileitem)) return; KrViewItem *item = preAddItem(fileitem); if (!item) return; // don't add it after all if(_previews) _previews->updatePreview(item); if (fileitem->isDir()) ++_numDirs; ++_count; if (item->name() == nameToMakeCurrent()) { setCurrentKrViewItem(item); // dictionary based - quick makeItemVisible(item); } op()->emitSelectionChanged(); } void KrView::updateItem(FileItem *fileitem) { if (isFiltered(fileitem)) delItem(fileitem->getName()); else { preUpdateItem(fileitem); if(_previews) _previews->updatePreview(findItemByFileItem(fileitem)); } op()->emitSelectionChanged(); } void KrView::clear() { if(_previews) _previews->clear(); _count = _numDirs = 0; delete _dummyFileItem; _dummyFileItem = 0; redraw(); } bool KrView::handleKeyEvent(QKeyEvent *e) { switch (e->key()) { case Qt::Key_Enter : case Qt::Key_Return : { if (e->modifiers() & Qt::ControlModifier) // let the panel handle it e->ignore(); else { KrViewItem * i = getCurrentKrViewItem(); if (i == 0) return true; QString tmp = i->name(); op()->emitExecuted(tmp); } return true; } case Qt::Key_QuoteLeft : // Terminal Emulator bugfix if (e->modifiers() == Qt::ControlModifier) { // let the panel handle it e->ignore(); } else { // a normal click - do a lynx-like moving thing op()->emitGoHome(); // ask krusader to move to the home directory } return true; case Qt::Key_Delete : // delete/trash the file op()->emitDefaultDeleteFiles(e->modifiers() == Qt::ShiftModifier || e->modifiers() == Qt::ControlModifier); return true; case Qt::Key_Insert: { KrViewItem * i = getCurrentKrViewItem(); if (!i) return true; i->setSelected(!i->isSelected()); if (KrSelectionMode::getSelectionHandler()->insertMovesDown()) { KrViewItem * next = getNext(i); if (next) { setCurrentKrViewItem(next); makeItemVisible(next); } } op()->emitSelectionChanged(); return true; } case Qt::Key_Space: { KrViewItem * viewItem = getCurrentKrViewItem(); if (viewItem != 0) { viewItem->setSelected(!viewItem->isSelected()); if (KrSelectionMode::getSelectionHandler()->spaceMovesDown()) { KrViewItem * next = getNext(viewItem); if (next) { setCurrentKrViewItem(next); makeItemVisible(next); } } op()->emitSelectionChanged(); } return true; } case Qt::Key_Backspace : // Terminal Emulator bugfix case Qt::Key_Left : if (e->modifiers() == Qt::ControlModifier || e->modifiers() == Qt::ShiftModifier || e->modifiers() == Qt::AltModifier) { // let the panel handle it e->ignore(); } else { // a normal click - do a lynx-like moving thing op()->emitDirUp(); // ask krusader to move up a directory } return true; // safety case Qt::Key_Right : if (e->modifiers() == Qt::ControlModifier || e->modifiers() == Qt::ShiftModifier || e->modifiers() == Qt::AltModifier) { // let the panel handle it e->ignore(); } else { // just a normal click - do a lynx-like moving thing KrViewItem *i = getCurrentKrViewItem(); if (i) op()->emitGoInside(i->name()); } return true; case Qt::Key_Up : if (e->modifiers() == Qt::ControlModifier) { // let the panel handle it - jump to the Location Bar e->ignore(); } else { KrViewItem *item = getCurrentKrViewItem(); if (item) { if (e->modifiers() == Qt::ShiftModifier) { item->setSelected(!item->isSelected()); op()->emitSelectionChanged(); } item = getPrev(item); if (item) { setCurrentKrViewItem(item); makeItemVisible(item); } } } return true; case Qt::Key_Down : if (e->modifiers() == Qt::ControlModifier || e->modifiers() == (Qt::ControlModifier | Qt::ShiftModifier)) { // let the panel handle it - jump to command line e->ignore(); } else { KrViewItem *item = getCurrentKrViewItem(); if (item) { if (e->modifiers() == Qt::ShiftModifier) { item->setSelected(!item->isSelected()); op()->emitSelectionChanged(); } item = getNext(item); if (item) { setCurrentKrViewItem(item); makeItemVisible(item); } } } return true; case Qt::Key_Home: { if (e->modifiers() & Qt::ShiftModifier) { /* Shift+Home */ bool select = true; KrViewItem *pos = getCurrentKrViewItem(); if (pos == 0) pos = getLast(); KrViewItem *item = getFirst(); op()->setMassSelectionUpdate(true); while (item) { item->setSelected(select); if (item == pos) select = false; item = getNext(item); } op()->setMassSelectionUpdate(false); } KrViewItem * first = getFirst(); if (first) { setCurrentKrViewItem(first); makeItemVisible(first); } } return true; case Qt::Key_End: if (e->modifiers() & Qt::ShiftModifier) { bool select = false; KrViewItem *pos = getCurrentKrViewItem(); if (pos == 0) pos = getFirst(); op()->setMassSelectionUpdate(true); KrViewItem *item = getFirst(); while (item) { if (item == pos) select = true; item->setSelected(select); item = getNext(item); } op()->setMassSelectionUpdate(false); } else { KrViewItem *last = getLast(); if (last) { setCurrentKrViewItem(last); makeItemVisible(last); } } return true; case Qt::Key_PageDown: { KrViewItem * current = getCurrentKrViewItem(); int downStep = itemsPerPage(); while (downStep != 0 && current) { KrViewItem * newCurrent = getNext(current); if (newCurrent == 0) break; current = newCurrent; downStep--; } if (current) { setCurrentKrViewItem(current); makeItemVisible(current); } return true; } case Qt::Key_PageUp: { KrViewItem * current = getCurrentKrViewItem(); int upStep = itemsPerPage(); while (upStep != 0 && current) { KrViewItem * newCurrent = getPrev(current); if (newCurrent == 0) break; current = newCurrent; upStep--; } if (current) { setCurrentKrViewItem(current); makeItemVisible(current); } return true; } case Qt::Key_Escape: e->ignore(); return true; // otherwise the selection gets lost??!?? // also it is needed by the panel case Qt::Key_A : // mark all if (e->modifiers() == Qt::ControlModifier) { //FIXME: shouldn't there also be a shortcut for unselecting everything ? selectAllIncludingDirs(); return true; } // default continues here !!!!!!!!!!! default: return false; } return false; } void KrView::zoomIn() { int idx = iconSizes.indexOf(_fileIconSize); if(idx >= 0 && (idx+1) < iconSizes.count()) setFileIconSize(iconSizes[idx+1]); } void KrView::zoomOut() { int idx = iconSizes.indexOf(_fileIconSize); if(idx > 0) setFileIconSize(iconSizes[idx-1]); } void KrView::setFileIconSize(int size) { if(iconSizes.indexOf(size) < 0) return; _fileIconSize = size; if(_previews) { _previews->clear(); _previews->update(); } redraw(); op()->emitRefreshActions(); } int KrView::defaultFileIconSize() { KConfigGroup grpSvr(_config, _instance.name()); return grpSvr.readEntry("IconSize", _FilelistIconSize).toInt(); } void KrView::saveDefaultSettings(KrViewProperties::PropertyType properties) { saveSettings(KConfigGroup(_config, _instance.name()), properties); op()->emitRefreshActions(); } void KrView::restoreDefaultSettings() { restoreSettings(KConfigGroup(_config, _instance.name())); } void KrView::saveSettings(KConfigGroup group, KrViewProperties::PropertyType properties) { if(properties & KrViewProperties::PropIconSize) group.writeEntry("IconSize", fileIconSize()); if(properties & KrViewProperties::PropShowPreviews) group.writeEntry("ShowPreviews", previewsShown()); if(properties & KrViewProperties::PropSortMode) saveSortMode(group); if(properties & KrViewProperties::PropFilter) { group.writeEntry("Filter", static_cast(_properties->filter)); group.writeEntry("FilterApplysToDirs", _properties->filterApplysToDirs); if(_properties->filterSettings.isValid()) _properties->filterSettings.save(KConfigGroup(&group, "FilterSettings")); } } void KrView::restoreSettings(KConfigGroup group) { _ignoreSettingsChange = true; doRestoreSettings(group); _ignoreSettingsChange = false; refresh(); } void KrView::doRestoreSettings(KConfigGroup group) { restoreSortMode(group); setFileIconSize(group.readEntry("IconSize", defaultFileIconSize())); showPreviews(group.readEntry("ShowPreviews", false)); _properties->filter = static_cast(group.readEntry("Filter", static_cast(KrViewProperties::All))); _properties->filterApplysToDirs = group.readEntry("FilterApplysToDirs", false); _properties->filterSettings.load(KConfigGroup(&group, "FilterSettings")); _properties->filterMask = _properties->filterSettings.toQuery(); } void KrView::applySettingsToOthers() { for(int i = 0; i < _instance.m_objects.length(); i++) { KrView *view = _instance.m_objects[i]; if(this != view) { view->_ignoreSettingsChange = true; view->copySettingsFrom(this); view->_ignoreSettingsChange = false; } } } void KrView::sortModeUpdated(KrViewProperties::ColumnType sortColumn, bool descending) { if(sortColumn == _properties->sortColumn && descending == (bool) (_properties->sortOptions & KrViewProperties::Descending)) return; int options = _properties->sortOptions; if(descending) options |= KrViewProperties::Descending; else options &= ~KrViewProperties::Descending; _properties->sortColumn = sortColumn; _properties->sortOptions = static_cast(options); // op()->settingsChanged(KrViewProperties::PropSortMode); } void KrView::saveSortMode(KConfigGroup &group) { group.writeEntry("Sort Column", static_cast(_properties->sortColumn)); group.writeEntry("Descending Sort Order", _properties->sortOptions & KrViewProperties::Descending); } void KrView::restoreSortMode(KConfigGroup &group) { int column = group.readEntry("Sort Column", static_cast(KrViewProperties::Name)); bool isDescending = group.readEntry("Descending Sort Order", false); setSortMode(static_cast(column), isDescending); } -QString KrView::krPermissionString(const FileItem * fileitem) +QString KrView::krPermissionText(const FileItem * fileitem) { QString tmp; switch (fileitem->isReadable()) { case ALLOWED_PERM: tmp+='r'; break; case UNKNOWN_PERM: tmp+='?'; break; case NO_PERM: tmp+='-'; break; } switch (fileitem->isWriteable()) { case ALLOWED_PERM: tmp+='w'; break; case UNKNOWN_PERM: tmp+='?'; break; case NO_PERM: tmp+='-'; break; } switch (fileitem->isExecutable()) { case ALLOWED_PERM: tmp+='x'; break; case UNKNOWN_PERM: tmp+='?'; break; case NO_PERM: tmp+='-'; break; } return tmp; } -QString KrView::sizeToString(const KrViewProperties *properties, KIO::filesize_t size) +QString KrView::permissionsText(const KrViewProperties *properties, const FileItem *fileItem) +{ + return properties->numericPermissions ? + QString().asprintf("%.4o", fileItem->getMode() & (S_ISUID | S_ISGID | S_ISVTX | + S_IRWXU | S_IRWXG | S_IRWXO)) : + fileItem->getPerm(); +} + +QString KrView::sizeText(const KrViewProperties *properties, KIO::filesize_t size) { return properties->humanReadableSize ? KIO::convertSize(size) : KRpermHandler::parseSize(size); } +QString KrView::mimeTypeText(FileItem *fileItem) +{ + QMimeType mt = QMimeDatabase().mimeTypeForName(fileItem->getMime()); + return mt.isValid() ? mt.comment() : QString(); +} + bool KrView::isFiltered(FileItem *fileitem) { if (_quickFilterMask.isValid() && _quickFilterMask.indexIn(fileitem->getName()) == -1) return true; bool filteredOut = false; bool isDir = fileitem->isDir(); if (!isDir || (isDir && properties()->filterApplysToDirs)) { switch (properties()->filter) { case KrViewProperties::All : break; case KrViewProperties::Custom : if (!properties()->filterMask.match(fileitem)) filteredOut = true; break; case KrViewProperties::Dirs: if (!isDir) filteredOut = true; break; case KrViewProperties::Files: if (isDir) filteredOut = true; break; default: break; } } return filteredOut; } void KrView::setFiles(DirListerInterface *files) { if(files != _files) { clear(); if(_files) QObject::disconnect(_files, 0, op(), 0); _files = files; } if(!_files) return; QObject::disconnect(_files, 0, op(), 0); QObject::connect(_files, SIGNAL(refreshDone(bool)), op(), SLOT(startUpdate())); QObject::connect(_files, SIGNAL(cleared()), op(), SLOT(cleared())); QObject::connect(_files, SIGNAL(addedFileItem(FileItem*)), op(), SLOT(fileAdded(FileItem*))); QObject::connect(_files, SIGNAL(updatedFileItem(FileItem*)), op(), SLOT(fileUpdated(FileItem*))); } void KrView::setFilter(KrViewProperties::FilterSpec filter, FilterSettings customFilter, bool applyToDirs) { _properties->filter = filter; _properties->filterSettings = customFilter; _properties->filterMask = customFilter.toQuery(); _properties->filterApplysToDirs = applyToDirs; refresh(); } void KrView::setFilter(KrViewProperties::FilterSpec filter) { KConfigGroup cfg(_config, "Look&Feel"); bool rememberSettings = cfg.readEntry("FilterDialogRemembersSettings", _FilterDialogRemembersSettings); bool applyToDirs = rememberSettings ? _properties->filterApplysToDirs : false; switch (filter) { case KrViewProperties::All : break; case KrViewProperties::Custom : { FilterDialog dialog(_widget, i18n("Filter Files"), QStringList(i18n("Apply filter to folders")), false); dialog.checkExtraOption(i18n("Apply filter to folders"), applyToDirs); if(rememberSettings) dialog.applySettings(_properties->filterSettings); dialog.exec(); FilterSettings s(dialog.getSettings()); if(!s.isValid()) // if the user canceled - quit return; _properties->filterSettings = s; _properties->filterMask = s.toQuery(); applyToDirs = dialog.isExtraOptionChecked(i18n("Apply filter to folders")); } break; default: return; } _properties->filterApplysToDirs = applyToDirs; _properties->filter = filter; refresh(); } void KrView::customSelection(bool select) { KConfigGroup grpSvr(_config, "Look&Feel"); bool includeDirs = grpSvr.readEntry("Mark Dirs", _MarkDirs); FilterDialog dialog(0, i18n("Select Files"), QStringList(i18n("Apply selection to folders")), false); dialog.checkExtraOption(i18n("Apply selection to folders"), includeDirs); dialog.exec(); KRQuery query = dialog.getQuery(); // if the user canceled - quit if (query.isNull()) return ; includeDirs = dialog.isExtraOptionChecked(i18n("Apply selection to folders")); changeSelection(query, select, includeDirs); } void KrView::refresh() { QString currentItem = getCurrentItem(); QList selection = selectedUrls(); QModelIndex currentIndex = getCurrentIndex(); clear(); if(!_files) return; QList fileItems; // if we are not at the root add the ".." entry if(!_files->isRoot()) { _dummyFileItem = FileItem::createDummy(); fileItems << _dummyFileItem; } foreach(FileItem *fileitem, _files->fileItems()) { if(!fileitem || isFiltered(fileitem)) continue; if(fileitem->isDir()) _numDirs++; _count++; fileItems << fileitem; } populate(fileItems, _dummyFileItem); if(!selection.isEmpty()) setSelectionUrls(selection); if (!nameToMakeCurrent().isEmpty()) { setCurrentItem(nameToMakeCurrent()); setNameToMakeCurrent(""); } else if (!currentItem.isEmpty()) { if (currentItem == ".." && _count > 0 && !_quickFilterMask.isEmpty() && _quickFilterMask.isValid()) { // In a filtered view we should never select the dummy entry if // there are real matches. setCurrentKrViewItem(getNext(getFirst())); } else setCurrentItem(currentItem, currentIndex); } else { setCurrentKrViewItem(getFirst()); } updatePreviews(); redraw(); op()->emitSelectionChanged(); } void KrView::setSelected(const FileItem* fileitem, bool select) { if(fileitem == _dummyFileItem) return; if(select) clearSavedSelection(); intSetSelected(fileitem, select); } void KrView::saveSelection() { _savedSelection = selectedUrls(); op()->emitRefreshActions(); } void KrView::restoreSelection() { if(canRestoreSelection()) setSelectionUrls(_savedSelection); } void KrView::clearSavedSelection() { _savedSelection.clear(); op()->emitRefreshActions(); } void KrView::markSameBaseName() { KrViewItem* item = getCurrentKrViewItem(); if (!item) return; KRQuery query(QString("%1.*").arg(item->name(false))); changeSelection(query, true, false); } void KrView::markSameExtension() { KrViewItem* item = getCurrentKrViewItem(); if (!item) return; KRQuery query(QString("*.%1").arg(item->extension())); changeSelection(query, true, false); } diff --git a/krusader/Panel/krview.h b/krusader/Panel/krview.h index 5f76dfe5..abae2df7 100644 --- a/krusader/Panel/krview.h +++ b/krusader/Panel/krview.h @@ -1,445 +1,449 @@ /*************************************************************************** krview.h ------------------- copyright : (C) 2000-2002 by Shie Erlich & Rafi Yanai e-mail : krusader@users.sourceforge.net web site : http://krusader.sourceforge.net --------------------------------------------------------------------------- Description *************************************************************************** A db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD H e a d e r F i l e *************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef KRVIEW_H #define KRVIEW_H // QtCore #include #include #include #include #include #include // QtGui #include #include #include "../Filter/filtersettings.h" #include "../FileSystem/krquery.h" #define MAX_BRIEF_COLS 5 class KrView; class KrViewItem; class KrPreviews; class KrViewInstance; class DirListerInterface; typedef QList KrViewItemList; // KrViewProperties // This class is an interface class between KrView and KrViewItem // In order for KrViewItem to be as independent as possible, KrView holds // an instance of this class, and fills it with the correct data. A reference // to this should be given to each KrViewItem, which then queries it for // information regarding how things should be displayed in the current view. // // Every property that the item needs to know about the view must be here! class KrViewProperties { public: KrViewProperties() : numericPermissions(false), displayIcons(false), sortColumn(Name), sortOptions(static_cast(0)), sortMethod(Alphabetical), filter(KrViewProperties::All), filterMask(KRQuery("*")), filterApplysToDirs(false), localeAwareCompareIsCaseSensitive(false), humanReadableSize(), numberOfColumns(1) { } enum PropertyType { NoProperty = 0x0, PropIconSize = 0x1, PropShowPreviews = 0x2, PropSortMode = 0x4, PropColumns = 0x8, PropFilter = 0x10, AllProperties = PropIconSize | PropShowPreviews | PropSortMode | PropColumns | PropFilter }; enum ColumnType { NoColumn = -1, Name = 0x0, Ext = 0x1, Size = 0x2, Type = 0x3, Modified = 0x4, Permissions = 0x5, KrPermissions = 0x6, Owner = 0x7, Group = 0x8, MAX_COLUMNS = 0x09 }; enum SortOptions { Descending = 0x200, DirsFirst = 0x400, IgnoreCase = 0x800, AlwaysSortDirsByName = 0x1000, LocaleAwareSort = 0x2000 }; enum SortMethod { Alphabetical = 0x1, AlphabeticalNumbers = 0x2, CharacterCode = 0x4, CharacterCodeNumbers = 0x8, Krusader = 0x10 }; enum FilterSpec { Dirs = 0x1, Files = 0x2, All = 0x3, Custom = 0x4 }; bool numericPermissions; // show full permission column as octal numbers bool displayIcons; // true if icons should be displayed in this view ColumnType sortColumn; SortOptions sortOptions; SortMethod sortMethod; // sort method for names and extensions FilterSpec filter; // what items to show (all, custom, exec) KRQuery filterMask; // what items to show (*.cpp, *.h etc) FilterSettings filterSettings; bool filterApplysToDirs; bool localeAwareCompareIsCaseSensitive; // mostly, it is not! depends on LC_COLLATE bool humanReadableSize; // display size as KB, MB or just as a long number QStringList atomicExtensions; // list of strings, which will be treated as one extension. Must // start with a dot. int numberOfColumns; // the number of columns in the brief view }; // operator can handle two ways of doing things: // 1. if the view is a widget (inherits krview and klistview for example) // 2. if the view HAS A widget (a krview-son has a member of klistview) // this is done by specifying the view and the widget in the constructor, // even if they are actually the same object (specify it twice in that case) class KrViewOperator : public QObject { Q_OBJECT public: KrViewOperator(KrView *view, QWidget *widget); ~KrViewOperator(); KrView *view() const { return _view; } QWidget *widget() const { return _widget; } void startDrag(); void emitGotDrop(QDropEvent *e) { emit gotDrop(e); } void emitLetsDrag(QStringList items, QPixmap icon) { emit letsDrag(items, icon); } void emitItemDescription(const QString &desc) { emit itemDescription(desc); } void emitContextMenu(const QPoint &point) { emit contextMenu(point); } void emitEmptyContextMenu(const QPoint &point) { emit emptyContextMenu(point); } void emitRenameItem(const QString &oldName, const QString &newName) { emit renameItem(oldName, newName); } void emitExecuted(const QString &name) { emit executed(name); } void emitGoInside(const QString &name) { emit goInside(name); } void emitNeedFocus() { emit needFocus(); } void emitMiddleButtonClicked(KrViewItem *item) { emit middleButtonClicked(item); } void emitCurrentChanged(KrViewItem *item) { emit currentChanged(item); } void emitPreviewJobStarted(KJob *job) { emit previewJobStarted(job); } void emitGoHome() { emit goHome(); } void emitDirUp() { emit dirUp(); } void emitDefaultDeleteFiles(bool invertMode) { emit defaultDeleteFiles(invertMode); } void emitRefreshActions() { emit refreshActions(); } void emitGoBack() { emit goBack(); } void emitGoForward() { emit goForward(); } bool searchItem(const QString &, bool, int = 0); // search for item and set cursor bool filterSearch(const QString &, bool); // filter view items void setMassSelectionUpdate(bool upd); bool isMassSelectionUpdate() { return _massSelectionUpdate; } void settingsChanged(KrViewProperties::PropertyType properties); public slots: void emitSelectionChanged() { if (!_massSelectionUpdate) emit selectionChanged(); } signals: void selectionChanged(); void gotDrop(QDropEvent *e); void letsDrag(QStringList items, QPixmap icon); void itemDescription(const QString &desc); void contextMenu(const QPoint &point); void emptyContextMenu(const QPoint &point); void renameItem(const QString &oldName, const QString &newName); void executed(const QString &name); void goInside(const QString &name); void needFocus(); void middleButtonClicked(KrViewItem *item); void currentChanged(KrViewItem *item); void previewJobStarted(KJob *job); void goHome(); void defaultDeleteFiles(bool invertMode); void dirUp(); void refreshActions(); void goBack(); void goForward(); protected slots: void saveDefaultSettings(); void startUpdate(); void cleared(); void fileAdded(FileItem *fileitem); void fileUpdated(FileItem *fileitem); protected: // never delete those KrView *_view; QWidget *_widget; private: bool _massSelectionUpdate; QTimer _saveDefaultSettingsTimer; static KrViewProperties::PropertyType _changedProperties; static KrView *_changedView; }; /**************************************************************************** * READ THIS FIRST: Using the view * * You always hold a pointer to KrView, thus you can only use functions declared * in this class. If you need something else, either this class is missing something * or you are ;-) * * The functions you'd usually want: * 1) getSelectedItems - returns all selected items, or (if none) the current item. * it never returns anything which includes the "..", and thus can return an empty list! * 2) getSelectedKrViewItems - the same as (1), but returns a QValueList with KrViewItems * 3) getCurrentItem, setCurrentItem - work with QString * 4) getFirst, getNext, getPrev, getCurrentKrViewItem - all work with KrViewItems, and * used to iterate through a list of items. note that getNext and getPrev accept a pointer * to the current item (used in detailedview for safe iterating), thus your loop should be: * for (KrViewItem *it = view->getFirst(); it!=0; it = view->getNext(it)) { blah; } * 5) nameToMakeCurrent(), setNameToMakeCurrent() - work with QString * * IMPORTANT NOTE: every one who subclasses this must call initProperties() in the constructor !!! */ class KrView { friend class KrViewItem; friend class KrViewOperator; public: class IconSizes : public QVector { public: IconSizes() : QVector() { *this << 12 << 16 << 22 << 32 << 48 << 64 << 128 << 256; } }; // instantiating a new view // 1. new KrView // 2. view->init() // notes: constructor does as little as possible, setup() does the rest. esp, note that // if you need something from operator or properties, move it into setup() void init(bool enableUpdateDefaultSettings = true); KrViewInstance *instance() { return &_instance; } static const IconSizes iconSizes; protected: void initProperties(); KrViewProperties *createViewProperties() { return new KrViewProperties(); } KrViewOperator *createOperator() { return new KrViewOperator(this, _widget); } virtual void setup() = 0; /////////////////////////////////////////////////////// // Every view must implement the following functions // /////////////////////////////////////////////////////// public: // interview related functions virtual QModelIndex getCurrentIndex() = 0; virtual bool isSelected(const QModelIndex &) = 0; virtual bool ensureVisibilityAfterSelect() = 0; virtual void selectRegion(KrViewItem *, KrViewItem *, bool) = 0; virtual uint numSelected() const = 0; virtual QList selectedUrls() = 0; virtual void setSelectionUrls(const QList urls) = 0; virtual KrViewItem *getFirst() = 0; virtual KrViewItem *getLast() = 0; virtual KrViewItem *getNext(KrViewItem *current) = 0; virtual KrViewItem *getPrev(KrViewItem *current) = 0; virtual KrViewItem *getCurrentKrViewItem() = 0; virtual KrViewItem *getKrViewItemAt(const QPoint &vp) = 0; virtual KrViewItem *findItemByName(const QString &name) = 0; virtual KrViewItem *findItemByFileItem(FileItem *vf) = 0; virtual KrViewItem *findItemByUrl(const QUrl &url) = 0; virtual QString getCurrentItem() const = 0; virtual void setCurrentItem(const QString &name, const QModelIndex &fallbackToIndex = QModelIndex()) = 0; virtual void setCurrentKrViewItem(KrViewItem *item) = 0; virtual void makeItemVisible(const KrViewItem *item) = 0; virtual bool isItemVisible(const KrViewItem *item) = 0; virtual void updateView() = 0; virtual void sort() = 0; virtual void refreshColors() = 0; virtual void redraw() = 0; virtual bool handleKeyEvent(QKeyEvent *e); virtual void prepareForActive() = 0; virtual void prepareForPassive() = 0; virtual void renameCurrentItem() = 0; // Rename current item. returns immediately virtual int itemsPerPage() = 0; virtual void showContextMenu(const QPoint &point = QPoint(0, 0)) = 0; protected: virtual KrViewItem *preAddItem(FileItem *fileitem) = 0; virtual void preDelItem(KrViewItem *item) = 0; virtual void preUpdateItem(FileItem *fileitem) = 0; virtual void copySettingsFrom(KrView *other) = 0; virtual void populate(const QList &fileItems, FileItem *dummy) = 0; virtual void intSetSelected(const FileItem *fileitem, bool select) = 0; virtual void clear(); void addItem(FileItem *fileitem); void updateItem(FileItem *fileitem); void delItem(const QString &name); public: ////////////////////////////////////////////////////// // the following functions are already implemented, // // and normally - should NOT be re-implemented. // ////////////////////////////////////////////////////// uint numFiles() const { return _count - _numDirs; } uint numDirs() const { return _numDirs; } uint count() const { return _count; } void getSelectedItems(QStringList *names, bool ignoreJustFocused = false); void getItemsByMask(QString mask, QStringList *names, bool dirs = true, bool files = true); void getSelectedKrViewItems(KrViewItemList *items); void selectAllIncludingDirs() { changeSelection(KRQuery("*"), true, true); } void select(const KRQuery &filter = KRQuery("*")) { changeSelection(filter, true); } void unselect(const KRQuery &filter = KRQuery("*")) { changeSelection(filter, false); } void unselectAll() { changeSelection(KRQuery("*"), false, true); } void invertSelection(); QString nameToMakeCurrent() const { return _nameToMakeCurrent; } void setNameToMakeCurrent(const QString name) { _nameToMakeCurrent = name; } QString firstUnmarkedBelowCurrent(); QString statistics(); const KrViewProperties *properties() const { return _properties; } KrViewOperator *op() const { return _operator; } void showPreviews(bool show); bool previewsShown() { return _previews != 0; } void applySettingsToOthers(); void setFiles(DirListerInterface *files); void refresh(); bool changeSelection(const KRQuery &filter, bool select); bool changeSelection(const KRQuery &filter, bool select, bool includeDirs, bool makeVisible = false); bool isFiltered(FileItem *fileitem); void setSelected(const FileItem *fileitem, bool select); ///////////////////////////////////////////////////////////// // the following functions have a default and minimalistic // // implementation, and may be re-implemented if needed // ///////////////////////////////////////////////////////////// virtual void setSortMode(KrViewProperties::ColumnType sortColumn, bool descending) { sortModeUpdated(sortColumn, descending); } const KRQuery &filterMask() const { return _properties->filterMask; } KrViewProperties::FilterSpec filter() const { return _properties->filter; } void setFilter(KrViewProperties::FilterSpec filter); void setFilter(KrViewProperties::FilterSpec filter, FilterSettings customFilter, bool applyToDirs); void customSelection(bool select); int defaultFileIconSize(); virtual void setFileIconSize(int size); void setDefaultFileIconSize() { setFileIconSize(defaultFileIconSize()); } void zoomIn(); void zoomOut(); // save this view's settings to be restored after restart virtual void saveSettings(KConfigGroup grp, KrViewProperties::PropertyType properties = KrViewProperties::AllProperties); inline QWidget *widget() { return _widget; } inline int fileIconSize() const { return _fileIconSize; } inline bool isFocused() const { return _focused; } QPixmap getIcon(FileItem *fileitem); void setMainWindow(QWidget *mainWindow) { _mainWindow = mainWindow; } // save this view's settings as default for new views of this type void saveDefaultSettings( KrViewProperties::PropertyType properties = KrViewProperties::AllProperties); // restore the default settings for this view type void restoreDefaultSettings(); // call this to restore this view's settings after restart void restoreSettings(KConfigGroup grp); void saveSelection(); void restoreSelection(); bool canRestoreSelection() { return !_savedSelection.isEmpty(); } void clearSavedSelection(); void markSameBaseName(); void markSameExtension(); // todo: what about selection modes ??? virtual ~KrView(); static QPixmap getIcon(FileItem *fileitem, bool active, int size = 0); static QPixmap processIcon(const QPixmap &icon, bool dim, const QColor &dimColor, int dimFactor, bool symlink); - static QString krPermissionString(const FileItem *fileitem); - static QString sizeToString(const KrViewProperties *properties, KIO::filesize_t size); + + // Get GUI strings for file item properties + static QString krPermissionText(const FileItem *fileitem); + static QString permissionsText(const KrViewProperties *properties, const FileItem *fileItem); + static QString sizeText(const KrViewProperties *properties, KIO::filesize_t size); + static QString mimeTypeText(FileItem *fileItem); protected: KrView(KrViewInstance &instance, KConfig *cfg); virtual void doRestoreSettings(KConfigGroup grp); virtual KIO::filesize_t calcSize() = 0; virtual KIO::filesize_t calcSelectedSize() = 0; void sortModeUpdated(KrViewProperties::ColumnType sortColumn, bool descending); inline void setWidget(QWidget *w) { _widget = w; } KConfig *_config; KrViewProperties *_properties; KrViewOperator *_operator; bool _focused; int _fileIconSize; private: void updatePreviews(); void saveSortMode(KConfigGroup &group); void restoreSortMode(KConfigGroup &group); KrViewInstance &_instance; DirListerInterface *_files; QWidget *_mainWindow; QWidget *_widget; QList _savedSelection; QString _nameToMakeCurrent; KrPreviews *_previews; bool _updateDefaultSettings; bool _ignoreSettingsChange; QRegExp _quickFilterMask; uint _count, _numDirs; FileItem *_dummyFileItem; }; #endif /* KRVIEW_H */ diff --git a/krusader/Panel/krviewitem.cpp b/krusader/Panel/krviewitem.cpp index 940b01b1..bd5cc7bd 100644 --- a/krusader/Panel/krviewitem.cpp +++ b/krusader/Panel/krviewitem.cpp @@ -1,148 +1,148 @@ /***************************************************************************** * Copyright (C) 2000-2002 Shie Erlich * * Copyright (C) 2000-2002 Rafi Yanai * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This package is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this package; if not, write to the Free Software * * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ #include "krviewitem.h" #include "krinterview.h" #include "krvfsmodel.h" #include "../FileSystem/fileitem.h" #include "../FileSystem/krpermhandler.h" // QtCore #include #include #include // QtGui #include #include KrViewItem::KrViewItem(FileItem *fileitem, KrInterView *parentView): _fileitem(fileitem), _view(parentView), _viewProperties(parentView->properties()), _hasExtension(false), _hidden(false), _extension("") { dummyFileItem = parentView->_model->dummyFileItem() == fileitem; if (fileitem) { // check if the file has an extension const QString& fileitemName = fileitem->getName(); int loc = fileitemName.lastIndexOf('.'); if (loc > 0) { // avoid mishandling of .bashrc and friend // check if it has one of the predefined 'atomic extensions' for (QStringList::const_iterator i = _viewProperties->atomicExtensions.begin(); i != _viewProperties->atomicExtensions.end(); ++i) { if (fileitemName.endsWith(*i)) { loc = fileitemName.length() - (*i).length(); break; } } _name = fileitemName.left(loc); _extension = fileitemName.mid(loc + 1); _hasExtension = true; } if (fileitemName.startsWith('.')) _hidden = true; } } const QString& KrViewItem::name(bool withExtension) const { if (!withExtension && _hasExtension) return _name; else return _fileitem->getName(); } QString KrViewItem::description() const { if (dummyFileItem) return i18n("Climb up the folder tree"); // else is implied QString mimeTypeComment; QMimeType mt = QMimeDatabase().mimeTypeForName(_fileitem->getMime()); if (mt.isValid()) mimeTypeComment = mt.comment(); - const QString size = KrView::sizeToString(_viewProperties, _fileitem->getSize()); + const QString size = KrView::sizeText(_viewProperties, _fileitem->getSize()); QString text = _fileitem->getName(); if (_fileitem->isSymLink()) { text += " -> " + _fileitem->getSymDest() + " "; if (_fileitem->isBrokenLink()) text += i18n("(Broken Link)"); else if (mimeTypeComment.isEmpty()) text += i18n("Symbolic Link") ; else text += i18n("%1 (Link)", mimeTypeComment); } else { if (_fileitem->isDir()) text += "/"; if (S_ISREG(_fileitem->getMode()) || (_fileitem->isDir() && _fileitem->getSize() != 0)) text += QString(" (%1)").arg(size); text += " " + mimeTypeComment; } return text; } QPixmap KrViewItem::icon() { #if 0 QPixmap *p; // This is bad - very bad. the function must return a valid reference, // This is an interface flow - shie please fix it with a function that return QPixmap* // this way we can return 0 - and do our error checking... // shie answers: why? what's the difference? if we return an empty pixmap, others can use it as it // is, without worrying or needing to do error checking. empty pixmap displays nothing #endif if (dummyFileItem || !_viewProperties->displayIcons) return QPixmap(); else return KrView::getIcon(_fileitem, true); } bool KrViewItem::isSelected() const { return _view->isSelected(_fileitem); } void KrViewItem::setSelected(bool s) { _view->setSelected(_fileitem, s); if(!_view->op()->isMassSelectionUpdate()) { redraw(); _view->op()->emitSelectionChanged(); } } QRect KrViewItem::itemRect() const { return _view->itemRect(_fileitem); } void KrViewItem::redraw() { _view->_itemView->viewport()->update(itemRect()); } void KrViewItem::setSize(KIO::filesize_t size) { _fileitem->setSize(size); }