Cherry-picking upstream release 0.12.0.

* Bumped Standards to 4.1.1
* Bumped build-tools >= 0.4.0
* Bumped libfm-qt-dev >= 0.12.0
* Bumped years in copyright
* Added  build dependency libexif-dev
* Added Breaks and Replaces for lxqt-common << 0.12.0
ubuntu/disco debian/0.12.0-1
Alf Gaida 7 years ago
parent 307faf782b
commit 5fba8b840b

@ -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 * remove 0.11.3 changelog entries
* Bump patch version * Bump patch version
* Release 0.11.3: Update changelog * Release 0.11.3: Update changelog

@ -6,12 +6,14 @@ if (POLICY CMP0063)
cmake_policy (SET CMP0063 NEW) cmake_policy (SET CMP0063 NEW)
endif (POLICY CMP0063) endif (POLICY CMP0063)
# PcmanFm-Qt Version
set(PCMANFM_QT_VERSION_MAJOR 0) set(PCMANFM_QT_VERSION_MAJOR 0)
set(PCMANFM_QT_VERSION_MINOR 11) set(PCMANFM_QT_VERSION_MINOR 12)
set(PCMANFM_QT_VERSION_PATCH 3) set(PCMANFM_QT_VERSION_PATCH 0)
set(PCMANFM_QT_VERSION ${PCMANFM_QT_VERSION_MAJOR}.${PCMANFM_QT_VERSION_MINOR}.${PCMANFM_QT_VERSION_PATCH}) 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") 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(fm-qt REQUIRED)
find_package(lxqt-build-tools ${LXQTBT_MINIMUM_VERSION} 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) option(UPDATE_TRANSLATIONS "Update source translation translations/*.ts files" OFF)
include(GNUInstallDirs) include(GNUInstallDirs)
include(LXQtConfigVars)
include(LXQtTranslateTs) include(LXQtTranslateTs)
include(LXQtTranslateDesktop) include(LXQtTranslateDesktop)
include(LXQtCompilerSettings NO_POLICY_SCOPE) include(LXQtCompilerSettings NO_POLICY_SCOPE)
@ -61,3 +64,7 @@ if(BUILD_DOCUMENTATION)
) )
install(DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/docs" DESTINATION "${CMAKE_INSTALL_DOCDIR}") install(DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/docs" DESTINATION "${CMAKE_INSTALL_DOCDIR}")
endif() endif()
# merged from lxqt-common
add_subdirectory(autostart)
add_subdirectory(config)

@ -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
)

@ -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

@ -0,0 +1,2 @@
# Translations
Name[ar]=سطح المكتب

@ -0,0 +1,2 @@
# Translations
Name[cs]=Plocha

@ -0,0 +1,2 @@
# Translations
Name[cs_CZ]=Plocha

@ -0,0 +1,2 @@
# Translations
Name[da]=Skrivebord

@ -0,0 +1,2 @@
# Translations
Name[de]=Arbeitsfläche

@ -0,0 +1,2 @@
# Translations
Name[el]=Επιφάνεια εργασίας

@ -0,0 +1,2 @@
# Translations
Name[eo]=Labortablo

@ -0,0 +1,2 @@
# Translations
Name[es]=Escritorio

@ -0,0 +1,2 @@
# Translations
Name[es_VE]=Escritorio

@ -0,0 +1,2 @@
# Translations
Name[eu]=Mahaigaina

@ -0,0 +1,2 @@
# Translations
Name[fi]=Työpöytä

@ -0,0 +1,2 @@
# Translations
Name[fr]=Bureau

@ -0,0 +1,2 @@
# Translations
Name[hu]=Asztal

@ -0,0 +1,2 @@
# Translations
Name[ia]=Scriptorio

@ -0,0 +1,2 @@
# Translations
Name[it_IT]=Desktop

@ -0,0 +1,2 @@
# Translations
Name[ja]=デスクトップ

@ -0,0 +1,2 @@
# Translations
Name[lt]=Darbalaukis

@ -0,0 +1,2 @@
# Translations
Name[nl]=Bureaublad

@ -0,0 +1,2 @@
# Translations
Name[pl_PL]=Pulpit

@ -0,0 +1,2 @@
# Translations
Name[pt]=Área de trabalho

@ -0,0 +1,2 @@
# Translations
Name[pt_BR]=Área de trabalho

@ -0,0 +1,2 @@
# Translations
Name[ro_RO]=Desktop

@ -0,0 +1,2 @@
# Translations
Name[ru]=Pабочий стол

@ -0,0 +1,2 @@
# Translations
Name[ru_RU]=Рабочий стол

@ -0,0 +1,2 @@
# Translations
Name[sl]=Namizje

@ -0,0 +1,2 @@
# Translations
Name[th_TH]=เดสก์ท็อป

@ -0,0 +1,2 @@
# Translations
Name[tr]=Masaüstü

@ -0,0 +1,2 @@
# Translations
Name[uk]=Стільниця

@ -0,0 +1,2 @@
# Translations
Name[zh_CN]=桌面

@ -0,0 +1,2 @@
# Translations
Name[zh_TW]=桌面

@ -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
)

@ -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

12
debian/changelog vendored

@ -1,3 +1,15 @@
pcmanfm-qt (0.12.0-1) experimental; urgency=medium
* Cherry-picking upstream release 0.12.0.
* Bumped Standards to 4.1.1
* Bumped build-tools >= 0.4.0
* Bumped libfm-qt-dev >= 0.12.0
* Bumped years in copyright
* Added build dependency libexif-dev
* Added Breaks and Replaces for lxqt-common << 0.12.0
-- Alf Gaida <agaida@siduction.org> Tue, 24 Oct 2017 21:53:39 +0200
pcmanfm-qt (0.11.3-4) unstable; urgency=medium pcmanfm-qt (0.11.3-4) unstable; urgency=medium
* Depend on desktop-file-utils (Closes: #866900) * Depend on desktop-file-utils (Closes: #866900)

16
debian/control vendored

@ -8,17 +8,19 @@ Uploaders: Alf Gaida <agaida@siduction.org>,
Section: x11 Section: x11
Priority: optional Priority: optional
Build-Depends: debhelper (>= 10), Build-Depends: debhelper (>= 10),
libfm-qt-dev (>= 0.11.2), libexif-dev,
libfm-qt-dev (>= 0.12.0),
libglib2.0-dev, libglib2.0-dev,
libkf5windowsystem-dev, libkf5windowsystem-dev,
libmenu-cache-dev, libmenu-cache-dev,
libqt5svg5-dev, libqt5svg5-dev,
libqt5x11extras5-dev, libqt5x11extras5-dev,
libx11-dev, libx11-dev,
lxqt-build-tools (>= 0.3.0) lxqt-build-tools (>= 0.4.0),
Standards-Version: 4.0.0 quilt
Vcs-Browser: https://anonscm.debian.org/cgit/pkg-lxqt/pcmanfm-qt.git/?h=debian/sid Standards-Version: 4.1.1
Vcs-Git: https://anonscm.debian.org/git/pkg-lxqt/pcmanfm-qt.git -b debian/sid Vcs-Browser: https://anonscm.debian.org/cgit/pkg-lxqt/pcmanfm-qt.git/?h=debian/experimental
Vcs-Git: https://anonscm.debian.org/git/pkg-lxqt/pcmanfm-qt.git -b debian/experimental
Homepage: https://github.com/lxde/pcmanfm-qt Homepage: https://github.com/lxde/pcmanfm-qt
Package: pcmanfm-qt Package: pcmanfm-qt
@ -28,7 +30,7 @@ Depends: ${misc:Depends},
default-dbus-session-bus | dbus-session-bus | dbus-x11, default-dbus-session-bus | dbus-session-bus | dbus-x11,
desktop-file-utils, desktop-file-utils,
libfm-modules, libfm-modules,
libfm-qt3 (>= 0.11.2), libfm-qt3 (>= 0.12.0),
lxqt-sudo lxqt-sudo
Recommends: eject, Recommends: eject,
ffmpegthumbnailer, ffmpegthumbnailer,
@ -39,6 +41,8 @@ Recommends: eject,
oxygen-icon-theme | breeze-icon-theme | faenza-icon-theme | gnome-icon-theme, oxygen-icon-theme | breeze-icon-theme | faenza-icon-theme | gnome-icon-theme,
pcmanfm-qt-l10n pcmanfm-qt-l10n
Suggests: cdtool [linux-any] Suggests: cdtool [linux-any]
Breaks: lxqt-common (<< 0.12.0)
Replaces: lxqt-common (<< 0.12.0)
Description: extremely fast and lightweight file and desktop icon manager Description: extremely fast and lightweight file and desktop icon manager
PCManFM-Qt is the Qt port of the LXDE file manager PCManFM. PCManFM-Qt is the Qt port of the LXDE file manager PCManFM.
. .

6
debian/copyright vendored

@ -3,8 +3,8 @@ Upstream-Name: pcmanfm-qt
Source: https://github.com/lxde/pcmanfm-qt Source: https://github.com/lxde/pcmanfm-qt
Files: * Files: *
Copyright: 2013-2016 LXQt team Copyright: 2013-2017 LXQt team
2013-2016 Hong Jen Yee (PCMan) <pcman.tw@gmail.com> 2013-2017 Hong Jen Yee (PCMan) <pcman.tw@gmail.com>
2012-2013 Andriy Grytsenko (LStranger) <andrej@rep.kiev.ua> 2012-2013 Andriy Grytsenko (LStranger) <andrej@rep.kiev.ua>
2014 Kuzma Shapran <kuzma.shapran@gmail.com> 2014 Kuzma Shapran <kuzma.shapran@gmail.com>
License: GPL-2.0+ License: GPL-2.0+
@ -12,7 +12,7 @@ License: GPL-2.0+
Files: debian/* Files: debian/*
Copyright: 2014-2015 Wen Liao <wen.cf83@gmail.com> Copyright: 2014-2015 Wen Liao <wen.cf83@gmail.com>
2014-2016 ChangZhuo Chen (陳昌倬) <czchen@debian.org> 2014-2016 ChangZhuo Chen (陳昌倬) <czchen@debian.org>
2013-2016 Alf Gaida <agaida@siduction.org> 2013-2017 Alf Gaida <agaida@siduction.org>
2015 Andrew Lee (李健秋) <ajqlee@debian.org> 2015 Andrew Lee (李健秋) <ajqlee@debian.org>
License: GPL-2.0+ License: GPL-2.0+

@ -4,13 +4,13 @@ set(pcmanfm_SRCS
mainwindow.cpp mainwindow.cpp
tabpage.cpp tabpage.cpp
tabbar.cpp tabbar.cpp
statusbar.cpp
view.cpp view.cpp
launcher.cpp launcher.cpp
preferencesdialog.cpp preferencesdialog.cpp
xdgdir.cpp xdgdir.cpp
desktoppreferencesdialog.cpp desktoppreferencesdialog.cpp
desktopwindow.cpp desktopwindow.cpp
desktopitemdelegate.cpp
autorundialog.cpp autorundialog.cpp
connectserverdialog.cpp connectserverdialog.cpp
settings.cpp settings.cpp

@ -43,7 +43,7 @@
#include <libfm-qt/mountoperation.h> #include <libfm-qt/mountoperation.h>
#include <libfm-qt/filesearchdialog.h> #include <libfm-qt/filesearchdialog.h>
#include <libfm-qt/path.h> #include <libfm-qt/path.h>
#include <libfm-qt/terminal.h> #include <libfm-qt/core/terminal.h>
#include "applicationadaptor.h" #include "applicationadaptor.h"
#include "preferencesdialog.h" #include "preferencesdialog.h"
@ -63,8 +63,9 @@ static const char* ifaceName = "org.pcmanfm.Application";
int ProxyStyle::styleHint(StyleHint hint, const QStyleOption* option, const QWidget* widget, QStyleHintReturn* returnData) const { int ProxyStyle::styleHint(StyleHint hint, const QStyleOption* option, const QWidget* widget, QStyleHintReturn* returnData) const {
Application* app = static_cast<Application*>(qApp); Application* app = static_cast<Application*>(qApp);
if(hint == QStyle::SH_ItemView_ActivateItemOnSingleClick) if(hint == QStyle::SH_ItemView_ActivateItemOnSingleClick) {
return app->settings().singleClick(); return app->settings().singleClick();
}
return QProxyStyle::styleHint(hint, option, widget, returnData); return QProxyStyle::styleHint(hint, option, widget, returnData);
} }
@ -78,8 +79,8 @@ Application::Application(int& argc, char** argv):
desktopWindows_(), desktopWindows_(),
preferencesDialog_(), preferencesDialog_(),
editBookmarksialog_(), editBookmarksialog_(),
volumeMonitor_(NULL), volumeMonitor_(nullptr),
userDirsWatcher_(NULL), userDirsWatcher_(nullptr),
lxqtRunning_(false) { lxqtRunning_(false) {
argc_ = argc; argc_ = argc;
@ -145,13 +146,13 @@ Application::~Application() {
// removeNativeEventFilter(this); // removeNativeEventFilter(this);
} }
void Application::initWatch() void Application::initWatch() {
{
QFile file_(QStandardPaths::writableLocation(QStandardPaths::ConfigLocation) + QStringLiteral("/user-dirs.dirs")); QFile file_(QStandardPaths::writableLocation(QStandardPaths::ConfigLocation) + QStringLiteral("/user-dirs.dirs"));
if(! file_.open(QIODevice::ReadOnly | QIODevice::Text)) { if(! file_.open(QIODevice::ReadOnly | QIODevice::Text)) {
qDebug() << Q_FUNC_INFO << "Could not read: " << userDirsFile_; qDebug() << Q_FUNC_INFO << "Could not read: " << userDirsFile_;
userDirsFile_ = QString(); userDirsFile_ = QString();
} else { }
else {
userDirsFile_ = file_.fileName(); userDirsFile_ = file_.fileName();
} }
@ -206,10 +207,12 @@ bool Application::parseCommandLineArgs() {
if(isPrimaryInstance) { if(isPrimaryInstance) {
qDebug("isPrimaryInstance"); qDebug("isPrimaryInstance");
if(parser.isSet(daemonOption)) if(parser.isSet(daemonOption)) {
daemonMode_ = true; daemonMode_ = true;
if(parser.isSet(profileOption)) }
if(parser.isSet(profileOption)) {
profileName_ = parser.value(profileOption); profileName_ = parser.value(profileOption);
}
// load settings // load settings
settings_.load(profileName_); settings_.load(profileName_);
@ -219,8 +222,9 @@ bool Application::parseCommandLineArgs() {
desktopManager(true); desktopManager(true);
keepRunning = true; keepRunning = true;
} }
else if(parser.isSet(desktopOffOption)) else if(parser.isSet(desktopOffOption)) {
desktopManager(false); desktopManager(false);
}
if(parser.isSet(desktopPrefOption)) { // desktop preference dialog if(parser.isSet(desktopPrefOption)) { // desktop preference dialog
desktopPrefrences(parser.value(desktopPrefOption)); desktopPrefrences(parser.value(desktopPrefOption));
@ -234,19 +238,22 @@ bool Application::parseCommandLineArgs() {
preferences(parser.value(showPrefOption)); preferences(parser.value(showPrefOption));
keepRunning = true; keepRunning = true;
} }
else if(parser.isSet(setWallpaperOption) || parser.isSet(wallpaperModeOption)) // set wall paper else if(parser.isSet(setWallpaperOption) || parser.isSet(wallpaperModeOption)) { // set wall paper
setWallpaper(parser.value(setWallpaperOption), parser.value(wallpaperModeOption)); setWallpaper(parser.value(setWallpaperOption), parser.value(wallpaperModeOption));
}
else { else {
if(!parser.isSet(desktopOption) && !parser.isSet(desktopOffOption)) { if(!parser.isSet(desktopOption) && !parser.isSet(desktopOffOption)) {
QStringList paths = parser.positionalArguments(); QStringList paths = parser.positionalArguments();
if(paths.isEmpty()) { if(paths.isEmpty()) {
// if no path is specified and we're using daemon mode, // if no path is specified and we're using daemon mode,
// don't open current working directory // don't open current working directory
if(!daemonMode_) if(!daemonMode_) {
paths.push_back(QDir::currentPath()); paths.push_back(QDir::currentPath());
} }
if(!paths.isEmpty()) }
if(!paths.isEmpty()) {
launchFiles(QDir::currentPath(), paths, parser.isSet(newWindowOption)); launchFiles(QDir::currentPath(), paths, parser.isSet(newWindowOption));
}
keepRunning = true; keepRunning = true;
} }
} }
@ -259,10 +266,12 @@ bool Application::parseCommandLineArgs() {
return false; return false;
} }
if(parser.isSet(desktopOption)) if(parser.isSet(desktopOption)) {
iface.call("desktopManager", true); iface.call("desktopManager", true);
else if(parser.isSet(desktopOffOption)) }
else if(parser.isSet(desktopOffOption)) {
iface.call("desktopManager", false); iface.call("desktopManager", false);
}
if(parser.isSet(desktopPrefOption)) { // desktop preference dialog if(parser.isSet(desktopPrefOption)) { // desktop preference dialog
iface.call("desktopPrefrences", parser.value(desktopPrefOption)); iface.call("desktopPrefrences", parser.value(desktopPrefOption));
@ -305,11 +314,13 @@ void Application::init() {
int Application::exec() { int Application::exec() {
if(!parseCommandLineArgs()) if(!parseCommandLineArgs()) {
return 0; return 0;
}
if(daemonMode_) // keep running even when there is no window opened. if(daemonMode_) { // keep running even when there is no window opened.
setQuitOnLastWindowClosed(false); setQuitOnLastWindowClosed(false);
}
volumeMonitor_ = g_volume_monitor_get(); volumeMonitor_ = g_volume_monitor_get();
// delay the volume manager a little because in newer versions of glib/gio there's a problem. // delay the volume manager a little because in newer versions of glib/gio there's a problem.
@ -324,8 +335,7 @@ int Application::exec() {
} }
void Application::onUserDirsChanged() void Application::onUserDirsChanged() {
{
qDebug() << Q_FUNC_INFO; qDebug() << Q_FUNC_INFO;
bool file_deleted = !userDirsWatcher_->files().contains(userDirsFile_); bool file_deleted = !userDirsWatcher_->files().contains(userDirsFile_);
if(file_deleted) { if(file_deleted) {
@ -342,7 +352,8 @@ void Application::onUserDirsChanged()
for(int i = 0; i < N; ++i) { for(int i = 0; i < N; ++i) {
desktopWindows_.at(i)->setDesktopFolder(); desktopWindows_.at(i)->setDesktopFolder();
} }
} else { }
else {
qWarning("Application::onUserDirsChanged: %s doesn't exist", qWarning("Application::onUserDirsChanged: %s doesn't exist",
userDesktopFolder_.toUtf8().constData()); userDesktopFolder_.toUtf8().constData());
} }
@ -441,22 +452,29 @@ void Application::desktopPrefrences(QString page) {
void Application::onFindFileAccepted() { void Application::onFindFileAccepted() {
Fm::FileSearchDialog* dlg = static_cast<Fm::FileSearchDialog*>(sender()); Fm::FileSearchDialog* dlg = static_cast<Fm::FileSearchDialog*>(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::Path uri = dlg->searchUri();
Fm::PathList paths; Fm::FilePathList paths;
paths.pushTail(uri); Fm::GFilePtr gf{uri.toGfile(), false};
paths.push_back(Fm::FilePath{gf.get(), true});
MainWindow* window = MainWindow::lastActive(); MainWindow* window = MainWindow::lastActive();
Launcher(window).launchPaths(NULL, paths); Launcher(window).launchPaths(nullptr, paths);
} }
void Application::onConnectToServerAccepted() { void Application::onConnectToServerAccepted() {
ConnectServerDialog* dlg = static_cast<ConnectServerDialog*>(sender()); ConnectServerDialog* dlg = static_cast<ConnectServerDialog*>(sender());
QString uri = dlg->uriText(); QString uri = dlg->uriText();
Fm::Path path = Fm::Path::newForStr(uri.toUtf8().constData()); Fm::FilePathList paths;
qDebug() << uri << " => " << path.toStr(); paths.push_back(Fm::FilePath::fromDisplayName(uri.toUtf8().constData()));
Fm::PathList paths;
paths.pushTail(path);
MainWindow* window = MainWindow::lastActive(); MainWindow* window = MainWindow::lastActive();
Launcher(window).launchPaths(NULL, paths); Launcher(window).launchPaths(nullptr, paths);
} }
void Application::findFiles(QStringList paths) { void Application::findFiles(QStringList paths) {
@ -464,6 +482,14 @@ void Application::findFiles(QStringList paths) {
Fm::FileSearchDialog* dlg = new Fm::FileSearchDialog(paths); Fm::FileSearchDialog* dlg = new Fm::FileSearchDialog(paths);
connect(dlg, &QDialog::accepted, this, &Application::onFindFileAccepted); connect(dlg, &QDialog::accepted, this, &Application::onFindFileAccepted);
dlg->setAttribute(Qt::WA_DeleteOnClose); 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(); dlg->show();
} }
@ -475,54 +501,48 @@ void Application::connectToServer() {
} }
void Application::launchFiles(QString cwd, QStringList paths, bool inNewWindow) { void Application::launchFiles(QString cwd, QStringList paths, bool inNewWindow) {
Fm::PathList pathList; Fm::FilePathList pathList;
Fm::Path cwd_path; Fm::FilePath cwd_path;
QStringList::iterator it; QStringList::iterator it;
Q_FOREACH(const QString& it, paths) { Q_FOREACH(const QString& it, paths) {
QByteArray pathName = it.toLocal8Bit(); QByteArray pathName = it.toLocal8Bit();
Fm::Path path; Fm::FilePath path;
if(pathName[0] == '/') // absolute path if(pathName == "~") { // special case for home dir
path = Fm::Path::newForPath(pathName.constData()); path = Fm::FilePath::homeDir();
else if(pathName.contains(":/")) // URI }
path = Fm::Path::newForUri(pathName.constData()); if(pathName[0] == '/') { // absolute path
else if(pathName == "~") // special case for home dir path = Fm::FilePath::fromLocalPath(pathName.constData());
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); 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(NULL).launchPaths(NULL, pathList); Launcher(nullptr).launchPaths(nullptr, pathList);
} }
void Application::openFolders(Fm::FileInfoList files) { void Application::openFolders(Fm::FileInfoList files) {
Launcher(NULL).launchFiles(NULL, files); Launcher(nullptr).launchFiles(nullptr, std::move(files));
} }
void Application::openFolderInTerminal(Fm::Path path) { void Application::openFolderInTerminal(Fm::FilePath path) {
if(!settings_.terminal().isEmpty()) { if(!settings_.terminal().isEmpty()) {
char* cwd_str; Fm::GErrorPtr err;
if(path.isNative()) auto terminalName = settings_.terminal().toUtf8();
cwd_str = path.toStr(); if(!Fm::launchTerminal(terminalName.constData(), path, err)) {
else { // gio will map remote filesystems to local FUSE-mounted paths here. QMessageBox::critical(nullptr, tr("Error"), err.message());
GFile* gf = path.toGfile();
cwd_str = g_file_get_path(gf);
g_object_unref(gf);
} }
GError* err = NULL;
if(!Fm::Terminal::launch(cwd_str, &err)) {
QMessageBox::critical(NULL, tr("Error"), QString::fromUtf8(err->message));
g_error_free(err);
}
g_free(cwd_str);
} }
else { else {
// show an error message and ask the user to set the command // show an error message and ask the user to set the command
QMessageBox::critical(NULL, tr("Error"), tr("Terminal emulator is not set.")); QMessageBox::critical(nullptr, tr("Error"), tr("Terminal emulator is not set."));
preferences("advanced"); preferences("advanced");
} }
} }
@ -558,8 +578,9 @@ void Application::setWallpaper(QString path, QString modeString) {
// defined in this function and we can clearly see that it does not // defined in this function and we can clearly see that it does not
// overflow. // overflow.
mode = static_cast<DesktopWindow::WallpaperMode>(i); mode = static_cast<DesktopWindow::WallpaperMode>(i);
if(mode != settings_.wallpaperMode()) if(mode != settings_.wallpaperMode()) {
changed = true; changed = true;
}
break; break;
} }
} }
@ -568,10 +589,12 @@ void Application::setWallpaper(QString path, QString modeString) {
if(changed) { if(changed) {
if(enableDesktopManager_) { if(enableDesktopManager_) {
Q_FOREACH(DesktopWindow* desktopWindow, desktopWindows_) { Q_FOREACH(DesktopWindow* desktopWindow, desktopWindows_) {
if(!path.isEmpty()) if(!path.isEmpty()) {
desktopWindow->setWallpaperFile(path); desktopWindow->setWallpaperFile(path);
if(mode != settings_.wallpaperMode()) }
if(mode != settings_.wallpaperMode()) {
desktopWindow->setWallpaperMode(mode); desktopWindow->setWallpaperMode(mode);
}
desktopWindow->updateWallpaper(); desktopWindow->updateWallpaper();
} }
settings_.save(); // save the settings to the config file settings_.save(); // save the settings to the config file
@ -620,8 +643,9 @@ void Application::onScreenCountChanged(int newCount) {
} }
// we used non-virtual mode originally, but now we're switched to virtual mode // we used non-virtual mode originally, but now we're switched to virtual mode
if(isVirtual) if(isVirtual) {
newCount = 1; // we only want one desktop window for all screens in virtual mode newCount = 1; // we only want one desktop window for all screens in virtual mode
}
if(newCount > desktopWindows_.size()) { if(newCount > desktopWindows_.size()) {
// add more desktop windows // add more desktop windows
@ -641,10 +665,12 @@ void Application::onScreenCountChanged(int newCount) {
if(newCount == 1) { // now only 1 screen is in use if(newCount == 1) { // now only 1 screen is in use
DesktopWindow* desktop = desktopWindows_.at(0); DesktopWindow* desktop = desktopWindows_.at(0);
if(isVirtual) if(isVirtual) {
desktop->setScreenNum(-1); desktop->setScreenNum(-1);
else // non-virtual mode, and we only have 1 screen }
else { // non-virtual mode, and we only have 1 screen
desktop->setScreenNum(0); desktop->setScreenNum(0);
}
desktop->updateWallpaper(); desktop->updateWallpaper();
} }
} }
@ -664,15 +690,16 @@ void Application::updateFromSettings() {
mainWindow->updateFromSettings(settings_); mainWindow->updateFromSettings(settings_);
} }
} }
if(desktopManagerEnabled()) if(desktopManagerEnabled()) {
updateDesktopsFromSettings(); updateDesktopsFromSettings();
} }
}
void Application::updateDesktopsFromSettings() { void Application::updateDesktopsFromSettings(bool changeSlide) {
QVector<DesktopWindow*>::iterator it; QVector<DesktopWindow*>::iterator it;
for(it = desktopWindows_.begin(); it != desktopWindows_.end(); ++it) { for(it = desktopWindows_.begin(); it != desktopWindows_.end(); ++it) {
DesktopWindow* desktopWindow = static_cast<DesktopWindow*>(*it); DesktopWindow* desktopWindow = static_cast<DesktopWindow*>(*it);
desktopWindow->updateFromSettings(settings_); desktopWindow->updateFromSettings(settings_, changeSlide);
} }
} }
@ -694,8 +721,9 @@ void Application::initVolumeManager() {
GList* vols = g_volume_monitor_get_volumes(volumeMonitor_); GList* vols = g_volume_monitor_get_volumes(volumeMonitor_);
for(GList* l = vols; l; l = l->next) { for(GList* l = vols; l; l = l->next) {
GVolume* volume = G_VOLUME(l->data); GVolume* volume = G_VOLUME(l->data);
if(g_volume_should_automount(volume)) if(g_volume_should_automount(volume)) {
autoMountVolume(volume, false); autoMountVolume(volume, false);
}
g_object_unref(volume); g_object_unref(volume);
} }
g_list_free(vols); g_list_free(vols);
@ -703,18 +731,21 @@ void Application::initVolumeManager() {
} }
bool Application::autoMountVolume(GVolume* volume, bool interactive) { bool Application::autoMountVolume(GVolume* volume, bool interactive) {
if(!g_volume_should_automount(volume) || !g_volume_can_mount(volume)) if(!g_volume_should_automount(volume) || !g_volume_can_mount(volume)) {
return FALSE; return FALSE;
}
GMount* mount = g_volume_get_mount(volume); GMount* mount = g_volume_get_mount(volume);
if(!mount) { // not mounted, automount is needed if(!mount) { // not mounted, automount is needed
// try automount // try automount
Fm::MountOperation* op = new Fm::MountOperation(interactive); Fm::MountOperation* op = new Fm::MountOperation(interactive);
op->mount(volume); op->mount(volume);
if(!op->wait()) if(!op->wait()) {
return false; return false;
if(!interactive) }
if(!interactive) {
return true; return true;
}
mount = g_volume_get_mount(volume); mount = g_volume_get_mount(volume);
} }
@ -730,9 +761,10 @@ bool Application::autoMountVolume(GVolume* volume, bool interactive) {
// static // static
void Application::onVolumeAdded(GVolumeMonitor* monitor, GVolume* volume, Application* pThis) { void Application::onVolumeAdded(GVolumeMonitor* monitor, GVolume* volume, Application* pThis) {
if(pThis->settings_.mountRemovable()) if(pThis->settings_.mountRemovable()) {
pThis->autoMountVolume(volume, true); pThis->autoMountVolume(volume, true);
} }
}
#if 0 #if 0
bool Application::nativeEventFilter(const QByteArray& eventType, void* message, long* result) { bool Application::nativeEventFilter(const QByteArray& eventType, void* message, long* result) {
@ -788,10 +820,11 @@ void Application::onScreenDestroyed(QObject* screenObj) {
reloadNeeded = true; reloadNeeded = true;
} }
} }
if(reloadNeeded) if(reloadNeeded) {
QTimer::singleShot(0, this, SLOT(reloadDesktopsAsNeeded())); QTimer::singleShot(0, this, SLOT(reloadDesktopsAsNeeded()));
} }
} }
}
void Application::reloadDesktopsAsNeeded() { void Application::reloadDesktopsAsNeeded() {
if(enableDesktopManager_) { if(enableDesktopManager_) {
@ -845,7 +878,8 @@ void Application::installSigtermHandler() {
if(::sigaction(SIGTERM, &action, 0) != 0) { if(::sigaction(SIGTERM, &action, 0) != 0) {
qWarning("Couldn't install SIGTERM handler"); qWarning("Couldn't install SIGTERM handler");
} }
} else { }
else {
qWarning("Couldn't create SIGTERM socketpair"); qWarning("Couldn't create SIGTERM socketpair");
} }
} }

@ -31,6 +31,9 @@
#include <QTranslator> #include <QTranslator>
#include <gio/gio.h> #include <gio/gio.h>
#include <libfm-qt/core/filepath.h>
#include <libfm-qt/core/fileinfo.h>
class QScreen; class QScreen;
class QFileSystemWatcher; class QFileSystemWatcher;
@ -84,9 +87,9 @@ public:
} }
void updateFromSettings(); void updateFromSettings();
void updateDesktopsFromSettings(); void updateDesktopsFromSettings(bool changeSlide = true);
void openFolderInTerminal(Fm::Path path); void openFolderInTerminal(Fm::FilePath path);
void openFolders(Fm::FileInfoList files); void openFolders(Fm::FileInfoList files);
QString profileName() { QString profileName() {

@ -23,20 +23,22 @@
#include <QListWidgetItem> #include <QListWidgetItem>
#include "application.h" #include "application.h"
#include "mainwindow.h" #include "mainwindow.h"
#include <libfm-qt/core/filepath.h>
#include <libfm-qt/core/iconinfo.h>
namespace PCManFM { namespace PCManFM {
AutoRunDialog::AutoRunDialog(GVolume* volume, GMount* mount, QWidget* parent, Qt::WindowFlags f): AutoRunDialog::AutoRunDialog(GVolume* volume, GMount* mount, QWidget* parent, Qt::WindowFlags f):
QDialog(parent, f), QDialog(parent, f),
cancellable(g_cancellable_new()), cancellable(g_cancellable_new()),
applications(NULL), applications(nullptr),
mount_(G_MOUNT(g_object_ref(mount))) { mount_(G_MOUNT(g_object_ref(mount))) {
setAttribute(Qt::WA_DeleteOnClose); setAttribute(Qt::WA_DeleteOnClose);
ui.setupUi(this); ui.setupUi(this);
GIcon* gicon = g_volume_get_icon(volume); GIcon* gicon = g_volume_get_icon(volume);
QIcon icon = Fm::IconTheme::icon(gicon); QIcon icon = Fm::IconInfo::fromGIcon(gicon)->qicon();
ui.icon->setPixmap(icon.pixmap(QSize(48, 48))); ui.icon->setPixmap(icon.pixmap(QSize(48, 48)));
// add actions // add actions
@ -47,11 +49,12 @@ AutoRunDialog::AutoRunDialog(GVolume* volume, GMount* mount, QWidget* parent, Qt
} }
AutoRunDialog::~AutoRunDialog() { AutoRunDialog::~AutoRunDialog() {
g_list_foreach(applications, (GFunc)g_object_unref, NULL); g_list_foreach(applications, (GFunc)g_object_unref, nullptr);
g_list_free(applications); g_list_free(applications);
if(mount_) if(mount_) {
g_object_unref(mount_); g_object_unref(mount_);
}
if(cancellable) { if(cancellable) {
g_cancellable_cancel(cancellable); g_cancellable_cancel(cancellable);
@ -66,15 +69,15 @@ void AutoRunDialog::accept() {
void* p = item->data(Qt::UserRole).value<void*>(); void* p = item->data(Qt::UserRole).value<void*>();
if(p) { // run the selected application if(p) { // run the selected application
GAppInfo* app = G_APP_INFO(p); GAppInfo* app = G_APP_INFO(p);
GList* filelist = g_list_prepend(NULL, gf); GList* filelist = g_list_prepend(nullptr, gf);
g_app_info_launch(app, filelist, NULL, NULL); g_app_info_launch(app, filelist, nullptr, nullptr);
g_list_free(filelist); g_list_free(filelist);
} }
else { else {
// the default action, open the mounted folder in the file manager // the default action, open the mounted folder in the file manager
Application* app = static_cast<Application*>(qApp); Application* app = static_cast<Application*>(qApp);
Settings& settings = app->settings(); Settings& settings = app->settings();
Fm::Path path = Fm::Path::newForGfile(gf); Fm::FilePath path{gf, true};
// open the path in a new window // open the path in a new window
// FIXME: or should we open it in a new tab? Make this optional later // FIXME: or should we open it in a new tab? Make this optional later
MainWindow* win = new MainWindow(path); MainWindow* win = new MainWindow(path);
@ -93,19 +96,20 @@ void AutoRunDialog::accept() {
void AutoRunDialog::onContentTypeFinished(GMount* mount, GAsyncResult* res, AutoRunDialog* pThis) { void AutoRunDialog::onContentTypeFinished(GMount* mount, GAsyncResult* res, AutoRunDialog* pThis) {
if(pThis->cancellable) { if(pThis->cancellable) {
g_object_unref(pThis->cancellable); g_object_unref(pThis->cancellable);
pThis->cancellable = NULL; pThis->cancellable = nullptr;
} }
char** types = g_mount_guess_content_type_finish(mount, res, NULL); char** types = g_mount_guess_content_type_finish(mount, res, nullptr);
char* desc = NULL; char* desc = nullptr;
if(types) { if(types) {
if(types[0]) { if(types[0]) {
for(char** type = types; *type; ++type) { for(char** type = types; *type; ++type) {
GList* l = g_app_info_get_all_for_type(*type); GList* l = g_app_info_get_all_for_type(*type);
if(l) if(l) {
pThis->applications = g_list_concat(pThis->applications, l); pThis->applications = g_list_concat(pThis->applications, l);
} }
}
desc = g_content_type_get_description(types[0]); desc = g_content_type_get_description(types[0]);
} }
g_strfreev(types); g_strfreev(types);
@ -115,7 +119,7 @@ void AutoRunDialog::onContentTypeFinished(GMount* mount, GAsyncResult* res, Auto
for(GList* l = pThis->applications; l; l = l->next, ++pos) { for(GList* l = pThis->applications; l; l = l->next, ++pos) {
GAppInfo* app = G_APP_INFO(l->data); GAppInfo* app = G_APP_INFO(l->data);
GIcon* gicon = g_app_info_get_icon(app); GIcon* gicon = g_app_info_get_icon(app);
QIcon icon = Fm::IconTheme::icon(gicon); QIcon icon = Fm::IconInfo::fromGIcon(gicon)->qicon();
QString text = QString::fromUtf8(g_app_info_get_name(app)); QString text = QString::fromUtf8(g_app_info_get_name(app));
QListWidgetItem* item = new QListWidgetItem(icon, text); QListWidgetItem* item = new QListWidgetItem(icon, text);
item->setData(Qt::UserRole, qVariantFromValue<void*>(app)); item->setData(Qt::UserRole, qVariantFromValue<void*>(app));
@ -128,8 +132,9 @@ void AutoRunDialog::onContentTypeFinished(GMount* mount, GAsyncResult* res, Auto
pThis->ui.mediumType->setText(QString::fromUtf8(desc)); pThis->ui.mediumType->setText(QString::fromUtf8(desc));
g_free(desc); g_free(desc);
} }
else else {
pThis->ui.mediumType->setText(tr("Removable Disk")); pThis->ui.mediumType->setText(tr("Removable Disk"));
}
// select the first item // select the first item
pThis->ui.listWidget->item(0)->setSelected(true); pThis->ui.listWidget->item(0)->setSelected(true);

@ -310,6 +310,144 @@ A space is also reserved for 3 lines of text.</string>
</item> </item>
</layout> </layout>
</widget> </widget>
<widget class="QWidget" name="bgPage">
<attribute name="title">
<string>Slide Show</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QGroupBox" name="slideShow">
<property name="title">
<string>Enable Slide Show</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>false</bool>
</property>
<layout class="QGridLayout" name="gridLayout_4">
<item row="0" column="0" colspan="7">
<widget class="QLabel" name="label_10">
<property name="text">
<string>Wallpaper image folder:</string>
</property>
</widget>
</item>
<item row="1" column="6">
<widget class="QPushButton" name="folderBrowse">
<property name="text">
<string>Browse</string>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QSpinBox" name="hours">
<property name="suffix">
<string> hour(s)</string>
</property>
<property name="maximum">
<number>24</number>
</property>
</widget>
</item>
<item row="2" column="3">
<widget class="QLabel" name="label_12">
<property name="text">
<string>and</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="margin">
<number>5</number>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_11">
<property name="toolTip">
<string>Intervals less than 5min will be ignored</string>
</property>
<property name="text">
<string>Interval:</string>
</property>
</widget>
</item>
<item row="2" column="4">
<widget class="QSpinBox" name="minutes">
<property name="suffix">
<string> minute(s)</string>
</property>
<property name="maximum">
<number>55</number>
</property>
<property name="singleStep">
<number>5</number>
</property>
</widget>
</item>
<item row="2" column="5">
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>10</width>
<height>5</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="0" colspan="6">
<widget class="QLineEdit" name="imageFolder">
<property name="placeholderText">
<string>Wallpaper folder</string>
</property>
</widget>
</item>
<item row="2" column="1">
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Minimum</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>5</width>
<height>5</height>
</size>
</property>
</spacer>
</item>
<item row="3" column="0" colspan="6">
<widget class="QCheckBox" name="randomize">
<property name="text">
<string>Randomize the slide show</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<widget class="QWidget" name="advancedPage"> <widget class="QWidget" name="advancedPage">
<attribute name="title"> <attribute name="title">
<string>Advanced</string> <string>Advanced</string>

@ -1,207 +0,0 @@
/*
Copyright (C) 2013 Hong Jen Yee (PCMan) <pcman.tw@gmail.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "desktopitemdelegate.h"
#include <libfm-qt/foldermodel.h>
#include <libfm-qt/fileinfo.h>
#include <QApplication>
#include <QListView>
#include <QPainter>
#include <QIcon>
#include <QTextLayout>
#include <QTextOption>
#include <QTextLine>
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<FmFileInfo*>(index.data(Fm::FolderModel::FileInfoRole).value<void*>());
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<QSize>(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

@ -1,64 +0,0 @@
/*
Copyright (C) 2013 Hong Jen Yee (PCMan) <pcman.tw@gmail.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef PCMANFM_DESKTOPITEMDELEGATE_H
#define PCMANFM_DESKTOPITEMDELEGATE_H
#include <QStyledItemDelegate>
#include <QColor>
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

@ -84,6 +84,14 @@ DesktopPreferencesDialog::DesktopPreferencesDialog(QWidget* parent, Qt::WindowFl
qDebug("wallpaper: %s", settings.wallpaper().toUtf8().data()); qDebug("wallpaper: %s", settings.wallpaper().toUtf8().data());
ui.imageFile->setText(settings.wallpaper()); 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) { for(std::size_t i = 0; i < G_N_ELEMENTS(iconSizes); ++i) {
int size = iconSizes[i]; int size = iconSizes[i];
ui.iconSize->addItem(QString("%1 x %1").arg(size), size); ui.iconSize->addItem(QString("%1 x %1").arg(size), size);
@ -145,12 +153,22 @@ void DesktopPreferencesDialog::applySettings()
settings.setWallpaper(ui.imageFile->text()); settings.setWallpaper(ui.imageFile->text());
int mode = ui.wallpaperMode->itemData(ui.wallpaperMode->currentIndex()).toInt(); int mode = ui.wallpaperMode->itemData(ui.wallpaperMode->currentIndex()).toInt();
settings.setWallpaperMode(mode); 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.setDesktopIconSize(ui.iconSize->itemData(ui.iconSize->currentIndex()).toInt());
settings.setDesktopFont(ui.font->font()); settings.setDesktopFont(ui.font->font());
settings.setDesktopBgColor(ui.backgroundColor->color()); settings.setDesktopBgColor(ui.backgroundColor->color());
settings.setDesktopFgColor(ui.textColor->color()); settings.setDesktopFgColor(ui.textColor->color());
settings.setDesktopShadowColor(ui.shadowColor->color()); settings.setDesktopShadowColor(ui.shadowColor->color());
settings.setShowWmMenu(ui.showWmMenu->isChecked()); settings.setShowWmMenu(ui.showWmMenu->isChecked());
settings.setDesktopCellMargins(QSize(ui.hMargin->value(), ui.vMargin->value())); settings.setDesktopCellMargins(QSize(ui.hMargin->value(), ui.vMargin->value()));
settings.save(); settings.save();
@ -164,7 +182,7 @@ void DesktopPreferencesDialog::onApplyClicked()
void DesktopPreferencesDialog::accept() { void DesktopPreferencesDialog::accept() {
applySettings(); applySettings();
static_cast<Application*>(qApp)->updateDesktopsFromSettings(); static_cast<Application*>(qApp)->updateDesktopsFromSettings(false); // don't change slide wallpaper on clicking OK
QDialog::accept(); 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() void DesktopPreferencesDialog::onBrowseDesktopFolderClicked()
{ {
QFileDialog dlg; QFileDialog dlg;

@ -46,6 +46,7 @@ protected Q_SLOTS:
void onApplyClicked(); void onApplyClicked();
void onWallpaperModeChanged(int index); void onWallpaperModeChanged(int index);
void onBrowseClicked(); void onBrowseClicked();
void onFolderBrowseClicked();
void onBrowseDesktopFolderClicked(); void onBrowseDesktopFolderClicked();
void lockMargins(bool lock); void lockMargins(bool lock);

@ -30,6 +30,7 @@
#include <QLayout> #include <QLayout>
#include <QDebug> #include <QDebug>
#include <QTimer> #include <QTimer>
#include <QTime>
#include <QSettings> #include <QSettings>
#include <QStringBuilder> #include <QStringBuilder>
#include <QDir> #include <QDir>
@ -37,19 +38,19 @@
#include <QDropEvent> #include <QDropEvent>
#include <QMimeData> #include <QMimeData>
#include <QPaintEvent> #include <QPaintEvent>
#include <QStandardPaths>
#include "./application.h" #include "./application.h"
#include "mainwindow.h" #include "mainwindow.h"
#include "desktopitemdelegate.h"
#include <libfm-qt/foldermenu.h> #include <libfm-qt/foldermenu.h>
#include <libfm-qt/filemenu.h> #include <libfm-qt/filemenu.h>
#include <libfm-qt/folderitemdelegate.h>
#include <libfm-qt/cachedfoldermodel.h> #include <libfm-qt/cachedfoldermodel.h>
#include <libfm-qt/folderview_p.h> #include <libfm-qt/folderview_p.h>
#include <libfm-qt/fileoperation.h> #include <libfm-qt/fileoperation.h>
#include <libfm-qt/filepropsdialog.h> #include <libfm-qt/filepropsdialog.h>
#include <libfm-qt/utilities.h> #include <libfm-qt/utilities.h>
#include <libfm-qt/path.h> #include <libfm-qt/core/fileinfo.h>
#include <libfm-qt/fileinfo.h>
#include "xdgdir.h" #include "xdgdir.h"
#include <QX11Info> #include <QX11Info>
@ -57,17 +58,23 @@
#include <xcb/xcb.h> #include <xcb/xcb.h>
#include <X11/Xlib.h> #include <X11/Xlib.h>
#define MIN_SLIDE_INTERVAL 5*60000 // 5 min
#define MAX_SLIDE_INTERVAL (24*60+55)*60000 // 24 h and 55 min
namespace PCManFM { namespace PCManFM {
DesktopWindow::DesktopWindow(int screenNum): DesktopWindow::DesktopWindow(int screenNum):
View(Fm::FolderView::IconMode), View(Fm::FolderView::IconMode),
proxyModel_(NULL), proxyModel_(nullptr),
model_(NULL), model_(nullptr),
wallpaperMode_(WallpaperNone), wallpaperMode_(WallpaperNone),
fileLauncher_(NULL), slideShowInterval_(0),
wallpaperTimer_(nullptr),
wallpaperRandomize_(false),
fileLauncher_(nullptr),
showWmMenu_(false), showWmMenu_(false),
screenNum_(screenNum), screenNum_(screenNum),
relayoutTimer_(NULL) { relayoutTimer_(nullptr) {
QDesktopWidget* desktopWidget = QApplication::desktop(); QDesktopWidget* desktopWidget = QApplication::desktop();
setWindowFlags(Qt::Window | Qt::FramelessWindowHint); setWindowFlags(Qt::Window | Qt::FramelessWindowHint);
@ -84,9 +91,9 @@ DesktopWindow::DesktopWindow(int screenNum):
// This is to workaround Qt bug 54384 which affects Qt >= 5.6 // This is to workaround Qt bug 54384 which affects Qt >= 5.6
// https://bugreports.qt.io/browse/QTBUG-54384 // 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. // Setting a QPixmap larger then the screen resolution to desktop's QPalette won't work.
// So we did a hack here: Disable the automatic background painting. // So we make the viewport transparent by preventing its backround from being filled automatically.
// Then paint the background of the list view ourselves by hook into its paint event handling method with a event filter. // Then we paint desktop's background ourselves by using its paint event handling method.
listView_->viewport()->setAutoFillBackground(false); listView_->viewport()->setAutoFillBackground(false);
// NOTE: When XRnadR is in use, the all screens are actually combined to form a // NOTE: When XRnadR is in use, the all screens are actually combined to form a
@ -98,7 +105,8 @@ DesktopWindow::DesktopWindow(int screenNum):
loadItemPositions(); loadItemPositions();
Settings& settings = static_cast<Application* >(qApp)->settings(); Settings& settings = static_cast<Application* >(qApp)->settings();
model_ = Fm::CachedFolderModel::modelFromPath(Fm::Path::getDesktop()); auto desktopPath = Fm::FilePath::fromLocalPath(XdgDir::readDesktopDir().toStdString().c_str());
model_ = Fm::CachedFolderModel::modelFromPath(desktopPath);
folder_ = model_->folder(); folder_ = model_->folder();
proxyModel_ = new Fm::ProxyFolderModel(); proxyModel_ = new Fm::ProxyFolderModel();
@ -116,10 +124,6 @@ DesktopWindow::DesktopWindow(int screenNum):
connect(listView_, &QListView::indexesMoved, this, &DesktopWindow::onIndexesMoved); connect(listView_, &QListView::indexesMoved, this, &DesktopWindow::onIndexesMoved);
} }
// set our own delegate
delegate_ = new DesktopItemDelegate(listView_);
listView_->setItemDelegateForColumn(Fm::FolderModel::ColumnFileName, delegate_);
// remove frame // remove frame
listView_->setFrameShape(QFrame::NoFrame); listView_->setFrameShape(QFrame::NoFrame);
// inhibit scrollbars FIXME: this should be optional in the future // inhibit scrollbars FIXME: this should be optional in the future
@ -143,7 +147,7 @@ DesktopWindow::DesktopWindow(int screenNum):
connect(shortcut, &QShortcut::activated, this, &DesktopWindow::onPasteActivated); connect(shortcut, &QShortcut::activated, this, &DesktopWindow::onPasteActivated);
shortcut = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_A), this); // select all shortcut = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_A), this); // select all
connect(shortcut, &QShortcut::activated, listView_, &QListView::selectAll); connect(shortcut, &QShortcut::activated, this, &FolderView::selectAll);
shortcut = new QShortcut(QKeySequence(Qt::Key_Delete), this); // delete shortcut = new QShortcut(QKeySequence(Qt::Key_Delete), this); // delete
connect(shortcut, &QShortcut::activated, this, &DesktopWindow::onDeleteActivated); connect(shortcut, &QShortcut::activated, this, &DesktopWindow::onDeleteActivated);
@ -162,15 +166,24 @@ DesktopWindow::~DesktopWindow() {
listView_->viewport()->removeEventFilter(this); listView_->viewport()->removeEventFilter(this);
listView_->removeEventFilter(this); listView_->removeEventFilter(this);
if(relayoutTimer_) if(relayoutTimer_) {
relayoutTimer_->stop();
delete relayoutTimer_; delete relayoutTimer_;
}
if(wallpaperTimer_) {
wallpaperTimer_->stop();
delete wallpaperTimer_;
}
if(proxyModel_) if(proxyModel_) {
delete proxyModel_; delete proxyModel_;
}
if(model_) if(model_) {
model_->unref(); model_->unref();
} }
}
void DesktopWindow::setBackground(const QColor& color) { void DesktopWindow::setBackground(const QColor& color) {
bgColor_ = color; bgColor_ = color;
@ -185,10 +198,12 @@ void DesktopWindow::setForeground(const QColor& color) {
void DesktopWindow::setShadow(const QColor& color) { void DesktopWindow::setShadow(const QColor& color) {
shadowColor_ = color; shadowColor_ = color;
delegate_->setShadowColor(color); auto delegate = static_cast<Fm::FolderItemDelegate*>(listView_->itemDelegateForColumn(Fm::FolderModel::ColumnFileName));
delegate->setShadowColor(color);
} }
void DesktopWindow::onOpenDirRequested(FmPath* path, int target) { void DesktopWindow::onOpenDirRequested(const Fm::FilePath& path, int target) {
Q_UNUSED(target);
// open in new window unconditionally. // open in new window unconditionally.
Application* app = static_cast<Application*>(qApp); Application* app = static_cast<Application*>(qApp);
MainWindow* newWin = new MainWindow(path); MainWindow* newWin = new MainWindow(path);
@ -209,7 +224,7 @@ void DesktopWindow::resizeEvent(QResizeEvent* event) {
} }
void DesktopWindow::setDesktopFolder() { void DesktopWindow::setDesktopFolder() {
Fm::Path path = Fm::Path::newForPath(XdgDir::readDesktopDir().toStdString().c_str()); auto path = Fm::FilePath::fromLocalPath(XdgDir::readDesktopDir().toStdString().c_str());
model_ = Fm::CachedFolderModel::modelFromPath(path); model_ = Fm::CachedFolderModel::modelFromPath(path);
proxyModel_->setSourceModel(model_); proxyModel_->setSourceModel(model_);
} }
@ -222,6 +237,22 @@ 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) { QImage DesktopWindow::loadWallpaperFile(QSize requiredSize) {
// NOTE: for ease of programming, we only use the cache for the primary screen. // NOTE: for ease of programming, we only use the cache for the primary screen.
bool useCache = (screenNum_ == -1 || screenNum_ == 0); bool useCache = (screenNum_ == -1 || screenNum_ == 0);
@ -230,8 +261,9 @@ QImage DesktopWindow::loadWallpaperFile(QSize requiredSize) {
if(useCache) { if(useCache) {
// see if we have a scaled version cached on disk // see if we have a scaled version cached on disk
cacheFileName = QString::fromLocal8Bit(qgetenv("XDG_CACHE_HOME")); cacheFileName = QString::fromLocal8Bit(qgetenv("XDG_CACHE_HOME"));
if(cacheFileName.isEmpty()) if(cacheFileName.isEmpty()) {
cacheFileName = QDir::homePath() % QLatin1String("/.cache"); cacheFileName = QDir::homePath() % QLatin1String("/.cache");
}
Application* app = static_cast<Application*>(qApp); Application* app = static_cast<Application*>(qApp);
cacheFileName += QLatin1String("/pcmanfm-qt/") % app->profileName(); cacheFileName += QLatin1String("/pcmanfm-qt/") % app->profileName();
QDir().mkpath(cacheFileName); // ensure that the cache dir exists QDir().mkpath(cacheFileName); // ensure that the cache dir exists
@ -254,20 +286,22 @@ QImage DesktopWindow::loadWallpaperFile(QSize requiredSize) {
if(cachedSize == requiredSize) { // see if the cached wallpaper has the size we want if(cachedSize == requiredSize) { // see if the cached wallpaper has the size we want
QImage image = reader.read(); // return the loaded image QImage image = reader.read(); // return the loaded image
qDebug() << "origin" << origin; qDebug() << "origin" << origin;
if(origin == wallpaperFile_) if(origin == wallpaperFile_) {
return image; return image;
} }
} }
} }
} }
}
qDebug() << "no cached wallpaper. generate a new one!"; qDebug() << "no cached wallpaper. generate a new one!";
} }
// we don't have a cached scaled image, load the original file // we don't have a cached scaled image, load the original file
QImage image(wallpaperFile_); QImage image(wallpaperFile_);
qDebug() << "size of original image" << image.size(); qDebug() << "size of original image" << image.size();
if(image.isNull() || image.size() == requiredSize) // if the original size is what we want if(image.isNull() || image.size() == requiredSize) { // if the original size is what we want
return image; return image;
}
// scale the original image // scale the original image
QImage scaled = image.scaled(requiredSize.width(), requiredSize.height(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation); QImage scaled = image.scaled(requiredSize.width(), requiredSize.height(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
@ -281,10 +315,12 @@ QImage DesktopWindow::loadWallpaperFile(QSize requiredSize) {
// write the scaled cache image to disk // write the scaled cache image to disk
const char* format; // we keep jpg format for *.jpg files, and use png format for others. 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)) if(wallpaperFile_.endsWith(QLatin1String(".jpg"), Qt::CaseInsensitive) || wallpaperFile_.endsWith(QLatin1String(".jpeg"), Qt::CaseInsensitive)) {
format = "JPG"; format = "JPG";
else }
else {
format = "PNG"; format = "PNG";
}
scaled.save(cacheFileName, format); scaled.save(cacheFileName, format);
} }
qDebug() << "wallpaper cached saved to " << cacheFileName; qDebug() << "wallpaper cached saved to " << cacheFileName;
@ -300,7 +336,16 @@ void DesktopWindow::updateWallpaper() {
QImage image; QImage image;
if(wallpaperMode_ == WallpaperTile) { // use the original size if(wallpaperMode_ == WallpaperTile) { // use the original size
image = QImage(wallpaperFile_); image = QImage(wallpaperFile_);
pixmap = QPixmap::fromImage(image); // 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) { else if(wallpaperMode_ == WallpaperStretch) {
image = loadWallpaperFile(size()); image = loadWallpaperFile(size());
@ -333,10 +378,97 @@ void DesktopWindow::updateWallpaper() {
} }
} }
void DesktopWindow::updateFromSettings(Settings& settings) { bool DesktopWindow::pickWallpaper() {
if(slideShowInterval_ <= 0
|| !QFileInfo(wallpaperDir_).isDir()) {
return false;
}
QList<QByteArray> 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<Application*>(qApp)->settings();
settings.setLastSlide(lastSlide_);
return true;
}
}
return false;
}
void DesktopWindow::nextWallpaper() {
if(pickWallpaper()) {
updateWallpaper();
update();
}
}
void DesktopWindow::updateFromSettings(Settings& settings, bool changeSlide) {
setDesktopFolder(); setDesktopFolder();
setWallpaperFile(settings.wallpaper()); setWallpaperFile(settings.wallpaper());
setWallpaperMode(settings.wallpaperMode()); 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()); setFont(settings.desktopFont());
setIconSize(Fm::FolderView::IconMode, QSize(settings.desktopIconSize(), settings.desktopIconSize())); setIconSize(Fm::FolderView::IconMode, QSize(settings.desktopIconSize(), settings.desktopIconSize()));
setMargins(settings.desktopCellMargins()); setMargins(settings.desktopCellMargins());
@ -346,13 +478,44 @@ void DesktopWindow::updateFromSettings(Settings& settings) {
setBackground(settings.desktopBgColor()); setBackground(settings.desktopBgColor());
setShadow(settings.desktopShadowColor()); setShadow(settings.desktopShadowColor());
showWmMenu_ = settings.showWmMenu(); 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(); updateWallpaper();
update(); update();
if(wallpaperTimer_) {
wallpaperTimer_->start(slideShowInterval_);
}
} }
void DesktopWindow::onFileClicked(int type, FmFileInfo* fileInfo) { void DesktopWindow::onFileClicked(int type, const std::shared_ptr<const Fm::FileInfo>& fileInfo) {
if(!fileInfo && showWmMenu_) if(!fileInfo && showWmMenu_) {
return; // do not show the popup if we want to use the desktop menu provided by the WM. return; // do not show the popup if we want to use the desktop menu provided by the WM.
}
View::onFileClicked(type, fileInfo); View::onFileClicked(type, fileInfo);
} }
@ -364,15 +527,15 @@ void DesktopWindow::prepareFileMenu(Fm::FileMenu* menu) {
menu->insertSeparator(menu->separator2()); menu->insertSeparator(menu->separator2());
menu->insertAction(menu->separator2(), action); menu->insertAction(menu->separator2(), action);
Fm::FileInfoList files = menu->files(); bool checked(true);
// select exactly one item auto files = menu->files();
if(fm_file_info_list_get_length(files) == 1) { for(const auto& file : files) {
Fm::FileInfo file = menu->firstFile(); if(customItemPos_.find(file->name()) == customItemPos_.cend()) {
if(customItemPos_.find(file.getName()) != customItemPos_.end()) { checked = false;
// the file item has a custom position break;
action->setChecked(true);
} }
} }
action->setChecked(checked);
connect(action, &QAction::toggled, this, &DesktopWindow::onStickToCurrentPos); connect(action, &QAction::toggled, this, &DesktopWindow::onStickToCurrentPos);
} }
@ -390,31 +553,42 @@ void DesktopWindow::onDesktopPreferences() {
} }
void DesktopWindow::onRowsInserted(const QModelIndex& parent, int start, int end) { 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) { void DesktopWindow::onRowsAboutToBeRemoved(const QModelIndex& parent, int start, int end) {
Q_UNUSED(parent); Q_UNUSED(parent);
Q_UNUSED(start); Q_UNUSED(start);
Q_UNUSED(end); Q_UNUSED(end);
if(!customItemPos_.isEmpty()) { if(!customItemPos_.empty()) {
// also delete stored custom item positions for the items currently being removed. // also delete stored custom item positions for the items currently being removed.
// Here we can't rely on ProxyFolderModel::fileInfoFromIndex() because, although rows // Here we can't rely on ProxyFolderModel::fileInfoFromIndex() because, although rows
// aren't removed yet, files are already removed. // aren't removed yet, files are already removed.
QHash<QByteArray, QPoint> _customItemPos = customItemPos_; bool changed = false;
char* dektopPath = Fm::Path::getDesktop().toStr(); char* dektopPath = Fm::Path::getDesktop().toStr();
QString desktopDir = QString(dektopPath) + QString("/"); QString desktopDir = QString(dektopPath) + QString("/");
g_free(dektopPath); g_free(dektopPath);
QHash<QByteArray, QPoint>::iterator it; for(auto it = customItemPos_.cbegin(); it != customItemPos_.cend();) {
for(it = _customItemPos.begin(); it != _customItemPos.end(); ++it) { auto& name = it->first;
const QByteArray& name = it.key(); if(!QFile::exists(desktopDir + QString::fromStdString(name))) {
if(!QFile::exists(desktopDir + QString::fromUtf8(name, name.length()))) it = customItemPos_.erase(it);
customItemPos_.remove(it.key()); changed = true;
}
else {
++it;
}
} }
if(customItemPos_ != _customItemPos) if(changed) {
saveItemPositions(); saveItemPositions();
} }
queueRelayout(); }
listView_->setUpdatesEnabled(false);
queueRelayout(100);
} }
void DesktopWindow::onLayoutChanged() { void DesktopWindow::onLayoutChanged() {
@ -440,8 +614,8 @@ void DesktopWindow::onDataChanged(const QModelIndex& topLeft, const QModelIndex&
for(int i = topLeft.row(); i <= bottomRight.row(); ++i) { for(int i = topLeft.row(); i <= bottomRight.row(); ++i) {
QModelIndex index = topLeft.sibling(i, 0); QModelIndex index = topLeft.sibling(i, 0);
if(index.isValid() && displayNames_.contains(index)) { if(index.isValid() && displayNames_.contains(index)) {
Fm::FileInfo file = proxyModel_->fileInfoFromIndex(index); auto file = proxyModel_->fileInfoFromIndex(index);
if(displayNames_[index] != file.getDispName()) { if(displayNames_[index] != file->displayName()) {
relayout = true; relayout = true;
break; break;
} }
@ -456,6 +630,8 @@ void DesktopWindow::onDataChanged(const QModelIndex& topLeft, const QModelIndex&
} }
void DesktopWindow::onIndexesMoved(const QModelIndexList& indexes) { void DesktopWindow::onIndexesMoved(const QModelIndexList& indexes) {
auto delegate = static_cast<Fm::FolderItemDelegate*>(listView_->itemDelegateForColumn(0));
auto itemSize = delegate->itemSize();
// remember the custom position for the items // remember the custom position for the items
Q_FOREACH(const QModelIndex& index, indexes) { Q_FOREACH(const QModelIndex& index, indexes) {
// Under some circumstances, Qt might emit indexMoved for // Under some circumstances, Qt might emit indexMoved for
@ -464,17 +640,22 @@ void DesktopWindow::onIndexesMoved(const QModelIndexList& indexes) {
// Since we only care about rows, not individual cells, // Since we only care about rows, not individual cells,
// let's handle column 0 of every row here. // let's handle column 0 of every row here.
if(index.column() == 0) { if(index.column() == 0) {
Fm::FileInfo file = proxyModel_->fileInfoFromIndex(index); auto file = proxyModel_->fileInfoFromIndex(index);
QRect itemRect = listView_->rectForIndex(index); QRect itemRect = listView_->rectForIndex(index);
QPoint tl = itemRect.topLeft(); QPoint tl = itemRect.topLeft();
QRect workArea = qApp->desktop()->availableGeometry(screenNum_); QRect workArea = qApp->desktop()->availableGeometry(screenNum_);
workArea.adjust(12, 12, -12, -12); workArea.adjust(12, 12, -12, -12);
if(customItemPos_.keys(tl).isEmpty() // don't put items on each other
// check if the position is occupied by another item
auto existingItem = std::find_if(customItemPos_.cbegin(), customItemPos_.cend(), [tl](const std::pair<std::string, QPoint>& 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() >= workArea.x() && tl.y() >= workArea.y()
&& tl.x() + listView_->gridSize().width() <= workArea.right() + 1 // for historical reasons (-> Qt doc) && tl.x() + itemSize.width() <= workArea.right() + 1 // for historical reasons (-> Qt doc)
&& tl.y() + listView_->gridSize().height() <= workArea.bottom() + 1) { // as above && tl.y() + itemSize.height() <= workArea.bottom() + 1) { // as above
QByteArray name = file.getName(); customItemPos_[file->name()] = tl;
customItemPos_[name] = tl;
// qDebug() << "indexMoved:" << name << index << itemRect; // qDebug() << "indexMoved:" << name << index << itemRect;
} }
} }
@ -490,10 +671,13 @@ void DesktopWindow::removeBottomGap() {
the vertical cell margin to prevent relatively large gaps the vertical cell margin to prevent relatively large gaps
from taking shape at the desktop bottom. from taking shape at the desktop bottom.
************************************************************/ ************************************************************/
auto delegate = static_cast<Fm::FolderItemDelegate*>(listView_->itemDelegateForColumn(0));
auto itemSize = delegate->itemSize();
qDebug() << "delegate:" << delegate->itemSize();
QSize cellMargins = getMargins(); QSize cellMargins = getMargins();
int workAreaHeight = qApp->desktop()->availableGeometry(screenNum_).height() int workAreaHeight = qApp->desktop()->availableGeometry(screenNum_).height()
- 24; // a 12-pix margin will be considered everywhere - 24; // a 12-pix margin will be considered everywhere
int cellHeight = listView_->gridSize().height() + listView_->spacing(); int cellHeight = itemSize.height() + listView_->spacing();
int iconNumber = workAreaHeight / cellHeight; int iconNumber = workAreaHeight / cellHeight;
int bottomGap = workAreaHeight % cellHeight; int bottomGap = workAreaHeight % cellHeight;
/******************************************* /*******************************************
@ -516,10 +700,11 @@ void DesktopWindow::removeBottomGap() {
/*************************************************** /***************************************************
... but if that can't be done, try to spread icons! ... but if that can't be done, try to spread icons!
***************************************************/ ***************************************************/
else else {
cellMargins += QSize(0, (bottomGap / iconNumber) / 2); cellMargins += QSize(0, (bottomGap / iconNumber) / 2);
}
// set the new margins (if they're changed) // set the new margins (if they're changed)
delegate_->setMargins(cellMargins); delegate->setMargins(cellMargins);
setMargins(cellMargins); setMargins(cellMargins);
// in case the text shadow is reset to (0,0,0,0) // in case the text shadow is reset to (0,0,0,0)
setShadow(settings.desktopShadowColor()); setShadow(settings.desktopShadowColor());
@ -528,8 +713,7 @@ void DesktopWindow::removeBottomGap() {
void DesktopWindow::paintBackground(QPaintEvent* event) { void DesktopWindow::paintBackground(QPaintEvent* event) {
// This is to workaround Qt bug 54384 which affects Qt >= 5.6 // This is to workaround Qt bug 54384 which affects Qt >= 5.6
// https://bugreports.qt.io/browse/QTBUG-54384 // 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(this);
QPainter painter(listView_->viewport()); // the painter paints on the viewport widget, not the QListView.
if(wallpaperMode_ == WallpaperNone || wallpaperPixmap_.isNull()) { if(wallpaperMode_ == WallpaperNone || wallpaperPixmap_.isNull()) {
painter.fillRect(event->rect(), QBrush(bgColor_)); painter.fillRect(event->rect(), QBrush(bgColor_));
} }
@ -547,47 +731,53 @@ void DesktopWindow::relayoutItems() {
if(relayoutTimer_) { if(relayoutTimer_) {
// this slot might be called from the timer, so we cannot delete it directly here. // this slot might be called from the timer, so we cannot delete it directly here.
relayoutTimer_->deleteLater(); relayoutTimer_->deleteLater();
relayoutTimer_ = NULL; relayoutTimer_ = nullptr;
} }
QDesktopWidget* desktop = qApp->desktop(); QDesktopWidget* desktop = qApp->desktop();
int screen = 0; int screen = 0;
int row = 0; int row = 0;
int rowCount = proxyModel_->rowCount(); int rowCount = proxyModel_->rowCount();
auto delegate = static_cast<Fm::FolderItemDelegate*>(listView_->itemDelegateForColumn(0));
auto itemSize = delegate->itemSize();
for(;;) { for(;;) {
if(desktop->isVirtualDesktop()) { if(desktop->isVirtualDesktop()) {
if(screen >= desktop->numScreens()) if(screen >= desktop->numScreens()) {
break; break;
}else { }
}
else {
screen = screenNum_; screen = screenNum_;
} }
QRect workArea = desktop->availableGeometry(screen); QRect workArea = desktop->availableGeometry(screen);
workArea.adjust(12, 12, -12, -12); // add a 12 pixel margin to the work area workArea.adjust(12, 12, -12, -12); // add a 12 pixel margin to the work area
// qDebug() << "workArea" << screen << workArea; // qDebug() << "workArea" << screen << workArea;
// FIXME: we use an internal class declared in a private header here, which is pretty bad. // FIXME: we use an internal class declared in a private header here, which is pretty bad.
QSize grid = listView_->gridSize();
QPoint pos = workArea.topLeft(); QPoint pos = workArea.topLeft();
for(; row < rowCount; ++row) { for(; row < rowCount; ++row) {
QModelIndex index = proxyModel_->index(row, 0); QModelIndex index = proxyModel_->index(row, 0);
int itemWidth = delegate_->sizeHint(listView_->getViewOptions(), index).width(); int itemWidth = delegate->sizeHint(listView_->getViewOptions(), index).width();
Fm::FileInfo file = proxyModel_->fileInfoFromIndex(index); auto file = proxyModel_->fileInfoFromIndex(index);
// remember display names of desktop entries and shortcuts // remember display names of desktop entries and shortcuts
if(file.isDesktopEntry() || file.isShortcut()) if(file->isDesktopEntry() || file->isShortcut()) {
displayNames_[index] = QString(file.getDispName()); displayNames_[index] = file->displayName();
QByteArray name = file.getName(); }
QHash<QByteArray, QPoint>::iterator it = customItemPos_.find(name); auto name = file->name();
if(it != customItemPos_.end()) { // the item has a custom position auto find_it = customItemPos_.find(name);
QPoint customPos = *it; if(find_it != customItemPos_.cend()) { // the item has a custom position
QPoint customPos = find_it->second;
// center the contents vertically // center the contents vertically
listView_->setPositionForIndex(customPos + QPoint((grid.width() - itemWidth) / 2, 0), index); listView_->setPositionForIndex(customPos + QPoint((itemSize.width() - itemWidth) / 2, 0), index);
// qDebug() << "set custom pos:" << name << row << index << customPos; // qDebug() << "set custom pos:" << name << row << index << customPos;
continue; continue;
} }
// check if the current pos is alredy occupied by a custom item // check if the current pos is alredy occupied by a custom item
bool used = false; bool used = false;
for(it = customItemPos_.begin(); it != customItemPos_.end(); ++it) { for(auto it = customItemPos_.cbegin(); it != customItemPos_.cend(); ++it) {
QPoint customPos = *it; QPoint customPos = it->second;
if(QRect(customPos, grid).contains(pos)) { if(QRect(customPos, itemSize).contains(pos)) {
used = true; used = true;
break; break;
} }
@ -597,18 +787,18 @@ void DesktopWindow::relayoutItems() {
} }
else { else {
// center the contents vertically // center the contents vertically
listView_->setPositionForIndex(pos + QPoint((grid.width() - itemWidth) / 2, 0), index); listView_->setPositionForIndex(pos + QPoint((itemSize.width() - itemWidth) / 2, 0), index);
// qDebug() << "set pos" << name << row << index << pos; // qDebug() << "set pos" << name << row << index << pos;
} }
// move to next cell in the column // move to next cell in the column
pos.setY(pos.y() + grid.height() + listView_->spacing()); pos.setY(pos.y() + itemSize.height() + listView_->spacing());
if(pos.y() + grid.height() > workArea.bottom() + 1) { 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 // 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.setX(pos.x() + itemSize.width() + listView_->spacing());
pos.setY(workArea.top()); pos.setY(workArea.top());
// check if the new column exceeds the right margin of work area // check if the new column exceeds the right margin of work area
if(pos.x() + grid.width() > workArea.right() + 1) { if(pos.x() + itemSize.width() > workArea.right() + 1) {
if(desktop->isVirtualDesktop()) { if(desktop->isVirtualDesktop()) {
// in virtual desktop mode, go to next screen // in virtual desktop mode, go to next screen
++screen; ++screen;
@ -617,23 +807,37 @@ void DesktopWindow::relayoutItems() {
} }
} }
} }
if(row >= rowCount) if(row >= rowCount) {
break; break;
} }
} }
if(!listView_->updatesEnabled()) {
listView_->setUpdatesEnabled(true);
}
}
void DesktopWindow::loadItemPositions() { void DesktopWindow::loadItemPositions() {
// load custom item positions // load custom item positions
customItemPos_.clear(); customItemPos_.clear();
Settings& settings = static_cast<Application*>(qApp)->settings(); Settings& settings = static_cast<Application*>(qApp)->settings();
QString configFile = QString("%1/desktop-items-%2.conf").arg(settings.profileDir(settings.profileName())).arg(screenNum_); QString configFile = QString("%1/desktop-items-%2.conf").arg(settings.profileDir(settings.profileName())).arg(screenNum_);
QSettings file(configFile, QSettings::IniFormat); QSettings file(configFile, QSettings::IniFormat);
QSize grid = listView_->gridSize();
auto delegate = static_cast<Fm::FolderItemDelegate*>(listView_->itemDelegateForColumn(0));
auto grid = delegate->itemSize();
QRect workArea = qApp->desktop()->availableGeometry(screenNum_); QRect workArea = qApp->desktop()->availableGeometry(screenNum_);
workArea.adjust(12, 12, -12, -12); workArea.adjust(12, 12, -12, -12);
char* dektopPath = Fm::Path::getDesktop().toStr(); char* dektopPath = Fm::Path::getDesktop().toStr();
QString desktopDir = QString(dektopPath) + QString("/"); QString desktopDir = QString(dektopPath) + QString("/");
g_free(dektopPath); g_free(dektopPath);
std::vector<QPoint> usedPos;
for(auto& item: customItemPos_) {
usedPos.push_back(item.second);
}
// FIXME: this is inefficient
Q_FOREACH(const QString& name, file.childGroups()) { Q_FOREACH(const QString& name, file.childGroups()) {
if(!QFile::exists(desktopDir + name.toUtf8())) { if(!QFile::exists(desktopDir + name.toUtf8())) {
// the file may have been removed from outside LXQT // the file may have been removed from outside LXQT
@ -644,24 +848,20 @@ void DesktopWindow::loadItemPositions() {
if(var.isValid()) { if(var.isValid()) {
QPoint customPos = var.toPoint(); QPoint customPos = var.toPoint();
if(customPos.x() >= workArea.x() && customPos.y() >= workArea.y() if(customPos.x() >= workArea.x() && customPos.y() >= workArea.y()
&& customPos.x() + listView_->gridSize().width() <= workArea.right() + 1 && customPos.x() + grid.width() <= workArea.right() + 1
&& customPos.y() + listView_->gridSize().height() <= workArea.bottom() + 1) && customPos.y() + grid.height() <= workArea.bottom() + 1) {
{
// correct positions that are't aligned to the grid // correct positions that are't aligned to the grid
qreal w = qAbs((qreal)customPos.x() - (qreal)workArea.x()) alignToGrid(customPos, workArea.topLeft(), grid, listView_->spacing());
/ (qreal)(grid.width() + listView_->spacing()); // FIXME: this is very inefficient
qreal h = qAbs(customPos.y() - (qreal)workArea.y()) while(std::find(usedPos.cbegin(), usedPos.cend(), customPos) != usedPos.cend()) {
/ (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()); customPos.setY(customPos.y() + grid.height() + listView_->spacing());
if(customPos.y() + grid.height() > workArea.bottom() + 1) { if(customPos.y() + grid.height() > workArea.bottom() + 1) {
customPos.setX(customPos.x() + grid.width() + listView_->spacing()); customPos.setX(customPos.x() + grid.width() + listView_->spacing());
customPos.setY(workArea.top()); customPos.setY(workArea.top());
} }
} }
customItemPos_[name.toUtf8()] = customPos; customItemPos_[name.toStdString()] = customPos;
usedPos.push_back(customPos);
} }
} }
file.endGroup(); file.endGroup();
@ -677,40 +877,41 @@ void DesktopWindow::saveItemPositions() {
file.clear(); // remove all existing entries file.clear(); // remove all existing entries
// FIXME: we have to remove dead entries not associated to any files? // FIXME: we have to remove dead entries not associated to any files?
QHash<QByteArray, QPoint>::iterator it; for(auto it = customItemPos_.cbegin(); it != customItemPos_.cend(); ++it) {
for(it = customItemPos_.begin(); it != customItemPos_.end(); ++it) { auto& name = it->first;
const QByteArray& name = it.key(); auto& pos = it->second;
QPoint pos = it.value(); file.beginGroup(QString::fromStdString(name));
file.beginGroup(QString::fromUtf8(name, name.length()));
file.setValue("pos", pos); file.setValue("pos", pos);
file.endGroup(); file.endGroup();
} }
} }
void DesktopWindow::onStickToCurrentPos(bool toggled) { void DesktopWindow::onStickToCurrentPos(bool toggled) {
QAction* action = static_cast<QAction*>(sender());
Fm::FileMenu* menu = static_cast<Fm::FileMenu*>(action->parent());
QModelIndexList indexes = listView_->selectionModel()->selectedIndexes(); QModelIndexList indexes = listView_->selectionModel()->selectedIndexes();
if(!indexes.isEmpty()) { if(!indexes.isEmpty()) {
Fm::FileInfo file = menu->firstFile(); bool relayout(false);
QByteArray name = file.getName(); QModelIndexList::const_iterator it;
QModelIndex index = indexes.first(); for(it = indexes.constBegin(); it != indexes.constEnd(); ++it) {
if(toggled) { // remember to current custom position auto file = proxyModel_->fileInfoFromIndex(*it);
QRect itemRect = listView_->rectForIndex(index); auto name = file->name();
if(toggled) { // remember the current custom position
QRect itemRect = listView_->rectForIndex(*it);
customItemPos_[name] = itemRect.topLeft(); customItemPos_[name] = itemRect.topLeft();
saveItemPositions();
} }
else { // cancel custom position and perform relayout else { // cancel custom position and perform relayout
QHash<QByteArray, QPoint>::iterator it = customItemPos_.find(name); auto item = customItemPos_.find(name);
if(it != customItemPos_.end()) { if(item != customItemPos_.end()) {
customItemPos_.erase(it); customItemPos_.erase(item);
relayout = true;
}
}
}
saveItemPositions(); saveItemPositions();
if(relayout) {
relayoutItems(); relayoutItems();
} }
} }
} }
}
void DesktopWindow::queueRelayout(int delay) { void DesktopWindow::queueRelayout(int delay) {
// qDebug() << "queueRelayout"; // qDebug() << "queueRelayout";
@ -726,15 +927,15 @@ void DesktopWindow::queueRelayout(int delay) {
// slots for file operations // slots for file operations
void DesktopWindow::onCutActivated() { void DesktopWindow::onCutActivated() {
Fm::PathList paths = selectedFilePaths(); auto paths = selectedFilePaths();
if(!paths.isNull()) { if(!paths.empty()) {
Fm::cutFilesToClipboard(paths); Fm::cutFilesToClipboard(paths);
} }
} }
void DesktopWindow::onCopyActivated() { void DesktopWindow::onCopyActivated() {
Fm::PathList paths = selectedFilePaths(); auto paths = selectedFilePaths();
if(!paths.isNull()) { if(!paths.empty()) {
Fm::copyFilesToClipboard(paths); Fm::copyFilesToClipboard(paths);
} }
} }
@ -744,31 +945,41 @@ void DesktopWindow::onPasteActivated() {
} }
void DesktopWindow::onDeleteActivated() { void DesktopWindow::onDeleteActivated() {
Fm::PathList paths = selectedFilePaths(); auto paths = selectedFilePaths();
if(!paths.isNull()) { if(!paths.empty()) {
Settings& settings = static_cast<Application*>(qApp)->settings(); Settings& settings = static_cast<Application*>(qApp)->settings();
bool shiftPressed = (qApp->keyboardModifiers() & Qt::ShiftModifier ? true : false); bool shiftPressed = (qApp->keyboardModifiers() & Qt::ShiftModifier ? true : false);
if(settings.useTrash() && !shiftPressed) if(settings.useTrash() && !shiftPressed) {
Fm::FileOperation::trashFiles(paths, settings.confirmTrash()); Fm::FileOperation::trashFiles(paths, settings.confirmTrash());
else }
else {
Fm::FileOperation::deleteFiles(paths, settings.confirmDelete()); Fm::FileOperation::deleteFiles(paths, settings.confirmDelete());
} }
} }
}
void DesktopWindow::onRenameActivated() { void DesktopWindow::onRenameActivated() {
Fm::FileInfoList files = selectedFiles(); // do inline renaming if only one item is selected,
if(!files.isNull()) { // otherwise use the renaming dialog
for(GList* l = fm_file_info_list_peek_head_link(files); l; l = l->next) { if(selectedIndexes().size() == 1) {
FmFileInfo* info = FM_FILE_INFO(l->data); QModelIndex cur = listView_->currentIndex();
Fm::renameFile(info, NULL); if (cur.isValid()) {
listView_->edit(cur);
return;
}
}
auto files = selectedFiles();
if(!files.empty()) {
for(auto& info: files) {
Fm::renameFile(info, nullptr);
} }
} }
} }
void DesktopWindow::onFilePropertiesActivated() { void DesktopWindow::onFilePropertiesActivated() {
Fm::FileInfoList files = selectedFiles(); auto files = selectedFiles();
if(!files.isNull()) { if(!files.empty()) {
Fm::FilePropsDialog::showForFiles(files); Fm::FilePropsDialog::showForFiles(std::move(files));
} }
} }
@ -810,12 +1021,15 @@ static void forwardMouseEventToRoot(QMouseEvent* event) {
} }
// convert Qt modifiers to XCB states // convert Qt modifiers to XCB states
if(event->modifiers() & Qt::ShiftModifier) if(event->modifiers() & Qt::ShiftModifier) {
xcb_event.state |= XCB_MOD_MASK_SHIFT; xcb_event.state |= XCB_MOD_MASK_SHIFT;
if(event->modifiers() & Qt::ControlModifier) }
if(event->modifiers() & Qt::ControlModifier) {
xcb_event.state |= XCB_MOD_MASK_SHIFT; xcb_event.state |= XCB_MOD_MASK_SHIFT;
if(event->modifiers() & Qt::AltModifier) }
if(event->modifiers() & Qt::AltModifier) {
xcb_event.state |= XCB_MOD_MASK_1; xcb_event.state |= XCB_MOD_MASK_1;
}
xcb_event.sequence = 0; xcb_event.sequence = 0;
xcb_event.time = event->timestamp(); xcb_event.time = event->timestamp();
@ -835,20 +1049,20 @@ static void forwardMouseEventToRoot(QMouseEvent* event) {
xcb_flush(QX11Info::connection()); xcb_flush(QX11Info::connection());
} }
bool DesktopWindow::event(QEvent* event) bool DesktopWindow::event(QEvent* event) {
{
switch(event->type()) { switch(event->type()) {
case QEvent::WinIdChange: { case QEvent::WinIdChange: {
qDebug() << "winid change:" << effectiveWinId(); qDebug() << "winid change:" << effectiveWinId();
if(effectiveWinId() == 0) if(effectiveWinId() == 0) {
break; break;
}
// set freedesktop.org EWMH hints properly // set freedesktop.org EWMH hints properly
if(QX11Info::isPlatformX11() && QX11Info::connection()) { if(QX11Info::isPlatformX11() && QX11Info::connection()) {
xcb_connection_t* con = QX11Info::connection(); xcb_connection_t* con = QX11Info::connection();
const char* atom_name = "_NET_WM_WINDOW_TYPE_DESKTOP"; 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; 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"; 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 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_atom_t XA_ATOM = 4;
xcb_change_property(con, XCB_PROP_MODE_REPLACE, effectiveWinId(), prop_atom, XA_ATOM, 32, 1, &atom); xcb_change_property(con, XCB_PROP_MODE_REPLACE, effectiveWinId(), prop_atom, XA_ATOM, 32, 1, &atom);
} }
@ -874,8 +1088,9 @@ bool DesktopWindow::eventFilter(QObject * watched, QEvent * event) {
switch(event->type()) { switch(event->type()) {
case QEvent::StyleChange: case QEvent::StyleChange:
case QEvent::FontChange: case QEvent::FontChange:
if(model_) if(model_) {
queueRelayout(); queueRelayout();
}
break; break;
default: default:
break; break;
@ -883,10 +1098,6 @@ bool DesktopWindow::eventFilter(QObject * watched, QEvent * event) {
} }
else if(watched == listView_->viewport()) { else if(watched == listView_->viewport()) {
switch(event->type()) { switch(event->type()) {
case QEvent::Paint: {
paintBackground(static_cast<QPaintEvent*>(event));
break;
}
case QEvent::MouseButtonPress: case QEvent::MouseButtonPress:
case QEvent::MouseButtonRelease: case QEvent::MouseButtonRelease:
if(showWmMenu_) { if(showWmMenu_) {
@ -904,15 +1115,15 @@ bool DesktopWindow::eventFilter(QObject * watched, QEvent * event) {
break; break;
} }
} }
return false; return Fm::FolderView::eventFilter(watched, event);
} }
void DesktopWindow::childDropEvent(QDropEvent* e) { void DesktopWindow::childDropEvent(QDropEvent* e) {
const QMimeData* mimeData = e->mimeData();
bool moveItem = false; bool moveItem = false;
if(e->source() == listView_ && e->keyboardModifiers() == Qt::NoModifier) { if(e->source() == listView_ && e->keyboardModifiers() == Qt::NoModifier) {
// drag source is our list view, and no other modifier keys are pressed // drag source is our list view, and no other modifier keys are pressed
// => we're dragging desktop items // => we're dragging desktop items
const QMimeData *mimeData = e->mimeData();
if(mimeData->hasFormat("application/x-qabstractitemmodeldatalist")) { if(mimeData->hasFormat("application/x-qabstractitemmodeldatalist")) {
QModelIndex dropIndex = listView_->indexAt(e->pos()); QModelIndex dropIndex = listView_->indexAt(e->pos());
if(dropIndex.isValid()) { // drop on an item if(dropIndex.isValid()) { // drop on an item
@ -926,10 +1137,50 @@ void DesktopWindow::childDropEvent(QDropEvent* e) {
} }
} }
} }
if(moveItem) if(moveItem) {
e->accept(); e->accept();
else }
else {
auto delegate = static_cast<Fm::FolderItemDelegate*>(listView_->itemDelegateForColumn(0));
auto grid = delegate->itemSize();
Fm::FolderView::childDropEvent(e); 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<QUrl> 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) { void DesktopWindow::closeEvent(QCloseEvent* event) {
@ -937,6 +1188,11 @@ void DesktopWindow::closeEvent(QCloseEvent *event) {
event->ignore(); event->ignore();
} }
void DesktopWindow::paintEvent(QPaintEvent *event) {
paintBackground(event);
QWidget::paintEvent(event);
}
void DesktopWindow::setScreenNum(int num) { void DesktopWindow::setScreenNum(int num) {
if(screenNum_ != num) { if(screenNum_ != num) {
screenNum_ = num; screenNum_ = num;

@ -23,11 +23,14 @@
#include "view.h" #include "view.h"
#include "launcher.h" #include "launcher.h"
#include <unordered_map>
#include <string>
#include <QHash> #include <QHash>
#include <QPoint> #include <QPoint>
#include <QByteArray> #include <QByteArray>
#include <xcb/xcb.h> #include <xcb/xcb.h>
#include <libfm-qt/folder.h> #include <libfm-qt/core/folder.h>
namespace Fm { namespace Fm {
class CachedFolderModel; class CachedFolderModel;
@ -37,7 +40,6 @@ namespace Fm {
namespace PCManFM { namespace PCManFM {
class DesktopItemDelegate;
class Settings; class Settings;
class DesktopWindow : public View { class DesktopWindow : public View {
@ -63,10 +65,16 @@ public:
void setDesktopFolder(); void setDesktopFolder();
void setWallpaperFile(QString filename); void setWallpaperFile(QString filename);
void setWallpaperMode(WallpaperMode mode = WallpaperStretch); 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 setWallpaperAlpha(qreal alpha);
void updateWallpaper(); void updateWallpaper();
void updateFromSettings(Settings& settings); bool pickWallpaper();
void nextWallpaper();
void updateFromSettings(Settings& settings, bool changeSlide = true);
void queueRelayout(int delay = 0); void queueRelayout(int delay = 0);
@ -77,24 +85,25 @@ public:
void setScreenNum(int num); void setScreenNum(int num);
protected: protected:
virtual void prepareFolderMenu(Fm::FolderMenu* menu); virtual void prepareFolderMenu(Fm::FolderMenu* menu) override;
virtual void prepareFileMenu(Fm::FileMenu* menu); virtual void prepareFileMenu(Fm::FileMenu* menu) override;
virtual void resizeEvent(QResizeEvent* event); virtual void resizeEvent(QResizeEvent* event) override;
virtual void onFileClicked(int type, FmFileInfo* fileInfo); virtual void onFileClicked(int type, const std::shared_ptr<const Fm::FileInfo>& fileInfo) override;
void loadItemPositions(); void loadItemPositions();
void saveItemPositions(); void saveItemPositions();
QImage loadWallpaperFile(QSize requiredSize); QImage loadWallpaperFile(QSize requiredSize);
virtual bool event(QEvent* event); virtual bool event(QEvent* event) override;
virtual bool eventFilter(QObject * watched, QEvent * event); virtual bool eventFilter(QObject* watched, QEvent* event) override;
virtual void childDropEvent(QDropEvent* e); virtual void childDropEvent(QDropEvent* e) override;
virtual void closeEvent(QCloseEvent *event); virtual void closeEvent(QCloseEvent* event) override;
virtual void paintEvent(QPaintEvent *event) override;
protected Q_SLOTS: protected Q_SLOTS:
void onOpenDirRequested(FmPath* path, int target); void onOpenDirRequested(const Fm::FilePath& path, int target);
void onDesktopPreferences(); void onDesktopPreferences();
void onRowsAboutToBeRemoved(const QModelIndex& parent, int start, int end); void onRowsAboutToBeRemoved(const QModelIndex& parent, int start, int end);
@ -120,11 +129,12 @@ protected Q_SLOTS:
private: private:
void removeBottomGap(); void removeBottomGap();
void paintBackground(QPaintEvent* event); void paintBackground(QPaintEvent* event);
static void alignToGrid(QPoint& pos, const QPoint& topLeft, const QSize& grid, const int spacing);
private: private:
Fm::ProxyFolderModel* proxyModel_; Fm::ProxyFolderModel* proxyModel_;
Fm::CachedFolderModel* model_; Fm::CachedFolderModel* model_;
Fm::Folder folder_; std::shared_ptr<Fm::Folder> folder_;
Fm::FolderViewListView* listView_; Fm::FolderViewListView* listView_;
QColor fgColor_; QColor fgColor_;
@ -132,13 +142,17 @@ private:
QColor shadowColor_; QColor shadowColor_;
QString wallpaperFile_; QString wallpaperFile_;
WallpaperMode wallpaperMode_; WallpaperMode wallpaperMode_;
QString lastSlide_;
QString wallpaperDir_;
int slideShowInterval_;
QTimer* wallpaperTimer_;
bool wallpaperRandomize_;
QPixmap wallpaperPixmap_; QPixmap wallpaperPixmap_;
DesktopItemDelegate* delegate_;
Launcher fileLauncher_; Launcher fileLauncher_;
bool showWmMenu_; bool showWmMenu_;
int screenNum_; int screenNum_;
QHash<QByteArray, QPoint> customItemPos_; std::unordered_map<std::string, QPoint> customItemPos_;
QHash<QModelIndex, QString> displayNames_; // only for desktop entries and shortcuts QHash<QModelIndex, QString> displayNames_; // only for desktop entries and shortcuts
QTimer* relayoutTimer_; QTimer* relayoutTimer_;
}; };

@ -1,517 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>FindFilesDialog</class>
<widget class="QDialog" name="FindFilesDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>431</width>
<height>416</height>
</rect>
</property>
<property name="windowTitle">
<string>Find Files</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QTabWidget" name="tabWidget">
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="tab">
<attribute name="title">
<string>Name/Location</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>File name patterns</string>
</property>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Pattern:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="lineEdit"/>
</item>
<item row="1" column="0" colspan="2">
<widget class="QCheckBox" name="checkBox">
<property name="text">
<string>Case insensitive</string>
</property>
</widget>
</item>
<item row="2" column="0" colspan="2">
<widget class="QCheckBox" name="checkBox_2">
<property name="text">
<string>Use regular expression</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_2">
<property name="title">
<string>Places to search</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QListWidget" name="listWidget"/>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QPushButton" name="pushButton">
<property name="text">
<string>Add</string>
</property>
<property name="icon">
<iconset theme="list-add">
<normaloff/>
</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton_2">
<property name="text">
<string>Remove</string>
</property>
<property name="icon">
<iconset theme="list-remove">
<normaloff/>
</iconset>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</item>
<item>
<widget class="QCheckBox" name="checkBox_3">
<property name="text">
<string>Search in sub directories</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBox_4">
<property name="text">
<string>Search hidden files</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="tab_2">
<attribute name="title">
<string>File Type</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_6">
<item>
<widget class="QGroupBox" name="groupBox_3">
<property name="title">
<string>File Type</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_5">
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>Only search for files of following types:</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBox_5">
<property name="text">
<string>Text files</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBox_6">
<property name="text">
<string>Image files</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBox_7">
<property name="text">
<string>Audio files</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBox_8">
<property name="text">
<string>Video files</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBox_9">
<property name="text">
<string>Documents</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<widget class="QWidget" name="tab_4">
<attribute name="title">
<string>Content</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_8">
<item>
<widget class="QGroupBox" name="groupBox_4">
<property name="title">
<string>File contains</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_7">
<item>
<widget class="QLineEdit" name="lineEdit_2"/>
</item>
<item>
<widget class="QCheckBox" name="checkBox_10">
<property name="text">
<string>Case insensitive</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBox_11">
<property name="text">
<string>Use regular expression</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<widget class="QWidget" name="tab_3">
<attribute name="title">
<string>Properties</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_9">
<item>
<widget class="QGroupBox" name="groupBox_5">
<property name="title">
<string>File Size</string>
</property>
<layout class="QFormLayout" name="formLayout_3">
<item row="0" column="0">
<widget class="QCheckBox" name="checkBox_12">
<property name="text">
<string>Bigger than:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QSpinBox" name="spinBox">
<property name="enabled">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="comboBox">
<property name="enabled">
<bool>false</bool>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="checkBox_13">
<property name="text">
<string>Smaller than:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QSpinBox" name="spinBox_2">
<property name="enabled">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="comboBox_2">
<property name="enabled">
<bool>false</bool>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_6">
<property name="title">
<string>Last Modified Time</string>
</property>
<layout class="QFormLayout" name="formLayout_2">
<item row="0" column="0">
<widget class="QCheckBox" name="checkBox_14">
<property name="text">
<string>Earlier than:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QDateTimeEdit" name="dateTimeEdit">
<property name="enabled">
<bool>false</bool>
</property>
<property name="calendarPopup">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="checkBox_15">
<property name="text">
<string>Later than:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QDateTimeEdit" name="dateTimeEdit_2">
<property name="enabled">
<bool>false</bool>
</property>
<property name="calendarPopup">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer_4">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>FindFilesDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>222</x>
<y>344</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>FindFilesDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>290</x>
<y>350</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>checkBox_14</sender>
<signal>toggled(bool)</signal>
<receiver>dateTimeEdit</receiver>
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>129</x>
<y>166</y>
</hint>
<hint type="destinationlabel">
<x>294</x>
<y>170</y>
</hint>
</hints>
</connection>
<connection>
<sender>checkBox_15</sender>
<signal>toggled(bool)</signal>
<receiver>dateTimeEdit_2</receiver>
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>91</x>
<y>188</y>
</hint>
<hint type="destinationlabel">
<x>302</x>
<y>195</y>
</hint>
</hints>
</connection>
<connection>
<sender>checkBox_12</sender>
<signal>toggled(bool)</signal>
<receiver>spinBox</receiver>
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>102</x>
<y>73</y>
</hint>
<hint type="destinationlabel">
<x>184</x>
<y>77</y>
</hint>
</hints>
</connection>
<connection>
<sender>checkBox_12</sender>
<signal>toggled(bool)</signal>
<receiver>comboBox</receiver>
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>49</x>
<y>72</y>
</hint>
<hint type="destinationlabel">
<x>357</x>
<y>76</y>
</hint>
</hints>
</connection>
<connection>
<sender>checkBox_13</sender>
<signal>toggled(bool)</signal>
<receiver>spinBox_2</receiver>
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>123</x>
<y>101</y>
</hint>
<hint type="destinationlabel">
<x>186</x>
<y>104</y>
</hint>
</hints>
</connection>
<connection>
<sender>checkBox_13</sender>
<signal>toggled(bool)</signal>
<receiver>comboBox_2</receiver>
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>53</x>
<y>98</y>
</hint>
<hint type="destinationlabel">
<x>339</x>
<y>108</y>
</hint>
</hints>
</connection>
</connections>
</ui>

@ -21,6 +21,7 @@
#include "launcher.h" #include "launcher.h"
#include "mainwindow.h" #include "mainwindow.h"
#include "application.h" #include "application.h"
#include <libfm-qt/core/filepath.h>
namespace PCManFM { namespace PCManFM {
@ -38,23 +39,26 @@ Launcher::~Launcher() {
bool Launcher::openFolder(GAppLaunchContext* ctx, GList* folder_infos, GError** err) { bool Launcher::openFolder(GAppLaunchContext* ctx, GList* folder_infos, GError** err) {
GList* l = folder_infos; GList* l = folder_infos;
Fm::FileInfo fi = FM_FILE_INFO(l->data); FmFileInfo* fi = FM_FILE_INFO(l->data);
Application* app = static_cast<Application*>(qApp); Application* app = static_cast<Application*>(qApp);
MainWindow* mainWindow = mainWindow_; MainWindow* mainWindow = mainWindow_;
Fm::FilePath path{fm_path_to_gfile(fm_file_info_get_path(fi)), false};
if(!mainWindow) { if(!mainWindow) {
mainWindow = new MainWindow(fi.getPath()); mainWindow = new MainWindow(std::move(path));
mainWindow->resize(app->settings().windowWidth(), app->settings().windowHeight()); mainWindow->resize(app->settings().windowWidth(), app->settings().windowHeight());
if(app->settings().windowMaximized()) { if(app->settings().windowMaximized()) {
mainWindow->setWindowState(mainWindow->windowState() | Qt::WindowMaximized); mainWindow->setWindowState(mainWindow->windowState() | Qt::WindowMaximized);
} }
} }
else else {
mainWindow->chdir(fi.getPath()); mainWindow->chdir(std::move(path));
}
l = l->next; l = l->next;
for(; l; l = l->next) { for(; l; l = l->next) {
fi = FM_FILE_INFO(l->data); fi = FM_FILE_INFO(l->data);
mainWindow->addTab(fi.getPath()); path = Fm::FilePath{fm_path_to_gfile(fm_file_info_get_path(fi)), false};
mainWindow->addTab(std::move(path));
} }
mainWindow->show(); mainWindow->show();
mainWindow->raise(); mainWindow->raise();

@ -29,7 +29,7 @@ class MainWindow;
class Launcher : public Fm::FileLauncher { class Launcher : public Fm::FileLauncher {
public: public:
Launcher(MainWindow* mainWindow = NULL); Launcher(MainWindow* mainWindow = nullptr);
~Launcher(); ~Launcher();
protected: protected:

@ -197,7 +197,7 @@
<addaction name="menuToolbars"/> <addaction name="menuToolbars"/>
<addaction name="menuPathBarStyle"/> <addaction name="menuPathBarStyle"/>
</widget> </widget>
<widget class="QMenu" name="menu_Editw"> <widget class="QMenu" name="menu_Edit">
<property name="title"> <property name="title">
<string>&amp;Edit</string> <string>&amp;Edit</string>
</property> </property>
@ -245,14 +245,14 @@
<addaction name="actionFindFiles"/> <addaction name="actionFindFiles"/>
</widget> </widget>
<addaction name="menu_File"/> <addaction name="menu_File"/>
<addaction name="menu_Editw"/> <addaction name="menu_Edit"/>
<addaction name="menu_View"/> <addaction name="menu_View"/>
<addaction name="menu_Go"/> <addaction name="menu_Go"/>
<addaction name="menu_Bookmarks"/> <addaction name="menu_Bookmarks"/>
<addaction name="menu_Tool"/> <addaction name="menu_Tool"/>
<addaction name="menu_Help"/> <addaction name="menu_Help"/>
</widget> </widget>
<widget class="QStatusBar" name="statusbar"/> <widget class="PCManFM::StatusBar" name="statusbar"/>
<widget class="QToolBar" name="toolBar"> <widget class="QToolBar" name="toolBar">
<property name="contextMenuPolicy"> <property name="contextMenuPolicy">
<enum>Qt::PreventContextMenu</enum> <enum>Qt::PreventContextMenu</enum>
@ -836,6 +836,12 @@
<header>tabbar.h</header> <header>tabbar.h</header>
<container>1</container> <container>1</container>
</customwidget> </customwidget>
<customwidget>
<class>PCManFM::StatusBar</class>
<extends>QStatusBar</extends>
<header>statusbar.h</header>
<container>1</container>
</customwidget>
<customwidget> <customwidget>
<class>Fm::SidePane</class> <class>Fm::SidePane</class>
<extends>QWidget</extends> <extends>QWidget</extends>

@ -29,8 +29,8 @@
#include <QToolButton> #include <QToolButton>
#include <QShortcut> #include <QShortcut>
#include <QKeySequence> #include <QKeySequence>
#include <QDir>
#include <QSettings> #include <QSettings>
#include <QStandardPaths>
#include <QDebug> #include <QDebug>
#include "tabpage.h" #include "tabpage.h"
@ -42,9 +42,7 @@
#include <libfm-qt/filepropsdialog.h> #include <libfm-qt/filepropsdialog.h>
#include <libfm-qt/pathedit.h> #include <libfm-qt/pathedit.h>
#include <libfm-qt/pathbar.h> #include <libfm-qt/pathbar.h>
#include <libfm-qt/path.h> #include <libfm-qt/core/fileinfo.h>
#include <libfm-qt/fileinfo.h>
#include <libfm-qt/folder.h>
#include "ui_about.h" #include "ui_about.h"
#include "application.h" #include "application.h"
@ -55,13 +53,14 @@ namespace PCManFM {
// static // static
MainWindow* MainWindow::lastActive_ = nullptr; MainWindow* MainWindow::lastActive_ = nullptr;
MainWindow::MainWindow(Path path): MainWindow::MainWindow(Fm::FilePath path):
QMainWindow(), QMainWindow(),
pathEntry_(nullptr), pathEntry_(nullptr),
pathBar_(nullptr), pathBar_(nullptr),
fileLauncher_(this), fileLauncher_(this),
rightClickIndex_(-1), rightClickIndex_(-1),
updatingViewMenu_(false) { updatingViewMenu_(false),
bookmarks_{Fm::Bookmarks::globalInstance()} {
Settings& settings = static_cast<Application*>(qApp)->settings(); Settings& settings = static_cast<Application*>(qApp)->settings();
setAttribute(Qt::WA_DeleteOnClose); setAttribute(Qt::WA_DeleteOnClose);
@ -71,8 +70,9 @@ MainWindow::MainWindow(Path path):
// hide menu items that are not usable // hide menu items that are not usable
//if(!uriExists("computer:///")) //if(!uriExists("computer:///"))
// ui.actionComputer->setVisible(false); // ui.actionComputer->setVisible(false);
if(!settings.supportTrash()) if(!settings.supportTrash()) {
ui.actionTrash->setVisible(false); ui.actionTrash->setVisible(false);
}
// FIXME: add an option to hide network:/// // FIXME: add an option to hide network:///
// We cannot use uriExists() here since calling this on "network:///" // We cannot use uriExists() here since calling this on "network:///"
@ -136,10 +136,12 @@ MainWindow::MainWindow(Path path):
// path bar // path bar
createPathBar(settings.pathBarButtons()); createPathBar(settings.pathBarButtons());
if(settings.pathBarButtons()) if(settings.pathBarButtons()) {
ui.actionPathButtons->setChecked(true); ui.actionPathButtons->setChecked(true);
else }
else {
ui.actionLocationBar->setChecked(true); ui.actionLocationBar->setChecked(true);
}
// add filesystem info to status bar // add filesystem info to status bar
fsInfoLabel_ = new QLabel(ui.statusbar); fsInfoLabel_ = new QLabel(ui.statusbar);
@ -153,8 +155,7 @@ MainWindow::MainWindow(Path path):
ui.splitter->setSizes(sizes); ui.splitter->setSizes(sizes);
// load bookmark menu // load bookmark menu
bookmarks_ = Fm::Bookmarks::dup(); connect(bookmarks_.get(), &Fm::Bookmarks::changed, this, &MainWindow::onBookmarksChanged);
g_signal_connect(bookmarks_, "changed", G_CALLBACK(onBookmarksChanged), this);
loadBookmarksMenu(); loadBookmarksMenu();
// Fix the menu groups which is not done by Qt designer // Fix the menu groups which is not done by Qt designer
@ -191,15 +192,16 @@ MainWindow::MainWindow(Path path):
// Show or hide the menu bar // Show or hide the menu bar
QMenu* menu = new QMenu(ui.toolBar); QMenu* menu = new QMenu(ui.toolBar);
menu->addMenu(ui.menu_File); menu->addMenu(ui.menu_File);
menu->addMenu(ui.menu_Editw); menu->addMenu(ui.menu_Edit);
menu->addMenu(ui.menu_View); menu->addMenu(ui.menu_View);
menu->addMenu(ui.menu_Go); menu->addMenu(ui.menu_Go);
menu->addMenu(ui.menu_Bookmarks); menu->addMenu(ui.menu_Bookmarks);
menu->addMenu(ui.menu_Tool); menu->addMenu(ui.menu_Tool);
menu->addMenu(ui.menu_Help); menu->addMenu(ui.menu_Help);
ui.actionMenu->setMenu(menu); ui.actionMenu->setMenu(menu);
if(ui.actionMenu->icon().isNull()) if(ui.actionMenu->icon().isNull()) {
ui.actionMenu->setIcon(QIcon::fromTheme("applications-system")); ui.actionMenu->setIcon(QIcon::fromTheme("applications-system"));
}
QToolButton* menuBtn = static_cast<QToolButton*>(ui.toolBar->widgetForAction(ui.actionMenu)); QToolButton* menuBtn = static_cast<QToolButton*>(ui.toolBar->widgetForAction(ui.actionMenu));
menuBtn->setPopupMode(QToolButton::InstantPopup); menuBtn->setPopupMode(QToolButton::InstantPopup);
@ -264,29 +266,28 @@ MainWindow::MainWindow(Path path):
connect(shortcut, &QShortcut::activated, ui.filterBar, &QLineEdit::clear); connect(shortcut, &QShortcut::activated, ui.filterBar, &QLineEdit::clear);
} }
if(!path.isNull()) if(path) {
addTab(path); addTab(path);
}
// size from settings // size from settings
if(settings.rememberWindowSize()) { if(settings.rememberWindowSize()) {
resize(settings.windowWidth(), settings.windowHeight()); resize(settings.windowWidth(), settings.windowHeight());
if(settings.windowMaximized()) if(settings.windowMaximized()) {
setWindowState(windowState() | Qt::WindowMaximized); setWindowState(windowState() | Qt::WindowMaximized);
} }
}
if(QApplication::layoutDirection() == Qt::RightToLeft) if(QApplication::layoutDirection() == Qt::RightToLeft) {
setRTLIcons(true); setRTLIcons(true);
} }
}
MainWindow::~MainWindow() { MainWindow::~MainWindow() {
if(!bookmarks_.isNull()) {
g_signal_handlers_disconnect_by_func(bookmarks_, (gpointer)G_CALLBACK(onBookmarksChanged), this);
}
} }
void MainWindow::chdir(Path path) { void MainWindow::chdir(Fm::FilePath path) {
TabPage* page = currentPage(); TabPage* page = currentPage();
if(page) { if(page) {
ui.filterBar->clear(); ui.filterBar->clear();
page->chdir(path, true); page->chdir(path, true);
@ -305,17 +306,16 @@ void MainWindow::createPathBar(bool usePathButtons) {
else { else {
bar = pathEntry_ = new Fm::PathEdit(this); bar = pathEntry_ = new Fm::PathEdit(this);
connect(pathEntry_, &Fm::PathEdit::returnPressed, this, &MainWindow::onPathEntryReturnPressed); connect(pathEntry_, &Fm::PathEdit::returnPressed, this, &MainWindow::onPathEntryReturnPressed);
connect(pathEntry_, &QLineEdit::textEdited, this, &MainWindow::onPathEntryEdited);
} }
ui.toolBar->insertWidget(ui.actionGo, bar); ui.toolBar->insertWidget(ui.actionGo, bar);
ui.actionGo->setVisible(!usePathButtons); ui.actionGo->setVisible(!usePathButtons);
} }
// add a new tab // add a new tab
int MainWindow::addTab(Path path) { int MainWindow::addTab(Fm::FilePath path) {
Settings& settings = static_cast<Application*>(qApp)->settings(); Settings& settings = static_cast<Application*>(qApp)->settings();
TabPage* newPage = new TabPage(path, this); TabPage* newPage = new TabPage(this);
newPage->setFileLauncher(&fileLauncher_); newPage->setFileLauncher(&fileLauncher_);
int index = ui.stackedWidget->addWidget(newPage); int index = ui.stackedWidget->addWidget(newPage);
connect(newPage, &TabPage::titleChanged, this, &MainWindow::onTabPageTitleChanged); connect(newPage, &TabPage::titleChanged, this, &MainWindow::onTabPageTitleChanged);
@ -325,12 +325,12 @@ int MainWindow::addTab(Path path) {
connect(newPage, &TabPage::backwardRequested, this, &MainWindow::on_actionGoBack_triggered); connect(newPage, &TabPage::backwardRequested, this, &MainWindow::on_actionGoBack_triggered);
connect(newPage, &TabPage::forwardRequested, this, &MainWindow::on_actionGoForward_triggered); connect(newPage, &TabPage::forwardRequested, this, &MainWindow::on_actionGoForward_triggered);
ui.tabBar->insertTab(index, newPage->title()); newPage->chdir(path, true);
ui.tabBar->insertTab(index, newPage->windowTitle());
if(!settings.alwaysShowTabs()) { if(!settings.alwaysShowTabs()) {
ui.tabBar->setVisible(ui.tabBar->count() > 1); ui.tabBar->setVisible(ui.tabBar->count() > 1);
} }
return index; return index;
} }
@ -357,27 +357,20 @@ void MainWindow::toggleMenuBar(bool checked) {
void MainWindow::onPathEntryReturnPressed() { void MainWindow::onPathEntryReturnPressed() {
QString text = pathEntry_->text(); QString text = pathEntry_->text();
QByteArray utext = text.toUtf8(); QByteArray utext = text.toLocal8Bit();
chdir(Fm::Path::newForDisplayName(utext)); chdir(Fm::FilePath::fromPathStr(utext.constData()));
} }
void MainWindow::onPathEntryEdited(const QString& text) { void MainWindow::onPathBarChdir(const Fm::FilePath& dirPath) {
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 // call chdir() only when needed because otherwise
// filter bar will be cleard on changing current tab // filter bar will be cleard on changing current tab
TabPage* page = currentPage(); TabPage* page = currentPage();
if(page && dirPath != page->path()) if(page && dirPath != page->path()) {
chdir(dirPath); chdir(dirPath);
} }
}
void MainWindow::onPathBarMiddleClickChdir(FmPath* dirPath) { void MainWindow::onPathBarMiddleClickChdir(const Fm::FilePath& dirPath) {
addTab(dirPath); addTab(dirPath);
} }
@ -412,14 +405,15 @@ void MainWindow::on_actionGoForward_triggered() {
} }
void MainWindow::on_actionHome_triggered() { void MainWindow::on_actionHome_triggered() {
chdir(Fm::Path::getHome()); chdir(Fm::FilePath::homeDir());
} }
void MainWindow::on_actionReload_triggered() { void MainWindow::on_actionReload_triggered() {
currentPage()->reload(); currentPage()->reload();
if(pathEntry_ != nullptr) if(pathEntry_ != nullptr) {
pathEntry_->setText(currentPage()->pathName()); pathEntry_->setText(currentPage()->pathName());
} }
}
void MainWindow::on_actionConnectToServer_triggered() { void MainWindow::on_actionConnectToServer_triggered() {
Application* app = static_cast<Application*>(qApp); Application* app = static_cast<Application*>(qApp);
@ -431,33 +425,33 @@ void MainWindow::on_actionGo_triggered() {
} }
void MainWindow::on_actionNewTab_triggered() { void MainWindow::on_actionNewTab_triggered() {
Fm::Path path = currentPage()->path(); auto path = currentPage()->path();
int index = addTab(path); int index = addTab(path);
ui.tabBar->setCurrentIndex(index); ui.tabBar->setCurrentIndex(index);
} }
void MainWindow::on_actionNewWin_triggered() { void MainWindow::on_actionNewWin_triggered() {
Fm::Path path = currentPage()->path(); auto path = currentPage()->path();
(new MainWindow(path))->show(); (new MainWindow(path))->show();
} }
void MainWindow::on_actionNewFolder_triggered() { void MainWindow::on_actionNewFolder_triggered() {
if(TabPage* tabPage = currentPage()) { if(TabPage* tabPage = currentPage()) {
Fm::Path dirPath = tabPage->folderView()->path(); auto dirPath = tabPage->folderView()->path();
if(dirPath) {
if(dirPath)
createFileOrFolder(CreateNewFolder, dirPath); createFileOrFolder(CreateNewFolder, dirPath);
} }
} }
}
void MainWindow::on_actionNewBlankFile_triggered() { void MainWindow::on_actionNewBlankFile_triggered() {
if(TabPage* tabPage = currentPage()) { if(TabPage* tabPage = currentPage()) {
Fm::Path dirPath = tabPage->folderView()->path(); auto dirPath = tabPage->folderView()->path();
if(dirPath) {
if(dirPath)
createFileOrFolder(CreateNewTextFile, dirPath); createFileOrFolder(CreateNewTextFile, dirPath);
} }
} }
}
void MainWindow::on_actionCloseTab_triggered() { void MainWindow::on_actionCloseTab_triggered() {
closeTab(ui.tabBar->currentIndex()); closeTab(ui.tabBar->currentIndex());
@ -472,8 +466,8 @@ void MainWindow::on_actionCloseWindow_triggered() {
void MainWindow::on_actionFileProperties_triggered() { void MainWindow::on_actionFileProperties_triggered() {
TabPage* page = currentPage(); TabPage* page = currentPage();
if(page) { if(page) {
Fm::FileInfoList files = page->selectedFiles(); auto files = page->selectedFiles();
if(!files.isNull()) { if(!files.empty()) {
Fm::FilePropsDialog::showForFiles(files); Fm::FilePropsDialog::showForFiles(files);
} }
} }
@ -481,20 +475,23 @@ void MainWindow::on_actionFileProperties_triggered() {
void MainWindow::on_actionFolderProperties_triggered() { void MainWindow::on_actionFolderProperties_triggered() {
TabPage* page = currentPage(); TabPage* page = currentPage();
if(page) { if(page) {
Fm::Folder folder = page->folder(); auto folder = page->folder();
if(!folder.isNull()) { if(folder) {
Fm::FileInfo info = folder.getInfo(); auto info = folder->info();
if(!info.isNull()) if(info) {
Fm::FilePropsDialog::showForFile(info); Fm::FilePropsDialog::showForFile(info);
} }
} }
} }
}
void MainWindow::on_actionShowHidden_triggered(bool checked) { void MainWindow::on_actionShowHidden_triggered(bool checked) {
currentPage()->setShowHidden(checked); currentPage()->setShowHidden(checked);
ui.sidePane->setShowHidden(checked); ui.sidePane->setShowHidden(checked);
if(!currentPage()->hasCustomizedView()) {
static_cast<Application*>(qApp)->settings().setShowHidden(checked); // remember globally
}
} }
void MainWindow::on_actionByFileName_triggered(bool checked) { void MainWindow::on_actionByFileName_triggered(bool checked) {
@ -540,8 +537,9 @@ void MainWindow::on_actionPreserveView_triggered(bool checked) {
void MainWindow::on_actionFilter_triggered(bool checked) { void MainWindow::on_actionFilter_triggered(bool checked) {
ui.filterBar->setVisible(checked); ui.filterBar->setVisible(checked);
if(checked) if(checked) {
ui.filterBar->setFocus(); ui.filterBar->setFocus();
}
else if(TabPage* tabPage = currentPage()) { else if(TabPage* tabPage = currentPage()) {
ui.filterBar->clear(); ui.filterBar->clear();
tabPage->folderView()->childView()->setFocus(); tabPage->folderView()->childView()->setFocus();
@ -585,33 +583,33 @@ void MainWindow::on_actionPathButtons_triggered(bool checked) {
} }
void MainWindow::on_actionComputer_triggered() { void MainWindow::on_actionComputer_triggered() {
chdir(Fm::Path::newForUri("computer:///")); chdir(Fm::FilePath::fromUri("computer:///"));
} }
void MainWindow::on_actionApplications_triggered() { void MainWindow::on_actionApplications_triggered() {
chdir(Fm::Path::getAppsMenu()); chdir(Fm::FilePath::fromUri("menu://applications/"));
} }
void MainWindow::on_actionTrash_triggered() { void MainWindow::on_actionTrash_triggered() {
chdir(Fm::Path::getTrash()); chdir(Fm::FilePath::fromUri("trash:///"));
} }
void MainWindow::on_actionNetwork_triggered() { void MainWindow::on_actionNetwork_triggered() {
chdir(Fm::Path::newForUri("network:///")); chdir(Fm::FilePath::fromUri("network:///"));
} }
void MainWindow::on_actionDesktop_triggered() { 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() { void MainWindow::on_actionAddToBookmarks_triggered() {
TabPage* page = currentPage(); TabPage* page = currentPage();
if(page) { if(page) {
Fm::Path cwd = page->path(); auto cwd = page->path();
if(!cwd.isNull()) { if(cwd) {
char* dispName = cwd.displayBasename(); auto dispName = cwd.baseName();
bookmarks_.insert(cwd, dispName, -1); bookmarks_->insert(cwd, dispName.get(), -1);
g_free(dispName);
} }
} }
} }
@ -679,11 +677,13 @@ void MainWindow::onTabBarTabMoved(int from, int to) {
} }
void MainWindow::focusFilterBar() { void MainWindow::focusFilterBar() {
if(!ui.filterBar->isVisible()) if(!ui.filterBar->isVisible()) {
ui.actionFilter->trigger(); ui.actionFilter->trigger();
else }
else {
ui.filterBar->setFocus(); ui.filterBar->setFocus();
} }
}
void MainWindow::onFilterStringChanged(QString str) { void MainWindow::onFilterStringChanged(QString str) {
if(TabPage* tabPage = currentPage()) { if(TabPage* tabPage = currentPage()) {
@ -718,10 +718,10 @@ void MainWindow::resizeEvent(QResizeEvent *event) {
} }
} }
void MainWindow::closeEvent(QCloseEvent *event) void MainWindow::closeEvent(QCloseEvent* event) {
{ if(lastActive_ == this) {
if(lastActive_ == this)
lastActive_ = nullptr; lastActive_ = nullptr;
}
QWidget::closeEvent(event); QWidget::closeEvent(event);
Settings& settings = static_cast<Application*>(qApp)->settings(); Settings& settings = static_cast<Application*>(qApp)->settings();
@ -737,16 +737,18 @@ void MainWindow::closeEvent(QCloseEvent *event)
void MainWindow::onTabBarCurrentChanged(int index) { void MainWindow::onTabBarCurrentChanged(int index) {
ui.stackedWidget->setCurrentIndex(index); ui.stackedWidget->setCurrentIndex(index);
if(TabPage* page = static_cast<TabPage*>(ui.stackedWidget->widget(index))) if(TabPage* page = static_cast<TabPage*>(ui.stackedWidget->widget(index))) {
ui.filterBar->setText(page->getFilterStr()); ui.filterBar->setText(page->getFilterStr());
}
updateUIForCurrentPage(); updateUIForCurrentPage();
} }
void MainWindow::updateStatusBarForCurrentPage() { void MainWindow::updateStatusBarForCurrentPage() {
TabPage* tabPage = currentPage(); TabPage* tabPage = currentPage();
QString text = tabPage->statusText(TabPage::StatusTextSelectedFiles); QString text = tabPage->statusText(TabPage::StatusTextSelectedFiles);
if(text.isEmpty()) if(text.isEmpty()) {
text = tabPage->statusText(TabPage::StatusTextNormal); text = tabPage->statusText(TabPage::StatusTextNormal);
}
ui.statusbar->showMessage(text); ui.statusbar->showMessage(text);
text = tabPage->statusText(TabPage::StatusTextFSInfo); text = tabPage->statusText(TabPage::StatusTextFSInfo);
@ -755,8 +757,9 @@ void MainWindow::updateStatusBarForCurrentPage() {
} }
void MainWindow::updateViewMenuForCurrentPage() { void MainWindow::updateViewMenuForCurrentPage() {
if(updatingViewMenu_) // prevent recursive calls if(updatingViewMenu_) { // prevent recursive calls
return; return;
}
updatingViewMenu_ = true; updatingViewMenu_ = true;
TabPage* tabPage = currentPage(); TabPage* tabPage = currentPage();
if(tabPage) { if(tabPage) {
@ -765,7 +768,7 @@ void MainWindow::updateViewMenuForCurrentPage() {
ui.actionPreserveView->setChecked(tabPage->hasCustomizedView()); ui.actionPreserveView->setChecked(tabPage->hasCustomizedView());
// view mode // view mode
QAction* modeAction = NULL; QAction* modeAction = nullptr;
switch(tabPage->viewMode()) { switch(tabPage->viewMode()) {
case Fm::FolderView::IconMode: case Fm::FolderView::IconMode:
@ -785,7 +788,7 @@ void MainWindow::updateViewMenuForCurrentPage() {
break; break;
} }
Q_ASSERT(modeAction != NULL); Q_ASSERT(modeAction != nullptr);
modeAction->setChecked(true); modeAction->setChecked(true);
// sort menu // sort menu
@ -797,21 +800,51 @@ void MainWindow::updateViewMenuForCurrentPage() {
sortActions[Fm::FolderModel::ColumnFileOwner] = ui.actionByOwner; sortActions[Fm::FolderModel::ColumnFileOwner] = ui.actionByOwner;
sortActions[tabPage->sortColumn()]->setChecked(true); sortActions[tabPage->sortColumn()]->setChecked(true);
if(tabPage->sortOrder() == Qt::AscendingOrder) if(tabPage->sortOrder() == Qt::AscendingOrder) {
ui.actionAscending->setChecked(true); ui.actionAscending->setChecked(true);
else }
else {
ui.actionDescending->setChecked(true); ui.actionDescending->setChecked(true);
}
ui.actionCaseSensitive->setChecked(tabPage->sortCaseSensitive()); ui.actionCaseSensitive->setChecked(tabPage->sortCaseSensitive());
ui.actionFolderFirst->setChecked(tabPage->sortFolderFirst()); ui.actionFolderFirst->setChecked(tabPage->sortFolderFirst());
} }
updatingViewMenu_ = false; 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.actionCopy->setEnabled(hasAccessible);
ui.actionCut->setEnabled(hasDeletable);
ui.actionDelete->setEnabled(hasDeletable);
ui.actionRename->setEnabled(hasRenamable);
}
void MainWindow::updateUIForCurrentPage() { void MainWindow::updateUIForCurrentPage() {
TabPage* tabPage = currentPage(); TabPage* tabPage = currentPage();
if(tabPage) { if(tabPage) {
setWindowTitle(tabPage->title()); setWindowTitle(tabPage->windowTitle());
if(pathEntry_ != nullptr) { if(pathEntry_ != nullptr) {
pathEntry_->setText(tabPage->pathName()); pathEntry_->setText(tabPage->pathName());
} }
@ -834,6 +867,16 @@ void MainWindow::updateUIForCurrentPage() {
updateViewMenuForCurrentPage(); updateViewMenuForCurrentPage();
updateStatusBarForCurrentPage(); 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) { void MainWindow::onStackedWidgetWidgetRemoved(int index) {
@ -855,12 +898,23 @@ void MainWindow::onStackedWidgetWidgetRemoved(int index) {
void MainWindow::onTabPageTitleChanged(QString title) { void MainWindow::onTabPageTitleChanged(QString title) {
TabPage* tabPage = static_cast<TabPage*>(sender()); TabPage* tabPage = static_cast<TabPage*>(sender());
int index = ui.stackedWidget->indexOf(tabPage); int index = ui.stackedWidget->indexOf(tabPage);
if(index >= 0) {
if(index >= 0)
ui.tabBar->setTabText(index, title); ui.tabBar->setTabText(index, title);
}
if(tabPage == currentPage()) if(tabPage == currentPage()) {
setWindowTitle(title); 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) { void MainWindow::onTabPageStatusChanged(int type, QString statusText) {
@ -869,12 +923,15 @@ void MainWindow::onTabPageStatusChanged(int type, QString statusText) {
switch(type) { switch(type) {
case TabPage::StatusTextNormal: case TabPage::StatusTextNormal:
case TabPage::StatusTextSelectedFiles: { case TabPage::StatusTextSelectedFiles: {
// FIXME: updating the status text so frequently is a little bit ineffiecient // although the status text may change very frequently,
QString text = statusText = tabPage->statusText(TabPage::StatusTextSelectedFiles); // the text of PCManFM::StatusBar is updated with a delay
if(text.isEmpty()) QString text = tabPage->statusText(TabPage::StatusTextSelectedFiles);
if(text.isEmpty()) {
ui.statusbar->showMessage(tabPage->statusText(TabPage::StatusTextNormal)); ui.statusbar->showMessage(tabPage->statusText(TabPage::StatusTextNormal));
else }
else {
ui.statusbar->showMessage(text); ui.statusbar->showMessage(text);
}
break; break;
} }
case TabPage::StatusTextFSInfo: case TabPage::StatusTextFSInfo:
@ -883,9 +940,13 @@ void MainWindow::onTabPageStatusChanged(int type, QString statusText) {
break; 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(FmPath* path, int target) { void MainWindow::onTabPageOpenDirRequested(const Fm::FilePath& path, int target) {
switch(target) { switch(target) {
case OpenInCurrentTab: case OpenInCurrentTab:
chdir(path); chdir(path);
@ -911,35 +972,40 @@ void MainWindow::onTabPageSortFilterChanged() {
settings.setSortOrder(tabPage->sortOrder()); settings.setSortOrder(tabPage->sortOrder());
settings.setSortFolderFirst(tabPage->sortFolderFirst()); settings.setSortFolderFirst(tabPage->sortFolderFirst());
settings.setSortCaseSensitive(tabPage->sortCaseSensitive()); 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) { void MainWindow::onSidePaneChdirRequested(int type, const Fm::FilePath &path) {
// FIXME: use enum for type value or change it to button. // FIXME: use enum for type value or change it to button.
if(type == 0) // left button (default) if(type == 0) { // left button (default)
chdir(path); chdir(path);
else if(type == 1) // middle button }
else if(type == 1) { // middle button
addTab(path); addTab(path);
else if(type == 2) // new window }
else if(type == 2) { // new window
(new MainWindow(path))->show(); (new MainWindow(path))->show();
} }
}
void MainWindow::onSidePaneOpenFolderInNewWindowRequested(FmPath* path) { void MainWindow::onSidePaneOpenFolderInNewWindowRequested(const Fm::FilePath &path) {
(new MainWindow(path))->show(); (new MainWindow(path))->show();
} }
void MainWindow::onSidePaneOpenFolderInNewTabRequested(FmPath* path) { void MainWindow::onSidePaneOpenFolderInNewTabRequested(const Fm::FilePath &path) {
addTab(path); addTab(path);
} }
void MainWindow::onSidePaneOpenFolderInTerminalRequested(FmPath* path) { void MainWindow::onSidePaneOpenFolderInTerminalRequested(const Fm::FilePath &path) {
Application* app = static_cast<Application*>(qApp); Application* app = static_cast<Application*>(qApp);
app->openFolderInTerminal(path); app->openFolderInTerminal(path);
} }
void MainWindow::onSidePaneCreateNewFolderRequested(FmPath* path) { void MainWindow::onSidePaneCreateNewFolderRequested(const Fm::FilePath &path) {
createFileOrFolder(CreateNewFolder, path); createFileOrFolder(CreateNewFolder, path);
} }
@ -953,38 +1019,34 @@ void MainWindow::onSplitterMoved(int pos, int index) {
} }
void MainWindow::loadBookmarksMenu() { void MainWindow::loadBookmarksMenu() {
GList* allBookmarks = bookmarks_.getAll();
QAction* before = ui.actionAddToBookmarks; QAction* before = ui.actionAddToBookmarks;
for(auto& item: bookmarks_->items()) {
for(GList* l = allBookmarks; l; l = l->next) {
FmBookmarkItem* item = reinterpret_cast<FmBookmarkItem*>(l->data);
BookmarkAction* action = new BookmarkAction(item, ui.menu_Bookmarks); BookmarkAction* action = new BookmarkAction(item, ui.menu_Bookmarks);
connect(action, &QAction::triggered, this, &MainWindow::onBookmarkActionTriggered); connect(action, &QAction::triggered, this, &MainWindow::onBookmarkActionTriggered);
ui.menu_Bookmarks->insertAction(before, action); ui.menu_Bookmarks->insertAction(before, action);
} }
ui.menu_Bookmarks->insertSeparator(before); ui.menu_Bookmarks->insertSeparator(before);
g_list_free_full(allBookmarks, (GDestroyNotify)fm_bookmark_item_unref);
} }
void MainWindow::onBookmarksChanged(FmBookmarks* bookmarks, MainWindow* pThis) { void MainWindow::onBookmarksChanged() {
// delete existing items // delete existing items
QList<QAction*> actions = pThis->ui.menu_Bookmarks->actions(); QList<QAction*> actions = ui.menu_Bookmarks->actions();
QList<QAction*>::const_iterator it = actions.begin(); QList<QAction*>::const_iterator it = actions.constBegin();
QList<QAction*>::const_iterator last_it = actions.end() - 2; QList<QAction*>::const_iterator last_it = actions.constEnd() - 2;
while(it != last_it) { while(it != last_it) {
QAction* action = *it; QAction* action = *it;
++it; ++it;
pThis->ui.menu_Bookmarks->removeAction(action); ui.menu_Bookmarks->removeAction(action);
} }
pThis->loadBookmarksMenu(); loadBookmarksMenu();
} }
void MainWindow::onBookmarkActionTriggered() { void MainWindow::onBookmarkActionTriggered() {
BookmarkAction* action = static_cast<BookmarkAction*>(sender()); BookmarkAction* action = static_cast<BookmarkAction*>(sender());
Fm::Path path = action->path(); auto path = action->path();
if(path) { if(path) {
Application* app = static_cast<Application*>(qApp); Application* app = static_cast<Application*>(qApp);
Settings& settings = app->settings(); Settings& settings = app->settings();
@ -1005,13 +1067,13 @@ void MainWindow::onBookmarkActionTriggered() {
void MainWindow::on_actionCopy_triggered() { void MainWindow::on_actionCopy_triggered() {
TabPage* page = currentPage(); TabPage* page = currentPage();
Fm::PathList paths = page->selectedFilePaths(); auto paths = page->selectedFilePaths();
copyFilesToClipboard(paths); copyFilesToClipboard(paths);
} }
void MainWindow::on_actionCut_triggered() { void MainWindow::on_actionCut_triggered() {
TabPage* page = currentPage(); TabPage* page = currentPage();
Fm::PathList paths = page->selectedFilePaths(); auto paths = page->selectedFilePaths();
cutFilesToClipboard(paths); cutFilesToClipboard(paths);
} }
@ -1023,21 +1085,39 @@ void MainWindow::on_actionDelete_triggered() {
Application* app = static_cast<Application*>(qApp); Application* app = static_cast<Application*>(qApp);
Settings& settings = app->settings(); Settings& settings = app->settings();
TabPage* page = currentPage(); TabPage* page = currentPage();
Fm::PathList paths = page->selectedFilePaths(); auto paths = page->selectedFilePaths();
bool shiftPressed = (qApp->keyboardModifiers() & Qt::ShiftModifier ? true : false); bool shiftPressed = (qApp->keyboardModifiers() & Qt::ShiftModifier ? true : false);
if(settings.useTrash() && !shiftPressed) if(settings.useTrash() && !shiftPressed) {
FileOperation::trashFiles(paths, settings.confirmTrash(), this); FileOperation::trashFiles(paths, settings.confirmTrash(), this);
else }
else {
FileOperation::deleteFiles(paths, settings.confirmDelete(), this); FileOperation::deleteFiles(paths, settings.confirmDelete(), this);
} }
}
void MainWindow::on_actionRename_triggered() { void MainWindow::on_actionRename_triggered() {
// do inline renaming if only one item is selected,
// otherwise use the renaming dialog
TabPage* page = currentPage(); TabPage* page = currentPage();
Fm::FileInfoList files = page->selectedFiles(); auto files = page->selectedFiles();
for(GList* l = fm_file_info_list_peek_head_link(files); l; l = l->next) { if(files.size() == 1) {
FmFileInfo* file = FM_FILE_INFO(l->data); QAbstractItemView* view = page->folderView()->childView();
Fm::renameFile(file, NULL); 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);
}
} }
} }
@ -1103,10 +1183,9 @@ void MainWindow::onBackForwardContextMenu(QPoint pos) {
QMenu menu; QMenu menu;
for(int i = 0; i < history.size(); ++i) { for(int i = 0; i < history.size(); ++i) {
const BrowseHistoryItem& item = history.at(i); const BrowseHistoryItem& item = history.at(i);
Fm::Path path = item.path(); auto path = item.path();
char* name = path.displayName(true); auto name = path.displayName();
QAction* action = menu.addAction(QString::fromUtf8(name)); QAction* action = menu.addAction(name.get());
g_free(name);
if(i == current) { if(i == current) {
// make the current path bold and checked // make the current path bold and checked
action->setCheckable(true); action->setCheckable(true);
@ -1127,14 +1206,19 @@ void MainWindow::onBackForwardContextMenu(QPoint pos) {
void MainWindow::tabContextMenu(const QPoint& pos) { void MainWindow::tabContextMenu(const QPoint& pos) {
int tabNum = ui.tabBar->count(); int tabNum = ui.tabBar->count();
if(tabNum <= 1) return; if(tabNum <= 1) {
return;
}
rightClickIndex_ = ui.tabBar->tabAt(pos); rightClickIndex_ = ui.tabBar->tabAt(pos);
if(rightClickIndex_ < 0) return; if(rightClickIndex_ < 0) {
return;
}
QMenu menu; QMenu menu;
if(rightClickIndex_ > 0) if(rightClickIndex_ > 0) {
menu.addAction(ui.actionCloseLeft); menu.addAction(ui.actionCloseLeft);
}
if(rightClickIndex_ < tabNum - 1) { if(rightClickIndex_ < tabNum - 1) {
menu.addAction(ui.actionCloseRight); menu.addAction(ui.actionCloseRight);
if(rightClickIndex_ > 0) { if(rightClickIndex_ > 0) {
@ -1153,10 +1237,13 @@ void MainWindow::closeLeftTabs() {
} }
void MainWindow::closeRightTabs() { void MainWindow::closeRightTabs() {
if(rightClickIndex_ < 0) return; if(rightClickIndex_ < 0) {
while(rightClickIndex_ < ui.tabBar->count() - 1) return;
}
while(rightClickIndex_ < ui.tabBar->count() - 1) {
closeTab(rightClickIndex_ + 1); closeTab(rightClickIndex_ + 1);
} }
}
void MainWindow::focusPathEntry() { void MainWindow::focusPathEntry() {
// use text entry for the path bar // use text entry for the path bar
@ -1208,7 +1295,7 @@ static const char* su_cmd_subst(char opt, gpointer user_data) {
static FmAppCommandParseOption su_cmd_opts[] = { static FmAppCommandParseOption su_cmd_opts[] = {
{ 's', su_cmd_subst }, { 's', su_cmd_subst },
{ 0, NULL } { 0, nullptr }
}; };
void MainWindow::on_actionOpenAsRoot_triggered() { void MainWindow::on_actionOpenAsRoot_triggered() {
@ -1222,33 +1309,30 @@ void MainWindow::on_actionOpenAsRoot_triggered() {
// run the su command // run the su command
// FIXME: it's better to get the filename of the current process rather than hard-code pcmanfm-qt here. // FIXME: it's better to get the filename of the current process rather than hard-code pcmanfm-qt here.
QByteArray suCommand = settings.suCommand().toLocal8Bit(); QByteArray suCommand = settings.suCommand().toLocal8Bit();
char* cmd = NULL; char* cmd = nullptr;
QByteArray programCommand = app->applicationFilePath().toLocal8Bit(); QByteArray programCommand = app->applicationFilePath().toLocal8Bit();
programCommand += " %U"; programCommand += " %U";
if(fm_app_command_parse(suCommand.constData(), su_cmd_opts, &cmd, gpointer(programCommand.constData())) == 0) { if(fm_app_command_parse(suCommand.constData(), su_cmd_opts, &cmd, gpointer(programCommand.constData())) == 0) {
/* no %s found so just append to it */ /* no %s found so just append to it */
g_free(cmd); g_free(cmd);
cmd = g_strconcat(suCommand.constData(), programCommand.constData(), NULL); cmd = g_strconcat(suCommand.constData(), programCommand.constData(), nullptr);
} }
GAppInfo* appInfo = g_app_info_create_from_commandline(cmd, NULL, GAppInfoCreateFlags(0), NULL); Fm::GAppInfoPtr appInfo{g_app_info_create_from_commandline(cmd, nullptr, GAppInfoCreateFlags(0), nullptr), false};
g_free(cmd); g_free(cmd);
if(appInfo) { if(appInfo) {
Fm::Path cwd = page->path(); auto cwd = page->path();
GError* err = NULL; Fm::GErrorPtr err;
char* uri = cwd.toUri(); auto uri = cwd.uri();
GList* uris = g_list_prepend(NULL, uri); GList* uris = g_list_prepend(nullptr, uri.get());
if(!g_app_info_launch_uris(appInfo, uris, NULL, &err)) { if(!g_app_info_launch_uris(appInfo.get(), uris, nullptr, &err)) {
QMessageBox::critical(this, tr("Error"), QString::fromUtf8(err->message)); QMessageBox::critical(this, tr("Error"), QString::fromUtf8(err->message));
g_error_free(err);
} }
g_list_free(uris); g_list_free(uris);
g_free(uri);
g_object_unref(appInfo);
} }
} }
else { else {
@ -1261,14 +1345,13 @@ void MainWindow::on_actionOpenAsRoot_triggered() {
void MainWindow::on_actionFindFiles_triggered() { void MainWindow::on_actionFindFiles_triggered() {
Application* app = static_cast<Application*>(qApp); Application* app = static_cast<Application*>(qApp);
Fm::PathList selectedPaths = currentPage()->selectedFilePaths(); auto selectedPaths = currentPage()->selectedFilePaths();
QStringList paths; QStringList paths;
if(!selectedPaths.isNull()) { if(!selectedPaths.empty()) {
for(GList* l = fm_path_list_peek_head_link(selectedPaths); l; l = l->next) { for(auto& path: selectedPaths) {
// FIXME: is it ok to use display name here? // FIXME: is it ok to use display name here?
// This might be broken on filesystems with non-UTF-8 filenames. // This might be broken on filesystems with non-UTF-8 filenames.
Fm::Path path(FM_PATH(l->data)); paths.append(path.displayName().get());
paths.append(path.displayName(false));
} }
} }
else { else {
@ -1287,19 +1370,23 @@ void MainWindow::on_actionOpenTerminal_triggered() {
void MainWindow::onShortcutNextTab() { void MainWindow::onShortcutNextTab() {
int current = ui.tabBar->currentIndex(); int current = ui.tabBar->currentIndex();
if(current < ui.tabBar->count() - 1) if(current < ui.tabBar->count() - 1) {
ui.tabBar->setCurrentIndex(current + 1); ui.tabBar->setCurrentIndex(current + 1);
else }
else {
ui.tabBar->setCurrentIndex(0); ui.tabBar->setCurrentIndex(0);
} }
}
void MainWindow::onShortcutPrevTab() { void MainWindow::onShortcutPrevTab() {
int current = ui.tabBar->currentIndex(); int current = ui.tabBar->currentIndex();
if(current > 0) if(current > 0) {
ui.tabBar->setCurrentIndex(current - 1); ui.tabBar->setCurrentIndex(current - 1);
else }
else {
ui.tabBar->setCurrentIndex(ui.tabBar->count() - 1); ui.tabBar->setCurrentIndex(ui.tabBar->count() - 1);
} }
}
// Switch to nth tab when Alt+n or Ctrl+n is pressed // Switch to nth tab when Alt+n or Ctrl+n is pressed
void MainWindow::onShortcutJumpToTab() { void MainWindow::onShortcutJumpToTab() {
@ -1311,19 +1398,24 @@ void MainWindow::onShortcutJumpToTab() {
// Then we know how to test if a key sequence contains a modifier. // 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. // 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 if((keyValue & Qt::ALT) == Qt::ALT) { // test if we have Alt key pressed
keyValue -= Qt::ALT; keyValue -= Qt::ALT;
else if((keyValue & Qt::CTRL) == Qt::CTRL) // test if we have Ctrl key pressed }
else if((keyValue & Qt::CTRL) == Qt::CTRL) { // test if we have Ctrl key pressed
keyValue -= Qt::CTRL; keyValue -= Qt::CTRL;
}
// now keyValue should contains '0' - '9' only // now keyValue should contains '0' - '9' only
int index; int index;
if(keyValue == '0') if(keyValue == '0') {
index = 9; index = 9;
else }
else {
index = keyValue - '1'; index = keyValue - '1';
if(index < ui.tabBar->count()) }
if(index < ui.tabBar->count()) {
ui.tabBar->setCurrentIndex(index); ui.tabBar->setCurrentIndex(index);
} }
}
} }

@ -32,8 +32,9 @@
#include <QStackedWidget> #include <QStackedWidget>
#include <QSplitter> #include <QSplitter>
#include "launcher.h" #include "launcher.h"
#include <libfm-qt/bookmarks.h>
#include <libfm-qt/path.h> #include <libfm-qt/path.h>
#include <libfm-qt/core/filepath.h>
#include <libfm-qt/core/bookmarks.h>
namespace Fm { namespace Fm {
class PathEdit; class PathEdit;
@ -48,11 +49,11 @@ class Settings;
class MainWindow : public QMainWindow { class MainWindow : public QMainWindow {
Q_OBJECT Q_OBJECT
public: public:
MainWindow(Fm::Path path = Fm::Path()); MainWindow(Fm::FilePath path = Fm::FilePath());
virtual ~MainWindow(); virtual ~MainWindow();
void chdir(Fm::Path path); void chdir(Fm::FilePath path);
int addTab(Fm::Path path); int addTab(Fm::FilePath path);
TabPage* currentPage() { TabPage* currentPage() {
return reinterpret_cast<TabPage*>(ui.stackedWidget->currentWidget()); return reinterpret_cast<TabPage*>(ui.stackedWidget->currentWidget());
@ -67,9 +68,8 @@ public:
protected Q_SLOTS: protected Q_SLOTS:
void onPathEntryReturnPressed(); void onPathEntryReturnPressed();
void onPathEntryEdited(const QString& text); void onPathBarChdir(const Fm::FilePath& dirPath);
void onPathBarChdir(FmPath* dirPath); void onPathBarMiddleClickChdir(const Fm::FilePath &dirPath);
void onPathBarMiddleClickChdir(FmPath* dirPath);
void on_actionNewTab_triggered(); void on_actionNewTab_triggered();
void on_actionNewWin_triggered(); void on_actionNewWin_triggered();
@ -150,14 +150,14 @@ protected Q_SLOTS:
void onTabPageTitleChanged(QString title); void onTabPageTitleChanged(QString title);
void onTabPageStatusChanged(int type, QString statusText); void onTabPageStatusChanged(int type, QString statusText);
void onTabPageOpenDirRequested(FmPath* path, int target); void onTabPageOpenDirRequested(const Fm::FilePath &path, int target);
void onTabPageSortFilterChanged(); void onTabPageSortFilterChanged();
void onSidePaneChdirRequested(int type, FmPath* path); void onSidePaneChdirRequested(int type, const Fm::FilePath &path);
void onSidePaneOpenFolderInNewWindowRequested(FmPath* path); void onSidePaneOpenFolderInNewWindowRequested(const Fm::FilePath &path);
void onSidePaneOpenFolderInNewTabRequested(FmPath* path); void onSidePaneOpenFolderInNewTabRequested(const Fm::FilePath &path);
void onSidePaneOpenFolderInTerminalRequested(FmPath* path); void onSidePaneOpenFolderInTerminalRequested(const Fm::FilePath &path);
void onSidePaneCreateNewFolderRequested(FmPath* path); void onSidePaneCreateNewFolderRequested(const Fm::FilePath &path);
void onSidePaneModeChanged(Fm::SidePane::Mode mode); void onSidePaneModeChanged(Fm::SidePane::Mode mode);
void onSplitterMoved(int pos, int index); void onSplitterMoved(int pos, int index);
void onResetFocus(); void onResetFocus();
@ -174,6 +174,8 @@ protected Q_SLOTS:
void focusPathEntry(); void focusPathEntry();
void toggleMenuBar(bool checked); void toggleMenuBar(bool checked);
void onBookmarksChanged();
protected: protected:
bool event(QEvent* event) override; bool event(QEvent* event) override;
void changeEvent(QEvent* event) override; void changeEvent(QEvent* event) override;
@ -182,10 +184,10 @@ protected:
virtual void closeEvent(QCloseEvent* event) override; virtual void closeEvent(QCloseEvent* event) override;
private: private:
static void onBookmarksChanged(FmBookmarks* bookmarks_, MainWindow* pThis);
void loadBookmarksMenu(); void loadBookmarksMenu();
void updateUIForCurrentPage(); void updateUIForCurrentPage();
void updateViewMenuForCurrentPage(); void updateViewMenuForCurrentPage();
void updateEditSelectedActions();
void updateStatusBarForCurrentPage(); void updateStatusBarForCurrentPage();
void setRTLIcons(bool isRTL); void setRTLIcons(bool isRTL);
void createPathBar(bool usePathButtons); void createPathBar(bool usePathButtons);
@ -195,7 +197,7 @@ private:
Fm::PathEdit* pathEntry_; Fm::PathEdit* pathEntry_;
Fm::PathBar* pathBar_; Fm::PathBar* pathBar_;
QLabel* fsInfoLabel_; QLabel* fsInfoLabel_;
Fm::Bookmarks bookmarks_; std::shared_ptr<Fm::Bookmarks> bookmarks_;
Launcher fileLauncher_; Launcher fileLauncher_;
int rightClickIndex_; int rightClickIndex_;
bool updatingViewMenu_; bool updatingViewMenu_;

@ -8,6 +8,8 @@ int main(int argc, char** argv) {
qunsetenv("QT_NO_GLIB"); qunsetenv("QT_NO_GLIB");
PCManFM::Application app(argc, argv); PCManFM::Application app(argc, argv);
app.setAttribute(Qt::AA_UseHighDpiPixmaps, true);
app.init(); app.init();
return app.exec(); return app.exec();
} }

@ -27,13 +27,10 @@
#include <QSettings> #include <QSettings>
#include <libfm-qt/folderview.h> #include <libfm-qt/folderview.h>
#include <libfm-qt/core/terminal.h>
namespace PCManFM { 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): PreferencesDialog::PreferencesDialog(QString activePage, QWidget* parent):
QDialog(parent) { QDialog(parent) {
ui.setupUi(this); ui.setupUi(this);
@ -59,13 +56,13 @@ static void findIconThemesInDir(QHash<QString, QString>& iconThemes, QString dir
GKeyFile* kf = g_key_file_new(); GKeyFile* kf = g_key_file_new();
Q_FOREACH(QString subDir, subDirs) { Q_FOREACH(QString subDir, subDirs) {
QString indexFile = dirName % '/' % subDir % "/index.theme"; QString indexFile = dirName % '/' % subDir % "/index.theme";
if(g_key_file_load_from_file(kf, indexFile.toLocal8Bit().constData(), GKeyFileFlags(0), NULL)) { if(g_key_file_load_from_file(kf, indexFile.toLocal8Bit().constData(), GKeyFileFlags(0), nullptr)) {
// FIXME: skip hidden ones // FIXME: skip hidden ones
// icon theme must have this key, so it has icons if it has this key // 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. // otherwise, it might be a cursor theme or any other kind of theme.
if(g_key_file_has_key(kf, "Icon Theme", "Directories", NULL)) { if(g_key_file_has_key(kf, "Icon Theme", "Directories", nullptr)) {
char* dispName = g_key_file_get_locale_string(kf, "Icon Theme", "Name", NULL, NULL); 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", NULL, NULL); // char* comment = g_key_file_get_locale_string(kf, "Icon Theme", "Comment", nullptr, nullptr);
iconThemes[subDir] = dispName; iconThemes[subDir] = dispName;
g_free(dispName); g_free(dispName);
} }
@ -90,7 +87,7 @@ void PreferencesDialog::initIconThemes(Settings& settings) {
iconThemes.remove("hicolor"); // remove hicolor, which is only a fallback iconThemes.remove("hicolor"); // remove hicolor, which is only a fallback
QHash<QString, QString>::const_iterator it; QHash<QString, QString>::const_iterator it;
for(it = iconThemes.begin(); it != iconThemes.end(); ++it) { for(it = iconThemes.constBegin(); it != iconThemes.constEnd(); ++it) {
ui.iconTheme->addItem(it.value(), it.key()); ui.iconTheme->addItem(it.value(), it.key());
} }
ui.iconTheme->model()->sort(0); // sort the list of icon theme names ui.iconTheme->model()->sort(0); // sort the list of icon theme names
@ -104,8 +101,9 @@ void PreferencesDialog::initIconThemes(Settings& settings) {
break; break;
} }
} }
if(i >= n) if(i >= n) {
i = 0; i = 0;
}
ui.iconTheme->setCurrentIndex(i); ui.iconTheme->setCurrentIndex(i);
} }
else { // auto-detection of icon theme works, hide the fallback icon theme combo box. else { // auto-detection of icon theme works, hide the fallback icon theme combo box.
@ -124,37 +122,45 @@ void PreferencesDialog::initArchivers(Settings& settings) {
for(const GList* l = allArchivers; l; l = l->next, ++i) { for(const GList* l = allArchivers; l; l = l->next, ++i) {
FmArchiver* archiver = reinterpret_cast<FmArchiver*>(l->data); FmArchiver* archiver = reinterpret_cast<FmArchiver*>(l->data);
ui.archiver->addItem(archiver->program, QString(archiver->program)); ui.archiver->addItem(archiver->program, QString(archiver->program));
if(archiver->program == settings.archiver()) if(archiver->program == settings.archiver()) {
ui.archiver->setCurrentIndex(i); ui.archiver->setCurrentIndex(i);
} }
} }
}
void PreferencesDialog::initDisplayPage(Settings& settings) { void PreferencesDialog::initDisplayPage(Settings& settings) {
initIconThemes(settings); initIconThemes(settings);
// icon sizes // icon sizes
for(std::size_t i = 0; i < G_N_ELEMENTS(bigIconSizes); ++i) { int i = 0;
int size = bigIconSizes[i]; for (const auto & size : Settings::iconSizes(Settings::Big)) {
ui.bigIconSize->addItem(QString("%1 x %1").arg(size), size); ui.bigIconSize->addItem(QString("%1 x %1").arg(size), size);
if(settings.bigIconSize() == size) if(settings.bigIconSize() == size) {
ui.bigIconSize->setCurrentIndex(i); ui.bigIconSize->setCurrentIndex(i);
} }
for(std::size_t i = 0; i < G_N_ELEMENTS(smallIconSizes); ++i) { ++i;
int size = smallIconSizes[i]; }
i = 0;
for (const auto & size : Settings::iconSizes(Settings::Small)) {
QString text = QString("%1 x %1").arg(size); QString text = QString("%1 x %1").arg(size);
ui.smallIconSize->addItem(text, size); ui.smallIconSize->addItem(text, size);
if(settings.smallIconSize() == size) if(settings.smallIconSize() == size) {
ui.smallIconSize->setCurrentIndex(i); ui.smallIconSize->setCurrentIndex(i);
}
ui.sidePaneIconSize->addItem(text, size); ui.sidePaneIconSize->addItem(text, size);
if(settings.sidePaneIconSize() == size) if(settings.sidePaneIconSize() == size) {
ui.sidePaneIconSize->setCurrentIndex(i); ui.sidePaneIconSize->setCurrentIndex(i);
} }
for(std::size_t i = 0; i < G_N_ELEMENTS(thumbnailIconSizes); ++i) { ++i;
int size = thumbnailIconSizes[i]; }
i = 0;
for (const auto & size : Settings::iconSizes(Settings::Thumbnail)) {
ui.thumbnailIconSize->addItem(QString("%1 x %1").arg(size), size); ui.thumbnailIconSize->addItem(QString("%1 x %1").arg(size), size);
if(settings.thumbnailIconSize() == size) if(settings.thumbnailIconSize() == size) {
ui.thumbnailIconSize->setCurrentIndex(i); ui.thumbnailIconSize->setCurrentIndex(i);
} }
++i;
}
ui.siUnit->setChecked(settings.siUnit()); ui.siUnit->setChecked(settings.siUnit());
ui.backupAsHidden->setChecked(settings.backupAsHidden()); ui.backupAsHidden->setChecked(settings.backupAsHidden());
@ -204,8 +210,9 @@ void PreferencesDialog::initBehaviorPage(Settings& settings) {
ui.configmDelete->setChecked(settings.confirmDelete()); ui.configmDelete->setChecked(settings.confirmDelete());
if(settings.supportTrash()) if(settings.supportTrash()) {
ui.useTrash->setChecked(settings.useTrash()); ui.useTrash->setChecked(settings.useTrash());
}
else { else {
ui.useTrash->hide(); ui.useTrash->hide();
} }
@ -225,16 +232,19 @@ void PreferencesDialog::initVolumePage(Settings& settings) {
ui.mountOnStartup->setChecked(settings.mountOnStartup()); ui.mountOnStartup->setChecked(settings.mountOnStartup());
ui.mountRemovable->setChecked(settings.mountRemovable()); ui.mountRemovable->setChecked(settings.mountRemovable());
ui.autoRun->setChecked(settings.autoRun()); ui.autoRun->setChecked(settings.autoRun());
if(settings.closeOnUnmount()) if(settings.closeOnUnmount()) {
ui.closeOnUnmount->setChecked(true); ui.closeOnUnmount->setChecked(true);
else }
else {
ui.goHomeOnUnmount->setChecked(true); ui.goHomeOnUnmount->setChecked(true);
} }
}
void PreferencesDialog::initTerminals(Settings& settings) { void PreferencesDialog::initTerminals(Settings& settings) {
// load the known terminal list from the terminal.list file of libfm // load the known terminal list from the terminal.list file of libfm
QSettings termlist(LIBFM_DATA_DIR "/terminals.list", QSettings::IniFormat); for(auto& terminal: Fm::allKnownTerminals()) {
ui.terminal->addItems(termlist.childGroups()); ui.terminal->addItem(terminal.get());
}
ui.terminal->setEditText(settings.terminal()); ui.terminal->setEditText(settings.terminal());
} }
@ -310,8 +320,9 @@ void PreferencesDialog::applyBehaviorPage(Settings& settings) {
settings.setViewMode(mode); settings.setViewMode(mode);
settings.setConfirmDelete(ui.configmDelete->isChecked()); settings.setConfirmDelete(ui.configmDelete->isChecked());
if(settings.supportTrash()) if(settings.supportTrash()) {
settings.setUseTrash(ui.useTrash->isChecked()); settings.setUseTrash(ui.useTrash->isChecked());
}
settings.setNoUsbTrash(ui.noUsbTrash->isChecked()); settings.setNoUsbTrash(ui.noUsbTrash->isChecked());
settings.setConfirmTrash(ui.confirmTrash->isChecked()); settings.setConfirmTrash(ui.confirmTrash->isChecked());
@ -378,8 +389,9 @@ void PreferencesDialog::lockMargins(bool lock) {
ui.vMargin->setValue(ui.hMargin->value()); ui.vMargin->setValue(ui.hMargin->value());
connect(ui.hMargin, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), ui.vMargin, &QSpinBox::setValue); connect(ui.hMargin, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), ui.vMargin, &QSpinBox::setValue);
} }
else else {
disconnect(ui.hMargin, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), ui.vMargin, &QSpinBox::setValue); disconnect(ui.hMargin, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), ui.vMargin, &QSpinBox::setValue);
} }
}
} // namespace PCManFM } // namespace PCManFM

@ -25,8 +25,7 @@
#include "ui_preferences.h" #include "ui_preferences.h"
#include <QString> #include <QString>
namespace PCManFM namespace PCManFM {
{
class Settings; class Settings;

@ -63,6 +63,10 @@ Settings::Settings():
closeOnUnmount_(false), closeOnUnmount_(false),
wallpaperMode_(0), wallpaperMode_(0),
wallpaper_(), wallpaper_(),
lastSlide_(),
wallpaperDir_(),
slideShowInterval_(0),
wallpaperRandomize_(false),
desktopBgColor_(), desktopBgColor_(),
desktopFgColor_(), desktopFgColor_(),
desktopShadowColor_(), desktopShadowColor_(),
@ -115,7 +119,13 @@ Settings::Settings():
sidePaneIconSize_(24), sidePaneIconSize_(24),
thumbnailIconSize_(128), thumbnailIconSize_(128),
folderViewCellMargins_(QSize(3, 3)), folderViewCellMargins_(QSize(3, 3)),
desktopCellMargins_(QSize(3, 1)) { desktopCellMargins_(QSize(3, 1)),
searchNameCaseInsensitive_(false),
searchContentCaseInsensitive_(false),
searchNameRegexp_(true),
searchContentRegexp_(true),
searchRecursive_(false),
searchhHidden_(false) {
} }
Settings::~Settings() { Settings::~Settings() {
@ -126,10 +136,12 @@ QString Settings::xdgUserConfigDir() {
QString dirName; QString dirName;
// WARNING: Don't use XDG_CONFIG_HOME with root because it might // WARNING: Don't use XDG_CONFIG_HOME with root because it might
// give the user config directory if gksu-properties is set to su. // give the user config directory if gksu-properties is set to su.
if(geteuid() != 0) // non-root user if(geteuid() != 0) { // non-root user
dirName = QStandardPaths::writableLocation(QStandardPaths::ConfigLocation); dirName = QStandardPaths::writableLocation(QStandardPaths::ConfigLocation);
if (dirName.isEmpty()) }
if(dirName.isEmpty()) {
dirName = QDir::homePath() % QLatin1String("/.config"); dirName = QDir::homePath() % QLatin1String("/.config");
}
return dirName; return dirName;
} }
@ -202,13 +214,19 @@ bool Settings::loadFile(QString filePath) {
settings.beginGroup("Desktop"); settings.beginGroup("Desktop");
wallpaperMode_ = wallpaperModeFromString(settings.value("WallpaperMode").toString()); wallpaperMode_ = wallpaperModeFromString(settings.value("WallpaperMode").toString());
wallpaper_ = settings.value("Wallpaper").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()); desktopBgColor_.setNamedColor(settings.value("BgColor", "#000000").toString());
desktopFgColor_.setNamedColor(settings.value("FgColor", "#ffffff").toString()); desktopFgColor_.setNamedColor(settings.value("FgColor", "#ffffff").toString());
desktopShadowColor_.setNamedColor(settings.value("ShadowColor", "#000000").toString()); desktopShadowColor_.setNamedColor(settings.value("ShadowColor", "#000000").toString());
if(settings.contains("Font")) if(settings.contains("Font")) {
desktopFont_.fromString(settings.value("Font").toString()); desktopFont_.fromString(settings.value("Font").toString());
else }
else {
desktopFont_ = QApplication::font(); desktopFont_ = QApplication::font();
}
desktopIconSize_ = settings.value("DesktopIconSize", 48).toInt(); desktopIconSize_ = settings.value("DesktopIconSize", 48).toInt();
showWmMenu_ = settings.value("ShowWmMenu", false).toBool(); showWmMenu_ = settings.value("ShowWmMenu", false).toBool();
desktopShowHidden_ = settings.value("ShowHidden", false).toBool(); desktopShowHidden_ = settings.value("ShowHidden", false).toBool();
@ -248,10 +266,10 @@ bool Settings::loadFile(QString filePath) {
shadowHidden_ = settings.value("ShadowHidden", false).toBool(); shadowHidden_ = settings.value("ShadowHidden", false).toBool();
// override config in libfm's FmConfig // override config in libfm's FmConfig
bigIconSize_ = settings.value("BigIconSize", 48).toInt(); bigIconSize_ = toIconSize(settings.value("BigIconSize", 48).toInt(), Big);
smallIconSize_ = settings.value("SmallIconSize", 24).toInt(); smallIconSize_ = toIconSize(settings.value("SmallIconSize", 24).toInt(), Small);
sidePaneIconSize_ = settings.value("SidePaneIconSize", 24).toInt(); sidePaneIconSize_ = toIconSize(settings.value("SidePaneIconSize", 24).toInt(), Small);
thumbnailIconSize_ = settings.value("ThumbnailIconSize", 128).toInt(); thumbnailIconSize_ = toIconSize(settings.value("ThumbnailIconSize", 128).toInt(), Thumbnail);
folderViewCellMargins_ = (settings.value("FolderViewCellMargins", QSize(3, 3)).toSize() folderViewCellMargins_ = (settings.value("FolderViewCellMargins", QSize(3, 3)).toSize()
.expandedTo(QSize(0, 0))).boundedTo(QSize(48, 48)); .expandedTo(QSize(0, 0))).boundedTo(QSize(48, 48));
@ -283,6 +301,15 @@ bool Settings::loadFile(QString filePath) {
pathBarButtons_ = settings.value("PathBarButtons", true).toBool(); pathBarButtons_ = settings.value("PathBarButtons", true).toBool();
settings.endGroup(); 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; return true;
} }
@ -319,6 +346,10 @@ bool Settings::saveFile(QString filePath) {
settings.beginGroup("Desktop"); settings.beginGroup("Desktop");
settings.setValue("WallpaperMode", wallpaperModeToString(wallpaperMode_)); settings.setValue("WallpaperMode", wallpaperModeToString(wallpaperMode_));
settings.setValue("Wallpaper", wallpaper_); 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("BgColor", desktopBgColor_.name());
settings.setValue("FgColor", desktopFgColor_.name()); settings.setValue("FgColor", desktopFgColor_.name());
settings.setValue("ShadowColor", desktopShadowColor_.name()); settings.setValue("ShadowColor", desktopShadowColor_.name());
@ -396,9 +427,46 @@ bool Settings::saveFile(QString filePath) {
// save per-folder settings // save per-folder settings
Fm::FolderConfig::saveCache(); 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; return true;
} }
const QList<int> & Settings::iconSizes(IconType type) {
static const QList<int> sizes_big = {96, 72, 64, 48, 32};
static const QList<int> sizes_thumbnail = {256, 224, 192, 160, 128, 96, 64};
static const QList<int> 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<int> & sizes = iconSizes(type);
for (const auto & s : sizes) {
if(size >= s) {
return s;
}
}
return sizes.back();
}
static const char* bookmarkOpenMethodToString(OpenDirTargetType value) { static const char* bookmarkOpenMethodToString(OpenDirTargetType value) {
switch(value) { switch(value) {
case OpenInCurrentTab: case OpenInCurrentTab:
@ -416,12 +484,15 @@ static const char* bookmarkOpenMethodToString(OpenDirTargetType value) {
static OpenDirTargetType bookmarkOpenMethodFromString(const QString str) { static OpenDirTargetType bookmarkOpenMethodFromString(const QString str) {
if(str == QStringLiteral("new_tab")) if(str == QStringLiteral("new_tab")) {
return OpenInNewTab; return OpenInNewTab;
else if(str == QStringLiteral("new_window")) }
else if(str == QStringLiteral("new_window")) {
return OpenInNewWindow; return OpenInNewWindow;
else if(str == QStringLiteral("last_window")) }
else if(str == QStringLiteral("last_window")) {
return OpenInLastActiveWindow; return OpenInLastActiveWindow;
}
return OpenInCurrentTab; return OpenInCurrentTab;
} }
@ -447,16 +518,21 @@ static const char* viewModeToString(Fm::FolderView::ViewMode value) {
Fm::FolderView::ViewMode viewModeFromString(const QString str) { Fm::FolderView::ViewMode viewModeFromString(const QString str) {
Fm::FolderView::ViewMode ret; Fm::FolderView::ViewMode ret;
if(str == "icon") if(str == "icon") {
ret = Fm::FolderView::IconMode; ret = Fm::FolderView::IconMode;
else if(str == "compact") }
else if(str == "compact") {
ret = Fm::FolderView::CompactMode; ret = Fm::FolderView::CompactMode;
else if(str == "detailed") }
else if(str == "detailed") {
ret = Fm::FolderView::DetailedListMode; ret = Fm::FolderView::DetailedListMode;
else if(str == "thumbnail") }
else if(str == "thumbnail") {
ret = Fm::FolderView::ThumbnailMode; ret = Fm::FolderView::ThumbnailMode;
else }
else {
ret = Fm::FolderView::IconMode; ret = Fm::FolderView::IconMode;
}
return ret; return ret;
} }
@ -493,18 +569,24 @@ static const char* sortColumnToString(Fm::FolderModel::ColumnId value) {
static Fm::FolderModel::ColumnId sortColumnFromString(const QString str) { static Fm::FolderModel::ColumnId sortColumnFromString(const QString str) {
Fm::FolderModel::ColumnId ret; Fm::FolderModel::ColumnId ret;
if(str == "name") if(str == "name") {
ret = Fm::FolderModel::ColumnFileName; ret = Fm::FolderModel::ColumnFileName;
else if(str == "type") }
else if(str == "type") {
ret = Fm::FolderModel::ColumnFileType; ret = Fm::FolderModel::ColumnFileType;
else if(str == "size") }
else if(str == "size") {
ret = Fm::FolderModel::ColumnFileSize; ret = Fm::FolderModel::ColumnFileSize;
else if(str == "mtime") }
else if(str == "mtime") {
ret = Fm::FolderModel::ColumnFileMTime; ret = Fm::FolderModel::ColumnFileMTime;
else if(str == "owner") }
else if(str == "owner") {
ret = Fm::FolderModel::ColumnFileOwner; ret = Fm::FolderModel::ColumnFileOwner;
else }
else {
ret = Fm::FolderModel::ColumnFileName; ret = Fm::FolderModel::ColumnFileName;
}
return ret; return ret;
} }
@ -536,18 +618,24 @@ static const char* wallpaperModeToString(int value) {
static int wallpaperModeFromString(const QString str) { static int wallpaperModeFromString(const QString str) {
int ret; int ret;
if(str == "stretch") if(str == "stretch") {
ret = DesktopWindow::WallpaperStretch; ret = DesktopWindow::WallpaperStretch;
else if(str == "fit") }
else if(str == "fit") {
ret = DesktopWindow::WallpaperFit; ret = DesktopWindow::WallpaperFit;
else if(str == "center") }
else if(str == "center") {
ret = DesktopWindow::WallpaperCenter; ret = DesktopWindow::WallpaperCenter;
else if(str == "tile") }
else if(str == "tile") {
ret = DesktopWindow::WallpaperTile; ret = DesktopWindow::WallpaperTile;
else if(str == "zoom") }
else if(str == "zoom") {
ret = DesktopWindow::WallpaperZoom; ret = DesktopWindow::WallpaperZoom;
else }
else {
ret = DesktopWindow::WallpaperNone; ret = DesktopWindow::WallpaperNone;
}
return ret; return ret;
} }
@ -570,12 +658,15 @@ static const char* sidePaneModeToString(Fm::SidePane::Mode value) {
static Fm::SidePane::Mode sidePaneModeFromString(const QString& str) { static Fm::SidePane::Mode sidePaneModeFromString(const QString& str) {
Fm::SidePane::Mode ret; Fm::SidePane::Mode ret;
if(str == "none") if(str == "none") {
ret = Fm::SidePane::ModeNone; ret = Fm::SidePane::ModeNone;
else if(str == "dirtree") }
else if(str == "dirtree") {
ret = Fm::SidePane::ModeDirTree; ret = Fm::SidePane::ModeDirTree;
else }
else {
ret = Fm::SidePane::ModePlaces; ret = Fm::SidePane::ModePlaces;
}
return ret; return ret;
} }
@ -589,7 +680,7 @@ void Settings::setTerminal(QString terminalCommand) {
// per-folder settings // per-folder settings
FolderSettings Settings::loadFolderSettings(Fm::Path path) const { FolderSettings Settings::loadFolderSettings(const Fm::FilePath& path) const {
FolderSettings settings; FolderSettings settings;
Fm::FolderConfig cfg(path); Fm::FolderConfig cfg(path);
// set defaults // set defaults
@ -643,8 +734,8 @@ FolderSettings Settings::loadFolderSettings(Fm::Path path) const {
return settings; return settings;
} }
void Settings::saveFolderSettings(Fm::Path path, const FolderSettings& settings) { void Settings::saveFolderSettings(const Fm::FilePath& path, const FolderSettings& settings) {
if(!path.isNull()) { if(path) {
// ensure that we have the libfm dir // ensure that we have the libfm dir
QString dirName = xdgUserConfigDir() % QStringLiteral("/libfm"); QString dirName = xdgUserConfigDir() % QStringLiteral("/libfm");
QDir().mkpath(dirName); // if libfm config dir does not exist, create it QDir().mkpath(dirName); // if libfm config dir does not exist, create it
@ -659,8 +750,8 @@ void Settings::saveFolderSettings(Fm::Path path, const FolderSettings& settings)
} }
} }
void Settings::clearFolderSettings(Fm::Path path) const { void Settings::clearFolderSettings(const Fm::FilePath& path) const {
if(!path.isNull()) { if(path) {
Fm::FolderConfig cfg(path); Fm::FolderConfig cfg(path);
cfg.purge(); cfg.purge();
} }

@ -27,7 +27,7 @@
#include <libfm-qt/foldermodel.h> #include <libfm-qt/foldermodel.h>
#include "desktopwindow.h" #include "desktopwindow.h"
#include <libfm-qt/sidepane.h> #include <libfm-qt/sidepane.h>
#include <libfm-qt/thumbnailloader.h> #include <libfm-qt/core/thumbnailjob.h>
namespace PCManFM { namespace PCManFM {
@ -121,6 +121,12 @@ private:
class Settings : public QObject { class Settings : public QObject {
Q_OBJECT Q_OBJECT
public: public:
enum IconType {
Small,
Big,
Thumbnail
};
Settings(); Settings();
virtual ~Settings(); virtual ~Settings();
@ -131,6 +137,7 @@ public:
bool saveFile(QString filePath); bool saveFile(QString filePath);
static QString xdgUserConfigDir(); static QString xdgUserConfigDir();
static const QList<int> & iconSizes(IconType type);
QString profileDir(QString profile, bool useFallback = false); QString profileDir(QString profile, bool useFallback = false);
@ -235,6 +242,38 @@ public:
wallpaper_ = wallpaper; wallpaper_ = wallpaper;
} }
QString wallpaperDir() const {
return wallpaperDir_;
}
void setLastSlide(QString wallpaper) {
lastSlide_ = wallpaper;
}
QString lastSlide() const {
return lastSlide_;
}
void setWallpaperDir(QString dir) {
wallpaperDir_ = dir;
}
int slideShowInterval() const {
return slideShowInterval_;
}
void setSlideShowInterval(int interval) {
slideShowInterval_ = interval;
}
bool wallpaperRandomize() const {
return wallpaperRandomize_;
}
void setWallpaperRandomize(bool randomize) {
wallpaperRandomize_ = randomize;
}
const QColor& desktopBgColor() const { const QColor& desktopBgColor() const {
return desktopBgColor_; return desktopBgColor_;
} }
@ -340,25 +379,31 @@ public:
} }
int windowWidth() const { int windowWidth() const {
if(rememberWindowSize_) if(rememberWindowSize_) {
return lastWindowWidth_; return lastWindowWidth_;
else }
else {
return fixedWindowWidth_; return fixedWindowWidth_;
} }
}
int windowHeight() const { int windowHeight() const {
if(rememberWindowSize_) if(rememberWindowSize_) {
return lastWindowHeight_; return lastWindowHeight_;
else }
else {
return fixedWindowHeight_; return fixedWindowHeight_;
} }
}
bool windowMaximized() const { bool windowMaximized() const {
if(rememberWindowSize_) if(rememberWindowSize_) {
return lastWindowMaximized_; return lastWindowMaximized_;
else }
else {
return false; return false;
} }
}
int fixedWindowWidth() const { int fixedWindowWidth() const {
return fixedWindowWidth_; return fixedWindowWidth_;
@ -560,8 +605,9 @@ public:
} }
bool useTrash() const { bool useTrash() const {
if(!supportTrash_) if(!supportTrash_) {
return false; return false;
}
return useTrash_; return useTrash_;
} }
@ -660,19 +706,19 @@ public:
} }
void setThumbnailLocalFilesOnly(bool value) { void setThumbnailLocalFilesOnly(bool value) {
Fm::ThumbnailLoader::setLocalFilesOnly(value); Fm::ThumbnailJob::setLocalFilesOnly(value);
} }
bool thumbnailLocalFilesOnly() { bool thumbnailLocalFilesOnly() const {
return Fm::ThumbnailLoader::localFilesOnly(); return Fm::ThumbnailJob::localFilesOnly();
} }
int maxThumbnailFileSize() { int maxThumbnailFileSize() const {
return Fm::ThumbnailLoader::maxThumbnailFileSize(); return Fm::ThumbnailJob::maxThumbnailFileSize();
} }
void setMaxThumbnailFileSize(int size) { void setMaxThumbnailFileSize(int size) {
Fm::ThumbnailLoader::setMaxThumbnailFileSize(size); Fm::ThumbnailJob::setMaxThumbnailFileSize(size);
} }
void setThumbnailIconSize(int thumbnailIconSize) { void setThumbnailIconSize(int thumbnailIconSize) {
@ -742,13 +788,63 @@ public:
} }
// per-folder settings // per-folder settings
FolderSettings loadFolderSettings(Fm::Path path) const; FolderSettings loadFolderSettings(const Fm::FilePath& path) const;
void saveFolderSettings(Fm::Path path, const FolderSettings &settings); void saveFolderSettings(const Fm::FilePath& path, const FolderSettings& settings);
void clearFolderSettings(Fm::Path path) const; void clearFolderSettings(const Fm::FilePath& path) const;
bool searchNameCaseInsensitive() const {
return searchNameCaseInsensitive_;
}
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: private:
int toIconSize(int size, IconType type) const;
QString profileName_; QString profileName_;
bool supportTrash_; bool supportTrash_;
@ -766,6 +862,10 @@ private:
int wallpaperMode_; int wallpaperMode_;
QString wallpaper_; QString wallpaper_;
QString lastSlide_;
QString wallpaperDir_;
int slideShowInterval_;
bool wallpaperRandomize_;
QColor desktopBgColor_; QColor desktopBgColor_;
QColor desktopFgColor_; QColor desktopFgColor_;
QColor desktopShadowColor_; QColor desktopShadowColor_;
@ -836,6 +936,14 @@ private:
QSize folderViewCellMargins_; QSize folderViewCellMargins_;
QSize desktopCellMargins_; QSize desktopCellMargins_;
// search settings
bool searchNameCaseInsensitive_;
bool searchContentCaseInsensitive_;
bool searchNameRegexp_;
bool searchContentRegexp_;
bool searchRecursive_;
bool searchhHidden_;
}; };
} }

@ -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 <QPainter>
#include <QStyleOption>
#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_);
}
}
}

@ -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 <QStatusBar>
#include <QLabel>
#include <QTimer>
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

@ -24,11 +24,13 @@
#include <libfm-qt/mountoperation.h> #include <libfm-qt/mountoperation.h>
#include <libfm-qt/proxyfoldermodel.h> #include <libfm-qt/proxyfoldermodel.h>
#include <libfm-qt/cachedfoldermodel.h> #include <libfm-qt/cachedfoldermodel.h>
#include <libfm-qt/fileinfo.h> #include <libfm-qt/core/fileinfo.h>
#include <libfm-qt/utilities.h>
#include <QApplication> #include <QApplication>
#include <QCursor> #include <QCursor>
#include <QMessageBox> #include <QMessageBox>
#include <QScrollBar> #include <QScrollBar>
#include <QDir>
#include "settings.h" #include "settings.h"
#include "application.h" #include "application.h"
#include <QTimer> #include <QTimer>
@ -39,42 +41,50 @@ using namespace Fm;
namespace PCManFM { namespace PCManFM {
bool ProxyFilter::filterAcceptsRow(const Fm::ProxyFolderModel* model, FmFileInfo* info) const { bool ProxyFilter::filterAcceptsRow(const Fm::ProxyFolderModel* model, const std::shared_ptr<const Fm::FileInfo>& info) const {
if(!model || !info) if(!model || !info) {
return true; return true;
QString baseName(fm_file_info_get_name(info)); }
if(!virtHiddenList_.isEmpty() && !model->showHidden() && virtHiddenList_.contains(baseName)) QString baseName = QString::fromStdString(info->name());
if(!virtHiddenList_.isEmpty() && !model->showHidden() && virtHiddenList_.contains(baseName)) {
return false; return false;
if(!filterStr_.isEmpty() && !baseName.contains(filterStr_, Qt::CaseInsensitive)) }
if(!filterStr_.isEmpty() && !baseName.contains(filterStr_, Qt::CaseInsensitive)) {
return false; return false;
}
return true; return true;
} }
void ProxyFilter::setVirtHidden(Fm::Folder folder) { void ProxyFilter::setVirtHidden(const std::shared_ptr<Fm::Folder> &folder) {
virtHiddenList_ = QStringList(); // reset the list virtHiddenList_ = QStringList(); // reset the list
if(folder.isNull()) if(!folder) {
return; return;
Fm::Path path = folder.getPath(); }
if(!path.isNull()) { auto path = folder->path();
char* pathStr = path.toStr(); if(path) {
auto pathStr = path.localPath();
if(pathStr) { if(pathStr) {
QString dotHidden = QString::fromUtf8(pathStr) + QString("/.hidden"); QString dotHidden = QString::fromUtf8(pathStr.get()) + QString("/.hidden");
g_free(pathStr);
// FIXME: this does not work for non-local filesystems // FIXME: this does not work for non-local filesystems
QFile file(dotHidden); QFile file(dotHidden);
if(file.open(QIODevice::ReadOnly | QIODevice::Text)) { if(file.open(QIODevice::ReadOnly | QIODevice::Text)) {
QTextStream in(&file); QTextStream in(&file);
while(!in.atEnd()) while(!in.atEnd()) {
virtHiddenList_.append(in.readLine()); virtHiddenList_.append(in.readLine());
}
file.close(); file.close();
} }
} }
} }
} }
TabPage::TabPage(Fm::Path path, QWidget* parent): TabPage::TabPage(QWidget* parent):
QWidget(parent), QWidget(parent),
folderModel_(NULL), folderView_{nullptr},
folderModel_{nullptr},
proxyModel_{nullptr},
proxyFilter_{nullptr},
verticalLayout{nullptr},
overrideCursor_(false) { overrideCursor_(false) {
Settings& settings = static_cast<Application*>(qApp)->settings(); Settings& settings = static_cast<Application*>(qApp)->settings();
@ -91,7 +101,7 @@ TabPage::TabPage(Fm::Path path, QWidget* parent):
folderView_ = new View(settings.viewMode(), this); folderView_ = new View(settings.viewMode(), this);
folderView_->setMargins(settings.folderViewCellMargins()); folderView_->setMargins(settings.folderViewCellMargins());
// newView->setColumnWidth(Fm::FolderModel::ColumnName, 200); // newView->setColumnWidth(Fm::FolderModel::ColumnName, 200);
connect(folderView_, &View::openDirRequested, this, &TabPage::onOpenDirRequested); connect(folderView_, &View::openDirRequested, this, &TabPage::openDirRequested);
connect(folderView_, &View::selChanged, this, &TabPage::onSelChanged); connect(folderView_, &View::selChanged, this, &TabPage::onSelChanged);
connect(folderView_, &View::clickedBack, this, &TabPage::backwardRequested); connect(folderView_, &View::clickedBack, this, &TabPage::backwardRequested);
connect(folderView_, &View::clickedForward, this, &TabPage::forwardRequested); connect(folderView_, &View::clickedForward, this, &TabPage::forwardRequested);
@ -102,18 +112,20 @@ TabPage::TabPage(Fm::Path path, QWidget* parent):
// FIXME: this is very dirty // FIXME: this is very dirty
folderView_->setModel(proxyModel_); folderView_->setModel(proxyModel_);
verticalLayout->addWidget(folderView_); verticalLayout->addWidget(folderView_);
chdir(path, true);
} }
TabPage::~TabPage() { TabPage::~TabPage() {
freeFolder(); freeFolder();
if(proxyFilter_) if(proxyFilter_) {
delete proxyFilter_; delete proxyFilter_;
if(proxyModel_) }
if(proxyModel_) {
delete proxyModel_; delete proxyModel_;
if(folderModel_) }
disconnect(folderModel_, &Fm::FolderModel::fileSizeChanged, this, &TabPage::onFileSizeChanged);
if(folderModel_) {
folderModel_->unref(); folderModel_->unref();
}
if(overrideCursor_) { if(overrideCursor_) {
QApplication::restoreOverrideCursor(); // remove busy cursor QApplication::restoreOverrideCursor(); // remove busy cursor
@ -121,30 +133,24 @@ TabPage::~TabPage() {
} }
void TabPage::freeFolder() { void TabPage::freeFolder() {
if(!folder_.isNull()) { if(folder_) {
if(folderSettings_.isCustomized()) { if(folderSettings_.isCustomized()) {
// save custom view settings for this folder // save custom view settings for this folder
static_cast<Application*>(qApp)->settings().saveFolderSettings(folder_.getPath(), folderSettings_); static_cast<Application*>(qApp)->settings().saveFolderSettings(folder_->path(), folderSettings_);
} }
g_signal_handlers_disconnect_by_func(folder_, (gpointer)onFolderStartLoading, this); disconnect(folder_.get(), nullptr, this, nullptr); // disconnect from all signals
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; folder_ = nullptr;
} }
} }
/*static*/ void TabPage::onFolderStartLoading(FmFolder* _folder, TabPage* pThis) { void TabPage::onFolderStartLoading() {
if(!pThis->overrideCursor_) { if(!overrideCursor_) {
// FIXME: sometimes FmFolder of libfm generates unpaired "start-loading" and // FIXME: sometimes FmFolder of libfm generates unpaired "start-loading" and
// "finish-loading" signals of uncertain reasons. This should be a bug in libfm. // "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 // Until it's fixed in libfm, we need to workaround the problem here, not to
// override the cursor twice. // override the cursor twice.
QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
pThis->overrideCursor_ = true; overrideCursor_ = true;
} }
#if 0 #if 0
#if FM_CHECK_VERSION(1, 0, 2) && 0 // disabled #if FM_CHECK_VERSION(1, 0, 2) && 0 // disabled
@ -161,35 +167,44 @@ void TabPage::freeFolder() {
} }
else else
#endif #endif
fm_folder_view_set_model(fv, NULL); fm_folder_view_set_model(fv, nullptr);
#endif #endif
} }
// slot void TabPage::onUiUpdated() {
void TabPage::restoreScrollPos() {
// scroll to recorded position // scroll to recorded position
folderView_->childView()->verticalScrollBar()->setValue(browseHistory().currentScrollPos()); folderView_->childView()->verticalScrollBar()->setValue(browseHistory().currentScrollPos());
// if the current folder is the parent folder of the last browsed folder, // if the current folder is the parent folder of the last browsed folder,
// select the folder item in current view. // select the folder item in current view.
if(!lastFolderPath_.isNull() && lastFolderPath_.getParent() == path()) { if(lastFolderPath_ && lastFolderPath_.parent() == path()) {
QModelIndex index = folderView_->indexFromFolderPath(lastFolderPath_); QModelIndex index = folderView_->indexFromFolderPath(lastFolderPath_);
if(index.isValid()) { if(index.isValid()) {
folderView_->childView()->scrollTo(index, QAbstractItemView::EnsureVisible); folderView_->childView()->scrollTo(index, QAbstractItemView::EnsureVisible);
folderView_->childView()->setCurrentIndex(index); folderView_->childView()->setCurrentIndex(index);
} }
} }
// update selection statusbar info when needed
connect(folderModel_, &Fm::FolderModel::fileSizeChanged, this, &TabPage::onFileSizeChanged);
} }
/*static*/ void TabPage::onFolderFinishLoading(FmFolder* _folder, TabPage* pThis) { void TabPage::onFileSizeChanged(const QModelIndex& index) {
// FIXME: is this needed? if(folderView_->hasSelection()) {
FmFileInfo* fi = fm_folder_get_info(_folder); QModelIndexList indexes = folderView_->selectionModel()->selectedIndexes();
if(indexes.contains(proxyModel_->mapFromSource(index))) {
onSelChanged();
}
}
}
void TabPage::onFolderFinishLoading() {
auto fi = folder_->info();
if(fi) { // if loading of the folder fails, it's possible that we don't have FmFileInfo. 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)); setWindowTitle(fi->displayName());
Q_EMIT pThis->titleChanged(pThis->title_); Q_EMIT titleChanged(fi->displayName());
} }
fm_folder_query_filesystem_info(_folder); // FIXME: is this needed? folder_->queryFilesystemInfo(); // FIXME: is this needed?
#if 0 #if 0
FmFolderView* fv = folder_view; FmFolderView* fv = folder_view;
const FmNavHistoryItem* item; const FmNavHistoryItem* item;
@ -202,7 +217,7 @@ void TabPage::restoreScrollPos() {
* and create the model again when it's fully loaded. * and create the model again when it's fully loaded.
* This optimization, however, is not used for FmFolder objects * This optimization, however, is not used for FmFolder objects
* with incremental loading (search://) */ * with incremental loading (search://) */
if(fm_folder_view_get_model(fv) == NULL) { if(fm_folder_view_get_model(fv) == nullptr) {
/* create a model for the folder and set it to the view */ /* create a model for the folder and set it to the view */
FmFolderModel* model = fm_folder_model_new(folder, app_config->show_hidden); FmFolderModel* model = fm_folder_model_new(folder, app_config->show_hidden);
fm_folder_view_set_model(fv, model); fm_folder_view_set_model(fv, model);
@ -218,26 +233,26 @@ void TabPage::restoreScrollPos() {
#endif #endif
// update status text // update status text
QString& text = pThis->statusText_[StatusTextNormal]; QString& text = statusText_[StatusTextNormal];
text = pThis->formatStatusText(); text = formatStatusText();
Q_EMIT pThis->statusChanged(StatusTextNormal, text); Q_EMIT statusChanged(StatusTextNormal, text);
if(pThis->overrideCursor_) { if(overrideCursor_) {
QApplication::restoreOverrideCursor(); // remove busy cursor QApplication::restoreOverrideCursor(); // remove busy cursor
pThis->overrideCursor_ = false; overrideCursor_ = false;
} }
// After finishing loading the folder, the model is updated, but Qt delays the UI update // 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 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. // For example, the scrollbar ranges are not updated yet. We solve this by installing an Qt timeout handler.
QTimer::singleShot(10, pThis, SLOT(restoreScrollPos())); QTimer::singleShot(10, this, SLOT(onUiUpdated()));
} }
/*static*/ FmJobErrorAction TabPage::onFolderError(FmFolder* _folder, GError* err, FmJobErrorSeverity severity, TabPage* pThis) { void TabPage::onFolderError(const Fm::GErrorPtr& err, Fm::Job::ErrorSeverity severity, Fm::Job::ErrorAction& response) {
if(err->domain == G_IO_ERROR) { if(err.domain() == G_IO_ERROR) {
if(err->code == G_IO_ERROR_NOT_MOUNTED && severity < FM_JOB_ERROR_CRITICAL) { if(err.code() == G_IO_ERROR_NOT_MOUNTED && severity < Fm::Job::ErrorSeverity::CRITICAL) {
FmPath* path = fm_folder_get_path(_folder); auto& path = folder_->path();
MountOperation* op = new MountOperation(pThis); MountOperation* op = new MountOperation(this);
op->mount(path); op->mount(path);
if(op->wait()) { // blocking event loop, wait for mount operation to finish. if(op->wait()) { // blocking event loop, wait for mount operation to finish.
// This will reload the folder, which generates a new "start-loading" // This will reload the folder, which generates a new "start-loading"
@ -246,12 +261,13 @@ void TabPage::restoreScrollPos() {
// Because the two signals are not correctly paired, we need to // Because the two signals are not correctly paired, we need to
// remove busy cursor here since "finish-loading" is not emitted. // remove busy cursor here since "finish-loading" is not emitted.
QApplication::restoreOverrideCursor(); // remove busy cursor QApplication::restoreOverrideCursor(); // remove busy cursor
pThis->overrideCursor_ = false; overrideCursor_ = false;
return FM_JOB_RETRY; response = Fm::Job::ErrorAction::RETRY;
return;
} }
} }
} }
if(severity >= FM_JOB_ERROR_MODERATE) { if(severity >= Fm::Job::ErrorSeverity::MODERATE) {
/* Only show more severe errors to the users and /* Only show more severe errors to the users and
* ignore milder errors. Otherwise too many error * ignore milder errors. Otherwise too many error
* message boxes can be annoying. * message boxes can be annoying.
@ -260,15 +276,15 @@ void TabPage::restoreScrollPos() {
* */ * */
// FIXME: consider replacing this modal dialog with an info bar to improve usability // FIXME: consider replacing this modal dialog with an info bar to improve usability
QMessageBox::critical(pThis, tr("Error"), QString::fromUtf8(err->message)); QMessageBox::critical(this, tr("Error"), err.message());
} }
return FM_JOB_CONTINUE; response = Fm::Job::ErrorAction::CONTINUE;
} }
/*static*/ void TabPage::onFolderFsInfo(FmFolder* _folder, TabPage* pThis) { void TabPage::onFolderFsInfo() {
guint64 free, total; guint64 free, total;
QString& msg = pThis->statusText_[StatusTextFSInfo]; QString& msg = statusText_[StatusTextFSInfo];
if(fm_folder_get_filesystem_info(_folder, &total, &free)) { if(folder_->getFilesystemInfo(&total, &free)) {
char total_str[64]; char total_str[64];
char free_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(free_str, sizeof(free_str), free, fm_config->si_unit);
@ -277,78 +293,90 @@ void TabPage::restoreScrollPos() {
.arg(QString::fromUtf8(free_str)) .arg(QString::fromUtf8(free_str))
.arg(QString::fromUtf8(total_str)); .arg(QString::fromUtf8(total_str));
} }
else else {
msg.clear(); msg.clear();
Q_EMIT pThis->statusChanged(StatusTextFSInfo, msg); }
Q_EMIT statusChanged(StatusTextFSInfo, msg);
} }
QString TabPage::formatStatusText() { QString TabPage::formatStatusText() {
if(proxyModel_ && !folder_.isNull()) { if(proxyModel_ && folder_) {
Fm::FileInfoList files = folder_.getFiles(); // FIXME: this is very inefficient
int total_files = fm_file_info_list_get_length(files); auto files = folder_->files();
int total_files = files.size();
int shown_files = proxyModel_->rowCount(); int shown_files = proxyModel_->rowCount();
int hidden_files = total_files - shown_files; int hidden_files = total_files - shown_files;
QString text = tr("%n item(s)", "", shown_files); QString text = tr("%n item(s)", "", shown_files);
if(hidden_files > 0) if(hidden_files > 0) {
text += tr(" (%n hidden)", "", hidden_files); text += tr(" (%n hidden)", "", hidden_files);
}
return text; return text;
} }
return QString(); return QString();
} }
/*static*/ void TabPage::onFolderRemoved(FmFolder* _folder, TabPage* pThis) { void TabPage::onFolderRemoved() {
// the folder we're showing is removed, destroy the widget // the folder we're showing is removed, destroy the widget
qDebug("folder removed"); qDebug("folder removed");
Settings& settings = static_cast<Application*>(qApp)->settings(); Settings& settings = static_cast<Application*>(qApp)->settings();
// NOTE: call pThis->deleteLater() directly from this GObject signal handler // NOTE: call deleteLater() directly from this GObject signal handler
// does not work but I don't know why. // does not work but I don't know why.
// Maybe it's the problem of glib mainloop integration? // Maybe it's the problem of glib mainloop integration?
// Call it when idle works, though. // Call it when idle works, though.
if(settings.closeOnUnmount()) if(settings.closeOnUnmount()) {
QTimer::singleShot(0, pThis, SLOT(deleteLater())); QTimer::singleShot(0, this, SLOT(deleteLater()));
else }
pThis->chdir(Fm::Path::getHome()); else {
chdir(Fm::FilePath::homeDir());
}
} }
/*static*/ void TabPage::onFolderUnmount(FmFolder* _folder, TabPage* pThis) { void TabPage::onFolderUnmount() {
// the folder we're showing is unmounted, destroy the widget // the folder we're showing is unmounted, destroy the widget
qDebug("folder unmount"); qDebug("folder unmount");
// NOTE: call pThis->deleteLater() directly from this GObject signal handler // NOTE: call deleteLater() directly from this GObject signal handler
// does not work but I don't know why. // does not work but I don't know why.
// Maybe it's the problem of glib mainloop integration? // Maybe it's the problem of glib mainloop integration?
// Call it when idle works, though. // Call it when idle works, though.
Settings& settings = static_cast<Application*>(qApp)->settings(); Settings& settings = static_cast<Application*>(qApp)->settings();
// NOTE: call pThis->deleteLater() directly from this GObject signal handler // NOTE: call deleteLater() directly from this GObject signal handler
// does not work but I don't know why. // does not work but I don't know why.
// Maybe it's the problem of glib mainloop integration? // Maybe it's the problem of glib mainloop integration?
// Call it when idle works, though. // Call it when idle works, though.
if(settings.closeOnUnmount()) if(settings.closeOnUnmount()) {
QTimer::singleShot(0, pThis, SLOT(deleteLater())); QTimer::singleShot(0, this, SLOT(deleteLater()));
else }
pThis->chdir(Fm::Path::getHome()); else {
chdir(Fm::FilePath::homeDir());
}
} }
/*static */ void TabPage::onFolderContentChanged(FmFolder* _folder, TabPage* pThis) { void TabPage::onFolderContentChanged() {
/* update status text */ /* update status text */
pThis->statusText_[StatusTextNormal] = pThis->formatStatusText(); statusText_[StatusTextNormal] = formatStatusText();
Q_EMIT pThis->statusChanged(StatusTextNormal, pThis->statusText_[StatusTextNormal]); Q_EMIT statusChanged(StatusTextNormal, statusText_[StatusTextNormal]);
} }
QString TabPage::pathName() { QString TabPage::pathName() {
char* disp_path = path().displayName(true); // auto disp_path = path().displayName();
QString ret = QString::fromUtf8(disp_path); // FIXME: displayName() returns invalid path sometimes.
g_free(disp_path); auto disp_path = path().toString();
return ret; return QString::fromUtf8(disp_path.get());
} }
void TabPage::chdir(Path newPath, bool addHistory) { void TabPage::chdir(Fm::FilePath newPath, bool addHistory) {
if(!folder_.isNull()) { // qDebug() << "TABPAGE CHDIR:" << newPath.toString().get();
if(folder_) {
// we're already in the specified dir // we're already in the specified dir
if(newPath == fm_folder_get_path(folder_)) if(newPath == folder_->path()) {
return; return;
}
// reset the status selected text
statusText_[StatusTextSelectedFiles] = QString();
// remember the previous folder path that we have browsed. // remember the previous folder path that we have browsed.
lastFolderPath_ = folder_.getPath(); lastFolderPath_ = folder_->path();
if(addHistory) { if(addHistory) {
// store current scroll pos in the browse history // store current scroll pos in the browse history
@ -359,18 +387,16 @@ void TabPage::chdir(Path newPath, bool addHistory) {
// free the previous model // free the previous model
if(folderModel_) { if(folderModel_) {
proxyModel_->setSourceModel(NULL); disconnect(folderModel_, &Fm::FolderModel::fileSizeChanged, this, &TabPage::onFileSizeChanged);
proxyModel_->setSourceModel(nullptr);
folderModel_->unref(); // unref the cached model folderModel_->unref(); // unref the cached model
folderModel_ = NULL; folderModel_ = nullptr;
} }
freeFolder(); freeFolder();
} }
char* disp_name = newPath.displayBasename(); Q_EMIT titleChanged(newPath.baseName().get()); // FIXME: display name
title_ = QString::fromUtf8(disp_name);
Q_EMIT titleChanged(title_);
g_free(disp_name);
folder_ = Fm::Folder::fromPath(newPath); folder_ = Fm::Folder::fromPath(newPath);
proxyFilter_->setVirtHidden(folder_); proxyFilter_->setVirtHidden(folder_);
@ -378,14 +404,16 @@ void TabPage::chdir(Path newPath, bool addHistory) {
// add current path to browse history // add current path to browse history
history_.add(path()); history_.add(path());
} }
g_signal_connect(folder_, "start-loading", G_CALLBACK(onFolderStartLoading), this); connect(folder_.get(), &Fm::Folder::startLoading, this, &TabPage::onFolderStartLoading);
g_signal_connect(folder_, "finish-loading", G_CALLBACK(onFolderFinishLoading), this); connect(folder_.get(), &Fm::Folder::finishLoading, this, &TabPage::onFolderFinishLoading);
g_signal_connect(folder_, "error", G_CALLBACK(onFolderError), this);
g_signal_connect(folder_, "fs-info", G_CALLBACK(onFolderFsInfo), this); // 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. */ /* destroy the page when the folder is unmounted or deleted. */
g_signal_connect(folder_, "removed", G_CALLBACK(onFolderRemoved), this); connect(folder_.get(), &Fm::Folder::removed, this, &TabPage::onFolderRemoved);
g_signal_connect(folder_, "unmount", G_CALLBACK(onFolderUnmount), this); connect(folder_.get(), &Fm::Folder::unmount, this, &TabPage::onFolderUnmount);
g_signal_connect(folder_, "content-changed", G_CALLBACK(onFolderContentChanged), this); connect(folder_.get(), &Fm::Folder::contentChanged, this, &TabPage::onFolderContentChanged);
folderModel_ = CachedFolderModel::modelFromFolder(folder_); folderModel_ = CachedFolderModel::modelFromFolder(folder_);
@ -400,13 +428,14 @@ void TabPage::chdir(Path newPath, bool addHistory) {
folderView_->setViewMode(folderSettings_.viewMode()); folderView_->setViewMode(folderSettings_.viewMode());
if(folder_.isLoaded()) { if(folder_->isLoaded()) {
onFolderStartLoading(folder_, this); onFolderStartLoading();
onFolderFinishLoading(folder_, this); onFolderFinishLoading();
onFolderFsInfo(folder_, this); onFolderFsInfo();
}
else {
onFolderStartLoading();
} }
else
onFolderStartLoading(folder_, this);
} }
void TabPage::selectAll() { void TabPage::selectAll() {
@ -417,34 +446,42 @@ void TabPage::invertSelection() {
folderView_->invertSelection(); folderView_->invertSelection();
} }
void TabPage::onOpenDirRequested(FmPath* path, int target) { void TabPage::reload() {
Q_EMIT openDirRequested(path, target); 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 // when the current selection in the folder view is changed
void TabPage::onSelChanged(int numSel) { void TabPage::onSelChanged() {
QString msg; QString msg;
if(numSel > 0) { if(folderView_->hasSelection()) {
auto files = folderView_->selectedFiles();
int numSel = files.size();
/* FIXME: display total size of all selected files. */ /* FIXME: display total size of all selected files. */
if(numSel == 1) { /* only one file is selected */ if(numSel == 1) { /* only one file is selected */
Fm::FileInfoList files = folderView_->selectedFiles(); auto& fi = files.front();
if(!files.isNull()) { if(!fi->isDir()) {
Fm::FileInfo fi = fm_file_info_list_peek_head(files);
const char* size_str = fi.getDispSize();
if(size_str) {
msg = QString("\"%1\" (%2) %3") msg = QString("\"%1\" (%2) %3")
.arg(QString::fromUtf8(fi.getDispName())) .arg(fi->displayName())
.arg(QString::fromUtf8(size_str)) .arg(Fm::formatFileSize(fi->size(), fm_config->si_unit)) // FIXME: deprecate fm_config
.arg(QString::fromUtf8(fi.getDesc())); .arg(fi->mimeType()->desc());
} }
else { else {
msg = QString("\"%1\" %2") msg = QString("\"%1\" %2")
.arg(QString::fromUtf8(fi.getDispName())) .arg(fi->displayName())
.arg(QString::fromUtf8(fi.getDesc())); .arg(fi->mimeType()->desc());
} }
/* FIXME: should we support statusbar plugins as in the gtk+ version? */ /* FIXME: should we support statusbar plugins as in the gtk+ version? */
} }
}
else { else {
goffset sum; goffset sum;
GList* l; GList* l;
@ -452,24 +489,17 @@ void TabPage::onSelChanged(int numSel) {
/* don't count if too many files are selected, that isn't lightweight */ /* don't count if too many files are selected, that isn't lightweight */
if(numSel < 1000) { if(numSel < 1000) {
sum = 0; sum = 0;
Fm::FileInfoList files = folderView_->selectedFiles(); for(auto& fi: files) {
if(!files.isNull()) { if(fi->isDir()) {
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 /* if we got a directory then we cannot tell it's size
unless we do deep count but we cannot afford it */ unless we do deep count but we cannot afford it */
sum = -1; sum = -1;
break; break;
} }
sum += fi.getSize(); sum += fi->size();
}
} }
if(sum >= 0) { if(sum >= 0) {
char size_str[128]; msg += QString(" (%1)").arg(Fm::formatFileSize(sum, fm_config->si_unit)); // FIXME: deprecate fm_config
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: should we support statusbar plugins as in the gtk+ version? */
} }
@ -502,8 +532,7 @@ void TabPage::forward() {
chdir(history_.currentPath(), false); chdir(history_.currentPath(), false);
} }
void TabPage::jumpToHistory(int index) void TabPage::jumpToHistory(int index) {
{
if(index >= 0 && index < history_.size()) { if(index >= 0 && index < history_.size()) {
// remember current scroll position // remember current scroll position
BrowseHistoryItem& item = history_.currentItem(); BrowseHistoryItem& item = history_.currentItem();
@ -516,15 +545,15 @@ void TabPage::jumpToHistory(int index)
} }
bool TabPage::canUp() { bool TabPage::canUp() {
Fm::Path _path = path(); auto _path = path();
return (!_path.isNull() && !_path.getParent().isNull()); return (_path && _path.hasParent());
} }
void TabPage::up() { void TabPage::up() {
Fm::Path _path = path(); auto _path = path();
if(!_path.isNull()) { if(_path) {
Fm::Path parent = _path.getParent(); auto parent = _path.parent();
if(!parent.isNull()) { if(parent) {
chdir(parent, true); chdir(parent, true);
} }
} }
@ -552,9 +581,10 @@ void TabPage::sort(int col, Qt::SortOrder order) {
static_cast<Application*>(qApp)->settings().saveFolderSettings(path(), folderSettings_); static_cast<Application*>(qApp)->settings().saveFolderSettings(path(), folderSettings_);
} }
} }
if(proxyModel_) if(proxyModel_) {
proxyModel_->sort(col, order); proxyModel_->sort(col, order);
} }
}
void TabPage::setSortFolderFirst(bool value) { void TabPage::setSortFolderFirst(bool value) {
if(folderSettings_.sortFolderFirst() != value) { if(folderSettings_.sortFolderFirst() != value) {
@ -584,24 +614,30 @@ void TabPage::setShowHidden(bool showHidden) {
static_cast<Application*>(qApp)->settings().saveFolderSettings(path(), folderSettings_); static_cast<Application*>(qApp)->settings().saveFolderSettings(path(), folderSettings_);
} }
} }
if(!proxyModel_ || showHidden == proxyModel_->showHidden()) if(!proxyModel_) {
return; return;
}
if(showHidden != proxyModel_->showHidden()) {
proxyModel_->setShowHidden(showHidden); proxyModel_->setShowHidden(showHidden);
}
// this may also be called by MainWindow::onTabPageSortFilterChanged to set status message
statusText_[StatusTextNormal] = formatStatusText(); statusText_[StatusTextNormal] = formatStatusText();
Q_EMIT statusChanged(StatusTextNormal, statusText_[StatusTextNormal]); Q_EMIT statusChanged(StatusTextNormal, statusText_[StatusTextNormal]);
} }
void TabPage::applyFilter() { void TabPage::applyFilter() {
if(!proxyModel_) if(!proxyModel_) {
return; return;
}
proxyModel_->updateFilters(); proxyModel_->updateFilters();
statusText_[StatusTextNormal] = formatStatusText(); statusText_[StatusTextNormal] = formatStatusText();
Q_EMIT statusChanged(StatusTextNormal, statusText_[StatusTextNormal]); Q_EMIT statusChanged(StatusTextNormal, statusText_[StatusTextNormal]);
} }
void TabPage::setCustomizedView(bool value) { void TabPage::setCustomizedView(bool value) {
if(folderSettings_.isCustomized() == value) if(folderSettings_.isCustomized() == value) {
return; return;
}
Settings& settings = static_cast<Application*>(qApp)->settings(); Settings& settings = static_cast<Application*>(qApp)->settings();
folderSettings_.setCustomized(value); folderSettings_.setCustomized(value);

@ -27,16 +27,18 @@
#include <libfm-qt/browsehistory.h> #include <libfm-qt/browsehistory.h>
#include "view.h" #include "view.h"
#include <libfm-qt/path.h> #include <libfm-qt/path.h>
#include <libfm-qt/folder.h>
#include <libfm-qt/fileinfo.h>
#include "settings.h" #include "settings.h"
#include <libfm-qt/core/fileinfo.h>
#include <libfm-qt/core/filepath.h>
#include <libfm-qt/core/folder.h>
namespace Fm { namespace Fm {
class FileLauncher; class FileLauncher;
class FolderModel; class FolderModel;
class ProxyFolderModel; class ProxyFolderModel;
class CachedFolderModel; class CachedFolderModel;
}; }
namespace PCManFM { namespace PCManFM {
@ -44,9 +46,9 @@ class Launcher;
class ProxyFilter : public Fm::ProxyFolderModelFilter { class ProxyFilter : public Fm::ProxyFolderModelFilter {
public: public:
bool filterAcceptsRow(const Fm::ProxyFolderModel* model, FmFileInfo* info) const; bool filterAcceptsRow(const Fm::ProxyFolderModel* model, const std::shared_ptr<const Fm::FileInfo>& info) const;
virtual ~ProxyFilter() {} virtual ~ProxyFilter() {}
void setVirtHidden(Fm::Folder folder); void setVirtHidden(const std::shared_ptr<Fm::Folder>& folder);
QString getFilterStr() { QString getFilterStr() {
return filterStr_; return filterStr_;
} }
@ -71,10 +73,10 @@ public:
}; };
public: public:
explicit TabPage(Fm::Path path, QWidget* parent = nullptr); explicit TabPage(QWidget* parent = nullptr);
virtual ~TabPage(); virtual ~TabPage();
void chdir(Fm::Path newPath, bool addHistory = true); void chdir(Fm::FilePath newPath, bool addHistory = true);
Fm::FolderView::ViewMode viewMode() { Fm::FolderView::ViewMode viewMode() {
return folderSettings_.viewMode(); return folderSettings_.viewMode();
@ -104,18 +106,18 @@ public:
void setSortCaseSensitive(bool value); void setSortCaseSensitive(bool value);
bool showHidden() { bool showHidden() {
return folderSettings_.showHidden(); return proxyModel_->showHidden();
} }
void setShowHidden(bool showHidden); void setShowHidden(bool showHidden);
Fm::Path path() { Fm::FilePath path() {
return Fm::Path(!folder_.isNull() ? folder_.getPath() : nullptr); return folder_ ? folder_->path() : Fm::FilePath();
} }
QString pathName(); QString pathName();
Fm::Folder& folder() { const std::shared_ptr<Fm::Folder>& folder() {
return folder_; return folder_;
} }
@ -135,7 +137,7 @@ public:
return folderView_->selectedFiles(); return folderView_->selectedFiles();
} }
Fm::PathList selectedFilePaths() { Fm::FilePathList selectedFilePaths() {
return folderView_->selectedFilePaths(); return folderView_->selectedFilePaths();
} }
@ -143,16 +145,7 @@ public:
void invertSelection(); void invertSelection();
void reload() { void reload();
if(!folder_.isNull()) {
proxyFilter_->setVirtHidden(folder_); // reread ".hidden"
folder_.reload();
}
}
QString title() const {
return title_;
}
QString statusText(StatusTextType type = StatusTextNormal) const { QString statusText(StatusTextType type = StatusTextNormal) const {
return statusText_[type]; return statusText_[type];
@ -187,15 +180,17 @@ public:
} }
QString getFilterStr() { QString getFilterStr() {
if(proxyFilter_) if(proxyFilter_) {
return proxyFilter_->getFilterStr(); return proxyFilter_->getFilterStr();
}
return QString(); return QString();
} }
void setFilterStr(QString str) { void setFilterStr(QString str) {
if(proxyFilter_) if(proxyFilter_) {
proxyFilter_->setFilterStr(str); proxyFilter_->setFilterStr(str);
} }
}
void applyFilter(); void applyFilter();
@ -208,27 +203,30 @@ public:
Q_SIGNALS: Q_SIGNALS:
void statusChanged(int type, QString statusText); void statusChanged(int type, QString statusText);
void titleChanged(QString title); void titleChanged(QString title);
void openDirRequested(FmPath* path, int target); void openDirRequested(const Fm::FilePath& path, int target);
void sortFilterChanged(); void sortFilterChanged();
void forwardRequested(); void forwardRequested();
void backwardRequested(); void backwardRequested();
protected Q_SLOTS: protected Q_SLOTS:
void onOpenDirRequested(FmPath* path, int target); void onSelChanged();
void onSelChanged(int numSel); void onUiUpdated();
void restoreScrollPos(); void onFileSizeChanged(const QModelIndex& index);
private: private:
void freeFolder(); void freeFolder();
QString formatStatusText(); QString formatStatusText();
static void onFolderStartLoading(FmFolder* _folder, TabPage* pThis); void onFolderStartLoading();
static void onFolderFinishLoading(FmFolder* _folder, TabPage* pThis); void onFolderFinishLoading();
static FmJobErrorAction onFolderError(FmFolder* _folder, GError* err, FmJobErrorSeverity severity, TabPage* pThis);
static void onFolderFsInfo(FmFolder* _folder, TabPage* pThis); // FIXME: this API design is bad and might be removed later
static void onFolderRemoved(FmFolder* _folder, TabPage* pThis); void onFolderError(const Fm::GErrorPtr& err, Fm::Job::ErrorSeverity severity, Fm::Job::ErrorAction& response);
static void onFolderUnmount(FmFolder* _folder, TabPage* pThis);
static void onFolderContentChanged(FmFolder* _folder, TabPage* pThis); void onFolderFsInfo();
void onFolderRemoved();
void onFolderUnmount();
void onFolderContentChanged();
private: private:
View* folderView_; View* folderView_;
@ -236,11 +234,10 @@ private:
Fm::ProxyFolderModel* proxyModel_; Fm::ProxyFolderModel* proxyModel_;
ProxyFilter* proxyFilter_; ProxyFilter* proxyFilter_;
QVBoxLayout* verticalLayout; QVBoxLayout* verticalLayout;
Fm::Folder folder_; std::shared_ptr<Fm::Folder> folder_;
QString title_;
QString statusText_[StatusTextNum]; QString statusText_[StatusTextNum];
Fm::BrowseHistory history_; // browsing history Fm::BrowseHistory history_; // browsing history
Fm::Path lastFolderPath_; // last browsed folder Fm::FilePath lastFolderPath_; // last browsed folder
bool overrideCursor_; bool overrideCursor_;
FolderSettings folderSettings_; FolderSettings folderSettings_;
}; };

@ -0,0 +1,4 @@
#Translations
Name[lt]=Darbalaukis
GenericName[lt]=Darbalaukio nustatymai
Comment[lt]=Keisti darbalaukio tvarkytuvės darbalaukio foną ir elgseną

@ -0,0 +1,4 @@
#Translations
Name[lt]=PCManFM failų tvarkytuvė
GenericName[lt]=Failų tvarkytuvė
Comment[lt]=Naršyti failų sistemą ir tvarkyti failus

@ -40,10 +40,10 @@ View::View(Fm::FolderView::ViewMode _mode, QWidget* parent):
View::~View() { View::~View() {
} }
void View::onFileClicked(int type, FmFileInfo* fileInfo) { void View::onFileClicked(int type, const std::shared_ptr<const Fm::FileInfo>& fileInfo) {
if(type == MiddleClick) { if(type == MiddleClick) {
if(fm_file_info_is_dir(fileInfo)) { if(fileInfo->isDir()) {
Q_EMIT openDirRequested(fm_file_info_get_path(fileInfo), OpenInNewTab); Q_EMIT openDirRequested(fileInfo->path(), OpenInNewTab);
} }
} }
else { else {
@ -60,18 +60,18 @@ void View::onNewWindow() {
void View::onNewTab() { void View::onNewTab() {
Fm::FileMenu* menu = static_cast<Fm::FileMenu*>(sender()->parent()); Fm::FileMenu* menu = static_cast<Fm::FileMenu*>(sender()->parent());
for(GList* l = fm_file_info_list_peek_head_link(menu->files()); l; l = l->next) { auto files = menu->files();
FmFileInfo* file = FM_FILE_INFO(l->data); for(auto& file: files) {
Q_EMIT openDirRequested(fm_file_info_get_path(file), OpenInNewTab); Q_EMIT openDirRequested(file->path(), OpenInNewTab);
} }
} }
void View::onOpenInTerminal() { void View::onOpenInTerminal() {
Application* app = static_cast<Application*>(qApp); Application* app = static_cast<Application*>(qApp);
Fm::FileMenu* menu = static_cast<Fm::FileMenu*>(sender()->parent()); Fm::FileMenu* menu = static_cast<Fm::FileMenu*>(sender()->parent());
for(GList* l = fm_file_info_list_peek_head_link(menu->files()); l; l = l->next) { auto files = menu->files();
Fm::FileInfo file = FM_FILE_INFO(l->data); for(auto& file: files) {
app->openFolderInTerminal(file.getPath()); app->openFolderInTerminal(file->path());
} }
} }
@ -88,17 +88,17 @@ void View::prepareFileMenu(Fm::FileMenu* menu) {
// add some more menu items for dirs // add some more menu items for dirs
bool all_native = true; bool all_native = true;
bool all_directory = true; bool all_directory = true;
Fm::FileInfoList files = menu->files(); auto files = menu->files();
for(GList* l = files.peekHeadLink(); l; l = l->next) { for(auto& fi: files) {
Fm::FileInfo fi = FM_FILE_INFO(l->data); if(!fi->isDir()) {
if(!fi.isDir())
all_directory = false; all_directory = false;
else if(fi.isDir() && !fi.isNative()) }
else if(fi->isDir() && !fi->isNative()) {
all_native = false; all_native = false;
} }
}
if (all_directory) if(all_directory) {
{
QAction* action = new QAction(QIcon::fromTheme("window-new"), tr("Open in New T&ab"), menu); QAction* action = new QAction(QIcon::fromTheme("window-new"), tr("Open in New T&ab"), menu);
connect(action, &QAction::triggered, this, &View::onNewTab); connect(action, &QAction::triggered, this, &View::onNewTab);
menu->insertAction(menu->separator1(), action); menu->insertAction(menu->separator1(), action);
@ -110,20 +110,21 @@ void View::prepareFileMenu(Fm::FileMenu* menu) {
// TODO: add search // TODO: add search
// action = menu->addAction(_("Search")); // action = menu->addAction(_("Search"));
if(all_native) if(all_native) {
{
action = new QAction(QIcon::fromTheme("utilities-terminal"), tr("Open in Termina&l"), menu); action = new QAction(QIcon::fromTheme("utilities-terminal"), tr("Open in Termina&l"), menu);
connect(action, &QAction::triggered, this, &View::onOpenInTerminal); connect(action, &QAction::triggered, this, &View::onOpenInTerminal);
menu->insertAction(menu->separator1(), action); menu->insertAction(menu->separator1(), action);
} }
} }
else { else {
if(menu->pasteAction()) // NULL for trash if(menu->pasteAction()) { // nullptr for trash
menu->pasteAction()->setVisible(false); menu->pasteAction()->setVisible(false);
if(menu->createAction()) }
if(menu->createAction()) {
menu->createAction()->setVisible(false); menu->createAction()->setVisible(false);
} }
} }
}
void View::prepareFolderMenu(Fm::FolderMenu* menu) { void View::prepareFolderMenu(Fm::FolderMenu* menu) {
} }

@ -22,6 +22,8 @@
#define PCMANFM_FOLDERVIEW_H #define PCMANFM_FOLDERVIEW_H
#include <libfm-qt/folderview.h> #include <libfm-qt/folderview.h>
#include <libfm-qt/core/filepath.h>
namespace Fm { namespace Fm {
class FileMenu; class FileMenu;
@ -49,7 +51,7 @@ public:
} }
Q_SIGNALS: Q_SIGNALS:
void openDirRequested(FmPath* path, int target); void openDirRequested(const Fm::FilePath& path, int target);
protected Q_SLOTS: protected Q_SLOTS:
void onNewWindow(); void onNewWindow();
@ -58,7 +60,7 @@ protected Q_SLOTS:
void onSearch(); void onSearch();
protected: protected:
virtual void onFileClicked(int type, FmFileInfo* fileInfo); virtual void onFileClicked(int type, const std::shared_ptr<const Fm::FileInfo>& fileInfo);
virtual void prepareFileMenu(Fm::FileMenu* menu); virtual void prepareFileMenu(Fm::FileMenu* menu);
virtual void prepareFolderMenu(Fm::FolderMenu* menu); virtual void prepareFolderMenu(Fm::FolderMenu* menu);
@ -66,5 +68,5 @@ private:
}; };
}; }
#endif // PCMANFM_FOLDERVIEW_H #endif // PCMANFM_FOLDERVIEW_H

Loading…
Cancel
Save