]> cloud.milkyroute.net Git - dolphin.git/commitdiff
Merged very early alpha-version of Dolphin 2.0
authorPeter Penz <peter.penz19@gmail.com>
Sat, 30 Jul 2011 18:13:09 +0000 (20:13 +0200)
committerPeter Penz <peter.penz19@gmail.com>
Sat, 30 Jul 2011 18:13:41 +0000 (20:13 +0200)
Dolphin 2.0 will get a new view-engine with the
following improvements:
- Better performance
- Animated transitions
- No clipped filenames due to dynamic item-sizes
- Grouping support for all view-modes
- Non-rectangular selection areas
- Simplified code for better maintenance

More details will be provided in a blog-entry during
the next days.

Please note that the code is in a very
early alpha-stage and although the most tricky parts
have been implemented already very basic things like
drag and drop or selections have not been pushed yet.
Those things are rather trivial to implement but this
still will take some time.

130 files changed:
src/CMakeLists.txt
src/config-X11.h.cmake [new file with mode: 0644]
src/dolphincontextmenu.cpp
src/dolphinmainwindow.cpp
src/dolphinpart.cpp
src/dolphinpart.desktop
src/dolphinui.rc
src/dolphinviewcontainer.cpp
src/dolphinviewcontainer.h
src/kitemviews/kfileitemlistview.cpp [new file with mode: 0644]
src/kitemviews/kfileitemlistview.h [new file with mode: 0644]
src/kitemviews/kfileitemlistwidget.cpp [new file with mode: 0644]
src/kitemviews/kfileitemlistwidget.h [new file with mode: 0644]
src/kitemviews/kfileitemmodel.cpp [new file with mode: 0644]
src/kitemviews/kfileitemmodel.h [new file with mode: 0644]
src/kitemviews/kfileitemmodelrolesupdater.cpp [new file with mode: 0644]
src/kitemviews/kfileitemmodelrolesupdater.h [new file with mode: 0644]
src/kitemviews/kitemlistcontainer.cpp [new file with mode: 0644]
src/kitemviews/kitemlistcontainer.h [new file with mode: 0644]
src/kitemviews/kitemlistcontroller.cpp [new file with mode: 0644]
src/kitemviews/kitemlistcontroller.h [new file with mode: 0644]
src/kitemviews/kitemlistgroupheader.cpp [new file with mode: 0644]
src/kitemviews/kitemlistgroupheader.h [moved from src/settings/viewmodes/columnviewsettingspage.h with 57% similarity]
src/kitemviews/kitemlistselectionmanager.cpp [new file with mode: 0644]
src/kitemviews/kitemlistselectionmanager.h [new file with mode: 0644]
src/kitemviews/kitemlistsizehintresolver.cpp [new file with mode: 0644]
src/kitemviews/kitemlistsizehintresolver_p.h [new file with mode: 0644]
src/kitemviews/kitemliststyleoption.cpp [moved from src/tests/dolphinviewtest_details.cpp with 70% similarity]
src/kitemviews/kitemliststyleoption.h [moved from src/tests/dolphinviewtest_columns.cpp with 71% similarity]
src/kitemviews/kitemlistview.cpp [new file with mode: 0644]
src/kitemviews/kitemlistview.h [new file with mode: 0644]
src/kitemviews/kitemlistviewanimation.cpp [new file with mode: 0644]
src/kitemviews/kitemlistviewanimation_p.h [new file with mode: 0644]
src/kitemviews/kitemlistviewlayouter.cpp [new file with mode: 0644]
src/kitemviews/kitemlistviewlayouter_p.h [new file with mode: 0644]
src/kitemviews/kitemlistwidget.cpp [new file with mode: 0644]
src/kitemviews/kitemlistwidget.h [new file with mode: 0644]
src/kitemviews/kitemmodelbase.cpp [new file with mode: 0644]
src/kitemviews/kitemmodelbase.h [new file with mode: 0644]
src/kitemviews/kpixmapmodifier.cpp [new file with mode: 0644]
src/kitemviews/kpixmapmodifier_p.h [moved from src/tests/dolphinviewtest_icons.cpp with 71% similarity]
src/main.cpp
src/panels/folders/dolphin_folderspanelsettings.kcfg
src/panels/folders/folderspanel.cpp
src/panels/folders/folderspanel.h
src/panels/folders/paneltreeview.cpp
src/panels/folders/treeviewcontextmenu.cpp
src/panels/information/dolphin_informationpanelsettings.kcfg
src/panels/information/informationpanelcontent.cpp
src/panels/places/placespanel.cpp
src/settings/additionalinfodialog.cpp
src/settings/additionalinfodialog.h
src/settings/applyviewpropsjob.cpp
src/settings/dolphin_columnmodesettings.kcfgc [deleted file]
src/settings/dolphin_compactmodesettings.kcfg [moved from src/settings/dolphin_columnmodesettings.kcfg with 79% similarity]
src/settings/dolphin_compactmodesettings.kcfgc [new file with mode: 0644]
src/settings/dolphin_detailsmodesettings.kcfg
src/settings/dolphin_detailsmodesettings.kcfgc
src/settings/dolphin_directoryviewpropertysettings.kcfg
src/settings/dolphin_iconsmodesettings.kcfg
src/settings/dolphin_iconsmodesettings.kcfgc
src/settings/dolphinsettings.cpp
src/settings/dolphinsettings.h
src/settings/kcm/kcmdolphinviewmodes.cpp
src/settings/viewmodes/columnviewsettingspage.cpp [deleted file]
src/settings/viewmodes/detailsviewsettingspage.cpp
src/settings/viewmodes/detailsviewsettingspage.h
src/settings/viewmodes/iconsviewsettingspage.cpp
src/settings/viewmodes/iconsviewsettingspage.h
src/settings/viewmodes/viewsettingspage.cpp
src/settings/viewpropertiesdialog.cpp
src/settings/viewpropertiesdialog.h
src/statusbar/dolphinstatusbar.cpp
src/statusbar/dolphinstatusbar.h
src/tests/CMakeLists.txt
src/tests/dolphindetailsviewtest.cpp [deleted file]
src/tests/dolphintreeviewtest.cpp [deleted file]
src/tests/dolphinviewtest_allviewmodes.cpp [deleted file]
src/tests/dolphinviewtest_allviewmodes.h [deleted file]
src/tests/kfileitemlistviewtest.cpp [new file with mode: 0644]
src/tests/kfileitemmodeltest.cpp [new file with mode: 0644]
src/tests/testbase.cpp [deleted file]
src/tests/testbase.h [deleted file]
src/tests/testdir.cpp
src/tests/testdir.h
src/views/additionalinfoaccessor.cpp
src/views/additionalinfoaccessor.h
src/views/dolphincategorydrawer.cpp [deleted file]
src/views/dolphincategorydrawer.h [deleted file]
src/views/dolphincolumnview.cpp [deleted file]
src/views/dolphincolumnview.h [deleted file]
src/views/dolphincolumnviewcontainer.cpp [deleted file]
src/views/dolphincolumnviewcontainer.h [deleted file]
src/views/dolphindetailsview.cpp [deleted file]
src/views/dolphindetailsview.h [deleted file]
src/views/dolphindetailsviewexpander.cpp [deleted file]
src/views/dolphindetailsviewexpander.h [deleted file]
src/views/dolphindirlister.cpp
src/views/dolphindirlister.h
src/views/dolphinfileitemdelegate.cpp [deleted file]
src/views/dolphinfileitemdelegate.h [deleted file]
src/views/dolphiniconsview.cpp [deleted file]
src/views/dolphiniconsview.h [deleted file]
src/views/dolphinitemlistcontainer.cpp [new file with mode: 0644]
src/views/dolphinitemlistcontainer.h [new file with mode: 0644]
src/views/dolphinmodel.cpp [deleted file]
src/views/dolphinmodel.h [deleted file]
src/views/dolphinsortfilterproxymodel.cpp [deleted file]
src/views/dolphinsortfilterproxymodel.h [deleted file]
src/views/dolphintreeview.cpp [deleted file]
src/views/dolphintreeview.h [deleted file]
src/views/dolphinview.cpp
src/views/dolphinview.h
src/views/dolphinviewactionhandler.cpp
src/views/dolphinviewactionhandler.h
src/views/dolphinviewcontroller.cpp [deleted file]
src/views/dolphinviewcontroller.h [deleted file]
src/views/renamedialog.cpp
src/views/selectionmanager.cpp [deleted file]
src/views/selectionmanager.h [deleted file]
src/views/selectiontoggle.cpp [deleted file]
src/views/selectiontoggle.h [deleted file]
src/views/tooltips/tooltipmanager.cpp
src/views/tooltips/tooltipmanager.h
src/views/versioncontrol/versioncontrolobserver.cpp
src/views/versioncontrol/versioncontrolobserver.h
src/views/viewextensionsfactory.cpp [deleted file]
src/views/viewextensionsfactory.h [deleted file]
src/views/viewproperties.cpp
src/views/viewproperties.h

index bc880bb67c92600a706965f0d2a6fc9ea810b2a8..314c6cb280da4e8c02fe1a44747382cc2becc4e6 100644 (file)
@@ -3,6 +3,9 @@ macro_log_feature(Nepomuk_FOUND "Nepomuk" "Nepomuk" "http://www.kde.org" FALSE "
 macro_bool_to_01(Nepomuk_FOUND HAVE_NEPOMUK)
 configure_file(config-nepomuk.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-nepomuk.h )
 
+macro_bool_to_01(X11_Xrender_FOUND HAVE_XRENDER)
+configure_file(config-X11.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-X11.h )
+
 include_directories( ${KDE4_INCLUDE_DIR} ${QT_INCLUDES} )
 
 if (Nepomuk_FOUND)
@@ -15,47 +18,49 @@ add_subdirectory(tests)
 ########### next target ###############
 
 set(dolphinprivate_LIB_SRCS
+    kitemviews/kfileitemlistview.cpp
+    kitemviews/kfileitemlistwidget.cpp
+    kitemviews/kfileitemmodel.cpp
+    kitemviews/kfileitemmodelrolesupdater.cpp
+    kitemviews/kitemlistcontainer.cpp
+    kitemviews/kitemlistcontroller.cpp
+    kitemviews/kitemlistgroupheader.cpp
+    kitemviews/kitemlistselectionmanager.cpp
+    kitemviews/kitemlistsizehintresolver.cpp
+    kitemviews/kitemliststyleoption.cpp
+    kitemviews/kitemlistview.cpp
+    kitemviews/kitemlistviewanimation.cpp
+    kitemviews/kitemlistviewlayouter.cpp
+    kitemviews/kitemlistwidget.cpp
+    kitemviews/kitemmodelbase.cpp
+    kitemviews/kpixmapmodifier.cpp
     settings/additionalinfodialog.cpp
     settings/applyviewpropsjob.cpp
     settings/dolphinsettings.cpp
     settings/viewpropertiesdialog.cpp
     settings/viewpropsprogressinfo.cpp
     views/additionalinfoaccessor.cpp
-    views/dolphincategorydrawer.cpp
     views/dolphindirlister.cpp
     views/dolphinview.cpp
-    views/dolphindetailsview.cpp
-    views/dolphindetailsviewexpander.cpp
-    views/dolphinfileitemdelegate.cpp
-    views/dolphiniconsview.cpp
-    views/dolphincolumnview.cpp
-    views/dolphincolumnviewcontainer.cpp
-    views/dolphinmodel.cpp
+    views/dolphinitemlistcontainer.cpp
     views/dolphinnewfilemenuobserver.cpp
     views/dolphinremoteencoding.cpp
-    views/dolphinsortfilterproxymodel.cpp
-    views/dolphintreeview.cpp
     views/dolphinviewactionhandler.cpp
     views/dolphinviewautoscroller.cpp
-    views/dolphinviewcontroller.cpp
-    views/draganddrophelper.cpp
     views/folderexpander.cpp
     views/renamedialog.cpp
-    views/selectiontoggle.cpp
-    views/selectionmanager.cpp
     views/tooltips/filemetadatatooltip.cpp
     views/tooltips/tooltipmanager.cpp
     views/versioncontrol/pendingthreadsmaintainer.cpp
     views/versioncontrol/updateitemstatesthread.cpp
     views/versioncontrol/versioncontrolobserver.cpp
-    views/viewextensionsfactory.cpp
     views/viewmodecontroller.cpp
     views/viewproperties.cpp
     views/zoomlevelinfo.cpp
 )
 
 kde4_add_kcfg_files(dolphinprivate_LIB_SRCS
-    settings/dolphin_columnmodesettings.kcfgc
+    settings/dolphin_compactmodesettings.kcfgc
     settings/dolphin_directoryviewpropertysettings.kcfgc
     settings/dolphin_detailsmodesettings.kcfgc
     settings/dolphin_iconsmodesettings.kcfgc
@@ -69,6 +74,10 @@ target_link_libraries(dolphinprivate ${KDE4_KFILE_LIBS} konq ${KDE4_KNEWSTUFF3_L
 if (Nepomuk_FOUND)
   target_link_libraries(dolphinprivate ${NEPOMUK_LIBRARIES} ${NEPOMUK_QUERY_LIBRARIES} nepomukutils ${SOPRANO_LIBRARIES})
 endif (Nepomuk_FOUND)
+if(X11_Xrender_FOUND)
+  target_link_libraries(dolphinprivate ${X11_Xrender_LIB} )
+endif(X11_Xrender_FOUND)
+
 
 
 set_target_properties(dolphinprivate PROPERTIES VERSION ${GENERIC_LIB_VERSION} SOVERSION ${GENERIC_LIB_SOVERSION} )
@@ -129,7 +138,6 @@ set(dolphin_SRCS
     settings/servicemodel.cpp
     settings/startup/startupsettingspage.cpp
     settings/trash/trashsettingspage.cpp
-    settings/viewmodes/columnviewsettingspage.cpp
     settings/viewmodes/detailsviewsettingspage.cpp
     settings/viewmodes/dolphinfontrequester.cpp
     settings/viewmodes/iconsizegroupbox.cpp
@@ -144,6 +152,9 @@ set(dolphin_SRCS
 kde4_add_kcfg_files(dolphin_SRCS
     panels/folders/dolphin_folderspanelsettings.kcfgc
     panels/information/dolphin_informationpanelsettings.kcfgc
+    settings/dolphin_compactmodesettings.kcfgc
+    settings/dolphin_detailsmodesettings.kcfgc
+    settings/dolphin_iconsmodesettings.kcfgc
     search/dolphin_searchsettings.kcfgc
     settings/dolphin_versioncontrolsettings.kcfgc
 )
@@ -190,7 +201,6 @@ install(TARGETS dolphin ${INSTALL_TARGETS_DEFAULT_ARGS})
 
 set(kcm_dolphinviewmodes_PART_SRCS
     settings/kcm/kcmdolphinviewmodes.cpp
-    settings/viewmodes/columnviewsettingspage.cpp
     settings/viewmodes/detailsviewsettingspage.cpp
     settings/viewmodes/dolphinfontrequester.cpp
     settings/viewmodes/iconsizegroupbox.cpp
@@ -221,7 +231,7 @@ set(kcm_dolphingeneral_PART_SRCS
     settings/servicemodel.cpp)
 
 kde4_add_kcfg_files(kcm_dolphinviewmodes_PART_SRCS
-    settings/dolphin_columnmodesettings.kcfgc
+    settings/dolphin_compactmodesettings.kcfgc
     settings/dolphin_directoryviewpropertysettings.kcfgc
     settings/dolphin_detailsmodesettings.kcfgc
     settings/dolphin_iconsmodesettings.kcfgc
@@ -273,7 +283,7 @@ install(TARGETS kio_filenamesearch DESTINATION ${PLUGIN_INSTALL_DIR})
 install( PROGRAMS dolphin.desktop DESTINATION ${XDG_APPS_INSTALL_DIR} )
 install( FILES settings/dolphin_directoryviewpropertysettings.kcfg
                settings/dolphin_generalsettings.kcfg
-               settings/dolphin_columnmodesettings.kcfg
+               settings/dolphin_compactmodesettings.kcfg
                settings/dolphin_iconsmodesettings.kcfg
                settings/dolphin_detailsmodesettings.kcfg
                settings/dolphin_versioncontrolsettings.kcfg
diff --git a/src/config-X11.h.cmake b/src/config-X11.h.cmake
new file mode 100644 (file)
index 0000000..d15b985
--- /dev/null
@@ -0,0 +1 @@
+#cmakedefine HAVE_XRENDER 1
index 7aac7707bb7c161698ef0e0122b5ab10fec5b2d9..2eb4e92d03f4f1a5903ede071e2901f9b1babe7a 100644 (file)
@@ -234,7 +234,7 @@ void DolphinContextMenu::openItemContextMenu()
             // setup 'Create New' menu
             DolphinNewFileMenu* newFileMenu = new DolphinNewFileMenu(m_mainWindow);
             const DolphinView* view = m_mainWindow->activeViewContainer()->view();
-            newFileMenu->setViewShowsHiddenFiles(view->showHiddenFiles());
+            newFileMenu->setViewShowsHiddenFiles(view->hiddenFilesShown());
             newFileMenu->checkUpToDate();
             newFileMenu->setPopupFiles(m_fileInfo.url());
             newFileMenu->setEnabled(selectedItemsProperties().supportsWriting());
@@ -320,7 +320,7 @@ void DolphinContextMenu::openViewportContextMenu()
     // setup 'Create New' menu
     KNewFileMenu* newFileMenu = m_mainWindow->newFileMenu();
     const DolphinView* view = m_mainWindow->activeViewContainer()->view();
-    newFileMenu->setViewShowsHiddenFiles(view->showHiddenFiles());
+    newFileMenu->setViewShowsHiddenFiles(view->hiddenFilesShown());
     newFileMenu->checkUpToDate();
     newFileMenu->setPopupFiles(m_baseUrl);
     m_popup->addMenu(newFileMenu->menu());
index 0f075a11cb4d0456eb60f989b6b56e2fbc0043a2..a379f31b095825bf354e12f6b7935c64de401751 100644 (file)
@@ -42,7 +42,6 @@
 #include "statusbar/dolphinstatusbar.h"
 #include "views/dolphinviewactionhandler.h"
 #include "views/dolphinremoteencoding.h"
-#include "views/draganddrophelper.h"
 #include "views/viewproperties.h"
 
 #ifndef Q_OS_WIN
@@ -161,8 +160,8 @@ DolphinMainWindow::DolphinMainWindow() :
             this, SLOT(showCommand(CommandType)));
     connect(DolphinSettings::instance().placesModel(), SIGNAL(errorMessage(const QString&)),
             this, SLOT(showErrorMessage(const QString&)));
-    connect(&DragAndDropHelper::instance(), SIGNAL(errorMessage(const QString&)),
-            this, SLOT(showErrorMessage(const QString&)));
+    //connect(&DragAndDropHelper::instance(), SIGNAL(errorMessage(const QString&)),
+    //        this, SLOT(showErrorMessage(const QString&)));
 
     const DolphinSettings& settings = DolphinSettings::instance();
 
@@ -725,14 +724,14 @@ void DolphinMainWindow::readProperties(const KConfigGroup& group)
 
 void DolphinMainWindow::updateNewMenu()
 {
-    m_newFileMenu->setViewShowsHiddenFiles(activeViewContainer()->view()->showHiddenFiles());
+    m_newFileMenu->setViewShowsHiddenFiles(activeViewContainer()->view()->hiddenFilesShown());
     m_newFileMenu->checkUpToDate();
     m_newFileMenu->setPopupFiles(activeViewContainer()->url());
 }
 
 void DolphinMainWindow::createDirectory()
 {
-    m_newFileMenu->setViewShowsHiddenFiles(activeViewContainer()->view()->showHiddenFiles());
+    m_newFileMenu->setViewShowsHiddenFiles(activeViewContainer()->view()->hiddenFilesShown());
     m_newFileMenu->setPopupFiles(activeViewContainer()->url());
     m_newFileMenu->createDirectory();
 }
@@ -1313,7 +1312,8 @@ void DolphinMainWindow::tabDropEvent(int tab, QDropEvent* event)
     if (!urls.isEmpty() && tab != -1) {
         const ViewTab& viewTab = m_viewTab[tab];
         const KUrl destPath = viewTab.isPrimaryViewActive ? viewTab.primaryView->url() : viewTab.secondaryView->url();
-        DragAndDropHelper::instance().dropUrls(KFileItem(), destPath, event, m_tabBar);
+        Q_UNUSED(destPath);
+        //DragAndDropHelper::instance().dropUrls(KFileItem(), destPath, event, m_tabBar);
     }
 }
 
@@ -2178,7 +2178,7 @@ void DolphinMainWindow::createSecondaryView(int tabIndex)
     const int newWidth = (m_viewTab[tabIndex].primaryView->width() - splitter->handleWidth()) / 2;
 
     const DolphinView* view = m_viewTab[tabIndex].primaryView->view();
-    m_viewTab[tabIndex].secondaryView = createViewContainer(view->rootUrl(), 0);
+    m_viewTab[tabIndex].secondaryView = createViewContainer(view->url(), 0);
     splitter->addWidget(m_viewTab[tabIndex].secondaryView);
     splitter->setSizes(QList<int>() << newWidth << newWidth);
     connectViewSignals(m_viewTab[tabIndex].secondaryView);
index 2990435953e0dd47f3e707146b64d7a06631d597..736ec6f4f1f491c93c42143cab40a11588319f94 100644 (file)
@@ -44,8 +44,6 @@
 #include "settings/dolphinsettings.h"
 #include "views/dolphinview.h"
 #include "views/dolphinviewactionhandler.h"
-#include "views/dolphinsortfilterproxymodel.h"
-#include "views/dolphinmodel.h"
 #include "views/dolphinnewfilemenuobserver.h"
 #include "views/dolphinremoteencoding.h"
 #include "views/dolphindirlister.h"
@@ -96,7 +94,7 @@ DolphinPart::DolphinPart(QWidget* parentWidget, QObject* parent, const QVariantL
             this, SLOT(slotSelectionChanged(KFileItemList)));
     connect(m_view, SIGNAL(requestItemInfo(KFileItem)),
             this, SLOT(slotRequestItemInfo(KFileItem)));
-    connect(m_view, SIGNAL(modeChanged()),
+    connect(m_view, SIGNAL(modeChanged(DolphinView::Mode,DolphinView::Mode)),
             this, SIGNAL(viewModeChanged())); // relay signal
     connect(m_view, SIGNAL(redirection(KUrl, KUrl)),
             this, SLOT(slotRedirection(KUrl, KUrl)));
@@ -531,7 +529,7 @@ void DolphinPart::updateNewMenu()
 {
     // As requested by KNewFileMenu :
     m_newFileMenu->checkUpToDate();
-    m_newFileMenu->setViewShowsHiddenFiles(m_view->showHiddenFiles());
+    m_newFileMenu->setViewShowsHiddenFiles(m_view->hiddenFilesShown());
     // And set the files that the menu apply on :
     m_newFileMenu->setPopupFiles(url());
 }
@@ -548,7 +546,7 @@ void DolphinPart::updateProgress(int percent)
 
 void DolphinPart::createDirectory()
 {
-    m_newFileMenu->setViewShowsHiddenFiles(m_view->showHiddenFiles());
+    m_newFileMenu->setViewShowsHiddenFiles(m_view->hiddenFilesShown());
     m_newFileMenu->setPopupFiles(url());
     m_newFileMenu->createDirectory();
 }
index 511f7f90085a1b1d6303bee3e1a6f1de7e0caecc..13dfacf4798ad78d72453c768d232cc4b588877c 100644 (file)
@@ -271,7 +271,7 @@ Name[te]=వివరాలు
 Name[tg]=Тафсилотҳо
 Name[th]=รายละเอียด
 Name[tr]=Ayrıntılar
-Name[ug]=تÛ\95پسÙ\89Ù\84اتÙ\89
+Name[ug]=تÛ\95پسÙ\89Ù\84اتÙ\84ار
 Name[uk]=Подробиці
 Name[uz]=Tafsilotlar
 Name[uz@cyrillic]=Тафсилотлар
index 82803cc1b5f3692dc10c73eeac028303bf8487a6..68e03752f5708e199ac24692d3d4001af015eeaf 100644 (file)
@@ -90,8 +90,8 @@
         <Action name="go_forward" />
         <Separator name="separator_1" />
         <Action name="icons" />
+        <Action name="compact" />
         <Action name="details" />
-        <Action name="columns" />
         <Separator name="separator_0" />
         <Action name="edit_find"/>
         <Action name="show_preview" />
         <Action priority="0" name="go_home"/>
         <Action priority="0" name="stop"/>
         <Action priority="0" name="icons"/>
+        <Action priority="0" name="compact"/>
         <Action priority="0" name="details"/>
-        <Action priority="0" name="columns"/>
         <Action priority="0" name="view_zoom_in"/>
         <Action priority="0" name="view_zoom_out"/>
         <Action priority="0" name="edit_cut"/>
index 67ea84d1b42a5e4f8e93ba05efd52d39399be5b9..8e00b0afc9a21c96775423d7658a7428a45b5cfb 100644 (file)
 #include "search/dolphinsearchbox.h"
 #include "settings/dolphinsettings.h"
 #include "statusbar/dolphinstatusbar.h"
-#include "views/dolphincolumnview.h"
-#include "views/dolphindetailsview.h"
-#include "views/draganddrophelper.h"
-#include "views/dolphiniconsview.h"
-#include "views/dolphinmodel.h"
-#include "views/dolphinviewcontroller.h"
 #include "views/viewmodecontroller.h"
 #include "views/viewproperties.h"
 
@@ -115,11 +109,12 @@ DolphinViewContainer::DolphinViewContainer(const KUrl& url, QWidget* parent) :
     connect(m_view, SIGNAL(urlIsFileError(const KUrl&)),  this, SLOT(openFile(const KUrl&)));
     connect(m_view, SIGNAL(selectionChanged(const KFileItemList&)),    this, SLOT(delayedStatusBarUpdate()));
     connect(m_view, SIGNAL(operationCompletedMessage(const QString&)), this, SLOT(showOperationCompletedMessage(const QString&)));
+    connect(m_view, SIGNAL(urlAboutToBeChanged(const KUrl&)),          this, SLOT(slotViewUrlAboutToBeChanged(const KUrl&)));
 
+    connect(m_urlNavigator, SIGNAL(urlAboutToBeChanged(const KUrl&)),
+            this, SLOT(slotUrlNavigatorLocationAboutToBeChanged(const KUrl&)));
     connect(m_urlNavigator, SIGNAL(urlChanged(const KUrl&)),
             this, SLOT(slotUrlNavigatorLocationChanged(const KUrl&)));
-    connect(m_urlNavigator, SIGNAL(urlAboutToBeChanged(const KUrl&)),
-            this, SLOT(saveViewState()));
     connect(m_urlNavigator, SIGNAL(historyChanged()),
             this, SLOT(slotHistoryChanged()));
 
@@ -378,6 +373,50 @@ void DolphinViewContainer::slotFinishedPathLoading()
     }
 }
 
+void DolphinViewContainer::slotItemTriggered(const KFileItem& item)
+{
+    KUrl url = item.targetUrl();
+
+    if (item.isDir()) {
+        m_view->setUrl(url);
+        return;
+    }
+
+    const GeneralSettings* settings = DolphinSettings::instance().generalSettings();
+    const bool browseThroughArchives = settings->browseThroughArchives();
+    if (browseThroughArchives && item.isFile() && url.isLocalFile()) {
+        // Generic mechanism for redirecting to tar:/<path>/ when clicking on a tar file,
+        // zip:/<path>/ when clicking on a zip file, etc.
+        // The .protocol file specifies the mimetype that the kioslave handles.
+        // Note that we don't use mimetype inheritance since we don't want to
+        // open OpenDocument files as zip folders...
+        const QString protocol = KProtocolManager::protocolForArchiveMimetype(item.mimetype());
+        if (!protocol.isEmpty()) {
+            url.setProtocol(protocol);
+            m_view->setUrl(url);
+            return;
+        }
+    }
+
+    if (item.mimetype() == QLatin1String("application/x-desktop")) {
+        // Redirect to the URL in Type=Link desktop files
+        KDesktopFile desktopFile(url.toLocalFile());
+        if (desktopFile.hasLinkType()) {
+            url = desktopFile.readUrl();
+            m_view->setUrl(url);
+            return;
+        }
+    }
+
+    item.run();
+}
+
+void DolphinViewContainer::openFile(const KUrl& url)
+{
+    const KFileItem item(KFileItem::Unknown, KFileItem::Unknown, url);
+    slotItemTriggered(item);
+}
+
 void DolphinViewContainer::showItemInfo(const KFileItem& item)
 {
     if (item.isNull()) {
@@ -427,20 +466,36 @@ void DolphinViewContainer::activate()
     setActive(true);
 }
 
-void DolphinViewContainer::saveViewState()
+void DolphinViewContainer::slotViewUrlAboutToBeChanged(const KUrl& url)
 {
-    QByteArray locationState;
-    QDataStream stream(&locationState, QIODevice::WriteOnly);
-    m_view->saveState(stream);
-    m_urlNavigator->saveLocationState(locationState);
+    // URL changes of the view can happen in two ways:
+    // 1. The URL navigator gets changed and will trigger the view to update its URL
+    // 2. The URL of the view gets changed and will trigger the URL navigator to update
+    //    its URL (e.g. by clicking on an item)
+    // In this scope the view-state may only get saved in case 2:
+    if (url != m_urlNavigator->locationUrl()) {
+        saveViewState();
+    }
+}
+
+void DolphinViewContainer::slotUrlNavigatorLocationAboutToBeChanged(const KUrl& url)
+{
+    // URL changes of the view can happen in two ways:
+    // 1. The URL navigator gets changed and will trigger the view to update its URL
+    // 2. The URL of the view gets changed and will trigger the URL navigator to update
+    //    its URL (e.g. by clicking on an item)
+    // In this scope the view-state may only get saved in case 1:
+    if (url != m_view->url()) {
+        saveViewState();
+    }
 }
 
 void DolphinViewContainer::slotUrlNavigatorLocationChanged(const KUrl& url)
 {
     if (KProtocolManager::supportsListing(url)) {
         setSearchModeEnabled(isSearchUrl(url));
-
         m_view->setUrl(url);
+
         if (isActive() && !isSearchUrl(url)) {
             // When an URL has been entered, the view should get the focus.
             // The focus must be requested asynchronously, as changing the URL might create
@@ -476,7 +531,9 @@ void DolphinViewContainer::slotUrlNavigatorLocationChanged(const KUrl& url)
 
 void DolphinViewContainer::dropUrls(const KUrl& destination, QDropEvent* event)
 {
-    DragAndDropHelper::instance().dropUrls(KFileItem(), destination, event, this);
+    Q_UNUSED(destination);
+    Q_UNUSED(event);
+    //DragAndDropHelper::instance().dropUrls(KFileItem(), destination, event, this);
 }
 
 void DolphinViewContainer::redirect(const KUrl& oldUrl, const KUrl& newUrl)
@@ -510,7 +567,6 @@ void DolphinViewContainer::saveUrlCompletionMode(KGlobalSettings::Completion com
 void DolphinViewContainer::slotHistoryChanged()
 {
     QByteArray locationState = m_urlNavigator->locationState();
-
     if (!locationState.isEmpty()) {
         QDataStream stream(&locationState, QIODevice::ReadOnly);
         m_view->restoreState(stream);
@@ -543,48 +599,12 @@ bool DolphinViewContainer::isSearchUrl(const KUrl& url) const
     return protocol.contains("search") || (protocol == QLatin1String("nepomuk"));
 }
 
-void DolphinViewContainer::slotItemTriggered(const KFileItem& item)
-{
-    KUrl url = item.targetUrl();
-
-    if (item.isDir()) {
-        m_view->setUrl(url);
-        return;
-    }
-
-    const GeneralSettings* settings = DolphinSettings::instance().generalSettings();
-    const bool browseThroughArchives = settings->browseThroughArchives();
-    if (browseThroughArchives && item.isFile() && url.isLocalFile()) {
-        // Generic mechanism for redirecting to tar:/<path>/ when clicking on a tar file,
-        // zip:/<path>/ when clicking on a zip file, etc.
-        // The .protocol file specifies the mimetype that the kioslave handles.
-        // Note that we don't use mimetype inheritance since we don't want to
-        // open OpenDocument files as zip folders...
-        const QString protocol = KProtocolManager::protocolForArchiveMimetype(item.mimetype());
-        if (!protocol.isEmpty()) {
-            url.setProtocol(protocol);
-            m_view->setUrl(url);
-            return;
-        }
-    }
-
-    if (item.mimetype() == "application/x-desktop") {
-        // redirect to the url in Type=Link desktop files
-        KDesktopFile desktopFile(url.toLocalFile());
-        if (desktopFile.hasLinkType()) {
-            url = desktopFile.readUrl();
-            m_view->setUrl(url);
-            return;
-        }
-    }
-
-    item.run();
-}
-
-void DolphinViewContainer::openFile(const KUrl& url)
+void DolphinViewContainer::saveViewState()
 {
-    const KFileItem item(KFileItem::Unknown, KFileItem::Unknown, url);
-    slotItemTriggered(item);
+    QByteArray locationState;
+    QDataStream stream(&locationState, QIODevice::WriteOnly);
+    m_view->saveState(stream);
+    m_urlNavigator->saveLocationState(locationState);
 }
 
 #include "dolphinviewcontainer.moc"
index 37b06b7d6e0efba49db66c2d303dea410ca605fd..7aea304b8d6f38e39b6d9d20e08cc9e839e6ca2a 100644 (file)
@@ -42,7 +42,7 @@ class DolphinStatusBar;
  * @short Represents a view for the directory content
  *        including the navigation bar, filter bar and status bar.
  *
- * View modes for icons, details and columns are supported. Currently
+ * View modes for icons, compact and details are supported. Currently
  * Dolphin allows to have up to two views inside the main window.
  *
  * @see DolphinView
@@ -212,10 +212,16 @@ private slots:
     void activate();
 
     /**
-     * Saves the state of the current view: contents position,
-     * root URL, ...
+     * Is invoked if the signal urlAboutToBeChanged() from the DolphinView
+     * is emitted. Tries to save the view-state.
      */
-    void saveViewState();
+    void slotViewUrlAboutToBeChanged(const KUrl& url);
+
+    /**
+     * Is invoked if the signal urlAboutToBeChanged() from the URL navigator
+     * is emitted. Tries to save the view-state.
+     */
+    void slotUrlNavigatorLocationAboutToBeChanged(const KUrl& url);
 
     /**
      * Restores the current view to show \a url and assures
@@ -266,6 +272,12 @@ private:
      */
     bool isSearchUrl(const KUrl& url) const;
 
+    /**
+     * Saves the state of the current view: contents position,
+     * root URL, ...
+     */
+    void saveViewState();
+
 private:
     QVBoxLayout* m_topLayout;
     KUrlNavigator* m_urlNavigator;
diff --git a/src/kitemviews/kfileitemlistview.cpp b/src/kitemviews/kfileitemlistview.cpp
new file mode 100644 (file)
index 0000000..a7217d3
--- /dev/null
@@ -0,0 +1,423 @@
+/***************************************************************************
+ *   Copyright (C) 2011 by Peter Penz <peter.penz19@gmail.com>             *
+ *                                                                         *
+ *   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 program 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 program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA            *
+ ***************************************************************************/
+
+#include "kfileitemlistview.h"
+
+#include "kitemlistgroupheader.h"
+#include "kfileitemmodelrolesupdater.h"
+#include "kfileitemlistwidget.h"
+#include "kfileitemmodel.h"
+#include <KLocale>
+#include <KStringHandler>
+
+#include <KDebug>
+
+#include <QTextLine>
+#include <QTimer>
+
+#define KFILEITEMLISTVIEW_DEBUG
+
+namespace {
+    const int ShortInterval = 50;
+    const int LongInterval = 300;
+}
+
+KFileItemListView::KFileItemListView(QGraphicsWidget* parent) :
+    KItemListView(parent),
+    m_itemLayout(IconsLayout),
+    m_modelRolesUpdater(0),
+    m_updateVisibleIndexRangeTimer(0),
+    m_updateIconSizeTimer(0),
+    m_minimumRolesWidths()
+{
+    setScrollOrientation(Qt::Vertical);
+    setWidgetCreator(new KItemListWidgetCreator<KFileItemListWidget>());
+    setGroupHeaderCreator(new KItemListGroupHeaderCreator<KItemListGroupHeader>());
+
+    m_updateVisibleIndexRangeTimer = new QTimer(this);
+    m_updateVisibleIndexRangeTimer->setSingleShot(true);
+    m_updateVisibleIndexRangeTimer->setInterval(ShortInterval);
+    connect(m_updateVisibleIndexRangeTimer, SIGNAL(timeout()), this, SLOT(updateVisibleIndexRange()));
+
+    m_updateIconSizeTimer = new QTimer(this);
+    m_updateIconSizeTimer->setSingleShot(true);
+    m_updateIconSizeTimer->setInterval(ShortInterval);
+    connect(m_updateIconSizeTimer, SIGNAL(timeout()), this, SLOT(updateIconSize()));
+
+    updateMinimumRolesWidths();
+}
+
+KFileItemListView::~KFileItemListView()
+{
+    delete widgetCreator();
+    delete groupHeaderCreator();
+
+    delete m_modelRolesUpdater;
+    m_modelRolesUpdater = 0;
+}
+
+void KFileItemListView::setPreviewsShown(bool show)
+{
+    if (m_modelRolesUpdater) {
+        m_modelRolesUpdater->setPreviewShown(show);
+    }
+}
+
+bool KFileItemListView::previewsShown() const
+{
+    return m_modelRolesUpdater->isPreviewShown();
+}
+
+void KFileItemListView::setItemLayout(Layout layout)
+{
+    if (m_itemLayout != layout) {
+        m_itemLayout = layout;
+        updateLayoutOfVisibleItems();
+    }
+}
+
+KFileItemListView::Layout KFileItemListView::itemLayout() const
+{
+    return m_itemLayout;
+}
+
+QSizeF KFileItemListView::itemSizeHint(int index) const
+{
+    const QHash<QByteArray, QVariant> values = model()->data(index);
+    const KItemListStyleOption& option = styleOption();
+    const int additionalRolesCount = qMax(visibleRoles().count() - 1, 0);
+
+    switch (m_itemLayout) {
+    case IconsLayout: {
+        const QString text = KStringHandler::preProcessWrap(values["name"].toString());
+
+        const qreal maxWidth = itemSize().width() - 2 * option.margin;
+        int textLinesCount = 0;
+        QTextLine line;
+
+        // Calculate the number of lines required for wrapping the name
+        QTextOption textOption(Qt::AlignHCenter);
+        textOption.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
+
+        QTextLayout layout(text, option.font);
+        layout.setTextOption(textOption);
+        layout.beginLayout();
+        while ((line = layout.createLine()).isValid()) {
+            line.setLineWidth(maxWidth);
+            line.naturalTextWidth();
+            ++textLinesCount;
+        }
+        layout.endLayout();
+
+        // Add one line for each additional information
+        textLinesCount += additionalRolesCount;
+
+        const qreal height = textLinesCount * option.fontMetrics.height() +
+                             option.iconSize +
+                             option.margin * 4;
+        return QSizeF(itemSize().width(), height);
+    }
+
+    case CompactLayout: {
+        // For each row exactly one role is shown. Calculate the maximum required width that is necessary
+        // to show all roles without horizontal clipping.
+        qreal maximumRequiredWidth = 0.0;
+        QHashIterator<QByteArray, int> it(visibleRoles());
+        while (it.hasNext()) {
+            it.next();
+            const QByteArray& role = it.key();
+            const QString text = values[role].toString();
+            const qreal requiredWidth = option.fontMetrics.width(text);
+            maximumRequiredWidth = qMax(maximumRequiredWidth, requiredWidth);
+        }
+
+        const qreal width = option.margin * 4 + option.iconSize + maximumRequiredWidth;
+        const qreal height = option.margin * 2 + qMax(option.iconSize, (1 + additionalRolesCount) * option.fontMetrics.height());
+        return QSizeF(width, height);
+    }
+
+    case DetailsLayout: {
+        // The width will be determined dynamically by KFileItemListView::visibleRoleSizes()
+        const qreal height = option.margin * 2 + qMax(option.iconSize, option.fontMetrics.height());
+        return QSizeF(-1, height);
+    }
+
+    default:
+        Q_ASSERT(false);
+        break;
+    }
+
+    return QSize();
+}
+
+QHash<QByteArray, QSizeF> KFileItemListView::visibleRoleSizes() const
+{
+    QElapsedTimer timer;
+    timer.start();
+
+    QHash<QByteArray, QSizeF> sizes;
+
+    const int itemCount = model()->count();
+    for (int i = 0; i < itemCount; ++i) {
+        QHashIterator<QByteArray, int> it(visibleRoles());
+        while (it.hasNext()) {
+            it.next();
+            const QByteArray& visibleRole = it.key();
+
+            QSizeF maxSize = sizes.value(visibleRole, QSizeF(0, 0));
+
+            const QSizeF itemSize = visibleRoleSizeHint(i, visibleRole);
+            maxSize = maxSize.expandedTo(itemSize);
+            sizes.insert(visibleRole, maxSize);
+        }
+
+        if (i > 100 && timer.elapsed() > 200) {
+            // When having several thousands of items calculating the sizes can get
+            // very expensive. We accept a possibly too small role-size in favour
+            // of having no blocking user interface.
+            #ifdef KFILEITEMLISTVIEW_DEBUG
+                kDebug() << "Timer exceeded, stopped after" << i << "items";
+            #endif
+            break;
+        }
+    }
+
+#ifdef KFILEITEMLISTVIEW_DEBUG
+    kDebug() << "[TIME] Calculated dynamic item size for " << itemCount << "items:" << timer.elapsed();
+#endif
+    return sizes;
+}
+
+void KFileItemListView::initializeItemListWidget(KItemListWidget* item)
+{
+    KFileItemListWidget* fileItemListWidget = static_cast<KFileItemListWidget*>(item);
+
+    switch (m_itemLayout) {
+    case IconsLayout:   fileItemListWidget->setLayout(KFileItemListWidget::IconsLayout); break;
+    case CompactLayout: fileItemListWidget->setLayout(KFileItemListWidget::CompactLayout); break;
+    case DetailsLayout: fileItemListWidget->setLayout(KFileItemListWidget::DetailsLayout); break;
+    default:            Q_ASSERT(false); break;
+    }
+}
+
+void KFileItemListView::onModelChanged(KItemModelBase* current, KItemModelBase* previous)
+{
+    Q_UNUSED(previous);
+    Q_ASSERT(qobject_cast<KFileItemModel*>(current));
+
+    if (m_modelRolesUpdater) {
+        delete m_modelRolesUpdater;
+    }
+
+    m_modelRolesUpdater = new KFileItemModelRolesUpdater(static_cast<KFileItemModel*>(current), this);
+    const int size = styleOption().iconSize;
+    m_modelRolesUpdater->setIconSize(QSize(size, size));
+}
+
+void KFileItemListView::onScrollOrientationChanged(Qt::Orientation current, Qt::Orientation previous)
+{
+    Q_UNUSED(current);
+    Q_UNUSED(previous);
+    updateLayoutOfVisibleItems();
+}
+
+void KFileItemListView::onItemSizeChanged(const QSizeF& current, const QSizeF& previous)
+{
+    Q_UNUSED(current);
+    Q_UNUSED(previous);
+    triggerVisibleIndexRangeUpdate();
+}
+
+void KFileItemListView::onOffsetChanged(qreal current, qreal previous)
+{
+    Q_UNUSED(current);
+    Q_UNUSED(previous);
+    triggerVisibleIndexRangeUpdate();
+}
+
+void KFileItemListView::onVisibleRolesChanged(const QHash<QByteArray, int>& current, const QHash<QByteArray, int>& previous)
+{
+    Q_UNUSED(previous);
+
+    Q_ASSERT(qobject_cast<KFileItemModel*>(model()));
+    KFileItemModel* fileItemModel = static_cast<KFileItemModel*>(model());
+
+    // KFileItemModel does not distinct between "visible" and "invisible" roles.
+    // Add all roles that are mandatory for having a working KFileItemListView:
+    QSet<QByteArray> keys = current.keys().toSet();
+    QSet<QByteArray> roles = keys;
+    roles.insert("iconPixmap");
+    roles.insert("iconName");
+    roles.insert("name"); // TODO: just don't allow to disable it
+    roles.insert("isDir");
+    if (m_itemLayout == DetailsLayout) {
+        roles.insert("isExpanded");
+        roles.insert("expansionLevel");
+    }
+
+    fileItemModel->setRoles(roles);
+
+    m_modelRolesUpdater->setRoles(keys);
+}
+
+void KFileItemListView::onStyleOptionChanged(const KItemListStyleOption& current, const KItemListStyleOption& previous)
+{
+    Q_UNUSED(current);
+    Q_UNUSED(previous);
+    triggerIconSizeUpdate();
+}
+
+void KFileItemListView::onTransactionBegin()
+{
+    m_modelRolesUpdater->setPaused(true);
+}
+
+void KFileItemListView::onTransactionEnd()
+{
+    // Only unpause the model-roles-updater if no timer is active. If one
+    // timer is still active the model-roles-updater will be unpaused later as
+    // soon as the timer has been exceeded.
+    const bool timerActive = m_updateVisibleIndexRangeTimer->isActive() ||
+                             m_updateIconSizeTimer->isActive();
+    if (!timerActive) {
+        m_modelRolesUpdater->setPaused(false);
+    }
+}
+
+void KFileItemListView::resizeEvent(QGraphicsSceneResizeEvent* event)
+{
+    KItemListView::resizeEvent(event);
+    triggerVisibleIndexRangeUpdate();
+}
+
+void KFileItemListView::slotItemsRemoved(const KItemRangeList& itemRanges)
+{
+    KItemListView::slotItemsRemoved(itemRanges);
+    updateTimersInterval();
+}
+
+void KFileItemListView::triggerVisibleIndexRangeUpdate()
+{
+    m_modelRolesUpdater->setPaused(true);
+    m_updateVisibleIndexRangeTimer->start();
+}
+
+void KFileItemListView::updateVisibleIndexRange()
+{
+    if (!m_modelRolesUpdater) {
+        return;
+    }
+
+    const int index = firstVisibleIndex();
+    const int count = lastVisibleIndex() - index + 1;
+    m_modelRolesUpdater->setVisibleIndexRange(index, count);
+
+    if (m_updateIconSizeTimer->isActive()) {
+        // If the icon-size update is pending do an immediate update
+        // of the icon-size before unpausing m_modelRolesUpdater. This prevents
+        // an unnecessary expensive recreation of all previews afterwards.
+        m_updateIconSizeTimer->stop();
+        const KItemListStyleOption& option = styleOption();
+        m_modelRolesUpdater->setIconSize(QSize(option.iconSize, option.iconSize));
+    }
+
+    m_modelRolesUpdater->setPaused(isTransactionActive());
+    updateTimersInterval();
+}
+
+void KFileItemListView::triggerIconSizeUpdate()
+{
+    m_modelRolesUpdater->setPaused(true);
+    m_updateIconSizeTimer->start();
+}
+
+void KFileItemListView::updateIconSize()
+{
+    if (!m_modelRolesUpdater) {
+        return;
+    }
+
+    const KItemListStyleOption& option = styleOption();
+    m_modelRolesUpdater->setIconSize(QSize(option.iconSize, option.iconSize));
+
+    if (m_updateVisibleIndexRangeTimer->isActive()) {
+        // If the visibility-index-range update is pending do an immediate update
+        // of the range before unpausing m_modelRolesUpdater. This prevents
+        // an unnecessary expensive recreation of all previews afterwards.
+        m_updateVisibleIndexRangeTimer->stop();
+        const int index = firstVisibleIndex();
+        const int count = lastVisibleIndex() - index + 1;
+        m_modelRolesUpdater->setVisibleIndexRange(index, count);
+    }
+
+    m_modelRolesUpdater->setPaused(isTransactionActive());
+    updateTimersInterval();
+}
+
+QSizeF KFileItemListView::visibleRoleSizeHint(int index, const QByteArray& role) const
+{
+    const KItemListStyleOption& option = styleOption();
+
+    qreal width = m_minimumRolesWidths.value(role, 0);
+    const qreal height = option.margin * 2 + option.fontMetrics.height();
+
+    const QVariant value = model()->data(index).value(role);
+    const QString text = value.toString();
+    if (!text.isEmpty()) {
+        width = qMax(width, qreal(option.margin * 2 + option.fontMetrics.width(text)));
+    }
+
+    return QSizeF(width, height);
+}
+
+void KFileItemListView::updateLayoutOfVisibleItems()
+{
+    foreach (KItemListWidget* widget, visibleItemListWidgets()) {
+        initializeItemListWidget(widget);
+    }
+    triggerVisibleIndexRangeUpdate();
+}
+
+void KFileItemListView::updateTimersInterval()
+{
+    if (!model()) {
+        return;
+    }
+
+    // The ShortInterval is used for cases like switching the directory: If the
+    // model is empty and filled later the creation of the previews should be done
+    // as soon as possible. The LongInterval is used when the model already contains
+    // items and assures that operations like zooming don't result in too many temporary
+    // recreations of the previews.
+
+    const int interval = (model()->count() <= 0) ? ShortInterval : LongInterval;
+    m_updateVisibleIndexRangeTimer->setInterval(interval);
+    m_updateIconSizeTimer->setInterval(interval);
+}
+
+void KFileItemListView::updateMinimumRolesWidths()
+{
+    m_minimumRolesWidths.clear();
+
+    const KItemListStyleOption& option = styleOption();
+    const QString sizeText = QLatin1String("888888") + i18nc("@item:intable", "items");
+    m_minimumRolesWidths.insert("size", option.fontMetrics.width(sizeText));
+}
+
+#include "kfileitemlistview.moc"
diff --git a/src/kitemviews/kfileitemlistview.h b/src/kitemviews/kfileitemlistview.h
new file mode 100644 (file)
index 0000000..acd03ed
--- /dev/null
@@ -0,0 +1,97 @@
+/***************************************************************************
+ *   Copyright (C) 2011 by Peter Penz <peter.penz19@gmail.com>             *
+ *                                                                         *
+ *   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 program 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 program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA            *
+ ***************************************************************************/
+
+#ifndef KFILEITEMLISTVIEW_H
+#define KFILEITEMLISTVIEW_H
+
+#include <libdolphin_export.h>
+
+#include <kitemviews/kitemlistview.h>
+
+class KFileItemModelRolesUpdater;
+class QTimer;
+
+class LIBDOLPHINPRIVATE_EXPORT KFileItemListView : public KItemListView
+{
+    Q_OBJECT
+
+public:
+    enum Layout
+    {
+        IconsLayout,
+        CompactLayout,
+        DetailsLayout
+    };
+
+    KFileItemListView(QGraphicsWidget* parent = 0);
+    virtual ~KFileItemListView();
+
+    void setPreviewsShown(bool show);
+    bool previewsShown() const;
+
+    void setItemLayout(Layout layout);
+    Layout itemLayout() const;
+
+    virtual QSizeF itemSizeHint(int index) const;
+    virtual QHash<QByteArray, QSizeF> visibleRoleSizes() const;
+
+protected:
+    virtual void initializeItemListWidget(KItemListWidget* item);
+    virtual void onModelChanged(KItemModelBase* current, KItemModelBase* previous);
+    virtual void onScrollOrientationChanged(Qt::Orientation current, Qt::Orientation previous);
+    virtual void onItemSizeChanged(const QSizeF& current, const QSizeF& previous);
+    virtual void onOffsetChanged(qreal current, qreal previous);
+    virtual void onVisibleRolesChanged(const QHash<QByteArray, int>& current, const QHash<QByteArray, int>& previous);
+    virtual void onStyleOptionChanged(const KItemListStyleOption& current, const KItemListStyleOption& previous);
+    virtual void onTransactionBegin();
+    virtual void onTransactionEnd();
+    virtual void resizeEvent(QGraphicsSceneResizeEvent* event);
+
+protected slots:
+    virtual void slotItemsRemoved(const KItemRangeList& itemRanges);
+
+private slots:
+    void triggerVisibleIndexRangeUpdate();
+    void updateVisibleIndexRange();
+
+    void triggerIconSizeUpdate();
+    void updateIconSize();
+
+private:
+    QSizeF visibleRoleSizeHint(int index, const QByteArray& role) const;
+    void updateLayoutOfVisibleItems();
+    void updateTimersInterval();
+    void updateMinimumRolesWidths();
+
+private:
+    Layout m_itemLayout;
+
+    KFileItemModelRolesUpdater* m_modelRolesUpdater;
+    QTimer* m_updateVisibleIndexRangeTimer;
+    QTimer* m_updateIconSizeTimer;
+
+    // Cache for calculating visibleRoleSizes() in a fast way
+    QHash<QByteArray, int> m_minimumRolesWidths;
+
+    friend class KFileItemListViewTest; // For unit testing
+};
+
+#endif
+
+
diff --git a/src/kitemviews/kfileitemlistwidget.cpp b/src/kitemviews/kfileitemlistwidget.cpp
new file mode 100644 (file)
index 0000000..4abc4d1
--- /dev/null
@@ -0,0 +1,728 @@
+/***************************************************************************
+ *   Copyright (C) 2011 by Peter Penz <peter.penz19@gmail.com>             *
+ *                                                                         *
+ *   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 program 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 program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA            *
+ ***************************************************************************/
+
+#include "kfileitemlistwidget.h"
+
+#include "kfileitemmodel.h"
+#include "kitemlistview.h"
+#include "kpixmapmodifier_p.h"
+
+#include <KIcon>
+#include <KIconEffect>
+#include <KIconLoader>
+#include <KLocale>
+#include <KStringHandler>
+#include <KDebug>
+
+#include <QFontMetricsF>
+#include <QGraphicsSceneResizeEvent>
+#include <QPainter>
+#include <QTextLayout>
+#include <QTextLine>
+
+//#define KFILEITEMLISTWIDGET_DEBUG
+
+KFileItemListWidget::KFileItemListWidget(QGraphicsItem* parent) :
+    KItemListWidget(parent),
+    m_isDir(false),
+    m_dirtyLayout(true),
+    m_dirtyContent(true),
+    m_dirtyContentRoles(),
+    m_layout(IconsLayout),
+    m_pixmapPos(),
+    m_pixmap(),
+    m_scaledPixmapSize(),
+    m_hoverPixmapRect(),
+    m_hoverPixmap(),
+    m_textPos(),
+    m_text(),
+    m_textsBoundingRect(),
+    m_sortedVisibleRoles(),
+    m_expansionArea(),
+    m_additionalInfoTextColor()
+{
+    for (int i = 0; i < TextIdCount; ++i) {
+        m_text[i].setTextFormat(Qt::PlainText);
+        m_text[i].setPerformanceHint(QStaticText::AggressiveCaching);
+    }
+}
+
+KFileItemListWidget::~KFileItemListWidget()
+{
+}
+
+void KFileItemListWidget::setLayout(Layout layout)
+{
+    if (m_layout != layout) {
+        m_layout = layout;
+        m_dirtyLayout = true;
+        update();
+    }
+}
+
+KFileItemListWidget::Layout KFileItemListWidget::layout() const
+{
+    return m_layout;
+}
+
+void KFileItemListWidget::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget)
+{
+    KItemListWidget::paint(painter, option, widget);
+
+    painter->setRenderHint(QPainter::Antialiasing);
+
+    if (m_dirtyContent || m_dirtyLayout) {
+        const_cast<KFileItemListWidget*>(this)->updateCache();
+    }
+
+    if (m_isDir && !m_expansionArea.isEmpty()) {
+        QStyleOption arrowOption;
+        arrowOption.rect = m_expansionArea.toRect();
+        const QStyle::PrimitiveElement arrow = data()["isExpanded"].toBool()
+                                               ? QStyle::PE_IndicatorArrowDown : QStyle::PE_IndicatorArrowRight;
+        style()->drawPrimitive(arrow, &arrowOption, painter);
+    }
+
+    const bool isHovered = (hoverOpacity() > 0.0);
+
+    const KItemListStyleOption& itemListStyleOption = styleOption();
+    if (isHovered) {
+        // Blend the unhovered and hovered pixmap if the hovering
+        // animation is ongoing
+        if (hoverOpacity() < 1.0) {
+            drawPixmap(painter, m_pixmap);
+        }
+
+        const qreal opacity = painter->opacity();
+        painter->setOpacity(hoverOpacity() * opacity);
+        drawPixmap(painter, m_hoverPixmap);
+
+        // Draw the hover background for the text
+        QRectF textsBoundingRect = m_textsBoundingRect;
+        const qreal marginDiff = itemListStyleOption.margin / 2;
+        textsBoundingRect.adjust(marginDiff, marginDiff, -marginDiff, -marginDiff);
+        painter->setOpacity(hoverOpacity() * opacity * 0.1);
+        painter->setPen(Qt::NoPen);
+        painter->setBrush(itemListStyleOption.palette.text());
+        painter->drawRoundedRect(textsBoundingRect, 4, 4);
+
+        painter->setOpacity(opacity);
+    } else {
+        drawPixmap(painter, m_pixmap);
+    }
+
+    painter->setFont(itemListStyleOption.font);
+    painter->setPen(itemListStyleOption.palette.text().color());
+    painter->drawStaticText(m_textPos[Name], m_text[Name]);
+
+    painter->setPen(m_additionalInfoTextColor);
+    for (int i = Name + 1; i < TextIdCount; ++i) {
+        painter->drawStaticText(m_textPos[i], m_text[i]);
+    }
+
+#ifdef KFILEITEMLISTWIDGET_DEBUG
+    painter->setPen(Qt::red);
+    painter->setBrush(Qt::NoBrush);
+    painter->drawText(QPointF(0, itemListStyleOption.fontMetrics.height()), QString::number(index()));
+    painter->drawRect(rect());
+#endif
+}
+
+bool KFileItemListWidget::contains(const QPointF& point) const
+{
+    return KItemListWidget::contains(point) || m_textsBoundingRect.contains(point);
+}
+
+QRectF KFileItemListWidget::hoverBoundingRect() const
+{
+    QRectF bounds = m_hoverPixmapRect;
+    const qreal margin = styleOption().margin;
+    bounds.adjust(-margin, -margin, margin, margin);
+    return bounds;
+}
+
+QRectF KFileItemListWidget::expansionToggleRect() const
+{
+    return m_isDir ? m_expansionArea : QRectF();
+}
+
+void KFileItemListWidget::dataChanged(const QHash<QByteArray, QVariant>& current,
+                                      const QSet<QByteArray>& roles)
+{
+    KItemListWidget::dataChanged(current, roles);
+    m_dirtyContent = true;
+
+    QSet<QByteArray> dirtyRoles;
+    if (roles.isEmpty()) {
+        dirtyRoles = visibleRoles().keys().toSet();
+        dirtyRoles.insert("iconPixmap");
+        dirtyRoles.insert("iconName");
+    } else {
+        dirtyRoles = roles;
+    }
+
+    QSetIterator<QByteArray> it(dirtyRoles);
+    while (it.hasNext()) {
+        const QByteArray& role = it.next();
+        m_dirtyContentRoles.insert(role);
+    }
+}
+
+void KFileItemListWidget::visibleRolesChanged(const QHash<QByteArray, int>& current,
+                                              const QHash<QByteArray, int>& previous)
+{
+    KItemListWidget::visibleRolesChanged(current, previous);
+    m_dirtyLayout = true;
+
+    // Cache the roles sorted into m_sortedVisibleRoles:
+    const int visibleRolesCount = current.count();
+    m_sortedVisibleRoles.clear();
+    m_sortedVisibleRoles.reserve(visibleRolesCount);
+    for (int i = 0; i < visibleRolesCount; ++i) {
+        m_sortedVisibleRoles.append(QByteArray());
+    }
+
+    QHashIterator<QByteArray, int> it(current);
+    while (it.hasNext()) {
+        it.next();
+
+        const int index = it.value();
+        if (index < 0 || index >= visibleRolesCount || !m_sortedVisibleRoles.at(index).isEmpty()) {
+            kWarning() << "The visible roles have an invalid sort order.";
+            break;
+        }
+
+        const QByteArray& role = it.key();
+        m_sortedVisibleRoles[index] = role;
+    }
+}
+
+void KFileItemListWidget::visibleRolesSizesChanged(const QHash<QByteArray, QSizeF>& current,
+                                                   const QHash<QByteArray, QSizeF>& previous)
+{
+    KItemListWidget::visibleRolesSizesChanged(current, previous);
+    m_dirtyLayout = true;
+}
+
+void KFileItemListWidget::styleOptionChanged(const KItemListStyleOption& current,
+                                             const KItemListStyleOption& previous)
+{
+    KItemListWidget::styleOptionChanged(current, previous);
+
+    // For the color of the additional info the inactive text color
+    // is not used as this might lead to unreadable text for some color schemes. Instead
+    // the text color is slightly mixed with the background color.
+    const QColor c1 = current.palette.text().color();
+    const QColor c2 = current.palette.background().color();
+    const int p1 = 70;
+    const int p2 = 100 - p1;
+    m_additionalInfoTextColor = QColor((c1.red()   * p1 + c2.red()   * p2) / 100,
+                                       (c1.green() * p1 + c2.green() * p2) / 100,
+                                       (c1.blue()  * p1 + c2.blue()  * p2) / 100);
+
+    m_dirtyLayout = true;
+}
+
+void KFileItemListWidget::resizeEvent(QGraphicsSceneResizeEvent* event)
+{
+    KItemListWidget::resizeEvent(event);
+    m_dirtyLayout = true;
+}
+
+void KFileItemListWidget::updateCache()
+{
+    if (index() < 0) {
+        return;
+    }
+
+    m_isDir = data()["isDir"].toBool();
+
+    updateExpansionArea();
+    updateTextsCache();
+    updatePixmapCache();
+
+    m_dirtyLayout = false;
+    m_dirtyContent = false;
+    m_dirtyContentRoles.clear();
+}
+
+void KFileItemListWidget::updateExpansionArea()
+{
+    if (m_layout == DetailsLayout) {
+        const QHash<QByteArray, QVariant> values = data();
+        Q_ASSERT(values.contains("expansionLevel"));
+        const KItemListStyleOption& option = styleOption();
+        const int expansionLevel = values.value("expansionLevel", 0).toInt();
+
+        const qreal widgetHeight = size().height();
+        const qreal expansionLevelSize = KIconLoader::SizeSmall;
+        const qreal x = option.margin + expansionLevel * widgetHeight;
+        const qreal y = (widgetHeight - expansionLevelSize) / 2;
+        m_expansionArea = QRectF(x, y, expansionLevelSize, expansionLevelSize);
+    } else {
+        m_expansionArea = QRectF();
+    }
+}
+
+void KFileItemListWidget::updatePixmapCache()
+{
+    // Precondition: Requires already updated m_textPos values to calculate
+    // the remaining height when the alignment is vertical.
+
+    const bool iconOnTop = (m_layout == IconsLayout);
+    const KItemListStyleOption& option = styleOption();
+    const int iconHeight = option.iconSize;
+
+    const QHash<QByteArray, QVariant> values = data();
+    const QSizeF widgetSize = size();
+
+    int scaledIconHeight = 0;
+    if (iconOnTop) {
+        scaledIconHeight = static_cast<int>(m_textPos[Name].y() - 3 * option.margin);
+    } else {
+        const int textRowsCount = (m_layout == CompactLayout) ? visibleRoles().count() : 1;
+        const qreal requiredTextHeight = textRowsCount * option.fontMetrics.height();
+        scaledIconHeight = (requiredTextHeight < iconHeight) ? widgetSize.height() - 2 * option.margin : iconHeight;
+    }
+
+    bool updatePixmap = (iconHeight != m_pixmap.height());
+    if (!updatePixmap && m_dirtyContent) {
+        updatePixmap = m_dirtyContentRoles.isEmpty()
+                       || m_dirtyContentRoles.contains("iconPixmap")
+                       || m_dirtyContentRoles.contains("iconName");
+    }
+
+    if (updatePixmap) {
+        m_pixmap = values["iconPixmap"].value<QPixmap>();
+        if (m_pixmap.isNull()) {
+            // Use the icon that fits to the MIME-type
+            QString iconName = values["iconName"].toString();
+            if (iconName.isEmpty()) {
+                // The icon-name has not been not resolved by KFileItemModelRolesUpdater,
+                // use a generic icon as fallback
+                iconName = QLatin1String("unknown");
+            }
+            m_pixmap = pixmapForIcon(iconName, iconHeight);
+            m_hoverPixmapRect.setSize(m_pixmap.size());
+        } else if (m_pixmap.size() != QSize(iconHeight, iconHeight)) {
+            // A custom pixmap has been applied. Assure that the pixmap
+            // is scaled to the available size.
+            const bool scale = m_pixmap.width() > iconHeight || m_pixmap.height() > iconHeight ||
+                               (m_pixmap.width() < iconHeight && m_pixmap.height() < iconHeight);
+            if (scale) {
+                KPixmapModifier::scale(m_pixmap, QSize(iconHeight, iconHeight));
+            }
+            m_hoverPixmapRect.setSize(m_pixmap.size());
+
+            // To simplify the handling of scaling the original pixmap
+            // will be embedded into a square pixmap.
+            QPixmap squarePixmap(iconHeight, iconHeight);
+            squarePixmap.fill(Qt::transparent);
+
+            QPainter painter(&squarePixmap);
+            if (iconOnTop) {
+                const int x = (iconHeight - m_pixmap.width()) / 2;  // Center horizontally
+                const int y = iconHeight - m_pixmap.height();       // Align on bottom
+                painter.drawPixmap(x, y, m_pixmap);
+            } else {
+                const int x = iconHeight - m_pixmap.width();        // Align right
+                const int y = (iconHeight - m_pixmap.height()) / 2; // Center vertically
+                painter.drawPixmap(x, y, m_pixmap);
+            }
+
+            m_pixmap = squarePixmap;
+        } else {
+            m_hoverPixmapRect.setSize(m_pixmap.size());
+        }
+
+        Q_ASSERT(m_pixmap.height() == iconHeight);
+    }
+
+    m_scaledPixmapSize = QSize(scaledIconHeight, scaledIconHeight);
+
+    if (iconOnTop) {
+        m_pixmapPos.setX((widgetSize.width() - m_scaledPixmapSize.width()) / 2);
+    } else {
+        m_pixmapPos.setX(m_textPos[Name].x() - 2 * option.margin - scaledIconHeight);
+    }
+    m_pixmapPos.setY(option.margin);
+
+    // Center the hover rectangle horizontally and align it on bottom
+    const qreal x = m_pixmapPos.x() + (m_scaledPixmapSize.width() - m_hoverPixmapRect.width()) / 2.0;
+    const qreal y = m_pixmapPos.y() + m_scaledPixmapSize.height() - m_hoverPixmapRect.height();
+    m_hoverPixmapRect.moveTopLeft(QPointF(x, y));
+
+    // Prepare the pixmap that is used when the item gets hovered
+    if (option.state & QStyle::State_MouseOver) {
+        m_hoverPixmap = m_pixmap;
+        KIconEffect* effect = KIconLoader::global()->iconEffect();
+        // In the KIconLoader terminology, active = hover.
+        if (effect->hasEffect(KIconLoader::Desktop, KIconLoader::ActiveState)) {
+            m_hoverPixmap =  effect->apply(m_pixmap, KIconLoader::Desktop, KIconLoader::ActiveState);
+        } else {
+            m_hoverPixmap = m_pixmap;
+        }
+    } else if (hoverOpacity() <= 0.0) {
+        // No hover animation is ongoing. Clear m_hoverPixmap to save memory.
+        m_hoverPixmap = QPixmap();
+    }
+}
+
+void KFileItemListWidget::updateTextsCache()
+{
+    QTextOption textOption;
+    switch (m_layout) {
+    case IconsLayout:
+        textOption.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
+        textOption.setAlignment(Qt::AlignHCenter);
+        break;
+    case CompactLayout:
+    case DetailsLayout:
+        textOption.setAlignment(Qt::AlignLeft);
+        textOption.setWrapMode(QTextOption::NoWrap);
+        break;
+    default:
+        Q_ASSERT(false);
+        break;
+    }
+
+    for (int i = 0; i < TextIdCount; ++i) {
+        m_text[i].setText(QString());
+        m_text[i].setTextOption(textOption);
+    }
+
+    switch (m_layout) {
+    case IconsLayout:   updateIconsLayoutTextCache(); break;
+    case CompactLayout: updateCompactLayoutTextCache(); break;
+    case DetailsLayout: updateDetailsLayoutTextCache(); break;
+    default: Q_ASSERT(false); break;
+    }
+}
+
+void KFileItemListWidget::updateIconsLayoutTextCache()
+{
+    //      +------+
+    //      | Icon |
+    //      +------+
+    //
+    //    Name role that
+    // might get wrapped above
+    //    several lines.
+    //  Additional role 1
+    //  Additional role 2
+
+    const QHash<QByteArray, QVariant> values = data();
+
+    const KItemListStyleOption& option = styleOption();
+    const qreal maxWidth = size().width() - 2 * option.margin;
+    const qreal widgetHeight = size().height();
+    const qreal fontHeight = option.fontMetrics.height();
+
+    // Initialize properties for the "name" role. It will be used as anchor
+    // for initializing the position of the other roles.
+    m_text[Name].setText(KStringHandler::preProcessWrap(values["name"].toString()));
+
+    // Calculate the number of lines required for the name and the required width
+    int textLinesCountForName = 0;
+    qreal requiredWidthForName = 0;
+    QTextLine line;
+
+    QTextLayout layout(m_text[Name].text(), option.font);
+    layout.setTextOption(m_text[Name].textOption());
+    layout.beginLayout();
+    while ((line = layout.createLine()).isValid()) {
+        line.setLineWidth(maxWidth);
+        requiredWidthForName = qMax(requiredWidthForName, line.naturalTextWidth());
+        ++textLinesCountForName;
+    }
+    layout.endLayout();
+
+    // Use one line for each additional information
+    int textLinesCount = textLinesCountForName;
+    const int additionalRolesCount = qMax(visibleRoles().count() - 1, 0);
+    textLinesCount += additionalRolesCount;
+
+    m_text[Name].setTextWidth(maxWidth);
+    m_textPos[Name] = QPointF(option.margin, widgetHeight - textLinesCount * fontHeight - option.margin);
+    m_textsBoundingRect = QRectF(option.margin + (maxWidth - requiredWidthForName) / 2,
+                                 m_textPos[Name].y(),
+                                 requiredWidthForName,
+                                 m_text[Name].size().height());
+
+    // Calculate the position for each additional information
+    qreal y = m_textPos[Name].y() + textLinesCountForName * fontHeight;
+    foreach (const QByteArray& role, m_sortedVisibleRoles) {
+        const TextId textId = roleTextId(role);
+        if (textId == Name) {
+            continue;
+        }
+
+        const QString text = roleText(textId, values[role]);
+        m_text[textId].setText(text);
+
+        qreal requiredWidth = 0;
+
+        QTextLayout layout(text, option.font);
+        layout.setTextOption(m_text[textId].textOption());
+        layout.beginLayout();
+        QTextLine textLine = layout.createLine();
+        if (textLine.isValid()) {
+            textLine.setLineWidth(maxWidth);
+            requiredWidth = textLine.naturalTextWidth();
+            if (textLine.textLength() < text.length()) {
+                // TODO: QFontMetrics::elidedText() works different regarding the given width
+                // in comparison to QTextLine::setLineWidth(). It might happen that the text does
+                // not get elided although it does not fit into the given width. As workaround
+                // the margin is substracted.
+                const QString elidedText = option.fontMetrics.elidedText(text, Qt::ElideRight, maxWidth - option.margin);
+                m_text[textId].setText(elidedText);
+            }
+        }
+        layout.endLayout();
+
+        m_textPos[textId] = QPointF(option.margin, y);
+        m_text[textId].setTextWidth(maxWidth);
+
+        const QRectF textBoundingRect(option.margin + (maxWidth - requiredWidth) / 2, y, requiredWidth, fontHeight);
+        m_textsBoundingRect |= textBoundingRect;
+
+        y += fontHeight;
+    }
+
+    // Add a margin to the text bounding rectangle
+    const qreal margin = option.margin;
+    m_textsBoundingRect.adjust(-margin, -margin, margin, margin);
+}
+
+void KFileItemListWidget::updateCompactLayoutTextCache()
+{
+    // +------+  Name role
+    // | Icon |  Additional role 1
+    // +------+  Additional role 2
+
+    const QHash<QByteArray, QVariant> values = data();
+
+    const KItemListStyleOption& option = styleOption();
+    const qreal widgetHeight = size().height();
+    const qreal fontHeight = option.fontMetrics.height();
+    const qreal textLinesHeight = qMax(visibleRoles().count(), 1) * fontHeight;
+    const int scaledIconSize = (textLinesHeight < option.iconSize) ? widgetHeight - 2 * option.margin : option.iconSize;
+
+    qreal maximumRequiredTextWidth = 0;
+    const qreal x = option.margin * 3 + scaledIconSize;
+    qreal y = (widgetHeight - textLinesHeight) / 2;
+    const qreal maxWidth = size().width() - x - option.margin;
+    foreach (const QByteArray& role, m_sortedVisibleRoles) {
+        const TextId textId = roleTextId(role);
+
+        const QString text = roleText(textId, values[role]);
+        m_text[textId].setText(text);
+
+        qreal requiredWidth = option.fontMetrics.width(text);
+        if (requiredWidth > maxWidth) {
+            requiredWidth = maxWidth;
+            const QString elidedText = option.fontMetrics.elidedText(text, Qt::ElideRight, maxWidth);
+            m_text[textId].setText(elidedText);
+        }
+
+        m_textPos[textId] = QPointF(x, y);
+        m_text[textId].setTextWidth(maxWidth);
+
+        maximumRequiredTextWidth = qMax(maximumRequiredTextWidth, requiredWidth);
+
+        y += fontHeight;
+    }
+
+    m_textsBoundingRect = QRectF(x - option.margin, 0, maximumRequiredTextWidth + 2 * option.margin, widgetHeight);
+}
+
+void KFileItemListWidget::updateDetailsLayoutTextCache()
+{
+    // Precondition: Requires already updated m_expansionArea
+    // to determine the left position.
+
+    // +------+
+    // | Icon |  Name role   Additional role 1   Additional role 2
+    // +------+
+    m_textsBoundingRect = QRectF();
+
+    const KItemListStyleOption& option = styleOption();
+    const QHash<QByteArray, QVariant> values = data();
+
+    const qreal widgetHeight = size().height();
+    const int scaledIconSize = widgetHeight - 2 * option.margin;
+    const int fontHeight = option.fontMetrics.height();
+
+    qreal x = m_expansionArea.right() + option.margin * 3 + scaledIconSize;
+    const qreal y = qMax(qreal(option.margin), (widgetHeight - fontHeight) / 2);
+
+    foreach (const QByteArray& role, m_sortedVisibleRoles) {
+        const TextId textId = roleTextId(role);
+
+        const QString text = roleText(textId, values[role]);
+        m_text[textId].setText(text);
+
+        const qreal requiredWidth = option.fontMetrics.width(text);
+        m_textPos[textId] = QPointF(x, y);
+
+        const qreal columnWidth = visibleRolesSizes().value(role, QSizeF(0, 0)).width();
+        x += columnWidth;
+
+        switch (textId) {
+        case Name: {
+            m_textsBoundingRect = QRectF(m_textPos[textId].x() - option.margin, 0,
+                                         requiredWidth + 2 * option.margin, size().height());
+
+            // The column after the name should always be aligned on the same x-position independent
+            // from the expansion-level shown in the name column
+            x -= m_expansionArea.right();
+            break;
+        }
+        case Size:
+            // The values for the size should be right aligned
+            m_textPos[textId].rx() += columnWidth - requiredWidth - 2 * option.margin;
+            break;
+
+        default:
+            break;
+        }
+    }
+}
+
+QString KFileItemListWidget::roleText(TextId textId, const QVariant& roleValue) const
+{
+    QString text;
+
+    switch (textId) {
+    case Name:
+    case Permissions:
+    case Owner:
+    case Group:
+    case Type:
+    case Destination:
+    case Path:
+        text = roleValue.toString();
+        break;
+
+    case Size: {
+        if (data().value("isDir").toBool()) {
+            // The item represents a directory. Show the number of sub directories
+            // instead of the file size of the directory.
+            if (!roleValue.isNull()) {
+                const KIO::filesize_t size = roleValue.value<KIO::filesize_t>();
+                text = i18ncp("@item:intable", "%1 item", "%1 items", size);
+            }
+        } else {
+            const KIO::filesize_t size = roleValue.value<KIO::filesize_t>();
+            text = KIO::convertSize(size);
+        }
+        break;
+    }
+
+    case Date: {
+        const QDateTime dateTime = roleValue.toDateTime();
+        text = KGlobal::locale()->formatDateTime(dateTime);
+        break;
+    }
+
+    default:
+        Q_ASSERT(false);
+        break;
+    }
+
+    return text;
+}
+
+void KFileItemListWidget::drawPixmap(QPainter* painter, const QPixmap& pixmap)
+{
+    const bool isHiddenItem = m_text[Name].text().startsWith(QLatin1Char('.'));
+    qreal opacity;
+    if (isHiddenItem) {
+        opacity = painter->opacity();
+        painter->setOpacity(opacity * 0.3);
+    }
+
+    if (m_scaledPixmapSize != pixmap.size()) {
+        QPixmap scaledPixmap = pixmap;
+        KPixmapModifier::scale(scaledPixmap, m_scaledPixmapSize);
+        painter->drawPixmap(m_pixmapPos, scaledPixmap);
+
+#ifdef KFILEITEMLISTWIDGET_DEBUG
+        painter->setPen(Qt::green);
+        painter->drawRect(QRectF(m_pixmapPos, QSizeF(scaledPixmap.size())));
+#endif
+    } else {
+        painter->drawPixmap(m_pixmapPos, pixmap);
+    }
+
+    if (isHiddenItem) {
+        painter->setOpacity(opacity);
+    }
+}
+
+QPixmap KFileItemListWidget::pixmapForIcon(const QString& name, int size)
+{
+    const KIcon icon(name);
+
+    int requestedSize;
+    if (size <= KIconLoader::SizeSmall) {
+        requestedSize = KIconLoader::SizeSmall;
+    } else if (size <= KIconLoader::SizeSmallMedium) {
+        requestedSize = KIconLoader::SizeSmallMedium;
+    } else if (size <= KIconLoader::SizeMedium) {
+        requestedSize = KIconLoader::SizeMedium;
+    } else if (size <= KIconLoader::SizeLarge) {
+        requestedSize = KIconLoader::SizeLarge;
+    } else if (size <= KIconLoader::SizeHuge) {
+        requestedSize = KIconLoader::SizeHuge;
+    } else if (size <= KIconLoader::SizeEnormous) {
+        requestedSize = KIconLoader::SizeEnormous;
+    } else if (size <= KIconLoader::SizeEnormous * 2) {
+        requestedSize = KIconLoader::SizeEnormous * 2;
+    } else {
+        requestedSize = size;
+    }
+
+    QPixmap pixmap = icon.pixmap(requestedSize, requestedSize);
+    if (requestedSize != size) {
+        KPixmapModifier::scale(pixmap, QSize(size, size));
+    }
+
+    return pixmap;
+}
+
+KFileItemListWidget::TextId KFileItemListWidget::roleTextId(const QByteArray& role)
+{
+    static QHash<QByteArray, TextId> rolesHash;
+    if (rolesHash.isEmpty()) {
+        rolesHash.insert("name", Name);
+        rolesHash.insert("size", Size);
+        rolesHash.insert("date", Date);
+        rolesHash.insert("permissions", Permissions);
+        rolesHash.insert("owner", Owner);
+        rolesHash.insert("group", Group);
+        rolesHash.insert("type", Type);
+        rolesHash.insert("destination", Destination);
+        rolesHash.insert("path", Path);
+    }
+
+    return rolesHash.value(role);
+}
+
+#include "kfileitemlistwidget.moc"
diff --git a/src/kitemviews/kfileitemlistwidget.h b/src/kitemviews/kfileitemlistwidget.h
new file mode 100644 (file)
index 0000000..3ce9531
--- /dev/null
@@ -0,0 +1,118 @@
+/***************************************************************************
+ *   Copyright (C) 2011 by Peter Penz <peter.penz19@gmail.com>             *
+ *                                                                         *
+ *   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 program 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 program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA            *
+ ***************************************************************************/
+
+#ifndef KFILEITEMLISTWIDGET_H
+#define KFILEITEMLISTWIDGET_H
+
+#include <libdolphin_export.h>
+
+#include <kitemviews/kitemlistwidget.h>
+
+#include <QPixmap>
+#include <QPointF>
+#include <QStaticText>
+
+class LIBDOLPHINPRIVATE_EXPORT KFileItemListWidget : public KItemListWidget
+{
+    Q_OBJECT
+
+public:
+    enum Layout
+    {
+        IconsLayout,
+        CompactLayout,
+        DetailsLayout
+    };
+
+    KFileItemListWidget(QGraphicsItem* parent);
+    virtual ~KFileItemListWidget();
+
+    void setLayout(Layout layout);
+    Layout layout() const;
+
+    virtual void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget = 0);
+
+    virtual bool contains(const QPointF& point) const;
+    virtual QRectF hoverBoundingRect() const;
+    virtual QRectF expansionToggleRect() const;
+
+protected:
+    virtual void dataChanged(const QHash<QByteArray, QVariant>& current, const QSet<QByteArray>& roles = QSet<QByteArray>());
+    virtual void visibleRolesChanged(const QHash<QByteArray, int>& current, const QHash<QByteArray, int>& previous);
+    virtual void visibleRolesSizesChanged(const QHash<QByteArray, QSizeF>& current, const QHash<QByteArray, QSizeF>& previous);
+    virtual void styleOptionChanged(const KItemListStyleOption& current, const KItemListStyleOption& previous);
+    virtual void resizeEvent(QGraphicsSceneResizeEvent* event);
+
+private:
+    enum TextId {
+        Name,
+        Size,
+        Date,
+        Permissions,
+        Owner,
+        Group,
+        Type,
+        Destination,
+        Path,
+        TextIdCount // Mandatory last entry
+    };
+
+    void updateCache();
+    void updateExpansionArea();
+    void updatePixmapCache();
+
+    void updateTextsCache();
+    void updateIconsLayoutTextCache();
+    void updateCompactLayoutTextCache();
+    void updateDetailsLayoutTextCache();
+
+    QString roleText(TextId textId, const QVariant& roleValue) const;
+
+    void drawPixmap(QPainter* painter, const QPixmap& pixmap);
+
+    static QPixmap pixmapForIcon(const QString& name, int size);
+    static TextId roleTextId(const QByteArray& role);
+
+private:
+    bool m_isDir;
+    bool m_dirtyLayout;
+    bool m_dirtyContent;
+    QSet<QByteArray> m_dirtyContentRoles;
+
+    Layout m_layout;
+    QPointF m_pixmapPos;
+    QPixmap m_pixmap;
+    QSize m_scaledPixmapSize;
+
+    QRectF m_hoverPixmapRect;
+    QPixmap m_hoverPixmap;
+
+    QPointF m_textPos[TextIdCount];
+    QStaticText m_text[TextIdCount];
+    QRectF m_textsBoundingRect;
+
+    QList<QByteArray> m_sortedVisibleRoles;
+
+    QRectF m_expansionArea;
+    QColor m_additionalInfoTextColor;
+};
+
+#endif
+
+
diff --git a/src/kitemviews/kfileitemmodel.cpp b/src/kitemviews/kfileitemmodel.cpp
new file mode 100644 (file)
index 0000000..b191aba
--- /dev/null
@@ -0,0 +1,868 @@
+/***************************************************************************
+ *   Copyright (C) 2011 by Peter Penz <peter.penz19@gmail.com>             *
+ *                                                                         *
+ *   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 program 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 program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA            *
+ ***************************************************************************/
+
+#include "kfileitemmodel.h"
+
+#include <KDirLister>
+#include <KLocale>
+#include <KStringHandler>
+#include <KDebug>
+
+#include <QTimer>
+
+#define KFILEITEMMODEL_DEBUG
+
+KFileItemModel::KFileItemModel(KDirLister* dirLister, QObject* parent) :
+    KItemModelBase(QByteArray(), "name", parent),
+    m_dirLister(dirLister),
+    m_naturalSorting(true),
+    m_sortFoldersFirst(true),
+    m_groupRole(NoRole),
+    m_sortRole(NameRole),
+    m_caseSensitivity(Qt::CaseInsensitive),
+    m_sortedItems(),
+    m_items(),
+    m_data(),
+    m_requestRole(),
+    m_minimumUpdateIntervalTimer(0),
+    m_maximumUpdateIntervalTimer(0),
+    m_pendingItemsToInsert(),
+    m_pendingItemsToDelete(),
+    m_rootExpansionLevel(-1)
+{
+    resetRoles();
+    m_requestRole[NameRole] = true;
+    m_requestRole[IsDirRole] = true;
+
+    Q_ASSERT(dirLister);
+
+    connect(dirLister, SIGNAL(canceled()), this, SLOT(slotCanceled()));
+    connect(dirLister, SIGNAL(completed()), this, SLOT(slotCompleted()));
+    connect(dirLister, SIGNAL(newItems(KFileItemList)), this, SLOT(slotNewItems(KFileItemList)));
+    connect(dirLister, SIGNAL(itemsDeleted(KFileItemList)), this, SLOT(slotItemsDeleted(KFileItemList)));
+    connect(dirLister, SIGNAL(clear()), this, SLOT(slotClear()));
+    connect(dirLister, SIGNAL(clear(KUrl)), this, SLOT(slotClear(KUrl)));
+
+    // Although the layout engine of KItemListView is fast it is very inefficient to e.g.
+    // emit 50 itemsInserted()-signals each 100 ms. m_minimumUpdateIntervalTimer assures that updates
+    // are done in 1 second intervals for equal operations.
+    m_minimumUpdateIntervalTimer = new QTimer(this);
+    m_minimumUpdateIntervalTimer->setInterval(1000);
+    m_minimumUpdateIntervalTimer->setSingleShot(true);
+    connect(m_minimumUpdateIntervalTimer, SIGNAL(timeout()), this, SLOT(dispatchPendingItems()));
+
+    // For slow KIO-slaves like used for searching it makes sense to show results periodically even
+    // before the completed() or canceled() signal has been emitted.
+    m_maximumUpdateIntervalTimer = new QTimer(this);
+    m_maximumUpdateIntervalTimer->setInterval(2000);
+    m_maximumUpdateIntervalTimer->setSingleShot(true);
+    connect(m_maximumUpdateIntervalTimer, SIGNAL(timeout()), this, SLOT(dispatchPendingItems()));
+
+    Q_ASSERT(m_minimumUpdateIntervalTimer->interval() <= m_maximumUpdateIntervalTimer->interval());
+}
+
+KFileItemModel::~KFileItemModel()
+{
+}
+
+int KFileItemModel::count() const
+{
+    return m_data.count();
+}
+
+QHash<QByteArray, QVariant> KFileItemModel::data(int index) const
+{
+    if (index >= 0 && index < count()) {
+        return m_data.at(index);
+    }
+    return QHash<QByteArray, QVariant>();
+}
+
+bool KFileItemModel::setData(int index, const QHash<QByteArray, QVariant>& values)
+{
+    if (index >= 0 && index < count()) {
+        QHash<QByteArray, QVariant> currentValue = m_data.at(index);
+
+        QSet<QByteArray> changedRoles;
+        QHashIterator<QByteArray, QVariant> it(values);
+        while (it.hasNext()) {
+            it.next();
+            const QByteArray role = it.key();
+            const QVariant value = it.value();
+
+            if (currentValue[role] != value) {
+                currentValue[role] = value;
+                changedRoles.insert(role);
+            }
+        }
+
+        if (!changedRoles.isEmpty()) {
+            m_data[index] = currentValue;
+            emit itemsChanged(KItemRangeList() << KItemRange(index, 1), changedRoles);
+        }
+
+        return true;
+    }
+    return false;
+}
+
+bool KFileItemModel::supportsGrouping() const
+{
+    return true;
+}
+
+bool KFileItemModel::supportsSorting() const
+{
+    return true;
+}
+
+KFileItem KFileItemModel::fileItem(int index) const
+{
+    if (index >= 0 && index < count()) {
+        return m_sortedItems.at(index);
+    }
+
+    return KFileItem();
+}
+
+int KFileItemModel::index(const KFileItem& item) const
+{
+    if (item.isNull()) {
+        return -1;
+    }
+
+    return m_items.value(item, -1);
+}
+
+void KFileItemModel::clear()
+{
+    slotClear();
+}
+
+void KFileItemModel::setRoles(const QSet<QByteArray>& roles)
+{
+    if (count() > 0) {
+        const bool supportedExpanding = m_requestRole[IsExpandedRole] && m_requestRole[ExpansionLevelRole];
+        const bool willSupportExpanding = roles.contains("isExpanded") && roles.contains("expansionLevel");
+        if (supportedExpanding && !willSupportExpanding) {
+            // No expanding is supported anymore. Take care to delete all items that have an expansion level
+            // that is not 0 (and hence are part of an expanded item).
+            removeExpandedItems();
+        }
+    }
+
+    resetRoles();
+    QSetIterator<QByteArray> it(roles);
+    while (it.hasNext()) {
+        const QByteArray& role = it.next();
+        m_requestRole[roleIndex(role)] = true;
+    }
+
+    if (count() > 0) {
+        // Update m_data with the changed requested roles
+        const int maxIndex = count() - 1;
+        for (int i = 0; i <= maxIndex; ++i) {
+            m_data[i] = retrieveData(m_sortedItems.at(i));
+        }
+
+        kWarning() << "TODO: Emitting itemsChanged() with no information what has changed!";
+        emit itemsChanged(KItemRangeList() << KItemRange(0, count()), QSet<QByteArray>());
+    }
+}
+
+QSet<QByteArray> KFileItemModel::roles() const
+{
+    QSet<QByteArray> roles;
+    for (int i = 0; i < RolesCount; ++i) {
+        if (m_requestRole[i]) {
+            switch (i) {
+            case NoRole:             break;
+            case NameRole:           roles.insert("name"); break;
+            case SizeRole:           roles.insert("size"); break;
+            case DateRole:           roles.insert("date"); break;
+            case PermissionsRole:    roles.insert("permissions"); break;
+            case OwnerRole:          roles.insert("owner"); break;
+            case GroupRole:          roles.insert("group"); break;
+            case TypeRole:           roles.insert("type"); break;
+            case DestinationRole:    roles.insert("destination"); break;
+            case PathRole:           roles.insert("path"); break;
+            case IsDirRole:          roles.insert("isDir"); break;
+            case IsExpandedRole:     roles.insert("isExpanded"); break;
+            case ExpansionLevelRole: roles.insert("expansionLevel"); break;
+            default:                 Q_ASSERT(false); break;
+            }
+        }
+    }
+    return roles;
+}
+
+bool KFileItemModel::setExpanded(int index, bool expanded)
+{
+    if (isExpanded(index) == expanded || index < 0 || index >= count()) {
+        return false;
+    }
+
+    QHash<QByteArray, QVariant> values;
+    values.insert("isExpanded", expanded);
+    if (!setData(index, values)) {
+        return false;
+    }
+
+    if (expanded) {
+        const KUrl url = m_sortedItems.at(index).url();
+        KDirLister* dirLister = m_dirLister.data();
+        if (dirLister) {
+            dirLister->openUrl(url, KDirLister::Keep);
+            return true;
+        }
+    } else {
+        KFileItemList itemsToRemove;
+        const int expansionLevel = data(index)["expansionLevel"].toInt();
+        ++index;
+        while (index < count() && data(index)["expansionLevel"].toInt() > expansionLevel) {
+            itemsToRemove.append(m_sortedItems.at(index));
+            ++index;
+        }
+        removeItems(itemsToRemove);
+        return true;
+    }
+
+    return false;
+}
+
+bool KFileItemModel::isExpanded(int index) const
+{
+    if (index >= 0 && index < count()) {
+        return m_data.at(index).value("isExpanded").toBool();
+    }
+    return false;
+}
+
+bool KFileItemModel::isExpandable(int index) const
+{
+    if (index >= 0 && index < count()) {
+        return m_sortedItems.at(index).isDir();
+    }
+    return false;
+}
+
+void KFileItemModel::onGroupRoleChanged(const QByteArray& current, const QByteArray& previous)
+{
+    Q_UNUSED(previous);
+    m_groupRole = roleIndex(current);
+}
+
+void KFileItemModel::onSortRoleChanged(const QByteArray& current, const QByteArray& previous)
+{
+    Q_UNUSED(previous);
+    const int itemCount = count();
+    if (itemCount <= 0) {
+        return;
+    }
+
+    m_sortRole = roleIndex(current);
+
+    KFileItemList sortedItems = m_sortedItems;
+    m_sortedItems.clear();
+    m_items.clear();
+    m_data.clear();
+    emit itemsRemoved(KItemRangeList() << KItemRange(0, itemCount));
+
+    sort(sortedItems.begin(), sortedItems.end());
+    int index = 0;
+    foreach (const KFileItem& item, sortedItems) {
+        m_sortedItems.append(item);
+        m_items.insert(item, index);
+        m_data.append(retrieveData(item));
+
+        ++index;
+    }
+
+    emit itemsInserted(KItemRangeList() << KItemRange(0, itemCount));
+}
+
+void KFileItemModel::slotCompleted()
+{
+    if (m_minimumUpdateIntervalTimer->isActive()) {
+        // dispatchPendingItems() will be called when the timer
+        // has been expired.
+        return;
+    }
+
+    dispatchPendingItems();
+    m_minimumUpdateIntervalTimer->start();
+}
+
+void KFileItemModel::slotCanceled()
+{
+    m_minimumUpdateIntervalTimer->stop();
+    m_maximumUpdateIntervalTimer->stop();
+    dispatchPendingItems();
+}
+
+void KFileItemModel::slotNewItems(const KFileItemList& items)
+{
+    if (!m_pendingItemsToDelete.isEmpty()) {
+        removeItems(m_pendingItemsToDelete);
+        m_pendingItemsToDelete.clear();
+    }
+    m_pendingItemsToInsert.append(items);
+
+    if (useMaximumUpdateInterval() && !m_maximumUpdateIntervalTimer->isActive()) {
+        // Assure that items get dispatched if no completed() or canceled() signal is
+        // emitted during the maximum update interval.
+        m_maximumUpdateIntervalTimer->start();
+    }
+}
+
+void KFileItemModel::slotItemsDeleted(const KFileItemList& items)
+{
+    if (!m_pendingItemsToInsert.isEmpty()) {
+        insertItems(m_pendingItemsToInsert);
+        m_pendingItemsToInsert.clear();
+    }
+    m_pendingItemsToDelete.append(items);
+}
+
+void KFileItemModel::slotClear()
+{
+#ifdef KFILEITEMMODEL_DEBUG
+    kDebug() << "Clearing all items";
+#endif
+
+    m_minimumUpdateIntervalTimer->stop();
+    m_maximumUpdateIntervalTimer->stop();
+    m_pendingItemsToInsert.clear();
+    m_pendingItemsToDelete.clear();
+
+    m_rootExpansionLevel = -1;
+
+    const int removedCount = m_data.count();
+    if (removedCount > 0) {
+        m_sortedItems.clear();
+        m_items.clear();
+        m_data.clear();
+        emit itemsRemoved(KItemRangeList() << KItemRange(0, removedCount));
+    }
+}
+
+void KFileItemModel::slotClear(const KUrl& url)
+{
+    Q_UNUSED(url);
+}
+
+void KFileItemModel::dispatchPendingItems()
+{
+    if (!m_pendingItemsToInsert.isEmpty()) {
+        Q_ASSERT(m_pendingItemsToDelete.isEmpty());
+        insertItems(m_pendingItemsToInsert);
+        m_pendingItemsToInsert.clear();
+    } else if (!m_pendingItemsToDelete.isEmpty()) {
+        Q_ASSERT(m_pendingItemsToInsert.isEmpty());
+        removeItems(m_pendingItemsToDelete);
+        m_pendingItemsToDelete.clear();
+    }
+}
+
+void KFileItemModel::insertItems(const KFileItemList& items)
+{
+    if (items.isEmpty()) {
+        return;
+    }
+
+#ifdef KFILEITEMMODEL_DEBUG
+    QElapsedTimer timer;
+    timer.start();
+    kDebug() << "===========================================================";
+    kDebug() << "Inserting" << items.count() << "items";
+#endif
+
+    KFileItemList sortedItems = items;
+    sort(sortedItems.begin(), sortedItems.end());
+
+#ifdef KFILEITEMMODEL_DEBUG
+    kDebug() << "[TIME] Sorting:" << timer.elapsed();
+#endif
+
+    KItemRangeList itemRanges;
+    int targetIndex = 0;
+    int sourceIndex = 0;
+    int insertedAtIndex = -1;
+    int insertedCount = 0;
+    while (sourceIndex < sortedItems.count()) {
+        // Find target index from m_items to insert the current item
+        // in a sorted order
+        const int previousTargetIndex = targetIndex;
+        while (targetIndex < m_sortedItems.count()) {
+            if (!lessThan(m_sortedItems.at(targetIndex), sortedItems.at(sourceIndex))) {
+                break;
+            }
+            ++targetIndex;
+        }
+
+        if (targetIndex - previousTargetIndex > 0 && insertedAtIndex >= 0) {
+            itemRanges << KItemRange(insertedAtIndex, insertedCount);
+            insertedAtIndex = targetIndex;
+            insertedCount = 0;
+        }
+
+        // Insert item at the position targetIndex
+        const KFileItem item = sortedItems.at(sourceIndex);
+        m_sortedItems.insert(targetIndex, item);
+        m_data.insert(targetIndex, retrieveData(item));
+        // m_items will be inserted after the loop (see comment below)
+        ++insertedCount;
+
+        if (insertedAtIndex < 0) {
+            insertedAtIndex = targetIndex;
+        }
+        ++targetIndex;
+        ++sourceIndex;
+    }
+
+    // The indexes of all m_items must be adjusted, not only the index
+    // of the new items
+    for (int i = 0; i < m_sortedItems.count(); ++i) {
+        m_items.insert(m_sortedItems.at(i), i);
+    }
+
+    itemRanges << KItemRange(insertedAtIndex, insertedCount);
+    emit itemsInserted(itemRanges);
+
+#ifdef KFILEITEMMODEL_DEBUG
+    kDebug() << "[TIME] Inserting of" << items.count() << "items:" << timer.elapsed();
+#endif
+}
+
+void KFileItemModel::removeItems(const KFileItemList& items)
+{
+    if (items.isEmpty()) {
+        return;
+    }
+
+#ifdef KFILEITEMMODEL_DEBUG
+    kDebug() << "Removing " << items.count() << "items";
+#endif
+
+    KFileItemList sortedItems = items;
+    sort(sortedItems.begin(), sortedItems.end());
+
+    QList<int> indexesToRemove;
+    indexesToRemove.reserve(items.count());
+
+    // Calculate the item ranges that will get deleted
+    KItemRangeList itemRanges;
+    int removedAtIndex = -1;
+    int removedCount = 0;
+    int targetIndex = 0;
+    foreach (const KFileItem& itemToRemove, sortedItems) {
+        const int previousTargetIndex = targetIndex;
+        while (targetIndex < m_sortedItems.count()) {
+            if (m_sortedItems.at(targetIndex) == itemToRemove) {
+                break;
+            }
+            ++targetIndex;
+        }
+        if (targetIndex >= m_sortedItems.count()) {
+            kWarning() << "Item that should be deleted has not been found!";
+            return;
+        }
+
+        if (targetIndex - previousTargetIndex > 0 && removedAtIndex >= 0) {
+            itemRanges << KItemRange(removedAtIndex, removedCount);
+            removedAtIndex = targetIndex;
+            removedCount = 0;
+        }
+
+        indexesToRemove.append(targetIndex);
+        if (removedAtIndex < 0) {
+            removedAtIndex = targetIndex;
+        }
+        ++removedCount;
+        ++targetIndex;
+    }
+
+    // Delete the items
+    for (int i = indexesToRemove.count() - 1; i >= 0; --i) {
+        const int indexToRemove = indexesToRemove.at(i);
+        m_items.remove(m_sortedItems.at(indexToRemove));
+        m_sortedItems.removeAt(indexToRemove);
+        m_data.removeAt(indexToRemove);
+    }
+
+    // The indexes of all m_items must be adjusted, not only the index
+    // of the removed items
+    for (int i = 0; i < m_sortedItems.count(); ++i) {
+        m_items.insert(m_sortedItems.at(i), i);
+    }
+
+    if (count() <= 0) {
+        m_rootExpansionLevel = -1;
+    }
+
+    itemRanges << KItemRange(removedAtIndex, removedCount);
+    emit itemsRemoved(itemRanges);
+}
+
+void KFileItemModel::removeExpandedItems()
+{
+
+    KFileItemList expandedItems;
+
+    const int maxIndex = m_data.count() - 1;
+    for (int i = 0; i <= maxIndex; ++i) {
+        if (m_data.at(i).value("expansionLevel").toInt() > 0) {
+            const KFileItem fileItem = m_sortedItems.at(i);
+            expandedItems.append(fileItem);
+        }
+    }
+
+    // The m_rootExpansionLevel may not get reset before all items with
+    // a bigger expansionLevel have been removed.
+    Q_ASSERT(m_rootExpansionLevel >= 0);
+    removeItems(expandedItems);
+
+    m_rootExpansionLevel = -1;
+}
+
+void KFileItemModel::resetRoles()
+{
+    for (int i = 0; i < RolesCount; ++i) {
+        m_requestRole[i] = false;
+    }
+}
+
+KFileItemModel::Role KFileItemModel::roleIndex(const QByteArray& role) const
+{
+    static QHash<QByteArray, Role> rolesHash;
+    if (rolesHash.isEmpty()) {
+        rolesHash.insert("name", NameRole);
+        rolesHash.insert("size", SizeRole);
+        rolesHash.insert("date", DateRole);
+        rolesHash.insert("permissions", PermissionsRole);
+        rolesHash.insert("owner", OwnerRole);
+        rolesHash.insert("group", GroupRole);
+        rolesHash.insert("type", TypeRole);
+        rolesHash.insert("destination", DestinationRole);
+        rolesHash.insert("path", PathRole);
+        rolesHash.insert("isDir", IsDirRole);
+        rolesHash.insert("isExpanded", IsExpandedRole);
+        rolesHash.insert("expansionLevel", ExpansionLevelRole);
+    }
+    return rolesHash.value(role, NoRole);
+}
+
+QHash<QByteArray, QVariant> KFileItemModel::retrieveData(const KFileItem& item) const
+{
+    // It is important to insert only roles that are fast to retrieve. E.g.
+    // KFileItem::iconName() can be very expensive if the MIME-type is unknown
+    // and hence will be retrieved asynchronously by KFileItemModelRolesUpdater.
+    QHash<QByteArray, QVariant> data;
+    data.insert("iconPixmap", QPixmap());
+
+    const bool isDir = item.isDir();
+    if (m_requestRole[IsDirRole]) {
+        data.insert("isDir", isDir);
+    }
+
+    if (m_requestRole[NameRole]) {
+        data.insert("name", item.name());
+    }
+
+    if (m_requestRole[SizeRole]) {
+        if (isDir) {
+            data.insert("size", QVariant());
+        } else {
+            data.insert("size", item.size());
+        }
+    }
+
+    if (m_requestRole[DateRole]) {
+        // Don't use KFileItem::timeString() as this is too expensive when
+        // having several thousands of items. Instead the formatting of the
+        // date-time will be done on-demand by the view when the date will be shown.
+        const KDateTime dateTime = item.time(KFileItem::ModificationTime);
+        data.insert("date", dateTime.dateTime());
+    }
+
+    if (m_requestRole[PermissionsRole]) {
+        data.insert("permissions", item.permissionsString());
+    }
+
+    if (m_requestRole[OwnerRole]) {
+        data.insert("owner", item.user());
+    }
+
+    if (m_requestRole[GroupRole]) {
+        data.insert("group", item.group());
+    }
+
+    if (m_requestRole[DestinationRole]) {
+        QString destination = item.linkDest();
+        if (destination.isEmpty()) {
+            destination = i18nc("@item:intable", "No destination");
+        }
+        data.insert("destination", destination);
+    }
+
+    if (m_requestRole[PathRole]) {
+        data.insert("path", item.localPath());
+    }
+
+    if (m_requestRole[IsExpandedRole]) {
+        data.insert("isExpanded", false);
+    }
+
+    if (m_requestRole[ExpansionLevelRole]) {
+        if (m_rootExpansionLevel < 0) {
+            KDirLister* dirLister = m_dirLister.data();
+            if (dirLister) {
+                const QString rootDir = dirLister->url().directory(KUrl::AppendTrailingSlash);
+                m_rootExpansionLevel = rootDir.count('/');
+            }
+        }
+        const QString dir = item.url().directory(KUrl::AppendTrailingSlash);
+        const int level = dir.count('/') - m_rootExpansionLevel - 1;
+        data.insert("expansionLevel", level);
+    }
+
+    if (item.isMimeTypeKnown()) {
+        data.insert("iconName", item.iconName());
+
+        if (m_requestRole[TypeRole]) {
+            data.insert("type", item.mimeComment());
+        }
+    }
+
+    return data;
+}
+
+bool KFileItemModel::lessThan(const KFileItem& a, const KFileItem& b) const
+{
+    int result = 0;
+
+    if (m_rootExpansionLevel >= 0) {
+        result = expansionLevelsCompare(a, b);
+        if (result != 0) {
+            // The items have parents with different expansion levels
+            return result < 0;
+        }
+    }
+
+    if (m_sortFoldersFirst) {
+        const bool isDirA = a.isDir();
+        const bool isDirB = b.isDir();
+        if (isDirA && !isDirB) {
+            return true;
+        } else if (!isDirA && isDirB) {
+            return false;
+        }
+    }
+
+    switch (m_sortRole) {
+    case NameRole: {
+        result = stringCompare(a.text(), b.text());
+        if (result == 0) {
+            // KFileItem::text() may not be unique in case UDS_DISPLAY_NAME is used
+            result = stringCompare(a.name(m_caseSensitivity == Qt::CaseInsensitive),
+                                   b.name(m_caseSensitivity == Qt::CaseInsensitive));
+        }
+        break;
+    }
+
+    case DateRole: {
+        const KDateTime dateTimeA = a.time(KFileItem::ModificationTime);
+        const KDateTime dateTimeB = b.time(KFileItem::ModificationTime);
+        if (dateTimeA < dateTimeB) {
+            result = -1;
+        } else if (dateTimeA > dateTimeB) {
+            result = +1;
+        }
+        break;
+    }
+
+    default:
+        break;
+    }
+
+    if (result == 0) {
+        // It must be assured that the sort order is always unique even if two values have been
+        // equal. In this case a comparison of the URL is done which is unique in all cases
+        // within KDirLister.
+        result = QString::compare(a.url().url(), b.url().url(), Qt::CaseSensitive);
+    }
+
+    return result < 0;
+}
+
+void KFileItemModel::sort(const KFileItemList::iterator& startIterator, const KFileItemList::iterator& endIterator)
+{
+    KFileItemList::iterator start = startIterator;
+    KFileItemList::iterator end = endIterator;
+
+    // The implementation is based on qSortHelper() from qalgorithms.h
+    // Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+    // In opposite to qSort() it allows to use a member-function for the comparison of elements.
+    while (1) {
+        int span = int(end - start);
+        if (span < 2) {
+            return;
+        }
+
+        --end;
+        KFileItemList::iterator low = start, high = end - 1;
+        KFileItemList::iterator pivot = start + span / 2;
+
+        if (lessThan(*end, *start)) {
+            qSwap(*end, *start);
+        }
+        if (span == 2) {
+            return;
+        }
+
+        if (lessThan(*pivot, *start)) {
+            qSwap(*pivot, *start);
+        }
+        if (lessThan(*end, *pivot)) {
+            qSwap(*end, *pivot);
+        }
+        if (span == 3) {
+            return;
+        }
+
+        qSwap(*pivot, *end);
+
+        while (low < high) {
+            while (low < high && lessThan(*low, *end)) {
+                ++low;
+            }
+
+            while (high > low && lessThan(*end, *high)) {
+                --high;
+            }
+            if (low < high) {
+                qSwap(*low, *high);
+                ++low;
+                --high;
+            } else {
+                break;
+            }
+        }
+
+        if (lessThan(*low, *end)) {
+            ++low;
+        }
+
+        qSwap(*end, *low);
+        sort(start, low);
+
+        start = low + 1;
+        ++end;
+    }
+}
+
+int KFileItemModel::stringCompare(const QString& a, const QString& b) const
+{
+    // Taken from KDirSortFilterProxyModel (kdelibs/kfile/kdirsortfilterproxymodel.*)
+    // Copyright (C) 2006 by Peter Penz <peter.penz@gmx.at>
+    // Copyright (C) 2006 by Dominic Battre <dominic@battre.de>
+    // Copyright (C) 2006 by Martin Pool <mbp@canonical.com>
+
+    if (m_caseSensitivity == Qt::CaseInsensitive) {
+        const int result = m_naturalSorting ? KStringHandler::naturalCompare(a, b, Qt::CaseInsensitive)
+                                            : QString::compare(a, b, Qt::CaseInsensitive);
+        if (result != 0) {
+            // Only return the result, if the strings are not equal. If they are equal by a case insensitive
+            // comparison, still a deterministic sort order is required. A case sensitive
+            // comparison is done as fallback.
+            return result;
+        }
+    }
+
+    return m_naturalSorting ? KStringHandler::naturalCompare(a, b, Qt::CaseSensitive)
+                            : QString::compare(a, b, Qt::CaseSensitive);
+}
+
+int KFileItemModel::expansionLevelsCompare(const KFileItem& a, const KFileItem& b) const
+{
+    const KUrl urlA = a.url();
+    const KUrl urlB = b.url();
+    if (urlA.directory() == urlB.directory()) {
+        // Both items have the same directory as parent
+        return 0;
+    }
+
+    // Check whether one item is the parent of the other item
+    if (urlA.isParentOf(urlB)) {
+        return -1;
+    } else if (urlB.isParentOf(urlA)) {
+        return +1;
+    }
+
+    // Determine the maximum common path of both items and
+    // remember the index in 'index'
+    const QString pathA = urlA.path();
+    const QString pathB = urlB.path();
+
+    const int maxIndex = qMin(pathA.length(), pathB.length()) - 1;
+    int index = 0;
+    while (index <= maxIndex && pathA.at(index) == pathB.at(index)) {
+        ++index;
+    }
+    if (index > maxIndex) {
+        index = maxIndex;
+    }
+    while (pathA.at(index) != QLatin1Char('/') && index > 0) {
+        --index;
+    }
+
+    // Determine the first sub-path after the common path and
+    // check whether it represents a directory or already a file
+    bool isDirA = true;
+    const QString subPathA = subPath(a, pathA, index, &isDirA);
+    bool isDirB = true;
+    const QString subPathB = subPath(b, pathB, index, &isDirB);
+
+    if (isDirA && !isDirB) {
+        return -1;
+    } else if (!isDirA && isDirB) {
+        return +1;
+    }
+
+    return stringCompare(subPathA, subPathB);
+}
+
+QString KFileItemModel::subPath(const KFileItem& item,
+                                const QString& itemPath,
+                                int start,
+                                bool* isDir) const
+{
+    Q_ASSERT(isDir);
+    const int pathIndex = itemPath.indexOf('/', start + 1);
+    *isDir = (pathIndex > 0) || item.isDir();
+    return itemPath.mid(start, pathIndex - start);
+}
+
+bool KFileItemModel::useMaximumUpdateInterval() const
+{
+    const KDirLister* dirLister = m_dirLister.data();
+    return dirLister && !dirLister->url().isLocalFile();
+}
+
+#include "kfileitemmodel.moc"
diff --git a/src/kitemviews/kfileitemmodel.h b/src/kitemviews/kfileitemmodel.h
new file mode 100644 (file)
index 0000000..e6c89d7
--- /dev/null
@@ -0,0 +1,192 @@
+/***************************************************************************
+ *   Copyright (C) 2011 by Peter Penz <peter.penz19@gmail.com>             *
+ *                                                                         *
+ *   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 program 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 program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA            *
+ ***************************************************************************/
+
+#ifndef KFILEITEMMODEL_H
+#define KFILEITEMMODEL_H
+
+#include <libdolphin_export.h>
+#include <KFileItemList>
+#include <KUrl>
+#include <kitemviews/kitemmodelbase.h>
+
+#include <QHash>
+
+class KDirLister;
+class QTimer;
+
+/**
+ * @brief KItemModelBase implementation for KFileItems.
+ *
+ * KFileItemModel is connected with one KDirLister. Each time the KDirLister
+ * emits new items, removes items or changes items the model gets synchronized.
+ *
+ * KFileItemModel supports sorting and grouping of items. Additional roles that
+ * are not part of KFileItem can be added with KFileItemModel::setData().
+ *
+ * Also the recursive expansion of sub-directories is supported by
+ * KFileItemModel::setExpanded().
+ */
+class LIBDOLPHINPRIVATE_EXPORT KFileItemModel : public KItemModelBase
+{
+    Q_OBJECT
+
+public:
+    explicit KFileItemModel(KDirLister* dirLister, QObject* parent = 0);
+    virtual ~KFileItemModel();
+
+    virtual int count() const;
+    virtual QHash<QByteArray, QVariant> data(int index) const;
+    virtual bool setData(int index, const QHash<QByteArray, QVariant> &values);
+
+    /**
+     * @return True
+     * @reimp
+     */
+    virtual bool supportsGrouping() const;
+
+    /**
+     * @return True
+     * @reimp
+     */
+    virtual bool supportsSorting() const;
+
+    /**
+     * @return The file-item for the index \a index. If the index is in a valid
+     *         range it is assured that the file-item is not null. The runtime
+     *         complexity of this call is O(1).
+     */
+    KFileItem fileItem(int index) const;
+
+    /**
+     * @return The index for the file-item \a item. -1 is returned if no file-item
+     *         is found or if the file-item is null. The runtime
+     *         complexity of this call is O(1).
+     */
+    int index(const KFileItem& item) const;
+
+    /**
+     * Clears all items of the model.
+     */
+    void clear();
+
+    // TODO: "name" + "isDir" is default in ctor
+    void setRoles(const QSet<QByteArray>& roles);
+    QSet<QByteArray> roles() const;
+
+    bool setExpanded(int index, bool expanded);
+    bool isExpanded(int index) const;
+    bool isExpandable(int index) const;
+
+protected:
+    virtual void onGroupRoleChanged(const QByteArray& current, const QByteArray& previous);
+    virtual void onSortRoleChanged(const QByteArray& current, const QByteArray& previous);
+
+private slots:
+    void slotCompleted();
+    void slotCanceled();
+    void slotNewItems(const KFileItemList& items);
+    void slotItemsDeleted(const KFileItemList& items);
+    void slotClear();
+    void slotClear(const KUrl& url);
+
+    void dispatchPendingItems();
+
+private:
+    void insertItems(const KFileItemList& items);
+    void removeItems(const KFileItemList& items);
+
+    void removeExpandedItems();
+
+    enum Role {
+        NoRole,
+        NameRole,
+        SizeRole,
+        DateRole,
+        PermissionsRole,
+        OwnerRole,
+        GroupRole,
+        TypeRole,
+        DestinationRole,
+        PathRole,
+        IsDirRole,
+        IsExpandedRole,
+        ExpansionLevelRole,
+        RolesCount // Mandatory last entry
+    };
+
+    void resetRoles();
+
+    Role roleIndex(const QByteArray& role) const;
+
+    QHash<QByteArray, QVariant> retrieveData(const KFileItem& item) const;
+
+    bool lessThan(const KFileItem& a, const KFileItem& b) const;
+    void sort(const KFileItemList::iterator& start, const KFileItemList::iterator& end);
+    int stringCompare(const QString& a, const QString& b) const;
+
+    /**
+     * Compares the expansion level of both items. The "expansion level" is defined
+     * by the number of parent directories. However simply comparing just the numbers
+     * is not sufficient, it is also important to check the hierarchy for having
+     * a correct order like shown in a tree.
+     */
+    int expansionLevelsCompare(const KFileItem& a, const KFileItem& b) const;
+
+    /**
+     * Helper method for expansionLevelCompare().
+     */
+    QString subPath(const KFileItem& item,
+                    const QString& itemPath,
+                    int start,
+                    bool* isDir) const;
+
+    bool useMaximumUpdateInterval() const;
+
+private:
+    QWeakPointer<KDirLister> m_dirLister;
+
+    bool m_naturalSorting;
+    bool m_sortFoldersFirst;
+
+    Role m_groupRole;
+    Role m_sortRole;
+    Qt::CaseSensitivity m_caseSensitivity;
+
+    KFileItemList m_sortedItems;   // Allows O(1) access for KFileItemModel::fileItem(int index)
+    QHash<KFileItem, int> m_items; // Allows O(1) access for KFileItemModel::index(const KFileItem& item)
+    QList<QHash<QByteArray, QVariant> > m_data;
+
+    bool m_requestRole[RolesCount];
+
+    QTimer* m_minimumUpdateIntervalTimer;
+    QTimer* m_maximumUpdateIntervalTimer;
+    KFileItemList m_pendingItemsToInsert;
+    KFileItemList m_pendingItemsToDelete;
+
+    // Stores the smallest expansion level of the root-URL. Is required to calculate
+    // the "expansionLevel" role in an efficient way. A value < 0 indicates that
+    // it has not been initialized yet.
+    mutable int m_rootExpansionLevel;
+
+    friend class KFileItemModelTest; // For unit testing
+};
+
+#endif
+
+
diff --git a/src/kitemviews/kfileitemmodelrolesupdater.cpp b/src/kitemviews/kfileitemmodelrolesupdater.cpp
new file mode 100644 (file)
index 0000000..325d08e
--- /dev/null
@@ -0,0 +1,765 @@
+/***************************************************************************
+ *   Copyright (C) 2011 by Peter Penz <peter.penz19@gmail.com>             *
+ *                                                                         *
+ *   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 program 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 program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA            *
+ ***************************************************************************/
+
+#include "kfileitemmodelrolesupdater.h"
+
+#include "kfileitemmodel.h"
+#include "kpixmapmodifier_p.h"
+
+#include <KConfig>
+#include <KConfigGroup>
+#include <KDebug>
+#include <KFileItem>
+#include <KGlobal>
+#include <KIO/PreviewJob>
+#include <QPainter>
+#include <QPixmap>
+#include <QElapsedTimer>
+#include <QTimer>
+
+// Required includes for subDirectoriesCount():
+#ifdef Q_WS_WIN
+    #include <QDir>
+#else
+    #include <dirent.h>
+    #include <QFile>
+#endif
+
+#define KFILEITEMMODELROLESUPDATER_DEBUG
+
+namespace {
+    const int MaxResolveItemsCount = 100;
+}
+
+KFileItemModelRolesUpdater::KFileItemModelRolesUpdater(KFileItemModel* model, QObject* parent) :
+    QObject(parent),
+    m_paused(false),
+    m_previewChangedDuringPausing(false),
+    m_iconSizeChangedDuringPausing(false),
+    m_rolesChangedDuringPausing(false),
+    m_previewShown(false),
+    m_clearPreviews(false),
+    m_model(model),
+    m_iconSize(),
+    m_firstVisibleIndex(0),
+    m_lastVisibleIndex(-1),
+    m_roles(),
+    m_enabledPlugins(),
+    m_pendingVisibleItems(),
+    m_pendingInvisibleItems(),
+    m_previewJobs(),
+    m_resolvePendingRolesTimer(0)
+{
+    Q_ASSERT(model);
+
+    const KConfigGroup globalConfig(KGlobal::config(), "PreviewSettings");
+    m_enabledPlugins = globalConfig.readEntry("Plugins", QStringList()
+                                                         << "directorythumbnail"
+                                                         << "imagethumbnail"
+                                                         << "jpegthumbnail");
+
+    connect(m_model, SIGNAL(itemsInserted(KItemRangeList)),
+            this,    SLOT(slotItemsInserted(KItemRangeList)));
+    connect(m_model, SIGNAL(itemsRemoved(KItemRangeList)),
+            this,    SLOT(slotItemsRemoved(KItemRangeList)));
+    connect(m_model, SIGNAL(itemsChanged(KItemRangeList,QSet<QByteArray>)),
+            this,    SLOT(slotItemsChanged(KItemRangeList,QSet<QByteArray>)));
+
+    // A timer with a minimal timeout is used to merge several triggerPendingRolesResolving() calls
+    // to only one call of resolvePendingRoles().
+    m_resolvePendingRolesTimer = new QTimer(this);
+    m_resolvePendingRolesTimer->setInterval(1);
+    m_resolvePendingRolesTimer->setSingleShot(true);
+    connect(m_resolvePendingRolesTimer, SIGNAL(timeout()), this, SLOT(resolvePendingRoles()));
+}
+
+KFileItemModelRolesUpdater::~KFileItemModelRolesUpdater()
+{
+}
+
+void KFileItemModelRolesUpdater::setIconSize(const QSize& size)
+{
+    if (size != m_iconSize) {
+        m_iconSize = size;
+        if (m_paused) {
+            m_iconSizeChangedDuringPausing = true;
+        } else if (m_previewShown) {
+            // An icon size change requires the regenerating of
+            // all previews
+            sortAndResolveAllRoles();
+        } else {
+            sortAndResolvePendingRoles();
+        }
+    }
+}
+
+QSize KFileItemModelRolesUpdater::iconSize() const
+{
+    return m_iconSize;
+}
+
+void KFileItemModelRolesUpdater::setVisibleIndexRange(int index, int count)
+{
+    if (index < 0) {
+        index = 0;
+    }
+    if (count < 0) {
+        count = 0;
+    }
+
+    if (index == m_firstVisibleIndex && count == m_lastVisibleIndex - m_firstVisibleIndex + 1) {
+        // The range has not been changed
+        return;
+    }
+
+    m_firstVisibleIndex = index;
+    m_lastVisibleIndex = qMin(index + count - 1, m_model->count() - 1);
+
+    if (hasPendingRoles() && !m_paused) {
+        sortAndResolvePendingRoles();
+    }
+}
+
+void KFileItemModelRolesUpdater::setPreviewShown(bool show)
+{
+    if (show == m_previewShown) {
+        return;
+    }
+
+    m_previewShown = show;
+    if (!show) {
+        m_clearPreviews = true;
+    }
+
+    if (m_paused) {
+        m_previewChangedDuringPausing = true;
+    } else {
+        sortAndResolveAllRoles();
+    }
+}
+
+bool KFileItemModelRolesUpdater::isPreviewShown() const
+{
+    return m_previewShown;
+}
+
+void KFileItemModelRolesUpdater::setEnabledPlugins(const QStringList& list)
+{
+    m_enabledPlugins = list;
+}
+
+void KFileItemModelRolesUpdater::setPaused(bool paused)
+{
+    if (paused == m_paused) {
+        return;
+    }
+
+    m_paused = paused;
+    if (paused) {
+        if (hasPendingRoles()) {
+            foreach (KJob* job, m_previewJobs) {
+                job->kill();
+            }
+            Q_ASSERT(m_previewJobs.isEmpty());
+        }
+    } else {
+        const bool resolveAll = (m_iconSizeChangedDuringPausing && m_previewShown) ||
+                                (m_previewChangedDuringPausing && !m_previewShown) ||
+                                m_rolesChangedDuringPausing;
+        if (resolveAll) {
+            sortAndResolveAllRoles();
+        } else {
+            sortAndResolvePendingRoles();
+        }
+
+        m_iconSizeChangedDuringPausing = false;
+        m_previewChangedDuringPausing = false;
+        m_rolesChangedDuringPausing = false;
+    }
+}
+
+void KFileItemModelRolesUpdater::setRoles(const QSet<QByteArray>& roles)
+{
+    if (roles.count() == m_roles.count()) {
+        bool isEqual = true;
+        foreach (const QByteArray& role, roles) {
+            if (!m_roles.contains(role)) {
+                isEqual = false;
+                break;
+            }
+        }
+        if (isEqual) {
+            return;
+        }
+    }
+
+    m_roles = roles;
+
+    if (m_paused) {
+        m_rolesChangedDuringPausing = true;
+    } else {
+        sortAndResolveAllRoles();
+    }
+}
+
+QSet<QByteArray> KFileItemModelRolesUpdater::roles() const
+{
+    return m_roles;
+}
+
+bool KFileItemModelRolesUpdater::isPaused() const
+{
+    return m_paused;
+}
+
+QStringList KFileItemModelRolesUpdater::enabledPlugins() const
+{
+    return m_enabledPlugins;
+}
+
+void KFileItemModelRolesUpdater::slotItemsInserted(const KItemRangeList& itemRanges)
+{
+    // If no valid index range is given assume that all items are visible.
+    // A cleanup will be done later as soon as the index range has been set.
+    const bool hasValidIndexRange = (m_lastVisibleIndex >= 0);
+
+    if (hasValidIndexRange) {
+        // Move all current pending visible items that are not visible anymore
+        // to the pending invisible items.
+        QSetIterator<KFileItem> it(m_pendingVisibleItems);
+        while (it.hasNext()) {
+            const KFileItem item = it.next();
+            const int index = m_model->index(item);
+            if (index < m_firstVisibleIndex || index > m_lastVisibleIndex) {
+                m_pendingVisibleItems.remove(item);
+                m_pendingInvisibleItems.insert(item);
+            }
+        }
+    }
+
+    int rangesCount = 0;
+
+    foreach (const KItemRange& range, itemRanges) {
+        rangesCount += range.count;
+
+        // Add the inserted items to the pending visible and invisible items
+        const int lastIndex = range.index + range.count - 1;
+        for (int i = range.index; i <= lastIndex; ++i) {
+            const KFileItem item = m_model->fileItem(i);
+            if (!hasValidIndexRange || (i >= m_firstVisibleIndex && i <= m_lastVisibleIndex)) {
+                m_pendingVisibleItems.insert(item);
+            } else {
+                m_pendingInvisibleItems.insert(item);
+            }
+        }
+    }
+
+    triggerPendingRolesResolving(rangesCount);
+}
+
+void KFileItemModelRolesUpdater::slotItemsRemoved(const KItemRangeList& itemRanges)
+{
+    Q_UNUSED(itemRanges);
+    m_firstVisibleIndex = 0;
+    m_lastVisibleIndex = -1;
+    if (hasPendingRoles() && m_model->count() <= 0) {
+        resetPendingRoles();
+    }
+}
+
+void KFileItemModelRolesUpdater::slotItemsChanged(const KItemRangeList& itemRanges,
+                                                  const QSet<QByteArray>& roles)
+{
+    Q_UNUSED(itemRanges);
+    Q_UNUSED(roles);
+    // TODO
+}
+
+void KFileItemModelRolesUpdater::slotGotPreview(const KFileItem& item, const QPixmap& pixmap)
+{
+    m_pendingVisibleItems.remove(item);
+    m_pendingInvisibleItems.remove(item);
+
+    const int index = m_model->index(item);
+    if (index < 0) {
+        return;
+    }
+
+    QPixmap scaledPixmap = pixmap;
+
+    const QString mimeType = item.mimetype();
+    const int slashIndex = mimeType.indexOf(QLatin1Char('/'));
+    const QString mimeTypeGroup = mimeType.left(slashIndex);
+    if (mimeTypeGroup == QLatin1String("image")) {
+        KPixmapModifier::applyFrame(scaledPixmap, m_iconSize);
+    } else {
+        KPixmapModifier::scale(scaledPixmap, m_iconSize);
+    }
+
+    QHash<QByteArray, QVariant> data = rolesData(item);
+    data.insert("iconPixmap", scaledPixmap);
+
+    disconnect(m_model, SIGNAL(itemsChanged(KItemRangeList,QSet<QByteArray>)),
+               this,    SLOT(slotItemsChanged(KItemRangeList,QSet<QByteArray>)));
+    m_model->setData(index, data);
+    connect(m_model, SIGNAL(itemsChanged(KItemRangeList,QSet<QByteArray>)),
+            this,    SLOT(slotItemsChanged(KItemRangeList,QSet<QByteArray>)));
+}
+
+void KFileItemModelRolesUpdater::slotPreviewFailed(const KFileItem& item)
+{
+    m_pendingVisibleItems.remove(item);
+    m_pendingInvisibleItems.remove(item);
+
+    const bool clearPreviews = m_clearPreviews;
+    m_clearPreviews = true;
+    applyResolvedRoles(item, ResolveAll);
+    m_clearPreviews = clearPreviews;
+}
+
+void KFileItemModelRolesUpdater::slotPreviewJobFinished(KJob* job)
+{
+#ifdef KFILEITEMMODELROLESUPDATER_DEBUG
+    kDebug() << "Preview job finished. Pending visible:" << m_pendingVisibleItems.count() << "invisible:" << m_pendingInvisibleItems.count();
+#endif
+
+    m_previewJobs.removeOne(job);
+    if (!m_previewJobs.isEmpty() || !hasPendingRoles()) {
+        return;
+    }
+
+    const KFileItemList visibleItems   = sortedItems(m_pendingVisibleItems);
+    const KFileItemList invisibleItems = itemSubSet(m_pendingInvisibleItems, MaxResolveItemsCount - visibleItems.count());
+    startPreviewJob(visibleItems + invisibleItems);
+}
+
+void KFileItemModelRolesUpdater::resolvePendingRoles()
+{
+    int resolvedCount = 0;
+
+    const bool hasSlowRoles = m_previewShown
+                              || m_roles.contains("size")
+                              || m_roles.contains("type");
+    const ResolveHint resolveHint = hasSlowRoles ? ResolveFast : ResolveAll;
+
+    // Resolving the MIME type can be expensive. Assure that not more than 200 ms are
+    // spend for resolving them synchronously. Usually this is more than enough to determine
+    // all visible items, but there are corner cases where this limit gets easily exceeded.
+    const int MaxTime = 200;
+    QElapsedTimer timer;
+    timer.start();
+
+    // Resolve the MIME type of all visible items
+    QSetIterator<KFileItem> visibleIt(m_pendingVisibleItems);
+    while (visibleIt.hasNext()) {
+        const KFileItem item = visibleIt.next();
+        applyResolvedRoles(item, resolveHint);
+        if (!hasSlowRoles) {
+            Q_ASSERT(!m_pendingInvisibleItems.contains(item));
+            // All roles have been resolved already by applyResolvedRoles()
+            m_pendingVisibleItems.remove(item);
+        }
+        ++resolvedCount;
+
+        if (timer.elapsed() > MaxTime) {
+            break;
+        }
+    }
+
+    // Resolve the MIME type of the invisible items at least until the timeout
+    // has been exceeded or the maximum number of items has been reached
+    KFileItemList invisibleItems;
+    if (m_lastVisibleIndex >= 0) {
+        // The visible range is valid, don't care about the order how the MIME
+        // type of invisible items get resolved
+        invisibleItems = m_pendingInvisibleItems.toList();
+    } else {
+        // The visible range is temporary invalid (e.g. happens when loading
+        // a directory) so take care to sort the currently invisible items where
+        // a part will get visible later
+        invisibleItems = sortedItems(m_pendingInvisibleItems);
+    }
+
+    int index = 0;
+    while (resolvedCount < MaxResolveItemsCount && index < invisibleItems.count() && timer.elapsed() <= MaxTime) {
+        const KFileItem item = invisibleItems.at(index);
+        applyResolvedRoles(item, resolveHint);
+
+        if (!hasSlowRoles) {
+            // All roles have been resolved already by applyResolvedRoles()
+            m_pendingInvisibleItems.remove(item);
+        }
+        ++index;
+        ++resolvedCount;
+    }
+
+    if (m_previewShown) {
+        KFileItemList items = sortedItems(m_pendingVisibleItems);
+        items += invisibleItems;
+        startPreviewJob(items);
+    } else {
+        QTimer::singleShot(0, this, SLOT(resolveNextPendingRoles()));
+    }
+
+#ifdef KFILEITEMMODELROLESUPDATER_DEBUG
+    if (timer.elapsed() > MaxTime) {
+        kDebug() << "Maximum time exceeded, skipping items... Remaining visible:" << m_pendingVisibleItems.count()
+                 << "invisible:" << m_pendingInvisibleItems.count();
+    }
+    kDebug() << "[TIME] Resolved pending roles:" << timer.elapsed();
+#endif
+}
+
+void KFileItemModelRolesUpdater::resolveNextPendingRoles()
+{
+    if (m_paused) {
+        return;
+    }
+
+    if (m_previewShown) {
+        // The preview has been turned on since the last run. Skip
+        // resolving further pending roles as this is done as soon
+        // as a preview has been received.
+        return;
+    }
+
+    int resolvedCount = 0;
+    bool changed = false;
+    for (int i = 0; i <= 1; ++i) {
+        QSet<KFileItem>& pendingItems = (i == 0) ? m_pendingVisibleItems : m_pendingInvisibleItems;
+        QSetIterator<KFileItem> it(pendingItems);
+        while (it.hasNext() && !changed && resolvedCount < MaxResolveItemsCount) {
+            const KFileItem item = it.next();
+            pendingItems.remove(item);
+            changed = applyResolvedRoles(item, ResolveAll);
+            ++resolvedCount;
+        }
+    }
+
+    if (hasPendingRoles()) {
+        QTimer::singleShot(0, this, SLOT(resolveNextPendingRoles()));
+    } else {
+        m_clearPreviews = false;
+    }
+
+#ifdef KFILEITEMMODELROLESUPDATER_DEBUG
+    static int callCount = 0;
+    ++callCount;
+    if (callCount % 100 == 0) {
+        kDebug() << "Remaining visible roles to resolve:" << m_pendingVisibleItems.count()
+                 << "invisible:" << m_pendingInvisibleItems.count();
+    }
+#endif
+}
+
+void KFileItemModelRolesUpdater::startPreviewJob(const KFileItemList& items)
+{
+    if (items.count() <= 0 || m_paused) {
+        return;
+    }
+
+    // PreviewJob internally caches items always with the size of
+    // 128 x 128 pixels or 256 x 256 pixels. A (slow) downscaling is done
+    // by PreviewJob if a smaller size is requested. For images KFileItemModelRolesUpdater must
+    // do a downscaling anyhow because of the frame, so in this case only the provided
+    // cache sizes are requested.
+    const QSize cacheSize = (m_iconSize.width() > 128) || (m_iconSize.height() > 128)
+                            ? QSize(256, 256) : QSize(128, 128);
+
+    KJob* job;
+    if (items.count() <= MaxResolveItemsCount) {
+        job = KIO::filePreview(items, cacheSize, &m_enabledPlugins);
+    } else {
+        KFileItemList itemsSubSet;
+        for (int i = 0; i <= MaxResolveItemsCount; ++i) {
+            itemsSubSet.append(items.at(i));
+        }
+        job = KIO::filePreview(itemsSubSet, cacheSize, &m_enabledPlugins);
+    }
+
+    connect(job,  SIGNAL(gotPreview(const KFileItem&, const QPixmap&)),
+            this, SLOT(slotGotPreview(const KFileItem&, const QPixmap&)));
+    connect(job,  SIGNAL(failed(KFileItem)),
+            this, SLOT(slotPreviewFailed(KFileItem)));
+    connect(job,  SIGNAL(finished(KJob*)),
+            this, SLOT(slotPreviewJobFinished(KJob*)));
+
+    m_previewJobs.append(job);
+}
+
+
+bool KFileItemModelRolesUpdater::hasPendingRoles() const
+{
+    return !m_pendingVisibleItems.isEmpty() || !m_pendingInvisibleItems.isEmpty();
+}
+
+void KFileItemModelRolesUpdater::resetPendingRoles()
+{
+    m_pendingVisibleItems.clear();
+    m_pendingInvisibleItems.clear();
+
+    foreach (KJob* job, m_previewJobs) {
+        job->kill();
+    }
+    Q_ASSERT(m_previewJobs.isEmpty());
+}
+
+void KFileItemModelRolesUpdater::triggerPendingRolesResolving(int count)
+{
+    Q_ASSERT(count <= m_model->count());
+    if (count == m_model->count()) {
+        // When initially loading a directory a synchronous resolving prevents a minor
+        // flickering when opening directories. This is also fine from a performance point
+        // of view as it is assured in resolvePendingRoles() to never block the event-loop
+        // for more than 200 ms.
+        resolvePendingRoles();
+    } else {
+        // Items have been added. This can be done in several small steps within one loop
+        // because of the sorting and hence may not trigger any expensive operation.
+        m_resolvePendingRolesTimer->start();
+    }
+}
+
+void KFileItemModelRolesUpdater::sortAndResolveAllRoles()
+{
+    if (m_paused) {
+        return;
+    }
+
+    resetPendingRoles();
+    Q_ASSERT(m_pendingVisibleItems.isEmpty());
+    Q_ASSERT(m_pendingInvisibleItems.isEmpty());
+
+    if (m_model->count() <= 0) {
+        return;
+    }
+
+    // Determine all visible items
+    Q_ASSERT(m_firstVisibleIndex >= 0);
+    for (int i = m_firstVisibleIndex; i <= m_lastVisibleIndex; ++i) {
+        const KFileItem item = m_model->fileItem(i);
+        if (!item.isNull()) {
+            m_pendingVisibleItems.insert(item);
+        }
+    }
+
+    // Determine all invisible items
+    for (int i = 0; i < m_firstVisibleIndex; ++i) {
+        const KFileItem item = m_model->fileItem(i);
+        if (!item.isNull()) {
+            m_pendingInvisibleItems.insert(item);
+        }
+    }
+    for (int i = m_lastVisibleIndex + 1; i < m_model->count(); ++i) {
+        const KFileItem item = m_model->fileItem(i);
+        if (!item.isNull()) {
+            m_pendingInvisibleItems.insert(item);
+        }
+    }
+
+    triggerPendingRolesResolving(m_pendingVisibleItems.count() +
+                                 m_pendingInvisibleItems.count());
+}
+
+void KFileItemModelRolesUpdater::sortAndResolvePendingRoles()
+{
+    Q_ASSERT(!m_paused);
+    if (m_model->count() <= 0) {
+        return;
+    }
+
+    // If no valid index range is given assume that all items are visible.
+    // A cleanup will be done later as soon as the index range has been set.
+    const bool hasValidIndexRange = (m_lastVisibleIndex >= 0);
+
+    // Trigger a preview generation of all pending items. Assure that the visible
+    // pending items get generated first.
+    QSet<KFileItem> pendingItems;
+    pendingItems += m_pendingVisibleItems;
+    pendingItems += m_pendingInvisibleItems;
+
+    resetPendingRoles();
+    Q_ASSERT(m_pendingVisibleItems.isEmpty());
+    Q_ASSERT(m_pendingInvisibleItems.isEmpty());
+
+    QSetIterator<KFileItem> it(pendingItems);
+    while (it.hasNext()) {
+        const KFileItem item = it.next();
+        if (item.isNull()) {
+            continue;
+        }
+
+        const int index = m_model->index(item);
+        if (!hasValidIndexRange || (index >= m_firstVisibleIndex && index <= m_lastVisibleIndex)) {
+            m_pendingVisibleItems.insert(item);
+        } else {
+            m_pendingInvisibleItems.insert(item);
+        }
+    }
+
+    triggerPendingRolesResolving(m_pendingVisibleItems.count() +
+                                 m_pendingInvisibleItems.count());
+}
+
+bool KFileItemModelRolesUpdater::applyResolvedRoles(const KFileItem& item, ResolveHint hint)
+{
+    const bool resolveAll = (hint == ResolveAll);
+
+    bool mimeTypeChanged = false;
+    if (!item.isMimeTypeKnown()) {
+        item.determineMimeType();
+        mimeTypeChanged = true;
+    }
+
+    if (mimeTypeChanged || resolveAll || m_clearPreviews) {
+        const int index = m_model->index(item);
+        if (index < 0) {
+            return false;
+        }
+
+        QHash<QByteArray, QVariant> data;
+        if (resolveAll) {
+            data = rolesData(item);
+        }
+
+        if (mimeTypeChanged || m_clearPreviews) {
+            data.insert("iconName", item.iconName());
+        }
+        if (m_clearPreviews) {
+            data.insert("iconPixmap", QString());
+        }
+
+        disconnect(m_model, SIGNAL(itemsChanged(KItemRangeList,QSet<QByteArray>)),
+                   this,    SLOT(slotItemsChanged(KItemRangeList,QSet<QByteArray>)));
+        m_model->setData(index, data);
+        connect(m_model, SIGNAL(itemsChanged(KItemRangeList,QSet<QByteArray>)),
+                this,    SLOT(slotItemsChanged(KItemRangeList,QSet<QByteArray>)));
+        return true;
+    }
+
+    return false;
+}
+
+QHash<QByteArray, QVariant> KFileItemModelRolesUpdater::rolesData(const KFileItem& item) const
+{
+    QHash<QByteArray, QVariant> data;
+
+    if (m_roles.contains("size")) {
+        if (item.isDir() && item.isLocalFile()) {
+            const QString path = item.localPath();
+            const int count = subDirectoriesCount(path);
+            if (count >= 0) {
+                data.insert("size", KIO::filesize_t(count));
+            }
+        }
+    }
+
+    if (m_roles.contains("type")) {
+        data.insert("type", item.mimeComment());
+    }
+
+    return data;
+}
+
+KFileItemList KFileItemModelRolesUpdater::sortedItems(const QSet<KFileItem>& items) const
+{
+    KFileItemList itemList;
+    if (items.isEmpty()) {
+        return itemList;
+    }
+
+#ifdef KFILEITEMMODELROLESUPDATER_DEBUG
+    QElapsedTimer timer;
+    timer.start();
+#endif
+
+    QList<int> indexes;
+    indexes.reserve(items.count());
+
+    QSetIterator<KFileItem> it(items);
+    while (it.hasNext()) {
+        const KFileItem item = it.next();
+        const int index = m_model->index(item);
+        indexes.append(index);
+    }
+    qSort(indexes);
+
+    itemList.reserve(items.count());
+    foreach (int index, indexes) {
+        itemList.append(m_model->fileItem(index));
+    }
+
+#ifdef KFILEITEMMODELROLESUPDATER_DEBUG
+    kDebug() << "[TIME] Sorting of items:" << timer.elapsed();
+#endif
+    return itemList;
+}
+
+KFileItemList KFileItemModelRolesUpdater::itemSubSet(const QSet<KFileItem>& items, int count)
+{
+    KFileItemList itemList;
+
+    int index = 0;
+    QSetIterator<KFileItem> it(items);
+    while (it.hasNext() && index < count) {
+        const KFileItem item = it.next();
+        if (item.isNull()) {
+            continue;
+        }
+        itemList.append(item);
+        ++index;
+    }
+
+    return itemList;
+}
+
+int KFileItemModelRolesUpdater::subDirectoriesCount(const QString& path)
+{
+#ifdef Q_WS_WIN
+    QDir dir(path);
+    return dir.entryList(QDir::AllEntries|QDir::NoDotAndDotDot|QDir::System).count();
+#else
+    // Taken from kdelibs/kio/kio/kdirmodel.cpp
+    // Copyright (C) 2006 David Faure <faure@kde.org>
+
+    int count = -1;
+    DIR* dir = ::opendir(QFile::encodeName(path));
+    if (dir) {
+        count = 0;
+        struct dirent *dirEntry = 0;
+        while ((dirEntry = ::readdir(dir))) {
+            if (dirEntry->d_name[0] == '.') {
+                if (dirEntry->d_name[1] == '\0') {
+                    // Skip "."
+                    continue;
+                }
+                if (dirEntry->d_name[1] == '.' && dirEntry->d_name[2] == '\0') {
+                    // Skip ".."
+                    continue;
+                }
+            }
+            ++count;
+        }
+        ::closedir(dir);
+    }
+    return count;
+#endif
+}
+
+#include "kfileitemmodelrolesupdater.moc"
diff --git a/src/kitemviews/kfileitemmodelrolesupdater.h b/src/kitemviews/kfileitemmodelrolesupdater.h
new file mode 100644 (file)
index 0000000..4931f9d
--- /dev/null
@@ -0,0 +1,177 @@
+/***************************************************************************
+ *   Copyright (C) 2011 by Peter Penz <peter.penz19@gmail.com>             *
+ *                                                                         *
+ *   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 program 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 program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA            *
+ ***************************************************************************/
+
+#ifndef KFILEITEMMODELROLESUPDATER_H
+#define KFILEITEMMODELROLESUPDATER_H
+
+#include <libdolphin_export.h>
+
+#include <KFileItem>
+#include <kitemviews/kitemmodelbase.h>
+
+#include <QObject>
+#include <QSet>
+#include <QSize>
+#include <QStringList>
+
+class KFileItemModel;
+class KJob;
+class QPixmap;
+class QTimer;
+
+/**
+ * @brief Resolves expensive roles asynchronously and applies them to the KFileItemModel.
+ *
+ * KFileItemModel only resolves roles that are inexpensive like e.g. the file name or
+ * the permissions. Creating previews or determining the MIME-type can be quite expensive
+ * and KFileItemModelRolesUpdater takes care to update such roles asynchronously.
+ */
+class LIBDOLPHINPRIVATE_EXPORT KFileItemModelRolesUpdater : public QObject
+{
+    Q_OBJECT
+
+public:
+    KFileItemModelRolesUpdater(KFileItemModel* model, QObject* parent = 0);
+    virtual ~KFileItemModelRolesUpdater();
+
+    void setIconSize(const QSize& size);
+    QSize iconSize() const;
+
+    /**
+     * Sets the range of items that are visible currently. The roles
+     * of visible items are resolved first.
+     */
+    void setVisibleIndexRange(int index, int count);
+
+    /**
+     * If \a show is set to true, the "iconPixmap" role will be filled with a preview
+     * of the file. If \a show is false the MIME type icon will be used for the "iconPixmap"
+     * role.
+     */
+    void setPreviewShown(bool show);
+    bool isPreviewShown() const;
+
+    /**
+     * If \a paused is set to true the asynchronous resolving of roles will be paused.
+     * State changes during pauses like changing the icon size or the preview-shown
+     * will be remembered and handled after unpausing.
+     */
+    void setPaused(bool paused);
+    bool isPaused() const;
+
+    /**
+     * Sets the roles that should be resolved asynchronously.
+     */
+    void setRoles(const QSet<QByteArray>& roles);
+    QSet<QByteArray> roles() const;
+
+    /**
+     * Sets the list of enabled thumbnail plugins.
+     * Per default all plugins enabled in the KConfigGroup "PreviewSettings"
+     * are used.
+     *
+     * Note that this method doesn't cause already generated previews
+     * to be regenerated.
+     *
+     * For a list of available plugins, call KServiceTypeTrader::self()->query("ThumbCreator").
+     *
+     * @see enabledPlugins
+     */
+    void setEnabledPlugins(const QStringList& list);
+
+    /**
+     * Returns the list of enabled thumbnail plugins.
+     * @see setEnabledPlugins
+     */
+    QStringList enabledPlugins() const;
+
+private slots:
+    void slotItemsInserted(const KItemRangeList& itemRanges);
+    void slotItemsRemoved(const KItemRangeList& itemRanges);
+    void slotItemsChanged(const KItemRangeList& itemRanges,
+                          const QSet<QByteArray>& roles);
+
+    void slotGotPreview(const KFileItem& item, const QPixmap& pixmap);
+    void slotPreviewFailed(const KFileItem& item);
+
+    /**
+     * Is invoked when the preview job has been finished and
+     * removes the job from the m_previewJobs list.
+     */
+    void slotPreviewJobFinished(KJob* job);
+
+    void resolvePendingRoles();
+    void resolveNextPendingRoles();
+
+private:
+    void startPreviewJob(const KFileItemList& items);
+
+    bool hasPendingRoles() const;
+    void resetPendingRoles();
+    void triggerPendingRolesResolving(int count);
+    void sortAndResolveAllRoles();
+    void sortAndResolvePendingRoles();
+
+    enum ResolveHint {
+        ResolveFast,
+        ResolveAll
+    };
+    bool applyResolvedRoles(const KFileItem& item, ResolveHint hint);
+    QHash<QByteArray, QVariant> rolesData(const KFileItem& item) const;
+
+    KFileItemList sortedItems(const QSet<KFileItem>& items) const;
+
+    static KFileItemList itemSubSet(const QSet<KFileItem>& items, int count);
+    static int subDirectoriesCount(const QString& path);
+
+private:
+    // Property for setPaused()/isPaused().
+    bool m_paused;
+
+    // Property changes during pausing must be remembered to be able
+    // to react when unpausing again:
+    bool m_previewChangedDuringPausing;
+    bool m_iconSizeChangedDuringPausing;
+    bool m_rolesChangedDuringPausing;
+
+    // Property for setPreviewShown()/previewShown().
+    bool m_previewShown;
+
+    // True if the role "iconPixmap" should be cleared when resolving the next
+    // role with resolveRole(). Is necessary if the preview gets disabled
+    // during the roles-updater has been paused by setPaused().
+    bool m_clearPreviews;
+
+    KFileItemModel* m_model;
+    QSize m_iconSize;
+    int m_firstVisibleIndex;
+    int m_lastVisibleIndex;
+    QSet<QByteArray> m_roles;
+    QStringList m_enabledPlugins;
+
+    QSet<KFileItem> m_pendingVisibleItems;
+    QSet<KFileItem> m_pendingInvisibleItems;
+    QList<KJob*> m_previewJobs;
+
+    QTimer* m_resolvePendingRolesTimer;
+};
+
+#endif
+
+
diff --git a/src/kitemviews/kitemlistcontainer.cpp b/src/kitemviews/kitemlistcontainer.cpp
new file mode 100644 (file)
index 0000000..09fb505
--- /dev/null
@@ -0,0 +1,191 @@
+/***************************************************************************
+ *   Copyright (C) 2011 by Peter Penz <peter.penz19@gmail.com>             *
+ *                                                                         *
+ *   Based on the Itemviews NG project from Trolltech Labs:                *
+ *   http://qt.gitorious.org/qt-labs/itemviews-ng                          *
+ *                                                                         *
+ *   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 program 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 program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA            *
+ ***************************************************************************/
+
+#include "kitemlistcontainer.h"
+
+#include "kitemlistcontroller.h"
+#include "kitemlistview.h"
+#include "kitemmodelbase.h"
+
+#include <QGraphicsScene>
+#include <QGraphicsView>
+#include <QScrollBar>
+#include <QStyle>
+
+#include <KDebug>
+
+class KItemListContainerViewport : public QGraphicsView
+{
+public:
+    KItemListContainerViewport(QGraphicsScene* scene, QWidget* parent)
+        : QGraphicsView(scene, parent)
+    {
+        setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+        setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+        setViewportMargins(0, 0, 0, 0);
+        setFrameShape(QFrame::NoFrame);
+    }
+
+    void scrollContentsBy(int dx, int dy)
+    {
+        Q_UNUSED(dx);
+        Q_UNUSED(dy);
+        // Do nothing. This prevents that e.g. the wheel-event
+        // results in a moving of the scene items.
+    }
+};
+
+KItemListContainer::KItemListContainer(KItemListController* controller, QWidget* parent) :
+    QAbstractScrollArea(parent),
+    m_controller(controller)
+{
+    Q_ASSERT(controller);
+    controller->setParent(this);
+    initialize();
+}
+
+KItemListContainer::KItemListContainer(QWidget* parent) :
+    QAbstractScrollArea(parent),
+    m_controller(0)
+{
+    initialize();
+}
+
+KItemListContainer::~KItemListContainer()
+{
+}
+
+KItemListController* KItemListContainer::controller() const
+{
+    return m_controller;
+}
+
+void KItemListContainer::showEvent(QShowEvent* event)
+{
+    QAbstractScrollArea::showEvent(event);
+    updateGeometries();
+}
+
+void KItemListContainer::resizeEvent(QResizeEvent* event)
+{
+    QAbstractScrollArea::resizeEvent(event);
+    updateGeometries();
+}
+
+void KItemListContainer::scrollContentsBy(int dx, int dy)
+{
+    KItemListView* view = m_controller->view();
+    if (!view) {
+        return;
+    }
+
+    const qreal currentOffset = view->offset();
+    const qreal offsetDiff = (view->scrollOrientation() == Qt::Vertical) ? dy : dx;
+    view->setOffset(currentOffset - offsetDiff);
+}
+
+void KItemListContainer::slotModelChanged(KItemModelBase* current, KItemModelBase* previous)
+{
+    Q_UNUSED(current);
+    Q_UNUSED(previous);
+}
+
+void KItemListContainer::slotViewChanged(KItemListView* current, KItemListView* previous)
+{
+    QGraphicsScene* scene = static_cast<QGraphicsView*>(viewport())->scene();
+    if (previous) {
+        scene->removeItem(previous);
+        disconnect(previous, SIGNAL(offsetChanged(int,int)), this, SLOT(updateScrollBars()));
+        disconnect(previous, SIGNAL(maximumOffsetChanged(int,int)), this, SLOT(updateScrollBars()));
+    }
+    if (current) {
+        scene->addItem(current);
+        connect(previous, SIGNAL(offsetChanged(int,int)), this, SLOT(updateScrollBars()));
+        connect(current, SIGNAL(maximumOffsetChanged(int,int)), this, SLOT(updateScrollBars()));
+    }
+}
+
+void KItemListContainer::updateScrollBars()
+{
+    const QSizeF size = m_controller->view()->size();
+
+    if (m_controller->view()->scrollOrientation() == Qt::Vertical) {
+        QScrollBar* scrollBar = verticalScrollBar();
+        const int value = m_controller->view()->offset();
+        const int maximum = qMax(0, int(m_controller->view()->maximumOffset() - size.height()));
+        scrollBar->setPageStep(size.height());
+        scrollBar->setMinimum(0);
+        scrollBar->setMaximum(maximum);
+        scrollBar->setValue(value);
+        horizontalScrollBar()->setMaximum(0);
+    } else {
+        QScrollBar* scrollBar = horizontalScrollBar();
+        const int value = m_controller->view()->offset();
+        const int maximum = qMax(0, int(m_controller->view()->maximumOffset() - size.width()));
+        scrollBar->setPageStep(size.width());
+        scrollBar->setMinimum(0);
+        scrollBar->setMaximum(maximum);
+        scrollBar->setValue(value);
+        verticalScrollBar()->setMaximum(0);
+    }
+}
+
+void KItemListContainer::updateGeometries()
+{
+    QRect rect = geometry();
+
+    int widthDec = frameWidth() * 2;
+    if (verticalScrollBar()->isVisible()) {
+        widthDec += style()->pixelMetric(QStyle::PM_ScrollBarExtent);
+    }
+
+    int heightDec = frameWidth() * 2;
+    if (horizontalScrollBar()->isVisible()) {
+        heightDec += style()->pixelMetric(QStyle::PM_ScrollBarExtent);
+    }
+
+    rect.adjust(0, 0, -widthDec, -heightDec);
+
+    m_controller->view()->setGeometry(QRect(0, 0, rect.width(), rect.height()));
+
+    static_cast<KItemListContainerViewport*>(viewport())->scene()->setSceneRect(0, 0, rect.width(), rect.height());
+    static_cast<KItemListContainerViewport*>(viewport())->viewport()->setGeometry(QRect(0, 0, rect.width(), rect.height()));
+
+    updateScrollBars();
+}
+
+void KItemListContainer::initialize()
+{
+    if (!m_controller) {
+        m_controller = new KItemListController(this);
+    }
+
+    connect(m_controller, SIGNAL(modelChanged(KItemModelBase*,KItemModelBase*)),
+            this, SLOT(slotModelChanged(KItemModelBase*,KItemModelBase*)));
+    connect(m_controller, SIGNAL(viewChanged(KItemListView*,KItemListView*)),
+            this, SLOT(slotViewChanged(KItemListView*,KItemListView*)));
+
+    QGraphicsView* graphicsView = new KItemListContainerViewport(new QGraphicsScene(this), this);
+    setViewport(graphicsView);
+}
+
+#include "kitemlistcontainer.moc"
diff --git a/src/kitemviews/kitemlistcontainer.h b/src/kitemviews/kitemlistcontainer.h
new file mode 100644 (file)
index 0000000..83044c4
--- /dev/null
@@ -0,0 +1,70 @@
+/***************************************************************************
+ *   Copyright (C) 2011 by Peter Penz <peter.penz19@gmail.com>             *
+ *                                                                         *
+ *   Based on the Itemviews NG project from Trolltech Labs:                *
+ *   http://qt.gitorious.org/qt-labs/itemviews-ng                          *
+ *                                                                         *
+ *   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 program 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 program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA            *
+ ***************************************************************************/
+
+#ifndef KITEMLISTCONTAINER_H
+#define KITEMLISTCONTAINER_H
+
+#include <libdolphin_export.h>
+
+#include <QAbstractScrollArea>
+
+class KItemListController;
+class KItemListView;
+class KItemModelBase;
+
+/**
+ * @brief Provides a QWidget based scrolling view for a KItemListController.
+ *
+ * @see KItemListController
+ */
+class LIBDOLPHINPRIVATE_EXPORT KItemListContainer : public QAbstractScrollArea
+{
+    Q_OBJECT
+
+public:
+    explicit KItemListContainer(KItemListController* controller, QWidget* parent = 0);
+    KItemListContainer(QWidget* parent = 0);
+    virtual ~KItemListContainer();
+
+    KItemListController* controller() const;
+
+protected:
+    virtual void showEvent(QShowEvent* event);
+    virtual void resizeEvent(QResizeEvent* event);
+    virtual void scrollContentsBy(int dx, int dy);
+
+private slots:
+    void slotModelChanged(KItemModelBase* current, KItemModelBase* previous);
+    void slotViewChanged(KItemListView* current, KItemListView* previous);
+    void updateScrollBars();
+
+private:
+    void initialize();
+    void updateGeometries();
+
+private:
+    KItemListController* m_controller;
+};
+
+#endif
+
+
diff --git a/src/kitemviews/kitemlistcontroller.cpp b/src/kitemviews/kitemlistcontroller.cpp
new file mode 100644 (file)
index 0000000..b709e56
--- /dev/null
@@ -0,0 +1,281 @@
+/***************************************************************************
+ *   Copyright (C) 2011 by Peter Penz <peter.penz19@gmail.com>             *
+ *                                                                         *
+ *   Based on the Itemviews NG project from Trolltech Labs:                *
+ *   http://qt.gitorious.org/qt-labs/itemviews-ng                          *
+ *                                                                         *
+ *   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 program 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 program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA            *
+ ***************************************************************************/
+
+#include "kitemlistcontroller.h"
+
+#include "kitemlistview.h"
+#include "kitemlistselectionmanager.h"
+
+#include <QEvent>
+#include <QGraphicsSceneEvent>
+#include <QTransform>
+
+#include <KDebug>
+
+KItemListController::KItemListController(QObject* parent) :
+    QObject(parent),
+    m_selectionBehavior(NoSelection),
+    m_model(0),
+    m_view(0),
+    m_selectionManager(new KItemListSelectionManager(this))
+{
+}
+
+KItemListController::~KItemListController()
+{
+}
+
+void KItemListController::setModel(KItemModelBase* model)
+{
+    if (m_model == model) {
+        return;
+    }
+
+    KItemModelBase* oldModel = m_model;
+    m_model = model;
+
+    if (m_view) {
+        m_view->setModel(m_model);
+    }
+
+    emit modelChanged(m_model, oldModel);
+}
+
+KItemModelBase* KItemListController::model() const
+{
+    return m_model;
+}
+
+KItemListSelectionManager* KItemListController::selectionManager() const
+{
+    return m_selectionManager;
+}
+
+void KItemListController::setView(KItemListView* view)
+{
+    if (m_view == view) {
+        return;
+    }
+
+    KItemListView* oldView = m_view;
+    m_view = view;
+
+    if (m_view) {
+        m_view->setController(this);
+        m_view->setModel(m_model);
+    }
+
+    emit viewChanged(m_view, oldView);
+}
+
+KItemListView* KItemListController::view() const
+{
+    return m_view;
+}
+
+void KItemListController::setSelectionBehavior(SelectionBehavior behavior)
+{
+    m_selectionBehavior = behavior;
+}
+
+KItemListController::SelectionBehavior KItemListController::selectionBehavior() const
+{
+    return m_selectionBehavior;
+}
+
+bool KItemListController::showEvent(QShowEvent* event)
+{
+    Q_UNUSED(event);
+    return false;
+}
+
+bool KItemListController::hideEvent(QHideEvent* event)
+{
+    Q_UNUSED(event);
+    return false;
+}
+
+bool KItemListController::keyPressEvent(QKeyEvent* event)
+{
+    Q_UNUSED(event);
+    return false;
+}
+
+bool KItemListController::inputMethodEvent(QInputMethodEvent* event)
+{
+    Q_UNUSED(event);
+    return false;
+}
+
+bool KItemListController::mousePressEvent(QGraphicsSceneMouseEvent* event, const QTransform& transform)
+{
+    Q_UNUSED(event);
+    Q_UNUSED(transform);
+    return false;
+}
+
+bool KItemListController::mouseMoveEvent(QGraphicsSceneMouseEvent* event, const QTransform& transform)
+{
+    Q_UNUSED(event);
+    Q_UNUSED(transform);
+    return false;
+}
+
+bool KItemListController::mouseReleaseEvent(QGraphicsSceneMouseEvent* event, const QTransform& transform)
+{
+    if (m_view) {
+        const QPointF pos = transform.map(event->pos());
+        const int index = m_view->itemAt(pos);
+        if (index >= 0) {
+            bool emitItemClicked = true;
+            if (event->button() & Qt::LeftButton) {
+                if (m_view->isAboveExpansionToggle(index, pos)) {
+                    emit itemExpansionToggleClicked(index);
+                    emitItemClicked = false;
+                }
+            }
+
+            if (emitItemClicked) {
+                emit itemClicked(index, event->button());
+            }
+        }
+    }
+
+    return false;
+}
+
+bool KItemListController::mouseDoubleClickEvent(QGraphicsSceneMouseEvent* event, const QTransform& transform)
+{
+    Q_UNUSED(event);
+    Q_UNUSED(transform);
+    return false;
+}
+
+bool KItemListController::dragEnterEvent(QGraphicsSceneDragDropEvent* event, const QTransform& transform)
+{
+    Q_UNUSED(event);
+    Q_UNUSED(transform);
+    return false;
+}
+
+bool KItemListController::dragLeaveEvent(QGraphicsSceneDragDropEvent* event, const QTransform& transform)
+{
+    Q_UNUSED(event);
+    Q_UNUSED(transform);
+    return false;
+}
+
+bool KItemListController::dragMoveEvent(QGraphicsSceneDragDropEvent* event, const QTransform& transform)
+{
+    Q_UNUSED(event);
+    Q_UNUSED(transform);
+    return false;
+}
+
+bool KItemListController::dropEvent(QGraphicsSceneDragDropEvent* event, const QTransform& transform)
+{
+    Q_UNUSED(event);
+    Q_UNUSED(transform);
+    return false;
+}
+
+bool KItemListController::hoverEnterEvent(QGraphicsSceneHoverEvent* event, const QTransform& transform)
+{
+    Q_UNUSED(event);
+    Q_UNUSED(transform);
+    return false;
+}
+
+bool KItemListController::hoverMoveEvent(QGraphicsSceneHoverEvent* event, const QTransform& transform)
+{
+    Q_UNUSED(event);
+    Q_UNUSED(transform);
+    return false;
+}
+
+bool KItemListController::hoverLeaveEvent(QGraphicsSceneHoverEvent* event, const QTransform& transform)
+{
+    Q_UNUSED(event);
+    Q_UNUSED(transform);
+    return false;
+}
+
+bool KItemListController::wheelEvent(QGraphicsSceneWheelEvent* event, const QTransform& transform)
+{
+    Q_UNUSED(event);
+    Q_UNUSED(transform);
+    return false;
+}
+
+bool KItemListController::resizeEvent(QGraphicsSceneResizeEvent* event, const QTransform& transform)
+{
+    Q_UNUSED(event);
+    Q_UNUSED(transform);
+    return false;
+}
+
+bool KItemListController::processEvent(QEvent* event, const QTransform& transform)
+{
+    if (!event) {
+        return false;
+    }
+
+    switch (event->type()) {
+//  case QEvent::FocusIn:
+//  case QEvent::FocusOut:
+//      return focusEvent(static_cast<QFocusEvent*>(event));
+    case QEvent::KeyPress:
+        return keyPressEvent(static_cast<QKeyEvent*>(event));
+    case QEvent::InputMethod:
+        return inputMethodEvent(static_cast<QInputMethodEvent*>(event));
+    case QEvent::GraphicsSceneMousePress:
+        return mousePressEvent(static_cast<QGraphicsSceneMouseEvent*>(event), QTransform());
+    case QEvent::GraphicsSceneMouseMove:
+        return mouseMoveEvent(static_cast<QGraphicsSceneMouseEvent*>(event), QTransform());
+    case QEvent::GraphicsSceneMouseRelease:
+        return mouseReleaseEvent(static_cast<QGraphicsSceneMouseEvent*>(event), QTransform());
+    case QEvent::GraphicsSceneWheel:
+         return wheelEvent(static_cast<QGraphicsSceneWheelEvent*>(event), QTransform());
+    case QEvent::GraphicsSceneDragEnter:
+        return dragEnterEvent(static_cast<QGraphicsSceneDragDropEvent*>(event), QTransform());
+    case QEvent::GraphicsSceneDragLeave:
+        return dragLeaveEvent(static_cast<QGraphicsSceneDragDropEvent*>(event), QTransform());
+    case QEvent::GraphicsSceneDragMove:
+        return dragMoveEvent(static_cast<QGraphicsSceneDragDropEvent*>(event), QTransform());
+    case QEvent::GraphicsSceneDrop:
+        return dropEvent(static_cast<QGraphicsSceneDragDropEvent*>(event), QTransform());
+    case QEvent::GraphicsSceneHoverEnter:
+        return hoverEnterEvent(static_cast<QGraphicsSceneHoverEvent*>(event), QTransform());
+    case QEvent::GraphicsSceneHoverMove:
+        return hoverMoveEvent(static_cast<QGraphicsSceneHoverEvent*>(event), QTransform());
+    case QEvent::GraphicsSceneHoverLeave:
+        return hoverLeaveEvent(static_cast<QGraphicsSceneHoverEvent*>(event), QTransform());
+    case QEvent::GraphicsSceneResize:
+        return resizeEvent(static_cast<QGraphicsSceneResizeEvent*>(event), transform);
+    default:
+        break;
+    }
+
+    return false;
+}
+
+#include "kitemlistcontroller.moc"
diff --git a/src/kitemviews/kitemlistcontroller.h b/src/kitemviews/kitemlistcontroller.h
new file mode 100644 (file)
index 0000000..4407e34
--- /dev/null
@@ -0,0 +1,118 @@
+/***************************************************************************
+ *   Copyright (C) 2011 by Peter Penz <peter.penz19@gmail.com>             *
+ *                                                                         *
+ *   Based on the Itemviews NG project from Trolltech Labs:                *
+ *   http://qt.gitorious.org/qt-labs/itemviews-ng                          *
+ *                                                                         *
+ *   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 program 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 program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA            *
+ ***************************************************************************/
+
+#ifndef KITEMLISTCONTROLLER_H
+#define KITEMLISTCONTROLLER_H
+
+#include <libdolphin_export.h>
+
+#include <QObject>
+
+class KItemModelBase;
+class KItemListSelectionManager;
+class KItemListView;
+class QGraphicsSceneHoverEvent;
+class QGraphicsSceneDragDropEvent;
+class QGraphicsSceneMouseEvent;
+class QGraphicsSceneResizeEvent;
+class QGraphicsSceneWheelEvent;
+class QHideEvent;
+class QInputMethodEvent;
+class QKeyEvent;
+class QShowEvent;
+class QTransform;
+
+/**
+ * @brief Controls the view, model and selection of an item-list.
+ *
+ * For a working item-list it is mandatory to set a compatible view and model
+ * with KItemListController::setView() and KItemListController::setModel().
+ *
+ * @see KItemListView
+ * @see KItemModelBase
+ * @see KItemListSelectionManager
+ */
+class LIBDOLPHINPRIVATE_EXPORT KItemListController : public QObject
+{
+    Q_OBJECT
+    Q_ENUMS(SelectionBehavior)
+    Q_PROPERTY(KItemModelBase* model READ model WRITE setModel)
+    Q_PROPERTY(KItemListView *view READ view WRITE setView)
+    Q_PROPERTY(SelectionBehavior selectionBehavior READ selectionBehavior WRITE setSelectionBehavior)
+
+public:
+    enum SelectionBehavior {
+        NoSelection,
+        SingleSelection,
+        MultiSelection
+    };
+
+    KItemListController(QObject* parent = 0);
+    virtual ~KItemListController();
+
+    void setModel(KItemModelBase* model);
+    KItemModelBase* model() const;
+
+    void setView(KItemListView* view);
+    KItemListView* view() const;
+
+    KItemListSelectionManager* selectionManager() const;
+
+    void setSelectionBehavior(SelectionBehavior behavior);
+    SelectionBehavior selectionBehavior() const;
+
+    virtual bool showEvent(QShowEvent* event);
+    virtual bool hideEvent(QHideEvent* event);
+    virtual bool keyPressEvent(QKeyEvent* event);
+    virtual bool inputMethodEvent(QInputMethodEvent* event);
+    virtual bool mousePressEvent(QGraphicsSceneMouseEvent* event, const QTransform& transform);
+    virtual bool mouseMoveEvent(QGraphicsSceneMouseEvent* event, const QTransform& transform);
+    virtual bool mouseReleaseEvent(QGraphicsSceneMouseEvent* event, const QTransform& transform);
+    virtual bool mouseDoubleClickEvent(QGraphicsSceneMouseEvent* event, const QTransform& transform);
+    virtual bool dragEnterEvent(QGraphicsSceneDragDropEvent* event, const QTransform& transform);
+    virtual bool dragLeaveEvent(QGraphicsSceneDragDropEvent* event, const QTransform& transform);
+    virtual bool dragMoveEvent(QGraphicsSceneDragDropEvent* event, const QTransform& transform);
+    virtual bool dropEvent(QGraphicsSceneDragDropEvent* event, const QTransform& transform);
+    virtual bool hoverEnterEvent(QGraphicsSceneHoverEvent* event, const QTransform& transform);
+    virtual bool hoverMoveEvent(QGraphicsSceneHoverEvent* event, const QTransform& transform);
+    virtual bool hoverLeaveEvent(QGraphicsSceneHoverEvent* event, const QTransform& transform);
+    virtual bool wheelEvent(QGraphicsSceneWheelEvent* event, const QTransform& transform);
+    virtual bool resizeEvent(QGraphicsSceneResizeEvent* event, const QTransform& transform);
+    virtual bool processEvent(QEvent* event, const QTransform& transform);
+
+signals:
+    void itemClicked(int index, Qt::MouseButton button);
+    void itemExpansionToggleClicked(int index);
+
+    void modelChanged(KItemModelBase* current, KItemModelBase* previous);
+    void viewChanged(KItemListView* current, KItemListView* previous);
+
+private:
+    SelectionBehavior m_selectionBehavior;
+    KItemModelBase* m_model;
+    KItemListView* m_view;
+    KItemListSelectionManager* m_selectionManager;
+};
+
+#endif
+
+
diff --git a/src/kitemviews/kitemlistgroupheader.cpp b/src/kitemviews/kitemlistgroupheader.cpp
new file mode 100644 (file)
index 0000000..4db2532
--- /dev/null
@@ -0,0 +1,58 @@
+/***************************************************************************
+ *   Copyright (C) 2011 by Peter Penz <peter.penz19@gmail.com>             *
+ *                                                                         *
+ *   Based on the Itemviews NG project from Trolltech Labs:                *
+ *   http://qt.gitorious.org/qt-labs/itemviews-ng                          *
+ *                                                                         *
+ *   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 program 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 program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA            *
+ ***************************************************************************/
+
+#include "kitemlistgroupheader.h"
+
+#include "kitemlistview.h"
+
+#include <QPainter>
+
+#include <KDebug>
+
+KItemListGroupHeader::KItemListGroupHeader(QGraphicsWidget* parent) :
+    QGraphicsWidget(parent, 0)
+{
+}
+
+KItemListGroupHeader::~KItemListGroupHeader()
+{
+}
+
+QSizeF KItemListGroupHeader::sizeHint(Qt::SizeHint which, const QSizeF& constraint) const
+{
+    Q_UNUSED(which);
+    Q_UNUSED(constraint);
+    return QSizeF();
+}
+
+void KItemListGroupHeader::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget)
+{
+    Q_UNUSED(option);
+    Q_UNUSED(widget);
+    painter->setPen(Qt::darkGreen);
+    painter->setBrush(QColor(0, 255, 0, 50));
+    painter->drawRect(rect());
+
+    //painter->drawText(rect(), QString::number(m_index));
+}
+
+#include "kitemlistgroupheader.moc"
similarity index 57%
rename from src/settings/viewmodes/columnviewsettingspage.h
rename to src/kitemviews/kitemlistgroupheader.h
index 2635e71f89ef1182141fc82d29821e0761fb1c42..135fd5e5f6ae2421bcd00e60528bdac5900db9c6 100644 (file)
@@ -1,5 +1,5 @@
 /***************************************************************************
- *   Copyright (C) 2006 by Peter Penz <peter.penz19@gmail.com>             *
+ *   Copyright (C) 2011 by Peter Penz <peter.penz19@gmail.com>             *
  *                                                                         *
  *   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  *
  *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA            *
  ***************************************************************************/
 
-#ifndef COLUMNVIEWSETTINGSPAGE_H
-#define COLUMNVIEWSETTINGSPAGE_H
+#ifndef KITEMLISTGROUPHEADER_H
+#define KITEMLISTGROUPHEADER_H
 
-#include "viewsettingspagebase.h"
+#include <libdolphin_export.h>
 
-class DolphinFontRequester;
-class IconSizeGroupBox;
-class KComboBox;
+#include <QGraphicsWidget>
 
-/**
- * @brief Represents the page from the Dolphin Settings which allows
- *        to modify the settings for the details view.
- */
-class ColumnViewSettingsPage : public ViewSettingsPageBase
+class KItemListView;
+
+class LIBDOLPHINPRIVATE_EXPORT KItemListGroupHeader : public QGraphicsWidget
 {
     Q_OBJECT
 
 public:
-    ColumnViewSettingsPage(QWidget* parent);
-    virtual ~ColumnViewSettingsPage();
-
-    /**
-     * Applies the settings for the details view.
-     * The settings are persisted automatically when
-     * closing Dolphin.
-     */
-    virtual void applySettings();
-
-    /** Restores the settings to default values. */
-    virtual void restoreDefaults();
-
-private:
-    void loadSettings();
+    KItemListGroupHeader(QGraphicsWidget* parent = 0);
+    virtual ~KItemListGroupHeader();
 
-private:
-    enum
-    {
-        BaseTextWidth = 200,
-        TextInc = 50
-    };
+    void setIndex(int index);
+    int index() const;
 
-    IconSizeGroupBox* m_iconSizeGroupBox;
-    DolphinFontRequester* m_fontRequester;
-    KComboBox* m_textWidthBox;
+    virtual QSizeF sizeHint(Qt::SizeHint which = Qt::PreferredSize, const QSizeF& constraint = QSizeF()) const;
+    virtual void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget = 0);
 };
-
 #endif
+
+
diff --git a/src/kitemviews/kitemlistselectionmanager.cpp b/src/kitemviews/kitemlistselectionmanager.cpp
new file mode 100644 (file)
index 0000000..6fe9ed8
--- /dev/null
@@ -0,0 +1,87 @@
+/***************************************************************************
+ *   Copyright (C) 2011 by Peter Penz <peter.penz19@gmail.com>             *
+ *                                                                         *
+ *   Based on the Itemviews NG project from Trolltech Labs:                *
+ *   http://qt.gitorious.org/qt-labs/itemviews-ng                          *
+ *                                                                         *
+ *   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 program 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 program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA            *
+ ***************************************************************************/
+
+#include "kitemlistselectionmanager.h"
+
+#include "kitemmodelbase.h"
+
+KItemListSelectionManager::KItemListSelectionManager(QObject* parent) :
+    QObject(parent),
+    m_currentItem(-1),
+    m_anchorItem(-1),
+    m_model(0)
+{
+}
+
+KItemListSelectionManager::~KItemListSelectionManager()
+{
+}
+
+void KItemListSelectionManager::setCurrentItem(int current)
+{
+    const int previous = m_currentItem;
+    if (m_model && current < m_model->count()) {
+        m_currentItem = current;
+    } else {
+        m_currentItem = -1;
+    }
+
+    if (m_currentItem != previous) {
+        emit currentChanged(m_currentItem, previous);
+    }
+}
+
+int KItemListSelectionManager::currentItem() const
+{
+    return m_currentItem;
+}
+
+void KItemListSelectionManager::setAnchorItem(int anchor)
+{
+    const int previous = m_anchorItem;
+    if (m_model && anchor < m_model->count()) {
+        m_anchorItem = anchor;
+    } else {
+        m_anchorItem = -1;
+    }
+
+    if (m_anchorItem != previous) {
+        emit anchorChanged(m_anchorItem, previous);
+    }
+}
+
+int KItemListSelectionManager::anchorItem() const
+{
+    return m_anchorItem;
+}
+
+KItemModelBase* KItemListSelectionManager::model() const
+{
+    return m_model;
+}
+
+void KItemListSelectionManager::setModel(KItemModelBase* model)
+{
+    m_model = model;
+}
+
+#include "kitemlistselectionmanager.moc"
diff --git a/src/kitemviews/kitemlistselectionmanager.h b/src/kitemviews/kitemlistselectionmanager.h
new file mode 100644 (file)
index 0000000..5c8e846
--- /dev/null
@@ -0,0 +1,69 @@
+/***************************************************************************
+ *   Copyright (C) 2011 by Peter Penz <peter.penz19@gmail.com>             *
+ *                                                                         *
+ *   Based on the Itemviews NG project from Trolltech Labs:                *
+ *   http://qt.gitorious.org/qt-labs/itemviews-ng                          *
+ *                                                                         *
+ *   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 program 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 program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA            *
+ ***************************************************************************/
+
+#ifndef KITEMLISTSELECTIONMANAGER_H
+#define KITEMLISTSELECTIONMANAGER_H
+
+#include <libdolphin_export.h>
+
+#include <QObject>
+
+class KItemModelBase;
+
+class LIBDOLPHINPRIVATE_EXPORT KItemListSelectionManager : public QObject
+{
+    Q_OBJECT
+
+public:
+    enum SelectionMode {
+        Select,
+        Deselect,
+        Toggle
+    };
+    
+    KItemListSelectionManager(QObject* parent = 0);
+    virtual ~KItemListSelectionManager();
+
+    void setCurrentItem(int current);
+    int currentItem() const;
+
+    void setAnchorItem(int anchor);
+    int anchorItem() const;
+
+    KItemModelBase* model() const;
+
+signals:
+    void currentChanged(int current, int previous);
+    void anchorChanged(int anchor, int previous);
+
+protected:
+    void setModel(KItemModelBase* model);
+
+private:
+    int m_currentItem;
+    int m_anchorItem;
+    KItemModelBase* m_model;
+
+    friend class KItemListController;
+};
+
+#endif
diff --git a/src/kitemviews/kitemlistsizehintresolver.cpp b/src/kitemviews/kitemlistsizehintresolver.cpp
new file mode 100644 (file)
index 0000000..00eb79b
--- /dev/null
@@ -0,0 +1,86 @@
+/***************************************************************************
+ *   Copyright (C) 2011 by Peter Penz <peter.penz19@gmail.com>             *
+ *                                                                         *
+ *   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 program 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 program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA            *
+ ***************************************************************************/
+
+#include "kitemlistsizehintresolver_p.h"
+
+#include <kitemviews/kitemlistview.h>
+#include <KDebug>
+
+KItemListSizeHintResolver::KItemListSizeHintResolver(const KItemListView* itemListView) :
+    m_itemListView(itemListView),
+    m_sizeHintCache()
+{
+}
+
+KItemListSizeHintResolver::~KItemListSizeHintResolver()
+{
+}
+
+QSizeF KItemListSizeHintResolver::sizeHint(int index) const
+{
+    QSizeF size = m_sizeHintCache.at(index);
+    if (size.isEmpty()) {
+        size = m_itemListView->itemSizeHint(index);
+        m_sizeHintCache[index] = size;
+    }
+    return size;
+}
+
+void KItemListSizeHintResolver::itemsInserted(int index, int count)
+{
+    const int currentCount = m_sizeHintCache.count();
+    m_sizeHintCache.reserve(currentCount + count);
+    while (count > 0) {
+        m_sizeHintCache.insert(index, QSizeF());
+        ++index;
+        --count;
+    }
+}
+
+void KItemListSizeHintResolver::itemsRemoved(int index, int count)
+{
+    const QList<QSizeF>::iterator begin = m_sizeHintCache.begin() + index;
+    const QList<QSizeF>::iterator end = begin + count;
+    m_sizeHintCache.erase(begin, end);
+}
+
+void KItemListSizeHintResolver::itemsMoved(int from, int to, int count)
+{
+    Q_UNUSED(from);
+    Q_UNUSED(to);
+    Q_UNUSED(count);
+}
+
+void KItemListSizeHintResolver::itemsChanged(int index, int count, const QSet<QByteArray>& roles)
+{
+    Q_UNUSED(roles);
+    while (count) {
+        m_sizeHintCache[index] = QSizeF();
+        ++index;
+        --count;
+    }
+}
+
+void KItemListSizeHintResolver::clearCache()
+{
+    const int count = m_sizeHintCache.count();
+    for (int i = 0; i < count; ++i) {
+        m_sizeHintCache[i] = QSizeF();
+    }
+}
diff --git a/src/kitemviews/kitemlistsizehintresolver_p.h b/src/kitemviews/kitemlistsizehintresolver_p.h
new file mode 100644 (file)
index 0000000..f4f65ec
--- /dev/null
@@ -0,0 +1,50 @@
+/***************************************************************************
+ *   Copyright (C) 2011 by Peter Penz <peter.penz19@gmail.com>             *
+ *                                                                         *
+ *   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 program 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 program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA            *
+ ***************************************************************************/
+
+#ifndef KITEMLISTSIZEHINTRESOLVER_H
+#define KITEMLISTSIZEHINTRESOLVER_H
+
+#include <libdolphin_export.h>
+
+#include <QByteArray>
+#include <QList>
+#include <QSizeF>
+
+class KItemListView;
+
+class LIBDOLPHINPRIVATE_EXPORT KItemListSizeHintResolver
+{
+public:
+    KItemListSizeHintResolver(const KItemListView* itemListView);
+    virtual ~KItemListSizeHintResolver();
+    QSizeF sizeHint(int index) const;
+
+    void itemsInserted(int index, int count);
+    void itemsRemoved(int index, int count);
+    void itemsMoved(int from, int to, int count);
+    void itemsChanged(int index, int count, const QSet<QByteArray>& roles);
+
+    void clearCache();
+
+private:
+    const KItemListView* m_itemListView;
+    mutable QList<QSizeF> m_sizeHintCache;
+};
+
+#endif
similarity index 70%
rename from src/tests/dolphinviewtest_details.cpp
rename to src/kitemviews/kitemliststyleoption.cpp
index 0034afd90c86db9308616d1a21ee9475b0222f6e..261dfc07b956713c34996af6aaf400c8032ef198 100644 (file)
@@ -1,5 +1,5 @@
 /***************************************************************************
- *   Copyright (C) 2010 by Frank Reininghaus (frank78ac@googlemail.com)    *
+ *   Copyright (C) 2011 by Peter Penz <peter.penz19@gmail.com>             *
  *                                                                         *
  *   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  *
  *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA            *
  ***************************************************************************/
 
-#include <qtest_kde.h>
+#include "kitemliststyleoption.h"
 
-#include "dolphinviewtest_allviewmodes.h"
-
-class DolphinViewTest_Details : public DolphinViewTest_AllViewModes
+KItemListStyleOption::KItemListStyleOption() :
+    QStyleOption(QStyleOption::Version, QStyleOption::SO_CustomBase + 1)
 {
-    Q_OBJECT
-
-public:
-
-    virtual DolphinView::Mode mode() const {
-        return DolphinView::DetailsView;
-    }
-
-    virtual bool verifyCorrectViewMode(const DolphinView* view) const {
-        return (view->mode() == DolphinView::DetailsView);
-    }
+}
 
-};
-
-QTEST_KDEMAIN(DolphinViewTest_Details, GUI)
+KItemListStyleOption::KItemListStyleOption(const KItemListStyleOption& other) :
+    QStyleOption(other)
+{
+    margin = other.margin;
+    iconSize = other.iconSize;
+    font = other.font;
+}
 
-#include "dolphinviewtest_details.moc"
+KItemListStyleOption::~KItemListStyleOption()
+{
+}
similarity index 71%
rename from src/tests/dolphinviewtest_columns.cpp
rename to src/kitemviews/kitemliststyleoption.h
index 40b88a2230ddf9b86c313cb79429742c13fac00f..d181204d7e0734fa99acf9d34c07524ffff37df2 100644 (file)
@@ -1,5 +1,5 @@
 /***************************************************************************
- *   Copyright (C) 2010 by Frank Reininghaus (frank78ac@googlemail.com)    *
+ *   Copyright (C) 2011 by Peter Penz <peter.penz19@gmail.com>             *
  *                                                                         *
  *   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  *
  *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA            *
  ***************************************************************************/
 
-#include <qtest_kde.h>
+#ifndef KITEMLISTSTYLEOPTION_H
+#define KITEMLISTSTYLEOPTION_H
 
-#include "dolphinviewtest_allviewmodes.h"
+#include <libdolphin_export.h>
 
-class DolphinViewTest_Columns : public DolphinViewTest_AllViewModes
-{
-    Q_OBJECT
+#include <QFont>
+#include <QStyleOption>
 
+class LIBDOLPHINPRIVATE_EXPORT KItemListStyleOption : public QStyleOption
+{
 public:
+    KItemListStyleOption();
+    KItemListStyleOption(const KItemListStyleOption& other);
+    virtual ~KItemListStyleOption();
 
-    virtual DolphinView::Mode mode() const {
-        return DolphinView::ColumnView;
-    }
-
-    virtual bool verifyCorrectViewMode(const DolphinView* view) const {
-        return (view->mode() == DolphinView::ColumnView);
-    }
-
+    int margin;
+    int iconSize;
+    QFont font;
 };
+#endif
 
-QTEST_KDEMAIN(DolphinViewTest_Columns, GUI)
 
-#include "dolphinviewtest_columns.moc"
diff --git a/src/kitemviews/kitemlistview.cpp b/src/kitemviews/kitemlistview.cpp
new file mode 100644 (file)
index 0000000..a089742
--- /dev/null
@@ -0,0 +1,1124 @@
+/***************************************************************************
+ *   Copyright (C) 2011 by Peter Penz <peter.penz19@gmail.com>             *
+ *                                                                         *
+ *   Based on the Itemviews NG project from Trolltech Labs:                *
+ *   http://qt.gitorious.org/qt-labs/itemviews-ng                          *
+ *                                                                         *
+ *   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 program 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 program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA            *
+ ***************************************************************************/
+
+#include "kitemlistview.h"
+
+#include "kitemlistcontroller.h"
+#include "kitemlistgroupheader.h"
+#include "kitemlistselectionmanager.h"
+#include "kitemlistsizehintresolver_p.h"
+#include "kitemlistviewlayouter_p.h"
+#include "kitemlistviewanimation_p.h"
+#include "kitemlistwidget.h"
+
+#include <KDebug>
+
+#include <QGraphicsSceneMouseEvent>
+#include <QPropertyAnimation>
+#include <QStyle>
+#include <QTimer>
+
+KItemListView::KItemListView(QGraphicsWidget* parent) :
+    QGraphicsWidget(parent),
+    m_grouped(false),
+    m_activeTransactions(0),
+    m_itemSize(),
+    m_controller(0),
+    m_model(0),
+    m_visibleRoles(),
+    m_visibleRolesSizes(),
+    m_widgetCreator(0),
+    m_groupHeaderCreator(0),
+    m_styleOption(),
+    m_visibleItems(),
+    m_visibleGroups(),
+    m_sizeHintResolver(0),
+    m_layouter(0),
+    m_animation(0),
+    m_layoutTimer(0),
+    m_oldOffset(0),
+    m_oldMaximumOffset(0)
+{
+    setAcceptHoverEvents(true);
+
+    m_sizeHintResolver = new KItemListSizeHintResolver(this);
+
+    m_layouter = new KItemListViewLayouter(this);
+    m_layouter->setSizeHintResolver(m_sizeHintResolver);
+
+    m_animation = new KItemListViewAnimation(this);
+    connect(m_animation, SIGNAL(finished(QGraphicsWidget*, KItemListViewAnimation::AnimationType)),
+            this, SLOT(slotAnimationFinished(QGraphicsWidget*, KItemListViewAnimation::AnimationType)));
+
+    m_layoutTimer = new QTimer(this);
+    m_layoutTimer->setInterval(300);
+    m_layoutTimer->setSingleShot(true);
+    connect(m_layoutTimer, SIGNAL(timeout()), this, SLOT(slotLayoutTimerFinished()));
+}
+
+KItemListView::~KItemListView()
+{
+    delete m_sizeHintResolver;
+    m_sizeHintResolver = 0;
+}
+
+void KItemListView::setScrollOrientation(Qt::Orientation orientation)
+{
+    const Qt::Orientation previousOrientation = m_layouter->scrollOrientation();
+    if (orientation == previousOrientation) {
+        return;
+    }
+
+    m_layouter->setScrollOrientation(orientation);
+    m_animation->setScrollOrientation(orientation);
+    m_sizeHintResolver->clearCache();
+    updateLayout();
+    onScrollOrientationChanged(orientation, previousOrientation);
+}
+
+Qt::Orientation KItemListView::scrollOrientation() const
+{
+    return m_layouter->scrollOrientation();
+}
+
+void KItemListView::setItemSize(const QSizeF& itemSize)
+{
+    const QSizeF previousSize = m_itemSize;
+    if (itemSize == previousSize) {
+        return;
+    }
+
+    m_itemSize = itemSize;
+
+    if (!markVisibleRolesSizesAsDirty()) {
+        if (itemSize.width() < previousSize.width() || itemSize.height() < previousSize.height()) {
+            prepareLayoutForIncreasedItemCount(itemSize, ItemSize);
+        } else {
+            m_layouter->setItemSize(itemSize);
+        }
+    }
+
+    m_sizeHintResolver->clearCache();
+    updateLayout();
+    onItemSizeChanged(itemSize, previousSize);
+}
+
+QSizeF KItemListView::itemSize() const
+{
+    return m_itemSize;
+}
+
+void KItemListView::setOffset(qreal offset)
+{
+    if (offset < 0) {
+        offset = 0;
+    }
+
+    const qreal previousOffset = m_layouter->offset();
+    if (offset == previousOffset) {
+        return;
+    }
+
+    m_layouter->setOffset(offset);
+    m_animation->setOffset(offset);
+    if (!m_layoutTimer->isActive()) {
+        doLayout(NoAnimation, 0, 0);
+        update();
+    }
+    onOffsetChanged(offset, previousOffset);
+}
+
+qreal KItemListView::offset() const
+{
+    return m_layouter->offset();
+}
+
+qreal KItemListView::maximumOffset() const
+{
+    return m_layouter->maximumOffset();
+}
+
+void KItemListView::setVisibleRoles(const QHash<QByteArray, int>& roles)
+{
+    const QHash<QByteArray, int> previousRoles = m_visibleRoles;
+    m_visibleRoles = roles;
+
+    QHashIterator<int, KItemListWidget*> it(m_visibleItems);
+    while (it.hasNext()) {
+        it.next();
+        KItemListWidget* widget = it.value();
+        widget->setVisibleRoles(roles);
+        widget->setVisibleRolesSizes(m_visibleRolesSizes);
+    }
+
+    m_sizeHintResolver->clearCache();
+    m_layouter->markAsDirty();
+    onVisibleRolesChanged(roles, previousRoles);
+
+    markVisibleRolesSizesAsDirty();
+    updateLayout();
+}
+
+QHash<QByteArray, int> KItemListView::visibleRoles() const
+{
+    return m_visibleRoles;
+}
+
+KItemListController* KItemListView::controller() const
+{
+    return m_controller;
+}
+
+KItemModelBase* KItemListView::model() const
+{
+    return m_model;
+}
+
+void KItemListView::setWidgetCreator(KItemListWidgetCreatorBase* widgetCreator)
+{
+    m_widgetCreator = widgetCreator;
+}
+
+KItemListWidgetCreatorBase* KItemListView::widgetCreator() const
+{
+    return m_widgetCreator;
+}
+
+void KItemListView::setGroupHeaderCreator(KItemListGroupHeaderCreatorBase* groupHeaderCreator)
+{
+    m_groupHeaderCreator = groupHeaderCreator;
+}
+
+KItemListGroupHeaderCreatorBase* KItemListView::groupHeaderCreator() const
+{
+    return m_groupHeaderCreator;
+}
+
+void KItemListView::setStyleOption(const KItemListStyleOption& option)
+{
+    const KItemListStyleOption previousOption = m_styleOption;
+    m_styleOption = option;
+
+    QHashIterator<int, KItemListWidget*> it(m_visibleItems);
+    while (it.hasNext()) {
+        it.next();
+        it.value()->setStyleOption(option);
+    }
+
+    m_sizeHintResolver->clearCache();
+    updateLayout();
+    onStyleOptionChanged(option, previousOption);
+}
+
+const KItemListStyleOption& KItemListView::styleOption() const
+{
+    return m_styleOption;
+}
+
+void KItemListView::setGeometry(const QRectF& rect)
+{
+    QGraphicsWidget::setGeometry(rect);
+    if (!m_model) {
+        return;
+    }
+
+    if (m_itemSize.isEmpty()) {
+        m_layouter->setItemSize(QSizeF());
+    }
+
+    if (m_model->count() > 0) {
+        prepareLayoutForIncreasedItemCount(rect.size(), LayouterSize);
+    } else {
+        m_layouter->setSize(rect.size());
+    }
+
+    m_layoutTimer->start();
+}
+
+int KItemListView::itemAt(const QPointF& pos) const
+{
+    if (!m_model) {
+        return -1;
+    }
+
+    QHashIterator<int, KItemListWidget*> it(m_visibleItems);
+    while (it.hasNext()) {
+        it.next();
+
+        const KItemListWidget* widget = it.value();
+        const QPointF mappedPos = widget->mapFromItem(this, pos);
+        if (widget->contains(mappedPos)) {
+            return it.key();
+        }
+    }
+
+    return -1;
+}
+
+bool KItemListView::isAboveSelectionToggle(int index, const QPointF& pos) const
+{
+    Q_UNUSED(index);
+    Q_UNUSED(pos);
+    return false;
+}
+
+bool KItemListView::isAboveExpansionToggle(int index, const QPointF& pos) const
+{
+    const KItemListWidget* widget = m_visibleItems.value(index);
+    if (widget) {
+        const QRectF expansionToggleRect = widget->expansionToggleRect();
+        if (!expansionToggleRect.isEmpty()) {
+            const QPointF mappedPos = widget->mapFromItem(this, pos);
+            return expansionToggleRect.contains(mappedPos);
+        }
+    }
+    return false;
+}
+
+int KItemListView::firstVisibleIndex() const
+{
+    return m_layouter->firstVisibleIndex();
+}
+
+int KItemListView::lastVisibleIndex() const
+{
+    return m_layouter->lastVisibleIndex();
+}
+
+QSizeF KItemListView::itemSizeHint(int index) const
+{
+    Q_UNUSED(index);
+    return itemSize();
+}
+
+QHash<QByteArray, QSizeF> KItemListView::visibleRoleSizes() const
+{
+    return QHash<QByteArray, QSizeF>();
+}
+
+void KItemListView::beginTransaction()
+{
+    ++m_activeTransactions;
+    if (m_activeTransactions == 1) {
+        onTransactionBegin();
+    }
+}
+
+void KItemListView::endTransaction()
+{
+    --m_activeTransactions;
+    if (m_activeTransactions < 0) {
+        m_activeTransactions = 0;
+        kWarning() << "Mismatch between beginTransaction()/endTransaction()";
+    }
+
+    if (m_activeTransactions == 0) {
+        onTransactionEnd();
+        updateLayout();
+    }
+}
+
+bool KItemListView::isTransactionActive() const
+{
+    return m_activeTransactions > 0;
+}
+
+void KItemListView::initializeItemListWidget(KItemListWidget* item)
+{
+    Q_UNUSED(item);
+}
+
+void KItemListView::onControllerChanged(KItemListController* current, KItemListController* previous)
+{
+    Q_UNUSED(current);
+    Q_UNUSED(previous);
+}
+
+void KItemListView::onModelChanged(KItemModelBase* current, KItemModelBase* previous)
+{
+    Q_UNUSED(current);
+    Q_UNUSED(previous);
+}
+
+void KItemListView::onScrollOrientationChanged(Qt::Orientation current, Qt::Orientation previous)
+{
+    Q_UNUSED(current);
+    Q_UNUSED(previous);
+}
+
+void KItemListView::onItemSizeChanged(const QSizeF& current, const QSizeF& previous)
+{
+    Q_UNUSED(current);
+    Q_UNUSED(previous);
+}
+
+void KItemListView::onOffsetChanged(qreal current, qreal previous)
+{
+    Q_UNUSED(current);
+    Q_UNUSED(previous);
+}
+
+void KItemListView::onVisibleRolesChanged(const QHash<QByteArray, int>& current, const QHash<QByteArray, int>& previous)
+{
+    Q_UNUSED(current);
+    Q_UNUSED(previous);
+}
+
+void KItemListView::onStyleOptionChanged(const KItemListStyleOption& current, const KItemListStyleOption& previous)
+{
+    Q_UNUSED(current);
+    Q_UNUSED(previous);
+}
+
+void KItemListView::onTransactionBegin()
+{
+}
+
+void KItemListView::onTransactionEnd()
+{
+}
+
+bool KItemListView::event(QEvent* event)
+{
+    // Forward all events to the controller and handle them there
+    if (m_controller && m_controller->processEvent(event, transform())) {
+        event->accept();
+        return true;
+    }
+    return QGraphicsWidget::event(event);
+}
+
+void KItemListView::mousePressEvent(QGraphicsSceneMouseEvent* event)
+{
+    event->accept();
+}
+
+void KItemListView::hoverMoveEvent(QGraphicsSceneHoverEvent* event)
+{
+    if (!m_model) {
+        return;
+    }
+
+    QHashIterator<int, KItemListWidget*> it(m_visibleItems);
+    while (it.hasNext()) {
+        it.next();
+
+        KItemListWidget* widget = it.value();
+        KItemListStyleOption styleOption = widget->styleOption();
+        const QPointF mappedPos = widget->mapFromItem(this, event->pos());
+
+        const bool hovered = widget->contains(mappedPos) &&
+                             !widget->expansionToggleRect().contains(mappedPos) &&
+                             !widget->selectionToggleRect().contains(mappedPos);
+        if (hovered) {
+            if (!(styleOption.state & QStyle::State_MouseOver)) {
+                styleOption.state |= QStyle::State_MouseOver;
+                widget->setStyleOption(styleOption);
+            }
+        } else if (styleOption.state & QStyle::State_MouseOver) {
+            styleOption.state &= ~QStyle::State_MouseOver;
+            widget->setStyleOption(styleOption);
+        }
+    }
+}
+
+void KItemListView::hoverLeaveEvent(QGraphicsSceneHoverEvent* event)
+{
+    Q_UNUSED(event);
+
+    if (!m_model) {
+        return;
+    }
+
+    QHashIterator<int, KItemListWidget*> it(m_visibleItems);
+    while (it.hasNext()) {
+        it.next();
+
+        KItemListWidget* widget = it.value();
+        KItemListStyleOption styleOption = widget->styleOption();
+        if (styleOption.state & QStyle::State_MouseOver) {
+            styleOption.state &= ~QStyle::State_MouseOver;
+            widget->setStyleOption(styleOption);
+        }
+    }
+}
+
+QList<KItemListWidget*> KItemListView::visibleItemListWidgets() const
+{
+    return m_visibleItems.values();
+}
+
+void KItemListView::slotItemsInserted(const KItemRangeList& itemRanges)
+{
+    markVisibleRolesSizesAsDirty();
+
+    const bool hasMultipleRanges = (itemRanges.count() > 1);
+    if (hasMultipleRanges) {
+        beginTransaction();
+    }
+
+    foreach (const KItemRange& range, itemRanges) {
+        const int index = range.index;
+        const int count = range.count;
+        if (index < 0 || count <= 0) {
+            kWarning() << "Invalid item range (index:" << index << ", count:" << count << ")";
+            continue;
+        }
+
+        m_sizeHintResolver->itemsInserted(index, count);
+
+        // Determine which visible items must be moved
+        QList<int> itemsToMove;
+        QHashIterator<int, KItemListWidget*> it(m_visibleItems);
+        while (it.hasNext()) {
+            it.next();
+            const int visibleItemIndex = it.key();
+            if (visibleItemIndex >= index) {
+                itemsToMove.append(visibleItemIndex);
+            }
+        }
+
+        // Update the indexes of all KItemListWidget instances that are located
+        // after the inserted items. It is important to adjust the indexes in the order
+        // from the highest index to the lowest index to prevent overlaps when setting the new index.
+        qSort(itemsToMove);
+        for (int i = itemsToMove.count() - 1; i >= 0; --i) {
+            KItemListWidget* widget = m_visibleItems.value(itemsToMove[i]);
+            Q_ASSERT(widget);
+            setWidgetIndex(widget, widget->index() + count);
+        }
+
+        m_layouter->markAsDirty();
+        if (m_model->count() == count && maximumOffset() > size().height()) {
+            kDebug() << "Scrollbar required, skipping layout";
+            const int scrollBarExtent = style()->pixelMetric(QStyle::PM_ScrollBarExtent);
+            QSizeF layouterSize = m_layouter->size();
+            if (scrollOrientation() == Qt::Vertical) {
+                layouterSize.rwidth() -= scrollBarExtent;
+            } else {
+                layouterSize.rheight() -= scrollBarExtent;
+            }
+            m_layouter->setSize(layouterSize);
+        }
+
+        if (!hasMultipleRanges) {
+            doLayout(Animation, index, count);
+            update();
+        }
+
+        if (m_controller) {
+            KItemListSelectionManager* selectionManager = m_controller->selectionManager();
+            const int current = selectionManager->currentItem();
+            if (current < 0) {
+                selectionManager->setCurrentItem(0);
+            } else if (current >= index) {
+                selectionManager->setCurrentItem(current + count);
+            }
+        }
+    }
+
+    if (hasMultipleRanges) {
+        endTransaction();
+    }
+}
+
+void KItemListView::slotItemsRemoved(const KItemRangeList& itemRanges)
+{
+    markVisibleRolesSizesAsDirty();
+
+    const bool hasMultipleRanges = (itemRanges.count() > 1);
+    if (hasMultipleRanges) {
+        beginTransaction();
+    }
+
+    for (int i = itemRanges.count() - 1; i >= 0; --i) {
+        const KItemRange& range = itemRanges.at(i);
+        const int index = range.index;
+        const int count = range.count;
+        if (index < 0 || count <= 0) {
+            kWarning() << "Invalid item range (index:" << index << ", count:" << count << ")";
+            continue;
+        }
+
+        m_sizeHintResolver->itemsRemoved(index, count);
+
+        const int firstRemovedIndex = index;
+        const int lastRemovedIndex = index + count - 1;
+        const int lastIndex = m_model->count() + count - 1;
+
+        // Remove all KItemListWidget instances that got deleted
+        for (int i = firstRemovedIndex; i <= lastRemovedIndex; ++i) {
+            KItemListWidget* widget = m_visibleItems.value(i);
+            if (!widget) {
+                continue;
+            }
+
+            m_animation->stop(widget);
+            // Stopping the animation might lead to recycling the widget if
+            // it is invisible (see slotAnimationFinished()).
+            // Check again whether it is still visible:
+            if (!m_visibleItems.contains(i)) {
+                continue;
+            }
+
+            if (m_model->count() == 0) {
+                // For performance reasons no animation is done when all items have
+                // been removed.
+                recycleWidget(widget);
+            } else {
+                // Animate the removing of the items. Special case: When removing an item there
+                // is no valid model index available anymore. For the
+                // remove-animation the item gets removed from m_visibleItems but the widget
+                // will stay alive until the animation has been finished and will
+                // be recycled (deleted) in KItemListView::slotAnimationFinished().
+                m_visibleItems.remove(i);
+                widget->setIndex(-1);
+                m_animation->start(widget, KItemListViewAnimation::DeleteAnimation);
+            }
+        }
+
+        // Update the indexes of all KItemListWidget instances that are located
+        // after the deleted items
+        for (int i = lastRemovedIndex + 1; i <= lastIndex; ++i) {
+            KItemListWidget* widget = m_visibleItems.value(i);
+            if (widget) {
+                const int newIndex = i - count;
+                setWidgetIndex(widget, newIndex);
+            }
+        }
+
+        m_layouter->markAsDirty();
+        if (!hasMultipleRanges) {
+            doLayout(Animation, index, -count);
+            update();
+        }
+
+        /*KItemListSelectionManager* selectionManager = m_controller->selectionManager();
+        const int current = selectionManager->currentItem();
+        if (count() <= 0) {
+            selectionManager->setCurrentItem(-1);
+        } else if (current >= index) {
+            selectionManager->setCurrentItem(current + count);
+        }*/
+    }
+
+    if (hasMultipleRanges) {
+        endTransaction();
+    }
+}
+
+void KItemListView::slotItemsChanged(const KItemRangeList& itemRanges,
+                                     const QSet<QByteArray>& roles)
+{
+    foreach (const KItemRange& itemRange, itemRanges) {
+        const int index = itemRange.index;
+        const int count = itemRange.count;
+
+        m_sizeHintResolver->itemsChanged(index, count, roles);
+
+        const int lastIndex = index + count - 1;
+        for (int i = index; i <= lastIndex; ++i) {
+            KItemListWidget* widget = m_visibleItems.value(i);
+            if (widget) {
+                widget->setData(m_model->data(i), roles);
+            }
+        }
+    }
+}
+
+void KItemListView::slotAnimationFinished(QGraphicsWidget* widget,
+                                          KItemListViewAnimation::AnimationType type)
+{
+    KItemListWidget* itemListWidget = qobject_cast<KItemListWidget*>(widget);
+    Q_ASSERT(itemListWidget);
+
+    switch (type) {
+    case KItemListViewAnimation::DeleteAnimation: {
+        // As we recycle the widget in this case it is important to assure that no
+        // other animation has been started. This is a convention in KItemListView and
+        // not a requirement defined by KItemListViewAnimation.
+        Q_ASSERT(!m_animation->isStarted(itemListWidget));
+
+        // All KItemListWidgets that are animated by the DeleteAnimation are not maintained
+        // by m_visibleWidgets and must be deleted manually after the animation has
+        // been finished.
+        KItemListGroupHeader* header = m_visibleGroups.value(itemListWidget);
+        if (header) {
+            m_groupHeaderCreator->recycle(header);
+            m_visibleGroups.remove(itemListWidget);
+        }
+        m_widgetCreator->recycle(itemListWidget);
+        break;
+    }
+
+    case KItemListViewAnimation::CreateAnimation:
+    case KItemListViewAnimation::MovingAnimation:
+    case KItemListViewAnimation::ResizeAnimation: {
+        const int index = itemListWidget->index();
+        const bool invisible = (index < m_layouter->firstVisibleIndex()) ||
+                               (index > m_layouter->lastVisibleIndex());
+        if (invisible && !m_animation->isStarted(itemListWidget)) {
+            recycleWidget(itemListWidget);
+        }
+        break;
+    }
+
+    default: break;
+    }
+}
+
+void KItemListView::slotLayoutTimerFinished()
+{
+    m_layouter->setSize(geometry().size());
+    doLayout(Animation, 0, 0);
+}
+
+void KItemListView::setController(KItemListController* controller)
+{
+    if (m_controller != controller) {
+        KItemListController* previous = m_controller;
+        m_controller = controller;
+        onControllerChanged(controller, previous);
+    }
+}
+
+void KItemListView::setModel(KItemModelBase* model)
+{
+    if (m_model == model) {
+        return;
+    }
+
+    KItemModelBase* previous = m_model;
+
+    if (m_model) {
+        disconnect(m_model, SIGNAL(itemsChanged(KItemRangeList,QSet<QByteArray>)),
+                   this,    SLOT(slotItemsChanged(KItemRangeList,QSet<QByteArray>)));
+        disconnect(m_model, SIGNAL(itemsInserted(KItemRangeList)),
+                   this,    SLOT(slotItemsInserted(KItemRangeList)));
+        disconnect(m_model, SIGNAL(itemsRemoved(KItemRangeList)),
+                   this,    SLOT(slotItemsRemoved(KItemRangeList)));
+    }
+
+    m_model = model;
+    m_layouter->setModel(model);
+    m_grouped = !model->groupRole().isEmpty();
+
+    if (m_model) {
+        connect(m_model, SIGNAL(itemsChanged(KItemRangeList,QSet<QByteArray>)),
+                this,    SLOT(slotItemsChanged(KItemRangeList,QSet<QByteArray>)));
+        connect(m_model, SIGNAL(itemsInserted(KItemRangeList)),
+                this,    SLOT(slotItemsInserted(KItemRangeList)));
+        connect(m_model, SIGNAL(itemsRemoved(KItemRangeList)),
+                this,    SLOT(slotItemsRemoved(KItemRangeList)));
+    }
+
+    onModelChanged(model, previous);
+}
+
+void KItemListView::updateLayout()
+{
+    doLayout(Animation, 0, 0);
+    update();
+}
+
+void KItemListView::doLayout(LayoutAnimationHint hint, int changedIndex, int changedCount)
+{
+    if (m_layoutTimer->isActive()) {
+        kDebug() << "Stopping layout timer, synchronous layout requested";
+        m_layoutTimer->stop();
+    }
+
+    if (m_model->count() < 0 || m_activeTransactions > 0) {
+        return;
+    }
+
+    applyDynamicItemSize();
+
+    const int firstVisibleIndex = m_layouter->firstVisibleIndex();
+    const int lastVisibleIndex = m_layouter->lastVisibleIndex();
+    if (firstVisibleIndex < 0) {
+        emitOffsetChanges();
+        return;
+    }
+
+    // Do a sanity check of the offset-property: When properties of the itemlist-view have been changed
+    // it might be possible that the maximum offset got changed too. Assure that the full visible range
+    // is still shown if the maximum offset got decreased.
+    const qreal visibleOffsetRange = (scrollOrientation() == Qt::Horizontal) ? size().width() : size().height();
+    const qreal maxOffsetToShowFullRange = maximumOffset() - visibleOffsetRange;
+    if (offset() > maxOffsetToShowFullRange) {
+        m_layouter->setOffset(qMax(qreal(0), maxOffsetToShowFullRange));
+    }
+
+    // Determine all items that are completely invisible and might be
+    // reused for items that just got (at least partly) visible.
+    // Items that do e.g. an animated moving of their position are not
+    // marked as invisible: This assures that a scrolling inside the view
+    // can be done without breaking an animation.
+    QList<int> reusableItems;
+    QHashIterator<int, KItemListWidget*> it(m_visibleItems);
+    while (it.hasNext()) {
+        it.next();
+        KItemListWidget* widget = it.value();
+        const int index = widget->index();
+        const bool invisible = (index < firstVisibleIndex) || (index > lastVisibleIndex);
+        if (invisible && !m_animation->isStarted(widget)) {
+            widget->setVisible(false);
+            reusableItems.append(index);
+        }
+    }
+
+    // Assure that for each visible item a KItemListWidget is available. KItemListWidget
+    // instances from invisible items are reused. If no reusable items are
+    // found then new KItemListWidget instances get created.
+    const bool animate = (hint == Animation);
+    for (int i = firstVisibleIndex; i <= lastVisibleIndex; ++i) {
+        bool applyNewPos = true;
+        bool wasHidden = false;
+
+        const QRectF itemBounds = m_layouter->itemBoundingRect(i);
+        const QPointF newPos = itemBounds.topLeft();
+        KItemListWidget* widget = m_visibleItems.value(i);
+        if (!widget) {
+            wasHidden = true;
+            if (!reusableItems.isEmpty()) {
+                // Reuse a KItemListWidget instance from an invisible item
+                const int oldIndex = reusableItems.takeLast();
+                widget = m_visibleItems.value(oldIndex);
+                setWidgetIndex(widget, i);
+            } else {
+                // No reusable KItemListWidget instance is available, create a new one
+                widget = createWidget(i);
+            }
+            widget->resize(itemBounds.size());
+
+            if (animate && changedCount < 0) {
+                // Items have been deleted, move the created item to the
+                // imaginary old position.
+                const QRectF itemBoundingRect = m_layouter->itemBoundingRect(i - changedCount);
+                if (itemBoundingRect.isEmpty()) {
+                    const QPointF invisibleOldPos = (scrollOrientation() == Qt::Vertical)
+                                                    ? QPointF(0, size().height()) : QPointF(size().width(), 0);
+                    widget->setPos(invisibleOldPos);
+                } else {
+                    widget->setPos(itemBoundingRect.topLeft());
+                }
+                applyNewPos = false;
+            }
+        } else if (m_animation->isStarted(widget, KItemListViewAnimation::MovingAnimation)) {
+            applyNewPos = false;
+        }
+
+        if (animate) {
+            const bool itemsRemoved = (changedCount < 0);
+            const bool itemsInserted = (changedCount > 0);
+
+            if (itemsRemoved && (i >= changedIndex + changedCount + 1)) {
+                // The item is located after the removed items. Animate the moving of the position.
+                m_animation->start(widget, KItemListViewAnimation::MovingAnimation, newPos);
+                applyNewPos = false;
+            } else if (itemsInserted && i >= changedIndex) {
+                // The item is located after the first inserted item
+                if (i <= changedIndex + changedCount - 1) {
+                    // The item is an inserted item. Animate the appearing of the item.
+                    // For performance reasons no animation is done when changedCount is equal
+                    // to all available items.
+                    if (changedCount < m_model->count()) {
+                        m_animation->start(widget, KItemListViewAnimation::CreateAnimation);
+                    }
+                } else if (!m_animation->isStarted(widget, KItemListViewAnimation::CreateAnimation)) {
+                    // The item was already there before, so animate the moving of the position.
+                    // No moving animation is done if the item is animated by a create animation: This
+                    // prevents a "move animation mess" when inserting several ranges in parallel.
+                    m_animation->start(widget, KItemListViewAnimation::MovingAnimation, newPos);
+                    applyNewPos = false;
+                }
+            } else if (!itemsRemoved && !itemsInserted && !wasHidden) {
+                // The size of the view might have been changed. Animate the moving of the position.
+                m_animation->start(widget, KItemListViewAnimation::MovingAnimation, newPos);
+                applyNewPos = false;
+            }
+        }
+
+        if (applyNewPos) {
+            widget->setPos(newPos);
+        }
+
+        Q_ASSERT(widget->index() == i);
+        widget->setVisible(true);
+
+        if (widget->size() != itemBounds.size()) {
+            m_animation->start(widget, KItemListViewAnimation::ResizeAnimation, itemBounds.size());
+        }
+    }
+
+    // Delete invisible KItemListWidget instances that have not been reused
+    foreach (int index, reusableItems) {
+        recycleWidget(m_visibleItems.value(index));
+    }
+
+    emitOffsetChanges();
+}
+
+void KItemListView::emitOffsetChanges()
+{
+    const int newOffset = m_layouter->offset();
+    if (m_oldOffset != newOffset) {
+        emit offsetChanged(newOffset, m_oldOffset);
+        m_oldOffset = newOffset;
+    }
+
+    const int newMaximumOffset = m_layouter->maximumOffset();
+    if (m_oldMaximumOffset != newMaximumOffset) {
+        emit maximumOffsetChanged(newMaximumOffset, m_oldMaximumOffset);
+        m_oldMaximumOffset = newMaximumOffset;
+    }
+}
+
+KItemListWidget* KItemListView::createWidget(int index)
+{
+    KItemListWidget* widget = m_widgetCreator->create(this);
+    widget->setVisibleRoles(m_visibleRoles);
+    widget->setVisibleRolesSizes(m_visibleRolesSizes);
+    widget->setStyleOption(m_styleOption);
+    widget->setIndex(index);
+    widget->setData(m_model->data(index));
+    m_visibleItems.insert(index, widget);
+
+    if (m_grouped) {
+        if (m_layouter->isFirstGroupItem(index)) {
+            KItemListGroupHeader* header = m_groupHeaderCreator->create(widget);
+            header->setPos(0, -50);
+            header->resize(50, 50);
+            m_visibleGroups.insert(widget, header);
+        }
+    }
+
+    initializeItemListWidget(widget);
+    return widget;
+}
+
+void KItemListView::recycleWidget(KItemListWidget* widget)
+{
+    if (m_grouped) {
+        KItemListGroupHeader* header = m_visibleGroups.value(widget);
+        if (header) {
+            m_groupHeaderCreator->recycle(header);
+            m_visibleGroups.remove(widget);
+        }
+    }
+
+    m_visibleItems.remove(widget->index());
+    m_widgetCreator->recycle(widget);
+}
+
+void KItemListView::setWidgetIndex(KItemListWidget* widget, int index)
+{
+    if (m_grouped) {
+        bool createHeader = m_layouter->isFirstGroupItem(index);
+        KItemListGroupHeader* header = m_visibleGroups.value(widget);
+        if (header) {
+            if (createHeader) {
+                createHeader = false;
+            } else {
+                m_groupHeaderCreator->recycle(header);
+                m_visibleGroups.remove(widget);
+            }
+        }
+
+        if (createHeader) {
+            KItemListGroupHeader* header = m_groupHeaderCreator->create(widget);
+            header->setPos(0, -50);
+            header->resize(50, 50);
+            m_visibleGroups.insert(widget, header);
+        }
+    }
+
+    const int oldIndex = widget->index();
+    m_visibleItems.remove(oldIndex);
+    widget->setVisibleRoles(m_visibleRoles);
+    widget->setVisibleRolesSizes(m_visibleRolesSizes);
+    widget->setStyleOption(m_styleOption);
+    widget->setIndex(index);
+    widget->setData(m_model->data(index));
+    m_visibleItems.insert(index, widget);
+
+    initializeItemListWidget(widget);
+}
+
+void KItemListView::prepareLayoutForIncreasedItemCount(const QSizeF& size, SizeType sizeType)
+{
+    // Calculate the first visible index and last visible index for the current size
+    const int currentFirst = m_layouter->firstVisibleIndex();
+    const int currentLast = m_layouter->lastVisibleIndex();
+
+    const QSizeF currentSize = (sizeType == LayouterSize) ? m_layouter->size() : m_layouter->itemSize();
+
+    // Calculate the first visible index and last visible index for the new size
+    setLayouterSize(size, sizeType);
+    const int newFirst = m_layouter->firstVisibleIndex();
+    const int newLast = m_layouter->lastVisibleIndex();
+
+    if ((currentFirst != newFirst) || (currentLast != newLast)) {
+        // At least one index has been changed. Assure that widgets for all possible
+        // visible items get created so that a move-animation can be started later.
+        const int maxVisibleItems = m_layouter->maximumVisibleItems();
+        int minFirst = qMin(newFirst, currentFirst);
+        const int maxLast = qMax(newLast, currentLast);
+
+        if (maxLast - minFirst + 1 < maxVisibleItems) {
+            // Increasing the size might result in a smaller KItemListView::offset().
+            // Decrease the first visible index in a way that at least the maximum
+            // visible items are shown.
+            minFirst = qMax(0, maxLast - maxVisibleItems + 1);
+        }
+
+        if (maxLast - minFirst > maxVisibleItems  + maxVisibleItems / 2) {
+            // The creating of widgets is quite expensive. Assure that never more
+            // than 50 % of the maximum visible items get created for the animations.
+            return;
+        }
+
+        setLayouterSize(currentSize, sizeType);
+        for (int i = minFirst; i <= maxLast; ++i) {
+            if (!m_visibleItems.contains(i)) {
+                KItemListWidget* widget = createWidget(i);
+                const QPointF pos = m_layouter->itemBoundingRect(i).topLeft();
+                widget->setPos(pos);
+            }
+        }
+        setLayouterSize(size, sizeType);
+    }
+}
+
+void KItemListView::setLayouterSize(const QSizeF& size, SizeType sizeType)
+{
+    switch (sizeType) {
+    case LayouterSize: m_layouter->setSize(size); break;
+    case ItemSize: m_layouter->setItemSize(size); break;
+    default: break;
+    }
+}
+
+bool KItemListView::markVisibleRolesSizesAsDirty()
+{
+    const bool dirty = m_itemSize.isEmpty();
+    if (dirty) {
+        m_visibleRolesSizes.clear();
+        m_layouter->setItemSize(QSizeF());
+    }
+    return dirty;
+}
+
+void KItemListView::applyDynamicItemSize()
+{
+    if (!m_itemSize.isEmpty()) {
+        return;
+    }
+
+    if (m_visibleRolesSizes.isEmpty()) {
+        m_visibleRolesSizes = visibleRoleSizes();
+        foreach (KItemListWidget* widget, visibleItemListWidgets()) {
+            widget->setVisibleRolesSizes(m_visibleRolesSizes);
+        }
+    }
+
+    if (m_layouter->itemSize().isEmpty()) {
+        qreal requiredWidth = 0;
+        qreal requiredHeight = 0;
+
+        QHashIterator<QByteArray, QSizeF> it(m_visibleRolesSizes);
+        while (it.hasNext()) {
+            it.next();
+            const QSizeF& visibleRoleSize = it.value();
+            requiredWidth  += visibleRoleSize.width();
+            requiredHeight += visibleRoleSize.height();
+        }
+
+        QSizeF dynamicItemSize = m_itemSize;
+        if (dynamicItemSize.width() <= 0) {
+            dynamicItemSize.setWidth(qMax(requiredWidth, size().width()));
+        }
+        if (dynamicItemSize.height() <= 0) {
+            dynamicItemSize.setHeight(qMax(requiredHeight, size().height()));
+        }
+
+        m_layouter->setItemSize(dynamicItemSize);
+    }
+}
+
+KItemListCreatorBase::~KItemListCreatorBase()
+{
+    qDeleteAll(m_recycleableWidgets);
+    qDeleteAll(m_createdWidgets);
+}
+
+void KItemListCreatorBase::addCreatedWidget(QGraphicsWidget* widget)
+{
+    m_createdWidgets.insert(widget);
+}
+
+void KItemListCreatorBase::pushRecycleableWidget(QGraphicsWidget* widget)
+{
+    Q_ASSERT(m_createdWidgets.contains(widget));
+    m_createdWidgets.remove(widget);
+
+    if (m_recycleableWidgets.count() < 100) {
+        m_recycleableWidgets.append(widget);
+        widget->setVisible(false);
+    } else {
+        delete widget;
+    }
+}
+
+QGraphicsWidget* KItemListCreatorBase::popRecycleableWidget()
+{
+    if (m_recycleableWidgets.isEmpty()) {
+        return 0;
+    }
+
+    QGraphicsWidget* widget = m_recycleableWidgets.takeLast();
+    m_createdWidgets.insert(widget);
+    return widget;
+}
+
+KItemListWidgetCreatorBase::~KItemListWidgetCreatorBase()
+{
+}
+
+void KItemListWidgetCreatorBase::recycle(KItemListWidget* widget)
+{
+    widget->setOpacity(1.0);
+    pushRecycleableWidget(widget);
+}
+
+KItemListGroupHeaderCreatorBase::~KItemListGroupHeaderCreatorBase()
+{
+}
+
+void KItemListGroupHeaderCreatorBase::recycle(KItemListGroupHeader* header)
+{
+    header->setOpacity(1.0);
+    pushRecycleableWidget(header);
+}
+
+#include "kitemlistview.moc"
diff --git a/src/kitemviews/kitemlistview.h b/src/kitemviews/kitemlistview.h
new file mode 100644 (file)
index 0000000..829736a
--- /dev/null
@@ -0,0 +1,360 @@
+/***************************************************************************
+ *   Copyright (C) 2011 by Peter Penz <peter.penz19@gmail.com>             *
+ *                                                                         *
+ *   Based on the Itemviews NG project from Trolltech Labs:                *
+ *   http://qt.gitorious.org/qt-labs/itemviews-ng                          *
+ *                                                                         *
+ *   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 program 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 program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA            *
+ ***************************************************************************/
+
+#ifndef KITEMLISTVIEW_H
+#define KITEMLISTVIEW_H
+
+#include <libdolphin_export.h>
+
+#include <kitemviews/kitemliststyleoption.h>
+#include <kitemviews/kitemlistviewanimation_p.h>
+#include <kitemviews/kitemlistwidget.h>
+#include <kitemviews/kitemmodelbase.h>
+#include <QGraphicsWidget>
+
+class KItemListController;
+class KItemListWidgetCreatorBase;
+class KItemListGroupHeader;
+class KItemListGroupHeaderCreatorBase;
+class KItemListSizeHintResolver;
+class KItemListViewAnimation;
+class KItemListViewLayouter;
+class KItemListWidget;
+class KItemListViewCreatorBase;
+class QTimer;
+
+/**
+ * @brief Represents the view of an item-list.
+ *
+ * The view is responsible for showing the items of the model within
+ * a GraphicsItem. Each visible item is represented by a KItemListWidget.
+ *
+ * The created view must be applied to the KItemListController with
+ * KItemListController::setView(). For showing a custom model it is not
+ * mandatory to derive from KItemListView, all that is necessary is
+ * to set a widget-creator that is capable to create KItemListWidgets
+ * showing the model items. A widget-creator can be set with
+ * KItemListView::setWidgetCreator().
+ *
+ * @see KItemListWidget
+ * @see KItemModelBase
+ */
+class LIBDOLPHINPRIVATE_EXPORT KItemListView : public QGraphicsWidget
+{
+    Q_OBJECT
+
+public:
+    KItemListView(QGraphicsWidget* parent = 0);
+    virtual ~KItemListView();
+
+    void setScrollOrientation(Qt::Orientation orientation);
+    Qt::Orientation scrollOrientation() const;
+
+    void setItemSize(const QSizeF& size);
+    QSizeF itemSize() const;
+
+    // TODO: add note that offset is not checked against maximumOffset, only against 0.
+    void setOffset(qreal offset);
+    qreal offset() const;
+
+    qreal maximumOffset() const;
+
+    /**
+     * Sets the visible roles to \p roles. The integer-value defines
+     * the order of the visible role: Smaller values are ordered first.
+     */
+    void setVisibleRoles(const QHash<QByteArray, int>& roles);
+    QHash<QByteArray, int> visibleRoles() const;
+
+    /**
+     * @return Controller of the item-list. The controller gets
+     *         initialized by KItemListController::setView() and will
+     *         result in calling KItemListController::onControllerChanged().
+     */
+    KItemListController* controller() const;
+
+    /**
+     * @return Model of the item-list. The model gets
+     *         initialized by KItemListController::setView() and will
+     *         result in calling KItemListController::onModelChanged().
+     */
+    KItemModelBase* model() const;
+
+    /**
+     * Sets the creator that creates a widget showing the
+     * content of one model-item. Usually it is sufficient
+     * to implement a custom widget X derived from KItemListWidget and
+     * set the creator by:
+     * <code>
+     * itemListView->setWidgetCreator(new KItemListWidgetCreator<X>());
+     * </code>
+     * Note that the ownership of the widget creator is not transferred to
+     * the item-list view: One instance of a widget creator might get shared
+     * by several item-list view instances.
+     **/
+    void setWidgetCreator(KItemListWidgetCreatorBase* widgetCreator);
+    KItemListWidgetCreatorBase* widgetCreator() const;
+
+    void setGroupHeaderCreator(KItemListGroupHeaderCreatorBase* groupHeaderCreator);
+    KItemListGroupHeaderCreatorBase* groupHeaderCreator() const;
+
+    void setStyleOption(const KItemListStyleOption& option);
+    const KItemListStyleOption& styleOption() const;
+
+    virtual void setGeometry(const QRectF& rect);
+
+    int itemAt(const QPointF& pos) const;
+    bool isAboveSelectionToggle(int index, const QPointF& pos) const;
+    bool isAboveExpansionToggle(int index, const QPointF& pos) const;
+
+    int firstVisibleIndex() const;
+    int lastVisibleIndex() const;
+
+    virtual QSizeF itemSizeHint(int index) const;
+    virtual QHash<QByteArray, QSizeF> visibleRoleSizes() const;
+
+    void beginTransaction();
+    void endTransaction();
+    bool isTransactionActive() const;
+
+signals:
+    void offsetChanged(int current, int previous);
+    void maximumOffsetChanged(int current, int previous);
+
+protected:
+    virtual void initializeItemListWidget(KItemListWidget* item);
+
+    virtual void onControllerChanged(KItemListController* current, KItemListController* previous);
+    virtual void onModelChanged(KItemModelBase* current, KItemModelBase* previous);
+
+    virtual void onScrollOrientationChanged(Qt::Orientation current, Qt::Orientation previous);
+    virtual void onItemSizeChanged(const QSizeF& current, const QSizeF& previous);
+    virtual void onOffsetChanged(qreal current, qreal previous);
+    virtual void onVisibleRolesChanged(const QHash<QByteArray, int>& current, const QHash<QByteArray, int>& previous);
+    virtual void onStyleOptionChanged(const KItemListStyleOption& current, const KItemListStyleOption& previous);
+
+    virtual void onTransactionBegin();
+    virtual void onTransactionEnd();
+
+    virtual bool event(QEvent* event);
+    virtual void mousePressEvent(QGraphicsSceneMouseEvent* event);
+    virtual void hoverMoveEvent(QGraphicsSceneHoverEvent* event);
+    virtual void hoverLeaveEvent(QGraphicsSceneHoverEvent* event);
+
+    QList<KItemListWidget*> visibleItemListWidgets() const;
+
+protected slots:
+    virtual void slotItemsInserted(const KItemRangeList& itemRanges);
+    virtual void slotItemsRemoved(const KItemRangeList& itemRanges);
+    virtual void slotItemsChanged(const KItemRangeList& itemRanges,
+                                  const QSet<QByteArray>& roles);
+
+private slots:
+    void slotAnimationFinished(QGraphicsWidget* widget,
+                               KItemListViewAnimation::AnimationType type);
+    void slotLayoutTimerFinished();
+
+private:
+    enum LayoutAnimationHint
+    {
+        NoAnimation,
+        Animation
+    };
+
+    enum SizeType
+    {
+        LayouterSize,
+        ItemSize
+    };
+
+    void setController(KItemListController* controller);
+    void setModel(KItemModelBase* model);
+
+    void updateLayout();
+    void doLayout(LayoutAnimationHint hint, int changedIndex, int changedCount);
+    void doGroupHeadersLayout(LayoutAnimationHint hint, int changedIndex, int changedCount);
+    void emitOffsetChanges();
+
+    KItemListWidget* createWidget(int index);
+    void recycleWidget(KItemListWidget* widget);
+    void setWidgetIndex(KItemListWidget* widget, int index);
+
+    /**
+     * Helper method for setGeometry() and setItemSize(): Calling both methods might result
+     * in a changed number of visible items. To assure that currently invisible items can
+     * get animated from the old position to the new position prepareLayoutForIncreasedItemCount()
+     * takes care to create all item widgets that are visible with the old or the new size.
+     * @param size     Size of the layouter or the item dependent on \p sizeType.
+     * @param sizeType LayouterSize: KItemListLayouter::setSize() is used.
+     *                 ItemSize: KItemListLayouter::setItemSize() is used.
+     */
+    void prepareLayoutForIncreasedItemCount(const QSizeF& size, SizeType sizeType);
+
+    /**
+     * Helper method for prepareLayoutForIncreasedItemCount().
+     */
+    void setLayouterSize(const QSizeF& size, SizeType sizeType);
+
+    /**
+     * Marks the visible roles as dirty so that they will get updated when doing the next
+     * layout. The visible roles will only get marked as dirty if an empty item-size is
+     * given.
+     * @return True if the visible roles have been marked as dirty.
+     */
+    bool markVisibleRolesSizesAsDirty();
+
+    /**
+     * Updates the m_visibleRoleSizes property and applies the dynamic
+     * size to the layouter.
+     */
+    void applyDynamicItemSize();
+
+private:
+    bool m_grouped;
+    int m_activeTransactions; // Counter for beginTransaction()/endTransaction()
+
+    QSizeF m_itemSize;
+    KItemListController* m_controller;
+    KItemModelBase* m_model;
+    QHash<QByteArray, int> m_visibleRoles;
+    QHash<QByteArray, QSizeF> m_visibleRolesSizes;
+    KItemListWidgetCreatorBase* m_widgetCreator;
+    KItemListGroupHeaderCreatorBase* m_groupHeaderCreator;
+    KItemListStyleOption m_styleOption;
+
+    QHash<int, KItemListWidget*> m_visibleItems;
+    QHash<KItemListWidget*, KItemListGroupHeader*> m_visibleGroups;
+
+    int m_scrollBarExtent;
+    KItemListSizeHintResolver* m_sizeHintResolver;
+    KItemListViewLayouter* m_layouter;
+    KItemListViewAnimation* m_animation;
+
+    QTimer* m_layoutTimer; // Triggers an asynchronous doLayout() call.
+    int m_oldOffset;
+    int m_oldMaximumOffset;
+
+    friend class KItemListController;
+};
+
+/**
+ * Allows to do a fast logical creation and deletion of QGraphicsWidgets
+ * by recycling existing QGraphicsWidgets instances. Is used by
+ * KItemListWidgetCreatorBase and KItemListGroupHeaderCreatorBase.
+ * @internal
+ */
+class LIBDOLPHINPRIVATE_EXPORT KItemListCreatorBase
+{
+public:
+    virtual ~KItemListCreatorBase();
+
+protected:
+    void addCreatedWidget(QGraphicsWidget* widget);
+    void pushRecycleableWidget(QGraphicsWidget* widget);
+    QGraphicsWidget* popRecycleableWidget();
+
+private:
+    QSet<QGraphicsWidget*> m_createdWidgets;
+    QList<QGraphicsWidget*> m_recycleableWidgets;
+};
+
+/**
+ * @brief Base class for creating KItemListWidgets.
+ *
+ * It is recommended that applications simply use the KItemListWidgetCreator-template class.
+ * For a custom implementation the methods create() and recyle() must be reimplemented.
+ * The intention of the widget creator is to prevent repetitive and expensive instantiations and
+ * deletions of KItemListWidgets by recycling existing widget instances.
+ */
+class LIBDOLPHINPRIVATE_EXPORT KItemListWidgetCreatorBase : public KItemListCreatorBase
+{
+public:
+    virtual ~KItemListWidgetCreatorBase();
+    virtual KItemListWidget* create(KItemListView* view) = 0;
+    virtual void recycle(KItemListWidget* widget);
+};
+
+template <class T>
+class LIBDOLPHINPRIVATE_EXPORT KItemListWidgetCreator : public KItemListWidgetCreatorBase
+{
+public:
+    virtual ~KItemListWidgetCreator();
+    virtual KItemListWidget* create(KItemListView* view);
+};
+
+template <class T>
+KItemListWidgetCreator<T>::~KItemListWidgetCreator()
+{
+}
+
+template <class T>
+KItemListWidget* KItemListWidgetCreator<T>::create(KItemListView* view)
+{
+    KItemListWidget* widget = static_cast<KItemListWidget*>(popRecycleableWidget());
+    if (!widget) {
+        widget = new T(view);
+        addCreatedWidget(widget);
+    }
+    return widget;
+}
+
+/**
+ * @brief Base class for creating KItemListGroupHeaders.
+ *
+ * It is recommended that applications simply use the KItemListGroupHeaderCreator-template class.
+ * For a custom implementation the methods create() and recyle() must be reimplemented.
+ * The intention of the group-header creator is to prevent repetitive and expensive instantiations and
+ * deletions of KItemListGroupHeaders by recycling existing header instances.
+ */
+class LIBDOLPHINPRIVATE_EXPORT KItemListGroupHeaderCreatorBase : public KItemListCreatorBase
+{
+public:
+    virtual ~KItemListGroupHeaderCreatorBase();
+    virtual KItemListGroupHeader* create(QGraphicsWidget* parent) = 0;
+    virtual void recycle(KItemListGroupHeader* header);
+};
+
+template <class T>
+class LIBDOLPHINPRIVATE_EXPORT KItemListGroupHeaderCreator : public KItemListGroupHeaderCreatorBase
+{
+public:
+    virtual ~KItemListGroupHeaderCreator();
+    virtual KItemListGroupHeader* create(QGraphicsWidget* parent);
+};
+
+template <class T>
+KItemListGroupHeaderCreator<T>::~KItemListGroupHeaderCreator()
+{
+}
+
+template <class T>
+KItemListGroupHeader* KItemListGroupHeaderCreator<T>::create(QGraphicsWidget* parent)
+{
+    KItemListGroupHeader* widget = static_cast<KItemListGroupHeader*>(popRecycleableWidget());
+    if (!widget) {
+        widget = new T(parent);
+        addCreatedWidget(widget);
+    }
+    return widget;
+}
+
+#endif
diff --git a/src/kitemviews/kitemlistviewanimation.cpp b/src/kitemviews/kitemlistviewanimation.cpp
new file mode 100644 (file)
index 0000000..449d557
--- /dev/null
@@ -0,0 +1,241 @@
+/***************************************************************************
+ *   Copyright (C) 2011 by Peter Penz <peter.penz19@gmail.com>             *
+ *                                                                         *
+ *   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 program 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 program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA            *
+ ***************************************************************************/
+
+#include "kitemlistviewanimation_p.h"
+
+#include "kitemlistview.h"
+
+#include <KDebug>
+
+#include <QGraphicsWidget>
+#include <QPropertyAnimation>
+
+KItemListViewAnimation::KItemListViewAnimation(QObject* parent) :
+    QObject(parent),
+    m_scrollOrientation(Qt::Vertical),
+    m_offset(0),
+    m_animation()
+{
+}
+
+KItemListViewAnimation::~KItemListViewAnimation()
+{
+    for (int type = 0; type < AnimationTypeCount; ++type) {
+        qDeleteAll(m_animation[type]);
+    }
+}
+
+void KItemListViewAnimation::setScrollOrientation(Qt::Orientation orientation)
+{
+    m_scrollOrientation = orientation;
+}
+
+Qt::Orientation KItemListViewAnimation::scrollOrientation() const
+{
+    return m_scrollOrientation;
+}
+
+void KItemListViewAnimation::setOffset(qreal offset)
+{
+    const qreal diff = m_offset - offset;
+    m_offset = offset;
+
+    // The change of the offset requires that the position of all
+    // animated QGraphicsWidgets get adjusted. An exception is made
+    // for the delete animation that should just fade away on the
+    // existing position.
+    for (int type = 0; type < AnimationTypeCount; ++type) {
+        if (type == DeleteAnimation) {
+            continue;
+        }
+
+        QHashIterator<QGraphicsWidget*, QPropertyAnimation*>  it(m_animation[type]);
+        while (it.hasNext()) {
+            it.next();
+
+            QGraphicsWidget* widget = it.key();
+            QPropertyAnimation* propertyAnim = it.value();
+
+            QPointF currentPos = widget->pos();
+            if (m_scrollOrientation == Qt::Vertical) {
+                currentPos.ry() += diff;
+            } else {
+                currentPos.rx() += diff;
+            }
+
+            if (type == MovingAnimation) {
+                // Stop the animation, calculate the moved start- and end-value
+                // and restart the animation for the remaining duration.
+                const int remainingDuration = propertyAnim->duration()
+                                              - propertyAnim->currentTime();
+
+                const bool block = propertyAnim->signalsBlocked();
+                propertyAnim->blockSignals(true);
+                propertyAnim->stop();
+
+                QPointF endPos = propertyAnim->endValue().toPointF();
+                if (m_scrollOrientation == Qt::Vertical) {
+                    endPos.ry() += diff;
+                } else {
+                    endPos.rx() += diff;
+                }
+
+                propertyAnim->setDuration(remainingDuration);
+                propertyAnim->setStartValue(currentPos);
+                propertyAnim->setEndValue(endPos);
+                propertyAnim->start();
+                propertyAnim->blockSignals(block);
+            } else {
+                widget->setPos(currentPos);
+            }
+        }
+    }
+}
+
+qreal KItemListViewAnimation::offset() const
+{
+    return m_offset;
+}
+
+void KItemListViewAnimation::start(QGraphicsWidget* widget, AnimationType type, const QVariant& endValue)
+{
+    stop(widget, type);
+
+    const int duration = 200;
+    QPropertyAnimation* propertyAnim = 0;
+
+    switch (type) {
+    case MovingAnimation: {
+        const QPointF newPos = endValue.toPointF();
+        if (newPos == widget->pos()) {
+            return;
+        }
+
+        propertyAnim = new QPropertyAnimation(widget, "pos");
+        propertyAnim->setDuration(duration);
+        propertyAnim->setEndValue(newPos);
+        break;
+    }
+
+    case CreateAnimation: {
+        propertyAnim = new QPropertyAnimation(widget, "opacity");
+        propertyAnim->setEasingCurve(QEasingCurve::InQuart);
+        propertyAnim->setDuration(duration);
+        propertyAnim->setStartValue(0.0);
+        propertyAnim->setEndValue(1.0);
+        break;
+    }
+
+    case DeleteAnimation: {
+        propertyAnim = new QPropertyAnimation(widget, "opacity");
+        propertyAnim->setEasingCurve(QEasingCurve::OutQuart);
+        propertyAnim->setDuration(duration);
+        propertyAnim->setStartValue(1.0);
+        propertyAnim->setEndValue(0.0);
+        break;
+    }
+
+    case ResizeAnimation: {
+        const QSizeF newSize = endValue.toSizeF();
+        if (newSize == widget->size()) {
+            return;
+        }
+
+        propertyAnim = new QPropertyAnimation(widget, "size");
+        propertyAnim->setDuration(duration);
+        propertyAnim->setEndValue(newSize);
+        break;
+    }
+
+    default:
+        break;
+    }
+
+    Q_ASSERT(propertyAnim);
+    connect(propertyAnim, SIGNAL(finished()), this, SLOT(slotFinished()));
+    m_animation[type].insert(widget, propertyAnim);
+
+    propertyAnim->start();
+}
+
+void KItemListViewAnimation::stop(QGraphicsWidget* widget, AnimationType type)
+{
+    QPropertyAnimation* propertyAnim = m_animation[type].value(widget);
+    if (propertyAnim) {
+        propertyAnim->stop();
+
+        switch (type) {
+        case MovingAnimation: break;
+        case CreateAnimation: widget->setOpacity(1.0); break;
+        case DeleteAnimation: widget->setOpacity(0.0); break;
+        case ResizeAnimation: break;
+        default: break;
+        }
+
+        m_animation[type].remove(widget);
+        delete propertyAnim;
+
+        emit finished(widget, type);
+    }
+}
+
+void KItemListViewAnimation::stop(QGraphicsWidget* widget)
+{
+    for (int type = 0; type < AnimationTypeCount; ++type) {
+        stop(widget, static_cast<AnimationType>(type));
+    }
+}
+
+bool KItemListViewAnimation::isStarted(QGraphicsWidget *widget, AnimationType type) const
+{
+    return m_animation[type].value(widget);
+}
+
+bool KItemListViewAnimation::isStarted(QGraphicsWidget* widget) const
+{
+    for (int type = 0; type < AnimationTypeCount; ++type) {
+        if (isStarted(widget, static_cast<AnimationType>(type))) {
+            return true;
+        }
+    }
+    return false;
+}
+
+void KItemListViewAnimation::slotFinished()
+{
+    QPropertyAnimation* finishedAnim = qobject_cast<QPropertyAnimation*>(sender());
+    for (int type = 0; type < AnimationTypeCount; ++type) {
+        QHashIterator<QGraphicsWidget*, QPropertyAnimation*> it(m_animation[type]);
+        while (it.hasNext()) {
+            it.next();
+            QPropertyAnimation* propertyAnim = it.value();
+            if (propertyAnim == finishedAnim) {
+                QGraphicsWidget* widget = it.key();
+                m_animation[type].remove(widget);
+                finishedAnim->deleteLater();
+
+                emit finished(widget, static_cast<AnimationType>(type));
+                return;
+            }
+        }
+    }
+    Q_ASSERT(false);
+}
+
+#include "kitemlistviewanimation_p.moc"
diff --git a/src/kitemviews/kitemlistviewanimation_p.h b/src/kitemviews/kitemlistviewanimation_p.h
new file mode 100644 (file)
index 0000000..0bf54d2
--- /dev/null
@@ -0,0 +1,79 @@
+/***************************************************************************
+ *   Copyright (C) 2011 by Peter Penz <peter.penz19@gmail.com>             *
+ *                                                                         *
+ *   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 program 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 program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA            *
+ ***************************************************************************/
+
+#ifndef KITEMLISTVIEWANIMATION_H
+#define KITEMLISTVIEWANIMATION_H
+
+#include <libdolphin_export.h>
+
+#include <QHash>
+#include <QObject>
+#include <QVariant>
+
+class KItemListView;
+class QGraphicsWidget;
+class QPointF;
+class QPropertyAnimation;
+
+class LIBDOLPHINPRIVATE_EXPORT KItemListViewAnimation : public QObject
+{
+    Q_OBJECT
+
+public:
+    enum AnimationType {
+        MovingAnimation,
+        CreateAnimation,
+        DeleteAnimation,
+        ResizeAnimation
+    };
+
+    KItemListViewAnimation(QObject* parent = 0);
+    virtual ~KItemListViewAnimation();
+
+    void setScrollOrientation(Qt::Orientation orientation);
+    Qt::Orientation scrollOrientation() const;
+
+    void setOffset(qreal offset);
+    qreal offset() const;
+
+    void start(QGraphicsWidget* widget, AnimationType type, const QVariant& endValue = QVariant());
+
+    void stop(QGraphicsWidget* widget, AnimationType type);
+    void stop(QGraphicsWidget* widget);
+
+    bool isStarted(QGraphicsWidget *widget, AnimationType type) const;
+    bool isStarted(QGraphicsWidget* widget) const;
+
+signals:
+    void finished(QGraphicsWidget* widget, KItemListViewAnimation::AnimationType type);
+
+private slots:
+    void slotFinished();
+
+private:
+    enum { AnimationTypeCount = 4 };
+
+    Qt::Orientation m_scrollOrientation;
+    qreal m_offset;
+    QHash<QGraphicsWidget*, QPropertyAnimation*> m_animation[AnimationTypeCount];
+};
+
+#endif
+
+
diff --git a/src/kitemviews/kitemlistviewlayouter.cpp b/src/kitemviews/kitemlistviewlayouter.cpp
new file mode 100644 (file)
index 0000000..7d420e0
--- /dev/null
@@ -0,0 +1,474 @@
+/***************************************************************************
+ *   Copyright (C) 2011 by Peter Penz <peter.penz19@gmail.com>             *
+ *                                                                         *
+ *   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 program 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 program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA            *
+ ***************************************************************************/
+
+#include "kitemlistviewlayouter_p.h"
+
+#include "kitemmodelbase.h"
+#include "kitemlistsizehintresolver_p.h"
+
+#include <KDebug>
+
+#define KITEMLISTVIEWLAYOUTER_DEBUG
+
+namespace {
+    // TODO
+    const int HeaderHeight = 50;
+};
+
+KItemListViewLayouter::KItemListViewLayouter(QObject* parent) :
+    QObject(parent),
+    m_dirty(true),
+    m_visibleIndexesDirty(true),
+    m_grouped(false),
+    m_scrollOrientation(Qt::Vertical),
+    m_size(),
+    m_itemSize(128, 128),
+    m_model(0),
+    m_sizeHintResolver(0),
+    m_offset(0),
+    m_maximumOffset(0),
+    m_firstVisibleIndex(-1),
+    m_lastVisibleIndex(-1),
+    m_firstVisibleGroupIndex(-1),
+    m_columnWidth(0),
+    m_xPosInc(0),
+    m_columnCount(0),
+    m_groups(),
+    m_groupIndexes(),
+    m_itemBoundingRects()
+{
+}
+
+KItemListViewLayouter::~KItemListViewLayouter()
+{
+}
+
+void KItemListViewLayouter::setScrollOrientation(Qt::Orientation orientation)
+{
+    if (m_scrollOrientation != orientation) {
+        m_scrollOrientation = orientation;
+        m_dirty = true;
+    }
+}
+
+Qt::Orientation KItemListViewLayouter::scrollOrientation() const
+{
+    return m_scrollOrientation;
+}
+
+void KItemListViewLayouter::setSize(const QSizeF& size)
+{
+    if (m_size != size) {
+        m_size = size;
+        m_dirty = true;
+    }
+}
+
+QSizeF KItemListViewLayouter::size() const
+{
+    return m_size;
+}
+
+void KItemListViewLayouter::setItemSize(const QSizeF& size)
+{
+    if (m_itemSize != size) {
+        m_itemSize = size;
+        m_dirty = true;
+    }
+}
+
+QSizeF KItemListViewLayouter::itemSize() const
+{
+    return m_itemSize;
+}
+
+void KItemListViewLayouter::setOffset(qreal offset)
+{
+    if (m_offset != offset) {
+        m_offset = offset;
+        m_visibleIndexesDirty = true;
+    }
+}
+
+qreal KItemListViewLayouter::offset() const
+{
+    return m_offset;
+}
+
+void KItemListViewLayouter::setModel(const KItemModelBase* model)
+{
+    if (m_model != model) {
+        m_model = model;
+        m_dirty = true;
+    }
+}
+
+const KItemModelBase* KItemListViewLayouter::model() const
+{
+    return m_model;
+}
+
+void KItemListViewLayouter::setSizeHintResolver(const KItemListSizeHintResolver* sizeHintResolver)
+{
+    if (m_sizeHintResolver != sizeHintResolver) {
+        m_sizeHintResolver = sizeHintResolver;
+        m_dirty = true;
+    }
+}
+
+const KItemListSizeHintResolver* KItemListViewLayouter::sizeHintResolver() const
+{
+    return m_sizeHintResolver;
+}
+
+qreal KItemListViewLayouter::maximumOffset() const
+{
+    const_cast<KItemListViewLayouter*>(this)->doLayout();
+    return m_maximumOffset;
+}
+
+int KItemListViewLayouter::firstVisibleIndex() const
+{
+    const_cast<KItemListViewLayouter*>(this)->doLayout();
+    return m_firstVisibleIndex;
+}
+
+int KItemListViewLayouter::lastVisibleIndex() const
+{
+    const_cast<KItemListViewLayouter*>(this)->doLayout();
+    return m_lastVisibleIndex;
+}
+
+QRectF KItemListViewLayouter::itemBoundingRect(int index) const
+{
+    const_cast<KItemListViewLayouter*>(this)->doLayout();
+    if (index < 0 || index >= m_itemBoundingRects.count()) {
+        return QRectF();
+    }
+
+    if (m_scrollOrientation == Qt::Horizontal) {
+        // Rotate the logical direction which is always vertical by 90°
+        // to get the physical horizontal direction
+        const QRectF& b = m_itemBoundingRects[index];
+        QRectF bounds(b.y(), b.x(), b.height(), b.width());
+        QPointF pos = bounds.topLeft();
+        pos.rx() -= m_offset;
+        bounds.moveTo(pos);
+        return bounds;
+    }
+
+    QRectF bounds = m_itemBoundingRects[index];
+    QPointF pos = bounds.topLeft();
+    pos.ry() -= m_offset;
+    bounds.moveTo(pos);
+    return bounds;
+}
+
+int KItemListViewLayouter::maximumVisibleItems() const
+{
+    const_cast<KItemListViewLayouter*>(this)->doLayout();
+
+    const int height = static_cast<int>(m_size.height());
+    const int rowHeight = static_cast<int>(m_itemSize.height());
+    int rows = height / rowHeight;
+    if (height % rowHeight != 0) {
+        ++rows;
+    }
+
+    return rows * m_columnCount;
+}
+
+bool KItemListViewLayouter::isFirstGroupItem(int itemIndex) const
+{
+    return m_groupIndexes.contains(itemIndex);
+}
+
+void KItemListViewLayouter::markAsDirty()
+{
+    m_dirty = true;
+}
+
+void KItemListViewLayouter::doLayout()
+{
+    if (m_dirty) {
+#ifdef KITEMLISTVIEWLAYOUTER_DEBUG
+        QElapsedTimer timer;
+        timer.start();
+#endif
+
+        m_visibleIndexesDirty = true;
+
+        QSizeF itemSize = m_itemSize;
+        QSizeF size = m_size;
+
+        const bool horizontalScrolling = (m_scrollOrientation == Qt::Horizontal);
+        if (horizontalScrolling) {
+            itemSize.setWidth(m_itemSize.height());
+            itemSize.setHeight(m_itemSize.width());
+            size.setWidth(m_size.height());
+            size.setHeight(m_size.width());
+        }
+
+        m_columnWidth = itemSize.width();
+        m_columnCount = qMax(1, int(size.width() / m_columnWidth));
+        m_xPosInc = 0;
+
+        const int itemCount = m_model->count();
+        if (itemCount > m_columnCount) {
+            // Apply the unused width equally to each column
+            const qreal unusedWidth = size.width() - m_columnCount * m_columnWidth;
+            const qreal columnInc = unusedWidth / (m_columnCount + 1);
+            m_columnWidth += columnInc;
+            m_xPosInc += columnInc;
+        }
+
+        int rowCount = itemCount / m_columnCount;
+        if (itemCount % m_columnCount != 0) {
+            ++rowCount;
+        }
+
+        m_itemBoundingRects.reserve(itemCount);
+
+        qreal y = 0;
+        int rowIndex = 0;
+
+        int index = 0;
+        while (index < itemCount) {
+            qreal x = m_xPosInc;
+            qreal maxItemHeight = itemSize.height();
+
+            int column = 0;
+            while (index < itemCount && column < m_columnCount) {
+                qreal requiredItemHeight = itemSize.height();
+                if (m_sizeHintResolver) {
+                    const QSizeF sizeHint = m_sizeHintResolver->sizeHint(index);
+                    const qreal sizeHintHeight = horizontalScrolling ? sizeHint.width() : sizeHint.height();
+                    if (sizeHintHeight > requiredItemHeight) {
+                        requiredItemHeight = sizeHintHeight;
+                    }
+                }
+
+                const QRectF bounds(x, y, itemSize.width(), requiredItemHeight);
+                if (index < m_itemBoundingRects.count()) {
+                    m_itemBoundingRects[index] = bounds;
+                } else {
+                    m_itemBoundingRects.append(bounds);
+                }
+
+                maxItemHeight = qMax(maxItemHeight, requiredItemHeight);
+                x += m_columnWidth;
+                ++index;
+                ++column;
+            }
+
+            y += maxItemHeight;
+            ++rowIndex;
+        }
+        if (m_itemBoundingRects.count() > itemCount) {
+            m_itemBoundingRects.erase(m_itemBoundingRects.begin() + itemCount,
+                                      m_itemBoundingRects.end());
+        }
+
+        m_maximumOffset = (itemCount > 0) ? m_itemBoundingRects.last().bottom() : 0;
+
+        m_grouped = !m_model->groupRole().isEmpty();
+        /*if (m_grouped) {
+            createGroupHeaders();
+
+            const int lastGroupItemCount = m_model->count() - m_groups.last().firstItemIndex;
+            m_maximumOffset = m_groups.last().y + (lastGroupItemCount / m_columnCount) * m_rowHeight;
+            if (lastGroupItemCount % m_columnCount != 0) {
+                m_maximumOffset += m_rowHeight;
+            }
+        } else {*/
+         //   m_maximumOffset = m_minimumRowHeight * rowCount;
+        //}
+
+#ifdef KITEMLISTVIEWLAYOUTER_DEBUG
+        kDebug() << "[TIME] doLayout() for " << m_model->count() << "items:" << timer.elapsed();
+#endif
+        m_dirty = false;
+    }
+
+    if (m_grouped) {
+        updateGroupedVisibleIndexes();
+    } else {
+        updateVisibleIndexes();
+    }
+}
+
+void KItemListViewLayouter::updateVisibleIndexes()
+{
+    if (!m_visibleIndexesDirty) {
+        return;
+    }
+
+    Q_ASSERT(!m_grouped);
+    Q_ASSERT(!m_dirty);
+
+    if (m_model->count() <= 0) {
+        m_firstVisibleIndex = -1;
+        m_lastVisibleIndex = -1;
+        m_visibleIndexesDirty = false;
+        return;
+    }
+
+    const bool horizontalScrolling = (m_scrollOrientation == Qt::Horizontal);
+    const int minimumHeight =  horizontalScrolling ? m_itemSize.width()
+                                                   : m_itemSize.height();
+
+    // Calculate the first visible index:
+    // 1. Guess the index by using the minimum row height
+    const int maxIndex = m_model->count() - 1;
+    m_firstVisibleIndex = int(m_offset / minimumHeight) * m_columnCount;
+
+    // 2. Decrease the index by checking the real row heights
+    int prevRowIndex = m_firstVisibleIndex - m_columnCount;
+    while (prevRowIndex > maxIndex) {
+        prevRowIndex -= m_columnCount;
+    }
+
+    while (prevRowIndex >= 0 && m_itemBoundingRects[prevRowIndex].bottom() >= m_offset) {
+        m_firstVisibleIndex = prevRowIndex;
+        prevRowIndex -= m_columnCount;
+    }
+    m_firstVisibleIndex = qBound(0, m_firstVisibleIndex, maxIndex);
+
+    // Calculate the last visible index
+    const int visibleHeight = horizontalScrolling ? m_size.width() : m_size.height();
+    const qreal bottom = m_offset + visibleHeight;
+    m_lastVisibleIndex = m_firstVisibleIndex; // first visible row, first column
+    int nextRowIndex = m_lastVisibleIndex + m_columnCount;
+    while (nextRowIndex <= maxIndex && m_itemBoundingRects[nextRowIndex].y() <= bottom) {
+        m_lastVisibleIndex = nextRowIndex;
+        nextRowIndex += m_columnCount;
+    }
+    m_lastVisibleIndex += m_columnCount - 1; // move it to the last column
+    m_lastVisibleIndex = qBound(0, m_lastVisibleIndex, maxIndex);
+
+    m_visibleIndexesDirty = false;
+}
+
+void KItemListViewLayouter::updateGroupedVisibleIndexes()
+{
+    if (!m_visibleIndexesDirty) {
+        return;
+    }
+
+    Q_ASSERT(m_grouped);
+    Q_ASSERT(!m_dirty);
+
+    if (m_model->count() <= 0) {
+        m_firstVisibleIndex = -1;
+        m_lastVisibleIndex = -1;
+        m_visibleIndexesDirty = false;
+        return;
+    }
+
+    // Find the first visible group
+    const int lastGroupIndex = m_groups.count() - 1;
+    int groupIndex = lastGroupIndex;
+    for (int i = 1; i < m_groups.count(); ++i) {
+        if (m_groups[i].y >= m_offset) {
+            groupIndex = i - 1;
+            break;
+        }
+    }
+
+    // Calculate the first visible index
+    qreal groupY = m_groups[groupIndex].y;
+    m_firstVisibleIndex = m_groups[groupIndex].firstItemIndex;
+    const int invisibleRowCount = int(m_offset - groupY) / int(m_itemSize.height());
+    m_firstVisibleIndex += invisibleRowCount * m_columnCount;
+    if (groupIndex + 1 <= lastGroupIndex) {
+        // Check whether the calculated first visible index remains inside the current
+        // group. If this is not the case let the first element of the next group be the first
+        // visible index.
+        const int nextGroupIndex = m_groups[groupIndex + 1].firstItemIndex;
+        if (m_firstVisibleIndex > nextGroupIndex) {
+            m_firstVisibleIndex = nextGroupIndex;
+        }
+    }
+
+    m_firstVisibleGroupIndex = groupIndex;
+
+    const int maxIndex = m_model->count() - 1;
+    m_firstVisibleIndex = qBound(0, m_firstVisibleIndex, maxIndex);
+
+    // Calculate the last visible index: Find group where the last visible item is shown.
+    const qreal visibleBottom = m_offset + m_size.height(); // TODO: respect Qt::Horizontal alignment
+    while ((groupIndex < lastGroupIndex) && (m_groups[groupIndex + 1].y < visibleBottom)) {
+        ++groupIndex;
+    }
+
+    groupY = m_groups[groupIndex].y;
+    m_lastVisibleIndex = m_groups[groupIndex].firstItemIndex;
+    const int availableHeight = static_cast<int>(visibleBottom - groupY);
+    int visibleRowCount = availableHeight / int(m_itemSize.height());
+    if (availableHeight % int(m_itemSize.height()) != 0) {
+        ++visibleRowCount;
+    }
+    m_lastVisibleIndex += visibleRowCount * m_columnCount - 1;
+
+    if (groupIndex + 1 <= lastGroupIndex) {
+        // Check whether the calculate last visible index remains inside the current group.
+        // If this is not the case let the last element of this group be the last visible index.
+        const int nextGroupIndex = m_groups[groupIndex + 1].firstItemIndex;
+        if (m_lastVisibleIndex >= nextGroupIndex) {
+            m_lastVisibleIndex = nextGroupIndex - 1;
+        }
+    }
+    //Q_ASSERT(m_lastVisibleIndex < m_model->count());
+    m_lastVisibleIndex = qBound(0, m_lastVisibleIndex, maxIndex);
+
+    m_visibleIndexesDirty = false;
+}
+
+void KItemListViewLayouter::createGroupHeaders()
+{
+    m_groups.clear();
+    m_groupIndexes.clear();
+
+    // TODO:
+    QList<int> numbers;
+    numbers << 0 << 5 << 6 << 13 << 20 << 25 << 30 << 35 << 50;
+
+    qreal y = 0;
+    for (int i = 0; i < numbers.count(); ++i) {
+        if (i > 0) {
+            const int previousGroupItemCount = numbers[i] - m_groups.last().firstItemIndex;
+            int previousGroupRowCount = previousGroupItemCount / m_columnCount;
+            if (previousGroupItemCount % m_columnCount != 0) {
+                ++previousGroupRowCount;
+            }
+            const qreal previousGroupHeight = previousGroupRowCount * m_itemSize.height();
+            y += previousGroupHeight;
+        }
+        y += HeaderHeight;
+
+        ItemGroup itemGroup;
+        itemGroup.firstItemIndex = numbers[i];
+        itemGroup.y = y;
+
+        m_groups.append(itemGroup);
+        m_groupIndexes.insert(itemGroup.firstItemIndex);
+    }
+}
+
+#include "kitemlistviewlayouter_p.moc"
diff --git a/src/kitemviews/kitemlistviewlayouter_p.h b/src/kitemviews/kitemlistviewlayouter_p.h
new file mode 100644 (file)
index 0000000..775e9ff
--- /dev/null
@@ -0,0 +1,126 @@
+/***************************************************************************
+ *   Copyright (C) 2011 by Peter Penz <peter.penz19@gmail.com>             *
+ *                                                                         *
+ *   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 program 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 program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA            *
+ ***************************************************************************/
+
+#ifndef KITEMLISTVIEWLAYOUTER_H
+#define KITEMLISTVIEWLAYOUTER_H
+
+#include <libdolphin_export.h>
+
+#include <QObject>
+#include <QRectF>
+#include <QSet>
+#include <QSizeF>
+
+class KItemModelBase;
+class KItemListSizeHintResolver;
+
+class LIBDOLPHINPRIVATE_EXPORT KItemListViewLayouter : public QObject
+{
+    Q_OBJECT
+
+public:
+    KItemListViewLayouter(QObject* parent = 0);
+    virtual ~KItemListViewLayouter();
+
+    void setScrollOrientation(Qt::Orientation orientation);
+    Qt::Orientation scrollOrientation() const;
+
+    void setSize(const QSizeF& size);
+    QSizeF size() const;
+
+    void setItemSize(const QSizeF& size);
+    QSizeF itemSize() const;
+
+    // TODO: add note that offset can be < 0 or > maximumOffset!
+    void setOffset(qreal offset);
+    qreal offset() const;
+
+    void setModel(const KItemModelBase* model);
+    const KItemModelBase* model() const;
+
+    void setSizeHintResolver(const KItemListSizeHintResolver* sizeHintResolver);
+    const KItemListSizeHintResolver* sizeHintResolver() const;
+
+    qreal maximumOffset() const;
+
+    // TODO: mention that return value is -1 if count == 0
+    int firstVisibleIndex() const;
+
+    // TODO: mention that return value is -1 if count == 0
+    int lastVisibleIndex() const;
+
+    QRectF itemBoundingRect(int index) const;
+
+    int maximumVisibleItems() const;
+
+    /**
+     * @return True if the item with the index \p itemIndex
+     *         is the first item within a group.
+     */
+    bool isFirstGroupItem(int itemIndex) const;
+
+    void markAsDirty();
+
+private:
+    void doLayout();
+
+    void updateVisibleIndexes();
+    void updateGroupedVisibleIndexes();
+    void createGroupHeaders();
+
+private:
+    bool m_dirty;
+    bool m_visibleIndexesDirty;
+    bool m_grouped;
+
+    Qt::Orientation m_scrollOrientation;
+    QSizeF m_size;
+
+    QSizeF m_itemSize;
+    const KItemModelBase* m_model;
+    const KItemListSizeHintResolver* m_sizeHintResolver;
+
+    qreal m_offset;
+    qreal m_maximumOffset;
+
+    int m_firstVisibleIndex;
+    int m_lastVisibleIndex;
+
+    int m_firstVisibleGroupIndex;
+
+    qreal m_columnWidth;
+    qreal m_xPosInc;
+    int m_columnCount;
+
+    struct ItemGroup {
+        int firstItemIndex;
+        qreal y;
+    };
+    QList<ItemGroup> m_groups;
+
+    // Stores all item indexes that are the first item of a group.
+    // Assures fast access for KItemListViewLayouter::isFirstGroupItem().
+    QSet<int> m_groupIndexes;
+
+    QList<QRectF> m_itemBoundingRects;
+};
+
+#endif
+
+
diff --git a/src/kitemviews/kitemlistwidget.cpp b/src/kitemviews/kitemlistwidget.cpp
new file mode 100644 (file)
index 0000000..3f08d9f
--- /dev/null
@@ -0,0 +1,260 @@
+/***************************************************************************
+ *   Copyright (C) 2011 by Peter Penz <peter.penz19@gmail.com>             *
+ *                                                                         *
+ *   Based on the Itemviews NG project from Trolltech Labs:                *
+ *   http://qt.gitorious.org/qt-labs/itemviews-ng                          *
+ *                                                                         *
+ *   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 program 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 program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA            *
+ ***************************************************************************/
+
+#include "kitemlistwidget.h"
+
+#include "kitemlistview.h"
+#include "kitemmodelbase.h"
+
+#include <KDebug>
+
+#include <QPainter>
+#include <QPropertyAnimation>
+#include <QStyle>
+
+KItemListWidget::KItemListWidget(QGraphicsItem* parent) :
+    QGraphicsWidget(parent, 0),
+    m_index(-1),
+    m_data(),
+    m_visibleRoles(),
+    m_visibleRolesSizes(),
+    m_styleOption(),
+    m_hoverOpacity(0),
+    m_hoverCache(0),
+    m_hoverAnimation(0)
+{
+}
+
+KItemListWidget::~KItemListWidget()
+{
+    clearCache();
+}
+
+void KItemListWidget::setIndex(int index)
+{
+    if (m_index != index) {
+        if (m_hoverAnimation) {
+            m_hoverAnimation->stop();
+            m_hoverOpacity = 0;
+        }
+        clearCache();
+
+        m_index = index;
+    }
+}
+
+int KItemListWidget::index() const
+{
+    return m_index;
+}
+
+void KItemListWidget::setData(const QHash<QByteArray, QVariant>& data,
+                              const QSet<QByteArray>& roles)
+{
+    clearCache();
+    if (roles.isEmpty()) {
+        m_data = data;
+        dataChanged(m_data);
+    } else {
+        foreach (const QByteArray& role, roles) {
+            m_data[role] = data[role];
+        }
+        dataChanged(m_data, roles);
+    }
+}
+
+QHash<QByteArray, QVariant> KItemListWidget::data() const
+{
+    return m_data;
+}
+
+void KItemListWidget::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget)
+{
+    Q_UNUSED(option);
+    if (m_hoverOpacity <= 0.0) {
+        return;
+    }
+
+    const QRect hoverBounds = hoverBoundingRect().toRect();
+    if (!m_hoverCache) {
+        m_hoverCache = new QPixmap(hoverBounds.size());
+        m_hoverCache->fill(Qt::transparent);
+
+        QPainter pixmapPainter(m_hoverCache);
+
+        QStyleOptionViewItemV4 viewItemOption;
+        viewItemOption.initFrom(widget);
+        viewItemOption.rect = QRect(0, 0, hoverBounds.width(), hoverBounds.height());
+        viewItemOption.state = QStyle::State_Enabled | QStyle::State_MouseOver;
+        viewItemOption.viewItemPosition = QStyleOptionViewItemV4::OnlyOne;
+
+        widget->style()->drawPrimitive(QStyle::PE_PanelItemViewItem, &viewItemOption, &pixmapPainter, widget);
+    }
+
+    const qreal opacity = painter->opacity();
+    painter->setOpacity(m_hoverOpacity * opacity);
+    painter->drawPixmap(hoverBounds.topLeft(), *m_hoverCache);
+    painter->setOpacity(opacity);
+}
+
+void KItemListWidget::setVisibleRoles(const QHash<QByteArray, int>& roles)
+{
+    const QHash<QByteArray, int> previousRoles = m_visibleRoles;
+    m_visibleRoles = roles;
+    visibleRolesChanged(roles, previousRoles);
+}
+
+QHash<QByteArray, int> KItemListWidget::visibleRoles() const
+{
+    return m_visibleRoles;
+}
+
+void KItemListWidget::setVisibleRolesSizes(const QHash<QByteArray, QSizeF> rolesSizes)
+{
+    const QHash<QByteArray, QSizeF> previousRolesSizes = m_visibleRolesSizes;
+    m_visibleRolesSizes = rolesSizes;
+    visibleRolesSizesChanged(rolesSizes, previousRolesSizes);
+}
+
+QHash<QByteArray, QSizeF> KItemListWidget::visibleRolesSizes() const
+{
+    return m_visibleRolesSizes;
+}
+
+void KItemListWidget::setStyleOption(const KItemListStyleOption& option)
+{
+    const KItemListStyleOption previous = m_styleOption;
+    if (m_index >= 0) {
+        clearCache();
+
+        const bool wasHovered = (previous.state & QStyle::State_MouseOver);
+        m_styleOption = option;
+        const bool isHovered = (m_styleOption.state & QStyle::State_MouseOver);
+
+        if (wasHovered != isHovered) {
+            // The hovering state has been changed. Assure that a fade-animation
+            // is done to the new state.
+            if (!m_hoverAnimation) {
+                m_hoverAnimation = new QPropertyAnimation(this, "hoverOpacity", this);
+                m_hoverAnimation->setDuration(200);
+            }
+            m_hoverAnimation->stop();
+
+            if (!wasHovered && isHovered) {
+                m_hoverAnimation->setEndValue(1.0);
+            } else {
+                Q_ASSERT(wasHovered && !isHovered);
+                m_hoverAnimation->setEndValue(0.0);
+            }
+
+            m_hoverAnimation->start();
+        }
+    } else {
+        m_styleOption = option;
+    }
+
+    styleOptionChanged(option, previous);
+}
+
+const KItemListStyleOption& KItemListWidget::styleOption() const
+{
+    return m_styleOption;
+}
+
+bool KItemListWidget::contains(const QPointF& point) const
+{
+    return hoverBoundingRect().contains(point) ||
+           expansionToggleRect().contains(point) ||
+           selectionToggleRect().contains(point);
+}
+
+QRectF KItemListWidget::hoverBoundingRect() const
+{
+    return QRectF(QPointF(0, 0), size());
+}
+
+QRectF KItemListWidget::selectionToggleRect() const
+{
+    return QRectF();
+}
+
+QRectF KItemListWidget::expansionToggleRect() const
+{
+    return QRectF();
+}
+
+void KItemListWidget::dataChanged(const QHash<QByteArray, QVariant>& current,
+                                  const QSet<QByteArray>& roles)
+{
+    Q_UNUSED(current);
+    Q_UNUSED(roles);
+    update();
+}
+
+void KItemListWidget::visibleRolesChanged(const QHash<QByteArray, int>& current,
+                                          const QHash<QByteArray, int>& previous)
+{
+    Q_UNUSED(current);
+    Q_UNUSED(previous);
+    update();
+}
+
+void KItemListWidget::visibleRolesSizesChanged(const QHash<QByteArray, QSizeF>& current,
+                                               const QHash<QByteArray, QSizeF>& previous)
+{
+    Q_UNUSED(current);
+    Q_UNUSED(previous);
+    update();
+}
+
+void KItemListWidget::styleOptionChanged(const KItemListStyleOption& current,
+                                         const KItemListStyleOption& previous)
+{
+    Q_UNUSED(current);
+    Q_UNUSED(previous);
+    update();
+}
+
+void KItemListWidget::resizeEvent(QGraphicsSceneResizeEvent* event)
+{
+    QGraphicsWidget::resizeEvent(event);
+    clearCache();
+}
+
+qreal KItemListWidget::hoverOpacity() const
+{
+    return m_hoverOpacity;
+}
+
+void KItemListWidget::setHoverOpacity(qreal opacity)
+{
+    m_hoverOpacity = opacity;
+    update();
+}
+
+void KItemListWidget::clearCache()
+{
+    delete m_hoverCache;
+    m_hoverCache = 0;
+}
+
+#include "kitemlistwidget.moc"
diff --git a/src/kitemviews/kitemlistwidget.h b/src/kitemviews/kitemlistwidget.h
new file mode 100644 (file)
index 0000000..eb2ebf4
--- /dev/null
@@ -0,0 +1,134 @@
+/***************************************************************************
+ *   Copyright (C) 2011 by Peter Penz <peter.penz19@gmail.com>             *
+ *                                                                         *
+ *   Based on the Itemviews NG project from Trolltech Labs:                *
+ *   http://qt.gitorious.org/qt-labs/itemviews-ng                          *
+ *                                                                         *
+ *   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 program 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 program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA            *
+ ***************************************************************************/
+
+#ifndef KITEMLISTWIDGET_H
+#define KITEMLISTWIDGET_H
+
+#include <libdolphin_export.h>
+
+#include <kitemviews/kitemliststyleoption.h>
+
+#include <QGraphicsWidget>
+
+class QPropertyAnimation;
+
+/**
+ * @brief Widget that shows a visible item from the model.
+ *
+ * For showing an item from a custom model it is required to at least overwrite KItemListWidget::paint().
+ * All properties are set by KItemListView, for each property there is a corresponding
+ * virtual protected method that allows to react on property changes.
+ */
+class LIBDOLPHINPRIVATE_EXPORT KItemListWidget : public QGraphicsWidget
+{
+    Q_OBJECT
+
+public:
+    KItemListWidget(QGraphicsItem* parent);
+    virtual ~KItemListWidget();
+
+    void setIndex(int index);
+    int index() const;
+
+    void setData(const QHash<QByteArray, QVariant>& data, const QSet<QByteArray>& roles = QSet<QByteArray>());
+    QHash<QByteArray, QVariant> data() const;
+
+    /**
+     * Draws the hover-bounding-rectangle if the item is hovered. Overwrite this method
+     * to show the data of the custom model provided by KItemListWidget::data().
+     * @reimp
+     */
+    virtual void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget = 0);
+
+    /**
+     * Sets the visible roles to \p roles. The integer-value defines
+     * the order of the visible role: Smaller values are ordered first.
+     */
+    void setVisibleRoles(const QHash<QByteArray, int>& roles);
+    QHash<QByteArray, int> visibleRoles() const;
+
+    void setVisibleRolesSizes(const QHash<QByteArray, QSizeF> rolesSizes);
+    QHash<QByteArray, QSizeF> visibleRolesSizes() const;
+
+    void setStyleOption(const KItemListStyleOption& option);
+    const KItemListStyleOption& styleOption() const;
+
+    /**
+     * @return True if \a point is inside KItemListWidget::hoverBoundingRect(),
+     *         KItemListWidget::selectionToggleRect() or KItemListWidget::expansionToggleRect().
+     * @reimp
+     */
+    virtual bool contains(const QPointF& point) const;
+
+    /**
+     * @return Bounding rectangle for the area that acts as hovering-area. Per default
+     *         the bounding rectangle of the KItemListWidget is returned.
+     */
+    virtual QRectF hoverBoundingRect() const;
+
+    /**
+     * @return Rectangle for the selection-toggle that is used to select or deselect an item.
+     *         Per default an empty rectangle is returned which means that no selection-toggle
+     *         is available.
+     */
+    virtual QRectF selectionToggleRect() const;
+
+    /**
+     * @return Rectangle for the expansion-toggle that is used to open a sub-tree of the model.
+     *         Per default an empty rectangle is returned which means that no opening of sub-trees
+     *         is supported.
+     */
+    virtual QRectF expansionToggleRect() const;
+
+protected:
+    virtual void dataChanged(const QHash<QByteArray, QVariant>& current, const QSet<QByteArray>& roles = QSet<QByteArray>());
+    virtual void visibleRolesChanged(const QHash<QByteArray, int>& current, const QHash<QByteArray, int>& previous);
+    virtual void visibleRolesSizesChanged(const QHash<QByteArray, QSizeF>& current, const QHash<QByteArray, QSizeF>& previous);
+    virtual void styleOptionChanged(const KItemListStyleOption& current, const KItemListStyleOption& previous);
+    virtual void resizeEvent(QGraphicsSceneResizeEvent* event);
+
+    /**
+     * @return The current opacity of the hover-animation. When implementing a custom painting-code for a hover-state
+     *         this opacity value should be respected.
+     */
+    qreal hoverOpacity() const;
+
+private:
+    void setHoverOpacity(qreal opacity);
+    void clearCache();
+
+private:
+    Q_PROPERTY(qreal hoverOpacity READ hoverOpacity WRITE setHoverOpacity)
+
+    int m_index;
+    QHash<QByteArray, QVariant> m_data;
+    QHash<QByteArray, int> m_visibleRoles;
+    QHash<QByteArray, QSizeF> m_visibleRolesSizes;
+    KItemListStyleOption m_styleOption;
+
+    qreal m_hoverOpacity;
+    mutable QPixmap* m_hoverCache;
+    QPropertyAnimation* m_hoverAnimation;
+};
+#endif
+
+
diff --git a/src/kitemviews/kitemmodelbase.cpp b/src/kitemviews/kitemmodelbase.cpp
new file mode 100644 (file)
index 0000000..63e771e
--- /dev/null
@@ -0,0 +1,113 @@
+/***************************************************************************
+ *   Copyright (C) 2011 by Peter Penz <peter.penz19@gmail.com>             *
+ *                                                                         *
+ *   Based on the Itemviews NG project from Trolltech Labs:                *
+ *   http://qt.gitorious.org/qt-labs/itemviews-ng                          *
+ *                                                                         *
+ *   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 program 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 program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA            *
+ ***************************************************************************/
+
+#include "kitemmodelbase.h"
+
+KItemRange::KItemRange(int index, int count) :
+    index(index),
+    count(count)
+{
+}
+
+KItemModelBase::KItemModelBase(QObject* parent) :
+    QObject(parent),
+    m_groupRole(),
+    m_sortRole()
+{
+}
+
+KItemModelBase::KItemModelBase(const QByteArray& groupRole, const QByteArray& sortRole, QObject* parent) :
+    QObject(parent),
+    m_groupRole(groupRole),
+    m_sortRole(sortRole)
+{
+}
+
+KItemModelBase::~KItemModelBase()
+{
+}
+
+bool KItemModelBase::setData(int index, const QHash<QByteArray, QVariant> &values)
+{
+    Q_UNUSED(index);
+    Q_UNUSED(values);
+    return false;
+}
+
+bool KItemModelBase::supportsGrouping() const
+{
+    return false;
+}
+
+void KItemModelBase::setGroupRole(const QByteArray& role)
+{
+    if (supportsGrouping() && role != m_groupRole) {
+        const QByteArray previous = m_groupRole;
+        m_groupRole = role;
+        onGroupRoleChanged(role, previous);
+        emit groupRoleChanged(role, previous);
+    }
+}
+
+QByteArray KItemModelBase::groupRole() const
+{
+    return m_groupRole;
+}
+
+bool KItemModelBase::supportsSorting() const
+{
+    return false;
+}
+
+void KItemModelBase::setSortRole(const QByteArray& role)
+{
+    if (supportsSorting() && role != m_sortRole) {
+        const QByteArray previous = m_sortRole;
+        m_sortRole = role;
+        onSortRoleChanged(role, previous);
+        emit sortRoleChanged(role, previous);
+    }
+}
+
+QByteArray KItemModelBase::sortRole() const
+{
+    return m_sortRole;
+}
+
+QString KItemModelBase::roleDescription(const QByteArray& role) const
+{
+    return role;
+}
+
+void KItemModelBase::onGroupRoleChanged(const QByteArray& current, const QByteArray& previous)
+{
+    Q_UNUSED(current);
+    Q_UNUSED(previous);
+}
+
+void KItemModelBase::onSortRoleChanged(const QByteArray& current, const QByteArray& previous)
+{
+    Q_UNUSED(current);
+    Q_UNUSED(previous);
+}
+
+#include "kitemmodelbase.moc"
diff --git a/src/kitemviews/kitemmodelbase.h b/src/kitemviews/kitemmodelbase.h
new file mode 100644 (file)
index 0000000..4eb96c8
--- /dev/null
@@ -0,0 +1,145 @@
+/***************************************************************************
+ *   Copyright (C) 2011 by Peter Penz <peter.penz19@gmail.com>             *
+ *                                                                         *
+ *   Based on the Itemviews NG project from Trolltech Labs:                *
+ *   http://qt.gitorious.org/qt-labs/itemviews-ng                          *
+ *                                                                         *
+ *   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 program 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 program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA            *
+ ***************************************************************************/
+
+#ifndef KITEMMODELBASE_H
+#define KITEMMODELBASE_H
+
+#include <libdolphin_export.h>
+
+#include <QHash>
+#include <QObject>
+#include <QSet>
+#include <QVariant>
+
+struct KItemRange
+{
+    KItemRange(int index, int count);
+    int index;
+    int count;
+};
+typedef QList<KItemRange> KItemRangeList;
+
+/**
+ * @brief Base class for model implementations used by KItemListView and KItemListController.
+ *
+ * A item-model consists of a variable number of items. The number of items
+ * is given by KItemModelBase::count(). The data of an item is accessed by a unique index
+ * with KItemModelBase::data(). The indexes are integer-values counting from 0 to the
+ * KItemModelBase::count() - 1.
+ *
+ * One item consists of a variable number of role/value-pairs.
+ *
+ * A model can optionally provide sorting- and/or grouping-capabilities.
+ */
+class LIBDOLPHINPRIVATE_EXPORT KItemModelBase : public QObject
+{
+    Q_OBJECT
+
+public:
+    KItemModelBase(QObject* parent = 0);
+    KItemModelBase(const QByteArray& groupRole, const QByteArray& sortRole, QObject* parent = 0);
+    virtual ~KItemModelBase();
+
+    /** @return The number of items. */
+    virtual int count() const = 0;
+
+    virtual QHash<QByteArray, QVariant> data(int index) const = 0;
+
+    /**
+     * Sets the data for the item at \a index to the given \a values. Returns true
+     * if the data was set on the item; returns false otherwise.
+     *
+     * The default implementation does not set the data, and will always return
+     * false.
+     */
+    virtual bool setData(int index, const QHash<QByteArray, QVariant>& values);
+
+    /**
+     * @return True if the model supports grouping of data. Per default false is returned.
+     *         If the model should support grouping it is necessary to overwrite
+     *         this method to return true and to implement KItemModelBase::onGroupRoleChanged().
+     */
+    virtual bool supportsGrouping() const;
+
+    /**
+     * Sets the group-role to \a role. The method KItemModelBase::onGroupRoleChanged() will be
+     * called so that model-implementations can react on the group-role change. Afterwards the
+     * signal groupRoleChanged() will be emitted.
+     */
+    void setGroupRole(const QByteArray& role);
+    QByteArray groupRole() const;
+
+    /**
+     * @return True if the model supports sorting of data. Per default false is returned.
+     *         If the model should support sorting it is necessary to overwrite
+     *         this method to return true and to implement KItemModelBase::onSortRoleChanged().
+     */
+    virtual bool supportsSorting() const;
+
+    /**
+     * Sets the sor-role to \a role. The method KItemModelBase::onSortRoleChanged() will be
+     * called so that model-implementations can react on the sort-role change. Afterwards the
+     * signal sortRoleChanged() will be emitted.
+     */
+    void setSortRole(const QByteArray& role);
+    QByteArray sortRole() const;
+
+    virtual QString roleDescription(const QByteArray& role) const;
+
+signals:
+    void itemsInserted(const KItemRangeList& itemRanges);
+    void itemsRemoved(const KItemRangeList& itemRanges);
+    void itemsMoved(const KItemRangeList& itemRanges);
+    void itemsChanged(const KItemRangeList& itemRanges, const QSet<QByteArray>& roles);
+
+    void groupRoleChanged(const QByteArray& current, const QByteArray& previous);
+    void sortRoleChanged(const QByteArray& current, const QByteArray& previous);
+
+protected:
+    /**
+     * Is invoked if the group role has been changed by KItemModelBase::setGroupRole(). Allows
+     * to react on the changed group role before the signal groupRoleChanged() will be emitted.
+     * The implementation must assure that the items are sorted in a way that they are grouped
+     * by the role given by \a current. Usually the most efficient way is to emit a
+     * itemsRemoved() signal for all items, reorder the items internally and to emit a
+     * itemsInserted() signal afterwards.
+     */
+    virtual void onGroupRoleChanged(const QByteArray& current, const QByteArray& previous);
+
+    /**
+     * Is invoked if the sort role has been changed by KItemModelBase::setSortRole(). Allows
+     * to react on the changed sort role before the signal sortRoleChanged() will be emitted.
+     * The implementation must assure that the items are sorted by the role given by \a current.
+     * Usually the most efficient way is to emit a
+     * itemsRemoved() signal for all items, reorder the items internally and to emit a
+     * itemsInserted() signal afterwards.
+     */
+    virtual void onSortRoleChanged(const QByteArray& current, const QByteArray& previous);
+
+private:
+    QByteArray m_groupRole;
+    QByteArray m_sortRole;
+};
+
+#endif
+
+
diff --git a/src/kitemviews/kpixmapmodifier.cpp b/src/kitemviews/kpixmapmodifier.cpp
new file mode 100644 (file)
index 0000000..e210f0b
--- /dev/null
@@ -0,0 +1,388 @@
+//krazy:exclude=copyright (email of Maxim is missing)
+/*
+    This file is a part of the KDE project
+
+    Copyright © 2006 Zack Rusin <zack@kde.org>
+    Copyright © 2006-2007, 2008 Fredrik Höglund <fredrik@kde.org>
+
+    The stack blur algorithm was invented by Mario Klingemann <mario@quasimondo.com>
+
+    This implementation is based on the version in Anti-Grain Geometry Version 2.4,
+    Copyright © 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions
+    are met:
+
+    1. Redistributions of source code must retain the above copyright
+       notice, this list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright
+       notice, this list of conditions and the following disclaimer in the
+       documentation and/or other materials provided with the distribution.
+
+    THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+    IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+    OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+    IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+    INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+    NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+    THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "kpixmapmodifier_p.h"
+
+#include <QImage>
+#include <QPainter>
+#include <QPixmap>
+#include <QSize>
+
+#include <KDebug>
+
+#include <config-X11.h> // for HAVE_XRENDER
+#if defined(Q_WS_X11) && defined(HAVE_XRENDER)
+#  include <QX11Info>
+#  include <X11/Xlib.h>
+#  include <X11/extensions/Xrender.h>
+#endif
+
+static const quint32 stackBlur8Mul[255] =
+{
+    512,512,456,512,328,456,335,512,405,328,271,456,388,335,292,512,
+    454,405,364,328,298,271,496,456,420,388,360,335,312,292,273,512,
+    482,454,428,405,383,364,345,328,312,298,284,271,259,496,475,456,
+    437,420,404,388,374,360,347,335,323,312,302,292,282,273,265,512,
+    497,482,468,454,441,428,417,405,394,383,373,364,354,345,337,328,
+    320,312,305,298,291,284,278,271,265,259,507,496,485,475,465,456,
+    446,437,428,420,412,404,396,388,381,374,367,360,354,347,341,335,
+    329,323,318,312,307,302,297,292,287,282,278,273,269,265,261,512,
+    505,497,489,482,475,468,461,454,447,441,435,428,422,417,411,405,
+    399,394,389,383,378,373,368,364,359,354,350,345,341,337,332,328,
+    324,320,316,312,309,305,301,298,294,291,287,284,281,278,274,271,
+    268,265,262,259,257,507,501,496,491,485,480,475,470,465,460,456,
+    451,446,442,437,433,428,424,420,416,412,408,404,400,396,392,388,
+    385,381,377,374,370,367,363,360,357,354,350,347,344,341,338,335,
+    332,329,326,323,320,318,315,312,310,307,304,302,299,297,294,292,
+    289,287,285,282,280,278,275,273,271,269,267,265,263,261,259
+};
+
+static const quint32 stackBlur8Shr[255] =
+{
+    9, 11, 12, 13, 13, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 17,
+    17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 18, 19,
+    19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 20, 20, 20,
+    20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21,
+    21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+    21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22,
+    22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+    22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23,
+    23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+    23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+    23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+    23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+    24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+    24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+    24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+    24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24
+};
+
+static void blurHorizontal(QImage& image, unsigned int* stack, int div, int radius)
+{
+    int stackindex;
+    int stackstart;
+
+    quint32 * const pixels = reinterpret_cast<quint32 *>(image.bits());
+    quint32 pixel;
+
+    int w = image.width();
+    int h = image.height();
+    int wm = w - 1;
+
+    unsigned int mulSum = stackBlur8Mul[radius];
+    unsigned int shrSum = stackBlur8Shr[radius];
+
+    unsigned int sum, sumIn, sumOut;
+
+    for (int y = 0; y < h; y++) {
+        sum    = 0;
+        sumIn  = 0;
+        sumOut = 0;
+
+        const int yw = y * w;
+        pixel = pixels[yw];
+        for (int i = 0; i <= radius; i++) {
+            stack[i] = qAlpha(pixel);
+
+            sum += stack[i] * (i + 1);
+            sumOut += stack[i];
+        }
+
+        for (int i = 1; i <= radius; i++) {
+            pixel = pixels[yw + qMin(i, wm)];
+
+            unsigned int* stackpix = &stack[i + radius];
+            *stackpix = qAlpha(pixel);
+
+            sum    += *stackpix * (radius + 1 - i);
+            sumIn += *stackpix;
+        }
+
+        stackindex = radius;
+        for (int x = 0, i = yw; x < w; x++) {
+            pixels[i++] = (((sum * mulSum) >> shrSum) << 24) & 0xff000000;
+
+            sum -= sumOut;
+
+            stackstart = stackindex + div - radius;
+            if (stackstart >= div) {
+                stackstart -= div;
+            }
+
+            unsigned int* stackpix = &stack[stackstart];
+
+            sumOut -= *stackpix;
+
+            pixel = pixels[yw + qMin(x + radius + 1, wm)];
+
+            *stackpix = qAlpha(pixel);
+
+            sumIn += *stackpix;
+            sum    += sumIn;
+
+            if (++stackindex >= div) {
+                stackindex = 0;
+            }
+
+            stackpix = &stack[stackindex];
+
+            sumOut += *stackpix;
+            sumIn  -= *stackpix;
+        }
+    }
+}
+
+static void blurVertical(QImage& image, unsigned int* stack, int div, int radius)
+{
+    int stackindex;
+    int stackstart;
+
+    quint32 * const pixels = reinterpret_cast<quint32 *>(image.bits());
+    quint32 pixel;
+
+    int w = image.width();
+    int h = image.height();
+    int hm = h - 1;
+
+    int mul_sum = stackBlur8Mul[radius];
+    int shr_sum = stackBlur8Shr[radius];
+
+    unsigned int sum, sumIn, sumOut;
+
+    for (int x = 0; x < w; x++) {
+        sum    = 0;
+        sumIn  = 0;
+        sumOut = 0;
+
+        pixel = pixels[x];
+        for (int i = 0; i <= radius; i++) {
+            stack[i] = qAlpha(pixel);
+
+            sum += stack[i] * (i + 1);
+            sumOut += stack[i];
+        }
+
+        for (int i = 1; i <= radius; i++) {
+            pixel = pixels[qMin(i, hm) * w + x];
+
+            unsigned int* stackpix = &stack[i + radius];
+            *stackpix = qAlpha(pixel);
+
+            sum    += *stackpix * (radius + 1 - i);
+            sumIn += *stackpix;
+        }
+
+        stackindex = radius;
+        for (int y = 0, i = x; y < h; y++, i += w) {
+            pixels[i] = (((sum * mul_sum) >> shr_sum) << 24) & 0xff000000;
+
+            sum -= sumOut;
+
+            stackstart = stackindex + div - radius;
+            if (stackstart >= div)
+                stackstart -= div;
+
+            unsigned int* stackpix = &stack[stackstart];
+
+            sumOut -= *stackpix;
+
+            pixel = pixels[qMin(y + radius + 1, hm) * w + x];
+
+            *stackpix = qAlpha(pixel);
+
+            sumIn += *stackpix;
+            sum    += sumIn;
+
+            if (++stackindex >= div) {
+                stackindex = 0;
+            }
+
+            stackpix = &stack[stackindex];
+
+            sumOut += *stackpix;
+            sumIn  -= *stackpix;
+        }
+    }
+}
+
+static void stackBlur(QImage& image, float radius)
+{
+    radius = qRound(radius);
+
+    int div = int(radius * 2) + 1;
+    unsigned int* stack  = new unsigned int[div];
+
+    blurHorizontal(image, stack, div, radius);
+    blurVertical(image, stack, div, radius);
+
+    delete [] stack;
+}
+
+static void shadowBlur(QImage& image, float radius, const QColor& color)
+{
+    if (radius < 0) {
+        return;
+    }
+
+    if (radius > 0) {
+        stackBlur(image, radius);
+    }
+
+    // Correct the color and opacity of the shadow
+    QPainter p(&image);
+    p.setCompositionMode(QPainter::CompositionMode_SourceIn);
+    p.fillRect(image.rect(), color);
+}
+
+namespace {
+    /** Helper class for drawing frames for KPixmapModifier::applyFrame(). */
+    class TileSet
+    {
+    public:
+        enum { LeftMargin = 3, TopMargin = 2, RightMargin = 3, BottomMargin = 4 };
+
+        enum Tile { TopLeftCorner = 0, TopSide, TopRightCorner, LeftSide,
+                    RightSide, BottomLeftCorner, BottomSide, BottomRightCorner,
+                    NumTiles };
+
+        TileSet()
+        {
+            QImage image(8 * 3, 8 * 3, QImage::Format_ARGB32_Premultiplied);
+
+            QPainter p(&image);
+            p.setCompositionMode(QPainter::CompositionMode_Source);
+            p.fillRect(image.rect(), Qt::transparent);
+            p.fillRect(image.rect().adjusted(3, 3, -3, -3), Qt::black);
+            p.end();
+
+            shadowBlur(image, 3, Qt::black);
+
+            QPixmap pixmap = QPixmap::fromImage(image);
+            m_tiles[TopLeftCorner]     = pixmap.copy(0, 0, 8, 8);
+            m_tiles[TopSide]           = pixmap.copy(8, 0, 8, 8);
+            m_tiles[TopRightCorner]    = pixmap.copy(16, 0, 8, 8);
+            m_tiles[LeftSide]          = pixmap.copy(0, 8, 8, 8);
+            m_tiles[RightSide]         = pixmap.copy(16, 8, 8, 8);
+            m_tiles[BottomLeftCorner]  = pixmap.copy(0, 16, 8, 8);
+            m_tiles[BottomSide]        = pixmap.copy(8, 16, 8, 8);
+            m_tiles[BottomRightCorner] = pixmap.copy(16, 16, 8, 8);
+        }
+
+        void paint(QPainter* p, const QRect& r)
+        {
+            p->drawPixmap(r.topLeft(), m_tiles[TopLeftCorner]);
+            if (r.width() - 16 > 0) {
+                p->drawTiledPixmap(r.x() + 8, r.y(), r.width() - 16, 8, m_tiles[TopSide]);
+            }
+            p->drawPixmap(r.right() - 8 + 1, r.y(), m_tiles[TopRightCorner]);
+            if (r.height() - 16 > 0) {
+                p->drawTiledPixmap(r.x(), r.y() + 8, 8, r.height() - 16,  m_tiles[LeftSide]);
+                p->drawTiledPixmap(r.right() - 8 + 1, r.y() + 8, 8, r.height() - 16, m_tiles[RightSide]);
+            }
+            p->drawPixmap(r.x(), r.bottom() - 8 + 1, m_tiles[BottomLeftCorner]);
+            if (r.width() - 16 > 0) {
+                p->drawTiledPixmap(r.x() + 8, r.bottom() - 8 + 1, r.width() - 16, 8, m_tiles[BottomSide]);
+            }
+            p->drawPixmap(r.right() - 8 + 1, r.bottom() - 8 + 1, m_tiles[BottomRightCorner]);
+
+            const QRect contentRect = r.adjusted(LeftMargin + 1, TopMargin + 1,
+                                                 -(RightMargin + 1), -(BottomMargin + 1));
+            p->fillRect(contentRect, Qt::transparent);
+        }
+
+        QPixmap m_tiles[NumTiles];
+    };
+}
+
+void KPixmapModifier::scale(QPixmap& pixmap, const QSize& scaledSize)
+{
+#if defined(Q_WS_X11) && defined(HAVE_XRENDER)
+    // Assume that the texture size limit is 2048x2048
+    if ((pixmap.width() <= 2048) && (pixmap.height() <= 2048) && pixmap.x11PictureHandle()) {
+        QSize scaledPixmapSize = pixmap.size();
+        scaledPixmapSize.scale(scaledSize, Qt::KeepAspectRatio);
+
+        const qreal factor = scaledPixmapSize.width() / qreal(pixmap.width());
+
+        XTransform xform = {{
+            { XDoubleToFixed(1 / factor), 0, 0 },
+            { 0, XDoubleToFixed(1 / factor), 0 },
+            { 0, 0, XDoubleToFixed(1) }
+        }};
+
+        QPixmap scaledPixmap(scaledPixmapSize);
+        scaledPixmap.fill(Qt::transparent);
+
+        Display* dpy = QX11Info::display();
+
+        XRenderPictureAttributes attr;
+        attr.repeat = RepeatPad;
+        XRenderChangePicture(dpy, pixmap.x11PictureHandle(), CPRepeat, &attr);
+
+        XRenderSetPictureFilter(dpy, pixmap.x11PictureHandle(), FilterBilinear, 0, 0);
+        XRenderSetPictureTransform(dpy, pixmap.x11PictureHandle(), &xform);
+        XRenderComposite(dpy, PictOpOver, pixmap.x11PictureHandle(), None, scaledPixmap.x11PictureHandle(),
+                         0, 0, 0, 0, 0, 0, scaledPixmap.width(), scaledPixmap.height());
+        pixmap = scaledPixmap;
+    } else {
+        pixmap = pixmap.scaled(scaledSize, Qt::KeepAspectRatio, Qt::FastTransformation);
+    }
+#else
+    pixmap = pixmap.scaled(scaledSize, Qt::KeepAspectRatio, Qt::FastTransformation);
+#endif
+}
+
+void KPixmapModifier::applyFrame(QPixmap& icon, const QSize& scaledSize)
+{
+    static TileSet tileSet;
+
+    // Resize the icon to the maximum size minus the space required for the frame
+    const QSize size(scaledSize.width() - TileSet::LeftMargin - TileSet::RightMargin,
+                     scaledSize.height() - TileSet::TopMargin - TileSet::BottomMargin);
+    scale(icon, size);
+
+    QPixmap framedIcon(icon.size().width() + TileSet::LeftMargin + TileSet::RightMargin,
+                       icon.size().height() + TileSet::TopMargin + TileSet::BottomMargin);
+    framedIcon.fill(Qt::transparent);
+
+    QPainter painter;
+    painter.begin(&framedIcon);
+    painter.setCompositionMode(QPainter::CompositionMode_Source);
+    tileSet.paint(&painter, framedIcon.rect());
+    painter.setCompositionMode(QPainter::CompositionMode_SourceOver);
+    painter.drawPixmap(TileSet::LeftMargin, TileSet::TopMargin, icon);
+
+    icon = framedIcon;
+}
+
similarity index 71%
rename from src/tests/dolphinviewtest_icons.cpp
rename to src/kitemviews/kpixmapmodifier_p.h
index 5f928f40317a2451eb98ae459911252105bc7ae3..bca5e442a47c97fce47b7ad6a62a443dcea8c186 100644 (file)
@@ -1,5 +1,5 @@
 /***************************************************************************
- *   Copyright (C) 2010 by Frank Reininghaus (frank78ac@googlemail.com)    *
+ *   Copyright (C) 2011 by Peter Penz <peter.penz19@gmail.com>             *
  *                                                                         *
  *   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  *
  *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA            *
  ***************************************************************************/
 
-#include <qtest_kde.h>
+#ifndef KPIXMAPMODIFIER_H
+#define KPIXMAPMODIFIER_H
 
-#include "dolphinviewtest_allviewmodes.h"
+#include <libdolphin_export.h>
 
-class DolphinViewTest_Icons : public DolphinViewTest_AllViewModes
-{
-    Q_OBJECT
+class QPixmap;
+class QSize;
 
+class LIBDOLPHINPRIVATE_EXPORT KPixmapModifier
+{
 public:
-
-    virtual DolphinView::Mode mode() const {
-        return DolphinView::IconsView;
-    }
-
-    virtual bool verifyCorrectViewMode(const DolphinView* view) const {
-        return (view->mode() == DolphinView::IconsView);
-    }
-
+    static void scale(QPixmap& pixmap, const QSize& scaledSize);
+    static void applyFrame(QPixmap& icon, const QSize& scaledSize);
 };
 
-QTEST_KDEMAIN(DolphinViewTest_Icons, GUI)
+#endif
+
 
-#include "dolphinviewtest_icons.moc"
index 3f26bbb579023d8bb1c6007cb93ade908a70cc84..f8d50e9e151fac978bac33e7133c427889f006ce 100644 (file)
@@ -33,7 +33,7 @@ KDE_EXPORT int kdemain(int argc, char **argv)
 {
     KAboutData about("dolphin", 0,
                      ki18nc("@title", "Dolphin"),
-                     "1.6.9",
+                     "1.99",
                      ki18nc("@title", "File Manager"),
                      KAboutData::License_GPL,
                      ki18nc("@info:credit", "(C) 2006-2011 Peter Penz"));
index 716be829cf328c65cb4cfe7f23c839a8160ecde7..8b8ca66f82c26cb1d7372a9b13580a302cd73cf7 100644 (file)
@@ -6,8 +6,8 @@
       http://www.kde.org/standards/kcfg/1.0/kcfg.xsd">
     <kcfgfile name="dolphinrc"/>
     <group name="FoldersPanel">
-        <entry name="ShowHiddenFiles" type="Bool">
-            <label>Show hidden files</label>
+        <entry name="HiddenFilesShown" type="Bool">
+            <label>Hidden files shown</label>
             <default>false</default>
         </entry>
         <entry name="AutoScrolling" type="Bool">
index ccdf13decc165cfe886498e198643dea191caa46..fe0f0b134956a7dc32a9d45427ec18c7a70e7838 100644 (file)
@@ -39,9 +39,6 @@
 #include <QScrollBar>
 #include <QTimer>
 
-#include <views/draganddrophelper.h>
-#include <views/dolphinmodel.h>
-#include <views/dolphinsortfilterproxymodel.h>
 #include <views/dolphinview.h>
 #include <views/folderexpander.h>
 #include <views/renamedialog.h>
@@ -51,8 +48,8 @@ FoldersPanel::FoldersPanel(QWidget* parent) :
     m_setLeafVisible(false),
     m_mouseButtons(Qt::NoButton),
     m_dirLister(0),
-    m_dolphinModel(0),
-    m_proxyModel(0),
+    //m_dolphinModel(0),
+    //m_proxyModel(0),
     m_treeView(0),
     m_leafDir()
 {
@@ -63,25 +60,26 @@ FoldersPanel::~FoldersPanel()
 {
     FoldersPanelSettings::self()->writeConfig();
 
-    delete m_proxyModel;
-    m_proxyModel = 0;
-    delete m_dolphinModel;
-    m_dolphinModel = 0;
-    m_dirLister = 0; // deleted by m_dolphinModel
+    //delete m_proxyModel;
+    //m_proxyModel = 0;
+    //delete m_dolphinModel;
+    //m_dolphinModel = 0;
+    delete m_dirLister;
+    m_dirLister = 0;
 }
 
-void FoldersPanel::setShowHiddenFiles(bool show)
+void FoldersPanel::setHiddenFilesShown(bool show)
 {
-    FoldersPanelSettings::setShowHiddenFiles(show);
+    FoldersPanelSettings::setHiddenFilesShown(show);
     if (m_dirLister) {
         m_dirLister->setShowingDotFiles(show);
         m_dirLister->openUrl(m_dirLister->url(), KDirLister::Reload);
     }
 }
 
-bool FoldersPanel::showHiddenFiles() const
+bool FoldersPanel::hiddenFilesShown() const
 {
-    return FoldersPanelSettings::showHiddenFiles();
+    return FoldersPanelSettings::hiddenFilesShown();
 }
 
 void FoldersPanel::setAutoScrolling(bool enable)
@@ -98,9 +96,9 @@ bool FoldersPanel::autoScrolling() const
 void FoldersPanel::rename(const KFileItem& item)
 {
     if (DolphinSettings::instance().generalSettings()->renameInline()) {
-        const QModelIndex dirIndex = m_dolphinModel->indexForItem(item);
-        const QModelIndex proxyIndex = m_proxyModel->mapFromSource(dirIndex);
-        m_treeView->edit(proxyIndex);
+        //const QModelIndex dirIndex = m_dolphinModel->indexForItem(item);
+        //const QModelIndex proxyIndex = m_proxyModel->mapFromSource(dirIndex);
+        //m_treeView->edit(proxyIndex);
     } else {
         RenameDialog* dialog = new RenameDialog(this, KFileItemList() << item);
         dialog->setAttribute(Qt::WA_DeleteOnClose);
@@ -143,10 +141,10 @@ void FoldersPanel::showEvent(QShowEvent* event)
         m_dirLister->setMainWindow(window());
         m_dirLister->setDelayedMimeTypes(true);
         m_dirLister->setAutoErrorHandlingEnabled(false, this);
-        m_dirLister->setShowingDotFiles(FoldersPanelSettings::showHiddenFiles());
+        m_dirLister->setShowingDotFiles(FoldersPanelSettings::hiddenFilesShown());
         connect(m_dirLister, SIGNAL(completed()), this, SLOT(slotDirListerCompleted()));
 
-        Q_ASSERT(!m_dolphinModel);
+        /*Q_ASSERT(!m_dolphinModel);
         m_dolphinModel = new DolphinModel(this);
         m_dolphinModel->setDirLister(m_dirLister);
         m_dolphinModel->setDropsAllowed(DolphinModel::DropOnDirectory);
@@ -180,7 +178,7 @@ void FoldersPanel::showEvent(QShowEvent* event)
 
         QVBoxLayout* layout = new QVBoxLayout(this);
         layout->setMargin(0);
-        layout->addWidget(m_treeView);
+        layout->addWidget(m_treeView);*/
     }
 
     loadTree(url());
@@ -192,11 +190,11 @@ void FoldersPanel::contextMenuEvent(QContextMenuEvent* event)
     Panel::contextMenuEvent(event);
 
     KFileItem item;
-    const QModelIndex index = m_treeView->indexAt(event->pos());
+    /*const QModelIndex index = m_treeView->indexAt(event->pos());
     if (index.isValid()) {
         const QModelIndex dolphinModelIndex = m_proxyModel->mapToSource(index);
         item = m_dolphinModel->itemForIndex(dolphinModelIndex);
-    }
+    }*/
 
     QPointer<TreeViewContextMenu> contextMenu = new TreeViewContextMenu(this, item);
     contextMenu->open();
@@ -216,22 +214,25 @@ void FoldersPanel::keyPressEvent(QKeyEvent* event)
 
 void FoldersPanel::updateActiveView(const QModelIndex& index)
 {
-    const QModelIndex dirIndex = m_proxyModel->mapToSource(index);
+    Q_UNUSED(index);
+    /*const QModelIndex dirIndex = m_proxyModel->mapToSource(index);
     const KFileItem item = m_dolphinModel->itemForIndex(dirIndex);
     if (!item.isNull()) {
         emit changeUrl(item.url(), m_mouseButtons);
-    }
+    }*/
 }
 
 void FoldersPanel::dropUrls(const QModelIndex& index, QDropEvent* event)
 {
+    Q_UNUSED(event);
     if (index.isValid()) {
-        const QModelIndex dirIndex = m_proxyModel->mapToSource(index);
+        /*const QModelIndex dirIndex = m_proxyModel->mapToSource(index);
         KFileItem item = m_dolphinModel->itemForIndex(dirIndex);
         Q_ASSERT(!item.isNull());
         if (item.isDir()) {
-            DragAndDropHelper::instance().dropUrls(item, item.url(), event, this);
-        }
+            Q_UNUSED(event);
+            //DragAndDropHelper::instance().dropUrls(item, item.url(), event, this);
+        }*/
     }
 }
 
@@ -243,11 +244,11 @@ void FoldersPanel::expandToDir(const QModelIndex& index)
 
 void FoldersPanel::scrollToLeaf()
 {
-    const QModelIndex dirIndex = m_dolphinModel->indexForUrl(m_leafDir);
+    /*const QModelIndex dirIndex = m_dolphinModel->indexForUrl(m_leafDir);
     const QModelIndex proxyIndex = m_proxyModel->mapFromSource(dirIndex);
     if (proxyIndex.isValid()) {
         m_treeView->scrollTo(proxyIndex);
-    }
+    }*/
 }
 
 void FoldersPanel::updateMouseButtons()
@@ -257,7 +258,7 @@ void FoldersPanel::updateMouseButtons()
 
 void FoldersPanel::slotDirListerCompleted()
 {
-    m_treeView->resizeColumnToContents(DolphinModel::Name);
+//    m_treeView->resizeColumnToContents(DolphinModel::Name);
 }
 
 void FoldersPanel::slotHorizontalScrollBarMoved(int value)
@@ -295,12 +296,12 @@ void FoldersPanel::loadTree(const KUrl& url)
         m_dirLister->stop();
         m_dirLister->openUrl(baseUrl, KDirLister::Reload);
     }
-    m_dolphinModel->expandToUrl(m_leafDir);
+    //m_dolphinModel->expandToUrl(m_leafDir);
 }
 
 void FoldersPanel::selectLeafDirectory()
 {
-    const QModelIndex dirIndex = m_dolphinModel->indexForUrl(m_leafDir);
+    /*const QModelIndex dirIndex = m_dolphinModel->indexForUrl(m_leafDir);
     const QModelIndex proxyIndex = m_proxyModel->mapFromSource(dirIndex);
 
     if (proxyIndex.isValid()) {
@@ -314,7 +315,7 @@ void FoldersPanel::selectLeafDirectory()
             QTimer::singleShot(0, this, SLOT(scrollToLeaf()));
             m_setLeafVisible = false;
         }
-    }
+    }*/
 }
 
 #include "folderspanel.moc"
index 3031166e999489df9e369adb273c694cbad954d8..727fc7c71bc7bc893ee57179b27e74605c5af92d 100644 (file)
@@ -45,8 +45,8 @@ public:
     FoldersPanel(QWidget* parent = 0);
     virtual ~FoldersPanel();
 
-    void setShowHiddenFiles(bool show);
-    bool showHiddenFiles() const;
+    void setHiddenFilesShown(bool show);
+    bool hiddenFilesShown() const;
 
     void setAutoScrolling(bool enable);
     bool autoScrolling() const;
@@ -123,8 +123,8 @@ private:
     bool m_setLeafVisible;
     Qt::MouseButtons m_mouseButtons;
     KDirLister* m_dirLister;
-    DolphinModel* m_dolphinModel;
-    DolphinSortFilterProxyModel* m_proxyModel;
+    //DolphinModel* m_dolphinModel;
+    //DolphinSortFilterProxyModel* m_proxyModel;
     PanelTreeView* m_treeView;
     KUrl m_leafDir;
 };
index f6aa73aeaddbf4acaf7d5cf0c6fc630db25feb5c..26a543d56cc703e555cff2a47c2cd21647ec4914 100644 (file)
@@ -26,9 +26,6 @@
 #include <QHeaderView>
 #include <QScrollBar>
 
-#include <views/dolphinmodel.h>
-#include <views/draganddrophelper.h>
-
 PanelTreeView::PanelTreeView(QWidget* parent) :
     KTreeView(parent)
 {
@@ -69,10 +66,10 @@ bool PanelTreeView::event(QEvent* event)
     switch (event->type()) {
     case QEvent::Polish:
         // Hide all columns except of the 'Name' column
-        for (int i = DolphinModel::Name + 1; i < DolphinModel::ExtraColumnCount; ++i) {
+        /*for (int i = DolphinModel::Name + 1; i < DolphinModel::ExtraColumnCount; ++i) {
             hideColumn(i);
         }
-        header()->hide();
+        header()->hide();*/
         break;
 
     case QEvent::Show:
@@ -97,7 +94,8 @@ bool PanelTreeView::event(QEvent* event)
 
 void PanelTreeView::startDrag(Qt::DropActions supportedActions)
 {
-    DragAndDropHelper::instance().startDrag(this, supportedActions);
+    Q_UNUSED(supportedActions);
+    //DragAndDropHelper::instance().startDrag(this, supportedActions);
 }
 
 void PanelTreeView::dragEnterEvent(QDragEnterEvent* event)
index b66d445ccc742f0aa450b18f9899ea9e45c3131d..5db3e2c2a7aa862aa3b859250cfef582b4ae5aaa 100644 (file)
@@ -117,7 +117,7 @@ void TreeViewContextMenu::open()
 
     QAction* showHiddenFilesAction = new QAction(i18nc("@action:inmenu", "Show Hidden Files"), this);
     showHiddenFilesAction->setCheckable(true);
-    showHiddenFilesAction->setChecked(m_parent->showHiddenFiles());
+    showHiddenFilesAction->setChecked(m_parent->hiddenFilesShown());
     popup->addAction(showHiddenFilesAction);
     connect(showHiddenFilesAction, SIGNAL(toggled(bool)), this, SLOT(setShowHiddenFiles(bool)));
 
@@ -199,7 +199,7 @@ void TreeViewContextMenu::showProperties()
 
 void TreeViewContextMenu::setShowHiddenFiles(bool show)
 {
-    m_parent->setShowHiddenFiles(show);
+    m_parent->setHiddenFilesShown(show);
 }
 
 void TreeViewContextMenu::setAutoScrolling(bool enable)
index 4df3dedcda7b1258a92bc9612f6e61b16458f318..53c756d2404d9bc99363c1d3d6fc8dabb48d1382 100644 (file)
@@ -6,8 +6,8 @@
       http://www.kde.org/standards/kcfg/1.0/kcfg.xsd">
     <kcfgfile name="dolphinrc"/>
     <group name="InformationPanel">
-        <entry name="showPreview" type="Bool">
-            <label>Show preview</label>
+        <entry name="previewsShown" type="Bool">
+            <label>Previews shown</label>
             <default>true</default>
         </entry>
     </group>
index 2d90007bf2760b7b613b5c6dcbe910d912d5e4a2..1084fa0855c351c46e30812b7342ad03c57d2f8a 100644 (file)
@@ -102,8 +102,8 @@ InformationPanelContent::InformationPanelContent(QWidget* parent) :
     m_nameLabel->setAlignment(Qt::AlignHCenter);
     m_nameLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
 
-    const bool showPreview = InformationPanelSettings::showPreview();
-    m_preview->setVisible(showPreview);
+    const bool previewsShown = InformationPanelSettings::previewsShown();
+    m_preview->setVisible(previewsShown);
 
     m_metaDataWidget = new KFileMetaDataWidget(parent);
     m_metaDataWidget->setFont(KGlobalSettings::smallestReadableFont());
@@ -188,7 +188,7 @@ void InformationPanelContent::showItem(const KFileItem& item)
         m_metaDataWidget->setItems(KFileItemList() << item);
     }
 
-    if (InformationPanelSettings::showPreview()) {
+    if (InformationPanelSettings::previewsShown()) {
         const QString mimeType = item.mimetype();
         const bool usePhonon = Phonon::BackendCapabilities::isMimeTypeAvailable(mimeType) &&
                                (mimeType != "image/png");  // TODO: workaround, as Phonon
@@ -267,7 +267,7 @@ void InformationPanelContent::configureSettings(const QList<QAction*>& customCon
     QAction* previewAction = popup.addAction(i18nc("@action:inmenu", "Preview"));
     previewAction->setIcon(KIcon("view-preview"));
     previewAction->setCheckable(true);
-    previewAction->setChecked(InformationPanelSettings::showPreview());
+    previewAction->setChecked(InformationPanelSettings::previewsShown());
 
     QAction* configureAction = popup.addAction(i18nc("@action:inmenu", "Configure..."));
     configureAction->setIcon(KIcon("configure"));
@@ -287,7 +287,7 @@ void InformationPanelContent::configureSettings(const QList<QAction*>& customCon
     const bool isChecked = action->isChecked();
     if (action == previewAction) {
         m_preview->setVisible(isChecked);
-        InformationPanelSettings::setShowPreview(isChecked);
+        InformationPanelSettings::setPreviewsShown(isChecked);
     } else if (action == configureAction) {
         FileMetaDataConfigurationDialog* dialog = new FileMetaDataConfigurationDialog();
         dialog->setDescription(i18nc("@label::textbox",
index c2af7a6d73181d0727ef1eb25cbb06cd708aed36..e70fdf574e84d4ff2f9029118519f132748510c0 100644 (file)
@@ -22,7 +22,6 @@
 
 #include <KFileItem>
 #include <konq_operations.h>
-#include "views/draganddrophelper.h"
 
 PlacesPanel::PlacesPanel(QWidget* parent) :
     KFilePlacesView(parent),
@@ -47,7 +46,10 @@ void PlacesPanel::mousePressEvent(QMouseEvent* event)
 
 void PlacesPanel::slotUrlsDropped(const KUrl& dest, QDropEvent* event, QWidget* parent)
 {
-    DragAndDropHelper::instance().dropUrls(KFileItem(), dest, event, parent);
+    Q_UNUSED(dest);
+    Q_UNUSED(event);
+    Q_UNUSED(parent);
+    //DragAndDropHelper::instance().dropUrls(KFileItem(), dest, event, parent);
 }
 
 void PlacesPanel::emitExtendedUrlChangedSignal(const KUrl& url)
index 2e7d33cb30d21c8f8ece6422787d196d79f2246f..9b47e928f7b522bd47b10e7f0a3f2054effea0e9 100644 (file)
@@ -28,7 +28,7 @@
 #include "views/additionalinfoaccessor.h"
 
 AdditionalInfoDialog::AdditionalInfoDialog(QWidget* parent,
-                                           KFileItemDelegate::InformationList infoList) :
+                                           const QList<DolphinView::AdditionalInfo>& infoList) :
     KDialog(parent),
     m_infoList(infoList),
     m_checkBoxes()
@@ -49,8 +49,8 @@ AdditionalInfoDialog::AdditionalInfoDialog(QWidget* parent,
 
     // Add checkboxes
     const AdditionalInfoAccessor& infoAccessor = AdditionalInfoAccessor::instance();
-    const KFileItemDelegate::InformationList keys = infoAccessor.keys();
-    foreach (const KFileItemDelegate::Information info, keys) {
+    const QList<DolphinView::AdditionalInfo> keys = infoAccessor.keys();
+    foreach (DolphinView::AdditionalInfo info, keys) {
         QCheckBox* checkBox = new QCheckBox(infoAccessor.translation(info), mainWidget);
         checkBox->setChecked(infoList.contains(info));
         layout->addWidget(checkBox);
@@ -75,7 +75,7 @@ AdditionalInfoDialog::~AdditionalInfoDialog()
     saveDialogSize(dialogConfig, KConfigBase::Persistent);
 }
 
-KFileItemDelegate::InformationList AdditionalInfoDialog::informationList() const
+QList<DolphinView::AdditionalInfo> AdditionalInfoDialog::informationList() const
 {
     return m_infoList;
 }
@@ -84,9 +84,9 @@ void AdditionalInfoDialog::slotOk()
 {
     m_infoList.clear();
 
-    const KFileItemDelegate::InformationList keys = AdditionalInfoAccessor::instance().keys();
+    const QList<DolphinView::AdditionalInfo> keys = AdditionalInfoAccessor::instance().keys();
     int index = 0;
-    foreach (const KFileItemDelegate::Information info, keys) {
+    foreach (DolphinView::AdditionalInfo info, keys) {
         if (m_checkBoxes[index]->isChecked()) {
             m_infoList.append(info);
         }
index eca2c86c6f6606fb3d7295ac6d372f5f2eeb6368..6f38f617c0f073b29c4eca0b97ed5b90be231d20 100644 (file)
@@ -20,8 +20,8 @@
 #ifndef ADDITIONALINFODIALOG_H
 #define ADDITIONALINFODIALOG_H
 
+#include <views/dolphinview.h>
 #include <KDialog>
-#include <KFileItemDelegate>
 #include <QList>
 
 class QCheckBox;
@@ -34,15 +34,15 @@ class AdditionalInfoDialog : public KDialog
     Q_OBJECT
 
 public:
-    AdditionalInfoDialog(QWidget* parent, KFileItemDelegate::InformationList infoList);
+    AdditionalInfoDialog(QWidget* parent, const QList<DolphinView::AdditionalInfo>& infoList);
     virtual ~AdditionalInfoDialog();
-    KFileItemDelegate::InformationList informationList() const;
+    QList<DolphinView::AdditionalInfo> informationList() const;
 
 private slots:
     void slotOk();
 
 private:
-    KFileItemDelegate::InformationList m_infoList;
+    QList<DolphinView::AdditionalInfo> m_infoList;
     QList<QCheckBox*> m_checkBoxes;
 };
 
index 4010ab47785f0bc3139b9f8e17995f6206ac80a8..dd97888519fba7e485f7262a01edb3dcd7bb5109 100644 (file)
@@ -32,8 +32,8 @@ ApplyViewPropsJob::ApplyViewPropsJob(const KUrl& dir,
 {
     m_viewProps = new ViewProperties(dir);
     m_viewProps->setViewMode(viewProps.viewMode());
-    m_viewProps->setShowPreview(viewProps.showPreview());
-    m_viewProps->setShowHiddenFiles(viewProps.showHiddenFiles());
+    m_viewProps->setPreviewsShown(viewProps.previewsShown());
+    m_viewProps->setHiddenFilesShown(viewProps.hiddenFilesShown());
     m_viewProps->setSorting(viewProps.sorting());
     m_viewProps->setSortOrder(viewProps.sortOrder());
 
diff --git a/src/settings/dolphin_columnmodesettings.kcfgc b/src/settings/dolphin_columnmodesettings.kcfgc
deleted file mode 100644 (file)
index 5513433..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-File=dolphin_columnmodesettings.kcfg
-ClassName=ColumnModeSettings
-Singleton=false
-Mutators=true
similarity index 79%
rename from src/settings/dolphin_columnmodesettings.kcfg
rename to src/settings/dolphin_compactmodesettings.kcfg
index 963d326cc5264b65c9887870716f44a61f388406..bb050d4807a29797c9be1bc4c8ffcd57cbf0ec56 100644 (file)
@@ -3,19 +3,19 @@
 <kcfg xmlns="http://www.kde.org/standards/kcfg/1.0"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0
-      http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" >
-    <include>kiconloader.h</include>
+      http://www.kde.org/standards/kcfg/1.0/kcfg.xsd">
     <include>kglobalsettings.h</include>
+    <include>kiconloader.h</include>
     <kcfgfile name="dolphinrc"/>
-    <group name="ColumnMode">
-        <entry name="FontFamily" type="String">
-            <label>Font family</label>
-            <default code="true">KGlobalSettings::generalFont().family()</default>
-        </entry>
+    <group name="CompactMode">
         <entry name="UseSystemFont" type="Bool">
             <label>Use system font</label>
             <default>true</default>
         </entry>
+        <entry name="FontFamily" type="String">
+            <label>Font family</label>
+            <default code="true">KGlobalSettings::generalFont().family()</default>
+        </entry>
         <entry name="FontSize" type="Double">
             <label>Font size</label>
             <default code="true">KGlobalSettings::generalFont().pointSizeF()</default>
         </entry>
         <entry name="IconSize" type="Int">
             <label>Icon size</label>
-            <default code="true">KIconLoader::SizeSmall</default>
+            <default code="true">KIconLoader::SizeMedium</default>
         </entry>
         <entry name="PreviewSize" type="Int">
             <label>Preview size</label>
-            <default code="true">KIconLoader::SizeLarge</default>
-        </entry>
-        <entry name="ColumnWidth" type="Int">
-            <label>Column width</label>
-            <default>250</default>
+            <default code="true">KIconLoader::SizeHuge</default>
         </entry>
     </group>
 </kcfg>
diff --git a/src/settings/dolphin_compactmodesettings.kcfgc b/src/settings/dolphin_compactmodesettings.kcfgc
new file mode 100644 (file)
index 0000000..8341185
--- /dev/null
@@ -0,0 +1,4 @@
+File=dolphin_compactmodesettings.kcfg
+ClassName=CompactModeSettings
+Singleton=yes
+Mutators=true
index d58e038092d6274256468900924d2b01be978044..0fb1bf0b549de1e8ca6d503d9782cb9b90de96be 100644 (file)
             <label>Preview size</label>
             <default code="true">KIconLoader::SizeLarge</default>
         </entry>
-        <entry name="ExpandableFolders" type="Bool">
-            <label>Expandable folders</label>
-            <default>false</default>
-        </entry>
         <entry name="ColumnPositions" type="IntList">
             <label>Position of columns</label>
             <default>0,1,2,3,4,5,6,7,8</default>
index 06da2e9e0c89d41b212d527f4fbea81cd8265782..7acfa3c7da557a09c303ef85112301fbe26c9bca 100644 (file)
@@ -1,4 +1,4 @@
 File=dolphin_detailsmodesettings.kcfg
 ClassName=DetailsModeSettings
-Singleton=false 
+Singleton=yes
 Mutators=true
index 00415206372482d82ad49bced05492bdfba2fa83..7e62267a9186045126b0ef389e84c426f005bfec 100644 (file)
@@ -7,8 +7,8 @@
 
 <kcfgfile arg="true" />
     <group name="Settings">
-        <entry name="ShowHiddenFiles" key="ShowDotFiles" type="Bool" >
-            <label context="@label">Show hidden files</label>
+        <entry name="HiddenFilesShown" type="Bool" >
+            <label context="@label">Hidden files shown</label>
             <whatsthis context="@info:whatsthis">When this option is enabled hidden files, such as those starting with a '.', will be shown in the file view.</whatsthis>
             <default>false</default>
         </entry>
@@ -18,7 +18,7 @@
         <entry name="Version" type="Int" >
             <label context="@label">Version</label>
             <whatsthis context="@info:whatsthis">This option defines the used version of the view properties.</whatsthis>
-            <default>1</default>
+            <default>2</default>
             <min>1</min>
         </entry>
 
             <label context="@label">View Mode</label>
             <whatsthis context="@info:whatsthis">This option controls the style of the view. Currently supported values include icons (0), details (1) and column (2) views.</whatsthis>
             <default>DolphinView::IconsView</default>
-            <min>0</min>
-            <max code="true">DolphinView::MaxModeEnum</max>
         </entry>
 
-        <entry name="ShowPreview" type="Bool" >
-            <label context="@label">Show preview</label>
+        <entry name="PreviewsShown" type="Bool" >
+            <label context="@label">Previews shown</label>
             <whatsthis context="@info:whatsthis">When this option is enabled, a preview of the file content is shown as an icon.</whatsthis>
             <default>false</default>
         </entry>
@@ -46,8 +44,6 @@
             <label context="@label">Sort files by</label>
             <whatsthis context="@info:whatsthis">This option defines which attribute (name, size, date, etc.) sorting is performed on.</whatsthis>
             <default code="true">DolphinView::SortByName</default>
-            <min>0</min>
-            <max code="true">DolphinView::MaxSortingEnum</max>
         </entry>
 
         <entry name="SortOrder" type="Int" >
             <default>true</default>
         </entry>
 
-        <entry name="AdditionalInfo" type="Int">
-            <label context="@label">Additional information (deprecated, use AdditionInfoV2 instead)</label>
-            <default>0</default>
-        </entry>
-
-        <entry name="AdditionalInfoV2" type="StringList">
+        <entry name="AdditionalInfo" type="StringList">
             <label context="@label">Additional information</label>
             <default></default>
         </entry>
index f50ab3eadf1ebd13828f793889db816c4ca45c1c..fb01a8c6517ae6d04db05474337d2733342b25f9 100644 (file)
@@ -6,13 +6,8 @@
       http://www.kde.org/standards/kcfg/1.0/kcfg.xsd">
     <include>kglobalsettings.h</include>
     <include>kiconloader.h</include>
-    <include>QListView</include>
     <kcfgfile name="dolphinrc"/>
     <group name="IconsMode">
-        <entry name="Arrangement" type="Int">
-            <label>Arrangement</label>
-            <default code="true">QListView::TopToBottom</default>
-        </entry>
         <entry name="UseSystemFont" type="Bool">
             <label>Use system font</label>
             <default>true</default>
             <label>Font weight</label>
             <default>0</default>
         </entry>
-        <entry name="ItemHeight" type="Int">
-            <label>Item height</label>
-            <!--
-                 check 'void IconsViewSettingsPage::applySettings()' as reference (iconsviewsettingspage.cpp):
-                 itemHeight += fontHeight * numberOfTextlines + 10;
-            /-->
-            <default code="true">KIconLoader::SizeMedium + QFontMetrics(KGlobalSettings::generalFont()).height() * 2 + 10</default>
-        </entry>
-        <entry name="ItemWidth" type="Int">
-            <label>Item width</label>
-            <!--
-                 check 'void IconsViewSettingsPage::applySettings()' as reference (iconsviewsettingspage.cpp):
-                 itemWidth = TopToBottomBase + textSizeIndex * TopToBottomInc;
-            /-->
-            <default>96</default>
-        </entry>
-        <entry name="GridSpacing" type="Int">
-            <label>Grid spacing</label>
-            <default>8</default>
-        </entry>
         <entry name="IconSize" type="Int">
             <label>Icon size</label>
             <default code="true">KIconLoader::SizeMedium</default>
         </entry>
-        <entry name="NumberOfTextlines" type="Int">
-            <label>Number of textlines</label>
-            <!-- don't forget adjusting the "ItemHeight" too when changing this value /-->
-            <default>2</default>
-        </entry>
         <entry name="PreviewSize" type="Int">
             <label>Preview size</label>
             <default code="true">KIconLoader::SizeHuge</default>
         </entry>
+        <entry name="TextWidthIndex" type="Int">
+            <label>Text width index</label>
+            <default>1</default>
+        </entry>
     </group>
 </kcfg>
index 9987ce93893109bd61dced3ef82ec9f017d89027..9ab145bc2ce4feb2a0de0cff29230a1980dc78a0 100644 (file)
@@ -1,4 +1,4 @@
 File=dolphin_iconsmodesettings.kcfg
 ClassName=IconsModeSettings
-Singleton=false 
+Singleton=yes
 Mutators=true
index 7f160b1410c6c41c77dc7ccf75a6775ecac941c0..9fc0cea3d3f7b0768a9b39163e13efafde5e8847 100644 (file)
@@ -25,7 +25,6 @@
 #include <KLocale>
 #include <KStandardDirs>
 
-#include "dolphin_columnmodesettings.h"
 #include "dolphin_detailsmodesettings.h"
 #include "dolphin_generalsettings.h"
 #include "dolphin_iconsmodesettings.h"
@@ -45,17 +44,11 @@ DolphinSettings& DolphinSettings::instance()
 void DolphinSettings::save()
 {
     m_generalSettings->writeConfig();
-    m_iconsModeSettings->writeConfig();
-    m_detailsModeSettings->writeConfig();
-    m_columnModeSettings->writeConfig();
 }
 
 DolphinSettings::DolphinSettings()
 {
     m_generalSettings = new GeneralSettings();
-    m_iconsModeSettings = new IconsModeSettings();
-    m_detailsModeSettings = new DetailsModeSettings();
-    m_columnModeSettings = new ColumnModeSettings();
     m_placesModel = new KFilePlacesModel();
 }
 
@@ -64,15 +57,6 @@ DolphinSettings::~DolphinSettings()
     delete m_generalSettings;
     m_generalSettings = 0;
 
-    delete m_iconsModeSettings;
-    m_iconsModeSettings = 0;
-
-    delete m_detailsModeSettings;
-    m_detailsModeSettings = 0;
-
-    delete m_columnModeSettings;
-    m_columnModeSettings = 0;
-
     delete m_placesModel;
     m_placesModel = 0;
 }
index 54141ad3e094f282f618f512720ae82245b615fc..88e1d29054b785dea992e8b38e6029d6ad5d82b6 100644 (file)
 
 #include <libdolphin_export.h>
 
-class ColumnModeSettings;
-class DetailsModeSettings;
 class GeneralSettings;
-class IconsModeSettings;
 class KFilePlacesModel;
 
+// TODO: Remove this class completely and just work with the settings directly instead
+
 /**
  * @brief Manages and stores all settings from Dolphin.
  *
@@ -46,9 +45,6 @@ public:
     static DolphinSettings& instance();
 
     GeneralSettings* generalSettings() const;
-    IconsModeSettings* iconsModeSettings() const;
-    DetailsModeSettings* detailsModeSettings() const;
-    ColumnModeSettings* columnModeSettings() const;
     KFilePlacesModel* placesModel() const;
     virtual void save();
 
@@ -59,9 +55,6 @@ protected:
 
 private:
     GeneralSettings* m_generalSettings;
-    IconsModeSettings* m_iconsModeSettings;
-    DetailsModeSettings* m_detailsModeSettings;
-    ColumnModeSettings* m_columnModeSettings;
     KFilePlacesModel* m_placesModel;
 };
 
@@ -70,21 +63,6 @@ inline GeneralSettings* DolphinSettings::generalSettings() const
     return m_generalSettings;
 }
 
-inline IconsModeSettings* DolphinSettings::iconsModeSettings() const
-{
-    return m_iconsModeSettings;
-}
-
-inline DetailsModeSettings* DolphinSettings::detailsModeSettings() const
-{
-    return m_detailsModeSettings;
-}
-
-inline ColumnModeSettings* DolphinSettings::columnModeSettings() const
-{
-    return m_columnModeSettings;
-}
-
 inline KFilePlacesModel* DolphinSettings::placesModel() const
 {
     return m_placesModel;
index b5ed44f63735bf19f5be5cf553308bba70e0e369..4e49257cea3a2b85d1863c53b9e9fffedb8505da 100644 (file)
@@ -25,7 +25,6 @@
 #include <KPluginFactory>
 #include <KPluginLoader>
 
-#include <settings/viewmodes/columnviewsettingspage.h>
 #include <settings/viewmodes/detailsviewsettingspage.h>
 #include <settings/viewmodes/iconsviewsettingspage.h>
 
@@ -59,19 +58,15 @@ DolphinViewModesConfigModule::DolphinViewModesConfigModule(QWidget* parent, cons
     tabWidget->addTab(iconsPage, KIcon("view-list-icons"), i18nc("@title:tab", "Icons"));
     connect(iconsPage, SIGNAL(changed()), this, SLOT(changed()));
 
+    // TODO: initialize 'Compact' tab
+
     // initialize 'Details' tab
     DetailsViewSettingsPage* detailsPage = new DetailsViewSettingsPage(tabWidget);
-    tabWidget->addTab(detailsPage, KIcon("view-list-details"), i18nc("@title:tab", "Details"));
+    tabWidget->addTab(detailsPage, KIcon("view-list-text"), i18nc("@title:tab", "Details"));
     connect(detailsPage, SIGNAL(changed()), this, SLOT(changed()));
 
-    // initialize 'Column' tab
-    ColumnViewSettingsPage* columnPage = new ColumnViewSettingsPage(tabWidget);
-    tabWidget->addTab(columnPage, KIcon("view-file-columns"), i18nc("@title:tab", "Column"));
-    connect(columnPage, SIGNAL(changed()), this, SLOT(changed()));
-
     m_pages.append(iconsPage);
     m_pages.append(detailsPage);
-    m_pages.append(columnPage);
 
     topLayout->addWidget(tabWidget, 0, 0);
 }
diff --git a/src/settings/viewmodes/columnviewsettingspage.cpp b/src/settings/viewmodes/columnviewsettingspage.cpp
deleted file mode 100644 (file)
index 888e35d..0000000
+++ /dev/null
@@ -1,158 +0,0 @@
-/***************************************************************************
- *   Copyright (C) 2006 by Peter Penz <peter.penz19@gmail.com>             *
- *                                                                         *
- *   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 program 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 program; if not, write to the                         *
- *   Free Software Foundation, Inc.,                                       *
- *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA            *
- ***************************************************************************/
-
-#include "columnviewsettingspage.h"
-
-#include "dolphinfontrequester.h"
-#include <dolphin_columnmodesettings.h>
-#include "iconsizegroupbox.h"
-
-#include <KDialog>
-#include <KLocale>
-#include <KComboBox>
-
-#include <settings/dolphinsettings.h>
-
-#include <QButtonGroup>
-#include <QCheckBox>
-#include <QGroupBox>
-#include <QHBoxLayout>
-#include <QLabel>
-#include <QSlider>
-#include <QRadioButton>
-
-#include <views/zoomlevelinfo.h>
-
-ColumnViewSettingsPage::ColumnViewSettingsPage(QWidget* parent) :
-    ViewSettingsPageBase(parent),
-    m_iconSizeGroupBox(0),
-    m_fontRequester(0),
-    m_textWidthBox(0)
-{
-    const int spacing = KDialog::spacingHint();
-    const int margin = KDialog::marginHint();
-    const QSizePolicy sizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
-
-    setSpacing(spacing);
-    setMargin(margin);
-
-    // Create "Icon" properties
-    m_iconSizeGroupBox = new IconSizeGroupBox(this);
-    m_iconSizeGroupBox->setSizePolicy(sizePolicy);
-
-    const int min = ZoomLevelInfo::minimumLevel();
-    const int max = ZoomLevelInfo::maximumLevel();
-    m_iconSizeGroupBox->setDefaultSizeRange(min, max);
-    m_iconSizeGroupBox->setPreviewSizeRange(min, max);
-
-    // create "Text" properties
-    QGroupBox* textGroup = new QGroupBox(i18nc("@title:group", "Text"), this);
-    textGroup->setSizePolicy(sizePolicy);
-
-    QLabel* fontLabel = new QLabel(i18nc("@label:listbox", "Font:"), textGroup);
-    m_fontRequester = new DolphinFontRequester(textGroup);
-
-    QLabel* textWidthLabel = new QLabel(i18nc("@label:listbox", "Text width:"), textGroup);
-    m_textWidthBox = new KComboBox(textGroup);
-    m_textWidthBox->addItem(i18nc("@item:inlistbox Text width", "Small"));
-    m_textWidthBox->addItem(i18nc("@item:inlistbox Text width", "Medium"));
-    m_textWidthBox->addItem(i18nc("@item:inlistbox Text width", "Large"));
-    m_textWidthBox->addItem(i18nc("@item:inlistbox Text width", "Huge"));
-
-    QGridLayout* textGroupLayout = new QGridLayout(textGroup);
-    textGroupLayout->addWidget(fontLabel, 0, 0, Qt::AlignRight);
-    textGroupLayout->addWidget(m_fontRequester, 0, 1);
-    textGroupLayout->addWidget(textWidthLabel, 1, 0, Qt::AlignRight);
-    textGroupLayout->addWidget(m_textWidthBox, 1, 1);
-
-    // Add a dummy widget with no restriction regarding
-    // a vertical resizing. This assures that the dialog layout
-    // is not stretched vertically.
-    new QWidget(this);
-
-    loadSettings();
-
-    connect(m_iconSizeGroupBox, SIGNAL(defaultSizeChanged(int)), this, SIGNAL(changed()));
-    connect(m_iconSizeGroupBox, SIGNAL(previewSizeChanged(int)), this, SIGNAL(changed()));
-    connect(m_fontRequester, SIGNAL(changed()), this, SIGNAL(changed()));
-    connect(m_textWidthBox, SIGNAL(currentIndexChanged(int)), this, SIGNAL(changed()));
-}
-
-ColumnViewSettingsPage::~ColumnViewSettingsPage()
-{
-}
-
-void ColumnViewSettingsPage::applySettings()
-{
-    ColumnModeSettings* settings = DolphinSettings::instance().columnModeSettings();
-
-    const int iconSize = ZoomLevelInfo::iconSizeForZoomLevel(m_iconSizeGroupBox->defaultSizeValue());
-    const int previewSize = ZoomLevelInfo::iconSizeForZoomLevel(m_iconSizeGroupBox->previewSizeValue());
-    settings->setIconSize(iconSize);
-    settings->setPreviewSize(previewSize);
-
-    const QFont font = m_fontRequester->font();
-    settings->setUseSystemFont(m_fontRequester->mode() == DolphinFontRequester::SystemFont);
-    settings->setFontFamily(font.family());
-    settings->setFontSize(font.pointSizeF());
-    settings->setItalicFont(font.italic());
-    settings->setFontWeight(font.weight());
-
-    const int columnWidth = BaseTextWidth + (m_textWidthBox->currentIndex() * TextInc);
-    settings->setColumnWidth(columnWidth);
-
-    settings->writeConfig();
-}
-
-void ColumnViewSettingsPage::restoreDefaults()
-{
-    ColumnModeSettings* settings = DolphinSettings::instance().columnModeSettings();
-    settings->useDefaults(true);
-    loadSettings();
-    settings->useDefaults(false);
-}
-
-void ColumnViewSettingsPage::loadSettings()
-{
-    ColumnModeSettings* settings = DolphinSettings::instance().columnModeSettings();
-
-    const QSize iconSize(settings->iconSize(), settings->iconSize());
-    const int iconSizeValue = ZoomLevelInfo::zoomLevelForIconSize(iconSize);
-    m_iconSizeGroupBox->setDefaultSizeValue(iconSizeValue);
-
-    const QSize previewSize(settings->previewSize(), settings->previewSize());
-    const int previewSizeValue = ZoomLevelInfo::zoomLevelForIconSize(previewSize);
-    m_iconSizeGroupBox->setPreviewSizeValue(previewSizeValue);
-
-    if (settings->useSystemFont()) {
-        m_fontRequester->setMode(DolphinFontRequester::SystemFont);
-    } else {
-        QFont font(settings->fontFamily(),
-                   qRound(settings->fontSize()));
-        font.setItalic(settings->italicFont());
-        font.setWeight(settings->fontWeight());
-        font.setPointSizeF(settings->fontSize());
-        m_fontRequester->setMode(DolphinFontRequester::CustomFont);
-        m_fontRequester->setCustomFont(font);
-    }
-
-    m_textWidthBox->setCurrentIndex((settings->columnWidth() - BaseTextWidth) / TextInc);
-}
-
-#include "columnviewsettingspage.moc"
index fbf26902f11dd435c7840859b1d895d54a9bf656..b2338dc9b90a6c98450fb38c3773db258a8cdb54 100644 (file)
@@ -26,8 +26,6 @@
 #include <KDialog>
 #include <KLocale>
 
-#include <settings/dolphinsettings.h>
-
 #include <QButtonGroup>
 #include <QCheckBox>
 #include <QComboBox>
@@ -42,8 +40,7 @@
 DetailsViewSettingsPage::DetailsViewSettingsPage(QWidget* parent) :
     ViewSettingsPageBase(parent),
     m_iconSizeGroupBox(0),
-    m_fontRequester(0),
-    m_expandableFolders(0)
+    m_fontRequester(0)
 {
     const int spacing = KDialog::spacingHint();
     const int margin = KDialog::marginHint();
@@ -72,9 +69,6 @@ DetailsViewSettingsPage::DetailsViewSettingsPage(QWidget* parent) :
     textLayout->addWidget(fontLabel, 0, Qt::AlignRight);
     textLayout->addWidget(m_fontRequester);
 
-    // create "Expandable Folders" checkbox
-    m_expandableFolders = new QCheckBox(i18nc("@option:check", "Expandable folders"), this);
-
     // Add a dummy widget with no restriction regarding
     // a vertical resizing. This assures that the dialog layout
     // is not stretched vertically.
@@ -85,7 +79,6 @@ DetailsViewSettingsPage::DetailsViewSettingsPage(QWidget* parent) :
     connect(m_iconSizeGroupBox, SIGNAL(defaultSizeChanged(int)), this, SIGNAL(changed()));
     connect(m_iconSizeGroupBox, SIGNAL(previewSizeChanged(int)), this, SIGNAL(changed()));
     connect(m_fontRequester, SIGNAL(changed()), this, SIGNAL(changed()));
-    connect(m_expandableFolders, SIGNAL(toggled(bool)), this, SIGNAL(changed()));
 }
 
 DetailsViewSettingsPage::~DetailsViewSettingsPage()
@@ -94,58 +87,49 @@ DetailsViewSettingsPage::~DetailsViewSettingsPage()
 
 void DetailsViewSettingsPage::applySettings()
 {
-    DetailsModeSettings* settings = DolphinSettings::instance().detailsModeSettings();
-
     const int iconSize = ZoomLevelInfo::iconSizeForZoomLevel(m_iconSizeGroupBox->defaultSizeValue());
     const int previewSize = ZoomLevelInfo::iconSizeForZoomLevel(m_iconSizeGroupBox->previewSizeValue());
-    settings->setIconSize(iconSize);
-    settings->setPreviewSize(previewSize);
+    DetailsModeSettings::setIconSize(iconSize);
+    DetailsModeSettings::setPreviewSize(previewSize);
 
     const QFont font = m_fontRequester->font();
-    settings->setUseSystemFont(m_fontRequester->mode() == DolphinFontRequester::SystemFont);
-    settings->setFontFamily(font.family());
-    settings->setFontSize(font.pointSizeF());
-    settings->setItalicFont(font.italic());
-    settings->setFontWeight(font.weight());
+    DetailsModeSettings::setUseSystemFont(m_fontRequester->mode() == DolphinFontRequester::SystemFont);
+    DetailsModeSettings::setFontFamily(font.family());
+    DetailsModeSettings::setFontSize(font.pointSizeF());
+    DetailsModeSettings::setItalicFont(font.italic());
+    DetailsModeSettings::setFontWeight(font.weight());
 
-    settings->setExpandableFolders(m_expandableFolders->isChecked());
-
-    settings->writeConfig();
+    DetailsModeSettings::self()->writeConfig();
 }
 
 void DetailsViewSettingsPage::restoreDefaults()
 {
-    DetailsModeSettings* settings = DolphinSettings::instance().detailsModeSettings();
-    settings->useDefaults(true);
+    DetailsModeSettings::self()->useDefaults(true);
     loadSettings();
-    settings->useDefaults(false);
+    DetailsModeSettings::self()->useDefaults(false);
 }
 
 void DetailsViewSettingsPage::loadSettings()
 {
-    DetailsModeSettings* settings = DolphinSettings::instance().detailsModeSettings();
-
-    const QSize iconSize(settings->iconSize(), settings->iconSize());
+    const QSize iconSize(DetailsModeSettings::iconSize(), DetailsModeSettings::iconSize());
     const int iconSizeValue = ZoomLevelInfo::zoomLevelForIconSize(iconSize);
     m_iconSizeGroupBox->setDefaultSizeValue(iconSizeValue);
 
-    const QSize previewSize(settings->previewSize(), settings->previewSize());
+    const QSize previewSize(DetailsModeSettings::previewSize(), DetailsModeSettings::previewSize());
     const int previewSizeValue = ZoomLevelInfo::zoomLevelForIconSize(previewSize);
     m_iconSizeGroupBox->setPreviewSizeValue(previewSizeValue);
 
-    if (settings->useSystemFont()) {
+    if (DetailsModeSettings::useSystemFont()) {
         m_fontRequester->setMode(DolphinFontRequester::SystemFont);
     } else {
-        QFont font(settings->fontFamily(),
-                   qRound(settings->fontSize()));
-        font.setItalic(settings->italicFont());
-        font.setWeight(settings->fontWeight());
-        font.setPointSizeF(settings->fontSize());
+        QFont font(DetailsModeSettings::fontFamily(),
+                   qRound(DetailsModeSettings::fontSize()));
+        font.setItalic(DetailsModeSettings::italicFont());
+        font.setWeight(DetailsModeSettings::fontWeight());
+        font.setPointSizeF(DetailsModeSettings::fontSize());
         m_fontRequester->setMode(DolphinFontRequester::CustomFont);
         m_fontRequester->setCustomFont(font);
     }
-
-    m_expandableFolders->setChecked(settings->expandableFolders());
 }
 
 #include "detailsviewsettingspage.moc"
index 73d911a320f40284b9b8a904819ad9d477ce58b4..9532241aa8737c2156c0ab80e5afd37d935e27dd 100644 (file)
@@ -24,7 +24,6 @@
 
 class DolphinFontRequester;
 class IconSizeGroupBox;
-class QCheckBox;
 
 /**
  * @brief Represents the page from the Dolphin Settings which allows
@@ -54,7 +53,6 @@ private:
 private:
     IconSizeGroupBox* m_iconSizeGroupBox;
     DolphinFontRequester* m_fontRequester;
-    QCheckBox* m_expandableFolders;
 };
 
 #endif
index 91ca738a16ece24a08fe848e0abd0be1f6ba4db1..41438fb22764199ff45909cbd0d12fc252f9db42 100644 (file)
@@ -20,7 +20,6 @@
 #include "iconsviewsettingspage.h"
 
 #include "dolphinfontrequester.h"
-#include "settings/dolphinsettings.h"
 #include "iconsizegroupbox.h"
 
 #include "dolphin_iconsmodesettings.h"
 #include <QCheckBox>
 #include <QGroupBox>
 #include <QLabel>
-#include <QListView>
 #include <QPushButton>
 #include <QGridLayout>
-#include <QVBoxLayout>
 
 #include <views/zoomlevelinfo.h>
 
@@ -46,10 +43,7 @@ IconsViewSettingsPage::IconsViewSettingsPage(QWidget* parent) :
     ViewSettingsPageBase(parent),
     m_iconSizeGroupBox(0),
     m_textWidthBox(0),
-    m_fontRequester(0),
-    m_textlinesCountBox(0),
-    m_arrangementBox(0),
-    m_gridSpacingBox(0)
+    m_fontRequester(0)
 {
     const int spacing = KDialog::spacingHint();
     const int margin = KDialog::marginHint();
@@ -67,7 +61,7 @@ IconsViewSettingsPage::IconsViewSettingsPage(QWidget* parent) :
     m_iconSizeGroupBox->setDefaultSizeRange(min, max);
     m_iconSizeGroupBox->setPreviewSizeRange(min, max);
 
-    // create 'Text' group for selecting the font, the number of lines
+    // Create 'Text' group for selecting the font, the number of lines
     // and the text width
     QGroupBox* textGroup = new QGroupBox(i18nc("@title:group", "Text"), this);
     textGroup->setSizePolicy(sizePolicy);
@@ -75,11 +69,6 @@ IconsViewSettingsPage::IconsViewSettingsPage(QWidget* parent) :
     QLabel* fontLabel = new QLabel(i18nc("@label:listbox", "Font:"), textGroup);
     m_fontRequester = new DolphinFontRequester(textGroup);
 
-    QLabel* textlinesCountLabel = new QLabel(i18nc("@label:textbox", "Number of lines:"), textGroup);
-    m_textlinesCountBox = new KIntSpinBox(textGroup);
-    m_textlinesCountBox->setMinimum(1);
-    m_textlinesCountBox->setMaximum(5);
-
     QLabel* textWidthLabel = new QLabel(i18nc("@label:listbox", "Text width:"), textGroup);
     m_textWidthBox = new KComboBox(textGroup);
     m_textWidthBox->addItem(i18nc("@item:inlistbox Text width", "Small"));
@@ -90,33 +79,9 @@ IconsViewSettingsPage::IconsViewSettingsPage(QWidget* parent) :
     QGridLayout* textGroupLayout = new QGridLayout(textGroup);
     textGroupLayout->addWidget(fontLabel, 0, 0, Qt::AlignRight);
     textGroupLayout->addWidget(m_fontRequester, 0, 1);
-    textGroupLayout->addWidget(textlinesCountLabel, 1, 0, Qt::AlignRight);
-    textGroupLayout->addWidget(m_textlinesCountBox, 1, 1);
     textGroupLayout->addWidget(textWidthLabel, 2, 0, Qt::AlignRight);
     textGroupLayout->addWidget(m_textWidthBox, 2, 1);
 
-    // create the 'Grid' group for selecting the arrangement and the grid spacing
-    QGroupBox* gridGroup = new QGroupBox(i18nc("@title:group", "Grid"), this);
-    gridGroup->setSizePolicy(sizePolicy);
-
-    QLabel* arrangementLabel = new QLabel(i18nc("@label:listbox", "Arrangement:"), gridGroup);
-    m_arrangementBox = new KComboBox(gridGroup);
-    m_arrangementBox->addItem(i18nc("@item:inlistbox Arrangement", "Columns"));
-    m_arrangementBox->addItem(i18nc("@item:inlistbox Arrangement", "Rows"));
-
-    QLabel* gridSpacingLabel = new QLabel(i18nc("@label:listbox", "Grid spacing:"), gridGroup);
-    m_gridSpacingBox = new KComboBox(gridGroup);
-    m_gridSpacingBox->addItem(i18nc("@item:inlistbox Grid spacing", "None"));
-    m_gridSpacingBox->addItem(i18nc("@item:inlistbox Grid spacing", "Small"));
-    m_gridSpacingBox->addItem(i18nc("@item:inlistbox Grid spacing", "Medium"));
-    m_gridSpacingBox->addItem(i18nc("@item:inlistbox Grid spacing", "Large"));
-
-    QGridLayout* gridGroupLayout = new QGridLayout(gridGroup);
-    gridGroupLayout->addWidget(arrangementLabel, 0, 0, Qt::AlignRight);
-    gridGroupLayout->addWidget(m_arrangementBox, 0, 1);
-    gridGroupLayout->addWidget(gridSpacingLabel, 1, 0, Qt::AlignRight);
-    gridGroupLayout->addWidget(m_gridSpacingBox, 1, 1);
-
     // Add a dummy widget with no restriction regarding
     // a vertical resizing. This assures that the dialog layout
     // is not stretched vertically.
@@ -127,10 +92,7 @@ IconsViewSettingsPage::IconsViewSettingsPage(QWidget* parent) :
     connect(m_iconSizeGroupBox, SIGNAL(defaultSizeChanged(int)), this, SIGNAL(changed()));
     connect(m_iconSizeGroupBox, SIGNAL(previewSizeChanged(int)), this, SIGNAL(changed()));
     connect(m_fontRequester, SIGNAL(changed()), this, SIGNAL(changed()));
-    connect(m_textlinesCountBox, SIGNAL(valueChanged(int)), this, SIGNAL(changed()));
     connect(m_textWidthBox, SIGNAL(currentIndexChanged(int)), this, SIGNAL(changed()));
-    connect(m_arrangementBox, SIGNAL(currentIndexChanged(int)), this, SIGNAL(changed()));
-    connect(m_gridSpacingBox, SIGNAL(currentIndexChanged(int)), this, SIGNAL(changed()));
 }
 
 IconsViewSettingsPage::~IconsViewSettingsPage()
@@ -139,108 +101,53 @@ IconsViewSettingsPage::~IconsViewSettingsPage()
 
 void IconsViewSettingsPage::applySettings()
 {
-    IconsModeSettings* settings = DolphinSettings::instance().iconsModeSettings();
-
     const int iconSize = ZoomLevelInfo::iconSizeForZoomLevel(m_iconSizeGroupBox->defaultSizeValue());
     const int previewSize = ZoomLevelInfo::iconSizeForZoomLevel(m_iconSizeGroupBox->previewSizeValue());
-    settings->setIconSize(iconSize);
-    settings->setPreviewSize(previewSize);
+    IconsModeSettings::setIconSize(iconSize);
+    IconsModeSettings::setPreviewSize(previewSize);
 
     const QFont font = m_fontRequester->font();
-    const int fontHeight = QFontMetrics(font).height();
-
-    const int arrangement = (m_arrangementBox->currentIndex() == 0) ?
-                            QListView::LeftToRight :
-                            QListView::TopToBottom;
-    settings->setArrangement(arrangement);
-
-    const int numberOfTextlines = m_textlinesCountBox->value();
-
-    const int defaultSize = settings->iconSize();
-    int itemWidth = defaultSize;
-    int itemHeight = defaultSize;
-    const int textSizeIndex = m_textWidthBox->currentIndex();
-    if (arrangement == QListView::TopToBottom) {
-        itemWidth += TopToBottomBase + textSizeIndex * TopToBottomInc;
-        itemHeight += fontHeight * numberOfTextlines + 10;
-    } else {
-        itemWidth += LeftToRightBase + textSizeIndex * LeftToRightInc;
-    }
-
-    settings->setItemWidth(itemWidth);
-    settings->setItemHeight(itemHeight);
-
-    settings->setUseSystemFont(m_fontRequester->mode() == DolphinFontRequester::SystemFont);
-    settings->setFontFamily(font.family());
-    settings->setFontSize(font.pointSizeF());
-    settings->setItalicFont(font.italic());
-    settings->setFontWeight(font.weight());
+    IconsModeSettings::setUseSystemFont(m_fontRequester->mode() == DolphinFontRequester::SystemFont);
+    IconsModeSettings::setFontFamily(font.family());
+    IconsModeSettings::setFontSize(font.pointSizeF());
+    IconsModeSettings::setItalicFont(font.italic());
+    IconsModeSettings::setFontWeight(font.weight());
 
-    settings->setNumberOfTextlines(numberOfTextlines);
+    IconsModeSettings::setTextWidthIndex(m_textWidthBox->currentIndex());
 
-    const int index = m_gridSpacingBox->currentIndex();
-    if (index == 0) {
-        // No grid spacing
-        settings->setGridSpacing(0);
-    } else {
-        settings->setGridSpacing(GridSpacingBase + (index - 1) * GridSpacingInc);
-    }
-
-    settings->writeConfig();
+    IconsModeSettings::self()->writeConfig();
 }
 
 void IconsViewSettingsPage::restoreDefaults()
 {
-    IconsModeSettings* settings = DolphinSettings::instance().iconsModeSettings();
-    settings->useDefaults(true);
+    IconsModeSettings::self()->useDefaults(true);
     loadSettings();
-    settings->useDefaults(false);
+    IconsModeSettings::self()->useDefaults(false);
 }
 
 void IconsViewSettingsPage::loadSettings()
 {
-    IconsModeSettings* settings = DolphinSettings::instance().iconsModeSettings();
-
-    const QSize iconSize(settings->iconSize(), settings->iconSize());
+    const QSize iconSize(IconsModeSettings::iconSize(), IconsModeSettings::iconSize());
     const int iconSizeValue = ZoomLevelInfo::zoomLevelForIconSize(iconSize);
     m_iconSizeGroupBox->setDefaultSizeValue(iconSizeValue);
 
-    const QSize previewSize(settings->previewSize(), settings->previewSize());
+    const QSize previewSize(IconsModeSettings::previewSize(), IconsModeSettings::previewSize());
     const int previewSizeValue = ZoomLevelInfo::zoomLevelForIconSize(previewSize);
     m_iconSizeGroupBox->setPreviewSizeValue(previewSizeValue);
 
-    if (settings->useSystemFont()) {
+    if (IconsModeSettings::useSystemFont()) {
         m_fontRequester->setMode(DolphinFontRequester::SystemFont);
     } else {
-        QFont font(settings->fontFamily(),
-                   qRound(settings->fontSize()));
-        font.setItalic(settings->italicFont());
-        font.setWeight(settings->fontWeight());
-        font.setPointSizeF(settings->fontSize());
+        QFont font(IconsModeSettings::fontFamily(),
+                   qRound(IconsModeSettings::fontSize()));
+        font.setItalic(IconsModeSettings::italicFont());
+        font.setWeight(IconsModeSettings::fontWeight());
+        font.setPointSizeF(IconsModeSettings::fontSize());
         m_fontRequester->setMode(DolphinFontRequester::CustomFont);
         m_fontRequester->setCustomFont(font);
     }
 
-    m_textlinesCountBox->setValue(settings->numberOfTextlines());
-
-    const bool leftToRightArrangement = (settings->arrangement() == QListView::LeftToRight);
-    int textWidthIndex = 0;
-    const int remainingWidth = settings->itemWidth() - settings->iconSize();
-    if (leftToRightArrangement) {
-        textWidthIndex = (remainingWidth - LeftToRightBase) / LeftToRightInc;
-    } else {
-        textWidthIndex = (remainingWidth - TopToBottomBase) / TopToBottomInc;
-    }
-    // ensure that chosen index is always valid
-    textWidthIndex = qMax(textWidthIndex, 0);
-    textWidthIndex = qMin(textWidthIndex, m_textWidthBox->count() - 1);
-
-    m_textWidthBox->setCurrentIndex(textWidthIndex);
-    m_arrangementBox->setCurrentIndex(leftToRightArrangement ? 0 : 1);
-
-    const int spacing = settings->gridSpacing();
-    const int index = (spacing <= 0) ? 0 : 1 + (spacing - GridSpacingBase) / GridSpacingInc;
-    m_gridSpacingBox->setCurrentIndex(index);
+    m_textWidthBox->setCurrentIndex(IconsModeSettings::textWidthIndex());
 }
 
 #include "iconsviewsettingspage.moc"
index 3b60cdf7f7aeff2fb11b4122ad088f968e988d11..ad829f131ffe530279f0a26d4a5c01d27e33ba01 100644 (file)
@@ -20,7 +20,6 @@
 #ifndef ICONSVIEWSETTINGSPAGE_H
 #define ICONSVIEWSETTINGSPAGE_H
 
-#include <views/dolphiniconsview.h>
 #include "viewsettingspagebase.h"
 
 class DolphinFontRequester;
@@ -36,10 +35,7 @@ class KIntSpinBox;
  * - icon size
  * - preview size
  * - text width
- * - grid spacing
  * - font
- * - number of text lines
- * - arrangement
  *
  * @see DolphinIconsViewSettings
  */
@@ -65,23 +61,9 @@ private:
     void loadSettings();
 
 private:
-    enum
-    {
-        GridSpacingBase =   8,
-        GridSpacingInc  =  12,
-        LeftToRightBase = 128,
-        LeftToRightInc  =  64,
-        TopToBottomBase =  32,
-        TopToBottomInc  =  32
-    };
-
     IconSizeGroupBox* m_iconSizeGroupBox;
     KComboBox* m_textWidthBox;
     DolphinFontRequester* m_fontRequester;
-    KIntSpinBox* m_textlinesCountBox;
-
-    KComboBox* m_arrangementBox;
-    KComboBox* m_gridSpacingBox;
 };
 
 #endif
index 4530d866df519acb407b6fc335750fd32f8c43cb..ac4ed929678fd0662cb54b3d4661840f6cc37d82 100644 (file)
@@ -20,7 +20,6 @@
 
 #include "viewsettingspage.h"
 
-#include "columnviewsettingspage.h"
 #include "iconsviewsettingspage.h"
 #include "detailsviewsettingspage.h"
 
@@ -46,19 +45,15 @@ ViewSettingsPage::ViewSettingsPage(QWidget* parent) :
     tabWidget->addTab(iconsPage, KIcon("view-list-icons"), i18nc("@title:tab", "Icons"));
     connect(iconsPage, SIGNAL(changed()), this, SIGNAL(changed()));
 
+    // TODO: initialize 'Compact' tab
+
     // initialize 'Details' tab
     DetailsViewSettingsPage* detailsPage = new DetailsViewSettingsPage(tabWidget);
-    tabWidget->addTab(detailsPage, KIcon("view-list-details"), i18nc("@title:tab", "Details"));
+    tabWidget->addTab(detailsPage, KIcon("view-list-text"), i18nc("@title:tab", "Details"));
     connect(detailsPage, SIGNAL(changed()), this, SIGNAL(changed()));
 
-    // initialize 'Column' tab
-    ColumnViewSettingsPage* columnPage = new ColumnViewSettingsPage(tabWidget);
-    tabWidget->addTab(columnPage, KIcon("view-file-columns"), i18nc("@title:tab", "Column"));
-    connect(columnPage, SIGNAL(changed()), this, SIGNAL(changed()));
-
     m_pages.append(iconsPage);
     m_pages.append(detailsPage);
-    m_pages.append(columnPage);
 
     topLayout->addWidget(tabWidget, 0, 0);
 }
index 2a35f7eb8bba8b1107f1edebcc06fc782135e918..5f57d6eb4fe50469de1540d0664a8d3c929f6e90 100644 (file)
@@ -52,7 +52,6 @@
 #include <QRadioButton>
 #include <QBoxLayout>
 
-#include <views/dolphinsortfilterproxymodel.h>
 #include <views/viewproperties.h>
 
 ViewPropertiesDialog::ViewPropertiesDialog(DolphinView* dolphinView) :
@@ -64,7 +63,7 @@ ViewPropertiesDialog::ViewPropertiesDialog(DolphinView* dolphinView) :
     m_sortOrder(0),
     m_sorting(0),
     m_sortFoldersFirst(0),
-    m_showPreview(0),
+    m_previewsShown(0),
     m_showInGroups(0),
     m_showHiddenFiles(0),
     m_additionalInfo(0),
@@ -97,8 +96,8 @@ ViewPropertiesDialog::ViewPropertiesDialog(DolphinView* dolphinView) :
     QLabel* viewModeLabel = new QLabel(i18nc("@label:listbox", "View mode:"), propsGrid);
     m_viewMode = new KComboBox(propsGrid);
     m_viewMode->addItem(KIcon("view-list-icons"), i18nc("@item:inlistbox", "Icons"));
-    m_viewMode->addItem(KIcon("view-list-details"), i18nc("@item:inlistbox", "Details"));
-    m_viewMode->addItem(KIcon("view-file-columns"), i18nc("@item:inlistbox", "Column"));
+    m_viewMode->addItem(KIcon("feffi"), i18nc("@item:inlistbox", "Compact")); // TODO: adjust icons
+    m_viewMode->addItem(KIcon("view-list-text"), i18nc("@item:inlistbox", "Details"));
 
     QLabel* sortingLabel = new QLabel(i18nc("@label:listbox", "Sorting:"), propsGrid);
     QWidget* sortingBox = new QWidget(propsGrid);
@@ -125,7 +124,7 @@ ViewPropertiesDialog::ViewPropertiesDialog(DolphinView* dolphinView) :
     // }
 #endif
     m_sortFoldersFirst = new QCheckBox(i18nc("@option:check", "Show folders first"));
-    m_showPreview = new QCheckBox(i18nc("@option:check", "Show preview"));
+    m_previewsShown = new QCheckBox(i18nc("@option:check", "Show preview"));
     m_showInGroups = new QCheckBox(i18nc("@option:check", "Show in groups"));
     m_showHiddenFiles = new QCheckBox(i18nc("@option:check", "Show hidden files"));
 
@@ -146,7 +145,7 @@ ViewPropertiesDialog::ViewPropertiesDialog(DolphinView* dolphinView) :
     QVBoxLayout* propsBoxLayout = new QVBoxLayout(propsBox);
     propsBoxLayout->addWidget(propsGrid);
     propsBoxLayout->addWidget(m_sortFoldersFirst);
-    propsBoxLayout->addWidget(m_showPreview);
+    propsBoxLayout->addWidget(m_previewsShown);
     propsBoxLayout->addWidget(m_showInGroups);
     propsBoxLayout->addWidget(m_showHiddenFiles);
     propsBoxLayout->addWidget(m_additionalInfo);
@@ -163,7 +162,7 @@ ViewPropertiesDialog::ViewPropertiesDialog(DolphinView* dolphinView) :
             this, SLOT(configureAdditionalInfo()));
     connect(m_sortFoldersFirst, SIGNAL(clicked()),
             this, SLOT(slotSortFoldersFirstChanged()));
-    connect(m_showPreview, SIGNAL(clicked()),
+    connect(m_previewsShown, SIGNAL(clicked()),
             this, SLOT(slotShowPreviewChanged()));
     connect(m_showInGroups, SIGNAL(clicked()),
             this, SLOT(slotCategorizedSortingChanged()));
@@ -249,17 +248,15 @@ void ViewPropertiesDialog::slotViewModeChanged(int index)
 {
     m_viewProps->setViewMode(static_cast<DolphinView::Mode>(index));
     markAsDirty(true);
-
-    const DolphinView::Mode mode = m_viewProps->viewMode();
-    m_showInGroups->setEnabled(mode == DolphinView::IconsView);
-    m_additionalInfo->setEnabled(mode != DolphinView::ColumnView);
 }
 
 void ViewPropertiesDialog::slotSortingChanged(int index)
 {
-    const DolphinView::Sorting sorting = DolphinSortFilterProxyModel::sortingForColumn(index);
-    m_viewProps->setSorting(sorting);
-    markAsDirty(true);
+    Q_UNUSED(index);
+    Q_ASSERT(false);
+    //const DolphinView::Sorting sorting = DolphinSortFilterProxyModel::sortingForColumn(index);
+    //m_viewProps->setSorting(sorting);
+    //markAsDirty(true);
 }
 
 void ViewPropertiesDialog::slotSortOrderChanged(int index)
@@ -284,15 +281,15 @@ void ViewPropertiesDialog::slotSortFoldersFirstChanged()
 
 void ViewPropertiesDialog::slotShowPreviewChanged()
 {
-    const bool show = m_showPreview->isChecked();
-    m_viewProps->setShowPreview(show);
+    const bool show = m_previewsShown->isChecked();
+    m_viewProps->setPreviewsShown(show);
     markAsDirty(true);
 }
 
 void ViewPropertiesDialog::slotShowHiddenFilesChanged()
 {
     const bool show = m_showHiddenFiles->isChecked();
-    m_viewProps->setShowHiddenFiles(show);
+    m_viewProps->setHiddenFilesShown(show);
     markAsDirty(true);
 }
 
@@ -304,22 +301,22 @@ void ViewPropertiesDialog::markAsDirty(bool isDirty)
 
 void ViewPropertiesDialog::configureAdditionalInfo()
 {
-    KFileItemDelegate::InformationList info = m_viewProps->additionalInfo();
+    QList<DolphinView::AdditionalInfo> infoList = m_viewProps->additionalInfoList();
     const bool useDefaultInfo = (m_viewProps->viewMode() == DolphinView::DetailsView) &&
-                                (info.isEmpty() || info.contains(KFileItemDelegate::NoInformation));
+                                (infoList.isEmpty() || infoList.contains(DolphinView::NoInfo));
     if (useDefaultInfo) {
         // Using the details view without any additional information (-> additional column)
         // makes no sense and leads to a usability problem as no viewport area is available
         // anymore. Hence as fallback provide at least a size and date column.
-        info.clear();
-        info.append(KFileItemDelegate::Size);
-        info.append(KFileItemDelegate::ModificationTime);
-        m_viewProps->setAdditionalInfo(info);
+        infoList.clear();
+        infoList.append(DolphinView::SizeInfo);
+        infoList.append(DolphinView::DateInfo);
+        m_viewProps->setAdditionalInfoList(infoList);
     }
 
-    QPointer<AdditionalInfoDialog> dialog = new AdditionalInfoDialog(this, info);
+    QPointer<AdditionalInfoDialog> dialog = new AdditionalInfoDialog(this, infoList);
     if (dialog->exec() == QDialog::Accepted) {
-        m_viewProps->setAdditionalInfo(dialog->informationList());
+        m_viewProps->setAdditionalInfoList(dialog->informationList());
         markAsDirty(true);
     }
     delete dialog;
@@ -383,9 +380,9 @@ void ViewPropertiesDialog::applyViewProperties()
     m_dolphinView->setSortOrder(m_viewProps->sortOrder());
     m_dolphinView->setSortFoldersFirst(m_viewProps->sortFoldersFirst());
     m_dolphinView->setCategorizedSorting(m_viewProps->categorizedSorting());
-    m_dolphinView->setAdditionalInfo(m_viewProps->additionalInfo());
-    m_dolphinView->setShowPreview(m_viewProps->showPreview());
-    m_dolphinView->setShowHiddenFiles(m_viewProps->showHiddenFiles());
+    m_dolphinView->setAdditionalInfoList(m_viewProps->additionalInfoList());
+    m_dolphinView->setPreviewsShown(m_viewProps->previewsShown());
+    m_dolphinView->setHiddenFilesShown(m_viewProps->hiddenFilesShown());
 
     m_viewProps->save();
 
@@ -409,12 +406,12 @@ void ViewPropertiesDialog::loadSettings()
 
     m_sortFoldersFirst->setChecked(m_viewProps->sortFoldersFirst());
     // load show preview, show in groups and show hidden files settings
-    m_showPreview->setChecked(m_viewProps->showPreview());
+    m_previewsShown->setChecked(m_viewProps->previewsShown());
 
     m_showInGroups->setChecked(m_viewProps->categorizedSorting());
     m_showInGroups->setEnabled(index == DolphinView::IconsView); // only the icons view supports categorized sorting
 
-    m_showHiddenFiles->setChecked(m_viewProps->showHiddenFiles());
+    m_showHiddenFiles->setChecked(m_viewProps->hiddenFilesShown());
     markAsDirty(false);
 }
 
index d2170f33181978ee4a32debc888dff2ad9598386..694cffe880fd01b0bdb6b6c3caa0e6a948413968 100644 (file)
@@ -73,7 +73,7 @@ private:
     KComboBox* m_sortOrder;
     KComboBox* m_sorting;
     QCheckBox* m_sortFoldersFirst;
-    QCheckBox* m_showPreview;
+    QCheckBox* m_previewsShown;
     QCheckBox* m_showInGroups;
     QCheckBox* m_showHiddenFiles;
     QPushButton* m_additionalInfo;
index 2433d73649dafe7f0bad5ee819181b9f7e7df00c..b005d45c687b5c546c257e5d34da376dc6a1b918 100644 (file)
@@ -48,10 +48,7 @@ DolphinStatusBar::DolphinStatusBar(QWidget* parent, DolphinView* view) :
     m_view(view),
     m_messageLabel(0),
     m_spaceInfo(0),
-    m_zoomWidget(0),
-    m_zoomOut(0),
     m_zoomSlider(0),
-    m_zoomIn(0),
     m_progressBar(0),
     m_stopButton(0),
     m_progress(100),
@@ -64,14 +61,8 @@ DolphinStatusBar::DolphinStatusBar(QWidget* parent, DolphinView* view) :
     // Initialize message label
     m_messageLabel = new KonqStatusBarMessageLabel(this);
 
-    // Initialize zoom slider
-    m_zoomWidget = new QWidget(this);
-
-    m_zoomOut = new QToolButton(m_zoomWidget);
-    m_zoomOut->setIcon(KIcon("file-zoom-out"));
-    m_zoomOut->setAutoRaise(true);
-
-    m_zoomSlider = new QSlider(Qt::Horizontal, m_zoomWidget);
+    // Initialize zoom widget
+    m_zoomSlider = new QSlider(Qt::Horizontal, this);
     m_zoomSlider->setPageStep(1);
 
     const int min = ZoomLevelInfo::minimumLevel();
@@ -80,23 +71,9 @@ DolphinStatusBar::DolphinStatusBar(QWidget* parent, DolphinView* view) :
     m_zoomSlider->setValue(view->zoomLevel());
     updateZoomSliderToolTip(view->zoomLevel());
 
-    m_zoomIn = new QToolButton(m_zoomWidget);
-    m_zoomIn->setIcon(KIcon("file-zoom-in"));
-    m_zoomIn->setAutoRaise(true);
-
-    // Initialize zoom widget layout
-    QHBoxLayout* zoomWidgetLayout = new QHBoxLayout(m_zoomWidget);
-    zoomWidgetLayout->setSpacing(0);
-    zoomWidgetLayout->setMargin(0);
-    zoomWidgetLayout->addWidget(m_zoomOut);
-    zoomWidgetLayout->addWidget(m_zoomSlider);
-    zoomWidgetLayout->addWidget(m_zoomIn);
-
     connect(m_zoomSlider, SIGNAL(valueChanged(int)), this, SLOT(setZoomLevel(int)));
     connect(m_zoomSlider, SIGNAL(sliderMoved(int)), this, SLOT(showZoomSliderToolTip(int)));
-    connect(m_view, SIGNAL(zoomLevelChanged(int)), m_zoomSlider, SLOT(setValue(int)));
-    connect(m_zoomOut, SIGNAL(clicked()), this, SLOT(zoomOut()));
-    connect(m_zoomIn, SIGNAL(clicked()), this, SLOT(zoomIn()));
+    connect(m_view, SIGNAL(zoomLevelChanged(int, int)), this, SLOT(slotZoomLevelChanged(int, int)));
 
     // Initialize space information
     m_spaceInfo = new StatusBarSpaceInfo(this);
@@ -123,8 +100,8 @@ DolphinStatusBar::DolphinStatusBar(QWidget* parent, DolphinView* view) :
 
     // Initialize top layout and size policies
     const int fontHeight = QFontMetrics(m_messageLabel->font()).height();
-    const int zoomWidgetHeight = m_zoomWidget->minimumSizeHint().height();
-    const int contentHeight = qMax(fontHeight, zoomWidgetHeight);
+    const int zoomSliderHeight = m_zoomSlider->minimumSizeHint().height();
+    const int contentHeight = qMax(fontHeight, zoomSliderHeight);
 
     m_messageLabel->setMinimumTextHeight(contentHeight);
 
@@ -132,14 +109,14 @@ DolphinStatusBar::DolphinStatusBar(QWidget* parent, DolphinView* view) :
     m_spaceInfo->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
 
     m_progressBar->setMaximumSize(200, contentHeight);
-    m_zoomWidget->setMaximumSize(150, contentHeight);
+    m_zoomSlider->setMaximumSize(150, contentHeight);
     m_zoomSlider->setMinimumWidth(30);
 
     QHBoxLayout* topLayout = new QHBoxLayout(this);
     topLayout->setMargin(0);
     topLayout->setSpacing(4);
     topLayout->addWidget(m_messageLabel);
-    topLayout->addWidget(m_zoomWidget);
+    topLayout->addWidget(m_zoomSlider);
     topLayout->addWidget(m_spaceInfo);
     topLayout->addWidget(m_stopButton);
     topLayout->addWidget(m_progressText);
@@ -317,7 +294,7 @@ void DolphinStatusBar::contextMenuEvent(QContextMenuEvent* event)
     } else if (action == showZoomSliderAction) {
         const bool visible = showZoomSliderAction->isChecked();
         settings->setShowZoomSlider(visible);
-        m_zoomWidget->setVisible(visible);
+        m_zoomSlider->setVisible(visible);
     } else if (action == showSpaceInfoAction) {
         const bool visible = showSpaceInfoAction->isChecked();
         settings->setShowSpaceInfo(visible);
@@ -332,24 +309,10 @@ void DolphinStatusBar::updateSpaceInfoContent(const KUrl& url)
 
 void DolphinStatusBar::setZoomLevel(int zoomLevel)
 {
-    m_zoomOut->setEnabled(zoomLevel > m_zoomSlider->minimum());
-    m_zoomIn->setEnabled(zoomLevel < m_zoomSlider->maximum());
     m_view->setZoomLevel(zoomLevel);
     updateZoomSliderToolTip(zoomLevel);
 }
 
-void DolphinStatusBar::zoomOut()
-{
-    const int value = m_zoomSlider->value();
-    m_zoomSlider->setValue(value - 1);
-}
-
-void DolphinStatusBar::zoomIn()
-{
-    const int value = m_zoomSlider->value();
-    m_zoomSlider->setValue(value + 1);
-}
-
 void DolphinStatusBar::showZoomSliderToolTip(int zoomLevel)
 {
     updateZoomSliderToolTip(zoomLevel);
@@ -360,6 +323,12 @@ void DolphinStatusBar::showZoomSliderToolTip(int zoomLevel)
     QApplication::sendEvent(m_zoomSlider, &toolTipEvent);
 }
 
+void DolphinStatusBar::slotZoomLevelChanged(int current, int previous)
+{
+    Q_UNUSED(previous);
+    m_zoomSlider->setValue(current);
+}
+
 void DolphinStatusBar::updateProgressInfo()
 {
     const bool isErrorShown = (m_messageLabel->type() == KonqStatusBarMessageLabel::Error);
@@ -383,14 +352,14 @@ void DolphinStatusBar::updateProgressInfo()
 void DolphinStatusBar::setExtensionsVisible(bool visible)
 {
     bool showSpaceInfo = visible;
-    bool showZoomWidget = visible;
+    bool showZoomSlider = visible;
     if (visible) {
         const GeneralSettings* settings = DolphinSettings::instance().generalSettings();
         showSpaceInfo = settings->showSpaceInfo();
-        showZoomWidget = settings->showZoomSlider();
+        showZoomSlider = settings->showZoomSlider();
     }
     m_spaceInfo->setVisible(showSpaceInfo);
-    m_zoomWidget->setVisible(showZoomWidget);
+    m_zoomSlider->setVisible(showZoomSlider);
 }
 
 void DolphinStatusBar::updateZoomSliderToolTip(int zoomLevel)
index 56244001be17ff49068a51da2ffcf0236df426d0..7d56746f638417efdb56a792a076fb72bde3f07a 100644 (file)
@@ -137,9 +137,8 @@ private slots:
      */
     void setZoomLevel(int zoomLevel);
 
-    void zoomOut();
-    void zoomIn();
     void showZoomSliderToolTip(int zoomLevel);
+    void slotZoomLevelChanged(int current, int previous);
 
     void updateProgressInfo();
 
@@ -163,10 +162,7 @@ private:
     KonqStatusBarMessageLabel* m_messageLabel;
     StatusBarSpaceInfo* m_spaceInfo;
 
-    QWidget* m_zoomWidget;
-    QToolButton* m_zoomOut;
     QSlider* m_zoomSlider;
-    QToolButton* m_zoomIn;
 
     QLabel* m_progressText;
     QProgressBar* m_progressBar;
index e10f8d0c93c64ccc1cf06b5a193ba70ff0756a83..5038ee8d7d7a04d9bfedef79aef446d71725f1e6 100644 (file)
@@ -1,9 +1,27 @@
 set( EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR} )
 include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/.. ${CMAKE_CURRENT_BUILD_DIR}/.. ${KDE4_INCLUDES} )
 
-# DolphinDetailsView
-kde4_add_unit_test(dolphindetailsviewtest TEST dolphindetailsviewtest.cpp testdir.cpp testbase.cpp ../views/zoomlevelinfo.cpp)
-target_link_libraries(dolphindetailsviewtest dolphinprivate ${KDE4_KIO_LIBS} ${QT_QTTEST_LIBRARY})
+# KFileItemListViewTest
+set(kfileitemlistviewtest_SRCS
+    kfileitemlistviewtest.cpp
+    testdir.cpp
+    ../kitemviews/kfileitemmodel.cpp
+    ../kitemviews/kfileitemlistview.cpp
+    ../kitemviews/kitemmodelbase.cpp
+    ../kitemviews/kitemlistview.cpp
+)
+kde4_add_unit_test(kfileitemlistviewtest TEST ${kfileitemlistviewtest_SRCS})
+target_link_libraries(kfileitemlistviewtest dolphinprivate ${KDE4_KIO_LIBS} ${QT_QTTEST_LIBRARY})
+
+# KFileItemModelTest
+set(kfileitemmodeltest_SRCS
+    kfileitemmodeltest.cpp
+    testdir.cpp
+    ../kitemviews/kfileitemmodel.cpp
+    ../kitemviews/kitemmodelbase.cpp
+)
+kde4_add_unit_test(kfileitemmodeltest TEST ${kfileitemmodeltest_SRCS})
+target_link_libraries(kfileitemmodeltest dolphinprivate ${KDE4_KIO_LIBS} ${QT_QTTEST_LIBRARY})
 
 # DolphinSearchBox
 if (Nepomuk_FOUND)
@@ -18,20 +36,3 @@ if (Nepomuk_FOUND)
   kde4_add_unit_test(dolphinsearchboxtest TEST ${dolphinsearchboxtest_SRCS})
   target_link_libraries(dolphinsearchboxtest ${KDE4_KIO_LIBS} ${SOPRANO_LIBRARIES} ${NEPOMUK_LIBRARIES} ${NEPOMUK_QUERY_LIBRARIES} nepomukutils ${QT_QTTEST_LIBRARY})
 endif (Nepomuk_FOUND)
-
-
-# DolphinTreeView
-kde4_add_unit_test(dolphintreeviewtest TEST dolphintreeviewtest.cpp)
-target_link_libraries(dolphintreeviewtest dolphinprivate ${KDE4_KDEUI_LIBS} ${QT_QTTEST_LIBRARY})
-
-# DolphinView - columns
-kde4_add_unit_test(dolphinviewtest_columns TEST dolphinviewtest_columns.cpp dolphinviewtest_allviewmodes.cpp testdir.cpp testbase.cpp ../views/zoomlevelinfo.cpp)
-target_link_libraries(dolphinviewtest_columns dolphinprivate ${KDE4_KIO_LIBS} ${QT_QTTEST_LIBRARY})
-
-# DolphinView - details
-kde4_add_unit_test(dolphinviewtest_details TEST dolphinviewtest_details.cpp dolphinviewtest_allviewmodes.cpp testdir.cpp testbase.cpp ../views/zoomlevelinfo.cpp)
-target_link_libraries(dolphinviewtest_details dolphinprivate ${KDE4_KIO_LIBS} ${QT_QTTEST_LIBRARY})
-
-# DolphinView - icons
-kde4_add_unit_test(dolphinviewtest_icons TEST dolphinviewtest_icons.cpp dolphinviewtest_allviewmodes.cpp testdir.cpp testbase.cpp ../views/zoomlevelinfo.cpp)
-target_link_libraries(dolphinviewtest_icons dolphinprivate ${KDE4_KIO_LIBS} ${QT_QTTEST_LIBRARY})
diff --git a/src/tests/dolphindetailsviewtest.cpp b/src/tests/dolphindetailsviewtest.cpp
deleted file mode 100644 (file)
index 31b4a57..0000000
+++ /dev/null
@@ -1,304 +0,0 @@
-/***************************************************************************
- *   Copyright (C) 2010 by Frank Reininghaus (frank78ac@googlemail.com)    *
- *                                                                         *
- *   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 program 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 program; if not, write to the                         *
- *   Free Software Foundation, Inc.,                                       *
- *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA            *
- ***************************************************************************/
-
-#include <qtest_kde.h>
-
-#include "testbase.h"
-#include "testdir.h"
-
-#include "views/dolphindetailsview.h"
-#include "views/dolphinview.h"
-#include "views/dolphinmodel.h"
-#include "views/dolphinsortfilterproxymodel.h"
-#include "views/zoomlevelinfo.h"
-
-#include <qtestmouse.h>
-#include <qtestkeyboard.h>
-
-class DolphinDetailsViewTest : public TestBase
-{
-    Q_OBJECT
-
-private slots:
-
-    void testExpandedUrls();
-
-    void bug217447_shiftArrowSelection();
-    void bug234600_overlappingIconsWhenZooming();
-    void bug257401_longFilenamesKeyboardNavigation();
-
-private:
-
-    /**
-     * initView(DolphinView*) sets the correct view mode, shows the view on the screen, and waits
-     * until loading the folder in the view is finished.
-     *
-     * Many unit tests need access to the internal DolphinDetailsView in DolphinView.
-     * Therefore, a pointer to the details view is returned by initView(DolphinView*).
-     */
-    DolphinDetailsView* initView(DolphinView* view) const {
-        QSignalSpy spyFinishedPathLoading(view, SIGNAL(finishedPathLoading(const KUrl&)));
-        view->setMode(DolphinView::DetailsView);
-        DolphinDetailsView* detailsView = qobject_cast<DolphinDetailsView*>(itemView(view));
-        Q_ASSERT(detailsView);
-        detailsView->setFoldersExpandable(true);
-        view->resize(400, 400);
-        view->show();
-        QTest::qWaitForWindowShown(view);
-
-        // If the DolphinView's finishedPathLoading(const KUrl&) signal has not been received yet,
-        // we have to wait a bit more.
-        // The reason why the if-statement is needed here is that the signal might have been emitted
-        // while we were waiting in QTest::qWaitForWindowShown(view)
-        // -> waitForFinishedPathLoading(view) would fail in that case.
-        if (spyFinishedPathLoading.isEmpty()) {
-            waitForFinishedPathLoading(view);
-        }
-
-        return detailsView;
-    }
-
-    QModelIndex proxyModelIndexForUrl(const DolphinView* view, const KUrl& url) const {
-        const QModelIndex index = view->m_viewAccessor.m_dolphinModel->indexForUrl(url);
-        return view->m_viewAccessor.m_proxyModel->mapFromSource(index);
-    }
-};
-
-/**
- * This test verifies that DolphinDetailsView::expandedUrls() returns the right set of URLs.
- * The test creates a folder hierarchy: 3 folders (a, b, c) contain 3 subfolders (also named a, b, c) each.
- * Each of those contains 3 further subfolders of the same name.
- */
-
-void DolphinDetailsViewTest::testExpandedUrls()
-{
-    QStringList files;
-    QStringList subFolderNames;
-    subFolderNames << "a" << "b" << "c";
-
-    foreach(const QString& level1, subFolderNames) {
-        foreach(const QString& level2, subFolderNames) {
-            foreach(const QString& level3, subFolderNames) {
-                files << level1 + "/" + level2 + "/" + level3 + "/testfile";
-            }
-        }
-    }
-
-    TestDir dir;
-    dir.createFiles(files);
-    DolphinView view(dir.url(), 0);
-    DolphinDetailsView* detailsView = initView(&view);
-
-    // We start with an empty set of expanded URLs.
-    QSet<KUrl> expectedExpandedUrls;
-    QCOMPARE(detailsView->expandedUrls(), expectedExpandedUrls);
-
-    // Expand URLs one by one and verify the result of DolphinDetailsView::expandedUrls()
-    QStringList itemsToExpand;
-    itemsToExpand << "b" << "b/a" << "b/a/c" << "b/c" << "c";
-
-    foreach(const QString& item, itemsToExpand) {
-        KUrl url(dir.name() + item);
-        detailsView->expand(proxyModelIndexForUrl(&view, url));
-        expectedExpandedUrls += url;
-        QCOMPARE(detailsView->expandedUrls(), expectedExpandedUrls);
-
-        // Before we proceed, we have to make sure that the view has finished
-        // loading the contents of the expanded folder.
-        waitForFinishedPathLoading(&view);
-    }
-
-    // Collapse URLs one by one and verify the result of DolphinDetailsView::expandedUrls()
-    QStringList itemsToCollapse;
-    itemsToCollapse << "b/c" << "b/a/c" << "c" << "b/a" << "b";
-
-    foreach(const QString& item, itemsToCollapse) {
-        KUrl url(dir.name() + item);
-        detailsView->collapse(proxyModelIndexForUrl(&view, url));
-        expectedExpandedUrls -= url;
-        QCOMPARE(detailsView->expandedUrls(), expectedExpandedUrls);
-    }
-}
-
-/**
- * When the first item in the view is active and Shift is held while the "arrow down"
- * key is pressed repeatedly, the selection should grow by one item for each key press.
- * A change in Qt 4.6 revealed a bug in DolphinDetailsView which broke this, see
- *
- * https://bugs.kde.org/show_bug.cgi?id=217447
- *
- * The problem was that DolphinDetailsView, which uses not the full width of the "Name"
- * column for an item, but only the width of the actual file name, did not reimplement
- * QTreeView::visualRect(). This caused item selection to fail because QAbstractItemView
- * uses the center of the visualRect of an item internally. If the width of the file name
- * is less than half the width of the "Name" column, the center of an item's visualRect
- * was therefore outside the space that DolphinDetailsView actually assigned to the
- * item, and this led to unexpected deselection of items.
- *
- * TODO: To make the test more reliable, one could adjust the width of the "Name"
- * column before the test in order to really make sure that the column is more than twice
- * as wide as the space actually occupied by the file names (this triggers the bug).
- */
-
-void DolphinDetailsViewTest::bug217447_shiftArrowSelection()
-{
-    TestDir dir;
-    for (int i = 0; i < 100; i++) {
-        dir.createFile(QString("%1").arg(i));
-    }
-    DolphinView view(dir.url(), 0);
-    DolphinDetailsView* detailsView = initView(&view);
-
-    // Select the first item
-    QModelIndex index0 = detailsView->model()->index(0, 0);
-    detailsView->setCurrentIndex(index0);
-    QCOMPARE(detailsView->currentIndex(), index0);
-
-    // Before we test Shift-selection, we verify that the root cause is fixed a bit more
-    // directly: we check that passing the corners or the center of an item's visualRect
-    // to itemAt() returns the item (and not an invalid model index).
-    QRect rect = detailsView->visualRect(index0);
-    QCOMPARE(detailsView->indexAt(rect.center()), index0);
-    QCOMPARE(detailsView->indexAt(rect.topLeft()), index0);
-    QCOMPARE(detailsView->indexAt(rect.topRight()), index0);
-    QCOMPARE(detailsView->indexAt(rect.bottomLeft()), index0);
-    QCOMPARE(detailsView->indexAt(rect.bottomRight()), index0);
-
-    // Another way to test this is to Ctrl-click the center of the visualRect.
-    // The selection state of the item should be toggled.
-    detailsView->clearSelection();
-    QItemSelectionModel* selectionModel = detailsView->selectionModel();
-    QCOMPARE(selectionModel->selectedIndexes().count(), 0);
-
-    QTest::mouseClick(detailsView->viewport(), Qt::LeftButton, Qt::ControlModifier, rect.center());
-    QModelIndexList selectedIndexes = selectionModel->selectedIndexes();
-    QCOMPARE(selectedIndexes.count(), 1);
-    QVERIFY(selectedIndexes.contains(index0));
-
-    // Now we go down item by item using Shift+Down. In each step, we check that the current item
-    // is added to the selection and that the size of the selection grows by one.
-
-    int current = 1;
-
-    while (current < 100) {
-        QTest::keyClick(detailsView->viewport(), Qt::Key_Down, Qt::ShiftModifier);
-        QModelIndex currentIndex = detailsView->model()->index(current, 0);
-        QCOMPARE(detailsView->currentIndex(), currentIndex);
-
-        selectedIndexes = selectionModel->selectedIndexes();
-        QCOMPARE(selectedIndexes.count(), current + 1);
-        QVERIFY(selectedIndexes.contains(currentIndex));
-
-        current++;
-    }
-}
-
-/**
- * When the icon size is changed, we have to make sure that the maximumSize given
- * to KFileItemDelegate for rendering each item is updated correctly. If this is not
- * done, the visualRects are clipped by the incorrect maximum size, and the icons
- * may overlap, see
- *
- * https://bugs.kde.org/show_bug.cgi?id=234600
- */
-
-void DolphinDetailsViewTest::bug234600_overlappingIconsWhenZooming()
-{
-    QStringList files;
-    files << "a" << "b" << "c" << "d";
-
-    TestDir dir;
-    dir.createFiles(files);
-    DolphinView view(dir.url(), 0);
-    DolphinDetailsView* detailsView = initView(&view);
-
-    QModelIndex index0 = detailsView->model()->index(0, 0);
-    detailsView->setCurrentIndex(index0);
-    QCOMPARE(detailsView->currentIndex(), index0);
-
-    // Setting the zoom level to the minimum value and triggering DolphinDetailsView::currentChanged(...)
-    // should make sure that the bug is triggered.
-    int zoomLevelBackup = view.zoomLevel();
-    int zoomLevel = ZoomLevelInfo::minimumLevel();
-    view.setZoomLevel(zoomLevel);
-
-    QModelIndex index1 = detailsView->model()->index(1, 0);
-    detailsView->setCurrentIndex(index1);
-    QCOMPARE(detailsView->currentIndex(), index1);
-
-    // Increase the zoom level successively to the maximum.
-    while(zoomLevel < ZoomLevelInfo::maximumLevel()) {
-        zoomLevel++;
-        view.setZoomLevel(zoomLevel);
-        QCOMPARE(view.zoomLevel(), zoomLevel);
-
-        //Check for each zoom level that the height of each item is at least the icon size.
-        QVERIFY(detailsView->visualRect(index1).height() >= ZoomLevelInfo::iconSizeForZoomLevel(zoomLevel));
-    }
-
-    view.setZoomLevel(zoomLevelBackup);
-}
-
-/**
- * The width of the visualRect of an item is usually replaced by the width of the file name.
- * However, if the file name is wider then the view's name column, this leads to problems with
- * keyboard navigation if files with very long names are present in the current folder, see
- *
- * https://bugs.kde.org/show_bug.cgi?id=257401
- *
- * This test checks that the visualRect of an item is never wider than the "Name" column.
- */
-
-void DolphinDetailsViewTest::bug257401_longFilenamesKeyboardNavigation() {
-    TestDir dir;
-    QString name;
-    for (int i = 0; i < 20; i++) {
-        name += "mmmmmmmmmm";
-        dir.createFile(name);
-    }
-    DolphinView view(dir.url(), 0);
-    DolphinDetailsView* detailsView = initView(&view);
-
-    // Select the first item
-    QModelIndex index0 = detailsView->model()->index(0, 0);
-    detailsView->setCurrentIndex(index0);
-    QCOMPARE(detailsView->currentIndex(), index0);
-    QVERIFY(detailsView->visualRect(index0).width() < detailsView->columnWidth(DolphinModel::Name));
-
-    QItemSelectionModel* selectionModel = detailsView->selectionModel();
-    QModelIndexList selectedIndexes = selectionModel->selectedIndexes();
-    QCOMPARE(selectedIndexes.count(), 1);
-    QVERIFY(selectedIndexes.contains(index0));
-
-    // Move down successively using the "Down" key and check that current item
-    // and selection are as expected.
-    for (int i = 0; i < 19; i++) {
-        QTest::keyClick(detailsView->viewport(), Qt::Key_Down, Qt::NoModifier);
-        QModelIndex currentIndex = detailsView->model()->index(i + 1, 0);
-        QCOMPARE(detailsView->currentIndex(), currentIndex);
-        QVERIFY(detailsView->visualRect(currentIndex).width() <= detailsView->columnWidth(DolphinModel::Name));
-        selectedIndexes = selectionModel->selectedIndexes();
-        QCOMPARE(selectedIndexes.count(), 1);
-        QVERIFY(selectedIndexes.contains(currentIndex));
-    }
-}
-
-QTEST_KDEMAIN(DolphinDetailsViewTest, GUI)
-
-#include "dolphindetailsviewtest.moc"
diff --git a/src/tests/dolphintreeviewtest.cpp b/src/tests/dolphintreeviewtest.cpp
deleted file mode 100644 (file)
index 149570d..0000000
+++ /dev/null
@@ -1,413 +0,0 @@
-/*****************************************************************************
- *   Copyright (C) 2010-2011 by Frank Reininghaus (frank78ac@googlemail.com) *
- *                                                                           *
- *   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 program 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 program; if not, write to the                           *
- *   Free Software Foundation, Inc.,                                         *
- *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA              *
- *****************************************************************************/
-
-#include <qtest_kde.h>
-#include <KDebug>
-#include <KAction>
-
-#include "views/dolphintreeview.h"
-
-#include <qtestkeyboard.h>
-#include <qtestmouse.h>
-#include <QStringListModel>
-
-class DolphinTreeViewTest : public QObject
-{
-    Q_OBJECT
-
-private slots:
-
-    void testKeyboardNavigationSelectionUpdate();
-
-    void bug218114_visualRegionForSelection();
-    void bug220898_focusOut();
-
-private:
-
-    /** A method that simplifies checking a view's current item and selection */
-    static void verifyCurrentItemAndSelection(const QAbstractItemView& view, const QModelIndex& expectedCurrent, const QModelIndexList& expectedSelection) {
-        QCOMPARE(view.currentIndex(), expectedCurrent);
-        const QModelIndexList selectedIndexes = view.selectionModel()->selectedIndexes();
-        QCOMPARE(selectedIndexes.count(), expectedSelection.count());
-        foreach(const QModelIndex& index, expectedSelection) {
-            QVERIFY(selectedIndexes.contains(index));
-        }
-    }
-
-    /** Use this method if only one item is selected */
-    static void verifyCurrentItemAndSelection(const QAbstractItemView& view, const QModelIndex& current, const QModelIndex& selected) {
-        QModelIndexList list;
-        list << selected;
-        verifyCurrentItemAndSelection(view, current, list);
-    }
-
-    /** Use this method if the only selected item is the current item */
-    static void verifyCurrentItemAndSelection(const QAbstractItemView& view, const QModelIndex& current) {
-        verifyCurrentItemAndSelection(view, current, current);
-    }
-
-};
-
-/**
- * TestView is a simple view class derived from DolphinTreeView.
- * It makes sure that the visualRect for each index contains only the item text as
- * returned by QAbstractItemModel::data(...) for the role Qt::DisplayRole.
- *
- * We have to check that DolphinTreeView handles the case of visualRects with different widths
- * correctly because this is the case in DolphinDetailsView which is derived from DolphinTreeView.
- */
-
-class TestView : public DolphinTreeView
-{
-    Q_OBJECT
-
-public:
-
-    TestView(QWidget* parent = 0) : DolphinTreeView(parent) {};
-    ~TestView() {};
-
-    QRect visualRect(const QModelIndex& index) const {
-        QRect rect = DolphinTreeView::visualRect(index);
-
-        const QStyleOptionViewItem option = viewOptions();
-        const QFontMetrics fontMetrics(option.font);
-        int width = option.decorationSize.width() + fontMetrics.width(model()->data(index).toString());
-
-        rect.setWidth(width);
-        return rect;
-    }
-
-};
-
-/**
- * This test checks that updating the selection after key presses works as expected.
- * Qt does not handle this internally if the first letter of an item is pressed, which
- * is why DolphinTreeView has some custom code for this. The test verifies that this
- * works without unwanted side effects.
- *
- * The test uses the class TreeViewWithDeleteShortcut which deletes the selected items
- * when Shift-Delete is pressed. This is needed to test the fix for bug 259656 (see below).
- */
-
-class TreeViewWithDeleteShortcut : public DolphinTreeView {
-
-    Q_OBJECT
-
-public:
-
-    TreeViewWithDeleteShortcut(QWidget* parent = 0) : DolphinTreeView(parent) {
-        // To test the fix for bug 259656, we need a delete shortcut.
-        KAction* deleteAction = new KAction(this);
-        deleteAction->setShortcut(Qt::SHIFT | Qt::Key_Delete);
-        addAction(deleteAction);
-        connect(deleteAction, SIGNAL(triggered()), this, SLOT(deleteSelectedItems()));
-    };
-
-    ~TreeViewWithDeleteShortcut() {};
-
-public slots:
-
-    void deleteSelectedItems() {
-        // We have to delete the items one by one and update the list of selected items after
-        // each step because every removal will invalidate the model indexes in the list.
-        QModelIndexList selectedItems = selectionModel()->selectedIndexes();
-        while (!selectedItems.isEmpty()) {
-            const QModelIndex index = selectedItems.takeFirst();
-            model()->removeRow(index.row());
-            selectedItems = selectionModel()->selectedIndexes();
-        }
-    }
-};
-
-void DolphinTreeViewTest::testKeyboardNavigationSelectionUpdate() {
-    QStringList items;
-    items << "a" << "b" << "c" << "d" << "e";
-    QStringListModel model(items);
-
-    QModelIndex index[5];
-    for (int i = 0; i < 5; i++) {
-        index[i] = model.index(i, 0);
-    }
-
-    TreeViewWithDeleteShortcut view;
-    view.setModel(&model);
-    view.setSelectionMode(QAbstractItemView::ExtendedSelection);
-    view.resize(400, 400);
-    view.show();
-    QTest::qWaitForWindowShown(&view);
-
-    view.clearSelection();
-    QVERIFY(view.selectionModel()->selectedIndexes().isEmpty());
-
-    /**
-     * Check that basic keyboard navigation with arrow keys works.
-     */
-
-    view.setCurrentIndex(index[0]);
-    verifyCurrentItemAndSelection(view, index[0]);
-
-    // Go down -> item 1 ("b") should be selected
-    kDebug() << "Down";
-    QTest::keyClick(view.viewport(), Qt::Key_Down);
-    verifyCurrentItemAndSelection(view, index[1]);
-
-    // Go down -> item 2 ("c") should be selected
-    kDebug() << "Down";
-    QTest::keyClick(view.viewport(), Qt::Key_Down);
-    verifyCurrentItemAndSelection(view, index[2]);
-
-    // Ctrl-Up -> item 2 ("c") remains selected
-    kDebug() << "Ctrl-Up";
-    QTest::keyClick(view.viewport(), Qt::Key_Up, Qt::ControlModifier);
-    verifyCurrentItemAndSelection(view, index[1], index[2]);
-
-    // Go up -> item 0 ("a") should be selected
-    kDebug() << "Up";
-    QTest::keyClick(view.viewport(), Qt::Key_Up);
-    verifyCurrentItemAndSelection(view, index[0]);
-
-    // Shift-Down -> items 0 and 1 ("a" and "b") should be selected
-    kDebug() << "Shift-Down";
-    QTest::keyClick(view.viewport(), Qt::Key_Down, Qt::ShiftModifier);
-    QModelIndexList expectedSelection;
-    expectedSelection << index[0] << index[1];
-    verifyCurrentItemAndSelection(view, index[1], expectedSelection);
-
-    /**
-    * When the first letter of a file name is pressed, this file becomes the current item
-    * and gets selected. If the user then Shift-clicks another item, it is expected that
-    * all items between these two items get selected. Before the bug
-    *
-    * https://bugs.kde.org/show_bug.cgi?id=201459
-    *
-    * was fixed, this was not the case: the starting point for the Shift-selection was not
-    * updated if an item was selected by pressing the first letter of the file name.
-    */
-
-    view.clearSelection();
-    QVERIFY(view.selectionModel()->selectedIndexes().isEmpty());
-
-    // Control-click item 0 ("a")
-    kDebug() << "Ctrl-click on \"a\"";
-    QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::ControlModifier, view.visualRect(index[0]).center());
-    verifyCurrentItemAndSelection(view, index[0]);
-
-    // Press "c", such that item 2 ("c") should be the current one.
-    kDebug() << "Press \"c\"";
-    QTest::keyClick(view.viewport(), Qt::Key_C);
-    verifyCurrentItemAndSelection(view, index[2]);
-
-    // Now Shift-Click the last item ("e"). We expect that 3 items ("c", "d", "e") are selected.
-    kDebug() << "Shift-click on \"e\"";
-    QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::ShiftModifier, view.visualRect(index[4]).center());
-    expectedSelection.clear();
-    expectedSelection << index[2] << index[3] << index[4];
-    verifyCurrentItemAndSelection(view, index[4], expectedSelection);
-
-    /**
-     * Starting a drag&drop operation should not clear the selection, see
-     *
-     * https://bugs.kde.org/show_bug.cgi?id=158649
-     */
-
-    view.clearSelection();
-    QVERIFY(view.selectionModel()->selectedIndexes().isEmpty());
-
-    // Click item 0 ("a")
-    kDebug() << "Click on \"a\"";
-    QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::NoModifier, view.visualRect(index[0]).center());
-    verifyCurrentItemAndSelection(view, index[0]);
-
-    // Shift-Down -> "a" and "b" should be selected
-    kDebug() << "Shift-Down";
-    QTest::keyClick(view.viewport(), Qt::Key_Down, Qt::ShiftModifier);
-    expectedSelection.clear();
-    expectedSelection << index[0] << index[1];
-    verifyCurrentItemAndSelection(view, index[1], expectedSelection);
-
-    // Press mouse button on item 0 ("a"), but do not release it. Check that the selection is unchanged
-    kDebug() << "Mouse press on \"a\"";
-    QTest::mousePress(view.viewport(), Qt::LeftButton, Qt::NoModifier, view.visualRect(index[0]).center());
-    verifyCurrentItemAndSelection(view, index[0], expectedSelection);
-
-    // Move mouse to item 1 ("b"), check that selection is unchanged
-    kDebug() << "Move mouse to \"b\"";
-    QMouseEvent moveEvent(QEvent::MouseMove, view.visualRect(index[1]).center(), Qt::NoButton, Qt::LeftButton, Qt::NoModifier);
-    bool moveEventReceived = qApp->notify(view.viewport(), &moveEvent);
-    QVERIFY(moveEventReceived);
-    verifyCurrentItemAndSelection(view, index[0], expectedSelection);
-
-    // Release mouse button on item 1 ("b"), check that selection is unchanged
-    kDebug() << "Mouse release on \"b\"";
-    QTest::mouseRelease(view.viewport(), Qt::LeftButton, Qt::NoModifier, view.visualRect(index[1]).center());
-    verifyCurrentItemAndSelection(view, index[0], expectedSelection);
-
-    /**
-     * Keeping Shift+Delete pressed for some time should delete only one item, see
-     *
-     * https://bugs.kde.org/show_bug.cgi?id=259656
-     */
-
-    view.clearSelection();
-    QVERIFY(view.selectionModel()->selectedIndexes().isEmpty());
-
-    // Click item 0 ("a")
-    kDebug() << "Click on \"a\"";
-    QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::NoModifier, view.visualRect(index[0]).center());
-    verifyCurrentItemAndSelection(view, index[0]);
-
-    // Press Shift-Delete and keep the keys pressed for some time
-    kDebug() << "Press Shift-Delete";
-    QTest::keyPress(view.viewport(), Qt::Key_Delete, Qt::ShiftModifier);
-    QTest::qWait(200);
-    QTest::keyRelease(view.viewport(), Qt::Key_Delete, Qt::ShiftModifier);
-
-    // Verify that only one item has been deleted
-    QCOMPARE(view.model()->rowCount(), 4);
-}
-
-/**
- * QTreeView assumes implicitly that the width of each item's visualRect is the same. This leads to painting
- * problems in Dolphin if items with different widths are in one QItemSelectionRange, see
- *
- * https://bugs.kde.org/show_bug.cgi?id=218114
- *
- * To fix this, DolphinTreeView has a custom implementation of visualRegionForSelection(). The following
- * unit test checks that.
- */
-
-void DolphinTreeViewTest::bug218114_visualRegionForSelection()
-{
-    QStringList items;
-    items << "a" << "an item with a long name" << "a";
-    QStringListModel model(items);
-
-    QModelIndex index0 = model.index(0, 0);
-    QModelIndex index1 = model.index(1, 0);
-    QModelIndex index2 = model.index(2, 0);
-
-    TestView view;
-    view.setModel(&model);
-    view.setSelectionMode(QAbstractItemView::ExtendedSelection);
-    view.resize(400, 400);
-    view.show();
-    QTest::qWaitForWindowShown(&view);
-
-    // First check that the width of index1 is larger than that of index0 and index2 (this triggers the bug).
-
-    QVERIFY(view.visualRect(index0).width() < view.visualRect(index1).width());
-    QVERIFY(view.visualRect(index2).width() < view.visualRect(index1).width());
-
-    // Select all items in one go.
-
-    view.selectAll();
-    const QItemSelection selection = view.selectionModel()->selection();
-    QCOMPARE(selection.count(), 1);
-    QCOMPARE(selection.indexes().count(), 3);
-
-    // Verify that the visualRegionForSelection contains all visualRects.
-    // We do this indirectly using QRegion::boundingRect() because
-    // QRegion::contains(const QRect&) returns true even if the QRect is not
-    // entirely inside the QRegion.
-
-    const QRegion region = view.visualRegionForSelection(selection);
-    const QRect boundingRect = region.boundingRect();
-
-    QVERIFY(boundingRect.contains(view.visualRect(index0)));
-    QVERIFY(boundingRect.contains(view.visualRect(index1)));
-    QVERIFY(boundingRect.contains(view.visualRect(index2)));
-}
-
-/**
- * This test verifies that selection of multiple items with the mouse works
- * if a key was pressed and the keyboard focus moved to another window before the
- * key was released, see
- *
- * https://bugs.kde.org/show_bug.cgi?id=220898
- */
-
-void DolphinTreeViewTest::bug220898_focusOut()
-{
-    QStringList items;
-    items << "a" << "b" << "c" << "d" << "e";
-    QStringListModel model(items);
-
-    QModelIndex index[5];
-    for (int i = 0; i < 5; i++) {
-        index[i] = model.index(i, 0);
-    }
-
-    TestView view;
-    view.setModel(&model);
-    view.setSelectionMode(QAbstractItemView::ExtendedSelection);
-    view.resize(400, 400);
-    view.show();
-    QTest::qWaitForWindowShown(&view);
-
-    view.setCurrentIndex(index[0]);
-    verifyCurrentItemAndSelection(view, index[0]);
-
-    // Press Down
-    QTest::keyPress(view.viewport(), Qt::Key_Down, Qt::NoModifier);
-
-    // Move keyboard focus to another widget
-    QWidget widget;
-    widget.show();
-    QTest::qWaitForWindowShown(&widget);
-    widget.setFocus();
-
-    // Wait until the widgets have received the focus events
-    while (view.viewport()->hasFocus()) {
-        QTest::qWait(10);
-    }
-    QVERIFY(!view.viewport()->hasFocus());
-
-    // Release the "Down" key
-    QTest::keyRelease(&widget, Qt::Key_Down, Qt::NoModifier);
-
-    // Move keyboard focus back to the view
-    widget.hide();
-    view.viewport()->setFocus();
-
-    // Wait until the widgets have received the focus events
-    while (widget.hasFocus()) {
-        QTest::qWait(10);
-    }
-    QVERIFY(!widget.hasFocus());
-
-    // Press left mouse button below the last item
-    const int lastRowHeight = view.sizeHintForRow(4);
-    QTest::mousePress(view.viewport(), Qt::LeftButton, Qt::NoModifier, view.visualRect(index[4]).center() + QPoint(0, lastRowHeight));
-
-    // Move mouse to the first item and release
-    QTest::mouseMove(view.viewport(), view.visualRect(index[0]).center());
-    QMouseEvent moveEvent(QEvent::MouseMove, view.visualRect(index[0]).center(), Qt::NoButton, Qt::LeftButton, Qt::NoModifier);
-    bool moveEventReceived = qApp->notify(view.viewport(), &moveEvent);
-    QVERIFY(moveEventReceived);
-    QTest::mouseRelease(view.viewport(), Qt::LeftButton, Qt::NoModifier, view.visualRect(index[0]).center());
-
-    // All items should be selected
-    QModelIndexList expectedSelection;
-    expectedSelection << index[0] << index[1] << index[2] << index[3] << index[4];
-    verifyCurrentItemAndSelection(view, index[0], expectedSelection);
-}
-
-QTEST_KDEMAIN(DolphinTreeViewTest, GUI)
-
-#include "dolphintreeviewtest.moc"
diff --git a/src/tests/dolphinviewtest_allviewmodes.cpp b/src/tests/dolphinviewtest_allviewmodes.cpp
deleted file mode 100644 (file)
index cac4c71..0000000
+++ /dev/null
@@ -1,596 +0,0 @@
-/****************************************************************************
- *   Copyright (C) 2010-2011 by Frank Reininghaus (frank78ac@googlemail.com) *
- *                                                                           *
- *   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 program 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 program; if not, write to the                           *
- *   Free Software Foundation, Inc.,                                         *
- *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA              *
- *****************************************************************************/
-
-#include <kdebug.h>
-
-#include "dolphinviewtest_allviewmodes.h"
-
-#include <qtest_kde.h>
-
-#include "testdir.h"
-
-#include "views/dolphinview.h"
-#include "views/dolphinmodel.h"
-#include "views/dolphindirlister.h"
-#include "views/dolphinsortfilterproxymodel.h"
-#include "views/zoomlevelinfo.h"
-
-#include <QScrollBar>
-
-#include <qtestmouse.h>
-#include <qtestkeyboard.h>
-
-DolphinViewTest_AllViewModes::DolphinViewTest_AllViewModes() {
-    // Need to register KFileItemList for use with QSignalSpy
-    qRegisterMetaType<KFileItemList>("KFileItemList");
-}
-
-/**
- * testSelection() checks the basic selection functionality of DolphinView, including:
- *
- * selectedItems()
- * selectedItemsCount()
- * selectAll()
- * invertSelection()
- * clearSelection()
- * hasSelection()
- *
- * and the signal selectionChanged(const KFileItemList& selection)
- */
-
-Q_DECLARE_METATYPE(KFileItemList)
-
-void DolphinViewTest_AllViewModes::testSelection() {
-    TestDir dir;
-    const int totalItems = 50;
-    for (int i = 0; i < totalItems; i++) {
-        dir.createFile(QString("%1").arg(i));
-    }
-
-    DolphinView view(dir.url(), 0);
-    QAbstractItemView* itemView = initView(&view);
-
-    // Start with an empty selection
-    view.clearSelection();
-
-    QCOMPARE(view.selectedItems().count(), 0);
-    QCOMPARE(view.selectedItemsCount(), 0);
-    QVERIFY(!view.hasSelection());
-
-    // First some simple tests where either all or no items are selected
-    view.selectAll();
-    verifySelectedItemsCount(&view, totalItems);
-
-    view.invertSelection();
-    verifySelectedItemsCount(&view, 0);
-
-    view.invertSelection();
-    verifySelectedItemsCount(&view, totalItems);
-
-    view.clearSelection();
-    verifySelectedItemsCount(&view, 0);
-
-    // Now we select individual items using mouse clicks
-    QModelIndex index = itemView->model()->index(2, 0);
-    itemView->scrollTo(index);
-    QTest::mouseClick(itemView->viewport(), Qt::LeftButton, Qt::ControlModifier, itemView->visualRect(index).center());
-    verifySelectedItemsCount(&view, 1);
-
-    index = itemView->model()->index(totalItems - 5, 0);
-    itemView->scrollTo(index);
-    QTest::mouseClick(itemView->viewport(), Qt::LeftButton, Qt::ControlModifier, itemView->visualRect(index).center());
-    verifySelectedItemsCount(&view, 2);
-
-    index = itemView->model()->index(totalItems - 2, 0);
-    itemView->scrollTo(index);
-    QTest::mouseClick(itemView->viewport(), Qt::LeftButton, Qt::ShiftModifier, itemView->visualRect(index).center());
-    verifySelectedItemsCount(&view, 5);
-
-    view.invertSelection();
-    verifySelectedItemsCount(&view, totalItems - 5);
-
-    // Pressing Esc should clear the selection
-    QTest::keyClick(itemView->viewport(), Qt::Key_Escape);
-    verifySelectedItemsCount(&view, 0);
-}
-
-/**
- * Check that setting the directory view properties works.
- */
-
-void DolphinViewTest_AllViewModes::testViewPropertySettings()
-{
-    // Create some files with different sizes and modification times to check the different sorting options
-    QDateTime now = QDateTime::currentDateTime();
-
-    TestDir dir;
-    dir.createFile("a", "A file", now.addDays(-3));
-    dir.createFile("b", "A larger file", now.addDays(0));
-    dir.createDir("c", now.addDays(-2));
-    dir.createFile("d", "The largest file in this directory", now.addDays(-1));
-    dir.createFile("e", "An even larger file", now.addDays(-4));
-    dir.createFile(".f");
-
-    DolphinView view(dir.url(), 0);
-    initView(&view);
-
-    // First set all settings to the default.
-    view.setSorting(DolphinView::SortByName);
-    QCOMPARE(view.sorting(), DolphinView::SortByName);
-
-    view.setSortOrder(Qt::AscendingOrder);
-    QCOMPARE(view.sortOrder(), Qt::AscendingOrder);
-
-    view.setSortFoldersFirst(true);
-    QVERIFY(view.sortFoldersFirst());
-
-    view.setShowPreview(false);
-    QVERIFY(!view.showPreview());
-
-    if (view.showHiddenFiles()) {
-        // Changing the "hidden files" setting triggers the dir lister
-        // -> we have to wait until loading the hidden files is finished
-        view.setShowHiddenFiles(false);
-        waitForFinishedPathLoading(&view);
-    }
-    QVERIFY(!view.showHiddenFiles());
-
-    /** Check that the sort order is correct for different kinds of settings */
-
-    // Sort by Name, ascending
-    QCOMPARE(view.sorting(), DolphinView::SortByName);
-    QCOMPARE(view.sortOrder(), Qt::AscendingOrder);
-    QCOMPARE(viewItems(&view), QStringList() << "c" << "a" << "b" << "d" << "e");
-
-    // Sort by Name, descending
-    view.setSortOrder(Qt::DescendingOrder);
-    QCOMPARE(view.sorting(), DolphinView::SortByName);
-    QCOMPARE(view.sortOrder(), Qt::DescendingOrder);
-    QCOMPARE(viewItems(&view), QStringList() << "c" << "e" << "d" << "b" << "a");
-
-    // Sort by Size, descending
-    view.setSorting(DolphinView::SortBySize);
-    QCOMPARE(view.sorting(), DolphinView::SortBySize);
-    QCOMPARE(view.sortOrder(), Qt::DescendingOrder);
-    QCOMPARE(viewItems(&view), QStringList() << "c" << "d" << "e" << "b" << "a");
-
-    // Sort by Size, ascending
-    view.setSortOrder(Qt::AscendingOrder);
-    QCOMPARE(view.sorting(), DolphinView::SortBySize);
-    QCOMPARE(view.sortOrder(), Qt::AscendingOrder);
-    QCOMPARE(viewItems(&view), QStringList() << "c" << "a" << "b" << "e" << "d");
-
-    // Sort by Date, ascending
-    view.setSorting(DolphinView::SortByDate);
-    QCOMPARE(view.sorting(), DolphinView::SortByDate);
-    QCOMPARE(view.sortOrder(), Qt::AscendingOrder);
-    QCOMPARE(viewItems(&view), QStringList() << "c" << "e" << "a" << "d" << "b");
-
-    // Sort by Date, descending
-    view.setSortOrder(Qt::DescendingOrder);
-    QCOMPARE(view.sorting(), DolphinView::SortByDate);
-    QCOMPARE(view.sortOrder(), Qt::DescendingOrder);
-    QCOMPARE(viewItems(&view), QStringList() << "c" << "b" << "d" << "a" << "e");
-
-    // Disable "Sort Folders First"
-    view.setSortFoldersFirst(false);
-    QVERIFY(!view.sortFoldersFirst());
-    QCOMPARE(viewItems(&view), QStringList()<< "b" << "d" << "c"  << "a" << "e");
-
-    // Try again with Sort by Name, ascending
-    view.setSorting(DolphinView::SortByName);
-    view.setSortOrder(Qt::AscendingOrder);
-    QCOMPARE(view.sorting(), DolphinView::SortByName);
-    QCOMPARE(view.sortOrder(), Qt::AscendingOrder);
-    QCOMPARE(viewItems(&view), QStringList() << "a" << "b" << "c" << "d" << "e");
-
-    // Show hidden files. This triggers the dir lister
-    // -> we have to wait until loading the hidden files is finished
-    view.setShowHiddenFiles(true);
-    waitForFinishedPathLoading(&view);
-    QVERIFY(view.showHiddenFiles());
-
-    // Depending on the settings, a .directory file might have been created.
-    // Remove it from the list to get consistent results.
-    QStringList result = viewItems(&view);
-    result.removeAll(".directory");
-    QCOMPARE(result, QStringList() << ".f" << "a" << "b" << "c" << "d" << "e");
-
-    // Previews
-    view.setShowPreview(true);
-    QVERIFY(view.showPreview());
-
-    // TODO: Check that the view properties are restored correctly when changing the folder and then going back.
-}
-
-/**
- * testZoomLevel() checks that setting the zoom level works, both using DolphinView's API and using Ctrl+mouse wheel.
- */
-
-void DolphinViewTest_AllViewModes::testZoomLevel()
-{
-    TestDir dir;
-    dir.createFiles(QStringList() << "a" << "b");
-    DolphinView view(dir.url(), 0);
-    QAbstractItemView* itemView = initView(&view);
-
-    view.setShowPreview(false);
-    QVERIFY(!view.showPreview());
-
-    int zoomLevelBackup = view.zoomLevel();
-
-    int zoomLevel = ZoomLevelInfo::minimumLevel();
-    view.setZoomLevel(zoomLevel);
-    QCOMPARE(view.zoomLevel(), zoomLevel);
-
-    // Increase the zoom level successively to the maximum.
-    while(zoomLevel < ZoomLevelInfo::maximumLevel()) {
-        zoomLevel++;
-        view.setZoomLevel(zoomLevel);
-        QCOMPARE(view.zoomLevel(), zoomLevel);
-    }
-
-    // Try setting a zoom level larger than the maximum
-    view.setZoomLevel(ZoomLevelInfo::maximumLevel() + 1);
-    QCOMPARE(view.zoomLevel(), ZoomLevelInfo::maximumLevel());
-
-    // Turn previews on and try setting a zoom level smaller than the minimum
-    view.setShowPreview(true);
-    QVERIFY(view.showPreview());
-    view.setZoomLevel(ZoomLevelInfo::minimumLevel() - 1);
-    QCOMPARE(view.zoomLevel(), ZoomLevelInfo::minimumLevel());
-
-    // Turn previews off again and check that the zoom level is restored
-    view.setShowPreview(false);
-    QVERIFY(!view.showPreview());
-    QCOMPARE(view.zoomLevel(), ZoomLevelInfo::maximumLevel());
-
-    // Change the zoom level using Ctrl+mouse wheel
-    QModelIndex index = itemView->model()->index(0, 0);
-    itemView->scrollTo(index);
-
-    while (view.zoomLevel() > ZoomLevelInfo::minimumLevel()) {
-        int oldZoomLevel = view.zoomLevel();
-        QWheelEvent wheelEvent(itemView->visualRect(index).center(), -1, Qt::NoButton, Qt::ControlModifier);
-        bool wheelEventReceived = qApp->notify(itemView->viewport(), &wheelEvent);
-        QVERIFY(wheelEventReceived);
-        QVERIFY(view.zoomLevel() < oldZoomLevel);
-    }
-    QCOMPARE(view.zoomLevel(), ZoomLevelInfo::minimumLevel());
-
-    while (view.zoomLevel() < ZoomLevelInfo::maximumLevel()) {
-        int oldZoomLevel = view.zoomLevel();
-        QWheelEvent wheelEvent(itemView->visualRect(index).center(), 1, Qt::NoButton, Qt::ControlModifier);
-        bool wheelEventReceived = qApp->notify(itemView->viewport(), &wheelEvent);
-        QVERIFY(wheelEventReceived);
-        QVERIFY(view.zoomLevel() > oldZoomLevel);
-    }
-    QCOMPARE(view.zoomLevel(), ZoomLevelInfo::maximumLevel());
-
-    // Turn previews on again and check that the zoom level is restored
-    view.setShowPreview(true);
-    QVERIFY(view.showPreview());
-    QCOMPARE(view.zoomLevel(), ZoomLevelInfo::minimumLevel());
-
-    // Restore the initial state
-    view.setZoomLevel(zoomLevelBackup);
-    view.setShowPreview(false);
-    view.setZoomLevel(zoomLevelBackup);
-}
-
-/**
- * testSaveAndRestoreState() checks if saving and restoring the view state (current item, scroll position).
- *
- * Note that we call qApp->sendPostedEvents() every time the view's finishedPathLoading(const KUrl&) signal
- * is received. The reason is that the scroll position is restored in the slot restoreContentsPosition(),
- * which is been invoked using a queued connection in DolphinView::slotLoadingCompleted(). To make sure
- * that this slot is really executed before we proceed, we have to empty the event queue using qApp->sendPostedEvents().
- */
-
-void DolphinViewTest_AllViewModes::testSaveAndRestoreState()
-{
-    const int totalItems = 50;
-    TestDir dir;
-    for (int i = 0; i < totalItems; i++) {
-        dir.createFile(QString("%1").arg(i));
-    }
-    dir.createDir("51");
-    DolphinView view(dir.url(), 0);
-    initView(&view);
-
-    // Set sorting settings to the default to make sure that the item positions are reproducible.
-    view.setSorting(DolphinView::SortByName);
-    QCOMPARE(view.sorting(), DolphinView::SortByName);
-    view.setSortOrder(Qt::AscendingOrder);
-    QCOMPARE(view.sortOrder(), Qt::AscendingOrder);
-
-    // Make sure that previews are off and that the icon size does not depend on the preview setting.
-    // This is needed for the test for bug 270437, see below.
-    view.setShowPreview(false);
-    int zoomLevel = view.zoomLevel();
-    view.setShowPreview(true);
-    view.setZoomLevel(zoomLevel);
-    view.setShowPreview(false);
-
-    // Select item 45
-    const QModelIndex index45 = itemView(&view)->model()->index(45, 0);
-    itemView(&view)->scrollTo(index45);
-    itemView(&view)->setCurrentIndex(index45);
-    const int scrollPosX = itemView(&view)->horizontalScrollBar()->value();
-    const int scrollPosY = itemView(&view)->verticalScrollBar()->value();
-
-    // Save the view state
-    QByteArray viewState;
-    QDataStream saveStream(&viewState, QIODevice::WriteOnly);
-    view.saveState(saveStream);
-
-    // Change the URL
-    view.setUrl(KUrl(dir.name() + "51"));
-    waitForFinishedPathLoading(&view);
-    qApp->sendPostedEvents();
-
-    // Go back, but do not call DolphinView::restoreState()
-    view.setUrl(dir.url());
-    waitForFinishedPathLoading(&view);
-    qApp->sendPostedEvents();
-
-    // Verify that the view is scrolled to top-left corner and that item 45 is not the current item.
-    // Note that the vertical position of the columns view might not be zero -> skip that part
-    // of the check in this case.
-    QVERIFY(itemView(&view)->currentIndex() != index45);
-    QCOMPARE(itemView(&view)->horizontalScrollBar()->value(), 0);
-    if (mode() != DolphinView::ColumnView) {
-        QCOMPARE(itemView(&view)->verticalScrollBar()->value(), 0);
-    }
-
-    // Change the URL again
-    view.setUrl(KUrl(dir.name() + "51"));
-    waitForFinishedPathLoading(&view);
-    qApp->sendPostedEvents();
-
-    // Check that the current item and scroll position are correct if DolphinView::restoreState()
-    // is called after the URL change
-    view.setUrl(dir.url());
-    QDataStream restoreStream(viewState);
-    view.restoreState(restoreStream);
-    waitForFinishedPathLoading(&view);
-    qApp->sendPostedEvents();
-
-    QCOMPARE(itemView(&view)->currentIndex(), index45);
-    QCOMPARE(itemView(&view)->horizontalScrollBar()->value(), scrollPosX);
-    QCOMPARE(itemView(&view)->verticalScrollBar()->value(), scrollPosY);
-
-    /**
-     * Additionally, we verify the fix for the bug https://bugs.kde.org/show_bug.cgi?id=270437
-     * Actually, it's a bug in KFilePreviewGenerator, but it is easier to test it here.
-     */
-
-    // Turn previews on.
-    view.setShowPreview(true);
-    QVERIFY(view.showPreview());
-
-    // We have to process all events in the queue to make sure that previews are really on.
-    qApp->sendPostedEvents();
-
-    // Current item and scroll position should not change.
-    QCOMPARE(itemView(&view)->currentIndex(), index45);
-    QCOMPARE(itemView(&view)->horizontalScrollBar()->value(), scrollPosX);
-    QCOMPARE(itemView(&view)->verticalScrollBar()->value(), scrollPosY);
-
-    // Turn previews off again. Before bug 270437, this triggered the dir lister's openUrl() method
-    // -> we check that by listening to the view's startedPathLoading() signal and wait until the loading is finished in that case.
-    QSignalSpy spy(&view, SIGNAL(startedPathLoading(const KUrl&)));
-    view.setShowPreview(false);
-    QVERIFY(!view.showPreview());
-    qApp->sendPostedEvents();
-    if (!spy.isEmpty()) {
-        // The dir lister reloads the directory. We wait until the loading is finished.
-        waitForFinishedPathLoading(&view);
-    }
-
-    // Current item and scroll position should not change.
-    QCOMPARE(itemView(&view)->currentIndex(), index45);
-    QCOMPARE(itemView(&view)->horizontalScrollBar()->value(), scrollPosX);
-    QCOMPARE(itemView(&view)->verticalScrollBar()->value(), scrollPosY);
-}
-
-/**
- * testKeyboardFocus() checks whether a view grabs the keyboard focus.
- *
- * A view may never grab the keyboard focus itself and must respect the focus-state
- * when switching the view mode, see
- *
- * https://bugs.kde.org/show_bug.cgi?id=261147
- */
-
-void DolphinViewTest_AllViewModes::testKeyboardFocus()
-{
-    TestDir dir;
-    dir.createFiles(QStringList() << "a" << "b");
-    DolphinView view(dir.url(), 0);
-    initView(&view);
-
-    // Move the keyboard focus to another widget.
-    QWidget widget;
-    widget.show();
-    QTest::qWaitForWindowShown(&widget);
-    widget.setFocus();
-
-    QVERIFY(!view.hasFocus());
-
-    // Switch view modes and verify that the view does not get the focus back
-    for (int i = 0; i <= DolphinView::MaxModeEnum; ++i) {
-        view.setMode(static_cast<DolphinView::Mode>(i));
-        QVERIFY(!view.hasFocus());
-    }
-}
-
-/**
- * testCutCopyPaste() checks if cutting or copying items in one view and pasting
- * them in another one works.
- */
-
-void DolphinViewTest_AllViewModes::testCutCopyPaste()
-{
-    TestDir dir1;
-    dir1.createFiles(QStringList() << "a" << "b" << "c" << "d");
-    DolphinView view1(dir1.url(), 0);
-    QAbstractItemView* itemView1 = initView(&view1);
-
-    TestDir dir2;
-    dir2.createFiles(QStringList() << "1" << "2" << "3" << "4");
-    dir2.createDir("subfolder");
-    DolphinView view2(dir2.url(), 0);
-    QAbstractItemView* itemView2 = initView(&view2);
-
-    // Make sure that both views are sorted by name in ascending order
-    // TODO: Maybe that should be done in initView(), such all tests can rely on it...?
-    view1.setSorting(DolphinView::SortByName);
-    view1.setSortOrder(Qt::AscendingOrder);
-    view2.setSorting(DolphinView::SortByName);
-    view2.setSortOrder(Qt::AscendingOrder);
-    view2.setSortFoldersFirst(true);
-
-    QCOMPARE(viewItems(&view1), QStringList() << "a" << "b" << "c" << "d");
-    QCOMPARE(viewItems(&view2), QStringList() << "subfolder" << "1" << "2" << "3" << "4");
-
-    /** Copy and paste */
-    // Select an item ("d") n view1, copy it and paste it in view2.
-    // Note that we have to wait for view2's finishedPathLoading() signal because the pasting is done in the background.
-    QModelIndex index = itemView1->model()->index(3, 0);
-    itemView1->scrollTo(index);
-    QTest::mouseClick(itemView1->viewport(), Qt::LeftButton, Qt::ControlModifier, itemView1->visualRect(index).center());
-    verifySelectedItemsCount(&view1, 1);
-    QCOMPARE(selectedItems(&view1), QStringList() << "d");
-    view1.copySelectedItems();
-    view2.paste();
-    waitForFinishedPathLoading(&view2);
-    QCOMPARE(viewItems(&view1), QStringList() << "a" << "b" << "c" << "d");
-    QCOMPARE(viewItems(&view2), QStringList() << "subfolder" << "1" << "2" << "3" << "4" << "d");
-    // The pasted item should be selected
-    QCOMPARE(selectedItems(&view2), QStringList() << "d");
-
-    /** Cut and paste */
-    // Select two items ("3", "4") in view2, cut and paste in view1.
-    view2.clearSelection();
-    index = itemView2->model()->index(3, 0);
-    itemView2->scrollTo(index);
-    QTest::mouseClick(itemView2->viewport(), Qt::LeftButton, Qt::ControlModifier, itemView2->visualRect(index).center());
-    verifySelectedItemsCount(&view2, 1);
-    index = itemView2->model()->index(4, 0);
-    itemView2->scrollTo(index);
-    QTest::mouseClick(itemView2->viewport(), Qt::LeftButton, Qt::ShiftModifier, itemView2->visualRect(index).center());
-    verifySelectedItemsCount(&view2, 2);
-    QCOMPARE(selectedItems(&view2), QStringList() << "3" << "4");
-    view2.cutSelectedItems();
-    // In view1, "d" is still selected
-    QCOMPARE(selectedItems(&view1), QStringList() << "d");
-    // Paste "3" and "4"
-    view1.paste();
-    waitForFinishedPathLoading(&view1);
-    // In principle, KIO could implement copy&paste such that the pasted items are already there, but the cut items
-    // have not been removed yet. Therefore, we check the number of items in view2 and also wait for that view's
-    // finishedPathLoading() signal if the cut items are still there.
-    if (viewItems(&view2).count() > 4) {
-        waitForFinishedPathLoading(&view2);
-    }
-    QCOMPARE(viewItems(&view1), QStringList() << "3" << "4" << "a" << "b" << "c" << "d");
-    QCOMPARE(viewItems(&view2), QStringList() << "subfolder" << "1" << "2" << "d");
-    // The pasted items ("3", "4") should be selected now, and the previous selection ("d") should be cleared.
-    QCOMPARE(selectedItems(&view1), QStringList() << "3" << "4");
-
-    /** Copy and paste into subfolder */
-    view1.clearSelection();
-    index = itemView1->model()->index(3, 0);
-    itemView1->scrollTo(index);
-    QTest::mouseClick(itemView1->viewport(), Qt::LeftButton, Qt::ControlModifier, itemView1->visualRect(index).center());
-    verifySelectedItemsCount(&view1, 1);
-    QCOMPARE(selectedItems(&view1), QStringList() << "b");
-    view1.copySelectedItems();
-    // Now we use view1 to display the subfolder, which is still empty.
-    view1.setUrl(KUrl(dir2.name() + "subfolder"));
-    waitForFinishedPathLoading(&view1);
-    QCOMPARE(viewItems(&view1), QStringList());
-    // Select the subfolder.in view2
-    view2.clearSelection();
-    index = itemView2->model()->index(0, 0);
-    itemView2->scrollTo(index);
-    QTest::mouseClick(itemView2->viewport(), Qt::LeftButton, Qt::ControlModifier, itemView2->visualRect(index).center());
-    verifySelectedItemsCount(&view2, 1);
-    // Paste into the subfolder
-    view2.pasteIntoFolder();
-    waitForFinishedPathLoading(&view1);
-    QCOMPARE(viewItems(&view1), QStringList() << "b");
-    // The pasted items in view1 are *not* selected now (because the pasting was done indirectly using view2.pasteIntoFolder()).
-}
-
-// Private member functions which are used by the tests
-
-/**
- * initView(DolphinView*) sets the correct view mode, shows the view on the screen, and waits until loading the
- * folder in the view is finished.
- *
- * Many unit tests need access to DolphinView's internal item view (icons, details, or columns).
- * Therefore, a pointer to the item view is returned by initView(DolphinView*).
- */
-
-QAbstractItemView* DolphinViewTest_AllViewModes::initView(DolphinView* view) const
-{
-    QSignalSpy spyFinishedPathLoading(view, SIGNAL(finishedPathLoading(const KUrl&)));
-    view->setMode(mode());
-    Q_ASSERT(verifyCorrectViewMode(view));
-    view->resize(200, 300);
-    view->show();
-    QTest::qWaitForWindowShown(view);
-
-    // If the DolphinView's finishedPathLoading(const KUrl&) signal has not been received yet,
-    // we have to wait a bit more.
-    // The reason why the if-statement is needed here is that the signal might have been emitted
-    // while we were waiting in QTest::qWaitForWindowShown(view)
-    // -> waitForFinishedPathLoading(view) would fail in that case.
-    if (spyFinishedPathLoading.isEmpty()) {
-        waitForFinishedPathLoading(view);
-    }
-
-    return itemView(view);
-}
-
-/**
- * verifySelectedItemsCount(int) waits until the DolphinView's selectionChanged(const KFileItemList&)
- * signal is received and checks that the selection state of the view is as expected.
- */
-
-void DolphinViewTest_AllViewModes::verifySelectedItemsCount(DolphinView* view, int itemsCount) const
-{
-    QSignalSpy spySelectionChanged(view, SIGNAL(selectionChanged(const KFileItemList&)));
-    QVERIFY(QTest::kWaitForSignal(view, SIGNAL(selectionChanged(const KFileItemList&)), 2000));
-
-    QCOMPARE(view->selectedItems().count(), itemsCount);
-    QCOMPARE(view->selectedItemsCount(), itemsCount);
-    QCOMPARE(spySelectionChanged.count(), 1);
-    QCOMPARE(qvariant_cast<KFileItemList>(spySelectionChanged.at(0).at(0)).count(), itemsCount);
-    if (itemsCount) {
-        QVERIFY(view->hasSelection());
-    }
-    else {
-        QVERIFY(!view->hasSelection());
-    }
-}
-
-#include "dolphinviewtest_allviewmodes.moc"
diff --git a/src/tests/dolphinviewtest_allviewmodes.h b/src/tests/dolphinviewtest_allviewmodes.h
deleted file mode 100644 (file)
index d062bb0..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-/*****************************************************************************
- *   Copyright (C) 2010-2011 by Frank Reininghaus (frank78ac@googlemail.com) *
- *                                                                           *
- *   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 program 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 program; if not, write to the                           *
- *   Free Software Foundation, Inc.,                                         *
- *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA              *
- *****************************************************************************/
-
-#ifndef DOLPHINVIEWTEST_ALLVIEWMODES
-#define DOLPHINVIEWTEST_ALLVIEWMODES
-
-#include "testbase.h"
-
-#include "views/dolphinview.h"
-
-/**
- * DolphinViewTest_AllViewModes is used as a base class for tests that check the
- * basic functionality of DolphinView in all view modes. The derived classes
- * have to provide implementations for the virtual methods mode() and verifyCorrectViewMode(),
- * see below.
- *
- * Tests for DolphinView functionality that is specific to a particular view mode or
- * to switching between different view modes should not be added here, but to another
- * DolphinView unit test.
- */
-
-class DolphinViewTest_AllViewModes : public TestBase
-{
-    Q_OBJECT
-
-public:
-
-    DolphinViewTest_AllViewModes();
-
-private slots:
-
-    void testSelection();
-    void testViewPropertySettings();
-    void testZoomLevel();
-    void testSaveAndRestoreState();
-    void testKeyboardFocus();
-    void testCutCopyPaste();
-
-private:
-
-    /**
-     * Sets the correct view mode, shows the view on the screen, and waits until loading the
-     * folder in the view is finished.
-     *
-     * Many unit tests need access to DolphinVie's internal item view (icons, details, or columns).
-     * Therefore, a pointer to the item view is returned by initView(DolphinView*).
-     */
-    QAbstractItemView* initView(DolphinView* view) const;
-
-    /** Returns the view mode (Icons, Details, Columns) to be used in the test. */
-    virtual DolphinView::Mode mode() const = 0;
-
-    /** Should return true if the view mode is correct. */
-    virtual bool verifyCorrectViewMode(const DolphinView* view) const = 0;
-
-    /**
-     * Waits for the DolphinView's selectionChanged(const KFileItemList&) to be emitted
-     * and verifies that the number of selected items is as expected.
-     */
-    void verifySelectedItemsCount(DolphinView* view, int itemsCount) const;
-
-};
-
-#endif
diff --git a/src/tests/kfileitemlistviewtest.cpp b/src/tests/kfileitemlistviewtest.cpp
new file mode 100644 (file)
index 0000000..1b9e1b3
--- /dev/null
@@ -0,0 +1,100 @@
+/***************************************************************************
+ *   Copyright (C) 2011 by Peter Penz <peter.penz19@gmail.com>             *
+ *                                                                         *
+ *   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 program 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 program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA            *
+ ***************************************************************************/
+
+#include <qtest_kde.h>
+
+#include <KDirLister>
+#include "kitemviews/kfileitemlistview.h"
+#include "kitemviews/kfileitemmodel.h"
+#include "testdir.h"
+
+#include <QGraphicsView>
+
+namespace {
+    const int DefaultTimeout = 2000;
+};
+
+class KFileItemListViewTest : public QObject
+{
+    Q_OBJECT
+
+private slots:
+    void init();
+    void cleanup();
+
+    void testFeffi();
+
+private:
+    KFileItemListView* m_listView;
+    KFileItemModel* m_model;
+    KDirLister* m_dirLister;
+    TestDir* m_testDir;
+    QGraphicsView* m_graphicsView;
+};
+
+void KFileItemListViewTest::init()
+{
+    qRegisterMetaType<KItemRangeList>("KItemRangeList");
+    qRegisterMetaType<KFileItemList>("KFileItemList");
+
+    m_testDir = new TestDir();
+    m_dirLister = new KDirLister();
+    m_model = new KFileItemModel(m_dirLister);
+
+    m_listView = new KFileItemListView();
+    m_listView->onModelChanged(m_model, 0);
+
+    m_graphicsView = new QGraphicsView();
+    m_graphicsView->show();
+    QTest::qWaitForWindowShown(m_graphicsView);
+}
+
+void KFileItemListViewTest::cleanup()
+{
+    delete m_graphicsView;
+    m_graphicsView = 0;
+
+    delete m_listView;
+    m_listView = 0;
+
+    delete m_model;
+    m_model = 0;
+
+    delete m_dirLister;
+    m_dirLister = 0;
+
+    delete m_testDir;
+    m_testDir = 0;
+}
+
+void KFileItemListViewTest::testFeffi()
+{
+    QStringList files;
+    files << "a.txt" << "b.txt" << "c.txt";
+    m_testDir->createFiles(files);
+
+    m_dirLister->openUrl(m_testDir->url());
+    QVERIFY(QTest::kWaitForSignal(m_model, SIGNAL(itemsInserted(KItemRangeList)), DefaultTimeout));
+
+    QCOMPARE(m_model->count(), 3);
+}
+
+QTEST_KDEMAIN(KFileItemListViewTest, GUI)
+
+#include "kfileitemlistviewtest.moc"
diff --git a/src/tests/kfileitemmodeltest.cpp b/src/tests/kfileitemmodeltest.cpp
new file mode 100644 (file)
index 0000000..82fc3fb
--- /dev/null
@@ -0,0 +1,210 @@
+/***************************************************************************
+ *   Copyright (C) 2011 by Peter Penz <peter.penz19@gmail.com>             *
+ *                                                                         *
+ *   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 program 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 program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA            *
+ ***************************************************************************/
+
+#include <qtest_kde.h>
+
+#include <KDirLister>
+#include "kitemviews/kfileitemmodel.h"
+#include "testdir.h"
+
+namespace {
+    const int DefaultTimeout = 2000;
+};
+
+class KFileItemModelTest : public QObject
+{
+    Q_OBJECT
+
+private slots:
+    void init();
+    void cleanup();
+
+    void testDefaultRoles();
+    void testDefaultSortRole();
+    void testDefaultGroupRole();
+    void testNewItems();
+    void testInsertingItems();
+
+    void testExpansionLevelsCompare_data();
+    void testExpansionLevelsCompare();
+
+private:
+    bool isModelConsistent() const;
+
+private:
+    KFileItemModel* m_model;
+    KDirLister* m_dirLister;
+    TestDir* m_testDir;
+};
+
+void KFileItemModelTest::init()
+{
+    qRegisterMetaType<KItemRangeList>("KItemRangeList");
+    qRegisterMetaType<KFileItemList>("KFileItemList");
+
+    m_testDir = new TestDir();
+    m_dirLister = new KDirLister();
+    m_model = new KFileItemModel(m_dirLister);
+}
+
+void KFileItemModelTest::cleanup()
+{
+    delete m_model;
+    m_model = 0;
+
+    delete m_dirLister;
+    m_dirLister = 0;
+
+    delete m_testDir;
+    m_testDir = 0;
+}
+
+void KFileItemModelTest::testDefaultRoles()
+{
+    const QSet<QByteArray> roles = m_model->roles();
+    QCOMPARE(roles.count(), 2);
+    QVERIFY(roles.contains("name"));
+    QVERIFY(roles.contains("isDir"));
+}
+
+void KFileItemModelTest::testDefaultSortRole()
+{
+    QCOMPARE(m_model->sortRole(), QByteArray("name"));
+
+    QStringList files;
+    files << "c.txt" << "a.txt" << "b.txt";
+
+    m_testDir->createFiles(files);
+
+    m_dirLister->openUrl(m_testDir->url());
+    QVERIFY(QTest::kWaitForSignal(m_model, SIGNAL(itemsInserted(KItemRangeList)), DefaultTimeout));
+
+    QCOMPARE(m_model->count(), 3);
+    QCOMPARE(m_model->data(0)["name"].toString(), QString("a.txt"));
+    QCOMPARE(m_model->data(1)["name"].toString(), QString("b.txt"));
+    QCOMPARE(m_model->data(2)["name"].toString(), QString("c.txt"));
+}
+
+void KFileItemModelTest::testDefaultGroupRole()
+{
+    QVERIFY(m_model->groupRole().isEmpty());
+}
+
+void KFileItemModelTest::testNewItems()
+{
+    QStringList files;
+    files << "a.txt" << "b.txt" << "c.txt";
+    m_testDir->createFiles(files);
+
+    m_dirLister->openUrl(m_testDir->url());
+    QVERIFY(QTest::kWaitForSignal(m_model, SIGNAL(itemsInserted(KItemRangeList)), DefaultTimeout));
+
+    QCOMPARE(m_model->count(), 3);
+
+    QVERIFY(isModelConsistent());
+}
+
+void KFileItemModelTest::testInsertingItems()
+{
+    // QSKIP("Temporary disabled", SkipSingle);
+
+    // KFileItemModel prevents that inserting a punch of items sequentially
+    // results in an itemsInserted()-signal for each item. Instead internally
+    // a timeout is given that collects such operations and results in only
+    // one itemsInserted()-signal. However in this test we want to stress
+    // KFileItemModel to do a lot of insert operation and hence decrease
+    // the timeout to 1 millisecond.
+    m_model->m_minimumUpdateIntervalTimer->setInterval(1);
+
+    m_testDir->createFile("1");
+    m_dirLister->openUrl(m_testDir->url());
+    QVERIFY(QTest::kWaitForSignal(m_model, SIGNAL(itemsInserted(KItemRangeList)), DefaultTimeout));
+    QCOMPARE(m_model->count(), 1);
+
+    // Insert 10 items for 20 times. After each insert operation the model consistency
+    // is checked.
+    QSet<int> insertedItems;
+    for (int i = 0; i < 20; ++i) {
+        QSignalSpy spy(m_model, SIGNAL(itemsInserted(KItemRangeList)));
+
+        for (int j = 0; j < 10; ++j) {
+            int itemName = qrand();
+            while (insertedItems.contains(itemName)) {
+                itemName = qrand();
+            }
+            insertedItems.insert(itemName);
+
+            m_testDir->createFile(QString::number(itemName));
+        }
+
+        m_dirLister->updateDirectory(m_testDir->url());
+        if (spy.count() == 0) {
+            QVERIFY(QTest::kWaitForSignal(m_model, SIGNAL(itemsInserted(KItemRangeList)), DefaultTimeout));
+        }
+
+        QVERIFY(isModelConsistent());
+    }
+
+    QCOMPARE(m_model->count(), 201);
+}
+
+void KFileItemModelTest::testExpansionLevelsCompare_data()
+{
+    QTest::addColumn<QString>("urlA");
+    QTest::addColumn<QString>("urlB");
+    QTest::addColumn<int>("result");
+
+    QTest::newRow("Equal") << "/a/b" << "/a/b" << 0;
+    QTest::newRow("Sub path: A < B") << "/a/b" << "/a/b/c" << -1;
+    QTest::newRow("Sub path: A > B") << "/a/b/c" << "/a/b" << +1;
+}
+
+void KFileItemModelTest::testExpansionLevelsCompare()
+{
+    QFETCH(QString, urlA);
+    QFETCH(QString, urlB);
+    QFETCH(int, result);
+
+    const KFileItem a(KUrl(urlA), QString(), mode_t(-1));
+    const KFileItem b(KUrl(urlB), QString(), mode_t(-1));
+    QCOMPARE(m_model->expansionLevelsCompare(a, b), result);
+}
+
+bool KFileItemModelTest::isModelConsistent() const
+{
+    for (int i = 0; i < m_model->count(); ++i) {
+        const KFileItem item = m_model->fileItem(i);
+        if (item.isNull()) {
+            qWarning() << "Item" << i << "is null";
+            return false;
+        }
+
+        const int itemIndex = m_model->index(item);
+        if (itemIndex != i) {
+            qWarning() << "Item" << i << "has a wrong index:" << itemIndex;
+            return false;
+        }
+    }
+
+    return true;
+}
+
+QTEST_KDEMAIN(KFileItemModelTest, NoGUI)
+
+#include "kfileitemmodeltest.moc"
diff --git a/src/tests/testbase.cpp b/src/tests/testbase.cpp
deleted file mode 100644 (file)
index de323aa..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-/*****************************************************************************
- *   Copyright (C) 2010-2011 by Frank Reininghaus (frank78ac@googlemail.com) *
- *                                                                           *
- *   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 program 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 program; if not, write to the                           *
- *   Free Software Foundation, Inc.,                                         *
- *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA              *
- *****************************************************************************/
-
-#include "testbase.h"
-
-#include <qtest_kde.h>
-
-#include "views/dolphinview.h"
-#include "views/dolphinmodel.h"
-#include "views/dolphindirlister.h"
-#include "views/dolphinsortfilterproxymodel.h"
-
-#include <QAbstractItemView>
-
-QAbstractItemView* TestBase::itemView(const DolphinView* view)
-{
-    return view->m_viewAccessor.itemView();
-}
-
-void TestBase::waitForFinishedPathLoading(DolphinView* view, int milliseconds)
-{
-    // If the signal is not received, somthing is going seriously wrong.
-    // -> assert here rather than continuing, which might result in test failures which are hard to unterstand.
-    bool viewHasFinishedLoading = QTest::kWaitForSignal(view, SIGNAL(finishedPathLoading(const KUrl&)), milliseconds);
-    Q_ASSERT(viewHasFinishedLoading);
-    Q_UNUSED(viewHasFinishedLoading) // suppress compiler warining is asserts are disabled
-}
-
-void TestBase::reloadViewAndWait(DolphinView* view)
-{
-    view->reload();
-    waitForFinishedPathLoading(view);
-}
-
-QStringList TestBase::viewItems(const DolphinView* view)
-{
-    QStringList itemList;
-    const QAbstractItemModel* model = itemView(view)->model();
-
-    for (int row = 0; row < model->rowCount(); row++) {
-        itemList << model->data(model->index(row, 0), Qt::DisplayRole).toString();
-    }
-
-    return itemList;
-}
-
-QStringList TestBase::selectedItems(const DolphinView* view)
-{
-    QStringList itemList;
-    const QAbstractItemModel* model = itemView(view)->model();
-    const QModelIndexList selectedIndexes = itemView(view)->selectionModel()->selectedIndexes();
-
-    for (int row = 0; row < model->rowCount(); row++) {
-        const QModelIndex index = model->index(row, 0);
-        if (selectedIndexes.contains(index)) {
-            itemList << model->data(model->index(row, 0), Qt::DisplayRole).toString();
-        }
-    }
-
-    return itemList;
-}
diff --git a/src/tests/testbase.h b/src/tests/testbase.h
deleted file mode 100644 (file)
index 957d822..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-/*****************************************************************************
- *   Copyright (C) 2010-2011 by Frank Reininghaus (frank78ac@googlemail.com) *
- *                                                                           *
- *   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 program 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 program; if not, write to the                           *
- *   Free Software Foundation, Inc.,                                         *
- *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA              *
- *****************************************************************************/
-
-#ifndef TESTBASE_H
-#define TESTBASE_H
-
-#include <QtCore/QObject>
-
-class QAbstractItemView;
-class DolphinDirLister;
-class DolphinModel;
-class DolphinSortFilterProxyModel;
-class DolphinView;
-
-/**
- * The class TestBase (which is a friend of DolphinView's) provides access to some
- * parts of DolphinView to the unit tests.
- *
- * TODO: TestBase should also backup the DolphinSettings and restore them later!
- */
-
-class TestBase : public QObject
-{
-    Q_OBJECT
-
-public:
-
-    TestBase() {};
-    ~TestBase() {};
-
-    /** Returns the item view (icons, details, or columns) */
-    static QAbstractItemView* itemView(const DolphinView* view);
-
-    /**
-     * Waits until the view emits its finishedPathLoading(const KUrl&) signal.
-     * Asserts if the signal is not received within the given number of milliseconds.
-     */
-    static void waitForFinishedPathLoading(DolphinView* view, int milliseconds=20000);
-
-    /** Reloads the view and waits for the finishedPathLoading(const KUrl&) signal. */
-    static void reloadViewAndWait(DolphinView* view);
-
-    /** Returns the items shown in the view. The order corresponds to the sort order of the view. */
-    static QStringList viewItems(const DolphinView* view);
-
-    /** Returns the items which are selected in the view. The order corresponds to the sort order of the view. */
-    static QStringList selectedItems(const DolphinView* view);
-
-};
-
-#endif
index 64d7f1aaab766afd3705b52f9b5483d58114f473..5e961d2abecd1858c9b362b5750eb9b7fd24392d 100644 (file)
 #include <sys/utime.h>
 #endif
 
-/** The following function is taken from kdelibs/kio/tests/kiotesthelper.h, copyright (C) 2006 by David Faure */
+TestDir::TestDir()
+{
+}
+
+TestDir::~TestDir()
+{
+}
 
+KUrl TestDir::url() const
+{
+    return KUrl(name());
+}
+
+/** The following function is taken from kdelibs/kio/tests/kiotesthelper.h, copyright (C) 2006 by David Faure */
 static void setTimeStamp(const QString& path, const QDateTime& mtime)
 {
 #ifdef Q_OS_UNIX
@@ -63,7 +75,7 @@ void TestDir::createFile(const QString& path, const QByteArray& data, const QDat
 
 void TestDir::createFiles(const QStringList& files)
 {
-    foreach(const QString& path, files) {
+    foreach (const QString& path, files) {
         createFile(path);
     }
 }
index bff46269064efe99d07102458138ce7c0249de4c..bcaa034b58604855456172430e7278822aa44f4e 100644 (file)
  * TestDir provides a temporary directory. In addition to KTempDir, it has
  * methods that create files and subdirectories inside the directory.
  */
-
 class TestDir : public KTempDir
 {
 
 public:
+    TestDir();
+    virtual ~TestDir();
 
-    TestDir() {}
-    ~TestDir() {}
-
-    KUrl url() const { return KUrl(name()); }
+    KUrl url() const;
 
     /**
      * The following functions create either a file, a list of files, or a directory.
      * The paths may be absolute or relative to the test directory. Any missing parent
      * directories will be created automatically.
      */
-
-    void createFile(const QString& path, const QByteArray& data = QByteArray("test"), const QDateTime& time = QDateTime());
+    void createFile(const QString& path,
+                    const QByteArray& data = QByteArray("test"),
+                    const QDateTime& time = QDateTime());
     void createFiles(const QStringList& files);
     void createDir(const QString& path, const QDateTime& time = QDateTime());
 
 private:
-
     void makePathAbsoluteAndCreateParents(QString& path);
 
 };
index 426d7a2c4b6d37e9e975dd7c1f33e3eec3b95d92..465a2b3dd628aa244151e0af5595232e59cd189a 100644 (file)
@@ -19,7 +19,6 @@
 
 #include "additionalinfoaccessor.h"
 
-#include "dolphinmodel.h"
 #include <KGlobal>
 #include <KLocale>
 
@@ -35,31 +34,31 @@ AdditionalInfoAccessor& AdditionalInfoAccessor::instance()
     return s_additionalInfoManager->instance;
 }
 
-KFileItemDelegate::InformationList AdditionalInfoAccessor::keys() const
+QList<DolphinView::AdditionalInfo> AdditionalInfoAccessor::keys() const
 {
-    return m_information;
+    return m_infoList;
 }
 
-KFileItemDelegate::Information AdditionalInfoAccessor::keyForColumn(int columnIndex) const
+QByteArray AdditionalInfoAccessor::role(DolphinView::AdditionalInfo info) const
 {
-    KFileItemDelegate::Information info = KFileItemDelegate::NoInformation;
-
-    switch (columnIndex) {
-    case DolphinModel::Size:           info = KFileItemDelegate::Size; break;
-    case DolphinModel::ModifiedTime:   info = KFileItemDelegate::ModificationTime; break;
-    case DolphinModel::Permissions:    info = KFileItemDelegate::Permissions; break;
-    case DolphinModel::Owner:          info = KFileItemDelegate::Owner; break;
-    case DolphinModel::Group:          info = KFileItemDelegate::OwnerAndGroup; break;
-    case DolphinModel::Type:           info = KFileItemDelegate::FriendlyMimeType; break;
-    case DolphinModel::LinkDest:       info = KFileItemDelegate::LinkDest; break;
-    case DolphinModel::LocalPathOrUrl: info = KFileItemDelegate::LocalPathOrUrl; break;
+    QByteArray role;
+    switch (info) {
+    case DolphinView::NameInfo:        role = "name"; break;
+    case DolphinView::SizeInfo:        role = "size"; break;
+    case DolphinView::DateInfo:        role = "date"; break;
+    case DolphinView::PermissionsInfo: role = "permissions"; break;
+    case DolphinView::OwnerInfo:       role = "owner"; break;
+    case DolphinView::GroupInfo:       role = "group"; break;
+    case DolphinView::TypeInfo:        role = "type"; break;
+    case DolphinView::DestinationInfo: role = "destination"; break;
+    case DolphinView::PathInfo:        role = "path"; break;
     default: break;
     }
 
-    return info;
+    return role;
 }
 
-QString AdditionalInfoAccessor::actionCollectionName(KFileItemDelegate::Information info,
+QString AdditionalInfoAccessor::actionCollectionName(DolphinView::AdditionalInfo info,
                                                      ActionCollectionType type) const
 {
     QString name;
@@ -76,62 +75,56 @@ QString AdditionalInfoAccessor::actionCollectionName(KFileItemDelegate::Informat
     return name;
 }
 
-QString AdditionalInfoAccessor::translation(KFileItemDelegate::Information info) const
+QString AdditionalInfoAccessor::translation(DolphinView::AdditionalInfo info) const
 {
     return i18nc(m_map[info]->context, m_map[info]->translation);
 }
 
-QString AdditionalInfoAccessor::value(KFileItemDelegate::Information info) const
+QString AdditionalInfoAccessor::value(DolphinView::AdditionalInfo info) const
 {
     return m_map[info]->value;
 }
 
-DolphinView::Sorting AdditionalInfoAccessor::sorting(KFileItemDelegate::Information info) const
+DolphinView::Sorting AdditionalInfoAccessor::sorting(DolphinView::AdditionalInfo info) const
 {
     return m_map[info]->sorting;
 }
 
-int AdditionalInfoAccessor::bitValue(KFileItemDelegate::Information info) const
-{
-    return m_map[info]->bitValue;
-}
-
 AdditionalInfoAccessor::AdditionalInfoAccessor() :
-    m_information(),
+    m_infoList(),
     m_map()
 {
     static const AdditionalInfoAccessor::AdditionalInfo additionalInfo[] = {
         // Entries for view-properties version 1:
-        { "size",        I18N_NOOP2_NOSTRIP("@label", "Size"),             "Size",            DolphinView::SortBySize,          1 },
-        { "date",        I18N_NOOP2_NOSTRIP("@label", "Date"),             "Date",            DolphinView::SortByDate,          2 },
-        { "permissions", I18N_NOOP2_NOSTRIP("@label", "Permissions"),      "Permissions",     DolphinView::SortByPermissions,   4 },
-        { "owner",       I18N_NOOP2_NOSTRIP("@label", "Owner"),            "Owner",           DolphinView::SortByOwner,         8 },
-        { "group",       I18N_NOOP2_NOSTRIP("@label", "Group"),            "Group",           DolphinView::SortByGroup,        16 },
-        { "type",        I18N_NOOP2_NOSTRIP("@label", "Type"),             "Type",            DolphinView::SortByType,         32 },
-        { "destination", I18N_NOOP2_NOSTRIP("@label", "Link Destination"), "LinkDestination", DolphinView::SortByDestination,  64 },
-        { "path",        I18N_NOOP2_NOSTRIP("@label", "Path"),             "Path",            DolphinView::SortByPath,        128 }
-        // Entries for view-properties version >= 2 (the last column can be set to 0):
+        { "size",        I18N_NOOP2_NOSTRIP("@label", "Size"),             "Size",            DolphinView::SortBySize},
+        { "date",        I18N_NOOP2_NOSTRIP("@label", "Date"),             "Date",            DolphinView::SortByDate},
+        { "permissions", I18N_NOOP2_NOSTRIP("@label", "Permissions"),      "Permissions",     DolphinView::SortByPermissions},
+        { "owner",       I18N_NOOP2_NOSTRIP("@label", "Owner"),            "Owner",           DolphinView::SortByOwner},
+        { "group",       I18N_NOOP2_NOSTRIP("@label", "Group"),            "Group",           DolphinView::SortByGroup},
+        { "type",        I18N_NOOP2_NOSTRIP("@label", "Type"),             "Type",            DolphinView::SortByType},
+        { "destination", I18N_NOOP2_NOSTRIP("@label", "Link Destination"), "LinkDestination", DolphinView::SortByDestination},
+        { "path",        I18N_NOOP2_NOSTRIP("@label", "Path"),             "Path",            DolphinView::SortByPath}
     };
 
-    m_map.insert(KFileItemDelegate::Size, &additionalInfo[0]);
-    m_map.insert(KFileItemDelegate::ModificationTime, &additionalInfo[1]);
-    m_map.insert(KFileItemDelegate::Permissions, &additionalInfo[2]);
-    m_map.insert(KFileItemDelegate::Owner, &additionalInfo[3]);
-    m_map.insert(KFileItemDelegate::OwnerAndGroup, &additionalInfo[4]);
-    m_map.insert(KFileItemDelegate::FriendlyMimeType, &additionalInfo[5]);
-    m_map.insert(KFileItemDelegate::LinkDest, &additionalInfo[6]);
-    m_map.insert(KFileItemDelegate::LocalPathOrUrl, &additionalInfo[7]);
-
-    // The m_information list defines all available keys and the sort order
-    // (don't use m_information = m_map.keys(), as the order is undefined).
-    m_information.append(KFileItemDelegate::Size);
-    m_information.append(KFileItemDelegate::ModificationTime);
-    m_information.append(KFileItemDelegate::Permissions);
-    m_information.append(KFileItemDelegate::Owner);
-    m_information.append(KFileItemDelegate::OwnerAndGroup);
-    m_information.append(KFileItemDelegate::FriendlyMimeType);
-    m_information.append(KFileItemDelegate::LinkDest);
-    m_information.append(KFileItemDelegate::LocalPathOrUrl);
+    m_map.insert(DolphinView::SizeInfo, &additionalInfo[0]);
+    m_map.insert(DolphinView::DateInfo, &additionalInfo[1]);
+    m_map.insert(DolphinView::PermissionsInfo, &additionalInfo[2]);
+    m_map.insert(DolphinView::OwnerInfo, &additionalInfo[3]);
+    m_map.insert(DolphinView::GroupInfo, &additionalInfo[4]);
+    m_map.insert(DolphinView::TypeInfo, &additionalInfo[5]);
+    m_map.insert(DolphinView::DestinationInfo, &additionalInfo[6]);
+    m_map.insert(DolphinView::PathInfo, &additionalInfo[7]);
+
+    // The m_infoList defines all available keys and the sort order
+    // (don't use m_information = m_map.keys(), as the order would be undefined).
+    m_infoList.append(DolphinView::SizeInfo);
+    m_infoList.append(DolphinView::DateInfo);
+    m_infoList.append(DolphinView::PermissionsInfo);
+    m_infoList.append(DolphinView::OwnerInfo);
+    m_infoList.append(DolphinView::GroupInfo);
+    m_infoList.append(DolphinView::TypeInfo);
+    m_infoList.append(DolphinView::DestinationInfo);
+    m_infoList.append(DolphinView::PathInfo);
 }
 
 AdditionalInfoAccessor::~AdditionalInfoAccessor()
index dbec097fdf999029f5ff520bd3ef2afcb7597d8e..d6dcc8e3fb746522efc716826a27316028dea597 100644 (file)
@@ -60,31 +60,21 @@ public:
      *         All entries of this list are keys for accessing the corresponding
      *         data (see actionCollectionName(), translation(), bitValue()).
      */
-    KFileItemDelegate::InformationList keys() const;
+    QList<DolphinView::AdditionalInfo> keys() const;
 
-    /**
-     * @return Key for the model column with the index \p columnIndex.
-     */
-    KFileItemDelegate::Information keyForColumn(int columnIndex) const;
+    QByteArray role(DolphinView::AdditionalInfo info) const;
 
-    QString actionCollectionName(KFileItemDelegate::Information info, ActionCollectionType type) const;
+    QString actionCollectionName(DolphinView::AdditionalInfo info, ActionCollectionType type) const;
 
-    QString translation(KFileItemDelegate::Information info) const;
+    QString translation(DolphinView::AdditionalInfo info) const;
 
     /**
      * @return String representation of the value that is stored in the .directory
      *         by ViewProperties.
      */
-    QString value(KFileItemDelegate::Information info) const;
-
-    DolphinView::Sorting sorting(KFileItemDelegate::Information info) const;
+    QString value(DolphinView::AdditionalInfo info) const;
 
-    /**
-     * @return Bitvalue for \p info that is stored in a ViewProperties instance.
-     *         Is required only for backward compatibility with the version 1 of
-     *         the view-properties.
-     */
-    int bitValue(KFileItemDelegate::Information info) const;
+    DolphinView::Sorting sorting(DolphinView::AdditionalInfo info) const;
 
 protected:
     AdditionalInfoAccessor();
@@ -98,11 +88,10 @@ private:
         const char* const translation;
         const char* const value;
         const DolphinView::Sorting sorting;
-        const int bitValue; // for backward compatibility with version 1 of view-properties
     };
 
-    KFileItemDelegate::InformationList m_information;
-    QMap<KFileItemDelegate::Information, const AdditionalInfo*> m_map;
+    QList<DolphinView::AdditionalInfo> m_infoList;
+    QMap<DolphinView::AdditionalInfo, const AdditionalInfo*> m_map;
 };
 
 #endif
diff --git a/src/views/dolphincategorydrawer.cpp b/src/views/dolphincategorydrawer.cpp
deleted file mode 100644 (file)
index 1f39133..0000000
+++ /dev/null
@@ -1,377 +0,0 @@
-/*
-  * This file is part of the KDE project
-  * Copyright (C) 2007 Rafael Fernández López <ereslibre@kde.org>
-  *
-  * This library is free software; you can redistribute it and/or
-  * modify it under the terms of the GNU Library General Public
-  * License as published by the Free Software Foundation; either
-  * version 2 of the License, or (at your option) any later version.
-  *
-  * This library 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
-  * Library General Public License for more details.
-  *
-  * You should have received a copy of the GNU Library General Public License
-  * along with this library; see the file COPYING.LIB.  If not, write to
-  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-  * Boston, MA 02110-1301, USA.
-  */
-
-#include "dolphincategorydrawer.h"
-
-#include <config-nepomuk.h>
-
-#include <QPainter>
-#include <QFile>
-#include <QDir>
-#include <QApplication>
-#include <QStyleOption>
-
-#ifdef HAVE_NEPOMUK
-#include <Nepomuk/KRatingPainter>
-#endif
-
-#include <KIconLoader>
-#include <KIconEffect>
-#include <KCategorizedSortFilterProxyModel>
-#include <KUser>
-#include <KCategorizedView>
-
-#include "dolphinview.h"
-#include "dolphinmodel.h"
-
-#define HORIZONTAL_HINT 3
-
-DolphinCategoryDrawer::DolphinCategoryDrawer(KCategorizedView *view)
-        : KCategoryDrawerV3(view)
-        , hotSpotPressed(NoneHotSpot)
-        , selectAll(KIconLoader::global()->loadIcon("list-add", KIconLoader::Desktop, 16))
-        , selectAllHovered(KIconLoader::global()->iconEffect()->apply(selectAll, KIconLoader::Desktop, KIconLoader::ActiveState))
-        , selectAllDisabled(KIconLoader::global()->iconEffect()->apply(selectAll, KIconLoader::Desktop, KIconLoader::DisabledState))
-        , unselectAll(KIconLoader::global()->loadIcon("list-remove", KIconLoader::Desktop, 16))
-        , unselectAllHovered(KIconLoader::global()->iconEffect()->apply(unselectAll, KIconLoader::Desktop, KIconLoader::ActiveState))
-        , unselectAllDisabled(KIconLoader::global()->iconEffect()->apply(unselectAll, KIconLoader::Desktop, KIconLoader::DisabledState))
-{
-}
-
-DolphinCategoryDrawer::~DolphinCategoryDrawer()
-{
-}
-
-bool DolphinCategoryDrawer::allCategorySelected(const QString &category) const
-{
-    const QModelIndexList list = view()->block(category);
-    foreach (const QModelIndex &index, list) {
-        if (!view()->selectionModel()->isSelected(index)) {
-            return false;
-        }
-    }
-    return true;
-}
-
-bool DolphinCategoryDrawer::someCategorySelected(const QString &category) const
-{
-    const QModelIndexList list = view()->block(category);
-    foreach (const QModelIndex &index, list) {
-        if (view()->selectionModel()->isSelected(index)) {
-            return true;
-        }
-    }
-    return false;
-}
-
-void DolphinCategoryDrawer::drawCategory(const QModelIndex &index, int sortRole,
-                                         const QStyleOption &option, QPainter *painter) const
-{
-    Q_UNUSED(sortRole);
-    painter->setRenderHint(QPainter::Antialiasing);
-
-    if (!index.isValid()) {
-        return;
-    }
-
-    const QString category = index.model()->data(index, KCategorizedSortFilterProxyModel::CategoryDisplayRole).toString();
-    const QRect optRect = option.rect;
-    QFont font(QApplication::font());
-    font.setBold(true);
-    const QFontMetrics fontMetrics = QFontMetrics(font);
-
-    QColor outlineColor = option.palette.text().color();
-    outlineColor.setAlphaF(0.35);
-
-    //BEGIN: top left corner
-    {
-        painter->save();
-        painter->setPen(outlineColor);
-        const QPointF topLeft(optRect.topLeft());
-        QRectF arc(topLeft, QSizeF(4, 4));
-        arc.translate(0.5, 0.5);
-        painter->drawArc(arc, 1440, 1440);
-        painter->restore();
-    }
-    //END: top left corner
-
-    //BEGIN: left vertical line
-    {
-        QPoint start(optRect.topLeft());
-        start.ry() += 3;
-        QPoint verticalGradBottom(optRect.topLeft());
-        verticalGradBottom.ry() += fontMetrics.height() + 5;
-        QLinearGradient gradient(start, verticalGradBottom);
-        gradient.setColorAt(0, outlineColor);
-        gradient.setColorAt(1, Qt::transparent);
-        painter->fillRect(QRect(start, QSize(1, fontMetrics.height() + 5)), gradient);
-    }
-    //END: left vertical line
-
-    //BEGIN: horizontal line
-    {
-        QPoint start(optRect.topLeft());
-        start.rx() += 3;
-        QPoint horizontalGradTop(optRect.topLeft());
-        horizontalGradTop.rx() += optRect.width() - 6;
-        painter->fillRect(QRect(start, QSize(optRect.width() - 6, 1)), outlineColor);
-    }
-    //END: horizontal line
-
-    //BEGIN: top right corner
-    {
-        painter->save();
-        painter->setPen(outlineColor);
-        QPointF topRight(optRect.topRight());
-        topRight.rx() -= 4;
-        QRectF arc(topRight, QSizeF(4, 4));
-        arc.translate(0.5, 0.5);
-        painter->drawArc(arc, 0, 1440);
-        painter->restore();
-    }
-    //END: top right corner
-
-    //BEGIN: right vertical line
-    {
-        QPoint start(optRect.topRight());
-        start.ry() += 3;
-        QPoint verticalGradBottom(optRect.topRight());
-        verticalGradBottom.ry() += fontMetrics.height() + 5;
-        QLinearGradient gradient(start, verticalGradBottom);
-        gradient.setColorAt(0, outlineColor);
-        gradient.setColorAt(1, Qt::transparent);
-        painter->fillRect(QRect(start, QSize(1, fontMetrics.height() + 5)), gradient);
-    }
-    //END: right vertical line
-
-    const int iconSize = KIconLoader::global()->currentSize(KIconLoader::Small);
-
-    //BEGIN: select/unselect all
-    {
-        if (this->category == category) {
-            QRect iconAllRect(option.rect);
-            iconAllRect.setTop(iconAllRect.top() + 4);
-            iconAllRect.setLeft(iconAllRect.right() - 16 - 7);
-            iconAllRect.setSize(QSize(iconSize, iconSize));
-            if (!allCategorySelected(category)) {
-                if (iconAllRect.contains(pos)) {
-                    painter->drawPixmap(iconAllRect, selectAllHovered);
-                } else {
-                    painter->drawPixmap(iconAllRect, selectAll);
-                }
-            } else {
-                painter->drawPixmap(iconAllRect, selectAllDisabled);
-            }
-            QRect iconNoneRect(option.rect);
-            iconNoneRect.setTop(iconNoneRect.top() + 4);
-            iconNoneRect.setLeft(iconNoneRect.right() - 16 * 2 - 7 * 2);
-            iconNoneRect.setSize(QSize(iconSize, iconSize));
-            if (someCategorySelected(category)) {
-                if (iconNoneRect.contains(pos)) {
-                    painter->drawPixmap(iconNoneRect, unselectAllHovered);
-                } else {
-                    painter->drawPixmap(iconNoneRect, unselectAll);
-                }
-            } else {
-                painter->drawPixmap(iconNoneRect, unselectAllDisabled);
-            }
-        }
-    }
-    //END: select/unselect all
-
-    //BEGIN: category information
-    {
-        bool paintIcon;
-        QPixmap icon;
-        switch (index.column()) {
-             case KDirModel::Owner: {
-                     paintIcon = true;
-                     KUser user(category);
-                     const QString faceIconPath = user.faceIconPath();
-                     if (faceIconPath.isEmpty()) {
-                         icon = KIconLoader::global()->loadIcon("user-identity", KIconLoader::NoGroup, iconSize);
-                     } else {
-                         icon = QPixmap::fromImage(QImage(faceIconPath).scaledToHeight(iconSize, Qt::SmoothTransformation));
-                     }
-                 }
-                 break;
-             case KDirModel::Type: {
-                     paintIcon = true;
-                     const KCategorizedSortFilterProxyModel *proxyModel = static_cast<const KCategorizedSortFilterProxyModel*>(index.model());
-                     const DolphinModel *model = static_cast<const DolphinModel*>(proxyModel->sourceModel());
-                     KFileItem item = model->itemForIndex(proxyModel->mapToSource(index));
-                     // This is the only way of getting the icon right. Others will fail on corner
-                     // cases like the item representing this group has been set a different icon,
-                     // so the group icon drawn is that one particularly. This way assures the drawn
-                     // icon is the one of the mimetype of the group itself. (ereslibre)
-                     icon = KIconLoader::global()->loadMimeTypeIcon(item.mimeTypePtr()->iconName(), KIconLoader::NoGroup, iconSize);
-                 }
-                 break;
-             default:
-                 paintIcon = false;
-             }
-
-        if (paintIcon) {
-            QRect iconRect(option.rect);
-            iconRect.setTop(iconRect.top() + 4);
-            iconRect.setLeft(iconRect.left() + 7);
-            iconRect.setSize(QSize(iconSize, iconSize));
-
-            painter->drawPixmap(iconRect, icon);
-        }
-
-        //BEGIN: text
-        {
-            QRect textRect(option.rect);
-            textRect.setTop(textRect.top() + 7);
-            textRect.setLeft(textRect.left() + 7 + (paintIcon ? (iconSize + 6) : 0));
-            textRect.setHeight(qMax(fontMetrics.height(), iconSize));
-            textRect.setRight(textRect.right() - 7);
-            textRect.setBottom(textRect.bottom() - 5); // only one pixel separation here (no gradient)
-
-            painter->save();
-            painter->setFont(font);
-            QColor penColor(option.palette.text().color());
-            penColor.setAlphaF(0.6);
-            painter->setPen(penColor);
-            painter->drawText(textRect, Qt::AlignLeft | Qt::AlignVCenter, category);
-            painter->restore();
-        }
-        //END: text
-    }
-    //BEGIN: category information
-}
-
-int DolphinCategoryDrawer::categoryHeight(const QModelIndex &index, const QStyleOption &) const
-{
-    int iconSize = KIconLoader::global()->currentSize(KIconLoader::Small);
-    QFont font(QApplication::font());
-    font.setBold(true);
-    const QFontMetrics fontMetrics = QFontMetrics(font);
-    int heightWithoutIcon = fontMetrics.height() + (iconSize / 4) * 2 + 1; /* 1 pixel-width gradient */
-    bool paintIcon;
-
-    switch (index.column()) {
-    case KDirModel::Owner:
-    case KDirModel::Type:
-        paintIcon = true;
-        break;
-    default:
-        paintIcon = false;
-    }
-
-    if (paintIcon) {
-        return qMax(heightWithoutIcon + 5, iconSize + 1 /* 1 pixel-width gradient */
-                    + 5 /* top and bottom separation */);
-    }
-
-    return heightWithoutIcon + 5;
-}
-
-void DolphinCategoryDrawer::mouseButtonPressed(const QModelIndex &index, const QRect &blockRect, QMouseEvent *event)
-{
-    if (!index.isValid()) {
-        event->ignore();
-        return;
-    }
-    const QString category = index.model()->data(index, KCategorizedSortFilterProxyModel::CategoryDisplayRole).toString();
-    int iconSize = KIconLoader::global()->currentSize(KIconLoader::Small);
-    if (this->category == category) {
-        QRect iconAllRect(blockRect);
-        iconAllRect.setTop(iconAllRect.top() + 4);
-        iconAllRect.setLeft(iconAllRect.right() - 16 - 7);
-        iconAllRect.setSize(QSize(iconSize, iconSize));
-        if (iconAllRect.contains(pos)) {
-            event->accept();
-            hotSpotPressed = SelectAllHotSpot;
-            categoryPressed = index;
-            return;
-        }
-        QRect iconNoneRect(blockRect);
-        iconNoneRect.setTop(iconNoneRect.top() + 4);
-        iconNoneRect.setLeft(iconNoneRect.right() - 16 * 2 - 7 * 2);
-        iconNoneRect.setSize(QSize(iconSize, iconSize));
-        if (iconNoneRect.contains(pos)) {
-            event->accept();
-            hotSpotPressed = UnselectAllHotSpot;
-            categoryPressed = index;
-            return;
-        }
-    }
-    event->ignore();
-}
-
-void DolphinCategoryDrawer::mouseButtonReleased(const QModelIndex &index, const QRect &blockRect, QMouseEvent *event)
-{
-    if (!index.isValid() || hotSpotPressed == NoneHotSpot || categoryPressed != index) {
-        event->ignore();
-        return;
-    }
-    categoryPressed = QModelIndex();
-    const QString category = index.model()->data(index, KCategorizedSortFilterProxyModel::CategoryDisplayRole).toString();
-    int iconSize = KIconLoader::global()->currentSize(KIconLoader::Small);
-    if (this->category == category) {
-        QRect iconAllRect(blockRect);
-        iconAllRect.setTop(iconAllRect.top() + 4);
-        iconAllRect.setLeft(iconAllRect.right() - 16 - 7);
-        iconAllRect.setSize(QSize(iconSize, iconSize));
-        if (iconAllRect.contains(pos)) {
-            if (hotSpotPressed == SelectAllHotSpot) {
-                event->accept();
-                emit actionRequested(SelectAll, index);
-            } else {
-                event->ignore();
-                hotSpotPressed = NoneHotSpot;
-            }
-            return;
-        }
-        QRect iconNoneRect(blockRect);
-        iconNoneRect.setTop(iconNoneRect.top() + 4);
-        iconNoneRect.setLeft(iconNoneRect.right() - 16 * 2 - 7 * 2);
-        iconNoneRect.setSize(QSize(iconSize, iconSize));
-        if (iconNoneRect.contains(pos)) {
-            if (hotSpotPressed == UnselectAllHotSpot) {
-                event->accept();
-                emit actionRequested(UnselectAll, index);
-            } else {
-                event->ignore();
-                hotSpotPressed = NoneHotSpot;
-            }
-            return;
-        }
-    }
-    event->ignore();
-}
-
-void DolphinCategoryDrawer::mouseMoved(const QModelIndex &index, const QRect &, QMouseEvent *event)
-{
-    event->ignore();
-    if (!index.isValid()) {
-        return;
-    }
-    pos = event->pos();
-    category = index.model()->data(index, KCategorizedSortFilterProxyModel::CategoryDisplayRole).toString();
-}
-
-void DolphinCategoryDrawer::mouseLeft(const QModelIndex &, const QRect &)
-{
-    pos = QPoint();
-    category.clear();
-}
diff --git a/src/views/dolphincategorydrawer.h b/src/views/dolphincategorydrawer.h
deleted file mode 100644 (file)
index 94c9e69..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-/* This file is part of the KDE project
-  * Copyright (C) 2007 Rafael Fernández López <ereslibre@kde.org>
-  *
-  * This library is free software; you can redistribute it and/or
-  * modify it under the terms of the GNU Library General Public
-  * License as published by the Free Software Foundation; either
-  * version 2 of the License, or (at your option) any later version.
-  *
-  * This library 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
-  * Library General Public License for more details.
-  *
-  * You should have received a copy of the GNU Library General Public License
-  * along with this library; see the file COPYING.LIB.  If not, write to
-  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-  * Boston, MA 02110-1301, USA.
-*/
-
-#ifndef DOLPHINCATEGORYDRAWER_H
-#define DOLPHINCATEGORYDRAWER_H
-
-#include <kcategorydrawer.h>
-
-#include <QStyleOption>
-#include <QModelIndex>
-
-#include <libdolphin_export.h>
-
-class LIBDOLPHINPRIVATE_EXPORT DolphinCategoryDrawer
-    : public KCategoryDrawerV3
-{
-public:
-    using KCategoryDrawerV2::mouseButtonPressed;
-    using KCategoryDrawerV2::mouseButtonReleased;
-
-    enum Action {
-        SelectAll = 0,
-        UnselectAll
-    };
-
-    DolphinCategoryDrawer(KCategorizedView *view);
-
-    virtual ~DolphinCategoryDrawer();
-
-    bool allCategorySelected(const QString &category) const;
-
-    bool someCategorySelected(const QString &category) const;
-
-    virtual void drawCategory(const QModelIndex &index, int sortRole,
-                              const QStyleOption &option, QPainter *painter) const;
-
-    virtual int categoryHeight(const QModelIndex &index, const QStyleOption &option) const;
-
-protected:
-    virtual void mouseButtonPressed(const QModelIndex &index, const QRect &blockRect, QMouseEvent *event);
-
-    virtual void mouseButtonReleased(const QModelIndex &index, const QRect &blockRect, QMouseEvent *event);
-
-    virtual void mouseMoved(const QModelIndex &index, const QRect &blockRect, QMouseEvent *event);
-
-    virtual void mouseLeft(const QModelIndex &index,const QRect &blockRect);
-
-private:
-    enum HotSpot {
-        NoneHotSpot = 0,
-        SelectAllHotSpot,
-        UnselectAllHotSpot
-    };
-
-    HotSpot hotSpotPressed;
-    QModelIndex categoryPressed;
-
-    QPixmap selectAll;
-    QPixmap selectAllHovered;
-    QPixmap selectAllDisabled;
-    QPixmap unselectAll;
-    QPixmap unselectAllHovered;
-    QPixmap unselectAllDisabled;
-
-    QPoint pos;
-    QString category;
-};
-
-#endif // DOLPHINCATEGORYDRAWER_H
diff --git a/src/views/dolphincolumnview.cpp b/src/views/dolphincolumnview.cpp
deleted file mode 100644 (file)
index 3425c46..0000000
+++ /dev/null
@@ -1,621 +0,0 @@
-/***************************************************************************
- *   Copyright (C) 2007-2009 by Peter Penz <peter.penz19@gmail.com>        *
- *                                                                         *
- *   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 program 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 program; if not, write to the                         *
- *   Free Software Foundation, Inc.,                                       *
- *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA            *
- ***************************************************************************/
-
-#include "dolphincolumnview.h"
-
-#include "dolphinmodel.h"
-#include "dolphincolumnviewcontainer.h"
-#include "dolphinviewcontroller.h"
-#include "dolphindirlister.h"
-#include "dolphinfileitemdelegate.h"
-#include "dolphinsortfilterproxymodel.h"
-#include "settings/dolphinsettings.h"
-#include "dolphinviewautoscroller.h"
-#include "dolphin_columnmodesettings.h"
-#include "dolphin_generalsettings.h"
-#include "draganddrophelper.h"
-#include "folderexpander.h"
-#include "tooltips/tooltipmanager.h"
-#include "viewextensionsfactory.h"
-#include "viewmodecontroller.h"
-#include "zoomlevelinfo.h"
-
-#include <KColorScheme>
-#include <KDirLister>
-#include <KFileItem>
-#include <KIO/PreviewJob>
-#include <KIcon>
-#include <KIconEffect>
-#include <KJob>
-#include <KLocale>
-#include <konqmimedata.h>
-
-#include <QApplication>
-#include <QClipboard>
-#include <QHeaderView>
-#include <QLabel>
-#include <QPainter>
-#include <QPoint>
-#include <QScrollBar>
-
-DolphinColumnView::DolphinColumnView(QWidget* parent,
-                                     DolphinColumnViewContainer* container,
-                                     const KUrl& url) :
-    DolphinTreeView(parent),
-    m_active(false),
-    m_container(container),
-    m_extensionsFactory(0),
-    m_url(url),
-    m_childUrl(),
-    m_font(),
-    m_decorationSize(),
-    m_dirLister(0),
-    m_dolphinModel(0),
-    m_proxyModel(0),
-    m_resizeWidget(0),
-    m_resizeXOrigin(-1)
-{
-    setMouseTracking(true);
-    setAcceptDrops(true);
-    setUniformRowHeights(true);
-    setSelectionBehavior(SelectItems);
-    setSelectionMode(QAbstractItemView::ExtendedSelection);
-    setDragDropMode(QAbstractItemView::DragDrop);
-    setDropIndicatorShown(false);
-    setRootIsDecorated(false);
-    setItemsExpandable(false);
-    setEditTriggers(QAbstractItemView::NoEditTriggers);
-    setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
-    setVerticalScrollMode(QTreeView::ScrollPerPixel);
-
-    m_resizeWidget = new QLabel(this);
-    m_resizeWidget->setPixmap(KIcon("transform-move").pixmap(KIconLoader::SizeSmall));
-    m_resizeWidget->setToolTip(i18nc("@info:tooltip", "Resize column"));
-    setCornerWidget(m_resizeWidget);
-    m_resizeWidget->installEventFilter(this);
-
-    const ColumnModeSettings* settings = DolphinSettings::instance().columnModeSettings();
-    Q_ASSERT(settings);
-
-    if (settings->useSystemFont()) {
-        m_font = KGlobalSettings::generalFont();
-    } else {
-        m_font = QFont(settings->fontFamily(),
-                       qRound(settings->fontSize()),
-                       settings->fontWeight(),
-                       settings->italicFont());
-        m_font.setPointSizeF(settings->fontSize());
-    }
-
-    setMinimumWidth(settings->fontSize() * 10);
-    setMaximumWidth(settings->columnWidth());
-
-    connect(this, SIGNAL(viewportEntered()),
-            m_container->m_dolphinViewController, SLOT(emitViewportEntered()));
-    connect(this, SIGNAL(entered(const QModelIndex&)),
-            this, SLOT(slotEntered(const QModelIndex&)));
-
-    const DolphinView* dolphinView = m_container->m_dolphinViewController->view();
-    connect(dolphinView, SIGNAL(showPreviewChanged()),
-            this, SLOT(slotShowPreviewChanged()));
-
-    m_dirLister = new DolphinDirLister();
-    m_dirLister->setAutoUpdate(true);
-    m_dirLister->setMainWindow(window());
-    m_dirLister->setDelayedMimeTypes(true);
-    const bool showHiddenFiles = m_container->m_dolphinViewController->view()->showHiddenFiles();
-    m_dirLister->setShowingDotFiles(showHiddenFiles);
-    connect(m_dirLister, SIGNAL(completed()), this, SLOT(slotDirListerCompleted()));
-
-    m_dolphinModel = new DolphinModel(this);
-    m_dolphinModel->setDirLister(m_dirLister);
-    m_dolphinModel->setDropsAllowed(DolphinModel::DropOnDirectory);
-
-    m_proxyModel = new DolphinSortFilterProxyModel(this);
-    m_proxyModel->setSourceModel(m_dolphinModel);
-    m_proxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
-
-    m_proxyModel->setSorting(dolphinView->sorting());
-    m_proxyModel->setSortOrder(dolphinView->sortOrder());
-    m_proxyModel->setSortFoldersFirst(dolphinView->sortFoldersFirst());
-
-    setModel(m_proxyModel);
-
-    connect(KGlobalSettings::self(), SIGNAL(kdisplayFontChanged()),
-            this, SLOT(updateFont()));
-
-    const ViewModeController* viewModeController = m_container->m_viewModeController;
-    connect(viewModeController, SIGNAL(zoomLevelChanged(int)),
-            this, SLOT(setZoomLevel(int)));
-    const QString nameFilter = viewModeController->nameFilter();
-    if (!nameFilter.isEmpty()) {
-        m_proxyModel->setFilterFixedString(nameFilter);
-    }
-
-    updateDecorationSize(dolphinView->showPreview());
-    updateBackground();
-
-    DolphinViewController* dolphinViewController = m_container->m_dolphinViewController;
-    m_extensionsFactory = new ViewExtensionsFactory(this, dolphinViewController, viewModeController);
-    m_extensionsFactory->fileItemDelegate()->setMinimizedNameColumn(true);
-
-    m_dirLister->openUrl(url, KDirLister::NoFlags);
-}
-
-DolphinColumnView::~DolphinColumnView()
-{
-    delete m_proxyModel;
-    m_proxyModel = 0;
-    delete m_dolphinModel;
-    m_dolphinModel = 0;
-    m_dirLister = 0; // deleted by m_dolphinModel
-}
-
-
-void DolphinColumnView::setActive(bool active)
-{
-    if (m_active != active) {
-        m_active = active;
-
-        if (active) {
-            activate();
-        } else {
-            deactivate();
-        }
-    }
-}
-
-bool DolphinColumnView::isActive() const
-{
-    return m_active;
-}
-
-void DolphinColumnView::setChildUrl(const KUrl& url)
-{
-    m_childUrl = url;
-}
-
-KUrl DolphinColumnView::childUrl() const
-{
-    return m_childUrl;
-}
-
-void DolphinColumnView::setUrl(const KUrl& url)
-{
-    if (url != m_url) {
-        m_url = url;
-        m_dirLister->openUrl(url, KDirLister::NoFlags);
-    }
-}
-
-KUrl DolphinColumnView::url() const
-{
-    return m_url;
-}
-
-void DolphinColumnView::updateBackground()
-{
-    // TODO: The alpha-value 150 is copied from DolphinView::setActive(). When
-    // cleaning up the cut-indication of DolphinColumnView with the code from
-    // DolphinView a common helper-class should be available which can be shared
-    // by all view implementations -> no hardcoded value anymore
-    const QPalette::ColorRole role = viewport()->backgroundRole();
-    QColor color = viewport()->palette().color(role);
-    color.setAlpha((m_active && m_container->m_active) ? 255 : 150);
-
-    QPalette palette = viewport()->palette();
-    palette.setColor(role, color);
-    viewport()->setPalette(palette);
-
-    update();
-}
-
-KFileItem DolphinColumnView::itemAt(const QPoint& pos) const
-{
-    KFileItem item;
-    const QModelIndex index = indexAt(pos);
-    if (index.isValid() && (index.column() == DolphinModel::Name)) {
-        const QModelIndex dolphinModelIndex = m_proxyModel->mapToSource(index);
-        item = m_dolphinModel->itemForIndex(dolphinModelIndex);
-    }
-    return item;
-}
-
-void DolphinColumnView::setSelectionModel(QItemSelectionModel* model)
-{
-    // If a change of the selection is done although the view is not active
-    // (e. g. by the selection markers), the column must be activated. This
-    // is done by listening to the current selectionChanged() signal.
-    if (selectionModel()) {
-        disconnect(selectionModel(), SIGNAL(selectionChanged(QItemSelection, QItemSelection)),
-                   this, SLOT(requestActivation()));
-    }
-
-    DolphinTreeView::setSelectionModel(model);
-
-    connect(selectionModel(), SIGNAL(selectionChanged(QItemSelection, QItemSelection)),
-            this, SLOT(requestActivation()));
-}
-
-QStyleOptionViewItem DolphinColumnView::viewOptions() const
-{
-    QStyleOptionViewItem viewOptions = DolphinTreeView::viewOptions();
-    viewOptions.font = m_font;
-    viewOptions.fontMetrics = QFontMetrics(m_font);
-    viewOptions.decorationSize = m_decorationSize;
-    viewOptions.showDecorationSelected = true;
-    return viewOptions;
-}
-
-bool DolphinColumnView::event(QEvent* event)
-{
-    if (event->type() == QEvent::Polish) {
-        // Hide all columns except of the 'Name' column
-        for (int i = DolphinModel::Name + 1; i < DolphinModel::ExtraColumnCount; ++i) {
-            hideColumn(i);
-        }
-        header()->hide();
-    }
-
-    return DolphinTreeView::event(event);
-}
-
-void DolphinColumnView::startDrag(Qt::DropActions supportedActions)
-{
-    DragAndDropHelper::instance().startDrag(this, supportedActions, m_container->m_dolphinViewController);
-    DolphinTreeView::startDrag(supportedActions);
-}
-
-void DolphinColumnView::dragEnterEvent(QDragEnterEvent* event)
-{
-    event->acceptProposedAction();
-    requestActivation();
-    DolphinTreeView::dragEnterEvent(event);
-}
-
-void DolphinColumnView::dragMoveEvent(QDragMoveEvent* event)
-{
-    DolphinTreeView::dragMoveEvent(event);
-    event->acceptProposedAction();
-}
-
-void DolphinColumnView::dropEvent(QDropEvent* event)
-{
-    const QModelIndex index = indexAt(event->pos());
-    m_container->m_dolphinViewController->setItemView(this);
-    const QModelIndex dolphinModelIndex = m_proxyModel->mapToSource(index);
-    const KFileItem item = m_dolphinModel->itemForIndex(dolphinModelIndex);
-    m_container->m_dolphinViewController->indicateDroppedUrls(item, event);
-    DolphinTreeView::dropEvent(event);
-}
-
-void DolphinColumnView::paintEvent(QPaintEvent* event)
-{
-    if (!m_childUrl.isEmpty()) {
-        // Indicate the shown URL of the next column by highlighting the shown folder item
-        const QModelIndex dirIndex = m_dolphinModel->indexForUrl(m_childUrl);
-        const QModelIndex proxyIndex = m_proxyModel->mapFromSource(dirIndex);
-        if (proxyIndex.isValid() && !selectionModel()->isSelected(proxyIndex)) {
-            QPainter painter(viewport());
-
-            QStyleOptionViewItemV4 option;
-            option.initFrom(this);
-            option.rect = visualRect(proxyIndex);
-            option.state = QStyle::State_Enabled | QStyle::State_HasFocus;
-            option.viewItemPosition = QStyleOptionViewItemV4::OnlyOne;
-            style()->drawPrimitive(QStyle::PE_FrameFocusRect, &option, &painter, this);
-        }
-    }
-
-    DolphinTreeView::paintEvent(event);
-}
-
-void DolphinColumnView::mousePressEvent(QMouseEvent* event)
-{
-    requestActivation();
-    if (!indexAt(event->pos()).isValid() && (QApplication::mouseButtons() & Qt::MidButton)) {
-        m_container->m_dolphinViewController->replaceUrlByClipboard();
-    }
-
-    DolphinTreeView::mousePressEvent(event);
-}
-
-void DolphinColumnView::keyPressEvent(QKeyEvent* event)
-{
-    const bool hadSelection = selectionModel()->hasSelection();
-    DolphinTreeView::keyPressEvent(event);
-
-    DolphinViewController* controller = m_container->m_dolphinViewController;
-    controller->handleKeyPressEvent(event);
-    switch (event->key()) {
-    case Qt::Key_Right: {
-        // Special key handling for the column: A Key_Right should
-        // open a new column for the currently selected folder.
-        QModelIndex dolphinModelIndex = m_proxyModel->mapToSource(currentIndex());
-
-        // If there is no selection we automatically move to the child url
-        // instead of the first directory.
-        // See BUG:263110
-        if (!hadSelection && !childUrl().isEmpty()) {
-            dolphinModelIndex = m_dolphinModel->indexForUrl(childUrl());
-        }
-
-        const KFileItem item = m_dolphinModel->itemForIndex(dolphinModelIndex);
-        if (!item.isNull() && item.isDir()) {
-            controller->emitItemTriggered(item);
-        }
-        break;
-    }
-
-    case Qt::Key_Escape:
-        selectionModel()->setCurrentIndex(selectionModel()->currentIndex(),
-                                          QItemSelectionModel::Current |
-                                          QItemSelectionModel::Clear);
-        break;
-
-    default:
-        break;
-    }
-}
-
-void DolphinColumnView::contextMenuEvent(QContextMenuEvent* event)
-{
-    requestActivation();
-    DolphinTreeView::contextMenuEvent(event);
-    m_container->m_dolphinViewController->triggerContextMenuRequest(event->pos());
-}
-
-void DolphinColumnView::wheelEvent(QWheelEvent* event)
-{
-    const int step = m_decorationSize.height();
-    verticalScrollBar()->setSingleStep(step);
-    DolphinTreeView::wheelEvent(event);
-}
-
-void DolphinColumnView::leaveEvent(QEvent* event)
-{
-    DolphinTreeView::leaveEvent(event);
-    // if the mouse is above an item and moved very fast outside the widget,
-    // no viewportEntered() signal might be emitted although the mouse has been moved
-    // above the viewport
-    m_container->m_dolphinViewController->emitViewportEntered();
-}
-
-void DolphinColumnView::currentChanged(const QModelIndex& current, const QModelIndex& previous)
-{
-    DolphinTreeView::currentChanged(current, previous);
-    m_extensionsFactory->handleCurrentIndexChange(current, previous);
-}
-
-QRect DolphinColumnView::visualRect(const QModelIndex& index) const
-{
-    QRect rect = DolphinTreeView::visualRect(index);
-
-    const QModelIndex dolphinModelIndex = m_proxyModel->mapToSource(index);
-    const KFileItem item = m_dolphinModel->itemForIndex(dolphinModelIndex);
-    if (!item.isNull()) {
-        const int width = DolphinFileItemDelegate::nameColumnWidth(item.text(), viewOptions());
-        rect.setWidth(width);
-    }
-
-    return rect;
-}
-
-bool DolphinColumnView::acceptsDrop(const QModelIndex& index) const
-{
-    if (index.isValid() && (index.column() == DolphinModel::Name)) {
-        // Accept drops above directories
-        const QModelIndex dolphinModelIndex = m_proxyModel->mapToSource(index);
-        const KFileItem item = m_dolphinModel->itemForIndex(dolphinModelIndex);
-        return !item.isNull() && item.isDir();
-    }
-
-    return false;
-}
-
-bool DolphinColumnView::eventFilter(QObject* watched, QEvent* event)
-{
-    if (watched == m_resizeWidget) {
-        switch (event->type()) {
-        case QEvent::MouseButtonPress: {
-            // Initiate the resizing of the column
-            QMouseEvent* mouseEvent = static_cast<QMouseEvent*>(event);
-            m_resizeXOrigin = mouseEvent->globalX();
-            m_resizeWidget->setMouseTracking(true);
-            event->accept();
-            return true;
-        }
-
-        case QEvent::MouseButtonDblClick: {
-            // Reset the column width to the default value
-            const ColumnModeSettings* settings = DolphinSettings::instance().columnModeSettings();
-            setMaximumWidth(settings->columnWidth());
-            m_container->layoutColumns();
-            m_resizeWidget->setMouseTracking(false);
-            m_resizeXOrigin = -1;
-            event->accept();
-            return true;
-        }
-
-        case QEvent::MouseMove: {
-            // Resize the column and trigger a relayout of the container
-            QMouseEvent* mouseEvent = static_cast<QMouseEvent*>(event);
-            int requestedWidth = maximumWidth() - m_resizeXOrigin + mouseEvent->globalX();;
-            if (requestedWidth < minimumWidth()) {
-                requestedWidth = minimumWidth();
-            }
-            setMaximumWidth(requestedWidth);
-
-            m_container->layoutColumns();
-
-            m_resizeXOrigin = mouseEvent->globalX();
-
-            event->accept();
-            return true;
-        }
-
-        case QEvent::MouseButtonRelease: {
-            // The resizing has been finished
-            m_resizeWidget->setMouseTracking(false);
-            m_resizeXOrigin = -1;
-            event->accept();
-            return true;
-        }
-
-        default:
-            break;
-        }
-    }
-    return DolphinTreeView::eventFilter(watched, event);
-}
-void DolphinColumnView::setZoomLevel(int level)
-{
-    const int size = ZoomLevelInfo::iconSizeForZoomLevel(level);
-    ColumnModeSettings* settings = DolphinSettings::instance().columnModeSettings();
-
-    const bool showPreview = m_container->m_dolphinViewController->view()->showPreview();
-    if (showPreview) {
-        settings->setPreviewSize(size);
-    } else {
-        settings->setIconSize(size);
-    }
-
-    updateDecorationSize(showPreview);
-}
-
-void DolphinColumnView::slotEntered(const QModelIndex& index)
-{
-    m_container->m_dolphinViewController->setItemView(this);
-    m_container->m_dolphinViewController->emitItemEntered(index);
-}
-
-void DolphinColumnView::requestActivation()
-{
-    m_container->m_dolphinViewController->requestActivation();
-    if (!m_active) {
-        m_container->requestActivation(this);
-        selectionModel()->clear();
-    }
-}
-
-void DolphinColumnView::updateFont()
-{
-    const ColumnModeSettings* settings = DolphinSettings::instance().columnModeSettings();
-    Q_ASSERT(settings);
-
-    if (settings->useSystemFont()) {
-        m_font = KGlobalSettings::generalFont();
-    }
-}
-
-void DolphinColumnView::slotShowPreviewChanged()
-{
-    const DolphinView* view = m_container->m_dolphinViewController->view();
-    updateDecorationSize(view->showPreview());
-}
-
-void DolphinColumnView::slotDirListerCompleted()
-{
-    if (!m_childUrl.isEmpty()) {
-        return;
-    }
-
-    // Try to optimize the width of the column, so that no name gets clipped
-    const int requiredWidth = sizeHintForColumn(DolphinModel::Name);
-
-    const ColumnModeSettings* settings = DolphinSettings::instance().columnModeSettings();
-    if (requiredWidth > settings->columnWidth()) {
-        int frameAroundContents = 0;
-        if (style()->styleHint(QStyle::SH_ScrollView_FrameOnlyAroundContents)) {
-            // TODO: Using 2 PM_DefaultFrameWidths are not sufficient. Check Qt-code
-            // for other pixelmetrics that should be added...
-            frameAroundContents = style()->pixelMetric(QStyle::PM_DefaultFrameWidth) * 4;
-        }
-
-        const int scrollBarWidth = style()->pixelMetric(QStyle::PM_ScrollBarExtent, 0, verticalScrollBar());
-
-        setMaximumWidth(requiredWidth + frameAroundContents + scrollBarWidth);
-        m_container->layoutColumns();
-        if (m_active) {
-            m_container->assureVisibleActiveColumn();
-        }
-    }
-}
-
-void DolphinColumnView::activate()
-{
-    setFocus(Qt::OtherFocusReason);
-
-    connect(this, SIGNAL(clicked(const QModelIndex&)),
-            m_container->m_dolphinViewController, SLOT(requestTab(const QModelIndex&)));
-    if (KGlobalSettings::singleClick()) {
-        connect(this, SIGNAL(clicked(const QModelIndex&)),
-                m_container->m_dolphinViewController, SLOT(triggerItem(const QModelIndex&)));
-    } else {
-        connect(this, SIGNAL(doubleClicked(const QModelIndex&)),
-                m_container->m_dolphinViewController, SLOT(triggerItem(const QModelIndex&)));
-    }
-
-    if (selectionModel() && selectionModel()->currentIndex().isValid()) {
-        selectionModel()->setCurrentIndex(selectionModel()->currentIndex(), QItemSelectionModel::SelectCurrent);
-    }
-
-    updateBackground();
-}
-
-void DolphinColumnView::deactivate()
-{
-    clearFocus();
-
-    disconnect(this, SIGNAL(clicked(const QModelIndex&)),
-               m_container->m_dolphinViewController, SLOT(requestTab(const QModelIndex&)));
-    if (KGlobalSettings::singleClick()) {
-        disconnect(this, SIGNAL(clicked(const QModelIndex&)),
-                   m_container->m_dolphinViewController, SLOT(triggerItem(const QModelIndex&)));
-    } else {
-        disconnect(this, SIGNAL(doubleClicked(const QModelIndex&)),
-                   m_container->m_dolphinViewController, SLOT(triggerItem(const QModelIndex&)));
-    }
-
-    // It is important to disconnect the connection to requestActivation() temporary, otherwise the internal
-    // clearing of the selection would result in activating the column again.
-    disconnect(selectionModel(), SIGNAL(selectionChanged(QItemSelection, QItemSelection)),
-               this, SLOT(requestActivation()));
-    const QModelIndex current = selectionModel()->currentIndex();
-    selectionModel()->clear();
-    selectionModel()->setCurrentIndex(current, QItemSelectionModel::NoUpdate);
-    connect(selectionModel(), SIGNAL(selectionChanged(QItemSelection, QItemSelection)),
-            this, SLOT(requestActivation()));
-
-    updateBackground();
-}
-
-void DolphinColumnView::updateDecorationSize(bool showPreview)
-{
-    ColumnModeSettings* settings = DolphinSettings::instance().columnModeSettings();
-    const int iconSize = showPreview ? settings->previewSize() : settings->iconSize();
-    const QSize size(iconSize, iconSize);
-    setIconSize(size);
-
-    m_decorationSize = size;
-
-    doItemsLayout();
-}
-
-#include "dolphincolumnview.moc"
diff --git a/src/views/dolphincolumnview.h b/src/views/dolphincolumnview.h
deleted file mode 100644 (file)
index 2a4726a..0000000
+++ /dev/null
@@ -1,151 +0,0 @@
-/***************************************************************************
- *   Copyright (C) 2007-2009 by Peter Penz <peter.penz19@gmail.com>        *
- *                                                                         *
- *   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 program 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 program; if not, write to the                         *
- *   Free Software Foundation, Inc.,                                       *
- *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA            *
- ***************************************************************************/
-
-#ifndef DOLPHINCOLUMNVIEW_H
-#define DOLPHINCOLUMNVIEW_H
-
-#include "dolphinview.h"
-#include "dolphintreeview.h"
-
-#include <QFont>
-#include <QSize>
-#include <QStyleOption>
-
-#include <KUrl>
-
-class DolphinColumnViewContainer;
-class DolphinModel;
-class DolphinSortFilterProxyModel;
-class DolphinDirLister;
-class KFileItem;
-class QLabel;
-class SelectionManager;
-class ViewExtensionsFactory;
-
-/**
- * Represents one column inside the DolphinColumnViewContainer.
- */
-class DolphinColumnView : public DolphinTreeView
-{
-    Q_OBJECT
-
-public:
-    DolphinColumnView(QWidget* parent,
-                      DolphinColumnViewContainer* container,
-                      const KUrl& url);
-    virtual ~DolphinColumnView();
-
-    /**
-     * An active column is defined as column, which shows the same URL
-     * as indicated by the URL navigator. The active column is usually
-     * drawn in a lighter color. All operations are applied to this column.
-     */
-    void setActive(bool active);
-    bool isActive() const;
-
-    /**
-     * Sets the directory URL of the child column that is shown next to
-     * this column. This property is used for a visual indication
-     * of the shown directory, it does not trigger a loading of the model.
-     * When no url is selected and the user presses right, then child
-     * url will be used as column.
-     */
-    void setChildUrl(const KUrl& url);
-    KUrl childUrl() const;
-
-    /** Sets the directory URL that is shown inside the column widget. */
-    void setUrl(const KUrl& url);
-
-    /** Returns the directory URL that is shown inside the column widget. */
-    KUrl url() const;
-
-    /**
-     * Updates the background color dependent from the activation state
-     * \a isViewActive of the column view.
-     */
-    void updateBackground();
-
-    /**
-     * Returns the item on the position \a pos. The KFileItem instance
-     * is null if no item is below the position.
-     */
-    KFileItem itemAt(const QPoint& pos) const;
-
-    virtual void setSelectionModel(QItemSelectionModel* model);
-
-protected:
-    virtual QStyleOptionViewItem viewOptions() const;
-    virtual bool event(QEvent* event);
-    virtual void startDrag(Qt::DropActions supportedActions);
-    virtual void dragEnterEvent(QDragEnterEvent* event);
-    virtual void dragMoveEvent(QDragMoveEvent* event);
-    virtual void dropEvent(QDropEvent* event);
-    virtual void paintEvent(QPaintEvent* event);
-    virtual void mousePressEvent(QMouseEvent* event);
-    virtual void keyPressEvent(QKeyEvent* event);
-    virtual void contextMenuEvent(QContextMenuEvent* event);
-    virtual void wheelEvent(QWheelEvent* event);
-    virtual void leaveEvent(QEvent* event);
-    virtual void currentChanged(const QModelIndex& current, const QModelIndex& previous);
-    virtual QRect visualRect(const QModelIndex& index) const;
-    virtual bool acceptsDrop(const QModelIndex& index) const;
-    virtual bool eventFilter(QObject* watched, QEvent* event);
-
-private slots:
-    void setZoomLevel(int level);
-
-    void slotEntered(const QModelIndex& index);
-    void requestActivation();
-    void updateFont();
-
-    void slotShowPreviewChanged();
-
-    void slotDirListerCompleted();
-
-private:
-    /** Used by DolphinColumnView::setActive(). */
-    void activate();
-
-    /** Used by DolphinColumnView::setActive(). */
-    void deactivate();
-
-    void updateDecorationSize(bool showPreview);
-
-private:
-    bool m_active;
-    DolphinColumnViewContainer* m_container;
-    SelectionManager* m_selectionManager;
-    ViewExtensionsFactory* m_extensionsFactory;
-    KUrl m_url;      // URL of the directory that is shown
-    KUrl m_childUrl; // URL of the next column that is shown
-
-    QFont m_font;
-    QSize m_decorationSize;
-
-    DolphinDirLister* m_dirLister;
-    DolphinModel* m_dolphinModel;
-    DolphinSortFilterProxyModel* m_proxyModel;
-
-    QLabel* m_resizeWidget;
-    int m_resizeXOrigin;
-
-    friend class DolphinColumnViewContainer;
-};
-
-#endif
diff --git a/src/views/dolphincolumnviewcontainer.cpp b/src/views/dolphincolumnviewcontainer.cpp
deleted file mode 100644 (file)
index 3216dd2..0000000
+++ /dev/null
@@ -1,427 +0,0 @@
-/***************************************************************************
- *   Copyright (C) 2007-2009 by Peter Penz <peter.penz19@gmail.com>        *
- *                                                                         *
- *   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 program 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 program; if not, write to the                         *
- *   Free Software Foundation, Inc.,                                       *
- *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA            *
- ***************************************************************************/
-
-#include "dolphincolumnviewcontainer.h"
-
-#include "dolphin_columnmodesettings.h"
-
-#include "dolphincolumnview.h"
-#include "dolphinviewcontroller.h"
-#include "dolphinsortfilterproxymodel.h"
-#include "draganddrophelper.h"
-#include "settings/dolphinsettings.h"
-#include "viewmodecontroller.h"
-
-#include <QPoint>
-#include <QScrollBar>
-#include <QTimeLine>
-#include <QTimer>
-
-DolphinColumnViewContainer::DolphinColumnViewContainer(QWidget* parent,
-                                                       DolphinViewController* dolphinViewController,
-                                                       const ViewModeController* viewModeController) :
-    QScrollArea(parent),
-    m_dolphinViewController(dolphinViewController),
-    m_viewModeController(viewModeController),
-    m_active(false),
-    m_index(-1),
-    m_contentX(0),
-    m_columns(),
-    m_emptyViewport(0),
-    m_animation(0),
-    m_dragSource(0),
-    m_activeUrlTimer(0),
-    m_assureVisibleActiveColumnTimer(0)
-{
-    Q_ASSERT(dolphinViewController);
-    Q_ASSERT(viewModeController);
-
-    setAcceptDrops(true);
-    setFocusPolicy(Qt::NoFocus);
-    setFrameShape(QFrame::NoFrame);
-    setLayoutDirection(Qt::LeftToRight);
-
-    connect(viewModeController, SIGNAL(activationChanged(bool)),
-            this, SLOT(updateColumnsBackground(bool)));
-
-    connect(horizontalScrollBar(), SIGNAL(valueChanged(int)),
-            this, SLOT(moveContentHorizontally(int)));
-
-    m_animation = new QTimeLine(500, this);
-    connect(m_animation, SIGNAL(frameChanged(int)), horizontalScrollBar(), SLOT(setValue(int)));
-
-    m_activeUrlTimer = new QTimer(this);
-    m_activeUrlTimer->setSingleShot(true);
-    m_activeUrlTimer->setInterval(200);
-    connect(m_activeUrlTimer, SIGNAL(timeout()),
-            this, SLOT(updateActiveUrl()));
-
-    // Assuring that the active column gets fully visible is done with a small delay. This
-    // prevents that for temporary activations an animation gets started (e. g. when clicking
-    // on any folder of the parent column, the child column gets activated).
-    m_assureVisibleActiveColumnTimer = new QTimer(this);
-    m_assureVisibleActiveColumnTimer->setSingleShot(true);
-    m_assureVisibleActiveColumnTimer->setInterval(200);
-    connect(m_assureVisibleActiveColumnTimer, SIGNAL(timeout()),
-            this, SLOT(slotAssureVisibleActiveColumn()));
-
-    DolphinColumnView* column = new DolphinColumnView(viewport(), this, viewModeController->url());
-    m_columns.append(column);
-    requestActivation(column);
-
-    m_emptyViewport = new QFrame(viewport());
-    m_emptyViewport->setFrameStyle(QFrame::StyledPanel | QFrame::Sunken);
-
-    updateColumnsBackground(true);
-}
-
-DolphinColumnViewContainer::~DolphinColumnViewContainer()
-{
-    delete m_dragSource;
-    m_dragSource = 0;
-}
-
-KUrl DolphinColumnViewContainer::rootUrl() const
-{
-    return m_columns[0]->url();
-}
-
-QAbstractItemView* DolphinColumnViewContainer::activeColumn() const
-{
-    return m_columns[m_index];
-}
-
-void DolphinColumnViewContainer::showColumn(const KUrl& url)
-{
-    if (!rootUrl().isParentOf(url)) {
-        removeAllColumns();
-        m_columns[0]->setUrl(url);
-        return;
-    }
-
-    int columnIndex = 0;
-    foreach (DolphinColumnView* column, m_columns) {
-        if (column->url().equals(url, KUrl::CompareWithoutTrailingSlash)) {
-            // the column represents already the requested URL, hence activate it
-            requestActivation(column);
-            layoutColumns();
-            return;
-        } else if (!column->url().isParentOf(url)) {
-            // the column is no parent of the requested URL, hence
-            // just delete all remaining columns
-            if (columnIndex > 0) {
-                QList<DolphinColumnView*>::iterator start = m_columns.begin() + columnIndex;
-                QList<DolphinColumnView*>::iterator end = m_columns.end();
-                for (QList<DolphinColumnView*>::iterator it = start; it != end; ++it) {
-                    deleteColumn(*it);
-                }
-                m_columns.erase(start, end);
-
-                const int maxIndex = m_columns.count() - 1;
-                Q_ASSERT(maxIndex >= 0);
-                if (m_index > maxIndex) {
-                    m_index = maxIndex;
-                }
-                break;
-            }
-        }
-        ++columnIndex;
-    }
-
-    // Create missing columns. Assuming that the path is "/home/peter/Temp/" and
-    // the target path is "/home/peter/Temp/a/b/c/", then the columns "a", "b" and
-    // "c" will be created.
-    const int lastIndex = m_columns.count() - 1;
-    Q_ASSERT(lastIndex >= 0);
-
-    const KUrl& activeUrl = m_columns[lastIndex]->url();
-    Q_ASSERT(activeUrl.isParentOf(url));
-    Q_ASSERT(activeUrl != url);
-
-    QString path = activeUrl.url(KUrl::AddTrailingSlash);
-    const QString targetPath = url.url(KUrl::AddTrailingSlash);
-
-    columnIndex = lastIndex;
-    int slashIndex = path.count('/');
-    bool hasSubPath = (slashIndex >= 0);
-    while (hasSubPath) {
-        const QString subPath = targetPath.section('/', slashIndex, slashIndex);
-        if (subPath.isEmpty()) {
-            hasSubPath = false;
-        } else {
-            path += subPath + '/';
-            ++slashIndex;
-
-            const KUrl childUrl = KUrl(path);
-            m_columns[columnIndex]->setChildUrl(childUrl);
-            columnIndex++;
-
-            DolphinColumnView* column = new DolphinColumnView(viewport(), this, childUrl);
-            m_columns.append(column);
-
-            // Before invoking layoutColumns() the column must be set visible temporary.
-            // To prevent a flickering the initial geometry is set to a hidden position.
-            column->setGeometry(QRect(-1, -1, 1, 1));
-            column->show();
-            layoutColumns();
-        }
-    }
-
-    requestActivation(m_columns[columnIndex]);
-}
-
-void DolphinColumnViewContainer::mousePressEvent(QMouseEvent* event)
-{
-    m_dolphinViewController->requestActivation();
-    QScrollArea::mousePressEvent(event);
-}
-
-void DolphinColumnViewContainer::keyPressEvent(QKeyEvent* event)
-{
-    if (event->key() == Qt::Key_Left) {
-        if (m_index > 0) {
-            requestActivation(m_columns[m_index - 1]);
-        }
-    } else {
-        QScrollArea::keyPressEvent(event);
-    }
-}
-
-void DolphinColumnViewContainer::resizeEvent(QResizeEvent* event)
-{
-    QScrollArea::resizeEvent(event);
-    layoutColumns();
-    assureVisibleActiveColumn();
-}
-
-void DolphinColumnViewContainer::wheelEvent(QWheelEvent* event)
-{
-    // let Ctrl+wheel events propagate to the DolphinView for icon zooming
-    if ((event->modifiers() & Qt::ControlModifier) == Qt::ControlModifier) {
-        event->ignore();
-    } else {
-        QScrollArea::wheelEvent(event);
-    }
-}
-
-void DolphinColumnViewContainer::moveContentHorizontally(int x)
-{
-    m_contentX = isRightToLeft() ? +x : -x;
-    layoutColumns();
-}
-
-void DolphinColumnViewContainer::updateColumnsBackground(bool active)
-{
-    if (active == m_active) {
-        return;
-    }
-
-    m_active = active;
-
-    // dim the background of the viewport
-    const QPalette::ColorRole role = viewport()->backgroundRole();
-    QColor background = viewport()->palette().color(role);
-    background.setAlpha(0);  // make background transparent
-
-    QPalette palette = viewport()->palette();
-    palette.setColor(role, background);
-    viewport()->setPalette(palette);
-
-    foreach (DolphinColumnView* column, m_columns) {
-        column->updateBackground();
-    }
-}
-
-void DolphinColumnViewContainer::updateActiveUrl()
-{
-    const KUrl activeUrl = m_columns[m_index]->url();
-    m_dolphinViewController->requestUrlChange(activeUrl);
-}
-
-void DolphinColumnViewContainer::slotAssureVisibleActiveColumn()
-{
-    const int viewportWidth = viewport()->width();
-    const int x = activeColumn()->x();
-
-    // When a column that is partly visible gets activated,
-    // it is useful to also assure that the neighbor column is partly visible.
-    // This allows the user to scroll to the first/last column without using the
-    // scrollbar and drag & drop operations to invisible columns.
-    const int neighborColumnGap = 3 * style()->pixelMetric(QStyle::PM_ScrollBarExtent, 0, verticalScrollBar());
-
-    const int width = activeColumn()->maximumWidth();
-    if (x + width > viewportWidth) {
-        const int newContentX = m_contentX - x - width + viewportWidth;
-        if (isRightToLeft()) {
-            m_animation->setFrameRange(m_contentX, newContentX + neighborColumnGap);
-        } else {
-            m_animation->setFrameRange(-m_contentX, -newContentX + neighborColumnGap);
-        }
-        if (m_animation->state() != QTimeLine::Running) {
-           m_animation->start();
-        }
-    } else if (x < 0) {
-        const int newContentX = m_contentX - x;
-        if (isRightToLeft()) {
-            m_animation->setFrameRange(m_contentX, newContentX - neighborColumnGap);
-        } else {
-            m_animation->setFrameRange(-m_contentX, -newContentX - neighborColumnGap);
-        }
-        if (m_animation->state() != QTimeLine::Running) {
-           m_animation->start();
-        }
-    }
-}
-
-void DolphinColumnViewContainer::assureVisibleActiveColumn()
-{
-    m_assureVisibleActiveColumnTimer->start();
-}
-
-void DolphinColumnViewContainer::layoutColumns()
-{
-    // Layout the position of the columns corresponding to their maximum width
-    QRect emptyViewportRect;
-    if (isRightToLeft()) {
-        int columnWidth = m_columns[0]->maximumWidth();
-        int x = viewport()->width() - columnWidth + m_contentX;
-        foreach (DolphinColumnView* column, m_columns) {
-            columnWidth = column->maximumWidth();
-            column->setGeometry(QRect(x, 0, columnWidth, viewport()->height()));
-            x -= columnWidth;
-        }
-        emptyViewportRect = QRect(0, 0, x + columnWidth, viewport()->height());
-    } else {
-        int x = m_contentX;
-        foreach (DolphinColumnView* column, m_columns) {
-            const int columnWidth = column->maximumWidth();
-            column->setGeometry(QRect(x, 0, columnWidth, viewport()->height()));
-            x += columnWidth;
-        }
-        emptyViewportRect = QRect(x, 0, viewport()->width() - x, viewport()->height());
-    }
-
-    // Show an empty viewport if the columns don't cover the whole viewport
-    if (emptyViewportRect.isValid()) {
-        m_emptyViewport->show();
-        m_emptyViewport->setGeometry(emptyViewportRect);
-    } else {
-        m_emptyViewport->hide();
-    }
-
-    // Update the horizontal position indicator
-    int contentWidth = 0;
-    foreach (DolphinColumnView* column, m_columns) {
-        contentWidth += column->maximumWidth();
-    }
-
-    const int scrollBarMax = contentWidth - viewport()->width();
-    const bool updateScrollBar =    (horizontalScrollBar()->pageStep() != contentWidth)
-                                 || (horizontalScrollBar()->maximum()  != scrollBarMax);
-    if (updateScrollBar) {
-        horizontalScrollBar()->setPageStep(contentWidth);
-        horizontalScrollBar()->setRange(0, scrollBarMax);
-    }
-}
-
-void DolphinColumnViewContainer::requestActivation(DolphinColumnView* column)
-{
-    if (m_dolphinViewController->itemView() != column) {
-        m_dolphinViewController->setItemView(column);
-    }
-    if (focusProxy() != column) {
-        setFocusProxy(column);
-    }
-
-    if (!column->isActive()) {
-        // Deactivate the currently active column
-        if (m_index >= 0) {
-            m_columns[m_index]->setActive(false);
-        }
-
-        // Get the index of the column that should get activated
-        int index = 0;
-        foreach (DolphinColumnView* currColumn, m_columns) {
-            if (currColumn == column) {
-                break;
-            }
-            ++index;
-        }
-
-        Q_ASSERT(index != m_index);
-        Q_ASSERT(index < m_columns.count());
-
-        // Activate the requested column
-        m_index = index;
-        m_columns[m_index]->setActive(true);
-
-        m_activeUrlTimer->start(); // calls slot updateActiveUrl()
-    }
-
-    assureVisibleActiveColumn();
-}
-
-void DolphinColumnViewContainer::removeAllColumns()
-{
-    QList<DolphinColumnView*>::iterator start = m_columns.begin() + 1;
-    QList<DolphinColumnView*>::iterator end = m_columns.end();
-    for (QList<DolphinColumnView*>::iterator it = start; it != end; ++it) {
-        deleteColumn(*it);
-    }
-    m_columns.erase(start, end);
-    m_index = 0;
-    m_columns[0]->setActive(true);
-    assureVisibleActiveColumn();
-}
-
-void DolphinColumnViewContainer::deleteColumn(DolphinColumnView* column)
-{
-    if (!column) {
-        return;
-    }
-
-    if (m_dolphinViewController->itemView() == column) {
-        m_dolphinViewController->setItemView(0);
-    }
-    // deleteWhenNotDragSource(column) does not necessarily delete column,
-    // and we want its preview generator destroyed immediately.
-    column->hide();
-    // Prevent automatic destruction of column when this DolphinColumnViewContainer
-    // is destroyed.
-    column->setParent(0);
-    column->disconnect();
-
-    if (DragAndDropHelper::instance().isDragSource(column)) {
-        // The column is a drag source (the feature "Open folders
-        // during drag operations" is used). Deleting the view
-        // during an ongoing drag operation is not allowed, so
-        // this will postponed.
-        if (m_dragSource) {
-            // the old stored view is obviously not the drag source anymore
-            m_dragSource->deleteLater();
-            m_dragSource = 0;
-        }
-        m_dragSource = column;
-    } else {
-        delete column;
-        column = 0;
-    }
-}
-
-#include "dolphincolumnviewcontainer.moc"
diff --git a/src/views/dolphincolumnviewcontainer.h b/src/views/dolphincolumnviewcontainer.h
deleted file mode 100644 (file)
index af62599..0000000
+++ /dev/null
@@ -1,150 +0,0 @@
-/***************************************************************************
- *   Copyright (C) 2007-2009 by Peter Penz <peter.penz19@gmail.com>        *
- *                                                                         *
- *   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 program 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 program; if not, write to the                         *
- *   Free Software Foundation, Inc.,                                       *
- *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA            *
- ***************************************************************************/
-
-#ifndef DOLPHINCOLUMNVIEWCONTAINER_H
-#define DOLPHINCOLUMNVIEWCONTAINER_H
-
-#include "dolphinview.h"
-
-#include <KUrl>
-
-#include <QList>
-#include <QScrollArea>
-#include <QString>
-
-class DolphinColumnView;
-class DolphinViewController;
-class QFrame;
-class QTimeLine;
-class QTimer;
-
-/**
- * @brief Represents a container for columns represented as instances
- *        of DolphinColumnView.
- *
- * @see DolphinColumnView
- */
-class DolphinColumnViewContainer : public QScrollArea
-{
-    Q_OBJECT
-
-public:
-    /**
-     * @param parent                Parent widget.
-     * @param dolphinViewController Allows the DolphinColumnView to control the
-     *                              DolphinView in a limited way.
-     * @param viewModeController    Controller that is used by the DolphinView
-     *                              to control the DolphinColumnView. The DolphinColumnView
-     *                              only has read access to the controller.
-     * @param model                 Directory that is shown.
-     */
-    explicit DolphinColumnViewContainer(QWidget* parent,
-                                        DolphinViewController* dolphinViewController,
-                                        const ViewModeController* viewModeController);
-    virtual ~DolphinColumnViewContainer();
-
-    KUrl rootUrl() const;
-
-    QAbstractItemView* activeColumn() const;
-
-    /**
-     * Shows the column which represents the URL \a url. If the column
-     * is already shown, it gets activated, otherwise it will be created.
-     */
-    void showColumn(const KUrl& url);
-
-protected:
-    virtual void mousePressEvent(QMouseEvent* event);
-    virtual void keyPressEvent(QKeyEvent* event);
-    virtual void resizeEvent(QResizeEvent* event);
-    virtual void wheelEvent(QWheelEvent* event);
-
-private slots:
-    /**
-     * Moves the content of the columns view to represent
-     * the scrollbar position \a x.
-     */
-    void moveContentHorizontally(int x);
-
-    /**
-     * Updates the background color of the columns to respect
-     * the current activation state \a active.
-     */
-    void updateColumnsBackground(bool active);
-
-    /**
-     * Tells the Dolphin controller to update the active URL
-     * to m_activeUrl. The slot is called asynchronously with a
-     * small delay, as this prevents a flickering when a directory
-     * from an inactive column gets selected.
-     */
-    void updateActiveUrl();
-
-    /**
-     * Invoked when m_assureVisibleActiveColumnTimer has been exceeded.
-     * Assures that the currently active column is fully visible
-     * by adjusting the horizontal position of the content.
-     */
-    void slotAssureVisibleActiveColumn();
-
-private:
-    /**
-     * Assures that the currently active column is fully visible
-     * by adjusting the horizontal position of the content. The
-     * adjustment is done with a small delay (see
-     * slotAssureVisibleActiveColumn();
-     */
-    void assureVisibleActiveColumn();
-
-    void layoutColumns();
-
-    /**
-     * Request the activation for the column \a column. It is assured
-     * that the columns gets fully visible by adjusting the horizontal
-     * position of the content.
-     */
-    void requestActivation(DolphinColumnView* column);
-
-    /** Removes all columns except of the root column. */
-    void removeAllColumns();
-
-    /**
-     * Deletes the column. If the itemview of the controller is set to the column,
-     * the controllers itemview is set to 0.
-     */
-    void deleteColumn(DolphinColumnView* column);
-
-private:
-    DolphinViewController* m_dolphinViewController;
-    const ViewModeController* m_viewModeController;
-    bool m_active;
-    int m_index;
-    int m_contentX;
-    QList<DolphinColumnView*> m_columns;
-    QFrame* m_emptyViewport;
-    QTimeLine* m_animation;
-    QAbstractItemView* m_dragSource;
-
-    QTimer* m_activeUrlTimer;
-    QTimer* m_assureVisibleActiveColumnTimer;
-
-    friend class DolphinColumnView;
-};
-
-#endif
diff --git a/src/views/dolphindetailsview.cpp b/src/views/dolphindetailsview.cpp
deleted file mode 100644 (file)
index 0ce26df..0000000
+++ /dev/null
@@ -1,706 +0,0 @@
-/***************************************************************************
- *   Copyright (C) 2006 by Peter Penz (peter.penz@gmx.at)                  *
- *   Copyright (C) 2008 by Simon St. James (kdedevel@etotheipiplusone.com) *
- *                                                                         *
- *   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 program 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 program; if not, write to the                         *
- *   Free Software Foundation, Inc.,                                       *
- *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA            *
- ***************************************************************************/
-
-#include "dolphindetailsview.h"
-
-#include "additionalinfoaccessor.h"
-#include "dolphinmodel.h"
-#include "dolphinviewcontroller.h"
-#include "dolphinfileitemdelegate.h"
-#include "settings/dolphinsettings.h"
-#include "dolphinsortfilterproxymodel.h"
-#include "dolphinviewautoscroller.h"
-#include "draganddrophelper.h"
-#include "viewextensionsfactory.h"
-#include "viewmodecontroller.h"
-#include "viewproperties.h"
-#include "zoomlevelinfo.h"
-
-#include "dolphin_detailsmodesettings.h"
-#include "dolphin_generalsettings.h"
-
-#include <KDirModel>
-#include <KDirLister>
-#include <KLocale>
-#include <KMenu>
-
-#include <QApplication>
-#include <QHeaderView>
-#include <QScrollBar>
-
-DolphinDetailsView::DolphinDetailsView(QWidget* parent,
-                                       DolphinViewController* dolphinViewController,
-                                       const ViewModeController* viewModeController,
-                                       DolphinSortFilterProxyModel* proxyModel) :
-    DolphinTreeView(parent),
-    m_autoResize(true),
-    m_dolphinViewController(dolphinViewController),
-    m_extensionsFactory(0),
-    m_expandableFoldersAction(0),
-    m_expandedUrls(),
-    m_font(),
-    m_decorationSize()
-{
-    const DetailsModeSettings* settings = DolphinSettings::instance().detailsModeSettings();
-    Q_ASSERT(settings);
-    Q_ASSERT(dolphinViewController);
-    Q_ASSERT(viewModeController);
-
-    setLayoutDirection(Qt::LeftToRight);
-    setAcceptDrops(true);
-    setSortingEnabled(true);
-    setSelectionBehavior(SelectItems);
-    setDragDropMode(QAbstractItemView::DragDrop);
-    setDropIndicatorShown(false);
-    setAlternatingRowColors(true);
-    setRootIsDecorated(settings->expandableFolders());
-    setItemsExpandable(settings->expandableFolders());
-    setEditTriggers(QAbstractItemView::NoEditTriggers);
-    setModel(proxyModel);
-
-    setMouseTracking(true);
-
-    const ViewProperties props(viewModeController->url());
-    setSortIndicatorSection(props.sorting());
-    setSortIndicatorOrder(props.sortOrder());
-
-    QHeaderView* headerView = header();
-    connect(headerView, SIGNAL(sectionClicked(int)),
-            this, SLOT(synchronizeSortingState(int)));
-    headerView->setContextMenuPolicy(Qt::CustomContextMenu);
-    connect(headerView, SIGNAL(customContextMenuRequested(const QPoint&)),
-            this, SLOT(configureSettings(const QPoint&)));
-    connect(headerView, SIGNAL(sectionResized(int, int, int)),
-            this, SLOT(slotHeaderSectionResized(int, int, int)));
-    connect(headerView, SIGNAL(sectionHandleDoubleClicked(int)),
-            this, SLOT(disableAutoResizing()));
-
-    connect(parent, SIGNAL(sortingChanged(DolphinView::Sorting)),
-            this, SLOT(setSortIndicatorSection(DolphinView::Sorting)));
-    connect(parent, SIGNAL(sortOrderChanged(Qt::SortOrder)),
-            this, SLOT(setSortIndicatorOrder(Qt::SortOrder)));
-
-    connect(this, SIGNAL(clicked(const QModelIndex&)),
-            dolphinViewController, SLOT(requestTab(const QModelIndex&)));
-    if (KGlobalSettings::singleClick()) {
-        connect(this, SIGNAL(clicked(const QModelIndex&)),
-                dolphinViewController, SLOT(triggerItem(const QModelIndex&)));
-    } else {
-        connect(this, SIGNAL(doubleClicked(const QModelIndex&)),
-                dolphinViewController, SLOT(triggerItem(const QModelIndex&)));
-    }
-
-    connect(this, SIGNAL(entered(const QModelIndex&)),
-            this, SLOT(slotEntered(const QModelIndex&)));
-    connect(this, SIGNAL(viewportEntered()),
-            dolphinViewController, SLOT(emitViewportEntered()));
-    connect(viewModeController, SIGNAL(zoomLevelChanged(int)),
-            this, SLOT(setZoomLevel(int)));
-    connect(dolphinViewController->view(), SIGNAL(additionalInfoChanged()),
-            this, SLOT(updateColumnVisibility()));
-    connect(viewModeController, SIGNAL(activationChanged(bool)),
-            this, SLOT(slotActivationChanged(bool)));
-
-    if (settings->useSystemFont()) {
-        m_font = KGlobalSettings::generalFont();
-    } else {
-        m_font = QFont(settings->fontFamily(),
-                       qRound(settings->fontSize()),
-                       settings->fontWeight(),
-                       settings->italicFont());
-        m_font.setPointSizeF(settings->fontSize());
-    }
-
-    setVerticalScrollMode(QTreeView::ScrollPerPixel);
-    setHorizontalScrollMode(QTreeView::ScrollPerPixel);
-
-    const DolphinView* view = dolphinViewController->view();
-    connect(view, SIGNAL(showPreviewChanged()),
-            this, SLOT(slotShowPreviewChanged()));
-
-    viewport()->installEventFilter(this);
-
-    connect(KGlobalSettings::self(), SIGNAL(settingsChanged(int)),
-            this, SLOT(slotGlobalSettingsChanged(int)));
-
-    m_expandableFoldersAction = new QAction(i18nc("@option:check", "Expandable Folders"), this);
-    m_expandableFoldersAction->setCheckable(true);
-    connect(m_expandableFoldersAction, SIGNAL(toggled(bool)),
-            this, SLOT(setFoldersExpandable(bool)));
-
-    connect(this, SIGNAL(expanded(const QModelIndex&)), this, SLOT(slotExpanded(const QModelIndex&)));
-    connect(this, SIGNAL(collapsed(const QModelIndex&)), this, SLOT(slotCollapsed(const QModelIndex&)));
-
-    updateDecorationSize(view->showPreview());
-
-    m_extensionsFactory = new ViewExtensionsFactory(this, dolphinViewController, viewModeController);
-    m_extensionsFactory->fileItemDelegate()->setMinimizedNameColumn(true);
-
-    KDirLister *dirLister = qobject_cast<KDirModel*>(proxyModel->sourceModel())->dirLister();
-    connect(dirLister, SIGNAL(newItems(KFileItemList)), this, SLOT(resizeColumns()));
-}
-
-DolphinDetailsView::~DolphinDetailsView()
-{
-}
-
-QSet<KUrl> DolphinDetailsView::expandedUrls() const
-{
-    return m_expandedUrls;
-}
-
-bool DolphinDetailsView::event(QEvent* event)
-{
-    if (event->type() == QEvent::Polish) {
-        header()->setResizeMode(QHeaderView::Interactive);
-        updateColumnVisibility();
-    }
-
-    return DolphinTreeView::event(event);
-}
-
-QStyleOptionViewItem DolphinDetailsView::viewOptions() const
-{
-    QStyleOptionViewItem viewOptions = DolphinTreeView::viewOptions();
-    viewOptions.font = m_font;
-    viewOptions.fontMetrics = QFontMetrics(m_font);
-    viewOptions.showDecorationSelected = true;
-    viewOptions.decorationSize = m_decorationSize;
-    return viewOptions;
-}
-
-void DolphinDetailsView::contextMenuEvent(QContextMenuEvent* event)
-{
-    DolphinTreeView::contextMenuEvent(event);
-
-    DetailsModeSettings* settings = DolphinSettings::instance().detailsModeSettings();
-    m_expandableFoldersAction->setChecked(settings->expandableFolders());
-    m_dolphinViewController->triggerContextMenuRequest(event->pos(),
-                                            QList<QAction*>() << m_expandableFoldersAction);
-}
-
-void DolphinDetailsView::mousePressEvent(QMouseEvent* event)
-{
-    m_dolphinViewController->requestActivation();
-
-    DolphinTreeView::mousePressEvent(event);
-
-    const QModelIndex index = indexAt(event->pos());
-    if (!index.isValid() || (index.column() != DolphinModel::Name)) {
-        // The mouse press is done somewhere outside the filename column
-        if (QApplication::mouseButtons() & Qt::MidButton) {
-            m_dolphinViewController->replaceUrlByClipboard();
-        }
-    }
-}
-
-void DolphinDetailsView::startDrag(Qt::DropActions supportedActions)
-{
-    DragAndDropHelper::instance().startDrag(this, supportedActions, m_dolphinViewController);
-    DolphinTreeView::startDrag(supportedActions);
-}
-
-void DolphinDetailsView::dragEnterEvent(QDragEnterEvent* event)
-{
-    event->acceptProposedAction();
-    DolphinTreeView::dragEnterEvent(event);
-}
-
-void DolphinDetailsView::dragMoveEvent(QDragMoveEvent* event)
-{
-    DolphinTreeView::dragMoveEvent(event);
-    event->acceptProposedAction();
-}
-
-void DolphinDetailsView::dropEvent(QDropEvent* event)
-{
-    const QModelIndex index = indexAt(event->pos());
-    KFileItem item;
-    if (index.isValid() && (index.column() == DolphinModel::Name)) {
-        item = m_dolphinViewController->itemForIndex(index);
-    }
-    m_dolphinViewController->indicateDroppedUrls(item, event);
-    DolphinTreeView::dropEvent(event);
-}
-
-void DolphinDetailsView::keyPressEvent(QKeyEvent* event)
-{
-    DolphinTreeView::keyPressEvent(event);
-    m_dolphinViewController->handleKeyPressEvent(event);
-}
-
-void DolphinDetailsView::resizeEvent(QResizeEvent* event)
-{
-    DolphinTreeView::resizeEvent(event);
-    if (m_autoResize) {
-        resizeColumns();
-    }
-}
-
-void DolphinDetailsView::wheelEvent(QWheelEvent* event)
-{
-    const int step = m_decorationSize.height();
-    verticalScrollBar()->setSingleStep(step);
-    DolphinTreeView::wheelEvent(event);
-}
-
-void DolphinDetailsView::currentChanged(const QModelIndex& current, const QModelIndex& previous)
-{
-    m_extensionsFactory->handleCurrentIndexChange(current, previous);
-    DolphinTreeView::currentChanged(current, previous);
-
-    // If folders are expanded, the width which is available for editing may have changed
-    // because it depends on the level of the current item in the folder hierarchy.
-    adjustMaximumSizeForEditing(current);
-}
-
-bool DolphinDetailsView::eventFilter(QObject* watched, QEvent* event)
-{
-    if ((watched == viewport()) && (event->type() == QEvent::Leave)) {
-        // If the mouse is above an item and moved very fast outside the widget,
-        // no viewportEntered() signal might be emitted although the mouse has been moved
-        // above the viewport.
-        m_dolphinViewController->emitViewportEntered();
-    }
-
-    return DolphinTreeView::eventFilter(watched, event);
-}
-
-QRect DolphinDetailsView::visualRect(const QModelIndex& index) const
-{
-    QRect rect = DolphinTreeView::visualRect(index);
-    const KFileItem item = m_dolphinViewController->itemForIndex(index);
-    if (!item.isNull()) {
-        const int width = DolphinFileItemDelegate::nameColumnWidth(item.text(), viewOptions());
-
-        if (width < rect.width()) {
-            rect.setWidth(width);
-        }
-    }
-
-    return rect;
-}
-
-bool DolphinDetailsView::acceptsDrop(const QModelIndex& index) const
-{
-    if (index.isValid() && (index.column() == DolphinModel::Name)) {
-        // Accept drops above directories
-        const KFileItem item = m_dolphinViewController->itemForIndex(index);
-        return !item.isNull() && item.isDir();
-    }
-
-    return false;
-}
-
-void DolphinDetailsView::rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end)
-{
-    removeExpandedIndexes(parent, start, end);
-    DolphinTreeView::rowsAboutToBeRemoved(parent, start, end);
-}
-
-void DolphinDetailsView::setSortIndicatorSection(DolphinView::Sorting sorting)
-{
-    header()->setSortIndicator(sorting, header()->sortIndicatorOrder());
-}
-
-void DolphinDetailsView::setSortIndicatorOrder(Qt::SortOrder sortOrder)
-{
-    header()->setSortIndicator(header()->sortIndicatorSection(), sortOrder);
-}
-
-void DolphinDetailsView::synchronizeSortingState(int column)
-{
-    // The sorting has already been changed in QTreeView if this slot is
-    // invoked, but Dolphin is not informed about this.
-    DolphinView::Sorting sorting = DolphinSortFilterProxyModel::sortingForColumn(column);
-    const Qt::SortOrder sortOrder = header()->sortIndicatorOrder();
-    m_dolphinViewController->indicateSortingChange(sorting);
-    m_dolphinViewController->indicateSortOrderChange(sortOrder);
-}
-
-void DolphinDetailsView::slotEntered(const QModelIndex& index)
-{
-    if (index.column() == DolphinModel::Name) {
-        m_dolphinViewController->emitItemEntered(index);
-    } else {
-        m_dolphinViewController->emitViewportEntered();
-    }
-}
-
-void DolphinDetailsView::setZoomLevel(int level)
-{
-    const int size = ZoomLevelInfo::iconSizeForZoomLevel(level);
-    DetailsModeSettings* settings = DolphinSettings::instance().detailsModeSettings();
-
-    const bool showPreview = m_dolphinViewController->view()->showPreview();
-    if (showPreview) {
-        settings->setPreviewSize(size);
-    } else {
-        settings->setIconSize(size);
-    }
-
-    updateDecorationSize(showPreview);
-}
-
-void DolphinDetailsView::slotShowPreviewChanged()
-{
-    const DolphinView* view = m_dolphinViewController->view();
-    updateDecorationSize(view->showPreview());
-}
-
-void DolphinDetailsView::configureSettings(const QPoint& pos)
-{
-    KMenu popup(this);
-    popup.addTitle(i18nc("@title:menu", "Columns"));
-
-    // Add checkbox items for each column
-    QHeaderView* headerView = header();
-    const int columns = model()->columnCount();
-    for (int i = 0; i < columns; ++i) {
-        const int logicalIndex = headerView->logicalIndex(i);
-        const QString text = model()->headerData(logicalIndex, Qt::Horizontal).toString();
-        if (!text.isEmpty()) {
-            QAction* action = popup.addAction(text);
-            action->setCheckable(true);
-            action->setChecked(!headerView->isSectionHidden(logicalIndex));
-            action->setData(logicalIndex);
-            action->setEnabled(logicalIndex != DolphinModel::Name);
-        }
-    }
-    popup.addSeparator();
-
-    QAction* activatedAction = popup.exec(header()->mapToGlobal(pos));
-    if (activatedAction) {
-        const bool show = activatedAction->isChecked();
-        const int columnIndex = activatedAction->data().toInt();
-
-        KFileItemDelegate::InformationList list = m_dolphinViewController->view()->additionalInfo();
-        const KFileItemDelegate::Information info = infoForColumn(columnIndex);
-        if (show) {
-            Q_ASSERT(!list.contains(info));
-            list.append(info);
-        } else {
-            Q_ASSERT(list.contains(info));
-            const int index = list.indexOf(info);
-            list.removeAt(index);
-        }
-
-        m_dolphinViewController->indicateAdditionalInfoChange(list);
-        setColumnHidden(columnIndex, !show);
-        resizeColumns();
-    }
-}
-
-void DolphinDetailsView::updateColumnVisibility()
-{
-    QHeaderView* headerView = header();
-    disconnect(headerView, SIGNAL(sectionMoved(int, int, int)),
-               this, SLOT(saveColumnPositions()));
-
-    const DetailsModeSettings* settings = DolphinSettings::instance().detailsModeSettings();
-    const QList<int> columnPositions = settings->columnPositions();
-
-    const KFileItemDelegate::InformationList list = m_dolphinViewController->view()->additionalInfo();
-    for (int i = DolphinModel::Name; i < DolphinModel::ExtraColumnCount; ++i) {
-        const KFileItemDelegate::Information info = infoForColumn(i);
-        const bool hide = !list.contains(info) && (i != DolphinModel::Name);
-        if (isColumnHidden(i) != hide) {
-            setColumnHidden(i, hide);
-        }
-
-        // If the list columnPositions has been written by an older Dolphin version,
-        // its length might be smaller than DolphinModel::ExtraColumnCount. Therefore,
-        // we have to check if item number i exists before accessing it.
-        if (i < columnPositions.length()) {
-            const int position = columnPositions[i];
-
-            // The position might be outside the correct range if the list columnPositions
-            // has been written by a newer Dolphin version with more columns.
-            if (position < DolphinModel::ExtraColumnCount) {
-                const int from = headerView->visualIndex(i);
-                headerView->moveSection(from, position);
-            }
-        }
-    }
-
-    resizeColumns();
-
-    connect(headerView, SIGNAL(sectionMoved(int, int, int)),
-            this, SLOT(saveColumnPositions()));
-}
-
-void DolphinDetailsView::resizeColumns()
-{
-    // Using the resize mode QHeaderView::ResizeToContents is too slow (it takes
-    // around 3 seconds for each (!) resize operation when having > 10000 items).
-    // This gets a problem especially when opening large directories, where several
-    // resize operations are received for showing the currently available items during
-    // loading (the application hangs around 20 seconds when loading > 10000 items).
-
-    QHeaderView* headerView = header();
-    const int rowCount = model()->rowCount();
-    QFontMetrics fontMetrics(viewport()->font());
-    const int horizontalGap = fontMetrics.height();
-
-    // Define the maximum number of rows, where an exact (but expensive) calculation
-    // of the widths is done.
-    const int maxRowCount = 200;
-
-    // Calculate the required with for each column and store it in columnWidth[]
-    int columnWidth[DolphinModel::ExtraColumnCount];
-
-    for (int column = 0; column < DolphinModel::ExtraColumnCount; ++column) {
-        columnWidth[column] = 0;
-        if (!isColumnHidden(column)) {
-            // Calculate the required width for the current column and consider only
-            // up to maxRowCount columns for performance reasons
-            if (rowCount > 0) {
-                const int count = qMin(rowCount, maxRowCount);
-                for (int row = 0; row < count; ++row) {
-                    const QModelIndex index = model()->index(row, column);
-                    QString text;
-                    if (column == DolphinModel::Size) {
-                        // This is a workaround as KFileItemDelegate::sizeHint() does not
-                        // work in a way that is required for calculating the size.
-                        const QAbstractProxyModel* proxyModel = qobject_cast<const QAbstractProxyModel*>(model());
-                        const KDirModel* dirModel = qobject_cast<const KDirModel*>(proxyModel->sourceModel());
-                        const QModelIndex dirIndex = proxyModel->mapToSource(index);
-                        text = itemSizeString(dirIndex, dirModel->itemForIndex(dirIndex));
-                    } else {
-                        text = model()->data(index).toString();
-                    }
-                    const int width = fontMetrics.width(text) + horizontalGap;
-                    if (width > columnWidth[column]) {
-                        columnWidth[column] = width;
-                    }
-                }
-            }
-
-            // Assure that the required width is sufficient for the header too
-            const int logicalIndex = headerView->logicalIndex(column);
-            const QString headline = model()->headerData(logicalIndex, Qt::Horizontal).toString();
-            const int headlineWidth = fontMetrics.width(headline) + horizontalGap;
-
-            columnWidth[column] = qMax(columnWidth[column], headlineWidth);
-        }
-    }
-
-    // Resize all columns except of the name column
-    int requiredWidth = 0;
-    for (int column = KDirModel::Size; column < DolphinModel::ExtraColumnCount; ++column) {
-        if (!isColumnHidden(column)) {
-            requiredWidth += columnWidth[column];
-            headerView->resizeSection(column, columnWidth[column]);
-        }
-    }
-
-    // Resize the name column in a way that the whole available width is used
-    columnWidth[KDirModel::Name] = viewport()->width() - requiredWidth;
-
-    const int minNameWidth = 300;
-    if (columnWidth[KDirModel::Name] < minNameWidth) {
-        columnWidth[KDirModel::Name] = minNameWidth;
-
-        if ((rowCount > 0) && (rowCount < maxRowCount)) {
-            // Try to decrease the name column width without clipping any text
-            const int nameWidth = sizeHintForColumn(DolphinModel::Name);
-            if (nameWidth + requiredWidth <= viewport()->width()) {
-                columnWidth[KDirModel::Name] = viewport()->width() - requiredWidth;
-            } else if (nameWidth < minNameWidth) {
-                columnWidth[KDirModel::Name] = nameWidth;
-            }
-        }
-    }
-
-    headerView->resizeSection(KDirModel::Name, columnWidth[KDirModel::Name]);
-}
-
-void DolphinDetailsView::saveColumnPositions()
-{
-    QList<int> columnPositions;
-    for (int i = DolphinModel::Name; i < DolphinModel::ExtraColumnCount; ++i) {
-        columnPositions.append(header()->visualIndex(i));
-    }
-
-    DetailsModeSettings* settings = DolphinSettings::instance().detailsModeSettings();
-    settings->setColumnPositions(columnPositions);
-}
-
-void DolphinDetailsView::slotHeaderSectionResized(int logicalIndex, int oldSize, int newSize)
-{
-    Q_UNUSED(logicalIndex);
-    Q_UNUSED(oldSize);
-    Q_UNUSED(newSize);
-    // 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()) {
-        disableAutoResizing();
-    }
-
-    adjustMaximumSizeForEditing(currentIndex());
-}
-
-void DolphinDetailsView::slotActivationChanged(bool active)
-{
-    setAlternatingRowColors(active);
-}
-
-void DolphinDetailsView::disableAutoResizing()
-{
-    m_autoResize = false;
-}
-
-void DolphinDetailsView::requestActivation()
-{
-    m_dolphinViewController->requestActivation();
-}
-
-void DolphinDetailsView::slotGlobalSettingsChanged(int category)
-{
-    Q_UNUSED(category);
-
-    const DetailsModeSettings* settings = DolphinSettings::instance().detailsModeSettings();
-    Q_ASSERT(settings);
-    if (settings->useSystemFont()) {
-        m_font = KGlobalSettings::generalFont();
-    }
-    // Disconnect then reconnect, since the settings have been changed, the connection requirements may have also.
-    disconnect(this, SIGNAL(clicked(QModelIndex)), m_dolphinViewController, SLOT(triggerItem(QModelIndex)));
-    disconnect(this, SIGNAL(doubleClicked(QModelIndex)), m_dolphinViewController, SLOT(triggerItem(QModelIndex)));
-    if (KGlobalSettings::singleClick()) {
-        connect(this, SIGNAL(clicked(QModelIndex)), m_dolphinViewController, SLOT(triggerItem(QModelIndex)));
-    } else {
-        connect(this, SIGNAL(doubleClicked(QModelIndex)), m_dolphinViewController, SLOT(triggerItem(QModelIndex)));
-    }
-}
-
-
-void DolphinDetailsView::setFoldersExpandable(bool expandable)
-{
-    if (!expandable) {
-        // Collapse all expanded folders, as QTreeView::setItemsExpandable(false)
-        // does not do this task
-        const int rowCount = model()->rowCount();
-        for (int row = 0; row < rowCount; ++row) {
-            setExpanded(model()->index(row, 0), false);
-        }
-    }
-    DetailsModeSettings* settings = DolphinSettings::instance().detailsModeSettings();
-    settings->setExpandableFolders(expandable);
-    setRootIsDecorated(expandable);
-    setItemsExpandable(expandable);
-
-    // The width of the space which is available for editing has changed
-    // because of the (dis)appearance of the expanding toggles
-    adjustMaximumSizeForEditing(currentIndex());
-}
-
-void DolphinDetailsView::slotExpanded(const QModelIndex& index)
-{
-    KFileItem item = m_dolphinViewController->itemForIndex(index);
-    if (!item.isNull()) {
-        m_expandedUrls.insert(item.url());
-    }
-}
-
-void DolphinDetailsView::slotCollapsed(const QModelIndex& index)
-{
-    KFileItem item = m_dolphinViewController->itemForIndex(index);
-    if (!item.isNull()) {
-        m_expandedUrls.remove(item.url());
-    }
-}
-
-void DolphinDetailsView::removeExpandedIndexes(const QModelIndex& parent, int start, int end)
-{
-    if (m_expandedUrls.isEmpty()) {
-        return;
-    }
-
-    for (int row = start; row <= end; row++) {
-        const QModelIndex index = model()->index(row, 0, parent);
-        if (isExpanded(index)) {
-            slotCollapsed(index);
-            removeExpandedIndexes(index, 0, model()->rowCount(index) - 1);
-        }
-    }
-}
-
-void DolphinDetailsView::updateDecorationSize(bool showPreview)
-{
-    DetailsModeSettings* settings = DolphinSettings::instance().detailsModeSettings();
-    const int iconSize = showPreview ? settings->previewSize() : settings->iconSize();
-    setIconSize(QSize(iconSize, iconSize));
-    m_decorationSize = QSize(iconSize, iconSize);
-
-    if (m_extensionsFactory) {
-        // The old maximumSize used by KFileItemDelegate is not valid any more after the icon size change.
-        // It must be discarded before doItemsLayout() is called (see bug 234600).
-        m_extensionsFactory->fileItemDelegate()->setMaximumSize(QSize());
-    }
-
-    doItemsLayout();
-
-    // Calculate the new maximumSize for KFileItemDelegate after the icon size change.
-    QModelIndex current = currentIndex();
-    if (current.isValid()) {
-        adjustMaximumSizeForEditing(current);
-    }
-}
-
-KFileItemDelegate::Information DolphinDetailsView::infoForColumn(int columnIndex) const
-{
-    return AdditionalInfoAccessor::instance().keyForColumn(columnIndex);
-}
-
-void DolphinDetailsView::adjustMaximumSizeForEditing(const QModelIndex& index)
-{
-    // Make sure that the full width of the "Name" column is available for "Rename Inline".
-    // Before we do that, we have to check if m_extensionsFactory has been initialised because
-    // it is possible that we end up here before the constructor is finished (see bug 257035)
-    if (m_extensionsFactory) {
-        m_extensionsFactory->fileItemDelegate()->setMaximumSize(QTreeView::visualRect(index).size());
-    }
-}
-
-QString DolphinDetailsView::itemSizeString(const QModelIndex& index, const KFileItem& item) const
-{
-    // The following code has been copied from KFileItemDelegate::Private::itemSize()
-    // Copyright (c) 2006-2007, 2008 Fredrik Höglund <fredrik@kde.org>
-    // Ideally this should be handled by KFileItemDelegate::sizeHint().
-    if (item.isFile()) {
-        return KGlobal::locale()->formatByteSize(item.size());
-    }
-
-    // Return the number of items in the directory
-    const QVariant value = index.data(KDirModel::ChildCountRole);
-    const int count = value.type() == QVariant::Int ? value.toInt() : KDirModel::ChildCountUnknown;
-
-    if (count == KDirModel::ChildCountUnknown) {
-        return QString();
-    }
-
-    return i18ncp("Items in a folder", "1 item", "%1 items", count);
-}
-
-#include "dolphindetailsview.moc"
diff --git a/src/views/dolphindetailsview.h b/src/views/dolphindetailsview.h
deleted file mode 100644 (file)
index 305035d..0000000
+++ /dev/null
@@ -1,224 +0,0 @@
-/***************************************************************************
- *   Copyright (C) 2006-2010 by Peter Penz <peter.penz19@gmail.com>        *
- *                                                                         *
- *   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 program 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 program; if not, write to the                         *
- *   Free Software Foundation, Inc.,                                       *
- *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA            *
- ***************************************************************************/
-
-#ifndef DOLPHINDETAILSVIEW_H
-#define DOLPHINDETAILSVIEW_H
-
-#include "dolphintreeview.h"
-#include <QTreeView>
-#include <libdolphin_export.h>
-#include <views/dolphinview.h>
-
-class DolphinViewController;
-class DolphinSortFilterProxyModel;
-class ViewExtensionsFactory;
-
-/**
- * @brief Represents the details view which shows the name, size,
- *        date, permissions, owner and group of an item.
- *
- * The width of the columns is automatically adjusted in a way
- * that full available width of the view is used by stretching the width
- * of the name column.
- */
-class LIBDOLPHINPRIVATE_EXPORT DolphinDetailsView : public DolphinTreeView
-{
-    Q_OBJECT
-
-public:
-    /**
-     * @param parent                Parent widget.
-     * @param dolphinViewController Allows the DolphinDetailsView to control the
-     *                              DolphinView in a limited way.
-     * @param viewModeController    Controller that is used by the DolphinView
-     *                              to control the DolphinDetailsView. The DolphinDetailsView
-     *                              only has read access to the controller.
-     * @param model                 Directory that is shown.
-     */
-    explicit DolphinDetailsView(QWidget* parent,
-                                DolphinViewController* dolphinViewController,
-                                const ViewModeController* viewModeController,
-                                DolphinSortFilterProxyModel* model);
-    virtual ~DolphinDetailsView();
-
-    /**
-     * Returns a set containing the URLs of all expanded items.
-     */
-    QSet<KUrl> expandedUrls() const;
-
-public:
-    virtual QRect visualRect(const QModelIndex& index) const;
-
-protected:
-    virtual bool event(QEvent* event);
-    virtual QStyleOptionViewItem viewOptions() const;
-    virtual void contextMenuEvent(QContextMenuEvent* event);
-    virtual void mousePressEvent(QMouseEvent* event);
-    virtual void startDrag(Qt::DropActions supportedActions);
-    virtual void dragEnterEvent(QDragEnterEvent* event);
-    virtual void dragMoveEvent(QDragMoveEvent* event);
-    virtual void dropEvent(QDropEvent* event);
-    virtual void keyPressEvent(QKeyEvent* event);
-    virtual void resizeEvent(QResizeEvent* event);
-    virtual void wheelEvent(QWheelEvent* event);
-    virtual void currentChanged(const QModelIndex& current, const QModelIndex& previous);
-    virtual bool eventFilter(QObject* watched, QEvent* event);
-    virtual bool acceptsDrop(const QModelIndex& index) const;
-
-protected slots:
-    virtual void rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end);
-
-private slots:
-    /**
-     * Sets the sort indicator section of the header view
-     * corresponding to \a sorting.
-     */
-    void setSortIndicatorSection(DolphinView::Sorting sorting);
-
-    /**
-     * Sets the sort indicator order of the header view
-     * corresponding to \a sortOrder.
-     */
-    void setSortIndicatorOrder(Qt::SortOrder sortOrder);
-
-    /**
-     * Synchronizes the sorting state of the Dolphin menu 'View -> Sort'
-     * with the current state of the details view.
-     * @param column Index of the current sorting column.
-     */
-    void synchronizeSortingState(int column);
-
-    /**
-     * Is invoked when the mouse cursor has entered an item. The controller
-     * gets informed to emit the itemEntered() signal if the mouse cursor
-     * is above the name column. Otherwise the controller gets informed
-     * to emit the itemViewportEntered() signal (all other columns should
-     * behave as viewport area).
-     */
-    void slotEntered(const QModelIndex& index);
-
-    void setZoomLevel(int level);
-
-    void slotShowPreviewChanged();
-
-    /**
-     * Opens a context menu at the position \a pos and allows to
-     * configure the visibility of the header columns and whether
-     * expandable folders should be shown.
-     */
-    void configureSettings(const QPoint& pos);
-
-    /**
-     * Updates the visibilty state of columns and their order.
-     */
-    void updateColumnVisibility();
-
-    /**
-     * Resizes all columns in a way to use the whole available width of the view.
-     */
-    void resizeColumns();
-
-    /**
-     * Saves order of the columns as global setting.
-     */
-    void saveColumnPositions();
-
-    /**
-     * Disables the automatical resizing of columns, if the user has resized the columns
-     * with the mouse.
-     */
-    void slotHeaderSectionResized(int logicalIndex, int oldSize, int newSize);
-
-    /**
-     * Changes the alternating row colors setting depending from
-     * the activation state \a active.
-     */
-    void slotActivationChanged(bool active);
-
-    /**
-     * Disables the automatical resizing of the columns. Per default all columns
-     * are resized to use the maximum available width of the view as good as possible.
-     */
-    void disableAutoResizing();
-
-    void requestActivation();
-
-    void slotGlobalSettingsChanged(int category);
-
-    /**
-     * If \a expandable is true, the details view acts as tree view.
-     * The current expandable state is remembered in the settings.
-     */
-    void setFoldersExpandable(bool expandable);
-
-    /**
-     * These slots update the list of expanded items.
-     */
-    void slotExpanded(const QModelIndex& index);
-    void slotCollapsed(const QModelIndex& index);
-
-private:
-    /**
-     * Removes the URLs corresponding to the children of \a index in the rows
-     * between \a start and \a end inclusive from the set of expanded URLs.
-     */
-    void removeExpandedIndexes(const QModelIndex& parent, int start, int end);
-
-    /**
-     * Updates the size of the decoration dependent on the
-     * icon size of the DetailsModeSettings. The controller
-     * will get informed about possible zoom in/zoom out
-     * operations.
-     */
-    void updateDecorationSize(bool showPreview);
-
-    KFileItemDelegate::Information infoForColumn(int columnIndex) const;
-
-    /**
-     * Sets the maximum size available for editing in the delegate.
-     */
-    void adjustMaximumSizeForEditing(const QModelIndex& index);
-
-    /**
-     * Helper method for DolphinDetailsView::resizeColumns(): Returns the
-     * string representation of the size-value for the given index.
-     */
-    QString itemSizeString(const QModelIndex& index, const KFileItem& item) const;
-
-private:
-    bool m_autoResize; // if true, the columns are resized automatically to the available width
-
-    DolphinViewController* m_dolphinViewController;
-    ViewExtensionsFactory* m_extensionsFactory;
-    QAction* m_expandableFoldersAction;
-
-    // A set containing the URLs of all currently expanded folders.
-    // We cannot use a QSet<QModelIndex> because a QModelIndex is not guaranteed to remain valid over time.
-    // Also a QSet<QPersistentModelIndex> does not work as expected because it is not guaranteed that
-    // subsequent expand/collapse events of the same file item will yield the same QPersistentModelIndex.
-    QSet<KUrl> m_expandedUrls;
-
-    QFont m_font;
-    QSize m_decorationSize;
-
-    // For unit tests
-    friend class DolphinDetailsViewTest;
-};
-
-#endif
diff --git a/src/views/dolphindetailsviewexpander.cpp b/src/views/dolphindetailsviewexpander.cpp
deleted file mode 100644 (file)
index cc4bc67..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-/***************************************************************************
- *   Copyright (C) 2009 by Frank Reininghaus (frank78ac@googlemail.com)    *
- *                                                                         *
- *   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 program 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 program; if not, write to the                         *
- *   Free Software Foundation, Inc.,                                       *
- *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA            *
- ***************************************************************************/
-
-#include "dolphindetailsviewexpander.h"
-
-#include "dolphindetailsview.h"
-#include "dolphinmodel.h"
-#include "dolphinsortfilterproxymodel.h"
-
-#include <KDirLister>
-#include <KDirModel>
-
-DolphinDetailsViewExpander::DolphinDetailsViewExpander(DolphinDetailsView* parent,
-                                                       const QSet<KUrl>& urlsToExpand) :
-    QObject(parent),
-    m_detailsView(parent),
-    m_dirLister(0),
-    m_dolphinModel(0),
-    m_proxyModel(0)
-{
-    Q_ASSERT(parent);
-
-    m_proxyModel = qobject_cast<const DolphinSortFilterProxyModel*>(parent->model());
-    Q_ASSERT(m_proxyModel);
-
-    m_dolphinModel = qobject_cast<const DolphinModel*>(m_proxyModel->sourceModel());
-    Q_ASSERT(m_dolphinModel);
-
-    m_dirLister = m_dolphinModel->dirLister();
-    Q_ASSERT(m_dirLister);
-
-    // The URLs must be sorted. E.g. /home/user/ cannot be expanded before /home/
-    // because it is not known to the dir model before.
-    m_urlsToExpand = urlsToExpand.toList();
-    qSort(m_urlsToExpand);
-
-    // The dir lister must have completed the folder listing before a subfolder can be expanded.
-    connect(m_dirLister, SIGNAL(completed()), this, SLOT(slotDirListerCompleted()));
-}
-
-DolphinDetailsViewExpander::~DolphinDetailsViewExpander()
-{
-}
-
-void DolphinDetailsViewExpander::stop()
-{
-    disconnect(m_dirLister, SIGNAL(completed()), this, SLOT(slotDirListerCompleted()));
-    deleteLater();
-}
-
-void DolphinDetailsViewExpander::slotDirListerCompleted()
-{
-    QModelIndex dirIndex;
-
-    while(!m_urlsToExpand.isEmpty() && !dirIndex.isValid()) {
-        const KUrl url = m_urlsToExpand.takeFirst();
-        dirIndex = m_dolphinModel->indexForUrl(url);
-    }
-
-    if(dirIndex.isValid()) {
-        // A valid model index was found. Note that only one item is expanded in each call of this slot
-        // because expanding any item will trigger KDirLister::openUrl(...) via KDirModel::fetchMore(...),
-        // and we can only continue when the dir lister is done.
-        const QModelIndex proxyIndex = m_proxyModel->mapFromSource(dirIndex);
-        m_detailsView->expand(proxyIndex);
-    }
-    else {
-        emit completed();
-        stop();
-    }
-}
diff --git a/src/views/dolphindetailsviewexpander.h b/src/views/dolphindetailsviewexpander.h
deleted file mode 100644 (file)
index b4dc2fc..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-/***************************************************************************
- *   Copyright (C) 2009 by Frank Reininghaus (frank78ac@googlemail.com)    *
- *                                                                         *
- *   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 program 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 program; if not, write to the                         *
- *   Free Software Foundation, Inc.,                                       *
- *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA            *
- ***************************************************************************/
-
-#ifndef DOLPHINDETAILSVIEWEXPANDER_H
-#define DOLPHINDETAILSVIEWEXPANDER_H
-
-#include <QObject>
-#include <QSet>
-#include <QList>
-
-class DolphinDetailsView;
-class KUrl;
-class KDirLister;
-class DolphinModel;
-class DolphinSortFilterProxyModel;
-
-/**
- * @brief Expands a given set of subfolders in collaboration with the dir lister and the dir model.
- *
- * Note that only one subfolder can be expanded at a time. Each expansion triggers KDirLister::openUrl(...),
- * and further expansions can only be done the next time the dir lister emits its completed() signal.
- */
-class DolphinDetailsViewExpander : public QObject
-{
-    Q_OBJECT
-
-public:
-    explicit DolphinDetailsViewExpander(DolphinDetailsView* parent,
-                                        const QSet<KUrl>& urlsToExpand);
-
-    virtual ~DolphinDetailsViewExpander();
-
-    /**
-     * Stops the expansion and deletes the object via deleteLater().
-     */
-    void stop();
-
-private slots:
-    /**
-     * This slot is invoked every time the dir lister has completed a listing.
-     * It expands the first URL from the list m_urlsToExpand that can be found in the dir model.
-     * If the list is empty, stop() is called.
-     */
-    void slotDirListerCompleted();
-
-signals:
-    /**
-     * Is emitted when the expander has finished expanding URLs in the details view.
-     */
-    void completed();
-
-private:
-    QList<KUrl> m_urlsToExpand;
-
-    DolphinDetailsView* m_detailsView;
-    const KDirLister* m_dirLister;
-    const DolphinModel* m_dolphinModel;
-    const DolphinSortFilterProxyModel* m_proxyModel;
-};
-
-#endif
index 568681fb77b61e82480f9fb70368b71fc49b0746..b62abe167bd6977e3df43ec46f72bc1ef81734d2 100644 (file)
@@ -21,8 +21,8 @@
 #include <KLocale>
 #include <KIO/JobClasses>
 
-DolphinDirLister::DolphinDirLister() :
-    KDirLister()
+DolphinDirLister::DolphinDirLister(QObject* parent) :
+    KDirLister(parent)
 {
     setAutoErrorHandlingEnabled(false, 0);
 }
index 662c7c0aa0a15702361a650dd67ecccdffe5e077..0955df2321deba8c3c6928a138a216fae3f2f2fe 100644 (file)
@@ -32,7 +32,7 @@ class LIBDOLPHINPRIVATE_EXPORT DolphinDirLister : public KDirLister
     Q_OBJECT
 
 public:
-    DolphinDirLister();
+    DolphinDirLister(QObject* parent = 0);
     virtual ~DolphinDirLister();
 
 signals:
diff --git a/src/views/dolphinfileitemdelegate.cpp b/src/views/dolphinfileitemdelegate.cpp
deleted file mode 100644 (file)
index 4d66c73..0000000
+++ /dev/null
@@ -1,221 +0,0 @@
-/***************************************************************************
- *   Copyright (C) 2008 by Peter Penz <peter.penz19@gmail.com>             *
- *                                                                         *
- *   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 program 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 program; if not, write to the                         *
- *   Free Software Foundation, Inc.,                                       *
- *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA            *
- ***************************************************************************/
-
-#include "dolphinfileitemdelegate.h"
-
-#include "dolphinmodel.h"
-#include <KColorScheme>
-#include <KFileItem>
-#include <KGlobalSettings>
-#include <KIcon>
-#include <KIconLoader>
-#include <KStringHandler>
-
-#include <QAbstractItemModel>
-#include <QAbstractProxyModel>
-#include <QFontMetrics>
-#include <QPalette>
-#include <QPainter>
-#include <QStyleOptionViewItemV4>
-
-DolphinFileItemDelegate::DolphinFileItemDelegate(QObject* parent) :
-    KFileItemDelegate(parent),
-    m_hasMinimizedNameColumn(false),
-    m_cachedSize(),
-    m_cachedEmblems(),
-    m_cachedInactiveTextColorDirty(true)
-{
-    setJobTransfersVisible(true);
-    connect(KGlobalSettings::self(), SIGNAL(kdisplayPaletteChanged()), this, SLOT(handleDisplayPaletteChange()));
-}
-
-DolphinFileItemDelegate::~DolphinFileItemDelegate()
-{
-}
-
-void DolphinFileItemDelegate::paint(QPainter* painter,
-                                    const QStyleOptionViewItem& option,
-                                    const QModelIndex& index) const
-{
-    const QAbstractProxyModel* proxyModel = static_cast<const QAbstractProxyModel*>(index.model());
-    const DolphinModel* dolphinModel = static_cast<const DolphinModel*>(proxyModel->sourceModel());
-    const bool isNameColumn = (index.column() == KDirModel::Name);
-
-    QStyleOptionViewItemV4 opt(option);
-    if (m_hasMinimizedNameColumn && isNameColumn) {
-        adjustOptionWidth(opt, proxyModel, dolphinModel, index);
-    }
-
-    if (!isNameColumn) {
-        // Use the inactive text color for all columns except the name column. This indicates for the user that
-        // hovering other columns does not change the actions context.
-        QPalette palette = opt.palette;
-        if (m_cachedInactiveTextColorDirty) {
-            m_cachedInactiveTextColor = KColorScheme(QPalette::Active).foreground(KColorScheme::InactiveText).color();
-            m_cachedInactiveTextColorDirty = false;
-        }
-        palette.setColor(QPalette::Text, m_cachedInactiveTextColor);
-        opt.palette = palette;
-    }
-
-    if (dolphinModel->hasVersionData() && isNameColumn) {
-        // The currently shown items are under revision control. Show the current revision
-        // state by adding an emblem and changing the text tintColor.
-        const QModelIndex dirIndex = proxyModel->mapToSource(index);
-        const QModelIndex revisionIndex = dolphinModel->index(dirIndex.row(), DolphinModel::Version, dirIndex.parent());
-        const QVariant data = dolphinModel->data(revisionIndex, Qt::DecorationRole);
-        const KVersionControlPlugin::VersionState state = static_cast<KVersionControlPlugin::VersionState>(data.toInt());
-
-        adjustOptionTextColor(opt, state);
-
-        KFileItemDelegate::paint(painter, opt, index);
-
-        if (state != KVersionControlPlugin::UnversionedVersion) {
-            const QRect rect = iconRect(option, index);
-            const QPixmap emblem = emblemForState(state, rect.size());
-            painter->drawPixmap(rect.x(), rect.y() + rect.height() - emblem.height(), emblem);
-        }
-    } else {
-        KFileItemDelegate::paint(painter, opt, index);
-    }
-}
-
-int DolphinFileItemDelegate::nameColumnWidth(const QString& name, const QStyleOptionViewItem& option)
-{
-    QFontMetrics fontMetrics(option.font);
-    int width = option.decorationSize.width() + fontMetrics.width(KStringHandler::preProcessWrap(name)) + 16;
-
-    const int defaultWidth = option.rect.width();
-    if ((defaultWidth > 0) && (defaultWidth < width)) {
-        width = defaultWidth;
-    }
-    return width;
-}
-
-void DolphinFileItemDelegate::handleDisplayPaletteChange()
-{
-    m_cachedInactiveTextColorDirty = true;
-}
-
-void DolphinFileItemDelegate::adjustOptionWidth(QStyleOptionViewItemV4& option,
-                                                const QAbstractProxyModel* proxyModel,
-                                                const DolphinModel* dolphinModel,
-                                                const QModelIndex& index)
-{
-    const QModelIndex dirIndex = proxyModel->mapToSource(index);
-    const KFileItem item = dolphinModel->itemForIndex(dirIndex);
-    if (!item.isNull()) {
-        // symbolic links are displayed in an italic font
-        if (item.isLink()) {
-            option.font.setItalic(true);
-        }
-
-        const int width = nameColumnWidth(item.text(), option);
-        option.rect.setWidth(width);
-    }
-}
-
-void DolphinFileItemDelegate::adjustOptionTextColor(QStyleOptionViewItemV4& option,
-                                                    KVersionControlPlugin::VersionState state)
-{
-    QColor tintColor;
-
-    // Using hardcoded colors is generally a bad idea. In this case the colors just act
-    // as tint colors and are mixed with the current set text color. The tint colors
-    // have been optimized for the base colors of the corresponding Oxygen emblems.
-    switch (state) {
-    case KVersionControlPlugin::UpdateRequiredVersion:          tintColor = Qt::yellow; break;
-    case KVersionControlPlugin::LocallyModifiedUnstagedVersion: tintColor = Qt::darkGreen; break;
-    case KVersionControlPlugin::LocallyModifiedVersion:         tintColor = Qt::green; break;
-    case KVersionControlPlugin::AddedVersion:                   tintColor = Qt::green; break;
-    case KVersionControlPlugin::RemovedVersion:                 tintColor = Qt::darkRed; break;
-    case KVersionControlPlugin::ConflictingVersion:             tintColor = Qt::red; break;
-    case KVersionControlPlugin::UnversionedVersion:
-    case KVersionControlPlugin::NormalVersion:
-    default:
-        // use the default text color
-        return;
-    }
-
-    QPalette palette = option.palette;
-    const QColor textColor = palette.color(QPalette::Text);
-    tintColor = QColor((tintColor.red()   + textColor.red())   / 2,
-                       (tintColor.green() + textColor.green()) / 2,
-                       (tintColor.blue()  + textColor.blue())  / 2,
-                       (tintColor.alpha() + textColor.alpha()) / 2);
-    palette.setColor(QPalette::Text, tintColor);
-    option.palette = palette;
-}
-
-QPixmap DolphinFileItemDelegate::emblemForState(KVersionControlPlugin::VersionState state, const QSize& size) const
-{
-    Q_ASSERT(state <= KVersionControlPlugin::LocallyModifiedUnstagedVersion);
-    if (m_cachedSize != size) {
-        m_cachedSize = size;
-
-        const int iconHeight = size.height();
-        int emblemHeight = KIconLoader::SizeSmall;
-        if (iconHeight >= KIconLoader::SizeEnormous) {
-            emblemHeight = KIconLoader::SizeMedium;
-        } else if (iconHeight >= KIconLoader::SizeLarge) {
-            emblemHeight = KIconLoader::SizeSmallMedium;
-        } else if (iconHeight >= KIconLoader::SizeMedium) {
-            emblemHeight = KIconLoader::SizeSmall;
-        } else {
-            emblemHeight = KIconLoader::SizeSmall / 2;
-        }
-
-        const QSize emblemSize(emblemHeight, emblemHeight);
-        for (int i = KVersionControlPlugin::NormalVersion; i <= KVersionControlPlugin::LocallyModifiedUnstagedVersion; ++i) {
-            QString iconName;
-            switch (i) {
-            case KVersionControlPlugin::NormalVersion:
-                iconName = "vcs-normal";
-                break;
-            case KVersionControlPlugin::UpdateRequiredVersion:
-                iconName = "vcs-update-required";
-                break;
-            case KVersionControlPlugin::LocallyModifiedVersion:
-                iconName = "vcs-locally-modified";
-                break;
-            case KVersionControlPlugin::LocallyModifiedUnstagedVersion:
-                iconName = "vcs-locally-modified-unstaged";
-                break;
-            case KVersionControlPlugin::AddedVersion:
-                iconName = "vcs-added";
-                break;
-            case KVersionControlPlugin::RemovedVersion:
-                iconName = "vcs-removed";
-                break;
-            case KVersionControlPlugin::ConflictingVersion:
-                iconName = "vcs-conflicting";
-                break;
-            case KVersionControlPlugin::UnversionedVersion:
-                break;
-            default:
-                Q_ASSERT(false);
-                break;
-            }
-
-            m_cachedEmblems[i] = KIcon(iconName).pixmap(emblemSize);
-        }
-    }
-    return m_cachedEmblems[state];
-}
-
diff --git a/src/views/dolphinfileitemdelegate.h b/src/views/dolphinfileitemdelegate.h
deleted file mode 100644 (file)
index ab4a9fd..0000000
+++ /dev/null
@@ -1,96 +0,0 @@
-/***************************************************************************
- *   Copyright (C) 2008 by Peter Penz <peter.penz19@gmail.com>             *
- *                                                                         *
- *   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 program 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 program; if not, write to the                         *
- *   Free Software Foundation, Inc.,                                       *
- *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA            *
- ***************************************************************************/
-
-#ifndef DOLPHINFILEITEMDELEGATE_H
-#define DOLPHINFILEITEMDELEGATE_H
-
-#include <KFileItemDelegate>
-#include <views/dolphinmodel.h>
-
-class QAbstractProxyModel;
-
-/**
- * Extends KFileItemDelegate by the ability to show the hover effect
- * and the selection in a minimized way for the name column of
- * the details view.
- *
- * Note that this is a workaround, as Qt does not support having custom
- * shapes within the visual rect of an item view. The visual part of
- * workaround is handled inside DolphinFileItemDelegate, the behavior
- * changes are handled in DolphinTreeView.
- */
-class DolphinFileItemDelegate : public KFileItemDelegate
-{
-    Q_OBJECT
-public:
-    explicit DolphinFileItemDelegate(QObject* parent = 0);
-    virtual ~DolphinFileItemDelegate();
-
-    /**
-     * If \a minimized is true, the hover effect and the selection are
-     * only drawn above the icon and text of an item. Per default
-     * \a minimized is false, which means that the whole visual rect is
-     * used like in KFileItemDelegate.
-     */
-    void setMinimizedNameColumn(bool minimized);
-    bool hasMinimizedNameColumn() const;
-
-    virtual void paint(QPainter* painter,
-                       const QStyleOptionViewItem& option,
-                       const QModelIndex& index) const;
-
-    /**
-     * Returns the minimized width of the name column for the name \a name. This method
-     * is also used in DolphinDetailsView to handle the selection of items correctly.
-     */
-    static int nameColumnWidth(const QString& name, const QStyleOptionViewItem& option);
-
-private slots:
-    void handleDisplayPaletteChange();
-
-private:
-    static void adjustOptionWidth(QStyleOptionViewItemV4& option,
-                                  const QAbstractProxyModel* proxyModel,
-                                  const DolphinModel* dolphinModel,
-                                  const QModelIndex& index);
-
-    static void adjustOptionTextColor(QStyleOptionViewItemV4& option,
-                                      KVersionControlPlugin::VersionState state);
-
-    QPixmap emblemForState(KVersionControlPlugin::VersionState state, const QSize& size) const;
-
-private:
-    bool m_hasMinimizedNameColumn;
-    mutable QSize m_cachedSize;
-    mutable QPixmap m_cachedEmblems[KVersionControlPlugin::LocallyModifiedUnstagedVersion + 1];
-    mutable QColor m_cachedInactiveTextColor;
-    mutable bool m_cachedInactiveTextColorDirty;
-};
-
-inline void DolphinFileItemDelegate::setMinimizedNameColumn(bool minimized)
-{
-    m_hasMinimizedNameColumn = minimized;
-}
-
-inline bool DolphinFileItemDelegate::hasMinimizedNameColumn() const
-{
-    return m_hasMinimizedNameColumn;
-}
-
-#endif
diff --git a/src/views/dolphiniconsview.cpp b/src/views/dolphiniconsview.cpp
deleted file mode 100644 (file)
index a863de7..0000000
+++ /dev/null
@@ -1,524 +0,0 @@
-/***************************************************************************
- *   Copyright (C) 2006-2009 by Peter Penz <peter.penz19@gmail.com>        *
- *                                                                         *
- *   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 program 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 program; if not, write to the                         *
- *   Free Software Foundation, Inc.,                                       *
- *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA            *
- ***************************************************************************/
-
-#include "dolphiniconsview.h"
-
-#include "dolphincategorydrawer.h"
-#include "dolphinviewcontroller.h"
-#include "settings/dolphinsettings.h"
-#include "dolphinsortfilterproxymodel.h"
-#include "dolphin_iconsmodesettings.h"
-#include "dolphin_generalsettings.h"
-#include "draganddrophelper.h"
-#include "selectionmanager.h"
-#include "viewextensionsfactory.h"
-#include "viewmodecontroller.h"
-#include "zoomlevelinfo.h"
-
-#include <KCategorizedSortFilterProxyModel>
-#include <KDialog>
-#include <KFileItemDelegate>
-
-#include <QAbstractProxyModel>
-#include <QApplication>
-#include <QScrollBar>
-
-DolphinIconsView::DolphinIconsView(QWidget* parent,
-                                   DolphinViewController* dolphinViewController,
-                                   const ViewModeController* viewModeController,
-                                   DolphinSortFilterProxyModel* proxyModel) :
-    KCategorizedView(parent),
-    m_dolphinViewController(dolphinViewController),
-    m_categoryDrawer(new DolphinCategoryDrawer(this)),
-    m_extensionsFactory(0),
-    m_font(),
-    m_decorationSize(),
-    m_decorationPosition(QStyleOptionViewItem::Top),
-    m_displayAlignment(Qt::AlignHCenter),
-    m_itemSize(),
-    m_dropRect()
-{
-    Q_ASSERT(dolphinViewController);
-    Q_ASSERT(viewModeController);
-
-    setModel(proxyModel);
-    setLayoutDirection(Qt::LeftToRight);
-    setViewMode(QListView::IconMode);
-    setResizeMode(QListView::Adjust);
-    setMovement(QListView::Static);
-    setDragEnabled(true);
-    setEditTriggers(QAbstractItemView::NoEditTriggers);
-    viewport()->setAcceptDrops(true);
-
-    setMouseTracking(true);
-
-    connect(this, SIGNAL(clicked(const QModelIndex&)),
-            dolphinViewController, SLOT(requestTab(const QModelIndex&)));
-    if (KGlobalSettings::singleClick()) {
-        connect(this, SIGNAL(clicked(const QModelIndex&)),
-                dolphinViewController, SLOT(triggerItem(const QModelIndex&)));
-    } else {
-        connect(this, SIGNAL(doubleClicked(const QModelIndex&)),
-                dolphinViewController, SLOT(triggerItem(const QModelIndex&)));
-    }
-
-    connect(this, SIGNAL(entered(const QModelIndex&)),
-            dolphinViewController, SLOT(emitItemEntered(const QModelIndex&)));
-    connect(this, SIGNAL(viewportEntered()),
-            dolphinViewController, SLOT(emitViewportEntered()));
-    connect(viewModeController, SIGNAL(zoomLevelChanged(int)),
-            this, SLOT(setZoomLevel(int)));
-
-    const DolphinView* view = dolphinViewController->view();
-    connect(view, SIGNAL(showPreviewChanged()),
-            this, SLOT(slotShowPreviewChanged()));
-    connect(view, SIGNAL(additionalInfoChanged()),
-            this, SLOT(slotAdditionalInfoChanged()));
-
-    // apply the icons mode settings to the widget
-    const IconsModeSettings* settings = DolphinSettings::instance().iconsModeSettings();
-    Q_ASSERT(settings);
-
-    if (settings->useSystemFont()) {
-        m_font = KGlobalSettings::generalFont();
-    } else {
-        m_font = QFont(settings->fontFamily(),
-                       qRound(settings->fontSize()),
-                       settings->fontWeight(),
-                       settings->italicFont());
-        m_font.setPointSizeF(settings->fontSize());
-    }
-
-    setWordWrap(settings->numberOfTextlines() > 1);
-
-    if (settings->arrangement() == QListView::TopToBottom) {
-        setFlow(QListView::LeftToRight);
-        m_decorationPosition = QStyleOptionViewItem::Top;
-        m_displayAlignment = Qt::AlignHCenter;
-    } else {
-        setFlow(QListView::TopToBottom);
-        m_decorationPosition = QStyleOptionViewItem::Left;
-        m_displayAlignment = Qt::AlignLeft | Qt::AlignVCenter;
-    }
-
-    connect(m_categoryDrawer, SIGNAL(actionRequested(int,QModelIndex)), this, SLOT(categoryDrawerActionRequested(int,QModelIndex)));
-    setCategoryDrawer(m_categoryDrawer);
-
-    connect(KGlobalSettings::self(), SIGNAL(settingsChanged(int)),
-            this, SLOT(slotGlobalSettingsChanged(int)));
-
-    updateGridSize(view->showPreview(), 0);
-    m_extensionsFactory = new ViewExtensionsFactory(this, dolphinViewController, viewModeController);
-}
-
-DolphinIconsView::~DolphinIconsView()
-{
-}
-
-void DolphinIconsView::dataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight)
-{
-    KCategorizedView::dataChanged(topLeft, bottomRight);
-
-    KCategorizedSortFilterProxyModel* proxyModel = dynamic_cast<KCategorizedSortFilterProxyModel*>(model());
-    if (!proxyModel->isCategorizedModel()) {
-        // bypass a QListView issue that items are not layout correctly if the decoration size of
-        // an index changes
-        scheduleDelayedItemsLayout();
-    }
-}
-
-QStyleOptionViewItem DolphinIconsView::viewOptions() const
-{
-    QStyleOptionViewItem viewOptions = KCategorizedView::viewOptions();
-    viewOptions.font = m_font;
-    viewOptions.fontMetrics = QFontMetrics(m_font);
-    viewOptions.decorationPosition = m_decorationPosition;
-    viewOptions.decorationSize = m_decorationSize;
-    viewOptions.displayAlignment = m_displayAlignment;
-    viewOptions.showDecorationSelected = true;
-    return viewOptions;
-}
-
-void DolphinIconsView::contextMenuEvent(QContextMenuEvent* event)
-{
-    KCategorizedView::contextMenuEvent(event);
-    m_dolphinViewController->triggerContextMenuRequest(event->pos());
-}
-
-void DolphinIconsView::mousePressEvent(QMouseEvent* event)
-{
-    m_dolphinViewController->requestActivation();
-    const QModelIndex index = indexAt(event->pos());
-    if (index.isValid() && (event->button() == Qt::LeftButton)) {
-        // TODO: It should not be necessary to manually set the dragging state, but I could
-        // not reproduce this issue with a Qt-only example yet to find the root cause.
-        // Issue description: start Dolphin, split the view and drag an item from the
-        // inactive view to the active view by a very fast mouse movement. Result:
-        // the item gets selected instead of being dragged...
-        setState(QAbstractItemView::DraggingState);
-    }
-
-    if (!index.isValid() && (QApplication::mouseButtons() & Qt::MidButton)) {
-         m_dolphinViewController->replaceUrlByClipboard();
-    }
-
-    KCategorizedView::mousePressEvent(event);
-}
-
-void DolphinIconsView::startDrag(Qt::DropActions supportedActions)
-{
-    DragAndDropHelper::instance().startDrag(this, supportedActions, m_dolphinViewController);
-}
-
-void DolphinIconsView::dragEnterEvent(QDragEnterEvent* event)
-{
-    event->acceptProposedAction();
-}
-
-void DolphinIconsView::dragLeaveEvent(QDragLeaveEvent* event)
-{
-    KCategorizedView::dragLeaveEvent(event);
-    setDirtyRegion(m_dropRect);
-}
-
-void DolphinIconsView::dragMoveEvent(QDragMoveEvent* event)
-{
-    KCategorizedView::dragMoveEvent(event);
-
-    // TODO: remove this code when the issue #160611 is solved in Qt 4.4
-    const QModelIndex index = indexAt(event->pos());
-    setDirtyRegion(m_dropRect);
-
-    m_dropRect.setSize(QSize()); // set as invalid
-    if (index.isValid()) {
-        const KFileItem item = m_dolphinViewController->itemForIndex(index);
-        if (!item.isNull() && item.isDir()) {
-            m_dropRect = visualRect(index);
-        } else {
-            m_dropRect.setSize(QSize()); // set as invalid
-        }
-    }
-    event->acceptProposedAction();
-
-    setDirtyRegion(m_dropRect);
-}
-
-void DolphinIconsView::dropEvent(QDropEvent* event)
-{
-    const QModelIndex index = indexAt(event->pos());
-    const KFileItem item = m_dolphinViewController->itemForIndex(index);
-    m_dolphinViewController->indicateDroppedUrls(item, event);
-    // don't call KCategorizedView::dropEvent(event), as it moves
-    // the items which is not wanted
-}
-
-QModelIndex DolphinIconsView::moveCursor(CursorAction cursorAction, Qt::KeyboardModifiers modifiers)
-{
-    const QModelIndex oldCurrent = currentIndex();
-
-    QModelIndex newCurrent = KCategorizedView::moveCursor(cursorAction, modifiers);
-    if (newCurrent != oldCurrent) {
-        return newCurrent;
-    }
-
-    // The cursor has not been moved by the base implementation. Provide a
-    // wrap behavior, so that the cursor will go to the next item when reaching
-    // the border.
-    const IconsModeSettings* settings = DolphinSettings::instance().iconsModeSettings();
-    if (settings->arrangement() == QListView::LeftToRight) {
-        switch (cursorAction) {
-        case MoveUp:
-            if (newCurrent.row() == 0) {
-                return newCurrent;
-            }
-            newCurrent = KCategorizedView::moveCursor(MoveLeft, modifiers);
-            selectionModel()->setCurrentIndex(newCurrent, QItemSelectionModel::NoUpdate);
-            newCurrent = KCategorizedView::moveCursor(MovePageDown, modifiers);
-            break;
-
-        case MoveDown:
-            if (newCurrent.row() == (model()->rowCount() - 1)) {
-                return newCurrent;
-            }
-            newCurrent = KCategorizedView::moveCursor(MovePageUp, modifiers);
-            selectionModel()->setCurrentIndex(newCurrent, QItemSelectionModel::NoUpdate);
-            newCurrent = KCategorizedView::moveCursor(MoveRight, modifiers);
-            break;
-
-        default:
-            break;
-        }
-    } else {
-        QModelIndex current = oldCurrent;
-        switch (cursorAction) {
-        case MoveLeft:
-            if (newCurrent.row() == 0) {
-                return newCurrent;
-            }
-            newCurrent = KCategorizedView::moveCursor(MoveUp, modifiers);
-            do {
-                selectionModel()->setCurrentIndex(newCurrent, QItemSelectionModel::NoUpdate);
-                current = newCurrent;
-                newCurrent = KCategorizedView::moveCursor(MoveRight, modifiers);
-            } while (newCurrent != current);
-            break;
-
-        case MoveRight:
-            if (newCurrent.row() == (model()->rowCount() - 1)) {
-                return newCurrent;
-            }
-            do {
-                selectionModel()->setCurrentIndex(newCurrent, QItemSelectionModel::NoUpdate);
-                current = newCurrent;
-                newCurrent = KCategorizedView::moveCursor(MoveLeft, modifiers);
-            } while (newCurrent != current);
-            newCurrent = KCategorizedView::moveCursor(MoveDown, modifiers);
-            break;
-
-        default:
-            break;
-        }
-    }
-
-    // Revert all changes of the current item to make sure that item selection works correctly
-    selectionModel()->setCurrentIndex(oldCurrent, QItemSelectionModel::NoUpdate);
-    return newCurrent;
-}
-
-void DolphinIconsView::keyPressEvent(QKeyEvent* event)
-{
-    KCategorizedView::keyPressEvent(event);
-    m_dolphinViewController->handleKeyPressEvent(event);
-}
-
-void DolphinIconsView::wheelEvent(QWheelEvent* event)
-{
-    horizontalScrollBar()->setSingleStep(m_itemSize.width() / 5);
-    verticalScrollBar()->setSingleStep(m_itemSize.height() / 5);
-
-    KCategorizedView::wheelEvent(event);
-    // if the icons are aligned left to right, the vertical wheel event should
-    // be applied to the horizontal scrollbar
-    const IconsModeSettings* settings = DolphinSettings::instance().iconsModeSettings();
-    const bool scrollHorizontal = (event->orientation() == Qt::Vertical) &&
-                                  (settings->arrangement() == QListView::LeftToRight);
-    if (scrollHorizontal) {
-        QWheelEvent horizEvent(event->pos(),
-                               event->delta(),
-                               event->buttons(),
-                               event->modifiers(),
-                               Qt::Horizontal);
-        QApplication::sendEvent(horizontalScrollBar(), &horizEvent);
-    }
-}
-
-void DolphinIconsView::showEvent(QShowEvent* event)
-{
-    KFileItemDelegate* delegate = dynamic_cast<KFileItemDelegate*>(itemDelegate());
-    delegate->setMaximumSize(m_itemSize);
-
-    KCategorizedView::showEvent(event);
-}
-
-void DolphinIconsView::leaveEvent(QEvent* event)
-{
-    KCategorizedView::leaveEvent(event);
-    // if the mouse is above an item and moved very fast outside the widget,
-    // no viewportEntered() signal might be emitted although the mouse has been moved
-    // above the viewport
-    m_dolphinViewController->emitViewportEntered();
-}
-
-void DolphinIconsView::currentChanged(const QModelIndex& current, const QModelIndex& previous)
-{
-    KCategorizedView::currentChanged(current, previous);
-    m_extensionsFactory->handleCurrentIndexChange(current, previous);
-}
-
-void DolphinIconsView::resizeEvent(QResizeEvent* event)
-{
-    KCategorizedView::resizeEvent(event);
-    const DolphinView* view = m_dolphinViewController->view();
-    updateGridSize(view->showPreview(), view->additionalInfo().count());
-}
-
-void DolphinIconsView::slotShowPreviewChanged()
-{
-    const DolphinView* view = m_dolphinViewController->view();
-    updateGridSize(view->showPreview(), additionalInfoCount());
-}
-
-void DolphinIconsView::slotAdditionalInfoChanged()
-{
-    const DolphinView* view = m_dolphinViewController->view();
-    const bool showPreview = view->showPreview();
-    updateGridSize(showPreview, view->additionalInfo().count());
-}
-
-void DolphinIconsView::setZoomLevel(int level)
-{
-    IconsModeSettings* settings = DolphinSettings::instance().iconsModeSettings();
-
-    const int oldIconSize = settings->iconSize();
-    int newIconSize = oldIconSize;
-
-    const bool showPreview = m_dolphinViewController->view()->showPreview();
-    if (showPreview) {
-        const int previewSize = ZoomLevelInfo::iconSizeForZoomLevel(level);
-        settings->setPreviewSize(previewSize);
-    } else {
-        newIconSize = ZoomLevelInfo::iconSizeForZoomLevel(level);
-        settings->setIconSize(newIconSize);
-    }
-
-    // increase also the grid size
-    const int diff = newIconSize - oldIconSize;
-    settings->setItemWidth(settings->itemWidth() + diff);
-    settings->setItemHeight(settings->itemHeight() + diff);
-
-    updateGridSize(showPreview, additionalInfoCount());
-}
-
-void DolphinIconsView::requestActivation()
-{
-    m_dolphinViewController->requestActivation();
-}
-
-void DolphinIconsView::slotGlobalSettingsChanged(int category)
-{
-    Q_UNUSED(category);
-
-    const IconsModeSettings* settings = DolphinSettings::instance().iconsModeSettings();
-    Q_ASSERT(settings);
-    if (settings->useSystemFont()) {
-        m_font = KGlobalSettings::generalFont();
-    }
-
-    disconnect(this, SIGNAL(clicked(QModelIndex)), m_dolphinViewController, SLOT(triggerItem(QModelIndex)));
-    disconnect(this, SIGNAL(doubleClicked(QModelIndex)), m_dolphinViewController, SLOT(triggerItem(QModelIndex)));
-    if (KGlobalSettings::singleClick()) {
-        connect(this, SIGNAL(clicked(QModelIndex)), m_dolphinViewController, SLOT(triggerItem(QModelIndex)));
-    } else {
-        connect(this, SIGNAL(doubleClicked(QModelIndex)), m_dolphinViewController, SLOT(triggerItem(QModelIndex)));
-    }
-}
-
-void DolphinIconsView::categoryDrawerActionRequested(int action, const QModelIndex &index)
-{
-    const QSortFilterProxyModel *model = dynamic_cast<const QSortFilterProxyModel*>(index.model());
-    const QModelIndex topLeft = model->index(index.row(), modelColumn());
-    QModelIndex bottomRight = topLeft;
-    const QString category = model->data(index, KCategorizedSortFilterProxyModel::CategoryDisplayRole).toString();
-    QModelIndex current = topLeft;
-    while (true) {
-        current = model->index(current.row() + 1, modelColumn());
-        const QString curCategory = model->data(model->index(current.row(), index.column()), KCategorizedSortFilterProxyModel::CategoryDisplayRole).toString();
-        if (!current.isValid() || category != curCategory) {
-            break;
-        }
-        bottomRight = current;
-    }
-    switch (action) {
-        case DolphinCategoryDrawer::SelectAll:
-            selectionModel()->select(QItemSelection(topLeft, bottomRight), QItemSelectionModel::Select);
-            break;
-        case DolphinCategoryDrawer::UnselectAll:
-            selectionModel()->select(QItemSelection(topLeft, bottomRight), QItemSelectionModel::Deselect);
-            break;
-        default:
-            break;
-    }
-}
-
-void DolphinIconsView::updateGridSize(bool showPreview, int additionalInfoCount)
-{
-    const IconsModeSettings* settings = DolphinSettings::instance().iconsModeSettings();
-    Q_ASSERT(settings);
-
-    int itemWidth = settings->itemWidth();
-    int itemHeight = settings->itemHeight();
-    int size = settings->iconSize();
-
-    if (showPreview) {
-        const int previewSize = settings->previewSize();
-        const int diff = previewSize - size;
-        itemWidth  += diff;
-        itemHeight += diff;
-
-        size = previewSize;
-    }
-
-    Q_ASSERT(additionalInfoCount >= 0);
-    itemHeight += additionalInfoCount * QFontMetrics(m_font).height();
-
-    // Optimize the item size of the grid in a way to prevent large gaps on the
-    // right border (= row arrangement) or the bottom border (= column arrangement).
-    // There is no public API in QListView to find out the used width of the viewport
-    // for the layout. The following calculation of 'contentWidth'/'contentHeight'
-    // is based on QListViewPrivate::prepareItemsLayout() (Copyright (C) 2009 Nokia Corporation).
-    int frameAroundContents = 0;
-    if (style()->styleHint(QStyle::SH_ScrollView_FrameOnlyAroundContents)) {
-        frameAroundContents = style()->pixelMetric(QStyle::PM_DefaultFrameWidth) * 2;
-    }
-    const int spacing = settings->gridSpacing();
-    if (settings->arrangement() == QListView::TopToBottom) {
-        const int contentWidth = viewport()->width() - 1
-                                 - frameAroundContents
-                                 - style()->pixelMetric(QStyle::PM_ScrollBarExtent, 0, horizontalScrollBar());
-        const int gridWidth = itemWidth + spacing * 2;
-        const int horizItemCount = contentWidth / gridWidth;
-        if (horizItemCount > 0) {
-            itemWidth += (contentWidth - horizItemCount * gridWidth) / horizItemCount;
-        }
-
-        // The decoration width indirectly defines the maximum
-        // width for the text wrapping. To use the maximum item width
-        // for text wrapping, it is used as decoration width.
-        m_decorationSize = QSize(itemWidth, size);
-        setIconSize(QSize(itemWidth, size));
-    } else {
-        const int contentHeight = viewport()->height() - 1
-                                  - frameAroundContents
-                                  - style()->pixelMetric(QStyle::PM_ScrollBarExtent, 0, verticalScrollBar());
-        const int gridHeight = itemHeight + spacing;
-        const int vertItemCount = contentHeight / gridHeight;
-        if (vertItemCount > 0) {
-            itemHeight += (contentHeight - vertItemCount * gridHeight) / vertItemCount;
-        }
-
-        m_decorationSize = QSize(size, size);
-        setIconSize(QSize(size, size));
-    }
-
-    m_itemSize = QSize(itemWidth, itemHeight);
-    setGridSizeOwn(QSize(itemWidth + spacing * 2, itemHeight + spacing));
-
-    KFileItemDelegate* delegate = dynamic_cast<KFileItemDelegate*>(itemDelegate());
-    if (delegate) {
-        delegate->setMaximumSize(m_itemSize);
-    }
-}
-
-int DolphinIconsView::additionalInfoCount() const
-{
-    const DolphinView* view = m_dolphinViewController->view();
-    return view->additionalInfo().count();
-}
-
-#include "dolphiniconsview.moc"
diff --git a/src/views/dolphiniconsview.h b/src/views/dolphiniconsview.h
deleted file mode 100644 (file)
index 2dd1aa7..0000000
+++ /dev/null
@@ -1,121 +0,0 @@
-/***************************************************************************
- *   Copyright (C) 2006-2009 by Peter Penz <peter.penz19@gmail.com>        *
- *                                                                         *
- *   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 program 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 program; if not, write to the                         *
- *   Free Software Foundation, Inc.,                                       *
- *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA            *
- ***************************************************************************/
-
-#ifndef DOLPHINICONSVIEW_H
-#define DOLPHINICONSVIEW_H
-
-#include <KCategorizedView>
-
-#include <KFileItem>
-#include <KFileItemDelegate>
-
-#include <QFont>
-#include <QSize>
-#include <QStyleOption>
-
-#include <libdolphin_export.h>
-
-class DolphinViewController;
-class DolphinCategoryDrawer;
-class DolphinSortFilterProxyModel;
-class ViewExtensionsFactory;
-class ViewModeController;
-
-/**
- * @brief Represents the view, where each item is shown as an icon.
- *
- * It is also possible that instead of the icon a preview of the item
- * content is shown.
- */
-class LIBDOLPHINPRIVATE_EXPORT DolphinIconsView : public KCategorizedView
-{
-    Q_OBJECT
-
-public:
-    /**
-     * @param parent                Parent widget.
-     * @param dolphinViewController Allows the DolphinIconsView to control the
-     *                              DolphinView in a limited way.
-     * @param viewModeController    Controller that is used by the DolphinView
-     *                              to control the DolphinIconsView. The DolphinIconsView
-     *                              only has read access to the controller.
-     * @param model                 Directory that is shown.
-     */
-    explicit DolphinIconsView(QWidget* parent,
-                              DolphinViewController* dolphinViewController,
-                              const ViewModeController* viewModeController,
-                              DolphinSortFilterProxyModel* proxyModel);
-    virtual ~DolphinIconsView();
-
-protected slots:
-    virtual void dataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight);
-
-protected:
-    virtual QStyleOptionViewItem viewOptions() const;
-    virtual void contextMenuEvent(QContextMenuEvent* event);
-    virtual void mousePressEvent(QMouseEvent* event);
-    virtual void startDrag(Qt::DropActions supportedActions);
-    virtual void dragEnterEvent(QDragEnterEvent* event);
-    virtual void dragLeaveEvent(QDragLeaveEvent* event);
-    virtual void dragMoveEvent(QDragMoveEvent* event);
-    virtual void dropEvent(QDropEvent* event);
-    virtual QModelIndex moveCursor(CursorAction cursorAction, Qt::KeyboardModifiers modifiers);
-    virtual void keyPressEvent(QKeyEvent* event);
-    virtual void wheelEvent(QWheelEvent* event);
-    virtual void showEvent(QShowEvent* event);
-    virtual void leaveEvent(QEvent* event);
-    virtual void currentChanged(const QModelIndex& current, const QModelIndex& previous);
-    virtual void resizeEvent(QResizeEvent* event);
-
-private slots:
-    void slotShowPreviewChanged();
-    void slotAdditionalInfoChanged();
-    void setZoomLevel(int level);
-    void requestActivation();
-    void slotGlobalSettingsChanged(int category);
-    void categoryDrawerActionRequested(int action, const QModelIndex &index);
-
-private:
-    /**
-     * Updates the size of the grid depending on the state
-     * of \a showPreview and \a additionalInfoCount.
-     */
-    void updateGridSize(bool showPreview, int additionalInfoCount);
-
-    /**
-     * Returns the number of additional information lines that should
-     * be shown below the item name.
-     */
-    int additionalInfoCount() const;
-
-private:
-    DolphinViewController* m_dolphinViewController;
-    DolphinCategoryDrawer* m_categoryDrawer;
-    ViewExtensionsFactory* m_extensionsFactory;
-
-    QFont m_font;
-    QSize m_decorationSize;
-    QStyleOptionViewItem::Position m_decorationPosition;
-    Qt::Alignment m_displayAlignment;
-
-    QSize m_itemSize;
-    QRect m_dropRect;
-};
-
-#endif
diff --git a/src/views/dolphinitemlistcontainer.cpp b/src/views/dolphinitemlistcontainer.cpp
new file mode 100644 (file)
index 0000000..9c9ad6d
--- /dev/null
@@ -0,0 +1,279 @@
+/***************************************************************************
+ *   Copyright (C) 2011 by Peter Penz <peter.penz19@gmail.com>             *
+ *                                                                         *
+ *   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 program 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 program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA            *
+ ***************************************************************************/
+
+#include "dolphinitemlistcontainer.h"
+
+#include "dolphin_iconsmodesettings.h"
+#include "dolphin_detailsmodesettings.h"
+#include "dolphin_compactmodesettings.h"
+
+#include <kitemviews/kitemliststyleoption.h>
+#include <kitemviews/kfileitemlistview.h>
+#include <kitemviews/kfileitemmodel.h>
+#include <kitemviews/kitemlistcontroller.h>
+#include <kitemviews/kitemliststyleoption.h>
+
+#include <KDirLister>
+#include <KGlobalSettings>
+
+#include <views/viewmodecontroller.h>
+
+#include "zoomlevelinfo.h"
+
+
+DolphinItemListContainer::DolphinItemListContainer(KDirLister* dirLister,
+                                                   QWidget* parent) :
+    KItemListContainer(parent),
+    m_zoomLevel(0),
+    m_fileItemListView(0)
+{
+    controller()->setModel(new KFileItemModel(dirLister, this));
+
+    m_fileItemListView = new KFileItemListView();
+    controller()->setView(m_fileItemListView);
+
+    KItemListStyleOption option;
+
+    // TODO:
+    option.font = parent->font();
+    option.fontMetrics = QFontMetrics(parent->font());
+
+    updateGridSize();
+/*
+    connect(this, SIGNAL(clicked(const QModelIndex&)),
+            dolphinViewController, SLOT(requestTab(const QModelIndex&)));*/
+/*
+    connect(this, SIGNAL(entered(const QModelIndex&)),
+            dolphinViewController, SLOT(emitItemEntered(const QModelIndex&)));
+    connect(this, SIGNAL(viewportEntered()),
+            dolphinViewController, SLOT(emitViewportEntered()));*/
+
+    // apply the icons mode settings to the widget
+    //const IconsModeSettings* settings = DolphinSettings::instance().iconsModeSettings();
+    //Q_ASSERT(settings);
+
+    /*if (settings->useSystemFont()) {
+        m_font = KGlobalSettings::generalFont();
+    } else {
+        m_font = QFont(settings->fontFamily(),
+                       qRound(settings->fontSize()),
+                       settings->fontWeight(),
+                       settings->italicFont());
+        m_font.setPointSizeF(settings->fontSize());
+    }
+
+    setWordWrap(settings->numberOfTextlines() > 1);
+
+    if (settings->arrangement() == QListView::TopToBottom) {
+        setFlow(QListView::LeftToRight);
+        m_decorationPosition = QStyleOptionViewItem::Top;
+        m_displayAlignment = Qt::AlignHCenter;
+    } else {
+        setFlow(QListView::TopToBottom);
+        m_decorationPosition = QStyleOptionViewItem::Left;
+        m_displayAlignment = Qt::AlignLeft | Qt::AlignVCenter;
+    }
+
+    connect(m_categoryDrawer, SIGNAL(actionRequested(int,QModelIndex)), this, SLOT(categoryDrawerActionRequested(int,QModelIndex)));
+    setCategoryDrawer(m_categoryDrawer);
+
+    connect(KGlobalSettings::self(), SIGNAL(settingsChanged(int)),
+            this, SLOT(slotGlobalSettingsChanged(int)));*/
+
+    //updateGridSize(dolphinView->showPreview(), 0);
+    /*m_extensionsFactory = new ViewExtensionsFactory(this, dolphinViewController, viewModeController);*/
+}
+
+DolphinItemListContainer::~DolphinItemListContainer()
+{
+    IconsModeSettings::self()->writeConfig();
+    CompactModeSettings::self()->writeConfig();
+    DetailsModeSettings::self()->writeConfig();
+
+    KItemListView* view = controller()->view();
+    controller()->setView(0);
+    delete view;
+}
+
+void DolphinItemListContainer::setPreviewsShown(bool show)
+{
+    beginTransaction();
+    m_fileItemListView->setPreviewsShown(show);
+    updateGridSize();
+    endTransaction();
+}
+
+bool DolphinItemListContainer::previewsShown() const
+{
+    return m_fileItemListView->previewsShown();
+}
+
+void DolphinItemListContainer::setVisibleRoles(const QHash<QByteArray, int>& roles)
+{
+    m_fileItemListView->setVisibleRoles(roles);
+    updateGridSize();
+}
+
+QHash<QByteArray, int> DolphinItemListContainer::visibleRoles() const
+{
+    return m_fileItemListView->visibleRoles();
+}
+
+void DolphinItemListContainer::setZoomLevel(int level)
+{
+    if (level < ZoomLevelInfo::minimumLevel()) {
+        level = ZoomLevelInfo::minimumLevel();
+    } else if (level > ZoomLevelInfo::maximumLevel()) {
+        level = ZoomLevelInfo::maximumLevel();
+    }
+
+    if (level == m_zoomLevel) {
+        return;
+    }
+
+    m_zoomLevel = level;
+
+    if (previewsShown()) {
+        const int previewSize = ZoomLevelInfo::iconSizeForZoomLevel(level);
+
+        switch (itemLayout()) {
+        case KFileItemListView::IconsLayout:   IconsModeSettings::setPreviewSize(previewSize); break;
+        case KFileItemListView::CompactLayout: CompactModeSettings::setPreviewSize(previewSize); break;
+        case KFileItemListView::DetailsLayout: DetailsModeSettings::setPreviewSize(previewSize); break;
+        default: Q_ASSERT(false); break;
+        }
+    } else {
+        const int iconSize = ZoomLevelInfo::iconSizeForZoomLevel(level);
+        switch (itemLayout()) {
+        case KFileItemListView::IconsLayout:   IconsModeSettings::setIconSize(iconSize); break;
+        case KFileItemListView::CompactLayout: CompactModeSettings::setIconSize(iconSize); break;
+        case KFileItemListView::DetailsLayout: DetailsModeSettings::setIconSize(iconSize); break;
+        default: Q_ASSERT(false); break;
+        }
+    }
+
+    updateGridSize();
+}
+
+int DolphinItemListContainer::zoomLevel() const
+{
+    return m_zoomLevel;
+}
+
+void DolphinItemListContainer::setItemLayout(KFileItemListView::Layout layout)
+{
+    if (layout == itemLayout()) {
+        return;
+    }
+
+    beginTransaction();
+    m_fileItemListView->setItemLayout(layout);
+
+    switch (layout) {
+    case KFileItemListView::IconsLayout:
+    case KFileItemListView::DetailsLayout:
+        m_fileItemListView->setScrollOrientation(Qt::Vertical);
+        break;
+    case KFileItemListView::CompactLayout:
+        m_fileItemListView->setScrollOrientation(Qt::Horizontal);
+        break;
+    default:
+        Q_ASSERT(false);
+        break;
+    }
+
+    updateGridSize();
+    endTransaction();
+}
+
+KFileItemListView::Layout DolphinItemListContainer::itemLayout() const
+{
+    return m_fileItemListView->itemLayout();
+}
+
+void DolphinItemListContainer::beginTransaction()
+{
+    m_fileItemListView->beginTransaction();
+}
+
+void DolphinItemListContainer::endTransaction()
+{
+    m_fileItemListView->endTransaction();
+}
+
+void DolphinItemListContainer::updateGridSize()
+{
+    // Calculate the size of the icon
+    int iconSize;
+    if (previewsShown()) {
+        switch (itemLayout()) {
+        case KFileItemListView::IconsLayout:   iconSize = IconsModeSettings::previewSize(); break;
+        case KFileItemListView::CompactLayout: iconSize = CompactModeSettings::previewSize(); break;
+        case KFileItemListView::DetailsLayout: iconSize = DetailsModeSettings::previewSize(); break;
+        default: Q_ASSERT(false); break;
+        }
+    } else {
+        switch (itemLayout()) {
+        case KFileItemListView::IconsLayout:   iconSize = IconsModeSettings::iconSize(); break;
+        case KFileItemListView::CompactLayout: iconSize = CompactModeSettings::iconSize(); break;
+        case KFileItemListView::DetailsLayout: iconSize = DetailsModeSettings::iconSize(); break;
+        default: Q_ASSERT(false); break;
+        }
+    }
+
+    m_zoomLevel = ZoomLevelInfo::zoomLevelForIconSize(QSize(iconSize, iconSize));
+    KItemListStyleOption styleOption = m_fileItemListView->styleOption();
+
+    const int innerMargin = (iconSize >= KIconLoader::SizeSmallMedium) ? 4 : 2;
+
+    // Calculate the item-width and item-height
+    int itemWidth;
+    int itemHeight;
+    switch (itemLayout()) {
+    case KFileItemListView::IconsLayout: {
+        const int minItemWidth = 64;
+        itemWidth = minItemWidth + IconsModeSettings::textWidthIndex() * 64; // TODO:
+        if (itemWidth < iconSize + innerMargin * 2) {
+            itemWidth = iconSize + innerMargin * 2;
+        }
+        itemHeight = innerMargin * 2 + iconSize + styleOption.fontMetrics.height();
+        break;
+    }
+    case KFileItemListView::CompactLayout: {
+        itemWidth = innerMargin * 2;
+        const int textLinesCount = m_fileItemListView->visibleRoles().count();
+        itemHeight = innerMargin * 2 + qMax(iconSize, textLinesCount * styleOption.fontMetrics.height());
+        break;
+    }
+    case KFileItemListView::DetailsLayout: {
+        itemWidth = -1;
+        itemHeight = innerMargin * 2 + qMax(iconSize, styleOption.fontMetrics.height());
+        break;
+    }
+    default: Q_ASSERT(false); break;
+    }
+
+    // Apply the calculated values
+    styleOption.margin = innerMargin;
+    styleOption.iconSize = iconSize;
+    m_fileItemListView->setStyleOption(styleOption);
+    m_fileItemListView->setItemSize(QSizeF(itemWidth, itemHeight));
+}
+
+#include "dolphinitemlistcontainer.moc"
diff --git a/src/views/dolphinitemlistcontainer.h b/src/views/dolphinitemlistcontainer.h
new file mode 100644 (file)
index 0000000..599a4bd
--- /dev/null
@@ -0,0 +1,78 @@
+/***************************************************************************
+ *   Copyright (C) 2011 by Peter Penz <peter.penz19@gmail.com>             *
+ *                                                                         *
+ *   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 program 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 program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA            *
+ ***************************************************************************/
+
+#ifndef DOLPHINITEMLISTCONTAINER_H
+#define DOLPHINITEMLISTCONTAINER_H
+
+#include <kitemviews/kfileitemlistview.h>
+#include <kitemviews/kitemlistcontainer.h>
+
+#include <libdolphin_export.h>
+
+class KDirLister;
+class KFileItemListView;
+
+/**
+ * @brief Extends KItemListContainer by Dolphin specific properties.
+ *
+ * The view and model for KFileItems are created automatically when
+ * instantating KItemListContainer.
+ *
+ * The Dolphin settings of the icons-, compact- and details-view are
+ * converted internally to properties that can be used to configure e.g.
+ * the item-size and visible roles of the KItemListView.
+ */
+class LIBDOLPHINPRIVATE_EXPORT DolphinItemListContainer : public KItemListContainer
+{
+    Q_OBJECT
+
+public:
+    DolphinItemListContainer(KDirLister* dirLister,
+                             QWidget* parent = 0);
+
+    virtual ~DolphinItemListContainer();
+
+    void setPreviewsShown(bool show);
+    bool previewsShown() const;
+
+    /**
+     * Sets the visible roles to \p roles. The integer-value defines
+     * the order of the visible role: Smaller values are ordered first.
+     */
+    void setVisibleRoles(const QHash<QByteArray, int>& roles);
+    QHash<QByteArray, int> visibleRoles() const;
+
+    void setZoomLevel(int level);
+    int zoomLevel() const;
+
+    void setItemLayout(KFileItemListView::Layout layout);
+    KFileItemListView::Layout itemLayout() const;
+
+    void beginTransaction();
+    void endTransaction();
+
+private:
+    void updateGridSize();
+
+private:
+    int m_zoomLevel;
+    KFileItemListView* m_fileItemListView;
+};
+
+#endif
diff --git a/src/views/dolphinmodel.cpp b/src/views/dolphinmodel.cpp
deleted file mode 100644 (file)
index c999dfa..0000000
+++ /dev/null
@@ -1,448 +0,0 @@
-/**
-  * This file is part of the KDE project
-  * Copyright (C) 2007 Rafael Fernández López <ereslibre@kde.org>
-  *
-  * This library is free software; you can redistribute it and/or
-  * modify it under the terms of the GNU Library General Public
-  * License as published by the Free Software Foundation; either
-  * version 2 of the License, or (at your option) any later version.
-  *
-  * This library 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
-  * Library General Public License for more details.
-  *
-  * You should have received a copy of the GNU Library General Public License
-  * along with this library; see the file COPYING.LIB.  If not, write to
-  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-  * Boston, MA 02110-1301, USA.
-  */
-
-#include "dolphinmodel.h"
-
-#include "dolphinsortfilterproxymodel.h"
-
-#include <KCategorizedView>
-#include <KDateTime>
-#include <KDirModel>
-#include <KFileItem>
-#include <KIconLoader>
-#include <KLocale>
-#include <KUrl>
-#include <KUser>
-#include <KMimeType>
-#include <KStandardDirs>
-
-#include <QList>
-#include <QSortFilterProxyModel>
-#include <QPainter>
-#include <QPersistentModelIndex>
-#include <QDir>
-#include <QFileInfo>
-
-const char* const DolphinModel::m_others = I18N_NOOP2("@title:group Name", "Others");
-
-DolphinModel::DolphinModel(QObject* parent) :
-    KDirModel(parent),
-    m_hasVersionData(false),
-    m_revisionHash()
-{
-    setJobTransfersVisible(true);
-}
-
-DolphinModel::~DolphinModel()
-{
-}
-
-bool DolphinModel::setData(const QModelIndex& index, const QVariant& value, int role)
-{
-    if ((index.column() == DolphinModel::Version) && (role == Qt::DecorationRole)) {
-        // TODO: remove data again when items are deleted...
-
-        const QPersistentModelIndex key = index;
-        const KVersionControlPlugin::VersionState state = static_cast<KVersionControlPlugin::VersionState>(value.toInt());
-        if (m_revisionHash.value(key, KVersionControlPlugin::UnversionedVersion) != state) {
-            if (!m_hasVersionData) {
-                connect(this, SIGNAL(rowsRemoved (const QModelIndex&, int, int)),
-                        this, SLOT(slotRowsRemoved(const QModelIndex&, int, int)));
-                m_hasVersionData = true;
-            }
-
-            m_revisionHash.insert(key, state);
-            emit dataChanged(index, index);
-            return true;
-        }
-    }
-
-    return KDirModel::setData(index, value, role);
-}
-
-QVariant DolphinModel::data(const QModelIndex& index, int role) const
-{
-    switch (role) {
-    case KCategorizedSortFilterProxyModel::CategoryDisplayRole:
-        return displayRoleData(index);
-
-    case KCategorizedSortFilterProxyModel::CategorySortRole:
-        return sortRoleData(index);
-
-    case Qt::DecorationRole:
-        if (index.column() == DolphinModel::Version) {
-            return m_revisionHash.value(index, KVersionControlPlugin::UnversionedVersion);
-        }
-        break;
-
-    case Qt::DisplayRole:
-        switch (index.column()) {
-        case DolphinModel::LinkDest: {
-            const KDirModel *dirModel = qobject_cast<const KDirModel*>(index.model());
-            const KFileItem item = dirModel->itemForIndex(index);
-            return item.linkDest();
-        }
-
-        case DolphinModel::LocalPathOrUrl:
-            const KDirModel *dirModel = qobject_cast<const KDirModel*>(index.model());
-            const KFileItem item = dirModel->itemForIndex(index);
-            const KUrl url = item.mostLocalUrl();
-            if (url.protocol() == QLatin1String("trash")) {
-                const KIO::UDSEntry udsEntry = item.entry();
-                return udsEntry.stringValue(KIO::UDSEntry::UDS_EXTRA);
-            }
-            return url.directory();
-        }
-        break;
-
-    default:
-        break;
-    }
-
-    return KDirModel::data(index, role);
-}
-
-QVariant DolphinModel::headerData(int section, Qt::Orientation orientation, int role) const
-{
-    if ((orientation == Qt::Horizontal) && (role == Qt::DisplayRole)) {
-        switch (section) {
-        case DolphinModel::LinkDest:
-            return i18nc("@title::column", "Link Destination");
-        case DolphinModel::LocalPathOrUrl:
-            return i18nc("@title::column", "Path");
-        default:
-            return KDirModel::headerData(section, orientation, role);
-        }
-    }
-    return QVariant();
-}
-
-int DolphinModel::columnCount(const QModelIndex& parent) const
-{
-    return KDirModel::columnCount(parent) + (ExtraColumnCount - ColumnCount);
-}
-
-void DolphinModel::clearVersionData()
-{
-    m_revisionHash.clear();
-    m_hasVersionData = false;
-}
-
-bool DolphinModel::hasVersionData() const
-{
-    return m_hasVersionData;
-}
-
-void DolphinModel::slotRowsRemoved(const QModelIndex& parent, int start, int end)
-{
-    if (m_hasVersionData) {
-        const int column = parent.column();
-        for (int row = start; row <= end; ++row) {
-            m_revisionHash.remove(parent.child(row, column));
-        }
-    }
-}
-
-QVariant DolphinModel::displayRoleData(const QModelIndex& index) const
-{
-    QString retString;
-
-    if (!index.isValid()) {
-        return retString;
-    }
-
-    const KDirModel *dirModel = qobject_cast<const KDirModel*>(index.model());
-    KFileItem item = dirModel->itemForIndex(index);
-
-    switch (index.column()) {
-    case KDirModel::Name: {
-        // KDirModel checks columns to know to which role are
-        // we talking about
-        const QModelIndex nameIndex = index.model()->index(index.row(), KDirModel::Name, index.parent());
-        if (!nameIndex.isValid()) {
-            return retString;
-        }
-        const QVariant data = nameIndex.model()->data(nameIndex, Qt::DisplayRole);
-        const QString name = data.toString();
-        if (!name.isEmpty()) {
-            if (!item.isHidden() && name.at(0).isLetter())
-                retString = name.at(0).toUpper();
-            else if (item.isHidden()) {
-                if (name.at(0) == '.') {
-                    if (name.size() > 1 && name.at(1).isLetter()) {
-                        retString = name.at(1).toUpper();
-                    } else {
-                        retString = i18nc("@title:group Name", m_others);
-                    }
-                } else {
-                    retString = name.at(0).toUpper();
-                }
-            } else {
-                bool validCategory = false;
-
-                const QString str(name.toUpper());
-                const QChar* currA = str.unicode();
-                while (!currA->isNull() && !validCategory) {
-                    if (currA->isLetter()) {
-                        validCategory = true;
-                    } else if (currA->isDigit()) {
-                        return i18nc("@title:group Name", m_others);
-                    } else {
-                        ++currA;
-                    }
-                }
-
-                retString = validCategory ? *currA : i18nc("@title:group Name", m_others);
-            }
-        }
-        break;
-    }
-
-    case KDirModel::Size: {
-        const KIO::filesize_t fileSize = !item.isNull() ? item.size() : ~0U;
-        if (!item.isNull() && item.isDir()) {
-            retString = i18nc("@title:group Size", "Folders");
-        } else if (fileSize < 5242880) {
-            retString = i18nc("@title:group Size", "Small");
-        } else if (fileSize < 10485760) {
-            retString = i18nc("@title:group Size", "Medium");
-        } else {
-            retString = i18nc("@title:group Size", "Big");
-        }
-        break;
-    }
-
-    case KDirModel::ModifiedTime: {
-        KDateTime modifiedTime = item.time(KFileItem::ModificationTime);
-        modifiedTime = modifiedTime.toLocalZone();
-
-        const QDate currentDate = KDateTime::currentLocalDateTime().date();
-        const QDate modifiedDate = modifiedTime.date();
-
-        const int daysDistance = modifiedDate.daysTo(currentDate);
-
-        int yearForCurrentWeek = 0;
-        int currentWeek = currentDate.weekNumber(&yearForCurrentWeek);
-        if (yearForCurrentWeek == currentDate.year() + 1) {
-            currentWeek = 53;
-        }
-
-        int yearForModifiedWeek = 0;
-        int modifiedWeek = modifiedDate.weekNumber(&yearForModifiedWeek);
-        if (yearForModifiedWeek == modifiedDate.year() + 1) {
-            modifiedWeek = 53;
-        }
-
-        if (currentDate.year() == modifiedDate.year() && currentDate.month() == modifiedDate.month()) {
-            if (modifiedWeek > currentWeek) {
-                // use case: modified date = 2010-01-01, current date = 2010-01-22
-                //           modified week = 53,         current week = 3
-                modifiedWeek = 0;
-            }
-            switch (currentWeek - modifiedWeek) {
-            case 0:
-                switch (daysDistance) {
-                case 0:  retString = i18nc("@title:group Date", "Today"); break;
-                case 1:  retString = i18nc("@title:group Date", "Yesterday"); break;
-                default: retString = modifiedTime.toString(i18nc("@title:group The week day name: %A", "%A"));
-                }
-                break;
-            case 1:
-                retString = i18nc("@title:group Date", "Last Week");
-                break;
-            case 2:
-                retString = i18nc("@title:group Date", "Two Weeks Ago");
-                break;
-            case 3:
-                retString = i18nc("@title:group Date", "Three Weeks Ago");
-                break;
-            case 4:
-            case 5:
-                retString = i18nc("@title:group Date", "Earlier this Month");
-                break;
-            default:
-                Q_ASSERT(false);
-            }
-        } else {
-            const QDate lastMonthDate = currentDate.addMonths(-1);
-            if  (lastMonthDate.year() == modifiedDate.year() && lastMonthDate.month() == modifiedDate.month()) {
-                if (daysDistance == 1) {
-                    retString = modifiedTime.toString(i18nc("@title:group Date: %B is full month name in current locale, and %Y is full year number", "Yesterday (%B, %Y)"));
-                } else if (daysDistance <= 7) {
-                    retString = modifiedTime.toString(i18nc("@title:group The week day name: %A, %B is full month name in current locale, and %Y is full year number", "%A (%B, %Y)"));
-                } else if (daysDistance <= 7 * 2) {
-                    retString = modifiedTime.toString(i18nc("@title:group Date: %B is full month name in current locale, and %Y is full year number", "Last Week (%B, %Y)"));
-                } else if (daysDistance <= 7 * 3) {
-                    retString = modifiedTime.toString(i18nc("@title:group Date: %B is full month name in current locale, and %Y is full year number", "Two Weeks Ago (%B, %Y)"));
-                } else if (daysDistance <= 7 * 4) {
-                    retString = modifiedTime.toString(i18nc("@title:group Date: %B is full month name in current locale, and %Y is full year number", "Three Weeks Ago (%B, %Y)"));
-                } else {
-                    retString = modifiedTime.toString(i18nc("@title:group Date: %B is full month name in current locale, and %Y is full year number", "Earlier on %B, %Y"));
-                }
-            } else {
-                retString = modifiedTime.toString(i18nc("@title:group The month and year: %B is full month name in current locale, and %Y is full year number", "%B, %Y"));
-            }
-        }
-        break;
-    }
-
-    case KDirModel::Permissions: {
-        QString user;
-        QString group;
-        QString others;
-
-        QFileInfo info(item.url().pathOrUrl());
-
-        // set user string
-        if (info.permission(QFile::ReadUser)) {
-            user = i18nc("@item:intext Access permission, concatenated", "Read, ");
-        }
-        if (info.permission(QFile::WriteUser)) {
-            user += i18nc("@item:intext Access permission, concatenated", "Write, ");
-        }
-        if (info.permission(QFile::ExeUser)) {
-            user += i18nc("@item:intext Access permission, concatenated", "Execute, ");
-        }
-        user = user.isEmpty() ? i18nc("@item:intext Access permission, concatenated", "Forbidden") : user.mid(0, user.count() - 2);
-
-        // set group string
-        if (info.permission(QFile::ReadGroup)) {
-            group = i18nc("@item:intext Access permission, concatenated", "Read, ");
-        }
-        if (info.permission(QFile::WriteGroup)) {
-            group += i18nc("@item:intext Access permission, concatenated", "Write, ");
-        }
-        if (info.permission(QFile::ExeGroup)) {
-            group += i18nc("@item:intext Access permission, concatenated", "Execute, ");
-        }
-        group = group.isEmpty() ? i18nc("@item:intext Access permission, concatenated", "Forbidden") : group.mid(0, group.count() - 2);
-
-        // set permission string
-        if (info.permission(QFile::ReadOther)) {
-            others = i18nc("@item:intext Access permission, concatenated", "Read, ");
-        }
-        if (info.permission(QFile::WriteOther)) {
-            others += i18nc("@item:intext Access permission, concatenated", "Write, ");
-        }
-        if (info.permission(QFile::ExeOther)) {
-            others += i18nc("@item:intext Access permission, concatenated", "Execute, ");
-        }
-        others = others.isEmpty() ? i18nc("@item:intext Access permission, concatenated", "Forbidden") : others.mid(0, others.count() - 2);
-
-        retString = i18nc("@title:group Files and folders by permissions", "(User: %1) (Group: %2) (Others: %3)", user, group, others);
-        break;
-    }
-
-    case KDirModel::Owner:
-        retString = item.user();
-        break;
-
-    case KDirModel::Group:
-        retString = item.group();
-        break;
-
-    case KDirModel::Type:
-        retString = item.mimeComment();
-        break;
-
-    case DolphinModel::Version:
-        retString = "test";
-        break;
-    }
-
-    return retString;
-}
-
-QVariant DolphinModel::sortRoleData(const QModelIndex& index) const
-{
-    QVariant retVariant;
-
-    if (!index.isValid()) {
-        return retVariant;
-    }
-
-    const KDirModel *dirModel = qobject_cast<const KDirModel*>(index.model());
-    KFileItem item = dirModel->itemForIndex(index);
-
-    switch (index.column()) {
-    case KDirModel::Name: {
-        retVariant = data(index, KCategorizedSortFilterProxyModel::CategoryDisplayRole);
-        if (retVariant == i18nc("@title:group Name", m_others)) {
-            // assure that the "Others" group is always the last categorization
-            retVariant = QString('Z').append(QChar::ReplacementCharacter);
-        }
-        break;
-    }
-
-    case KDirModel::Size: {
-        const KIO::filesize_t fileSize = !item.isNull() ? item.size() : ~0U;
-        if (item.isDir()) {
-            retVariant = 0;
-        } else if (fileSize < 5242880) {
-            retVariant = 1;
-        } else if (fileSize < 10485760) {
-            retVariant = 2;
-        } else {
-            retVariant = 3;
-        }
-        break;
-    }
-
-    case KDirModel::ModifiedTime: {
-        KDateTime modifiedTime = item.time(KFileItem::ModificationTime);
-        modifiedTime = modifiedTime.toLocalZone();
-
-        const QDate currentDate = KDateTime::currentLocalDateTime().date();
-        const QDate modifiedDate = modifiedTime.date();
-
-        retVariant = -modifiedDate.daysTo(currentDate);
-        break;
-    }
-
-    case KDirModel::Permissions: {
-        QFileInfo info(item.url().pathOrUrl());
-
-        retVariant = -KDirSortFilterProxyModel::pointsForPermissions(info);
-        break;
-    }
-
-    case KDirModel::Owner:
-        retVariant = item.user();
-        break;
-
-    case KDirModel::Group:
-        retVariant = item.group();
-        break;
-
-    case KDirModel::Type:
-        if (item.isDir()) {
-            // when sorting we want folders to be placed first
-            retVariant = QString(); // krazy:exclude=nullstrassign
-        } else {
-            retVariant = item.mimeComment();
-        }
-        break;
-
-    default:
-        break;
-    }
-
-    return retVariant;
-}
diff --git a/src/views/dolphinmodel.h b/src/views/dolphinmodel.h
deleted file mode 100644 (file)
index 2f6d1f0..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
-  * This file is part of the KDE project
-  * Copyright (C) 2007 Rafael Fernández López <ereslibre@kde.org>
-  *
-  * This library is free software; you can redistribute it and/or
-  * modify it under the terms of the GNU Library General Public
-  * License as published by the Free Software Foundation; either
-  * version 2 of the License, or (at your option) any later version.
-  *
-  * This library 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
-  * Library General Public License for more details.
-  *
-  * You should have received a copy of the GNU Library General Public License
-  * along with this library; see the file COPYING.LIB.  If not, write to
-  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-  * Boston, MA 02110-1301, USA.
-*/
-
-#ifndef DOLPHINMODEL_H
-#define DOLPHINMODEL_H
-
-#include <KDirModel>
-#include <kversioncontrolplugin.h>
-#include <libdolphin_export.h>
-
-#include <QHash>
-#include <QPersistentModelIndex>
-
-class LIBDOLPHINPRIVATE_EXPORT DolphinModel : public KDirModel
-{
-    Q_OBJECT
-
-public:
-    enum AdditionalColumns {
-        LinkDest = KDirModel::ColumnCount,
-        LocalPathOrUrl,
-        // Assure that invisible columns are added as last entries:
-        Version,
-        ExtraColumnCount // Mandatory last entry
-    };
-
-    DolphinModel(QObject* parent = 0);
-    virtual ~DolphinModel();
-
-    virtual bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole);
-    virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const;
-    virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
-    virtual int columnCount(const QModelIndex& parent = QModelIndex()) const;
-
-    void clearVersionData();
-    bool hasVersionData() const;
-
-private slots:
-    void slotRowsRemoved(const QModelIndex& parent, int start, int end);
-
-private:
-    QVariant displayRoleData(const QModelIndex& index) const;
-    QVariant sortRoleData(const QModelIndex& index) const;
-
-private:
-    bool m_hasVersionData;
-    QHash<QPersistentModelIndex, KVersionControlPlugin::VersionState> m_revisionHash;
-
-    static const char* const m_others;
-};
-
-#endif // DOLPHINMODEL_H
diff --git a/src/views/dolphinsortfilterproxymodel.cpp b/src/views/dolphinsortfilterproxymodel.cpp
deleted file mode 100644 (file)
index a2d513b..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-/***************************************************************************
- *   Copyright (C) 2006-2010 by Peter Penz <peter.penz19@gmail.com>        *
- *   Copyright (C) 2006 by Dominic Battre <dominic@battre.de>              *
- *   Copyright (C) 2006 by Martin Pool <mbp@canonical.com>                 *
- *   Copyright (C) 2007 by Rafael Fernández López <ereslibre@kde.org>      *
- *                                                                         *
- *   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 program 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 program; if not, write to the                         *
- *   Free Software Foundation, Inc.,                                       *
- *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA            *
- ***************************************************************************/
-
-#include "dolphinsortfilterproxymodel.h"
-
-DolphinSortFilterProxyModel::DolphinSortFilterProxyModel(QObject* parent) :
-    KDirSortFilterProxyModel(parent),
-    m_sorting(DolphinView::SortByName),
-    m_sortOrder(Qt::AscendingOrder)
-{
-}
-
-DolphinSortFilterProxyModel::~DolphinSortFilterProxyModel()
-{
-}
-
-void DolphinSortFilterProxyModel::setSorting(DolphinView::Sorting sorting)
-{
-    m_sorting = sorting;
-    KDirSortFilterProxyModel::sort(static_cast<int>(m_sorting), m_sortOrder);
-}
-
-void DolphinSortFilterProxyModel::setSortOrder(Qt::SortOrder sortOrder)
-{
-    m_sortOrder = sortOrder;
-    KDirSortFilterProxyModel::sort(static_cast<int>(m_sorting), m_sortOrder);
-}
-
-void DolphinSortFilterProxyModel::setSortFoldersFirst(bool foldersFirst)
-{
-    if (foldersFirst != sortFoldersFirst()) {
-        KDirSortFilterProxyModel::setSortFoldersFirst(foldersFirst);
-
-        // We need to make sure that the files and folders are really resorted.
-        // Without the following two lines, QSortFilterProxyModel::sort(int column, Qt::SortOrder order)
-        // would do nothing because neither the column nor the sort order have changed.
-        // TODO: remove this hack if we find a better way to force the ProxyModel to re-sort the data.
-        const Qt::SortOrder tmpSortOrder = (m_sortOrder == Qt::AscendingOrder ? Qt::DescendingOrder : Qt::AscendingOrder);
-        KDirSortFilterProxyModel::sort(static_cast<int>(m_sorting), tmpSortOrder);
-
-        // Now comes the real sorting with the old column and sort order
-        KDirSortFilterProxyModel::sort(static_cast<int>(m_sorting), m_sortOrder);
-    }
-}
-
-void DolphinSortFilterProxyModel::sort(int column, Qt::SortOrder sortOrder)
-{
-    m_sorting = sortingForColumn(column);
-    m_sortOrder = sortOrder;
-
-    emit sortingRoleChanged();
-    KDirSortFilterProxyModel::sort(static_cast<int>(m_sorting), sortOrder);
-}
-
-DolphinView::Sorting DolphinSortFilterProxyModel::sortingForColumn(int column)
-{
-    Q_ASSERT(column >= 0);
-    Q_ASSERT(column <= DolphinView::MaxSortingEnum);
-    return static_cast<DolphinView::Sorting>(column);
-}
-
-#include "dolphinsortfilterproxymodel.moc"
diff --git a/src/views/dolphinsortfilterproxymodel.h b/src/views/dolphinsortfilterproxymodel.h
deleted file mode 100644 (file)
index a4770e8..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-/***************************************************************************
- *   Copyright (C) 2006-2010 by Peter Penz <peter.penz19@gmail.com>        *
- *                                                                         *
- *   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 program 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 program; if not, write to the                         *
- *   Free Software Foundation, Inc.,                                       *
- *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA            *
- ***************************************************************************/
-
-#ifndef DOLPHINSORTFILTERPROXYMODEL_H
-#define DOLPHINSORTFILTERPROXYMODEL_H
-
-#include <views/dolphinview.h>
-#include <kdirsortfilterproxymodel.h>
-#include <libdolphin_export.h>
-
-/**
- * @brief Acts as proxy model for DolphinModel to sort and filter
- *        KFileItems.
- *
- * Per default a natural sorting is done. This means that items like:
- * - item_10.png
- * - item_1.png
- * - item_2.png
- * are sorted like
- * - item_1.png
- * - item_2.png
- * - item_10.png
- */
-class LIBDOLPHINPRIVATE_EXPORT DolphinSortFilterProxyModel : public KDirSortFilterProxyModel
-{
-    Q_OBJECT
-
-public:
-    DolphinSortFilterProxyModel(QObject* parent = 0);
-    virtual ~DolphinSortFilterProxyModel();
-
-    void setSorting(DolphinView::Sorting sorting);
-    DolphinView::Sorting sorting() const;
-
-    void setSortOrder(Qt::SortOrder sortOrder);
-    Qt::SortOrder sortOrder() const;
-
-    void setSortFoldersFirst(bool foldersFirst);
-
-    /** @reimplemented */
-    virtual void sort(int column,
-                      Qt::SortOrder order = Qt::AscendingOrder);
-
-    /**
-     * Helper method to get the DolphinView::Sorting type for a given
-     * column \a column. If the column is smaller 0 or greater than the
-     * available columns, DolphinView::SortByName is returned.
-     */
-    static DolphinView::Sorting sortingForColumn(int column);
-
-signals:
-    void sortingRoleChanged();
-
-private:
-    DolphinView::Sorting m_sorting:16;
-    Qt::SortOrder m_sortOrder:16;
-};
-
-inline DolphinView::Sorting DolphinSortFilterProxyModel::sorting() const
-{
-    return m_sorting;
-}
-
-inline Qt::SortOrder DolphinSortFilterProxyModel::sortOrder() const
-{
-    return m_sortOrder;
-}
-
-#endif
diff --git a/src/views/dolphintreeview.cpp b/src/views/dolphintreeview.cpp
deleted file mode 100644 (file)
index 64b66aa..0000000
+++ /dev/null
@@ -1,530 +0,0 @@
-/***************************************************************************
- *   Copyright (C) 2010 by Peter Penz <peter.penz19@gmail.com>             *
- *   Copyright (C) 2008 by Simon St. James <kdedevel@etotheipiplusone.com> *
- *                                                                         *
- *   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 program 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 program; if not, write to the                         *
- *   Free Software Foundation, Inc.,                                       *
- *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA            *
- ***************************************************************************/
-
-#include "dolphintreeview.h"
-
-#include "dolphinmodel.h"
-
-#include <QApplication>
-#include <QEvent>
-#include <QHeaderView>
-#include <QMouseEvent>
-#include <QPainter>
-#include <QScrollBar>
-
-DolphinTreeView::DolphinTreeView(QWidget* parent) :
-    QTreeView(parent),
-    m_expandingTogglePressed(false),
-    m_useDefaultIndexAt(true),
-    m_ignoreScrollTo(false),
-    m_dropRect(),
-    m_band()
-{
-    setUniformRowHeights(true);
-}
-
-DolphinTreeView::~DolphinTreeView()
-{
-}
-
-void DolphinTreeView::keyboardSearch(const QString & search)
-{
-    const QModelIndex oldCurrent = currentIndex();
-    QTreeView::keyboardSearch(search);
-    if (currentIndex() != oldCurrent) {
-        // The current index has changed, but it is not selected yet.
-        // To select it, we call setCurrentIndex(...).
-        setCurrentIndex(currentIndex());
-    }
-}
-
-QRegion DolphinTreeView::visualRegionForSelection(const QItemSelection& selection) const
-{
-    // We have to make sure that the visualRect of each model index is inside the region.
-    // QTreeView::visualRegionForSelection does not do it right because it assumes implicitly
-    // that all visualRects have the same width, which is in general not the case here.
-    QRegion selectionRegion;
-    const QModelIndexList indexes = selection.indexes();
-
-    foreach(const QModelIndex& index, indexes) {
-        selectionRegion += visualRect(index);
-    }
-
-    return selectionRegion;
-}
-
-bool DolphinTreeView::acceptsDrop(const QModelIndex& index) const
-{
-    Q_UNUSED(index);
-    return false;
-}
-
-bool DolphinTreeView::event(QEvent* event)
-{
-    switch (event->type()) {
-    case QEvent::Polish:
-        m_useDefaultIndexAt = false;
-        break;
-    default:
-        break;
-    }
-    return QTreeView::event(event);
-}
-
-void DolphinTreeView::mousePressEvent(QMouseEvent* event)
-{
-    const QModelIndex current = currentIndex();
-    QTreeView::mousePressEvent(event);
-
-    m_expandingTogglePressed = isAboveExpandingToggle(event->pos());
-
-    const QModelIndex index = indexAt(event->pos());
-    const bool updateState = index.isValid() &&
-                             (index.column() == DolphinModel::Name) &&
-                             (event->button() == Qt::LeftButton);
-    if (updateState) {
-        setState(QAbstractItemView::DraggingState);
-    }
-
-    if (!index.isValid() || (index.column() != DolphinModel::Name)) {
-        const Qt::KeyboardModifiers mod = QApplication::keyboardModifiers();
-        if (!m_expandingTogglePressed && !(mod & Qt::ShiftModifier) && !(mod & Qt::ControlModifier)) {
-            clearSelection();
-        }
-
-        // Restore the current index, other columns are handled as viewport area.
-        // setCurrentIndex(...) implicitly calls scrollTo(...), which we want to ignore.
-        m_ignoreScrollTo = true;
-        selectionModel()->setCurrentIndex(current, QItemSelectionModel::Current);
-        m_ignoreScrollTo = false;
-
-        if ((event->button() == Qt::LeftButton) && !m_expandingTogglePressed) {
-            // Inform Qt about what we are doing - otherwise it starts dragging items around!
-            setState(DragSelectingState);
-            m_band.show = true;
-            // Incremental update data will not be useful - start from scratch.
-            m_band.ignoreOldInfo = true;
-            const QPoint scrollPos(horizontalScrollBar()->value(), verticalScrollBar()->value());
-            m_band.origin = event->pos()  + scrollPos;
-            m_band.destination = m_band.origin;
-            m_band.originalSelection = selectionModel()->selection();
-        }
-    }
-}
-
-void DolphinTreeView::mouseMoveEvent(QMouseEvent* event)
-{
-    if (m_expandingTogglePressed) {
-        // Per default QTreeView starts either a selection or a drag operation when dragging
-        // the expanding toggle button (Qt-issue - see TODO comment in DolphinIconsView::mousePressEvent()).
-        // Turn off this behavior in Dolphin to stay predictable:
-        setState(QAbstractItemView::NoState);
-        return;
-    }
-
-    if (m_band.show) {
-        const QPoint mousePos = event->pos();
-        const QModelIndex index = indexAt(mousePos);
-        if (!index.isValid()) {
-            // The destination of the selection rectangle is above the viewport. In this
-            // case QTreeView does no selection at all, which is not the wanted behavior
-            // in Dolphin. Select all items within the elastic band rectangle.
-            updateElasticBandSelection();
-        }
-
-        // TODO: Enable QTreeView::mouseMoveEvent(event) again, as soon
-        // as the Qt-issue #199631 has been fixed.
-        // QTreeView::mouseMoveEvent(event);
-        QAbstractItemView::mouseMoveEvent(event);
-        updateElasticBand();
-    } else {
-        // TODO: Enable QTreeView::mouseMoveEvent(event) again, as soon
-        // as the Qt-issue #199631 has been fixed.
-        // QTreeView::mouseMoveEvent(event);
-        QAbstractItemView::mouseMoveEvent(event);
-    }
-}
-
-void DolphinTreeView::mouseReleaseEvent(QMouseEvent* event)
-{
-    if (!m_expandingTogglePressed) {
-        const QModelIndex index = indexAt(event->pos());
-        if (index.isValid() && (index.column() == DolphinModel::Name)) {
-            QTreeView::mouseReleaseEvent(event);
-        } else {
-            // don't change the current index if the cursor is released
-            // above any other column than the name column, as the other
-            // columns act as viewport
-            const QModelIndex current = currentIndex();
-            QTreeView::mouseReleaseEvent(event);
-            selectionModel()->setCurrentIndex(current, QItemSelectionModel::Current);
-        }
-    }
-    m_expandingTogglePressed = false;
-
-    if (m_band.show) {
-        setState(NoState);
-        updateElasticBand();
-        m_band.show = false;
-    }
-}
-
-void DolphinTreeView::startDrag(Qt::DropActions supportedActions)
-{
-    Q_UNUSED(supportedActions);
-    m_band.show = false;
-}
-
-void DolphinTreeView::dragEnterEvent(QDragEnterEvent* event)
-{
-    Q_UNUSED(event);
-    if (m_band.show) {
-        updateElasticBand();
-        m_band.show = false;
-    }
-}
-
-void DolphinTreeView::dragMoveEvent(QDragMoveEvent* event)
-{
-    QTreeView::dragMoveEvent(event);
-
-    setDirtyRegion(m_dropRect);
-
-    const QModelIndex index = indexAt(event->pos());
-    if (acceptsDrop(index)) {
-        m_dropRect = visualRect(index);
-    } else {
-        m_dropRect.setSize(QSize()); // set invalid
-    }
-    setDirtyRegion(m_dropRect);
-}
-
-void DolphinTreeView::dragLeaveEvent(QDragLeaveEvent* event)
-{
-    QTreeView::dragLeaveEvent(event);
-    setDirtyRegion(m_dropRect);
-}
-
-void DolphinTreeView::paintEvent(QPaintEvent* event)
-{
-    QTreeView::paintEvent(event);
-    if (m_band.show) {
-        // The following code has been taken from QListView
-        // and adapted to DolphinDetailsView.
-        // (C) 1992-2007 Trolltech ASA
-        QStyleOptionRubberBand opt;
-        opt.initFrom(this);
-        opt.shape = QRubberBand::Rectangle;
-        opt.opaque = false;
-        opt.rect = elasticBandRect();
-
-        QPainter painter(viewport());
-        painter.save();
-        style()->drawControl(QStyle::CE_RubberBand, &opt, &painter);
-        painter.restore();
-    }
-}
-
-QModelIndex DolphinTreeView::indexAt(const QPoint& point) const
-{
-    // The blank portion of the name column counts as empty space
-    const QModelIndex index = QTreeView::indexAt(point);
-    const bool isAboveEmptySpace  = !m_useDefaultIndexAt &&
-                                    (index.column() == KDirModel::Name) &&
-                                    !visualRect(index).contains(point);
-    return isAboveEmptySpace ? QModelIndex() : index;
-}
-
-void DolphinTreeView::setSelection(const QRect& rect, QItemSelectionModel::SelectionFlags command)
-{
-    // We must override setSelection() as Qt calls it internally and when this happens
-    // we must ensure that the default indexAt() is used.
-    if (!m_band.show) {
-        m_useDefaultIndexAt = true;
-        QTreeView::setSelection(rect, command);
-        m_useDefaultIndexAt = false;
-    } else {
-        // Use our own elastic band selection algorithm
-        updateElasticBandSelection();
-    }
-}
-
-
-void DolphinTreeView::scrollTo(const QModelIndex & index, ScrollHint hint)
-{
-    if (!m_ignoreScrollTo) {
-        QTreeView::scrollTo(index, hint);
-    }
-}
-
-void DolphinTreeView::updateElasticBandSelection()
-{
-    if (!m_band.show) {
-        return;
-    }
-
-    // Ensure the elastic band itself is up-to-date, in
-    // case we are being called due to e.g. a drag event.
-    updateElasticBand();
-
-    // Clip horizontally to the name column, as some filenames will be
-    // longer than the column.  We don't clip vertically as origin
-    // may be above or below the current viewport area.
-    const int nameColumnX = header()->sectionPosition(DolphinModel::Name);
-    const int nameColumnWidth = header()->sectionSize(DolphinModel::Name);
-    QRect selRect = elasticBandRect().normalized();
-    QRect nameColumnArea(nameColumnX, selRect.y(), nameColumnWidth, selRect.height());
-    selRect = nameColumnArea.intersect(selRect).normalized();
-    // Get the last elastic band rectangle, expressed in viewpoint coordinates.
-    const QPoint scrollPos(horizontalScrollBar()->value(), verticalScrollBar()->value());
-    QRect oldSelRect = QRect(m_band.lastSelectionOrigin - scrollPos, m_band.lastSelectionDestination - scrollPos).normalized();
-
-    if (selRect.isNull()) {
-        selectionModel()->select(m_band.originalSelection, QItemSelectionModel::ClearAndSelect);
-        m_band.ignoreOldInfo = true;
-        return;
-    }
-
-    if (!m_band.ignoreOldInfo) {
-        // Do some quick checks to see if we can rule out the need to
-        // update the selection.
-        Q_ASSERT(uniformRowHeights());
-        QModelIndex dummyIndex = model()->index(0, 0);
-        if (!dummyIndex.isValid()) {
-            // No items in the model presumably.
-            return;
-        }
-
-        // If the elastic band does not cover the same rows as before, we'll
-        // need to re-check, and also invalidate the old item distances.
-        const int rowHeight = QTreeView::rowHeight(dummyIndex);
-        const bool coveringSameRows =
-            (selRect.top()    / rowHeight == oldSelRect.top()    / rowHeight) &&
-            (selRect.bottom() / rowHeight == oldSelRect.bottom() / rowHeight);
-        if (coveringSameRows) {
-            // Covering the same rows, but have we moved far enough horizontally
-            // that we might have (de)selected some other items?
-            const bool itemSelectionChanged =
-                ((selRect.left() > oldSelRect.left()) &&
-                 (selRect.left() > m_band.insideNearestLeftEdge)) ||
-                ((selRect.left() < oldSelRect.left()) &&
-                 (selRect.left() <= m_band.outsideNearestLeftEdge)) ||
-                ((selRect.right() < oldSelRect.right()) &&
-                 (selRect.left() >= m_band.insideNearestRightEdge)) ||
-                ((selRect.right() > oldSelRect.right()) &&
-                 (selRect.right() >= m_band.outsideNearestRightEdge));
-
-            if (!itemSelectionChanged) {
-                return;
-            }
-        }
-    } else {
-        // This is the only piece of optimization data that needs to be explicitly
-        // discarded.
-        m_band.lastSelectionOrigin = QPoint();
-        m_band.lastSelectionDestination = QPoint();
-        oldSelRect = selRect;
-    }
-
-    // Do the selection from scratch. Force a update of the horizontal distances info.
-    m_band.insideNearestLeftEdge   = nameColumnX + nameColumnWidth + 1;
-    m_band.insideNearestRightEdge  = nameColumnX - 1;
-    m_band.outsideNearestLeftEdge  = nameColumnX - 1;
-    m_band.outsideNearestRightEdge = nameColumnX + nameColumnWidth + 1;
-
-    // Include the old selection rect as well, so we can deselect
-    // items that were inside it but not in the new selRect.
-    const QRect boundingRect = selRect.united(oldSelRect).normalized();
-    if (boundingRect.isNull()) {
-        return;
-    }
-
-    // Get the index of the item in this row in the name column.
-    // TODO - would this still work if the columns could be re-ordered?
-    QModelIndex startIndex = QTreeView::indexAt(boundingRect.topLeft());
-    if (startIndex.parent().isValid()) {
-        startIndex = startIndex.parent().child(startIndex.row(), KDirModel::Name);
-    } else {
-        startIndex = model()->index(startIndex.row(), KDirModel::Name);
-    }
-    if (!startIndex.isValid()) {
-        selectionModel()->select(m_band.originalSelection, QItemSelectionModel::ClearAndSelect);
-        m_band.ignoreOldInfo = true;
-        return;
-    }
-
-   // Go through all indexes between the top and bottom of boundingRect, and
-   // update the selection.
-   const int verticalCutoff = boundingRect.bottom();
-   QModelIndex currIndex = startIndex;
-   QModelIndex lastIndex;
-   bool allItemsInBoundDone = false;
-
-   // Calling selectionModel()->select(...) for each item that needs to be
-   // toggled is slow as each call emits selectionChanged(...) so store them
-   // and do the selection toggle in one batch.
-   QItemSelection itemsToToggle;
-   // QItemSelection's deal with continuous ranges of indexes better than
-   // single indexes, so try to portion items that need to be toggled into ranges.
-   bool formingToggleIndexRange = false;
-   QModelIndex toggleIndexRangeBegin = QModelIndex();
-
-   do {
-       QRect currIndexRect = visualRect(currIndex);
-
-        // Update some optimization info as we go.
-       const int cr = currIndexRect.right();
-       const int cl = currIndexRect.left();
-       const int sl = selRect.left();
-       const int sr = selRect.right();
-       // "The right edge of the name is outside of the rect but nearer than m_outsideNearestLeft", etc
-       if ((cr < sl && cr > m_band.outsideNearestLeftEdge)) {
-           m_band.outsideNearestLeftEdge = cr;
-       }
-       if ((cl > sr && cl < m_band.outsideNearestRightEdge)) {
-           m_band.outsideNearestRightEdge = cl;
-       }
-       if ((cl >= sl && cl <= sr && cl > m_band.insideNearestRightEdge)) {
-           m_band.insideNearestRightEdge = cl;
-       }
-       if ((cr >= sl && cr <= sr && cr < m_band.insideNearestLeftEdge)) {
-           m_band.insideNearestLeftEdge = cr;
-       }
-
-       bool currentlySelected = selectionModel()->isSelected(currIndex);
-       bool originallySelected = m_band.originalSelection.contains(currIndex);
-       bool intersectsSelectedRect = currIndexRect.intersects(selRect);
-       bool shouldBeSelected = (intersectsSelectedRect && !originallySelected) || (!intersectsSelectedRect && originallySelected);
-       bool needToToggleItem = (currentlySelected && !shouldBeSelected) || (!currentlySelected && shouldBeSelected);
-       if (needToToggleItem && !formingToggleIndexRange) {
-            toggleIndexRangeBegin = currIndex;
-            formingToggleIndexRange = true;
-       }
-
-       // NOTE: indexBelow actually walks up and down expanded trees for us.
-       QModelIndex nextIndex = indexBelow(currIndex);
-       allItemsInBoundDone = !nextIndex.isValid() || currIndexRect.top() > verticalCutoff;
-
-       const bool commitToggleIndexRange = formingToggleIndexRange &&
-                                           (!needToToggleItem ||
-                                            allItemsInBoundDone ||
-                                            currIndex.parent() != toggleIndexRangeBegin.parent());
-       if (commitToggleIndexRange) {
-           formingToggleIndexRange = false;
-            // If this is the last item in the bounds and it is also the beginning of a range,
-            // don't toggle lastIndex - it will already have been dealt with.
-           if (!allItemsInBoundDone || toggleIndexRangeBegin != currIndex) {
-               itemsToToggle.select(toggleIndexRangeBegin, lastIndex);
-           }
-            // Need to start a new range immediately with currIndex?
-           if (needToToggleItem) {
-               toggleIndexRangeBegin = currIndex;
-               formingToggleIndexRange = true;
-           }
-           if (allItemsInBoundDone && needToToggleItem) {
-                // Toggle the very last item in the bounds.
-               itemsToToggle.select(currIndex, currIndex);
-           }
-       }
-
-       // Next item
-       lastIndex = currIndex;
-       currIndex = nextIndex;
-    } while (!allItemsInBoundDone);
-
-
-    selectionModel()->select(itemsToToggle, QItemSelectionModel::Toggle);
-
-    m_band.lastSelectionOrigin = m_band.origin;
-    m_band.lastSelectionDestination = m_band.destination;
-    m_band.ignoreOldInfo = false;
-}
-
-void DolphinTreeView::updateElasticBand()
-{
-    if (m_band.show) {
-        QRect dirtyRegion(elasticBandRect());
-        const QPoint scrollPos(horizontalScrollBar()->value(), verticalScrollBar()->value());
-        m_band.destination = viewport()->mapFromGlobal(QCursor::pos()) + scrollPos;
-        // Going above the (logical) top-left of the view causes complications during selection;
-        // we may as well prevent it.
-        if (m_band.destination.y() < 0) {
-            m_band.destination.setY(0);
-        }
-        if (m_band.destination.x() < 0) {
-            m_band.destination.setX(0);
-        }
-        dirtyRegion = dirtyRegion.united(elasticBandRect());
-        setDirtyRegion(dirtyRegion);
-    }
-}
-
-QRect DolphinTreeView::elasticBandRect() const
-{
-    const QPoint scrollPos(horizontalScrollBar()->value(), verticalScrollBar()->value());
-
-    const QPoint topLeft = m_band.origin - scrollPos;
-    const QPoint bottomRight = m_band.destination - scrollPos;
-    return QRect(topLeft, bottomRight).normalized();
-}
-
-bool DolphinTreeView::isAboveExpandingToggle(const QPoint& pos) const
-{
-    // QTreeView offers no public API to get the information whether an index has an
-    // expanding toggle and what boundaries the toggle has. The following approach
-    // also assumes a toggle for file items.
-    if (itemsExpandable()) {
-        const QModelIndex index = QTreeView::indexAt(pos);
-        if (index.isValid() && (index.column() == KDirModel::Name)) {
-            QRect rect = visualRect(index);
-            const int toggleSize = rect.height();
-            if (isRightToLeft()) {
-                rect.moveRight(rect.right());
-            } else {
-                rect.moveLeft(rect.x() - toggleSize);
-            }
-            rect.setWidth(toggleSize);
-
-            QStyleOption opt;
-            opt.initFrom(this);
-            opt.rect = rect;
-            rect = style()->subElementRect(QStyle::SE_TreeViewDisclosureItem, &opt, this);
-
-            return rect.contains(pos);
-        }
-    }
-    return false;
-}
-
-DolphinTreeView::ElasticBand::ElasticBand() :
-    show(false),
-    origin(),
-    destination(),
-    lastSelectionOrigin(),
-    lastSelectionDestination(),
-    ignoreOldInfo(true),
-    outsideNearestLeftEdge(0),
-    outsideNearestRightEdge(0),
-    insideNearestLeftEdge(0),
-    insideNearestRightEdge(0)
-{
-}
-
-#include "dolphintreeview.moc"
diff --git a/src/views/dolphintreeview.h b/src/views/dolphintreeview.h
deleted file mode 100644 (file)
index c037d41..0000000
+++ /dev/null
@@ -1,134 +0,0 @@
-/***************************************************************************
- *   Copyright (C) 2010 by Peter Penz <peter.penz19@gmail.com>             *
- *   Copyright (C) 2008 by Simon St. James <kdedevel@etotheipiplusone.com> *
- *                                                                         *
- *   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 program 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 program; if not, write to the                         *
- *   Free Software Foundation, Inc.,                                       *
- *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA            *
- ***************************************************************************/
-
-#ifndef DOLPHINTREEVIEW_H
-#define DOLPHINTREEVIEW_H
-
-#include <QTreeView>
-#include <libdolphin_export.h>
-
-/**
- * @brief Extends QTreeView by a custom selection- and hover-mechanism.
- *
- * QTreeView does not respect the width of a cell for the hover-feedback
- * and when selecting items. DolphinTreeView improves this by respecting the
- * content-width of the first column. The selection-mechanism also
- * respects the content-width.
- */
-class LIBDOLPHINPRIVATE_EXPORT DolphinTreeView : public QTreeView
-{
-    Q_OBJECT
-
-public:
-    explicit DolphinTreeView(QWidget* parent = 0);
-    virtual ~DolphinTreeView();
-
-    virtual QModelIndex indexAt (const QPoint& point) const;
-    virtual void keyboardSearch(const QString & search);
-    virtual QRegion visualRegionForSelection(const QItemSelection& selection) const;
-
-protected:
-    /**
-     * @return True, if the item with the index \p index accepts a drop. In this
-     *         case a visual feedback for the user is given during dragging. Per
-     *         default false is returned.
-     */
-    virtual bool acceptsDrop(const QModelIndex& index) const;
-
-    virtual bool event(QEvent* event);
-    virtual void mousePressEvent(QMouseEvent* event);
-    virtual void mouseMoveEvent(QMouseEvent* event);
-    virtual void mouseReleaseEvent(QMouseEvent* event);
-    virtual void startDrag(Qt::DropActions supportedActions);
-    virtual void dragEnterEvent(QDragEnterEvent* event);
-    virtual void dragMoveEvent(QDragMoveEvent* event);
-    virtual void dragLeaveEvent(QDragLeaveEvent* event);
-    virtual void paintEvent(QPaintEvent* event);
-    virtual void setSelection(const QRect& rect, QItemSelectionModel::SelectionFlags command);
-    virtual void scrollTo(const QModelIndex& index, ScrollHint hint = EnsureVisible);
-
-private slots:
-    /**
-     * If the elastic band is currently shown, update the elastic band based on
-     * the current mouse position and ensure that the selection is the set of items
-     * intersecting it.
-     */
-    void updateElasticBandSelection();
-
-    /**
-     * Updates the destination \a destination from
-     * the elastic band to the current mouse position and triggers
-     * an update.
-     */
-    void updateElasticBand();
-
-    /**
-     * Returns the rectangle for the elastic band dependent from the
-     * origin \a origin, the current destination
-     * \a destination and the viewport position.
-     */
-    QRect elasticBandRect() const;
-
-private:
-    /**
-     * Returns true, if \a pos is within the expanding toggle of a tree.
-     */
-    bool isAboveExpandingToggle(const QPoint& pos) const;
-
-private:
-    bool m_expandingTogglePressed;
-    bool m_useDefaultIndexAt; // true, if QTreeView::indexAt() should be used
-    bool m_ignoreScrollTo;    // true if calls to scrollTo(...) should do nothing.
-
-    QRect m_dropRect;
-
-    struct ElasticBand
-    {
-        ElasticBand();
-
-        // Elastic band origin and destination coordinates are relative to t
-        // he origin of the view, not the viewport.
-        bool show;
-        QPoint origin;
-        QPoint destination;
-
-        // Optimization mechanisms for use with elastic band selection.
-        // Basically, allow "incremental" updates to the selection based
-        // on the last elastic band shape.
-        QPoint lastSelectionOrigin;
-        QPoint lastSelectionDestination;
-
-        // If true, compute the set of selected elements from scratch (slower)
-        bool ignoreOldInfo;
-
-        // Edges of the filenames that are closest to the edges of oldSelectionRect.
-        // Used to decide whether horizontal changes in the elastic band are likely
-        // to require us to re-check which items are selected.
-        int outsideNearestLeftEdge;
-        int outsideNearestRightEdge;
-        int insideNearestLeftEdge;
-        int insideNearestRightEdge;
-        // The set of items that were selected at the time this band was shown.
-        // NOTE: Unless CTRL was pressed when the band was created, this is always empty.
-        QItemSelection originalSelection;
-    } m_band;
-};
-
-#endif
index 681ce74f7fe352f4305ee439069984bb2e2d4106..bcc682876c17e39cc63084f89074cf2d7fff1e06 100644 (file)
 #include <KFileItem>
 #include <KFileItemListProperties>
 #include <KLocale>
+#include <kitemviews/kfileitemmodel.h>
+#include <kitemviews/kfileitemlistview.h>
+#include <kitemviews/kitemlistview.h>
+#include <kitemviews/kitemlistcontroller.h>
 #include <KIO/DeleteJob>
 #include <KIO/NetAccess>
 #include <KIO/PreviewJob>
 
 #include "additionalinfoaccessor.h"
 #include "dolphindirlister.h"
-#include "dolphinmodel.h"
-#include "dolphincolumnviewcontainer.h"
-#include "dolphinviewcontroller.h"
-#include "dolphindetailsview.h"
-#include "dolphinfileitemdelegate.h"
 #include "dolphinnewfilemenuobserver.h"
-#include "dolphinsortfilterproxymodel.h"
 #include "dolphin_detailsmodesettings.h"
-#include "dolphiniconsview.h"
 #include "dolphin_generalsettings.h"
-#include "draganddrophelper.h"
 #include "renamedialog.h"
 #include "settings/dolphinsettings.h"
 #include "viewmodecontroller.h"
 #include "viewproperties.h"
 #include "zoomlevelinfo.h"
-#include "dolphindetailsviewexpander.h"
+
+// TODO:
+#include "dolphinitemlistcontainer.h"
+
+namespace {
+    const int MaxModeEnum = DolphinView::CompactView;
+    const int MaxSortingEnum = DolphinView::SortByPath;
+};
 
 DolphinView::DolphinView(const KUrl& url, QWidget* parent) :
     QWidget(parent),
     m_active(true),
-    m_showPreview(false),
-    m_storedCategorizedSorting(false),
     m_tabsForFiles(false),
-    m_isContextMenuOpen(false),
     m_assureVisibleCurrentIndex(false),
     m_expanderActive(false),
     m_isFolderWritable(true),
+    m_url(url),
     m_mode(DolphinView::IconsView),
+    m_additionalInfoList(),
     m_topLayout(0),
-    m_dolphinViewController(0),
-    m_viewModeController(0),
-    m_viewAccessor(),
+    m_dirLister(0),
+    m_container(0),
     m_selectionChangedTimer(0),
     m_activeItemUrl(),
     m_restoredContentsPosition(),
@@ -94,12 +95,12 @@ DolphinView::DolphinView(const KUrl& url, QWidget* parent) :
     m_topLayout->setSpacing(0);
     m_topLayout->setMargin(0);
 
-    m_dolphinViewController = new DolphinViewController(this);
+    //m_dolphinViewController = new DolphinViewController(this);
 
-    m_viewModeController = new ViewModeController(this);
-    m_viewModeController->setUrl(url);
+    //m_viewModeController = new ViewModeController(this);
+    //m_viewModeController->setUrl(url);
 
-    connect(m_viewModeController, SIGNAL(urlChanged(const KUrl&)),
+    /*connect(m_viewModeController, SIGNAL(urlChanged(const KUrl&)),
             this, SIGNAL(urlChanged(const KUrl&)));
 
     connect(m_dolphinViewController, SIGNAL(requestContextMenu(const QPoint&, const QList<QAction*>&)),
@@ -112,20 +113,20 @@ DolphinView::DolphinView(const KUrl& url, QWidget* parent) :
             this, SLOT(updateSortOrder(Qt::SortOrder)));
     connect(m_dolphinViewController, SIGNAL(sortFoldersFirstChanged(bool)),
             this, SLOT(updateSortFoldersFirst(bool)));
-    connect(m_dolphinViewController, SIGNAL(additionalInfoChanged(const KFileItemDelegate::InformationList&)),
-            this, SLOT(updateAdditionalInfo(const KFileItemDelegate::InformationList&)));
-    connect(m_dolphinViewController, SIGNAL(itemTriggered(const KFileItem&)),
-            this, SLOT(triggerItem(const KFileItem&)));
-    connect(m_dolphinViewController, SIGNAL(tabRequested(const KUrl&)),
-            this, SIGNAL(tabRequested(const KUrl&)));
-    connect(m_dolphinViewController, SIGNAL(activated()),
+    connect(m_dolphinViewController, SIGNAL(additionalInfoChanged(const QList<DolphinView::AdditionalInfo>&)),
+            this, SLOT(updateAdditionalInfo(const QList<DolphinView::AdditionalInfo>&)));*/
+    //connect(m_dolphinViewController, SIGNAL(itemTriggered(const KFileItem&)),
+    //        this, SLOT(triggerItem(const KFileItem&)));
+    //connect(m_dolphinViewController, SIGNAL(tabRequested(const KUrl&)),
+    //        this, SIGNAL(tabRequested(const KUrl&)));
+    /*connect(m_dolphinViewController, SIGNAL(activated()),
             this, SLOT(activate()));
     connect(m_dolphinViewController, SIGNAL(itemEntered(const KFileItem&)),
             this, SLOT(showHoverInformation(const KFileItem&)));
     connect(m_dolphinViewController, SIGNAL(viewportEntered()),
             this, SLOT(clearHoverInformation()));
     connect(m_dolphinViewController, SIGNAL(urlChangeRequested(KUrl)),
-            this, SLOT(slotUrlChangeRequested(KUrl)));
+            this, SLOT(slotUrlChangeRequested(KUrl)));*/
 
     // When a new item has been created by the "Create New..." menu, the item should
     // get selected and it must be assured that the item will get visible. As the
@@ -139,8 +140,38 @@ DolphinView::DolphinView(const KUrl& url, QWidget* parent) :
     connect(m_selectionChangedTimer, SIGNAL(timeout()),
             this, SLOT(emitSelectionChangedSignal()));
 
+    m_dirLister = new DolphinDirLister(this);
+    m_dirLister->setAutoUpdate(true);
+    m_dirLister->setDelayedMimeTypes(true);
+
+    connect(m_dirLister, SIGNAL(redirection(KUrl,KUrl)), this, SLOT(slotRedirection(KUrl,KUrl)));
+    connect(m_dirLister, SIGNAL(started(KUrl)),          this, SLOT(slotDirListerStarted(KUrl)));
+    connect(m_dirLister, SIGNAL(completed()),            this, SLOT(slotDirListerCompleted()));
+    connect(m_dirLister, SIGNAL(refreshItems(const QList<QPair<KFileItem,KFileItem>>&)),
+            this, SLOT(slotRefreshItems()));
+
+    connect(m_dirLister, SIGNAL(clear()),                      this, SIGNAL(itemCountChanged()));
+    connect(m_dirLister, SIGNAL(newItems(KFileItemList)),      this, SIGNAL(itemCountChanged()));
+    connect(m_dirLister, SIGNAL(infoMessage(const QString&)),  this, SIGNAL(infoMessage(const QString&)));
+    connect(m_dirLister, SIGNAL(errorMessage(const QString&)), this, SIGNAL(infoMessage(const QString&)));
+    connect(m_dirLister, SIGNAL(percent(int)),                 this, SIGNAL(pathLoadingProgress(int)));
+    connect(m_dirLister, SIGNAL(urlIsFileError(const KUrl&)),  this, SIGNAL(urlIsFileError(const KUrl&)));
+    connect(m_dirLister, SIGNAL(itemsDeleted(const KFileItemList&)), this, SIGNAL(itemCountChanged()));
+
+    m_container = new DolphinItemListContainer(m_dirLister, this);
+    QHash<QByteArray, int> visibleRoles;
+    visibleRoles.insert("name", 0);
+    m_container->setVisibleRoles(visibleRoles);
+
+    KItemListController* controller = m_container->controller();
+    connect(controller, SIGNAL(itemClicked(int, Qt::MouseButton)),
+            this, SLOT(slotItemClicked(int, Qt::MouseButton)));
+    connect(controller, SIGNAL(itemExpansionToggleClicked(int)), this, SLOT(slotItemExpansionToggleClicked(int)));
+
     applyViewProperties();
-    m_topLayout->addWidget(m_viewAccessor.layoutTarget());
+    m_topLayout->addWidget(m_container);
+
+    loadDirectory(url);
 }
 
 DolphinView::~DolphinView()
@@ -149,17 +180,7 @@ DolphinView::~DolphinView()
 
 KUrl DolphinView::url() const
 {
-    return m_viewModeController->url();
-}
-
-KUrl DolphinView::rootUrl() const
-{
-    const KUrl viewUrl = url();
-    const KUrl root = m_viewAccessor.rootUrl();
-    if (root.isEmpty() || !root.isParentOf(viewUrl)) {
-        return viewUrl;
-    }
-    return root;
+    return m_url;
 }
 
 void DolphinView::setActive(bool active)
@@ -175,21 +196,26 @@ void DolphinView::setActive(bool active)
         color.setAlpha(150);
     }
 
-    QWidget* viewport = m_viewAccessor.itemView()->viewport();
-    QPalette palette;
-    palette.setColor(viewport->backgroundRole(), color);
-    viewport->setPalette(palette);
+    /*QAbstractItemView* view = m_viewAccessor.itemView();
+    QWidget* viewport = view ? view->viewport() : 0;
+    if (viewport) {
+        QPalette palette;
+        palette.setColor(viewport->backgroundRole(), color);
+        viewport->setPalette(palette);
+    }*/
 
     update();
 
     if (active) {
-        m_viewAccessor.itemView()->setFocus();
+        //if (view) {
+        //    view->setFocus();
+        //}
         emit activated();
         emitSelectionChangedSignal();
         emit writeStateChanged(m_isFolderWritable);
     }
 
-    m_viewModeController->indicateActivationChange(active);
+    //m_viewModeController->indicateActivationChange(active);
 }
 
 bool DolphinView::isActive() const
@@ -199,49 +225,13 @@ bool DolphinView::isActive() const
 
 void DolphinView::setMode(Mode mode)
 {
-    if (mode == m_mode) {
-        return; // the wished mode is already set
-    }
+    if (mode != m_mode) {
+        ViewProperties props(url());
+        props.setViewMode(mode);
+        props.save();
 
-    const int oldZoomLevel = m_viewModeController->zoomLevel();
-    m_mode = mode;
-
-    // remember the currently selected items, so that they will
-    // be restored after reloading the directory
-    m_selectedItems = selectedItems();
-
-    const bool hasFocus = m_viewAccessor.itemView()->hasFocus();
-    deleteView();
-
-    const KUrl viewPropsUrl = rootUrl();
-    ViewProperties props(viewPropsUrl);
-    props.setViewMode(m_mode);
-    createView();
-
-    if (hasFocus) {
-        m_viewAccessor.itemView()->setFocus();
-    }
-
-    // the file item delegate has been recreated, apply the current
-    // additional information manually
-    const KFileItemDelegate::InformationList infoList = props.additionalInfo();
-    m_viewAccessor.itemDelegate()->setShowInformation(infoList);
-    emit additionalInfoChanged();
-
-    // Not all view modes support categorized sorting. Adjust the sorting model
-    // if changing the view mode results in a change of the categorized sorting
-    // capabilities.
-    m_storedCategorizedSorting = props.categorizedSorting();
-    const bool categorized = m_storedCategorizedSorting && supportsCategorizedSorting();
-    if (categorized != m_viewAccessor.proxyModel()->isCategorizedModel()) {
-        m_viewAccessor.proxyModel()->setCategorizedModel(categorized);
-        emit categorizedSortingChanged();
+        applyViewProperties();
     }
-
-    emit modeChanged();
-
-    updateZoomLevel(oldZoomLevel);
-    loadDirectory(viewPropsUrl);
 }
 
 DolphinView::Mode DolphinView::mode() const
@@ -249,46 +239,30 @@ DolphinView::Mode DolphinView::mode() const
     return m_mode;
 }
 
-bool DolphinView::showPreview() const
+bool DolphinView::previewsShown() const
 {
-    return m_showPreview;
+    return m_container->previewsShown();
 }
 
-bool DolphinView::showHiddenFiles() const
+bool DolphinView::hiddenFilesShown() const
 {
-    return m_viewAccessor.dirLister()->showingDotFiles();
+    return m_dirLister->showingDotFiles();
 }
 
 bool DolphinView::categorizedSorting() const
 {
-    // If all view modes would support categorized sorting, returning
-    // m_viewAccessor.proxyModel()->isCategorizedModel() would be the way to go. As
-    // currently only the icons view supports caterized sorting, we remember
-    // the stored view properties state in m_storedCategorizedSorting and
-    // return this state. The application takes care to disable the corresponding
-    // checkbox by checking DolphinView::supportsCategorizedSorting() to indicate
-    // that this setting is not applied to the current view mode.
-    return m_storedCategorizedSorting;
-}
-
-bool DolphinView::supportsCategorizedSorting() const
-{
-    return m_viewAccessor.supportsCategorizedSorting();
-}
-
-KFileItem DolphinView::rootItem() const
-{
-    return m_viewAccessor.dirLister()->rootItem();
+    return false; //m_storedCategorizedSorting;
 }
 
 KFileItemList DolphinView::items() const
 {
-    return m_viewAccessor.dirLister()->items();
+    return m_dirLister->items();
 }
 
 KFileItemList DolphinView::selectedItems() const
 {
-    KFileItemList itemList;
+    return KFileItemList();
+/*    KFileItemList itemList;
     const QAbstractItemView* view = m_viewAccessor.itemView();
     if (!view) {
         return itemList;
@@ -304,17 +278,18 @@ KFileItemList DolphinView::selectedItems() const
         }
     }
 
-    return itemList;
+    return itemList;*/
 }
 
 int DolphinView::selectedItemsCount() const
 {
-    const QAbstractItemView* view = m_viewAccessor.itemView();
+    return 0;
+    /*const QAbstractItemView* view = m_viewAccessor.itemView();
     if (!view) {
         return 0;
     }
 
-    return view->selectionModel()->selectedIndexes().count();
+    return view->selectionModel()->selectedIndexes().count();*/
 }
 
 void DolphinView::markUrlsAsSelected(const QList<KUrl>& urls)
@@ -327,30 +302,27 @@ void DolphinView::markUrlsAsSelected(const QList<KUrl>& urls)
 
 void DolphinView::setItemSelectionEnabled(const QRegExp& pattern, bool enabled)
 {
-    const QItemSelection matchingIndexes = childrenMatchingPattern(QModelIndex(), pattern);
+    Q_UNUSED(pattern);
+    Q_UNUSED(enabled);
+    /*const QItemSelection matchingIndexes = childrenMatchingPattern(QModelIndex(), pattern);
     const QItemSelectionModel::SelectionFlags command = enabled
                                                       ? QItemSelectionModel::Select
                                                       : QItemSelectionModel::Deselect;
-    m_viewAccessor.itemView()->selectionModel()->select(matchingIndexes, command);
+    m_viewAccessor.itemView()->selectionModel()->select(matchingIndexes, command);*/
 }
 
 void DolphinView::setZoomLevel(int level)
 {
-    if (level < ZoomLevelInfo::minimumLevel()) {
-        level = ZoomLevelInfo::minimumLevel();
-    } else if (level > ZoomLevelInfo::maximumLevel()) {
-        level = ZoomLevelInfo::maximumLevel();
-    }
-
-    if (level != zoomLevel()) {
-        m_viewModeController->setZoomLevel(level);
-        emit zoomLevelChanged(level);
+    const int oldZoomLevel = zoomLevel();
+    m_container->setZoomLevel(level);
+    if (zoomLevel() != oldZoomLevel) {
+        emit zoomLevelChanged(zoomLevel(), oldZoomLevel);
     }
 }
 
 int DolphinView::zoomLevel() const
 {
-    return m_viewModeController->zoomLevel();
+    return m_container->zoomLevel();
 }
 
 void DolphinView::setSorting(Sorting sorting)
@@ -362,7 +334,8 @@ void DolphinView::setSorting(Sorting sorting)
 
 DolphinView::Sorting DolphinView::sorting() const
 {
-    return m_viewAccessor.proxyModel()->sorting();
+    return DolphinView::SortByName;
+    //return m_viewAccessor.proxyModel()->sorting();
 }
 
 void DolphinView::setSortOrder(Qt::SortOrder order)
@@ -374,7 +347,7 @@ void DolphinView::setSortOrder(Qt::SortOrder order)
 
 Qt::SortOrder DolphinView::sortOrder() const
 {
-    return m_viewAccessor.proxyModel()->sortOrder();
+    return Qt::AscendingOrder; // m_viewAccessor.proxyModel()->sortOrder();
 }
 
 void DolphinView::setSortFoldersFirst(bool foldersFirst)
@@ -386,26 +359,25 @@ void DolphinView::setSortFoldersFirst(bool foldersFirst)
 
 bool DolphinView::sortFoldersFirst() const
 {
-    return m_viewAccessor.proxyModel()->sortFoldersFirst();
+    return true; // m_viewAccessor.proxyModel()->sortFoldersFirst();
 }
 
-void DolphinView::setAdditionalInfo(KFileItemDelegate::InformationList info)
+void DolphinView::setAdditionalInfoList(const QList<AdditionalInfo>& info)
 {
-    const KUrl viewPropsUrl = rootUrl();
-    ViewProperties props(viewPropsUrl);
-    props.setAdditionalInfo(info);
-    m_viewAccessor.itemDelegate()->setShowInformation(info);
+    const QList<AdditionalInfo> previousList = info;
 
-    emit additionalInfoChanged();
+    ViewProperties props(url());
+    props.setAdditionalInfoList(info);
 
-    if (m_viewAccessor.reloadOnAdditionalInfoChange()) {
-        loadDirectory(viewPropsUrl);
-    }
+    m_additionalInfoList = info;
+    applyAdditionalInfoListToView();
+
+    emit additionalInfoListChanged(m_additionalInfoList, previousList);
 }
 
-KFileItemDelegate::InformationList DolphinView::additionalInfo() const
+QList<DolphinView::AdditionalInfo> DolphinView::additionalInfoList() const
 {
-    return m_viewAccessor.itemDelegate()->showInformation();
+    return m_additionalInfoList;
 }
 
 void DolphinView::reload()
@@ -424,16 +396,15 @@ void DolphinView::reload()
 
 void DolphinView::stopLoading()
 {
-    m_viewAccessor.dirLister()->stop();
+    m_dirLister->stop();
 }
 
 void DolphinView::refresh()
 {
     const bool oldActivationState = m_active;
-    const int oldZoomLevel = m_viewModeController->zoomLevel();
+    const int oldZoomLevel = zoomLevel();
     m_active = true;
 
-    createView();
     applyViewProperties();
     reload();
 
@@ -443,19 +414,20 @@ void DolphinView::refresh()
 
 void DolphinView::setNameFilter(const QString& nameFilter)
 {
-    m_viewModeController->setNameFilter(nameFilter);
+    Q_UNUSED(nameFilter);
+    //m_viewModeController->setNameFilter(nameFilter);
 }
 
 QString DolphinView::nameFilter() const
 {
-    return m_viewModeController->nameFilter();
+    return QString(); //m_viewModeController->nameFilter();
 }
 
 void DolphinView::calculateItemCount(int& fileCount,
                                      int& folderCount,
                                      KIO::filesize_t& totalFileSize) const
 {
-    foreach (const KFileItem& item, m_viewAccessor.dirLister()->items()) {
+    foreach (const KFileItem& item, m_dirLister->items()) {
         if (item.isDir()) {
             ++folderCount;
         } else {
@@ -526,34 +498,31 @@ QString DolphinView::statusBarText() const
 
 QList<QAction*> DolphinView::versionControlActions(const KFileItemList& items) const
 {
-    return m_dolphinViewController->versionControlActions(items);
+    Q_UNUSED(items);
+    return QList<QAction*>(); //m_dolphinViewController->versionControlActions(items);
 }
 
 void DolphinView::setUrl(const KUrl& url)
 {
-    if (m_viewModeController->url() == url) {
+    if (url == m_url) {
         return;
     }
 
-    const bool hadSelection = hasSelection();
-
-    // The selection model and directory lister might change in the case of the column view:
-    disconnectViewAccessor();
+    emit urlAboutToBeChanged(url);
 
+    const bool hadSelection = hasSelection();
     m_newFileNames.clear();
+    m_url = url;
 
-    m_viewModeController->setUrl(url); // emits urlChanged, which we forward
-    m_viewAccessor.prepareUrlChange(url);
+    // It is important to clear the items from the model before
+    // applying the view properties, otherwise expensive operations
+    // might be done on the existing items although they get cleared
+    // anyhow afterwards by loadDirectory().
+    fileItemModel()->clear();
     applyViewProperties();
-
-    // When changing the URL there is no need to keep the version
-    // data of the previous URL.
-    m_viewAccessor.dirModel()->clearVersionData();
-
-    // Reconnect to the (probably) new selection model and directory lister
-    connectViewAccessor();
     loadDirectory(url);
 
+    emit urlChanged(url);
     if (hadSelection || hasSelection()) {
         emitSelectionChangedSignal();
     }
@@ -561,12 +530,12 @@ void DolphinView::setUrl(const KUrl& url)
 
 void DolphinView::selectAll()
 {
-    m_viewAccessor.itemView()->selectAll();
+    //m_viewAccessor.itemView()->selectAll();
 }
 
 void DolphinView::invertSelection()
 {
-    // Implementation note: Using selectionModel->select(selection, QItemSelectionModel::Toggle) does not
+/*    // Implementation note: Using selectionModel->select(selection, QItemSelectionModel::Toggle) does not
     // work, as QItemSelectionModel::hasSelection() provides invalid values in this case. This might be a Qt-issue -
     // when changing the implementation with an updated Qt-version don't forget to run the Dolphin-unit-tests that
     // verify this usecase.
@@ -583,11 +552,12 @@ void DolphinView::invertSelection()
 
     QItemSelectionModel* selectionModel = m_viewAccessor.itemView()->selectionModel();
     selectionModel->select(invertedSelection, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Current);
+    */
 }
 
 void DolphinView::clearSelection()
 {
-    m_viewAccessor.itemView()->clearSelection();
+    //m_viewAccessor.itemView()->clearSelection();
 }
 
 void DolphinView::renameSelectedItems()
@@ -598,17 +568,17 @@ void DolphinView::renameSelectedItems()
         return;
     }
 
-    if ((itemCount == 1) && DolphinSettings::instance().generalSettings()->renameInline()) {
+    /*if ((itemCount == 1) && DolphinSettings::instance().generalSettings()->renameInline()) {
         const QModelIndex dirIndex = m_viewAccessor.dirModel()->indexForItem(items.first());
         const QModelIndex proxyIndex = m_viewAccessor.proxyModel()->mapFromSource(dirIndex);
         m_viewAccessor.itemView()->edit(proxyIndex);
-    } else {
+    } else {*/
         RenameDialog* dialog = new RenameDialog(this, items);
         dialog->setAttribute(Qt::WA_DeleteOnClose);
         dialog->show();
         dialog->raise();
         dialog->activateWindow();
-    }
+    //}
 
     // assure that the current index remains visible when KDirLister
     // will notify the view about changed items
@@ -662,40 +632,33 @@ void DolphinView::pasteIntoFolder()
     }
 }
 
-void DolphinView::setShowPreview(bool show)
+void DolphinView::setPreviewsShown(bool show)
 {
-    if (m_showPreview == show) {
+    if (previewsShown() == show) {
         return;
     }
 
-    const KUrl viewPropsUrl = rootUrl();
-    ViewProperties props(viewPropsUrl);
-    props.setShowPreview(show);
-
-    m_showPreview = show;
-    const int oldZoomLevel = m_viewModeController->zoomLevel();
-    emit showPreviewChanged();
+    ViewProperties props(url());
+    props.setPreviewsShown(show);
 
-    // Enabling or disabling the preview might change the icon size of the view.
-    // As the view does not emit a signal when the icon size has been changed,
-    // the used zoom level of the controller must be adjusted manually:
-    updateZoomLevel(oldZoomLevel);
+    m_container->setPreviewsShown(show);
+    emit previewsShownChanged(show);
 }
 
-void DolphinView::setShowHiddenFiles(bool show)
+void DolphinView::setHiddenFilesShown(bool show)
 {
-    if (m_viewAccessor.dirLister()->showingDotFiles() == show) {
+    if (m_dirLister->showingDotFiles() == show) {
         return;
     }
 
     m_selectedItems = selectedItems();
 
-    const KUrl viewPropsUrl = rootUrl();
-    ViewProperties props(viewPropsUrl);
-    props.setShowHiddenFiles(show);
+    ViewProperties props(url());
+    props.setHiddenFilesShown(show);
 
-    m_viewAccessor.dirLister()->setShowingDotFiles(show);
-    emit showHiddenFilesChanged();
+    m_dirLister->setShowingDotFiles(show);
+    m_dirLister->emitChanges();
+    emit hiddenFilesShownChanged(show);
 }
 
 void DolphinView::setCategorizedSorting(bool categorized)
@@ -704,18 +667,13 @@ void DolphinView::setCategorizedSorting(bool categorized)
         return;
     }
 
-    // setCategorizedSorting(true) may only get invoked
-    // if the view supports categorized sorting
-    Q_ASSERT(!categorized || supportsCategorizedSorting());
-
-    ViewProperties props(rootUrl());
+    ViewProperties props(url());
     props.setCategorizedSorting(categorized);
     props.save();
 
-    m_storedCategorizedSorting = categorized;
-    m_viewAccessor.proxyModel()->setCategorizedModel(categorized);
+    //m_viewAccessor.proxyModel()->setCategorizedModel(categorized);
 
-    emit categorizedSortingChanged();
+    emit categorizedSortingChanged(categorized);
 }
 
 void DolphinView::mouseReleaseEvent(QMouseEvent* event)
@@ -724,61 +682,16 @@ void DolphinView::mouseReleaseEvent(QMouseEvent* event)
     setActive(true);
 }
 
-bool DolphinView::eventFilter(QObject* watched, QEvent* event)
+void DolphinView::contextMenuEvent(QContextMenuEvent* event)
 {
-    switch (event->type()) {
-    case QEvent::FocusIn:
-        if (watched == m_viewAccessor.itemView()) {
-            m_dolphinViewController->requestActivation();
-        }
-        break;
-
-    case QEvent::DragEnter:
-        if (watched == m_viewAccessor.itemView()->viewport()) {
-            setActive(true);
-        }
-        break;
-
-    case QEvent::KeyPress:
-        if (watched == m_viewAccessor.itemView()) {
-            // clear the selection when Escape has been pressed
-            QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
-            if (keyEvent->key() == Qt::Key_Escape) {
-                clearSelection();
-            }
-        }
-        break;
-
-    case QEvent::Wheel:
-        if (watched == m_viewAccessor.itemView()->viewport()) {
-            // Ctrl+wheel events should cause icon zooming, but not if the left mouse button is pressed
-            // (the user is probably trying to scroll during a selection in that case)
-            QWheelEvent* wheelEvent = static_cast<QWheelEvent*>(event);
-            if (wheelEvent->modifiers() & Qt::ControlModifier && !(wheelEvent->buttons() & Qt::LeftButton)) {
-                const int delta = wheelEvent->delta();
-                const int level = zoomLevel();
-                if (delta > 0) {
-                    setZoomLevel(level + 1);
-                } else if (delta < 0) {
-                    setZoomLevel(level - 1);
-                }
-                return true;
-            }
-        }
-        break;
-
-    default:
-        break;
-    }
-
-    return QWidget::eventFilter(watched, event);
-}
+    Q_UNUSED(event);
 
-void DolphinView::showEvent(QShowEvent* event)
-{
-    QWidget::showEvent(event);
-    if (!event->spontaneous()) {
-        loadDirectory(url());
+    const QPoint pos = m_container->mapFromGlobal(QCursor::pos());
+    const KItemListView* view = m_container->controller()->view();
+    if (view->itemAt(pos) < 0) {
+        // Only open the context-menu if the cursor is above the viewport
+        // (the context-menu for items is handled in slotItemClicked())
+        requestContextMenu(KFileItem(), url(), QList<QAction*>());
     }
 }
 
@@ -787,21 +700,27 @@ void DolphinView::activate()
     setActive(true);
 }
 
-void DolphinView::triggerItem(const KFileItem& item)
+void DolphinView::slotItemClicked(int index, Qt::MouseButton button)
 {
-    const Qt::KeyboardModifiers modifier = QApplication::keyboardModifiers();
-    if ((modifier & Qt::ShiftModifier) || (modifier & Qt::ControlModifier)) {
-        // items are selected by the user, hence don't trigger the
-        // item specified by 'index'
-        return;
-    }
+    const KFileItem item = fileItemModel()->fileItem(index);
 
-    // TODO: the m_isContextMenuOpen check is a workaround for Qt-issue 207192
-    if (item.isNull() || m_isContextMenuOpen) {
-        return;
+    if (button & Qt::LeftButton) {
+        emit itemTriggered(item); // caught by DolphinViewContainer or DolphinPart
+    } else if (button & Qt::MidButton) {
+        if (item.isDir() || isTabsForFilesEnabled()) {
+            emit tabRequested(item.url());
+        }
+    } else if (button & Qt::RightButton) {
+        // TODO: attach customActions for the details-view
+        emit requestContextMenu(item, url(), QList<QAction*>());
     }
+}
 
-    emit itemTriggered(item); // caught by DolphinViewContainer or DolphinPart
+void DolphinView::slotItemExpansionToggleClicked(int index)
+{
+    KFileItemModel* model = fileItemModel();
+    const bool expanded = model->isExpanded(index);
+    model->setExpanded(index, !expanded);
 }
 
 void DolphinView::slotSelectionChanged(const QItemSelection& selected, const QItemSelection& deselected)
@@ -826,86 +745,63 @@ void DolphinView::emitSelectionChangedSignal()
 void DolphinView::openContextMenu(const QPoint& pos,
                                   const QList<QAction*>& customActions)
 {
+    Q_UNUSED(pos);
     KFileItem item;
-    const QModelIndex index = m_viewAccessor.itemView()->indexAt(pos);
+    /*QAbstractItemView* view = m_viewAccessor.itemView();
+    QModelIndex index;
+    if (view) {
+        index = view->indexAt(pos);
+    }
+
     if (index.isValid() && (index.column() == DolphinModel::Name)) {
         const QModelIndex dolphinModelIndex = m_viewAccessor.proxyModel()->mapToSource(index);
         item = m_viewAccessor.dirModel()->itemForIndex(dolphinModelIndex);
-    }
+    }*/
 
-    m_isContextMenuOpen = true; // TODO: workaround for Qt-issue 207192
     emit requestContextMenu(item, url(), customActions);
-    m_isContextMenuOpen = false;
 }
 
 void DolphinView::dropUrls(const KFileItem& destItem,
                            const KUrl& destPath,
                            QDropEvent* event)
 {
+    Q_UNUSED(destItem);
+    Q_UNUSED(destPath);
     addNewFileNames(event->mimeData());
-    DragAndDropHelper::instance().dropUrls(destItem, destPath, event, this);
+    //DragAndDropHelper::instance().dropUrls(destItem, destPath, event, this);
 }
 
 void DolphinView::updateSorting(DolphinView::Sorting sorting)
 {
-    ViewProperties props(rootUrl());
+    ViewProperties props(url());
     props.setSorting(sorting);
 
-    m_viewAccessor.proxyModel()->setSorting(sorting);
+    KItemModelBase* model = m_container->controller()->model();
+    model->setSortRole(sortRoleForSorting(sorting));
 
     emit sortingChanged(sorting);
 }
 
 void DolphinView::updateSortOrder(Qt::SortOrder order)
 {
-    ViewProperties props(rootUrl());
+    ViewProperties props(url());
     props.setSortOrder(order);
 
-    m_viewAccessor.proxyModel()->setSortOrder(order);
+    //m_viewAccessor.proxyModel()->setSortOrder(order);
 
     emit sortOrderChanged(order);
 }
 
 void DolphinView::updateSortFoldersFirst(bool foldersFirst)
 {
-    ViewProperties props(rootUrl());
+    ViewProperties props(url());
     props.setSortFoldersFirst(foldersFirst);
 
-    m_viewAccessor.proxyModel()->setSortFoldersFirst(foldersFirst);
+    //m_viewAccessor.proxyModel()->setSortFoldersFirst(foldersFirst);
 
     emit sortFoldersFirstChanged(foldersFirst);
 }
 
-void DolphinView::updateAdditionalInfo(const KFileItemDelegate::InformationList& info)
-{
-    ViewProperties props(rootUrl());
-    props.setAdditionalInfo(info);
-    props.save();
-
-    m_viewAccessor.itemDelegate()->setShowInformation(info);
-
-    emit additionalInfoChanged();
-}
-
-void DolphinView::updateAdditionalInfoActions(KActionCollection* collection)
-{
-    const AdditionalInfoAccessor& infoAccessor = AdditionalInfoAccessor::instance();
-
-    const KFileItemDelegate::InformationList checkedInfo = m_viewAccessor.itemDelegate()->showInformation();
-    const KFileItemDelegate::InformationList infoKeys = infoAccessor.keys();
-
-    const bool enable = (m_mode == DolphinView::DetailsView) ||
-                        (m_mode == DolphinView::IconsView);
-
-    foreach (const KFileItemDelegate::Information& info, infoKeys) {
-        const QString name = infoAccessor.actionCollectionName(info, AdditionalInfoAccessor::AdditionalInfoType);
-        QAction* action = collection->action(name);
-        Q_ASSERT(action);
-        action->setEnabled(enable);
-        action->setChecked(checkedInfo.contains(info));
-    }
-}
-
 QPair<bool, QString> DolphinView::pasteInfo() const
 {
     return KonqOperations::pasteInfo(url());
@@ -923,7 +819,7 @@ bool DolphinView::isTabsForFilesEnabled() const
 
 bool DolphinView::itemsExpandable() const
 {
-    return m_viewAccessor.itemsExpandable();
+    return false; //m_viewAccessor.itemsExpandable();
 }
 
 void DolphinView::restoreState(QDataStream& stream)
@@ -931,81 +827,75 @@ void DolphinView::restoreState(QDataStream& stream)
     // Restore the URL of the current item that had the keyboard focus
     stream >> m_activeItemUrl;
 
-    // Restore the root URL
-    KUrl rootUrl;
-    stream >> rootUrl;
-    m_viewAccessor.setRootUrl(rootUrl);
-
     // Restore the view position
     stream >> m_restoredContentsPosition;
 
     // Restore expanded folders (only relevant for the details view - will be ignored by the view in other view modes)
     QSet<KUrl> urlsToExpand;
     stream >> urlsToExpand;
-    const DolphinDetailsViewExpander* expander = m_viewAccessor.setExpandedUrls(urlsToExpand);
+    /*const DolphinDetailsViewExpander* expander = m_viewAccessor.setExpandedUrls(urlsToExpand);
     if (expander) {
         m_expanderActive = true;
         connect (expander, SIGNAL(completed()), this, SLOT(slotLoadingCompleted()));
     }
     else {
         m_expanderActive = false;
-    }
+    }*/
 }
 
 void DolphinView::saveState(QDataStream& stream)
 {
     // Save the URL of the current item that has the keyboard focus
-    KFileItem currentItem;
-    const QAbstractItemView* view = m_viewAccessor.itemView();
-
-    if (view) {
-        const QModelIndex proxyIndex = view->currentIndex();
-        const QModelIndex dirModelIndex = m_viewAccessor.proxyModel()->mapToSource(proxyIndex);
-        currentItem = m_viewAccessor.dirModel()->itemForIndex(dirModelIndex);
-    }
 
     KUrl currentItemUrl;
-    if (!currentItem.isNull()) {
-        currentItemUrl = currentItem.url();
-    }
+    //if (!currentItem.isNull()) {
+    //    currentItemUrl = currentItem.url();
+    //}
 
     stream << currentItemUrl;
 
-    // Save the root URL
-    stream << m_viewAccessor.rootUrl();
-
     // Save view position
-    const int x = view->horizontalScrollBar()->value();
-    const int y = view->verticalScrollBar()->value();
+    const qreal x = m_container->horizontalScrollBar()->value();
+    const qreal y = m_container->verticalScrollBar()->value();
     stream << QPoint(x, y);
+    kDebug() << "saving view state" << QPoint(x, y);
 
     // Save expanded folders (only relevant for the details view - the set will be empty in other view modes)
-    stream << m_viewAccessor.expandedUrls();
+    //stream << m_viewAccessor.expandedUrls();
 }
 
 bool DolphinView::hasSelection() const
 {
-    const QAbstractItemView* view = m_viewAccessor.itemView();
-    return view && view->selectionModel()->hasSelection();
+    //const QAbstractItemView* view = m_viewAccessor.itemView();
+    //return view && view->selectionModel()->hasSelection();
+    return false;
+}
+
+KFileItem DolphinView::rootItem() const
+{
+    return m_dirLister->rootItem();
 }
 
 void DolphinView::observeCreatedItem(const KUrl& url)
 {
     m_createdItemUrl = url;
-    connect(m_viewAccessor.dirModel(), SIGNAL(rowsInserted(const QModelIndex&, int, int)),
-            this, SLOT(selectAndScrollToCreatedItem()));
+    //connect(m_dirModel, SIGNAL(rowsInserted(const QModelIndex&, int, int)),
+    //        this, SLOT(selectAndScrollToCreatedItem()));
 }
 
 void DolphinView::selectAndScrollToCreatedItem()
 {
-    const QModelIndex dirIndex = m_viewAccessor.dirModel()->indexForUrl(m_createdItemUrl);
+    /*const QModelIndex dirIndex = m_viewAccessor.dirModel()->indexForUrl(m_createdItemUrl);
     if (dirIndex.isValid()) {
         const QModelIndex proxyIndex = m_viewAccessor.proxyModel()->mapFromSource(dirIndex);
-        m_viewAccessor.itemView()->setCurrentIndex(proxyIndex);
+        QAbstractItemView* view = m_viewAccessor.itemView();
+        if (view) {
+            view->setCurrentIndex(proxyIndex);
+        }
     }
 
     disconnect(m_viewAccessor.dirModel(), SIGNAL(rowsInserted(const QModelIndex&, int, int)),
-               this, SLOT(selectAndScrollToCreatedItem()));
+               this, SLOT(selectAndScrollToCreatedItem()));*/
     m_createdItemUrl = KUrl();
 }
 
@@ -1013,7 +903,7 @@ void DolphinView::slotRedirection(const KUrl& oldUrl, const KUrl& newUrl)
 {
     if (oldUrl.equals(url(), KUrl::CompareWithoutTrailingSlash)) {
         emit redirection(oldUrl, newUrl);
-        m_viewModeController->redirectToUrl(newUrl); // #186947
+        m_url = newUrl; // #186947
     }
 }
 
@@ -1024,18 +914,16 @@ void DolphinView::restoreContentsPosition()
         const int y = m_restoredContentsPosition.y();
         m_restoredContentsPosition = QPoint();
 
-        QAbstractItemView* view = m_viewAccessor.itemView();
-        Q_ASSERT(view);
-        view->horizontalScrollBar()->setValue(x);
-        view->verticalScrollBar()->setValue(y);
+        m_container->horizontalScrollBar()->setValue(x);
+        m_container->verticalScrollBar()->setValue(y);
     }
 }
 
-void DolphinView::slotUrlChangeRequested(const KUrl& url)
+/*void DolphinView::slotUrlChangeRequested(const KUrl& url)
 {
     m_viewModeController->setUrl(url);
     updateWritableState();
-}
+}*/
 
 void DolphinView::showHoverInformation(const KFileItem& item)
 {
@@ -1077,18 +965,21 @@ void DolphinView::slotDirListerCompleted()
     if (!m_newFileNames.isEmpty()) {
         // select all newly added items created by a paste operation or
         // a drag & drop operation, and clear the previous selection
-        m_viewAccessor.itemView()->clearSelection();
-        const int rowCount = m_viewAccessor.proxyModel()->rowCount();
-        QItemSelection selection;
-        for (int row = 0; row < rowCount; ++row) {
-            const QModelIndex proxyIndex = m_viewAccessor.proxyModel()->index(row, 0);
-            const QModelIndex dirIndex = m_viewAccessor.proxyModel()->mapToSource(proxyIndex);
-            const KUrl url = m_viewAccessor.dirModel()->itemForIndex(dirIndex).url();
-            if (m_newFileNames.contains(url.fileName())) {
-                selection.merge(QItemSelection(proxyIndex, proxyIndex), QItemSelectionModel::Select);
+        /*QAbstractItemView* view = m_viewAccessor.itemView();
+        if (view) {
+            view->clearSelection();
+            const int rowCount = m_viewAccessor.proxyModel()->rowCount();
+            QItemSelection selection;
+            for (int row = 0; row < rowCount; ++row) {
+                const QModelIndex proxyIndex = m_viewAccessor.proxyModel()->index(row, 0);
+                const QModelIndex dirIndex = m_viewAccessor.proxyModel()->mapToSource(proxyIndex);
+                const KUrl url = m_viewAccessor.dirModel()->itemForIndex(dirIndex).url();
+                if (m_newFileNames.contains(url.fileName())) {
+                    selection.merge(QItemSelection(proxyIndex, proxyIndex), QItemSelectionModel::Select);
+                }
             }
-        }
-        m_viewAccessor.itemView()->selectionModel()->select(selection, QItemSelectionModel::Select);
+            view->selectionModel()->select(selection, QItemSelectionModel::Select);
+        }*/
 
         m_newFileNames.clear();
     }
@@ -1102,21 +993,23 @@ void DolphinView::slotLoadingCompleted()
 
     if (!m_activeItemUrl.isEmpty()) {
         // assure that the current item remains visible
-        const QModelIndex dirIndex = m_viewAccessor.dirModel()->indexForUrl(m_activeItemUrl);
+        /*const QModelIndex dirIndex = m_viewAccessor.dirModel()->indexForUrl(m_activeItemUrl);
         if (dirIndex.isValid()) {
             const QModelIndex proxyIndex = m_viewAccessor.proxyModel()->mapFromSource(dirIndex);
             QAbstractItemView* view = m_viewAccessor.itemView();
-            const bool clearSelection = !hasSelection();
-            view->setCurrentIndex(proxyIndex);
-            if (clearSelection) {
-                view->clearSelection();
+            if (view) {
+                const bool clearSelection = !hasSelection();
+                view->setCurrentIndex(proxyIndex);
+                if (clearSelection) {
+                    view->clearSelection();
+                }
             }
             m_activeItemUrl.clear();
-        }
+        }*/
     }
 
     if (!m_selectedItems.isEmpty()) {
-        const KUrl& baseUrl = url();
+        /*const KUrl& baseUrl = url();
         KUrl url;
         QItemSelection newSelection;
         foreach(const KFileItem& item, m_selectedItems) {
@@ -1126,15 +1019,18 @@ void DolphinView::slotLoadingCompleted()
                 newSelection.select(index, index);
             }
         }
-        m_viewAccessor.itemView()->selectionModel()->select(newSelection,
+        QAbstractItemView* view = m_viewAccessor.itemView();
+        if (view) {
+            view->selectionModel()->select(newSelection,
                                                             QItemSelectionModel::ClearAndSelect
                                                             | QItemSelectionModel::Current);
+        }*/
         m_selectedItems.clear();
     }
 
     // Restore the contents position. This has to be done using a Qt::QueuedConnection
     // because the view might not be in its final state yet.
-    QMetaObject::invokeMethod(this, "restoreContentsPosition", Qt::QueuedConnection);
+    QTimer::singleShot(0, this, SLOT(restoreContentsPosition()));
 
     emit finishedPathLoading(url());
 }
@@ -1143,10 +1039,18 @@ void DolphinView::slotRefreshItems()
 {
     if (m_assureVisibleCurrentIndex) {
         m_assureVisibleCurrentIndex = false;
-        m_viewAccessor.itemView()->scrollTo(m_viewAccessor.itemView()->currentIndex());
+        //QAbstractItemView* view = m_viewAccessor.itemView();
+        //if (view) {
+        //    m_viewAccessor.itemView()->scrollTo(m_viewAccessor.itemView()->currentIndex());
+        //}
     }
 }
 
+KFileItemModel* DolphinView::fileItemModel() const
+{
+    return static_cast<KFileItemModel*>(m_container->controller()->model());
+}
+
 void DolphinView::loadDirectory(const KUrl& url, bool reload)
 {
     if (!url.isValid()) {
@@ -1159,50 +1063,61 @@ void DolphinView::loadDirectory(const KUrl& url, bool reload)
         return;
     }
 
-    KDirLister* dirLister = m_viewAccessor.dirLister();
-    dirLister->openUrl(url, reload ? KDirLister::Reload : KDirLister::NoFlags);
+    m_dirLister->openUrl(url, reload ? KDirLister::Reload : KDirLister::NoFlags);
 }
 
 void DolphinView::applyViewProperties()
 {
-    const ViewProperties props(rootUrl());
+    m_container->beginTransaction();
+
+    const ViewProperties props(url());
 
     const Mode mode = props.viewMode();
     if (m_mode != mode) {
-        const int oldZoomLevel = m_viewModeController->zoomLevel();
-
+        const Mode previousMode = m_mode;
         m_mode = mode;
-        createView();
-        emit modeChanged();
 
-        updateZoomLevel(oldZoomLevel);
-    }
-    if (!m_viewAccessor.itemView()) {
-        createView();
-    }
+        // Changing the mode might result in changing
+        // the zoom level. Remember the old zoom level so
+        // that zoomLevelChanged() can get emitted.
+        const int oldZoomLevel = m_container->zoomLevel();
+
+        switch (m_mode) {
+        case IconsView:   m_container->setItemLayout(KFileItemListView::IconsLayout); break;
+        case CompactView: m_container->setItemLayout(KFileItemListView::CompactLayout); break;
+        case DetailsView: m_container->setItemLayout(KFileItemListView::DetailsLayout); break;
+        default: Q_ASSERT(false); break;
+        }
+
+        emit modeChanged(m_mode, previousMode);
 
-    Q_ASSERT(m_viewAccessor.itemView());
-    Q_ASSERT(m_viewAccessor.itemDelegate());
+        if (m_container->zoomLevel() != oldZoomLevel) {
+            emit zoomLevelChanged(m_container->zoomLevel(), oldZoomLevel);
+        }
+    }
 
-    const bool showHiddenFiles = props.showHiddenFiles();
-    if (showHiddenFiles != m_viewAccessor.dirLister()->showingDotFiles()) {
-        m_viewAccessor.dirLister()->setShowingDotFiles(showHiddenFiles);
-        emit showHiddenFilesChanged();
+    const bool hiddenFilesShown = props.hiddenFilesShown();
+    if (hiddenFilesShown != m_dirLister->showingDotFiles()) {
+        m_dirLister->setShowingDotFiles(hiddenFilesShown);
+        m_dirLister->emitChanges();
+        emit hiddenFilesShownChanged(hiddenFilesShown);
     }
 
-    m_storedCategorizedSorting = props.categorizedSorting();
+/*    m_storedCategorizedSorting = props.categorizedSorting();
     const bool categorized = m_storedCategorizedSorting && supportsCategorizedSorting();
     if (categorized != m_viewAccessor.proxyModel()->isCategorizedModel()) {
         m_viewAccessor.proxyModel()->setCategorizedModel(categorized);
         emit categorizedSortingChanged();
-    }
+    }*/
 
     const DolphinView::Sorting sorting = props.sorting();
-    if (sorting != m_viewAccessor.proxyModel()->sorting()) {
-        m_viewAccessor.proxyModel()->setSorting(sorting);
+    KItemModelBase* model = m_container->controller()->model();
+    const QByteArray newSortRole = sortRoleForSorting(sorting);
+    if (newSortRole != model->sortRole()) {
+        model->setSortRole(newSortRole);
         emit sortingChanged(sorting);
     }
-
+/*
     const Qt::SortOrder sortOrder = props.sortOrder();
     if (sortOrder != m_viewAccessor.proxyModel()->sortOrder()) {
         m_viewAccessor.proxyModel()->setSortOrder(sortOrder);
@@ -1214,72 +1129,45 @@ void DolphinView::applyViewProperties()
         m_viewAccessor.proxyModel()->setSortFoldersFirst(sortFoldersFirst);
         emit sortFoldersFirstChanged(sortFoldersFirst);
     }
-
-    KFileItemDelegate::InformationList info = props.additionalInfo();
-    if (info != m_viewAccessor.itemDelegate()->showInformation()) {
-        m_viewAccessor.itemDelegate()->setShowInformation(info);
-        emit additionalInfoChanged();
-    }
-
-    const bool showPreview = props.showPreview();
-    if (showPreview != m_showPreview) {
-        m_showPreview = showPreview;
-        const int oldZoomLevel = m_viewModeController->zoomLevel();
-        emit showPreviewChanged();
-
-        // Enabling or disabling the preview might change the icon size of the view.
-        // As the view does not emit a signal when the icon size has been changed,
-        // the used zoom level of the controller must be adjusted manually:
-        updateZoomLevel(oldZoomLevel);
+*/
+    const QList<DolphinView::AdditionalInfo> infoList = props.additionalInfoList();
+    if (infoList != m_additionalInfoList) {
+        const QList<DolphinView::AdditionalInfo> previousList = m_additionalInfoList;
+        m_additionalInfoList = infoList;
+        applyAdditionalInfoListToView();
+        emit additionalInfoListChanged(m_additionalInfoList, previousList);
     }
-}
-
-void DolphinView::createView()
-{
-    deleteView();
-
-    Q_ASSERT(!m_viewAccessor.itemView());
-    Q_ASSERT(!m_dolphinViewController->itemView());
-    m_viewAccessor.createView(this, m_dolphinViewController, m_viewModeController, m_mode);
 
-    QAbstractItemView* view = m_viewAccessor.itemView();
-    Q_ASSERT(view);
-    view->installEventFilter(this);
-    view->viewport()->installEventFilter(this);
+    const bool previewsShown = props.previewsShown();
+    if (previewsShown != m_container->previewsShown()) {
+        const int oldZoomLevel = zoomLevel();
 
-    m_dolphinViewController->setItemView(view);
+        m_container->setPreviewsShown(previewsShown);
+        emit previewsShownChanged(previewsShown);
 
-    const int zoomLevel = ZoomLevelInfo::zoomLevelForIconSize(view->iconSize());
-    m_viewModeController->setZoomLevel(zoomLevel);
-
-    connectViewAccessor();
+        // Changing the preview-state might result in a changed zoom-level
+        if (oldZoomLevel != zoomLevel()) {
+            emit zoomLevelChanged(zoomLevel(), oldZoomLevel);
+        }
+    }
 
-    setFocusProxy(m_viewAccessor.layoutTarget());
-    m_topLayout->insertWidget(1, m_viewAccessor.layoutTarget());
+    m_container->endTransaction();
 }
 
-void DolphinView::deleteView()
+void DolphinView::applyAdditionalInfoListToView()
 {
-    QAbstractItemView* view = m_viewAccessor.itemView();
-    Q_ASSERT(!m_dolphinViewController->itemView() || (m_dolphinViewController->itemView() == view));
-    m_dolphinViewController->setItemView(0);
-
-    if (view) {
-        disconnectViewAccessor();
-
-        if (hasFocus()) {
-            // It's important to set the keyboard focus to the parent
-            // before deleting the view: Otherwise when having a split
-            // view the other view will get the focus and will request
-            // an activation (see DolphinView::eventFilter()).
-            setFocusProxy(0);
-            setFocus();
-        }
+    const AdditionalInfoAccessor& infoAccessor = AdditionalInfoAccessor::instance();
 
-        m_viewModeController->disconnect(view);
+    QHash<QByteArray, int> visibleRoles;
+    visibleRoles.insert("name", 0);
 
-        m_viewAccessor.deleteView();
+    int index = 1;
+    foreach (AdditionalInfo info, m_additionalInfoList) {
+        visibleRoles.insert(infoAccessor.role(info), index);
+        ++index;
     }
+
+    m_container->setVisibleRoles(visibleRoles);
 }
 
 void DolphinView::pasteToUrl(const KUrl& url)
@@ -1290,17 +1178,19 @@ void DolphinView::pasteToUrl(const KUrl& url)
 
 void DolphinView::updateZoomLevel(int oldZoomLevel)
 {
-    const int newZoomLevel = ZoomLevelInfo::zoomLevelForIconSize(m_viewAccessor.itemView()->iconSize());
+    Q_UNUSED(oldZoomLevel);
+ /*   const int newZoomLevel = ZoomLevelInfo::zoomLevelForIconSize(m_viewAccessor.itemView()->iconSize());
     if (oldZoomLevel != newZoomLevel) {
         m_viewModeController->setZoomLevel(newZoomLevel);
         emit zoomLevelChanged(newZoomLevel);
-    }
+    }*/
 }
 
 KUrl::List DolphinView::simplifiedSelectedUrls() const
 {
+    Q_ASSERT(false); // TODO
     KUrl::List urls;
-
+/*
     const KFileItemList items = selectedItems();
     foreach (const KFileItem &item, items) {
         urls.append(item.url());
@@ -1309,17 +1199,18 @@ KUrl::List DolphinView::simplifiedSelectedUrls() const
 
     if (itemsExpandable()) {
         urls = KDirModel::simplifiedUrlList(urls);
-    }
+    }*/
 
     return urls;
 }
 
 QMimeData* DolphinView::selectionMimeData() const
 {
-    const QAbstractItemView* view = m_viewAccessor.itemView();
+    /*const QAbstractItemView* view = m_viewAccessor.itemView();
     Q_ASSERT((view) && (view->selectionModel()));
     const QItemSelection selection = m_viewAccessor.proxyModel()->mapSelectionToSource(view->selectionModel()->selection());
-    return m_viewAccessor.dirModel()->mimeData(selection.indexes());
+    return m_viewAccessor.dirModel()->mimeData(selection.indexes());*/
+    return 0;
 }
 
 void DolphinView::addNewFileNames(const QMimeData* mimeData)
@@ -1332,8 +1223,10 @@ void DolphinView::addNewFileNames(const QMimeData* mimeData)
 
 QItemSelection DolphinView::childrenMatchingPattern(const QModelIndex& parent, const QRegExp& pattern) const
 {
+    Q_UNUSED(parent);
+    Q_UNUSED(pattern);
     QItemSelection matchingIndexes;
-    const DolphinSortFilterProxyModel* proxyModel = m_viewAccessor.proxyModel();
+    /*const DolphinSortFilterProxyModel* proxyModel = m_viewAccessor.proxyModel();
     const DolphinModel* dolphinModel = m_viewAccessor.dirModel();
 
     const int rowCount = proxyModel->rowCount(parent);
@@ -1349,61 +1242,17 @@ QItemSelection DolphinView::childrenMatchingPattern(const QModelIndex& parent, c
         if (proxyModel->hasChildren(index)) {
             matchingIndexes += childrenMatchingPattern(index, pattern);
         }
-    }
+    }*/
 
     return matchingIndexes;
 }
 
-void DolphinView::connectViewAccessor()
-{
-    KDirLister* dirLister = m_viewAccessor.dirLister();
-    connect(dirLister, SIGNAL(redirection(KUrl,KUrl)), this, SLOT(slotRedirection(KUrl,KUrl)));
-    connect(dirLister, SIGNAL(started(KUrl)),          this, SLOT(slotDirListerStarted(KUrl)));
-    connect(dirLister, SIGNAL(completed()),            this, SLOT(slotDirListerCompleted()));
-    connect(dirLister, SIGNAL(refreshItems(const QList<QPair<KFileItem,KFileItem>>&)),
-            this, SLOT(slotRefreshItems()));
-
-    connect(dirLister, SIGNAL(clear()),                      this, SIGNAL(itemCountChanged()));
-    connect(dirLister, SIGNAL(newItems(KFileItemList)),      this, SIGNAL(itemCountChanged()));
-    connect(dirLister, SIGNAL(infoMessage(const QString&)),  this, SIGNAL(infoMessage(const QString&)));
-    connect(dirLister, SIGNAL(errorMessage(const QString&)), this, SIGNAL(infoMessage(const QString&)));
-    connect(dirLister, SIGNAL(percent(int)),                 this, SIGNAL(pathLoadingProgress(int)));
-    connect(dirLister, SIGNAL(urlIsFileError(const KUrl&)),  this, SIGNAL(urlIsFileError(const KUrl&)));
-    connect(dirLister, SIGNAL(itemsDeleted(const KFileItemList&)), this, SIGNAL(itemCountChanged()));
-
-    QAbstractItemView* view = m_viewAccessor.itemView();
-    connect(view->selectionModel(), SIGNAL(selectionChanged(QItemSelection, QItemSelection)),
-            this, SLOT(slotSelectionChanged(QItemSelection, QItemSelection)));
-}
-
-void DolphinView::disconnectViewAccessor()
-{
-    KDirLister* dirLister = m_viewAccessor.dirLister();
-    disconnect(dirLister, SIGNAL(redirection(KUrl,KUrl)), this, SLOT(slotRedirection(KUrl,KUrl)));
-    disconnect(dirLister, SIGNAL(started(KUrl)),          this, SLOT(slotDirListerStarted(KUrl)));
-    disconnect(dirLister, SIGNAL(completed()),            this, SLOT(slotDirListerCompleted()));
-    disconnect(dirLister, SIGNAL(refreshItems(const QList<QPair<KFileItem,KFileItem>>&)),
-               this, SLOT(slotRefreshItems()));
-
-    disconnect(dirLister, SIGNAL(clear()),                      this, SIGNAL(itemCountChanged()));
-    disconnect(dirLister, SIGNAL(newItems(KFileItemList)),      this, SIGNAL(itemCountChanged()));
-    disconnect(dirLister, SIGNAL(infoMessage(const QString&)),  this, SIGNAL(infoMessage(const QString&)));
-    disconnect(dirLister, SIGNAL(errorMessage(const QString&)), this, SIGNAL(errorMessage(const QString&)));
-    disconnect(dirLister, SIGNAL(percent(int)),                 this, SIGNAL(pathLoadingProgress(int)));
-    disconnect(dirLister, SIGNAL(urlIsFileError(const KUrl&)),  this, SIGNAL(urlIsFileError(const KUrl&)));
-    disconnect(dirLister, SIGNAL(itemsDeleted(const KFileItemList&)), this, SIGNAL(itemCountChanged()));
-
-    QAbstractItemView* view = m_viewAccessor.itemView();
-    disconnect(view->selectionModel(), SIGNAL(selectionChanged(QItemSelection, QItemSelection)),
-               this, SLOT(slotSelectionChanged(QItemSelection, QItemSelection)));
-}
-
 void DolphinView::updateWritableState()
 {
     const bool wasFolderWritable = m_isFolderWritable;
     m_isFolderWritable = true;
 
-    const KFileItem item = m_viewAccessor.dirLister()->rootItem();
+    const KFileItem item; // = m_viewAccessor.dirLister()->rootItem();
     if (!item.isNull()) {
         KFileItemListProperties capabilities(KFileItemList() << item);
         m_isFolderWritable = capabilities.supportsWriting();
@@ -1413,225 +1262,22 @@ void DolphinView::updateWritableState()
     }
 }
 
-DolphinView::ViewAccessor::ViewAccessor() :
-    m_rootUrl(),
-    m_iconsView(0),
-    m_detailsView(0),
-    m_columnsContainer(0),
-    m_dolphinModel(0),
-    m_proxyModel(0),
-    m_dragSource(0)
-{
-    DolphinDirLister* dirLister = new DolphinDirLister();
-    dirLister->setAutoUpdate(true);
-    dirLister->setDelayedMimeTypes(true);
-
-    m_dolphinModel = new DolphinModel();
-    m_dolphinModel->setDirLister(dirLister);  // m_dolphinModel takes ownership of dirLister
-    m_dolphinModel->setDropsAllowed(DolphinModel::DropOnDirectory);
-
-    m_proxyModel = new DolphinSortFilterProxyModel();
-    m_proxyModel->setSourceModel(m_dolphinModel);
-    m_proxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
-}
-
-DolphinView::ViewAccessor::~ViewAccessor()
-{
-    delete m_proxyModel;
-    m_proxyModel = 0;
-
-    delete m_dolphinModel;
-    m_dolphinModel = 0;
-
-    delete m_dragSource;
-    m_dragSource = 0;
-}
-
-void DolphinView::ViewAccessor::createView(QWidget* parent,
-                                           DolphinViewController* dolphinViewController,
-                                           const ViewModeController* viewModeController,
-                                           Mode mode)
-{
-    Q_ASSERT(!itemView());
-
-    switch (mode) {
-    case IconsView:
-        m_iconsView = new DolphinIconsView(parent,
-                                           dolphinViewController,
-                                           viewModeController,
-                                           m_proxyModel);
-        break;
-
-    case DetailsView:
-        m_detailsView = new DolphinDetailsView(parent,
-                                               dolphinViewController,
-                                               viewModeController,
-                                               m_proxyModel);
-        break;
-
-    case ColumnView:
-        m_columnsContainer = new DolphinColumnViewContainer(parent,
-                                                            dolphinViewController,
-                                                            viewModeController);
-        if (!m_rootUrl.isEmpty() && m_rootUrl.isParentOf(viewModeController->url())) {
-            // The column-view must show several columns starting with m_rootUrl as
-            // first column and viewModeController->url() as last column.
-            m_columnsContainer->showColumn(m_rootUrl);
-            m_columnsContainer->showColumn(viewModeController->url());
-        }
-        break;
-
-    default:
-        Q_ASSERT(false);
-    }
-
-    KDirLister* lister = dirLister();
-    if (lister) {
-        lister->setMainWindow(parent->window());
-    }
-}
-
-void DolphinView::ViewAccessor::deleteView()
-{
-    if (m_columnsContainer) {
-        m_columnsContainer->close();
-        m_columnsContainer->disconnect();
-        m_columnsContainer->deleteLater();
-        m_columnsContainer = 0;
-    } else {
-        QAbstractItemView* view = itemView();
-        if (view) {
-            view->close();
-            view->disconnect();
-
-            if (DragAndDropHelper::instance().isDragSource(view)) {
-                // The view is a drag source (the feature "Open folders
-                // during drag operations" is used). Deleting the view
-                // during an ongoing drag operation is not allowed, so
-                // this will postponed.
-                if (m_dragSource) {
-                    // the old stored view is obviously not the drag source anymore
-                    m_dragSource->deleteLater();
-                    m_dragSource = 0;
-                }
-                view->hide();
-                m_dragSource = view;
-            } else {
-                view->deleteLater();
-                view = 0;
-            }
-        }
-
-        m_iconsView = 0;
-        m_detailsView = 0;
-    }
-}
-
-void DolphinView::ViewAccessor::prepareUrlChange(const KUrl& url)
-{
-    if (m_columnsContainer) {
-        m_columnsContainer->showColumn(url);
-    }
-}
-
-QAbstractItemView* DolphinView::ViewAccessor::itemView() const
-{
-    if (m_iconsView) {
-        return m_iconsView;
-    }
-
-    if (m_detailsView) {
-        return m_detailsView;
-    }
-
-    if (m_columnsContainer) {
-        return m_columnsContainer->activeColumn();
-    }
-
-    return 0;
-}
-
-KFileItemDelegate* DolphinView::ViewAccessor::itemDelegate() const
-{
-    return static_cast<KFileItemDelegate*>(itemView()->itemDelegate());
-}
-
-QWidget* DolphinView::ViewAccessor::layoutTarget() const
+QByteArray DolphinView::sortRoleForSorting(Sorting sorting) const
 {
-    if (m_columnsContainer) {
-        return m_columnsContainer;
+    switch (sorting) {
+    case SortByName:        return "name";
+    case SortBySize:        return "size";
+    case SortByDate:        return "date";
+    case SortByPermissions: return "permissions";
+    case SortByOwner:       return "owner";
+    case SortByGroup:       return "group";
+    case SortByType:        return "type";
+    case SortByDestination: return "destination";
+    case SortByPath:        return "path";
+    default: break;
     }
-    return itemView();
-}
-
-void DolphinView::ViewAccessor::setRootUrl(const KUrl& rootUrl)
-{
-    m_rootUrl = rootUrl;
-}
-
-KUrl DolphinView::ViewAccessor::rootUrl() const
-{
-    return m_columnsContainer ? m_columnsContainer->rootUrl() : m_rootUrl;
-}
 
-bool DolphinView::ViewAccessor::supportsCategorizedSorting() const
-{
-    return m_iconsView != 0;
-}
-
-bool DolphinView::ViewAccessor::itemsExpandable() const
-{
-    return m_detailsView && m_detailsView->itemsExpandable();
-}
-
-QSet<KUrl> DolphinView::ViewAccessor::expandedUrls() const
-{
-    if (m_detailsView) {
-        return m_detailsView->expandedUrls();
-    }
-
-    return QSet<KUrl>();
-}
-
-const DolphinDetailsViewExpander* DolphinView::ViewAccessor::setExpandedUrls(const QSet<KUrl>& urlsToExpand)
-{
-    if (m_detailsView && m_detailsView->itemsExpandable() && !urlsToExpand.isEmpty()) {
-        // Check if another expander is already active and stop it if necessary.
-        if(!m_detailsViewExpander.isNull()) {
-            m_detailsViewExpander->stop();
-        }
-
-        m_detailsViewExpander = new DolphinDetailsViewExpander(m_detailsView, urlsToExpand);
-        return m_detailsViewExpander;
-    }
-    else {
-        return 0;
-    }
-}
-
-bool DolphinView::ViewAccessor::reloadOnAdditionalInfoChange() const
-{
-    // the details view requires no reloading of the directory, as it maps
-    // the file item delegate info to its columns internally
-    return m_detailsView != 0;
-}
-
-DolphinModel* DolphinView::ViewAccessor::dirModel() const
-{
-    return static_cast<DolphinModel*>(proxyModel()->sourceModel());
-}
-
-DolphinSortFilterProxyModel* DolphinView::ViewAccessor::proxyModel() const
-{
-    if (m_columnsContainer) {
-        return static_cast<DolphinSortFilterProxyModel*>(m_columnsContainer->activeColumn()->model());
-    }
-    return m_proxyModel;
-}
-
-KDirLister* DolphinView::ViewAccessor::dirLister() const
-{
-    return dirModel()->dirLister();
+    return QByteArray();
 }
 
 #include "dolphinview.moc"
index 48967e62bacd5a18d68be8f509e05a13ba5fcc83..f5bc7d92278272bffc09312b4eb43f8ef4e46020 100644 (file)
 
 typedef KIO::FileUndoManager::CommandType CommandType;
 
-class DolphinColumnViewContainer;
-class DolphinDetailsView;
-class DolphinDetailsViewExpander;
-class DolphinIconsView;
-class DolphinModel;
-class DolphinSortFilterProxyModel;
-class DolphinViewController;
+class DolphinDirLister;
+class DolphinItemListContainer;
 class KAction;
 class KActionCollection;
-class KDirLister;
+class KFileItemModel;
 class KUrl;
-class ViewModeController;
 class ViewProperties;
 class QRegExp;
 
 /**
  * @short Represents a view for the directory content.
  *
- * View modes for icons, details and columns are supported. It's
+ * View modes for icons, compact and details are supported. It's
  * possible to adjust:
  * - sort order
  * - sort type
  * - show hidden files
  * - show previews
- *
- * @see DolphinIconsView
- * @see DolphinDetailsView
- * @see DolphinColumnView
+ * - enable grouping
  */
 class LIBDOLPHINPRIVATE_EXPORT DolphinView : public QWidget
 {
@@ -76,31 +67,28 @@ class LIBDOLPHINPRIVATE_EXPORT DolphinView : public QWidget
 
 public:
     /**
-     * Defines the view mode for a directory. The view mode
-     * can be defined when constructing a DolphinView. The
+     * Defines the view mode for a directory. The
      * view mode is automatically updated if the directory itself
      * defines a view mode (see class ViewProperties for details).
      */
     enum Mode
     {
         /**
-         * The directory items are shown as icons including an
-         * icon name.
+         * The items are shown as icons with a name-label below.
          */
         IconsView = 0,
 
         /**
-         * The icon, the name and at least the size of the directory
-         * items are shown in a table. It is possible to add columns
-         * for date, group and permissions.
+         * The icon, the name and the size of the items are
+         * shown per default as a table.
          */
         DetailsView = 1,
 
         /**
-         * Each folder is shown in a separate column.
+         * The items are shown as icons with the name-label aligned
+         * to the right side.
          */
-        ColumnView = 2,
-        MaxModeEnum = ColumnView
+        CompactView = 3
     };
 
     /** Defines the sort order for the items of a directory. */
@@ -114,15 +102,29 @@ public:
         SortByGroup,
         SortByType,
         SortByDestination,
-        SortByPath,
-        MaxSortingEnum = SortByPath
+        SortByPath
+    };
+
+    /** Defines the additional information shown for the items of a directory. */
+    enum AdditionalInfo
+    {
+        NoInfo = 0,
+        NameInfo,
+        SizeInfo,
+        DateInfo,
+        PermissionsInfo,
+        OwnerInfo,
+        GroupInfo,
+        TypeInfo,
+        DestinationInfo,
+        PathInfo
     };
 
     /**
      * @param url              Specifies the content which should be shown.
      * @param parent           Parent widget of the view.
      */
-    DolphinView( const KUrl& url, QWidget* parent);
+    DolphinView(const KUrl& url, QWidget* parent);
 
     virtual ~DolphinView();
 
@@ -132,17 +134,6 @@ public:
      */
     KUrl url() const;
 
-    /**
-     * Returns the root URL of the view, which is defined as the first
-     * visible path of DolphinView::url(). Usually the root URL is
-     * equal to DolphinView::url(), but in the case of the column view
-     * when 2 columns are shown, the root URL might be:
-     * /home/peter/Documents
-     * and DolphinView::url() might return
-     * /home/peter/Documents/Music/
-     */
-    KUrl rootUrl() const;
-
     /**
      * If \a active is true, the view will marked as active. The active
      * view is defined as view where all actions are applied to.
@@ -159,30 +150,15 @@ public:
     void setMode(Mode mode);
     Mode mode() const;
 
-    /** See setShowPreview */
-    bool showPreview() const;
+    /** See setPreviewsShown */
+    bool previewsShown() const;
 
     /** See setShowHiddenFiles */
-    bool showHiddenFiles() const;
+    bool hiddenFilesShown() const;
 
     /** See setCategorizedSorting */
     bool categorizedSorting() const;
 
-    /**
-     * Returns true, if the categorized sorting is supported by the current
-     * used mode (see DolphinView::setMode()). Currently only DolphinView::IconsView
-     * supports categorizations. To check whether the categorized
-     * sorting is set, use DolphinView::categorizedSorting().
-     */
-    bool supportsCategorizedSorting() const;
-
-    /**
-     * Returns the root item which represents the current URL. Note that the returned
-     * item can be null (KFileItem::isNull() will return true) in case that the directory
-     * has not been loaded.
-     */
-    KFileItem rootItem() const;
-
     /**
      * Returns the items of the view.
      */
@@ -253,10 +229,10 @@ public:
     bool sortFoldersFirst() const;
 
     /** Sets the additional information which should be shown for the items. */
-    void setAdditionalInfo(KFileItemDelegate::InformationList info);
+    void setAdditionalInfoList(const QList<AdditionalInfo>& info);
 
     /** Returns the additional information which should be shown for the items. */
-    KFileItemDelegate::InformationList additionalInfo() const;
+    QList<AdditionalInfo> additionalInfoList() const;
 
     /** Reloads the current directory. */
     void reload();
@@ -299,11 +275,6 @@ public:
      */
     QList<QAction*> versionControlActions(const KFileItemList& items) const;
 
-    /**
-     * Updates the state of the 'Additional Information' actions in \a collection.
-     */
-    void updateAdditionalInfoActions(KActionCollection* collection);
-
     /**
      * Returns the state of the paste action:
      * first is whether the action should be enabled
@@ -339,6 +310,13 @@ public:
     /** Returns true, if at least one item is selected. */
     bool hasSelection() const;
 
+    /**
+     * Returns the root item which represents the current URL. Note that the returned
+     * item can be null (KFileItem::isNull() will return true) in case that the directory
+     * has not been loaded.
+     */
+    KFileItem rootItem() const;
+
 public slots:
     /**
      * Changes the directory to \a url. If the current directory is equal to
@@ -403,7 +381,7 @@ public slots:
      * (GeneralSettings::globalViewProps() returns false), then the
      * preview setting will be stored automatically.
      */
-    void setShowPreview(bool show);
+    void setPreviewsShown(bool show);
 
     /**
      * Shows all hidden files of the current directory,
@@ -412,7 +390,7 @@ public slots:
      * (GeneralSettings::globalViewProps() returns false), then the
      * show hidden file setting will be stored automatically.
      */
-    void setShowHiddenFiles(bool show);
+    void setHiddenFilesShown(bool show);
 
     /**
      * Summarizes all sorted items by their category \a categorized
@@ -429,6 +407,13 @@ signals:
      */
     void activated();
 
+    /**
+     * Is emitted if the URL of the view will be changed to \a url.
+     * After the URL has been changed the signal urlChanged() will
+     * be emitted.
+     */
+    void urlAboutToBeChanged(const KUrl& url);
+
     /** Is emitted if URL of the view has been changed to \a url. */
     void urlChanged(const KUrl& url);
 
@@ -451,16 +436,16 @@ signals:
      * Is emitted if the view mode (IconsView, DetailsView,
      * PreviewsView) has been changed.
      */
-    void modeChanged();
+    void modeChanged(Mode current, Mode previous);
 
     /** Is emitted if the 'show preview' property has been changed. */
-    void showPreviewChanged();
+    void previewsShownChanged(bool shown);
 
     /** Is emitted if the 'show hidden files' property has been changed. */
-    void showHiddenFilesChanged();
+    void hiddenFilesShownChanged(bool shown);
 
     /** Is emitted if the 'categorized sorting' property has been changed. */
-    void categorizedSortingChanged();
+    void categorizedSortingChanged(bool sortCategorized);
 
     /** Is emitted if the sorting by name, size or date has been changed. */
     void sortingChanged(DolphinView::Sorting sorting);
@@ -472,10 +457,11 @@ signals:
     void sortFoldersFirstChanged(bool foldersFirst);
 
     /** Is emitted if the additional information shown for this view has been changed. */
-    void additionalInfoChanged();
+    void additionalInfoListChanged(const QList<DolphinView::AdditionalInfo>& current,
+                                   const QList<DolphinView::AdditionalInfo>& previous);
 
     /** Is emitted if the zoom level has been changed by zooming in or out. */
-    void zoomLevelChanged(int level);
+    void zoomLevelChanged(int current, int previous);
 
     /**
      * Is emitted if information of an item is requested to be shown e. g. in the panel.
@@ -556,10 +542,8 @@ signals:
     void writeStateChanged(bool isFolderWritable);
 
 protected:
-    /** @see QWidget::mouseReleaseEvent */
     virtual void mouseReleaseEvent(QMouseEvent* event);
-    virtual bool eventFilter(QObject* watched, QEvent* event);
-    virtual void showEvent(QShowEvent* event);
+    virtual void contextMenuEvent(QContextMenuEvent* event);
 
 private slots:
     /**
@@ -568,12 +552,9 @@ private slots:
      */
     void activate();
 
-    /**
-     * If the item \a item is a directory, then this
-     * directory will be loaded. If the  item is a file, the corresponding
-     * application will get started.
-     */
-    void triggerItem(const KFileItem& index);
+    void slotItemClicked(int index, Qt::MouseButton button);
+
+    void slotItemExpansionToggleClicked(int index);
 
     /**
      * Emits the signal \a selectionChanged() with a small delay. This is
@@ -624,12 +605,6 @@ private slots:
      */
     void updateSortFoldersFirst(bool foldersFirst);
 
-    /**
-     * Updates the view properties of the current URL to the
-     * additional information given by \a info.
-     */
-    void updateAdditionalInfo(const KFileItemDelegate::InformationList& info);
-
     /**
      * Updates the status bar to show hover information for the
      * item \a item. If currently other items are selected,
@@ -699,9 +674,11 @@ private slots:
      */
     void restoreContentsPosition();
 
-    void slotUrlChangeRequested(const KUrl& url);
+    //void slotUrlChangeRequested(const KUrl& url);
 
 private:
+    KFileItemModel* fileItemModel() const;
+
     void loadDirectory(const KUrl& url, bool reload = false);
 
     /**
@@ -710,13 +687,7 @@ private:
      */
     void applyViewProperties();
 
-    /**
-     * Creates a new view representing the given view mode (DolphinView::mode()).
-     * The current view will get deleted.
-     */
-    void createView();
-
-    void deleteView();
+    void applyAdditionalInfoListToView();
 
     /**
      * Helper method for DolphinView::paste() and DolphinView::pasteIntoFolder().
@@ -758,9 +729,6 @@ private:
      */
     QItemSelection childrenMatchingPattern(const QModelIndex& parent, const QRegExp& pattern) const;
 
-    void connectViewAccessor();
-    void disconnectViewAccessor();
-
     /**
      * Updates m_isFolderWritable dependent on whether the folder represented by
      * the current URL is writable. If the state has changed, the signal
@@ -768,88 +736,23 @@ private:
      */
     void updateWritableState();
 
-private:
-    /**
-     * Abstracts the access to the different view implementations
-     * for icons-, details- and column-view.
-     */
-    class ViewAccessor
-    {
-    public:
-        ViewAccessor();
-        ~ViewAccessor();
-
-        void createView(QWidget* parent,
-                        DolphinViewController* dolphinViewController,
-                        const ViewModeController* viewModeController,
-                        Mode mode);
-        void deleteView();
-
-        /**
-         * Must be invoked before the URL has been changed and allows view implementations
-         * like the column view to create a new column.
-         */
-        void prepareUrlChange(const KUrl& url);
-
-        QAbstractItemView* itemView() const;
-        KFileItemDelegate* itemDelegate() const;
-
-        /**
-         * Returns the widget that should be added to the layout as target. Usually
-         * the item view itself is returned, but in the case of the column view
-         * a container widget is returned.
-         */
-        QWidget* layoutTarget() const;
-
-        void setRootUrl(const KUrl& rootUrl);
-        KUrl rootUrl() const;
-
-        bool supportsCategorizedSorting() const;
-        bool itemsExpandable() const;
-        QSet<KUrl> expandedUrls() const;
-        const DolphinDetailsViewExpander* setExpandedUrls(const QSet<KUrl>& urlsToExpand);
-
-        /**
-         * Returns true, if a reloading of the items is required
-         * when the additional information properties have been changed
-         * by the user.
-         */
-        bool reloadOnAdditionalInfoChange() const;
-
-        DolphinModel* dirModel() const;
-        DolphinSortFilterProxyModel* proxyModel() const;
-        KDirLister* dirLister() const;
-
-    private:
-        KUrl m_rootUrl;
-        DolphinIconsView* m_iconsView;
-        DolphinDetailsView* m_detailsView;
-        DolphinColumnViewContainer* m_columnsContainer;
-        DolphinModel* m_dolphinModel;
-        DolphinSortFilterProxyModel* m_proxyModel;
-        QAbstractItemView* m_dragSource;
-        QPointer<DolphinDetailsViewExpander> m_detailsViewExpander;
-
-        // For unit tests
-        friend class DolphinDetailsViewTest;
-    };
+    QByteArray sortRoleForSorting(Sorting sorting) const;
 
+private:
     bool m_active : 1;
-    bool m_showPreview : 1;
-    bool m_storedCategorizedSorting : 1;
     bool m_tabsForFiles : 1;
-    bool m_isContextMenuOpen : 1;   // TODO: workaround for Qt-issue 207192
     bool m_assureVisibleCurrentIndex : 1;
     bool m_expanderActive : 1;
     bool m_isFolderWritable : 1;
 
+    KUrl m_url;
     Mode m_mode;
+    QList<AdditionalInfo> m_additionalInfoList;
 
     QVBoxLayout* m_topLayout;
 
-    DolphinViewController* m_dolphinViewController;
-    ViewModeController* m_viewModeController;
-    ViewAccessor m_viewAccessor;
+    DolphinDirLister* m_dirLister;
+    DolphinItemListContainer* m_container;
 
     QTimer* m_selectionChangedTimer;
 
index 6046abc8c0a43c7bbd76bbc86bcc91a4ab34557c..87e828dfa8b0851bcf9539f3705a6486f721fb23 100644 (file)
@@ -36,6 +36,8 @@
 #include <KRun>
 #include <KPropertiesDialog>
 
+#include <KDebug>
+
 DolphinViewActionHandler::DolphinViewActionHandler(KActionCollection* collection, QObject* parent)
     : QObject(parent),
       m_actionCollection(collection),
@@ -49,29 +51,32 @@ void DolphinViewActionHandler::setCurrentView(DolphinView* view)
 {
     Q_ASSERT(view);
 
-    if (m_currentView)
+    if (m_currentView) {
         disconnect(m_currentView, 0, this, 0);
+    }
 
     m_currentView = view;
 
-    connect(view, SIGNAL(modeChanged()),
+    connect(view, SIGNAL(modeChanged(DolphinView::Mode, DolphinView::Mode)),
             this, SLOT(updateViewActions()));
-    connect(view, SIGNAL(showPreviewChanged()),
-            this, SLOT(slotShowPreviewChanged()));
+    connect(view, SIGNAL(previewsShownChanged(bool)),
+            this, SLOT(slotPreviewsShownChanged(bool)));
     connect(view, SIGNAL(sortOrderChanged(Qt::SortOrder)),
             this, SLOT(slotSortOrderChanged(Qt::SortOrder)));
     connect(view, SIGNAL(sortFoldersFirstChanged(bool)),
             this, SLOT(slotSortFoldersFirstChanged(bool)));
-    connect(view, SIGNAL(additionalInfoChanged()),
-            this, SLOT(slotAdditionalInfoChanged()));
-    connect(view, SIGNAL(categorizedSortingChanged()),
-            this, SLOT(slotCategorizedSortingChanged()));
-    connect(view, SIGNAL(showHiddenFilesChanged()),
-            this, SLOT(slotShowHiddenFilesChanged()));
+    connect(view, SIGNAL(additionalInfoListChanged(QList<DolphinView::AdditionalInfo>,
+                                                   QList<DolphinView::AdditionalInfo>)),
+            this, SLOT(slotAdditionalInfoListChanged(QList<DolphinView::AdditionalInfo>,
+                                                     QList<DolphinView::AdditionalInfo>)));
+    connect(view, SIGNAL(categorizedSortingChanged(bool)),
+            this, SLOT(slotCategorizedSortingChanged(bool)));
+    connect(view, SIGNAL(hiddenFilesShownChanged(bool)),
+            this, SLOT(slotHiddenFilesShownChanged(bool)));
     connect(view, SIGNAL(sortingChanged(DolphinView::Sorting)),
             this, SLOT(slotSortingChanged(DolphinView::Sorting)));
-    connect(view, SIGNAL(zoomLevelChanged(int)),
-            this, SLOT(slotZoomLevelChanged(int)));
+    connect(view, SIGNAL(zoomLevelChanged(int, int)),
+            this, SLOT(slotZoomLevelChanged(int, int)));
 }
 
 DolphinView* DolphinViewActionHandler::currentView()
@@ -130,14 +135,14 @@ void DolphinViewActionHandler::createActions()
 
     // View menu
     KToggleAction* iconsAction = iconsModeAction();
+    KToggleAction* compactAction = compactModeAction();
     KToggleAction* detailsAction = detailsModeAction();
-    KToggleAction* columnsAction = columnsModeAction();
 
     KSelectAction* viewModeActions = m_actionCollection->add<KSelectAction>("view_mode");
     viewModeActions->setText(i18nc("@action:intoolbar", "View Mode"));
     viewModeActions->addAction(iconsAction);
+    viewModeActions->addAction(compactAction);
     viewModeActions->addAction(detailsAction);
-    viewModeActions->addAction(columnsAction);
     viewModeActions->setToolBarMode(KSelectAction::MenuMode);
     connect(viewModeActions, SIGNAL(triggered(QAction*)), this, SLOT(slotViewModeActionTriggered(QAction*)));
 
@@ -214,8 +219,8 @@ QActionGroup* DolphinViewActionHandler::createAdditionalInformationActionGroup()
 
     const AdditionalInfoAccessor& infoAccessor = AdditionalInfoAccessor::instance();
 
-    const KFileItemDelegate::InformationList infoKeys = infoAccessor.keys();
-    foreach (KFileItemDelegate::Information info, infoKeys) {
+    const QList<DolphinView::AdditionalInfo> infoList = infoAccessor.keys();
+    foreach (DolphinView::AdditionalInfo info, infoList) {
         const QString name = infoAccessor.actionCollectionName(info, AdditionalInfoAccessor::AdditionalInfoType);
         KToggleAction* action = m_actionCollection->add<KToggleAction>(name);
         action->setText(infoAccessor.translation(info));
@@ -239,8 +244,8 @@ QActionGroup* DolphinViewActionHandler::createSortByActionGroup()
     sortByActionGroup->addAction(sortByName);
 
     const AdditionalInfoAccessor& infoAccessor = AdditionalInfoAccessor::instance();
-    const KFileItemDelegate::InformationList infoKeys = infoAccessor.keys();
-    foreach (KFileItemDelegate::Information info, infoKeys) {
+    const QList<DolphinView::AdditionalInfo> infoList = infoAccessor.keys();
+    foreach (DolphinView::AdditionalInfo info, infoList) {
         const QString name = infoAccessor.actionCollectionName(info, AdditionalInfoAccessor::SortByType);
         KToggleAction* action = m_actionCollection->add<KToggleAction>(name);
         action->setText(infoAccessor.translation(info));
@@ -289,11 +294,12 @@ void DolphinViewActionHandler::slotDeleteItems()
 void DolphinViewActionHandler::togglePreview(bool show)
 {
     emit actionBeingHandled();
-    m_currentView->setShowPreview(show);
+    m_currentView->setPreviewsShown(show);
 }
 
-void DolphinViewActionHandler::slotShowPreviewChanged()
+void DolphinViewActionHandler::slotPreviewsShownChanged(bool shown)
 {
+    Q_UNUSED(shown);
     // It is not enough to update the 'Show Preview' action, also
     // the 'Zoom In' and 'Zoom Out' actions must be adapted.
     updateViewActions();
@@ -306,8 +312,8 @@ QString DolphinViewActionHandler::currentViewModeActionName() const
         return "icons";
     case DolphinView::DetailsView:
         return "details";
-    case DolphinView::ColumnView:
-        return "columns";
+    case DolphinView::CompactView:
+        return "compact";
     }
     return QString(); // can't happen
 }
@@ -328,17 +334,17 @@ void DolphinViewActionHandler::updateViewActions()
     }
 
     QAction* showPreviewAction = m_actionCollection->action("show_preview");
-    showPreviewAction->setChecked(m_currentView->showPreview());
+    showPreviewAction->setChecked(m_currentView->previewsShown());
 
     slotSortOrderChanged(m_currentView->sortOrder());
     slotSortFoldersFirstChanged(m_currentView->sortFoldersFirst());
-    slotAdditionalInfoChanged();
-    slotCategorizedSortingChanged();
+    slotAdditionalInfoListChanged(m_currentView->additionalInfoList(), QList<DolphinView::AdditionalInfo>());
+    slotCategorizedSortingChanged(m_currentView->categorizedSorting());
     slotSortingChanged(m_currentView->sorting());
-    slotZoomLevelChanged(m_currentView->zoomLevel());
+    slotZoomLevelChanged(m_currentView->zoomLevel(), -1);
 
     QAction* showHiddenFilesAction = m_actionCollection->action("show_hidden_files");
-    showHiddenFilesAction->setChecked(m_currentView->showHiddenFiles());
+    showHiddenFilesAction->setChecked(m_currentView->hiddenFilesShown());
 }
 
 void DolphinViewActionHandler::zoomIn()
@@ -385,10 +391,10 @@ void DolphinViewActionHandler::toggleAdditionalInfo(QAction* action)
 {
     emit actionBeingHandled();
 
-    const KFileItemDelegate::Information info =
-        static_cast<KFileItemDelegate::Information>(action->data().toInt());
+    const DolphinView::AdditionalInfo info =
+        static_cast<DolphinView::AdditionalInfo>(action->data().toInt());
 
-    KFileItemDelegate::InformationList list = m_currentView->additionalInfo();
+    QList<DolphinView::AdditionalInfo> list = m_currentView->additionalInfoList();
 
     const bool show = action->isChecked();
 
@@ -396,17 +402,30 @@ void DolphinViewActionHandler::toggleAdditionalInfo(QAction* action)
     const bool containsInfo = (index >= 0);
     if (show && !containsInfo) {
         list.append(info);
-        m_currentView->setAdditionalInfo(list);
+        m_currentView->setAdditionalInfoList(list);
     } else if (!show && containsInfo) {
         list.removeAt(index);
-        m_currentView->setAdditionalInfo(list);
+        m_currentView->setAdditionalInfoList(list);
         Q_ASSERT(list.indexOf(info) < 0);
     }
 }
 
-void DolphinViewActionHandler::slotAdditionalInfoChanged()
+void DolphinViewActionHandler::slotAdditionalInfoListChanged(const QList<DolphinView::AdditionalInfo>& current,
+                                                             const QList<DolphinView::AdditionalInfo>& previous)
 {
-    m_currentView->updateAdditionalInfoActions(m_actionCollection);
+    Q_UNUSED(previous);
+
+    const AdditionalInfoAccessor& infoAccessor = AdditionalInfoAccessor::instance();
+
+    const QList<DolphinView::AdditionalInfo> checkedInfo = current;
+    const QList<DolphinView::AdditionalInfo> infoList = infoAccessor.keys();
+
+    foreach (DolphinView::AdditionalInfo info, infoList) {
+        const QString name = infoAccessor.actionCollectionName(info, AdditionalInfoAccessor::AdditionalInfoType);
+        QAction* action = m_actionCollection->action(name);
+        Q_ASSERT(action);
+        action->setChecked(checkedInfo.contains(info));
+    }
 }
 
 void DolphinViewActionHandler::toggleSortCategorization(bool categorizedSorting)
@@ -414,23 +433,22 @@ void DolphinViewActionHandler::toggleSortCategorization(bool categorizedSorting)
     m_currentView->setCategorizedSorting(categorizedSorting);
 }
 
-void DolphinViewActionHandler::slotCategorizedSortingChanged()
+void DolphinViewActionHandler::slotCategorizedSortingChanged(bool sortCategorized)
 {
     QAction* showInGroupsAction = m_actionCollection->action("show_in_groups");
-    showInGroupsAction->setChecked(m_currentView->categorizedSorting());
-    showInGroupsAction->setEnabled(m_currentView->supportsCategorizedSorting());
+    showInGroupsAction->setChecked(sortCategorized);
 }
 
 void DolphinViewActionHandler::toggleShowHiddenFiles(bool show)
 {
     emit actionBeingHandled();
-    m_currentView->setShowHiddenFiles(show);
+    m_currentView->setHiddenFilesShown(show);
 }
 
-void DolphinViewActionHandler::slotShowHiddenFilesChanged()
+void DolphinViewActionHandler::slotHiddenFilesShownChanged(bool shown)
 {
     QAction* showHiddenFilesAction = m_actionCollection->action("show_hidden_files");
-    showHiddenFilesAction->setChecked(m_currentView->showHiddenFiles());
+    showHiddenFilesAction->setChecked(shown);
 }
 
 
@@ -445,28 +463,28 @@ KToggleAction* DolphinViewActionHandler::iconsModeAction()
     return iconsView;
 }
 
+KToggleAction* DolphinViewActionHandler::compactModeAction()
+{
+    KToggleAction* iconsView = m_actionCollection->add<KToggleAction>("compact");
+    iconsView->setText(i18nc("@action:inmenu View Mode", "Compact"));
+    iconsView->setToolTip(i18nc("@info", "Compact view mode"));
+    iconsView->setShortcut(Qt::CTRL | Qt::Key_2);
+    iconsView->setIcon(KIcon("view-list-details")); // TODO: discuss with Oxygen-team the wrong (?) name
+    iconsView->setData(QVariant::fromValue(DolphinView::CompactView));
+    return iconsView;
+}
+
 KToggleAction* DolphinViewActionHandler::detailsModeAction()
 {
     KToggleAction* detailsView = m_actionCollection->add<KToggleAction>("details");
     detailsView->setText(i18nc("@action:inmenu View Mode", "Details"));
     detailsView->setToolTip(i18nc("@info", "Details view mode"));
-    detailsView->setShortcut(Qt::CTRL | Qt::Key_2);
-    detailsView->setIcon(KIcon("view-list-details"));
+    detailsView->setShortcut(Qt::CTRL | Qt::Key_3);
+    detailsView->setIcon(KIcon("view-list-text"));
     detailsView->setData(QVariant::fromValue(DolphinView::DetailsView));
     return detailsView;
 }
 
-KToggleAction* DolphinViewActionHandler::columnsModeAction()
-{
-    KToggleAction* columnView = m_actionCollection->add<KToggleAction>("columns");
-    columnView->setText(i18nc("@action:inmenu View Mode", "Columns"));
-    columnView->setToolTip(i18nc("@info", "Columns view mode"));
-    columnView->setShortcut(Qt::CTRL | Qt::Key_3);
-    columnView->setIcon(KIcon("view-file-columns"));
-    columnView->setData(QVariant::fromValue(DolphinView::ColumnView));
-    return columnView;
-}
-
 void DolphinViewActionHandler::slotSortingChanged(DolphinView::Sorting sorting)
 {
     QAction* action = 0;
@@ -474,8 +492,8 @@ void DolphinViewActionHandler::slotSortingChanged(DolphinView::Sorting sorting)
         action = m_actionCollection->action("sort_by_name");
     } else {
         const AdditionalInfoAccessor& infoAccessor = AdditionalInfoAccessor::instance();
-        const KFileItemDelegate::InformationList infoKeys = infoAccessor.keys();
-        foreach (const KFileItemDelegate::Information info, infoKeys) {
+        const QList<DolphinView::AdditionalInfo> infoList = infoAccessor.keys();
+        foreach (DolphinView::AdditionalInfo info, infoList) {
             if (sorting == infoAccessor.sorting(info)) {
                 const QString name = infoAccessor.actionCollectionName(info, AdditionalInfoAccessor::SortByType);
                 action = m_actionCollection->action(name);
@@ -492,16 +510,18 @@ void DolphinViewActionHandler::slotSortingChanged(DolphinView::Sorting sorting)
     }
 }
 
-void DolphinViewActionHandler::slotZoomLevelChanged(int level)
+void DolphinViewActionHandler::slotZoomLevelChanged(int current, int previous)
 {
+    Q_UNUSED(previous);
+
     QAction* zoomInAction = m_actionCollection->action(KStandardAction::name(KStandardAction::ZoomIn));
     if (zoomInAction) {
-        zoomInAction->setEnabled(level < ZoomLevelInfo::maximumLevel());
+        zoomInAction->setEnabled(current < ZoomLevelInfo::maximumLevel());
     }
 
     QAction* zoomOutAction = m_actionCollection->action(KStandardAction::name(KStandardAction::ZoomOut));
     if (zoomOutAction) {
-        zoomOutAction->setEnabled(level > ZoomLevelInfo::minimumLevel());
+        zoomOutAction->setEnabled(current > ZoomLevelInfo::minimumLevel());
     }
 }
 
index 72e768375df1fa112d9f74530b1d65dfea5b93de..4e5a0d32f09046198e789679ae0fa34716a8944d 100644 (file)
@@ -124,7 +124,7 @@ private Q_SLOTS:
     void togglePreview(bool);
 
     /** Updates the state of the 'Show preview' menu action. */
-    void slotShowPreviewChanged();
+    void slotPreviewsShownChanged(bool shown);
 
     /** Increases the size of the current set view mode. */
     void zoomIn();
@@ -156,7 +156,7 @@ private Q_SLOTS:
     /**
      * Updates the state of the 'Zoom In' and 'Zoom Out' actions.
      */
-    void slotZoomLevelChanged(int level);
+    void slotZoomLevelChanged(int current, int previous);
 
     /**
      * Switches on or off the displaying of additional information
@@ -172,7 +172,8 @@ private Q_SLOTS:
     /**
      * Updates the state of the 'Additional Information' actions.
      */
-    void slotAdditionalInfoChanged();
+    void slotAdditionalInfoListChanged(const QList<DolphinView::AdditionalInfo>& current,
+                                       const QList<DolphinView::AdditionalInfo>& previous);
 
     /**
      * Switches between sorting by categories or not.
@@ -182,7 +183,7 @@ private Q_SLOTS:
     /**
      * Updates the state of the 'Categorized sorting' menu action.
      */
-    void slotCategorizedSortingChanged();
+    void slotCategorizedSortingChanged(bool sortCategorized);
 
     /**
      * Switches between showing and hiding of hidden marked files
@@ -192,7 +193,7 @@ private Q_SLOTS:
     /**
      * Updates the state of the 'Show hidden files' menu action.
      */
-    void slotShowHiddenFilesChanged();
+    void slotHiddenFilesShownChanged(bool shown);
 
     /**
      * Opens the view properties dialog, which allows to modify the properties
@@ -234,16 +235,16 @@ private:
     KToggleAction* iconsModeAction();
 
     /**
-     * Returns the "switch to details mode" action.
+     * Returns the "switch to compact mode" action.
      * Helper method for createActions();
      */
-    KToggleAction* detailsModeAction();
+    KToggleAction* compactModeAction();
 
     /**
-     * Returns the "switch to columns mode" action.
+     * Returns the "switch to details mode" action.
      * Helper method for createActions();
      */
-    KToggleAction* columnsModeAction();
+    KToggleAction* detailsModeAction();
 
     KActionCollection* m_actionCollection;
     DolphinView* m_currentView;
diff --git a/src/views/dolphinviewcontroller.cpp b/src/views/dolphinviewcontroller.cpp
deleted file mode 100644 (file)
index e182e48..0000000
+++ /dev/null
@@ -1,257 +0,0 @@
-/***************************************************************************
- *   Copyright (C) 2010 by Peter Penz <peter.penz19@gmail.com>             *
- *                                                                         *
- *   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 program 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 program; if not, write to the                         *
- *   Free Software Foundation, Inc.,                                       *
- *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA            *
- ***************************************************************************/
-
-#include "dolphinviewcontroller.h"
-#include "zoomlevelinfo.h"
-
-#include <KDirModel>
-#include <KFileItemActions>
-#include <QAbstractProxyModel>
-#include <QApplication>
-#include <QClipboard>
-#include <QDir>
-
-Qt::MouseButtons DolphinViewController::m_mouseButtons = Qt::NoButton;
-
-DolphinViewController::DolphinViewController(DolphinView* dolphinView) :
-    QObject(dolphinView),
-    m_dolphinView(dolphinView),
-    m_itemView(0),
-    m_versionControlActions()
-{
-}
-
-DolphinViewController::~DolphinViewController()
-{
-}
-
-const DolphinView* DolphinViewController::view() const
-{
-    return m_dolphinView;
-}
-
-void DolphinViewController::requestUrlChange(const KUrl& url)
-{
-    emit urlChangeRequested(url);
-}
-
-void DolphinViewController::setItemView(QAbstractItemView* view)
-{
-    if (m_itemView) {
-        disconnect(m_itemView, SIGNAL(pressed(const QModelIndex&)),
-                   this, SLOT(updateMouseButtonState()));
-    }
-
-    m_itemView = view;
-
-    if (m_itemView) {
-        // TODO: this is a workaround until  Qt-issue 176832 has been fixed
-        connect(m_itemView, SIGNAL(pressed(const QModelIndex&)),
-                this, SLOT(updateMouseButtonState()));
-    }
-}
-
-QAbstractItemView* DolphinViewController::itemView() const
-{
-    return m_itemView;
-}
-
-void DolphinViewController::triggerContextMenuRequest(const QPoint& pos,
-                                                  const QList<QAction*>& customActions)
-{
-    emit activated();
-    emit requestContextMenu(pos, customActions);
-}
-
-void DolphinViewController::requestActivation()
-{
-    emit activated();
-}
-
-void DolphinViewController::indicateDroppedUrls(const KFileItem& destItem, QDropEvent* event)
-{
-    emit urlsDropped(destItem, m_dolphinView->url(), event);
-}
-
-
-void DolphinViewController::indicateSortingChange(DolphinView::Sorting sorting)
-{
-    emit sortingChanged(sorting);
-}
-
-void DolphinViewController::indicateSortOrderChange(Qt::SortOrder order)
-{
-    emit sortOrderChanged(order);
-}
-
-void DolphinViewController::indicateSortFoldersFirstChange(bool foldersFirst)
-{
-    emit sortFoldersFirstChanged(foldersFirst);
-}
-
-void DolphinViewController::indicateAdditionalInfoChange(const KFileItemDelegate::InformationList& info)
-{
-    emit additionalInfoChanged(info);
-}
-
-void DolphinViewController::setVersionControlActions(QList<QAction*> actions)
-{
-    m_versionControlActions = actions;
-}
-
-QList<QAction*> DolphinViewController::versionControlActions(const KFileItemList& items)
-{
-    emit requestVersionControlActions(items);
-    // All view implementations are connected with the signal requestVersionControlActions()
-    // (see ViewExtensionFactory) and will invoke DolphinViewController::setVersionControlActions(),
-    // so that the context dependent actions can be returned.
-    return m_versionControlActions;
-}
-
-void DolphinViewController::handleKeyPressEvent(QKeyEvent* event)
-{
-    if (!m_itemView) {
-        return;
-    }
-
-    const QItemSelectionModel* selModel = m_itemView->selectionModel();
-    const QModelIndex currentIndex = selModel->currentIndex();
-    const bool trigger = currentIndex.isValid()
-                         && ((event->key() == Qt::Key_Return) || (event->key() == Qt::Key_Enter))
-                         && !selModel->selectedIndexes().isEmpty();
-    if (!trigger) {
-        return;
-    }
-
-    // Collect selected files and selected directories
-    // as two separate lists.
-    QModelIndexList dirQueue;
-    const QModelIndexList indexList = selModel->selectedIndexes();
-    KFileItemList fileOpenList;
-    foreach (const QModelIndex& index, indexList) {
-        if (itemForIndex(index).isDir()) {
-            dirQueue << index;
-        } else {
-            fileOpenList << itemForIndex(index);
-        }
-    }
-
-    // Handle selected files
-    if (fileOpenList.count() == 1) {
-        emit itemTriggered(fileOpenList.first());
-    } else {
-        KFileItemActions fileItemActions;
-        fileItemActions.runPreferredApplications(fileOpenList, "DesktopEntryName != 'dolphin'");
-    }
-
-    // Handle selected directories
-    if (dirQueue.count() == 1) {
-        // Open directory in the view
-        emit itemTriggered(itemForIndex(dirQueue[0]));
-    } else {
-        // Open directories in separate tabs
-        foreach(const QModelIndex& dir, dirQueue) {
-            emit tabRequested(itemForIndex(dir).url());
-        }
-    }
-}
-
-void DolphinViewController::replaceUrlByClipboard()
-{
-    const QClipboard* clipboard = QApplication::clipboard();
-    QString text;
-    if (clipboard->mimeData(QClipboard::Selection)->hasText()) {
-        text = clipboard->mimeData(QClipboard::Selection)->text();
-    } else if (clipboard->mimeData(QClipboard::Clipboard)->hasText()) {
-        text = clipboard->mimeData(QClipboard::Clipboard)->text();
-    }
-    if (!text.isEmpty() && QDir::isAbsolutePath(text)) {
-        m_dolphinView->setUrl(KUrl(text));
-    }
-}
-
-void DolphinViewController::requestToolTipHiding()
-{
-    emit hideToolTip();
-}
-
-void DolphinViewController::emitItemTriggered(const KFileItem& item)
-{
-    emit itemTriggered(item);
-}
-
-KFileItem DolphinViewController::itemForIndex(const QModelIndex& index) const
-{
-    if (m_itemView) {
-        QAbstractProxyModel* proxyModel = static_cast<QAbstractProxyModel*>(m_itemView->model());
-        if (proxyModel) {
-            KDirModel* dirModel = static_cast<KDirModel*>(proxyModel->sourceModel());
-            const QModelIndex dirIndex = proxyModel->mapToSource(index);
-            return dirModel->itemForIndex(dirIndex);
-        }
-    }
-
-    return KFileItem();
-}
-
-void DolphinViewController::triggerItem(const QModelIndex& index)
-{
-    if (m_mouseButtons & Qt::LeftButton) {
-        const KFileItem item = itemForIndex(index);
-        if (index.isValid() && (index.column() == KDirModel::Name)) {
-            emit itemTriggered(item);
-        } else if (m_itemView) {
-            m_itemView->clearSelection();
-            emit itemEntered(KFileItem());
-        }
-    }
-}
-
-void DolphinViewController::requestTab(const QModelIndex& index)
-{
-    if (m_mouseButtons & Qt::MidButton) {
-        const KFileItem item = itemForIndex(index);
-        const bool validRequest = index.isValid() &&
-                                  (index.column() == KDirModel::Name) &&
-                                  (item.isDir() || m_dolphinView->isTabsForFilesEnabled());
-        if (validRequest) {
-            emit tabRequested(item.url());
-        }
-    }
-}
-
-void DolphinViewController::emitItemEntered(const QModelIndex& index)
-{
-    KFileItem item = itemForIndex(index);
-    if (!item.isNull()) {
-        emit itemEntered(item);
-    }
-}
-
-void DolphinViewController::emitViewportEntered()
-{
-    emit viewportEntered();
-}
-
-void DolphinViewController::updateMouseButtonState()
-{
-    m_mouseButtons = QApplication::mouseButtons();
-}
-
-#include "dolphinviewcontroller.moc"
diff --git a/src/views/dolphinviewcontroller.h b/src/views/dolphinviewcontroller.h
deleted file mode 100644 (file)
index 0616e7f..0000000
+++ /dev/null
@@ -1,311 +0,0 @@
-/***************************************************************************
- *   Copyright (C) 2010 by Peter Penz <peter.penz19@gmail.com>             *
- *                                                                         *
- *   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 program 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 program; if not, write to the                         *
- *   Free Software Foundation, Inc.,                                       *
- *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA            *
- ***************************************************************************/
-
-#ifndef DOLPHINVIEWCONTROLLER_H
-#define DOLPHINVIEWCONTROLLER_H
-
-#include <views/dolphinview.h>
-#include <KUrl>
-#include <QObject>
-#include <libdolphin_export.h>
-
-class QAbstractItemView;
-class DolphinView;
-class KUrl;
-class QPoint;
-
-/**
- * @brief Allows the view mode implementations (DolphinIconsView, DolphinDetailsView, DolphinColumnView)
- *        to do a limited control of the DolphinView.
- *
- * The DolphinView connects to the signals of DolphinViewController to react on changes
- * that have been triggered by the view mode implementations. The view mode implementations
- * have read access to the whole DolphinView by DolphinViewController::view(). Limited control of the
- * DolphinView by the view mode implementations are defined by the public DolphinViewController methods.
- */
-class LIBDOLPHINPRIVATE_EXPORT DolphinViewController : public QObject
-{
-    Q_OBJECT
-
-public:
-    explicit DolphinViewController(DolphinView* dolphinView);
-    virtual ~DolphinViewController();
-
-    /**
-     * Allows read access for the view mode implementation
-     * to the DolphinView.
-     */
-    const DolphinView* view() const;
-
-    /**
-     * Requests the DolphinView to change the URL to \p url. The signal
-     * urlChangeRequested will be emitted.
-     */
-    void requestUrlChange(const KUrl& url);
-
-    /**
-     * Changes the current view mode implementation where the controller is working.
-     * This is only necessary for views like the column view, where internally
-     * several QAbstractItemView instances are used.
-     */
-    void setItemView(QAbstractItemView* view);
-    QAbstractItemView* itemView() const;
-
-    /**
-     * Requests a context menu for the position \a pos. DolphinView
-     * takes care itself to get the selected items depending from
-     * \a pos. It is possible to define a custom list of actions for
-     * the context menu by \a customActions.
-     */
-    void triggerContextMenuRequest(const QPoint& pos,
-                                   const QList<QAction*>& customActions = QList<QAction*>());
-
-    /**
-     * Requests an activation of the DolphinView and emits the signal
-     * activated(). This method should be invoked by the view mode implementation
-     * if e. g. a mouse click on the view has been done.
-     */
-    void requestActivation();
-
-    /**
-     * Indicates that URLs are dropped above a destination. The DolphinView
-     * will start the corresponding action (copy, move, link).
-     * @param destItem  Item of the destination (can be null, see KFileItem::isNull()).
-     * @param event     Drop event
-     */
-    void indicateDroppedUrls(const KFileItem& destItem, QDropEvent* event);
-
-    /**
-     * Informs the DolphinView about a sorting change done inside
-     * the view mode implementation.
-     */
-    void indicateSortingChange(DolphinView::Sorting sorting);
-
-    /**
-     * Informs the DolphinView about a sort order change done inside
-     * the view mode implementation.
-     */
-    void indicateSortOrderChange(Qt::SortOrder order);
-
-    /**
-     * Informs the DolphinView about a change between separate sorting
-     * (with folders first) and mixed sorting of files and folders done inside
-     * the view mode implementation.
-     */
-    void indicateSortFoldersFirstChange(bool foldersFirst);
-
-    /**
-     * Informs the DolphinView about an additional information change
-     * done inside the view mode implementation.
-     */
-    void indicateAdditionalInfoChange(const KFileItemDelegate::InformationList& info);
-
-    /**
-     * Sets the available version control actions. Is called by the view
-     * mode implementation as soon as the DolphinView has requested them by the signal
-     * requestVersionControlActions().
-     */
-    void setVersionControlActions(QList<QAction*> actions);
-
-    /**
-     * Emits the signal requestVersionControlActions(). The view mode implementation
-     * listens to the signal and will invoke a DolphinViewController::setVersionControlActions()
-     * and the result will be returned.
-     */
-    QList<QAction*> versionControlActions(const KFileItemList& items);
-
-    /**
-     * Must be be invoked in each view mode implementation whenever a key has been
-     * pressed. If the selection model of \a view is not empty and
-     * the return key has been pressed, the selected items will get triggered.
-     */
-    void handleKeyPressEvent(QKeyEvent* event);
-
-    /**
-     * Replaces the URL of the DolphinView  with the content
-     * of the clipboard as URL. If the clipboard contains no text,
-     * nothing will be done.
-     */
-    void replaceUrlByClipboard();
-
-    /**
-     * Requests the view mode implementation to hide tooltips.
-     */
-    void requestToolTipHiding();
-
-    /**
-     * Emits the signal itemTriggered() for the item \a item.
-     * The method can be used by the view mode implementations to
-     * trigger an item directly without mouse interaction.
-     * If the item triggering is done by the mouse, it is recommended
-     * to use DolphinViewController::triggerItem(), as this will check
-     * the used mouse buttons to execute the correct action.
-     */
-    void emitItemTriggered(const KFileItem& item);
-
-    /**
-     * Returns the file item for the proxy index \a index of the DolphinView.
-     */
-    KFileItem itemForIndex(const QModelIndex& index) const;
-
-public slots:
-    /**
-     * Emits the signal itemTriggered() if the file item for the index \a index
-     * is not null and the left mouse button has been pressed. If the item is
-     * null, the signal itemEntered() is emitted.
-     * The method should be invoked by the view mode implementations whenever the
-     * user has triggered an item with the mouse (see
-     * QAbstractItemView::clicked() or QAbstractItemView::doubleClicked()).
-     */
-    void triggerItem(const QModelIndex& index);
-
-    /**
-     * Emits the signal tabRequested(), if the file item for the index \a index
-     * represents a directory and when the middle mouse button has been pressed.
-     */
-    void requestTab(const QModelIndex& index);
-
-    /**
-     * Emits the signal itemEntered() if the file item for the index \a index
-     * is not null. The method should be invoked by the view mode implementation
-     * whenever the mouse cursor is above an item.
-     */
-    void emitItemEntered(const QModelIndex& index);
-
-    /**
-     * Emits the signal viewportEntered(). The method should be invoked by
-     * the view mode implementation whenever the mouse cursor is above the viewport.
-     */
-    void emitViewportEntered();
-
-signals:
-    void urlChangeRequested(const KUrl& url);
-
-    /**
-     * Is emitted if a context menu should be opened (see triggerContextMenuRequest()).
-     * @param pos           Position relative to the view widget where the
-     *                      context menu should be opened. It is recommended
-     *                      to get the corresponding model index from
-     *                      this position.
-     * @param customActions List of actions that is added to the context menu when
-     *                      the menu is opened above the viewport.
-     */
-    void requestContextMenu(const QPoint& pos, QList<QAction*> customActions);
-
-    /**
-     * Is emitted if the view has been activated by e. g. a mouse click.
-     */
-    void activated();
-
-    /**
-     * Is emitted if URLs have been dropped to the destination
-     * path \a destPath. If the URLs have been dropped above an item of
-     * the destination path, the item is indicated by \a destItem
-     * (can be null, see KFileItem::isNull()).
-     */
-    void urlsDropped(const KFileItem& destItem,
-                     const KUrl& destPath,
-                     QDropEvent* event);
-
-    /**
-     * Is emitted if the sorting has been changed to \a sorting by
-     * the view mode implementation (see indicateSortingChanged().
-     * The DolphinView connects to
-     * this signal to update its menu action.
-     */
-    void sortingChanged(DolphinView::Sorting sorting);
-
-    /**
-     * Is emitted if the sort order has been changed to \a order
-     * by the view mode implementation (see indicateSortOrderChanged().
-     * The DolphinView connects
-     * to this signal to update its menu actions.
-     */
-    void sortOrderChanged(Qt::SortOrder order);
-
-    /**
-     * Is emitted if 'sort folders first' has been changed to \a foldersFirst
-     * by the view mode implementation (see indicateSortOrderChanged().
-     * The DolphinView connects
-     * to this signal to update its menu actions.
-     */
-    void sortFoldersFirstChanged(bool foldersFirst);
-
-    /**
-     * Is emitted if the additional info has been changed to \a info
-     * by the view mode implementation. The DolphinView connects
-     * to this signal to update its menu actions.
-     */
-    void additionalInfoChanged(const KFileItemDelegate::InformationList& info);
-
-    /**
-     * Is emitted if the item \a item should be triggered. The abstract
-     * Dolphin view connects to this signal. If the item represents a directory,
-     * the directory is opened. On a file the corresponding application is opened.
-     * The item is null (see KFileItem::isNull()), when clicking on the viewport itself.
-     */
-    void itemTriggered(const KFileItem& item);
-
-    /**
-     * Is emitted if the mouse cursor has entered the item
-     * given by \a index (see emitItemEntered()).
-     */
-    void itemEntered(const KFileItem& item);
-
-    /**
-     * Is emitted if a new tab should be opened for the URL \a url.
-     */
-    void tabRequested(const KUrl& url);
-
-    /**
-     * Is emitted if the mouse cursor has entered
-     * the viewport (see emitViewportEntered()).
-     */
-    void viewportEntered();
-
-    /**
-     * Is emitted, if DolphinViewController::requestToolTipHiding() is invoked
-     * and requests to hide all tooltips.
-     */
-    void hideToolTip();
-
-    /**
-     * Is emitted if pending previews should be canceled (e. g. because of an URL change).
-     */
-    void cancelPreviews();
-
-    /**
-     * Requests the view mode implementation to invoke DolphinViewController::setVersionControlActions(),
-     * so that they can be returned with DolphinViewController::versionControlActions() for
-     * the DolphinView.
-     */
-    void requestVersionControlActions(const KFileItemList& items);
-
-private slots:
-    void updateMouseButtonState();
-
-private:
-    static Qt::MouseButtons m_mouseButtons; // TODO: this is a workaround until  Qt-issue 176832 has been fixed
-
-    DolphinView* m_dolphinView;
-    QAbstractItemView* m_itemView;
-    QList<QAction*> m_versionControlActions;
-};
-
-#endif
index 830884dc2c800c1311959e413ce614e17fc2dbb1..c0c6ad58c1153daed7c15b3f7be661fb39bffb4d 100644 (file)
@@ -65,12 +65,9 @@ RenameDialog::RenameDialog(QWidget *parent, const KFileItemList& items) :
 
     QLabel* editLabel = 0;
     if (m_renameOneItem) {
-        m_newName =  items.first().name();
-        editLabel = new QLabel(i18nc("@label:textbox", "Rename the item <filename>%1</filename> to:",
-                                     KStringHandler::csqueeze(m_newName)), page);
-        if (m_newName.size() > 40) {
-            editLabel->setToolTip(m_newName); // Set the filename as a the tool tip...
-        }
+        m_newName = items.first().name();
+        editLabel = new QLabel(i18nc("@label:textbox", "Rename the item <filename>%1</filename> to:", m_newName),
+                               page);
     } else {
         m_newName = i18nc("@info:status", "New name #");
         editLabel = new QLabel(i18ncp("@label:textbox",
diff --git a/src/views/selectionmanager.cpp b/src/views/selectionmanager.cpp
deleted file mode 100644 (file)
index 7a9e814..0000000
+++ /dev/null
@@ -1,278 +0,0 @@
-/***************************************************************************
- *   Copyright (C) 2008 by Peter Penz <peter.penz19@gmail.com>             *
- *                                                                         *
- *   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 program 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 program; if not, write to the                         *
- *   Free Software Foundation, Inc.,                                       *
- *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA            *
- ***************************************************************************/
-
-#include "selectionmanager.h"
-
-#include "dolphinmodel.h"
-#include "dolphin_generalsettings.h"
-#include "selectiontoggle.h"
-#include "settings/dolphinsettings.h"
-#include <KDirModel>
-#include <KGlobalSettings>
-#include <KIconEffect>
-
-#include <QAbstractButton>
-#include <QAbstractItemView>
-#include <QAbstractProxyModel>
-#include <QApplication>
-#include <QModelIndex>
-#include <QPainter>
-#include <QPaintEvent>
-#include <QRect>
-#include <QTimeLine>
-
-SelectionManager::SelectionManager(QAbstractItemView* parent) :
-    QObject(parent),
-    m_view(parent),
-    m_toggle(0),
-    m_connected(false),
-    m_appliedPointingHandCursor(false)
-{
-    connect(parent, SIGNAL(entered(const QModelIndex&)),
-            this, SLOT(slotEntered(const QModelIndex&)));
-    connect(parent, SIGNAL(viewportEntered()),
-            this, SLOT(slotViewportEntered()));
-
-    const GeneralSettings* settings = DolphinSettings::instance().generalSettings();
-    if (settings->showSelectionToggle()) {
-        m_toggle = new SelectionToggle(m_view->viewport());
-        m_toggle->setCheckable(true);
-        m_toggle->hide();
-        connect(m_toggle, SIGNAL(clicked(bool)),
-                this, SLOT(setItemSelected(bool)));
-        m_toggle->installEventFilter(this);
-    }
-
-    m_view->viewport()->installEventFilter(this);
-}
-
-SelectionManager::~SelectionManager()
-{
-}
-
-bool SelectionManager::eventFilter(QObject* watched, QEvent* event)
-{
-    if (watched == m_view->viewport()) {
-        switch (event->type()) {
-        case QEvent::Leave:
-            if (m_toggle) {
-                m_toggle->hide();
-            }
-            restoreCursor();
-            break;
-
-        case QEvent::MouseButtonPress: {
-            // Set the toggle invisible, if a mouse button has been pressed
-            // outside the toggle boundaries. This e.g. assures, that the toggle
-            // gets invisible during dragging items.
-            if (m_toggle) {
-                const QRect toggleBounds(m_toggle->mapToGlobal(QPoint(0, 0)), m_toggle->size());
-                m_toggle->setVisible(toggleBounds.contains(QCursor::pos()));
-            }
-            break;
-        }
-
-        default:
-            break;
-        }
-    } else if (watched == m_toggle) {
-        switch (event->type()) {
-        case QEvent::Enter:
-            QApplication::changeOverrideCursor(Qt::ArrowCursor);
-            break;
-
-        case QEvent::Leave:
-            QApplication::changeOverrideCursor(Qt::PointingHandCursor);
-            break;
-
-        default:
-            break;
-        }
-    }
-
-    return QObject::eventFilter(watched, event);
-}
-
-void SelectionManager::reset()
-{
-    if (m_toggle) {
-        m_toggle->reset();
-    }
-}
-
-void SelectionManager::slotEntered(const QModelIndex& index)
-{
-    const bool isSelectionCandidate = index.isValid() &&
-                                      (index.column() == DolphinModel::Name) &&
-                                      (QApplication::mouseButtons() == Qt::NoButton);
-
-    restoreCursor();
-    if (isSelectionCandidate && KGlobalSettings::singleClick()) {
-        applyPointingHandCursor();
-    }
-
-    if (isSelectionCandidate) {
-        if (!m_connected) {
-            connect(m_view->model(), SIGNAL(rowsRemoved(const QModelIndex&, int, int)),
-                    this, SLOT(slotRowsRemoved(const QModelIndex&, int, int)));
-            connect(m_view->selectionModel(),
-                    SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection&)),
-                    this,
-                    SLOT(slotSelectionChanged(const QItemSelection&, const QItemSelection&)));
-            m_connected = true;
-        }
-    } else {
-        disconnect(m_view->model(), SIGNAL(rowsRemoved(const QModelIndex&, int, int)),
-                   this, SLOT(slotRowsRemoved(const QModelIndex&, int, int)));
-        disconnect(m_view->selectionModel(),
-                   SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection&)),
-                   this,
-                   SLOT(slotSelectionChanged(const QItemSelection&, const QItemSelection&)));
-        m_connected = false;
-    }
-
-    if (!m_toggle) {
-        return;
-    }
-
-    m_toggle->hide();
-    if (isSelectionCandidate) {
-        m_toggle->setUrl(urlForIndex(index));
-
-        // Increase the size of the toggle for large items
-        const int iconHeight = m_view->iconSize().height();
-
-        int toggleSize = KIconLoader::SizeSmall;
-        if (iconHeight >= KIconLoader::SizeEnormous) {
-            toggleSize = KIconLoader::SizeMedium;
-        } else if (iconHeight >= KIconLoader::SizeLarge) {
-            toggleSize = KIconLoader::SizeSmallMedium;
-        }
-
-        // Add a small invisible margin, if the item-height is nearly
-        // equal to the toggleSize (#169494).
-        const QRect rect = m_view->visualRect(index);
-        int margin = (rect.height() - toggleSize) / 2;
-        if (margin > 4) {
-            margin = 0;
-        }
-        toggleSize += 2 * margin;
-        m_toggle->setMargin(margin);
-        m_toggle->resize(toggleSize, toggleSize);
-        m_toggle->move(rect.topLeft());
-
-        QItemSelectionModel* selModel = m_view->selectionModel();
-        m_toggle->setChecked(selModel->isSelected(index));
-        m_toggle->show();
-    } else {
-        m_toggle->setUrl(KUrl());
-    }
-}
-
-void SelectionManager::slotViewportEntered()
-{
-    if (m_toggle) {
-        m_toggle->hide();
-    }
-    restoreCursor();
-}
-
-void SelectionManager::setItemSelected(bool selected)
-{
-    emit selectionChanged();
-
-    if (m_toggle && !m_toggle->url().isEmpty()) {
-        const QModelIndex index = indexForUrl(m_toggle->url());
-        if (index.isValid()) {
-            QItemSelectionModel* selModel = m_view->selectionModel();
-            if (selected) {
-                selModel->select(index, QItemSelectionModel::Select);
-            } else {
-                selModel->select(index, QItemSelectionModel::Deselect);
-            }
-            selModel->setCurrentIndex(index, QItemSelectionModel::Current);
-        }
-    }
-}
-
-void SelectionManager::slotRowsRemoved(const QModelIndex& parent, int start, int end)
-{
-    Q_UNUSED(parent);
-    Q_UNUSED(start);
-    Q_UNUSED(end);
-    if (m_toggle) {
-        m_toggle->hide();
-    }
-    restoreCursor();
-}
-
-void SelectionManager::slotSelectionChanged(const QItemSelection& selected,
-                                            const QItemSelection& deselected)
-{
-    // The selection has been changed outside the scope of the selection manager
-    // (e. g. by the rubberband or the "Select All" action). Take care updating
-    // the state of the toggle button.
-    if (m_toggle && !m_toggle->url().isEmpty()) {
-        const QModelIndex index = indexForUrl(m_toggle->url());
-        if (index.isValid()) {
-            if (selected.contains(index)) {
-                m_toggle->setChecked(true);
-            }
-
-            if (deselected.contains(index)) {
-                m_toggle->setChecked(false);
-            }
-        }
-    }
-}
-
-KUrl SelectionManager::urlForIndex(const QModelIndex& index) const
-{
-    QAbstractProxyModel* proxyModel = static_cast<QAbstractProxyModel*>(m_view->model());
-    KDirModel* dirModel = static_cast<KDirModel*>(proxyModel->sourceModel());
-    const QModelIndex dirIndex = proxyModel->mapToSource(index);
-    return dirModel->itemForIndex(dirIndex).url();
-}
-
-const QModelIndex SelectionManager::indexForUrl(const KUrl& url) const
-{
-    QAbstractProxyModel* proxyModel = static_cast<QAbstractProxyModel*>(m_view->model());
-    KDirModel* dirModel = static_cast<KDirModel*>(proxyModel->sourceModel());
-    const QModelIndex dirIndex = dirModel->indexForUrl(url);
-    return proxyModel->mapFromSource(dirIndex);
-}
-
-
-void SelectionManager::applyPointingHandCursor()
-{
-    if (!m_appliedPointingHandCursor) {
-        QApplication::setOverrideCursor(QCursor(Qt::PointingHandCursor));
-        m_appliedPointingHandCursor = true;
-    }
-}
-
-void SelectionManager::restoreCursor()
-{
-    if (m_appliedPointingHandCursor) {
-        QApplication::restoreOverrideCursor();
-        m_appliedPointingHandCursor = false;
-    }
-}
-
-#include "selectionmanager.moc"
diff --git a/src/views/selectionmanager.h b/src/views/selectionmanager.h
deleted file mode 100644 (file)
index 7a3a194..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-/***************************************************************************
- *   Copyright (C) 2008 by Peter Penz <peter.penz19@gmail.com>             *
- *                                                                         *
- *   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 program 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 program; if not, write to the                         *
- *   Free Software Foundation, Inc.,                                       *
- *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA            *
- ***************************************************************************/
-
-#ifndef SELECTIONMANAGER_H
-#define SELECTIONMANAGER_H
-
-#include <KFileItem>
-
-#include <QObject>
-
-class QAbstractItemView;
-class QModelIndex;
-class QItemSelection;
-class SelectionToggle;
-
-/**
- * @brief Allows to select and deselect items for item views.
- *
- * Whenever an item is hovered by the mouse, a toggle button is shown
- * which allows to select/deselect the current item.
- */
-class SelectionManager : public QObject
-{
-    Q_OBJECT
-
-public:
-    SelectionManager(QAbstractItemView* parent);
-    virtual ~SelectionManager();
-    virtual bool eventFilter(QObject* watched, QEvent* event);
-
-public slots:
-    /**
-     * Resets the selection manager so that the toggle button gets
-     * invisible.
-     */
-    void reset();
-
-signals:
-    /** Is emitted if the selection has been changed by the toggle button. */
-    void selectionChanged();
-
-private slots:
-    void slotEntered(const QModelIndex& index);
-    void slotViewportEntered();
-    void setItemSelected(bool selected);
-    void slotRowsRemoved(const QModelIndex& parent, int start, int end);
-    void slotSelectionChanged(const QItemSelection& selected, const QItemSelection& deselected);
-
-private:
-    KUrl urlForIndex(const QModelIndex& index) const;
-    const QModelIndex indexForUrl(const KUrl& url) const;
-    void applyPointingHandCursor();
-    void restoreCursor();
-
-private:
-    QAbstractItemView* m_view;
-    SelectionToggle* m_toggle;
-    bool m_connected;
-    bool m_appliedPointingHandCursor;
-};
-
-#endif
diff --git a/src/views/selectiontoggle.cpp b/src/views/selectiontoggle.cpp
deleted file mode 100644 (file)
index d602600..0000000
+++ /dev/null
@@ -1,241 +0,0 @@
-/***************************************************************************
- *   Copyright (C) 2008 by Peter Penz <peter.penz19@gmail.com>             *
- *                                                                         *
- *   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 program 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 program; if not, write to the                         *
- *   Free Software Foundation, Inc.,                                       *
- *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA            *
- ***************************************************************************/
-
-#include "selectiontoggle.h"
-
-#include <KGlobalSettings>
-#include <KIcon>
-#include <KIconLoader>
-#include <KIconEffect>
-#include <KLocale>
-
-#include <QApplication>
-#include <QPainter>
-#include <QPaintEvent>
-#include <QRect>
-#include <QTimer>
-#include <QTimeLine>
-
-#include <KDebug>
-
-SelectionToggle::SelectionToggle(QWidget* parent) :
-    QAbstractButton(parent),
-    m_isHovered(false),
-    m_leftMouseButtonPressed(false),
-    m_fadingValue(0),
-    m_margin(0),
-    m_icon(),
-    m_fadingTimeLine(0)
-{
-    setFocusPolicy(Qt::NoFocus);
-    parent->installEventFilter(this);
-    resize(sizeHint());
-    setIconOverlay(isChecked());
-    connect(this, SIGNAL(toggled(bool)),
-            this, SLOT(setIconOverlay(bool)));
-    connect(KGlobalSettings::self(), SIGNAL(iconChanged(int)),
-            this, SLOT(refreshIcon()));
-}
-
-SelectionToggle::~SelectionToggle()
-{
-}
-
-QSize SelectionToggle::sizeHint() const
-{
-    return QSize(16, 16);
-}
-
-void SelectionToggle::reset()
-{
-    m_url = KUrl();
-    hide();
-}
-
-void SelectionToggle::setUrl(const KUrl& url)
-{
-    m_url = url;
-    if (!url.isEmpty()) {
-        startFading();
-    }
-}
-
-void SelectionToggle::setMargin(int margin)
-{
-    if (margin != m_margin) {
-        m_margin = margin;
-        update();
-    }
-}
-
-int SelectionToggle::margin() const
-{
-    return m_margin;
-}
-
-KUrl SelectionToggle::url() const
-{
-    return m_url;
-}
-
-void SelectionToggle::setVisible(bool visible)
-{
-    QAbstractButton::setVisible(visible);
-
-    stopFading();
-    if (visible) {
-        startFading();
-    }
-
-}
-
-bool SelectionToggle::eventFilter(QObject* obj, QEvent* event)
-{
-    if ((obj == parent()) && (event->type() == QEvent::MouseMove) && m_leftMouseButtonPressed) {
-        // Don't forward mouse move events to the viewport,
-        // otherwise a rubberband selection will be shown when
-        // clicking on the selection toggle and moving the mouse
-        // above the viewport.
-        return true;
-    }
-
-    return QAbstractButton::eventFilter(obj, event);
-}
-
-void SelectionToggle::enterEvent(QEvent* event)
-{
-    QAbstractButton::enterEvent(event);
-
-    // if the mouse cursor is above the selection toggle, display
-    // it immediately without fading timer
-    m_isHovered = true;
-    if (m_fadingTimeLine) {
-        m_fadingTimeLine->stop();
-    }
-    m_fadingValue = 255;
-    setToolTip(isChecked() ? i18nc("@info:tooltip", "Deselect Item") :
-                             i18nc("@info:tooltip", "Select Item"));
-    update();
-}
-
-void SelectionToggle::leaveEvent(QEvent* event)
-{
-    QAbstractButton::leaveEvent(event);
-
-    m_isHovered = false;
-    update();
-}
-
-void SelectionToggle::mousePressEvent(QMouseEvent* event)
-{
-    QAbstractButton::mousePressEvent(event);
-    m_leftMouseButtonPressed = (event->buttons() & Qt::LeftButton);
-}
-
-void SelectionToggle::mouseReleaseEvent(QMouseEvent* event)
-{
-    QAbstractButton::mouseReleaseEvent(event);
-    m_leftMouseButtonPressed = (event->buttons() & Qt::LeftButton);
-}
-
-void SelectionToggle::resizeEvent(QResizeEvent* event)
-{
-    QAbstractButton::resizeEvent(event);
-    setIconOverlay(isChecked());
-}
-
-void SelectionToggle::paintEvent(QPaintEvent* event)
-{
-    QPainter painter(this);
-    painter.setClipRect(event->rect());
-
-    // draw the icon overlay
-    const QPoint pos(m_margin, m_margin);
-    if (m_isHovered) {
-        KIconEffect *iconEffect = KIconLoader::global()->iconEffect();
-        QPixmap activeIcon = iconEffect->apply(m_icon, KIconLoader::Desktop, KIconLoader::ActiveState);
-        painter.drawPixmap(pos, activeIcon);
-    } else {
-        if (m_fadingValue < 255) {
-            // apply an alpha mask respecting the fading value to the icon
-            QPixmap icon = m_icon;
-            QPixmap alphaMask(icon.width(), icon.height());
-            const QColor color(m_fadingValue, m_fadingValue, m_fadingValue);
-            alphaMask.fill(color);
-            icon.setAlphaChannel(alphaMask);
-            painter.drawPixmap(pos, icon);
-        } else {
-            // no fading is required
-            painter.drawPixmap(pos, m_icon);
-        }
-    }
-
-}
-
-void SelectionToggle::setFadingValue(int value)
-{
-    m_fadingValue = value;
-    if (m_fadingValue >= 255) {
-        Q_ASSERT(m_fadingTimeLine);
-        m_fadingTimeLine->stop();
-    }
-    update();
-}
-
-void SelectionToggle::setIconOverlay(bool checked)
-{
-    const char* icon = checked ? "list-remove" : "list-add";
-    const int size = qMin(width() - 2 * m_margin, height() - 2 * m_margin);
-    m_icon = KIconLoader::global()->loadIcon(icon,
-                                             KIconLoader::NoGroup,
-                                             size);
-    update();
-}
-
-void SelectionToggle::refreshIcon()
-{
-    setIconOverlay(isChecked());
-}
-
-void SelectionToggle::startFading()
-{
-    Q_ASSERT(!m_fadingTimeLine);
-
-    const bool animate = KGlobalSettings::graphicEffectsLevel() & KGlobalSettings::SimpleAnimationEffects;
-    const int duration = animate ? 600 : 1;
-
-    m_fadingTimeLine = new QTimeLine(duration, this);
-    connect(m_fadingTimeLine, SIGNAL(frameChanged(int)),
-            this, SLOT(setFadingValue(int)));
-    m_fadingTimeLine->setFrameRange(0, 255);
-    m_fadingTimeLine->start();
-    m_fadingValue = 0;
-}
-
-void SelectionToggle::stopFading()
-{
-    if (m_fadingTimeLine) {
-        m_fadingTimeLine->stop();
-        delete m_fadingTimeLine;
-        m_fadingTimeLine = 0;
-    }
-    m_fadingValue = 0;
-}
-
-#include "selectiontoggle.moc"
diff --git a/src/views/selectiontoggle.h b/src/views/selectiontoggle.h
deleted file mode 100644 (file)
index 221ab07..0000000
+++ /dev/null
@@ -1,99 +0,0 @@
-/***************************************************************************
- *   Copyright (C) 2008 by Peter Penz <peter.penz19@gmail.com>             *
- *                                                                         *
- *   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 program 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 program; if not, write to the                         *
- *   Free Software Foundation, Inc.,                                       *
- *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA            *
- ***************************************************************************/
-
-#ifndef SELECTIONTOGGLE_H
-#define SELECTIONTOGGLE_H
-
-#include <KUrl>
-
-#include <QAbstractButton>
-#include <QPixmap>
-
-class QTimeLine;
-
-/**
- * @brief Toggle button for changing the selection of an hovered item.
- *
- * The toggle button is visually invisible until it is displayed at least
- * for one second.
- *
- * @see SelectionManager
- */
-class SelectionToggle : public QAbstractButton
-{
-    Q_OBJECT
-
-public:
-    explicit SelectionToggle(QWidget* parent);
-    virtual ~SelectionToggle();
-    virtual QSize sizeHint() const;
-
-    /**
-     * Resets the selection toggle so that it is hidden and stays
-     * visually invisible for at least one second after it is shown again.
-     */
-    void reset();
-
-    void setUrl(const KUrl& url);
-    KUrl url() const;
-
-    /**
-     * Sets the margin around the selection-icon in pixels. Per default
-     * the value is 0.
-     */
-    void setMargin(int margin);
-    int margin() const;
-
-public slots:
-    virtual void setVisible(bool visible);
-
-protected:
-    virtual bool eventFilter(QObject* obj, QEvent* event);
-    virtual void enterEvent(QEvent* event);
-    virtual void leaveEvent(QEvent* event);
-    virtual void mousePressEvent(QMouseEvent* event);
-    virtual void mouseReleaseEvent(QMouseEvent* event);
-    virtual void resizeEvent(QResizeEvent* event);
-    virtual void paintEvent(QPaintEvent* event);
-
-private slots:
-    /**
-     * Sets the alpha value for the fading animation and is
-     * connected with m_fadingTimeLine.
-     */
-    void setFadingValue(int value);
-
-    void setIconOverlay(bool checked);
-    void refreshIcon();
-
-private:
-    void startFading();
-    void stopFading();
-
-private:
-    bool m_isHovered;
-    bool m_leftMouseButtonPressed;
-    int m_fadingValue;
-    int m_margin;
-    QPixmap m_icon;
-    QTimeLine* m_fadingTimeLine;
-    KUrl m_url;
-};
-
-#endif
index 69ed1e3be064caf56edb07cd0bd209a3d3ef42b3..e532bee82c9299ca1a0564d6a9e17bc940c72805 100644 (file)
 
 #include <QApplication>
 #include <QDesktopWidget>
+#include <QLayout>
 #include <QScrollArea>
 #include <QScrollBar>
 #include <QTimer>
 
-#include <views/dolphinmodel.h>
-#include <views/dolphinsortfilterproxymodel.h>
-
-ToolTipManager::ToolTipManager(QAbstractItemView* parent,
-                               DolphinSortFilterProxyModel* model) :
+ToolTipManager::ToolTipManager(QWidget* parent) :
     QObject(parent),
     m_view(parent),
-    m_dolphinModel(0),
-    m_proxyModel(model),
     m_showToolTipTimer(0),
     m_contentRetrievalTimer(0),
     m_fileMetaDataToolTip(0),
@@ -48,11 +43,11 @@ ToolTipManager::ToolTipManager(QAbstractItemView* parent,
     m_item(),
     m_itemRect()
 {
-    m_dolphinModel = static_cast<DolphinModel*>(m_proxyModel->sourceModel());
-    connect(parent, SIGNAL(entered(const QModelIndex&)),
-            this, SLOT(requestToolTip(const QModelIndex&)));
-    connect(parent, SIGNAL(viewportEntered()),
-            this, SLOT(hideToolTip()));
+    //m_dolphinModel = static_cast<DolphinModel*>(m_proxyModel->sourceModel());
+    //connect(parent, SIGNAL(entered(const QModelIndex&)),
+    //        this, SLOT(requestToolTip(const QModelIndex&)));
+    //connect(parent, SIGNAL(viewportEntered()),
+    //        this, SLOT(hideToolTip()));
 
     // Initialize timers
     m_showToolTipTimer = new QTimer(this);
@@ -70,14 +65,14 @@ ToolTipManager::ToolTipManager(QAbstractItemView* parent,
     // When the mousewheel is used, the items don't get a hovered indication
     // (Qt-issue #200665). To assure that the tooltip still gets hidden,
     // the scrollbars are observed.
-    connect(parent->horizontalScrollBar(), SIGNAL(valueChanged(int)),
+    /*connect(parent->horizontalScrollBar(), SIGNAL(valueChanged(int)),
             this, SLOT(hideToolTip()));
     connect(parent->verticalScrollBar(), SIGNAL(valueChanged(int)),
-            this, SLOT(hideToolTip()));
+            this, SLOT(hideToolTip()));*/
 
     Q_ASSERT(m_view);
-    m_view->viewport()->installEventFilter(this);
-    m_view->installEventFilter(this);
+    //m_view->viewport()->installEventFilter(this);
+    //m_view->installEventFilter(this);
 }
 
 ToolTipManager::~ToolTipManager()
@@ -103,7 +98,7 @@ void ToolTipManager::hideToolTip()
 
 bool ToolTipManager::eventFilter(QObject* watched, QEvent* event)
 {
-    if (watched == m_view->viewport()) {
+    /*if (watched == m_view->viewport()) {
         switch (event->type()) {
         case QEvent::Leave:
         case QEvent::MouseButtonPress:
@@ -114,24 +109,25 @@ bool ToolTipManager::eventFilter(QObject* watched, QEvent* event)
         }
     } else if ((watched == m_view) && (event->type() == QEvent::KeyPress)) {
         hideToolTip();
-    }
+    }*/
 
     return QObject::eventFilter(watched, event);
 }
 
 void ToolTipManager::requestToolTip(const QModelIndex& index)
 {
+    Q_UNUSED(index);
     hideToolTip();
 
     // Only request a tooltip for the name column and when no selection or
     // drag & drop operation is done (indicated by the left mouse button)
-    if ((index.column() == DolphinModel::Name) && !(QApplication::mouseButtons() & Qt::LeftButton)) {
-        m_itemRect = m_view->visualRect(index);
-        const QPoint pos = m_view->viewport()->mapToGlobal(m_itemRect.topLeft());
+    if (!(QApplication::mouseButtons() & Qt::LeftButton)) {
+        m_itemRect = QRect(); //m_view->visualRect(index);
+        const QPoint pos; // = m_view->viewport()->mapToGlobal(m_itemRect.topLeft());
         m_itemRect.moveTo(pos);
 
-        const QModelIndex dirIndex = m_proxyModel->mapToSource(index);
-        m_item = m_dolphinModel->itemForIndex(dirIndex);
+        //const QModelIndex dirIndex = m_proxyModel->mapToSource(index);
+        //m_item = m_dolphinModel->itemForIndex(dirIndex);
 
         // Only start the retrieving of the content, when the mouse has been over this
         // item for 200 milliseconds. This prevents a lot of useless preview jobs and
index f8bcd3dfdb256e8ac4a7126e7b192d03c98426a9..11ef3d3aca33b17cb31b28654e63e3a7ac118de8 100644 (file)
@@ -44,8 +44,7 @@ class ToolTipManager : public QObject
     Q_OBJECT
 
 public:
-    explicit ToolTipManager(QAbstractItemView* parent,
-                            DolphinSortFilterProxyModel* model);
+    explicit ToolTipManager(QWidget* parent);
     virtual ~ToolTipManager();
 
 public slots:
@@ -68,7 +67,7 @@ private slots:
     void showToolTip();
 
 private:
-    QAbstractItemView* m_view;
+    QWidget* m_view;
     DolphinModel* m_dolphinModel;
     DolphinSortFilterProxyModel* m_proxyModel;
 
index 62f50f30b7bfb0261e41bcf47c4bcbd623ae0f63..02329866fedb3630fffdc40ffd6d0ed95f7143ca 100644 (file)
 #include <QMutexLocker>
 #include <QTimer>
 
-#include <views/dolphinmodel.h>
-
-VersionControlObserver::VersionControlObserver(QAbstractItemView* view) :
+VersionControlObserver::VersionControlObserver(QWidget* view) :
     QObject(view),
     m_pendingItemStatesUpdate(false),
     m_versionedDirectory(false),
     m_silentUpdate(false),
     m_view(view),
-    m_dirLister(0),
-    m_dolphinModel(0),
+    //m_dirLister(0),
+    //m_dolphinModel(0),
     m_dirVerificationTimer(0),
     m_plugin(0),
     m_updateItemStatesThread(0)
 {
     Q_ASSERT(view);
 
-    QAbstractProxyModel* proxyModel = qobject_cast<QAbstractProxyModel*>(view->model());
+    /*QAbstractProxyModel* proxyModel = qobject_cast<QAbstractProxyModel*>(view->model());
     m_dolphinModel = proxyModel ?
                      qobject_cast<DolphinModel*>(proxyModel->sourceModel()) :
                      qobject_cast<DolphinModel*>(view->model());
@@ -71,7 +69,7 @@ VersionControlObserver::VersionControlObserver(QAbstractItemView* view) :
         m_dirVerificationTimer->setInterval(500);
         connect(m_dirVerificationTimer, SIGNAL(timeout()),
                 this, SLOT(verifyDirectory()));
-    }
+    }*/
 }
 
 VersionControlObserver::~VersionControlObserver()
@@ -133,7 +131,7 @@ void VersionControlObserver::silentDirectoryVerification()
 
 void VersionControlObserver::verifyDirectory()
 {
-    const KUrl versionControlUrl = m_dirLister->url();
+    const KUrl versionControlUrl; // = m_dirLister->url();
     if (!versionControlUrl.isLocalFile()) {
         return;
     }
@@ -143,7 +141,7 @@ void VersionControlObserver::verifyDirectory()
     }
 
     m_plugin = searchPlugin(versionControlUrl);
-    if (m_plugin) {
+    /*if (m_plugin) {
         connect(m_plugin, SIGNAL(versionStatesChanged()),
                 this, SLOT(silentDirectoryVerification()));
         connect(m_plugin, SIGNAL(infoMessage(QString)),
@@ -176,7 +174,7 @@ void VersionControlObserver::verifyDirectory()
                    this, SLOT(delayedDirectoryVerification()));
         disconnect(m_dirLister, SIGNAL(newItems(const KFileItemList&)),
                    this, SLOT(delayedDirectoryVerification()));
-    }
+    }*/
 }
 
 void VersionControlObserver::slotThreadFinished()
@@ -195,7 +193,7 @@ void VersionControlObserver::slotThreadFinished()
     // (a detailed description of the root cause is given in the class KFilePreviewGenerator
     // from kdelibs). To bypass this bottleneck, the signals of the model are temporary blocked.
     // This works as the update of the data does not require a relayout of the views used in Dolphin.
-    const bool signalsBlocked = m_dolphinModel->signalsBlocked();
+    /*const bool signalsBlocked = m_dolphinModel->signalsBlocked();
     m_dolphinModel->blockSignals(true);
 
     const QList<ItemState> itemStates = m_updateItemStatesThread->itemStates();
@@ -218,7 +216,7 @@ void VersionControlObserver::slotThreadFinished()
     if (m_pendingItemStatesUpdate) {
         m_pendingItemStatesUpdate = false;
         updateItemStates();
-    }
+    }*/
 }
 
 void VersionControlObserver::updateItemStates()
@@ -249,7 +247,9 @@ void VersionControlObserver::updateItemStates()
 
 void VersionControlObserver::addDirectory(const QModelIndex& parentIndex, QList<ItemState>& itemStates)
 {
-    const int rowCount = m_dolphinModel->rowCount(parentIndex);
+    Q_UNUSED(parentIndex);
+    Q_UNUSED(itemStates);
+    /*const int rowCount = m_dolphinModel->rowCount(parentIndex);
     for (int row = 0; row < rowCount; ++row) {
         const QModelIndex index = m_dolphinModel->index(row, DolphinModel::Version, parentIndex);
         addDirectory(index, itemStates);
@@ -260,7 +260,7 @@ void VersionControlObserver::addDirectory(const QModelIndex& parentIndex, QList<
         itemState.version = KVersionControlPlugin::UnversionedVersion;
 
         itemStates.append(itemState);
-    }
+    }*/
 }
 
 KVersionControlPlugin* VersionControlObserver::searchPlugin(const KUrl& directory) const
@@ -296,7 +296,8 @@ KVersionControlPlugin* VersionControlObserver::searchPlugin(const KUrl& director
 
     // Verify whether the current directory contains revision information
     // like .svn, .git, ...
-    foreach (KVersionControlPlugin* plugin, plugins) {
+    Q_UNUSED(directory);
+    /*foreach (KVersionControlPlugin* plugin, plugins) {
         // Use the KDirLister cache to check for .svn, .git, ... files
         KUrl dirUrl(directory);
         KUrl fileUrl = dirUrl;
@@ -324,14 +325,14 @@ KVersionControlPlugin* VersionControlObserver::searchPlugin(const KUrl& director
                 upUrl = dirUrl.upUrl();
             }
         }
-    }
+    }*/
 
     return 0;
 }
 
 bool VersionControlObserver::isVersioned() const
 {
-    return m_dolphinModel->hasVersionData() && m_plugin;
+    return false; //m_dolphinModel->hasVersionData() && m_plugin;
 }
 
 #include "versioncontrolobserver.moc"
index 214c072cdb57806792a7d017d84804009735d0d5..71405fabdd7848a6429468a09bdadf88a91e93fe 100644 (file)
@@ -51,7 +51,7 @@ class LIBDOLPHINPRIVATE_EXPORT VersionControlObserver : public QObject
     Q_OBJECT
 
 public:
-    VersionControlObserver(QAbstractItemView* view);
+    VersionControlObserver(QWidget* parent);
     virtual ~VersionControlObserver();
 
     QList<QAction*> contextMenuActions(const KFileItemList& items) const;
@@ -133,9 +133,9 @@ private:
     bool m_silentUpdate; // if true, no messages will be send during the update
                          // of version states
 
-    QAbstractItemView* m_view;
-    KDirLister* m_dirLister;
-    DolphinModel* m_dolphinModel;
+    QWidget* m_view;
+    //KDirLister* m_dirLister;
+    //DolphinModel* m_dolphinModel;
 
     QTimer* m_dirVerificationTimer;
 
diff --git a/src/views/viewextensionsfactory.cpp b/src/views/viewextensionsfactory.cpp
deleted file mode 100644 (file)
index a52871f..0000000
+++ /dev/null
@@ -1,249 +0,0 @@
-/***************************************************************************
- *   Copyright (C) 2009 by Peter Penz <peter.penz19@gmail.com>             *
- *                                                                         *
- *   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 program 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 program; if not, write to the                         *
- *   Free Software Foundation, Inc.,                                       *
- *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA            *
- ***************************************************************************/
-
-#include "viewextensionsfactory.h"
-
-#include "dolphinfileitemdelegate.h"
-#include "dolphinsortfilterproxymodel.h"
-#include "dolphinview.h"
-#include "dolphinviewcontroller.h"
-#include "dolphinviewautoscroller.h"
-#include "folderexpander.h"
-#include "selectionmanager.h"
-#include "settings/dolphinsettings.h"
-#include "tooltips/tooltipmanager.h"
-#include "versioncontrol/versioncontrolobserver.h"
-#include "viewmodecontroller.h"
-
-#include "dolphin_generalsettings.h"
-
-#include <KDirLister>
-#include <KDirModel>
-#include <KFilePreviewGenerator>
-#include <QAbstractItemView>
-#include <QApplication>
-
-ViewExtensionsFactory::ViewExtensionsFactory(QAbstractItemView* view,
-                                             DolphinViewController* dolphinViewController,
-                                             const ViewModeController* viewModeController) :
-    QObject(view),
-    m_view(view),
-    m_dolphinViewController(dolphinViewController),
-    m_toolTipManager(0),
-    m_previewGenerator(0),
-    m_selectionManager(0),
-    m_autoScroller(0),
-    m_fileItemDelegate(0),
-    m_versionControlObserver(0)
-{
-    view->setSelectionMode(QAbstractItemView::ExtendedSelection);
-
-    GeneralSettings* settings = DolphinSettings::instance().generalSettings();
-
-    // initialize tooltips
-    if (settings->showToolTips()) {
-        DolphinSortFilterProxyModel* proxyModel = static_cast<DolphinSortFilterProxyModel*>(view->model());
-        m_toolTipManager = new ToolTipManager(view, proxyModel);
-
-        connect(dolphinViewController, SIGNAL(hideToolTip()),
-                m_toolTipManager, SLOT(hideToolTip()));
-    }
-
-    // initialize preview generator
-    Q_ASSERT(view->iconSize().isValid());
-    m_previewGenerator = new KFilePreviewGenerator(view);
-    m_previewGenerator->setPreviewShown(dolphinViewController->view()->showPreview());
-    connect(viewModeController, SIGNAL(zoomLevelChanged(int)),
-            this, SLOT(slotZoomLevelChanged()));
-    connect(viewModeController, SIGNAL(cancelPreviews()),
-            this, SLOT(cancelPreviews()));
-
-    // slotPreviewChanged() is connected as Qt::QueuedConnection to prevent performance
-    // issues when the directory lister changes its URL after the preview-changes have
-    // been applied. Usecase: Switch from directory A having no previews to
-    // directory B with previews (see sequence in DolphinView::setUrl()).
-    connect(dolphinViewController->view(), SIGNAL(showPreviewChanged()),
-            this, SLOT(slotShowPreviewChanged()),
-            Qt::QueuedConnection);
-
-    // initialize selection manager
-    m_selectionManager = new SelectionManager(view);
-    connect(m_selectionManager, SIGNAL(selectionChanged()),
-            this, SLOT(requestActivation()));
-    connect(viewModeController, SIGNAL(urlChanged(const KUrl&)),
-            m_selectionManager, SLOT(reset()));
-
-    // initialize auto scroller
-    m_autoScroller = new DolphinViewAutoScroller(view);
-
-    // initialize file item delegate
-    m_fileItemDelegate = new DolphinFileItemDelegate(view);
-    m_fileItemDelegate->setShowToolTipWhenElided(false);
-    view->setItemDelegate(m_fileItemDelegate);
-
-    // initialize version control observer
-    const DolphinView* dolphinView = dolphinViewController->view();
-    m_versionControlObserver = new VersionControlObserver(view);
-    connect(m_versionControlObserver, SIGNAL(infoMessage(const QString&)),
-            dolphinView, SIGNAL(infoMessage(const QString&)));
-    connect(m_versionControlObserver, SIGNAL(errorMessage(const QString&)),
-            dolphinView, SIGNAL(errorMessage(const QString&)));
-    connect(m_versionControlObserver, SIGNAL(operationCompletedMessage(const QString&)),
-            dolphinView, SIGNAL(operationCompletedMessage(const QString&)));
-    connect(dolphinViewController, SIGNAL(requestVersionControlActions(const KFileItemList&)),
-            this, SLOT(slotRequestVersionControlActions(const KFileItemList&)));
-
-    // react on view property changes
-    connect(dolphinView, SIGNAL(showHiddenFilesChanged()),
-            this, SLOT(slotShowHiddenFilesChanged()));
-    connect(dolphinView, SIGNAL(sortingChanged(DolphinView::Sorting)),
-            this, SLOT(slotSortingChanged(DolphinView::Sorting)));
-    connect(dolphinView, SIGNAL(sortOrderChanged(Qt::SortOrder)),
-            this, SLOT(slotSortOrderChanged(Qt::SortOrder)));
-    connect(dolphinView, SIGNAL(sortFoldersFirstChanged(bool)),
-            this, SLOT(slotSortFoldersFirstChanged(bool)));
-
-    // Give the view the ability to auto-expand its directories on hovering
-    // (the column view takes care about this itself). If the details view
-    // uses expandable folders, the auto-expanding should be used always.
-    m_folderExpander = new FolderExpander(view, proxyModel());
-    m_folderExpander->setEnabled(settings->autoExpandFolders());
-    connect(m_folderExpander, SIGNAL(enterDir(const QModelIndex&)),
-            dolphinViewController, SLOT(triggerItem(const QModelIndex&)));
-
-    // react on namefilter changes
-    connect(viewModeController, SIGNAL(nameFilterChanged(const QString&)),
-            this, SLOT(slotNameFilterChanged(const QString&)));
-
-    view->viewport()->installEventFilter(this);
-}
-
-ViewExtensionsFactory::~ViewExtensionsFactory()
-{
-}
-
-void ViewExtensionsFactory::handleCurrentIndexChange(const QModelIndex& current, const QModelIndex& previous)
-{
-    m_autoScroller->handleCurrentIndexChange(current, previous);
-}
-
-DolphinFileItemDelegate* ViewExtensionsFactory::fileItemDelegate() const
-{
-    return m_fileItemDelegate;
-}
-
-void ViewExtensionsFactory::setAutoFolderExpandingEnabled(bool enabled)
-{
-    m_folderExpander->setEnabled(enabled);
-}
-
-bool ViewExtensionsFactory::autoFolderExpandingEnabled() const
-{
-    return m_folderExpander->enabled();
-}
-
-bool ViewExtensionsFactory::eventFilter(QObject* watched, QEvent* event)
-{
-    Q_UNUSED(watched);
-    if ((event->type() == QEvent::Wheel) && m_selectionManager) {
-        m_selectionManager->reset();
-    }
-    return false;
-}
-
-void ViewExtensionsFactory::slotZoomLevelChanged()
-{
-    m_previewGenerator->updateIcons();
-    if (m_selectionManager) {
-        m_selectionManager->reset();
-    }
-}
-
-void ViewExtensionsFactory::cancelPreviews()
-{
-    m_previewGenerator->cancelPreviews();
-}
-
-void ViewExtensionsFactory::slotShowPreviewChanged()
-{
-    const bool show = m_dolphinViewController->view()->showPreview();
-    m_previewGenerator->setPreviewShown(show);
-}
-
-void ViewExtensionsFactory::slotShowHiddenFilesChanged()
-{
-    KDirModel* dirModel = static_cast<KDirModel*>(proxyModel()->sourceModel());
-    KDirLister* dirLister = dirModel->dirLister();
-
-    dirLister->stop();
-
-    const bool show = m_dolphinViewController->view()->showHiddenFiles();
-    dirLister->setShowingDotFiles(show);
-
-    const KUrl url = dirLister->url();
-    if (url.isValid()) {
-        dirLister->openUrl(url, KDirLister::NoFlags);
-    }
-}
-
-void ViewExtensionsFactory::slotSortingChanged(DolphinView::Sorting sorting)
-{
-    proxyModel()->setSorting(sorting);
-}
-
-void ViewExtensionsFactory::slotSortOrderChanged(Qt::SortOrder order)
-{
-    proxyModel()->setSortOrder(order);
-}
-
-void ViewExtensionsFactory::slotSortFoldersFirstChanged(bool foldersFirst)
-{
-    proxyModel()->setSortFoldersFirst(foldersFirst);
-}
-
-void ViewExtensionsFactory::slotNameFilterChanged(const QString& nameFilter)
-{
-    proxyModel()->setFilterFixedString(nameFilter);
-}
-
-void ViewExtensionsFactory::slotRequestVersionControlActions(const KFileItemList& items)
-{
-    QList<QAction*> actions;
-    if (items.isEmpty()) {
-        const KDirModel* dirModel = static_cast<const KDirModel*>(proxyModel()->sourceModel());
-        const KUrl url = dirModel->dirLister()->url();
-        actions = m_versionControlObserver->contextMenuActions(url.path(KUrl::AddTrailingSlash));
-    } else {
-        actions = m_versionControlObserver->contextMenuActions(items);
-    }
-    m_dolphinViewController->setVersionControlActions(actions);
-}
-
-void ViewExtensionsFactory::requestActivation()
-{
-    m_dolphinViewController->requestActivation();
-}
-
-DolphinSortFilterProxyModel* ViewExtensionsFactory::proxyModel() const
-{
-    return static_cast<DolphinSortFilterProxyModel*>(m_view->model());
-}
-
-#include "viewextensionsfactory.moc"
-
diff --git a/src/views/viewextensionsfactory.h b/src/views/viewextensionsfactory.h
deleted file mode 100644 (file)
index 134868b..0000000
+++ /dev/null
@@ -1,105 +0,0 @@
-/***************************************************************************
- *   Copyright (C) 2009 by Peter Penz <peter.penz19@gmail.com>             *
- *                                                                         *
- *   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 program 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 program; if not, write to the                         *
- *   Free Software Foundation, Inc.,                                       *
- *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA            *
- ***************************************************************************/
-
-#ifndef VIEWEXTENSIONSFACTORY_H
-#define VIEWEXTENSIONSFACTORY_H
-
-#include <QObject>
-
-#include "dolphinview.h"
-
-class DolphinFileItemDelegate;
-class DolphinSortFilterProxyModel;
-class DolphinViewAutoScroller;
-class KFilePreviewGenerator;
-class FolderExpander;
-class QModelIndex;
-class SelectionManager;
-class ToolTipManager;
-class QAbstractItemView;
-class VersionControlObserver;
-class ViewModeController;
-
-/**
- * @brief Responsible for creating extensions like tooltips and previews
- *        that are available in all view implementations.
- *
- * Each view implementation (iconsview, detailsview, columnview) must
- * instantiate an instance of this class to assure having
- * a common behavior that is independent from the custom functionality of
- * a view implementation.
- */
-class ViewExtensionsFactory : public QObject
-{
-    Q_OBJECT
-
-public:
-    explicit ViewExtensionsFactory(QAbstractItemView* view,
-                                   DolphinViewController* dolphinViewController,
-                                   const ViewModeController* viewModeController);
-    virtual ~ViewExtensionsFactory();
-
-    /**
-     * Must be invoked by the item view, when QAbstractItemView::currentChanged()
-     * has been called. Assures that the current item stays visible when it has been
-     * changed by the keyboard.
-     */
-    void handleCurrentIndexChange(const QModelIndex& current, const QModelIndex& previous);
-
-    DolphinFileItemDelegate* fileItemDelegate() const;
-
-    /**
-     * Enables the automatically expanding of a folder when dragging
-     * items above the folder.
-     */
-    void setAutoFolderExpandingEnabled(bool enabled);
-    bool autoFolderExpandingEnabled() const;
-
-protected:
-    virtual bool eventFilter(QObject* watched, QEvent* event);
-
-private slots:
-    void slotZoomLevelChanged();
-    void cancelPreviews();
-    void slotShowPreviewChanged();
-    void slotShowHiddenFilesChanged();
-    void slotSortingChanged(DolphinView::Sorting sorting);
-    void slotSortOrderChanged(Qt::SortOrder order);
-    void slotSortFoldersFirstChanged(bool foldersFirst);
-    void slotNameFilterChanged(const QString& nameFilter);
-    void slotRequestVersionControlActions(const KFileItemList& items);
-    void requestActivation();
-
-private:
-    DolphinSortFilterProxyModel* proxyModel() const;
-
-private:
-    QAbstractItemView* m_view;
-    DolphinViewController* m_dolphinViewController;
-    ToolTipManager* m_toolTipManager;
-    KFilePreviewGenerator* m_previewGenerator;
-    SelectionManager* m_selectionManager;
-    DolphinViewAutoScroller* m_autoScroller;
-    DolphinFileItemDelegate* m_fileItemDelegate;
-    VersionControlObserver* m_versionControlObserver;
-    FolderExpander* m_folderExpander;
-};
-
-#endif
-
index d0c6fcf1e50fe44064db279409c74bf63a916afb..aeea67428feacaba1b36cd4144674484e91315b3 100644 (file)
@@ -38,7 +38,7 @@
 namespace {
     // String representation to mark the additional properties of
     // the details view as customized by the user. See
-    // ViewProperties::additionalInfoV2() for more information.
+    // ViewProperties::additionalInfoList() for more information.
     const char* CustomizedDetailsString = "CustomizedDetails";
 }
 
@@ -83,7 +83,7 @@ ViewProperties::ViewProperties(const KUrl& url) :
     if (useDefaultProps) {
         if (useDetailsViewWithPath) {
             setViewMode(DolphinView::DetailsView);
-            setAdditionalInfo(KFileItemDelegate::InformationList() << KFileItemDelegate::LocalPathOrUrl);
+            setAdditionalInfoList(QList<DolphinView::AdditionalInfo>() << DolphinView::PathInfo);
         } else {
             // The global view-properties act as default for directories without
             // any view-property configuration
@@ -121,23 +121,23 @@ DolphinView::Mode ViewProperties::viewMode() const
     return static_cast<DolphinView::Mode>(m_node->viewMode());
 }
 
-void ViewProperties::setShowPreview(bool show)
+void ViewProperties::setPreviewsShown(bool show)
 {
-    if (m_node->showPreview() != show) {
-        m_node->setShowPreview(show);
+    if (m_node->previewsShown() != show) {
+        m_node->setPreviewsShown(show);
         update();
     }
 }
 
-bool ViewProperties::showPreview() const
+bool ViewProperties::previewsShown() const
 {
-    return m_node->showPreview();
+    return m_node->previewsShown();
 }
 
-void ViewProperties::setShowHiddenFiles(bool show)
+void ViewProperties::setHiddenFilesShown(bool show)
 {
-    if (m_node->showHiddenFiles() != show) {
-        m_node->setShowHiddenFiles(show);
+    if (m_node->hiddenFilesShown() != show) {
+        m_node->setHiddenFilesShown(show);
         update();
     }
 }
@@ -155,9 +155,9 @@ bool ViewProperties::categorizedSorting() const
     return m_node->categorizedSorting();
 }
 
-bool ViewProperties::showHiddenFiles() const
+bool ViewProperties::hiddenFilesShown() const
 {
-    return m_node->showHiddenFiles();
+    return m_node->hiddenFilesShown();
 }
 
 void ViewProperties::setSorting(DolphinView::Sorting sorting)
@@ -199,13 +199,13 @@ bool ViewProperties::sortFoldersFirst() const
     return m_node->sortFoldersFirst();
 }
 
-void ViewProperties::setAdditionalInfo(const KFileItemDelegate::InformationList& list)
+void ViewProperties::setAdditionalInfoList(const QList<DolphinView::AdditionalInfo>& list)
 {
-    // See ViewProperties::additionalInfoV2() for the storage format
+    // See ViewProperties::additionalInfoList() for the storage format
     // of the additional information.
 
     // Remove the old values stored for the current view-mode
-    const QStringList oldInfoStringList = m_node->additionalInfoV2();
+    const QStringList oldInfoStringList = m_node->additionalInfo();
     const QString prefix = viewModePrefix();
     QStringList newInfoStringList = oldInfoStringList;
     for (int i = newInfoStringList.count() - 1; i >= 0; --i) {
@@ -216,7 +216,7 @@ void ViewProperties::setAdditionalInfo(const KFileItemDelegate::InformationList&
 
     // Add the updated values for the current view-mode
     AdditionalInfoAccessor& infoAccessor = AdditionalInfoAccessor::instance();
-    foreach (KFileItemDelegate::Information info, list) {
+    foreach (DolphinView::AdditionalInfo info, list) {
         newInfoStringList.append(prefix + infoAccessor.value(info));
     }
 
@@ -232,10 +232,6 @@ void ViewProperties::setAdditionalInfo(const KFileItemDelegate::InformationList&
     }
 
     if (changed) {
-        if (m_node->version() < 2) {
-            m_node->setVersion(2);
-        }
-
         const bool markCustomizedDetails = (m_node->viewMode() == DolphinView::DetailsView)
                                            && !newInfoStringList.contains(CustomizedDetailsString);
         if (markCustomizedDetails) {
@@ -246,35 +242,80 @@ void ViewProperties::setAdditionalInfo(const KFileItemDelegate::InformationList&
             newInfoStringList.append(CustomizedDetailsString);
         }
 
-        m_node->setAdditionalInfoV2(newInfoStringList);
+        m_node->setAdditionalInfo(newInfoStringList);
         update();
     }
 }
 
-KFileItemDelegate::InformationList ViewProperties::additionalInfo() const
+QList<DolphinView::AdditionalInfo> ViewProperties::additionalInfoList() const
 {
-    KFileItemDelegate::InformationList usedInfo;
+    // The shown additional information is stored for each view-mode separately as
+    // string with the view-mode as prefix. Example:
+    //
+    // AdditionalInfo=Details_Size,Details_Date,Details_Owner,Icon_Size
+    //
+    // To get the representation as QList<DolphinView::AdditionalInfo>, the current
+    // view-mode must be checked and the values of this mode added to the list.
+    //
+    // For the details-view a special case must be respected: Per default the size
+    // and date should be shown without creating a .directory file. Only if
+    // the user explictly has modified the properties of the details view (marked
+    // by "CustomizedDetails"), also a details-view with no additional information
+    // is accepted.
+
+    QList<DolphinView::AdditionalInfo> usedInfo;
+
+    // infoHash allows to get the mapped DolphinView::AdditionalInfo value
+    // for a stored string-value in a fast way
+    static QHash<QString, DolphinView::AdditionalInfo> infoHash;
+    if (infoHash.isEmpty()) {
+        AdditionalInfoAccessor& infoAccessor = AdditionalInfoAccessor::instance();
+        const QList<DolphinView::AdditionalInfo> keys = infoAccessor.keys();
+        foreach (DolphinView::AdditionalInfo key, keys) {
+            infoHash.insert(infoAccessor.value(key), key);
+        }
+    }
+
+    // Iterate through all stored keys stored as strings and map them to
+    // the corresponding DolphinView::AdditionalInfo values.
+    const QString prefix = viewModePrefix();
+    const int prefixLength = prefix.length();
+    const QStringList infoStringList = m_node->additionalInfo();
+    foreach (const QString& infoString, infoStringList) {
+        if (infoString.startsWith(prefix)) {
+            const QString key = infoString.right(infoString.length() - prefixLength);
+            if (infoHash.contains(key)) {
+                usedInfo.append(infoHash.value(key));
+            } else {
+                kWarning() << "Did not find the key" << key << "in the information string";
+            }
+        }
+    }
 
-    switch (m_node->version()) {
-    case 1: usedInfo = additionalInfoV1(); break;
-    case 2: usedInfo = additionalInfoV2(); break;
-    default: kWarning() << "Unknown version of the view properties";
+    // For the details view the size and date should be shown per default
+    // until the additional information has been explicitly changed by the user
+    const bool useDefaultValues = usedInfo.isEmpty()
+                                  && (m_node->viewMode() == DolphinView::DetailsView)
+                                  && !infoStringList.contains(CustomizedDetailsString);
+    Q_UNUSED(useDefaultValues);
+    if (useDefaultValues) {
+        usedInfo.append(DolphinView::SizeInfo);
+        usedInfo.append(DolphinView::DateInfo);
     }
 
     return usedInfo;
 }
 
-
 void ViewProperties::setDirProperties(const ViewProperties& props)
 {
     setViewMode(props.viewMode());
-    setShowPreview(props.showPreview());
-    setShowHiddenFiles(props.showHiddenFiles());
+    setPreviewsShown(props.previewsShown());
+    setHiddenFilesShown(props.hiddenFilesShown());
     setCategorizedSorting(props.categorizedSorting());
     setSorting(props.sorting());
     setSortOrder(props.sortOrder());
     setSortFoldersFirst(props.sortFoldersFirst());
-    setAdditionalInfo(props.additionalInfo());
+    setAdditionalInfoList(props.additionalInfoList());
 }
 
 void ViewProperties::setAutoSaveEnabled(bool autoSave)
@@ -291,22 +332,6 @@ void ViewProperties::update()
 {
     m_changedProps = true;
     m_node->setTimestamp(QDateTime::currentDateTime());
-
-    // If the view-properties are stored in an older format, take
-    // care to update them to the current format.
-    switch (m_node->version()) {
-    case 1: {
-        const KFileItemDelegate::InformationList infoList = additionalInfoV1();
-        m_node->setVersion(2);
-        setAdditionalInfo(infoList);
-        break;
-    }
-    case 2:
-        // Current version. Nothing needs to get converted.
-        break;
-    default:
-        kWarning() << "Unknown version of the view properties";
-    }
 }
 
 void ViewProperties::save()
@@ -330,107 +355,14 @@ QString ViewProperties::destinationDir(const QString& subDir) const
     return KStandardDirs::locateLocal("data", basePath);
 }
 
-KFileItemDelegate::InformationList ViewProperties::additionalInfoV1() const
-{
-    KFileItemDelegate::InformationList usedInfo;
-
-    int decodedInfo = m_node->additionalInfo();
-
-    switch (viewMode()) {
-    case DolphinView::DetailsView:
-        decodedInfo = decodedInfo & 0xFF;
-        if (decodedInfo == 0) {
-            // A details view without any additional info makes no sense, hence
-            // provide at least a size-info and date-info as fallback
-            AdditionalInfoAccessor& infoAccessor = AdditionalInfoAccessor::instance();
-            decodedInfo = infoAccessor.bitValue(KFileItemDelegate::Size) |
-                          infoAccessor.bitValue(KFileItemDelegate::ModificationTime);
-        }
-        break;
-    case DolphinView::IconsView:
-        decodedInfo = (decodedInfo >> 8) & 0xFF;
-        break;
-    case DolphinView::ColumnView:
-        decodedInfo = (decodedInfo >> 16) & 0xFF;
-        break;
-    default: break;
-    }
-
-    AdditionalInfoAccessor& infoAccessor = AdditionalInfoAccessor::instance();
-    const KFileItemDelegate::InformationList infoKeys = infoAccessor.keys();
-
-    foreach (const KFileItemDelegate::Information info, infoKeys) {
-        if (decodedInfo & infoAccessor.bitValue(info)) {
-            usedInfo.append(info);
-        }
-    }
-
-    return usedInfo;
-}
-
-KFileItemDelegate::InformationList ViewProperties::additionalInfoV2() const
-{
-    // The shown additional information is stored for each view-mode separately as
-    // string with the view-mode as prefix. Example:
-    //
-    // AdditionalInfoV2=Details_Size,Details_Date,Details_Owner,Icon_Size
-    //
-    // To get the representation as KFileItemDelegate::InformationList, the current
-    // view-mode must be checked and the values of this mode added to the list.
-    //
-    // For the details-view a special case must be respected: Per default the size
-    // and date should be shown without creating a .directory file. Only if
-    // the user explictly has modified the properties of the details view (marked
-    // by "CustomizedDetails"), also a details-view with no additional information
-    // is accepted.
-
-    KFileItemDelegate::InformationList usedInfo;
-
-    // infoHash allows to get the mapped KFileItemDelegate::Information value
-    // for a stored string-value in a fast way
-    static QHash<QString, KFileItemDelegate::Information> infoHash;
-    if (infoHash.isEmpty()) {
-        AdditionalInfoAccessor& infoAccessor = AdditionalInfoAccessor::instance();
-        const KFileItemDelegate::InformationList keys = infoAccessor.keys();
-        foreach (const KFileItemDelegate::Information key, keys) {
-            infoHash.insert(infoAccessor.value(key), key);
-        }
-    }
-
-    // Iterate through all stored keys stored as strings and map them to
-    // the corresponding KFileItemDelegate::Information values.
-    const QString prefix = viewModePrefix();
-    const int prefixLength = prefix.length();
-    const QStringList infoStringList = m_node->additionalInfoV2();
-    foreach (const QString& infoString, infoStringList) {
-        if (infoString.startsWith(prefix)) {
-            const QString key = infoString.right(infoString.length() - prefixLength);
-            Q_ASSERT(infoHash.contains(key));
-            usedInfo.append(infoHash.value(key));
-        }
-    }
-
-    // For the details view the size and date should be shown per default
-    // until the additional information has been explicitly changed by the user
-    const bool useDefaultValues = usedInfo.isEmpty()
-                                  && (m_node->viewMode() == DolphinView::DetailsView)
-                                  && !infoStringList.contains(CustomizedDetailsString);
-    if (useDefaultValues) {
-        usedInfo.append(KFileItemDelegate::Size);
-        usedInfo.append(KFileItemDelegate::ModificationTime);
-    }
-
-    return usedInfo;
-}
-
 QString ViewProperties::viewModePrefix() const
 {
     QString prefix;
 
     switch (m_node->viewMode()) {
-    case DolphinView::DetailsView: prefix = "Details_"; break;
     case DolphinView::IconsView:   prefix = "Icons_"; break;
-    case DolphinView::ColumnView:  prefix = "Column_"; break;
+    case DolphinView::CompactView: prefix = "Compact_"; break;
+    case DolphinView::DetailsView: prefix = "Details_"; break;
     default: kWarning() << "Unknown view-mode of the view properties";
     }
 
index ac373d677cc352128e9f1847e9442287d33c0d76..c95134a156ac6a8158096d67182dd5f8168219ad 100644 (file)
@@ -37,7 +37,7 @@ class ViewPropertySettings;
  * \code
  * ViewProperties props(KUrl("/home/peter/Documents"));
  * const DolphinView::Mode mode = props.viewMode();
- * const bool showHiddenFiles = props.isShowHiddenFilesEnabled();
+ * const bool hiddenFilesShown = props.hiddenFilesShown();
  * \endcode
  *
  * When modifying a view property, the '.directory' file is automatically updated
@@ -56,11 +56,11 @@ public:
     void setViewMode(DolphinView::Mode mode);
     DolphinView::Mode viewMode() const;
 
-    void setShowPreview(bool show);
-    bool showPreview() const;
+    void setPreviewsShown(bool show);
+    bool previewsShown() const;
 
-    void setShowHiddenFiles(bool show);
-    bool showHiddenFiles() const;
+    void setHiddenFilesShown(bool show);
+    bool hiddenFilesShown() const;
 
     void setCategorizedSorting(bool categorized);
     bool categorizedSorting() const;
@@ -79,14 +79,14 @@ public:
      * Note that the additional-info property is the only property where
      * the value is dependent from another property (in this case the view-mode).
      */
-    void setAdditionalInfo(const KFileItemDelegate::InformationList& info);
+    void setAdditionalInfoList(const QList<DolphinView::AdditionalInfo>& info);
 
     /**
      * Returns the additional information for the current set view-mode.
      * Note that the additional-info property is the only property where
      * the value is dependent from another property (in this case the view-mode).
      */
-    KFileItemDelegate::InformationList additionalInfo() const;
+    QList<DolphinView::AdditionalInfo> additionalInfoList() const;
 
     /**
      * Sets the directory properties view mode, show preview,
@@ -131,18 +131,6 @@ private:
      */
     QString destinationDir(const QString& subDir) const;
 
-    /**
-     * Helper method for ViewProperties::additionalInfo(): Returns
-     * the additional info for the outdated version 1 of the view-properties.
-     */
-    KFileItemDelegate::InformationList additionalInfoV1() const;
-
-    /**
-     * Helper method for ViewProperties::additionalInfo(): Returns
-     * the additional info for the current version 2 of the view-properties.
-     */
-    KFileItemDelegate::InformationList additionalInfoV2() const;
-
     /**
      * Returns the view-mode prefix when storing additional properties for
      * a view-mode.