Skip to content

Commit

Permalink
Added an option for single window mode (#1097)
Browse files Browse the repository at this point in the history
With the option enabled, folders will be opened in new tabs of an existing window (the last focused or created window) if an external app calls pcmanfm-qt, the command-line is used, or folders are clicked on desktop.

The option is disabled by default.

The user could still open folders in new windows by using the context menu or adding the `-n/--new-window` command-line option. Actually, `-n/--new-window` makes sense only after this change.

Also, the pointer to the last active window is changed to a guarded pointer. An ordinary pointer was a potential cause of crash but, luckily, it couldn't cause a crash before this feature.

Closes #1094 and fixes #1096
  • Loading branch information
tsujan authored Apr 22, 2020
1 parent 53f48ab commit 4df37c0
Show file tree
Hide file tree
Showing 11 changed files with 93 additions and 20 deletions.
23 changes: 21 additions & 2 deletions pcmanfm/application.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -505,7 +505,7 @@ void Application::connectToServer() {
dlg->show();
}

void Application::launchFiles(QString cwd, QStringList paths, bool /*inNewWindow*/) {
void Application::launchFiles(QString cwd, QStringList paths, bool inNewWindow) {
Fm::FilePathList pathList;
Fm::FilePath cwd_path;
QStringList::iterator it;
Expand All @@ -530,7 +530,26 @@ void Application::launchFiles(QString cwd, QStringList paths, bool /*inNewWindow
pathList.push_back(std::move(path));
}

Launcher(nullptr).launchPaths(nullptr, pathList);
if(!inNewWindow && settings_.singleWindowMode()) {
MainWindow* window = MainWindow::lastActive();
// if there is no last active window, find the last created window
if(window == nullptr) {
QWidgetList windows = topLevelWidgets();
for(int i = 0; i < windows.size(); ++i) {
auto win = windows.at(windows.size() - 1 - i);
if(win->inherits("PCManFM::MainWindow")) {
window = static_cast<MainWindow*>(win);
break;
}
}
}
auto launcher = Launcher(window);
launcher.openInNewTab();
launcher.launchPaths(nullptr, pathList);
}
else {
Launcher(nullptr).launchPaths(nullptr, pathList);
}
}

void Application::openFolders(Fm::FileInfoList files) {
Expand Down
1 change: 1 addition & 0 deletions pcmanfm/launcher.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ bool Launcher::openFolder(GAppLaunchContext* /*ctx*/, const Fm::FileInfoList& fo
}
mainWindow->show();
mainWindow->raise();
mainWindow->activateWindow();
openInNewTab_ = false;
return true;
}
Expand Down
4 changes: 4 additions & 0 deletions pcmanfm/launcher.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ class Launcher : public Fm::FileLauncher {
Launcher(MainWindow* mainWindow = nullptr);
~Launcher();

bool hasMainWindow() const {
return mainWindow_ != nullptr;
}

void openInNewTab() {
openInNewTab_ = true;
}
Expand Down
2 changes: 1 addition & 1 deletion pcmanfm/mainwindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ void ViewFrame::removeTopBar() {
//======================================================================

// static
MainWindow* MainWindow::lastActive_ = nullptr;
QPointer<MainWindow> MainWindow::lastActive_;

MainWindow::MainWindow(Fm::FilePath path):
QMainWindow(),
Expand Down
3 changes: 2 additions & 1 deletion pcmanfm/mainwindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#define FM_MAIN_WINDOW_H

#include "ui_main-win.h"
#include <QPointer>
#include <QMainWindow>
#include <QListView>
#include <QSortFilterProxyModel>
Expand Down Expand Up @@ -268,7 +269,7 @@ protected Q_SLOTS:
// not from another window. So, we get the mode at the start and keep it.
bool splitView_;

static MainWindow* lastActive_;
static QPointer<MainWindow> lastActive_;
};

}
Expand Down
12 changes: 11 additions & 1 deletion pcmanfm/preferences.ui
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,16 @@
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="singleWindowMode">
<property name="toolTip">
<string>Open folders in new tabs as far as possible</string>
</property>
<property name="text">
<string>Single window mode</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
Expand Down Expand Up @@ -469,7 +479,7 @@ A space is also reserved for 3 lines of text.</string>
</layout>
</widget>
<widget class="QWidget" name="uiPage">
<layout class="QVBoxLayout" name="verticalLayout_5" stretch="0,0,1">
<layout class="QVBoxLayout" name="verticalLayout_5" stretch="0,1">
<item>
<widget class="QGroupBox" name="groupBox_5">
<property name="title">
Expand Down
2 changes: 2 additions & 0 deletions pcmanfm/preferencesdialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,7 @@ void PreferencesDialog::initBehaviorPage(Settings& settings) {
ui.confirmTrash->setChecked(settings.confirmTrash());
ui.quickExec->setChecked(settings.quickExec());
ui.selectNewFiles->setChecked(settings.selectNewFiles());
ui.singleWindowMode->setChecked(settings.singleWindowMode());

// app restart warning
connect(ui.quickExec, &QAbstractButton::toggled, [this, &settings] (bool checked) {
Expand Down Expand Up @@ -338,6 +339,7 @@ void PreferencesDialog::applyBehaviorPage(Settings& settings) {
settings.setConfirmTrash(ui.confirmTrash->isChecked());
settings.setQuickExec(ui.quickExec->isChecked());
settings.setSelectNewFiles(ui.selectNewFiles->isChecked());
settings.setSingleWindowMode(ui.singleWindowMode->isChecked());
}

void PreferencesDialog::applyThumbnailPage(Settings& settings) {
Expand Down
3 changes: 3 additions & 0 deletions pcmanfm/settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ Settings::Settings():
supportTrash_(Fm::uriExists("trash:///")), // check if trash:/// is supported
fallbackIconThemeName_(),
useFallbackIconTheme_(QIcon::themeName().isEmpty() || QIcon::themeName() == QLatin1String("hicolor")),
singleWindowMode_(false),
bookmarkOpenMethod_(OpenInCurrentTab),
suCommand_(),
terminal_(),
Expand Down Expand Up @@ -212,6 +213,7 @@ bool Settings::loadFile(QString filePath) {
settings.endGroup();

settings.beginGroup(QStringLiteral("Behavior"));
singleWindowMode_ = settings.value(QStringLiteral("SingleWindowMode"), false).toBool();
bookmarkOpenMethod_ = bookmarkOpenMethodFromString(settings.value(QStringLiteral("BookmarkOpenMethod")).toString());
// settings for use with libfm
useTrash_ = settings.value(QStringLiteral("UseTrash"), true).toBool();
Expand Down Expand Up @@ -360,6 +362,7 @@ bool Settings::saveFile(QString filePath) {
settings.endGroup();

settings.beginGroup(QStringLiteral("Behavior"));
settings.setValue(QStringLiteral("SingleWindowMode"), singleWindowMode_);
settings.setValue(QStringLiteral("BookmarkOpenMethod"), QString::fromUtf8(bookmarkOpenMethodToString(bookmarkOpenMethod_)));
// settings for use with libfm
settings.setValue(QStringLiteral("UseTrash"), useTrash_);
Expand Down
9 changes: 9 additions & 0 deletions pcmanfm/settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,14 @@ class Settings : public QObject {
fallbackIconThemeName_ = iconThemeName;
}

bool singleWindowMode() const {
return singleWindowMode_;
}

void setSingleWindowMode(bool singleWindowMode) {
singleWindowMode_ = singleWindowMode;
}

OpenDirTargetType bookmarkOpenMethod() {
return bookmarkOpenMethod_;
}
Expand Down Expand Up @@ -986,6 +994,7 @@ class Settings : public QObject {
QString fallbackIconThemeName_;
bool useFallbackIconTheme_;

bool singleWindowMode_;
OpenDirTargetType bookmarkOpenMethod_;
QString suCommand_;
QString terminal_;
Expand Down
53 changes: 38 additions & 15 deletions pcmanfm/view.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,15 +42,12 @@ View::~View() {

void View::onFileClicked(int type, const std::shared_ptr<const Fm::FileInfo>& fileInfo) {
if(type == MiddleClick) {
if(fileInfo->isDir() && fileLauncher()) {
if(fileInfo->isDir()) {
// fileInfo->path() shouldn't be used directly because
// it won't work in places like computer:/// or network:///
Fm::FileInfoList files;
files.emplace_back(fileInfo);
if(auto launcher = dynamic_cast<Launcher*>(fileLauncher())) {
launcher->openInNewTab();
}
fileLauncher()->launchFiles(nullptr, std::move(files));
launchFiles(std::move(files), true);
}
}
else {
Expand All @@ -68,7 +65,7 @@ void View::onFileClicked(int type, const std::shared_ptr<const Fm::FileInfo>& fi
return;
}
}
fileLauncher()->launchFiles(nullptr, std::move(files));
launchFiles(std::move(files));
}
}
}
Expand All @@ -80,20 +77,14 @@ void View::onFileClicked(int type, const std::shared_ptr<const Fm::FileInfo>& fi

void View::onNewWindow() {
Fm::FileMenu* menu = static_cast<Fm::FileMenu*>(sender()->parent());
// FIXME: open the files in a new window
Application* app = static_cast<Application*>(qApp);
app->openFolders(menu->files());
}

void View::onNewTab() {
if(fileLauncher()) {
Fm::FileMenu* menu = static_cast<Fm::FileMenu*>(sender()->parent());
auto files = menu->files();
if(auto launcher = dynamic_cast<Launcher*>(fileLauncher())) {
launcher->openInNewTab();
}
fileLauncher()->launchFiles(nullptr, std::move(files));
}
Fm::FileMenu* menu = static_cast<Fm::FileMenu*>(sender()->parent());
auto files = menu->files();
launchFiles(std::move(files), true);
}

void View::onOpenInTerminal() {
Expand Down Expand Up @@ -179,4 +170,36 @@ void View::updateFromSettings(Settings& settings) {
}
}

void View::launchFiles(Fm::FileInfoList files, bool inNewTabs) {
if(fileLauncher()) {
if(auto launcher = dynamic_cast<Launcher*>(fileLauncher())) {
// this happens on desktop
if(!launcher->hasMainWindow()
&& (inNewTabs
|| static_cast<Application*>(qApp)->settings().singleWindowMode())) {
MainWindow* window = MainWindow::lastActive();
// if there is no last active window, find the last created window
if(window == nullptr) {
QWidgetList windows = qApp->topLevelWidgets();
for(int i = 0; i < windows.size(); ++i) {
auto win = windows.at(windows.size() - 1 - i);
if(win->inherits("PCManFM::MainWindow")) {
window = static_cast<MainWindow*>(win);
break;
}
}
}
auto tempLauncher = Launcher(window);
tempLauncher.openInNewTab();
tempLauncher.launchFiles(nullptr, std::move(files));
return;
}
if(inNewTabs) {
launcher->openInNewTab();
}
}
fileLauncher()->launchFiles(nullptr, std::move(files));
}
}

} // namespace PCManFM
1 change: 1 addition & 0 deletions pcmanfm/view.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ protected Q_SLOTS:
virtual void prepareFolderMenu(Fm::FolderMenu* menu);

private:
void launchFiles(Fm::FileInfoList files, bool inNewTabs = false);

};

Expand Down

0 comments on commit 4df37c0

Please sign in to comment.