diff --git a/CHANGELOG b/CHANGELOG index 9cb2111..cde510c 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,7 +1,93 @@ -pcmanfm-qt-0.11.3 / 2017-01-14 +pcmanfm-qt-0.12.0 / 2017-10-21 ============================== + * Set Version + * removed dangeling symlink to debian dir + * Text eliding, long texts and newline + * Update status message appropriately + * fixup...use static const + * Fix icon sizes + * Just fixed my typo in search settings (#574) + * Lithuanian translation + * Lithuanian translation + * Disable menubar actions that cannot be used + * Save and restore search settings + * Don't export github templates + * Wallpaper Slide Show + * Inline renaming with F2 for detailed list view (#554) + * Inline renaming with F2 + * Fix showing/hiding hidden files (#535) + * Don't select or scroll to child folder on reloading (#536) + * Replace customized DesktopItemDelegate hacks with the standard Fm::FolderItemDelegate provided by libfm-qt. (#529) + * liblxqt version make no sense here + * Copied issue template + * Fix Ctrl+A on desktop (#526) + * Update statusbar size info when needed + * Drops Qt5Core_VERSION_STRING + * set Qt::AA_UseHighDpiPixmaps to true + * Fix jerky desktop items + * Place dropped item at drop position (#504) + * Make custom pos checkbox work for multiple items (#499) + * Fix crash on removing desktop items with custom position (#496) + * Fix cursor on hovering desktop items + * Fix pressing RETURN in location bar + * Remove the old tilde replacement + * Included LXQTConfigVars + * Fixed config/CMakeLists.txt - removed not needed things + * Added merged autostart and config to CMakeLists.txt + * Updated *_da.desktop files and removed *_da_DK.desktop files + * Update desktop entries and Replace fr_FR by fr + * lxqt-rc.xml: Change default config install path + * PCManFM-Qt: Update default wallpaper (#49) + * Merge pull request #48 from lxde/pcmanfm-qt-sort-order + * Settings Openbox updated. + * Default key shortcuts added to lxqt-globalkeysd. + * Use lxqt-sudo in pcmanfm-qt config file by default. + * Update Greek translation (el) Remove country variant from language code + * CMake: Adds Runtime and Devel install COMPONENTs + * Coding style changes + * Adds double quotes to everything that may break + * Updates the build system to use the Targets infrastructure + * adjust default wallpaper to default theme + * Drops hardcoded /etc/xdg paths + * Updated german translation, replaced Qt4 by Qt in all xsession/translations + * Updates translations infrastructure + * Update the required minimum cmake version + * remove dead template lines switch OnlyShowIn from Razor -> LXQt stringchanges LxQt -> LXQt + * Add session.conf and windowmanagers.conf. + * Support lxqt-session and add necessary xdg autostart desktop entry files. + * Rename dirs and replace razor with lxqt. Install lxqt.conf to /etc/xdg/lxqt and provide theme config. + * Properly set default wallpaper for pcmanfm-qt. Comment out openbox config handling in startlxde-qt since it's not needed. + * Remove custom openbox config file in desktop.conf temporarily until lxsession is fixed. + * Fix file paths, replacing razor with lxqt. * Remove Alt+F2 and Ctrl+Esc from openbox config file to avoid conflicts with lxqt-panel & lxqt-globalkeys. + * Add default configuration files for lxde-qt session. + * Use const iterators (Fix a FTBFS in debug mode) (#483) + * Fixed desktop items movement + * Fixes some pedantic bugs + * Correct alignment of small icons on desktop + * Rename namespace Fm2 to Fm. + * Remove unused header includes. + * Fix a bug in correct tab page dir path which causes problems of file searching. + * Fix incorrect URI of application menu. + * Fix the broken folder reload. + * Fix incorrect title update of tabs. + * Add basic error handling when folder loading is failed. + * Port status message handling to the new libfm C++ API. + * Use Fm2::Path::homePath() API. + * Use the new libfm C++ terminal emulator APIs. + * Adopt to changes of libfm C++ APIs. + * Deprecate the use of Fm::Thumbnailer. + * Replace all NULL with C++ 11 nullptr. + * Initial port to the new C++ libfm API. + * DesktopWindow: Render tilled wallpaper manually + * Use const iterators + * Checks bookmarks iterators validity (#444) + +0.11.3 / 2017-01-14 +=================== + + * Release 0.11.3: Update changelog * remove 0.11.3 changelog entries * Bump patch version * Release 0.11.3: Update changelog diff --git a/CMakeLists.txt b/CMakeLists.txt index f29d0fe..7544a18 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,12 +6,14 @@ if (POLICY CMP0063) cmake_policy (SET CMP0063 NEW) endif (POLICY CMP0063) +# PcmanFm-Qt Version set(PCMANFM_QT_VERSION_MAJOR 0) -set(PCMANFM_QT_VERSION_MINOR 11) -set(PCMANFM_QT_VERSION_PATCH 3) +set(PCMANFM_QT_VERSION_MINOR 12) +set(PCMANFM_QT_VERSION_PATCH 0) + set(PCMANFM_QT_VERSION ${PCMANFM_QT_VERSION_MAJOR}.${PCMANFM_QT_VERSION_MINOR}.${PCMANFM_QT_VERSION_PATCH}) -set(LXQTBT_MINIMUM_VERSION "0.1.0") +set(LXQTBT_MINIMUM_VERSION "0.4.0") list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake") @@ -22,10 +24,11 @@ find_package(Qt5X11Extras 5.2 REQUIRED) find_package(fm-qt REQUIRED) find_package(lxqt-build-tools ${LXQTBT_MINIMUM_VERSION} REQUIRED) -message(STATUS "Building ${PROJECT_NAME} with Qt ${Qt5Core_VERSION_STRING}") +message(STATUS "Building ${PROJECT_NAME} with Qt ${Qt5Core_VERSION}") option(UPDATE_TRANSLATIONS "Update source translation translations/*.ts files" OFF) include(GNUInstallDirs) +include(LXQtConfigVars) include(LXQtTranslateTs) include(LXQtTranslateDesktop) include(LXQtCompilerSettings NO_POLICY_SCOPE) @@ -61,3 +64,7 @@ if(BUILD_DOCUMENTATION) ) install(DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/docs" DESTINATION "${CMAKE_INSTALL_DOCDIR}") endif() + +# merged from lxqt-common +add_subdirectory(autostart) +add_subdirectory(config) diff --git a/autostart/CMakeLists.txt b/autostart/CMakeLists.txt new file mode 100644 index 0000000..5f596a5 --- /dev/null +++ b/autostart/CMakeLists.txt @@ -0,0 +1,17 @@ +cmake_minimum_required(VERSION 3.0.2 FATAL_ERROR) + +file(GLOB DESKTOP_FILES_IN *.desktop.in) + +# Translations ********************************** +lxqt_translate_desktop(DESKTOP_FILES + SOURCES + ${DESKTOP_FILES_IN} +) +add_custom_target(autostart_desktop_files ALL DEPENDS ${DESKTOP_FILES}) +#************************************************ + +install(FILES + ${DESKTOP_FILES} + DESTINATION "${LXQT_ETC_XDG_DIR}/autostart" + COMPONENT Runtime +) diff --git a/autostart/lxqt-desktop.desktop.in b/autostart/lxqt-desktop.desktop.in new file mode 100644 index 0000000..b5ba08d --- /dev/null +++ b/autostart/lxqt-desktop.desktop.in @@ -0,0 +1,9 @@ +[Desktop Entry] +Type=Application +Name=Desktop +Exec=pcmanfm-qt --desktop --profile=lxqt +TryExec=pcmanfm-qt +OnlyShowIn=LXQt; +X-LXQt-Module=true + +#TRANSLATIONS_DIR=translations diff --git a/autostart/translations/lxqt-desktop_ar.desktop b/autostart/translations/lxqt-desktop_ar.desktop new file mode 100644 index 0000000..488c8f2 --- /dev/null +++ b/autostart/translations/lxqt-desktop_ar.desktop @@ -0,0 +1,2 @@ +# Translations +Name[ar]=سطح المكتب diff --git a/autostart/translations/lxqt-desktop_cs.desktop b/autostart/translations/lxqt-desktop_cs.desktop new file mode 100644 index 0000000..41772aa --- /dev/null +++ b/autostart/translations/lxqt-desktop_cs.desktop @@ -0,0 +1,2 @@ +# Translations +Name[cs]=Plocha diff --git a/autostart/translations/lxqt-desktop_cs_CZ.desktop b/autostart/translations/lxqt-desktop_cs_CZ.desktop new file mode 100644 index 0000000..baeb22a --- /dev/null +++ b/autostart/translations/lxqt-desktop_cs_CZ.desktop @@ -0,0 +1,2 @@ +# Translations +Name[cs_CZ]=Plocha diff --git a/autostart/translations/lxqt-desktop_da.desktop b/autostart/translations/lxqt-desktop_da.desktop new file mode 100644 index 0000000..27a277c --- /dev/null +++ b/autostart/translations/lxqt-desktop_da.desktop @@ -0,0 +1,2 @@ +# Translations +Name[da]=Skrivebord diff --git a/autostart/translations/lxqt-desktop_de.desktop b/autostart/translations/lxqt-desktop_de.desktop new file mode 100644 index 0000000..032c706 --- /dev/null +++ b/autostart/translations/lxqt-desktop_de.desktop @@ -0,0 +1,2 @@ +# Translations +Name[de]=Arbeitsfläche diff --git a/autostart/translations/lxqt-desktop_el.desktop b/autostart/translations/lxqt-desktop_el.desktop new file mode 100644 index 0000000..6794a7a --- /dev/null +++ b/autostart/translations/lxqt-desktop_el.desktop @@ -0,0 +1,2 @@ +# Translations +Name[el]=Επιφάνεια εργασίας diff --git a/autostart/translations/lxqt-desktop_eo.desktop b/autostart/translations/lxqt-desktop_eo.desktop new file mode 100644 index 0000000..5eed7a0 --- /dev/null +++ b/autostart/translations/lxqt-desktop_eo.desktop @@ -0,0 +1,2 @@ +# Translations +Name[eo]=Labortablo diff --git a/autostart/translations/lxqt-desktop_es.desktop b/autostart/translations/lxqt-desktop_es.desktop new file mode 100644 index 0000000..abbfb96 --- /dev/null +++ b/autostart/translations/lxqt-desktop_es.desktop @@ -0,0 +1,2 @@ +# Translations +Name[es]=Escritorio diff --git a/autostart/translations/lxqt-desktop_es_VE.desktop b/autostart/translations/lxqt-desktop_es_VE.desktop new file mode 100644 index 0000000..f6f5cef --- /dev/null +++ b/autostart/translations/lxqt-desktop_es_VE.desktop @@ -0,0 +1,2 @@ +# Translations +Name[es_VE]=Escritorio diff --git a/autostart/translations/lxqt-desktop_eu.desktop b/autostart/translations/lxqt-desktop_eu.desktop new file mode 100644 index 0000000..b5d67f1 --- /dev/null +++ b/autostart/translations/lxqt-desktop_eu.desktop @@ -0,0 +1,2 @@ +# Translations +Name[eu]=Mahaigaina diff --git a/autostart/translations/lxqt-desktop_fi.desktop b/autostart/translations/lxqt-desktop_fi.desktop new file mode 100644 index 0000000..00bc361 --- /dev/null +++ b/autostart/translations/lxqt-desktop_fi.desktop @@ -0,0 +1,2 @@ +# Translations +Name[fi]=Työpöytä diff --git a/autostart/translations/lxqt-desktop_fr.desktop b/autostart/translations/lxqt-desktop_fr.desktop new file mode 100644 index 0000000..5ec4dae --- /dev/null +++ b/autostart/translations/lxqt-desktop_fr.desktop @@ -0,0 +1,2 @@ +# Translations +Name[fr]=Bureau diff --git a/autostart/translations/lxqt-desktop_hu.desktop b/autostart/translations/lxqt-desktop_hu.desktop new file mode 100644 index 0000000..f562df9 --- /dev/null +++ b/autostart/translations/lxqt-desktop_hu.desktop @@ -0,0 +1,2 @@ +# Translations +Name[hu]=Asztal diff --git a/autostart/translations/lxqt-desktop_ia.desktop b/autostart/translations/lxqt-desktop_ia.desktop new file mode 100644 index 0000000..084a547 --- /dev/null +++ b/autostart/translations/lxqt-desktop_ia.desktop @@ -0,0 +1,2 @@ +# Translations +Name[ia]=Scriptorio diff --git a/autostart/translations/lxqt-desktop_it_IT.desktop b/autostart/translations/lxqt-desktop_it_IT.desktop new file mode 100644 index 0000000..cf53f2f --- /dev/null +++ b/autostart/translations/lxqt-desktop_it_IT.desktop @@ -0,0 +1,2 @@ +# Translations +Name[it_IT]=Desktop diff --git a/autostart/translations/lxqt-desktop_ja.desktop b/autostart/translations/lxqt-desktop_ja.desktop new file mode 100644 index 0000000..997c2ca --- /dev/null +++ b/autostart/translations/lxqt-desktop_ja.desktop @@ -0,0 +1,2 @@ +# Translations +Name[ja]=デスクトップ diff --git a/autostart/translations/lxqt-desktop_lt.desktop b/autostart/translations/lxqt-desktop_lt.desktop new file mode 100644 index 0000000..e32a241 --- /dev/null +++ b/autostart/translations/lxqt-desktop_lt.desktop @@ -0,0 +1,2 @@ +# Translations +Name[lt]=Darbalaukis diff --git a/autostart/translations/lxqt-desktop_nl.desktop b/autostart/translations/lxqt-desktop_nl.desktop new file mode 100644 index 0000000..9d5a268 --- /dev/null +++ b/autostart/translations/lxqt-desktop_nl.desktop @@ -0,0 +1,2 @@ +# Translations +Name[nl]=Bureaublad diff --git a/autostart/translations/lxqt-desktop_pl_PL.desktop b/autostart/translations/lxqt-desktop_pl_PL.desktop new file mode 100644 index 0000000..8842c2e --- /dev/null +++ b/autostart/translations/lxqt-desktop_pl_PL.desktop @@ -0,0 +1,2 @@ +# Translations +Name[pl_PL]=Pulpit diff --git a/autostart/translations/lxqt-desktop_pt.desktop b/autostart/translations/lxqt-desktop_pt.desktop new file mode 100644 index 0000000..168881a --- /dev/null +++ b/autostart/translations/lxqt-desktop_pt.desktop @@ -0,0 +1,2 @@ +# Translations +Name[pt]=Área de trabalho diff --git a/autostart/translations/lxqt-desktop_pt_BR.desktop b/autostart/translations/lxqt-desktop_pt_BR.desktop new file mode 100644 index 0000000..525b1cf --- /dev/null +++ b/autostart/translations/lxqt-desktop_pt_BR.desktop @@ -0,0 +1,2 @@ +# Translations +Name[pt_BR]=Área de trabalho diff --git a/autostart/translations/lxqt-desktop_ro_RO.desktop b/autostart/translations/lxqt-desktop_ro_RO.desktop new file mode 100644 index 0000000..67c3c8c --- /dev/null +++ b/autostart/translations/lxqt-desktop_ro_RO.desktop @@ -0,0 +1,2 @@ +# Translations +Name[ro_RO]=Desktop diff --git a/autostart/translations/lxqt-desktop_ru.desktop b/autostart/translations/lxqt-desktop_ru.desktop new file mode 100644 index 0000000..212067a --- /dev/null +++ b/autostart/translations/lxqt-desktop_ru.desktop @@ -0,0 +1,2 @@ +# Translations +Name[ru]=Pабочий стол diff --git a/autostart/translations/lxqt-desktop_ru_RU.desktop b/autostart/translations/lxqt-desktop_ru_RU.desktop new file mode 100644 index 0000000..cd0ea09 --- /dev/null +++ b/autostart/translations/lxqt-desktop_ru_RU.desktop @@ -0,0 +1,2 @@ +# Translations +Name[ru_RU]=Рабочий стол diff --git a/autostart/translations/lxqt-desktop_sl.desktop b/autostart/translations/lxqt-desktop_sl.desktop new file mode 100644 index 0000000..b22f360 --- /dev/null +++ b/autostart/translations/lxqt-desktop_sl.desktop @@ -0,0 +1,2 @@ +# Translations +Name[sl]=Namizje diff --git a/autostart/translations/lxqt-desktop_th_TH.desktop b/autostart/translations/lxqt-desktop_th_TH.desktop new file mode 100644 index 0000000..9884b62 --- /dev/null +++ b/autostart/translations/lxqt-desktop_th_TH.desktop @@ -0,0 +1,2 @@ +# Translations +Name[th_TH]=เดสก์ท็อป diff --git a/autostart/translations/lxqt-desktop_tr.desktop b/autostart/translations/lxqt-desktop_tr.desktop new file mode 100644 index 0000000..4de2076 --- /dev/null +++ b/autostart/translations/lxqt-desktop_tr.desktop @@ -0,0 +1,2 @@ +# Translations +Name[tr]=Masaüstü diff --git a/autostart/translations/lxqt-desktop_uk.desktop b/autostart/translations/lxqt-desktop_uk.desktop new file mode 100644 index 0000000..c31081a --- /dev/null +++ b/autostart/translations/lxqt-desktop_uk.desktop @@ -0,0 +1,2 @@ +# Translations +Name[uk]=Стільниця diff --git a/autostart/translations/lxqt-desktop_zh_CN.desktop b/autostart/translations/lxqt-desktop_zh_CN.desktop new file mode 100644 index 0000000..a6312e1 --- /dev/null +++ b/autostart/translations/lxqt-desktop_zh_CN.desktop @@ -0,0 +1,2 @@ +# Translations +Name[zh_CN]=桌面 diff --git a/autostart/translations/lxqt-desktop_zh_TW.desktop b/autostart/translations/lxqt-desktop_zh_TW.desktop new file mode 100644 index 0000000..e474b74 --- /dev/null +++ b/autostart/translations/lxqt-desktop_zh_TW.desktop @@ -0,0 +1,2 @@ +# Translations +Name[zh_TW]=桌面 diff --git a/config/CMakeLists.txt b/config/CMakeLists.txt new file mode 100644 index 0000000..e9cfe75 --- /dev/null +++ b/config/CMakeLists.txt @@ -0,0 +1,8 @@ +# install default config files to /etc/xdg + +configure_file(pcmanfm-qt/lxqt/settings.conf.in pcmanfm-qt/lxqt/settings.conf @ONLY) +install(FILES + "${CMAKE_CURRENT_BINARY_DIR}/pcmanfm-qt/lxqt/settings.conf" + DESTINATION "${LXQT_ETC_XDG_DIR}/pcmanfm-qt/lxqt" + COMPONENT Runtime +) diff --git a/config/pcmanfm-qt/lxqt/settings.conf.in b/config/pcmanfm-qt/lxqt/settings.conf.in new file mode 100644 index 0000000..b7ef002 --- /dev/null +++ b/config/pcmanfm-qt/lxqt/settings.conf.in @@ -0,0 +1,53 @@ +[System] +IconThemeName=elementary +SuCommand=lxqt-sudo %s +TerminalCommand= +Archiver=file-roller +SIUnit=false +TerminalDirCommand=xterm +TerminalExecCommand=xterm -e %s + +[Behavior] +BookmarkOpenMethod=0 +UseTrash=true +SingleClick=false +ConfirmDelete=true + +[Desktop] +WallpaperMode=stretch +Wallpaper=@LXQT_SHARE_DIR@/themes/frost/lxqt-origami-light.png +BgColor=#000000 +FgColor=#ffffff +ShadowColor=#000000 +ShowHidden=false +SortOrder=ascending +SortColumn=name +Font="Sans Serif,10,-1,5,50,0,0,0,0,0" + +[Volume] +MountOnStartup=true +MountRemovable=true +AutoRun=true + +[FolderView] +Mode=icon +ShowHidden=false +SortOrder=ascending +SortColumn=name +BigIconSize=48 +SmallIconSize=24 +SidePaneIconSize=24 +ThumbnailIconSize=128 + +[Window] +Width=640 +Height=480 +AlwaysShowTabs=false +ShowTabClose=true +SplitterPos=150 +SidePaneMode=0 + +[Thumbnail] +ShowThumbnails=true +MaxThumbnailFileSize=4096 +ThumbnailLocalFilesOnly=true diff --git a/pcmanfm/CMakeLists.txt b/pcmanfm/CMakeLists.txt index e7ddb57..b6dc98d 100644 --- a/pcmanfm/CMakeLists.txt +++ b/pcmanfm/CMakeLists.txt @@ -4,13 +4,13 @@ set(pcmanfm_SRCS mainwindow.cpp tabpage.cpp tabbar.cpp + statusbar.cpp view.cpp launcher.cpp preferencesdialog.cpp xdgdir.cpp desktoppreferencesdialog.cpp desktopwindow.cpp - desktopitemdelegate.cpp autorundialog.cpp connectserverdialog.cpp settings.cpp diff --git a/pcmanfm/application.cpp b/pcmanfm/application.cpp index f75e4d9..f26b003 100644 --- a/pcmanfm/application.cpp +++ b/pcmanfm/application.cpp @@ -43,7 +43,7 @@ #include #include #include -#include +#include #include "applicationadaptor.h" #include "preferencesdialog.h" @@ -62,306 +62,317 @@ static const char* serviceName = "org.pcmanfm.PCManFM"; static const char* ifaceName = "org.pcmanfm.Application"; int ProxyStyle::styleHint(StyleHint hint, const QStyleOption* option, const QWidget* widget, QStyleHintReturn* returnData) const { - Application* app = static_cast(qApp); - if(hint == QStyle::SH_ItemView_ActivateItemOnSingleClick) - return app->settings().singleClick(); - return QProxyStyle::styleHint(hint, option, widget, returnData); + Application* app = static_cast(qApp); + if(hint == QStyle::SH_ItemView_ActivateItemOnSingleClick) { + return app->settings().singleClick(); + } + return QProxyStyle::styleHint(hint, option, widget, returnData); } Application::Application(int& argc, char** argv): - QApplication(argc, argv), - libFm_(), - settings_(), - profileName_("default"), - daemonMode_(false), - enableDesktopManager_(false), - desktopWindows_(), - preferencesDialog_(), - editBookmarksialog_(), - volumeMonitor_(NULL), - userDirsWatcher_(NULL), - lxqtRunning_(false) { - - argc_ = argc; - argv_ = argv; - - setApplicationVersion(PCMANFM_QT_VERSION); - - // QDBusConnection::sessionBus().registerObject("/org/pcmanfm/Application", this); - QDBusConnection dbus = QDBusConnection::sessionBus(); - if(dbus.registerService(serviceName)) { - // we successfully registered the service - isPrimaryInstance = true; - setStyle(new ProxyStyle()); - desktop()->installEventFilter(this); - - new ApplicationAdaptor(this); - dbus.registerObject("/Application", this); - - connect(this, &Application::aboutToQuit, this, &Application::onAboutToQuit); - // aboutToQuit() is not signalled on SIGTERM, install signal handler - installSigtermHandler(); - settings_.load(profileName_); - - // decrease the cache size to reduce memory usage - QPixmapCache::setCacheLimit(2048); - - if(settings_.useFallbackIconTheme()) { - QIcon::setThemeName(settings_.fallbackIconThemeName()); - Fm::IconTheme::checkChanged(); - } - - // Check if LXQt Session is running. LXQt has it's own Desktop Folder - // editor. We just hide our editor when LXQt is running. - QDBusInterface* lxqtSessionIface = new QDBusInterface( - QStringLiteral("org.lxqt.session"), - QStringLiteral("/LXQtSession")); - if (lxqtSessionIface) { - if (lxqtSessionIface->isValid()) { - lxqtRunning_ = true; - userDesktopFolder_ = XdgDir::readDesktopDir(); - initWatch(); - } - delete lxqtSessionIface; - lxqtSessionIface = 0; - } - } - else { - // an service of the same name is already registered. - // we're not the first instance - isPrimaryInstance = false; - } + QApplication(argc, argv), + libFm_(), + settings_(), + profileName_("default"), + daemonMode_(false), + enableDesktopManager_(false), + desktopWindows_(), + preferencesDialog_(), + editBookmarksialog_(), + volumeMonitor_(nullptr), + userDirsWatcher_(nullptr), + lxqtRunning_(false) { + + argc_ = argc; + argv_ = argv; + + setApplicationVersion(PCMANFM_QT_VERSION); + + // QDBusConnection::sessionBus().registerObject("/org/pcmanfm/Application", this); + QDBusConnection dbus = QDBusConnection::sessionBus(); + if(dbus.registerService(serviceName)) { + // we successfully registered the service + isPrimaryInstance = true; + setStyle(new ProxyStyle()); + desktop()->installEventFilter(this); + + new ApplicationAdaptor(this); + dbus.registerObject("/Application", this); + + connect(this, &Application::aboutToQuit, this, &Application::onAboutToQuit); + // aboutToQuit() is not signalled on SIGTERM, install signal handler + installSigtermHandler(); + settings_.load(profileName_); + + // decrease the cache size to reduce memory usage + QPixmapCache::setCacheLimit(2048); + + if(settings_.useFallbackIconTheme()) { + QIcon::setThemeName(settings_.fallbackIconThemeName()); + Fm::IconTheme::checkChanged(); + } + + // Check if LXQt Session is running. LXQt has it's own Desktop Folder + // editor. We just hide our editor when LXQt is running. + QDBusInterface* lxqtSessionIface = new QDBusInterface( + QStringLiteral("org.lxqt.session"), + QStringLiteral("/LXQtSession")); + if(lxqtSessionIface) { + if(lxqtSessionIface->isValid()) { + lxqtRunning_ = true; + userDesktopFolder_ = XdgDir::readDesktopDir(); + initWatch(); + } + delete lxqtSessionIface; + lxqtSessionIface = 0; + } + } + else { + // an service of the same name is already registered. + // we're not the first instance + isPrimaryInstance = false; + } } Application::~Application() { - desktop()->removeEventFilter(this); + desktop()->removeEventFilter(this); - if(volumeMonitor_) { - g_signal_handlers_disconnect_by_func(volumeMonitor_, gpointer(onVolumeAdded), this); - g_object_unref(volumeMonitor_); - } + if(volumeMonitor_) { + g_signal_handlers_disconnect_by_func(volumeMonitor_, gpointer(onVolumeAdded), this); + g_object_unref(volumeMonitor_); + } - // if(enableDesktopManager_) - // removeNativeEventFilter(this); + // if(enableDesktopManager_) + // removeNativeEventFilter(this); } -void Application::initWatch() -{ - QFile file_ (QStandardPaths::writableLocation(QStandardPaths::ConfigLocation) + QStringLiteral("/user-dirs.dirs")); - if(! file_.open(QIODevice::ReadOnly | QIODevice::Text)) { - qDebug() << Q_FUNC_INFO << "Could not read: " << userDirsFile_; - userDirsFile_ = QString(); - } else { - userDirsFile_ = file_.fileName(); - } +void Application::initWatch() { + QFile file_(QStandardPaths::writableLocation(QStandardPaths::ConfigLocation) + QStringLiteral("/user-dirs.dirs")); + if(! file_.open(QIODevice::ReadOnly | QIODevice::Text)) { + qDebug() << Q_FUNC_INFO << "Could not read: " << userDirsFile_; + userDirsFile_ = QString(); + } + else { + userDirsFile_ = file_.fileName(); + } - userDirsWatcher_ = new QFileSystemWatcher(this); - userDirsWatcher_->addPath(userDirsFile_); - connect(userDirsWatcher_, &QFileSystemWatcher::fileChanged, this, &Application::onUserDirsChanged); + userDirsWatcher_ = new QFileSystemWatcher(this); + userDirsWatcher_->addPath(userDirsFile_); + connect(userDirsWatcher_, &QFileSystemWatcher::fileChanged, this, &Application::onUserDirsChanged); } bool Application::parseCommandLineArgs() { - bool keepRunning = false; - QCommandLineParser parser; - parser.addHelpOption(); - parser.addVersionOption(); + bool keepRunning = false; + QCommandLineParser parser; + parser.addHelpOption(); + parser.addVersionOption(); - QCommandLineOption profileOption(QStringList() << "p" << "profile", tr("Name of configuration profile"), tr("PROFILE")); - parser.addOption(profileOption); + QCommandLineOption profileOption(QStringList() << "p" << "profile", tr("Name of configuration profile"), tr("PROFILE")); + parser.addOption(profileOption); - QCommandLineOption daemonOption(QStringList() << "d" << "daemon-mode", tr("Run PCManFM as a daemon")); - parser.addOption(daemonOption); + QCommandLineOption daemonOption(QStringList() << "d" << "daemon-mode", tr("Run PCManFM as a daemon")); + parser.addOption(daemonOption); - QCommandLineOption quitOption(QStringList() << "q" << "quit", tr("Quit PCManFM")); - parser.addOption(quitOption); + QCommandLineOption quitOption(QStringList() << "q" << "quit", tr("Quit PCManFM")); + parser.addOption(quitOption); - QCommandLineOption desktopOption("desktop", tr("Launch desktop manager")); - parser.addOption(desktopOption); + QCommandLineOption desktopOption("desktop", tr("Launch desktop manager")); + parser.addOption(desktopOption); - QCommandLineOption desktopOffOption("desktop-off", tr("Turn off desktop manager if it's running")); - parser.addOption(desktopOffOption); + QCommandLineOption desktopOffOption("desktop-off", tr("Turn off desktop manager if it's running")); + parser.addOption(desktopOffOption); - QCommandLineOption desktopPrefOption("desktop-pref", tr("Open desktop preference dialog on the page with the specified name"), tr("NAME")); - parser.addOption(desktopPrefOption); + QCommandLineOption desktopPrefOption("desktop-pref", tr("Open desktop preference dialog on the page with the specified name"), tr("NAME")); + parser.addOption(desktopPrefOption); - QCommandLineOption newWindowOption(QStringList() << "n" << "new-window", tr("Open new window")); - parser.addOption(newWindowOption); + QCommandLineOption newWindowOption(QStringList() << "n" << "new-window", tr("Open new window")); + parser.addOption(newWindowOption); - QCommandLineOption findFilesOption(QStringList() << "f" << "find-files", tr("Open Find Files utility")); - parser.addOption(findFilesOption); + QCommandLineOption findFilesOption(QStringList() << "f" << "find-files", tr("Open Find Files utility")); + parser.addOption(findFilesOption); - QCommandLineOption setWallpaperOption(QStringList() << "w" << "set-wallpaper", tr("Set desktop wallpaper from image FILE"), tr("FILE")); - parser.addOption(setWallpaperOption); + QCommandLineOption setWallpaperOption(QStringList() << "w" << "set-wallpaper", tr("Set desktop wallpaper from image FILE"), tr("FILE")); + parser.addOption(setWallpaperOption); - QCommandLineOption wallpaperModeOption("wallpaper-mode", tr("Set mode of desktop wallpaper. MODE=(%1)").arg("color|stretch|fit|center|tile|zoom"), tr("MODE")); - parser.addOption(wallpaperModeOption); + QCommandLineOption wallpaperModeOption("wallpaper-mode", tr("Set mode of desktop wallpaper. MODE=(%1)").arg("color|stretch|fit|center|tile|zoom"), tr("MODE")); + parser.addOption(wallpaperModeOption); - QCommandLineOption showPrefOption("show-pref", tr("Open Preferences dialog on the page with the specified name"), tr("NAME")); - parser.addOption(showPrefOption); + QCommandLineOption showPrefOption("show-pref", tr("Open Preferences dialog on the page with the specified name"), tr("NAME")); + parser.addOption(showPrefOption); - parser.addPositionalArgument("files", tr("Files or directories to open"), tr("[FILE1, FILE2,...]")); + parser.addPositionalArgument("files", tr("Files or directories to open"), tr("[FILE1, FILE2,...]")); - parser.process(arguments()); + parser.process(arguments()); - if(isPrimaryInstance) { - qDebug("isPrimaryInstance"); + if(isPrimaryInstance) { + qDebug("isPrimaryInstance"); - if(parser.isSet(daemonOption)) - daemonMode_ = true; - if(parser.isSet(profileOption)) - profileName_ = parser.value(profileOption); + if(parser.isSet(daemonOption)) { + daemonMode_ = true; + } + if(parser.isSet(profileOption)) { + profileName_ = parser.value(profileOption); + } - // load settings - settings_.load(profileName_); + // load settings + settings_.load(profileName_); - // desktop icon management - if(parser.isSet(desktopOption)) { - desktopManager(true); - keepRunning = true; - } - else if(parser.isSet(desktopOffOption)) - desktopManager(false); + // desktop icon management + if(parser.isSet(desktopOption)) { + desktopManager(true); + keepRunning = true; + } + else if(parser.isSet(desktopOffOption)) { + desktopManager(false); + } - if(parser.isSet(desktopPrefOption)) { // desktop preference dialog - desktopPrefrences(parser.value(desktopPrefOption)); - keepRunning = true; - } - else if(parser.isSet(findFilesOption)) { // file searching utility - findFiles(parser.positionalArguments()); - keepRunning = true; - } - else if(parser.isSet(showPrefOption)) { // preferences dialog - preferences(parser.value(showPrefOption)); - keepRunning = true; + if(parser.isSet(desktopPrefOption)) { // desktop preference dialog + desktopPrefrences(parser.value(desktopPrefOption)); + keepRunning = true; + } + else if(parser.isSet(findFilesOption)) { // file searching utility + findFiles(parser.positionalArguments()); + keepRunning = true; + } + else if(parser.isSet(showPrefOption)) { // preferences dialog + preferences(parser.value(showPrefOption)); + keepRunning = true; + } + else if(parser.isSet(setWallpaperOption) || parser.isSet(wallpaperModeOption)) { // set wall paper + setWallpaper(parser.value(setWallpaperOption), parser.value(wallpaperModeOption)); + } + else { + if(!parser.isSet(desktopOption) && !parser.isSet(desktopOffOption)) { + QStringList paths = parser.positionalArguments(); + if(paths.isEmpty()) { + // if no path is specified and we're using daemon mode, + // don't open current working directory + if(!daemonMode_) { + paths.push_back(QDir::currentPath()); + } + } + if(!paths.isEmpty()) { + launchFiles(QDir::currentPath(), paths, parser.isSet(newWindowOption)); + } + keepRunning = true; + } + } } - else if(parser.isSet(setWallpaperOption) || parser.isSet(wallpaperModeOption)) // set wall paper - setWallpaper(parser.value(setWallpaperOption), parser.value(wallpaperModeOption)); else { - if(!parser.isSet(desktopOption) && !parser.isSet(desktopOffOption)) { - QStringList paths = parser.positionalArguments(); - if(paths.isEmpty()) { - // if no path is specified and we're using daemon mode, - // don't open current working directory - if(!daemonMode_) - paths.push_back(QDir::currentPath()); - } - if(!paths.isEmpty()) - launchFiles(QDir::currentPath(), paths, parser.isSet(newWindowOption)); - keepRunning = true; - } - } - } - else { - QDBusConnection dbus = QDBusConnection::sessionBus(); - QDBusInterface iface(serviceName, "/Application", ifaceName, dbus, this); - if(parser.isSet(quitOption)) { - iface.call("quit"); - return false; - } + QDBusConnection dbus = QDBusConnection::sessionBus(); + QDBusInterface iface(serviceName, "/Application", ifaceName, dbus, this); + if(parser.isSet(quitOption)) { + iface.call("quit"); + return false; + } - if(parser.isSet(desktopOption)) - iface.call("desktopManager", true); - else if(parser.isSet(desktopOffOption)) - iface.call("desktopManager", false); + if(parser.isSet(desktopOption)) { + iface.call("desktopManager", true); + } + else if(parser.isSet(desktopOffOption)) { + iface.call("desktopManager", false); + } - if(parser.isSet(desktopPrefOption)) { // desktop preference dialog - iface.call("desktopPrefrences", parser.value(desktopPrefOption)); - } - else if(parser.isSet(findFilesOption)) { // file searching utility - iface.call("findFiles", parser.positionalArguments()); - } - else if(parser.isSet(showPrefOption)) { // preferences dialog - iface.call("preferences", parser.value(showPrefOption)); - } - else if(parser.isSet(setWallpaperOption) || parser.isSet(wallpaperModeOption)) { // set wall paper - iface.call("setWallpaper", parser.value(setWallpaperOption), parser.value(wallpaperModeOption)); - } - else { - if(!parser.isSet(desktopOption) && !parser.isSet(desktopOffOption)) { - QStringList paths = parser.positionalArguments(); - if(paths.isEmpty()) { - paths.push_back(QDir::currentPath()); + if(parser.isSet(desktopPrefOption)) { // desktop preference dialog + iface.call("desktopPrefrences", parser.value(desktopPrefOption)); + } + else if(parser.isSet(findFilesOption)) { // file searching utility + iface.call("findFiles", parser.positionalArguments()); + } + else if(parser.isSet(showPrefOption)) { // preferences dialog + iface.call("preferences", parser.value(showPrefOption)); + } + else if(parser.isSet(setWallpaperOption) || parser.isSet(wallpaperModeOption)) { // set wall paper + iface.call("setWallpaper", parser.value(setWallpaperOption), parser.value(wallpaperModeOption)); + } + else { + if(!parser.isSet(desktopOption) && !parser.isSet(desktopOffOption)) { + QStringList paths = parser.positionalArguments(); + if(paths.isEmpty()) { + paths.push_back(QDir::currentPath()); + } + iface.call("launchFiles", QDir::currentPath(), paths, parser.isSet(newWindowOption)); + } } - iface.call("launchFiles", QDir::currentPath(), paths, parser.isSet(newWindowOption)); - } } - } - return keepRunning; + return keepRunning; } void Application::init() { - // install the translations built-into Qt itself - qtTranslator.load("qt_" + QLocale::system().name(), QLibraryInfo::location(QLibraryInfo::TranslationsPath)); - installTranslator(&qtTranslator); + // install the translations built-into Qt itself + qtTranslator.load("qt_" + QLocale::system().name(), QLibraryInfo::location(QLibraryInfo::TranslationsPath)); + installTranslator(&qtTranslator); - // install libfm-qt translator - installTranslator(libFm_.translator()); + // install libfm-qt translator + installTranslator(libFm_.translator()); - // install our own tranlations - translator.load("pcmanfm-qt_" + QLocale::system().name(), PCMANFM_DATA_DIR "/translations"); - installTranslator(&translator); + // install our own tranlations + translator.load("pcmanfm-qt_" + QLocale::system().name(), PCMANFM_DATA_DIR "/translations"); + installTranslator(&translator); } int Application::exec() { - if(!parseCommandLineArgs()) - return 0; + if(!parseCommandLineArgs()) { + return 0; + } - if(daemonMode_) // keep running even when there is no window opened. - setQuitOnLastWindowClosed(false); + if(daemonMode_) { // keep running even when there is no window opened. + setQuitOnLastWindowClosed(false); + } - volumeMonitor_ = g_volume_monitor_get(); - // delay the volume manager a little because in newer versions of glib/gio there's a problem. - // when the first volume monitor object is created, it discovers volumes asynchonously. - // g_volume_monitor_get() immediately returns while the monitor is still discovering devices. - // So initially g_volume_monitor_get_volumes() returns nothing, but shortly after that - // we get volume-added signals for all of the volumes. This is not what we want. - // So, we wait for 3 seconds here to let it finish device discovery. - QTimer::singleShot(3000, this, SLOT(initVolumeManager())); + volumeMonitor_ = g_volume_monitor_get(); + // delay the volume manager a little because in newer versions of glib/gio there's a problem. + // when the first volume monitor object is created, it discovers volumes asynchonously. + // g_volume_monitor_get() immediately returns while the monitor is still discovering devices. + // So initially g_volume_monitor_get_volumes() returns nothing, but shortly after that + // we get volume-added signals for all of the volumes. This is not what we want. + // So, we wait for 3 seconds here to let it finish device discovery. + QTimer::singleShot(3000, this, SLOT(initVolumeManager())); - return QCoreApplication::exec(); + return QCoreApplication::exec(); } -void Application::onUserDirsChanged() -{ - qDebug() << Q_FUNC_INFO; - bool file_deleted = !userDirsWatcher_->files().contains(userDirsFile_); - if(file_deleted) { - // if our config file is already deleted, reinstall a new watcher - userDirsWatcher_->addPath(userDirsFile_); - } +void Application::onUserDirsChanged() { + qDebug() << Q_FUNC_INFO; + bool file_deleted = !userDirsWatcher_->files().contains(userDirsFile_); + if(file_deleted) { + // if our config file is already deleted, reinstall a new watcher + userDirsWatcher_->addPath(userDirsFile_); + } - const QString d = XdgDir::readDesktopDir(); - if (d != userDesktopFolder_) { - userDesktopFolder_ = d; - const QDir dir(d); - if (dir.exists()) { - const int N = desktopWindows_.size(); - for(int i = 0; i < N; ++i) { - desktopWindows_.at(i)->setDesktopFolder(); - } - } else { - qWarning("Application::onUserDirsChanged: %s doesn't exist", - userDesktopFolder_.toUtf8().constData()); + const QString d = XdgDir::readDesktopDir(); + if(d != userDesktopFolder_) { + userDesktopFolder_ = d; + const QDir dir(d); + if(dir.exists()) { + const int N = desktopWindows_.size(); + for(int i = 0; i < N; ++i) { + desktopWindows_.at(i)->setDesktopFolder(); + } + } + else { + qWarning("Application::onUserDirsChanged: %s doesn't exist", + userDesktopFolder_.toUtf8().constData()); + } } - } } void Application::onAboutToQuit() { - qDebug("aboutToQuit"); - settings_.save(); + qDebug("aboutToQuit"); + settings_.save(); } bool Application::eventFilter(QObject* watched, QEvent* event) { - if(watched == desktop()) { - if (event->type() == QEvent::StyleChange || - event->type() == QEvent::ThemeChange) { - setStyle(new ProxyStyle()); + if(watched == desktop()) { + if(event->type() == QEvent::StyleChange || + event->type() == QEvent::ThemeChange) { + setStyle(new ProxyStyle()); + } } - } - return QObject::eventFilter(watched, event); + return QObject::eventFilter(watched, event); } void Application::onLastWindowClosed() { @@ -373,491 +384,514 @@ void Application::onSaveStateRequest(QSessionManager& manager) { } void Application::desktopManager(bool enabled) { - // TODO: turn on or turn off desktpo management (desktop icons & wallpaper) - qDebug("desktopManager: %d", enabled); - QDesktopWidget* desktopWidget = desktop(); - if(enabled) { - if(!enableDesktopManager_) { - // installNativeEventFilter(this); - Q_FOREACH(QScreen* screen, screens()) { - connect(screen, &QScreen::virtualGeometryChanged, this, &Application::onVirtualGeometryChanged); - connect(screen, &QObject::destroyed, this, &Application::onScreenDestroyed); - } - connect(this, &QApplication::screenAdded, this, &Application::onScreenAdded); - connect(desktopWidget, &QDesktopWidget::resized, this, &Application::onScreenResized); - connect(desktopWidget, &QDesktopWidget::screenCountChanged, this, &Application::onScreenCountChanged); - - // NOTE: there are two modes - // When virtual desktop is used (all screens are combined to form a large virtual desktop), - // we only create one DesktopWindow. Otherwise, we create one for each screen. - if(desktopWidget->isVirtualDesktop()) { - DesktopWindow* window = createDesktopWindow(-1); - desktopWindows_.push_back(window); - } - else { - int n = desktopWidget->numScreens(); - desktopWindows_.reserve(n); - for(int i = 0; i < n; ++i) { - DesktopWindow* window = createDesktopWindow(i); - desktopWindows_.push_back(window); - } - } - } - } - else { - if(enableDesktopManager_) { - disconnect(desktopWidget, &QDesktopWidget::resized, this, &Application::onScreenResized); - disconnect(desktopWidget, &QDesktopWidget::screenCountChanged, this, &Application::onScreenCountChanged); - int n = desktopWindows_.size(); - for(int i = 0; i < n; ++i) { - DesktopWindow* window = desktopWindows_.at(i); - delete window; - } - desktopWindows_.clear(); - Q_FOREACH(QScreen* screen, screens()) { - disconnect(screen, &QScreen::virtualGeometryChanged, this, &Application::onVirtualGeometryChanged); - disconnect(screen, &QObject::destroyed, this, &Application::onScreenDestroyed); - } - disconnect(this, &QApplication::screenAdded, this, &Application::onScreenAdded); - // removeNativeEventFilter(this); - } - } - enableDesktopManager_ = enabled; + // TODO: turn on or turn off desktpo management (desktop icons & wallpaper) + qDebug("desktopManager: %d", enabled); + QDesktopWidget* desktopWidget = desktop(); + if(enabled) { + if(!enableDesktopManager_) { + // installNativeEventFilter(this); + Q_FOREACH(QScreen* screen, screens()) { + connect(screen, &QScreen::virtualGeometryChanged, this, &Application::onVirtualGeometryChanged); + connect(screen, &QObject::destroyed, this, &Application::onScreenDestroyed); + } + connect(this, &QApplication::screenAdded, this, &Application::onScreenAdded); + connect(desktopWidget, &QDesktopWidget::resized, this, &Application::onScreenResized); + connect(desktopWidget, &QDesktopWidget::screenCountChanged, this, &Application::onScreenCountChanged); + + // NOTE: there are two modes + // When virtual desktop is used (all screens are combined to form a large virtual desktop), + // we only create one DesktopWindow. Otherwise, we create one for each screen. + if(desktopWidget->isVirtualDesktop()) { + DesktopWindow* window = createDesktopWindow(-1); + desktopWindows_.push_back(window); + } + else { + int n = desktopWidget->numScreens(); + desktopWindows_.reserve(n); + for(int i = 0; i < n; ++i) { + DesktopWindow* window = createDesktopWindow(i); + desktopWindows_.push_back(window); + } + } + } + } + else { + if(enableDesktopManager_) { + disconnect(desktopWidget, &QDesktopWidget::resized, this, &Application::onScreenResized); + disconnect(desktopWidget, &QDesktopWidget::screenCountChanged, this, &Application::onScreenCountChanged); + int n = desktopWindows_.size(); + for(int i = 0; i < n; ++i) { + DesktopWindow* window = desktopWindows_.at(i); + delete window; + } + desktopWindows_.clear(); + Q_FOREACH(QScreen* screen, screens()) { + disconnect(screen, &QScreen::virtualGeometryChanged, this, &Application::onVirtualGeometryChanged); + disconnect(screen, &QObject::destroyed, this, &Application::onScreenDestroyed); + } + disconnect(this, &QApplication::screenAdded, this, &Application::onScreenAdded); + // removeNativeEventFilter(this); + } + } + enableDesktopManager_ = enabled; } void Application::desktopPrefrences(QString page) { - // show desktop preference window - if(!desktopPreferencesDialog_) { - desktopPreferencesDialog_ = new DesktopPreferencesDialog(); + // show desktop preference window + if(!desktopPreferencesDialog_) { + desktopPreferencesDialog_ = new DesktopPreferencesDialog(); - // Should be used only one time - desktopPreferencesDialog_->setEditDesktopFolder(!lxqtRunning_); - } - desktopPreferencesDialog_.data()->selectPage(page); - desktopPreferencesDialog_.data()->show(); - desktopPreferencesDialog_.data()->raise(); - desktopPreferencesDialog_.data()->activateWindow(); + // Should be used only one time + desktopPreferencesDialog_->setEditDesktopFolder(!lxqtRunning_); + } + desktopPreferencesDialog_.data()->selectPage(page); + desktopPreferencesDialog_.data()->show(); + desktopPreferencesDialog_.data()->raise(); + desktopPreferencesDialog_.data()->activateWindow(); } void Application::onFindFileAccepted() { - Fm::FileSearchDialog* dlg = static_cast(sender()); - Fm::Path uri = dlg->searchUri(); - Fm::PathList paths; - paths.pushTail(uri); - MainWindow* window = MainWindow::lastActive(); - Launcher(window).launchPaths(NULL, paths); + Fm::FileSearchDialog* dlg = static_cast(sender()); + // get search settings + settings_.setSearchNameCaseInsensitive(dlg->nameCaseInsensitive()); + settings_.setsearchContentCaseInsensitive(dlg->contentCaseInsensitive()); + settings_.setSearchNameRegexp(dlg->nameRegexp()); + settings_.setSearchContentRegexp(dlg->contentRegexp()); + settings_.setSearchRecursive(dlg->recursive()); + settings_.setSearchhHidden(dlg->searchhHidden()); + + Fm::Path uri = dlg->searchUri(); + Fm::FilePathList paths; + Fm::GFilePtr gf{uri.toGfile(), false}; + paths.push_back(Fm::FilePath{gf.get(), true}); + MainWindow* window = MainWindow::lastActive(); + Launcher(window).launchPaths(nullptr, paths); } void Application::onConnectToServerAccepted() { - ConnectServerDialog* dlg = static_cast(sender()); - QString uri = dlg->uriText(); - Fm::Path path = Fm::Path::newForStr(uri.toUtf8().constData()); - qDebug() << uri << " => " << path.toStr(); - Fm::PathList paths; - paths.pushTail(path); - MainWindow* window = MainWindow::lastActive(); - Launcher(window).launchPaths(NULL, paths); + ConnectServerDialog* dlg = static_cast(sender()); + QString uri = dlg->uriText(); + Fm::FilePathList paths; + paths.push_back(Fm::FilePath::fromDisplayName(uri.toUtf8().constData())); + MainWindow* window = MainWindow::lastActive(); + Launcher(window).launchPaths(nullptr, paths); } void Application::findFiles(QStringList paths) { - // launch file searching utility. - Fm::FileSearchDialog* dlg = new Fm::FileSearchDialog(paths); - connect(dlg, &QDialog::accepted, this, &Application::onFindFileAccepted); - dlg->setAttribute(Qt::WA_DeleteOnClose); - dlg->show(); + // launch file searching utility. + Fm::FileSearchDialog* dlg = new Fm::FileSearchDialog(paths); + connect(dlg, &QDialog::accepted, this, &Application::onFindFileAccepted); + dlg->setAttribute(Qt::WA_DeleteOnClose); + // set search settings + dlg->setNameCaseInsensitive(settings_.searchNameCaseInsensitive()); + dlg->setContentCaseInsensitive(settings_.searchContentCaseInsensitive()); + dlg->setNameRegexp(settings_.searchNameRegexp()); + dlg->setContentRegexp(settings_.searchContentRegexp()); + dlg->setRecursive(settings_.searchRecursive()); + dlg->setSearchhHidden(settings_.searchhHidden()); + + dlg->show(); } void Application::connectToServer() { - ConnectServerDialog* dlg = new ConnectServerDialog(); - connect(dlg, &QDialog::accepted, this, &Application::onConnectToServerAccepted); - dlg->setAttribute(Qt::WA_DeleteOnClose); - dlg->show(); + ConnectServerDialog* dlg = new ConnectServerDialog(); + connect(dlg, &QDialog::accepted, this, &Application::onConnectToServerAccepted); + dlg->setAttribute(Qt::WA_DeleteOnClose); + dlg->show(); } void Application::launchFiles(QString cwd, QStringList paths, bool inNewWindow) { - Fm::PathList pathList; - Fm::Path cwd_path; - QStringList::iterator it; - Q_FOREACH(const QString& it, paths) { - QByteArray pathName = it.toLocal8Bit(); - Fm::Path path; - if(pathName[0] == '/') // absolute path - path = Fm::Path::newForPath(pathName.constData()); - else if(pathName.contains(":/")) // URI - path = Fm::Path::newForUri(pathName.constData()); - else if(pathName == "~") // special case for home dir - path = Fm::Path::getHome(); - else // basename - { - if(Q_UNLIKELY(!cwd_path)) - cwd_path = Fm::Path::newForStr(cwd.toLocal8Bit().constData()); - path = cwd_path.newRelative(pathName.constData()); - } - fm_path_list_push_tail(pathList, path); - } - - Launcher(NULL).launchPaths(NULL, pathList); + Fm::FilePathList pathList; + Fm::FilePath cwd_path; + QStringList::iterator it; + Q_FOREACH(const QString& it, paths) { + QByteArray pathName = it.toLocal8Bit(); + Fm::FilePath path; + if(pathName == "~") { // special case for home dir + path = Fm::FilePath::homeDir(); + } + if(pathName[0] == '/') { // absolute path + path = Fm::FilePath::fromLocalPath(pathName.constData()); + } + else if(pathName.contains(":/")) { // URI + path = Fm::FilePath::fromUri(pathName.constData()); + } + else { // basename + if(Q_UNLIKELY(!cwd_path)) { + cwd_path = Fm::FilePath::fromLocalPath(cwd.toLocal8Bit().constData()); + } + path = cwd_path.relativePath(pathName.constData()); + } + pathList.push_back(std::move(path)); + } + + Launcher(nullptr).launchPaths(nullptr, pathList); } void Application::openFolders(Fm::FileInfoList files) { - Launcher(NULL).launchFiles(NULL, files); + Launcher(nullptr).launchFiles(nullptr, std::move(files)); } -void Application::openFolderInTerminal(Fm::Path path) { - if(!settings_.terminal().isEmpty()) { - char* cwd_str; - if(path.isNative()) - cwd_str = path.toStr(); - else { // gio will map remote filesystems to local FUSE-mounted paths here. - GFile* gf = path.toGfile(); - cwd_str = g_file_get_path(gf); - g_object_unref(gf); +void Application::openFolderInTerminal(Fm::FilePath path) { + if(!settings_.terminal().isEmpty()) { + Fm::GErrorPtr err; + auto terminalName = settings_.terminal().toUtf8(); + if(!Fm::launchTerminal(terminalName.constData(), path, err)) { + QMessageBox::critical(nullptr, tr("Error"), err.message()); + } } - GError* err = NULL; - if(!Fm::Terminal::launch(cwd_str, &err)) { - QMessageBox::critical(NULL, tr("Error"), QString::fromUtf8(err->message)); - g_error_free(err); + else { + // show an error message and ask the user to set the command + QMessageBox::critical(nullptr, tr("Error"), tr("Terminal emulator is not set.")); + preferences("advanced"); } - g_free(cwd_str); - } - else { - // show an error message and ask the user to set the command - QMessageBox::critical(NULL, tr("Error"), tr("Terminal emulator is not set.")); - preferences("advanced"); - } } void Application::preferences(QString page) { - // open preference dialog - if(!preferencesDialog_) { - preferencesDialog_ = new PreferencesDialog(page); - } - else { - preferencesDialog_.data()->selectPage(page); - } - preferencesDialog_.data()->show(); - preferencesDialog_.data()->raise(); - preferencesDialog_.data()->activateWindow(); + // open preference dialog + if(!preferencesDialog_) { + preferencesDialog_ = new PreferencesDialog(page); + } + else { + preferencesDialog_.data()->selectPage(page); + } + preferencesDialog_.data()->show(); + preferencesDialog_.data()->raise(); + preferencesDialog_.data()->activateWindow(); } void Application::setWallpaper(QString path, QString modeString) { - static const char* valid_wallpaper_modes[] = {"color", "stretch", "fit", "center", "tile"}; - DesktopWindow::WallpaperMode mode = settings_.wallpaperMode(); - bool changed = false; - - if(!path.isEmpty() && path != settings_.wallpaper()) { - if(QFile(path).exists()) { - settings_.setWallpaper(path); - changed = true; - } - } - // convert mode string to value - for(std::size_t i = 0; i < G_N_ELEMENTS(valid_wallpaper_modes); ++i) { - if(modeString == valid_wallpaper_modes[i]) { - // We don't take safety checks because valid_wallpaper_modes[] is - // defined in this function and we can clearly see that it does not - // overflow. - mode = static_cast(i); - if(mode != settings_.wallpaperMode()) - changed = true; - break; - } - } - // FIXME: support different wallpapers on different screen. - // update wallpaper - if(changed) { - if(enableDesktopManager_) { - Q_FOREACH(DesktopWindow * desktopWindow, desktopWindows_) { - if(!path.isEmpty()) - desktopWindow->setWallpaperFile(path); - if(mode != settings_.wallpaperMode()) - desktopWindow->setWallpaperMode(mode); - desktopWindow->updateWallpaper(); - } - settings_.save(); // save the settings to the config file + static const char* valid_wallpaper_modes[] = {"color", "stretch", "fit", "center", "tile"}; + DesktopWindow::WallpaperMode mode = settings_.wallpaperMode(); + bool changed = false; + + if(!path.isEmpty() && path != settings_.wallpaper()) { + if(QFile(path).exists()) { + settings_.setWallpaper(path); + changed = true; + } + } + // convert mode string to value + for(std::size_t i = 0; i < G_N_ELEMENTS(valid_wallpaper_modes); ++i) { + if(modeString == valid_wallpaper_modes[i]) { + // We don't take safety checks because valid_wallpaper_modes[] is + // defined in this function and we can clearly see that it does not + // overflow. + mode = static_cast(i); + if(mode != settings_.wallpaperMode()) { + changed = true; + } + break; + } + } + // FIXME: support different wallpapers on different screen. + // update wallpaper + if(changed) { + if(enableDesktopManager_) { + Q_FOREACH(DesktopWindow* desktopWindow, desktopWindows_) { + if(!path.isEmpty()) { + desktopWindow->setWallpaperFile(path); + } + if(mode != settings_.wallpaperMode()) { + desktopWindow->setWallpaperMode(mode); + } + desktopWindow->updateWallpaper(); + } + settings_.save(); // save the settings to the config file + } } - } } void Application::onScreenResized(int num) { - if(desktop()->isVirtualDesktop()) { - // in virtual desktop mode, we only have one desktop window. that is the first one. - DesktopWindow* window = desktopWindows_.at(0); - window->setGeometry(desktop()->geometry()); - } - else { - DesktopWindow* window = desktopWindows_.at(num); - QRect rect = desktop()->screenGeometry(num); - window->setGeometry(rect); - } + if(desktop()->isVirtualDesktop()) { + // in virtual desktop mode, we only have one desktop window. that is the first one. + DesktopWindow* window = desktopWindows_.at(0); + window->setGeometry(desktop()->geometry()); + } + else { + DesktopWindow* window = desktopWindows_.at(num); + QRect rect = desktop()->screenGeometry(num); + window->setGeometry(rect); + } } DesktopWindow* Application::createDesktopWindow(int screenNum) { - DesktopWindow* window = new DesktopWindow(screenNum); - if(screenNum == -1) { // one large virtual desktop only - QRect rect = desktop()->geometry(); - window->setGeometry(rect); - } - else { - QRect rect = desktop()->screenGeometry(screenNum); - window->setGeometry(rect); - } - window->updateFromSettings(settings_); - window->show(); - return window; + DesktopWindow* window = new DesktopWindow(screenNum); + if(screenNum == -1) { // one large virtual desktop only + QRect rect = desktop()->geometry(); + window->setGeometry(rect); + } + else { + QRect rect = desktop()->screenGeometry(screenNum); + window->setGeometry(rect); + } + window->updateFromSettings(settings_); + window->show(); + return window; } void Application::onScreenCountChanged(int newCount) { - QDesktopWidget* desktopWidget = desktop(); - bool oldVirtual = (desktopWindows_.size() == 1 && desktopWindows_.at(0)->screenNum() == -1); - bool isVirtual = desktopWidget->isVirtualDesktop(); - - if(oldVirtual && isVirtual) { - // if we are using virtual desktop mode previously, and the new mode is sitll virtual - // no further change is needed, only do relayout. - desktopWindows_.at(0)->queueRelayout(); - return; - } - - // we used non-virtual mode originally, but now we're switched to virtual mode - if(isVirtual) - newCount = 1; // we only want one desktop window for all screens in virtual mode - - if(newCount > desktopWindows_.size()) { - // add more desktop windows - for(int i = desktopWindows_.size(); i < newCount; ++i) { - DesktopWindow* desktop = createDesktopWindow(i); - desktopWindows_.push_back(desktop); - } - } - else if(newCount < desktopWindows_.size()) { - // delete excessive desktop windows - for(int i = newCount; i < desktopWindows_.size(); ++i) { - DesktopWindow* desktop = desktopWindows_.at(i); - delete desktop; - } - desktopWindows_.resize(newCount); - } - - if(newCount == 1) { // now only 1 screen is in use - DesktopWindow* desktop = desktopWindows_.at(0); - if(isVirtual) - desktop->setScreenNum(-1); - else // non-virtual mode, and we only have 1 screen - desktop->setScreenNum(0); - desktop->updateWallpaper(); - } + QDesktopWidget* desktopWidget = desktop(); + bool oldVirtual = (desktopWindows_.size() == 1 && desktopWindows_.at(0)->screenNum() == -1); + bool isVirtual = desktopWidget->isVirtualDesktop(); + + if(oldVirtual && isVirtual) { + // if we are using virtual desktop mode previously, and the new mode is sitll virtual + // no further change is needed, only do relayout. + desktopWindows_.at(0)->queueRelayout(); + return; + } + + // we used non-virtual mode originally, but now we're switched to virtual mode + if(isVirtual) { + newCount = 1; // we only want one desktop window for all screens in virtual mode + } + + if(newCount > desktopWindows_.size()) { + // add more desktop windows + for(int i = desktopWindows_.size(); i < newCount; ++i) { + DesktopWindow* desktop = createDesktopWindow(i); + desktopWindows_.push_back(desktop); + } + } + else if(newCount < desktopWindows_.size()) { + // delete excessive desktop windows + for(int i = newCount; i < desktopWindows_.size(); ++i) { + DesktopWindow* desktop = desktopWindows_.at(i); + delete desktop; + } + desktopWindows_.resize(newCount); + } + + if(newCount == 1) { // now only 1 screen is in use + DesktopWindow* desktop = desktopWindows_.at(0); + if(isVirtual) { + desktop->setScreenNum(-1); + } + else { // non-virtual mode, and we only have 1 screen + desktop->setScreenNum(0); + } + desktop->updateWallpaper(); + } } // called when Settings is changed to update UI void Application::updateFromSettings() { - // if(iconTheme.isEmpty()) - // Fm::IconTheme::setThemeName(settings_.fallbackIconThemeName()); - - // update main windows and desktop windows - QWidgetList windows = this->topLevelWidgets(); - QWidgetList::iterator it; - for(it = windows.begin(); it != windows.end(); ++it) { - QWidget* window = *it; - if(window->inherits("PCManFM::MainWindow")) { - MainWindow* mainWindow = static_cast(window); - mainWindow->updateFromSettings(settings_); + // if(iconTheme.isEmpty()) + // Fm::IconTheme::setThemeName(settings_.fallbackIconThemeName()); + + // update main windows and desktop windows + QWidgetList windows = this->topLevelWidgets(); + QWidgetList::iterator it; + for(it = windows.begin(); it != windows.end(); ++it) { + QWidget* window = *it; + if(window->inherits("PCManFM::MainWindow")) { + MainWindow* mainWindow = static_cast(window); + mainWindow->updateFromSettings(settings_); + } + } + if(desktopManagerEnabled()) { + updateDesktopsFromSettings(); } - } - if(desktopManagerEnabled()) - updateDesktopsFromSettings(); } -void Application::updateDesktopsFromSettings() { - QVector::iterator it; - for(it = desktopWindows_.begin(); it != desktopWindows_.end(); ++it) { - DesktopWindow* desktopWindow = static_cast(*it); - desktopWindow->updateFromSettings(settings_); - } +void Application::updateDesktopsFromSettings(bool changeSlide) { + QVector::iterator it; + for(it = desktopWindows_.begin(); it != desktopWindows_.end(); ++it) { + DesktopWindow* desktopWindow = static_cast(*it); + desktopWindow->updateFromSettings(settings_, changeSlide); + } } void Application::editBookmarks() { - if(!editBookmarksialog_) { - FmBookmarks* bookmarks = fm_bookmarks_dup(); - editBookmarksialog_ = new Fm::EditBookmarksDialog(bookmarks); - g_object_unref(bookmarks); - } - editBookmarksialog_.data()->show(); + if(!editBookmarksialog_) { + FmBookmarks* bookmarks = fm_bookmarks_dup(); + editBookmarksialog_ = new Fm::EditBookmarksDialog(bookmarks); + g_object_unref(bookmarks); + } + editBookmarksialog_.data()->show(); } void Application::initVolumeManager() { - g_signal_connect(volumeMonitor_, "volume-added", G_CALLBACK(onVolumeAdded), this); - - if(settings_.mountOnStartup()) { - /* try to automount all volumes */ - GList* vols = g_volume_monitor_get_volumes(volumeMonitor_); - for(GList* l = vols; l; l = l->next) { - GVolume* volume = G_VOLUME(l->data); - if(g_volume_should_automount(volume)) - autoMountVolume(volume, false); - g_object_unref(volume); + g_signal_connect(volumeMonitor_, "volume-added", G_CALLBACK(onVolumeAdded), this); + + if(settings_.mountOnStartup()) { + /* try to automount all volumes */ + GList* vols = g_volume_monitor_get_volumes(volumeMonitor_); + for(GList* l = vols; l; l = l->next) { + GVolume* volume = G_VOLUME(l->data); + if(g_volume_should_automount(volume)) { + autoMountVolume(volume, false); + } + g_object_unref(volume); + } + g_list_free(vols); } - g_list_free(vols); - } } bool Application::autoMountVolume(GVolume* volume, bool interactive) { - if(!g_volume_should_automount(volume) || !g_volume_can_mount(volume)) - return FALSE; - - GMount* mount = g_volume_get_mount(volume); - if(!mount) { // not mounted, automount is needed - // try automount - Fm::MountOperation* op = new Fm::MountOperation(interactive); - op->mount(volume); - if(!op->wait()) - return false; - if(!interactive) - return true; - mount = g_volume_get_mount(volume); - } - - if(mount) { - if(interactive && settings_.autoRun()) { // show autorun dialog - AutoRunDialog* dlg = new AutoRunDialog(volume, mount); - dlg->show(); - } - g_object_unref(mount); - } - return true; + if(!g_volume_should_automount(volume) || !g_volume_can_mount(volume)) { + return FALSE; + } + + GMount* mount = g_volume_get_mount(volume); + if(!mount) { // not mounted, automount is needed + // try automount + Fm::MountOperation* op = new Fm::MountOperation(interactive); + op->mount(volume); + if(!op->wait()) { + return false; + } + if(!interactive) { + return true; + } + mount = g_volume_get_mount(volume); + } + + if(mount) { + if(interactive && settings_.autoRun()) { // show autorun dialog + AutoRunDialog* dlg = new AutoRunDialog(volume, mount); + dlg->show(); + } + g_object_unref(mount); + } + return true; } // static void Application::onVolumeAdded(GVolumeMonitor* monitor, GVolume* volume, Application* pThis) { - if(pThis->settings_.mountRemovable()) - pThis->autoMountVolume(volume, true); + if(pThis->settings_.mountRemovable()) { + pThis->autoMountVolume(volume, true); + } } #if 0 -bool Application::nativeEventFilter(const QByteArray & eventType, void * message, long * result) { - if(eventType == "xcb_generic_event_t") { // XCB event - // filter all native X11 events (xcb) - xcb_generic_event_t* generic_event = reinterpret_cast(message); - // qDebug("XCB event: %d", generic_event->response_type & ~0x80); - Q_FOREACH(DesktopWindow * window, desktopWindows_) { +bool Application::nativeEventFilter(const QByteArray& eventType, void* message, long* result) { + if(eventType == "xcb_generic_event_t") { // XCB event + // filter all native X11 events (xcb) + xcb_generic_event_t* generic_event = reinterpret_cast(message); + // qDebug("XCB event: %d", generic_event->response_type & ~0x80); + Q_FOREACH(DesktopWindow* window, desktopWindows_) { + } } - } - return false; + return false; } #endif void Application::onScreenAdded(QScreen* newScreen) { - if(enableDesktopManager_) { - connect(newScreen, &QScreen::virtualGeometryChanged, this, &Application::onVirtualGeometryChanged); - connect(newScreen, &QObject::destroyed, this, &Application::onScreenDestroyed); - } + if(enableDesktopManager_) { + connect(newScreen, &QScreen::virtualGeometryChanged, this, &Application::onVirtualGeometryChanged); + connect(newScreen, &QObject::destroyed, this, &Application::onScreenDestroyed); + } } void Application::onScreenDestroyed(QObject* screenObj) { - // NOTE by PCMan: This is a workaround for Qt 5 bug #40681. - // With this very dirty workaround, we can fix lxde/lxde-qt bug #204, #205, and #206. - // Qt 5 has two new regression bugs which breaks lxqt-panel in a multihead environment. - // #40681: Regression bug: QWidget::winId() returns old value and QEvent::WinIdChange event is not emitted sometimes. (multihead setup) - // #40791: Regression: QPlatformWindow, QWindow, and QWidget::winId() are out of sync. - // Explanations for the workaround: - // Internally, Qt mantains a list of QScreens and update it when XRandR configuration changes. - // When the user turn off an monitor with xrandr --output --off, this will destroy the QScreen - // object which represent the output. If the QScreen being destroyed contains our panel widget, - // Qt will call QWindow::setScreen(0) on the internal windowHandle() of our panel widget to move it - // to the primary screen. However, moving a window to a different screen is more than just changing - // its position. With XRandR, all screens are actually part of the same virtual desktop. However, - // this is not the case in other setups, such as Xinerama and moving a window to another screen is - // not possible unless you destroy the widget and create it again for a new screen. - // Therefore, Qt destroy the widget and re-create it when moving our panel to a new screen. - // Unfortunately, destroying the window also destroy the child windows embedded into it, - // using XEMBED such as the tray icons. (#206) - // Second, when the window is re-created, the winId of the QWidget is changed, but Qt failed to - // generate QEvent::WinIdChange event so we have no way to know that. We have to set - // some X11 window properties using the native winId() to make it a dock, but this stop working - // because we cannot get the correct winId(), so this causes #204 and #205. - // - // The workaround is very simple. Just completely destroy the window before Qt has a chance to do - // QWindow::setScreen() for it. Later, we recreate the window ourselves. So this can bypassing the Qt bugs. - if(enableDesktopManager_) { - bool reloadNeeded = false; - // FIXME: add workarounds for Qt5 bug #40681 and #40791 here. - Q_FOREACH(DesktopWindow* desktop, desktopWindows_) { - if(desktop->windowHandle()->screen() == screenObj) { - desktop->destroy(); // destroy the underlying native window - reloadNeeded = true; - } - } - if(reloadNeeded) - QTimer::singleShot(0, this, SLOT(reloadDesktopsAsNeeded())); - } + // NOTE by PCMan: This is a workaround for Qt 5 bug #40681. + // With this very dirty workaround, we can fix lxde/lxde-qt bug #204, #205, and #206. + // Qt 5 has two new regression bugs which breaks lxqt-panel in a multihead environment. + // #40681: Regression bug: QWidget::winId() returns old value and QEvent::WinIdChange event is not emitted sometimes. (multihead setup) + // #40791: Regression: QPlatformWindow, QWindow, and QWidget::winId() are out of sync. + // Explanations for the workaround: + // Internally, Qt mantains a list of QScreens and update it when XRandR configuration changes. + // When the user turn off an monitor with xrandr --output --off, this will destroy the QScreen + // object which represent the output. If the QScreen being destroyed contains our panel widget, + // Qt will call QWindow::setScreen(0) on the internal windowHandle() of our panel widget to move it + // to the primary screen. However, moving a window to a different screen is more than just changing + // its position. With XRandR, all screens are actually part of the same virtual desktop. However, + // this is not the case in other setups, such as Xinerama and moving a window to another screen is + // not possible unless you destroy the widget and create it again for a new screen. + // Therefore, Qt destroy the widget and re-create it when moving our panel to a new screen. + // Unfortunately, destroying the window also destroy the child windows embedded into it, + // using XEMBED such as the tray icons. (#206) + // Second, when the window is re-created, the winId of the QWidget is changed, but Qt failed to + // generate QEvent::WinIdChange event so we have no way to know that. We have to set + // some X11 window properties using the native winId() to make it a dock, but this stop working + // because we cannot get the correct winId(), so this causes #204 and #205. + // + // The workaround is very simple. Just completely destroy the window before Qt has a chance to do + // QWindow::setScreen() for it. Later, we recreate the window ourselves. So this can bypassing the Qt bugs. + if(enableDesktopManager_) { + bool reloadNeeded = false; + // FIXME: add workarounds for Qt5 bug #40681 and #40791 here. + Q_FOREACH(DesktopWindow* desktop, desktopWindows_) { + if(desktop->windowHandle()->screen() == screenObj) { + desktop->destroy(); // destroy the underlying native window + reloadNeeded = true; + } + } + if(reloadNeeded) { + QTimer::singleShot(0, this, SLOT(reloadDesktopsAsNeeded())); + } + } } void Application::reloadDesktopsAsNeeded() { - if(enableDesktopManager_) { - // workarounds for Qt5 bug #40681 and #40791 here. - Q_FOREACH(DesktopWindow* desktop, desktopWindows_) { - if(!desktop->windowHandle()) { - desktop->create(); // re-create the underlying native window - desktop->queueRelayout(); - desktop->show(); - } + if(enableDesktopManager_) { + // workarounds for Qt5 bug #40681 and #40791 here. + Q_FOREACH(DesktopWindow* desktop, desktopWindows_) { + if(!desktop->windowHandle()) { + desktop->create(); // re-create the underlying native window + desktop->queueRelayout(); + desktop->show(); + } + } } - } } // This slot is for Qt 5 onlt, but the stupid Qt moc cannot do conditional compilation // so we have to define it for Qt 4 as well. void Application::onVirtualGeometryChanged(const QRect& rect) { - // NOTE: the following is a workaround for Qt bug 32567. - // https://bugreports.qt-project.org/browse/QTBUG-32567 - // Though the status of the bug report is closed, it's not yet fixed for X11. - // In theory, QDesktopWidget should emit "workAreaResized()" signal when the work area - // of any screen is changed, but in fact it does not do it. - // However, QScreen provided since Qt5 does not have the bug and - // virtualGeometryChanged() is emitted correctly when the workAreas changed. - // So we use it in Qt5. - if(enableDesktopManager_) { - // qDebug() << "onVirtualGeometryChanged"; - Q_FOREACH(DesktopWindow* desktop, desktopWindows_) { - desktop->queueRelayout(); + // NOTE: the following is a workaround for Qt bug 32567. + // https://bugreports.qt-project.org/browse/QTBUG-32567 + // Though the status of the bug report is closed, it's not yet fixed for X11. + // In theory, QDesktopWidget should emit "workAreaResized()" signal when the work area + // of any screen is changed, but in fact it does not do it. + // However, QScreen provided since Qt5 does not have the bug and + // virtualGeometryChanged() is emitted correctly when the workAreas changed. + // So we use it in Qt5. + if(enableDesktopManager_) { + // qDebug() << "onVirtualGeometryChanged"; + Q_FOREACH(DesktopWindow* desktop, desktopWindows_) { + desktop->queueRelayout(); + } } - } } static int sigterm_fd[2]; static void sigtermHandler(int) { - char c = 1; - ::write(sigterm_fd[0], &c, sizeof(c)); + char c = 1; + ::write(sigterm_fd[0], &c, sizeof(c)); } void Application::installSigtermHandler() { - if(::socketpair(AF_UNIX, SOCK_STREAM, 0, sigterm_fd) == 0) { - QSocketNotifier* notifier = new QSocketNotifier(sigterm_fd[1], QSocketNotifier::Read, this); - connect(notifier, &QSocketNotifier::activated, this, &Application::onSigtermNotified); - - struct sigaction action; - action.sa_handler = sigtermHandler; - ::sigemptyset(&action.sa_mask); - action.sa_flags = SA_RESTART; - if(::sigaction(SIGTERM, &action, 0) != 0) { - qWarning("Couldn't install SIGTERM handler"); + if(::socketpair(AF_UNIX, SOCK_STREAM, 0, sigterm_fd) == 0) { + QSocketNotifier* notifier = new QSocketNotifier(sigterm_fd[1], QSocketNotifier::Read, this); + connect(notifier, &QSocketNotifier::activated, this, &Application::onSigtermNotified); + + struct sigaction action; + action.sa_handler = sigtermHandler; + ::sigemptyset(&action.sa_mask); + action.sa_flags = SA_RESTART; + if(::sigaction(SIGTERM, &action, 0) != 0) { + qWarning("Couldn't install SIGTERM handler"); + } + } + else { + qWarning("Couldn't create SIGTERM socketpair"); } - } else { - qWarning("Couldn't create SIGTERM socketpair"); - } } void Application::onSigtermNotified() { - if (QSocketNotifier* notifier = qobject_cast(sender())) { - notifier->setEnabled(false); - char c; - ::read(sigterm_fd[1], &c, sizeof(c)); - quit(); - notifier->setEnabled(true); - } + if(QSocketNotifier* notifier = qobject_cast(sender())) { + notifier->setEnabled(false); + char c; + ::read(sigterm_fd[1], &c, sizeof(c)); + quit(); + notifier->setEnabled(true); + } } } // namespace PCManFM diff --git a/pcmanfm/application.h b/pcmanfm/application.h index 2d371da..13ba59f 100644 --- a/pcmanfm/application.h +++ b/pcmanfm/application.h @@ -31,6 +31,9 @@ #include #include +#include +#include + class QScreen; class QFileSystemWatcher; @@ -43,110 +46,110 @@ class PreferencesDialog; class DesktopPreferencesDialog; class ProxyStyle: public QProxyStyle { - Q_OBJECT + Q_OBJECT public: - ProxyStyle() : QProxyStyle() {} - virtual ~ProxyStyle() {} - virtual int styleHint(StyleHint hint, const QStyleOption * option = 0, const QWidget * widget = 0, QStyleHintReturn * returnData = 0) const; + ProxyStyle() : QProxyStyle() {} + virtual ~ProxyStyle() {} + virtual int styleHint(StyleHint hint, const QStyleOption* option = 0, const QWidget* widget = 0, QStyleHintReturn* returnData = 0) const; }; class Application : public QApplication { - Q_OBJECT - Q_PROPERTY(bool desktopManagerEnabled READ desktopManagerEnabled) + Q_OBJECT + Q_PROPERTY(bool desktopManagerEnabled READ desktopManagerEnabled) public: - Application(int& argc, char** argv); - virtual ~Application(); + Application(int& argc, char** argv); + virtual ~Application(); - void init(); - int exec(); + void init(); + int exec(); - Settings& settings() { - return settings_; - } + Settings& settings() { + return settings_; + } - Fm::LibFmQt& libFm() { - return libFm_; - } + Fm::LibFmQt& libFm() { + return libFm_; + } - // public interface exported via dbus - void launchFiles(QString cwd, QStringList paths, bool inNewWindow); - void setWallpaper(QString path, QString modeString); - void preferences(QString page); - void desktopPrefrences(QString page); - void editBookmarks(); - void desktopManager(bool enabled); - void findFiles(QStringList paths = QStringList()); - void connectToServer(); + // public interface exported via dbus + void launchFiles(QString cwd, QStringList paths, bool inNewWindow); + void setWallpaper(QString path, QString modeString); + void preferences(QString page); + void desktopPrefrences(QString page); + void editBookmarks(); + void desktopManager(bool enabled); + void findFiles(QStringList paths = QStringList()); + void connectToServer(); - bool desktopManagerEnabled() { - return enableDesktopManager_; - } + bool desktopManagerEnabled() { + return enableDesktopManager_; + } - void updateFromSettings(); - void updateDesktopsFromSettings(); + void updateFromSettings(); + void updateDesktopsFromSettings(bool changeSlide = true); - void openFolderInTerminal(Fm::Path path); - void openFolders(Fm::FileInfoList files); + void openFolderInTerminal(Fm::FilePath path); + void openFolders(Fm::FileInfoList files); - QString profileName() { - return profileName_; - } + QString profileName() { + return profileName_; + } protected Q_SLOTS: - void onAboutToQuit(); - void onSigtermNotified(); + void onAboutToQuit(); + void onSigtermNotified(); - void onLastWindowClosed(); - void onSaveStateRequest(QSessionManager & manager); - void onScreenResized(int num); - void onScreenCountChanged(int newCount); - void initVolumeManager(); + void onLastWindowClosed(); + void onSaveStateRequest(QSessionManager& manager); + void onScreenResized(int num); + void onScreenCountChanged(int newCount); + void initVolumeManager(); - void onVirtualGeometryChanged(const QRect& rect); - void onScreenDestroyed(QObject* screenObj); - void onScreenAdded(QScreen* newScreen); - void reloadDesktopsAsNeeded(); + void onVirtualGeometryChanged(const QRect& rect); + void onScreenDestroyed(QObject* screenObj); + void onScreenAdded(QScreen* newScreen); + void reloadDesktopsAsNeeded(); - void onFindFileAccepted(); - void onConnectToServerAccepted(); + void onFindFileAccepted(); + void onConnectToServerAccepted(); protected: - virtual bool eventFilter(QObject* watched, QEvent* event); - bool parseCommandLineArgs(); - DesktopWindow* createDesktopWindow(int screenNum); - bool autoMountVolume(GVolume* volume, bool interactive = true); + virtual bool eventFilter(QObject* watched, QEvent* event); + bool parseCommandLineArgs(); + DesktopWindow* createDesktopWindow(int screenNum); + bool autoMountVolume(GVolume* volume, bool interactive = true); - static void onVolumeAdded(GVolumeMonitor* monitor, GVolume* volume, Application* pThis); + static void onVolumeAdded(GVolumeMonitor* monitor, GVolume* volume, Application* pThis); private Q_SLOTS: - void onUserDirsChanged(); + void onUserDirsChanged(); private: - void initWatch(); - void installSigtermHandler(); - - bool isPrimaryInstance; - Fm::LibFmQt libFm_; - Settings settings_; - QString profileName_; - bool daemonMode_; - bool enableDesktopManager_; - QVector desktopWindows_; - QPointer preferencesDialog_; - QPointer desktopPreferencesDialog_; - QPointer editBookmarksialog_; - QTranslator translator; - QTranslator qtTranslator; - GVolumeMonitor* volumeMonitor_; - - QFileSystemWatcher *userDirsWatcher_; - QString userDirsFile_; - QString userDesktopFolder_; - bool lxqtRunning_; - - int argc_; - char** argv_; + void initWatch(); + void installSigtermHandler(); + + bool isPrimaryInstance; + Fm::LibFmQt libFm_; + Settings settings_; + QString profileName_; + bool daemonMode_; + bool enableDesktopManager_; + QVector desktopWindows_; + QPointer preferencesDialog_; + QPointer desktopPreferencesDialog_; + QPointer editBookmarksialog_; + QTranslator translator; + QTranslator qtTranslator; + GVolumeMonitor* volumeMonitor_; + + QFileSystemWatcher* userDirsWatcher_; + QString userDirsFile_; + QString userDesktopFolder_; + bool lxqtRunning_; + + int argc_; + char** argv_; }; } diff --git a/pcmanfm/autorundialog.cpp b/pcmanfm/autorundialog.cpp index 4036d1b..3ecdb6f 100644 --- a/pcmanfm/autorundialog.cpp +++ b/pcmanfm/autorundialog.cpp @@ -23,116 +23,121 @@ #include #include "application.h" #include "mainwindow.h" +#include +#include namespace PCManFM { AutoRunDialog::AutoRunDialog(GVolume* volume, GMount* mount, QWidget* parent, Qt::WindowFlags f): - QDialog(parent, f), - cancellable(g_cancellable_new()), - applications(NULL), - mount_(G_MOUNT(g_object_ref(mount))) { + QDialog(parent, f), + cancellable(g_cancellable_new()), + applications(nullptr), + mount_(G_MOUNT(g_object_ref(mount))) { - setAttribute(Qt::WA_DeleteOnClose); - ui.setupUi(this); + setAttribute(Qt::WA_DeleteOnClose); + ui.setupUi(this); - GIcon* gicon = g_volume_get_icon(volume); - QIcon icon = Fm::IconTheme::icon(gicon); - ui.icon->setPixmap(icon.pixmap(QSize(48, 48))); + GIcon* gicon = g_volume_get_icon(volume); + QIcon icon = Fm::IconInfo::fromGIcon(gicon)->qicon(); + ui.icon->setPixmap(icon.pixmap(QSize(48, 48))); - // add actions - QListWidgetItem* item = new QListWidgetItem(QIcon::fromTheme("system-file-manager"), tr("Open in file manager")); - ui.listWidget->addItem(item); + // add actions + QListWidgetItem* item = new QListWidgetItem(QIcon::fromTheme("system-file-manager"), tr("Open in file manager")); + ui.listWidget->addItem(item); - g_mount_guess_content_type(mount, TRUE, cancellable, (GAsyncReadyCallback)onContentTypeFinished, this); + g_mount_guess_content_type(mount, TRUE, cancellable, (GAsyncReadyCallback)onContentTypeFinished, this); } AutoRunDialog::~AutoRunDialog() { - g_list_foreach(applications, (GFunc)g_object_unref, NULL); - g_list_free(applications); + g_list_foreach(applications, (GFunc)g_object_unref, nullptr); + g_list_free(applications); - if(mount_) - g_object_unref(mount_); + if(mount_) { + g_object_unref(mount_); + } - if(cancellable) { - g_cancellable_cancel(cancellable); - g_object_unref(cancellable); - } + if(cancellable) { + g_cancellable_cancel(cancellable); + g_object_unref(cancellable); + } } void AutoRunDialog::accept() { - QListWidgetItem* item = ui.listWidget->selectedItems().first(); - if(item) { - GFile* gf = g_mount_get_root(mount_); - void* p = item->data(Qt::UserRole).value(); - if(p) { // run the selected application - GAppInfo* app = G_APP_INFO(p); - GList* filelist = g_list_prepend(NULL, gf); - g_app_info_launch(app, filelist, NULL, NULL); - g_list_free(filelist); - } - else { - // the default action, open the mounted folder in the file manager - Application* app = static_cast(qApp); - Settings& settings = app->settings(); - Fm::Path path = Fm::Path::newForGfile(gf); - // open the path in a new window - // FIXME: or should we open it in a new tab? Make this optional later - MainWindow* win = new MainWindow(path); - win->resize(settings.windowWidth(), settings.windowHeight()); - if(settings.windowMaximized()) { - win->setWindowState(win->windowState() | Qt::WindowMaximized); - } - win->show(); + QListWidgetItem* item = ui.listWidget->selectedItems().first(); + if(item) { + GFile* gf = g_mount_get_root(mount_); + void* p = item->data(Qt::UserRole).value(); + if(p) { // run the selected application + GAppInfo* app = G_APP_INFO(p); + GList* filelist = g_list_prepend(nullptr, gf); + g_app_info_launch(app, filelist, nullptr, nullptr); + g_list_free(filelist); + } + else { + // the default action, open the mounted folder in the file manager + Application* app = static_cast(qApp); + Settings& settings = app->settings(); + Fm::FilePath path{gf, true}; + // open the path in a new window + // FIXME: or should we open it in a new tab? Make this optional later + MainWindow* win = new MainWindow(path); + win->resize(settings.windowWidth(), settings.windowHeight()); + if(settings.windowMaximized()) { + win->setWindowState(win->windowState() | Qt::WindowMaximized); + } + win->show(); + } + g_object_unref(gf); } - g_object_unref(gf); - } - QDialog::accept(); + QDialog::accept(); } // static void AutoRunDialog::onContentTypeFinished(GMount* mount, GAsyncResult* res, AutoRunDialog* pThis) { - if(pThis->cancellable) { - g_object_unref(pThis->cancellable); - pThis->cancellable = NULL; - } - - char** types = g_mount_guess_content_type_finish(mount, res, NULL); - char* desc = NULL; - - if(types) { - if(types[0]) { - for(char** type = types; *type; ++type) { - GList* l = g_app_info_get_all_for_type(*type); - if(l) - pThis->applications = g_list_concat(pThis->applications, l); - } - desc = g_content_type_get_description(types[0]); + if(pThis->cancellable) { + g_object_unref(pThis->cancellable); + pThis->cancellable = nullptr; } - g_strfreev(types); - - if(pThis->applications) { - int pos = 0; - for(GList* l = pThis->applications; l; l = l->next, ++pos) { - GAppInfo* app = G_APP_INFO(l->data); - GIcon* gicon = g_app_info_get_icon(app); - QIcon icon = Fm::IconTheme::icon(gicon); - QString text = QString::fromUtf8(g_app_info_get_name(app)); - QListWidgetItem* item = new QListWidgetItem(icon, text); - item->setData(Qt::UserRole, qVariantFromValue(app)); - pThis->ui.listWidget->insertItem(pos, item); - } + + char** types = g_mount_guess_content_type_finish(mount, res, nullptr); + char* desc = nullptr; + + if(types) { + if(types[0]) { + for(char** type = types; *type; ++type) { + GList* l = g_app_info_get_all_for_type(*type); + if(l) { + pThis->applications = g_list_concat(pThis->applications, l); + } + } + desc = g_content_type_get_description(types[0]); + } + g_strfreev(types); + + if(pThis->applications) { + int pos = 0; + for(GList* l = pThis->applications; l; l = l->next, ++pos) { + GAppInfo* app = G_APP_INFO(l->data); + GIcon* gicon = g_app_info_get_icon(app); + QIcon icon = Fm::IconInfo::fromGIcon(gicon)->qicon(); + QString text = QString::fromUtf8(g_app_info_get_name(app)); + QListWidgetItem* item = new QListWidgetItem(icon, text); + item->setData(Qt::UserRole, qVariantFromValue(app)); + pThis->ui.listWidget->insertItem(pos, item); + } + } } - } - if(desc) { - pThis->ui.mediumType->setText(QString::fromUtf8(desc)); - g_free(desc); - } - else - pThis->ui.mediumType->setText(tr("Removable Disk")); + if(desc) { + pThis->ui.mediumType->setText(QString::fromUtf8(desc)); + g_free(desc); + } + else { + pThis->ui.mediumType->setText(tr("Removable Disk")); + } - // select the first item - pThis->ui.listWidget->item(0)->setSelected(true); + // select the first item + pThis->ui.listWidget->item(0)->setSelected(true); } } // namespace PCManFM diff --git a/pcmanfm/desktop-preferences.ui b/pcmanfm/desktop-preferences.ui index 94b90f6..65f59e8 100644 --- a/pcmanfm/desktop-preferences.ui +++ b/pcmanfm/desktop-preferences.ui @@ -310,6 +310,144 @@ A space is also reserved for 3 lines of text. + + + Slide Show + + + + + + Enable Slide Show + + + true + + + false + + + + + + Wallpaper image folder: + + + + + + + Browse + + + + + + + hour(s) + + + 24 + + + + + + + and + + + Qt::AlignCenter + + + 5 + + + + + + + Intervals less than 5min will be ignored + + + Interval: + + + + + + + minute(s) + + + 55 + + + 5 + + + + + + + Qt::Horizontal + + + + 10 + 5 + + + + + + + + Wallpaper folder + + + + + + + Qt::Horizontal + + + QSizePolicy::Minimum + + + + 5 + 5 + + + + + + + + Randomize the slide show + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + Advanced diff --git a/pcmanfm/desktopitemdelegate.cpp b/pcmanfm/desktopitemdelegate.cpp deleted file mode 100644 index 9ecb43e..0000000 --- a/pcmanfm/desktopitemdelegate.cpp +++ /dev/null @@ -1,207 +0,0 @@ -/* - - Copyright (C) 2013 Hong Jen Yee (PCMan) - - 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 "desktopitemdelegate.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace PCManFM { - -DesktopItemDelegate::DesktopItemDelegate(QListView* view, QObject* parent): - QStyledItemDelegate(parent ? parent : view), - view_(view), - symlinkIcon_(QIcon::fromTheme("emblem-symbolic-link")), - shadowColor_(0, 0, 0), - margins_(QSize(3, 3)) { -} - -// FIXME: we need to figure out a way to derive from Fm::FolderItemDelegate to avoid code duplication. -void DesktopItemDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const { - Q_ASSERT(index.isValid()); - QStyleOptionViewItem opt = option; - initStyleOption(&opt, index); - - painter->save(); - painter->setClipRect(option.rect); - - opt.decorationAlignment = Qt::AlignHCenter | Qt::AlignTop; - opt.displayAlignment = Qt::AlignTop | Qt::AlignHCenter; - - // draw the icon - QIcon::Mode iconMode; - if(opt.state & QStyle::State_Enabled) { - if(opt.state & QStyle::State_Selected) - iconMode = QIcon::Selected; - else { - iconMode = QIcon::Normal; - } - } - else - iconMode = QIcon::Disabled; - QPoint iconPos(opt.rect.x() + (opt.rect.width() - opt.decorationSize.width()) / 2, opt.rect.y()); - QPixmap pixmap = opt.icon.pixmap(opt.decorationSize, iconMode); - painter->drawPixmap(iconPos, pixmap); - - // draw some emblems for the item if needed - // we only support symlink emblem at the moment - Fm::FileInfo file = static_cast(index.data(Fm::FolderModel::FileInfoRole).value()); - if(!file.isNull()) { - if(file.isSymlink()) { - painter->drawPixmap(iconPos, symlinkIcon_.pixmap(opt.decorationSize / 2, iconMode)); - } - } - - // draw text - QSize gridSize = view_->gridSize() - 2 * margins_; - QRectF textRect(opt.rect.x() - (gridSize.width() - opt.rect.width()) / 2, - opt.rect.y() + opt.decorationSize.height(), - gridSize.width(), - gridSize.height() - opt.decorationSize.height()); - drawText(painter, opt, textRect); - - if(opt.state & QStyle::State_HasFocus) { - // FIXME: draw focus rect - } - painter->restore(); -} - -void DesktopItemDelegate::drawText(QPainter* painter, QStyleOptionViewItem& opt, QRectF& textRect) const { - QTextLayout layout(opt.text, opt.font); - - QTextOption textOption; - textOption.setAlignment(opt.displayAlignment); - textOption.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere); - textOption.setTextDirection(opt.direction); - layout.setTextOption(textOption); - qreal height = 0; - qreal width = 0; - int visibleLines = 0; - layout.beginLayout(); - QString elidedText; - textRect.adjust(2, 2, -2, -2); // a 2-px margin is considered at FolderView::updateGridSize() - for(;;) { - QTextLine line = layout.createLine(); - if(!line.isValid()) - break; - line.setLineWidth(textRect.width()); - height += opt.fontMetrics.leading(); - line.setPosition(QPointF(0, height)); - if((height + line.height() + textRect.y()) > textRect.bottom()) { - // if part of this line falls outside the textRect, ignore it and quit. - QTextLine lastLine = layout.lineAt(visibleLines - 1); - elidedText = opt.text.mid(lastLine.textStart()); - elidedText = opt.fontMetrics.elidedText(elidedText, opt.textElideMode, textRect.width()); - break; - } - height += line.height(); - width = qMax(width, line.naturalTextWidth()); - ++ visibleLines; - } - layout.endLayout(); - width = qMax(width, (qreal)opt.fontMetrics.width(elidedText)); - QRectF boundRect = layout.boundingRect(); - boundRect.setWidth(width); - boundRect.setHeight(height); - boundRect.moveTo(textRect.x() + (textRect.width() - width)/2, textRect.y()); - - QRectF selRect = boundRect.adjusted(-2, -2, 2, 2); - - if(!painter) { // no painter, calculate the bounding rect only - textRect = selRect; - return; - } - - if (opt.state & QStyle::State_Selected || opt.state & QStyle::State_MouseOver) { - if (const QWidget* widget = opt.widget) { // let the style engine do it - QStyle* style = widget->style() ? widget->style() : qApp->style(); - QStyleOptionViewItem o(opt); - o.text = QString(); - o.rect = selRect.toAlignedRect().intersected(opt.rect); // due to clipping and rounding, we might lose 1px - o.showDecorationSelected = true; - style->drawPrimitive(QStyle::PE_PanelItemViewItem, &o, painter, widget); - } - } - - if((opt.state & QStyle::State_Selected)) { - // qDebug("w: %f, h:%f, m:%f", boundRect.width(), boundRect.height(), layout.minimumWidth()); - if(!opt.widget) - painter->fillRect(selRect, opt.palette.highlight()); - painter->setPen(opt.palette.color(QPalette::Normal, QPalette::HighlightedText)); - } - else { // only draw shadow for non-selected items - // draw shadow, FIXME: is it possible to use QGraphicsDropShadowEffect here? - QPen prevPen = painter->pen(); - painter->setPen(QPen(shadowColor_)); - for(int i = 0; i < visibleLines; ++i) { - QTextLine line = layout.lineAt(i); - if(i == (visibleLines - 1) && !elidedText.isEmpty()) { // the last line, draw elided text - QPointF pos(boundRect.x() + line.position().x() + 1, boundRect.y() + line.y() + line.ascent() + 1); - painter->drawText(pos, elidedText); - } - else { - line.draw(painter, textRect.topLeft() + QPointF(1, 1)); - } - } - painter->setPen(prevPen); - } - - // draw text - for(int i = 0; i < visibleLines; ++i) { - QTextLine line = layout.lineAt(i); - if(i == (visibleLines - 1) && !elidedText.isEmpty()) { // the last line, draw elided text - QPointF pos(boundRect.x() + line.position().x(), boundRect.y() + line.y() + line.ascent()); - painter->drawText(pos, elidedText); - } - else { - line.draw(painter, textRect.topLeft()); - } - } -} - -QSize DesktopItemDelegate::sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const { - QVariant value = index.data(Qt::SizeHintRole); - if(value.isValid()) - return qvariant_cast(value); - QStyleOptionViewItem opt = option; - initStyleOption(&opt, index); - opt.decorationAlignment = Qt::AlignHCenter|Qt::AlignTop; - opt.displayAlignment = Qt::AlignTop|Qt::AlignHCenter; - - QSize gridSize = view_->gridSize() - 2 * margins_; - Q_ASSERT(gridSize != QSize()); - QRectF textRect(0, 0, gridSize.width(), gridSize.height() - opt.decorationSize.height()); - drawText(NULL, opt, textRect); // passing NULL for painter will calculate the bounding rect only. - int width = qMax((int)textRect.width(), opt.decorationSize.width()); - int height = opt.decorationSize.height() + textRect.height(); - return QSize(width, height); -} - -DesktopItemDelegate::~DesktopItemDelegate() { - -} - -} // namespace PCManFM diff --git a/pcmanfm/desktopitemdelegate.h b/pcmanfm/desktopitemdelegate.h deleted file mode 100644 index fc8bd89..0000000 --- a/pcmanfm/desktopitemdelegate.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - - Copyright (C) 2013 Hong Jen Yee (PCMan) - - 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 PCMANFM_DESKTOPITEMDELEGATE_H -#define PCMANFM_DESKTOPITEMDELEGATE_H - -#include -#include - -class QListView; -class QTextOption; -class QTextLayout; - -namespace PCManFM { - -class DesktopItemDelegate : public QStyledItemDelegate -{ -Q_OBJECT -public: - explicit DesktopItemDelegate(QListView* view, QObject* parent = 0); - virtual void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const; - virtual QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const; - virtual ~DesktopItemDelegate(); - - void setShadowColor(const QColor& shadowColor) { - shadowColor_ = shadowColor; - } - const QColor& shadowColor() const { - return shadowColor_; - } - void setMargins(QSize margins) { - margins_ = margins.expandedTo(QSize(0, 0)); - } - -private: - void drawText(QPainter* painter, QStyleOptionViewItem& opt, QRectF& textRect) const; - -private: - QListView* view_; - QIcon symlinkIcon_; - QColor shadowColor_; - QSize margins_; -}; - -} - -#endif // PCMANFM_DESKTOPITEMDELEGATE_H diff --git a/pcmanfm/desktoppreferencesdialog.cpp b/pcmanfm/desktoppreferencesdialog.cpp index 8664508..4c22c65 100644 --- a/pcmanfm/desktoppreferencesdialog.cpp +++ b/pcmanfm/desktoppreferencesdialog.cpp @@ -84,6 +84,14 @@ DesktopPreferencesDialog::DesktopPreferencesDialog(QWidget* parent, Qt::WindowFl qDebug("wallpaper: %s", settings.wallpaper().toUtf8().data()); ui.imageFile->setText(settings.wallpaper()); + ui.slideShow->setChecked(settings.slideShowInterval() > 0); + ui.imageFolder->setText(settings.wallpaperDir()); + int minutes = qMax(settings.slideShowInterval() / 60000, 5); // 5 min at least + ui.hours->setValue(minutes / 60); + ui.minutes->setValue(minutes % 60); + ui.randomize->setChecked(settings.wallpaperRandomize()); + connect(ui.folderBrowse, &QPushButton::clicked, this, &DesktopPreferencesDialog::onFolderBrowseClicked); + for(std::size_t i = 0; i < G_N_ELEMENTS(iconSizes); ++i) { int size = iconSizes[i]; ui.iconSize->addItem(QString("%1 x %1").arg(size), size); @@ -145,12 +153,22 @@ void DesktopPreferencesDialog::applySettings() settings.setWallpaper(ui.imageFile->text()); int mode = ui.wallpaperMode->itemData(ui.wallpaperMode->currentIndex()).toInt(); settings.setWallpaperMode(mode); + + settings.setWallpaperDir(ui.imageFolder->text()); + int interval = 0; + if(ui.slideShow->isChecked()) + interval = (ui.minutes->value() + 60 * ui.hours->value()) * 60000; + settings.setSlideShowInterval(interval); + settings.setWallpaperRandomize(ui.randomize->isChecked()); + settings.setDesktopIconSize(ui.iconSize->itemData(ui.iconSize->currentIndex()).toInt()); + settings.setDesktopFont(ui.font->font()); settings.setDesktopBgColor(ui.backgroundColor->color()); settings.setDesktopFgColor(ui.textColor->color()); settings.setDesktopShadowColor(ui.shadowColor->color()); settings.setShowWmMenu(ui.showWmMenu->isChecked()); + settings.setDesktopCellMargins(QSize(ui.hMargin->value(), ui.vMargin->value())); settings.save(); @@ -164,7 +182,7 @@ void DesktopPreferencesDialog::onApplyClicked() void DesktopPreferencesDialog::accept() { applySettings(); - static_cast(qApp)->updateDesktopsFromSettings(); + static_cast(qApp)->updateDesktopsFromSettings(false); // don't change slide wallpaper on clicking OK QDialog::accept(); } @@ -201,6 +219,19 @@ void DesktopPreferencesDialog::onBrowseClicked() { } } +void DesktopPreferencesDialog::onFolderBrowseClicked() { + QFileDialog dlg; + dlg.setAcceptMode(QFileDialog::AcceptOpen); + dlg.setFileMode(QFileDialog::Directory); + dlg.setOption(QFileDialog::ShowDirsOnly); + dlg.setDirectory(QDir::home().path()); + if(dlg.exec() == QDialog::Accepted) { + QString foldername; + foldername = dlg.selectedFiles().first(); + ui.imageFolder->setText(foldername); + } +} + void DesktopPreferencesDialog::onBrowseDesktopFolderClicked() { QFileDialog dlg; diff --git a/pcmanfm/desktoppreferencesdialog.h b/pcmanfm/desktoppreferencesdialog.h index f3a0af4..31a4fb0 100644 --- a/pcmanfm/desktoppreferencesdialog.h +++ b/pcmanfm/desktoppreferencesdialog.h @@ -46,6 +46,7 @@ protected Q_SLOTS: void onApplyClicked(); void onWallpaperModeChanged(int index); void onBrowseClicked(); + void onFolderBrowseClicked(); void onBrowseDesktopFolderClicked(); void lockMargins(bool lock); diff --git a/pcmanfm/desktopwindow.cpp b/pcmanfm/desktopwindow.cpp index 46bc95f..bf5e6f0 100644 --- a/pcmanfm/desktopwindow.cpp +++ b/pcmanfm/desktopwindow.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -37,19 +38,19 @@ #include #include #include +#include #include "./application.h" #include "mainwindow.h" -#include "desktopitemdelegate.h" #include #include +#include #include #include #include #include #include -#include -#include +#include #include "xdgdir.h" #include @@ -57,891 +58,1146 @@ #include #include +#define MIN_SLIDE_INTERVAL 5*60000 // 5 min +#define MAX_SLIDE_INTERVAL (24*60+55)*60000 // 24 h and 55 min + namespace PCManFM { DesktopWindow::DesktopWindow(int screenNum): - View(Fm::FolderView::IconMode), - proxyModel_(NULL), - model_(NULL), - wallpaperMode_(WallpaperNone), - fileLauncher_(NULL), - showWmMenu_(false), - screenNum_(screenNum), - relayoutTimer_(NULL) { - - QDesktopWidget* desktopWidget = QApplication::desktop(); - setWindowFlags(Qt::Window | Qt::FramelessWindowHint); - setAttribute(Qt::WA_X11NetWmWindowTypeDesktop); - setAttribute(Qt::WA_DeleteOnClose); - - // set our custom file launcher - View::setFileLauncher(&fileLauncher_); - - listView_ = static_cast(childView()); - listView_->setMovement(QListView::Snap); - listView_->setResizeMode(QListView::Adjust); - listView_->setFlow(QListView::TopToBottom); - - // This is to workaround Qt bug 54384 which affects Qt >= 5.6 - // https://bugreports.qt.io/browse/QTBUG-54384 - // Setting a QPixmap larger then the screen resolution to the background of a list view won't work. - // So we did a hack here: Disable the automatic background painting. - // Then paint the background of the list view ourselves by hook into its paint event handling method with a event filter. - listView_->viewport()->setAutoFillBackground(false); - - // NOTE: When XRnadR is in use, the all screens are actually combined to form a - // large virtual desktop and only one DesktopWindow needs to be created and screenNum is -1. - // In some older multihead setups, such as xinerama, every physical screen - // is treated as a separate desktop so many instances of DesktopWindow may be created. - // In this case we only want to show desktop icons on the primary screen. - if(desktopWidget->isVirtualDesktop() || screenNum_ == desktopWidget->primaryScreen()) { - loadItemPositions(); - Settings& settings = static_cast(qApp)->settings(); - - model_ = Fm::CachedFolderModel::modelFromPath(Fm::Path::getDesktop()); - folder_ = model_->folder(); - - proxyModel_ = new Fm::ProxyFolderModel(); - proxyModel_->setSourceModel(model_); - proxyModel_->setShowThumbnails(settings.showThumbnails()); - proxyModel_->sort(settings.desktopSortColumn(), settings.desktopSortOrder()); - proxyModel_->setFolderFirst(settings.desktopSortFolderFirst()); - setModel(proxyModel_); - - connect(proxyModel_, &Fm::ProxyFolderModel::rowsInserted, this, &DesktopWindow::onRowsInserted); - connect(proxyModel_, &Fm::ProxyFolderModel::rowsAboutToBeRemoved, this, &DesktopWindow::onRowsAboutToBeRemoved); - connect(proxyModel_, &Fm::ProxyFolderModel::layoutChanged, this, &DesktopWindow::onLayoutChanged); - connect(proxyModel_, &Fm::ProxyFolderModel::sortFilterChanged, this, &DesktopWindow::onModelSortFilterChanged); - connect(proxyModel_, &Fm::ProxyFolderModel::dataChanged, this, &DesktopWindow::onDataChanged); - connect(listView_, &QListView::indexesMoved, this, &DesktopWindow::onIndexesMoved); - } - - // set our own delegate - delegate_ = new DesktopItemDelegate(listView_); - listView_->setItemDelegateForColumn(Fm::FolderModel::ColumnFileName, delegate_); + View(Fm::FolderView::IconMode), + proxyModel_(nullptr), + model_(nullptr), + wallpaperMode_(WallpaperNone), + slideShowInterval_(0), + wallpaperTimer_(nullptr), + wallpaperRandomize_(false), + fileLauncher_(nullptr), + showWmMenu_(false), + screenNum_(screenNum), + relayoutTimer_(nullptr) { + + QDesktopWidget* desktopWidget = QApplication::desktop(); + setWindowFlags(Qt::Window | Qt::FramelessWindowHint); + setAttribute(Qt::WA_X11NetWmWindowTypeDesktop); + setAttribute(Qt::WA_DeleteOnClose); + + // set our custom file launcher + View::setFileLauncher(&fileLauncher_); + + listView_ = static_cast(childView()); + listView_->setMovement(QListView::Snap); + listView_->setResizeMode(QListView::Adjust); + listView_->setFlow(QListView::TopToBottom); + + // This is to workaround Qt bug 54384 which affects Qt >= 5.6 + // https://bugreports.qt.io/browse/QTBUG-54384 + // Setting a QPixmap larger then the screen resolution to desktop's QPalette won't work. + // So we make the viewport transparent by preventing its backround from being filled automatically. + // Then we paint desktop's background ourselves by using its paint event handling method. + listView_->viewport()->setAutoFillBackground(false); + + // NOTE: When XRnadR is in use, the all screens are actually combined to form a + // large virtual desktop and only one DesktopWindow needs to be created and screenNum is -1. + // In some older multihead setups, such as xinerama, every physical screen + // is treated as a separate desktop so many instances of DesktopWindow may be created. + // In this case we only want to show desktop icons on the primary screen. + if(desktopWidget->isVirtualDesktop() || screenNum_ == desktopWidget->primaryScreen()) { + loadItemPositions(); + Settings& settings = static_cast(qApp)->settings(); + + auto desktopPath = Fm::FilePath::fromLocalPath(XdgDir::readDesktopDir().toStdString().c_str()); + model_ = Fm::CachedFolderModel::modelFromPath(desktopPath); + folder_ = model_->folder(); + + proxyModel_ = new Fm::ProxyFolderModel(); + proxyModel_->setSourceModel(model_); + proxyModel_->setShowThumbnails(settings.showThumbnails()); + proxyModel_->sort(settings.desktopSortColumn(), settings.desktopSortOrder()); + proxyModel_->setFolderFirst(settings.desktopSortFolderFirst()); + setModel(proxyModel_); + + connect(proxyModel_, &Fm::ProxyFolderModel::rowsInserted, this, &DesktopWindow::onRowsInserted); + connect(proxyModel_, &Fm::ProxyFolderModel::rowsAboutToBeRemoved, this, &DesktopWindow::onRowsAboutToBeRemoved); + connect(proxyModel_, &Fm::ProxyFolderModel::layoutChanged, this, &DesktopWindow::onLayoutChanged); + connect(proxyModel_, &Fm::ProxyFolderModel::sortFilterChanged, this, &DesktopWindow::onModelSortFilterChanged); + connect(proxyModel_, &Fm::ProxyFolderModel::dataChanged, this, &DesktopWindow::onDataChanged); + connect(listView_, &QListView::indexesMoved, this, &DesktopWindow::onIndexesMoved); + } - // remove frame - listView_->setFrameShape(QFrame::NoFrame); - // inhibit scrollbars FIXME: this should be optional in the future - listView_->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - listView_->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + // remove frame + listView_->setFrameShape(QFrame::NoFrame); + // inhibit scrollbars FIXME: this should be optional in the future + listView_->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + listView_->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - connect(this, &DesktopWindow::openDirRequested, this, &DesktopWindow::onOpenDirRequested); + connect(this, &DesktopWindow::openDirRequested, this, &DesktopWindow::onOpenDirRequested); - listView_->installEventFilter(this); - listView_->viewport()->installEventFilter(this); + listView_->installEventFilter(this); + listView_->viewport()->installEventFilter(this); - // setup shortcuts - QShortcut* shortcut; - shortcut = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_X), this); // cut - connect(shortcut, &QShortcut::activated, this, &DesktopWindow::onCutActivated); + // setup shortcuts + QShortcut* shortcut; + shortcut = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_X), this); // cut + connect(shortcut, &QShortcut::activated, this, &DesktopWindow::onCutActivated); - shortcut = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_C), this); // copy - connect(shortcut, &QShortcut::activated, this, &DesktopWindow::onCopyActivated); + shortcut = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_C), this); // copy + connect(shortcut, &QShortcut::activated, this, &DesktopWindow::onCopyActivated); - shortcut = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_V), this); // paste - connect(shortcut, &QShortcut::activated, this, &DesktopWindow::onPasteActivated); + shortcut = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_V), this); // paste + connect(shortcut, &QShortcut::activated, this, &DesktopWindow::onPasteActivated); - shortcut = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_A), this); // select all - connect(shortcut, &QShortcut::activated, listView_, &QListView::selectAll); + shortcut = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_A), this); // select all + connect(shortcut, &QShortcut::activated, this, &FolderView::selectAll); - shortcut = new QShortcut(QKeySequence(Qt::Key_Delete), this); // delete - connect(shortcut, &QShortcut::activated, this, &DesktopWindow::onDeleteActivated); + shortcut = new QShortcut(QKeySequence(Qt::Key_Delete), this); // delete + connect(shortcut, &QShortcut::activated, this, &DesktopWindow::onDeleteActivated); - shortcut = new QShortcut(QKeySequence(Qt::Key_F2), this); // rename - connect(shortcut, &QShortcut::activated, this, &DesktopWindow::onRenameActivated); + shortcut = new QShortcut(QKeySequence(Qt::Key_F2), this); // rename + connect(shortcut, &QShortcut::activated, this, &DesktopWindow::onRenameActivated); - shortcut = new QShortcut(QKeySequence(Qt::ALT + Qt::Key_Return), this); // rename - connect(shortcut, &QShortcut::activated, this, &DesktopWindow::onFilePropertiesActivated); + shortcut = new QShortcut(QKeySequence(Qt::ALT + Qt::Key_Return), this); // rename + connect(shortcut, &QShortcut::activated, this, &DesktopWindow::onFilePropertiesActivated); - shortcut = new QShortcut(QKeySequence(Qt::SHIFT + Qt::Key_Delete), this); // force delete - connect(shortcut, &QShortcut::activated, this, &DesktopWindow::onDeleteActivated); + shortcut = new QShortcut(QKeySequence(Qt::SHIFT + Qt::Key_Delete), this); // force delete + connect(shortcut, &QShortcut::activated, this, &DesktopWindow::onDeleteActivated); } DesktopWindow::~DesktopWindow() { - listView_->viewport()->removeEventFilter(this); - listView_->removeEventFilter(this); + listView_->viewport()->removeEventFilter(this); + listView_->removeEventFilter(this); + + if(relayoutTimer_) { + relayoutTimer_->stop(); + delete relayoutTimer_; + } - if(relayoutTimer_) - delete relayoutTimer_; + if(wallpaperTimer_) { + wallpaperTimer_->stop(); + delete wallpaperTimer_; + } - if(proxyModel_) - delete proxyModel_; + if(proxyModel_) { + delete proxyModel_; + } - if(model_) - model_->unref(); + if(model_) { + model_->unref(); + } } void DesktopWindow::setBackground(const QColor& color) { - bgColor_ = color; + bgColor_ = color; } void DesktopWindow::setForeground(const QColor& color) { - QPalette p = listView_->palette(); - p.setBrush(QPalette::Text, color); - listView_->setPalette(p); - fgColor_ = color; + QPalette p = listView_->palette(); + p.setBrush(QPalette::Text, color); + listView_->setPalette(p); + fgColor_ = color; } void DesktopWindow::setShadow(const QColor& color) { - shadowColor_ = color; - delegate_->setShadowColor(color); + shadowColor_ = color; + auto delegate = static_cast(listView_->itemDelegateForColumn(Fm::FolderModel::ColumnFileName)); + delegate->setShadowColor(color); } -void DesktopWindow::onOpenDirRequested(FmPath* path, int target) { - // open in new window unconditionally. - Application* app = static_cast(qApp); - MainWindow* newWin = new MainWindow(path); - // apply window size from app->settings - newWin->resize(app->settings().windowWidth(), app->settings().windowHeight()); - newWin->show(); +void DesktopWindow::onOpenDirRequested(const Fm::FilePath& path, int target) { + Q_UNUSED(target); + // open in new window unconditionally. + Application* app = static_cast(qApp); + MainWindow* newWin = new MainWindow(path); + // apply window size from app->settings + newWin->resize(app->settings().windowWidth(), app->settings().windowHeight()); + newWin->show(); } void DesktopWindow::resizeEvent(QResizeEvent* event) { - QWidget::resizeEvent(event); + QWidget::resizeEvent(event); - // resize wall paper if needed - if(isVisible() && wallpaperMode_ != WallpaperNone && wallpaperMode_ != WallpaperTile) { - updateWallpaper(); - update(); - } - queueRelayout(100); // Qt use a 100 msec delay for relayout internally so we use it, too. + // resize wall paper if needed + if(isVisible() && wallpaperMode_ != WallpaperNone && wallpaperMode_ != WallpaperTile) { + updateWallpaper(); + update(); + } + queueRelayout(100); // Qt use a 100 msec delay for relayout internally so we use it, too. } void DesktopWindow::setDesktopFolder() { - Fm::Path path = Fm::Path::newForPath(XdgDir::readDesktopDir().toStdString().c_str()); - model_ = Fm::CachedFolderModel::modelFromPath(path); - proxyModel_->setSourceModel(model_); + auto path = Fm::FilePath::fromLocalPath(XdgDir::readDesktopDir().toStdString().c_str()); + model_ = Fm::CachedFolderModel::modelFromPath(path); + proxyModel_->setSourceModel(model_); } void DesktopWindow::setWallpaperFile(QString filename) { - wallpaperFile_ = filename; + wallpaperFile_ = filename; } void DesktopWindow::setWallpaperMode(WallpaperMode mode) { - wallpaperMode_ = mode; + wallpaperMode_ = mode; +} + +void DesktopWindow::setLastSlide(QString filename) { + lastSlide_ = filename; +} + +void DesktopWindow::setWallpaperDir(QString dirname) { + wallpaperDir_ = dirname; +} + +void DesktopWindow::setSlideShowInterval(int interval) { + slideShowInterval_ = interval; +} + +void DesktopWindow::setWallpaperRandomize(bool randomize) { + wallpaperRandomize_ = randomize; } QImage DesktopWindow::loadWallpaperFile(QSize requiredSize) { - // NOTE: for ease of programming, we only use the cache for the primary screen. - bool useCache = (screenNum_ == -1 || screenNum_ == 0); - QFile info; - QString cacheFileName; - if(useCache) { - // see if we have a scaled version cached on disk - cacheFileName = QString::fromLocal8Bit(qgetenv("XDG_CACHE_HOME")); - if(cacheFileName.isEmpty()) - cacheFileName = QDir::homePath() % QLatin1String("/.cache"); - Application* app = static_cast(qApp); - cacheFileName += QLatin1String("/pcmanfm-qt/") % app->profileName(); - QDir().mkpath(cacheFileName); // ensure that the cache dir exists - cacheFileName += QLatin1String("/wallpaper.cache"); - - // read info file - QString origin; - info.setFileName(cacheFileName % ".info"); - if(info.open(QIODevice::ReadOnly)) { - // FIXME: we need to compare mtime to see if the cache is out of date - origin = QString::fromLocal8Bit(info.readLine()); - info.close(); - if(!origin.isEmpty()) { - // try to see if we can get the size of the cached image. - QImageReader reader(cacheFileName); - reader.setAutoDetectImageFormat(true); - QSize cachedSize = reader.size(); - qDebug() << "size of cached file" << cachedSize << ", requiredSize:" << requiredSize; - if(cachedSize.isValid()) { - if(cachedSize == requiredSize) { // see if the cached wallpaper has the size we want - QImage image = reader.read(); // return the loaded image - qDebug() << "origin" << origin; - if(origin == wallpaperFile_) - return image; - } - } - } - } - qDebug() << "no cached wallpaper. generate a new one!"; - } - - // we don't have a cached scaled image, load the original file - QImage image(wallpaperFile_); - qDebug() << "size of original image" << image.size(); - if(image.isNull() || image.size() == requiredSize) // if the original size is what we want - return image; - - // scale the original image - QImage scaled = image.scaled(requiredSize.width(), requiredSize.height(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation); - // FIXME: should we save the scaled image if its size is larger than the original image? - - if(useCache) { - // write the path of the original image to the .info file - if(info.open(QIODevice::WriteOnly)) { - info.write(wallpaperFile_.toLocal8Bit()); - info.close(); - - // write the scaled cache image to disk - const char* format; // we keep jpg format for *.jpg files, and use png format for others. - if(wallpaperFile_.endsWith(QLatin1String(".jpg"), Qt::CaseInsensitive) || wallpaperFile_.endsWith(QLatin1String(".jpeg"), Qt::CaseInsensitive)) - format = "JPG"; - else - format = "PNG"; - scaled.save(cacheFileName, format); - } - qDebug() << "wallpaper cached saved to " << cacheFileName; - // FIXME: we might delay the write of the cached image? - } - return scaled; + // NOTE: for ease of programming, we only use the cache for the primary screen. + bool useCache = (screenNum_ == -1 || screenNum_ == 0); + QFile info; + QString cacheFileName; + if(useCache) { + // see if we have a scaled version cached on disk + cacheFileName = QString::fromLocal8Bit(qgetenv("XDG_CACHE_HOME")); + if(cacheFileName.isEmpty()) { + cacheFileName = QDir::homePath() % QLatin1String("/.cache"); + } + Application* app = static_cast(qApp); + cacheFileName += QLatin1String("/pcmanfm-qt/") % app->profileName(); + QDir().mkpath(cacheFileName); // ensure that the cache dir exists + cacheFileName += QLatin1String("/wallpaper.cache"); + + // read info file + QString origin; + info.setFileName(cacheFileName % ".info"); + if(info.open(QIODevice::ReadOnly)) { + // FIXME: we need to compare mtime to see if the cache is out of date + origin = QString::fromLocal8Bit(info.readLine()); + info.close(); + if(!origin.isEmpty()) { + // try to see if we can get the size of the cached image. + QImageReader reader(cacheFileName); + reader.setAutoDetectImageFormat(true); + QSize cachedSize = reader.size(); + qDebug() << "size of cached file" << cachedSize << ", requiredSize:" << requiredSize; + if(cachedSize.isValid()) { + if(cachedSize == requiredSize) { // see if the cached wallpaper has the size we want + QImage image = reader.read(); // return the loaded image + qDebug() << "origin" << origin; + if(origin == wallpaperFile_) { + return image; + } + } + } + } + } + qDebug() << "no cached wallpaper. generate a new one!"; + } + + // we don't have a cached scaled image, load the original file + QImage image(wallpaperFile_); + qDebug() << "size of original image" << image.size(); + if(image.isNull() || image.size() == requiredSize) { // if the original size is what we want + return image; + } + + // scale the original image + QImage scaled = image.scaled(requiredSize.width(), requiredSize.height(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation); + // FIXME: should we save the scaled image if its size is larger than the original image? + + if(useCache) { + // write the path of the original image to the .info file + if(info.open(QIODevice::WriteOnly)) { + info.write(wallpaperFile_.toLocal8Bit()); + info.close(); + + // write the scaled cache image to disk + const char* format; // we keep jpg format for *.jpg files, and use png format for others. + if(wallpaperFile_.endsWith(QLatin1String(".jpg"), Qt::CaseInsensitive) || wallpaperFile_.endsWith(QLatin1String(".jpeg"), Qt::CaseInsensitive)) { + format = "JPG"; + } + else { + format = "PNG"; + } + scaled.save(cacheFileName, format); + } + qDebug() << "wallpaper cached saved to " << cacheFileName; + // FIXME: we might delay the write of the cached image? + } + return scaled; } // really generate the background pixmap according to current settings and apply it. void DesktopWindow::updateWallpaper() { - if(wallpaperMode_ != WallpaperNone) { // use wallpaper - QPixmap pixmap; - QImage image; - if(wallpaperMode_ == WallpaperTile) { // use the original size - image = QImage(wallpaperFile_); - pixmap = QPixmap::fromImage(image); - } - else if(wallpaperMode_ == WallpaperStretch) { - image = loadWallpaperFile(size()); - pixmap = QPixmap::fromImage(image); - } - else { // WallpaperCenter || WallpaperFit - if(wallpaperMode_ == WallpaperCenter) { - image = QImage(wallpaperFile_); // load original image - } - else if(wallpaperMode_ == WallpaperFit || wallpaperMode_ == WallpaperZoom) { - // calculate the desired size - QSize origSize = QImageReader(wallpaperFile_).size(); // get the size of the original file - if(origSize.isValid()) { - QSize desiredSize = origSize; - Qt::AspectRatioMode mode = (wallpaperMode_ == WallpaperFit ? Qt::KeepAspectRatio : Qt::KeepAspectRatioByExpanding); - desiredSize.scale(width(), height(), mode); - image = loadWallpaperFile(desiredSize); // load the scaled image - } - } - if(!image.isNull()) { - pixmap = QPixmap(size()); - QPainter painter(&pixmap); - pixmap.fill(bgColor_); - int x = (width() - image.width()) / 2; - int y = (height() - image.height()) / 2; - painter.drawImage(x, y, image); - } - } - wallpaperPixmap_ = pixmap; - } -} - -void DesktopWindow::updateFromSettings(Settings& settings) { - setDesktopFolder(); - setWallpaperFile(settings.wallpaper()); - setWallpaperMode(settings.wallpaperMode()); - setFont(settings.desktopFont()); - setIconSize(Fm::FolderView::IconMode, QSize(settings.desktopIconSize(), settings.desktopIconSize())); - setMargins(settings.desktopCellMargins()); - // setIconSize and setMargins may trigger relayout of items by QListView, so we need to do the layout again. - queueRelayout(); - setForeground(settings.desktopFgColor()); - setBackground(settings.desktopBgColor()); - setShadow(settings.desktopShadowColor()); - showWmMenu_ = settings.showWmMenu(); - updateWallpaper(); - update(); -} - -void DesktopWindow::onFileClicked(int type, FmFileInfo* fileInfo) { - if(!fileInfo && showWmMenu_) - return; // do not show the popup if we want to use the desktop menu provided by the WM. - View::onFileClicked(type, fileInfo); + if(wallpaperMode_ != WallpaperNone) { // use wallpaper + QPixmap pixmap; + QImage image; + if(wallpaperMode_ == WallpaperTile) { // use the original size + image = QImage(wallpaperFile_); + // Note: We can't use the QPainter::drawTiledPixmap(), because it doesn't tile + // correctly for background pixmaps bigger than the current screen size. + const QSize s = size(); + pixmap = QPixmap{s}; + QPainter painter{&pixmap}; + for (int x = 0; x < s.width(); x += image.width()) { + for (int y = 0; y < s.height(); y += image.height()) { + painter.drawImage(x, y, image); + } + } + } + else if(wallpaperMode_ == WallpaperStretch) { + image = loadWallpaperFile(size()); + pixmap = QPixmap::fromImage(image); + } + else { // WallpaperCenter || WallpaperFit + if(wallpaperMode_ == WallpaperCenter) { + image = QImage(wallpaperFile_); // load original image + } + else if(wallpaperMode_ == WallpaperFit || wallpaperMode_ == WallpaperZoom) { + // calculate the desired size + QSize origSize = QImageReader(wallpaperFile_).size(); // get the size of the original file + if(origSize.isValid()) { + QSize desiredSize = origSize; + Qt::AspectRatioMode mode = (wallpaperMode_ == WallpaperFit ? Qt::KeepAspectRatio : Qt::KeepAspectRatioByExpanding); + desiredSize.scale(width(), height(), mode); + image = loadWallpaperFile(desiredSize); // load the scaled image + } + } + if(!image.isNull()) { + pixmap = QPixmap(size()); + QPainter painter(&pixmap); + pixmap.fill(bgColor_); + int x = (width() - image.width()) / 2; + int y = (height() - image.height()) / 2; + painter.drawImage(x, y, image); + } + } + wallpaperPixmap_ = pixmap; + } } -void DesktopWindow::prepareFileMenu(Fm::FileMenu* menu) { - // qDebug("DesktopWindow::prepareFileMenu"); - PCManFM::View::prepareFileMenu(menu); - QAction* action = new QAction(tr("Stic&k to Current Position"), menu); - action->setCheckable(true); - menu->insertSeparator(menu->separator2()); - menu->insertAction(menu->separator2(), action); +bool DesktopWindow::pickWallpaper() { + if(slideShowInterval_ <= 0 + || !QFileInfo(wallpaperDir_).isDir()) { + return false; + } - Fm::FileInfoList files = menu->files(); - // select exactly one item - if(fm_file_info_list_get_length(files) == 1) { - Fm::FileInfo file = menu->firstFile(); - if(customItemPos_.find(file.getName()) != customItemPos_.end()) { - // the file item has a custom position - action->setChecked(true); + QList formats = QImageReader::supportedImageFormats(); + QStringList formatsFilters; + for (const QByteArray& format: formats) + formatsFilters << QString("*.") + format; + QDir folder(wallpaperDir_); + QStringList files = folder.entryList(formatsFilters, + QDir::Files | QDir::NoDotAndDotDot, + QDir::Name); + if(!files.isEmpty()) { + QString dir = wallpaperDir_ + QLatin1Char('/'); + if(!wallpaperRandomize_) { + if(!lastSlide_.startsWith(dir)) { // not in the directory + wallpaperFile_ = dir + files.first(); + } + else { + QString ls = lastSlide_.remove(0, dir.size()); + if(ls.isEmpty() // invalid + || ls.contains(QLatin1Char('/'))) { // in a subdirectory or invalid + wallpaperFile_ = dir + files.first(); + } + else { + int index = files.indexOf(ls); + if(index == -1) { // removed or invalid + wallpaperFile_ = dir + files.first(); + } + else { + wallpaperFile_ = dir + (index + 1 < files.size() + ? files.at(index + 1) + : files.first()); + } + } + } + } + else { + if(files.size() > 1) { + if(lastSlide_.startsWith(dir)) { + QString ls = lastSlide_.remove(0, dir.size()); + if(!ls.isEmpty() && !ls.contains(QLatin1Char('/'))) + files.removeOne(ls); // choose from other images + } + // this is needed for the randomness, especially when choosing the first wallpaper + qsrand((uint)QTime::currentTime().msec()); + int randomValue = qrand() % files.size(); + wallpaperFile_ = dir + files.at(randomValue); + } + else { + wallpaperFile_ = dir + files.first(); + } + } + + if (lastSlide_ != wallpaperFile_) { + lastSlide_ = wallpaperFile_; + Settings& settings = static_cast(qApp)->settings(); + settings.setLastSlide(lastSlide_); + return true; + } } - } - connect(action, &QAction::toggled, this, &DesktopWindow::onStickToCurrentPos); + + return false; +} + +void DesktopWindow::nextWallpaper() { + if(pickWallpaper()) { + updateWallpaper(); + update(); + } +} + +void DesktopWindow::updateFromSettings(Settings& settings, bool changeSlide) { + setDesktopFolder(); + setWallpaperFile(settings.wallpaper()); + setWallpaperMode(settings.wallpaperMode()); + setLastSlide(settings.lastSlide()); + QString wallpaperDir = settings.wallpaperDir(); + if(wallpaperDir_ != wallpaperDir) { + changeSlide = true; // another wallpapaer directory; change slide! + } + setWallpaperDir(wallpaperDir); + int interval = settings.slideShowInterval(); + if(interval > 0 && (interval < MIN_SLIDE_INTERVAL || interval > MAX_SLIDE_INTERVAL)) { + interval = qBound(MIN_SLIDE_INTERVAL, interval, MAX_SLIDE_INTERVAL); + settings.setSlideShowInterval(interval); + } + setSlideShowInterval(interval); + setWallpaperRandomize(settings.wallpaperRandomize()); + setFont(settings.desktopFont()); + setIconSize(Fm::FolderView::IconMode, QSize(settings.desktopIconSize(), settings.desktopIconSize())); + setMargins(settings.desktopCellMargins()); + // setIconSize and setMargins may trigger relayout of items by QListView, so we need to do the layout again. + queueRelayout(); + setForeground(settings.desktopFgColor()); + setBackground(settings.desktopBgColor()); + setShadow(settings.desktopShadowColor()); + showWmMenu_ = settings.showWmMenu(); + + if(slideShowInterval_ > 0 + && QFileInfo(wallpaperDir_).isDir()) { + if(!wallpaperTimer_) { + changeSlide = true; // slideshow activated; change slide! + wallpaperTimer_ = new QTimer(); + connect(wallpaperTimer_, &QTimer::timeout, this, &DesktopWindow::nextWallpaper); + } + else { + wallpaperTimer_->stop(); // restart the timer after updating wallpaper + } + if(changeSlide) { + pickWallpaper(); + } + else if(QFile::exists(lastSlide_)) { + /* show the last slide if it still exists, + otherwise show the wallpaper until timeout */ + wallpaperFile_ = lastSlide_; + } + } + else if(wallpaperTimer_) { + wallpaperTimer_->stop(); + delete wallpaperTimer_; + wallpaperTimer_ = nullptr; + } + + updateWallpaper(); + update(); + + if(wallpaperTimer_) { + wallpaperTimer_->start(slideShowInterval_); + } +} + +void DesktopWindow::onFileClicked(int type, const std::shared_ptr& fileInfo) { + if(!fileInfo && showWmMenu_) { + return; // do not show the popup if we want to use the desktop menu provided by the WM. + } + View::onFileClicked(type, fileInfo); +} + +void DesktopWindow::prepareFileMenu(Fm::FileMenu* menu) { + // qDebug("DesktopWindow::prepareFileMenu"); + PCManFM::View::prepareFileMenu(menu); + QAction* action = new QAction(tr("Stic&k to Current Position"), menu); + action->setCheckable(true); + menu->insertSeparator(menu->separator2()); + menu->insertAction(menu->separator2(), action); + + bool checked(true); + auto files = menu->files(); + for(const auto& file : files) { + if(customItemPos_.find(file->name()) == customItemPos_.cend()) { + checked = false; + break; + } + } + action->setChecked(checked); + connect(action, &QAction::toggled, this, &DesktopWindow::onStickToCurrentPos); } void DesktopWindow::prepareFolderMenu(Fm::FolderMenu* menu) { - PCManFM::View::prepareFolderMenu(menu); - // remove file properties action - menu->removeAction(menu->propertiesAction()); - // add an action for desktop preferences instead - QAction* action = menu->addAction(tr("Desktop Preferences")); - connect(action, &QAction::triggered, this, &DesktopWindow::onDesktopPreferences); + PCManFM::View::prepareFolderMenu(menu); + // remove file properties action + menu->removeAction(menu->propertiesAction()); + // add an action for desktop preferences instead + QAction* action = menu->addAction(tr("Desktop Preferences")); + connect(action, &QAction::triggered, this, &DesktopWindow::onDesktopPreferences); } void DesktopWindow::onDesktopPreferences() { - static_cast(qApp)->desktopPrefrences(QString()); + static_cast(qApp)->desktopPrefrences(QString()); } void DesktopWindow::onRowsInserted(const QModelIndex& parent, int start, int end) { - queueRelayout(); + Q_UNUSED(parent); + Q_UNUSED(start); + Q_UNUSED(end); + // disable view updates temporarily and delay relayout to prevent items from shaking + listView_->setUpdatesEnabled(false); + queueRelayout(100); } void DesktopWindow::onRowsAboutToBeRemoved(const QModelIndex& parent, int start, int end) { - Q_UNUSED(parent); - Q_UNUSED(start); - Q_UNUSED(end); - if(!customItemPos_.isEmpty()) { - // also delete stored custom item positions for the items currently being removed. - // Here we can't rely on ProxyFolderModel::fileInfoFromIndex() because, although rows - // aren't removed yet, files are already removed. - QHash _customItemPos = customItemPos_; - char* dektopPath = Fm::Path::getDesktop().toStr(); - QString desktopDir = QString(dektopPath) + QString("/"); - g_free(dektopPath); - QHash::iterator it; - for(it = _customItemPos.begin(); it != _customItemPos.end(); ++it) { - const QByteArray& name = it.key(); - if(!QFile::exists(desktopDir + QString::fromUtf8(name, name.length()))) - customItemPos_.remove(it.key()); + Q_UNUSED(parent); + Q_UNUSED(start); + Q_UNUSED(end); + if(!customItemPos_.empty()) { + // also delete stored custom item positions for the items currently being removed. + // Here we can't rely on ProxyFolderModel::fileInfoFromIndex() because, although rows + // aren't removed yet, files are already removed. + bool changed = false; + char* dektopPath = Fm::Path::getDesktop().toStr(); + QString desktopDir = QString(dektopPath) + QString("/"); + g_free(dektopPath); + for(auto it = customItemPos_.cbegin(); it != customItemPos_.cend();) { + auto& name = it->first; + if(!QFile::exists(desktopDir + QString::fromStdString(name))) { + it = customItemPos_.erase(it); + changed = true; + } + else { + ++it; + } + } + if(changed) { + saveItemPositions(); + } } - if(customItemPos_ != _customItemPos) - saveItemPositions(); - } - queueRelayout(); + listView_->setUpdatesEnabled(false); + queueRelayout(100); } void DesktopWindow::onLayoutChanged() { - queueRelayout(); + queueRelayout(); } void DesktopWindow::onModelSortFilterChanged() { - Settings& settings = static_cast(qApp)->settings(); - settings.setDesktopSortColumn(static_cast(proxyModel_->sortColumn())); - settings.setDesktopSortOrder(proxyModel_->sortOrder()); - settings.setSesktopSortFolderFirst(proxyModel_->folderFirst()); + Settings& settings = static_cast(qApp)->settings(); + settings.setDesktopSortColumn(static_cast(proxyModel_->sortColumn())); + settings.setDesktopSortOrder(proxyModel_->sortOrder()); + settings.setSesktopSortFolderFirst(proxyModel_->folderFirst()); } void DesktopWindow::onDataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight) { - /**************************************************************************** - NOTE: The display names of desktop entries and shortcuts may change without - their files being renamed and, on such occasions, a relayout will be needed. - Since there is no signal for that, we use the signal dataChanged() and the - QHash displayNames_, which remembers such display names with every relayout. - ****************************************************************************/ - if(topLeft.column() == 0) { - bool relayout(false); - for(int i = topLeft.row(); i <= bottomRight.row(); ++i) { - QModelIndex index = topLeft.sibling(i, 0); - if(index.isValid() && displayNames_.contains(index)) { - Fm::FileInfo file = proxyModel_->fileInfoFromIndex(index); - if(displayNames_[index] != file.getDispName()) { - relayout = true; - break; - } - } - } - if(relayout) { - queueRelayout(); - // parts of the old display name might still be visible if it's long - listView_->viewport()->update(); - } - } + /**************************************************************************** + NOTE: The display names of desktop entries and shortcuts may change without + their files being renamed and, on such occasions, a relayout will be needed. + Since there is no signal for that, we use the signal dataChanged() and the + QHash displayNames_, which remembers such display names with every relayout. + ****************************************************************************/ + if(topLeft.column() == 0) { + bool relayout(false); + for(int i = topLeft.row(); i <= bottomRight.row(); ++i) { + QModelIndex index = topLeft.sibling(i, 0); + if(index.isValid() && displayNames_.contains(index)) { + auto file = proxyModel_->fileInfoFromIndex(index); + if(displayNames_[index] != file->displayName()) { + relayout = true; + break; + } + } + } + if(relayout) { + queueRelayout(); + // parts of the old display name might still be visible if it's long + listView_->viewport()->update(); + } + } } void DesktopWindow::onIndexesMoved(const QModelIndexList& indexes) { - // remember the custom position for the items - Q_FOREACH(const QModelIndex& index, indexes) { - // Under some circumstances, Qt might emit indexMoved for - // every single cells in the same row. (when QAbstractItemView::SelectItems is set) - // So indexes list may contain several indixes for the same row. - // Since we only care about rows, not individual cells, - // let's handle column 0 of every row here. - if(index.column() == 0) { - Fm::FileInfo file = proxyModel_->fileInfoFromIndex(index); - QRect itemRect = listView_->rectForIndex(index); - QPoint tl = itemRect.topLeft(); - QRect workArea = qApp->desktop()->availableGeometry(screenNum_); - workArea.adjust(12, 12, -12, -12); - if(customItemPos_.keys(tl).isEmpty() // don't put items on each other - && tl.x() >= workArea.x() && tl.y() >= workArea.y() - && tl.x() + listView_->gridSize().width() <= workArea.right() + 1 // for historical reasons (-> Qt doc) - && tl.y() + listView_->gridSize().height() <= workArea.bottom() + 1) { // as above - QByteArray name = file.getName(); - customItemPos_[name] = tl; - // qDebug() << "indexMoved:" << name << index << itemRect; - } - } - } - saveItemPositions(); - queueRelayout(); + auto delegate = static_cast(listView_->itemDelegateForColumn(0)); + auto itemSize = delegate->itemSize(); + // remember the custom position for the items + Q_FOREACH(const QModelIndex& index, indexes) { + // Under some circumstances, Qt might emit indexMoved for + // every single cells in the same row. (when QAbstractItemView::SelectItems is set) + // So indexes list may contain several indixes for the same row. + // Since we only care about rows, not individual cells, + // let's handle column 0 of every row here. + if(index.column() == 0) { + auto file = proxyModel_->fileInfoFromIndex(index); + QRect itemRect = listView_->rectForIndex(index); + QPoint tl = itemRect.topLeft(); + QRect workArea = qApp->desktop()->availableGeometry(screenNum_); + workArea.adjust(12, 12, -12, -12); + + // check if the position is occupied by another item + auto existingItem = std::find_if(customItemPos_.cbegin(), customItemPos_.cend(), [tl](const std::pair& elem){ + return elem.second == tl; + }); + + if(existingItem == customItemPos_.cend() // don't put items on each other + && tl.x() >= workArea.x() && tl.y() >= workArea.y() + && tl.x() + itemSize.width() <= workArea.right() + 1 // for historical reasons (-> Qt doc) + && tl.y() + itemSize.height() <= workArea.bottom() + 1) { // as above + customItemPos_[file->name()] = tl; + // qDebug() << "indexMoved:" << name << index << itemRect; + } + } + } + saveItemPositions(); + queueRelayout(); } void DesktopWindow::removeBottomGap() { - /************************************************************ - NOTE: Desktop is an area bounded from below while icons snap - to its grid srarting from above. Therefore, we try to adjust - the vertical cell margin to prevent relatively large gaps - from taking shape at the desktop bottom. - ************************************************************/ - QSize cellMargins = getMargins(); - int workAreaHeight = qApp->desktop()->availableGeometry(screenNum_).height() - - 24; // a 12-pix margin will be considered everywhere - int cellHeight = listView_->gridSize().height() + listView_->spacing(); - int iconNumber = workAreaHeight / cellHeight; - int bottomGap = workAreaHeight % cellHeight; - /******************************************* - First try to make room for an extra icon... - *******************************************/ - // If one pixel is subtracted from the vertical margin, cellHeight - // will decrease by 2 while bottomGap will increase by 2*iconNumber. - // So, we can add an icon to the bottom once this inequality holds: - // bottomGap + 2*n*iconNumber >= cellHeight - 2*n - // From here, we get our "subtrahend": - qreal exactNumber = ((qreal)cellHeight - (qreal)bottomGap) - / (2.0 * (qreal)iconNumber + 2.0); - int subtrahend = (int)exactNumber + ((int)exactNumber == exactNumber ? 0 : 1); - Settings& settings = static_cast(qApp)->settings(); - int minCellHeight = settings.desktopCellMargins().height(); - if(subtrahend > 0 - && cellMargins.height() - subtrahend >= minCellHeight) { - cellMargins -= QSize(0, subtrahend); - } - /*************************************************** - ... but if that can't be done, try to spread icons! - ***************************************************/ - else - cellMargins += QSize(0, (bottomGap / iconNumber) / 2); - // set the new margins (if they're changed) - delegate_->setMargins(cellMargins); - setMargins(cellMargins); - // in case the text shadow is reset to (0,0,0,0) - setShadow(settings.desktopShadowColor()); -} - -void DesktopWindow::paintBackground(QPaintEvent *event) { - // This is to workaround Qt bug 54384 which affects Qt >= 5.6 - // https://bugreports.qt.io/browse/QTBUG-54384 - // Since Qt does not paint the background of the QListView using the QPixmap we set properly, we do it ourselves. - QPainter painter(listView_->viewport()); // the painter paints on the viewport widget, not the QListView. - if(wallpaperMode_ == WallpaperNone || wallpaperPixmap_.isNull()) { - painter.fillRect(event->rect(), QBrush(bgColor_)); - } - else { - painter.drawPixmap(event->rect(), wallpaperPixmap_, event->rect()); - } + /************************************************************ + NOTE: Desktop is an area bounded from below while icons snap + to its grid srarting from above. Therefore, we try to adjust + the vertical cell margin to prevent relatively large gaps + from taking shape at the desktop bottom. + ************************************************************/ + auto delegate = static_cast(listView_->itemDelegateForColumn(0)); + auto itemSize = delegate->itemSize(); + qDebug() << "delegate:" << delegate->itemSize(); + QSize cellMargins = getMargins(); + int workAreaHeight = qApp->desktop()->availableGeometry(screenNum_).height() + - 24; // a 12-pix margin will be considered everywhere + int cellHeight = itemSize.height() + listView_->spacing(); + int iconNumber = workAreaHeight / cellHeight; + int bottomGap = workAreaHeight % cellHeight; + /******************************************* + First try to make room for an extra icon... + *******************************************/ + // If one pixel is subtracted from the vertical margin, cellHeight + // will decrease by 2 while bottomGap will increase by 2*iconNumber. + // So, we can add an icon to the bottom once this inequality holds: + // bottomGap + 2*n*iconNumber >= cellHeight - 2*n + // From here, we get our "subtrahend": + qreal exactNumber = ((qreal)cellHeight - (qreal)bottomGap) + / (2.0 * (qreal)iconNumber + 2.0); + int subtrahend = (int)exactNumber + ((int)exactNumber == exactNumber ? 0 : 1); + Settings& settings = static_cast(qApp)->settings(); + int minCellHeight = settings.desktopCellMargins().height(); + if(subtrahend > 0 + && cellMargins.height() - subtrahend >= minCellHeight) { + cellMargins -= QSize(0, subtrahend); + } + /*************************************************** + ... but if that can't be done, try to spread icons! + ***************************************************/ + else { + cellMargins += QSize(0, (bottomGap / iconNumber) / 2); + } + // set the new margins (if they're changed) + delegate->setMargins(cellMargins); + setMargins(cellMargins); + // in case the text shadow is reset to (0,0,0,0) + setShadow(settings.desktopShadowColor()); +} + +void DesktopWindow::paintBackground(QPaintEvent* event) { + // This is to workaround Qt bug 54384 which affects Qt >= 5.6 + // https://bugreports.qt.io/browse/QTBUG-54384 + QPainter painter(this); + if(wallpaperMode_ == WallpaperNone || wallpaperPixmap_.isNull()) { + painter.fillRect(event->rect(), QBrush(bgColor_)); + } + else { + painter.drawPixmap(event->rect(), wallpaperPixmap_, event->rect()); + } } // QListView does item layout in a very inflexible way, so let's do our custom layout again. // FIXME: this is very inefficient, but due to the design flaw of QListView, this is currently the only workaround. void DesktopWindow::relayoutItems() { - displayNames_.clear(); - loadItemPositions(); // something may have changed - // qDebug("relayoutItems()"); - if(relayoutTimer_) { - // this slot might be called from the timer, so we cannot delete it directly here. - relayoutTimer_->deleteLater(); - relayoutTimer_ = NULL; - } - - QDesktopWidget* desktop = qApp->desktop(); - int screen = 0; - int row = 0; - int rowCount = proxyModel_->rowCount(); - for(;;) { - if(desktop->isVirtualDesktop()) { - if(screen >= desktop->numScreens()) - break; - }else { - screen = screenNum_; - } - QRect workArea = desktop->availableGeometry(screen); - workArea.adjust(12, 12, -12, -12); // add a 12 pixel margin to the work area - // qDebug() << "workArea" << screen << workArea; - // FIXME: we use an internal class declared in a private header here, which is pretty bad. - QSize grid = listView_->gridSize(); - QPoint pos = workArea.topLeft(); - for(; row < rowCount; ++row) { - QModelIndex index = proxyModel_->index(row, 0); - int itemWidth = delegate_->sizeHint(listView_->getViewOptions(), index).width(); - Fm::FileInfo file = proxyModel_->fileInfoFromIndex(index); - // remember display names of desktop entries and shortcuts - if(file.isDesktopEntry() || file.isShortcut()) - displayNames_[index] = QString(file.getDispName()); - QByteArray name = file.getName(); - QHash::iterator it = customItemPos_.find(name); - if(it != customItemPos_.end()) { // the item has a custom position - QPoint customPos = *it; - // center the contents vertically - listView_->setPositionForIndex(customPos + QPoint((grid.width() - itemWidth) / 2, 0), index); - // qDebug() << "set custom pos:" << name << row << index << customPos; - continue; - } - // check if the current pos is alredy occupied by a custom item - bool used = false; - for(it = customItemPos_.begin(); it != customItemPos_.end(); ++it) { - QPoint customPos = *it; - if(QRect(customPos, grid).contains(pos)) { - used = true; - break; - } - } - if(used) { // go to next pos - --row; - } - else { - // center the contents vertically - listView_->setPositionForIndex(pos + QPoint((grid.width() - itemWidth) / 2, 0), index); - // qDebug() << "set pos" << name << row << index << pos; - } - // move to next cell in the column - pos.setY(pos.y() + grid.height() + listView_->spacing()); - if(pos.y() + grid.height() > workArea.bottom() + 1) { - // if the next position may exceed the bottom of work area, go to the top of next column - pos.setX(pos.x() + grid.width() + listView_->spacing()); - pos.setY(workArea.top()); - - // check if the new column exceeds the right margin of work area - if(pos.x() + grid.width() > workArea.right() + 1) { - if(desktop->isVirtualDesktop()) { - // in virtual desktop mode, go to next screen - ++screen; + displayNames_.clear(); + loadItemPositions(); // something may have changed + // qDebug("relayoutItems()"); + if(relayoutTimer_) { + // this slot might be called from the timer, so we cannot delete it directly here. + relayoutTimer_->deleteLater(); + relayoutTimer_ = nullptr; + } + + QDesktopWidget* desktop = qApp->desktop(); + int screen = 0; + int row = 0; + int rowCount = proxyModel_->rowCount(); + + auto delegate = static_cast(listView_->itemDelegateForColumn(0)); + auto itemSize = delegate->itemSize(); + + for(;;) { + if(desktop->isVirtualDesktop()) { + if(screen >= desktop->numScreens()) { + break; + } + } + else { + screen = screenNum_; + } + QRect workArea = desktop->availableGeometry(screen); + workArea.adjust(12, 12, -12, -12); // add a 12 pixel margin to the work area + // qDebug() << "workArea" << screen << workArea; + // FIXME: we use an internal class declared in a private header here, which is pretty bad. + QPoint pos = workArea.topLeft(); + for(; row < rowCount; ++row) { + QModelIndex index = proxyModel_->index(row, 0); + int itemWidth = delegate->sizeHint(listView_->getViewOptions(), index).width(); + auto file = proxyModel_->fileInfoFromIndex(index); + // remember display names of desktop entries and shortcuts + if(file->isDesktopEntry() || file->isShortcut()) { + displayNames_[index] = file->displayName(); + } + auto name = file->name(); + auto find_it = customItemPos_.find(name); + if(find_it != customItemPos_.cend()) { // the item has a custom position + QPoint customPos = find_it->second; + // center the contents vertically + listView_->setPositionForIndex(customPos + QPoint((itemSize.width() - itemWidth) / 2, 0), index); + // qDebug() << "set custom pos:" << name << row << index << customPos; + continue; + } + // check if the current pos is alredy occupied by a custom item + bool used = false; + for(auto it = customItemPos_.cbegin(); it != customItemPos_.cend(); ++it) { + QPoint customPos = it->second; + if(QRect(customPos, itemSize).contains(pos)) { + used = true; + break; + } + } + if(used) { // go to next pos + --row; + } + else { + // center the contents vertically + listView_->setPositionForIndex(pos + QPoint((itemSize.width() - itemWidth) / 2, 0), index); + // qDebug() << "set pos" << name << row << index << pos; + } + // move to next cell in the column + pos.setY(pos.y() + itemSize.height() + listView_->spacing()); + if(pos.y() + itemSize.height() > workArea.bottom() + 1) { + // if the next position may exceed the bottom of work area, go to the top of next column + pos.setX(pos.x() + itemSize.width() + listView_->spacing()); + pos.setY(workArea.top()); + + // check if the new column exceeds the right margin of work area + if(pos.x() + itemSize.width() > workArea.right() + 1) { + if(desktop->isVirtualDesktop()) { + // in virtual desktop mode, go to next screen + ++screen; + break; + } + } + } + } + if(row >= rowCount) { break; - } } - } } - if(row >= rowCount) - break; - } + + if(!listView_->updatesEnabled()) { + listView_->setUpdatesEnabled(true); + } } void DesktopWindow::loadItemPositions() { - // load custom item positions - customItemPos_.clear(); - Settings& settings = static_cast(qApp)->settings(); - QString configFile = QString("%1/desktop-items-%2.conf").arg(settings.profileDir(settings.profileName())).arg(screenNum_); - QSettings file(configFile, QSettings::IniFormat); - QSize grid = listView_->gridSize(); - QRect workArea = qApp->desktop()->availableGeometry(screenNum_); - workArea.adjust(12, 12, -12, -12); - char* dektopPath = Fm::Path::getDesktop().toStr(); - QString desktopDir = QString(dektopPath) + QString("/"); - g_free(dektopPath); - Q_FOREACH(const QString& name, file.childGroups()) { - if(!QFile::exists(desktopDir + name.toUtf8())) { - // the file may have been removed from outside LXQT - continue; - } - file.beginGroup(name); - QVariant var = file.value("pos"); - if(var.isValid()) { - QPoint customPos = var.toPoint(); - if (customPos.x() >= workArea.x() && customPos.y() >= workArea.y() - && customPos.x() + listView_->gridSize().width() <= workArea.right() + 1 - && customPos.y() + listView_->gridSize().height() <= workArea.bottom() + 1) - { - // correct positions that are't aligned to the grid - qreal w = qAbs((qreal)customPos.x() - (qreal)workArea.x()) - / (qreal)(grid.width() + listView_->spacing()); - qreal h = qAbs(customPos.y() - (qreal)workArea.y()) - / (qreal)(grid.height() + listView_->spacing()); - customPos.setX(workArea.x() + qRound(w) * (grid.width() + listView_->spacing())); - customPos.setY(workArea.y() + qRound(h) * (grid.height() + listView_->spacing())); - while(customItemPos_.values().contains(customPos)) { - customPos.setY(customPos.y() + grid.height() + listView_->spacing()); - if(customPos.y() + grid.height() > workArea.bottom() + 1) { - customPos.setX(customPos.x() + grid.width() + listView_->spacing()); - customPos.setY(workArea.top()); - } - } - customItemPos_[name.toUtf8()] = customPos; - } - } - file.endGroup(); - } + // load custom item positions + customItemPos_.clear(); + Settings& settings = static_cast(qApp)->settings(); + QString configFile = QString("%1/desktop-items-%2.conf").arg(settings.profileDir(settings.profileName())).arg(screenNum_); + QSettings file(configFile, QSettings::IniFormat); + + auto delegate = static_cast(listView_->itemDelegateForColumn(0)); + auto grid = delegate->itemSize(); + QRect workArea = qApp->desktop()->availableGeometry(screenNum_); + workArea.adjust(12, 12, -12, -12); + char* dektopPath = Fm::Path::getDesktop().toStr(); + QString desktopDir = QString(dektopPath) + QString("/"); + g_free(dektopPath); + + std::vector usedPos; + for(auto& item: customItemPos_) { + usedPos.push_back(item.second); + } + + // FIXME: this is inefficient + Q_FOREACH(const QString& name, file.childGroups()) { + if(!QFile::exists(desktopDir + name.toUtf8())) { + // the file may have been removed from outside LXQT + continue; + } + file.beginGroup(name); + QVariant var = file.value("pos"); + if(var.isValid()) { + QPoint customPos = var.toPoint(); + if(customPos.x() >= workArea.x() && customPos.y() >= workArea.y() + && customPos.x() + grid.width() <= workArea.right() + 1 + && customPos.y() + grid.height() <= workArea.bottom() + 1) { + // correct positions that are't aligned to the grid + alignToGrid(customPos, workArea.topLeft(), grid, listView_->spacing()); + // FIXME: this is very inefficient + while(std::find(usedPos.cbegin(), usedPos.cend(), customPos) != usedPos.cend()) { + customPos.setY(customPos.y() + grid.height() + listView_->spacing()); + if(customPos.y() + grid.height() > workArea.bottom() + 1) { + customPos.setX(customPos.x() + grid.width() + listView_->spacing()); + customPos.setY(workArea.top()); + } + } + customItemPos_[name.toStdString()] = customPos; + usedPos.push_back(customPos); + } + } + file.endGroup(); + } } void DesktopWindow::saveItemPositions() { - Settings& settings = static_cast(qApp)->settings(); - // store custom item positions - QString configFile = QString("%1/desktop-items-%2.conf").arg(settings.profileDir(settings.profileName())).arg(screenNum_); - // FIXME: using QSettings here is inefficient and it's not friendly to UTF-8. - QSettings file(configFile, QSettings::IniFormat); - file.clear(); // remove all existing entries - - // FIXME: we have to remove dead entries not associated to any files? - QHash::iterator it; - for(it = customItemPos_.begin(); it != customItemPos_.end(); ++it) { - const QByteArray& name = it.key(); - QPoint pos = it.value(); - file.beginGroup(QString::fromUtf8(name, name.length())); - file.setValue("pos", pos); - file.endGroup(); - } + Settings& settings = static_cast(qApp)->settings(); + // store custom item positions + QString configFile = QString("%1/desktop-items-%2.conf").arg(settings.profileDir(settings.profileName())).arg(screenNum_); + // FIXME: using QSettings here is inefficient and it's not friendly to UTF-8. + QSettings file(configFile, QSettings::IniFormat); + file.clear(); // remove all existing entries + + // FIXME: we have to remove dead entries not associated to any files? + for(auto it = customItemPos_.cbegin(); it != customItemPos_.cend(); ++it) { + auto& name = it->first; + auto& pos = it->second; + file.beginGroup(QString::fromStdString(name)); + file.setValue("pos", pos); + file.endGroup(); + } } void DesktopWindow::onStickToCurrentPos(bool toggled) { - QAction* action = static_cast(sender()); - Fm::FileMenu* menu = static_cast(action->parent()); - - QModelIndexList indexes = listView_->selectionModel()->selectedIndexes(); - if(!indexes.isEmpty()) { - Fm::FileInfo file = menu->firstFile(); - QByteArray name = file.getName(); - QModelIndex index = indexes.first(); - if(toggled) { // remember to current custom position - QRect itemRect = listView_->rectForIndex(index); - customItemPos_[name] = itemRect.topLeft(); - saveItemPositions(); - } - else { // cancel custom position and perform relayout - QHash::iterator it = customItemPos_.find(name); - if(it != customItemPos_.end()) { - customItemPos_.erase(it); + QModelIndexList indexes = listView_->selectionModel()->selectedIndexes(); + if(!indexes.isEmpty()) { + bool relayout(false); + QModelIndexList::const_iterator it; + for(it = indexes.constBegin(); it != indexes.constEnd(); ++it) { + auto file = proxyModel_->fileInfoFromIndex(*it); + auto name = file->name(); + if(toggled) { // remember the current custom position + QRect itemRect = listView_->rectForIndex(*it); + customItemPos_[name] = itemRect.topLeft(); + } + else { // cancel custom position and perform relayout + auto item = customItemPos_.find(name); + if(item != customItemPos_.end()) { + customItemPos_.erase(item); + relayout = true; + } + } + } saveItemPositions(); - relayoutItems(); - } + if(relayout) { + relayoutItems(); + } } - } } void DesktopWindow::queueRelayout(int delay) { - // qDebug() << "queueRelayout"; - removeBottomGap(); - if(!relayoutTimer_) { - relayoutTimer_ = new QTimer(); - relayoutTimer_->setSingleShot(true); - connect(relayoutTimer_, &QTimer::timeout, this, &DesktopWindow::relayoutItems); - relayoutTimer_->start(delay); - } + // qDebug() << "queueRelayout"; + removeBottomGap(); + if(!relayoutTimer_) { + relayoutTimer_ = new QTimer(); + relayoutTimer_->setSingleShot(true); + connect(relayoutTimer_, &QTimer::timeout, this, &DesktopWindow::relayoutItems); + relayoutTimer_->start(delay); + } } // slots for file operations void DesktopWindow::onCutActivated() { - Fm::PathList paths = selectedFilePaths(); - if(!paths.isNull()) { - Fm::cutFilesToClipboard(paths); - } + auto paths = selectedFilePaths(); + if(!paths.empty()) { + Fm::cutFilesToClipboard(paths); + } } void DesktopWindow::onCopyActivated() { - Fm::PathList paths = selectedFilePaths(); - if(!paths.isNull()) { - Fm::copyFilesToClipboard(paths); - } + auto paths = selectedFilePaths(); + if(!paths.empty()) { + Fm::copyFilesToClipboard(paths); + } } void DesktopWindow::onPasteActivated() { - Fm::pasteFilesFromClipboard(path()); + Fm::pasteFilesFromClipboard(path()); } void DesktopWindow::onDeleteActivated() { - Fm::PathList paths = selectedFilePaths(); - if(!paths.isNull()) { - Settings& settings = static_cast(qApp)->settings(); - bool shiftPressed = (qApp->keyboardModifiers() & Qt::ShiftModifier ? true : false); - if(settings.useTrash() && !shiftPressed) - Fm::FileOperation::trashFiles(paths, settings.confirmTrash()); - else - Fm::FileOperation::deleteFiles(paths, settings.confirmDelete()); - } + auto paths = selectedFilePaths(); + if(!paths.empty()) { + Settings& settings = static_cast(qApp)->settings(); + bool shiftPressed = (qApp->keyboardModifiers() & Qt::ShiftModifier ? true : false); + if(settings.useTrash() && !shiftPressed) { + Fm::FileOperation::trashFiles(paths, settings.confirmTrash()); + } + else { + Fm::FileOperation::deleteFiles(paths, settings.confirmDelete()); + } + } } void DesktopWindow::onRenameActivated() { - Fm::FileInfoList files = selectedFiles(); - if(!files.isNull()) { - for(GList* l = fm_file_info_list_peek_head_link(files); l; l = l->next) { - FmFileInfo* info = FM_FILE_INFO(l->data); - Fm::renameFile(info, NULL); + // do inline renaming if only one item is selected, + // otherwise use the renaming dialog + if(selectedIndexes().size() == 1) { + QModelIndex cur = listView_->currentIndex(); + if (cur.isValid()) { + listView_->edit(cur); + return; + } } - } + auto files = selectedFiles(); + if(!files.empty()) { + for(auto& info: files) { + Fm::renameFile(info, nullptr); + } + } } void DesktopWindow::onFilePropertiesActivated() { - Fm::FileInfoList files = selectedFiles(); - if(!files.isNull()) { - Fm::FilePropsDialog::showForFiles(files); - } + auto files = selectedFiles(); + if(!files.empty()) { + Fm::FilePropsDialog::showForFiles(std::move(files)); + } } static void forwardMouseEventToRoot(QMouseEvent* event) { - xcb_ungrab_pointer(QX11Info::connection(), event->timestamp()); - // forward the event to the root window - xcb_button_press_event_t xcb_event; - uint32_t mask = 0; - xcb_event.state = 0; - switch(event->type()) { - case QEvent::MouseButtonPress: - xcb_event.response_type = XCB_BUTTON_PRESS; - mask = XCB_EVENT_MASK_BUTTON_PRESS; - break; - case QEvent::MouseButtonRelease: - xcb_event.response_type = XCB_BUTTON_RELEASE; - mask = XCB_EVENT_MASK_BUTTON_RELEASE; - break; - default: - return; - } - - // convert Qt button to XCB button - switch(event->button()) { - case Qt::LeftButton: - xcb_event.detail = 1; - xcb_event.state |= XCB_BUTTON_MASK_1; - break; - case Qt::MiddleButton: - xcb_event.detail = 2; - xcb_event.state |= XCB_BUTTON_MASK_2; - break; - case Qt::RightButton: - xcb_event.detail = 3; - xcb_event.state |= XCB_BUTTON_MASK_3; - break; - default: - xcb_event.detail = 0; - } - - // convert Qt modifiers to XCB states - if(event->modifiers() & Qt::ShiftModifier) - xcb_event.state |= XCB_MOD_MASK_SHIFT; - if(event->modifiers() & Qt::ControlModifier) - xcb_event.state |= XCB_MOD_MASK_SHIFT; - if(event->modifiers() & Qt::AltModifier) - xcb_event.state |= XCB_MOD_MASK_1; - - xcb_event.sequence = 0; - xcb_event.time = event->timestamp(); - - WId root = QX11Info::appRootWindow(QX11Info::appScreen()); - xcb_event.event = root; - xcb_event.root = root; - xcb_event.child = 0; - - xcb_event.root_x = event->globalX(); - xcb_event.root_y = event->globalY(); - xcb_event.event_x = event->x(); - xcb_event.event_y = event->y(); - xcb_event.same_screen = 1; - - xcb_send_event(QX11Info::connection(), 0, root, mask, (char*)&xcb_event); - xcb_flush(QX11Info::connection()); -} - -bool DesktopWindow::event(QEvent* event) -{ - switch(event->type()) { - case QEvent::WinIdChange: { - qDebug() << "winid change:" << effectiveWinId(); - if(effectiveWinId() == 0) - break; - // set freedesktop.org EWMH hints properly - if(QX11Info::isPlatformX11() && QX11Info::connection()) { - xcb_connection_t* con = QX11Info::connection(); - const char* atom_name = "_NET_WM_WINDOW_TYPE_DESKTOP"; - xcb_atom_t atom = xcb_intern_atom_reply(con, xcb_intern_atom(con, 0, strlen(atom_name), atom_name), NULL)->atom; - const char* prop_atom_name = "_NET_WM_WINDOW_TYPE"; - xcb_atom_t prop_atom = xcb_intern_atom_reply(con, xcb_intern_atom(con, 0, strlen(prop_atom_name), prop_atom_name), NULL)->atom; - xcb_atom_t XA_ATOM = 4; - xcb_change_property(con, XCB_PROP_MODE_REPLACE, effectiveWinId(), prop_atom, XA_ATOM, 32, 1, &atom); - } - break; - } -#undef FontChange // FontChange is defined in the headers of XLib and clashes with Qt, let's undefine it. - case QEvent::StyleChange: - case QEvent::FontChange: - queueRelayout(); - break; + xcb_ungrab_pointer(QX11Info::connection(), event->timestamp()); + // forward the event to the root window + xcb_button_press_event_t xcb_event; + uint32_t mask = 0; + xcb_event.state = 0; + switch(event->type()) { + case QEvent::MouseButtonPress: + xcb_event.response_type = XCB_BUTTON_PRESS; + mask = XCB_EVENT_MASK_BUTTON_PRESS; + break; + case QEvent::MouseButtonRelease: + xcb_event.response_type = XCB_BUTTON_RELEASE; + mask = XCB_EVENT_MASK_BUTTON_RELEASE; + break; + default: + return; + } - default: - break; - } + // convert Qt button to XCB button + switch(event->button()) { + case Qt::LeftButton: + xcb_event.detail = 1; + xcb_event.state |= XCB_BUTTON_MASK_1; + break; + case Qt::MiddleButton: + xcb_event.detail = 2; + xcb_event.state |= XCB_BUTTON_MASK_2; + break; + case Qt::RightButton: + xcb_event.detail = 3; + xcb_event.state |= XCB_BUTTON_MASK_3; + break; + default: + xcb_event.detail = 0; + } - return QWidget::event(event); -} + // convert Qt modifiers to XCB states + if(event->modifiers() & Qt::ShiftModifier) { + xcb_event.state |= XCB_MOD_MASK_SHIFT; + } + if(event->modifiers() & Qt::ControlModifier) { + xcb_event.state |= XCB_MOD_MASK_SHIFT; + } + if(event->modifiers() & Qt::AltModifier) { + xcb_event.state |= XCB_MOD_MASK_1; + } -#undef FontChange // this seems to be defined in Xlib headers as a macro, undef it! + xcb_event.sequence = 0; + xcb_event.time = event->timestamp(); + + WId root = QX11Info::appRootWindow(QX11Info::appScreen()); + xcb_event.event = root; + xcb_event.root = root; + xcb_event.child = 0; + + xcb_event.root_x = event->globalX(); + xcb_event.root_y = event->globalY(); + xcb_event.event_x = event->x(); + xcb_event.event_y = event->y(); + xcb_event.same_screen = 1; + + xcb_send_event(QX11Info::connection(), 0, root, mask, (char*)&xcb_event); + xcb_flush(QX11Info::connection()); +} -bool DesktopWindow::eventFilter(QObject * watched, QEvent * event) { - if(watched == listView_) { +bool DesktopWindow::event(QEvent* event) { switch(event->type()) { + case QEvent::WinIdChange: { + qDebug() << "winid change:" << effectiveWinId(); + if(effectiveWinId() == 0) { + break; + } + // set freedesktop.org EWMH hints properly + if(QX11Info::isPlatformX11() && QX11Info::connection()) { + xcb_connection_t* con = QX11Info::connection(); + const char* atom_name = "_NET_WM_WINDOW_TYPE_DESKTOP"; + xcb_atom_t atom = xcb_intern_atom_reply(con, xcb_intern_atom(con, 0, strlen(atom_name), atom_name), nullptr)->atom; + const char* prop_atom_name = "_NET_WM_WINDOW_TYPE"; + xcb_atom_t prop_atom = xcb_intern_atom_reply(con, xcb_intern_atom(con, 0, strlen(prop_atom_name), prop_atom_name), nullptr)->atom; + xcb_atom_t XA_ATOM = 4; + xcb_change_property(con, XCB_PROP_MODE_REPLACE, effectiveWinId(), prop_atom, XA_ATOM, 32, 1, &atom); + } + break; + } +#undef FontChange // FontChange is defined in the headers of XLib and clashes with Qt, let's undefine it. case QEvent::StyleChange: case QEvent::FontChange: - if(model_) queueRelayout(); - break; + break; + default: - break; + break; } - } - else if(watched == listView_->viewport()) { - switch(event->type()) { - case QEvent::Paint: { - paintBackground(static_cast(event)); - break; - } - case QEvent::MouseButtonPress: - case QEvent::MouseButtonRelease: - if(showWmMenu_) { - QMouseEvent* e = static_cast(event); - // If we want to show the desktop menus provided by the window manager instead of ours, - // we have to forward the mouse events we received to the root window. - // check if the user click on blank area - QModelIndex index = listView_->indexAt(e->pos()); - if(!index.isValid() && e->button() != Qt::LeftButton) { - forwardMouseEventToRoot(e); - } - } - break; - default: - break; + + return QWidget::event(event); +} + +#undef FontChange // this seems to be defined in Xlib headers as a macro, undef it! + +bool DesktopWindow::eventFilter(QObject* watched, QEvent* event) { + if(watched == listView_) { + switch(event->type()) { + case QEvent::StyleChange: + case QEvent::FontChange: + if(model_) { + queueRelayout(); + } + break; + default: + break; + } } - } - return false; + else if(watched == listView_->viewport()) { + switch(event->type()) { + case QEvent::MouseButtonPress: + case QEvent::MouseButtonRelease: + if(showWmMenu_) { + QMouseEvent* e = static_cast(event); + // If we want to show the desktop menus provided by the window manager instead of ours, + // we have to forward the mouse events we received to the root window. + // check if the user click on blank area + QModelIndex index = listView_->indexAt(e->pos()); + if(!index.isValid() && e->button() != Qt::LeftButton) { + forwardMouseEventToRoot(e); + } + } + break; + default: + break; + } + } + return Fm::FolderView::eventFilter(watched, event); } void DesktopWindow::childDropEvent(QDropEvent* e) { - bool moveItem = false; - if(e->source() == listView_ && e->keyboardModifiers() == Qt::NoModifier) { - // drag source is our list view, and no other modifier keys are pressed - // => we're dragging desktop items - const QMimeData *mimeData = e->mimeData(); - if(mimeData->hasFormat("application/x-qabstractitemmodeldatalist")) { - QModelIndex dropIndex = listView_->indexAt(e->pos()); - if(dropIndex.isValid()) { // drop on an item - QModelIndexList selected = selectedIndexes(); // the dragged items - if(selected.contains(dropIndex)) { // drop on self, ignore - moveItem = true; - } - } - else { // drop on a blank area - moveItem = true; - } - } - } - if(moveItem) - e->accept(); - else - Fm::FolderView::childDropEvent(e); -} - -void DesktopWindow::closeEvent(QCloseEvent *event) { - // prevent the desktop window from being closed. - event->ignore(); + const QMimeData* mimeData = e->mimeData(); + bool moveItem = false; + if(e->source() == listView_ && e->keyboardModifiers() == Qt::NoModifier) { + // drag source is our list view, and no other modifier keys are pressed + // => we're dragging desktop items + if(mimeData->hasFormat("application/x-qabstractitemmodeldatalist")) { + QModelIndex dropIndex = listView_->indexAt(e->pos()); + if(dropIndex.isValid()) { // drop on an item + QModelIndexList selected = selectedIndexes(); // the dragged items + if(selected.contains(dropIndex)) { // drop on self, ignore + moveItem = true; + } + } + else { // drop on a blank area + moveItem = true; + } + } + } + if(moveItem) { + e->accept(); + } + else { + auto delegate = static_cast(listView_->itemDelegateForColumn(0)); + auto grid = delegate->itemSize(); + Fm::FolderView::childDropEvent(e); + // position dropped items successively, starting with the drop rectangle + if(mimeData->hasUrls() + && (e->dropAction() == Qt::CopyAction + || e->dropAction() == Qt::MoveAction + || e->dropAction() == Qt::LinkAction)) { + QList urlList = mimeData->urls(); + for(int i = 0; i < urlList.count(); ++i) { + std::string name = urlList.at(i).fileName().toUtf8().constData(); + if(!name.empty()) { // respect the positions of existing files + QString desktopDir = XdgDir::readDesktopDir() + QString(QLatin1String("/")); + if(!QFile::exists(desktopDir + QString::fromStdString(name))) { + QRect workArea = qApp->desktop()->availableGeometry(screenNum_); + workArea.adjust(12, 12, -12, -12); + QPoint pos = mapFromGlobal(e->pos()); + alignToGrid(pos, workArea.topLeft(), grid, listView_->spacing()); + if(i > 0) + pos.setY(pos.y() + grid.height() + listView_->spacing()); + if(pos.y() + grid.height() > workArea.bottom() + 1) { + pos.setX(pos.x() + grid.width() + listView_->spacing()); + pos.setY(workArea.top()); + } + customItemPos_[name] = pos; + } + } + } + saveItemPositions(); + } + } +} + +void DesktopWindow::alignToGrid(QPoint& pos, const QPoint& topLeft, const QSize& grid, const int spacing) { + qreal w = qAbs((qreal)pos.x() - (qreal)topLeft.x()) + / (qreal)(grid.width() + spacing); + qreal h = qAbs(pos.y() - (qreal)topLeft.y()) + / (qreal)(grid.height() + spacing); + pos.setX(topLeft.x() + qRound(w) * (grid.width() + spacing)); + pos.setY(topLeft.y() + qRound(h) * (grid.height() + spacing)); +} + +void DesktopWindow::closeEvent(QCloseEvent* event) { + // prevent the desktop window from being closed. + event->ignore(); +} + +void DesktopWindow::paintEvent(QPaintEvent *event) { + paintBackground(event); + QWidget::paintEvent(event); } void DesktopWindow::setScreenNum(int num) { - if(screenNum_ != num) { - screenNum_ = num; - queueRelayout(); - } + if(screenNum_ != num) { + screenNum_ = num; + queueRelayout(); + } } } // namespace PCManFM diff --git a/pcmanfm/desktopwindow.h b/pcmanfm/desktopwindow.h index cfa29d5..fce9f63 100644 --- a/pcmanfm/desktopwindow.h +++ b/pcmanfm/desktopwindow.h @@ -23,124 +23,138 @@ #include "view.h" #include "launcher.h" +#include +#include + #include #include #include #include -#include +#include namespace Fm { - class CachedFolderModel; - class ProxyFolderModel; - class FolderViewListView; +class CachedFolderModel; +class ProxyFolderModel; +class FolderViewListView; } namespace PCManFM { -class DesktopItemDelegate; class Settings; class DesktopWindow : public View { -Q_OBJECT + Q_OBJECT public: - friend class Application; - - enum WallpaperMode { - WallpaperNone, - WallpaperStretch, - WallpaperFit, - WallpaperCenter, - WallpaperTile, - WallpaperZoom - }; - - explicit DesktopWindow(int screenNum); - virtual ~DesktopWindow(); - - void setForeground(const QColor& color); - void setShadow(const QColor& color); - void setBackground(const QColor& color); - void setDesktopFolder(); - void setWallpaperFile(QString filename); - void setWallpaperMode(WallpaperMode mode = WallpaperStretch); - - // void setWallpaperAlpha(qreal alpha); - void updateWallpaper(); - void updateFromSettings(Settings& settings); - - void queueRelayout(int delay = 0); - - int screenNum() const { - return screenNum_; - } - - void setScreenNum(int num); + friend class Application; + + enum WallpaperMode { + WallpaperNone, + WallpaperStretch, + WallpaperFit, + WallpaperCenter, + WallpaperTile, + WallpaperZoom + }; + + explicit DesktopWindow(int screenNum); + virtual ~DesktopWindow(); + + void setForeground(const QColor& color); + void setShadow(const QColor& color); + void setBackground(const QColor& color); + void setDesktopFolder(); + void setWallpaperFile(QString filename); + void setWallpaperMode(WallpaperMode mode = WallpaperStretch); + void setLastSlide(QString filename); + void setWallpaperDir(QString dirname); + void setSlideShowInterval(int interval); + void setWallpaperRandomize(bool randomize); + + // void setWallpaperAlpha(qreal alpha); + void updateWallpaper(); + bool pickWallpaper(); + void nextWallpaper(); + void updateFromSettings(Settings& settings, bool changeSlide = true); + + void queueRelayout(int delay = 0); + + int screenNum() const { + return screenNum_; + } + + void setScreenNum(int num); protected: - virtual void prepareFolderMenu(Fm::FolderMenu* menu); - virtual void prepareFileMenu(Fm::FileMenu* menu); - virtual void resizeEvent(QResizeEvent* event); - virtual void onFileClicked(int type, FmFileInfo* fileInfo); + virtual void prepareFolderMenu(Fm::FolderMenu* menu) override; + virtual void prepareFileMenu(Fm::FileMenu* menu) override; + virtual void resizeEvent(QResizeEvent* event) override; + virtual void onFileClicked(int type, const std::shared_ptr& fileInfo) override; - void loadItemPositions(); - void saveItemPositions(); + void loadItemPositions(); + void saveItemPositions(); - QImage loadWallpaperFile(QSize requiredSize); + QImage loadWallpaperFile(QSize requiredSize); - virtual bool event(QEvent* event); - virtual bool eventFilter(QObject * watched, QEvent * event); + virtual bool event(QEvent* event) override; + virtual bool eventFilter(QObject* watched, QEvent* event) override; - virtual void childDropEvent(QDropEvent* e); - virtual void closeEvent(QCloseEvent *event); + virtual void childDropEvent(QDropEvent* e) override; + virtual void closeEvent(QCloseEvent* event) override; + virtual void paintEvent(QPaintEvent *event) override; protected Q_SLOTS: - void onOpenDirRequested(FmPath* path, int target); - void onDesktopPreferences(); + void onOpenDirRequested(const Fm::FilePath& path, int target); + void onDesktopPreferences(); - void onRowsAboutToBeRemoved(const QModelIndex& parent, int start, int end); - void onRowsInserted(const QModelIndex& parent, int start, int end); - void onLayoutChanged(); - void onModelSortFilterChanged(); - void onIndexesMoved(const QModelIndexList& indexes); - void onDataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight); + void onRowsAboutToBeRemoved(const QModelIndex& parent, int start, int end); + void onRowsInserted(const QModelIndex& parent, int start, int end); + void onLayoutChanged(); + void onModelSortFilterChanged(); + void onIndexesMoved(const QModelIndexList& indexes); + void onDataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight); - void relayoutItems(); - void onStickToCurrentPos(bool toggled); + void relayoutItems(); + void onStickToCurrentPos(bool toggled); - // void updateWorkArea(); + // void updateWorkArea(); - // file operations - void onCutActivated(); - void onCopyActivated(); - void onPasteActivated(); - void onRenameActivated(); - void onDeleteActivated(); - void onFilePropertiesActivated(); + // file operations + void onCutActivated(); + void onCopyActivated(); + void onPasteActivated(); + void onRenameActivated(); + void onDeleteActivated(); + void onFilePropertiesActivated(); private: - void removeBottomGap(); - void paintBackground(QPaintEvent* event); + void removeBottomGap(); + void paintBackground(QPaintEvent* event); + static void alignToGrid(QPoint& pos, const QPoint& topLeft, const QSize& grid, const int spacing); private: - Fm::ProxyFolderModel* proxyModel_; - Fm::CachedFolderModel* model_; - Fm::Folder folder_; - Fm::FolderViewListView* listView_; - - QColor fgColor_; - QColor bgColor_; - QColor shadowColor_; - QString wallpaperFile_; - WallpaperMode wallpaperMode_; - QPixmap wallpaperPixmap_; - DesktopItemDelegate* delegate_; - Launcher fileLauncher_; - bool showWmMenu_; - - int screenNum_; - QHash customItemPos_; - QHash displayNames_; // only for desktop entries and shortcuts - QTimer* relayoutTimer_; + Fm::ProxyFolderModel* proxyModel_; + Fm::CachedFolderModel* model_; + std::shared_ptr folder_; + Fm::FolderViewListView* listView_; + + QColor fgColor_; + QColor bgColor_; + QColor shadowColor_; + QString wallpaperFile_; + WallpaperMode wallpaperMode_; + QString lastSlide_; + QString wallpaperDir_; + int slideShowInterval_; + QTimer* wallpaperTimer_; + bool wallpaperRandomize_; + QPixmap wallpaperPixmap_; + Launcher fileLauncher_; + bool showWmMenu_; + + int screenNum_; + std::unordered_map customItemPos_; + QHash displayNames_; // only for desktop entries and shortcuts + QTimer* relayoutTimer_; }; } diff --git a/pcmanfm/file-search.ui b/pcmanfm/file-search.ui deleted file mode 100644 index 20dc03c..0000000 --- a/pcmanfm/file-search.ui +++ /dev/null @@ -1,517 +0,0 @@ - - - FindFilesDialog - - - - 0 - 0 - 431 - 416 - - - - Find Files - - - - - - 0 - - - - Name/Location - - - - - - File name patterns - - - - - - Pattern: - - - - - - - - - - Case insensitive - - - - - - - Use regular expression - - - - - - - - - - Places to search - - - - - - - - - - - - - Add - - - - - - - - - - - - Remove - - - - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - - - Search in sub directories - - - - - - - Search hidden files - - - - - - - - - - - File Type - - - - - - File Type - - - - - - Only search for files of following types: - - - - - - - Text files - - - - - - - Image files - - - - - - - Audio files - - - - - - - Video files - - - - - - - Documents - - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - Content - - - - - - File contains - - - - - - - - - Case insensitive - - - - - - - Use regular expression - - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - Properties - - - - - - File Size - - - - - - Bigger than: - - - - - - - - - false - - - - - - - false - - - - - - - - - Smaller than: - - - - - - - - - false - - - - - - - false - - - - - - - - - - - - Last Modified Time - - - - - - Earlier than: - - - - - - - false - - - true - - - - - - - Later than: - - - - - - - false - - - true - - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - - - buttonBox - accepted() - FindFilesDialog - accept() - - - 222 - 344 - - - 157 - 274 - - - - - buttonBox - rejected() - FindFilesDialog - reject() - - - 290 - 350 - - - 286 - 274 - - - - - checkBox_14 - toggled(bool) - dateTimeEdit - setEnabled(bool) - - - 129 - 166 - - - 294 - 170 - - - - - checkBox_15 - toggled(bool) - dateTimeEdit_2 - setEnabled(bool) - - - 91 - 188 - - - 302 - 195 - - - - - checkBox_12 - toggled(bool) - spinBox - setEnabled(bool) - - - 102 - 73 - - - 184 - 77 - - - - - checkBox_12 - toggled(bool) - comboBox - setEnabled(bool) - - - 49 - 72 - - - 357 - 76 - - - - - checkBox_13 - toggled(bool) - spinBox_2 - setEnabled(bool) - - - 123 - 101 - - - 186 - 104 - - - - - checkBox_13 - toggled(bool) - comboBox_2 - setEnabled(bool) - - - 53 - 98 - - - 339 - 108 - - - - - diff --git a/pcmanfm/launcher.cpp b/pcmanfm/launcher.cpp index 4d6e862..113547e 100644 --- a/pcmanfm/launcher.cpp +++ b/pcmanfm/launcher.cpp @@ -21,15 +21,16 @@ #include "launcher.h" #include "mainwindow.h" #include "application.h" +#include namespace PCManFM { Launcher::Launcher(PCManFM::MainWindow* mainWindow): - Fm::FileLauncher(), - mainWindow_(mainWindow) { + Fm::FileLauncher(), + mainWindow_(mainWindow) { - Application* app = static_cast(qApp); - setQuickExec(app->settings().quickExec()); + Application* app = static_cast(qApp); + setQuickExec(app->settings().quickExec()); } Launcher::~Launcher() { @@ -37,28 +38,31 @@ Launcher::~Launcher() { } bool Launcher::openFolder(GAppLaunchContext* ctx, GList* folder_infos, GError** err) { - GList* l = folder_infos; - Fm::FileInfo fi = FM_FILE_INFO(l->data); - Application* app = static_cast(qApp); - MainWindow* mainWindow = mainWindow_; - if(!mainWindow) { - mainWindow = new MainWindow(fi.getPath()); - mainWindow->resize(app->settings().windowWidth(), app->settings().windowHeight()); + GList* l = folder_infos; + FmFileInfo* fi = FM_FILE_INFO(l->data); + Application* app = static_cast(qApp); + MainWindow* mainWindow = mainWindow_; + Fm::FilePath path{fm_path_to_gfile(fm_file_info_get_path(fi)), false}; + if(!mainWindow) { + mainWindow = new MainWindow(std::move(path)); + mainWindow->resize(app->settings().windowWidth(), app->settings().windowHeight()); - if(app->settings().windowMaximized()) { - mainWindow->setWindowState(mainWindow->windowState() | Qt::WindowMaximized); + if(app->settings().windowMaximized()) { + mainWindow->setWindowState(mainWindow->windowState() | Qt::WindowMaximized); + } } - } - else - mainWindow->chdir(fi.getPath()); - l = l->next; - for(; l; l = l->next) { - fi = FM_FILE_INFO(l->data); - mainWindow->addTab(fi.getPath()); - } - mainWindow->show(); - mainWindow->raise(); - return true; + else { + mainWindow->chdir(std::move(path)); + } + l = l->next; + for(; l; l = l->next) { + fi = FM_FILE_INFO(l->data); + path = Fm::FilePath{fm_path_to_gfile(fm_file_info_get_path(fi)), false}; + mainWindow->addTab(std::move(path)); + } + mainWindow->show(); + mainWindow->raise(); + return true; } } //namespace PCManFM diff --git a/pcmanfm/launcher.h b/pcmanfm/launcher.h index f29ce9d..0e158d2 100644 --- a/pcmanfm/launcher.h +++ b/pcmanfm/launcher.h @@ -29,14 +29,14 @@ class MainWindow; class Launcher : public Fm::FileLauncher { public: - Launcher(MainWindow* mainWindow = NULL); - ~Launcher(); + Launcher(MainWindow* mainWindow = nullptr); + ~Launcher(); protected: - virtual bool openFolder(GAppLaunchContext* ctx, GList* folder_infos, GError** err); + virtual bool openFolder(GAppLaunchContext* ctx, GList* folder_infos, GError** err); private: - MainWindow* mainWindow_; + MainWindow* mainWindow_; }; } diff --git a/pcmanfm/main-win.ui b/pcmanfm/main-win.ui index 145c6d8..fd1ee0e 100644 --- a/pcmanfm/main-win.ui +++ b/pcmanfm/main-win.ui @@ -197,7 +197,7 @@ - + &Edit @@ -245,14 +245,14 @@ - + - + Qt::PreventContextMenu @@ -836,6 +836,12 @@
tabbar.h
1 + + PCManFM::StatusBar + QStatusBar +
statusbar.h
+ 1 +
Fm::SidePane QWidget diff --git a/pcmanfm/mainwindow.cpp b/pcmanfm/mainwindow.cpp index f4c144a..e088feb 100644 --- a/pcmanfm/mainwindow.cpp +++ b/pcmanfm/mainwindow.cpp @@ -29,8 +29,8 @@ #include #include #include -#include #include +#include #include #include "tabpage.h" @@ -42,9 +42,7 @@ #include #include #include -#include -#include -#include +#include #include "ui_about.h" #include "application.h" @@ -55,1275 +53,1369 @@ namespace PCManFM { // static MainWindow* MainWindow::lastActive_ = nullptr; -MainWindow::MainWindow(Path path): - QMainWindow(), - pathEntry_(nullptr), - pathBar_(nullptr), - fileLauncher_(this), - rightClickIndex_(-1), - updatingViewMenu_(false) { - - Settings& settings = static_cast(qApp)->settings(); - setAttribute(Qt::WA_DeleteOnClose); - // setup user interface - ui.setupUi(this); - - // hide menu items that are not usable - //if(!uriExists("computer:///")) - // ui.actionComputer->setVisible(false); - if(!settings.supportTrash()) - ui.actionTrash->setVisible(false); - - // FIXME: add an option to hide network:/// - // We cannot use uriExists() here since calling this on "network:///" - // is very slow and blocking. - //if(!uriExists("network:///")) - // ui.actionNetwork->setVisible(false); - - // add a context menu for showing browse history to back and forward buttons - QToolButton* forwardButton = static_cast(ui.toolBar->widgetForAction(ui.actionGoForward)); - forwardButton->setContextMenuPolicy(Qt::CustomContextMenu); - connect(forwardButton, &QToolButton::customContextMenuRequested, this, &MainWindow::onBackForwardContextMenu); - QToolButton* backButton = static_cast(ui.toolBar->widgetForAction(ui.actionGoBack)); - backButton->setContextMenuPolicy(Qt::CustomContextMenu); - connect(backButton, &QToolButton::customContextMenuRequested, this, &MainWindow::onBackForwardContextMenu); - - // tabbed browsing interface - ui.tabBar->setDocumentMode(true); - ui.tabBar->setTabsClosable(true); - ui.tabBar->setElideMode(Qt::ElideRight); - ui.tabBar->setExpanding(false); - ui.tabBar->setMovable(true); // reorder the tabs by dragging - if(!settings.fullWidthTabBar()) { - ui.verticalLayout->removeWidget(ui.tabBar); - ui.verticalLayout_2->insertWidget(0, ui.tabBar); - } +MainWindow::MainWindow(Fm::FilePath path): + QMainWindow(), + pathEntry_(nullptr), + pathBar_(nullptr), + fileLauncher_(this), + rightClickIndex_(-1), + updatingViewMenu_(false), + bookmarks_{Fm::Bookmarks::globalInstance()} { + + Settings& settings = static_cast(qApp)->settings(); + setAttribute(Qt::WA_DeleteOnClose); + // setup user interface + ui.setupUi(this); + + // hide menu items that are not usable + //if(!uriExists("computer:///")) + // ui.actionComputer->setVisible(false); + if(!settings.supportTrash()) { + ui.actionTrash->setVisible(false); + } + + // FIXME: add an option to hide network:/// + // We cannot use uriExists() here since calling this on "network:///" + // is very slow and blocking. + //if(!uriExists("network:///")) + // ui.actionNetwork->setVisible(false); + + // add a context menu for showing browse history to back and forward buttons + QToolButton* forwardButton = static_cast(ui.toolBar->widgetForAction(ui.actionGoForward)); + forwardButton->setContextMenuPolicy(Qt::CustomContextMenu); + connect(forwardButton, &QToolButton::customContextMenuRequested, this, &MainWindow::onBackForwardContextMenu); + QToolButton* backButton = static_cast(ui.toolBar->widgetForAction(ui.actionGoBack)); + backButton->setContextMenuPolicy(Qt::CustomContextMenu); + connect(backButton, &QToolButton::customContextMenuRequested, this, &MainWindow::onBackForwardContextMenu); + + // tabbed browsing interface + ui.tabBar->setDocumentMode(true); + ui.tabBar->setTabsClosable(true); + ui.tabBar->setElideMode(Qt::ElideRight); + ui.tabBar->setExpanding(false); + ui.tabBar->setMovable(true); // reorder the tabs by dragging + if(!settings.fullWidthTabBar()) { + ui.verticalLayout->removeWidget(ui.tabBar); + ui.verticalLayout_2->insertWidget(0, ui.tabBar); + } #if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0) - // switch to the tab under the cursor during dnd. - ui.tabBar->setChangeCurrentOnDrag(true); - ui.tabBar->setAcceptDrops(true); + // switch to the tab under the cursor during dnd. + ui.tabBar->setChangeCurrentOnDrag(true); + ui.tabBar->setAcceptDrops(true); #endif - ui.tabBar->setContextMenuPolicy(Qt::CustomContextMenu); - connect(ui.actionCloseRight, &QAction::triggered, this, &MainWindow::closeRightTabs); - connect(ui.actionCloseLeft, &QAction::triggered, this, &MainWindow::closeLeftTabs); - connect(ui.actionCloseOther, &QAction::triggered, this, &MainWindow::closeOtherTabs); - - connect(ui.tabBar, &QTabBar::currentChanged, this, &MainWindow::onTabBarCurrentChanged); - connect(ui.tabBar, &QTabBar::tabCloseRequested, this, &MainWindow::onTabBarCloseRequested); - connect(ui.tabBar, &QTabBar::tabMoved, this, &MainWindow::onTabBarTabMoved); - connect(ui.tabBar, &QTabBar::customContextMenuRequested, this, &MainWindow::tabContextMenu); - connect(ui.stackedWidget, &QStackedWidget::widgetRemoved, this, &MainWindow::onStackedWidgetWidgetRemoved); - - // FIXME: should we make the filter bar a per-view configuration? - ui.filterBar->setVisible(settings.showFilter()); - ui.actionFilter->setChecked(settings.showFilter()); - connect(ui.filterBar, &QLineEdit::textChanged, this, &MainWindow::onFilterStringChanged); - - // side pane - ui.sidePane->setIconSize(QSize(settings.sidePaneIconSize(), settings.sidePaneIconSize())); - ui.sidePane->setMode(settings.sidePaneMode()); - connect(ui.sidePane, &Fm::SidePane::chdirRequested, this, &MainWindow::onSidePaneChdirRequested); - connect(ui.sidePane, &Fm::SidePane::openFolderInNewWindowRequested, this, &MainWindow::onSidePaneOpenFolderInNewWindowRequested); - connect(ui.sidePane, &Fm::SidePane::openFolderInNewTabRequested, this, &MainWindow::onSidePaneOpenFolderInNewTabRequested); - connect(ui.sidePane, &Fm::SidePane::openFolderInTerminalRequested, this, &MainWindow::onSidePaneOpenFolderInTerminalRequested); - connect(ui.sidePane, &Fm::SidePane::createNewFolderRequested, this, &MainWindow::onSidePaneCreateNewFolderRequested); - connect(ui.sidePane, &Fm::SidePane::modeChanged, this, &MainWindow::onSidePaneModeChanged); - - // detect change of splitter position - connect(ui.splitter, &QSplitter::splitterMoved, this, &MainWindow::onSplitterMoved); - - // path bar - createPathBar(settings.pathBarButtons()); - if(settings.pathBarButtons()) - ui.actionPathButtons->setChecked(true); - else - ui.actionLocationBar->setChecked(true); - - // add filesystem info to status bar - fsInfoLabel_ = new QLabel(ui.statusbar); - ui.statusbar->addPermanentWidget(fsInfoLabel_); - - // setup the splitter - ui.splitter->setStretchFactor(1, 1); // only the right pane can be stretched - QList sizes; - sizes.append(settings.splitterPos()); - sizes.append(300); - ui.splitter->setSizes(sizes); - - // load bookmark menu - bookmarks_ = Fm::Bookmarks::dup(); - g_signal_connect(bookmarks_, "changed", G_CALLBACK(onBookmarksChanged), this); - loadBookmarksMenu(); - - // Fix the menu groups which is not done by Qt designer - // To my suprise, this was supported in Qt designer 3 :-( - QActionGroup* group = new QActionGroup(ui.menu_View); - group->setExclusive(true); - group->addAction(ui.actionIconView); - group->addAction(ui.actionCompactView); - group->addAction(ui.actionThumbnailView); - group->addAction(ui.actionDetailedList); - - group = new QActionGroup(ui.menuSorting); - group->setExclusive(true); - group->addAction(ui.actionByFileName); - group->addAction(ui.actionByMTime); - group->addAction(ui.actionByFileSize); - group->addAction(ui.actionByFileType); - group->addAction(ui.actionByOwner); - - group = new QActionGroup(ui.menuSorting); - group->setExclusive(true); - group->addAction(ui.actionAscending); - group->addAction(ui.actionDescending); - - group = new QActionGroup(ui.menuPathBarStyle); - group->setExclusive(true); - group->addAction(ui.actionLocationBar); - group->addAction(ui.actionPathButtons); - - // Add menubar actions to the main window this is necessary so that actions - // shortcuts are still working when the menubar is hidden. - addActions(ui.menubar->actions()); - - // Show or hide the menu bar - QMenu *menu = new QMenu(ui.toolBar); - menu->addMenu(ui.menu_File); - menu->addMenu(ui.menu_Editw); - menu->addMenu(ui.menu_View); - menu->addMenu(ui.menu_Go); - menu->addMenu(ui.menu_Bookmarks); - menu->addMenu(ui.menu_Tool); - menu->addMenu(ui.menu_Help); - ui.actionMenu->setMenu(menu); - if(ui.actionMenu->icon().isNull()) - ui.actionMenu->setIcon(QIcon::fromTheme("applications-system")); - QToolButton* menuBtn = static_cast(ui.toolBar->widgetForAction(ui.actionMenu)); - menuBtn->setPopupMode(QToolButton::InstantPopup); - - menuSep_ = ui.toolBar->insertSeparator(ui.actionMenu); - menuSep_->setVisible(!settings.showMenuBar()); - ui.actionMenu->setVisible(!settings.showMenuBar()); - ui.menubar->setVisible(settings.showMenuBar()); - ui.actionMenu_bar->setChecked(settings.showMenuBar()); - connect(ui.actionMenu_bar, &QAction::triggered, this, &MainWindow::toggleMenuBar); - - // create shortcuts - QShortcut* shortcut; - shortcut = new QShortcut(QKeySequence(Qt::Key_Escape), this); - connect(shortcut, &QShortcut::activated, this, &MainWindow::onResetFocus); - - shortcut = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_L), this); - connect(shortcut, &QShortcut::activated, this, &MainWindow::focusPathEntry); - - shortcut = new QShortcut(Qt::ALT + Qt::Key_D, this); - connect(shortcut, &QShortcut::activated, this, &MainWindow::focusPathEntry); - - shortcut = new QShortcut(Qt::CTRL + Qt::Key_Tab, this); - connect(shortcut, &QShortcut::activated, this, &MainWindow::onShortcutNextTab); - - shortcut = new QShortcut(Qt::CTRL + Qt::SHIFT + Qt::Key_Tab, this); - connect(shortcut, &QShortcut::activated, this, &MainWindow::onShortcutPrevTab); - - // Add Ctrl+PgUp and Ctrl+PgDown as well, because they are common in Firefox - // , Opera, Google Chromium/Google Chrome and most other tab-using - // applications. - shortcut = new QShortcut(Qt::CTRL + Qt::Key_PageDown, this); - connect(shortcut, &QShortcut::activated, this, &MainWindow::onShortcutNextTab); - - shortcut = new QShortcut(Qt::CTRL + Qt::Key_PageUp, this); - connect(shortcut, &QShortcut::activated, this, &MainWindow::onShortcutPrevTab); - - int i; - for(i = 0; i < 10; ++i) { - shortcut = new QShortcut(QKeySequence(Qt::ALT + Qt::Key_0 + i), this); - connect(shortcut, &QShortcut::activated, this, &MainWindow::onShortcutJumpToTab); - - shortcut = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_0 + i), this); - connect(shortcut, &QShortcut::activated, this, &MainWindow::onShortcutJumpToTab); - } - - shortcut = new QShortcut(QKeySequence(Qt::Key_Backspace), this); - connect(shortcut, &QShortcut::activated, this, &MainWindow::on_actionGoUp_triggered); - - shortcut = new QShortcut(QKeySequence(Qt::SHIFT + Qt::Key_Delete), this); - connect(shortcut, &QShortcut::activated, this, &MainWindow::on_actionDelete_triggered); - - shortcut = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_I), this); - connect(shortcut, &QShortcut::activated, this, &MainWindow::focusFilterBar); - - // in addition to F3, for convenience - shortcut = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_F), this); - connect(shortcut, &QShortcut::activated, ui.actionFindFiles, &QAction::trigger); - - if(QToolButton* clearButton = ui.filterBar->findChild()) { - clearButton->setToolTip(tr("Clear text (Ctrl+K)")); - shortcut = new QShortcut(Qt::CTRL + Qt::Key_K, this); - connect(shortcut, &QShortcut::activated, ui.filterBar, &QLineEdit::clear); - } - - if(!path.isNull()) - addTab(path); + ui.tabBar->setContextMenuPolicy(Qt::CustomContextMenu); + connect(ui.actionCloseRight, &QAction::triggered, this, &MainWindow::closeRightTabs); + connect(ui.actionCloseLeft, &QAction::triggered, this, &MainWindow::closeLeftTabs); + connect(ui.actionCloseOther, &QAction::triggered, this, &MainWindow::closeOtherTabs); + + connect(ui.tabBar, &QTabBar::currentChanged, this, &MainWindow::onTabBarCurrentChanged); + connect(ui.tabBar, &QTabBar::tabCloseRequested, this, &MainWindow::onTabBarCloseRequested); + connect(ui.tabBar, &QTabBar::tabMoved, this, &MainWindow::onTabBarTabMoved); + connect(ui.tabBar, &QTabBar::customContextMenuRequested, this, &MainWindow::tabContextMenu); + connect(ui.stackedWidget, &QStackedWidget::widgetRemoved, this, &MainWindow::onStackedWidgetWidgetRemoved); + + // FIXME: should we make the filter bar a per-view configuration? + ui.filterBar->setVisible(settings.showFilter()); + ui.actionFilter->setChecked(settings.showFilter()); + connect(ui.filterBar, &QLineEdit::textChanged, this, &MainWindow::onFilterStringChanged); + + // side pane + ui.sidePane->setIconSize(QSize(settings.sidePaneIconSize(), settings.sidePaneIconSize())); + ui.sidePane->setMode(settings.sidePaneMode()); + connect(ui.sidePane, &Fm::SidePane::chdirRequested, this, &MainWindow::onSidePaneChdirRequested); + connect(ui.sidePane, &Fm::SidePane::openFolderInNewWindowRequested, this, &MainWindow::onSidePaneOpenFolderInNewWindowRequested); + connect(ui.sidePane, &Fm::SidePane::openFolderInNewTabRequested, this, &MainWindow::onSidePaneOpenFolderInNewTabRequested); + connect(ui.sidePane, &Fm::SidePane::openFolderInTerminalRequested, this, &MainWindow::onSidePaneOpenFolderInTerminalRequested); + connect(ui.sidePane, &Fm::SidePane::createNewFolderRequested, this, &MainWindow::onSidePaneCreateNewFolderRequested); + connect(ui.sidePane, &Fm::SidePane::modeChanged, this, &MainWindow::onSidePaneModeChanged); + + // detect change of splitter position + connect(ui.splitter, &QSplitter::splitterMoved, this, &MainWindow::onSplitterMoved); + + // path bar + createPathBar(settings.pathBarButtons()); + if(settings.pathBarButtons()) { + ui.actionPathButtons->setChecked(true); + } + else { + ui.actionLocationBar->setChecked(true); + } + + // add filesystem info to status bar + fsInfoLabel_ = new QLabel(ui.statusbar); + ui.statusbar->addPermanentWidget(fsInfoLabel_); + + // setup the splitter + ui.splitter->setStretchFactor(1, 1); // only the right pane can be stretched + QList sizes; + sizes.append(settings.splitterPos()); + sizes.append(300); + ui.splitter->setSizes(sizes); + + // load bookmark menu + connect(bookmarks_.get(), &Fm::Bookmarks::changed, this, &MainWindow::onBookmarksChanged); + loadBookmarksMenu(); + + // Fix the menu groups which is not done by Qt designer + // To my suprise, this was supported in Qt designer 3 :-( + QActionGroup* group = new QActionGroup(ui.menu_View); + group->setExclusive(true); + group->addAction(ui.actionIconView); + group->addAction(ui.actionCompactView); + group->addAction(ui.actionThumbnailView); + group->addAction(ui.actionDetailedList); + + group = new QActionGroup(ui.menuSorting); + group->setExclusive(true); + group->addAction(ui.actionByFileName); + group->addAction(ui.actionByMTime); + group->addAction(ui.actionByFileSize); + group->addAction(ui.actionByFileType); + group->addAction(ui.actionByOwner); + + group = new QActionGroup(ui.menuSorting); + group->setExclusive(true); + group->addAction(ui.actionAscending); + group->addAction(ui.actionDescending); + + group = new QActionGroup(ui.menuPathBarStyle); + group->setExclusive(true); + group->addAction(ui.actionLocationBar); + group->addAction(ui.actionPathButtons); + + // Add menubar actions to the main window this is necessary so that actions + // shortcuts are still working when the menubar is hidden. + addActions(ui.menubar->actions()); + + // Show or hide the menu bar + QMenu* menu = new QMenu(ui.toolBar); + menu->addMenu(ui.menu_File); + menu->addMenu(ui.menu_Edit); + menu->addMenu(ui.menu_View); + menu->addMenu(ui.menu_Go); + menu->addMenu(ui.menu_Bookmarks); + menu->addMenu(ui.menu_Tool); + menu->addMenu(ui.menu_Help); + ui.actionMenu->setMenu(menu); + if(ui.actionMenu->icon().isNull()) { + ui.actionMenu->setIcon(QIcon::fromTheme("applications-system")); + } + QToolButton* menuBtn = static_cast(ui.toolBar->widgetForAction(ui.actionMenu)); + menuBtn->setPopupMode(QToolButton::InstantPopup); + + menuSep_ = ui.toolBar->insertSeparator(ui.actionMenu); + menuSep_->setVisible(!settings.showMenuBar()); + ui.actionMenu->setVisible(!settings.showMenuBar()); + ui.menubar->setVisible(settings.showMenuBar()); + ui.actionMenu_bar->setChecked(settings.showMenuBar()); + connect(ui.actionMenu_bar, &QAction::triggered, this, &MainWindow::toggleMenuBar); + + // create shortcuts + QShortcut* shortcut; + shortcut = new QShortcut(QKeySequence(Qt::Key_Escape), this); + connect(shortcut, &QShortcut::activated, this, &MainWindow::onResetFocus); - // size from settings - if(settings.rememberWindowSize()) { - resize(settings.windowWidth(), settings.windowHeight()); - if(settings.windowMaximized()) - setWindowState(windowState() | Qt::WindowMaximized); - } + shortcut = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_L), this); + connect(shortcut, &QShortcut::activated, this, &MainWindow::focusPathEntry); + + shortcut = new QShortcut(Qt::ALT + Qt::Key_D, this); + connect(shortcut, &QShortcut::activated, this, &MainWindow::focusPathEntry); + + shortcut = new QShortcut(Qt::CTRL + Qt::Key_Tab, this); + connect(shortcut, &QShortcut::activated, this, &MainWindow::onShortcutNextTab); + + shortcut = new QShortcut(Qt::CTRL + Qt::SHIFT + Qt::Key_Tab, this); + connect(shortcut, &QShortcut::activated, this, &MainWindow::onShortcutPrevTab); + + // Add Ctrl+PgUp and Ctrl+PgDown as well, because they are common in Firefox + // , Opera, Google Chromium/Google Chrome and most other tab-using + // applications. + shortcut = new QShortcut(Qt::CTRL + Qt::Key_PageDown, this); + connect(shortcut, &QShortcut::activated, this, &MainWindow::onShortcutNextTab); + + shortcut = new QShortcut(Qt::CTRL + Qt::Key_PageUp, this); + connect(shortcut, &QShortcut::activated, this, &MainWindow::onShortcutPrevTab); + + int i; + for(i = 0; i < 10; ++i) { + shortcut = new QShortcut(QKeySequence(Qt::ALT + Qt::Key_0 + i), this); + connect(shortcut, &QShortcut::activated, this, &MainWindow::onShortcutJumpToTab); + + shortcut = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_0 + i), this); + connect(shortcut, &QShortcut::activated, this, &MainWindow::onShortcutJumpToTab); + } + + shortcut = new QShortcut(QKeySequence(Qt::Key_Backspace), this); + connect(shortcut, &QShortcut::activated, this, &MainWindow::on_actionGoUp_triggered); + + shortcut = new QShortcut(QKeySequence(Qt::SHIFT + Qt::Key_Delete), this); + connect(shortcut, &QShortcut::activated, this, &MainWindow::on_actionDelete_triggered); + + shortcut = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_I), this); + connect(shortcut, &QShortcut::activated, this, &MainWindow::focusFilterBar); + + // in addition to F3, for convenience + shortcut = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_F), this); + connect(shortcut, &QShortcut::activated, ui.actionFindFiles, &QAction::trigger); + + if(QToolButton* clearButton = ui.filterBar->findChild()) { + clearButton->setToolTip(tr("Clear text (Ctrl+K)")); + shortcut = new QShortcut(Qt::CTRL + Qt::Key_K, this); + connect(shortcut, &QShortcut::activated, ui.filterBar, &QLineEdit::clear); + } - if(QApplication::layoutDirection() == Qt::RightToLeft) - setRTLIcons(true); + if(path) { + addTab(path); + } + + // size from settings + if(settings.rememberWindowSize()) { + resize(settings.windowWidth(), settings.windowHeight()); + if(settings.windowMaximized()) { + setWindowState(windowState() | Qt::WindowMaximized); + } + } + + if(QApplication::layoutDirection() == Qt::RightToLeft) { + setRTLIcons(true); + } } MainWindow::~MainWindow() { - if(!bookmarks_.isNull()) { - g_signal_handlers_disconnect_by_func(bookmarks_, (gpointer)G_CALLBACK(onBookmarksChanged), this); - } } -void MainWindow::chdir(Path path) { - TabPage* page = currentPage(); - - if(page) { - ui.filterBar->clear(); - page->chdir(path, true); - updateUIForCurrentPage(); - } +void MainWindow::chdir(Fm::FilePath path) { + TabPage* page = currentPage(); + if(page) { + ui.filterBar->clear(); + page->chdir(path, true); + updateUIForCurrentPage(); + } } void MainWindow::createPathBar(bool usePathButtons) { - QWidget* bar; - if(usePathButtons) { - bar = pathBar_ = new Fm::PathBar(this); - connect(pathBar_, &Fm::PathBar::chdir, this, &MainWindow::onPathBarChdir); - connect(pathBar_, &Fm::PathBar::middleClickChdir, this, &MainWindow::onPathBarMiddleClickChdir); - connect(pathBar_, &Fm::PathBar::editingFinished, this, &MainWindow::onResetFocus); - } - else { - bar = pathEntry_ = new Fm::PathEdit(this); - connect(pathEntry_, &Fm::PathEdit::returnPressed, this, &MainWindow::onPathEntryReturnPressed); - connect(pathEntry_, &QLineEdit::textEdited, this, &MainWindow::onPathEntryEdited); - } - ui.toolBar->insertWidget(ui.actionGo, bar); - ui.actionGo->setVisible(!usePathButtons); + QWidget* bar; + if(usePathButtons) { + bar = pathBar_ = new Fm::PathBar(this); + connect(pathBar_, &Fm::PathBar::chdir, this, &MainWindow::onPathBarChdir); + connect(pathBar_, &Fm::PathBar::middleClickChdir, this, &MainWindow::onPathBarMiddleClickChdir); + connect(pathBar_, &Fm::PathBar::editingFinished, this, &MainWindow::onResetFocus); + } + else { + bar = pathEntry_ = new Fm::PathEdit(this); + connect(pathEntry_, &Fm::PathEdit::returnPressed, this, &MainWindow::onPathEntryReturnPressed); + } + ui.toolBar->insertWidget(ui.actionGo, bar); + ui.actionGo->setVisible(!usePathButtons); } // add a new tab -int MainWindow::addTab(Path path) { - Settings& settings = static_cast(qApp)->settings(); - - TabPage* newPage = new TabPage(path, this); - newPage->setFileLauncher(&fileLauncher_); - int index = ui.stackedWidget->addWidget(newPage); - connect(newPage, &TabPage::titleChanged, this, &MainWindow::onTabPageTitleChanged); - connect(newPage, &TabPage::statusChanged, this, &MainWindow::onTabPageStatusChanged); - connect(newPage, &TabPage::openDirRequested, this, &MainWindow::onTabPageOpenDirRequested); - connect(newPage, &TabPage::sortFilterChanged, this, &MainWindow::onTabPageSortFilterChanged); - connect(newPage, &TabPage::backwardRequested, this, &MainWindow::on_actionGoBack_triggered); - connect(newPage, &TabPage::forwardRequested, this, &MainWindow::on_actionGoForward_triggered); - - ui.tabBar->insertTab(index, newPage->title()); - - if(!settings.alwaysShowTabs()) { - ui.tabBar->setVisible(ui.tabBar->count() > 1); - } +int MainWindow::addTab(Fm::FilePath path) { + Settings& settings = static_cast(qApp)->settings(); - return index; + TabPage* newPage = new TabPage(this); + newPage->setFileLauncher(&fileLauncher_); + int index = ui.stackedWidget->addWidget(newPage); + connect(newPage, &TabPage::titleChanged, this, &MainWindow::onTabPageTitleChanged); + connect(newPage, &TabPage::statusChanged, this, &MainWindow::onTabPageStatusChanged); + connect(newPage, &TabPage::openDirRequested, this, &MainWindow::onTabPageOpenDirRequested); + connect(newPage, &TabPage::sortFilterChanged, this, &MainWindow::onTabPageSortFilterChanged); + connect(newPage, &TabPage::backwardRequested, this, &MainWindow::on_actionGoBack_triggered); + connect(newPage, &TabPage::forwardRequested, this, &MainWindow::on_actionGoForward_triggered); + + newPage->chdir(path, true); + ui.tabBar->insertTab(index, newPage->windowTitle()); + + if(!settings.alwaysShowTabs()) { + ui.tabBar->setVisible(ui.tabBar->count() > 1); + } + return index; } void MainWindow::toggleMenuBar(bool checked) { - Settings& settings = static_cast(qApp)->settings(); - bool showMenuBar = !settings.showMenuBar(); - - if (!showMenuBar) { - if (QMessageBox::Cancel == QMessageBox::warning(this, - tr("Hide menu bar"), - tr("This will hide the menu bar completely, use Ctrl+M to show it again."), - QMessageBox::Ok | QMessageBox::Cancel)) { - ui.actionMenu_bar->setChecked(true); - return; + Settings& settings = static_cast(qApp)->settings(); + bool showMenuBar = !settings.showMenuBar(); + + if(!showMenuBar) { + if(QMessageBox::Cancel == QMessageBox::warning(this, + tr("Hide menu bar"), + tr("This will hide the menu bar completely, use Ctrl+M to show it again."), + QMessageBox::Ok | QMessageBox::Cancel)) { + ui.actionMenu_bar->setChecked(true); + return; + } } - } - ui.menubar->setVisible(showMenuBar); - ui.actionMenu_bar->setChecked(showMenuBar); - menuSep_->setVisible(!showMenuBar); - ui.actionMenu->setVisible(!showMenuBar); - settings.setShowMenuBar(showMenuBar); + ui.menubar->setVisible(showMenuBar); + ui.actionMenu_bar->setChecked(showMenuBar); + menuSep_->setVisible(!showMenuBar); + ui.actionMenu->setVisible(!showMenuBar); + settings.setShowMenuBar(showMenuBar); } void MainWindow::onPathEntryReturnPressed() { - QString text = pathEntry_->text(); - QByteArray utext = text.toUtf8(); - chdir(Fm::Path::newForDisplayName(utext)); + QString text = pathEntry_->text(); + QByteArray utext = text.toLocal8Bit(); + chdir(Fm::FilePath::fromPathStr(utext.constData())); } -void MainWindow::onPathEntryEdited(const QString& text) { - QString realText(text); - if(realText == "~" || realText.startsWith("~/")) { - realText.replace(0, 1, QDir::homePath()); - pathEntry_->setText(realText); - } -} - -void MainWindow::onPathBarChdir(FmPath* dirPath) { - // call chdir() only when needed because otherwise - // filter bar will be cleard on changing current tab - TabPage* page = currentPage(); - if(page && dirPath != page->path()) - chdir(dirPath); +void MainWindow::onPathBarChdir(const Fm::FilePath& dirPath) { + // call chdir() only when needed because otherwise + // filter bar will be cleard on changing current tab + TabPage* page = currentPage(); + if(page && dirPath != page->path()) { + chdir(dirPath); + } } -void MainWindow::onPathBarMiddleClickChdir(FmPath* dirPath) { - addTab(dirPath); +void MainWindow::onPathBarMiddleClickChdir(const Fm::FilePath& dirPath) { + addTab(dirPath); } void MainWindow::on_actionGoUp_triggered() { - TabPage* page = currentPage(); + TabPage* page = currentPage(); - if(page) { - ui.filterBar->clear(); - page->up(); - updateUIForCurrentPage(); - } + if(page) { + ui.filterBar->clear(); + page->up(); + updateUIForCurrentPage(); + } } void MainWindow::on_actionGoBack_triggered() { - TabPage* page = currentPage(); + TabPage* page = currentPage(); - if(page) { - ui.filterBar->clear(); - page->backward(); - updateUIForCurrentPage(); - } + if(page) { + ui.filterBar->clear(); + page->backward(); + updateUIForCurrentPage(); + } } void MainWindow::on_actionGoForward_triggered() { - TabPage* page = currentPage(); + TabPage* page = currentPage(); - if(page) { - ui.filterBar->clear(); - page->forward(); - updateUIForCurrentPage(); - } + if(page) { + ui.filterBar->clear(); + page->forward(); + updateUIForCurrentPage(); + } } void MainWindow::on_actionHome_triggered() { - chdir(Fm::Path::getHome()); + chdir(Fm::FilePath::homeDir()); } void MainWindow::on_actionReload_triggered() { - currentPage()->reload(); - if(pathEntry_ != nullptr) - pathEntry_->setText(currentPage()->pathName()); + currentPage()->reload(); + if(pathEntry_ != nullptr) { + pathEntry_->setText(currentPage()->pathName()); + } } void MainWindow::on_actionConnectToServer_triggered() { - Application* app = static_cast(qApp); - app->connectToServer(); + Application* app = static_cast(qApp); + app->connectToServer(); } void MainWindow::on_actionGo_triggered() { - onPathEntryReturnPressed(); + onPathEntryReturnPressed(); } void MainWindow::on_actionNewTab_triggered() { - Fm::Path path = currentPage()->path(); - int index = addTab(path); - ui.tabBar->setCurrentIndex(index); + auto path = currentPage()->path(); + int index = addTab(path); + ui.tabBar->setCurrentIndex(index); } void MainWindow::on_actionNewWin_triggered() { - Fm::Path path = currentPage()->path(); - (new MainWindow(path))->show(); + auto path = currentPage()->path(); + (new MainWindow(path))->show(); } void MainWindow::on_actionNewFolder_triggered() { - if(TabPage* tabPage = currentPage()) { - Fm::Path dirPath = tabPage->folderView()->path(); - - if(dirPath) - createFileOrFolder(CreateNewFolder, dirPath); - } + if(TabPage* tabPage = currentPage()) { + auto dirPath = tabPage->folderView()->path(); + if(dirPath) { + createFileOrFolder(CreateNewFolder, dirPath); + } + } } void MainWindow::on_actionNewBlankFile_triggered() { - if(TabPage* tabPage = currentPage()) { - Fm::Path dirPath = tabPage->folderView()->path(); - - if(dirPath) - createFileOrFolder(CreateNewTextFile, dirPath); - } + if(TabPage* tabPage = currentPage()) { + auto dirPath = tabPage->folderView()->path(); + if(dirPath) { + createFileOrFolder(CreateNewTextFile, dirPath); + } + } } void MainWindow::on_actionCloseTab_triggered() { - closeTab(ui.tabBar->currentIndex()); + closeTab(ui.tabBar->currentIndex()); } void MainWindow::on_actionCloseWindow_triggered() { - // FIXME: should we save state here? - close(); - // the window will be deleted automatically on close + // FIXME: should we save state here? + close(); + // the window will be deleted automatically on close } void MainWindow::on_actionFileProperties_triggered() { - TabPage* page = currentPage(); - if(page) { - Fm::FileInfoList files = page->selectedFiles(); - if(!files.isNull()) { - Fm::FilePropsDialog::showForFiles(files); + TabPage* page = currentPage(); + if(page) { + auto files = page->selectedFiles(); + if(!files.empty()) { + Fm::FilePropsDialog::showForFiles(files); + } } - } } void MainWindow::on_actionFolderProperties_triggered() { - TabPage* page = currentPage(); - - if(page) { - Fm::Folder folder = page->folder(); - if(!folder.isNull()) { - Fm::FileInfo info = folder.getInfo(); - if(!info.isNull()) - Fm::FilePropsDialog::showForFile(info); + TabPage* page = currentPage(); + if(page) { + auto folder = page->folder(); + if(folder) { + auto info = folder->info(); + if(info) { + Fm::FilePropsDialog::showForFile(info); + } + } } - } } void MainWindow::on_actionShowHidden_triggered(bool checked) { - currentPage()->setShowHidden(checked); - ui.sidePane->setShowHidden(checked); + currentPage()->setShowHidden(checked); + ui.sidePane->setShowHidden(checked); + if(!currentPage()->hasCustomizedView()) { + static_cast(qApp)->settings().setShowHidden(checked); // remember globally + } } void MainWindow::on_actionByFileName_triggered(bool checked) { - currentPage()->sort(Fm::FolderModel::ColumnFileName, currentPage()->sortOrder()); + currentPage()->sort(Fm::FolderModel::ColumnFileName, currentPage()->sortOrder()); } void MainWindow::on_actionByMTime_triggered(bool checked) { - currentPage()->sort(Fm::FolderModel::ColumnFileMTime, currentPage()->sortOrder()); + currentPage()->sort(Fm::FolderModel::ColumnFileMTime, currentPage()->sortOrder()); } void MainWindow::on_actionByOwner_triggered(bool checked) { - currentPage()->sort(Fm::FolderModel::ColumnFileOwner, currentPage()->sortOrder()); + currentPage()->sort(Fm::FolderModel::ColumnFileOwner, currentPage()->sortOrder()); } void MainWindow::on_actionByFileSize_triggered(bool checked) { - currentPage()->sort(Fm::FolderModel::ColumnFileSize, currentPage()->sortOrder()); + currentPage()->sort(Fm::FolderModel::ColumnFileSize, currentPage()->sortOrder()); } void MainWindow::on_actionByFileType_triggered(bool checked) { - currentPage()->sort(Fm::FolderModel::ColumnFileType, currentPage()->sortOrder()); + currentPage()->sort(Fm::FolderModel::ColumnFileType, currentPage()->sortOrder()); } void MainWindow::on_actionAscending_triggered(bool checked) { - currentPage()->sort(currentPage()->sortColumn(), Qt::AscendingOrder); + currentPage()->sort(currentPage()->sortColumn(), Qt::AscendingOrder); } void MainWindow::on_actionDescending_triggered(bool checked) { - currentPage()->sort(currentPage()->sortColumn(), Qt::DescendingOrder); + currentPage()->sort(currentPage()->sortColumn(), Qt::DescendingOrder); } void MainWindow::on_actionCaseSensitive_triggered(bool checked) { - currentPage()->setSortCaseSensitive(checked); + currentPage()->setSortCaseSensitive(checked); } void MainWindow::on_actionFolderFirst_triggered(bool checked) { - currentPage()->setSortFolderFirst(checked); + currentPage()->setSortFolderFirst(checked); } void MainWindow::on_actionPreserveView_triggered(bool checked) { - TabPage* page = currentPage(); - page->setCustomizedView(!page->hasCustomizedView()); + TabPage* page = currentPage(); + page->setCustomizedView(!page->hasCustomizedView()); } void MainWindow::on_actionFilter_triggered(bool checked) { - ui.filterBar->setVisible(checked); - if(checked) - ui.filterBar->setFocus(); - else if(TabPage* tabPage = currentPage()) { - ui.filterBar->clear(); - tabPage->folderView()->childView()->setFocus(); - // clear filter string for all tabs - int n = ui.stackedWidget->count(); - for(int i = 0; i < n; ++i) { - TabPage* page = static_cast(ui.stackedWidget->widget(i)); - if(!page->getFilterStr().isEmpty()) { - page->setFilterStr(QString()); - page->applyFilter(); - } + ui.filterBar->setVisible(checked); + if(checked) { + ui.filterBar->setFocus(); + } + else if(TabPage* tabPage = currentPage()) { + ui.filterBar->clear(); + tabPage->folderView()->childView()->setFocus(); + // clear filter string for all tabs + int n = ui.stackedWidget->count(); + for(int i = 0; i < n; ++i) { + TabPage* page = static_cast(ui.stackedWidget->widget(i)); + if(!page->getFilterStr().isEmpty()) { + page->setFilterStr(QString()); + page->applyFilter(); + } + } } - } - static_cast(qApp)->settings().setShowFilter(checked); + static_cast(qApp)->settings().setShowFilter(checked); } void MainWindow::on_actionLocationBar_triggered(bool checked) { - if(checked) { - // show current path in a location bar entry - if(pathBar_ != nullptr) { - delete pathBar_; - pathBar_ = nullptr; + if(checked) { + // show current path in a location bar entry + if(pathBar_ != nullptr) { + delete pathBar_; + pathBar_ = nullptr; + } + createPathBar(false); + pathEntry_->setText(currentPage()->pathName()); + static_cast(qApp)->settings().setPathBarButtons(false); } - createPathBar(false); - pathEntry_->setText(currentPage()->pathName()); - static_cast(qApp)->settings().setPathBarButtons(false); - } } void MainWindow::on_actionPathButtons_triggered(bool checked) { - if(checked && pathBar_ == nullptr) { - // show current path as buttons - if(pathEntry_ != nullptr) { - delete pathEntry_; - pathEntry_ = nullptr; + if(checked && pathBar_ == nullptr) { + // show current path as buttons + if(pathEntry_ != nullptr) { + delete pathEntry_; + pathEntry_ = nullptr; + } + createPathBar(true); + pathBar_->setPath(currentPage()->path()); + static_cast(qApp)->settings().setPathBarButtons(true); } - createPathBar(true); - pathBar_->setPath(currentPage()->path()); - static_cast(qApp)->settings().setPathBarButtons(true); - } } void MainWindow::on_actionComputer_triggered() { - chdir(Fm::Path::newForUri("computer:///")); + chdir(Fm::FilePath::fromUri("computer:///")); } void MainWindow::on_actionApplications_triggered() { - chdir(Fm::Path::getAppsMenu()); + chdir(Fm::FilePath::fromUri("menu://applications/")); } void MainWindow::on_actionTrash_triggered() { - chdir(Fm::Path::getTrash()); + chdir(Fm::FilePath::fromUri("trash:///")); } void MainWindow::on_actionNetwork_triggered() { - chdir(Fm::Path::newForUri("network:///")); + chdir(Fm::FilePath::fromUri("network:///")); } void MainWindow::on_actionDesktop_triggered() { - chdir(Fm::Path::getDesktop()); + auto desktop = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation).toLocal8Bit(); + chdir(Fm::FilePath::fromLocalPath(desktop.constData())); } void MainWindow::on_actionAddToBookmarks_triggered() { - TabPage* page = currentPage(); - if(page) { - Fm::Path cwd = page->path(); - if(!cwd.isNull()) { - char* dispName = cwd.displayBasename(); - bookmarks_.insert(cwd, dispName, -1); - g_free(dispName); + TabPage* page = currentPage(); + if(page) { + auto cwd = page->path(); + if(cwd) { + auto dispName = cwd.baseName(); + bookmarks_->insert(cwd, dispName.get(), -1); + } } - } } void MainWindow::on_actionEditBookmarks_triggered() { - Application* app = static_cast(qApp); - app->editBookmarks(); + Application* app = static_cast(qApp); + app->editBookmarks(); } void MainWindow::on_actionAbout_triggered() { - // the about dialog - class AboutDialog : public QDialog { - public: - explicit AboutDialog(QWidget* parent = 0, Qt::WindowFlags f = 0) { - ui.setupUi(this); - ui.version->setText(tr("Version: %1").arg(PCMANFM_QT_VERSION)); - } - private: - Ui::AboutDialog ui; - }; - AboutDialog dialog(this); - dialog.exec(); + // the about dialog + class AboutDialog : public QDialog { + public: + explicit AboutDialog(QWidget* parent = 0, Qt::WindowFlags f = 0) { + ui.setupUi(this); + ui.version->setText(tr("Version: %1").arg(PCMANFM_QT_VERSION)); + } + private: + Ui::AboutDialog ui; + }; + AboutDialog dialog(this); + dialog.exec(); } void MainWindow::on_actionIconView_triggered() { - currentPage()->setViewMode(Fm::FolderView::IconMode); + currentPage()->setViewMode(Fm::FolderView::IconMode); } void MainWindow::on_actionCompactView_triggered() { - currentPage()->setViewMode(Fm::FolderView::CompactMode); + currentPage()->setViewMode(Fm::FolderView::CompactMode); } void MainWindow::on_actionDetailedList_triggered() { - currentPage()->setViewMode(Fm::FolderView::DetailedListMode); + currentPage()->setViewMode(Fm::FolderView::DetailedListMode); } void MainWindow::on_actionThumbnailView_triggered() { - currentPage()->setViewMode(Fm::FolderView::ThumbnailMode); + currentPage()->setViewMode(Fm::FolderView::ThumbnailMode); } void MainWindow::onTabBarCloseRequested(int index) { - closeTab(index); + closeTab(index); } void MainWindow::onResetFocus() { - if(TabPage* page = currentPage()) { - page->folderView()->childView()->setFocus(); - } + if(TabPage* page = currentPage()) { + page->folderView()->childView()->setFocus(); + } } void MainWindow::onTabBarTabMoved(int from, int to) { - // a tab in the tab bar is moved by the user, so we have to move the - // corredponding tab page in the stacked widget to the new position, too. - QWidget* page = ui.stackedWidget->widget(from); - if(page) { - // we're not going to delete the tab page, so here we block signals - // to avoid calling the slot onStackedWidgetWidgetRemoved() before - // removing the page. Otherwise the page widget will be destroyed. - ui.stackedWidget->blockSignals(true); - ui.stackedWidget->removeWidget(page); - ui.stackedWidget->insertWidget(to, page); // insert the page to the new position - ui.stackedWidget->blockSignals(false); // unblock signals - ui.stackedWidget->setCurrentWidget(page); - } + // a tab in the tab bar is moved by the user, so we have to move the + // corredponding tab page in the stacked widget to the new position, too. + QWidget* page = ui.stackedWidget->widget(from); + if(page) { + // we're not going to delete the tab page, so here we block signals + // to avoid calling the slot onStackedWidgetWidgetRemoved() before + // removing the page. Otherwise the page widget will be destroyed. + ui.stackedWidget->blockSignals(true); + ui.stackedWidget->removeWidget(page); + ui.stackedWidget->insertWidget(to, page); // insert the page to the new position + ui.stackedWidget->blockSignals(false); // unblock signals + ui.stackedWidget->setCurrentWidget(page); + } } void MainWindow::focusFilterBar() { - if(!ui.filterBar->isVisible()) - ui.actionFilter->trigger(); - else - ui.filterBar->setFocus(); + if(!ui.filterBar->isVisible()) { + ui.actionFilter->trigger(); + } + else { + ui.filterBar->setFocus(); + } } void MainWindow::onFilterStringChanged(QString str) { - if(TabPage* tabPage = currentPage()) { - // appy filter only if needed (not if tab is changed) - if(str != tabPage->getFilterStr()) { - tabPage->setFilterStr(str); - tabPage->applyFilter(); + if(TabPage* tabPage = currentPage()) { + // appy filter only if needed (not if tab is changed) + if(str != tabPage->getFilterStr()) { + tabPage->setFilterStr(str); + tabPage->applyFilter(); + } } - } } void MainWindow::closeTab(int index) { - QWidget* page = ui.stackedWidget->widget(index); - if(page) { - ui.stackedWidget->removeWidget(page); // this does not delete the page widget - delete page; - // NOTE: we do not remove the tab here. - // it'll be donoe in onStackedWidgetWidgetRemoved() - } + QWidget* page = ui.stackedWidget->widget(index); + if(page) { + ui.stackedWidget->removeWidget(page); // this does not delete the page widget + delete page; + // NOTE: we do not remove the tab here. + // it'll be donoe in onStackedWidgetWidgetRemoved() + } } -void MainWindow::resizeEvent(QResizeEvent *event) { - QMainWindow::resizeEvent(event); - Settings& settings = static_cast(qApp)->settings(); - if(settings.rememberWindowSize()) { - settings.setLastWindowMaximized(isMaximized()); +void MainWindow::resizeEvent(QResizeEvent* event) { + QMainWindow::resizeEvent(event); + Settings& settings = static_cast(qApp)->settings(); + if(settings.rememberWindowSize()) { + settings.setLastWindowMaximized(isMaximized()); - if(!isMaximized()) { - settings.setLastWindowWidth(width()); - settings.setLastWindowHeight(height()); + if(!isMaximized()) { + settings.setLastWindowWidth(width()); + settings.setLastWindowHeight(height()); + } } - } } -void MainWindow::closeEvent(QCloseEvent *event) -{ - if(lastActive_ == this) - lastActive_ = nullptr; +void MainWindow::closeEvent(QCloseEvent* event) { + if(lastActive_ == this) { + lastActive_ = nullptr; + } - QWidget::closeEvent(event); - Settings& settings = static_cast(qApp)->settings(); - if(settings.rememberWindowSize()) { - settings.setLastWindowMaximized(isMaximized()); + QWidget::closeEvent(event); + Settings& settings = static_cast(qApp)->settings(); + if(settings.rememberWindowSize()) { + settings.setLastWindowMaximized(isMaximized()); - if(!isMaximized()) { - settings.setLastWindowWidth(width()); - settings.setLastWindowHeight(height()); + if(!isMaximized()) { + settings.setLastWindowWidth(width()); + settings.setLastWindowHeight(height()); + } } - } } void MainWindow::onTabBarCurrentChanged(int index) { - ui.stackedWidget->setCurrentIndex(index); - if(TabPage* page = static_cast(ui.stackedWidget->widget(index))) - ui.filterBar->setText(page->getFilterStr()); - updateUIForCurrentPage(); + ui.stackedWidget->setCurrentIndex(index); + if(TabPage* page = static_cast(ui.stackedWidget->widget(index))) { + ui.filterBar->setText(page->getFilterStr()); + } + updateUIForCurrentPage(); } void MainWindow::updateStatusBarForCurrentPage() { - TabPage* tabPage = currentPage(); - QString text = tabPage->statusText(TabPage::StatusTextSelectedFiles); - if(text.isEmpty()) - text = tabPage->statusText(TabPage::StatusTextNormal); - ui.statusbar->showMessage(text); + TabPage* tabPage = currentPage(); + QString text = tabPage->statusText(TabPage::StatusTextSelectedFiles); + if(text.isEmpty()) { + text = tabPage->statusText(TabPage::StatusTextNormal); + } + ui.statusbar->showMessage(text); - text = tabPage->statusText(TabPage::StatusTextFSInfo); - fsInfoLabel_->setText(text); - fsInfoLabel_->setVisible(!text.isEmpty()); + text = tabPage->statusText(TabPage::StatusTextFSInfo); + fsInfoLabel_->setText(text); + fsInfoLabel_->setVisible(!text.isEmpty()); } void MainWindow::updateViewMenuForCurrentPage() { - if(updatingViewMenu_) // prevent recursive calls - return; - updatingViewMenu_ = true; - TabPage* tabPage = currentPage(); - if(tabPage) { - // update menus. FIXME: should we move this to another method? - ui.actionShowHidden->setChecked(tabPage->showHidden()); - ui.actionPreserveView->setChecked(tabPage->hasCustomizedView()); - - // view mode - QAction* modeAction = NULL; - - switch(tabPage->viewMode()) { - case Fm::FolderView::IconMode: - modeAction = ui.actionIconView; - break; - - case Fm::FolderView::CompactMode: - modeAction = ui.actionCompactView; - break; - - case Fm::FolderView::DetailedListMode: - modeAction = ui.actionDetailedList; - break; - - case Fm::FolderView::ThumbnailMode: - modeAction = ui.actionThumbnailView; - break; - } - - Q_ASSERT(modeAction != NULL); - modeAction->setChecked(true); - - // sort menu - QAction* sortActions[Fm::FolderModel::NumOfColumns]; - sortActions[Fm::FolderModel::ColumnFileName] = ui.actionByFileName; - sortActions[Fm::FolderModel::ColumnFileMTime] = ui.actionByMTime; - sortActions[Fm::FolderModel::ColumnFileSize] = ui.actionByFileSize; - sortActions[Fm::FolderModel::ColumnFileType] = ui.actionByFileType; - sortActions[Fm::FolderModel::ColumnFileOwner] = ui.actionByOwner; - sortActions[tabPage->sortColumn()]->setChecked(true); - - if(tabPage->sortOrder() == Qt::AscendingOrder) - ui.actionAscending->setChecked(true); - else - ui.actionDescending->setChecked(true); - ui.actionCaseSensitive->setChecked(tabPage->sortCaseSensitive()); - ui.actionFolderFirst->setChecked(tabPage->sortFolderFirst()); - } - updatingViewMenu_ = false; -} + if(updatingViewMenu_) { // prevent recursive calls + return; + } + updatingViewMenu_ = true; + TabPage* tabPage = currentPage(); + if(tabPage) { + // update menus. FIXME: should we move this to another method? + ui.actionShowHidden->setChecked(tabPage->showHidden()); + ui.actionPreserveView->setChecked(tabPage->hasCustomizedView()); + + // view mode + QAction* modeAction = nullptr; + + switch(tabPage->viewMode()) { + case Fm::FolderView::IconMode: + modeAction = ui.actionIconView; + break; + + case Fm::FolderView::CompactMode: + modeAction = ui.actionCompactView; + break; + + case Fm::FolderView::DetailedListMode: + modeAction = ui.actionDetailedList; + break; + + case Fm::FolderView::ThumbnailMode: + modeAction = ui.actionThumbnailView; + break; + } -void MainWindow::updateUIForCurrentPage() { - TabPage* tabPage = currentPage(); + Q_ASSERT(modeAction != nullptr); + modeAction->setChecked(true); - if(tabPage) { - setWindowTitle(tabPage->title()); - if(pathEntry_ != nullptr) { - pathEntry_->setText(tabPage->pathName()); + // sort menu + QAction* sortActions[Fm::FolderModel::NumOfColumns]; + sortActions[Fm::FolderModel::ColumnFileName] = ui.actionByFileName; + sortActions[Fm::FolderModel::ColumnFileMTime] = ui.actionByMTime; + sortActions[Fm::FolderModel::ColumnFileSize] = ui.actionByFileSize; + sortActions[Fm::FolderModel::ColumnFileType] = ui.actionByFileType; + sortActions[Fm::FolderModel::ColumnFileOwner] = ui.actionByOwner; + sortActions[tabPage->sortColumn()]->setChecked(true); + + if(tabPage->sortOrder() == Qt::AscendingOrder) { + ui.actionAscending->setChecked(true); + } + else { + ui.actionDescending->setChecked(true); + } + ui.actionCaseSensitive->setChecked(tabPage->sortCaseSensitive()); + ui.actionFolderFirst->setChecked(tabPage->sortFolderFirst()); } - else if(pathBar_ != nullptr) { - pathBar_->setPath(tabPage->path()); + updatingViewMenu_ = false; +} + +// Update the enabled state of Edit actions for selected files +void MainWindow::updateEditSelectedActions() { + bool hasAccessible(false); + bool hasDeletable(false); + bool hasRenamable(false); + if(TabPage* page = currentPage()) { + auto files = page->selectedFiles(); + for(auto& file: files) { + if(file->isAccessible()) { + hasAccessible = true; + } + if(file->isDeletable()) { + hasDeletable = true; + } + if(file->canSetName()) { + hasRenamable = true; + } + if (hasAccessible && hasDeletable && hasRenamable) { + break; + } + } } - ui.statusbar->showMessage(tabPage->statusText()); - fsInfoLabel_->setText(tabPage->statusText(TabPage::StatusTextFSInfo)); - tabPage->folderView()->childView()->setFocus(); + ui.actionCopy->setEnabled(hasAccessible); + ui.actionCut->setEnabled(hasDeletable); + ui.actionDelete->setEnabled(hasDeletable); + ui.actionRename->setEnabled(hasRenamable); +} - // update side pane - ui.sidePane->setCurrentPath(tabPage->path()); - ui.sidePane->setShowHidden(tabPage->showHidden()); +void MainWindow::updateUIForCurrentPage() { + TabPage* tabPage = currentPage(); - // update back/forward/up toolbar buttons - ui.actionGoUp->setEnabled(tabPage->canUp()); - ui.actionGoBack->setEnabled(tabPage->canBackward()); - ui.actionGoForward->setEnabled(tabPage->canForward()); + if(tabPage) { + setWindowTitle(tabPage->windowTitle()); + if(pathEntry_ != nullptr) { + pathEntry_->setText(tabPage->pathName()); + } + else if(pathBar_ != nullptr) { + pathBar_->setPath(tabPage->path()); + } + ui.statusbar->showMessage(tabPage->statusText()); + fsInfoLabel_->setText(tabPage->statusText(TabPage::StatusTextFSInfo)); + tabPage->folderView()->childView()->setFocus(); + + // update side pane + ui.sidePane->setCurrentPath(tabPage->path()); + ui.sidePane->setShowHidden(tabPage->showHidden()); + + // update back/forward/up toolbar buttons + ui.actionGoUp->setEnabled(tabPage->canUp()); + ui.actionGoBack->setEnabled(tabPage->canBackward()); + ui.actionGoForward->setEnabled(tabPage->canForward()); - updateViewMenuForCurrentPage(); - updateStatusBarForCurrentPage(); - } + updateViewMenuForCurrentPage(); + updateStatusBarForCurrentPage(); + } + + // also update the enabled state of Edit actions + updateEditSelectedActions(); + bool isWritable(false); + if(tabPage && tabPage->folder()) { + if(auto info = tabPage->folder()->info()) { + isWritable = info->isWritable(); + } + } + ui.actionPaste->setEnabled(isWritable); } void MainWindow::onStackedWidgetWidgetRemoved(int index) { - // qDebug("onStackedWidgetWidgetRemoved: %d", index); - // need to remove associated tab from tabBar - ui.tabBar->removeTab(index); - if(ui.tabBar->count() == 0) { // this is the last one - deleteLater(); // destroy the whole window - // qDebug("delete window"); - } - else { - Settings& settings = static_cast(qApp)->settings(); - if(!settings.alwaysShowTabs() && ui.tabBar->count() == 1) { - ui.tabBar->setVisible(false); + // qDebug("onStackedWidgetWidgetRemoved: %d", index); + // need to remove associated tab from tabBar + ui.tabBar->removeTab(index); + if(ui.tabBar->count() == 0) { // this is the last one + deleteLater(); // destroy the whole window + // qDebug("delete window"); + } + else { + Settings& settings = static_cast(qApp)->settings(); + if(!settings.alwaysShowTabs() && ui.tabBar->count() == 1) { + ui.tabBar->setVisible(false); + } } - } } void MainWindow::onTabPageTitleChanged(QString title) { - TabPage* tabPage = static_cast(sender()); - int index = ui.stackedWidget->indexOf(tabPage); + TabPage* tabPage = static_cast(sender()); + int index = ui.stackedWidget->indexOf(tabPage); + if(index >= 0) { + ui.tabBar->setTabText(index, title); + } - if(index >= 0) - ui.tabBar->setTabText(index, title); + if(tabPage == currentPage()) { + setWindowTitle(title); - if(tabPage == currentPage()) - setWindowTitle(title); + // Since TabPage::titleChanged is emitted on changing directory, + // the enabled state of Paste action should be updated here + bool isWritable(false); + if(tabPage && tabPage->folder()) { + if(auto info = tabPage->folder()->info()) { + isWritable = info->isWritable(); + } + } + ui.actionPaste->setEnabled(isWritable); + } } void MainWindow::onTabPageStatusChanged(int type, QString statusText) { - TabPage* tabPage = static_cast(sender()); - if(tabPage == currentPage()) { - switch(type) { - case TabPage::StatusTextNormal: - case TabPage::StatusTextSelectedFiles: { - // FIXME: updating the status text so frequently is a little bit ineffiecient - QString text = statusText = tabPage->statusText(TabPage::StatusTextSelectedFiles); - if(text.isEmpty()) - ui.statusbar->showMessage(tabPage->statusText(TabPage::StatusTextNormal)); - else - ui.statusbar->showMessage(text); - break; - } - case TabPage::StatusTextFSInfo: - fsInfoLabel_->setText(tabPage->statusText(TabPage::StatusTextFSInfo)); - fsInfoLabel_->setVisible(!statusText.isEmpty()); - break; - } - } -} - -void MainWindow::onTabPageOpenDirRequested(FmPath* path, int target) { - switch(target) { - case OpenInCurrentTab: - chdir(path); - break; - - case OpenInNewTab: - addTab(path); - break; + TabPage* tabPage = static_cast(sender()); + if(tabPage == currentPage()) { + switch(type) { + case TabPage::StatusTextNormal: + case TabPage::StatusTextSelectedFiles: { + // although the status text may change very frequently, + // the text of PCManFM::StatusBar is updated with a delay + QString text = tabPage->statusText(TabPage::StatusTextSelectedFiles); + if(text.isEmpty()) { + ui.statusbar->showMessage(tabPage->statusText(TabPage::StatusTextNormal)); + } + else { + ui.statusbar->showMessage(text); + } + break; + } + case TabPage::StatusTextFSInfo: + fsInfoLabel_->setText(tabPage->statusText(TabPage::StatusTextFSInfo)); + fsInfoLabel_->setVisible(!statusText.isEmpty()); + break; + } + } - case OpenInNewWindow: - (new MainWindow(path))->show(); - break; - } + // Since TabPage::statusChanged is always emitted after View::selChanged, + // there is no need to connect a separate slot to the latter signal + updateEditSelectedActions(); +} + +void MainWindow::onTabPageOpenDirRequested(const Fm::FilePath& path, int target) { + switch(target) { + case OpenInCurrentTab: + chdir(path); + break; + + case OpenInNewTab: + addTab(path); + break; + + case OpenInNewWindow: + (new MainWindow(path))->show(); + break; + } } void MainWindow::onTabPageSortFilterChanged() { - TabPage* tabPage = static_cast(sender()); - if(tabPage == currentPage()) { - updateViewMenuForCurrentPage(); - if(!tabPage->hasCustomizedView()) { - Settings& settings = static_cast(qApp)->settings(); - settings.setSortColumn(static_cast(tabPage->sortColumn())); - settings.setSortOrder(tabPage->sortOrder()); - settings.setSortFolderFirst(tabPage->sortFolderFirst()); - settings.setSortCaseSensitive(tabPage->sortCaseSensitive()); + TabPage* tabPage = static_cast(sender()); + if(tabPage == currentPage()) { + updateViewMenuForCurrentPage(); + if(!tabPage->hasCustomizedView()) { + Settings& settings = static_cast(qApp)->settings(); + settings.setSortColumn(static_cast(tabPage->sortColumn())); + settings.setSortOrder(tabPage->sortOrder()); + settings.setSortFolderFirst(tabPage->sortFolderFirst()); + settings.setSortCaseSensitive(tabPage->sortCaseSensitive()); + settings.setShowHidden(tabPage->showHidden()); // remember globally , as in on_actionShowHidden_triggered() + } + tabPage->setShowHidden(tabPage->showHidden()); // change status text and perfolder setting } - } } -void MainWindow::onSidePaneChdirRequested(int type, FmPath* path) { - // FIXME: use enum for type value or change it to button. - if(type == 0) // left button (default) - chdir(path); - else if(type == 1) // middle button - addTab(path); - else if(type == 2) // new window - (new MainWindow(path))->show(); +void MainWindow::onSidePaneChdirRequested(int type, const Fm::FilePath &path) { + // FIXME: use enum for type value or change it to button. + if(type == 0) { // left button (default) + chdir(path); + } + else if(type == 1) { // middle button + addTab(path); + } + else if(type == 2) { // new window + (new MainWindow(path))->show(); + } } -void MainWindow::onSidePaneOpenFolderInNewWindowRequested(FmPath* path) { - (new MainWindow(path))->show(); +void MainWindow::onSidePaneOpenFolderInNewWindowRequested(const Fm::FilePath &path) { + (new MainWindow(path))->show(); } -void MainWindow::onSidePaneOpenFolderInNewTabRequested(FmPath* path) { - addTab(path); +void MainWindow::onSidePaneOpenFolderInNewTabRequested(const Fm::FilePath &path) { + addTab(path); } -void MainWindow::onSidePaneOpenFolderInTerminalRequested(FmPath* path) { - Application* app = static_cast(qApp); - app->openFolderInTerminal(path); +void MainWindow::onSidePaneOpenFolderInTerminalRequested(const Fm::FilePath &path) { + Application* app = static_cast(qApp); + app->openFolderInTerminal(path); } -void MainWindow::onSidePaneCreateNewFolderRequested(FmPath* path) { - createFileOrFolder(CreateNewFolder, path); +void MainWindow::onSidePaneCreateNewFolderRequested(const Fm::FilePath &path) { + createFileOrFolder(CreateNewFolder, path); } void MainWindow::onSidePaneModeChanged(Fm::SidePane::Mode mode) { - static_cast(qApp)->settings().setSidePaneMode(mode); + static_cast(qApp)->settings().setSidePaneMode(mode); } void MainWindow::onSplitterMoved(int pos, int index) { - Application* app = static_cast(qApp); - app->settings().setSplitterPos(pos); + Application* app = static_cast(qApp); + app->settings().setSplitterPos(pos); } void MainWindow::loadBookmarksMenu() { - GList* allBookmarks = bookmarks_.getAll(); - QAction* before = ui.actionAddToBookmarks; - - for(GList* l = allBookmarks; l; l = l->next) { - FmBookmarkItem* item = reinterpret_cast(l->data); - BookmarkAction* action = new BookmarkAction(item, ui.menu_Bookmarks); - connect(action, &QAction::triggered, this, &MainWindow::onBookmarkActionTriggered); - ui.menu_Bookmarks->insertAction(before, action); - } + QAction* before = ui.actionAddToBookmarks; + for(auto& item: bookmarks_->items()) { + BookmarkAction* action = new BookmarkAction(item, ui.menu_Bookmarks); + connect(action, &QAction::triggered, this, &MainWindow::onBookmarkActionTriggered); + ui.menu_Bookmarks->insertAction(before, action); + } - ui.menu_Bookmarks->insertSeparator(before); - g_list_free_full(allBookmarks, (GDestroyNotify)fm_bookmark_item_unref); + ui.menu_Bookmarks->insertSeparator(before); } -void MainWindow::onBookmarksChanged(FmBookmarks* bookmarks, MainWindow* pThis) { - // delete existing items - QList actions = pThis->ui.menu_Bookmarks->actions(); - QList::const_iterator it = actions.begin(); - QList::const_iterator last_it = actions.end() - 2; +void MainWindow::onBookmarksChanged() { + // delete existing items + QList actions = ui.menu_Bookmarks->actions(); + QList::const_iterator it = actions.constBegin(); + QList::const_iterator last_it = actions.constEnd() - 2; - while(it != last_it) { - QAction* action = *it; - ++it; - pThis->ui.menu_Bookmarks->removeAction(action); - } + while(it != last_it) { + QAction* action = *it; + ++it; + ui.menu_Bookmarks->removeAction(action); + } - pThis->loadBookmarksMenu(); + loadBookmarksMenu(); } void MainWindow::onBookmarkActionTriggered() { - BookmarkAction* action = static_cast(sender()); - Fm::Path path = action->path(); - if(path) { - Application* app = static_cast(qApp); - Settings& settings = app->settings(); - switch(settings.bookmarkOpenMethod()) { - case OpenInCurrentTab: /* current tab */ - default: - chdir(path); - break; - case OpenInNewTab: /* new tab */ - addTab(path); - break; - case OpenInNewWindow: /* new window */ - (new MainWindow(path))->show(); - break; + BookmarkAction* action = static_cast(sender()); + auto path = action->path(); + if(path) { + Application* app = static_cast(qApp); + Settings& settings = app->settings(); + switch(settings.bookmarkOpenMethod()) { + case OpenInCurrentTab: /* current tab */ + default: + chdir(path); + break; + case OpenInNewTab: /* new tab */ + addTab(path); + break; + case OpenInNewWindow: /* new window */ + (new MainWindow(path))->show(); + break; + } } - } } void MainWindow::on_actionCopy_triggered() { - TabPage* page = currentPage(); - Fm::PathList paths = page->selectedFilePaths(); - copyFilesToClipboard(paths); + TabPage* page = currentPage(); + auto paths = page->selectedFilePaths(); + copyFilesToClipboard(paths); } void MainWindow::on_actionCut_triggered() { - TabPage* page = currentPage(); - Fm::PathList paths = page->selectedFilePaths(); - cutFilesToClipboard(paths); + TabPage* page = currentPage(); + auto paths = page->selectedFilePaths(); + cutFilesToClipboard(paths); } void MainWindow::on_actionPaste_triggered() { - pasteFilesFromClipboard(currentPage()->path(), this); + pasteFilesFromClipboard(currentPage()->path(), this); } void MainWindow::on_actionDelete_triggered() { - Application* app = static_cast(qApp); - Settings& settings = app->settings(); - TabPage* page = currentPage(); - Fm::PathList paths = page->selectedFilePaths(); + Application* app = static_cast(qApp); + Settings& settings = app->settings(); + TabPage* page = currentPage(); + auto paths = page->selectedFilePaths(); - bool shiftPressed = (qApp->keyboardModifiers() & Qt::ShiftModifier ? true : false); - if(settings.useTrash() && !shiftPressed) - FileOperation::trashFiles(paths, settings.confirmTrash(), this); - else - FileOperation::deleteFiles(paths, settings.confirmDelete(), this); + bool shiftPressed = (qApp->keyboardModifiers() & Qt::ShiftModifier ? true : false); + if(settings.useTrash() && !shiftPressed) { + FileOperation::trashFiles(paths, settings.confirmTrash(), this); + } + else { + FileOperation::deleteFiles(paths, settings.confirmDelete(), this); + } } void MainWindow::on_actionRename_triggered() { - TabPage* page = currentPage(); - Fm::FileInfoList files = page->selectedFiles(); - for(GList* l = fm_file_info_list_peek_head_link(files); l; l = l->next) { - FmFileInfo* file = FM_FILE_INFO(l->data); - Fm::renameFile(file, NULL); - } + // do inline renaming if only one item is selected, + // otherwise use the renaming dialog + TabPage* page = currentPage(); + auto files = page->selectedFiles(); + if(files.size() == 1) { + QAbstractItemView* view = page->folderView()->childView(); + QModelIndexList selIndexes = view->selectionModel()->selectedIndexes(); + if(selIndexes.size() > 1) { // in the detailed list mode, only the first index is editable + view->setCurrentIndex(selIndexes.at(0)); + } + QModelIndex cur = view->currentIndex(); + if (cur.isValid()) { + view->scrollTo(cur); + view->edit(cur); + return; + } + } + if(!files.empty()) { + for(auto& file: files) { + Fm::renameFile(file, nullptr); + } + } } void MainWindow::on_actionSelectAll_triggered() { - currentPage()->selectAll(); + currentPage()->selectAll(); } void MainWindow::on_actionInvertSelection_triggered() { - currentPage()->invertSelection(); + currentPage()->invertSelection(); } void MainWindow::on_actionPreferences_triggered() { - Application* app = reinterpret_cast(qApp); - app->preferences(QString()); + Application* app = reinterpret_cast(qApp); + app->preferences(QString()); } // change some icons according to layout direction void MainWindow::setRTLIcons(bool isRTL) { - QIcon nxtIcn = QIcon::fromTheme("go-next"); - QIcon prevIcn = QIcon::fromTheme("go-previous"); - if(isRTL) { - ui.actionGoBack->setIcon(nxtIcn); - ui.actionCloseLeft->setIcon(nxtIcn); - ui.actionGoForward->setIcon(prevIcn); - ui.actionCloseRight->setIcon(prevIcn); - } - else { - ui.actionGoBack->setIcon(prevIcn); - ui.actionCloseLeft->setIcon(prevIcn); - ui.actionGoForward->setIcon(nxtIcn); - ui.actionCloseRight->setIcon(nxtIcn); - } + QIcon nxtIcn = QIcon::fromTheme("go-next"); + QIcon prevIcn = QIcon::fromTheme("go-previous"); + if(isRTL) { + ui.actionGoBack->setIcon(nxtIcn); + ui.actionCloseLeft->setIcon(nxtIcn); + ui.actionGoForward->setIcon(prevIcn); + ui.actionCloseRight->setIcon(prevIcn); + } + else { + ui.actionGoBack->setIcon(prevIcn); + ui.actionCloseLeft->setIcon(prevIcn); + ui.actionGoForward->setIcon(nxtIcn); + ui.actionCloseRight->setIcon(nxtIcn); + } } bool MainWindow::event(QEvent* event) { - switch(event->type()) { - case QEvent::WindowActivate: - lastActive_ = this; - default: - break; - } - return QMainWindow::event(event); + switch(event->type()) { + case QEvent::WindowActivate: + lastActive_ = this; + default: + break; + } + return QMainWindow::event(event); } -void MainWindow::changeEvent(QEvent *event) { - switch(event->type()) { +void MainWindow::changeEvent(QEvent* event) { + switch(event->type()) { case QEvent::LayoutDirectionChange: - setRTLIcons(QApplication::layoutDirection() == Qt::RightToLeft); - break; + setRTLIcons(QApplication::layoutDirection() == Qt::RightToLeft); + break; default: - break; - } - QWidget::changeEvent(event); + break; + } + QWidget::changeEvent(event); } void MainWindow::onBackForwardContextMenu(QPoint pos) { - // show a popup menu for browsing history here. - QToolButton* btn = static_cast(sender()); - TabPage* page = currentPage(); - Fm::BrowseHistory& history = page->browseHistory(); - int current = history.currentIndex(); - QMenu menu; - for(int i = 0; i < history.size(); ++i) { - const BrowseHistoryItem& item = history.at(i); - Fm::Path path = item.path(); - char* name = path.displayName(true); - QAction* action = menu.addAction(QString::fromUtf8(name)); - g_free(name); - if(i == current) { - // make the current path bold and checked - action->setCheckable(true); - action->setChecked(true); - QFont font = menu.font(); - font.setBold(true); - action->setFont(font); - } - } - QAction* selectedAction = menu.exec(btn->mapToGlobal(pos)); - if(selectedAction) { - int index = menu.actions().indexOf(selectedAction); - ui.filterBar->clear(); - page->jumpToHistory(index); - updateUIForCurrentPage(); - } + // show a popup menu for browsing history here. + QToolButton* btn = static_cast(sender()); + TabPage* page = currentPage(); + Fm::BrowseHistory& history = page->browseHistory(); + int current = history.currentIndex(); + QMenu menu; + for(int i = 0; i < history.size(); ++i) { + const BrowseHistoryItem& item = history.at(i); + auto path = item.path(); + auto name = path.displayName(); + QAction* action = menu.addAction(name.get()); + if(i == current) { + // make the current path bold and checked + action->setCheckable(true); + action->setChecked(true); + QFont font = menu.font(); + font.setBold(true); + action->setFont(font); + } + } + QAction* selectedAction = menu.exec(btn->mapToGlobal(pos)); + if(selectedAction) { + int index = menu.actions().indexOf(selectedAction); + ui.filterBar->clear(); + page->jumpToHistory(index); + updateUIForCurrentPage(); + } } void MainWindow::tabContextMenu(const QPoint& pos) { - int tabNum = ui.tabBar->count(); - if(tabNum <= 1) return; + int tabNum = ui.tabBar->count(); + if(tabNum <= 1) { + return; + } - rightClickIndex_ = ui.tabBar->tabAt(pos); - if(rightClickIndex_ < 0) return; + rightClickIndex_ = ui.tabBar->tabAt(pos); + if(rightClickIndex_ < 0) { + return; + } - QMenu menu; - if(rightClickIndex_ > 0) - menu.addAction(ui.actionCloseLeft); - if(rightClickIndex_ < tabNum - 1) { - menu.addAction(ui.actionCloseRight); + QMenu menu; if(rightClickIndex_ > 0) { - menu.addSeparator(); - menu.addAction(ui.actionCloseOther); + menu.addAction(ui.actionCloseLeft); } - } - menu.exec(ui.tabBar->mapToGlobal(pos)); + if(rightClickIndex_ < tabNum - 1) { + menu.addAction(ui.actionCloseRight); + if(rightClickIndex_ > 0) { + menu.addSeparator(); + menu.addAction(ui.actionCloseOther); + } + } + menu.exec(ui.tabBar->mapToGlobal(pos)); } void MainWindow::closeLeftTabs() { - while(rightClickIndex_ > 0) { - closeTab(rightClickIndex_ - 1); - --rightClickIndex_; - } + while(rightClickIndex_ > 0) { + closeTab(rightClickIndex_ - 1); + --rightClickIndex_; + } } void MainWindow::closeRightTabs() { - if(rightClickIndex_ < 0) return; - while(rightClickIndex_ < ui.tabBar->count() - 1) - closeTab(rightClickIndex_ + 1); + if(rightClickIndex_ < 0) { + return; + } + while(rightClickIndex_ < ui.tabBar->count() - 1) { + closeTab(rightClickIndex_ + 1); + } } void MainWindow::focusPathEntry() { - // use text entry for the path bar - if(pathEntry_ != nullptr) { - pathEntry_->setFocus(); - pathEntry_->selectAll(); - } - else if (pathBar_ != nullptr) { // use button-style path bar - pathBar_->openEditor(); - } + // use text entry for the path bar + if(pathEntry_ != nullptr) { + pathEntry_->setFocus(); + pathEntry_->selectAll(); + } + else if(pathBar_ != nullptr) { // use button-style path bar + pathBar_->openEditor(); + } } void MainWindow::updateFromSettings(Settings& settings) { - // apply settings - - // menu - ui.actionDelete->setText(settings.useTrash() ? tr("&Move to Trash") : tr("&Delete")); - ui.actionDelete->setIcon(settings.useTrash() ? QIcon::fromTheme("user-trash") : QIcon::fromTheme("edit-delete")); - - // side pane - ui.sidePane->setIconSize(QSize(settings.sidePaneIconSize(), settings.sidePaneIconSize())); - - // tabs - ui.tabBar->setTabsClosable(settings.showTabClose()); - ui.tabBar->setVisible(settings.alwaysShowTabs() || (ui.tabBar->count() > 1)); - if(ui.verticalLayout->indexOf(ui.tabBar) > -1) { - if(!settings.fullWidthTabBar()) { - ui.verticalLayout->removeWidget(ui.tabBar); - ui.verticalLayout_2->insertWidget(0, ui.tabBar); + // apply settings + + // menu + ui.actionDelete->setText(settings.useTrash() ? tr("&Move to Trash") : tr("&Delete")); + ui.actionDelete->setIcon(settings.useTrash() ? QIcon::fromTheme("user-trash") : QIcon::fromTheme("edit-delete")); + + // side pane + ui.sidePane->setIconSize(QSize(settings.sidePaneIconSize(), settings.sidePaneIconSize())); + + // tabs + ui.tabBar->setTabsClosable(settings.showTabClose()); + ui.tabBar->setVisible(settings.alwaysShowTabs() || (ui.tabBar->count() > 1)); + if(ui.verticalLayout->indexOf(ui.tabBar) > -1) { + if(!settings.fullWidthTabBar()) { + ui.verticalLayout->removeWidget(ui.tabBar); + ui.verticalLayout_2->insertWidget(0, ui.tabBar); + } + } + else if(ui.verticalLayout_2->indexOf(ui.tabBar) > -1 && settings.fullWidthTabBar()) { + ui.verticalLayout_2->removeWidget(ui.tabBar); + ui.verticalLayout->insertWidget(0, ui.tabBar); } - } - else if (ui.verticalLayout_2->indexOf(ui.tabBar) > -1 && settings.fullWidthTabBar()) { - ui.verticalLayout_2->removeWidget(ui.tabBar); - ui.verticalLayout->insertWidget(0, ui.tabBar); - } - // all tab pages - int n = ui.stackedWidget->count(); + // all tab pages + int n = ui.stackedWidget->count(); - for(int i = 0; i < n; ++i) { - TabPage* page = static_cast(ui.stackedWidget->widget(i)); - page->updateFromSettings(settings); - } + for(int i = 0; i < n; ++i) { + TabPage* page = static_cast(ui.stackedWidget->widget(i)); + page->updateFromSettings(settings); + } } static const char* su_cmd_subst(char opt, gpointer user_data) { - return (const char*)user_data; + return (const char*)user_data; } static FmAppCommandParseOption su_cmd_opts[] = { - { 's', su_cmd_subst }, - { 0, NULL } + { 's', su_cmd_subst }, + { 0, nullptr } }; void MainWindow::on_actionOpenAsRoot_triggered() { - TabPage* page = currentPage(); + TabPage* page = currentPage(); + + if(page) { + Application* app = static_cast(qApp); + Settings& settings = app->settings(); + + if(!settings.suCommand().isEmpty()) { + // run the su command + // FIXME: it's better to get the filename of the current process rather than hard-code pcmanfm-qt here. + QByteArray suCommand = settings.suCommand().toLocal8Bit(); + char* cmd = nullptr; + QByteArray programCommand = app->applicationFilePath().toLocal8Bit(); + programCommand += " %U"; + + if(fm_app_command_parse(suCommand.constData(), su_cmd_opts, &cmd, gpointer(programCommand.constData())) == 0) { + /* no %s found so just append to it */ + g_free(cmd); + cmd = g_strconcat(suCommand.constData(), programCommand.constData(), nullptr); + } + + Fm::GAppInfoPtr appInfo{g_app_info_create_from_commandline(cmd, nullptr, GAppInfoCreateFlags(0), nullptr), false}; + g_free(cmd); + + if(appInfo) { + auto cwd = page->path(); + Fm::GErrorPtr err; + auto uri = cwd.uri(); + GList* uris = g_list_prepend(nullptr, uri.get()); + + if(!g_app_info_launch_uris(appInfo.get(), uris, nullptr, &err)) { + QMessageBox::critical(this, tr("Error"), QString::fromUtf8(err->message)); + } + + g_list_free(uris); + } + } + else { + // show an error message and ask the user to set the command + QMessageBox::critical(this, tr("Error"), tr("Switch user command is not set.")); + app->preferences("advanced"); + } + } +} - if(page) { +void MainWindow::on_actionFindFiles_triggered() { Application* app = static_cast(qApp); - Settings& settings = app->settings(); - - if(!settings.suCommand().isEmpty()) { - // run the su command - // FIXME: it's better to get the filename of the current process rather than hard-code pcmanfm-qt here. - QByteArray suCommand = settings.suCommand().toLocal8Bit(); - char* cmd = NULL; - QByteArray programCommand = app->applicationFilePath().toLocal8Bit(); - programCommand += " %U"; - - if(fm_app_command_parse(suCommand.constData(), su_cmd_opts, &cmd, gpointer(programCommand.constData())) == 0) { - /* no %s found so just append to it */ - g_free(cmd); - cmd = g_strconcat(suCommand.constData(), programCommand.constData(), NULL); - } - - GAppInfo* appInfo = g_app_info_create_from_commandline(cmd, NULL, GAppInfoCreateFlags(0), NULL); - g_free(cmd); - - if(appInfo) { - Fm::Path cwd = page->path(); - GError* err = NULL; - char* uri = cwd.toUri(); - GList* uris = g_list_prepend(NULL, uri); - - if(!g_app_info_launch_uris(appInfo, uris, NULL, &err)) { - QMessageBox::critical(this, tr("Error"), QString::fromUtf8(err->message)); - g_error_free(err); + auto selectedPaths = currentPage()->selectedFilePaths(); + QStringList paths; + if(!selectedPaths.empty()) { + for(auto& path: selectedPaths) { + // FIXME: is it ok to use display name here? + // This might be broken on filesystems with non-UTF-8 filenames. + paths.append(path.displayName().get()); } - - g_list_free(uris); - g_free(uri); - g_object_unref(appInfo); - } } else { - // show an error message and ask the user to set the command - QMessageBox::critical(this, tr("Error"), tr("Switch user command is not set.")); - app->preferences("advanced"); + paths.append(currentPage()->pathName()); } - } -} - -void MainWindow::on_actionFindFiles_triggered() { - Application* app = static_cast(qApp); - Fm::PathList selectedPaths = currentPage()->selectedFilePaths(); - QStringList paths; - if(!selectedPaths.isNull()) { - for(GList* l = fm_path_list_peek_head_link(selectedPaths); l; l = l->next) { - // FIXME: is it ok to use display name here? - // This might be broken on filesystems with non-UTF-8 filenames. - Fm::Path path(FM_PATH(l->data)); - paths.append(path.displayName(false)); - } - } - else { - paths.append(currentPage()->pathName()); - } - app->findFiles(paths); + app->findFiles(paths); } void MainWindow::on_actionOpenTerminal_triggered() { - TabPage* page = currentPage(); - if(page) { - Application* app = static_cast(qApp); - app->openFolderInTerminal(page->path()); - } + TabPage* page = currentPage(); + if(page) { + Application* app = static_cast(qApp); + app->openFolderInTerminal(page->path()); + } } void MainWindow::onShortcutNextTab() { - int current = ui.tabBar->currentIndex(); - if(current < ui.tabBar->count() - 1) - ui.tabBar->setCurrentIndex(current + 1); - else - ui.tabBar->setCurrentIndex(0); + int current = ui.tabBar->currentIndex(); + if(current < ui.tabBar->count() - 1) { + ui.tabBar->setCurrentIndex(current + 1); + } + else { + ui.tabBar->setCurrentIndex(0); + } } void MainWindow::onShortcutPrevTab() { - int current = ui.tabBar->currentIndex(); - if(current > 0) - ui.tabBar->setCurrentIndex(current - 1); - else - ui.tabBar->setCurrentIndex(ui.tabBar->count() - 1); + int current = ui.tabBar->currentIndex(); + if(current > 0) { + ui.tabBar->setCurrentIndex(current - 1); + } + else { + ui.tabBar->setCurrentIndex(ui.tabBar->count() - 1); + } } // Switch to nth tab when Alt+n or Ctrl+n is pressed void MainWindow::onShortcutJumpToTab() { - QShortcut* shortcut = reinterpret_cast(sender()); - QKeySequence seq = shortcut->key(); - int keyValue = seq[0]; - // See the source code of QKeySequence and refer to the method: - // QString QKeySequencePrivate::encodeString(int key, QKeySequence::SequenceFormat format). - // Then we know how to test if a key sequence contains a modifier. - // It's a shame that Qt has no API for this task. - - if((keyValue & Qt::ALT) == Qt::ALT) // test if we have Alt key pressed - keyValue -= Qt::ALT; - else if((keyValue & Qt::CTRL) == Qt::CTRL) // test if we have Ctrl key pressed - keyValue -= Qt::CTRL; - - // now keyValue should contains '0' - '9' only - int index; - if(keyValue == '0') - index = 9; - else - index = keyValue - '1'; - if(index < ui.tabBar->count()) - ui.tabBar->setCurrentIndex(index); + QShortcut* shortcut = reinterpret_cast(sender()); + QKeySequence seq = shortcut->key(); + int keyValue = seq[0]; + // See the source code of QKeySequence and refer to the method: + // QString QKeySequencePrivate::encodeString(int key, QKeySequence::SequenceFormat format). + // Then we know how to test if a key sequence contains a modifier. + // It's a shame that Qt has no API for this task. + + if((keyValue & Qt::ALT) == Qt::ALT) { // test if we have Alt key pressed + keyValue -= Qt::ALT; + } + else if((keyValue & Qt::CTRL) == Qt::CTRL) { // test if we have Ctrl key pressed + keyValue -= Qt::CTRL; + } + + // now keyValue should contains '0' - '9' only + int index; + if(keyValue == '0') { + index = 9; + } + else { + index = keyValue - '1'; + } + if(index < ui.tabBar->count()) { + ui.tabBar->setCurrentIndex(index); + } } } diff --git a/pcmanfm/mainwindow.h b/pcmanfm/mainwindow.h index 3d21ffd..1cf4543 100644 --- a/pcmanfm/mainwindow.h +++ b/pcmanfm/mainwindow.h @@ -32,12 +32,13 @@ #include #include #include "launcher.h" -#include #include +#include +#include namespace Fm { - class PathEdit; - class PathBar; +class PathEdit; +class PathBar; } namespace PCManFM { @@ -46,162 +47,163 @@ class TabPage; class Settings; class MainWindow : public QMainWindow { -Q_OBJECT + Q_OBJECT public: - MainWindow(Fm::Path path = Fm::Path()); - virtual ~MainWindow(); + MainWindow(Fm::FilePath path = Fm::FilePath()); + virtual ~MainWindow(); - void chdir(Fm::Path path); - int addTab(Fm::Path path); + void chdir(Fm::FilePath path); + int addTab(Fm::FilePath path); - TabPage* currentPage() { - return reinterpret_cast(ui.stackedWidget->currentWidget()); - } + TabPage* currentPage() { + return reinterpret_cast(ui.stackedWidget->currentWidget()); + } - void updateFromSettings(Settings& settings); + void updateFromSettings(Settings& settings); - static MainWindow* lastActive() { - return lastActive_; - } + static MainWindow* lastActive() { + return lastActive_; + } protected Q_SLOTS: - void onPathEntryReturnPressed(); - void onPathEntryEdited(const QString& text); - void onPathBarChdir(FmPath* dirPath); - void onPathBarMiddleClickChdir(FmPath* dirPath); - - void on_actionNewTab_triggered(); - void on_actionNewWin_triggered(); - void on_actionNewFolder_triggered(); - void on_actionNewBlankFile_triggered(); - void on_actionCloseTab_triggered(); - void on_actionCloseWindow_triggered(); - void on_actionFileProperties_triggered(); - void on_actionFolderProperties_triggered(); - - void on_actionCut_triggered(); - void on_actionCopy_triggered(); - void on_actionPaste_triggered(); - void on_actionDelete_triggered(); - void on_actionRename_triggered(); - void on_actionSelectAll_triggered(); - void on_actionInvertSelection_triggered(); - void on_actionPreferences_triggered(); - - void on_actionGoBack_triggered(); - void on_actionGoForward_triggered(); - void on_actionGoUp_triggered(); - void on_actionHome_triggered(); - void on_actionReload_triggered(); - void on_actionConnectToServer_triggered(); - - void on_actionIconView_triggered(); - void on_actionCompactView_triggered(); - void on_actionDetailedList_triggered(); - void on_actionThumbnailView_triggered(); - - void on_actionGo_triggered(); - void on_actionShowHidden_triggered(bool check); - void on_actionPreserveView_triggered(bool checked); - - void on_actionByFileName_triggered(bool checked); - void on_actionByMTime_triggered(bool checked); - void on_actionByOwner_triggered(bool checked); - void on_actionByFileType_triggered(bool checked); - void on_actionByFileSize_triggered(bool checked); - void on_actionAscending_triggered(bool checked); - void on_actionDescending_triggered(bool checked); - void on_actionFolderFirst_triggered(bool checked); - void on_actionCaseSensitive_triggered(bool checked); - void on_actionFilter_triggered(bool checked); - - void on_actionLocationBar_triggered(bool checked); - void on_actionPathButtons_triggered(bool checked); - - void on_actionApplications_triggered(); - void on_actionComputer_triggered(); - void on_actionTrash_triggered(); - void on_actionNetwork_triggered(); - void on_actionDesktop_triggered(); - void on_actionAddToBookmarks_triggered(); - void on_actionEditBookmarks_triggered(); - - void on_actionOpenTerminal_triggered(); - void on_actionOpenAsRoot_triggered(); - void on_actionFindFiles_triggered(); - - void on_actionAbout_triggered(); - - void onBookmarkActionTriggered(); - - void onTabBarCloseRequested(int index); - void onTabBarCurrentChanged(int index); - void onTabBarTabMoved(int from, int to); - - void focusFilterBar(); - void onFilterStringChanged(QString str); - - void onShortcutPrevTab(); - void onShortcutNextTab(); - void onShortcutJumpToTab(); - - void onStackedWidgetWidgetRemoved(int index); - - void onTabPageTitleChanged(QString title); - void onTabPageStatusChanged(int type, QString statusText); - void onTabPageOpenDirRequested(FmPath* path, int target); - void onTabPageSortFilterChanged(); - - void onSidePaneChdirRequested(int type, FmPath* path); - void onSidePaneOpenFolderInNewWindowRequested(FmPath* path); - void onSidePaneOpenFolderInNewTabRequested(FmPath* path); - void onSidePaneOpenFolderInTerminalRequested(FmPath* path); - void onSidePaneCreateNewFolderRequested(FmPath* path); - void onSidePaneModeChanged(Fm::SidePane::Mode mode); - void onSplitterMoved(int pos, int index); - void onResetFocus(); - - void onBackForwardContextMenu(QPoint pos); - - void tabContextMenu(const QPoint& pos); - void closeLeftTabs(); - void closeRightTabs(); - void closeOtherTabs() { - closeLeftTabs(); - closeRightTabs(); - } - void focusPathEntry(); - void toggleMenuBar(bool checked); + void onPathEntryReturnPressed(); + void onPathBarChdir(const Fm::FilePath& dirPath); + void onPathBarMiddleClickChdir(const Fm::FilePath &dirPath); + + void on_actionNewTab_triggered(); + void on_actionNewWin_triggered(); + void on_actionNewFolder_triggered(); + void on_actionNewBlankFile_triggered(); + void on_actionCloseTab_triggered(); + void on_actionCloseWindow_triggered(); + void on_actionFileProperties_triggered(); + void on_actionFolderProperties_triggered(); + + void on_actionCut_triggered(); + void on_actionCopy_triggered(); + void on_actionPaste_triggered(); + void on_actionDelete_triggered(); + void on_actionRename_triggered(); + void on_actionSelectAll_triggered(); + void on_actionInvertSelection_triggered(); + void on_actionPreferences_triggered(); + + void on_actionGoBack_triggered(); + void on_actionGoForward_triggered(); + void on_actionGoUp_triggered(); + void on_actionHome_triggered(); + void on_actionReload_triggered(); + void on_actionConnectToServer_triggered(); + + void on_actionIconView_triggered(); + void on_actionCompactView_triggered(); + void on_actionDetailedList_triggered(); + void on_actionThumbnailView_triggered(); + + void on_actionGo_triggered(); + void on_actionShowHidden_triggered(bool check); + void on_actionPreserveView_triggered(bool checked); + + void on_actionByFileName_triggered(bool checked); + void on_actionByMTime_triggered(bool checked); + void on_actionByOwner_triggered(bool checked); + void on_actionByFileType_triggered(bool checked); + void on_actionByFileSize_triggered(bool checked); + void on_actionAscending_triggered(bool checked); + void on_actionDescending_triggered(bool checked); + void on_actionFolderFirst_triggered(bool checked); + void on_actionCaseSensitive_triggered(bool checked); + void on_actionFilter_triggered(bool checked); + + void on_actionLocationBar_triggered(bool checked); + void on_actionPathButtons_triggered(bool checked); + + void on_actionApplications_triggered(); + void on_actionComputer_triggered(); + void on_actionTrash_triggered(); + void on_actionNetwork_triggered(); + void on_actionDesktop_triggered(); + void on_actionAddToBookmarks_triggered(); + void on_actionEditBookmarks_triggered(); + + void on_actionOpenTerminal_triggered(); + void on_actionOpenAsRoot_triggered(); + void on_actionFindFiles_triggered(); + + void on_actionAbout_triggered(); + + void onBookmarkActionTriggered(); + + void onTabBarCloseRequested(int index); + void onTabBarCurrentChanged(int index); + void onTabBarTabMoved(int from, int to); + + void focusFilterBar(); + void onFilterStringChanged(QString str); + + void onShortcutPrevTab(); + void onShortcutNextTab(); + void onShortcutJumpToTab(); + + void onStackedWidgetWidgetRemoved(int index); + + void onTabPageTitleChanged(QString title); + void onTabPageStatusChanged(int type, QString statusText); + void onTabPageOpenDirRequested(const Fm::FilePath &path, int target); + void onTabPageSortFilterChanged(); + + void onSidePaneChdirRequested(int type, const Fm::FilePath &path); + void onSidePaneOpenFolderInNewWindowRequested(const Fm::FilePath &path); + void onSidePaneOpenFolderInNewTabRequested(const Fm::FilePath &path); + void onSidePaneOpenFolderInTerminalRequested(const Fm::FilePath &path); + void onSidePaneCreateNewFolderRequested(const Fm::FilePath &path); + void onSidePaneModeChanged(Fm::SidePane::Mode mode); + void onSplitterMoved(int pos, int index); + void onResetFocus(); + + void onBackForwardContextMenu(QPoint pos); + + void tabContextMenu(const QPoint& pos); + void closeLeftTabs(); + void closeRightTabs(); + void closeOtherTabs() { + closeLeftTabs(); + closeRightTabs(); + } + void focusPathEntry(); + void toggleMenuBar(bool checked); + + void onBookmarksChanged(); protected: - bool event(QEvent* event) override; - void changeEvent(QEvent *event) override; - void closeTab(int index); - virtual void resizeEvent(QResizeEvent *event) override; - virtual void closeEvent(QCloseEvent *event) override; + bool event(QEvent* event) override; + void changeEvent(QEvent* event) override; + void closeTab(int index); + virtual void resizeEvent(QResizeEvent* event) override; + virtual void closeEvent(QCloseEvent* event) override; private: - static void onBookmarksChanged(FmBookmarks* bookmarks_, MainWindow* pThis); - void loadBookmarksMenu(); - void updateUIForCurrentPage(); - void updateViewMenuForCurrentPage(); - void updateStatusBarForCurrentPage(); - void setRTLIcons(bool isRTL); - void createPathBar(bool usePathButtons); + void loadBookmarksMenu(); + void updateUIForCurrentPage(); + void updateViewMenuForCurrentPage(); + void updateEditSelectedActions(); + void updateStatusBarForCurrentPage(); + void setRTLIcons(bool isRTL); + void createPathBar(bool usePathButtons); private: - Ui::MainWindow ui; - Fm::PathEdit* pathEntry_; - Fm::PathBar* pathBar_; - QLabel* fsInfoLabel_; - Fm::Bookmarks bookmarks_; - Launcher fileLauncher_; - int rightClickIndex_; - bool updatingViewMenu_; - QAction* menuSep_; - - static MainWindow* lastActive_; + Ui::MainWindow ui; + Fm::PathEdit* pathEntry_; + Fm::PathBar* pathBar_; + QLabel* fsInfoLabel_; + std::shared_ptr bookmarks_; + Launcher fileLauncher_; + int rightClickIndex_; + bool updatingViewMenu_; + QAction* menuSep_; + + static MainWindow* lastActive_; }; } diff --git a/pcmanfm/pcmanfm.cpp b/pcmanfm/pcmanfm.cpp index a17d774..ea3bacd 100644 --- a/pcmanfm/pcmanfm.cpp +++ b/pcmanfm/pcmanfm.cpp @@ -3,11 +3,13 @@ #include int main(int argc, char** argv) { - // ensure that glib integration of Qt is not turned off - // This fixes #168: https://github.com/lxde/pcmanfm-qt/issues/168 - qunsetenv("QT_NO_GLIB"); + // ensure that glib integration of Qt is not turned off + // This fixes #168: https://github.com/lxde/pcmanfm-qt/issues/168 + qunsetenv("QT_NO_GLIB"); - PCManFM::Application app(argc, argv); - app.init(); - return app.exec(); + PCManFM::Application app(argc, argv); + app.setAttribute(Qt::AA_UseHighDpiPixmaps, true); + + app.init(); + return app.exec(); } diff --git a/pcmanfm/preferencesdialog.cpp b/pcmanfm/preferencesdialog.cpp index b2c48d5..da4095e 100644 --- a/pcmanfm/preferencesdialog.cpp +++ b/pcmanfm/preferencesdialog.cpp @@ -27,26 +27,23 @@ #include #include +#include namespace PCManFM { -static int bigIconSizes[] = {96, 72, 64, 48, 36, 32, 24, 20}; -static int smallIconSizes[] = {48, 36, 32, 24, 20, 16, 12}; -static int thumbnailIconSizes[] = {256, 224, 192, 160, 128, 96, 64}; +PreferencesDialog::PreferencesDialog(QString activePage, QWidget* parent): + QDialog(parent) { + ui.setupUi(this); + setAttribute(Qt::WA_DeleteOnClose); -PreferencesDialog::PreferencesDialog (QString activePage, QWidget* parent): - QDialog (parent) { - ui.setupUi(this); - setAttribute(Qt::WA_DeleteOnClose); + // resize the list widget according to the width of its content. + ui.listWidget->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding); + ui.listWidget->setMaximumWidth(ui.listWidget->sizeHintForColumn(0) + ui.listWidget->frameWidth() * 2 + 4); - // resize the list widget according to the width of its content. - ui.listWidget->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding); - ui.listWidget->setMaximumWidth(ui.listWidget->sizeHintForColumn(0) + ui.listWidget->frameWidth() * 2 + 4); + initFromSettings(); - initFromSettings(); - - selectPage(activePage); - adjustSize(); + selectPage(activePage); + adjustSize(); } PreferencesDialog::~PreferencesDialog() { @@ -54,106 +51,115 @@ PreferencesDialog::~PreferencesDialog() { } static void findIconThemesInDir(QHash& iconThemes, QString dirName) { - QDir dir(dirName); - QStringList subDirs = dir.entryList(QDir::AllDirs); - GKeyFile* kf = g_key_file_new(); - Q_FOREACH(QString subDir, subDirs) { - QString indexFile = dirName % '/' % subDir % "/index.theme"; - if(g_key_file_load_from_file(kf, indexFile.toLocal8Bit().constData(), GKeyFileFlags(0), NULL)) { - // FIXME: skip hidden ones - // icon theme must have this key, so it has icons if it has this key - // otherwise, it might be a cursor theme or any other kind of theme. - if(g_key_file_has_key(kf, "Icon Theme", "Directories", NULL)) { - char* dispName = g_key_file_get_locale_string(kf, "Icon Theme", "Name", NULL, NULL); - // char* comment = g_key_file_get_locale_string(kf, "Icon Theme", "Comment", NULL, NULL); - iconThemes[subDir] = dispName; - g_free(dispName); - } + QDir dir(dirName); + QStringList subDirs = dir.entryList(QDir::AllDirs); + GKeyFile* kf = g_key_file_new(); + Q_FOREACH(QString subDir, subDirs) { + QString indexFile = dirName % '/' % subDir % "/index.theme"; + if(g_key_file_load_from_file(kf, indexFile.toLocal8Bit().constData(), GKeyFileFlags(0), nullptr)) { + // FIXME: skip hidden ones + // icon theme must have this key, so it has icons if it has this key + // otherwise, it might be a cursor theme or any other kind of theme. + if(g_key_file_has_key(kf, "Icon Theme", "Directories", nullptr)) { + char* dispName = g_key_file_get_locale_string(kf, "Icon Theme", "Name", nullptr, nullptr); + // char* comment = g_key_file_get_locale_string(kf, "Icon Theme", "Comment", nullptr, nullptr); + iconThemes[subDir] = dispName; + g_free(dispName); + } + } } - } - g_key_file_free(kf); + g_key_file_free(kf); } void PreferencesDialog::initIconThemes(Settings& settings) { - // check if auto-detection is done (for example, from xsettings) - if(settings.useFallbackIconTheme()) { // auto-detection failed - // load xdg icon themes and select the current one - QHash iconThemes; - // user customed icon themes - findIconThemesInDir(iconThemes, QString(g_get_home_dir()) % "/.icons"); - - // search for icons in system data dir - const char* const* dataDirs = g_get_system_data_dirs(); - for(const char* const* dataDir = dataDirs; *dataDir; ++dataDir) { - findIconThemesInDir(iconThemes, QString(*dataDir) % "/icons"); - } - - iconThemes.remove("hicolor"); // remove hicolor, which is only a fallback - QHash::const_iterator it; - for(it = iconThemes.begin(); it != iconThemes.end(); ++it) { - ui.iconTheme->addItem(it.value(), it.key()); + // check if auto-detection is done (for example, from xsettings) + if(settings.useFallbackIconTheme()) { // auto-detection failed + // load xdg icon themes and select the current one + QHash iconThemes; + // user customed icon themes + findIconThemesInDir(iconThemes, QString(g_get_home_dir()) % "/.icons"); + + // search for icons in system data dir + const char* const* dataDirs = g_get_system_data_dirs(); + for(const char* const* dataDir = dataDirs; *dataDir; ++dataDir) { + findIconThemesInDir(iconThemes, QString(*dataDir) % "/icons"); + } + + iconThemes.remove("hicolor"); // remove hicolor, which is only a fallback + QHash::const_iterator it; + for(it = iconThemes.constBegin(); it != iconThemes.constEnd(); ++it) { + ui.iconTheme->addItem(it.value(), it.key()); + } + ui.iconTheme->model()->sort(0); // sort the list of icon theme names + + // select current theme name + int n = ui.iconTheme->count(); + int i; + for(i = 0; i < n; ++i) { + QVariant itemData = ui.iconTheme->itemData(i); + if(itemData == settings.fallbackIconThemeName()) { + break; + } + } + if(i >= n) { + i = 0; + } + ui.iconTheme->setCurrentIndex(i); } - ui.iconTheme->model()->sort(0); // sort the list of icon theme names - - // select current theme name - int n = ui.iconTheme->count(); - int i; - for(i = 0; i < n; ++i) { - QVariant itemData = ui.iconTheme->itemData(i); - if(itemData == settings.fallbackIconThemeName()) { - break; - } + else { // auto-detection of icon theme works, hide the fallback icon theme combo box. + ui.iconThemeLabel->hide(); + ui.iconTheme->hide(); } - if(i >= n) - i = 0; - ui.iconTheme->setCurrentIndex(i); - } - else { // auto-detection of icon theme works, hide the fallback icon theme combo box. - ui.iconThemeLabel->hide(); - ui.iconTheme->hide(); - } - - ui.hMargin->setValue(settings.folderViewCellMargins().width()); - ui.vMargin->setValue(settings.folderViewCellMargins().height()); - connect(ui.lockMargins, &QAbstractButton::clicked, this, &PreferencesDialog::lockMargins); + + ui.hMargin->setValue(settings.folderViewCellMargins().width()); + ui.vMargin->setValue(settings.folderViewCellMargins().height()); + connect(ui.lockMargins, &QAbstractButton::clicked, this, &PreferencesDialog::lockMargins); } void PreferencesDialog::initArchivers(Settings& settings) { - const GList* allArchivers = fm_archiver_get_all(); - int i = 0; - for(const GList* l = allArchivers; l; l = l->next, ++i) { - FmArchiver* archiver = reinterpret_cast(l->data); - ui.archiver->addItem(archiver->program, QString(archiver->program)); - if(archiver->program == settings.archiver()) - ui.archiver->setCurrentIndex(i); - } + const GList* allArchivers = fm_archiver_get_all(); + int i = 0; + for(const GList* l = allArchivers; l; l = l->next, ++i) { + FmArchiver* archiver = reinterpret_cast(l->data); + ui.archiver->addItem(archiver->program, QString(archiver->program)); + if(archiver->program == settings.archiver()) { + ui.archiver->setCurrentIndex(i); + } + } } void PreferencesDialog::initDisplayPage(Settings& settings) { initIconThemes(settings); // icon sizes - for(std::size_t i = 0; i < G_N_ELEMENTS(bigIconSizes); ++i) { - int size = bigIconSizes[i]; - ui.bigIconSize->addItem(QString("%1 x %1").arg(size), size); - if(settings.bigIconSize() == size) - ui.bigIconSize->setCurrentIndex(i); + int i = 0; + for (const auto & size : Settings::iconSizes(Settings::Big)) { + ui.bigIconSize->addItem(QString("%1 x %1").arg(size), size); + if(settings.bigIconSize() == size) { + ui.bigIconSize->setCurrentIndex(i); + } + ++i; } - for(std::size_t i = 0; i < G_N_ELEMENTS(smallIconSizes); ++i) { - int size = smallIconSizes[i]; - QString text = QString("%1 x %1").arg(size); - ui.smallIconSize->addItem(text, size); - if(settings.smallIconSize() == size) - ui.smallIconSize->setCurrentIndex(i); - - ui.sidePaneIconSize->addItem(text, size); - if(settings.sidePaneIconSize() == size) - ui.sidePaneIconSize->setCurrentIndex(i); + i = 0; + for (const auto & size : Settings::iconSizes(Settings::Small)) { + QString text = QString("%1 x %1").arg(size); + ui.smallIconSize->addItem(text, size); + if(settings.smallIconSize() == size) { + ui.smallIconSize->setCurrentIndex(i); + } + + ui.sidePaneIconSize->addItem(text, size); + if(settings.sidePaneIconSize() == size) { + ui.sidePaneIconSize->setCurrentIndex(i); + } + ++i; } - for(std::size_t i = 0; i < G_N_ELEMENTS(thumbnailIconSizes); ++i) { - int size = thumbnailIconSizes[i]; - ui.thumbnailIconSize->addItem(QString("%1 x %1").arg(size), size); - if(settings.thumbnailIconSize() == size) - ui.thumbnailIconSize->setCurrentIndex(i); + i = 0; + for (const auto & size : Settings::iconSizes(Settings::Thumbnail)) { + ui.thumbnailIconSize->addItem(QString("%1 x %1").arg(size), size); + if(settings.thumbnailIconSize() == size) { + ui.thumbnailIconSize->setCurrentIndex(i); + } + ++i; } ui.siUnit->setChecked(settings.siUnit()); @@ -168,218 +174,224 @@ void PreferencesDialog::initDisplayPage(Settings& settings) { } void PreferencesDialog::initUiPage(Settings& settings) { - ui.alwaysShowTabs->setChecked(settings.alwaysShowTabs()); - ui.fullWidthTabbar->setChecked(settings.fullWidthTabBar()); - ui.showTabClose->setChecked(settings.showTabClose()); - ui.rememberWindowSize->setChecked(settings.rememberWindowSize()); - ui.fixedWindowWidth->setValue(settings.fixedWindowWidth()); - ui.fixedWindowHeight->setValue(settings.fixedWindowHeight()); - - // FIXME: Hide options that we don't support yet. - ui.showInPlaces->parentWidget()->hide(); + ui.alwaysShowTabs->setChecked(settings.alwaysShowTabs()); + ui.fullWidthTabbar->setChecked(settings.fullWidthTabBar()); + ui.showTabClose->setChecked(settings.showTabClose()); + ui.rememberWindowSize->setChecked(settings.rememberWindowSize()); + ui.fixedWindowWidth->setValue(settings.fixedWindowWidth()); + ui.fixedWindowHeight->setValue(settings.fixedWindowHeight()); + + // FIXME: Hide options that we don't support yet. + ui.showInPlaces->parentWidget()->hide(); } void PreferencesDialog::initBehaviorPage(Settings& settings) { - ui.singleClick->setChecked(settings.singleClick()); - ui.autoSelectionDelay->setValue(double(settings.autoSelectionDelay()) / 1000); - - ui.bookmarkOpenMethod->setCurrentIndex(settings.bookmarkOpenMethod()); - - ui.viewMode->addItem(tr("Icon View"), (int)Fm::FolderView::IconMode); - ui.viewMode->addItem(tr("Compact View"), (int)Fm::FolderView::CompactMode); - ui.viewMode->addItem(tr("Thumbnail View"), (int)Fm::FolderView::ThumbnailMode); - ui.viewMode->addItem(tr("Detailed List View"), (int)Fm::FolderView::DetailedListMode); - const Fm::FolderView::ViewMode modes[] = { - Fm::FolderView::IconMode, - Fm::FolderView::CompactMode, - Fm::FolderView::ThumbnailMode, - Fm::FolderView::DetailedListMode - }; - for(std::size_t i = 0; i < G_N_ELEMENTS(modes); ++i) { - if(modes[i] == settings.viewMode()) { - ui.viewMode->setCurrentIndex(i); - break; + ui.singleClick->setChecked(settings.singleClick()); + ui.autoSelectionDelay->setValue(double(settings.autoSelectionDelay()) / 1000); + + ui.bookmarkOpenMethod->setCurrentIndex(settings.bookmarkOpenMethod()); + + ui.viewMode->addItem(tr("Icon View"), (int)Fm::FolderView::IconMode); + ui.viewMode->addItem(tr("Compact View"), (int)Fm::FolderView::CompactMode); + ui.viewMode->addItem(tr("Thumbnail View"), (int)Fm::FolderView::ThumbnailMode); + ui.viewMode->addItem(tr("Detailed List View"), (int)Fm::FolderView::DetailedListMode); + const Fm::FolderView::ViewMode modes[] = { + Fm::FolderView::IconMode, + Fm::FolderView::CompactMode, + Fm::FolderView::ThumbnailMode, + Fm::FolderView::DetailedListMode + }; + for(std::size_t i = 0; i < G_N_ELEMENTS(modes); ++i) { + if(modes[i] == settings.viewMode()) { + ui.viewMode->setCurrentIndex(i); + break; + } } - } - ui.configmDelete->setChecked(settings.confirmDelete()); + ui.configmDelete->setChecked(settings.confirmDelete()); - if(settings.supportTrash()) - ui.useTrash->setChecked(settings.useTrash()); - else { - ui.useTrash->hide(); - } + if(settings.supportTrash()) { + ui.useTrash->setChecked(settings.useTrash()); + } + else { + ui.useTrash->hide(); + } - ui.noUsbTrash->setChecked(settings.noUsbTrash()); - ui.confirmTrash->setChecked(settings.confirmTrash()); - ui.quickExec->setChecked(settings.quickExec()); + ui.noUsbTrash->setChecked(settings.noUsbTrash()); + ui.confirmTrash->setChecked(settings.confirmTrash()); + ui.quickExec->setChecked(settings.quickExec()); } void PreferencesDialog::initThumbnailPage(Settings& settings) { - ui.showThumbnails->setChecked(settings.showThumbnails()); - ui.thumbnailLocal->setChecked(settings.thumbnailLocalFilesOnly()); - ui.maxThumbnailFileSize->setValue(settings.maxThumbnailFileSize()); + ui.showThumbnails->setChecked(settings.showThumbnails()); + ui.thumbnailLocal->setChecked(settings.thumbnailLocalFilesOnly()); + ui.maxThumbnailFileSize->setValue(settings.maxThumbnailFileSize()); } void PreferencesDialog::initVolumePage(Settings& settings) { - ui.mountOnStartup->setChecked(settings.mountOnStartup()); - ui.mountRemovable->setChecked(settings.mountRemovable()); - ui.autoRun->setChecked(settings.autoRun()); - if(settings.closeOnUnmount()) - ui.closeOnUnmount->setChecked(true); - else - ui.goHomeOnUnmount->setChecked(true); + ui.mountOnStartup->setChecked(settings.mountOnStartup()); + ui.mountRemovable->setChecked(settings.mountRemovable()); + ui.autoRun->setChecked(settings.autoRun()); + if(settings.closeOnUnmount()) { + ui.closeOnUnmount->setChecked(true); + } + else { + ui.goHomeOnUnmount->setChecked(true); + } } void PreferencesDialog::initTerminals(Settings& settings) { - // load the known terminal list from the terminal.list file of libfm - QSettings termlist(LIBFM_DATA_DIR "/terminals.list", QSettings::IniFormat); - ui.terminal->addItems(termlist.childGroups()); - ui.terminal->setEditText(settings.terminal()); + // load the known terminal list from the terminal.list file of libfm + for(auto& terminal: Fm::allKnownTerminals()) { + ui.terminal->addItem(terminal.get()); + } + ui.terminal->setEditText(settings.terminal()); } void PreferencesDialog::initAdvancedPage(Settings& settings) { - initArchivers(settings); - initTerminals(settings); - ui.suCommand->setText(settings.suCommand()); + initArchivers(settings); + initTerminals(settings); + ui.suCommand->setText(settings.suCommand()); - ui.onlyUserTemplates->setChecked(settings.onlyUserTemplates()); - ui.templateTypeOnce->setChecked(settings.templateTypeOnce()); + ui.onlyUserTemplates->setChecked(settings.onlyUserTemplates()); + ui.templateTypeOnce->setChecked(settings.templateTypeOnce()); - ui.templateRunApp->setChecked(settings.templateRunApp()); + ui.templateRunApp->setChecked(settings.templateRunApp()); - // FIXME: Hide options that we don't support yet. - ui.templateRunApp->hide(); + // FIXME: Hide options that we don't support yet. + ui.templateRunApp->hide(); } void PreferencesDialog::initFromSettings() { - Settings& settings = static_cast(qApp)->settings(); - initDisplayPage(settings); - initUiPage(settings); - initBehaviorPage(settings); - initThumbnailPage(settings); - initVolumePage(settings); - initAdvancedPage(settings); + Settings& settings = static_cast(qApp)->settings(); + initDisplayPage(settings); + initUiPage(settings); + initBehaviorPage(settings); + initThumbnailPage(settings); + initVolumePage(settings); + initAdvancedPage(settings); } void PreferencesDialog::applyDisplayPage(Settings& settings) { - if(settings.useFallbackIconTheme()) { - // only apply the value if icon theme combo box is in use - // the combo box is hidden when auto-detection of icon theme from xsettings works. - QString newIconTheme = ui.iconTheme->itemData(ui.iconTheme->currentIndex()).toString(); - if(newIconTheme != settings.fallbackIconThemeName()) { - settings.setFallbackIconThemeName(newIconTheme); - QIcon::setThemeName(settings.fallbackIconThemeName()); - // update the UI by emitting a style change event - Q_FOREACH(QWidget *widget, QApplication::allWidgets()) { - QEvent event(QEvent::StyleChange); - QApplication::sendEvent(widget, &event); - } + if(settings.useFallbackIconTheme()) { + // only apply the value if icon theme combo box is in use + // the combo box is hidden when auto-detection of icon theme from xsettings works. + QString newIconTheme = ui.iconTheme->itemData(ui.iconTheme->currentIndex()).toString(); + if(newIconTheme != settings.fallbackIconThemeName()) { + settings.setFallbackIconThemeName(newIconTheme); + QIcon::setThemeName(settings.fallbackIconThemeName()); + // update the UI by emitting a style change event + Q_FOREACH(QWidget* widget, QApplication::allWidgets()) { + QEvent event(QEvent::StyleChange); + QApplication::sendEvent(widget, &event); + } + } } - } - - settings.setBigIconSize(ui.bigIconSize->itemData(ui.bigIconSize->currentIndex()).toInt()); - settings.setSmallIconSize(ui.smallIconSize->itemData(ui.smallIconSize->currentIndex()).toInt()); - settings.setThumbnailIconSize(ui.thumbnailIconSize->itemData(ui.thumbnailIconSize->currentIndex()).toInt()); - settings.setSidePaneIconSize(ui.sidePaneIconSize->itemData(ui.sidePaneIconSize->currentIndex()).toInt()); - - settings.setSiUnit(ui.siUnit->isChecked()); - settings.setBackupAsHidden(ui.backupAsHidden->isChecked()); - settings.setShowFullNames(ui.showFullNames->isChecked()); - settings.setShadowHidden(ui.shadowHidden->isChecked()); - settings.setFolderViewCellMargins(QSize(ui.hMargin->value(), ui.vMargin->value())); + + settings.setBigIconSize(ui.bigIconSize->itemData(ui.bigIconSize->currentIndex()).toInt()); + settings.setSmallIconSize(ui.smallIconSize->itemData(ui.smallIconSize->currentIndex()).toInt()); + settings.setThumbnailIconSize(ui.thumbnailIconSize->itemData(ui.thumbnailIconSize->currentIndex()).toInt()); + settings.setSidePaneIconSize(ui.sidePaneIconSize->itemData(ui.sidePaneIconSize->currentIndex()).toInt()); + + settings.setSiUnit(ui.siUnit->isChecked()); + settings.setBackupAsHidden(ui.backupAsHidden->isChecked()); + settings.setShowFullNames(ui.showFullNames->isChecked()); + settings.setShadowHidden(ui.shadowHidden->isChecked()); + settings.setFolderViewCellMargins(QSize(ui.hMargin->value(), ui.vMargin->value())); } void PreferencesDialog::applyUiPage(Settings& settings) { - settings.setAlwaysShowTabs(ui.alwaysShowTabs->isChecked()); - settings.setFullWidthTabBar(ui.fullWidthTabbar->isChecked()); - settings.setShowTabClose(ui.showTabClose->isChecked()); - settings.setRememberWindowSize(ui.rememberWindowSize->isChecked()); - settings.setFixedWindowWidth(ui.fixedWindowWidth->value()); - settings.setFixedWindowHeight(ui.fixedWindowHeight->value()); + settings.setAlwaysShowTabs(ui.alwaysShowTabs->isChecked()); + settings.setFullWidthTabBar(ui.fullWidthTabbar->isChecked()); + settings.setShowTabClose(ui.showTabClose->isChecked()); + settings.setRememberWindowSize(ui.rememberWindowSize->isChecked()); + settings.setFixedWindowWidth(ui.fixedWindowWidth->value()); + settings.setFixedWindowHeight(ui.fixedWindowHeight->value()); } void PreferencesDialog::applyBehaviorPage(Settings& settings) { - settings.setSingleClick(ui.singleClick->isChecked()); - settings.setAutoSelectionDelay(int(ui.autoSelectionDelay->value() * 1000)); + settings.setSingleClick(ui.singleClick->isChecked()); + settings.setAutoSelectionDelay(int(ui.autoSelectionDelay->value() * 1000)); - settings.setBookmarkOpenMethod(OpenDirTargetType(ui.bookmarkOpenMethod->currentIndex())); + settings.setBookmarkOpenMethod(OpenDirTargetType(ui.bookmarkOpenMethod->currentIndex())); - // FIXME: bug here? - Fm::FolderView::ViewMode mode = Fm::FolderView::ViewMode(ui.viewMode->itemData(ui.viewMode->currentIndex()).toInt()); - settings.setViewMode(mode); - settings.setConfirmDelete(ui.configmDelete->isChecked()); + // FIXME: bug here? + Fm::FolderView::ViewMode mode = Fm::FolderView::ViewMode(ui.viewMode->itemData(ui.viewMode->currentIndex()).toInt()); + settings.setViewMode(mode); + settings.setConfirmDelete(ui.configmDelete->isChecked()); - if(settings.supportTrash()) - settings.setUseTrash(ui.useTrash->isChecked()); + if(settings.supportTrash()) { + settings.setUseTrash(ui.useTrash->isChecked()); + } - settings.setNoUsbTrash(ui.noUsbTrash->isChecked()); - settings.setConfirmTrash(ui.confirmTrash->isChecked()); - settings.setQuickExec(ui.quickExec->isChecked()); + settings.setNoUsbTrash(ui.noUsbTrash->isChecked()); + settings.setConfirmTrash(ui.confirmTrash->isChecked()); + settings.setQuickExec(ui.quickExec->isChecked()); } void PreferencesDialog::applyThumbnailPage(Settings& settings) { - settings.setShowThumbnails(ui.showThumbnails->isChecked()); - settings.setThumbnailLocalFilesOnly(ui.thumbnailLocal->isChecked()); - settings.setMaxThumbnailFileSize(ui.maxThumbnailFileSize->value()); + settings.setShowThumbnails(ui.showThumbnails->isChecked()); + settings.setThumbnailLocalFilesOnly(ui.thumbnailLocal->isChecked()); + settings.setMaxThumbnailFileSize(ui.maxThumbnailFileSize->value()); } void PreferencesDialog::applyVolumePage(Settings& settings) { - settings.setAutoRun(ui.autoRun->isChecked()); - settings.setMountOnStartup(ui.mountOnStartup->isChecked()); - settings.setMountRemovable(ui.mountRemovable->isChecked()); - settings.setCloseOnUnmount(ui.closeOnUnmount->isChecked()); + settings.setAutoRun(ui.autoRun->isChecked()); + settings.setMountOnStartup(ui.mountOnStartup->isChecked()); + settings.setMountRemovable(ui.mountRemovable->isChecked()); + settings.setCloseOnUnmount(ui.closeOnUnmount->isChecked()); } void PreferencesDialog::applyAdvancedPage(Settings& settings) { - settings.setTerminal(ui.terminal->currentText()); - settings.setSuCommand(ui.suCommand->text()); - settings.setArchiver(ui.archiver->itemData(ui.archiver->currentIndex()).toString()); + settings.setTerminal(ui.terminal->currentText()); + settings.setSuCommand(ui.suCommand->text()); + settings.setArchiver(ui.archiver->itemData(ui.archiver->currentIndex()).toString()); - settings.setOnlyUserTemplates(ui.onlyUserTemplates->isChecked()); - settings.setTemplateTypeOnce(ui.templateTypeOnce->isChecked()); - settings.setTemplateRunApp(ui.templateRunApp->isChecked()); + settings.setOnlyUserTemplates(ui.onlyUserTemplates->isChecked()); + settings.setTemplateTypeOnce(ui.templateTypeOnce->isChecked()); + settings.setTemplateRunApp(ui.templateRunApp->isChecked()); } void PreferencesDialog::applySettings() { - Settings& settings = static_cast(qApp)->settings(); - applyDisplayPage(settings); - applyUiPage(settings); - applyBehaviorPage(settings); - applyThumbnailPage(settings); - applyVolumePage(settings); - applyAdvancedPage(settings); - - settings.save(); - - Application* app = static_cast(qApp); - app->updateFromSettings(); + Settings& settings = static_cast(qApp)->settings(); + applyDisplayPage(settings); + applyUiPage(settings); + applyBehaviorPage(settings); + applyThumbnailPage(settings); + applyVolumePage(settings); + applyAdvancedPage(settings); + + settings.save(); + + Application* app = static_cast(qApp); + app->updateFromSettings(); } void PreferencesDialog::accept() { - applySettings(); - QDialog::accept(); + applySettings(); + QDialog::accept(); } void PreferencesDialog::selectPage(QString name) { - if(!name.isEmpty()) { - QWidget* page = findChild(name + "Page"); - if(page) { - int index = ui.stackedWidget->indexOf(page); - ui.listWidget->setCurrentRow(index); + if(!name.isEmpty()) { + QWidget* page = findChild(name + "Page"); + if(page) { + int index = ui.stackedWidget->indexOf(page); + ui.listWidget->setCurrentRow(index); + } } - } } void PreferencesDialog::lockMargins(bool lock) { - ui.vMargin->setDisabled(lock); - if(lock) { - ui.vMargin->setValue(ui.hMargin->value()); - connect(ui.hMargin, static_cast(&QSpinBox::valueChanged), ui.vMargin, &QSpinBox::setValue); - } - else - disconnect(ui.hMargin, static_cast(&QSpinBox::valueChanged), ui.vMargin, &QSpinBox::setValue); + ui.vMargin->setDisabled(lock); + if(lock) { + ui.vMargin->setValue(ui.hMargin->value()); + connect(ui.hMargin, static_cast(&QSpinBox::valueChanged), ui.vMargin, &QSpinBox::setValue); + } + else { + disconnect(ui.hMargin, static_cast(&QSpinBox::valueChanged), ui.vMargin, &QSpinBox::setValue); + } } } // namespace PCManFM diff --git a/pcmanfm/preferencesdialog.h b/pcmanfm/preferencesdialog.h index 0228782..8661538 100644 --- a/pcmanfm/preferencesdialog.h +++ b/pcmanfm/preferencesdialog.h @@ -25,49 +25,48 @@ #include "ui_preferences.h" #include -namespace PCManFM -{ +namespace PCManFM { class Settings; class PreferencesDialog : public QDialog { -Q_OBJECT + Q_OBJECT public: - // activePage is the name of page to select (general, display, advanced...) - explicit PreferencesDialog(QString activePage = QString(), QWidget* parent = 0); - virtual ~PreferencesDialog(); + // activePage is the name of page to select (general, display, advanced...) + explicit PreferencesDialog(QString activePage = QString(), QWidget* parent = 0); + virtual ~PreferencesDialog(); - virtual void accept(); + virtual void accept(); - void selectPage(QString name); + void selectPage(QString name); protected Q_SLOTS: - void lockMargins(bool lock); + void lockMargins(bool lock); private: - void initIconThemes(Settings& settings); - void initArchivers(Settings& settings); - void initDisplayPage(Settings& settings); - void initUiPage(Settings& settings); - void initBehaviorPage(Settings& settings); - void initThumbnailPage(Settings& settings); - void initVolumePage(Settings& settings); - void initAdvancedPage(Settings& settings); - void initTerminals(Settings& settings); - - void applyUiPage(Settings& settings); - void applyDisplayPage(Settings& settings); - void applyBehaviorPage(Settings& settings); - void applyThumbnailPage(Settings& settings); - void applyVolumePage(Settings& settings); - void applyAdvancedPage(Settings& settings); - - void initFromSettings(); - void applySettings(); + void initIconThemes(Settings& settings); + void initArchivers(Settings& settings); + void initDisplayPage(Settings& settings); + void initUiPage(Settings& settings); + void initBehaviorPage(Settings& settings); + void initThumbnailPage(Settings& settings); + void initVolumePage(Settings& settings); + void initAdvancedPage(Settings& settings); + void initTerminals(Settings& settings); + + void applyUiPage(Settings& settings); + void applyDisplayPage(Settings& settings); + void applyBehaviorPage(Settings& settings); + void applyThumbnailPage(Settings& settings); + void applyVolumePage(Settings& settings); + void applyAdvancedPage(Settings& settings); + + void initFromSettings(); + void applySettings(); private: - Ui::PreferencesDialog ui; + Ui::PreferencesDialog ui; }; } diff --git a/pcmanfm/settings.cpp b/pcmanfm/settings.cpp index d418a29..284f25f 100644 --- a/pcmanfm/settings.cpp +++ b/pcmanfm/settings.cpp @@ -50,72 +50,82 @@ inline static const char* sortColumnToString(Fm::FolderModel::ColumnId value); inline static Fm::FolderModel::ColumnId sortColumnFromString(const QString str); Settings::Settings(): - QObject(), - supportTrash_(Fm::uriExists("trash:///")), // check if trash:/// is supported - fallbackIconThemeName_(), - useFallbackIconTheme_(QIcon::themeName().isEmpty() || QIcon::themeName() == "hicolor"), - bookmarkOpenMethod_(OpenInCurrentTab), - suCommand_(), - terminal_(), - mountOnStartup_(true), - mountRemovable_(true), - autoRun_(true), - closeOnUnmount_(false), - wallpaperMode_(0), - wallpaper_(), - desktopBgColor_(), - desktopFgColor_(), - desktopShadowColor_(), - desktopIconSize_(48), - showWmMenu_(false), - desktopShowHidden_(false), - desktopSortOrder_(Qt::AscendingOrder), - desktopSortColumn_(Fm::FolderModel::ColumnFileMTime), - desktopSortFolderFirst_(true), - alwaysShowTabs_(true), - showTabClose_(true), - rememberWindowSize_(true), - fixedWindowWidth_(640), - fixedWindowHeight_(480), - lastWindowWidth_(640), - lastWindowHeight_(480), - lastWindowMaximized_(false), - splitterPos_(120), - sidePaneMode_(Fm::SidePane::ModePlaces), - showMenuBar_(true), - fullWidthTabBar_(true), - viewMode_(Fm::FolderView::IconMode), - showHidden_(false), - sortOrder_(Qt::AscendingOrder), - sortColumn_(Fm::FolderModel::ColumnFileName), - sortFolderFirst_(true), - sortCaseSensitive_(false), - showFilter_(false), - pathBarButtons_(true), - // settings for use with libfm - singleClick_(false), - autoSelectionDelay_(600), - useTrash_(true), - confirmDelete_(true), - noUsbTrash_(false), - confirmTrash_(false), - quickExec_(false), - showThumbnails_(true), - archiver_(), - siUnit_(false), - placesHome_(true), - placesDesktop_(true), - placesApplications_(true), - placesTrash_(true), - placesRoot_(true), - placesComputer_(true), - placesNetwork_(true), - bigIconSize_(48), - smallIconSize_(24), - sidePaneIconSize_(24), - thumbnailIconSize_(128), - folderViewCellMargins_(QSize(3, 3)), - desktopCellMargins_(QSize(3, 1)) { + QObject(), + supportTrash_(Fm::uriExists("trash:///")), // check if trash:/// is supported + fallbackIconThemeName_(), + useFallbackIconTheme_(QIcon::themeName().isEmpty() || QIcon::themeName() == "hicolor"), + bookmarkOpenMethod_(OpenInCurrentTab), + suCommand_(), + terminal_(), + mountOnStartup_(true), + mountRemovable_(true), + autoRun_(true), + closeOnUnmount_(false), + wallpaperMode_(0), + wallpaper_(), + lastSlide_(), + wallpaperDir_(), + slideShowInterval_(0), + wallpaperRandomize_(false), + desktopBgColor_(), + desktopFgColor_(), + desktopShadowColor_(), + desktopIconSize_(48), + showWmMenu_(false), + desktopShowHidden_(false), + desktopSortOrder_(Qt::AscendingOrder), + desktopSortColumn_(Fm::FolderModel::ColumnFileMTime), + desktopSortFolderFirst_(true), + alwaysShowTabs_(true), + showTabClose_(true), + rememberWindowSize_(true), + fixedWindowWidth_(640), + fixedWindowHeight_(480), + lastWindowWidth_(640), + lastWindowHeight_(480), + lastWindowMaximized_(false), + splitterPos_(120), + sidePaneMode_(Fm::SidePane::ModePlaces), + showMenuBar_(true), + fullWidthTabBar_(true), + viewMode_(Fm::FolderView::IconMode), + showHidden_(false), + sortOrder_(Qt::AscendingOrder), + sortColumn_(Fm::FolderModel::ColumnFileName), + sortFolderFirst_(true), + sortCaseSensitive_(false), + showFilter_(false), + pathBarButtons_(true), + // settings for use with libfm + singleClick_(false), + autoSelectionDelay_(600), + useTrash_(true), + confirmDelete_(true), + noUsbTrash_(false), + confirmTrash_(false), + quickExec_(false), + showThumbnails_(true), + archiver_(), + siUnit_(false), + placesHome_(true), + placesDesktop_(true), + placesApplications_(true), + placesTrash_(true), + placesRoot_(true), + placesComputer_(true), + placesNetwork_(true), + bigIconSize_(48), + smallIconSize_(24), + sidePaneIconSize_(24), + thumbnailIconSize_(128), + folderViewCellMargins_(QSize(3, 3)), + desktopCellMargins_(QSize(3, 1)), + searchNameCaseInsensitive_(false), + searchContentCaseInsensitive_(false), + searchNameRegexp_(true), + searchContentRegexp_(true), + searchRecursive_(false), + searchhHidden_(false) { } Settings::~Settings() { @@ -123,460 +133,541 @@ Settings::~Settings() { } QString Settings::xdgUserConfigDir() { - QString dirName; - // WARNING: Don't use XDG_CONFIG_HOME with root because it might - // give the user config directory if gksu-properties is set to su. - if(geteuid() != 0) // non-root user - dirName = QStandardPaths::writableLocation(QStandardPaths::ConfigLocation); - if (dirName.isEmpty()) - dirName = QDir::homePath() % QLatin1String("/.config"); - return dirName; + QString dirName; + // WARNING: Don't use XDG_CONFIG_HOME with root because it might + // give the user config directory if gksu-properties is set to su. + if(geteuid() != 0) { // non-root user + dirName = QStandardPaths::writableLocation(QStandardPaths::ConfigLocation); + } + if(dirName.isEmpty()) { + dirName = QDir::homePath() % QLatin1String("/.config"); + } + return dirName; } QString Settings::profileDir(QString profile, bool useFallback) { - // try user-specific config file first - QString dirName = xdgUserConfigDir(); - dirName = dirName % "/pcmanfm-qt/" % profile; - QDir dir(dirName); - - // if user config dir does not exist, try system-wide config dirs instead - if(!dir.exists() && useFallback) { - QString fallbackDir; - for(const char* const* configDir = g_get_system_config_dirs(); *configDir; ++configDir) { - fallbackDir = QString(*configDir) % "/pcmanfm-qt/" % profile; - dir.setPath(fallbackDir); - if(dir.exists()) { - dirName = fallbackDir; - break; - } - } - } - return dirName; + // try user-specific config file first + QString dirName = xdgUserConfigDir(); + dirName = dirName % "/pcmanfm-qt/" % profile; + QDir dir(dirName); + + // if user config dir does not exist, try system-wide config dirs instead + if(!dir.exists() && useFallback) { + QString fallbackDir; + for(const char* const* configDir = g_get_system_config_dirs(); *configDir; ++configDir) { + fallbackDir = QString(*configDir) % "/pcmanfm-qt/" % profile; + dir.setPath(fallbackDir); + if(dir.exists()) { + dirName = fallbackDir; + break; + } + } + } + return dirName; } bool Settings::load(QString profile) { - profileName_ = profile; - QString fileName = profileDir(profile, true) % "/settings.conf"; - return loadFile(fileName); + profileName_ = profile; + QString fileName = profileDir(profile, true) % "/settings.conf"; + return loadFile(fileName); } bool Settings::save(QString profile) { - QString fileName = profileDir(profile.isEmpty() ? profileName_ : profile) % "/settings.conf"; - return saveFile(fileName); + QString fileName = profileDir(profile.isEmpty() ? profileName_ : profile) % "/settings.conf"; + return saveFile(fileName); } bool Settings::loadFile(QString filePath) { - QSettings settings(filePath, QSettings::IniFormat); - settings.beginGroup("System"); - fallbackIconThemeName_ = settings.value("FallbackIconThemeName").toString(); - if(fallbackIconThemeName_.isEmpty()) { - // FIXME: we should choose one from installed icon themes or get - // the value from XSETTINGS instead of hard code a fallback value. - fallbackIconThemeName_ = "oxygen"; // fallback icon theme name - } - suCommand_ = settings.value("SuCommand", "lxqt-sudo %s").toString(); - setTerminal(settings.value("Terminal", "xterm").toString()); - setArchiver(settings.value("Archiver", "file-roller").toString()); - setSiUnit(settings.value("SIUnit", false).toBool()); - - setOnlyUserTemplates(settings.value("OnlyUserTemplates", false).toBool()); - setTemplateTypeOnce(settings.value("TemplateTypeOnce", false).toBool()); - setTemplateRunApp(settings.value("TemplateRunApp", false).toBool()); - - settings.endGroup(); - - settings.beginGroup("Behavior"); - bookmarkOpenMethod_ = bookmarkOpenMethodFromString(settings.value("BookmarkOpenMethod").toString()); - // settings for use with libfm - useTrash_ = settings.value("UseTrash", true).toBool(); - singleClick_ = settings.value("SingleClick", false).toBool(); - autoSelectionDelay_ = settings.value("AutoSelectionDelay", 600).toInt(); - confirmDelete_ = settings.value("ConfirmDelete", true).toBool(); - setNoUsbTrash(settings.value("NoUsbTrash", false).toBool()); - confirmTrash_ = settings.value("ConfirmTrash", false).toBool(); - setQuickExec(settings.value("QuickExec", false).toBool()); - // bool thumbnailLocal_; - // bool thumbnailMax; - settings.endGroup(); - - settings.beginGroup("Desktop"); - wallpaperMode_ = wallpaperModeFromString(settings.value("WallpaperMode").toString()); - wallpaper_ = settings.value("Wallpaper").toString(); - desktopBgColor_.setNamedColor(settings.value("BgColor", "#000000").toString()); - desktopFgColor_.setNamedColor(settings.value("FgColor", "#ffffff").toString()); - desktopShadowColor_.setNamedColor(settings.value("ShadowColor", "#000000").toString()); - if(settings.contains("Font")) - desktopFont_.fromString(settings.value("Font").toString()); - else - desktopFont_ = QApplication::font(); - desktopIconSize_ = settings.value("DesktopIconSize", 48).toInt(); - showWmMenu_ = settings.value("ShowWmMenu", false).toBool(); - desktopShowHidden_ = settings.value("ShowHidden", false).toBool(); - - desktopSortOrder_ = sortOrderFromString(settings.value("SortOrder").toString()); - desktopSortColumn_ = sortColumnFromString(settings.value("SortColumn").toString()); - desktopSortFolderFirst_ = settings.value("SortFolderFirst", true).toBool(); - - desktopCellMargins_ = (settings.value("DesktopCellMargins", QSize(3, 1)).toSize() - .expandedTo(QSize(0, 0))).boundedTo(QSize(48, 48)); - settings.endGroup(); - - settings.beginGroup("Volume"); - mountOnStartup_ = settings.value("MountOnStartup", true).toBool(); - mountRemovable_ = settings.value("MountRemovable", true).toBool(); - autoRun_ = settings.value("AutoRun", true).toBool(); - closeOnUnmount_ = settings.value("CloseOnUnmount", true).toBool(); - settings.endGroup(); - - settings.beginGroup("Thumbnail"); - showThumbnails_ = settings.value("ShowThumbnails", true).toBool(); - setMaxThumbnailFileSize(settings.value("MaxThumbnailFileSize", 4096).toInt()); - setThumbnailLocalFilesOnly(settings.value("ThumbnailLocalFilesOnly", true).toBool()); - settings.endGroup(); - - settings.beginGroup("FolderView"); - viewMode_ = viewModeFromString(settings.value("Mode", Fm::FolderView::IconMode).toString()); - showHidden_ = settings.value("ShowHidden", false).toBool(); - sortOrder_ = sortOrderFromString(settings.value("SortOrder").toString()); - sortColumn_ = sortColumnFromString(settings.value("SortColumn").toString()); - sortFolderFirst_ = settings.value("SortFolderFirst", true).toBool(); - sortCaseSensitive_ = settings.value("SortCaseSensitive", false).toBool(); - showFilter_ = settings.value("ShowFilter", false).toBool(); - - setBackupAsHidden(settings.value("BackupAsHidden", false).toBool()); - showFullNames_ = settings.value("ShowFullNames", false).toBool(); - shadowHidden_ = settings.value("ShadowHidden", false).toBool(); - - // override config in libfm's FmConfig - bigIconSize_ = settings.value("BigIconSize", 48).toInt(); - smallIconSize_ = settings.value("SmallIconSize", 24).toInt(); - sidePaneIconSize_ = settings.value("SidePaneIconSize", 24).toInt(); - thumbnailIconSize_ = settings.value("ThumbnailIconSize", 128).toInt(); - - folderViewCellMargins_ = (settings.value("FolderViewCellMargins", QSize(3, 3)).toSize() - .expandedTo(QSize(0, 0))).boundedTo(QSize(48, 48)); - settings.endGroup(); - - settings.beginGroup("Places"); - placesHome_ = settings.value("PlacesHome", true).toBool(); - placesDesktop_ = settings.value("PlacesDesktop", true).toBool(); - placesApplications_ = settings.value("PlacesApplications", true).toBool(); - placesTrash_ = settings.value("PlacesTrash", true).toBool(); - placesRoot_ = settings.value("PlacesRoot", true).toBool(); - placesComputer_ = settings.value("PlacesComputer", true).toBool(); - placesNetwork_ = settings.value("PlacesNetwork", true).toBool(); - settings.endGroup(); - - settings.beginGroup("Window"); - fixedWindowWidth_ = settings.value("FixedWidth", 640).toInt(); - fixedWindowHeight_ = settings.value("FixedHeight", 480).toInt(); - lastWindowWidth_ = settings.value("LastWindowWidth", 640).toInt(); - lastWindowHeight_ = settings.value("LastWindowHeight", 480).toInt(); - lastWindowMaximized_ = settings.value("LastWindowMaximized", false).toBool(); - rememberWindowSize_ = settings.value("RememberWindowSize", true).toBool(); - alwaysShowTabs_ = settings.value("AlwaysShowTabs", true).toBool(); - showTabClose_ = settings.value("ShowTabClose", true).toBool(); - splitterPos_ = settings.value("SplitterPos", 150).toInt(); - sidePaneMode_ = sidePaneModeFromString(settings.value("SidePaneMode").toString()); - showMenuBar_ = settings.value("ShowMenuBar", true).toBool(); - fullWidthTabBar_ = settings.value("FullWidthTabBar", true).toBool(); - pathBarButtons_ = settings.value("PathBarButtons", true).toBool(); - settings.endGroup(); - - return true; + QSettings settings(filePath, QSettings::IniFormat); + settings.beginGroup("System"); + fallbackIconThemeName_ = settings.value("FallbackIconThemeName").toString(); + if(fallbackIconThemeName_.isEmpty()) { + // FIXME: we should choose one from installed icon themes or get + // the value from XSETTINGS instead of hard code a fallback value. + fallbackIconThemeName_ = "oxygen"; // fallback icon theme name + } + suCommand_ = settings.value("SuCommand", "lxqt-sudo %s").toString(); + setTerminal(settings.value("Terminal", "xterm").toString()); + setArchiver(settings.value("Archiver", "file-roller").toString()); + setSiUnit(settings.value("SIUnit", false).toBool()); + + setOnlyUserTemplates(settings.value("OnlyUserTemplates", false).toBool()); + setTemplateTypeOnce(settings.value("TemplateTypeOnce", false).toBool()); + setTemplateRunApp(settings.value("TemplateRunApp", false).toBool()); + + settings.endGroup(); + + settings.beginGroup("Behavior"); + bookmarkOpenMethod_ = bookmarkOpenMethodFromString(settings.value("BookmarkOpenMethod").toString()); + // settings for use with libfm + useTrash_ = settings.value("UseTrash", true).toBool(); + singleClick_ = settings.value("SingleClick", false).toBool(); + autoSelectionDelay_ = settings.value("AutoSelectionDelay", 600).toInt(); + confirmDelete_ = settings.value("ConfirmDelete", true).toBool(); + setNoUsbTrash(settings.value("NoUsbTrash", false).toBool()); + confirmTrash_ = settings.value("ConfirmTrash", false).toBool(); + setQuickExec(settings.value("QuickExec", false).toBool()); + // bool thumbnailLocal_; + // bool thumbnailMax; + settings.endGroup(); + + settings.beginGroup("Desktop"); + wallpaperMode_ = wallpaperModeFromString(settings.value("WallpaperMode").toString()); + wallpaper_ = settings.value("Wallpaper").toString(); + lastSlide_ = settings.value("LastSlide").toString(); + wallpaperDir_ = settings.value("WallpaperDirectory").toString(); + slideShowInterval_ = settings.value("SlideShowInterval", 0).toInt(); + wallpaperRandomize_ = settings.value("WallpaperRandomize").toBool(); + desktopBgColor_.setNamedColor(settings.value("BgColor", "#000000").toString()); + desktopFgColor_.setNamedColor(settings.value("FgColor", "#ffffff").toString()); + desktopShadowColor_.setNamedColor(settings.value("ShadowColor", "#000000").toString()); + if(settings.contains("Font")) { + desktopFont_.fromString(settings.value("Font").toString()); + } + else { + desktopFont_ = QApplication::font(); + } + desktopIconSize_ = settings.value("DesktopIconSize", 48).toInt(); + showWmMenu_ = settings.value("ShowWmMenu", false).toBool(); + desktopShowHidden_ = settings.value("ShowHidden", false).toBool(); + + desktopSortOrder_ = sortOrderFromString(settings.value("SortOrder").toString()); + desktopSortColumn_ = sortColumnFromString(settings.value("SortColumn").toString()); + desktopSortFolderFirst_ = settings.value("SortFolderFirst", true).toBool(); + + desktopCellMargins_ = (settings.value("DesktopCellMargins", QSize(3, 1)).toSize() + .expandedTo(QSize(0, 0))).boundedTo(QSize(48, 48)); + settings.endGroup(); + + settings.beginGroup("Volume"); + mountOnStartup_ = settings.value("MountOnStartup", true).toBool(); + mountRemovable_ = settings.value("MountRemovable", true).toBool(); + autoRun_ = settings.value("AutoRun", true).toBool(); + closeOnUnmount_ = settings.value("CloseOnUnmount", true).toBool(); + settings.endGroup(); + + settings.beginGroup("Thumbnail"); + showThumbnails_ = settings.value("ShowThumbnails", true).toBool(); + setMaxThumbnailFileSize(settings.value("MaxThumbnailFileSize", 4096).toInt()); + setThumbnailLocalFilesOnly(settings.value("ThumbnailLocalFilesOnly", true).toBool()); + settings.endGroup(); + + settings.beginGroup("FolderView"); + viewMode_ = viewModeFromString(settings.value("Mode", Fm::FolderView::IconMode).toString()); + showHidden_ = settings.value("ShowHidden", false).toBool(); + sortOrder_ = sortOrderFromString(settings.value("SortOrder").toString()); + sortColumn_ = sortColumnFromString(settings.value("SortColumn").toString()); + sortFolderFirst_ = settings.value("SortFolderFirst", true).toBool(); + sortCaseSensitive_ = settings.value("SortCaseSensitive", false).toBool(); + showFilter_ = settings.value("ShowFilter", false).toBool(); + + setBackupAsHidden(settings.value("BackupAsHidden", false).toBool()); + showFullNames_ = settings.value("ShowFullNames", false).toBool(); + shadowHidden_ = settings.value("ShadowHidden", false).toBool(); + + // override config in libfm's FmConfig + bigIconSize_ = toIconSize(settings.value("BigIconSize", 48).toInt(), Big); + smallIconSize_ = toIconSize(settings.value("SmallIconSize", 24).toInt(), Small); + sidePaneIconSize_ = toIconSize(settings.value("SidePaneIconSize", 24).toInt(), Small); + thumbnailIconSize_ = toIconSize(settings.value("ThumbnailIconSize", 128).toInt(), Thumbnail); + + folderViewCellMargins_ = (settings.value("FolderViewCellMargins", QSize(3, 3)).toSize() + .expandedTo(QSize(0, 0))).boundedTo(QSize(48, 48)); + settings.endGroup(); + + settings.beginGroup("Places"); + placesHome_ = settings.value("PlacesHome", true).toBool(); + placesDesktop_ = settings.value("PlacesDesktop", true).toBool(); + placesApplications_ = settings.value("PlacesApplications", true).toBool(); + placesTrash_ = settings.value("PlacesTrash", true).toBool(); + placesRoot_ = settings.value("PlacesRoot", true).toBool(); + placesComputer_ = settings.value("PlacesComputer", true).toBool(); + placesNetwork_ = settings.value("PlacesNetwork", true).toBool(); + settings.endGroup(); + + settings.beginGroup("Window"); + fixedWindowWidth_ = settings.value("FixedWidth", 640).toInt(); + fixedWindowHeight_ = settings.value("FixedHeight", 480).toInt(); + lastWindowWidth_ = settings.value("LastWindowWidth", 640).toInt(); + lastWindowHeight_ = settings.value("LastWindowHeight", 480).toInt(); + lastWindowMaximized_ = settings.value("LastWindowMaximized", false).toBool(); + rememberWindowSize_ = settings.value("RememberWindowSize", true).toBool(); + alwaysShowTabs_ = settings.value("AlwaysShowTabs", true).toBool(); + showTabClose_ = settings.value("ShowTabClose", true).toBool(); + splitterPos_ = settings.value("SplitterPos", 150).toInt(); + sidePaneMode_ = sidePaneModeFromString(settings.value("SidePaneMode").toString()); + showMenuBar_ = settings.value("ShowMenuBar", true).toBool(); + fullWidthTabBar_ = settings.value("FullWidthTabBar", true).toBool(); + pathBarButtons_ = settings.value("PathBarButtons", true).toBool(); + settings.endGroup(); + + settings.beginGroup("Search"); + searchNameCaseInsensitive_ = settings.value("searchNameCaseInsensitive", false).toBool(); + searchContentCaseInsensitive_ = settings.value("searchContentCaseInsensitive", false).toBool(); + searchNameRegexp_ = settings.value("searchNameRegexp", true).toBool(); + searchContentRegexp_ = settings.value("searchContentRegexp", true).toBool(); + searchRecursive_ = settings.value("searchRecursive", false).toBool(); + searchhHidden_ = settings.value("searchhHidden", false).toBool(); + settings.endGroup(); + + return true; } bool Settings::saveFile(QString filePath) { - QSettings settings(filePath, QSettings::IniFormat); - - settings.beginGroup("System"); - settings.setValue("FallbackIconThemeName", fallbackIconThemeName_); - settings.setValue("SuCommand", suCommand_); - settings.setValue("Terminal", terminal_); - settings.setValue("Archiver", archiver_); - settings.setValue("SIUnit", siUnit_); - - settings.setValue("OnlyUserTemplates", onlyUserTemplates_); - settings.setValue("TemplateTypeOnce", templateTypeOnce_); - settings.setValue("TemplateRunApp", templateRunApp_); - - settings.endGroup(); - - settings.beginGroup("Behavior"); - settings.setValue("BookmarkOpenMethod", bookmarkOpenMethodToString(bookmarkOpenMethod_)); - // settings for use with libfm - settings.setValue("UseTrash", useTrash_); - settings.setValue("SingleClick", singleClick_); - settings.setValue("AutoSelectionDelay", autoSelectionDelay_); - settings.setValue("ConfirmDelete", confirmDelete_); - settings.setValue("NoUsbTrash", noUsbTrash_); - settings.setValue("ConfirmTrash", confirmTrash_); - settings.setValue("QuickExec", quickExec_); - // bool thumbnailLocal_; - // bool thumbnailMax; - settings.endGroup(); - - settings.beginGroup("Desktop"); - settings.setValue("WallpaperMode", wallpaperModeToString(wallpaperMode_)); - settings.setValue("Wallpaper", wallpaper_); - settings.setValue("BgColor", desktopBgColor_.name()); - settings.setValue("FgColor", desktopFgColor_.name()); - settings.setValue("ShadowColor", desktopShadowColor_.name()); - settings.setValue("Font", desktopFont_.toString()); - settings.setValue("DesktopIconSize", desktopIconSize_); - settings.setValue("ShowWmMenu", showWmMenu_); - settings.setValue("ShowHidden", desktopShowHidden_); - settings.setValue("SortOrder", sortOrderToString(desktopSortOrder_)); - settings.setValue("SortColumn", sortColumnToString(desktopSortColumn_)); - settings.setValue("SortFolderFirst", desktopSortFolderFirst_); - settings.setValue("DesktopCellMargins", desktopCellMargins_); - settings.endGroup(); - - settings.beginGroup("Volume"); - settings.setValue("MountOnStartup", mountOnStartup_); - settings.setValue("MountRemovable", mountRemovable_); - settings.setValue("AutoRun", autoRun_); - settings.setValue("CloseOnUnmount", closeOnUnmount_); - settings.endGroup(); - - settings.beginGroup("Thumbnail"); - settings.setValue("ShowThumbnails", showThumbnails_); - settings.setValue("MaxThumbnailFileSize", maxThumbnailFileSize()); - settings.setValue("ThumbnailLocalFilesOnly", thumbnailLocalFilesOnly()); - settings.endGroup(); - - settings.beginGroup("FolderView"); - settings.setValue("Mode", viewModeToString(viewMode_)); - settings.setValue("ShowHidden", showHidden_); - settings.setValue("SortOrder", sortOrderToString(sortOrder_)); - settings.setValue("SortColumn", sortColumnToString(sortColumn_)); - settings.setValue("SortFolderFirst", sortFolderFirst_); - settings.setValue("SortCaseSensitive", sortCaseSensitive_); - settings.setValue("ShowFilter", showFilter_); - - settings.setValue("BackupAsHidden", backupAsHidden_); - settings.setValue("ShowFullNames", showFullNames_); - settings.setValue("ShadowHidden", shadowHidden_); - - // override config in libfm's FmConfig - settings.setValue("BigIconSize", bigIconSize_); - settings.setValue("SmallIconSize", smallIconSize_); - settings.setValue("SidePaneIconSize", sidePaneIconSize_); - settings.setValue("ThumbnailIconSize", thumbnailIconSize_); - - settings.setValue("FolderViewCellMargins", folderViewCellMargins_); - settings.endGroup(); - - settings.beginGroup("Places"); - settings.setValue("PlacesHome", placesHome_); - settings.setValue("PlacesDesktop", placesDesktop_); - settings.setValue("PlacesApplications", placesApplications_); - settings.setValue("PlacesTrash", placesTrash_); - settings.setValue("PlacesRoot", placesRoot_); - settings.setValue("PlacesComputer", placesComputer_); - settings.setValue("PlacesNetwork", placesNetwork_); - settings.endGroup(); - - settings.beginGroup("Window"); - settings.setValue("FixedWidth", fixedWindowWidth_); - settings.setValue("FixedHeight", fixedWindowHeight_); - settings.setValue("LastWindowWidth", lastWindowWidth_); - settings.setValue("LastWindowHeight", lastWindowHeight_); - settings.setValue("LastWindowMaximized", lastWindowMaximized_); - settings.setValue("RememberWindowSize", rememberWindowSize_); - settings.setValue("AlwaysShowTabs", alwaysShowTabs_); - settings.setValue("ShowTabClose", showTabClose_); - settings.setValue("SplitterPos", splitterPos_); - settings.setValue("SidePaneMode", sidePaneModeToString(sidePaneMode_)); - settings.setValue("ShowMenuBar", showMenuBar_); - settings.setValue("FullWidthTabBar", fullWidthTabBar_); - settings.setValue("PathBarButtons", pathBarButtons_); - settings.endGroup(); - - // save per-folder settings - Fm::FolderConfig::saveCache(); - - return true; + QSettings settings(filePath, QSettings::IniFormat); + + settings.beginGroup("System"); + settings.setValue("FallbackIconThemeName", fallbackIconThemeName_); + settings.setValue("SuCommand", suCommand_); + settings.setValue("Terminal", terminal_); + settings.setValue("Archiver", archiver_); + settings.setValue("SIUnit", siUnit_); + + settings.setValue("OnlyUserTemplates", onlyUserTemplates_); + settings.setValue("TemplateTypeOnce", templateTypeOnce_); + settings.setValue("TemplateRunApp", templateRunApp_); + + settings.endGroup(); + + settings.beginGroup("Behavior"); + settings.setValue("BookmarkOpenMethod", bookmarkOpenMethodToString(bookmarkOpenMethod_)); + // settings for use with libfm + settings.setValue("UseTrash", useTrash_); + settings.setValue("SingleClick", singleClick_); + settings.setValue("AutoSelectionDelay", autoSelectionDelay_); + settings.setValue("ConfirmDelete", confirmDelete_); + settings.setValue("NoUsbTrash", noUsbTrash_); + settings.setValue("ConfirmTrash", confirmTrash_); + settings.setValue("QuickExec", quickExec_); + // bool thumbnailLocal_; + // bool thumbnailMax; + settings.endGroup(); + + settings.beginGroup("Desktop"); + settings.setValue("WallpaperMode", wallpaperModeToString(wallpaperMode_)); + settings.setValue("Wallpaper", wallpaper_); + settings.setValue("LastSlide", lastSlide_); + settings.setValue("WallpaperDirectory", wallpaperDir_); + settings.setValue("SlideShowInterval", slideShowInterval_); + settings.setValue("WallpaperRandomize", wallpaperRandomize_); + settings.setValue("BgColor", desktopBgColor_.name()); + settings.setValue("FgColor", desktopFgColor_.name()); + settings.setValue("ShadowColor", desktopShadowColor_.name()); + settings.setValue("Font", desktopFont_.toString()); + settings.setValue("DesktopIconSize", desktopIconSize_); + settings.setValue("ShowWmMenu", showWmMenu_); + settings.setValue("ShowHidden", desktopShowHidden_); + settings.setValue("SortOrder", sortOrderToString(desktopSortOrder_)); + settings.setValue("SortColumn", sortColumnToString(desktopSortColumn_)); + settings.setValue("SortFolderFirst", desktopSortFolderFirst_); + settings.setValue("DesktopCellMargins", desktopCellMargins_); + settings.endGroup(); + + settings.beginGroup("Volume"); + settings.setValue("MountOnStartup", mountOnStartup_); + settings.setValue("MountRemovable", mountRemovable_); + settings.setValue("AutoRun", autoRun_); + settings.setValue("CloseOnUnmount", closeOnUnmount_); + settings.endGroup(); + + settings.beginGroup("Thumbnail"); + settings.setValue("ShowThumbnails", showThumbnails_); + settings.setValue("MaxThumbnailFileSize", maxThumbnailFileSize()); + settings.setValue("ThumbnailLocalFilesOnly", thumbnailLocalFilesOnly()); + settings.endGroup(); + + settings.beginGroup("FolderView"); + settings.setValue("Mode", viewModeToString(viewMode_)); + settings.setValue("ShowHidden", showHidden_); + settings.setValue("SortOrder", sortOrderToString(sortOrder_)); + settings.setValue("SortColumn", sortColumnToString(sortColumn_)); + settings.setValue("SortFolderFirst", sortFolderFirst_); + settings.setValue("SortCaseSensitive", sortCaseSensitive_); + settings.setValue("ShowFilter", showFilter_); + + settings.setValue("BackupAsHidden", backupAsHidden_); + settings.setValue("ShowFullNames", showFullNames_); + settings.setValue("ShadowHidden", shadowHidden_); + + // override config in libfm's FmConfig + settings.setValue("BigIconSize", bigIconSize_); + settings.setValue("SmallIconSize", smallIconSize_); + settings.setValue("SidePaneIconSize", sidePaneIconSize_); + settings.setValue("ThumbnailIconSize", thumbnailIconSize_); + + settings.setValue("FolderViewCellMargins", folderViewCellMargins_); + settings.endGroup(); + + settings.beginGroup("Places"); + settings.setValue("PlacesHome", placesHome_); + settings.setValue("PlacesDesktop", placesDesktop_); + settings.setValue("PlacesApplications", placesApplications_); + settings.setValue("PlacesTrash", placesTrash_); + settings.setValue("PlacesRoot", placesRoot_); + settings.setValue("PlacesComputer", placesComputer_); + settings.setValue("PlacesNetwork", placesNetwork_); + settings.endGroup(); + + settings.beginGroup("Window"); + settings.setValue("FixedWidth", fixedWindowWidth_); + settings.setValue("FixedHeight", fixedWindowHeight_); + settings.setValue("LastWindowWidth", lastWindowWidth_); + settings.setValue("LastWindowHeight", lastWindowHeight_); + settings.setValue("LastWindowMaximized", lastWindowMaximized_); + settings.setValue("RememberWindowSize", rememberWindowSize_); + settings.setValue("AlwaysShowTabs", alwaysShowTabs_); + settings.setValue("ShowTabClose", showTabClose_); + settings.setValue("SplitterPos", splitterPos_); + settings.setValue("SidePaneMode", sidePaneModeToString(sidePaneMode_)); + settings.setValue("ShowMenuBar", showMenuBar_); + settings.setValue("FullWidthTabBar", fullWidthTabBar_); + settings.setValue("PathBarButtons", pathBarButtons_); + settings.endGroup(); + + // save per-folder settings + Fm::FolderConfig::saveCache(); + + settings.beginGroup("Search"); + settings.setValue("searchNameCaseInsensitive", searchNameCaseInsensitive_); + settings.setValue("searchContentCaseInsensitive", searchContentCaseInsensitive_); + settings.setValue("searchNameRegexp", searchNameRegexp_); + settings.setValue("searchContentRegexp", searchContentRegexp_); + settings.setValue("searchRecursive", searchRecursive_); + settings.setValue("searchhHidden", searchhHidden_); + settings.endGroup(); + + return true; +} + +const QList & Settings::iconSizes(IconType type) { + static const QList sizes_big = {96, 72, 64, 48, 32}; + static const QList sizes_thumbnail = {256, 224, 192, 160, 128, 96, 64}; + static const QList sizes_small = {48, 32, 24, 22, 16}; + switch(type) { + case Big: + return sizes_big; + break; + case Thumbnail: + return sizes_thumbnail; + break; + case Small: + default: + return sizes_small; + break; + } +} + +int Settings::toIconSize(int size, IconType type) const { + const QList & sizes = iconSizes(type); + for (const auto & s : sizes) { + if(size >= s) { + return s; + } + } + return sizes.back(); } static const char* bookmarkOpenMethodToString(OpenDirTargetType value) { - switch(value) { - case OpenInCurrentTab: - default: - return "current_tab"; - case OpenInNewTab: - return "new_tab"; - case OpenInNewWindow: - return "new_window"; - case OpenInLastActiveWindow: - return "last_window"; - } - return ""; + switch(value) { + case OpenInCurrentTab: + default: + return "current_tab"; + case OpenInNewTab: + return "new_tab"; + case OpenInNewWindow: + return "new_window"; + case OpenInLastActiveWindow: + return "last_window"; + } + return ""; } static OpenDirTargetType bookmarkOpenMethodFromString(const QString str) { - if(str == QStringLiteral("new_tab")) - return OpenInNewTab; - else if(str == QStringLiteral("new_window")) - return OpenInNewWindow; - else if(str == QStringLiteral("last_window")) - return OpenInLastActiveWindow; - return OpenInCurrentTab; + if(str == QStringLiteral("new_tab")) { + return OpenInNewTab; + } + else if(str == QStringLiteral("new_window")) { + return OpenInNewWindow; + } + else if(str == QStringLiteral("last_window")) { + return OpenInLastActiveWindow; + } + return OpenInCurrentTab; } static const char* viewModeToString(Fm::FolderView::ViewMode value) { - const char* ret; - switch(value) { + const char* ret; + switch(value) { case Fm::FolderView::IconMode: default: - ret = "icon"; - break; + ret = "icon"; + break; case Fm::FolderView::CompactMode: - ret = "compact"; - break; + ret = "compact"; + break; case Fm::FolderView::DetailedListMode: - ret = "detailed"; - break; + ret = "detailed"; + break; case Fm::FolderView::ThumbnailMode: - ret = "thumbnail"; - break; - } - return ret; + ret = "thumbnail"; + break; + } + return ret; } Fm::FolderView::ViewMode viewModeFromString(const QString str) { - Fm::FolderView::ViewMode ret; - if(str == "icon") - ret = Fm::FolderView::IconMode; - else if(str == "compact") - ret = Fm::FolderView::CompactMode; - else if(str == "detailed") - ret = Fm::FolderView::DetailedListMode; - else if(str == "thumbnail") - ret = Fm::FolderView::ThumbnailMode; - else - ret = Fm::FolderView::IconMode; - return ret; + Fm::FolderView::ViewMode ret; + if(str == "icon") { + ret = Fm::FolderView::IconMode; + } + else if(str == "compact") { + ret = Fm::FolderView::CompactMode; + } + else if(str == "detailed") { + ret = Fm::FolderView::DetailedListMode; + } + else if(str == "thumbnail") { + ret = Fm::FolderView::ThumbnailMode; + } + else { + ret = Fm::FolderView::IconMode; + } + return ret; } static const char* sortOrderToString(Qt::SortOrder order) { - return (order == Qt::DescendingOrder ? "descending" : "ascending"); + return (order == Qt::DescendingOrder ? "descending" : "ascending"); } static Qt::SortOrder sortOrderFromString(const QString str) { - return (str == "descending" ? Qt::DescendingOrder : Qt::AscendingOrder); + return (str == "descending" ? Qt::DescendingOrder : Qt::AscendingOrder); } static const char* sortColumnToString(Fm::FolderModel::ColumnId value) { - const char* ret; - switch(value) { + const char* ret; + switch(value) { case Fm::FolderModel::ColumnFileName: default: - ret = "name"; - break; + ret = "name"; + break; case Fm::FolderModel::ColumnFileType: - ret = "type"; - break; + ret = "type"; + break; case Fm::FolderModel::ColumnFileSize: - ret = "size"; - break; + ret = "size"; + break; case Fm::FolderModel::ColumnFileMTime: - ret = "mtime"; - break; + ret = "mtime"; + break; case Fm::FolderModel::ColumnFileOwner: - ret = "owner"; - break; - } - return ret; + ret = "owner"; + break; + } + return ret; } static Fm::FolderModel::ColumnId sortColumnFromString(const QString str) { - Fm::FolderModel::ColumnId ret; - if(str == "name") - ret = Fm::FolderModel::ColumnFileName; - else if(str == "type") - ret = Fm::FolderModel::ColumnFileType; - else if(str == "size") - ret = Fm::FolderModel::ColumnFileSize; - else if(str == "mtime") - ret = Fm::FolderModel::ColumnFileMTime; - else if(str == "owner") - ret = Fm::FolderModel::ColumnFileOwner; - else - ret = Fm::FolderModel::ColumnFileName; - return ret; + Fm::FolderModel::ColumnId ret; + if(str == "name") { + ret = Fm::FolderModel::ColumnFileName; + } + else if(str == "type") { + ret = Fm::FolderModel::ColumnFileType; + } + else if(str == "size") { + ret = Fm::FolderModel::ColumnFileSize; + } + else if(str == "mtime") { + ret = Fm::FolderModel::ColumnFileMTime; + } + else if(str == "owner") { + ret = Fm::FolderModel::ColumnFileOwner; + } + else { + ret = Fm::FolderModel::ColumnFileName; + } + return ret; } static const char* wallpaperModeToString(int value) { - const char* ret; - switch(value) { + const char* ret; + switch(value) { case DesktopWindow::WallpaperNone: default: - ret = "none"; - break; + ret = "none"; + break; case DesktopWindow::WallpaperStretch: - ret = "stretch"; - break; + ret = "stretch"; + break; case DesktopWindow::WallpaperFit: - ret = "fit"; - break; + ret = "fit"; + break; case DesktopWindow::WallpaperCenter: - ret = "center"; - break; + ret = "center"; + break; case DesktopWindow::WallpaperTile: - ret = "tile"; - break; + ret = "tile"; + break; case DesktopWindow::WallpaperZoom: - ret = "zoom"; - break; - } - return ret; + ret = "zoom"; + break; + } + return ret; } static int wallpaperModeFromString(const QString str) { - int ret; - if(str == "stretch") - ret = DesktopWindow::WallpaperStretch; - else if(str == "fit") - ret = DesktopWindow::WallpaperFit; - else if(str == "center") - ret = DesktopWindow::WallpaperCenter; - else if(str == "tile") - ret = DesktopWindow::WallpaperTile; - else if(str == "zoom") - ret = DesktopWindow::WallpaperZoom; - else - ret = DesktopWindow::WallpaperNone; - return ret; + int ret; + if(str == "stretch") { + ret = DesktopWindow::WallpaperStretch; + } + else if(str == "fit") { + ret = DesktopWindow::WallpaperFit; + } + else if(str == "center") { + ret = DesktopWindow::WallpaperCenter; + } + else if(str == "tile") { + ret = DesktopWindow::WallpaperTile; + } + else if(str == "zoom") { + ret = DesktopWindow::WallpaperZoom; + } + else { + ret = DesktopWindow::WallpaperNone; + } + return ret; } static const char* sidePaneModeToString(Fm::SidePane::Mode value) { - const char* ret; - switch(value) { + const char* ret; + switch(value) { case Fm::SidePane::ModePlaces: default: - ret = "places"; - break; + ret = "places"; + break; case Fm::SidePane::ModeDirTree: - ret = "dirtree"; - break; + ret = "dirtree"; + break; case Fm::SidePane::ModeNone: - ret = "none"; - break; - } - return ret; + ret = "none"; + break; + } + return ret; } static Fm::SidePane::Mode sidePaneModeFromString(const QString& str) { - Fm::SidePane::Mode ret; - if(str == "none") - ret = Fm::SidePane::ModeNone; - else if(str == "dirtree") - ret = Fm::SidePane::ModeDirTree; - else - ret = Fm::SidePane::ModePlaces; - return ret; + Fm::SidePane::Mode ret; + if(str == "none") { + ret = Fm::SidePane::ModeNone; + } + else if(str == "dirtree") { + ret = Fm::SidePane::ModeDirTree; + } + else { + ret = Fm::SidePane::ModePlaces; + } + return ret; } void Settings::setTerminal(QString terminalCommand) { @@ -589,81 +680,81 @@ void Settings::setTerminal(QString terminalCommand) { // per-folder settings -FolderSettings Settings::loadFolderSettings(Fm::Path path) const { - FolderSettings settings; - Fm::FolderConfig cfg(path); - // set defaults - settings.setSortOrder(sortOrder()); - settings.setSortColumn(sortColumn()); - settings.setViewMode(viewMode()); - settings.setShowHidden(showHidden()); - settings.setSortFolderFirst(sortFolderFirst()); - settings.setSortCaseSensitive(sortCaseSensitive()); - // columns? - if(!cfg.isEmpty()) { - // load folder-specific settings - settings.setCustomized(true); - - char* str; - // load sorting - str = cfg.getString("SortOrder"); - if(str != nullptr) { - settings.setSortOrder(sortOrderFromString(str)); - g_free(str); - } - - str = cfg.getString("SortColumn"); - if(str != nullptr) { - settings.setSortColumn(sortColumnFromString(str)); - g_free(str); - } - - str = cfg.getString("ViewMode"); - if(str != nullptr) { - // set view mode - settings.setViewMode(viewModeFromString(str)); - g_free(str); - } - - gboolean show_hidden; - if(cfg.getBoolean("ShowHidden", &show_hidden)) { - settings.setShowHidden(show_hidden); - } - - gboolean folder_first; - if(cfg.getBoolean("SortFolderFirst", &folder_first)) { - settings.setSortFolderFirst(folder_first); - } - - gboolean case_sensitive; - if(cfg.getBoolean("SortCaseSensitive", &case_sensitive)) { - settings.setSortCaseSensitive(case_sensitive); - } - } - return settings; +FolderSettings Settings::loadFolderSettings(const Fm::FilePath& path) const { + FolderSettings settings; + Fm::FolderConfig cfg(path); + // set defaults + settings.setSortOrder(sortOrder()); + settings.setSortColumn(sortColumn()); + settings.setViewMode(viewMode()); + settings.setShowHidden(showHidden()); + settings.setSortFolderFirst(sortFolderFirst()); + settings.setSortCaseSensitive(sortCaseSensitive()); + // columns? + if(!cfg.isEmpty()) { + // load folder-specific settings + settings.setCustomized(true); + + char* str; + // load sorting + str = cfg.getString("SortOrder"); + if(str != nullptr) { + settings.setSortOrder(sortOrderFromString(str)); + g_free(str); + } + + str = cfg.getString("SortColumn"); + if(str != nullptr) { + settings.setSortColumn(sortColumnFromString(str)); + g_free(str); + } + + str = cfg.getString("ViewMode"); + if(str != nullptr) { + // set view mode + settings.setViewMode(viewModeFromString(str)); + g_free(str); + } + + gboolean show_hidden; + if(cfg.getBoolean("ShowHidden", &show_hidden)) { + settings.setShowHidden(show_hidden); + } + + gboolean folder_first; + if(cfg.getBoolean("SortFolderFirst", &folder_first)) { + settings.setSortFolderFirst(folder_first); + } + + gboolean case_sensitive; + if(cfg.getBoolean("SortCaseSensitive", &case_sensitive)) { + settings.setSortCaseSensitive(case_sensitive); + } + } + return settings; } -void Settings::saveFolderSettings(Fm::Path path, const FolderSettings& settings) { - if(!path.isNull()) { - // ensure that we have the libfm dir - QString dirName = xdgUserConfigDir() % QStringLiteral("/libfm"); - QDir().mkpath(dirName); // if libfm config dir does not exist, create it - - Fm::FolderConfig cfg(path); - cfg.setString("SortOrder", sortOrderToString(settings.sortOrder())); - cfg.setString("SortColumn", sortColumnToString(settings.sortColumn())); - cfg.setString("ViewMode", viewModeToString(settings.viewMode())); - cfg.setBoolean("ShowHidden", settings.showHidden()); - cfg.setBoolean("SortFolderFirst", settings.sortFolderFirst()); - cfg.setBoolean("SortCaseSensitive", settings.sortCaseSensitive()); - } +void Settings::saveFolderSettings(const Fm::FilePath& path, const FolderSettings& settings) { + if(path) { + // ensure that we have the libfm dir + QString dirName = xdgUserConfigDir() % QStringLiteral("/libfm"); + QDir().mkpath(dirName); // if libfm config dir does not exist, create it + + Fm::FolderConfig cfg(path); + cfg.setString("SortOrder", sortOrderToString(settings.sortOrder())); + cfg.setString("SortColumn", sortColumnToString(settings.sortColumn())); + cfg.setString("ViewMode", viewModeToString(settings.viewMode())); + cfg.setBoolean("ShowHidden", settings.showHidden()); + cfg.setBoolean("SortFolderFirst", settings.sortFolderFirst()); + cfg.setBoolean("SortCaseSensitive", settings.sortCaseSensitive()); + } } -void Settings::clearFolderSettings(Fm::Path path) const { - if(!path.isNull()) { - Fm::FolderConfig cfg(path); - cfg.purge(); - } +void Settings::clearFolderSettings(const Fm::FilePath& path) const { + if(path) { + Fm::FolderConfig cfg(path); + cfg.purge(); + } } diff --git a/pcmanfm/settings.h b/pcmanfm/settings.h index 971ba8c..5ca17fd 100644 --- a/pcmanfm/settings.h +++ b/pcmanfm/settings.h @@ -27,7 +27,7 @@ #include #include "desktopwindow.h" #include -#include +#include namespace PCManFM { @@ -40,802 +40,910 @@ enum OpenDirTargetType { class FolderSettings { public: - FolderSettings(): - isCustomized_(false), - sortOrder_(Qt::AscendingOrder), - sortColumn_(Fm::FolderModel::ColumnFileName), - viewMode_(Fm::FolderView::IconMode), - showHidden_(false), - sortFolderFirst_(true), - sortCaseSensitive_(true) { - } - - bool isCustomized() const { - return isCustomized_; - } - - void setCustomized(bool value) { - isCustomized_ = value; - } - - Qt::SortOrder sortOrder() const { - return sortOrder_; - } - - void setSortOrder(Qt::SortOrder value) { - sortOrder_ = value; - } - - Fm::FolderModel::ColumnId sortColumn() const { - return sortColumn_; - } - - void setSortColumn(Fm::FolderModel::ColumnId value) { - sortColumn_ = value; - } - - Fm::FolderView::ViewMode viewMode() const { - return viewMode_; - } - - void setViewMode(Fm::FolderView::ViewMode value) { - viewMode_ = value; - } - - bool sortFolderFirst() const { - return sortFolderFirst_; - } - - void setSortFolderFirst(bool value) { - sortFolderFirst_ = value; - } - - bool showHidden() const { - return showHidden_; - } - - void setShowHidden(bool value) { - showHidden_ = value; - } - - bool sortCaseSensitive() const { - return sortCaseSensitive_; - } - - void setSortCaseSensitive(bool value) { - sortCaseSensitive_ = value; - } + FolderSettings(): + isCustomized_(false), + sortOrder_(Qt::AscendingOrder), + sortColumn_(Fm::FolderModel::ColumnFileName), + viewMode_(Fm::FolderView::IconMode), + showHidden_(false), + sortFolderFirst_(true), + sortCaseSensitive_(true) { + } + + bool isCustomized() const { + return isCustomized_; + } + + void setCustomized(bool value) { + isCustomized_ = value; + } + + Qt::SortOrder sortOrder() const { + return sortOrder_; + } + + void setSortOrder(Qt::SortOrder value) { + sortOrder_ = value; + } + + Fm::FolderModel::ColumnId sortColumn() const { + return sortColumn_; + } + + void setSortColumn(Fm::FolderModel::ColumnId value) { + sortColumn_ = value; + } + + Fm::FolderView::ViewMode viewMode() const { + return viewMode_; + } + + void setViewMode(Fm::FolderView::ViewMode value) { + viewMode_ = value; + } + + bool sortFolderFirst() const { + return sortFolderFirst_; + } + + void setSortFolderFirst(bool value) { + sortFolderFirst_ = value; + } + + bool showHidden() const { + return showHidden_; + } + + void setShowHidden(bool value) { + showHidden_ = value; + } + + bool sortCaseSensitive() const { + return sortCaseSensitive_; + } + + void setSortCaseSensitive(bool value) { + sortCaseSensitive_ = value; + } private: - bool isCustomized_; - Qt::SortOrder sortOrder_; - Fm::FolderModel::ColumnId sortColumn_; - Fm::FolderView::ViewMode viewMode_; - bool showHidden_; - bool sortFolderFirst_; - bool sortCaseSensitive_; - // columns? + bool isCustomized_; + Qt::SortOrder sortOrder_; + Fm::FolderModel::ColumnId sortColumn_; + Fm::FolderView::ViewMode viewMode_; + bool showHidden_; + bool sortFolderFirst_; + bool sortCaseSensitive_; + // columns? }; class Settings : public QObject { - Q_OBJECT + Q_OBJECT public: - Settings(); - virtual ~Settings(); + enum IconType { + Small, + Big, + Thumbnail + }; - bool load(QString profile = "default"); - bool save(QString profile = QString()); + Settings(); + virtual ~Settings(); - bool loadFile(QString filePath); - bool saveFile(QString filePath); + bool load(QString profile = "default"); + bool save(QString profile = QString()); + + bool loadFile(QString filePath); + bool saveFile(QString filePath); - static QString xdgUserConfigDir(); + static QString xdgUserConfigDir(); + static const QList & iconSizes(IconType type); - QString profileDir(QString profile, bool useFallback = false); + QString profileDir(QString profile, bool useFallback = false); + + // setter/getter functions + QString profileName() const { + return profileName_; + } - // setter/getter functions - QString profileName() const { - return profileName_; - } + bool supportTrash() const { + return supportTrash_; + } - bool supportTrash() const { - return supportTrash_; - } + QString fallbackIconThemeName() const { + return fallbackIconThemeName_; + } - QString fallbackIconThemeName() const { - return fallbackIconThemeName_; - } + bool useFallbackIconTheme() const { + return useFallbackIconTheme_; + } - bool useFallbackIconTheme() const { - return useFallbackIconTheme_; - } + void setFallbackIconThemeName(QString iconThemeName) { + fallbackIconThemeName_ = iconThemeName; + } - void setFallbackIconThemeName(QString iconThemeName) { - fallbackIconThemeName_ = iconThemeName; - } + OpenDirTargetType bookmarkOpenMethod() { + return bookmarkOpenMethod_; + } - OpenDirTargetType bookmarkOpenMethod() { - return bookmarkOpenMethod_; - } + void setBookmarkOpenMethod(OpenDirTargetType bookmarkOpenMethod) { + bookmarkOpenMethod_ = bookmarkOpenMethod; + } - void setBookmarkOpenMethod(OpenDirTargetType bookmarkOpenMethod) { - bookmarkOpenMethod_ = bookmarkOpenMethod; - } + QString suCommand() const { + return suCommand_; + } - QString suCommand() const { - return suCommand_; - } + void setSuCommand(QString suCommand) { + suCommand_ = suCommand; + } - void setSuCommand(QString suCommand) { - suCommand_ = suCommand; - } + QString terminal() { + return terminal_; + } + void setTerminal(QString terminalCommand); - QString terminal() { - return terminal_; - } - void setTerminal(QString terminalCommand); + QString archiver() const { + return archiver_; + } - QString archiver() const { - return archiver_; - } + void setArchiver(QString archiver) { + archiver_ = archiver; + // override libfm FmConfig + g_free(fm_config->archiver); + fm_config->archiver = g_strdup(archiver_.toLocal8Bit().constData()); + } - void setArchiver(QString archiver) { - archiver_ = archiver; - // override libfm FmConfig - g_free(fm_config->archiver); - fm_config->archiver = g_strdup(archiver_.toLocal8Bit().constData()); - } + bool mountOnStartup() const { + return mountOnStartup_; + } - bool mountOnStartup() const { - return mountOnStartup_; - } + void setMountOnStartup(bool mountOnStartup) { + mountOnStartup_ = mountOnStartup; + } - void setMountOnStartup(bool mountOnStartup) { - mountOnStartup_ = mountOnStartup; - } + bool mountRemovable() { + return mountRemovable_; + } - bool mountRemovable() { - return mountRemovable_; - } + void setMountRemovable(bool mountRemovable) { + mountRemovable_ = mountRemovable; + } - void setMountRemovable(bool mountRemovable) { - mountRemovable_ = mountRemovable; - } + bool autoRun() const { + return autoRun_; + } - bool autoRun() const { - return autoRun_; - } + void setAutoRun(bool autoRun) { + autoRun_ = autoRun; + } - void setAutoRun(bool autoRun) { - autoRun_ = autoRun; - } + bool closeOnUnmount() const { + return closeOnUnmount_; + } - bool closeOnUnmount() const { - return closeOnUnmount_; - } + void setCloseOnUnmount(bool value) { + closeOnUnmount_ = value; + } - void setCloseOnUnmount(bool value) { - closeOnUnmount_ = value; - } + DesktopWindow::WallpaperMode wallpaperMode() const { + return DesktopWindow::WallpaperMode(wallpaperMode_); + } - DesktopWindow::WallpaperMode wallpaperMode() const { - return DesktopWindow::WallpaperMode(wallpaperMode_); - } + void setWallpaperMode(int wallpaperMode) { + wallpaperMode_ = wallpaperMode; + } - void setWallpaperMode(int wallpaperMode) { - wallpaperMode_ = wallpaperMode; - } + QString wallpaper() const { + return wallpaper_; + } - QString wallpaper() const { - return wallpaper_; - } + void setWallpaper(QString wallpaper) { + wallpaper_ = wallpaper; + } + + QString wallpaperDir() const { + return wallpaperDir_; + } - void setWallpaper(QString wallpaper) { - wallpaper_ = wallpaper; - } - - const QColor& desktopBgColor() const { - return desktopBgColor_; - } + void setLastSlide(QString wallpaper) { + lastSlide_ = wallpaper; + } - void setDesktopBgColor(QColor desktopBgColor) { - desktopBgColor_ = desktopBgColor; - } - - const QColor& desktopFgColor() const { - return desktopFgColor_; - } - - void setDesktopFgColor(QColor desktopFgColor) { - desktopFgColor_ = desktopFgColor; - } - - const QColor& desktopShadowColor() const { - return desktopShadowColor_; - } - - void setDesktopShadowColor(QColor desktopShadowColor) { - desktopShadowColor_ = desktopShadowColor; - } - - QFont desktopFont() const { - return desktopFont_; - } - - void setDesktopFont(QFont font) { - desktopFont_ = font; - } - - int desktopIconSize() const { - return desktopIconSize_; - } - - void setDesktopIconSize(int desktopIconSize) { - desktopIconSize_ = desktopIconSize; - } - - bool showWmMenu() const { - return showWmMenu_; - } - - void setShowWmMenu(bool value) { - showWmMenu_ = value; - } - - bool desktopShowHidden() const { - return desktopShowHidden_; - } - - void setDesktopShowHidden(bool desktopShowHidden) { - desktopShowHidden_ = desktopShowHidden; - } - - Qt::SortOrder desktopSortOrder() const { - return desktopSortOrder_; - } - - void setDesktopSortOrder(Qt::SortOrder desktopSortOrder) { - desktopSortOrder_ = desktopSortOrder; - } - - Fm::FolderModel::ColumnId desktopSortColumn() const { - return desktopSortColumn_; - } - - void setDesktopSortColumn(Fm::FolderModel::ColumnId desktopSortColumn) { - desktopSortColumn_ = desktopSortColumn; - } - - bool desktopSortFolderFirst() const { - return desktopSortFolderFirst_; - } - - void setSesktopSortFolderFirst(bool desktopFolderFirst) { - desktopSortFolderFirst_ = desktopFolderFirst; - } - - bool alwaysShowTabs() const { - return alwaysShowTabs_; - } - - void setAlwaysShowTabs(bool alwaysShowTabs) { - alwaysShowTabs_ = alwaysShowTabs; - } - - bool showTabClose() const { - return showTabClose_; - } - - void setShowTabClose(bool showTabClose) { - showTabClose_ = showTabClose; - } - - bool rememberWindowSize() const { - return rememberWindowSize_; - } - - void setRememberWindowSize(bool rememberWindowSize) { - rememberWindowSize_ = rememberWindowSize; - } - - int windowWidth() const { - if(rememberWindowSize_) - return lastWindowWidth_; - else - return fixedWindowWidth_; - } - - int windowHeight() const { - if(rememberWindowSize_) - return lastWindowHeight_; - else - return fixedWindowHeight_; - } - - bool windowMaximized() const { - if(rememberWindowSize_) - return lastWindowMaximized_; - else - return false; - } - - int fixedWindowWidth() const { - return fixedWindowWidth_; - } - - void setFixedWindowWidth(int fixedWindowWidth) { - fixedWindowWidth_ = fixedWindowWidth; - } - - int fixedWindowHeight() const { - return fixedWindowHeight_; - } - - void setFixedWindowHeight(int fixedWindowHeight) { - fixedWindowHeight_ = fixedWindowHeight; - } - - void setLastWindowWidth(int lastWindowWidth) { - lastWindowWidth_ = lastWindowWidth; - } - - void setLastWindowHeight(int lastWindowHeight) { - lastWindowHeight_ = lastWindowHeight; - } - - void setLastWindowMaximized(bool lastWindowMaximized) { - lastWindowMaximized_ = lastWindowMaximized; - } - - int splitterPos() const { - return splitterPos_; - } - - void setSplitterPos(int splitterPos) { - splitterPos_ = splitterPos; - } - - Fm::SidePane::Mode sidePaneMode() const { - return sidePaneMode_; - } - - void setSidePaneMode(Fm::SidePane::Mode sidePaneMode) { - sidePaneMode_ = sidePaneMode; - } - - bool showMenuBar() const { - return showMenuBar_; - } - - void setShowMenuBar(bool showMenuBar) { - showMenuBar_ = showMenuBar; - } - - bool fullWidthTabBar() const { - return fullWidthTabBar_; - } - - void setFullWidthTabBar(bool fullWith) { - fullWidthTabBar_ = fullWith; - } - - Fm::FolderView::ViewMode viewMode() const { - return viewMode_; - } - - void setViewMode(Fm::FolderView::ViewMode viewMode) { - viewMode_ = viewMode; - } - - bool showHidden() const { - return showHidden_; - } - - void setShowHidden(bool showHidden) { - showHidden_ = showHidden; - } - - bool sortCaseSensitive() const { - return sortCaseSensitive_; - } - - void setSortCaseSensitive(bool value) { - sortCaseSensitive_ = value; - } + QString lastSlide() const { + return lastSlide_; + } + void setWallpaperDir(QString dir) { + wallpaperDir_ = dir; + } - bool placesHome() const { - return placesHome_; - } + int slideShowInterval() const { + return slideShowInterval_; + } - void setPlacesHome(bool placesHome) { - placesHome_ = placesHome; - } + void setSlideShowInterval(int interval) { + slideShowInterval_ = interval; + } - bool placesDesktop() const { - return placesDesktop_; - } + bool wallpaperRandomize() const { + return wallpaperRandomize_; + } - void setPlacesDesktop(bool placesDesktop) { - placesDesktop_ = placesDesktop; - } + void setWallpaperRandomize(bool randomize) { + wallpaperRandomize_ = randomize; + } - bool placesApplications() const { - return placesApplications_; - } + const QColor& desktopBgColor() const { + return desktopBgColor_; + } - void setPlacesApplications(bool placesApplications) { - placesApplications_ = placesApplications; - } + void setDesktopBgColor(QColor desktopBgColor) { + desktopBgColor_ = desktopBgColor; + } + + const QColor& desktopFgColor() const { + return desktopFgColor_; + } + + void setDesktopFgColor(QColor desktopFgColor) { + desktopFgColor_ = desktopFgColor; + } + + const QColor& desktopShadowColor() const { + return desktopShadowColor_; + } + + void setDesktopShadowColor(QColor desktopShadowColor) { + desktopShadowColor_ = desktopShadowColor; + } + + QFont desktopFont() const { + return desktopFont_; + } + + void setDesktopFont(QFont font) { + desktopFont_ = font; + } + + int desktopIconSize() const { + return desktopIconSize_; + } + + void setDesktopIconSize(int desktopIconSize) { + desktopIconSize_ = desktopIconSize; + } + + bool showWmMenu() const { + return showWmMenu_; + } + + void setShowWmMenu(bool value) { + showWmMenu_ = value; + } + + bool desktopShowHidden() const { + return desktopShowHidden_; + } + + void setDesktopShowHidden(bool desktopShowHidden) { + desktopShowHidden_ = desktopShowHidden; + } + + Qt::SortOrder desktopSortOrder() const { + return desktopSortOrder_; + } + + void setDesktopSortOrder(Qt::SortOrder desktopSortOrder) { + desktopSortOrder_ = desktopSortOrder; + } + + Fm::FolderModel::ColumnId desktopSortColumn() const { + return desktopSortColumn_; + } + + void setDesktopSortColumn(Fm::FolderModel::ColumnId desktopSortColumn) { + desktopSortColumn_ = desktopSortColumn; + } + + bool desktopSortFolderFirst() const { + return desktopSortFolderFirst_; + } + + void setSesktopSortFolderFirst(bool desktopFolderFirst) { + desktopSortFolderFirst_ = desktopFolderFirst; + } + + bool alwaysShowTabs() const { + return alwaysShowTabs_; + } + + void setAlwaysShowTabs(bool alwaysShowTabs) { + alwaysShowTabs_ = alwaysShowTabs; + } + + bool showTabClose() const { + return showTabClose_; + } + + void setShowTabClose(bool showTabClose) { + showTabClose_ = showTabClose; + } + + bool rememberWindowSize() const { + return rememberWindowSize_; + } + + void setRememberWindowSize(bool rememberWindowSize) { + rememberWindowSize_ = rememberWindowSize; + } + + int windowWidth() const { + if(rememberWindowSize_) { + return lastWindowWidth_; + } + else { + return fixedWindowWidth_; + } + } + + int windowHeight() const { + if(rememberWindowSize_) { + return lastWindowHeight_; + } + else { + return fixedWindowHeight_; + } + } + + bool windowMaximized() const { + if(rememberWindowSize_) { + return lastWindowMaximized_; + } + else { + return false; + } + } + + int fixedWindowWidth() const { + return fixedWindowWidth_; + } + + void setFixedWindowWidth(int fixedWindowWidth) { + fixedWindowWidth_ = fixedWindowWidth; + } + + int fixedWindowHeight() const { + return fixedWindowHeight_; + } + + void setFixedWindowHeight(int fixedWindowHeight) { + fixedWindowHeight_ = fixedWindowHeight; + } + + void setLastWindowWidth(int lastWindowWidth) { + lastWindowWidth_ = lastWindowWidth; + } + + void setLastWindowHeight(int lastWindowHeight) { + lastWindowHeight_ = lastWindowHeight; + } + + void setLastWindowMaximized(bool lastWindowMaximized) { + lastWindowMaximized_ = lastWindowMaximized; + } + + int splitterPos() const { + return splitterPos_; + } + + void setSplitterPos(int splitterPos) { + splitterPos_ = splitterPos; + } + + Fm::SidePane::Mode sidePaneMode() const { + return sidePaneMode_; + } + + void setSidePaneMode(Fm::SidePane::Mode sidePaneMode) { + sidePaneMode_ = sidePaneMode; + } + + bool showMenuBar() const { + return showMenuBar_; + } + + void setShowMenuBar(bool showMenuBar) { + showMenuBar_ = showMenuBar; + } + + bool fullWidthTabBar() const { + return fullWidthTabBar_; + } + + void setFullWidthTabBar(bool fullWith) { + fullWidthTabBar_ = fullWith; + } + + Fm::FolderView::ViewMode viewMode() const { + return viewMode_; + } + + void setViewMode(Fm::FolderView::ViewMode viewMode) { + viewMode_ = viewMode; + } + + bool showHidden() const { + return showHidden_; + } + + void setShowHidden(bool showHidden) { + showHidden_ = showHidden; + } + + bool sortCaseSensitive() const { + return sortCaseSensitive_; + } + + void setSortCaseSensitive(bool value) { + sortCaseSensitive_ = value; + } + + + bool placesHome() const { + return placesHome_; + } - bool placesTrash() const { - return placesTrash_; - } + void setPlacesHome(bool placesHome) { + placesHome_ = placesHome; + } - void setPlacesTrash(bool placesTrash) { - placesTrash_ = placesTrash; - } + bool placesDesktop() const { + return placesDesktop_; + } - bool placesRoot() const { - return placesRoot_; - } + void setPlacesDesktop(bool placesDesktop) { + placesDesktop_ = placesDesktop; + } - void setPlacesRoot(bool placesRoot) { - placesRoot_ = placesRoot; - } + bool placesApplications() const { + return placesApplications_; + } - bool placesComputer() const { - return placesComputer_; - } + void setPlacesApplications(bool placesApplications) { + placesApplications_ = placesApplications; + } - void setPlacesComputer(bool placesComputer) { - placesComputer_ = placesComputer; - } + bool placesTrash() const { + return placesTrash_; + } - bool placesNetwork() const { - return placesNetwork_; - } + void setPlacesTrash(bool placesTrash) { + placesTrash_ = placesTrash; + } - void setPlacesNetwork(bool placesNetwork) { - placesNetwork_ = placesNetwork; - } + bool placesRoot() const { + return placesRoot_; + } + void setPlacesRoot(bool placesRoot) { + placesRoot_ = placesRoot; + } - Qt::SortOrder sortOrder() const { - return sortOrder_; - } + bool placesComputer() const { + return placesComputer_; + } - void setSortOrder(Qt::SortOrder sortOrder) { - sortOrder_ = sortOrder; - } + void setPlacesComputer(bool placesComputer) { + placesComputer_ = placesComputer; + } - Fm::FolderModel::ColumnId sortColumn() const { - return sortColumn_; - } + bool placesNetwork() const { + return placesNetwork_; + } - void setSortColumn(Fm::FolderModel::ColumnId sortColumn) { - sortColumn_ = sortColumn; - } + void setPlacesNetwork(bool placesNetwork) { + placesNetwork_ = placesNetwork; + } - bool sortFolderFirst() const { - return sortFolderFirst_; - } - void setSortFolderFirst(bool folderFirst) { - sortFolderFirst_ = folderFirst; - } + Qt::SortOrder sortOrder() const { + return sortOrder_; + } - bool showFilter() const { - return showFilter_; - } + void setSortOrder(Qt::SortOrder sortOrder) { + sortOrder_ = sortOrder; + } - void setShowFilter(bool value) { - showFilter_ = value; - } + Fm::FolderModel::ColumnId sortColumn() const { + return sortColumn_; + } - bool pathBarButtons() const { - return pathBarButtons_; - } + void setSortColumn(Fm::FolderModel::ColumnId sortColumn) { + sortColumn_ = sortColumn; + } - void setPathBarButtons(bool value) { - pathBarButtons_ = value; - } + bool sortFolderFirst() const { + return sortFolderFirst_; + } - // settings for use with libfm - bool singleClick() const { - return singleClick_; - } + void setSortFolderFirst(bool folderFirst) { + sortFolderFirst_ = folderFirst; + } - void setSingleClick(bool singleClick) { - singleClick_ = singleClick; - } + bool showFilter() const { + return showFilter_; + } - int autoSelectionDelay() const { - return autoSelectionDelay_; - } + void setShowFilter(bool value) { + showFilter_ = value; + } - void setAutoSelectionDelay(int value) { - autoSelectionDelay_ = value; - } + bool pathBarButtons() const { + return pathBarButtons_; + } - bool useTrash() const { - if(!supportTrash_) - return false; - return useTrash_; - } + void setPathBarButtons(bool value) { + pathBarButtons_ = value; + } - void setUseTrash(bool useTrash) { - useTrash_ = useTrash; - } + // settings for use with libfm + bool singleClick() const { + return singleClick_; + } - bool confirmDelete() const { - return confirmDelete_; - } + void setSingleClick(bool singleClick) { + singleClick_ = singleClick; + } - void setConfirmDelete(bool confirmDelete) { - confirmDelete_ = confirmDelete; - } + int autoSelectionDelay() const { + return autoSelectionDelay_; + } - bool noUsbTrash() const { - return noUsbTrash_; - } + void setAutoSelectionDelay(int value) { + autoSelectionDelay_ = value; + } - void setNoUsbTrash(bool noUsbTrash) { - noUsbTrash_ = noUsbTrash; - fm_config->no_usb_trash = noUsbTrash_; // also set this to libfm since FmFileOpsJob reads this config value before trashing files. - } + bool useTrash() const { + if(!supportTrash_) { + return false; + } + return useTrash_; + } - bool confirmTrash() const { - return confirmTrash_; - } + void setUseTrash(bool useTrash) { + useTrash_ = useTrash; + } - void setConfirmTrash(bool value) { - confirmTrash_ = value; - } + bool confirmDelete() const { + return confirmDelete_; + } - bool quickExec() const { - return quickExec_; - } + void setConfirmDelete(bool confirmDelete) { + confirmDelete_ = confirmDelete; + } - void setQuickExec(bool value) { - quickExec_ = value; - fm_config->quick_exec = quickExec_; - } - - // bool thumbnailLocal_; - // bool thumbnailMax; + bool noUsbTrash() const { + return noUsbTrash_; + } - int bigIconSize() const { - return bigIconSize_; - } + void setNoUsbTrash(bool noUsbTrash) { + noUsbTrash_ = noUsbTrash; + fm_config->no_usb_trash = noUsbTrash_; // also set this to libfm since FmFileOpsJob reads this config value before trashing files. + } - void setBigIconSize(int bigIconSize) { - bigIconSize_ = bigIconSize; - } + bool confirmTrash() const { + return confirmTrash_; + } - int smallIconSize() const { - return smallIconSize_; - } + void setConfirmTrash(bool value) { + confirmTrash_ = value; + } - void setSmallIconSize(int smallIconSize) { - smallIconSize_ = smallIconSize; - } - - int sidePaneIconSize() const { - return sidePaneIconSize_; - } - - void setSidePaneIconSize(int sidePaneIconSize) { - sidePaneIconSize_ = sidePaneIconSize; - } - - int thumbnailIconSize() const { - return thumbnailIconSize_; - } - - QSize folderViewCellMargins() const { - return folderViewCellMargins_; - } - - void setFolderViewCellMargins(QSize size) { - folderViewCellMargins_ = size; - } - - QSize desktopCellMargins() const { - return desktopCellMargins_; - } + bool quickExec() const { + return quickExec_; + } - void setDesktopCellMargins(QSize size) { - desktopCellMargins_ = size; - } + void setQuickExec(bool value) { + quickExec_ = value; + fm_config->quick_exec = quickExec_; + } + + // bool thumbnailLocal_; + // bool thumbnailMax; + + int bigIconSize() const { + return bigIconSize_; + } + + void setBigIconSize(int bigIconSize) { + bigIconSize_ = bigIconSize; + } + + int smallIconSize() const { + return smallIconSize_; + } + + void setSmallIconSize(int smallIconSize) { + smallIconSize_ = smallIconSize; + } + + int sidePaneIconSize() const { + return sidePaneIconSize_; + } + + void setSidePaneIconSize(int sidePaneIconSize) { + sidePaneIconSize_ = sidePaneIconSize; + } + + int thumbnailIconSize() const { + return thumbnailIconSize_; + } + + QSize folderViewCellMargins() const { + return folderViewCellMargins_; + } + + void setFolderViewCellMargins(QSize size) { + folderViewCellMargins_ = size; + } + + QSize desktopCellMargins() const { + return desktopCellMargins_; + } + void setDesktopCellMargins(QSize size) { + desktopCellMargins_ = size; + } - bool showThumbnails() { - return showThumbnails_; - } - void setShowThumbnails(bool show) { - showThumbnails_ = show; - } + bool showThumbnails() { + return showThumbnails_; + } + + void setShowThumbnails(bool show) { + showThumbnails_ = show; + } + + void setThumbnailLocalFilesOnly(bool value) { + Fm::ThumbnailJob::setLocalFilesOnly(value); + } + + bool thumbnailLocalFilesOnly() const { + return Fm::ThumbnailJob::localFilesOnly(); + } - void setThumbnailLocalFilesOnly(bool value) { - Fm::ThumbnailLoader::setLocalFilesOnly(value); - } + int maxThumbnailFileSize() const { + return Fm::ThumbnailJob::maxThumbnailFileSize(); + } - bool thumbnailLocalFilesOnly() { - return Fm::ThumbnailLoader::localFilesOnly(); - } + void setMaxThumbnailFileSize(int size) { + Fm::ThumbnailJob::setMaxThumbnailFileSize(size); + } - int maxThumbnailFileSize() { - return Fm::ThumbnailLoader::maxThumbnailFileSize(); - } + void setThumbnailIconSize(int thumbnailIconSize) { + thumbnailIconSize_ = thumbnailIconSize; + } - void setMaxThumbnailFileSize(int size) { - Fm::ThumbnailLoader::setMaxThumbnailFileSize(size); - } + bool siUnit() { + return siUnit_; + } - void setThumbnailIconSize(int thumbnailIconSize) { - thumbnailIconSize_ = thumbnailIconSize; - } + void setSiUnit(bool siUnit) { + siUnit_ = siUnit; + // override libfm FmConfig settings. FIXME: should we do this? + fm_config->si_unit = (gboolean)siUnit_; + } - bool siUnit() { - return siUnit_; - } + bool backupAsHidden() const { + return backupAsHidden_; + } - void setSiUnit(bool siUnit) { - siUnit_ = siUnit; - // override libfm FmConfig settings. FIXME: should we do this? - fm_config->si_unit = (gboolean)siUnit_; - } + void setBackupAsHidden(bool value) { + backupAsHidden_ = value; + fm_config->backup_as_hidden = backupAsHidden_; // also set this to libfm since fm_file_info_is_hidden() reads this value internally. + } - bool backupAsHidden() const { - return backupAsHidden_; - } + bool showFullNames() const { + return showFullNames_; + } - void setBackupAsHidden(bool value) { - backupAsHidden_ = value; - fm_config->backup_as_hidden = backupAsHidden_; // also set this to libfm since fm_file_info_is_hidden() reads this value internally. - } + void setShowFullNames(bool value) { + showFullNames_ = value; + } - bool showFullNames() const { - return showFullNames_; - } + bool shadowHidden() const { + return shadowHidden_; + } - void setShowFullNames(bool value) { - showFullNames_ = value; - } + void setShadowHidden(bool value) { + shadowHidden_ = value; + } - bool shadowHidden() const { - return shadowHidden_; - } + bool onlyUserTemplates() const { + return onlyUserTemplates_; + } - void setShadowHidden(bool value) { - shadowHidden_ = value; - } + void setOnlyUserTemplates(bool value) { + onlyUserTemplates_ = value; + fm_config->only_user_templates = onlyUserTemplates_; + } - bool onlyUserTemplates() const { - return onlyUserTemplates_; - } + bool templateTypeOnce() const { + return templateTypeOnce_; + } - void setOnlyUserTemplates(bool value) { - onlyUserTemplates_ = value; - fm_config->only_user_templates = onlyUserTemplates_; - } + void setTemplateTypeOnce(bool value) { + templateTypeOnce_ = value; + fm_config->template_type_once = templateTypeOnce_; + } - bool templateTypeOnce() const { - return templateTypeOnce_; - } + bool templateRunApp() const { + return templateRunApp_; + } - void setTemplateTypeOnce(bool value) { - templateTypeOnce_ = value; - fm_config->template_type_once = templateTypeOnce_; - } + void setTemplateRunApp(bool value) { + templateRunApp_ = value; + fm_config->template_run_app = templateRunApp_; + } - bool templateRunApp() const { - return templateRunApp_; - } + // per-folder settings + FolderSettings loadFolderSettings(const Fm::FilePath& path) const; - void setTemplateRunApp(bool value) { - templateRunApp_ = value; - fm_config->template_run_app = templateRunApp_; - } + void saveFolderSettings(const Fm::FilePath& path, const FolderSettings& settings); - // per-folder settings - FolderSettings loadFolderSettings(Fm::Path path) const; + void clearFolderSettings(const Fm::FilePath& path) const; - void saveFolderSettings(Fm::Path path, const FolderSettings &settings); + bool searchNameCaseInsensitive() const { + return searchNameCaseInsensitive_; + } - void clearFolderSettings(Fm::Path path) const; + void setSearchNameCaseInsensitive(bool caseInsensitive) { + searchNameCaseInsensitive_ = caseInsensitive; + } + + bool searchContentCaseInsensitive() const { + return searchContentCaseInsensitive_; + } + + void setsearchContentCaseInsensitive(bool caseInsensitive) { + searchContentCaseInsensitive_ = caseInsensitive; + } + + bool searchNameRegexp() const { + return searchNameRegexp_; + } + + void setSearchNameRegexp(bool reg) { + searchNameRegexp_ = reg; + } + + bool searchContentRegexp() const { + return searchContentRegexp_; + } + + void setSearchContentRegexp(bool reg) { + searchContentRegexp_ = reg; + } + + bool searchRecursive() const { + return searchRecursive_; + } + + void setSearchRecursive(bool rec) { + searchRecursive_ = rec; + } + + bool searchhHidden() const { + return searchhHidden_; + } + + void setSearchhHidden(bool hidden) { + searchhHidden_ = hidden; + } private: - QString profileName_; - bool supportTrash_; - - // PCManFM specific - QString fallbackIconThemeName_; - bool useFallbackIconTheme_; - - OpenDirTargetType bookmarkOpenMethod_; - QString suCommand_; - QString terminal_; - bool mountOnStartup_; - bool mountRemovable_; - bool autoRun_; - bool closeOnUnmount_; - - int wallpaperMode_; - QString wallpaper_; - QColor desktopBgColor_; - QColor desktopFgColor_; - QColor desktopShadowColor_; - QFont desktopFont_; - int desktopIconSize_; - bool showWmMenu_; - - bool desktopShowHidden_; - Qt::SortOrder desktopSortOrder_; - Fm::FolderModel::ColumnId desktopSortColumn_; - bool desktopSortFolderFirst_; - - bool alwaysShowTabs_; - bool showTabClose_; - bool rememberWindowSize_; - int fixedWindowWidth_; - int fixedWindowHeight_; - int lastWindowWidth_; - int lastWindowHeight_; - bool lastWindowMaximized_; - int splitterPos_; - Fm::SidePane::Mode sidePaneMode_; - bool showMenuBar_; - bool fullWidthTabBar_; - - Fm::FolderView::ViewMode viewMode_; - bool showHidden_; - Qt::SortOrder sortOrder_; - Fm::FolderModel::ColumnId sortColumn_; - bool sortFolderFirst_; - bool sortCaseSensitive_; - bool showFilter_; - bool pathBarButtons_; - - // settings for use with libfm - bool singleClick_; - int autoSelectionDelay_; - bool useTrash_; - bool confirmDelete_; - bool noUsbTrash_; // do not trash files on usb removable devices - bool confirmTrash_; // Confirm before moving files into "trash can" - bool quickExec_; // Don't ask options on launch executable file - - bool showThumbnails_; - - QString archiver_; - bool siUnit_; - bool backupAsHidden_; - bool showFullNames_; - bool shadowHidden_; - - bool placesHome_; - bool placesDesktop_; - bool placesApplications_; - bool placesTrash_; - bool placesRoot_; - bool placesComputer_; - bool placesNetwork_; - - int bigIconSize_; - int smallIconSize_; - int sidePaneIconSize_; - int thumbnailIconSize_; - - bool onlyUserTemplates_; - bool templateTypeOnce_; - bool templateRunApp_; - - QSize folderViewCellMargins_; - QSize desktopCellMargins_; + int toIconSize(int size, IconType type) const; + + QString profileName_; + bool supportTrash_; + + // PCManFM specific + QString fallbackIconThemeName_; + bool useFallbackIconTheme_; + + OpenDirTargetType bookmarkOpenMethod_; + QString suCommand_; + QString terminal_; + bool mountOnStartup_; + bool mountRemovable_; + bool autoRun_; + bool closeOnUnmount_; + + int wallpaperMode_; + QString wallpaper_; + QString lastSlide_; + QString wallpaperDir_; + int slideShowInterval_; + bool wallpaperRandomize_; + QColor desktopBgColor_; + QColor desktopFgColor_; + QColor desktopShadowColor_; + QFont desktopFont_; + int desktopIconSize_; + bool showWmMenu_; + + bool desktopShowHidden_; + Qt::SortOrder desktopSortOrder_; + Fm::FolderModel::ColumnId desktopSortColumn_; + bool desktopSortFolderFirst_; + + bool alwaysShowTabs_; + bool showTabClose_; + bool rememberWindowSize_; + int fixedWindowWidth_; + int fixedWindowHeight_; + int lastWindowWidth_; + int lastWindowHeight_; + bool lastWindowMaximized_; + int splitterPos_; + Fm::SidePane::Mode sidePaneMode_; + bool showMenuBar_; + bool fullWidthTabBar_; + + Fm::FolderView::ViewMode viewMode_; + bool showHidden_; + Qt::SortOrder sortOrder_; + Fm::FolderModel::ColumnId sortColumn_; + bool sortFolderFirst_; + bool sortCaseSensitive_; + bool showFilter_; + bool pathBarButtons_; + + // settings for use with libfm + bool singleClick_; + int autoSelectionDelay_; + bool useTrash_; + bool confirmDelete_; + bool noUsbTrash_; // do not trash files on usb removable devices + bool confirmTrash_; // Confirm before moving files into "trash can" + bool quickExec_; // Don't ask options on launch executable file + + bool showThumbnails_; + + QString archiver_; + bool siUnit_; + bool backupAsHidden_; + bool showFullNames_; + bool shadowHidden_; + + bool placesHome_; + bool placesDesktop_; + bool placesApplications_; + bool placesTrash_; + bool placesRoot_; + bool placesComputer_; + bool placesNetwork_; + + int bigIconSize_; + int smallIconSize_; + int sidePaneIconSize_; + int thumbnailIconSize_; + + bool onlyUserTemplates_; + bool templateTypeOnce_; + bool templateRunApp_; + + QSize folderViewCellMargins_; + QSize desktopCellMargins_; + + // search settings + bool searchNameCaseInsensitive_; + bool searchContentCaseInsensitive_; + bool searchNameRegexp_; + bool searchContentRegexp_; + bool searchRecursive_; + bool searchhHidden_; }; } diff --git a/pcmanfm/statusbar.cpp b/pcmanfm/statusbar.cpp new file mode 100644 index 0000000..e5dfdb4 --- /dev/null +++ b/pcmanfm/statusbar.cpp @@ -0,0 +1,96 @@ +/* + 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 "statusbar.h" +#include +#include + +#define MESSAGE_DELAY 250 + +namespace PCManFM { + +Label::Label(QWidget* parent, Qt::WindowFlags f): + QLabel(parent, f), + lastWidth_(0) { + setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); + // set a min width to prevent the window from widening with long texts + setMinimumWidth(fontMetrics().averageCharWidth() * 10); +} + +// A simplified version of QLabel::paintEvent() +// without pixmap or shortcut but with eliding. +void Label::paintEvent(QPaintEvent* /*event*/) { + QRect cr = contentsRect().adjusted(margin(), margin(), -margin(), -margin()); + QString txt = text(); + // if the text is changed or its rect is resized (due to window resizing), + // find whether it needs to be elided... + if (txt != lastText_ || cr.width() != lastWidth_) { + lastText_ = txt; + lastWidth_ = cr.width(); + elidedText_ = fontMetrics().elidedText(txt, Qt::ElideMiddle, cr.width()); + } + // ... then, draw the (elided) text + if(!elidedText_.isEmpty()) { + QPainter painter(this); + QStyleOption opt; + opt.initFrom(this); + style()->drawItemText(&painter, cr, alignment(), opt.palette, isEnabled(), elidedText_, foregroundRole()); + } +} + +StatusBar::StatusBar(QWidget *parent): + QStatusBar(parent), + lastTimeOut_(0) { + statusLabel_ = new Label(); + statusLabel_->setFrameShape(QFrame::NoFrame); + // 4px space on both sides (not to be mixed with the permanent widget) + statusLabel_->setContentsMargins(4, 0, 4, 0); + addWidget(statusLabel_); + + messageTimer_ = new QTimer (this); + messageTimer_->setSingleShot(true); + messageTimer_->setInterval(MESSAGE_DELAY); + connect(messageTimer_, &QTimer::timeout, this, &StatusBar::reallyShowMessage); +} + +StatusBar::~StatusBar() { + if(messageTimer_) { + messageTimer_->stop(); + delete messageTimer_; + } +} + +void StatusBar::showMessage(const QString &message, int timeout) { + // don't show the message immediately + lastMessage_ = message; + lastTimeOut_ = timeout; + if(!messageTimer_->isActive()) { + messageTimer_->start(); + } +} + +void StatusBar::reallyShowMessage() { + if(lastTimeOut_ == 0) { + // set the text on the label to prevent its disappearance on focusing menubar items + // and also ensure that it contsains no newline (because file names may contain it) + statusLabel_->setText(lastMessage_.replace(QLatin1Char('\n'), QLatin1Char(' '))); + } + else { + QStatusBar::showMessage(lastMessage_, lastTimeOut_); + } +} + +} diff --git a/pcmanfm/statusbar.h b/pcmanfm/statusbar.h new file mode 100644 index 0000000..acc14f5 --- /dev/null +++ b/pcmanfm/statusbar.h @@ -0,0 +1,63 @@ +/* + 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 FM_STATUSBAR_H +#define FM_STATUSBAR_H + +#include +#include +#include + +namespace PCManFM { + +class Label : public QLabel { +Q_OBJECT + +public: + explicit Label(QWidget *parent = 0, Qt::WindowFlags f = Qt::WindowFlags()); + +protected: + void paintEvent(QPaintEvent *event) override; + +private: + QString elidedText_; + QString lastText_; + int lastWidth_; +}; + +class StatusBar : public QStatusBar { +Q_OBJECT + +public: + explicit StatusBar(QWidget *parent = 0); + ~StatusBar(); + +public Q_SLOTS: + void showMessage(const QString &message, int timeout = 0); + +protected Q_SLOTS: + void reallyShowMessage(); + +private: + Label* statusLabel_; // for a stable (elided) text + QTimer* messageTimer_; + QString lastMessage_; + int lastTimeOut_; +}; + +} + +#endif // FM_STATUSBAR_H diff --git a/pcmanfm/tabpage.cpp b/pcmanfm/tabpage.cpp index 3ef3b36..929192f 100644 --- a/pcmanfm/tabpage.cpp +++ b/pcmanfm/tabpage.cpp @@ -24,11 +24,13 @@ #include #include #include -#include +#include +#include #include #include #include #include +#include #include "settings.h" #include "application.h" #include @@ -39,582 +41,616 @@ using namespace Fm; namespace PCManFM { -bool ProxyFilter::filterAcceptsRow(const Fm::ProxyFolderModel* model, FmFileInfo* info) const { - if(!model || !info) +bool ProxyFilter::filterAcceptsRow(const Fm::ProxyFolderModel* model, const std::shared_ptr& info) const { + if(!model || !info) { + return true; + } + QString baseName = QString::fromStdString(info->name()); + if(!virtHiddenList_.isEmpty() && !model->showHidden() && virtHiddenList_.contains(baseName)) { + return false; + } + if(!filterStr_.isEmpty() && !baseName.contains(filterStr_, Qt::CaseInsensitive)) { + return false; + } return true; - QString baseName(fm_file_info_get_name(info)); - if(!virtHiddenList_.isEmpty() && !model->showHidden() && virtHiddenList_.contains(baseName)) - return false; - if(!filterStr_.isEmpty() && !baseName.contains(filterStr_, Qt::CaseInsensitive)) - return false; - return true; -} - -void ProxyFilter::setVirtHidden(Fm::Folder folder) { - virtHiddenList_ = QStringList(); // reset the list - if(folder.isNull()) - return; - Fm::Path path = folder.getPath(); - if(!path.isNull()) { - char* pathStr = path.toStr(); - if(pathStr) { - QString dotHidden = QString::fromUtf8(pathStr) + QString("/.hidden"); - g_free(pathStr); - // FIXME: this does not work for non-local filesystems - QFile file(dotHidden); - if(file.open(QIODevice::ReadOnly | QIODevice::Text)) { - QTextStream in(&file); - while(!in.atEnd()) - virtHiddenList_.append(in.readLine()); - file.close(); - } - } - } -} - -TabPage::TabPage(Fm::Path path, QWidget* parent): - QWidget(parent), - folderModel_(NULL), - overrideCursor_(false) { - - Settings& settings = static_cast(qApp)->settings(); - - // create proxy folder model to do item filtering - proxyModel_ = new ProxyFolderModel(); - proxyModel_->setShowHidden(settings.showHidden()); - proxyModel_->setShowThumbnails(settings.showThumbnails()); - connect(proxyModel_, &ProxyFolderModel::sortFilterChanged, this, &TabPage::sortFilterChanged); - - verticalLayout = new QVBoxLayout(this); - verticalLayout->setContentsMargins(0, 0, 0, 0); - - folderView_ = new View(settings.viewMode(), this); - folderView_->setMargins(settings.folderViewCellMargins()); - // newView->setColumnWidth(Fm::FolderModel::ColumnName, 200); - connect(folderView_, &View::openDirRequested, this, &TabPage::onOpenDirRequested); - connect(folderView_, &View::selChanged, this, &TabPage::onSelChanged); - connect(folderView_, &View::clickedBack, this, &TabPage::backwardRequested); - connect(folderView_, &View::clickedForward, this, &TabPage::forwardRequested); - - proxyFilter_ = new ProxyFilter(); - proxyModel_->addFilter(proxyFilter_); - - // FIXME: this is very dirty - folderView_->setModel(proxyModel_); - verticalLayout->addWidget(folderView_); - - chdir(path, true); +} + +void ProxyFilter::setVirtHidden(const std::shared_ptr &folder) { + virtHiddenList_ = QStringList(); // reset the list + if(!folder) { + return; + } + auto path = folder->path(); + if(path) { + auto pathStr = path.localPath(); + if(pathStr) { + QString dotHidden = QString::fromUtf8(pathStr.get()) + QString("/.hidden"); + // FIXME: this does not work for non-local filesystems + QFile file(dotHidden); + if(file.open(QIODevice::ReadOnly | QIODevice::Text)) { + QTextStream in(&file); + while(!in.atEnd()) { + virtHiddenList_.append(in.readLine()); + } + file.close(); + } + } + } +} + +TabPage::TabPage(QWidget* parent): + QWidget(parent), + folderView_{nullptr}, + folderModel_{nullptr}, + proxyModel_{nullptr}, + proxyFilter_{nullptr}, + verticalLayout{nullptr}, + overrideCursor_(false) { + + Settings& settings = static_cast(qApp)->settings(); + + // create proxy folder model to do item filtering + proxyModel_ = new ProxyFolderModel(); + proxyModel_->setShowHidden(settings.showHidden()); + proxyModel_->setShowThumbnails(settings.showThumbnails()); + connect(proxyModel_, &ProxyFolderModel::sortFilterChanged, this, &TabPage::sortFilterChanged); + + verticalLayout = new QVBoxLayout(this); + verticalLayout->setContentsMargins(0, 0, 0, 0); + + folderView_ = new View(settings.viewMode(), this); + folderView_->setMargins(settings.folderViewCellMargins()); + // newView->setColumnWidth(Fm::FolderModel::ColumnName, 200); + connect(folderView_, &View::openDirRequested, this, &TabPage::openDirRequested); + connect(folderView_, &View::selChanged, this, &TabPage::onSelChanged); + connect(folderView_, &View::clickedBack, this, &TabPage::backwardRequested); + connect(folderView_, &View::clickedForward, this, &TabPage::forwardRequested); + + proxyFilter_ = new ProxyFilter(); + proxyModel_->addFilter(proxyFilter_); + + // FIXME: this is very dirty + folderView_->setModel(proxyModel_); + verticalLayout->addWidget(folderView_); } TabPage::~TabPage() { - freeFolder(); - if(proxyFilter_) - delete proxyFilter_; - if(proxyModel_) - delete proxyModel_; - if(folderModel_) - folderModel_->unref(); + freeFolder(); + if(proxyFilter_) { + delete proxyFilter_; + } + if(proxyModel_) { + delete proxyModel_; + } + disconnect(folderModel_, &Fm::FolderModel::fileSizeChanged, this, &TabPage::onFileSizeChanged); + if(folderModel_) { + folderModel_->unref(); + } - if(overrideCursor_) { - QApplication::restoreOverrideCursor(); // remove busy cursor - } + if(overrideCursor_) { + QApplication::restoreOverrideCursor(); // remove busy cursor + } } void TabPage::freeFolder() { - if(!folder_.isNull()) { - if(folderSettings_.isCustomized()) { - // save custom view settings for this folder - static_cast(qApp)->settings().saveFolderSettings(folder_.getPath(), folderSettings_); - } - g_signal_handlers_disconnect_by_func(folder_, (gpointer)onFolderStartLoading, this); - g_signal_handlers_disconnect_by_func(folder_, (gpointer)onFolderFinishLoading, this); - g_signal_handlers_disconnect_by_func(folder_, (gpointer)onFolderError, this); - g_signal_handlers_disconnect_by_func(folder_, (gpointer)onFolderFsInfo, this); - g_signal_handlers_disconnect_by_func(folder_, (gpointer)onFolderRemoved, this); - g_signal_handlers_disconnect_by_func(folder_, (gpointer)onFolderUnmount, this); - g_signal_handlers_disconnect_by_func(folder_, (gpointer)onFolderContentChanged, this); - folder_ = nullptr; - } -} - -/*static*/ void TabPage::onFolderStartLoading(FmFolder* _folder, TabPage* pThis) { - if(!pThis->overrideCursor_) { - // FIXME: sometimes FmFolder of libfm generates unpaired "start-loading" and - // "finish-loading" signals of uncertain reasons. This should be a bug in libfm. - // Until it's fixed in libfm, we need to workaround the problem here, not to - // override the cursor twice. - QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); - pThis->overrideCursor_ = true; - } + if(folder_) { + if(folderSettings_.isCustomized()) { + // save custom view settings for this folder + static_cast(qApp)->settings().saveFolderSettings(folder_->path(), folderSettings_); + } + disconnect(folder_.get(), nullptr, this, nullptr); // disconnect from all signals + folder_ = nullptr; + } +} + +void TabPage::onFolderStartLoading() { + if(!overrideCursor_) { + // FIXME: sometimes FmFolder of libfm generates unpaired "start-loading" and + // "finish-loading" signals of uncertain reasons. This should be a bug in libfm. + // Until it's fixed in libfm, we need to workaround the problem here, not to + // override the cursor twice. + QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); + overrideCursor_ = true; + } #if 0 #if FM_CHECK_VERSION(1, 0, 2) && 0 // disabled - if(fm_folder_is_incremental(_folder)) { - /* create a model for the folder and set it to the view - it is delayed for non-incremental folders since adding rows into - model is much faster without handlers connected to its signals */ - FmFolderModel* model = fm_folder_model_new(folder, FALSE); - fm_folder_view_set_model(fv, model); - fm_folder_model_set_sort(model, app_config->sort_by, - (app_config->sort_type == GTK_SORT_ASCENDING) ? - FM_SORT_ASCENDING : FM_SORT_DESCENDING); - g_object_unref(model); - } - else + if(fm_folder_is_incremental(_folder)) { + /* create a model for the folder and set it to the view + it is delayed for non-incremental folders since adding rows into + model is much faster without handlers connected to its signals */ + FmFolderModel* model = fm_folder_model_new(folder, FALSE); + fm_folder_view_set_model(fv, model); + fm_folder_model_set_sort(model, app_config->sort_by, + (app_config->sort_type == GTK_SORT_ASCENDING) ? + FM_SORT_ASCENDING : FM_SORT_DESCENDING); + g_object_unref(model); + } + else #endif - fm_folder_view_set_model(fv, NULL); + fm_folder_view_set_model(fv, nullptr); #endif } -// slot -void TabPage::restoreScrollPos() { - // scroll to recorded position - folderView_->childView()->verticalScrollBar()->setValue(browseHistory().currentScrollPos()); +void TabPage::onUiUpdated() { + // scroll to recorded position + folderView_->childView()->verticalScrollBar()->setValue(browseHistory().currentScrollPos()); + + // if the current folder is the parent folder of the last browsed folder, + // select the folder item in current view. + if(lastFolderPath_ && lastFolderPath_.parent() == path()) { + QModelIndex index = folderView_->indexFromFolderPath(lastFolderPath_); + if(index.isValid()) { + folderView_->childView()->scrollTo(index, QAbstractItemView::EnsureVisible); + folderView_->childView()->setCurrentIndex(index); + } + } + // update selection statusbar info when needed + connect(folderModel_, &Fm::FolderModel::fileSizeChanged, this, &TabPage::onFileSizeChanged); +} - // if the current folder is the parent folder of the last browsed folder, - // select the folder item in current view. - if(!lastFolderPath_.isNull() && lastFolderPath_.getParent() == path()) { - QModelIndex index = folderView_->indexFromFolderPath(lastFolderPath_); - if(index.isValid()) { - folderView_->childView()->scrollTo(index, QAbstractItemView::EnsureVisible); - folderView_->childView()->setCurrentIndex(index); +void TabPage::onFileSizeChanged(const QModelIndex& index) { + if(folderView_->hasSelection()) { + QModelIndexList indexes = folderView_->selectionModel()->selectedIndexes(); + if(indexes.contains(proxyModel_->mapFromSource(index))) { + onSelChanged(); + } } - } } -/*static*/ void TabPage::onFolderFinishLoading(FmFolder* _folder, TabPage* pThis) { - // FIXME: is this needed? - FmFileInfo* fi = fm_folder_get_info(_folder); - if(fi) { // if loading of the folder fails, it's possible that we don't have FmFileInfo. - pThis->title_ = QString::fromUtf8(fm_file_info_get_disp_name(fi)); - Q_EMIT pThis->titleChanged(pThis->title_); - } +void TabPage::onFolderFinishLoading() { + auto fi = folder_->info(); + if(fi) { // if loading of the folder fails, it's possible that we don't have FmFileInfo. + setWindowTitle(fi->displayName()); + Q_EMIT titleChanged(fi->displayName()); + } - fm_folder_query_filesystem_info(_folder); // FIXME: is this needed? + folder_->queryFilesystemInfo(); // FIXME: is this needed? #if 0 - FmFolderView* fv = folder_view; - const FmNavHistoryItem* item; - GtkScrolledWindow* scroll = GTK_SCROLLED_WINDOW(fv); - - /* Note: most of the time, we delay the creation of the - * folder model and do it after the whole folder is loaded. - * That is because adding rows into model is much faster when no handlers - * are connected to its signals. So we detach the model from folder view - * and create the model again when it's fully loaded. - * This optimization, however, is not used for FmFolder objects - * with incremental loading (search://) */ - if(fm_folder_view_get_model(fv) == NULL) { - /* create a model for the folder and set it to the view */ - FmFolderModel* model = fm_folder_model_new(folder, app_config->show_hidden); - fm_folder_view_set_model(fv, model); + FmFolderView* fv = folder_view; + const FmNavHistoryItem* item; + GtkScrolledWindow* scroll = GTK_SCROLLED_WINDOW(fv); + + /* Note: most of the time, we delay the creation of the + * folder model and do it after the whole folder is loaded. + * That is because adding rows into model is much faster when no handlers + * are connected to its signals. So we detach the model from folder view + * and create the model again when it's fully loaded. + * This optimization, however, is not used for FmFolder objects + * with incremental loading (search://) */ + if(fm_folder_view_get_model(fv) == nullptr) { + /* create a model for the folder and set it to the view */ + FmFolderModel* model = fm_folder_model_new(folder, app_config->show_hidden); + fm_folder_view_set_model(fv, model); #if FM_CHECK_VERSION(1, 0, 2) - /* since 1.0.2 sorting should be applied on model instead of view */ - fm_folder_model_set_sort(model, app_config->sort_by, - (app_config->sort_type == GTK_SORT_ASCENDING) ? - FM_SORT_ASCENDING : FM_SORT_DESCENDING); + /* since 1.0.2 sorting should be applied on model instead of view */ + fm_folder_model_set_sort(model, app_config->sort_by, + (app_config->sort_type == GTK_SORT_ASCENDING) ? + FM_SORT_ASCENDING : FM_SORT_DESCENDING); #endif - g_object_unref(model); - } + g_object_unref(model); + } #endif - // update status text - QString& text = pThis->statusText_[StatusTextNormal]; - text = pThis->formatStatusText(); - Q_EMIT pThis->statusChanged(StatusTextNormal, text); - - if(pThis->overrideCursor_) { - QApplication::restoreOverrideCursor(); // remove busy cursor - pThis->overrideCursor_ = false; - } - - // After finishing loading the folder, the model is updated, but Qt delays the UI update - // for performance reasons. Therefore at this point the UI is not up to date. - // Of course, the scrollbar ranges are not updated yet. We solve this by installing an Qt timeout handler. - QTimer::singleShot(10, pThis, SLOT(restoreScrollPos())); -} - -/*static*/ FmJobErrorAction TabPage::onFolderError(FmFolder* _folder, GError* err, FmJobErrorSeverity severity, TabPage* pThis) { - if(err->domain == G_IO_ERROR) { - if(err->code == G_IO_ERROR_NOT_MOUNTED && severity < FM_JOB_ERROR_CRITICAL) { - FmPath* path = fm_folder_get_path(_folder); - MountOperation* op = new MountOperation(pThis); - op->mount(path); - if(op->wait()) { // blocking event loop, wait for mount operation to finish. - // This will reload the folder, which generates a new "start-loading" - // signal, so we get more "start-loading" signals than "finish-loading" - // signals. FIXME: This is a bug of libfm. - // Because the two signals are not correctly paired, we need to - // remove busy cursor here since "finish-loading" is not emitted. + // update status text + QString& text = statusText_[StatusTextNormal]; + text = formatStatusText(); + Q_EMIT statusChanged(StatusTextNormal, text); + + if(overrideCursor_) { QApplication::restoreOverrideCursor(); // remove busy cursor - pThis->overrideCursor_ = false; - return FM_JOB_RETRY; - } - } - } - if(severity >= FM_JOB_ERROR_MODERATE) { - /* Only show more severe errors to the users and - * ignore milder errors. Otherwise too many error - * message boxes can be annoying. - * This fixes bug #3411298- Show "Permission denied" when switching to super user mode. - * https://sourceforge.net/tracker/?func=detail&aid=3411298&group_id=156956&atid=801864 - * */ - - // FIXME: consider replacing this modal dialog with an info bar to improve usability - QMessageBox::critical(pThis, tr("Error"), QString::fromUtf8(err->message)); - } - return FM_JOB_CONTINUE; -} - -/*static*/ void TabPage::onFolderFsInfo(FmFolder* _folder, TabPage* pThis) { - guint64 free, total; - QString& msg = pThis->statusText_[StatusTextFSInfo]; - if(fm_folder_get_filesystem_info(_folder, &total, &free)) { - char total_str[64]; - char free_str[64]; - fm_file_size_to_str(free_str, sizeof(free_str), free, fm_config->si_unit); - fm_file_size_to_str(total_str, sizeof(total_str), total, fm_config->si_unit); - msg = tr("Free space: %1 (Total: %2)") - .arg(QString::fromUtf8(free_str)) - .arg(QString::fromUtf8(total_str)); - } - else - msg.clear(); - Q_EMIT pThis->statusChanged(StatusTextFSInfo, msg); + overrideCursor_ = false; + } + + // After finishing loading the folder, the model is updated, but Qt delays the UI update + // for performance reasons. Therefore at this point the UI is not up to date. + // For example, the scrollbar ranges are not updated yet. We solve this by installing an Qt timeout handler. + QTimer::singleShot(10, this, SLOT(onUiUpdated())); +} + +void TabPage::onFolderError(const Fm::GErrorPtr& err, Fm::Job::ErrorSeverity severity, Fm::Job::ErrorAction& response) { + if(err.domain() == G_IO_ERROR) { + if(err.code() == G_IO_ERROR_NOT_MOUNTED && severity < Fm::Job::ErrorSeverity::CRITICAL) { + auto& path = folder_->path(); + MountOperation* op = new MountOperation(this); + op->mount(path); + if(op->wait()) { // blocking event loop, wait for mount operation to finish. + // This will reload the folder, which generates a new "start-loading" + // signal, so we get more "start-loading" signals than "finish-loading" + // signals. FIXME: This is a bug of libfm. + // Because the two signals are not correctly paired, we need to + // remove busy cursor here since "finish-loading" is not emitted. + QApplication::restoreOverrideCursor(); // remove busy cursor + overrideCursor_ = false; + response = Fm::Job::ErrorAction::RETRY; + return; + } + } + } + if(severity >= Fm::Job::ErrorSeverity::MODERATE) { + /* Only show more severe errors to the users and + * ignore milder errors. Otherwise too many error + * message boxes can be annoying. + * This fixes bug #3411298- Show "Permission denied" when switching to super user mode. + * https://sourceforge.net/tracker/?func=detail&aid=3411298&group_id=156956&atid=801864 + * */ + + // FIXME: consider replacing this modal dialog with an info bar to improve usability + QMessageBox::critical(this, tr("Error"), err.message()); + } + response = Fm::Job::ErrorAction::CONTINUE; +} + +void TabPage::onFolderFsInfo() { + guint64 free, total; + QString& msg = statusText_[StatusTextFSInfo]; + if(folder_->getFilesystemInfo(&total, &free)) { + char total_str[64]; + char free_str[64]; + fm_file_size_to_str(free_str, sizeof(free_str), free, fm_config->si_unit); + fm_file_size_to_str(total_str, sizeof(total_str), total, fm_config->si_unit); + msg = tr("Free space: %1 (Total: %2)") + .arg(QString::fromUtf8(free_str)) + .arg(QString::fromUtf8(total_str)); + } + else { + msg.clear(); + } + Q_EMIT statusChanged(StatusTextFSInfo, msg); } QString TabPage::formatStatusText() { - if(proxyModel_ && !folder_.isNull()) { - Fm::FileInfoList files = folder_.getFiles(); - int total_files = fm_file_info_list_get_length(files); - int shown_files = proxyModel_->rowCount(); - int hidden_files = total_files - shown_files; - QString text = tr("%n item(s)", "", shown_files); - if(hidden_files > 0) - text += tr(" (%n hidden)", "", hidden_files); - return text; - } - return QString(); -} - -/*static*/ void TabPage::onFolderRemoved(FmFolder* _folder, TabPage* pThis) { - // the folder we're showing is removed, destroy the widget - qDebug("folder removed"); - Settings& settings = static_cast(qApp)->settings(); - // NOTE: call pThis->deleteLater() directly from this GObject signal handler - // does not work but I don't know why. - // Maybe it's the problem of glib mainloop integration? - // Call it when idle works, though. - if(settings.closeOnUnmount()) - QTimer::singleShot(0, pThis, SLOT(deleteLater())); - else - pThis->chdir(Fm::Path::getHome()); -} - -/*static*/ void TabPage::onFolderUnmount(FmFolder* _folder, TabPage* pThis) { - // the folder we're showing is unmounted, destroy the widget - qDebug("folder unmount"); - // NOTE: call pThis->deleteLater() directly from this GObject signal handler - // does not work but I don't know why. - // Maybe it's the problem of glib mainloop integration? - // Call it when idle works, though. - Settings& settings = static_cast(qApp)->settings(); - // NOTE: call pThis->deleteLater() directly from this GObject signal handler - // does not work but I don't know why. - // Maybe it's the problem of glib mainloop integration? - // Call it when idle works, though. - if(settings.closeOnUnmount()) - QTimer::singleShot(0, pThis, SLOT(deleteLater())); - else - pThis->chdir(Fm::Path::getHome()); -} - -/*static */ void TabPage::onFolderContentChanged(FmFolder* _folder, TabPage* pThis) { - /* update status text */ - pThis->statusText_[StatusTextNormal] = pThis->formatStatusText(); - Q_EMIT pThis->statusChanged(StatusTextNormal, pThis->statusText_[StatusTextNormal]); + if(proxyModel_ && folder_) { + // FIXME: this is very inefficient + auto files = folder_->files(); + int total_files = files.size(); + int shown_files = proxyModel_->rowCount(); + int hidden_files = total_files - shown_files; + QString text = tr("%n item(s)", "", shown_files); + if(hidden_files > 0) { + text += tr(" (%n hidden)", "", hidden_files); + } + return text; + } + return QString(); +} + +void TabPage::onFolderRemoved() { + // the folder we're showing is removed, destroy the widget + qDebug("folder removed"); + Settings& settings = static_cast(qApp)->settings(); + // NOTE: call deleteLater() directly from this GObject signal handler + // does not work but I don't know why. + // Maybe it's the problem of glib mainloop integration? + // Call it when idle works, though. + if(settings.closeOnUnmount()) { + QTimer::singleShot(0, this, SLOT(deleteLater())); + } + else { + chdir(Fm::FilePath::homeDir()); + } } -QString TabPage::pathName() { - char* disp_path = path().displayName(true); - QString ret = QString::fromUtf8(disp_path); - g_free(disp_path); - return ret; +void TabPage::onFolderUnmount() { + // the folder we're showing is unmounted, destroy the widget + qDebug("folder unmount"); + // NOTE: call deleteLater() directly from this GObject signal handler + // does not work but I don't know why. + // Maybe it's the problem of glib mainloop integration? + // Call it when idle works, though. + Settings& settings = static_cast(qApp)->settings(); + // NOTE: call deleteLater() directly from this GObject signal handler + // does not work but I don't know why. + // Maybe it's the problem of glib mainloop integration? + // Call it when idle works, though. + if(settings.closeOnUnmount()) { + QTimer::singleShot(0, this, SLOT(deleteLater())); + } + else { + chdir(Fm::FilePath::homeDir()); + } } -void TabPage::chdir(Path newPath, bool addHistory) { - if(!folder_.isNull()) { - // we're already in the specified dir - if(newPath == fm_folder_get_path(folder_)) - return; +void TabPage::onFolderContentChanged() { + /* update status text */ + statusText_[StatusTextNormal] = formatStatusText(); + Q_EMIT statusChanged(StatusTextNormal, statusText_[StatusTextNormal]); +} - // remember the previous folder path that we have browsed. - lastFolderPath_ = folder_.getPath(); +QString TabPage::pathName() { + // auto disp_path = path().displayName(); + // FIXME: displayName() returns invalid path sometimes. + auto disp_path = path().toString(); + return QString::fromUtf8(disp_path.get()); +} + +void TabPage::chdir(Fm::FilePath newPath, bool addHistory) { + // qDebug() << "TABPAGE CHDIR:" << newPath.toString().get(); + if(folder_) { + // we're already in the specified dir + if(newPath == folder_->path()) { + return; + } - if(addHistory) { - // store current scroll pos in the browse history - BrowseHistoryItem& item = history_.currentItem(); - QAbstractItemView* childView = folderView_->childView(); - item.setScrollPos(childView->verticalScrollBar()->value()); - } + // reset the status selected text + statusText_[StatusTextSelectedFiles] = QString(); - // free the previous model - if(folderModel_) { - proxyModel_->setSourceModel(NULL); - folderModel_->unref(); // unref the cached model - folderModel_ = NULL; + // remember the previous folder path that we have browsed. + lastFolderPath_ = folder_->path(); + + if(addHistory) { + // store current scroll pos in the browse history + BrowseHistoryItem& item = history_.currentItem(); + QAbstractItemView* childView = folderView_->childView(); + item.setScrollPos(childView->verticalScrollBar()->value()); + } + + // free the previous model + if(folderModel_) { + disconnect(folderModel_, &Fm::FolderModel::fileSizeChanged, this, &TabPage::onFileSizeChanged); + proxyModel_->setSourceModel(nullptr); + folderModel_->unref(); // unref the cached model + folderModel_ = nullptr; + } + + freeFolder(); } - freeFolder(); - } - - char* disp_name = newPath.displayBasename(); - title_ = QString::fromUtf8(disp_name); - Q_EMIT titleChanged(title_); - g_free(disp_name); - - folder_ = Fm::Folder::fromPath(newPath); - proxyFilter_->setVirtHidden(folder_); - if(addHistory) { - // add current path to browse history - history_.add(path()); - } - g_signal_connect(folder_, "start-loading", G_CALLBACK(onFolderStartLoading), this); - g_signal_connect(folder_, "finish-loading", G_CALLBACK(onFolderFinishLoading), this); - g_signal_connect(folder_, "error", G_CALLBACK(onFolderError), this); - g_signal_connect(folder_, "fs-info", G_CALLBACK(onFolderFsInfo), this); - /* destroy the page when the folder is unmounted or deleted. */ - g_signal_connect(folder_, "removed", G_CALLBACK(onFolderRemoved), this); - g_signal_connect(folder_, "unmount", G_CALLBACK(onFolderUnmount), this); - g_signal_connect(folder_, "content-changed", G_CALLBACK(onFolderContentChanged), this); - - folderModel_ = CachedFolderModel::modelFromFolder(folder_); - - // set sorting, considering customized folders - Settings& settings = static_cast(qApp)->settings(); - folderSettings_ = settings.loadFolderSettings(path()); - proxyModel_->sort(folderSettings_.sortColumn(), folderSettings_.sortOrder()); - proxyModel_->setFolderFirst(folderSettings_.sortFolderFirst()); - proxyModel_->setShowHidden(folderSettings_.showHidden()); - proxyModel_->setSortCaseSensitivity(folderSettings_.sortCaseSensitive() ? Qt::CaseSensitive : Qt::CaseInsensitive); - proxyModel_->setSourceModel(folderModel_); - - folderView_->setViewMode(folderSettings_.viewMode()); - - if(folder_.isLoaded()) { - onFolderStartLoading(folder_, this); - onFolderFinishLoading(folder_, this); - onFolderFsInfo(folder_, this); - } - else - onFolderStartLoading(folder_, this); + Q_EMIT titleChanged(newPath.baseName().get()); // FIXME: display name + + folder_ = Fm::Folder::fromPath(newPath); + proxyFilter_->setVirtHidden(folder_); + if(addHistory) { + // add current path to browse history + history_.add(path()); + } + connect(folder_.get(), &Fm::Folder::startLoading, this, &TabPage::onFolderStartLoading); + connect(folder_.get(), &Fm::Folder::finishLoading, this, &TabPage::onFolderFinishLoading); + + // FIXME: Fm::Folder::error() is a bad design and might be removed in the future. + connect(folder_.get(), &Fm::Folder::error, this, &TabPage::onFolderError); + connect(folder_.get(), &Fm::Folder::fileSystemChanged, this, &TabPage::onFolderFsInfo); + /* destroy the page when the folder is unmounted or deleted. */ + connect(folder_.get(), &Fm::Folder::removed, this, &TabPage::onFolderRemoved); + connect(folder_.get(), &Fm::Folder::unmount, this, &TabPage::onFolderUnmount); + connect(folder_.get(), &Fm::Folder::contentChanged, this, &TabPage::onFolderContentChanged); + + folderModel_ = CachedFolderModel::modelFromFolder(folder_); + + // set sorting, considering customized folders + Settings& settings = static_cast(qApp)->settings(); + folderSettings_ = settings.loadFolderSettings(path()); + proxyModel_->sort(folderSettings_.sortColumn(), folderSettings_.sortOrder()); + proxyModel_->setFolderFirst(folderSettings_.sortFolderFirst()); + proxyModel_->setShowHidden(folderSettings_.showHidden()); + proxyModel_->setSortCaseSensitivity(folderSettings_.sortCaseSensitive() ? Qt::CaseSensitive : Qt::CaseInsensitive); + proxyModel_->setSourceModel(folderModel_); + + folderView_->setViewMode(folderSettings_.viewMode()); + + if(folder_->isLoaded()) { + onFolderStartLoading(); + onFolderFinishLoading(); + onFolderFsInfo(); + } + else { + onFolderStartLoading(); + } } void TabPage::selectAll() { - folderView_->selectAll(); + folderView_->selectAll(); } void TabPage::invertSelection() { - folderView_->invertSelection(); + folderView_->invertSelection(); } -void TabPage::onOpenDirRequested(FmPath* path, int target) { - Q_EMIT openDirRequested(path, target); +void TabPage::reload() { + if(folder_) { + proxyFilter_->setVirtHidden(folder_); // reread ".hidden" + // don't select or scroll to the previous folder after reload + lastFolderPath_ = Fm::FilePath(); + // but remember the current scroll position + BrowseHistoryItem& item = history_.currentItem(); + QAbstractItemView* childView = folderView_->childView(); + item.setScrollPos(childView->verticalScrollBar()->value()); + + folder_->reload(); + } } // when the current selection in the folder view is changed -void TabPage::onSelChanged(int numSel) { - QString msg; - if(numSel > 0) { - /* FIXME: display total size of all selected files. */ - if(numSel == 1) { /* only one file is selected */ - Fm::FileInfoList files = folderView_->selectedFiles(); - if(!files.isNull()) { - Fm::FileInfo fi = fm_file_info_list_peek_head(files); - const char* size_str = fi.getDispSize(); - if(size_str) { - msg = QString("\"%1\" (%2) %3") - .arg(QString::fromUtf8(fi.getDispName())) - .arg(QString::fromUtf8(size_str)) - .arg(QString::fromUtf8(fi.getDesc())); +void TabPage::onSelChanged() { + QString msg; + if(folderView_->hasSelection()) { + auto files = folderView_->selectedFiles(); + int numSel = files.size(); + /* FIXME: display total size of all selected files. */ + if(numSel == 1) { /* only one file is selected */ + auto& fi = files.front(); + if(!fi->isDir()) { + msg = QString("\"%1\" (%2) %3") + .arg(fi->displayName()) + .arg(Fm::formatFileSize(fi->size(), fm_config->si_unit)) // FIXME: deprecate fm_config + .arg(fi->mimeType()->desc()); + } + else { + msg = QString("\"%1\" %2") + .arg(fi->displayName()) + .arg(fi->mimeType()->desc()); + } + /* FIXME: should we support statusbar plugins as in the gtk+ version? */ } else { - msg = QString("\"%1\" %2") - .arg(QString::fromUtf8(fi.getDispName())) - .arg(QString::fromUtf8(fi.getDesc())); - } - /* FIXME: should we support statusbar plugins as in the gtk+ version? */ - } - } - else { - goffset sum; - GList* l; - msg = tr("%n item(s) selected", nullptr, numSel); - /* don't count if too many files are selected, that isn't lightweight */ - if(numSel < 1000) { - sum = 0; - Fm::FileInfoList files = folderView_->selectedFiles(); - if(!files.isNull()) { - for(l = files.peekHeadLink(); l; l = l->next) { - Fm::FileInfo fi = FM_FILE_INFO(l->data); - if(fi.isDir()) { - /* if we got a directory then we cannot tell it's size - unless we do deep count but we cannot afford it */ - sum = -1; - break; + goffset sum; + GList* l; + msg = tr("%n item(s) selected", nullptr, numSel); + /* don't count if too many files are selected, that isn't lightweight */ + if(numSel < 1000) { + sum = 0; + for(auto& fi: files) { + if(fi->isDir()) { + /* if we got a directory then we cannot tell it's size + unless we do deep count but we cannot afford it */ + sum = -1; + break; + } + sum += fi->size(); + } + if(sum >= 0) { + msg += QString(" (%1)").arg(Fm::formatFileSize(sum, fm_config->si_unit)); // FIXME: deprecate fm_config + } + /* FIXME: should we support statusbar plugins as in the gtk+ version? */ } - sum += fi.getSize(); - } + /* FIXME: can we show some more info on selection? + that isn't lightweight if a lot of files are selected */ } - if(sum >= 0) { - char size_str[128]; - fm_file_size_to_str(size_str, sizeof(size_str), sum, - fm_config->si_unit); - msg += QString(" (%1)").arg(QString::fromUtf8(size_str)); - } - /* FIXME: should we support statusbar plugins as in the gtk+ version? */ - } - /* FIXME: can we show some more info on selection? - that isn't lightweight if a lot of files are selected */ } - } - statusText_[StatusTextSelectedFiles] = msg; - Q_EMIT statusChanged(StatusTextSelectedFiles, msg); + statusText_[StatusTextSelectedFiles] = msg; + Q_EMIT statusChanged(StatusTextSelectedFiles, msg); } void TabPage::backward() { - // remember current scroll position - BrowseHistoryItem& item = history_.currentItem(); - QAbstractItemView* childView = folderView_->childView(); - item.setScrollPos(childView->verticalScrollBar()->value()); + // remember current scroll position + BrowseHistoryItem& item = history_.currentItem(); + QAbstractItemView* childView = folderView_->childView(); + item.setScrollPos(childView->verticalScrollBar()->value()); - history_.backward(); - chdir(history_.currentPath(), false); + history_.backward(); + chdir(history_.currentPath(), false); } void TabPage::forward() { - // remember current scroll position - BrowseHistoryItem& item = history_.currentItem(); - QAbstractItemView* childView = folderView_->childView(); - item.setScrollPos(childView->verticalScrollBar()->value()); - - history_.forward(); - chdir(history_.currentPath(), false); -} - -void TabPage::jumpToHistory(int index) -{ - if(index >=0 && index < history_.size()) { // remember current scroll position BrowseHistoryItem& item = history_.currentItem(); QAbstractItemView* childView = folderView_->childView(); item.setScrollPos(childView->verticalScrollBar()->value()); - history_.setCurrentIndex(index); + history_.forward(); chdir(history_.currentPath(), false); - } +} + +void TabPage::jumpToHistory(int index) { + if(index >= 0 && index < history_.size()) { + // remember current scroll position + BrowseHistoryItem& item = history_.currentItem(); + QAbstractItemView* childView = folderView_->childView(); + item.setScrollPos(childView->verticalScrollBar()->value()); + + history_.setCurrentIndex(index); + chdir(history_.currentPath(), false); + } } bool TabPage::canUp() { - Fm::Path _path = path(); - return (!_path.isNull() && !_path.getParent().isNull()); + auto _path = path(); + return (_path && _path.hasParent()); } void TabPage::up() { - Fm::Path _path = path(); - if(!_path.isNull()) { - Fm::Path parent = _path.getParent(); - if(!parent.isNull()) { - chdir(parent, true); + auto _path = path(); + if(_path) { + auto parent = _path.parent(); + if(parent) { + chdir(parent, true); + } } - } } void TabPage::updateFromSettings(Settings& settings) { - folderView_->updateFromSettings(settings); + folderView_->updateFromSettings(settings); } void TabPage::setViewMode(Fm::FolderView::ViewMode mode) { - if(folderSettings_.viewMode() != mode) { - folderSettings_.setViewMode(mode); - if(folderSettings_.isCustomized()) { - static_cast(qApp)->settings().saveFolderSettings(path(), folderSettings_); + if(folderSettings_.viewMode() != mode) { + folderSettings_.setViewMode(mode); + if(folderSettings_.isCustomized()) { + static_cast(qApp)->settings().saveFolderSettings(path(), folderSettings_); + } } - } - folderView_->setViewMode(mode); + folderView_->setViewMode(mode); } void TabPage::sort(int col, Qt::SortOrder order) { - if(folderSettings_.sortColumn() != col || folderSettings_.sortOrder() != order) { - folderSettings_.setSortColumn(Fm::FolderModel::ColumnId(col)); - folderSettings_.setSortOrder(order); - if(folderSettings_.isCustomized()) { - static_cast(qApp)->settings().saveFolderSettings(path(), folderSettings_); + if(folderSettings_.sortColumn() != col || folderSettings_.sortOrder() != order) { + folderSettings_.setSortColumn(Fm::FolderModel::ColumnId(col)); + folderSettings_.setSortOrder(order); + if(folderSettings_.isCustomized()) { + static_cast(qApp)->settings().saveFolderSettings(path(), folderSettings_); + } + } + if(proxyModel_) { + proxyModel_->sort(col, order); } - } - if(proxyModel_) - proxyModel_->sort(col, order); } void TabPage::setSortFolderFirst(bool value) { - if(folderSettings_.sortFolderFirst() != value) { - folderSettings_.setSortFolderFirst(value); - if(folderSettings_.isCustomized()) { - static_cast(qApp)->settings().saveFolderSettings(path(), folderSettings_); + if(folderSettings_.sortFolderFirst() != value) { + folderSettings_.setSortFolderFirst(value); + if(folderSettings_.isCustomized()) { + static_cast(qApp)->settings().saveFolderSettings(path(), folderSettings_); + } } - } - proxyModel_->setFolderFirst(value); + proxyModel_->setFolderFirst(value); } void TabPage::setSortCaseSensitive(bool value) { - if(folderSettings_.sortCaseSensitive() != value) { - folderSettings_.setSortCaseSensitive(value); - if(folderSettings_.isCustomized()) { - static_cast(qApp)->settings().saveFolderSettings(path(), folderSettings_); + if(folderSettings_.sortCaseSensitive() != value) { + folderSettings_.setSortCaseSensitive(value); + if(folderSettings_.isCustomized()) { + static_cast(qApp)->settings().saveFolderSettings(path(), folderSettings_); + } } - } - proxyModel_->setSortCaseSensitivity(value ? Qt::CaseSensitive : Qt::CaseInsensitive); + proxyModel_->setSortCaseSensitivity(value ? Qt::CaseSensitive : Qt::CaseInsensitive); } void TabPage::setShowHidden(bool showHidden) { - if(folderSettings_.showHidden() != showHidden) { - folderSettings_.setShowHidden(showHidden); - if(folderSettings_.isCustomized()) { - static_cast(qApp)->settings().saveFolderSettings(path(), folderSettings_); + if(folderSettings_.showHidden() != showHidden) { + folderSettings_.setShowHidden(showHidden); + if(folderSettings_.isCustomized()) { + static_cast(qApp)->settings().saveFolderSettings(path(), folderSettings_); + } + } + if(!proxyModel_) { + return; } - } - if(!proxyModel_ || showHidden == proxyModel_->showHidden()) - return; - proxyModel_->setShowHidden(showHidden); - statusText_[StatusTextNormal] = formatStatusText(); - Q_EMIT statusChanged(StatusTextNormal, statusText_[StatusTextNormal]); + if(showHidden != proxyModel_->showHidden()) { + proxyModel_->setShowHidden(showHidden); + } + // this may also be called by MainWindow::onTabPageSortFilterChanged to set status message + statusText_[StatusTextNormal] = formatStatusText(); + Q_EMIT statusChanged(StatusTextNormal, statusText_[StatusTextNormal]); } void TabPage::applyFilter() { - if(!proxyModel_) - return; - proxyModel_->updateFilters(); - statusText_[StatusTextNormal] = formatStatusText(); - Q_EMIT statusChanged(StatusTextNormal, statusText_[StatusTextNormal]); + if(!proxyModel_) { + return; + } + proxyModel_->updateFilters(); + statusText_[StatusTextNormal] = formatStatusText(); + Q_EMIT statusChanged(StatusTextNormal, statusText_[StatusTextNormal]); } void TabPage::setCustomizedView(bool value) { - if(folderSettings_.isCustomized() == value) - return; - - Settings& settings = static_cast(qApp)->settings(); - folderSettings_.setCustomized(value); - if(value) { // save customized folder view settings - settings.saveFolderSettings(path(), folderSettings_); - } - else { // use default folder view settings - settings.clearFolderSettings(path()); - setShowHidden(settings.showHidden()); - setSortCaseSensitive(settings.sortCaseSensitive()); - setSortFolderFirst(settings.sortFolderFirst()); - sort(settings.sortColumn(), settings.sortOrder()); - } + if(folderSettings_.isCustomized() == value) { + return; + } + + Settings& settings = static_cast(qApp)->settings(); + folderSettings_.setCustomized(value); + if(value) { // save customized folder view settings + settings.saveFolderSettings(path(), folderSettings_); + } + else { // use default folder view settings + settings.clearFolderSettings(path()); + setShowHidden(settings.showHidden()); + setSortCaseSensitive(settings.sortCaseSensitive()); + setSortFolderFirst(settings.sortFolderFirst()); + sort(settings.sortColumn(), settings.sortOrder()); + } } } // namespace PCManFM diff --git a/pcmanfm/tabpage.h b/pcmanfm/tabpage.h index 5187cd3..1abdc09 100644 --- a/pcmanfm/tabpage.h +++ b/pcmanfm/tabpage.h @@ -27,16 +27,18 @@ #include #include "view.h" #include -#include -#include #include "settings.h" +#include +#include +#include + namespace Fm { - class FileLauncher; - class FolderModel; - class ProxyFolderModel; - class CachedFolderModel; -}; +class FileLauncher; +class FolderModel; +class ProxyFolderModel; +class CachedFolderModel; +} namespace PCManFM { @@ -44,205 +46,200 @@ class Launcher; class ProxyFilter : public Fm::ProxyFolderModelFilter { public: - bool filterAcceptsRow(const Fm::ProxyFolderModel* model, FmFileInfo* info) const; - virtual ~ProxyFilter() {} - void setVirtHidden(Fm::Folder folder); - QString getFilterStr() { - return filterStr_; - } - void setFilterStr(QString str) { - filterStr_ = str; - } + bool filterAcceptsRow(const Fm::ProxyFolderModel* model, const std::shared_ptr& info) const; + virtual ~ProxyFilter() {} + void setVirtHidden(const std::shared_ptr& folder); + QString getFilterStr() { + return filterStr_; + } + void setFilterStr(QString str) { + filterStr_ = str; + } private: - QString filterStr_; - QStringList virtHiddenList_; + QString filterStr_; + QStringList virtHiddenList_; }; class TabPage : public QWidget { -Q_OBJECT + Q_OBJECT public: - enum StatusTextType { - StatusTextNormal, - StatusTextSelectedFiles, - StatusTextFSInfo, - StatusTextNum - }; + enum StatusTextType { + StatusTextNormal, + StatusTextSelectedFiles, + StatusTextFSInfo, + StatusTextNum + }; public: - explicit TabPage(Fm::Path path, QWidget* parent = nullptr); - virtual ~TabPage(); - - void chdir(Fm::Path newPath, bool addHistory = true); + explicit TabPage(QWidget* parent = nullptr); + virtual ~TabPage(); - Fm::FolderView::ViewMode viewMode() { - return folderSettings_.viewMode(); - } + void chdir(Fm::FilePath newPath, bool addHistory = true); - void setViewMode(Fm::FolderView::ViewMode mode); + Fm::FolderView::ViewMode viewMode() { + return folderSettings_.viewMode(); + } - void sort(int col, Qt::SortOrder order = Qt::AscendingOrder); + void setViewMode(Fm::FolderView::ViewMode mode); - int sortColumn() { - return folderSettings_.sortColumn(); - } + void sort(int col, Qt::SortOrder order = Qt::AscendingOrder); - Qt::SortOrder sortOrder() { - return folderSettings_.sortOrder(); - } + int sortColumn() { + return folderSettings_.sortColumn(); + } - bool sortFolderFirst() { - return folderSettings_.sortFolderFirst(); - } - void setSortFolderFirst(bool value); + Qt::SortOrder sortOrder() { + return folderSettings_.sortOrder(); + } - bool sortCaseSensitive() { - return folderSettings_.sortCaseSensitive(); - } + bool sortFolderFirst() { + return folderSettings_.sortFolderFirst(); + } + void setSortFolderFirst(bool value); - void setSortCaseSensitive(bool value); + bool sortCaseSensitive() { + return folderSettings_.sortCaseSensitive(); + } - bool showHidden() { - return folderSettings_.showHidden(); - } + void setSortCaseSensitive(bool value); - void setShowHidden(bool showHidden); + bool showHidden() { + return proxyModel_->showHidden(); + } - Fm::Path path() { - return Fm::Path(!folder_.isNull() ? folder_.getPath() : nullptr); - } + void setShowHidden(bool showHidden); - QString pathName(); + Fm::FilePath path() { + return folder_ ? folder_->path() : Fm::FilePath(); + } - Fm::Folder& folder() { - return folder_; - } + QString pathName(); - Fm::FolderModel* folderModel() { - return reinterpret_cast(folderModel_); - } + const std::shared_ptr& folder() { + return folder_; + } - View* folderView() { - return folderView_; - } + Fm::FolderModel* folderModel() { + return reinterpret_cast(folderModel_); + } - Fm::BrowseHistory& browseHistory() { - return history_; - } + View* folderView() { + return folderView_; + } - Fm::FileInfoList selectedFiles() { - return folderView_->selectedFiles(); - } + Fm::BrowseHistory& browseHistory() { + return history_; + } - Fm::PathList selectedFilePaths() { - return folderView_->selectedFilePaths(); - } + Fm::FileInfoList selectedFiles() { + return folderView_->selectedFiles(); + } - void selectAll(); + Fm::FilePathList selectedFilePaths() { + return folderView_->selectedFilePaths(); + } - void invertSelection(); + void selectAll(); - void reload() { - if(!folder_.isNull()) { - proxyFilter_->setVirtHidden(folder_); // reread ".hidden" - folder_.reload(); - } - } + void invertSelection(); - QString title() const { - return title_; - } + void reload(); - QString statusText(StatusTextType type = StatusTextNormal) const { - return statusText_[type]; - } + QString statusText(StatusTextType type = StatusTextNormal) const { + return statusText_[type]; + } - bool canBackward() { - return history_.canBackward(); - } + bool canBackward() { + return history_.canBackward(); + } - void backward(); + void backward(); - bool canForward() { - return history_.canForward(); - } + bool canForward() { + return history_.canForward(); + } - void forward(); + void forward(); - void jumpToHistory(int index); + void jumpToHistory(int index); - bool canUp(); + bool canUp(); - void up(); + void up(); - void updateFromSettings(Settings& settings); + void updateFromSettings(Settings& settings); - void setFileLauncher(Fm::FileLauncher* launcher) { - folderView_->setFileLauncher(launcher); - } + void setFileLauncher(Fm::FileLauncher* launcher) { + folderView_->setFileLauncher(launcher); + } - Fm::FileLauncher* fileLauncher() { - return folderView_->fileLauncher(); - } + Fm::FileLauncher* fileLauncher() { + return folderView_->fileLauncher(); + } - QString getFilterStr() { - if(proxyFilter_) - return proxyFilter_->getFilterStr(); - return QString(); - } + QString getFilterStr() { + if(proxyFilter_) { + return proxyFilter_->getFilterStr(); + } + return QString(); + } - void setFilterStr(QString str) { - if(proxyFilter_) - proxyFilter_->setFilterStr(str); - } + void setFilterStr(QString str) { + if(proxyFilter_) { + proxyFilter_->setFilterStr(str); + } + } - void applyFilter(); + void applyFilter(); - bool hasCustomizedView() { - return folderSettings_.isCustomized(); - } + bool hasCustomizedView() { + return folderSettings_.isCustomized(); + } - void setCustomizedView(bool value); + void setCustomizedView(bool value); Q_SIGNALS: - void statusChanged(int type, QString statusText); - void titleChanged(QString title); - void openDirRequested(FmPath* path, int target); - void sortFilterChanged(); - void forwardRequested(); - void backwardRequested(); + void statusChanged(int type, QString statusText); + void titleChanged(QString title); + void openDirRequested(const Fm::FilePath& path, int target); + void sortFilterChanged(); + void forwardRequested(); + void backwardRequested(); protected Q_SLOTS: - void onOpenDirRequested(FmPath* path, int target); - void onSelChanged(int numSel); - void restoreScrollPos(); + void onSelChanged(); + void onUiUpdated(); + void onFileSizeChanged(const QModelIndex& index); private: - void freeFolder(); - QString formatStatusText(); + void freeFolder(); + QString formatStatusText(); + + void onFolderStartLoading(); + void onFolderFinishLoading(); + + // FIXME: this API design is bad and might be removed later + void onFolderError(const Fm::GErrorPtr& err, Fm::Job::ErrorSeverity severity, Fm::Job::ErrorAction& response); - static void onFolderStartLoading(FmFolder* _folder, TabPage* pThis); - static void onFolderFinishLoading(FmFolder* _folder, TabPage* pThis); - static FmJobErrorAction onFolderError(FmFolder* _folder, GError* err, FmJobErrorSeverity severity, TabPage* pThis); - static void onFolderFsInfo(FmFolder* _folder, TabPage* pThis); - static void onFolderRemoved(FmFolder* _folder, TabPage* pThis); - static void onFolderUnmount(FmFolder* _folder, TabPage* pThis); - static void onFolderContentChanged(FmFolder* _folder, TabPage* pThis); + void onFolderFsInfo(); + void onFolderRemoved(); + void onFolderUnmount(); + void onFolderContentChanged(); private: - View* folderView_; - Fm::CachedFolderModel* folderModel_; - Fm::ProxyFolderModel* proxyModel_; - ProxyFilter* proxyFilter_; - QVBoxLayout* verticalLayout; - Fm::Folder folder_; - QString title_; - QString statusText_[StatusTextNum]; - Fm::BrowseHistory history_; // browsing history - Fm::Path lastFolderPath_; // last browsed folder - bool overrideCursor_; - FolderSettings folderSettings_; + View* folderView_; + Fm::CachedFolderModel* folderModel_; + Fm::ProxyFolderModel* proxyModel_; + ProxyFilter* proxyFilter_; + QVBoxLayout* verticalLayout; + std::shared_ptr folder_; + QString statusText_[StatusTextNum]; + Fm::BrowseHistory history_; // browsing history + Fm::FilePath lastFolderPath_; // last browsed folder + bool overrideCursor_; + FolderSettings folderSettings_; }; } diff --git a/pcmanfm/translations/pcmanfm-qt-desktop-pref_lt.desktop b/pcmanfm/translations/pcmanfm-qt-desktop-pref_lt.desktop new file mode 100644 index 0000000..21e5a52 --- /dev/null +++ b/pcmanfm/translations/pcmanfm-qt-desktop-pref_lt.desktop @@ -0,0 +1,4 @@ +#Translations +Name[lt]=Darbalaukis +GenericName[lt]=Darbalaukio nustatymai +Comment[lt]=Keisti darbalaukio tvarkytuvės darbalaukio foną ir elgseną diff --git a/pcmanfm/translations/pcmanfm-qt_lt.desktop b/pcmanfm/translations/pcmanfm-qt_lt.desktop new file mode 100644 index 0000000..afea779 --- /dev/null +++ b/pcmanfm/translations/pcmanfm-qt_lt.desktop @@ -0,0 +1,4 @@ +#Translations +Name[lt]=PCManFM failų tvarkytuvė +GenericName[lt]=Failų tvarkytuvė +Comment[lt]=Naršyti failų sistemą ir tvarkyti failus diff --git a/pcmanfm/view.cpp b/pcmanfm/view.cpp index b136d68..d6b6d0b 100644 --- a/pcmanfm/view.cpp +++ b/pcmanfm/view.cpp @@ -31,48 +31,48 @@ namespace PCManFM { View::View(Fm::FolderView::ViewMode _mode, QWidget* parent): - Fm::FolderView(_mode, parent) { + Fm::FolderView(_mode, parent) { - Settings& settings = static_cast(qApp)->settings(); - updateFromSettings(settings); + Settings& settings = static_cast(qApp)->settings(); + updateFromSettings(settings); } View::~View() { } -void View::onFileClicked(int type, FmFileInfo* fileInfo) { - if(type == MiddleClick) { - if(fm_file_info_is_dir(fileInfo)) { - Q_EMIT openDirRequested(fm_file_info_get_path(fileInfo), OpenInNewTab); +void View::onFileClicked(int type, const std::shared_ptr& fileInfo) { + if(type == MiddleClick) { + if(fileInfo->isDir()) { + Q_EMIT openDirRequested(fileInfo->path(), OpenInNewTab); + } + } + else { + Fm::FolderView::onFileClicked(type, fileInfo); } - } - else { - Fm::FolderView::onFileClicked(type, fileInfo); - } } void View::onNewWindow() { - Fm::FileMenu* menu = static_cast(sender()->parent()); - // FIXME: open the files in a new window - Application* app = static_cast(qApp); - app->openFolders(menu->files()); + Fm::FileMenu* menu = static_cast(sender()->parent()); + // FIXME: open the files in a new window + Application* app = static_cast(qApp); + app->openFolders(menu->files()); } void View::onNewTab() { - Fm::FileMenu* menu = static_cast(sender()->parent()); - for(GList* l = fm_file_info_list_peek_head_link(menu->files()); l; l = l->next) { - FmFileInfo* file = FM_FILE_INFO(l->data); - Q_EMIT openDirRequested(fm_file_info_get_path(file), OpenInNewTab); - } + Fm::FileMenu* menu = static_cast(sender()->parent()); + auto files = menu->files(); + for(auto& file: files) { + Q_EMIT openDirRequested(file->path(), OpenInNewTab); + } } void View::onOpenInTerminal() { - Application* app = static_cast(qApp); - Fm::FileMenu* menu = static_cast(sender()->parent()); - for(GList* l = fm_file_info_list_peek_head_link(menu->files()); l; l = l->next) { - Fm::FileInfo file = FM_FILE_INFO(l->data); - app->openFolderInTerminal(file.getPath()); - } + Application* app = static_cast(qApp); + Fm::FileMenu* menu = static_cast(sender()->parent()); + auto files = menu->files(); + for(auto& file: files) { + app->openFolderInTerminal(file->path()); + } } void View::onSearch() { @@ -80,49 +80,50 @@ void View::onSearch() { } void View::prepareFileMenu(Fm::FileMenu* menu) { - Application* app = static_cast(qApp); - menu->setConfirmDelete(app->settings().confirmDelete()); - menu->setConfirmTrash(app->settings().confirmTrash()); - menu->setUseTrash(app->settings().useTrash()); - - // add some more menu items for dirs - bool all_native = true; - bool all_directory = true; - Fm::FileInfoList files = menu->files(); - for(GList* l = files.peekHeadLink(); l; l = l->next) { - Fm::FileInfo fi = FM_FILE_INFO(l->data); - if(!fi.isDir()) - all_directory = false; - else if(fi.isDir() && !fi.isNative()) - all_native = false; - } - - if (all_directory) - { - QAction* action = new QAction(QIcon::fromTheme("window-new"), tr("Open in New T&ab"), menu); - connect(action, &QAction::triggered, this, &View::onNewTab); - menu->insertAction(menu->separator1(), action); - - action = new QAction(QIcon::fromTheme("window-new"), tr("Open in New Win&dow"), menu); - connect(action, &QAction::triggered, this, &View::onNewWindow); - menu->insertAction(menu->separator1(), action); - - // TODO: add search - // action = menu->addAction(_("Search")); - - if(all_native) - { - action = new QAction(QIcon::fromTheme("utilities-terminal"), tr("Open in Termina&l"), menu); - connect(action, &QAction::triggered, this, &View::onOpenInTerminal); - menu->insertAction(menu->separator1(), action); + Application* app = static_cast(qApp); + menu->setConfirmDelete(app->settings().confirmDelete()); + menu->setConfirmTrash(app->settings().confirmTrash()); + menu->setUseTrash(app->settings().useTrash()); + + // add some more menu items for dirs + bool all_native = true; + bool all_directory = true; + auto files = menu->files(); + for(auto& fi: files) { + if(!fi->isDir()) { + all_directory = false; + } + else if(fi->isDir() && !fi->isNative()) { + all_native = false; + } + } + + if(all_directory) { + QAction* action = new QAction(QIcon::fromTheme("window-new"), tr("Open in New T&ab"), menu); + connect(action, &QAction::triggered, this, &View::onNewTab); + menu->insertAction(menu->separator1(), action); + + action = new QAction(QIcon::fromTheme("window-new"), tr("Open in New Win&dow"), menu); + connect(action, &QAction::triggered, this, &View::onNewWindow); + menu->insertAction(menu->separator1(), action); + + // TODO: add search + // action = menu->addAction(_("Search")); + + if(all_native) { + action = new QAction(QIcon::fromTheme("utilities-terminal"), tr("Open in Termina&l"), menu); + connect(action, &QAction::triggered, this, &View::onOpenInTerminal); + menu->insertAction(menu->separator1(), action); + } + } + else { + if(menu->pasteAction()) { // nullptr for trash + menu->pasteAction()->setVisible(false); + } + if(menu->createAction()) { + menu->createAction()->setVisible(false); + } } - } - else { - if(menu->pasteAction()) // NULL for trash - menu->pasteAction()->setVisible(false); - if(menu->createAction()) - menu->createAction()->setVisible(false); - } } void View::prepareFolderMenu(Fm::FolderMenu* menu) { @@ -130,19 +131,19 @@ void View::prepareFolderMenu(Fm::FolderMenu* menu) { void View::updateFromSettings(Settings& settings) { - setIconSize(Fm::FolderView::IconMode, QSize(settings.bigIconSize(), settings.bigIconSize())); - setIconSize(Fm::FolderView::CompactMode, QSize(settings.smallIconSize(), settings.smallIconSize())); - setIconSize(Fm::FolderView::ThumbnailMode, QSize(settings.thumbnailIconSize(), settings.thumbnailIconSize())); - setIconSize(Fm::FolderView::DetailedListMode, QSize(settings.smallIconSize(), settings.smallIconSize())); + setIconSize(Fm::FolderView::IconMode, QSize(settings.bigIconSize(), settings.bigIconSize())); + setIconSize(Fm::FolderView::CompactMode, QSize(settings.smallIconSize(), settings.smallIconSize())); + setIconSize(Fm::FolderView::ThumbnailMode, QSize(settings.thumbnailIconSize(), settings.thumbnailIconSize())); + setIconSize(Fm::FolderView::DetailedListMode, QSize(settings.smallIconSize(), settings.smallIconSize())); - setMargins(settings.folderViewCellMargins()); + setMargins(settings.folderViewCellMargins()); - setAutoSelectionDelay(settings.autoSelectionDelay()); + setAutoSelectionDelay(settings.autoSelectionDelay()); - Fm::ProxyFolderModel* proxyModel = model(); - if(proxyModel) { - proxyModel->setShowThumbnails(settings.showThumbnails()); - } + Fm::ProxyFolderModel* proxyModel = model(); + if(proxyModel) { + proxyModel->setShowThumbnails(settings.showThumbnails()); + } } } // namespace PCManFM diff --git a/pcmanfm/view.h b/pcmanfm/view.h index f3b1128..297b33e 100644 --- a/pcmanfm/view.h +++ b/pcmanfm/view.h @@ -22,10 +22,12 @@ #define PCMANFM_FOLDERVIEW_H #include +#include + namespace Fm { - class FileMenu; - class FolderMenu; +class FileMenu; +class FolderMenu; } namespace PCManFM { @@ -33,38 +35,38 @@ namespace PCManFM { class Settings; class View : public Fm::FolderView { -Q_OBJECT + Q_OBJECT public: - explicit View(Fm::FolderView::ViewMode _mode = IconMode, QWidget* parent = 0); - virtual ~View(); + explicit View(Fm::FolderView::ViewMode _mode = IconMode, QWidget* parent = 0); + virtual ~View(); - void updateFromSettings(Settings& settings); + void updateFromSettings(Settings& settings); - QSize getMargins() const { - return Fm::FolderView::getMargins(); - } - void setMargins(QSize size) { - Fm::FolderView::setMargins(size); - } + QSize getMargins() const { + return Fm::FolderView::getMargins(); + } + void setMargins(QSize size) { + Fm::FolderView::setMargins(size); + } Q_SIGNALS: - void openDirRequested(FmPath* path, int target); + void openDirRequested(const Fm::FilePath& path, int target); protected Q_SLOTS: - void onNewWindow(); - void onNewTab(); - void onOpenInTerminal(); - void onSearch(); + void onNewWindow(); + void onNewTab(); + void onOpenInTerminal(); + void onSearch(); protected: - virtual void onFileClicked(int type, FmFileInfo* fileInfo); - virtual void prepareFileMenu(Fm::FileMenu* menu); - virtual void prepareFolderMenu(Fm::FolderMenu* menu); + virtual void onFileClicked(int type, const std::shared_ptr& fileInfo); + virtual void prepareFileMenu(Fm::FileMenu* menu); + virtual void prepareFolderMenu(Fm::FolderMenu* menu); private: }; -}; +} #endif // PCMANFM_FOLDERVIEW_H