Cherry-picking upstream release 0.13.0.

* Bumped build dependency libfm-qt-dev to >= 0.13.0~
* Bumped build dependency lxqt-build-tools to >= 0.5.0~
* Added papirus-icon-theme as default alternative for icon-themes
* Bumped year in copyright
* Removed ported back upstream patches.
* Moved debian/.gitignore -> ./.gitignore
ubuntu/disco debian/0.13.0-1
Alf Gaida 6 years ago
parent 6c761062c5
commit 0bb15fb1bf

17
.gitignore vendored

@ -1,11 +1,8 @@
/*.debhelper debian/*.debhelper
/*.log debian/*.log
/*.substvars debian/*.substvars
/debhelper-build-stamp debian/debhelper-build-stamp
/files debian/files
/mangled
debian/pcmanfm-qt/
/pcmanfm-qt/
/libfm-qt5-2/
/libfm-qt5-dev/
/tmp

@ -1,5 +1,5 @@
Upstream Authors: Upstream Authors:
LXQt team: http://lxqt.org LXQt team: https://lxqt.org
Hong Jen Yee (PCMan) <pcman.tw@gmail.com> Hong Jen Yee (PCMan) <pcman.tw@gmail.com>
Copyright: Copyright:

@ -1,7 +1,59 @@
pcmanfm-qt-0.12.0 / 2017-10-21 pcmanfm-qt-0.13.0 / 2018-05-21
============================== ==============================
* Check minimum version of libfm-qt
* Bumped minor version to 13
* Spanish translation update
* Avoid using the old FmPath struct in libfm and use libfm-qt Fm::FilePath instead.
* Just changed a label in Preferences
* Replace the deprecated Fm::MountOperation::mount() with Fm::MountOperation::mountEnclosingVolume().
* Cleanup
* Migrate to the new libfm-qt Fm::FileLauncher API.
* CMake: Prevent in-source builds
* Use new libfm-qt Fm::Archiver API. (#660)
* Fixed tab close button setting
* Optionally select newly created files
* fixes http -> https
* Fixed some lxde mentions
* Drop usage of Fm::IconTheme
* Add symlink target info to statusbar
* Add Simplified Chinese desktop entries (#640)
* Follow GLib to know if a file is hidden
* Remember hidden Places items between sessions
* Drop Qt foreach
* Use QString Use multi-arg
* Prevent a possible c++11 range-loop detach container (QList)
* Don't call QList::first() on temporary
* Warnings (#625)
* move config to /usr/share/pcmanfm-qt/lxqt
* Fixed the setting for "backup as hidden"" (#614)
* Sweep a desktop mess under the carpet
* cmake: Don't set CMP0063
* cmake: Handle CMP0071 - Mark DBus files with SKIP_AUTOGEN
* cmake: Handle CMP0071 related to UI files.
* Refer to PCManFM-Qt in desktop entries
* Add Spanish desktop entries
* Use QChars
* Simplify if statements
* Const it
* Fix typos, move encloseWithBidiMarks to private and fix its behaviour
* Fix direction of statusbar message
* Give context to singleShot()
* Added a short comment
* Wait for events to be processed before chdir
* Rename progress dialog
* Basic bulk rename
* Really cancel multiple renaming on cancelling
* Initialize dragStarted_ in constructor
* Compact disconnection format
* Tab DND
* View tool-buttons
0.12.0 / 2017-10-21
===================
* Release 0.12.0: Update changelog
* Set Version * Set Version
* removed dangeling symlink to debian dir * removed dangeling symlink to debian dir
* Text eliding, long texts and newline * Text eliding, long texts and newline

@ -1,39 +1,38 @@
cmake_minimum_required(VERSION 3.0.2) cmake_minimum_required(VERSION 3.0.2)
project(pcmanfm-qt) project(pcmanfm-qt)
# CMP0063: Honor visibility properties for all target types.
if (POLICY CMP0063)
cmake_policy (SET CMP0063 NEW)
endif (POLICY CMP0063)
# PcmanFm-Qt Version # PcmanFm-Qt Version
set(PCMANFM_QT_VERSION_MAJOR 0) set(PCMANFM_QT_VERSION_MAJOR 0)
set(PCMANFM_QT_VERSION_MINOR 12) set(PCMANFM_QT_VERSION_MINOR 13)
set(PCMANFM_QT_VERSION_PATCH 0) 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.4.0") set(QT_MINIMUM_VERSION "5.7.1")
set(LXQTBT_MINIMUM_VERSION "0.5.0")
set(LIBFMQT_MINIMUM_VERSION "5.0.0")
list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake") list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake")
find_package(Qt5Widgets 5.2 REQUIRED) find_package(Qt5Widgets ${QT_MINIMUM_VERSION} REQUIRED)
find_package(Qt5DBus 5.2 REQUIRED) find_package(Qt5DBus ${QT_MINIMUM_VERSION} REQUIRED)
find_package(Qt5LinguistTools 5.2 REQUIRED) find_package(Qt5LinguistTools ${QT_MINIMUM_VERSION} REQUIRED)
find_package(Qt5X11Extras 5.2 REQUIRED) find_package(Qt5X11Extras ${QT_MINIMUM_VERSION} REQUIRED)
find_package(fm-qt REQUIRED) find_package(fm-qt ${LIBFMQT_MINIMUM_VERSION} 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}") 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(LXQtPreventInSourceBuilds)
include(LXQtConfigVars) include(LXQtConfigVars)
include(LXQtTranslateTs) include(LXQtTranslateTs)
include(LXQtTranslateDesktop) include(LXQtTranslateDesktop)
include(LXQtCompilerSettings NO_POLICY_SCOPE) include(LXQtCompilerSettings NO_POLICY_SCOPE)
set(CMAKE_AUTOMOC TRUE) set(CMAKE_AUTOMOC TRUE)
set(CMAKE_AUTOUIC ON)
set(CMAKE_INCLUDE_CURRENT_DIR ON) set(CMAKE_INCLUDE_CURRENT_DIR ON)
add_subdirectory(pcmanfm) add_subdirectory(pcmanfm)

@ -2,38 +2,61 @@
## Overview ## Overview
PCManFM-Qt is the Qt port of PCManFM, the file manager of [LXDE](http://lxde.org). PCManFM-Qt is the Qt port of PCManFM, the file manager of [LXDE](https://lxde.org).
In LXQt sessions it is in addition used to handle the desktop. Nevertheless it can be used independently of LXQt as well. In LXQt sessions it is in addition used to handle the desktop. Nevertheless it
can be used independently of LXQt as well.
PCManFM-Qt is licensed under the terms of the [GPLv2](https://www.gnu.org/licenses/gpl-2.0.en.html) or any later version. See file LICENSE for its full text. PCManFM-Qt is licensed under the terms of the
[GPLv2](https://www.gnu.org/licenses/gpl-2.0.en.html) or any later version. See
file LICENSE for its full text.
## Installation ## Installation
### Compiling source code ### Compiling source code
Runtime dependencies are qtx11extras, lxmenu-data, [liblxqt](https://github.com/lxde/liblxqt) and [libfm-qt](https://github.com/lxde/libfm-qt). Runtime dependencies are qtx11extras, lxmenu-data,
Additional build dependencies are CMake and optionally Git to pull latest VCS checkouts. The localization files were outsourced to repository [lxqt-l10n](https://github.com/lxde/lxqt-l10n) so the corresponding dependencies are needed, too. Please refer to this repository's `README.md` for further information. [liblxqt](https://github.com/lxqt/liblxqt) and
[libfm-qt](https://github.com/lxqt/libfm-qt).
Additional build dependencies are CMake and optionally Git to pull latest VCS
checkouts. The localization files were outsourced to repository
[lxqt-l10n](https://github.com/lxqt/lxqt-l10n) so the corresponding dependencies
are needed, too. Please refer to this repository's `README.md` for further information.
Code configuration is handled by CMake. CMake variable `CMAKE_INSTALL_PREFIX` has to be set to `/usr` on most operating systems, depending on the way library paths are dealt with on 64bit systems variables like `CMAKE_INSTALL_LIBDIR` may have to be set as well. Code configuration is handled by CMake. CMake variable `CMAKE_INSTALL_PREFIX`
has to be set to `/usr` on most operating systems, depending on the way library
paths are dealt with on 64bit systems variables like `CMAKE_INSTALL_LIBDIR` may
have to be set as well.
To build run `make`, to install `make install` which accepts variable `DESTDIR` as usual. To build run `make`, to install `make install` which accepts variable `DESTDIR`
as usual.
### Binary packages ### Binary packages
Official binary packages are available in Arch Linux, Debian (as of Debian stretch), Fedora (version 0.10.0 only so far) and openSUSE (Leap 42.1 and Tumbleweed). Official binary packages are available in Arch Linux, Debian (as of Debian stretch),
Fedora (version 0.10.0 only so far) and openSUSE (Leap 42.1 and Tumbleweed).
## Usage ## Usage
The file manager functionality should be self-explanatory, handling of the desktop deserves some notes: The file manager functionality should be self-explanatory, handling of the
desktop deserves some notes:
To handle the desktop binary `pcmanfm-qt` has to be launched with switch `--desktop` set. Optionally switch `--profile` can be used to safe settings specific to certain session types like the different desktop environments. To handle the desktop binary `pcmanfm-qt` has to be launched with switch
In LXQt sessions, PCManFM-Qt is launched with theses switches set as [LXQt Module](https://github.com/lxde/lxqt-session#lxqt-modules). `--desktop` set. Optionally switch `--profile` can be used to safe settings
specific to certain session types like the different desktop environments.
In LXQt sessions, PCManFM-Qt is launched with theses switches set as
[LXQt Module](https://github.com/lxqt/lxqt-session#lxqt-modules).
To configure the desktop there's a dialogue "Desktop Preferences". Technically it corresponds with launching `pcmanfm-qt` with switch `--desktop-pref` set. It is available in the desktop's context menu and included as topic "Desktop" in sub-menu Preferences - LXQt settings of the panel's main menu as well as the [Configuration Center](https://github.com/lxde/lxqt-config#configuration-center) of lxqt-config. To configure the desktop there's a dialogue "Desktop Preferences". Technically
it corresponds with launching `pcmanfm-qt` with switch `--desktop-pref` set. It
is available in the desktop's context menu and included as topic "Desktop" in
sub-menu Preferences - LXQt settings of the panel's main menu as well as the
[Configuration Center](https://github.com/lxqt/lxqt-config#configuration-center)
of lxqt-config.
All switches (command line options) mentioned above are explained in detail in `man 1 pcmanfm-qt`. All switches (command line options) mentioned above are explained in detail in
`man 1 pcmanfm-qt`.
## Development ## Development
Issues should go to the tracker of PCManFM-Qt at https://github.com/lxde/pcmanfm-qt/issues. Issues should go to the tracker of PCManFM-Qt at https://github.com/lxqt/pcmanfm-qt/issues.

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

@ -3,6 +3,6 @@
configure_file(pcmanfm-qt/lxqt/settings.conf.in pcmanfm-qt/lxqt/settings.conf @ONLY) configure_file(pcmanfm-qt/lxqt/settings.conf.in pcmanfm-qt/lxqt/settings.conf @ONLY)
install(FILES install(FILES
"${CMAKE_CURRENT_BINARY_DIR}/pcmanfm-qt/lxqt/settings.conf" "${CMAKE_CURRENT_BINARY_DIR}/pcmanfm-qt/lxqt/settings.conf"
DESTINATION "${LXQT_ETC_XDG_DIR}/pcmanfm-qt/lxqt" DESTINATION "${CMAKE_INSTALL_DATADIR}/pcmanfm-qt/lxqt"
COMPONENT Runtime COMPONENT Runtime
) )

10
debian/changelog vendored

@ -1,8 +1,14 @@
pcmanfm-qt (0.13.0-1) experimental; urgency=medium pcmanfm-qt (0.13.0-1) experimental; urgency=medium
* * Cherry-picking upstream release 0.13.0.
* Bumped build dependency libfm-qt-dev to >= 0.13.0~
* Bumped build dependency lxqt-build-tools to >= 0.5.0~
* Added papirus-icon-theme as default alternative for icon-themes
* Bumped year in copyright
* Removed ported back upstream patches.
* Moved debian/.gitignore -> ./.gitignore
-- Alf Gaida <agaida@siduction.org> Mon, 21 May 2018 16:54:34 +0200 -- Alf Gaida <agaida@siduction.org> Sat, 26 May 2018 02:25:19 +0200
pcmanfm-qt (0.12.0-6) unstable; urgency=medium pcmanfm-qt (0.12.0-6) unstable; urgency=medium

@ -14,9 +14,10 @@ set(pcmanfm_SRCS
autorundialog.cpp autorundialog.cpp
connectserverdialog.cpp connectserverdialog.cpp
settings.cpp settings.cpp
bulkrename.cpp
) )
qt5_add_dbus_adaptor(pcmanfm_SRCS qt5_add_dbus_adaptor(pcmanfm_DBUS_SRCS
org.pcmanfm.Application.xml org.pcmanfm.Application.xml
application.h application.h
PCManFM::Application PCManFM::Application
@ -24,6 +25,11 @@ qt5_add_dbus_adaptor(pcmanfm_SRCS
ApplicationAdaptor ApplicationAdaptor
) )
# qt5_add_dbus_adaptor() already generated the moc files. It also marked the
# files with SKIP_AUTOMOC but we still need to mark them witk SKIP_AUTOGEN.
# TODO: Check if this behaviour is a CMake bug.
set_source_files_properties(${pcmanfm_DBUS_SRCS} PROPERTIES SKIP_AUTOGEN ON)
set(pcmanfm_UIS set(pcmanfm_UIS
main-win.ui main-win.ui
about.ui about.ui
@ -32,10 +38,9 @@ set(pcmanfm_UIS
desktop-folder.ui desktop-folder.ui
autorun.ui autorun.ui
connect.ui connect.ui
bulk-rename.ui
) )
qt5_wrap_ui(pcmanfm_UIS_H ${pcmanfm_UIS})
# add translation for pcmanfm-qt # add translation for pcmanfm-qt
lxqt_translate_ts(QM_FILES lxqt_translate_ts(QM_FILES
UPDATE_TRANSLATIONS ${UPDATE_TRANSLATIONS} UPDATE_TRANSLATIONS ${UPDATE_TRANSLATIONS}
@ -56,7 +61,8 @@ lxqt_translate_desktop(DESKTOP_FILES
add_executable(pcmanfm-qt add_executable(pcmanfm-qt
${pcmanfm_SRCS} ${pcmanfm_SRCS}
${pcmanfm_UIS_H} ${pcmanfm_DBUS_SRCS}
${pcmanfm_UIS}
${QM_FILES} ${QM_FILES}
${DESKTOP_FILES} ${DESKTOP_FILES}
) )
@ -66,6 +72,7 @@ target_compile_definitions(pcmanfm-qt
PCMANFM_DATA_DIR="${CMAKE_INSTALL_PREFIX}/share/pcmanfm-qt" PCMANFM_DATA_DIR="${CMAKE_INSTALL_PREFIX}/share/pcmanfm-qt"
PCMANFM_QT_VERSION="${PCMANFM_QT_VERSION}" PCMANFM_QT_VERSION="${PCMANFM_QT_VERSION}"
LIBFM_DATA_DIR="${PKG_FM_PREFIX}/share/libfm" LIBFM_DATA_DIR="${PKG_FM_PREFIX}/share/libfm"
QT_NO_FOREACH
) )
target_include_directories(pcmanfm-qt target_include_directories(pcmanfm-qt

@ -55,7 +55,7 @@
<item> <item>
<widget class="QLabel" name="label_3"> <widget class="QLabel" name="label_3">
<property name="text"> <property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;a href=&quot;http://lxqt.org/&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;http://lxqt.org/&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string> <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;a href=&quot;https://lxqt.org/&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;https://lxqt.org/&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property> </property>
<property name="textFormat"> <property name="textFormat">
<enum>Qt::RichText</enum> <enum>Qt::RichText</enum>

@ -42,7 +42,6 @@
#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/core/terminal.h> #include <libfm-qt/core/terminal.h>
#include "applicationadaptor.h" #include "applicationadaptor.h"
@ -109,7 +108,6 @@ Application::Application(int& argc, char** argv):
if(settings_.useFallbackIconTheme()) { if(settings_.useFallbackIconTheme()) {
QIcon::setThemeName(settings_.fallbackIconThemeName()); QIcon::setThemeName(settings_.fallbackIconThemeName());
Fm::IconTheme::checkChanged();
} }
// Check if LXQt Session is running. LXQt has it's own Desktop Folder // Check if LXQt Session is running. LXQt has it's own Desktop Folder
@ -379,7 +377,7 @@ void Application::onLastWindowClosed() {
} }
void Application::onSaveStateRequest(QSessionManager& manager) { void Application::onSaveStateRequest(QSessionManager& /*manager*/) {
} }
@ -390,7 +388,8 @@ void Application::desktopManager(bool enabled) {
if(enabled) { if(enabled) {
if(!enableDesktopManager_) { if(!enableDesktopManager_) {
// installNativeEventFilter(this); // installNativeEventFilter(this);
Q_FOREACH(QScreen* screen, screens()) { const auto allScreens = screens();
for(QScreen* screen : allScreens) {
connect(screen, &QScreen::virtualGeometryChanged, this, &Application::onVirtualGeometryChanged); connect(screen, &QScreen::virtualGeometryChanged, this, &Application::onVirtualGeometryChanged);
connect(screen, &QObject::destroyed, this, &Application::onScreenDestroyed); connect(screen, &QObject::destroyed, this, &Application::onScreenDestroyed);
} }
@ -425,7 +424,8 @@ void Application::desktopManager(bool enabled) {
delete window; delete window;
} }
desktopWindows_.clear(); desktopWindows_.clear();
Q_FOREACH(QScreen* screen, screens()) { const auto allScreens = screens();
for(QScreen* screen : allScreens) {
disconnect(screen, &QScreen::virtualGeometryChanged, this, &Application::onVirtualGeometryChanged); disconnect(screen, &QScreen::virtualGeometryChanged, this, &Application::onVirtualGeometryChanged);
disconnect(screen, &QObject::destroyed, this, &Application::onScreenDestroyed); disconnect(screen, &QObject::destroyed, this, &Application::onScreenDestroyed);
} }
@ -460,10 +460,8 @@ void Application::onFindFileAccepted() {
settings_.setSearchRecursive(dlg->recursive()); settings_.setSearchRecursive(dlg->recursive());
settings_.setSearchhHidden(dlg->searchhHidden()); settings_.setSearchhHidden(dlg->searchhHidden());
Fm::Path uri = dlg->searchUri();
Fm::FilePathList paths; Fm::FilePathList paths;
Fm::GFilePtr gf{uri.toGfile(), false}; paths.emplace_back(dlg->searchUri());
paths.push_back(Fm::FilePath{gf.get(), true});
MainWindow* window = MainWindow::lastActive(); MainWindow* window = MainWindow::lastActive();
Launcher(window).launchPaths(nullptr, paths); Launcher(window).launchPaths(nullptr, paths);
} }
@ -500,11 +498,11 @@ void Application::connectToServer() {
dlg->show(); dlg->show();
} }
void Application::launchFiles(QString cwd, QStringList paths, bool inNewWindow) { void Application::launchFiles(QString cwd, QStringList paths, bool /*inNewWindow*/) {
Fm::FilePathList pathList; Fm::FilePathList pathList;
Fm::FilePath cwd_path; Fm::FilePath cwd_path;
QStringList::iterator it; QStringList::iterator it;
Q_FOREACH(const QString& it, paths) { for(const QString& it : qAsConst(paths)) {
QByteArray pathName = it.toLocal8Bit(); QByteArray pathName = it.toLocal8Bit();
Fm::FilePath path; Fm::FilePath path;
if(pathName == "~") { // special case for home dir if(pathName == "~") { // special case for home dir
@ -588,7 +586,7 @@ void Application::setWallpaper(QString path, QString modeString) {
// update wallpaper // update wallpaper
if(changed) { if(changed) {
if(enableDesktopManager_) { if(enableDesktopManager_) {
Q_FOREACH(DesktopWindow* desktopWindow, desktopWindows_) { for(DesktopWindow* desktopWindow : qAsConst(desktopWindows_)) {
if(!path.isEmpty()) { if(!path.isEmpty()) {
desktopWindow->setWallpaperFile(path); desktopWindow->setWallpaperFile(path);
} }
@ -760,7 +758,7 @@ 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);
} }
@ -788,7 +786,7 @@ void Application::onScreenAdded(QScreen* newScreen) {
void Application::onScreenDestroyed(QObject* screenObj) { void Application::onScreenDestroyed(QObject* screenObj) {
// NOTE by PCMan: This is a workaround for Qt 5 bug #40681. // NOTE by PCMan: This is a workaround for Qt 5 bug #40681.
// With this very dirty workaround, we can fix lxde/lxde-qt bug #204, #205, and #206. // With this very dirty workaround, we can fix lxqt/lxqt bug #204, #205, and #206.
// Qt 5 has two new regression bugs which breaks lxqt-panel in a multihead environment. // Qt 5 has two new regression bugs which breaks lxqt-panel in a multihead environment.
// #40681: Regression bug: QWidget::winId() returns old value and QEvent::WinIdChange event is not emitted sometimes. (multihead setup) // #40681: Regression bug: QWidget::winId() returns old value and QEvent::WinIdChange event is not emitted sometimes. (multihead setup)
// #40791: Regression: QPlatformWindow, QWindow, and QWidget::winId() are out of sync. // #40791: Regression: QPlatformWindow, QWindow, and QWidget::winId() are out of sync.
@ -814,7 +812,7 @@ void Application::onScreenDestroyed(QObject* screenObj) {
if(enableDesktopManager_) { if(enableDesktopManager_) {
bool reloadNeeded = false; bool reloadNeeded = false;
// FIXME: add workarounds for Qt5 bug #40681 and #40791 here. // FIXME: add workarounds for Qt5 bug #40681 and #40791 here.
Q_FOREACH(DesktopWindow* desktop, desktopWindows_) { for(DesktopWindow* desktop : qAsConst(desktopWindows_)) {
if(desktop->windowHandle()->screen() == screenObj) { if(desktop->windowHandle()->screen() == screenObj) {
desktop->destroy(); // destroy the underlying native window desktop->destroy(); // destroy the underlying native window
reloadNeeded = true; reloadNeeded = true;
@ -829,7 +827,7 @@ void Application::onScreenDestroyed(QObject* screenObj) {
void Application::reloadDesktopsAsNeeded() { void Application::reloadDesktopsAsNeeded() {
if(enableDesktopManager_) { if(enableDesktopManager_) {
// workarounds for Qt5 bug #40681 and #40791 here. // workarounds for Qt5 bug #40681 and #40791 here.
Q_FOREACH(DesktopWindow* desktop, desktopWindows_) { for(DesktopWindow* desktop : qAsConst(desktopWindows_)) {
if(!desktop->windowHandle()) { if(!desktop->windowHandle()) {
desktop->create(); // re-create the underlying native window desktop->create(); // re-create the underlying native window
desktop->queueRelayout(); desktop->queueRelayout();
@ -841,7 +839,7 @@ void Application::reloadDesktopsAsNeeded() {
// This slot is for Qt 5 onlt, but the stupid Qt moc cannot do conditional compilation // This slot is for Qt 5 onlt, but the stupid Qt moc cannot do conditional compilation
// so we have to define it for Qt 4 as well. // so we have to define it for Qt 4 as well.
void Application::onVirtualGeometryChanged(const QRect& rect) { void Application::onVirtualGeometryChanged(const QRect& /*rect*/) {
// NOTE: the following is a workaround for Qt bug 32567. // NOTE: the following is a workaround for Qt bug 32567.
// https://bugreports.qt-project.org/browse/QTBUG-32567 // https://bugreports.qt-project.org/browse/QTBUG-32567
// Though the status of the bug report is closed, it's not yet fixed for X11. // Though the status of the bug report is closed, it's not yet fixed for X11.
@ -852,7 +850,7 @@ void Application::onVirtualGeometryChanged(const QRect& rect) {
// So we use it in Qt5. // So we use it in Qt5.
if(enableDesktopManager_) { if(enableDesktopManager_) {
// qDebug() << "onVirtualGeometryChanged"; // qDebug() << "onVirtualGeometryChanged";
Q_FOREACH(DesktopWindow* desktop, desktopWindows_) { for(DesktopWindow* desktop : qAsConst(desktopWindows_)) {
desktop->queueRelayout(); desktop->queueRelayout();
} }
} }

@ -19,7 +19,6 @@
#include "autorundialog.h" #include "autorundialog.h"
#include <libfm-qt/icontheme.h>
#include <QListWidgetItem> #include <QListWidgetItem>
#include "application.h" #include "application.h"
#include "mainwindow.h" #include "mainwindow.h"

@ -0,0 +1,92 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>BulkRenameDialog</class>
<widget class="QDialog" name="BulkRenameDialog">
<property name="windowTitle">
<string>Bulk Rename</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<property name="verticalSpacing">
<number>4</number>
</property>
<item row="2" column="2">
<widget class="QSpinBox" name="spinBox">
<property name="minimum">
<number>-1000</number>
</property>
<property name="maximum">
<number>1000</number>
</property>
</widget>
</item>
<item row="3" column="2">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::MinimumExpanding</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>5</width>
<height>5</height>
</size>
</property>
</spacer>
</item>
<item row="4" column="1" colspan="2">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLabel" name="label2">
<property name="text">
<string># will be replaced by numbers starting with:</string>
</property>
</widget>
</item>
<item row="2" column="0">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::MinimumExpanding</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>5</width>
<height>5</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="0" colspan="3">
<widget class="QLabel" name="label1">
<property name="text">
<string>Rename selected files to:</string>
</property>
</widget>
</item>
<item row="1" column="0" colspan="3">
<widget class="QLineEdit" name="lineEdit">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Name#</string>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

@ -0,0 +1,103 @@
/*
Copyright (C) 2017 Pedram Pourang (Tsu Jan) <tsujan2000@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 "bulkrename.h"
#include <QTimer>
#include <QPushButton>
#include <QMessageBox>
#include <QProgressDialog>
#include <libfm-qt/utilities.h>
namespace PCManFM {
BulkRenameDialog::BulkRenameDialog(QWidget* parent, Qt::WindowFlags flags) :
QDialog(parent, flags) {
ui.setupUi(this);
ui.lineEdit->setFocus();
connect(ui.buttonBox->button(QDialogButtonBox::Ok), &QAbstractButton::clicked, this, &QDialog::accept);
connect(ui.buttonBox->button(QDialogButtonBox::Cancel), &QAbstractButton::clicked, this, &QDialog::reject);
resize(minimumSize());
setMaximumHeight(minimumHeight()); // no vertical resizing
}
void BulkRenameDialog::showEvent(QShowEvent* event) {
QDialog::showEvent(event);
if(ui.lineEdit->text().endsWith(QLatin1Char('#'))) { // select what's before "#"
QTimer::singleShot(0, [this]() {
ui.lineEdit->setSelection(0, ui.lineEdit->text().size() - 1);
});
}
}
BulkRenamer::BulkRenamer(const Fm::FileInfoList& files, QWidget* parent) {
if(files.size() <= 1) { // no bulk rename with just one file
return;
}
QString baseName;
int start = 0;
BulkRenameDialog dlg(parent);
switch(dlg.exec()) {
case QDialog::Accepted:
baseName = dlg.getBaseName();
start = dlg.getStart();
break;
default:
return;
}
if(!baseName.contains(QLatin1Char('#'))) {
// insert "#" before the last dot
int end = baseName.lastIndexOf(QLatin1Char('.'));
if(end == -1) {
end = baseName.size();
}
baseName.insert(end, QLatin1Char('#'));
}
QProgressDialog progress(QObject::tr("Renaming files..."), QObject::tr("Abort"), 0, files.size(), parent);
progress.setWindowModality(Qt::WindowModal);
int i = 0, failed = 0;
for(auto& file: files) {
progress.setValue(i);
if(progress.wasCanceled()) {
progress.close();
QMessageBox::warning(parent, QObject::tr("Warning"), QObject::tr("Renaming is aborted."));
return;
}
auto fileName = QString::fromStdString(file->name());
QString newName = baseName;
newName.replace(QLatin1Char('#'), QString::number(start + i));
if (newName == fileName || !Fm::changeFileName(file->path(), newName, nullptr, false)) {
++failed;
}
++i;
}
progress.setValue(i);
if(failed == i) {
QMessageBox::critical(parent, QObject::tr("Error"), QObject::tr("No file could be renamed."));
}
else if(failed > 0) {
QMessageBox::critical(parent, QObject::tr("Error"), QObject::tr("Some files could not be renamed."));
}
}
BulkRenamer::~BulkRenamer() {
}
} //namespace PCManFM

@ -0,0 +1,57 @@
/*
Copyright (C) 2017 Pedram Pourang (Tsu Jan) <tsujan2000@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_BULKRENAME_H
#define PCMANFM_BULKRENAME_H
#include "ui_bulk-rename.h"
#include <QDialog>
#include <libfm-qt/core/fileinfo.h>
namespace PCManFM {
class BulkRenameDialog : public QDialog {
Q_OBJECT
public:
explicit BulkRenameDialog(QWidget* parent = nullptr, Qt::WindowFlags flags = 0);
QString getBaseName() const {
return ui.lineEdit->text();
}
int getStart() const {
return ui.spinBox->value();
}
protected:
virtual void showEvent(QShowEvent* event) override;
private:
Ui::BulkRenameDialog ui;
};
class BulkRenamer {
public:
BulkRenamer(const Fm::FileInfoList& files, QWidget* parent = nullptr);
~BulkRenamer();
};
}
#endif // PCMANFM_BULKRENAME_H

@ -21,8 +21,7 @@ ConnectServerDialog::ConnectServerDialog(QWidget *parent): QDialog(parent) {
connect(ui.host, &QLineEdit::textChanged, this, &ConnectServerDialog::checkInput); connect(ui.host, &QLineEdit::textChanged, this, &ConnectServerDialog::checkInput);
connect(ui.userName, &QLineEdit::textChanged, this, &ConnectServerDialog::checkInput); connect(ui.userName, &QLineEdit::textChanged, this, &ConnectServerDialog::checkInput);
for(const auto& serverType : const_cast<const QList<ServerType>&>(serverTypes)) {
for(const auto& serverType: serverTypes) {
ui.serverType->addItem(serverType.name); ui.serverType->addItem(serverType.name);
} }
@ -62,7 +61,7 @@ QString ConnectServerDialog::uriText() {
return uri; return uri;
} }
void ConnectServerDialog::onCurrentIndexChanged(int index) { void ConnectServerDialog::onCurrentIndexChanged(int /*index*/) {
int serverTypeIdx = ui.serverType->currentIndex(); int serverTypeIdx = ui.serverType->currentIndex();
const auto& serverType = serverTypes[serverTypeIdx]; const auto& serverType = serverTypes[serverTypeIdx];
ui.port->setValue(serverType.defaultPort); ui.port->setValue(serverType.defaultPort);

@ -203,8 +203,8 @@ void DesktopPreferencesDialog::onBrowseClicked() {
filter.reserve(256); filter.reserve(256);
filter = tr("Image Files"); filter = tr("Image Files");
filter += " ("; filter += " (";
QList<QByteArray> formats = QImageReader::supportedImageFormats(); const QList<QByteArray> formats = QImageReader::supportedImageFormats();
Q_FOREACH(QByteArray format, formats) { for(const QByteArray& format : formats) {
filter += "*."; filter += "*.";
filter += format.toLower(); filter += format.toLower();
filter += ' '; filter += ' ';
@ -214,7 +214,7 @@ void DesktopPreferencesDialog::onBrowseClicked() {
dlg.setNameFilterDetailsVisible(false); dlg.setNameFilterDetailsVisible(false);
if(dlg.exec() == QDialog::Accepted) { if(dlg.exec() == QDialog::Accepted) {
QString filename; QString filename;
filename = dlg.selectedFiles().first(); filename = dlg.selectedFiles().constFirst();
ui.imageFile->setText(filename); ui.imageFile->setText(filename);
} }
} }
@ -227,7 +227,7 @@ void DesktopPreferencesDialog::onFolderBrowseClicked() {
dlg.setDirectory(QDir::home().path()); dlg.setDirectory(QDir::home().path());
if(dlg.exec() == QDialog::Accepted) { if(dlg.exec() == QDialog::Accepted) {
QString foldername; QString foldername;
foldername = dlg.selectedFiles().first(); foldername = dlg.selectedFiles().constFirst();
ui.imageFolder->setText(foldername); ui.imageFolder->setText(foldername);
} }
} }
@ -240,7 +240,7 @@ void DesktopPreferencesDialog::onBrowseDesktopFolderClicked()
dlg.setFileMode(QFileDialog::DirectoryOnly); dlg.setFileMode(QFileDialog::DirectoryOnly);
if (dlg.exec() == QDialog::Accepted) { if (dlg.exec() == QDialog::Accepted) {
QString dir; QString dir;
dir = dlg.selectedFiles().first(); dir = dlg.selectedFiles().constFirst();
uiDesktopFolder.desktopFolder->setText(dir); uiDesktopFolder.desktopFolder->setText(dir);
} }
} }

@ -52,6 +52,7 @@
#include <libfm-qt/utilities.h> #include <libfm-qt/utilities.h>
#include <libfm-qt/core/fileinfo.h> #include <libfm-qt/core/fileinfo.h>
#include "xdgdir.h" #include "xdgdir.h"
#include "bulkrename.h"
#include <QX11Info> #include <QX11Info>
#include <QScreen> #include <QScreen>
@ -73,8 +74,10 @@ DesktopWindow::DesktopWindow(int screenNum):
wallpaperRandomize_(false), wallpaperRandomize_(false),
fileLauncher_(nullptr), fileLauncher_(nullptr),
showWmMenu_(false), showWmMenu_(false),
desktopHideItems_(false),
screenNum_(screenNum), screenNum_(screenNum),
relayoutTimer_(nullptr) { relayoutTimer_(nullptr),
selectionTimer_(nullptr) {
QDesktopWidget* desktopWidget = QApplication::desktop(); QDesktopWidget* desktopWidget = QApplication::desktop();
setWindowFlags(Qt::Window | Qt::FramelessWindowHint); setWindowFlags(Qt::Window | Qt::FramelessWindowHint);
@ -108,6 +111,8 @@ DesktopWindow::DesktopWindow(int screenNum):
auto desktopPath = Fm::FilePath::fromLocalPath(XdgDir::readDesktopDir().toStdString().c_str()); auto desktopPath = Fm::FilePath::fromLocalPath(XdgDir::readDesktopDir().toStdString().c_str());
model_ = Fm::CachedFolderModel::modelFromPath(desktopPath); model_ = Fm::CachedFolderModel::modelFromPath(desktopPath);
folder_ = model_->folder(); folder_ = model_->folder();
connect(folder_.get(), &Fm::Folder::startLoading, this, &DesktopWindow::onFolderStartLoading);
connect(folder_.get(), &Fm::Folder::finishLoading, this, &DesktopWindow::onFolderFinishLoading);
proxyModel_ = new Fm::ProxyFolderModel(); proxyModel_ = new Fm::ProxyFolderModel();
proxyModel_->setSourceModel(model_); proxyModel_->setSourceModel(model_);
@ -147,7 +152,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, this, &FolderView::selectAll); connect(shortcut, &QShortcut::activated, this, &DesktopWindow::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);
@ -155,7 +160,10 @@ DesktopWindow::DesktopWindow(int screenNum):
shortcut = new QShortcut(QKeySequence(Qt::Key_F2), this); // rename shortcut = new QShortcut(QKeySequence(Qt::Key_F2), this); // rename
connect(shortcut, &QShortcut::activated, this, &DesktopWindow::onRenameActivated); connect(shortcut, &QShortcut::activated, this, &DesktopWindow::onRenameActivated);
shortcut = new QShortcut(QKeySequence(Qt::ALT + Qt::Key_Return), this); // rename shortcut = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_F2), this); // bulk rename
connect(shortcut, &QShortcut::activated, this, &DesktopWindow::onBulkRenameActivated);
shortcut = new QShortcut(QKeySequence(Qt::ALT + Qt::Key_Return), this); // properties
connect(shortcut, &QShortcut::activated, this, &DesktopWindow::onFilePropertiesActivated); connect(shortcut, &QShortcut::activated, this, &DesktopWindow::onFilePropertiesActivated);
shortcut = new QShortcut(QKeySequence(Qt::SHIFT + Qt::Key_Delete), this); // force delete shortcut = new QShortcut(QKeySequence(Qt::SHIFT + Qt::Key_Delete), this); // force delete
@ -166,6 +174,8 @@ DesktopWindow::~DesktopWindow() {
listView_->viewport()->removeEventFilter(this); listView_->viewport()->removeEventFilter(this);
listView_->removeEventFilter(this); listView_->removeEventFilter(this);
disconnect(folder_.get(), nullptr, this, nullptr);
if(relayoutTimer_) { if(relayoutTimer_) {
relayoutTimer_->stop(); relayoutTimer_->stop();
delete relayoutTimer_; delete relayoutTimer_;
@ -181,6 +191,7 @@ DesktopWindow::~DesktopWindow() {
} }
if(model_) { if(model_) {
disconnect(model_, &Fm::FolderModel::filesAdded, this, &DesktopWindow::onFilesAdded);
model_->unref(); model_->unref();
} }
} }
@ -224,9 +235,31 @@ void DesktopWindow::resizeEvent(QResizeEvent* event) {
} }
void DesktopWindow::setDesktopFolder() { void DesktopWindow::setDesktopFolder() {
if(folder_) {
// free the previous model and folder
if(model_) {
disconnect(model_, &Fm::FolderModel::filesAdded, this, &DesktopWindow::onFilesAdded);
proxyModel_->setSourceModel(nullptr);
model_->unref(); // unref the cached model
model_ = nullptr;
}
disconnect(folder_.get(), nullptr, this, nullptr);
folder_ = nullptr;
}
auto path = Fm::FilePath::fromLocalPath(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);
folder_ = model_->folder();
connect(folder_.get(), &Fm::Folder::startLoading, this, &DesktopWindow::onFolderStartLoading);
connect(folder_.get(), &Fm::Folder::finishLoading, this, &DesktopWindow::onFolderFinishLoading);
proxyModel_->setSourceModel(model_); proxyModel_->setSourceModel(model_);
if(folder_->isLoaded()) {
onFolderStartLoading();
onFolderFinishLoading();
}
else {
onFolderStartLoading();
}
} }
void DesktopWindow::setWallpaperFile(QString filename) { void DesktopWindow::setWallpaperFile(QString filename) {
@ -478,6 +511,13 @@ void DesktopWindow::updateFromSettings(Settings& settings, bool changeSlide) {
setBackground(settings.desktopBgColor()); setBackground(settings.desktopBgColor());
setShadow(settings.desktopShadowColor()); setShadow(settings.desktopShadowColor());
showWmMenu_ = settings.showWmMenu(); showWmMenu_ = settings.showWmMenu();
desktopHideItems_ = settings.desktopHideItems();
if(desktopHideItems_) {
// hide all items by hiding the list view and also
// prevent the current item from being changed by arrow keys
listView_->clearFocus();
listView_->setVisible(false);
}
if(slideShowInterval_ > 0 if(slideShowInterval_ > 0
&& QFileInfo(wallpaperDir_).isDir()) { && QFileInfo(wallpaperDir_).isDir()) {
@ -516,7 +556,18 @@ void DesktopWindow::onFileClicked(int type, const std::shared_ptr<const Fm::File
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); if(desktopHideItems_) { // only a context menu with desktop actions
if(type == Fm::FolderView::ActivatedClick) {
return;
}
QMenu* menu = new QMenu(this);
addDesktopActions(menu);
menu->exec(QCursor::pos());
delete menu;
}
else {
View::onFileClicked(type, fileInfo);
}
} }
void DesktopWindow::prepareFileMenu(Fm::FileMenu* menu) { void DesktopWindow::prepareFileMenu(Fm::FileMenu* menu) {
@ -543,11 +594,42 @@ void DesktopWindow::prepareFolderMenu(Fm::FolderMenu* menu) {
PCManFM::View::prepareFolderMenu(menu); PCManFM::View::prepareFolderMenu(menu);
// remove file properties action // remove file properties action
menu->removeAction(menu->propertiesAction()); menu->removeAction(menu->propertiesAction());
// add an action for desktop preferences instead // add desktop actions instead
QAction* action = menu->addAction(tr("Desktop Preferences")); addDesktopActions(menu);
}
void DesktopWindow::addDesktopActions(QMenu* menu) {
QAction* action = menu->addAction(tr("Hide Desktop Items"));
action->setCheckable(true);
action->setChecked(desktopHideItems_);
menu->addSeparator();
connect(action, &QAction::triggered, this, &DesktopWindow::toggleDesktop);
action = menu->addAction(tr("Desktop Preferences"));
connect(action, &QAction::triggered, this, &DesktopWindow::onDesktopPreferences); connect(action, &QAction::triggered, this, &DesktopWindow::onDesktopPreferences);
} }
void DesktopWindow::toggleDesktop() {
desktopHideItems_ = !desktopHideItems_;
Settings& settings = static_cast<Application*>(qApp)->settings();
settings.setDesktopHideItems(desktopHideItems_);
listView_->setVisible(!desktopHideItems_);
// a relayout is needed on showing the items for the first time
// because the positions aren't updated while the view is hidden
if(!desktopHideItems_) {
listView_->setFocus(); // refocus the view
queueRelayout();
}
else { // prevent the current item from being changed by arrow keys
listView_->clearFocus();
}
}
void DesktopWindow::selectAll() {
if(!desktopHideItems_) {
FolderView::selectAll();
}
}
void DesktopWindow::onDesktopPreferences() { void DesktopWindow::onDesktopPreferences() {
static_cast<Application* >(qApp)->desktopPrefrences(QString()); static_cast<Application* >(qApp)->desktopPrefrences(QString());
} }
@ -570,9 +652,8 @@ void DesktopWindow::onRowsAboutToBeRemoved(const QModelIndex& parent, int start,
// 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.
bool changed = false; bool changed = false;
char* dektopPath = Fm::Path::getDesktop().toStr(); QString desktopDir = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation);
QString desktopDir = QString(dektopPath) + QString("/"); desktopDir += '/';
g_free(dektopPath);
for(auto it = customItemPos_.cbegin(); it != customItemPos_.cend();) { for(auto it = customItemPos_.cbegin(); it != customItemPos_.cend();) {
auto& name = it->first; auto& name = it->first;
if(!QFile::exists(desktopDir + QString::fromStdString(name))) { if(!QFile::exists(desktopDir + QString::fromStdString(name))) {
@ -599,7 +680,7 @@ void DesktopWindow::onModelSortFilterChanged() {
Settings& settings = static_cast<Application*>(qApp)->settings(); Settings& settings = static_cast<Application*>(qApp)->settings();
settings.setDesktopSortColumn(static_cast<Fm::FolderModel::ColumnId>(proxyModel_->sortColumn())); settings.setDesktopSortColumn(static_cast<Fm::FolderModel::ColumnId>(proxyModel_->sortColumn()));
settings.setDesktopSortOrder(proxyModel_->sortOrder()); settings.setDesktopSortOrder(proxyModel_->sortOrder());
settings.setSesktopSortFolderFirst(proxyModel_->folderFirst()); settings.setDesktopSortFolderFirst(proxyModel_->folderFirst());
} }
void DesktopWindow::onDataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight) { void DesktopWindow::onDataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight) {
@ -633,7 +714,7 @@ void DesktopWindow::onIndexesMoved(const QModelIndexList& indexes) {
auto delegate = static_cast<Fm::FolderItemDelegate*>(listView_->itemDelegateForColumn(0)); auto delegate = static_cast<Fm::FolderItemDelegate*>(listView_->itemDelegateForColumn(0));
auto itemSize = delegate->itemSize(); auto itemSize = delegate->itemSize();
// remember the custom position for the items // remember the custom position for the items
Q_FOREACH(const QModelIndex& index, indexes) { for(const QModelIndex& index : indexes) {
// Under some circumstances, Qt might emit indexMoved for // Under some circumstances, Qt might emit indexMoved for
// every single cells in the same row. (when QAbstractItemView::SelectItems is set) // every single cells in the same row. (when QAbstractItemView::SelectItems is set)
// So indexes list may contain several indixes for the same row. // So indexes list may contain several indixes for the same row.
@ -664,6 +745,35 @@ void DesktopWindow::onIndexesMoved(const QModelIndexList& indexes) {
queueRelayout(); queueRelayout();
} }
void DesktopWindow::onFolderStartLoading() { // desktop may be reloaded
if(model_) {
disconnect(model_, &Fm::FolderModel::filesAdded, this, &DesktopWindow::onFilesAdded);
}
}
void DesktopWindow::onFolderFinishLoading() {
QTimer::singleShot(10, [this]() { // Qt delays the UI update (as in TabPage::onFolderFinishLoading)
if(model_) {
connect(model_, &Fm::FolderModel::filesAdded, this, &DesktopWindow::onFilesAdded);
}
});
}
void DesktopWindow::onFilesAdded(const Fm::FileInfoList files) {
if(static_cast<Application*>(qApp)->settings().selectNewFiles()) {
if(!selectionTimer_) {
selectFiles(files, false);
selectionTimer_ = new QTimer (this);
selectionTimer_->setSingleShot(true);
selectionTimer_->start(200);
}
else {
selectFiles(files, selectionTimer_->isActive());
selectionTimer_->start(200);
}
}
}
void DesktopWindow::removeBottomGap() { void DesktopWindow::removeBottomGap() {
/************************************************************ /************************************************************
NOTE: Desktop is an area bounded from below while icons snap NOTE: Desktop is an area bounded from below while icons snap
@ -673,7 +783,7 @@ void DesktopWindow::removeBottomGap() {
************************************************************/ ************************************************************/
auto delegate = static_cast<Fm::FolderItemDelegate*>(listView_->itemDelegateForColumn(0)); auto delegate = static_cast<Fm::FolderItemDelegate*>(listView_->itemDelegateForColumn(0));
auto itemSize = delegate->itemSize(); auto itemSize = delegate->itemSize();
qDebug() << "delegate:" << 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
@ -828,17 +938,16 @@ void DesktopWindow::loadItemPositions() {
auto grid = delegate->itemSize(); 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(); QString desktopDir = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation);
QString desktopDir = QString(dektopPath) + QString("/"); desktopDir += '/';
g_free(dektopPath);
std::vector<QPoint> usedPos; std::vector<QPoint> usedPos;
for(auto& item: customItemPos_) { for(auto& item: customItemPos_) {
usedPos.push_back(item.second); usedPos.push_back(item.second);
} }
// FIXME: this is inefficient // FIXME: this is inefficient
Q_FOREACH(const QString& name, file.childGroups()) { const auto names = file.childGroups();
for(const QString& name : names) {
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
continue; continue;
@ -927,6 +1036,9 @@ void DesktopWindow::queueRelayout(int delay) {
// slots for file operations // slots for file operations
void DesktopWindow::onCutActivated() { void DesktopWindow::onCutActivated() {
if(desktopHideItems_) {
return;
}
auto paths = selectedFilePaths(); auto paths = selectedFilePaths();
if(!paths.empty()) { if(!paths.empty()) {
Fm::cutFilesToClipboard(paths); Fm::cutFilesToClipboard(paths);
@ -934,6 +1046,9 @@ void DesktopWindow::onCutActivated() {
} }
void DesktopWindow::onCopyActivated() { void DesktopWindow::onCopyActivated() {
if(desktopHideItems_) {
return;
}
auto paths = selectedFilePaths(); auto paths = selectedFilePaths();
if(!paths.empty()) { if(!paths.empty()) {
Fm::copyFilesToClipboard(paths); Fm::copyFilesToClipboard(paths);
@ -941,10 +1056,16 @@ void DesktopWindow::onCopyActivated() {
} }
void DesktopWindow::onPasteActivated() { void DesktopWindow::onPasteActivated() {
if(desktopHideItems_) {
return;
}
Fm::pasteFilesFromClipboard(path()); Fm::pasteFilesFromClipboard(path());
} }
void DesktopWindow::onDeleteActivated() { void DesktopWindow::onDeleteActivated() {
if(desktopHideItems_) {
return;
}
auto paths = selectedFilePaths(); auto paths = selectedFilePaths();
if(!paths.empty()) { if(!paths.empty()) {
Settings& settings = static_cast<Application*>(qApp)->settings(); Settings& settings = static_cast<Application*>(qApp)->settings();
@ -959,6 +1080,9 @@ void DesktopWindow::onDeleteActivated() {
} }
void DesktopWindow::onRenameActivated() { void DesktopWindow::onRenameActivated() {
if(desktopHideItems_) {
return;
}
// do inline renaming if only one item is selected, // do inline renaming if only one item is selected,
// otherwise use the renaming dialog // otherwise use the renaming dialog
if(selectedIndexes().size() == 1) { if(selectedIndexes().size() == 1) {
@ -971,12 +1095,24 @@ void DesktopWindow::onRenameActivated() {
auto files = selectedFiles(); auto files = selectedFiles();
if(!files.empty()) { if(!files.empty()) {
for(auto& info: files) { for(auto& info: files) {
Fm::renameFile(info, nullptr); if(!Fm::renameFile(info, nullptr)) {
break;
}
} }
} }
} }
void DesktopWindow::onBulkRenameActivated() {
if(desktopHideItems_) {
return;
}
BulkRenamer(selectedFiles(), this);
}
void DesktopWindow::onFilePropertiesActivated() { void DesktopWindow::onFilePropertiesActivated() {
if(desktopHideItems_) {
return;
}
auto files = selectedFiles(); auto files = selectedFiles();
if(!files.empty()) { if(!files.empty()) {
Fm::FilePropsDialog::showForFiles(std::move(files)); Fm::FilePropsDialog::showForFiles(std::move(files));
@ -1052,7 +1188,7 @@ static void forwardMouseEventToRoot(QMouseEvent* event) {
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;
} }

@ -105,6 +105,8 @@ protected:
protected Q_SLOTS: protected Q_SLOTS:
void onOpenDirRequested(const Fm::FilePath& path, int target); void onOpenDirRequested(const Fm::FilePath& path, int target);
void onDesktopPreferences(); void onDesktopPreferences();
void selectAll();
void toggleDesktop();
void onRowsAboutToBeRemoved(const QModelIndex& parent, int start, int end); void onRowsAboutToBeRemoved(const QModelIndex& parent, int start, int end);
void onRowsInserted(const QModelIndex& parent, int start, int end); void onRowsInserted(const QModelIndex& parent, int start, int end);
@ -112,6 +114,9 @@ protected Q_SLOTS:
void onModelSortFilterChanged(); void onModelSortFilterChanged();
void onIndexesMoved(const QModelIndexList& indexes); void onIndexesMoved(const QModelIndexList& indexes);
void onDataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight); void onDataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight);
void onFolderStartLoading();
void onFolderFinishLoading();
void onFilesAdded(const Fm::FileInfoList files);
void relayoutItems(); void relayoutItems();
void onStickToCurrentPos(bool toggled); void onStickToCurrentPos(bool toggled);
@ -123,11 +128,13 @@ protected Q_SLOTS:
void onCopyActivated(); void onCopyActivated();
void onPasteActivated(); void onPasteActivated();
void onRenameActivated(); void onRenameActivated();
void onBulkRenameActivated();
void onDeleteActivated(); void onDeleteActivated();
void onFilePropertiesActivated(); void onFilePropertiesActivated();
private: private:
void removeBottomGap(); void removeBottomGap();
void addDesktopActions(QMenu* menu);
void paintBackground(QPaintEvent* event); void paintBackground(QPaintEvent* event);
static void alignToGrid(QPoint& pos, const QPoint& topLeft, const QSize& grid, const int spacing); static void alignToGrid(QPoint& pos, const QPoint& topLeft, const QSize& grid, const int spacing);
@ -150,11 +157,13 @@ private:
QPixmap wallpaperPixmap_; QPixmap wallpaperPixmap_;
Launcher fileLauncher_; Launcher fileLauncher_;
bool showWmMenu_; bool showWmMenu_;
bool desktopHideItems_;
int screenNum_; int screenNum_;
std::unordered_map<std::string, 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_;
QTimer* selectionTimer_;
}; };
} }

@ -37,12 +37,11 @@ Launcher::~Launcher() {
} }
bool Launcher::openFolder(GAppLaunchContext* ctx, GList* folder_infos, GError** err) { bool Launcher::openFolder(GAppLaunchContext* /*ctx*/, const Fm::FileInfoList& folderInfos, Fm::GErrorPtr& /*err*/) {
GList* l = folder_infos; auto fi = folderInfos[0];
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}; Fm::FilePath path = fi->path();
if(!mainWindow) { if(!mainWindow) {
mainWindow = new MainWindow(std::move(path)); mainWindow = new MainWindow(std::move(path));
mainWindow->resize(app->settings().windowWidth(), app->settings().windowHeight()); mainWindow->resize(app->settings().windowWidth(), app->settings().windowHeight());
@ -54,10 +53,10 @@ bool Launcher::openFolder(GAppLaunchContext* ctx, GList* folder_infos, GError**
else { else {
mainWindow->chdir(std::move(path)); mainWindow->chdir(std::move(path));
} }
l = l->next;
for(; l; l = l->next) { for(size_t i = 1; i < folderInfos.size(); ++i) {
fi = FM_FILE_INFO(l->data); fi = folderInfos[i];
path = Fm::FilePath{fm_path_to_gfile(fm_file_info_get_path(fi)), false}; path = fi->path();
mainWindow->addTab(std::move(path)); mainWindow->addTab(std::move(path));
} }
mainWindow->show(); mainWindow->show();

@ -33,7 +33,7 @@ public:
~Launcher(); ~Launcher();
protected: protected:
virtual bool openFolder(GAppLaunchContext* ctx, GList* folder_infos, GError** err); bool openFolder(GAppLaunchContext* ctx, const Fm::FileInfoList& folderInfos, Fm::GErrorPtr& err) override;
private: private:
MainWindow* mainWindow_; MainWindow* mainWindow_;

@ -210,6 +210,9 @@
<addaction name="actionSelectAll"/> <addaction name="actionSelectAll"/>
<addaction name="actionInvertSelection"/> <addaction name="actionInvertSelection"/>
<addaction name="separator"/> <addaction name="separator"/>
<addaction name="separator"/>
<addaction name="actionBulkRename"/>
<addaction name="separator"/>
<addaction name="actionPreferences"/> <addaction name="actionPreferences"/>
</widget> </widget>
<widget class="QMenu" name="menu_Bookmarks"> <widget class="QMenu" name="menu_Bookmarks">
@ -278,6 +281,11 @@
<addaction name="actionGoUp"/> <addaction name="actionGoUp"/>
<addaction name="actionReload"/> <addaction name="actionReload"/>
<addaction name="separator"/> <addaction name="separator"/>
<addaction name="actionIconView"/>
<addaction name="actionThumbnailView"/>
<addaction name="actionCompactView"/>
<addaction name="actionDetailedList"/>
<addaction name="separator"/>
<addaction name="actionGo"/> <addaction name="actionGo"/>
<addaction name="actionMenu"/> <addaction name="actionMenu"/>
</widget> </widget>
@ -828,6 +836,17 @@
<string>&amp;Path Buttons</string> <string>&amp;Path Buttons</string>
</property> </property>
</action> </action>
<action name="actionBulkRename">
<property name="text">
<string>&amp;Bulk Rename</string>
</property>
<property name="toolTip">
<string>Bulk Rename</string>
</property>
<property name="shortcut">
<string>Ctrl+F2</string>
</property>
</action>
</widget> </widget>
<customwidgets> <customwidgets>
<customwidget> <customwidget>

@ -30,6 +30,7 @@
#include <QShortcut> #include <QShortcut>
#include <QKeySequence> #include <QKeySequence>
#include <QSettings> #include <QSettings>
#include <QMimeData>
#include <QStandardPaths> #include <QStandardPaths>
#include <QDebug> #include <QDebug>
@ -45,6 +46,7 @@
#include <libfm-qt/core/fileinfo.h> #include <libfm-qt/core/fileinfo.h>
#include "ui_about.h" #include "ui_about.h"
#include "application.h" #include "application.h"
#include "bulkrename.h"
using namespace Fm; using namespace Fm;
@ -57,10 +59,10 @@ MainWindow::MainWindow(Fm::FilePath path):
QMainWindow(), QMainWindow(),
pathEntry_(nullptr), pathEntry_(nullptr),
pathBar_(nullptr), pathBar_(nullptr),
bookmarks_{Fm::Bookmarks::globalInstance()},
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);
@ -90,7 +92,7 @@ MainWindow::MainWindow(Fm::FilePath path):
// tabbed browsing interface // tabbed browsing interface
ui.tabBar->setDocumentMode(true); ui.tabBar->setDocumentMode(true);
ui.tabBar->setTabsClosable(true); ui.tabBar->setTabsClosable(settings.showTabClose());
ui.tabBar->setElideMode(Qt::ElideRight); ui.tabBar->setElideMode(Qt::ElideRight);
ui.tabBar->setExpanding(false); ui.tabBar->setExpanding(false);
ui.tabBar->setMovable(true); // reorder the tabs by dragging ui.tabBar->setMovable(true); // reorder the tabs by dragging
@ -114,6 +116,7 @@ MainWindow::MainWindow(Fm::FilePath path):
connect(ui.tabBar, &QTabBar::tabCloseRequested, this, &MainWindow::onTabBarCloseRequested); connect(ui.tabBar, &QTabBar::tabCloseRequested, this, &MainWindow::onTabBarCloseRequested);
connect(ui.tabBar, &QTabBar::tabMoved, this, &MainWindow::onTabBarTabMoved); connect(ui.tabBar, &QTabBar::tabMoved, this, &MainWindow::onTabBarTabMoved);
connect(ui.tabBar, &QTabBar::customContextMenuRequested, this, &MainWindow::tabContextMenu); connect(ui.tabBar, &QTabBar::customContextMenuRequested, this, &MainWindow::tabContextMenu);
connect(ui.tabBar, &TabBar::tabDetached, this, &MainWindow::detachTab);
connect(ui.stackedWidget, &QStackedWidget::widgetRemoved, this, &MainWindow::onStackedWidgetWidgetRemoved); connect(ui.stackedWidget, &QStackedWidget::widgetRemoved, this, &MainWindow::onStackedWidgetWidgetRemoved);
// FIXME: should we make the filter bar a per-view configuration? // FIXME: should we make the filter bar a per-view configuration?
@ -124,12 +127,14 @@ MainWindow::MainWindow(Fm::FilePath path):
// side pane // side pane
ui.sidePane->setIconSize(QSize(settings.sidePaneIconSize(), settings.sidePaneIconSize())); ui.sidePane->setIconSize(QSize(settings.sidePaneIconSize(), settings.sidePaneIconSize()));
ui.sidePane->setMode(settings.sidePaneMode()); ui.sidePane->setMode(settings.sidePaneMode());
ui.sidePane->restoreHiddenPlaces(settings.getHiddenPlaces());
connect(ui.sidePane, &Fm::SidePane::chdirRequested, this, &MainWindow::onSidePaneChdirRequested); connect(ui.sidePane, &Fm::SidePane::chdirRequested, this, &MainWindow::onSidePaneChdirRequested);
connect(ui.sidePane, &Fm::SidePane::openFolderInNewWindowRequested, this, &MainWindow::onSidePaneOpenFolderInNewWindowRequested); connect(ui.sidePane, &Fm::SidePane::openFolderInNewWindowRequested, this, &MainWindow::onSidePaneOpenFolderInNewWindowRequested);
connect(ui.sidePane, &Fm::SidePane::openFolderInNewTabRequested, this, &MainWindow::onSidePaneOpenFolderInNewTabRequested); connect(ui.sidePane, &Fm::SidePane::openFolderInNewTabRequested, this, &MainWindow::onSidePaneOpenFolderInNewTabRequested);
connect(ui.sidePane, &Fm::SidePane::openFolderInTerminalRequested, this, &MainWindow::onSidePaneOpenFolderInTerminalRequested); connect(ui.sidePane, &Fm::SidePane::openFolderInTerminalRequested, this, &MainWindow::onSidePaneOpenFolderInTerminalRequested);
connect(ui.sidePane, &Fm::SidePane::createNewFolderRequested, this, &MainWindow::onSidePaneCreateNewFolderRequested); connect(ui.sidePane, &Fm::SidePane::createNewFolderRequested, this, &MainWindow::onSidePaneCreateNewFolderRequested);
connect(ui.sidePane, &Fm::SidePane::modeChanged, this, &MainWindow::onSidePaneModeChanged); connect(ui.sidePane, &Fm::SidePane::modeChanged, this, &MainWindow::onSidePaneModeChanged);
connect(ui.sidePane, &Fm::SidePane::hiddenPlaceSet, this, &MainWindow::onSettingHiddenPlace);
// detect change of splitter position // detect change of splitter position
connect(ui.splitter, &QSplitter::splitterMoved, this, &MainWindow::onSplitterMoved); connect(ui.splitter, &QSplitter::splitterMoved, this, &MainWindow::onSplitterMoved);
@ -158,6 +163,12 @@ MainWindow::MainWindow(Fm::FilePath path):
connect(bookmarks_.get(), &Fm::Bookmarks::changed, this, &MainWindow::onBookmarksChanged); connect(bookmarks_.get(), &Fm::Bookmarks::changed, this, &MainWindow::onBookmarksChanged);
loadBookmarksMenu(); loadBookmarksMenu();
// set generic icons for view actions
ui.actionIconView->setIcon(style()->standardIcon(QStyle::SP_FileDialogContentsView));
ui.actionThumbnailView->setIcon(style()->standardIcon(QStyle::SP_FileDialogInfoView));
ui.actionCompactView->setIcon(style()->standardIcon(QStyle::SP_FileDialogListView));
ui.actionDetailedList->setIcon(style()->standardIcon(QStyle::SP_FileDialogDetailedView));
// Fix the menu groups which is not done by Qt designer // Fix the menu groups which is not done by Qt designer
// To my suprise, this was supported in Qt designer 3 :-( // To my suprise, this was supported in Qt designer 3 :-(
QActionGroup* group = new QActionGroup(ui.menu_View); QActionGroup* group = new QActionGroup(ui.menu_View);
@ -271,28 +282,31 @@ MainWindow::MainWindow(Fm::FilePath path):
} }
// size from settings // size from settings
if(settings.rememberWindowSize()) { resize(settings.windowWidth(), settings.windowHeight());
resize(settings.windowWidth(), settings.windowHeight()); if(settings.rememberWindowSize() && 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);
} }
// we want tab dnd
setAcceptDrops(true);
} }
MainWindow::~MainWindow() { MainWindow::~MainWindow() {
} }
void MainWindow::chdir(Fm::FilePath path) { void MainWindow::chdir(Fm::FilePath path) {
TabPage* page = currentPage(); // wait until queued events are processed
if(page) { QTimer::singleShot(0, this, [this, path] {
ui.filterBar->clear(); if(TabPage* page = currentPage()) {
page->chdir(path, true); ui.filterBar->clear();
updateUIForCurrentPage(); page->chdir(path, true);
} updateUIForCurrentPage();
}
});
} }
void MainWindow::createPathBar(bool usePathButtons) { void MainWindow::createPathBar(bool usePathButtons) {
@ -311,30 +325,38 @@ void MainWindow::createPathBar(bool usePathButtons) {
ui.actionGo->setVisible(!usePathButtons); ui.actionGo->setVisible(!usePathButtons);
} }
// add a new tab int MainWindow::addTabWithPage(TabPage* page, Fm::FilePath path) {
int MainWindow::addTab(Fm::FilePath path) { if(page == nullptr) {
Settings& settings = static_cast<Application*>(qApp)->settings(); return -1;
}
page->setFileLauncher(&fileLauncher_);
int index = ui.stackedWidget->addWidget(page);
connect(page, &TabPage::titleChanged, this, &MainWindow::onTabPageTitleChanged);
connect(page, &TabPage::statusChanged, this, &MainWindow::onTabPageStatusChanged);
connect(page, &TabPage::openDirRequested, this, &MainWindow::onTabPageOpenDirRequested);
connect(page, &TabPage::sortFilterChanged, this, &MainWindow::onTabPageSortFilterChanged);
connect(page, &TabPage::backwardRequested, this, &MainWindow::on_actionGoBack_triggered);
connect(page, &TabPage::forwardRequested, this, &MainWindow::on_actionGoForward_triggered);
TabPage* newPage = new TabPage(this); if(path) {
newPage->setFileLauncher(&fileLauncher_); page->chdir(path, true);
int index = ui.stackedWidget->addWidget(newPage); }
connect(newPage, &TabPage::titleChanged, this, &MainWindow::onTabPageTitleChanged); ui.tabBar->insertTab(index, page->windowTitle());
connect(newPage, &TabPage::statusChanged, this, &MainWindow::onTabPageStatusChanged);
connect(newPage, &TabPage::openDirRequested, this, &MainWindow::onTabPageOpenDirRequested);
connect(newPage, &TabPage::sortFilterChanged, this, &MainWindow::onTabPageSortFilterChanged);
connect(newPage, &TabPage::backwardRequested, this, &MainWindow::on_actionGoBack_triggered);
connect(newPage, &TabPage::forwardRequested, this, &MainWindow::on_actionGoForward_triggered);
newPage->chdir(path, true);
ui.tabBar->insertTab(index, newPage->windowTitle());
Settings& settings = static_cast<Application*>(qApp)->settings();
if(!settings.alwaysShowTabs()) { if(!settings.alwaysShowTabs()) {
ui.tabBar->setVisible(ui.tabBar->count() > 1); ui.tabBar->setVisible(ui.tabBar->count() > 1);
} }
return index; return index;
} }
void MainWindow::toggleMenuBar(bool checked) { // add a new tab
int MainWindow::addTab(Fm::FilePath path) {
TabPage* newPage = new TabPage(this);
return addTabWithPage(newPage, path);
}
void MainWindow::toggleMenuBar(bool /*checked*/) {
Settings& settings = static_cast<Application*>(qApp)->settings(); Settings& settings = static_cast<Application*>(qApp)->settings();
bool showMenuBar = !settings.showMenuBar(); bool showMenuBar = !settings.showMenuBar();
@ -375,33 +397,34 @@ void MainWindow::onPathBarMiddleClickChdir(const Fm::FilePath& dirPath) {
} }
void MainWindow::on_actionGoUp_triggered() { void MainWindow::on_actionGoUp_triggered() {
TabPage* page = currentPage(); QTimer::singleShot(0, this, [this] {
if(TabPage* page = currentPage()) {
if(page) { ui.filterBar->clear();
ui.filterBar->clear(); page->up();
page->up(); updateUIForCurrentPage();
updateUIForCurrentPage(); }
} });
} }
void MainWindow::on_actionGoBack_triggered() { void MainWindow::on_actionGoBack_triggered() {
TabPage* page = currentPage(); QTimer::singleShot(0, this, [this] {
if(TabPage* page = currentPage()) {
if(page) { ui.filterBar->clear();
ui.filterBar->clear(); page->backward();
page->backward(); updateUIForCurrentPage();
updateUIForCurrentPage(); }
} });
} }
void MainWindow::on_actionGoForward_triggered() { void MainWindow::on_actionGoForward_triggered() {
TabPage* page = currentPage(); QTimer::singleShot(0, this, [this] {
if(TabPage* page = currentPage()) {
ui.filterBar->clear();
page->forward();
updateUIForCurrentPage();
}
});
if(page) {
ui.filterBar->clear();
page->forward();
updateUIForCurrentPage();
}
} }
void MainWindow::on_actionHome_triggered() { void MainWindow::on_actionHome_triggered() {
@ -494,31 +517,31 @@ void MainWindow::on_actionShowHidden_triggered(bool checked) {
} }
} }
void MainWindow::on_actionByFileName_triggered(bool checked) { void MainWindow::on_actionByFileName_triggered(bool /*checked*/) {
currentPage()->sort(Fm::FolderModel::ColumnFileName, currentPage()->sortOrder()); currentPage()->sort(Fm::FolderModel::ColumnFileName, currentPage()->sortOrder());
} }
void MainWindow::on_actionByMTime_triggered(bool checked) { void MainWindow::on_actionByMTime_triggered(bool /*checked*/) {
currentPage()->sort(Fm::FolderModel::ColumnFileMTime, currentPage()->sortOrder()); currentPage()->sort(Fm::FolderModel::ColumnFileMTime, currentPage()->sortOrder());
} }
void MainWindow::on_actionByOwner_triggered(bool checked) { void MainWindow::on_actionByOwner_triggered(bool /*checked*/) {
currentPage()->sort(Fm::FolderModel::ColumnFileOwner, currentPage()->sortOrder()); currentPage()->sort(Fm::FolderModel::ColumnFileOwner, currentPage()->sortOrder());
} }
void MainWindow::on_actionByFileSize_triggered(bool checked) { void MainWindow::on_actionByFileSize_triggered(bool /*checked*/) {
currentPage()->sort(Fm::FolderModel::ColumnFileSize, currentPage()->sortOrder()); currentPage()->sort(Fm::FolderModel::ColumnFileSize, currentPage()->sortOrder());
} }
void MainWindow::on_actionByFileType_triggered(bool checked) { void MainWindow::on_actionByFileType_triggered(bool /*checked*/) {
currentPage()->sort(Fm::FolderModel::ColumnFileType, currentPage()->sortOrder()); currentPage()->sort(Fm::FolderModel::ColumnFileType, currentPage()->sortOrder());
} }
void MainWindow::on_actionAscending_triggered(bool checked) { void MainWindow::on_actionAscending_triggered(bool /*checked*/) {
currentPage()->sort(currentPage()->sortColumn(), Qt::AscendingOrder); currentPage()->sort(currentPage()->sortColumn(), Qt::AscendingOrder);
} }
void MainWindow::on_actionDescending_triggered(bool checked) { void MainWindow::on_actionDescending_triggered(bool /*checked*/) {
currentPage()->sort(currentPage()->sortColumn(), Qt::DescendingOrder); currentPage()->sort(currentPage()->sortColumn(), Qt::DescendingOrder);
} }
@ -530,7 +553,7 @@ void MainWindow::on_actionFolderFirst_triggered(bool checked) {
currentPage()->setSortFolderFirst(checked); currentPage()->setSortFolderFirst(checked);
} }
void MainWindow::on_actionPreserveView_triggered(bool checked) { void MainWindow::on_actionPreserveView_triggered(bool /*checked*/) {
TabPage* page = currentPage(); TabPage* page = currentPage();
page->setCustomizedView(!page->hasCustomizedView()); page->setCustomizedView(!page->hasCustomizedView());
} }
@ -623,7 +646,7 @@ void MainWindow::on_actionAbout_triggered() {
// the about dialog // the about dialog
class AboutDialog : public QDialog { class AboutDialog : public QDialog {
public: public:
explicit AboutDialog(QWidget* parent = 0, Qt::WindowFlags f = 0) { explicit AboutDialog(QWidget* parent = 0, Qt::WindowFlags f = 0) : QDialog(parent, f) {
ui.setupUi(this); ui.setupUi(this);
ui.version->setText(tr("Version: %1").arg(PCMANFM_QT_VERSION)); ui.version->setText(tr("Version: %1").arg(PCMANFM_QT_VERSION));
} }
@ -816,7 +839,7 @@ void MainWindow::updateViewMenuForCurrentPage() {
void MainWindow::updateEditSelectedActions() { void MainWindow::updateEditSelectedActions() {
bool hasAccessible(false); bool hasAccessible(false);
bool hasDeletable(false); bool hasDeletable(false);
bool hasRenamable(false); int renamable(0);
if(TabPage* page = currentPage()) { if(TabPage* page = currentPage()) {
auto files = page->selectedFiles(); auto files = page->selectedFiles();
for(auto& file: files) { for(auto& file: files) {
@ -827,9 +850,9 @@ void MainWindow::updateEditSelectedActions() {
hasDeletable = true; hasDeletable = true;
} }
if(file->canSetName()) { if(file->canSetName()) {
hasRenamable = true; ++renamable;
} }
if (hasAccessible && hasDeletable && hasRenamable) { if (hasAccessible && hasDeletable && renamable > 1) {
break; break;
} }
} }
@ -837,7 +860,8 @@ void MainWindow::updateEditSelectedActions() {
ui.actionCopy->setEnabled(hasAccessible); ui.actionCopy->setEnabled(hasAccessible);
ui.actionCut->setEnabled(hasDeletable); ui.actionCut->setEnabled(hasDeletable);
ui.actionDelete->setEnabled(hasDeletable); ui.actionDelete->setEnabled(hasDeletable);
ui.actionRename->setEnabled(hasRenamable); ui.actionRename->setEnabled(renamable > 0);
ui.actionBulkRename->setEnabled(renamable > 1);
} }
void MainWindow::updateUIForCurrentPage() { void MainWindow::updateUIForCurrentPage() {
@ -1013,7 +1037,11 @@ void MainWindow::onSidePaneModeChanged(Fm::SidePane::Mode mode) {
static_cast<Application*>(qApp)->settings().setSidePaneMode(mode); static_cast<Application*>(qApp)->settings().setSidePaneMode(mode);
} }
void MainWindow::onSplitterMoved(int pos, int index) { void MainWindow::onSettingHiddenPlace(const QString& str, bool hide) {
static_cast<Application*>(qApp)->settings().setHiddenPlace(str, hide);
}
void MainWindow::onSplitterMoved(int pos, int /*index*/) {
Application* app = static_cast<Application*>(qApp); Application* app = static_cast<Application*>(qApp);
app->settings().setSplitterPos(pos); app->settings().setSplitterPos(pos);
} }
@ -1116,11 +1144,16 @@ void MainWindow::on_actionRename_triggered() {
} }
if(!files.empty()) { if(!files.empty()) {
for(auto& file: files) { for(auto& file: files) {
Fm::renameFile(file, nullptr); if(!Fm::renameFile(file, nullptr)) {
break;
}
} }
} }
} }
void MainWindow::on_actionBulkRename_triggered() {
BulkRenamer(currentPage()->selectedFiles(), this);
}
void MainWindow::on_actionSelectAll_triggered() { void MainWindow::on_actionSelectAll_triggered() {
currentPage()->selectAll(); currentPage()->selectAll();
@ -1181,12 +1214,12 @@ void MainWindow::onBackForwardContextMenu(QPoint pos) {
Fm::BrowseHistory& history = page->browseHistory(); Fm::BrowseHistory& history = page->browseHistory();
int current = history.currentIndex(); int current = history.currentIndex();
QMenu menu; QMenu menu;
for(int i = 0; i < history.size(); ++i) { for(size_t i = 0; i < history.size(); ++i) {
const BrowseHistoryItem& item = history.at(i); const BrowseHistoryItem& item = history.at(i);
auto path = item.path(); auto path = item.path();
auto name = path.displayName(); auto name = path.displayName();
QAction* action = menu.addAction(name.get()); QAction* action = menu.addAction(name.get());
if(i == current) { if(i == static_cast<size_t>(current)) {
// make the current path bold and checked // make the current path bold and checked
action->setCheckable(true); action->setCheckable(true);
action->setChecked(true); action->setChecked(true);
@ -1256,6 +1289,70 @@ void MainWindow::focusPathEntry() {
} }
} }
void MainWindow::dragEnterEvent(QDragEnterEvent* event) {
if(event->mimeData()->hasFormat("application/pcmanfm-qt-tab")) {
event->acceptProposedAction();
}
}
void MainWindow::dropEvent(QDropEvent* event) {
if(event->mimeData()->hasFormat("application/pcmanfm-qt-tab")) {
dropTab();
}
event->acceptProposedAction();
}
void MainWindow::dropTab() {
if(lastActive_ == nullptr // impossible
|| lastActive_ == this) { // don't drop on the same window
ui.tabBar->finishMouseMoveEvent();
return;
}
// close the tab in the first window and add
// its page to a new tab in the second window
TabPage* dropPage = lastActive_->currentPage();
if(dropPage) {
disconnect(dropPage, nullptr, lastActive_, nullptr);
// release mouse before tab removal because otherwise, the source tabbar
// might not be updated properly with tab reordering during a fast drag-and-drop
lastActive_->ui.tabBar->releaseMouse();
QWidget* page = lastActive_->ui.stackedWidget->currentWidget();
lastActive_->ui.stackedWidget->removeWidget(page);
int index = addTabWithPage(dropPage);
ui.tabBar->setCurrentIndex(index);
}
else {
ui.tabBar->finishMouseMoveEvent(); // impossible
}
}
void MainWindow::detachTab() {
if (ui.stackedWidget->count() == 1) { // don't detach a single tab
ui.tabBar->finishMouseMoveEvent();
return;
}
// close the tab and move its page to a new window
TabPage* dropPage = currentPage();
if(dropPage) {
disconnect(dropPage, nullptr, this, nullptr);
ui.tabBar->releaseMouse(); // as in dropTab()
QWidget* page = ui.stackedWidget->currentWidget();
ui.stackedWidget->removeWidget(page);
MainWindow* newWin = new MainWindow();
newWin->addTabWithPage(dropPage);
newWin->show();
}
else {
ui.tabBar->finishMouseMoveEvent(); // impossible
}
}
void MainWindow::updateFromSettings(Settings& settings) { void MainWindow::updateFromSettings(Settings& settings) {
// apply settings // apply settings
@ -1289,7 +1386,7 @@ void MainWindow::updateFromSettings(Settings& settings) {
} }
} }
static const char* su_cmd_subst(char opt, gpointer user_data) { static const char* su_cmd_subst(char /*opt*/, gpointer user_data) {
return (const char*)user_data; return (const char*)user_data;
} }

@ -32,7 +32,6 @@
#include <QStackedWidget> #include <QStackedWidget>
#include <QSplitter> #include <QSplitter>
#include "launcher.h" #include "launcher.h"
#include <libfm-qt/path.h>
#include <libfm-qt/core/filepath.h> #include <libfm-qt/core/filepath.h>
#include <libfm-qt/core/bookmarks.h> #include <libfm-qt/core/bookmarks.h>
@ -85,6 +84,7 @@ protected Q_SLOTS:
void on_actionPaste_triggered(); void on_actionPaste_triggered();
void on_actionDelete_triggered(); void on_actionDelete_triggered();
void on_actionRename_triggered(); void on_actionRename_triggered();
void on_actionBulkRename_triggered();
void on_actionSelectAll_triggered(); void on_actionSelectAll_triggered();
void on_actionInvertSelection_triggered(); void on_actionInvertSelection_triggered();
void on_actionPreferences_triggered(); void on_actionPreferences_triggered();
@ -173,15 +173,20 @@ protected Q_SLOTS:
} }
void focusPathEntry(); void focusPathEntry();
void toggleMenuBar(bool checked); void toggleMenuBar(bool checked);
void detachTab();
void onBookmarksChanged(); void onBookmarksChanged();
void onSettingHiddenPlace(const QString& str, bool hide);
protected: protected:
bool event(QEvent* event) override; bool event(QEvent* event) override;
void changeEvent(QEvent* event) override; void changeEvent(QEvent* event) override;
void closeTab(int index); void closeTab(int index);
virtual void resizeEvent(QResizeEvent* event) override; virtual void resizeEvent(QResizeEvent* event) override;
virtual void closeEvent(QCloseEvent* event) override; virtual void closeEvent(QCloseEvent* event) override;
virtual void dragEnterEvent(QDragEnterEvent* event) override;
virtual void dropEvent(QDropEvent* event) override;
private: private:
void loadBookmarksMenu(); void loadBookmarksMenu();
@ -191,6 +196,8 @@ private:
void updateStatusBarForCurrentPage(); void updateStatusBarForCurrentPage();
void setRTLIcons(bool isRTL); void setRTLIcons(bool isRTL);
void createPathBar(bool usePathButtons); void createPathBar(bool usePathButtons);
int addTabWithPage(TabPage* page, Fm::FilePath path = Fm::FilePath());
void dropTab();
private: private:
Ui::MainWindow ui; Ui::MainWindow ui;

@ -1,6 +1,6 @@
[Desktop Entry] [Desktop Entry]
Type=Application Type=Application
Name=PCManFM File Manager Name=PCManFM-Qt File Manager
GenericName=File Manager GenericName=File Manager
Comment=Browse the file system and manage the files Comment=Browse the file system and manage the files
Exec=pcmanfm-qt %U Exec=pcmanfm-qt %U

@ -4,7 +4,7 @@
int main(int argc, char** argv) { int main(int argc, char** argv) {
// ensure that glib integration of Qt is not turned off // ensure that glib integration of Qt is not turned off
// This fixes #168: https://github.com/lxde/pcmanfm-qt/issues/168 // This fixes #168: https://github.com/lxqt/pcmanfm-qt/issues/168
qunsetenv("QT_NO_GLIB"); qunsetenv("QT_NO_GLIB");
PCManFM::Application app(argc, argv); PCManFM::Application app(argc, argv);

@ -190,7 +190,15 @@
<item> <item>
<widget class="QCheckBox" name="quickExec"> <widget class="QCheckBox" name="quickExec">
<property name="text"> <property name="text">
<string>Don't ask options on launch executable file</string> <string>Launch executable files without prompt
(Requires application restart to take effect)</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="selectNewFiles">
<property name="text">
<string>Select newly created files</string>
</property> </property>
</widget> </widget>
</item> </item>

@ -28,6 +28,7 @@
#include <libfm-qt/folderview.h> #include <libfm-qt/folderview.h>
#include <libfm-qt/core/terminal.h> #include <libfm-qt/core/terminal.h>
#include <libfm-qt/core/archiver.h>
namespace PCManFM { namespace PCManFM {
@ -52,9 +53,9 @@ PreferencesDialog::~PreferencesDialog() {
static void findIconThemesInDir(QHash<QString, QString>& iconThemes, QString dirName) { static void findIconThemesInDir(QHash<QString, QString>& iconThemes, QString dirName) {
QDir dir(dirName); QDir dir(dirName);
QStringList subDirs = dir.entryList(QDir::AllDirs); const QStringList subDirs = dir.entryList(QDir::AllDirs);
GKeyFile* kf = g_key_file_new(); GKeyFile* kf = g_key_file_new();
Q_FOREACH(QString subDir, subDirs) { for(const 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), nullptr)) { if(g_key_file_load_from_file(kf, indexFile.toLocal8Bit().constData(), GKeyFileFlags(0), nullptr)) {
// FIXME: skip hidden ones // FIXME: skip hidden ones
@ -117,12 +118,11 @@ void PreferencesDialog::initIconThemes(Settings& settings) {
} }
void PreferencesDialog::initArchivers(Settings& settings) { void PreferencesDialog::initArchivers(Settings& settings) {
const GList* allArchivers = fm_archiver_get_all(); auto& allArchivers = Fm::Archiver::allArchivers();
int i = 0; for(int i = 0; i < int(allArchivers.size()); ++i) {
for(const GList* l = allArchivers; l; l = l->next, ++i) { auto& archiver = allArchivers[i];
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);
} }
} }
@ -220,6 +220,7 @@ void PreferencesDialog::initBehaviorPage(Settings& settings) {
ui.noUsbTrash->setChecked(settings.noUsbTrash()); ui.noUsbTrash->setChecked(settings.noUsbTrash());
ui.confirmTrash->setChecked(settings.confirmTrash()); ui.confirmTrash->setChecked(settings.confirmTrash());
ui.quickExec->setChecked(settings.quickExec()); ui.quickExec->setChecked(settings.quickExec());
ui.selectNewFiles->setChecked(settings.selectNewFiles());
} }
void PreferencesDialog::initThumbnailPage(Settings& settings) { void PreferencesDialog::initThumbnailPage(Settings& settings) {
@ -281,7 +282,8 @@ void PreferencesDialog::applyDisplayPage(Settings& settings) {
settings.setFallbackIconThemeName(newIconTheme); settings.setFallbackIconThemeName(newIconTheme);
QIcon::setThemeName(settings.fallbackIconThemeName()); QIcon::setThemeName(settings.fallbackIconThemeName());
// update the UI by emitting a style change event // update the UI by emitting a style change event
Q_FOREACH(QWidget* widget, QApplication::allWidgets()) { const auto widgets = QApplication::allWidgets();
for(QWidget* widget : widgets) {
QEvent event(QEvent::StyleChange); QEvent event(QEvent::StyleChange);
QApplication::sendEvent(widget, &event); QApplication::sendEvent(widget, &event);
} }
@ -327,6 +329,7 @@ void PreferencesDialog::applyBehaviorPage(Settings& settings) {
settings.setNoUsbTrash(ui.noUsbTrash->isChecked()); settings.setNoUsbTrash(ui.noUsbTrash->isChecked());
settings.setConfirmTrash(ui.confirmTrash->isChecked()); settings.setConfirmTrash(ui.confirmTrash->isChecked());
settings.setQuickExec(ui.quickExec->isChecked()); settings.setQuickExec(ui.quickExec->isChecked());
settings.setSelectNewFiles(ui.selectNewFiles->isChecked());
} }
void PreferencesDialog::applyThumbnailPage(Settings& settings) { void PreferencesDialog::applyThumbnailPage(Settings& settings) {

@ -73,6 +73,7 @@ Settings::Settings():
desktopIconSize_(48), desktopIconSize_(48),
showWmMenu_(false), showWmMenu_(false),
desktopShowHidden_(false), desktopShowHidden_(false),
desktopHideItems_(false),
desktopSortOrder_(Qt::AscendingOrder), desktopSortOrder_(Qt::AscendingOrder),
desktopSortColumn_(Fm::FolderModel::ColumnFileMTime), desktopSortColumn_(Fm::FolderModel::ColumnFileMTime),
desktopSortFolderFirst_(true), desktopSortFolderFirst_(true),
@ -104,6 +105,7 @@ Settings::Settings():
noUsbTrash_(false), noUsbTrash_(false),
confirmTrash_(false), confirmTrash_(false),
quickExec_(false), quickExec_(false),
selectNewFiles_(false),
showThumbnails_(true), showThumbnails_(true),
archiver_(), archiver_(),
siUnit_(false), siUnit_(false),
@ -207,6 +209,7 @@ bool Settings::loadFile(QString filePath) {
setNoUsbTrash(settings.value("NoUsbTrash", false).toBool()); setNoUsbTrash(settings.value("NoUsbTrash", false).toBool());
confirmTrash_ = settings.value("ConfirmTrash", false).toBool(); confirmTrash_ = settings.value("ConfirmTrash", false).toBool();
setQuickExec(settings.value("QuickExec", false).toBool()); setQuickExec(settings.value("QuickExec", false).toBool());
selectNewFiles_ = settings.value("SelectNewFiles", false).toBool();
// bool thumbnailLocal_; // bool thumbnailLocal_;
// bool thumbnailMax; // bool thumbnailMax;
settings.endGroup(); settings.endGroup();
@ -230,6 +233,7 @@ bool Settings::loadFile(QString filePath) {
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();
desktopHideItems_ = settings.value("HideItems", false).toBool();
desktopSortOrder_ = sortOrderFromString(settings.value("SortOrder").toString()); desktopSortOrder_ = sortOrderFromString(settings.value("SortOrder").toString());
desktopSortColumn_ = sortColumnFromString(settings.value("SortColumn").toString()); desktopSortColumn_ = sortColumnFromString(settings.value("SortColumn").toString());
@ -283,6 +287,7 @@ bool Settings::loadFile(QString filePath) {
placesRoot_ = settings.value("PlacesRoot", true).toBool(); placesRoot_ = settings.value("PlacesRoot", true).toBool();
placesComputer_ = settings.value("PlacesComputer", true).toBool(); placesComputer_ = settings.value("PlacesComputer", true).toBool();
placesNetwork_ = settings.value("PlacesNetwork", true).toBool(); placesNetwork_ = settings.value("PlacesNetwork", true).toBool();
hiddenPlaces_ = settings.value("HiddenPlaces").toStringList().toSet();
settings.endGroup(); settings.endGroup();
settings.beginGroup("Window"); settings.beginGroup("Window");
@ -339,6 +344,7 @@ bool Settings::saveFile(QString filePath) {
settings.setValue("NoUsbTrash", noUsbTrash_); settings.setValue("NoUsbTrash", noUsbTrash_);
settings.setValue("ConfirmTrash", confirmTrash_); settings.setValue("ConfirmTrash", confirmTrash_);
settings.setValue("QuickExec", quickExec_); settings.setValue("QuickExec", quickExec_);
settings.setValue("SelectNewFiles", selectNewFiles_);
// bool thumbnailLocal_; // bool thumbnailLocal_;
// bool thumbnailMax; // bool thumbnailMax;
settings.endGroup(); settings.endGroup();
@ -357,6 +363,7 @@ bool Settings::saveFile(QString filePath) {
settings.setValue("DesktopIconSize", desktopIconSize_); settings.setValue("DesktopIconSize", desktopIconSize_);
settings.setValue("ShowWmMenu", showWmMenu_); settings.setValue("ShowWmMenu", showWmMenu_);
settings.setValue("ShowHidden", desktopShowHidden_); settings.setValue("ShowHidden", desktopShowHidden_);
settings.setValue("HideItems", desktopHideItems_);
settings.setValue("SortOrder", sortOrderToString(desktopSortOrder_)); settings.setValue("SortOrder", sortOrderToString(desktopSortOrder_));
settings.setValue("SortColumn", sortColumnToString(desktopSortColumn_)); settings.setValue("SortColumn", sortColumnToString(desktopSortColumn_));
settings.setValue("SortFolderFirst", desktopSortFolderFirst_); settings.setValue("SortFolderFirst", desktopSortFolderFirst_);
@ -406,6 +413,13 @@ bool Settings::saveFile(QString filePath) {
settings.setValue("PlacesRoot", placesRoot_); settings.setValue("PlacesRoot", placesRoot_);
settings.setValue("PlacesComputer", placesComputer_); settings.setValue("PlacesComputer", placesComputer_);
settings.setValue("PlacesNetwork", placesNetwork_); settings.setValue("PlacesNetwork", placesNetwork_);
if (hiddenPlaces_.isEmpty()) { // don't save "@Invalid()"
settings.remove("HiddenPlaces");
}
else {
QStringList hiddenPlaces = hiddenPlaces_.toList();
settings.setValue("HiddenPlaces", hiddenPlaces);
}
settings.endGroup(); settings.endGroup();
settings.beginGroup("Window"); settings.beginGroup("Window");

@ -28,6 +28,7 @@
#include "desktopwindow.h" #include "desktopwindow.h"
#include <libfm-qt/sidepane.h> #include <libfm-qt/sidepane.h>
#include <libfm-qt/core/thumbnailjob.h> #include <libfm-qt/core/thumbnailjob.h>
#include <libfm-qt/core/archiver.h>
namespace PCManFM { namespace PCManFM {
@ -189,9 +190,7 @@ public:
void setArchiver(QString archiver) { void setArchiver(QString archiver) {
archiver_ = archiver; archiver_ = archiver;
// override libfm FmConfig Fm::Archiver::setDefaultArchiverByName(archiver_.toLocal8Bit().constData());
g_free(fm_config->archiver);
fm_config->archiver = g_strdup(archiver_.toLocal8Bit().constData());
} }
bool mountOnStartup() const { bool mountOnStartup() const {
@ -330,6 +329,14 @@ public:
desktopShowHidden_ = desktopShowHidden; desktopShowHidden_ = desktopShowHidden;
} }
bool desktopHideItems() const {
return desktopHideItems_;
}
void setDesktopHideItems(bool hide) {
desktopHideItems_ = hide;
}
Qt::SortOrder desktopSortOrder() const { Qt::SortOrder desktopSortOrder() const {
return desktopSortOrder_; return desktopSortOrder_;
} }
@ -350,7 +357,7 @@ public:
return desktopSortFolderFirst_; return desktopSortFolderFirst_;
} }
void setSesktopSortFolderFirst(bool desktopFolderFirst) { void setDesktopSortFolderFirst(bool desktopFolderFirst) {
desktopSortFolderFirst_ = desktopFolderFirst; desktopSortFolderFirst_ = desktopFolderFirst;
} }
@ -546,6 +553,19 @@ public:
placesNetwork_ = placesNetwork; placesNetwork_ = placesNetwork;
} }
QSet<QString> getHiddenPlaces() const {
return hiddenPlaces_;
}
void setHiddenPlace(const QString& str, bool hide) {
if(hide) {
hiddenPlaces_ << str;
}
else {
hiddenPlaces_.remove(str);
}
}
Qt::SortOrder sortOrder() const { Qt::SortOrder sortOrder() const {
return sortOrder_; return sortOrder_;
@ -649,6 +669,14 @@ public:
fm_config->quick_exec = quickExec_; fm_config->quick_exec = quickExec_;
} }
bool selectNewFiles() const {
return selectNewFiles_;
}
void setSelectNewFiles(bool value) {
selectNewFiles_ = value;
}
// bool thumbnailLocal_; // bool thumbnailLocal_;
// bool thumbnailMax; // bool thumbnailMax;
@ -874,6 +902,7 @@ private:
bool showWmMenu_; bool showWmMenu_;
bool desktopShowHidden_; bool desktopShowHidden_;
bool desktopHideItems_;
Qt::SortOrder desktopSortOrder_; Qt::SortOrder desktopSortOrder_;
Fm::FolderModel::ColumnId desktopSortColumn_; Fm::FolderModel::ColumnId desktopSortColumn_;
bool desktopSortFolderFirst_; bool desktopSortFolderFirst_;
@ -908,6 +937,7 @@ private:
bool noUsbTrash_; // do not trash files on usb removable devices bool noUsbTrash_; // do not trash files on usb removable devices
bool confirmTrash_; // Confirm before moving files into "trash can" bool confirmTrash_; // Confirm before moving files into "trash can"
bool quickExec_; // Don't ask options on launch executable file bool quickExec_; // Don't ask options on launch executable file
bool selectNewFiles_;
bool showThumbnails_; bool showThumbnails_;
@ -924,6 +954,7 @@ private:
bool placesRoot_; bool placesRoot_;
bool placesComputer_; bool placesComputer_;
bool placesNetwork_; bool placesNetwork_;
QSet<QString> hiddenPlaces_;
int bigIconSize_; int bigIconSize_;
int smallIconSize_; int smallIconSize_;

@ -19,23 +19,92 @@
#include "tabbar.h" #include "tabbar.h"
#include <QPointer>
#include <QMouseEvent> #include <QMouseEvent>
#include <QApplication>
#include <QDrag>
#include <QMimeData>
namespace PCManFM { namespace PCManFM {
TabBar::TabBar(QWidget *parent): TabBar::TabBar(QWidget *parent):
QTabBar(parent) QTabBar(parent),
dragStarted_(false)
{ {
} }
void TabBar::mousePressEvent(QMouseEvent *event) {
QTabBar::mousePressEvent (event);
if(event->button() == Qt::LeftButton
&& tabAt(event->pos()) > -1) {
dragStartPosition_ = event->pos();
}
dragStarted_ = false;
}
void TabBar::mouseMoveEvent(QMouseEvent *event)
{
if(!dragStartPosition_.isNull()
&& (event->pos() - dragStartPosition_).manhattanLength() < QApplication::startDragDistance()) {
dragStarted_ = true;
}
if((event->buttons() & Qt::LeftButton)
&& dragStarted_
&& !window()->geometry().contains(event->globalPos())) {
if(currentIndex() == -1) {
return;
}
QPointer<QDrag> drag = new QDrag(this);
QMimeData *mimeData = new QMimeData;
mimeData->setData("application/pcmanfm-qt-tab", QByteArray());
drag->setMimeData(mimeData);
Qt::DropAction dragged = drag->exec();
if(dragged == Qt::IgnoreAction) { // a tab is dropped outside all windows
if(count() > 1) {
Q_EMIT tabDetached();
}
else {
finishMouseMoveEvent();
}
event->accept();
}
else if(dragged == Qt::MoveAction) { // a tab is dropped into another window
event->accept();
}
drag->deleteLater();
}
else {
QTabBar::mouseMoveEvent(event);
}
}
void TabBar::finishMouseMoveEvent() {
QMouseEvent finishingEvent(QEvent::MouseMove, QPoint(), Qt::NoButton, Qt::NoButton, Qt::NoModifier);
mouseMoveEvent(&finishingEvent);
}
void TabBar::releaseMouse() {
QMouseEvent releasingEvent(QEvent::MouseButtonRelease, QPoint(), Qt::LeftButton, Qt::NoButton, Qt::NoModifier);
mouseReleaseEvent(&releasingEvent);
}
void TabBar::mouseReleaseEvent(QMouseEvent *event) { void TabBar::mouseReleaseEvent(QMouseEvent *event) {
if (event->button() == Qt::MiddleButton) { if (event->button() == Qt::MiddleButton) {
int index = tabAt(event->pos()); int index = tabAt(event->pos());
if (index != -1) { if (index != -1) {
Q_EMIT tabCloseRequested(index); Q_EMIT tabCloseRequested(index);
}
}
QTabBar::mouseReleaseEvent(event);
}
// Let the main window receive dragged tabs!
void TabBar::dragEnterEvent(QDragEnterEvent *event) {
if(event->mimeData()->hasFormat("application/pcmanfm-qt-tab")) {
event->ignore();
} }
}
QTabBar::mouseReleaseEvent(event);
} }
} }

@ -31,10 +31,23 @@ class TabBar : public QTabBar {
Q_OBJECT Q_OBJECT
public: public:
explicit TabBar(QWidget *parent = 0); explicit TabBar(QWidget *parent = 0);
void finishMouseMoveEvent();
void releaseMouse();
Q_SIGNALS:
void tabDetached();
protected: protected:
void mouseReleaseEvent(QMouseEvent *event); void mouseReleaseEvent(QMouseEvent *event);
// from qtabbar.cpp
virtual void mousePressEvent(QMouseEvent *event);
virtual void mouseMoveEvent(QMouseEvent *event);
virtual void dragEnterEvent(QDragEnterEvent *event);
private:
QPoint dragStartPosition_;
bool dragStarted_;
}; };
} }

@ -46,38 +46,12 @@ bool ProxyFilter::filterAcceptsRow(const Fm::ProxyFolderModel* model, const std:
return true; return true;
} }
QString baseName = QString::fromStdString(info->name()); QString baseName = QString::fromStdString(info->name());
if(!virtHiddenList_.isEmpty() && !model->showHidden() && virtHiddenList_.contains(baseName)) {
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(const std::shared_ptr<Fm::Folder> &folder) {
virtHiddenList_ = QStringList(); // reset the list
if(!folder) {
return;
}
auto path = folder->path();
if(path) {
auto pathStr = path.localPath();
if(pathStr) {
QString dotHidden = QString::fromUtf8(pathStr.get()) + QString("/.hidden");
// FIXME: this does not work for non-local filesystems
QFile file(dotHidden);
if(file.open(QIODevice::ReadOnly | QIODevice::Text)) {
QTextStream in(&file);
while(!in.atEnd()) {
virtHiddenList_.append(in.readLine());
}
file.close();
}
}
}
}
TabPage::TabPage(QWidget* parent): TabPage::TabPage(QWidget* parent):
QWidget(parent), QWidget(parent),
folderView_{nullptr}, folderView_{nullptr},
@ -85,13 +59,15 @@ TabPage::TabPage(QWidget* parent):
proxyModel_{nullptr}, proxyModel_{nullptr},
proxyFilter_{nullptr}, proxyFilter_{nullptr},
verticalLayout{nullptr}, verticalLayout{nullptr},
overrideCursor_(false) { overrideCursor_(false),
selectionTimer_(nullptr) {
Settings& settings = static_cast<Application*>(qApp)->settings(); Settings& settings = static_cast<Application*>(qApp)->settings();
// create proxy folder model to do item filtering // create proxy folder model to do item filtering
proxyModel_ = new ProxyFolderModel(); proxyModel_ = new ProxyFolderModel();
proxyModel_->setShowHidden(settings.showHidden()); proxyModel_->setShowHidden(settings.showHidden());
proxyModel_->setBackupAsHidden(settings.backupAsHidden());
proxyModel_->setShowThumbnails(settings.showThumbnails()); proxyModel_->setShowThumbnails(settings.showThumbnails());
connect(proxyModel_, &ProxyFolderModel::sortFilterChanged, this, &TabPage::sortFilterChanged); connect(proxyModel_, &ProxyFolderModel::sortFilterChanged, this, &TabPage::sortFilterChanged);
@ -122,8 +98,9 @@ TabPage::~TabPage() {
if(proxyModel_) { if(proxyModel_) {
delete proxyModel_; delete proxyModel_;
} }
disconnect(folderModel_, &Fm::FolderModel::fileSizeChanged, this, &TabPage::onFileSizeChanged);
if(folderModel_) { if(folderModel_) {
disconnect(folderModel_, &Fm::FolderModel::fileSizeChanged, this, &TabPage::onFileSizeChanged);
disconnect(folderModel_, &Fm::FolderModel::filesAdded, this, &TabPage::onFilesAdded);
folderModel_->unref(); folderModel_->unref();
} }
@ -144,6 +121,9 @@ void TabPage::freeFolder() {
} }
void TabPage::onFolderStartLoading() { void TabPage::onFolderStartLoading() {
if(folderModel_){
disconnect(folderModel_, &Fm::FolderModel::filesAdded, this, &TabPage::onFilesAdded);
}
if(!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.
@ -184,8 +164,12 @@ void TabPage::onUiUpdated() {
folderView_->childView()->setCurrentIndex(index); folderView_->childView()->setCurrentIndex(index);
} }
} }
// update selection statusbar info when needed if(folderModel_) {
connect(folderModel_, &Fm::FolderModel::fileSizeChanged, this, &TabPage::onFileSizeChanged); // update selection statusbar info when needed
connect(folderModel_, &Fm::FolderModel::fileSizeChanged, this, &TabPage::onFileSizeChanged);
// get ready to select files that may be added later
connect(folderModel_, &Fm::FolderModel::filesAdded, this, &TabPage::onFilesAdded);
}
} }
void TabPage::onFileSizeChanged(const QModelIndex& index) { void TabPage::onFileSizeChanged(const QModelIndex& index) {
@ -197,6 +181,22 @@ void TabPage::onFileSizeChanged(const QModelIndex& index) {
} }
} }
// slot
void TabPage::onFilesAdded(Fm::FileInfoList files) {
if(static_cast<Application*>(qApp)->settings().selectNewFiles()) {
if(!selectionTimer_) {
folderView_->selectFiles(files, false);
selectionTimer_ = new QTimer (this);
selectionTimer_->setSingleShot(true);
selectionTimer_->start(200);
}
else {
folderView_->selectFiles(files, selectionTimer_->isActive());
selectionTimer_->start(200);
}
}
}
void TabPage::onFolderFinishLoading() { void TabPage::onFolderFinishLoading() {
auto fi = folder_->info(); 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.
@ -252,8 +252,8 @@ void TabPage::onFolderError(const Fm::GErrorPtr& err, Fm::Job::ErrorSeverity sev
if(err.domain() == G_IO_ERROR) { if(err.domain() == G_IO_ERROR) {
if(err.code() == G_IO_ERROR_NOT_MOUNTED && severity < Fm::Job::ErrorSeverity::CRITICAL) { if(err.code() == G_IO_ERROR_NOT_MOUNTED && severity < Fm::Job::ErrorSeverity::CRITICAL) {
auto& path = folder_->path(); auto& path = folder_->path();
MountOperation* op = new MountOperation(this); MountOperation* op = new MountOperation(true);
op->mount(path); op->mountEnclosingVolume(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"
// signal, so we get more "start-loading" signals than "finish-loading" // signal, so we get more "start-loading" signals than "finish-loading"
@ -290,8 +290,8 @@ void TabPage::onFolderFsInfo() {
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);
fm_file_size_to_str(total_str, sizeof(total_str), total, fm_config->si_unit); fm_file_size_to_str(total_str, sizeof(total_str), total, fm_config->si_unit);
msg = tr("Free space: %1 (Total: %2)") msg = tr("Free space: %1 (Total: %2)")
.arg(QString::fromUtf8(free_str)) .arg(QString::fromUtf8(free_str),
.arg(QString::fromUtf8(total_str)); QString::fromUtf8(total_str));
} }
else { else {
msg.clear(); msg.clear();
@ -310,6 +310,12 @@ QString TabPage::formatStatusText() {
if(hidden_files > 0) { if(hidden_files > 0) {
text += tr(" (%n hidden)", "", hidden_files); text += tr(" (%n hidden)", "", hidden_files);
} }
auto fi = folder_->info();
if (fi && fi->isSymlink()) {
text += QString(" %2(%1)")
.arg(encloseWithBidiMarks(tr("Link to") + QChar(QChar::Space) + QString::fromStdString(fi->target())),
(layoutDirection() == Qt::RightToLeft) ? QChar(0x200f) : QChar(0x200e));
}
return text; return text;
} }
return QString(); return QString();
@ -388,6 +394,7 @@ void TabPage::chdir(Fm::FilePath newPath, bool addHistory) {
// free the previous model // free the previous model
if(folderModel_) { if(folderModel_) {
disconnect(folderModel_, &Fm::FolderModel::fileSizeChanged, this, &TabPage::onFileSizeChanged); disconnect(folderModel_, &Fm::FolderModel::fileSizeChanged, this, &TabPage::onFileSizeChanged);
disconnect(folderModel_, &Fm::FolderModel::filesAdded, this, &TabPage::onFilesAdded);
proxyModel_->setSourceModel(nullptr); proxyModel_->setSourceModel(nullptr);
folderModel_->unref(); // unref the cached model folderModel_->unref(); // unref the cached model
folderModel_ = nullptr; folderModel_ = nullptr;
@ -399,7 +406,6 @@ void TabPage::chdir(Fm::FilePath newPath, bool addHistory) {
Q_EMIT titleChanged(newPath.baseName().get()); // FIXME: display name Q_EMIT titleChanged(newPath.baseName().get()); // FIXME: display name
folder_ = Fm::Folder::fromPath(newPath); folder_ = Fm::Folder::fromPath(newPath);
proxyFilter_->setVirtHidden(folder_);
if(addHistory) { if(addHistory) {
// add current path to browse history // add current path to browse history
history_.add(path()); history_.add(path());
@ -448,7 +454,6 @@ void TabPage::invertSelection() {
void TabPage::reload() { void TabPage::reload() {
if(folder_) { if(folder_) {
proxyFilter_->setVirtHidden(folder_); // reread ".hidden"
// don't select or scroll to the previous folder after reload // don't select or scroll to the previous folder after reload
lastFolderPath_ = Fm::FilePath(); lastFolderPath_ = Fm::FilePath();
// but remember the current scroll position // but remember the current scroll position
@ -460,6 +465,17 @@ void TabPage::reload() {
} }
} }
// 200e LEFT-TO-RIGHT MARK
// 200f RIGHT-TO-LEFT MARK
// 202a LEFT-TO-RIGHT EMBEDDING
// 202b RIGHT-TO-LEFT EMBEDDING
// 202c POP DIRECTIONAL FORMATTING
QString TabPage::encloseWithBidiMarks(const QString& text) {
QChar bidiMark = text.isRightToLeft() ? QChar(0x200f) : QChar(0x200e);
QChar embedBidiMark = text.isRightToLeft() ? QChar(0x202b) : QChar(0x202a);
return embedBidiMark+text+bidiMark+QChar(0x202c);
}
// when the current selection in the folder view is changed // when the current selection in the folder view is changed
void TabPage::onSelChanged() { void TabPage::onSelChanged() {
QString msg; QString msg;
@ -467,24 +483,44 @@ void TabPage::onSelChanged() {
auto files = folderView_->selectedFiles(); auto files = folderView_->selectedFiles();
int numSel = files.size(); 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 (also, tell if it is a symlink)*/
auto& fi = files.front(); auto& fi = files.front();
if(!fi->isDir()) { if(!fi->isDir()) {
msg = QString("\"%1\" (%2) %3") if(fi->isSymlink()) {
.arg(fi->displayName()) msg = QString("%5\"%1\" %5(%2) %5%3 %5(%4)")
.arg(Fm::formatFileSize(fi->size(), fm_config->si_unit)) // FIXME: deprecate fm_config .arg(encloseWithBidiMarks(fi->displayName()),
.arg(fi->mimeType()->desc()); encloseWithBidiMarks(Fm::formatFileSize(fi->size(), fm_config->si_unit)),
encloseWithBidiMarks(fi->mimeType()->desc()),
encloseWithBidiMarks(tr("Link to") + QChar(QChar::Space) + QString::fromStdString(fi->target())),
(layoutDirection() == Qt::RightToLeft) ? QChar(0x200f) : QChar(0x200e));
}
else {
msg = QString("%4\"%1\" %4(%2) %4%3")
.arg(encloseWithBidiMarks(fi->displayName()),
encloseWithBidiMarks(Fm::formatFileSize(fi->size(), fm_config->si_unit)), // FIXME: deprecate fm_config
encloseWithBidiMarks(fi->mimeType()->desc()),
(layoutDirection() == Qt::RightToLeft) ? QChar(0x200f) : QChar(0x200e));
}
} }
else { else {
msg = QString("\"%1\" %2") if(fi->isSymlink()) {
.arg(fi->displayName()) msg = QString("%4\"%1\" %4%2 %4(%3)")
.arg(fi->mimeType()->desc()); .arg(encloseWithBidiMarks(fi->displayName()),
encloseWithBidiMarks(fi->mimeType()->desc()),
encloseWithBidiMarks(tr("Link to") + QChar(QChar::Space) + QString::fromStdString(fi->target())),
(layoutDirection() == Qt::RightToLeft) ? QChar(0x200f) : QChar(0x200e));
}
else {
msg = QString("%3\"%1\" %3%2")
.arg(encloseWithBidiMarks(fi->displayName()),
encloseWithBidiMarks(fi->mimeType()->desc()),
(layoutDirection() == Qt::RightToLeft) ? QChar(0x200f) : QChar(0x200e));
}
} }
/* 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;
msg = tr("%n item(s) selected", nullptr, numSel); msg = tr("%n item(s) selected", nullptr, 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) {
@ -533,7 +569,7 @@ void TabPage::forward() {
} }
void TabPage::jumpToHistory(int index) { void TabPage::jumpToHistory(int index) {
if(index >= 0 && index < history_.size()) { if(index >= 0 && static_cast<size_t>(index) < history_.size()) {
// remember current scroll position // remember current scroll position
BrowseHistoryItem& item = history_.currentItem(); BrowseHistoryItem& item = history_.currentItem();
QAbstractItemView* childView = folderView_->childView(); QAbstractItemView* childView = folderView_->childView();

@ -26,7 +26,6 @@
#include <libfm/fm.h> #include <libfm/fm.h>
#include <libfm-qt/browsehistory.h> #include <libfm-qt/browsehistory.h>
#include "view.h" #include "view.h"
#include <libfm-qt/path.h>
#include "settings.h" #include "settings.h"
#include <libfm-qt/core/fileinfo.h> #include <libfm-qt/core/fileinfo.h>
@ -48,7 +47,6 @@ class ProxyFilter : public Fm::ProxyFolderModelFilter {
public: public:
bool filterAcceptsRow(const Fm::ProxyFolderModel* model, const std::shared_ptr<const Fm::FileInfo>& info) const; bool filterAcceptsRow(const Fm::ProxyFolderModel* model, const std::shared_ptr<const Fm::FileInfo>& info) const;
virtual ~ProxyFilter() {} virtual ~ProxyFilter() {}
void setVirtHidden(const std::shared_ptr<Fm::Folder>& folder);
QString getFilterStr() { QString getFilterStr() {
return filterStr_; return filterStr_;
} }
@ -58,7 +56,6 @@ public:
private: private:
QString filterStr_; QString filterStr_;
QStringList virtHiddenList_;
}; };
class TabPage : public QWidget { class TabPage : public QWidget {
@ -212,11 +209,15 @@ protected Q_SLOTS:
void onSelChanged(); void onSelChanged();
void onUiUpdated(); void onUiUpdated();
void onFileSizeChanged(const QModelIndex& index); void onFileSizeChanged(const QModelIndex& index);
void onFilesAdded(const Fm::FileInfoList files);
private: private:
void freeFolder(); void freeFolder();
QString formatStatusText(); QString formatStatusText();
// Adds bidi marks (RLM/LRM/RLE/LRE/POP) around the text for the statusbar.
QString encloseWithBidiMarks(const QString& text);
void onFolderStartLoading(); void onFolderStartLoading();
void onFolderFinishLoading(); void onFolderFinishLoading();
@ -240,6 +241,7 @@ private:
Fm::FilePath lastFolderPath_; // last browsed folder Fm::FilePath lastFolderPath_; // last browsed folder
bool overrideCursor_; bool overrideCursor_;
FolderSettings folderSettings_; FolderSettings folderSettings_;
QTimer* selectionTimer_;
}; };
} }

@ -0,0 +1,3 @@
Name[es]=Escritorio
GenericName[es]=Configuración del escritorio
Comment[es]=Cambiar el fondo de pantalla y el comportamiento del escritorio

@ -1,4 +1,4 @@
#Translations / translated by tulliana <tulliana@yandex.com> #Translations / translated by tulliana <tulliana@yandex.com>
Name[tr]=Dosya Yöneticisi (pcmanfm-qt) Name[tr]=Dosya Yöneticisi (PCManFM-Qt)
GenericName[tr]=Dosya ve masaüstü yönetim uygulaması GenericName[tr]=Dosya ve masaüstü yönetim uygulaması
Comment[tr]=Dosya Yöneticisi ve Masaüstü Ayarları (duvarkağıtları, menüler vs..) Comment[tr]=Dosya Yöneticisi ve Masaüstü Ayarları (duvarkağıtları, menüler vs..)

@ -0,0 +1,4 @@
#Translations
Name[zh_CN]=桌面
GenericName[zh_CN]=桌面设置
Comment[zh_CN]=更改墙纸与桌面管理器的行为。

@ -1,4 +1,4 @@
#Translations #Translations
Name[ar]=مدير الملفّات PCManFM Name[ar]=مدير الملفّات PCManFM-Qt
GenericName[ar]=مدير ملفّات GenericName[ar]=مدير ملفّات
Comment[ar]=تصفّح نظام الملفّات وأدر ملفّاتك Comment[ar]=تصفّح نظام الملفّات وأدر ملفّاتك

@ -1,4 +1,4 @@
#Translations #Translations
Name[ca]=Gestor de fitxers PCManFM Name[ca]=Gestor de fitxers PCManFM-Qt
GenericName[ca]=Gestor de fitxers GenericName[ca]=Gestor de fitxers
Comment[ca]=Navegueu pel sistema de fitxers i gestioneu els fitxers Comment[ca]=Navegueu pel sistema de fitxers i gestioneu els fitxers

@ -1,3 +1,3 @@
Name[da]=PCManFM-filhåndtering Name[da]=PCManFM-Qt-filhåndtering
GenericName[da]=Filhåndtering GenericName[da]=Filhåndtering
Comment[da]=Gennemse filsystemet og håndtér filerne Comment[da]=Gennemse filsystemet og håndtér filerne

@ -1,4 +1,4 @@
Name[el]=Διαχειριστής αρχείων PCManFM Name[el]=Διαχειριστής αρχείων PCManFM-Qt
GenericName[el]=Διαχειριστής αρχείων GenericName[el]=Διαχειριστής αρχείων
Comment[el]=Περιήγηση του συστήματος αρχείων και διαχείριση των αρχείων Comment[el]=Περιήγηση του συστήματος αρχείων και διαχείριση των αρχείων

@ -0,0 +1,3 @@
Name[es]=Gestor de archivos PCManFM-Qt
GenericName[es]=Gestor de archivos
Comment[es]=Explorar el sistema de archivos y gestionar los archivos

@ -1,4 +1,4 @@
#Translations #Translations
Name[it]=Gestore file PCmanFM Name[it]=Gestore file PCManFM-Qt
GenericName[it]=Gestore file GenericName[it]=Gestore file
Comment[it]=Esplora e organizza file e cartelle Comment[it]=Esplora e organizza file e cartelle

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

@ -1,4 +1,4 @@
#Translations #Translations
Name[pl]=Menedżer plików PCManFM Name[pl]=Menedżer plików PCManFM-Qt
GenericName[pl]=Menedżer plików GenericName[pl]=Menedżer plików
Comment[pl]=Przegląd systemu plików i zarządzanie plikami Comment[pl]=Przegląd systemu plików i zarządzanie plikami

@ -1,4 +1,4 @@
#Translations #Translations
Name[pt]=Gestor de ficheiros PCManFM Name[pt]=Gestor de ficheiros PCManFM-Qt
GenericName[pt]=Gestor de ficheiros GenericName[pt]=Gestor de ficheiros
Comment[pt]=Explorar o sistema de ficheiros e gerir os seus ficheiros e pastas Comment[pt]=Explorar o sistema de ficheiros e gerir os seus ficheiros e pastas

@ -1,4 +1,4 @@
#Translations #Translations
Name[pt_BR]=Gerenciador de Arquivos PCManFM Name[pt_BR]=Gerenciador de Arquivos PCManFM-Qt
GenericName[pt_BR]=Gerenciador de Arquivos GenericName[pt_BR]=Gerenciador de Arquivos
Comment[pt_BR]=Navegue pelo sistema de arquivos e gerencie arquivos e pastas Comment[pt_BR]=Navegue pelo sistema de arquivos e gerencie arquivos e pastas

@ -1,4 +1,4 @@
#Translations #Translations
Name[ru]=Диспетчер файлов PCManFM Name[ru]=Диспетчер файлов PCManFM-Qt
GenericName[ru]=Диспетчер файлов GenericName[ru]=Диспетчер файлов
Comment[ru]=Просматривайте файловую систему и управляйте файлами Comment[ru]=Просматривайте файловую систему и управляйте файлами

@ -0,0 +1,4 @@
#Translations
Name[zh_CN]=PCManFM-Qt 文件管理器
GenericName[zh_CN]=文件管理器
Comment[zh_CN]=浏览文件系统并管理文件。

@ -126,7 +126,7 @@ void View::prepareFileMenu(Fm::FileMenu* menu) {
} }
} }
void View::prepareFolderMenu(Fm::FolderMenu* menu) { void View::prepareFolderMenu(Fm::FolderMenu* /*menu*/) {
} }
void View::updateFromSettings(Settings& settings) { void View::updateFromSettings(Settings& settings) {
@ -143,6 +143,7 @@ void View::updateFromSettings(Settings& settings) {
Fm::ProxyFolderModel* proxyModel = model(); Fm::ProxyFolderModel* proxyModel = model();
if(proxyModel) { if(proxyModel) {
proxyModel->setShowThumbnails(settings.showThumbnails()); proxyModel->setShowThumbnails(settings.showThumbnails());
proxyModel->setBackupAsHidden(settings.backupAsHidden());
} }
} }

Loading…
Cancel
Save