Adding upstream version 0.9.0+20150925.
This commit is contained in:
parent
de5ef5fc17
commit
f058f7ac4f
@ -63,6 +63,8 @@ set(libfm_SRCS
|
||||
appchoosercombobox.cpp
|
||||
appmenuview.cpp
|
||||
appchooserdialog.cpp
|
||||
filesearchdialog.cpp
|
||||
fm-search.c # might be moved to libfm later
|
||||
)
|
||||
|
||||
set(libfm_UIS
|
||||
@ -73,6 +75,7 @@ set(libfm_UIS
|
||||
edit-bookmarks.ui
|
||||
exec-file.ui
|
||||
app-chooser-dialog.ui
|
||||
filesearch.ui
|
||||
)
|
||||
|
||||
qt5_wrap_ui(libfm_UIS_H ${libfm_UIS})
|
||||
|
@ -62,6 +62,19 @@ void FileMenu::createMenu(FmFileInfoList* files, FmFileInfo* info, FmPath* cwd)
|
||||
confirmDelete_ = true;
|
||||
confirmTrash_ = false; // Confirm before moving files into "trash can"
|
||||
|
||||
openAction_ = NULL;
|
||||
openWithMenuAction_ = NULL;
|
||||
openWithAction_ = NULL;
|
||||
separator1_ = NULL;
|
||||
cutAction_ = NULL;
|
||||
copyAction_ = NULL;
|
||||
pasteAction_ = NULL;
|
||||
deleteAction_ = NULL;
|
||||
unTrashAction_ = NULL;
|
||||
renameAction_ = NULL;
|
||||
separator2_ = NULL;
|
||||
propertiesAction_ = NULL;
|
||||
|
||||
files_ = fm_file_info_list_ref(files);
|
||||
info_ = info ? fm_file_info_ref(info) : NULL;
|
||||
cwd_ = cwd ? fm_path_ref(cwd) : NULL;
|
||||
@ -346,8 +359,10 @@ void FileMenu::onRenameTriggered() {
|
||||
void FileMenu::setUseTrash(bool trash) {
|
||||
if(useTrash_ != trash) {
|
||||
useTrash_ = trash;
|
||||
deleteAction_->setText(useTrash_ ? tr("&Move to Trash") : tr("&Delete"));
|
||||
deleteAction_->setIcon(useTrash_ ? QIcon::fromTheme("user-trash") : QIcon::fromTheme("edit-delete"));
|
||||
if(deleteAction_) {
|
||||
deleteAction_->setText(useTrash_ ? tr("&Move to Trash") : tr("&Delete"));
|
||||
deleteAction_->setIcon(useTrash_ ? QIcon::fromTheme("user-trash") : QIcon::fromTheme("edit-delete"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
449
libfm-qt/filesearch.ui
Normal file
449
libfm-qt/filesearch.ui
Normal file
@ -0,0 +1,449 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>SearchDialog</class>
|
||||
<widget class="QDialog" name="SearchDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>512</width>
|
||||
<height>420</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Search Files</string>
|
||||
</property>
|
||||
<property name="windowIcon">
|
||||
<iconset theme="system-search">
|
||||
<normaloff/>
|
||||
</iconset>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QTabWidget" name="tabWidget">
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="tab">
|
||||
<attribute name="title">
|
||||
<string>Name/Location</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2" stretch="0,1">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>File Name Patterns:</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<widget class="QLineEdit" name="namePatterns">
|
||||
<property name="text">
|
||||
<string>*</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="nameCaseInsensitive">
|
||||
<property name="text">
|
||||
<string>Case insensitive</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="nameRegExp">
|
||||
<property name="text">
|
||||
<string>Use regular expression</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_2">
|
||||
<property name="title">
|
||||
<string>Places to Search:</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_5">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QListWidget" name="listView"/>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||
<item>
|
||||
<widget class="QPushButton" name="addPath">
|
||||
<property name="text">
|
||||
<string>&Add</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="list-add">
|
||||
<normaloff/>
|
||||
</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="removePath">
|
||||
<property name="text">
|
||||
<string>&Remove</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="list-remove">
|
||||
<normaloff/>
|
||||
</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="recursiveSearch">
|
||||
<property name="text">
|
||||
<string>Search in sub directories</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="searchHidden">
|
||||
<property name="text">
|
||||
<string>Search for hidden files</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab_2">
|
||||
<attribute name="title">
|
||||
<string>File Type</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_7">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_3">
|
||||
<property name="title">
|
||||
<string>Only search for files of following types:</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_6">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="searchTextFiles">
|
||||
<property name="text">
|
||||
<string>Text files</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="searchImages">
|
||||
<property name="text">
|
||||
<string>Image files</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="searchAudio">
|
||||
<property name="text">
|
||||
<string>Audio files</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="searchVideo">
|
||||
<property name="text">
|
||||
<string>Video files</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="searchDocuments">
|
||||
<property name="text">
|
||||
<string>Documents</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="searchFolders">
|
||||
<property name="text">
|
||||
<string>Folders</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab_3">
|
||||
<attribute name="title">
|
||||
<string>Content</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_9">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_4">
|
||||
<property name="title">
|
||||
<string>File contains:</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_8">
|
||||
<item>
|
||||
<widget class="QLineEdit" name="contentPattern"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="contentCaseInsensitive">
|
||||
<property name="text">
|
||||
<string>Case insensiti&ve</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="contentRegExp">
|
||||
<property name="text">
|
||||
<string>&Use regular expression</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>186</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab_4">
|
||||
<attribute name="title">
|
||||
<string>Properties</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_10">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_5">
|
||||
<property name="title">
|
||||
<string>File Size:</string>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QCheckBox" name="largerThan">
|
||||
<property name="text">
|
||||
<string>Larger than:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QSpinBox" name="minSize"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="minSizeUnit">
|
||||
<property name="currentIndex">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Bytes</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>KiB</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>MiB</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>GiB</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QCheckBox" name="smallerThan">
|
||||
<property name="text">
|
||||
<string>Smaller than:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
<widget class="QSpinBox" name="maxSize"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="maxSizeUnit">
|
||||
<property name="currentIndex">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Bytes</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>KiB</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>MiB</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>GiB</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_6">
|
||||
<property name="title">
|
||||
<string>Last Modified Time:</string>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout_2">
|
||||
<item row="0" column="0">
|
||||
<widget class="QCheckBox" name="earlierThan">
|
||||
<property name="text">
|
||||
<string>Earlier than:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QCheckBox" name="laterThan">
|
||||
<property name="text">
|
||||
<string>Later than:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QDateEdit" name="maxTime">
|
||||
<property name="calendarPopup">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QDateEdit" name="minTime">
|
||||
<property name="calendarPopup">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_4">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>SearchDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>SearchDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
143
libfm-qt/filesearchdialog.cpp
Normal file
143
libfm-qt/filesearchdialog.cpp
Normal file
@ -0,0 +1,143 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Hong Jen Yee (PCMan) <pcman.tw@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include "filesearchdialog.h"
|
||||
#include <QMessageBox>
|
||||
#include "fm-search.h"
|
||||
#include "ui_filesearch.h"
|
||||
#include <limits>
|
||||
#include <QFileDialog>
|
||||
|
||||
namespace Fm {
|
||||
|
||||
FileSearchDialog::FileSearchDialog(QStringList paths, QWidget* parent, Qt::WindowFlags f):
|
||||
QDialog(parent, f),
|
||||
ui(new Ui::SearchDialog()) {
|
||||
ui->setupUi(this);
|
||||
ui->minSize->setMaximum(std::numeric_limits<int>().max());
|
||||
ui->maxSize->setMaximum(std::numeric_limits<int>().max());
|
||||
Q_FOREACH(const QString& path, paths) {
|
||||
ui->listView->addItem(path);
|
||||
}
|
||||
|
||||
ui->maxTime->setDate(QDate::currentDate());
|
||||
ui->minTime->setDate(QDate::currentDate());
|
||||
|
||||
connect(ui->addPath, &QPushButton::clicked, this, &FileSearchDialog::onAddPath);
|
||||
connect(ui->removePath, &QPushButton::clicked, this, &FileSearchDialog::onRemovePath);
|
||||
}
|
||||
|
||||
FileSearchDialog::~FileSearchDialog() {
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void FileSearchDialog::accept() {
|
||||
// build the search:/// uri
|
||||
int n = ui->listView->count();
|
||||
if(n > 0) {
|
||||
FmSearch* search = fm_search_new();
|
||||
int i;
|
||||
for(i = 0; i < n; ++i) { // add directories
|
||||
QListWidgetItem* item = ui->listView->item(i);
|
||||
fm_search_add_dir(search, item->text().toLocal8Bit().constData());
|
||||
}
|
||||
|
||||
fm_search_set_recursive(search, ui->recursiveSearch->isChecked());
|
||||
fm_search_set_show_hidden(search, ui->searchHidden->isChecked());
|
||||
fm_search_set_name_patterns(search, ui->namePatterns->text().toUtf8().constData());
|
||||
fm_search_set_name_ci(search, ui->nameCaseInsensitive->isChecked());
|
||||
fm_search_set_name_regex(search, ui->nameRegExp->isChecked());
|
||||
|
||||
fm_search_set_content_pattern(search, ui->contentPattern->text().toUtf8().constData());
|
||||
fm_search_set_content_ci(search, ui->contentCaseInsensitive->isChecked());
|
||||
fm_search_set_content_regex(search, ui->contentRegExp->isChecked());
|
||||
|
||||
// search for the files of specific mime-types
|
||||
if(ui->searchTextFiles->isChecked())
|
||||
fm_search_add_mime_type(search, "text/plain");
|
||||
if(ui->searchImages->isChecked())
|
||||
fm_search_add_mime_type(search, "image/*");
|
||||
if(ui->searchAudio->isChecked())
|
||||
fm_search_add_mime_type(search, "audio/*");
|
||||
if(ui->searchVideo->isChecked())
|
||||
fm_search_add_mime_type(search, "video/*");
|
||||
if(ui->searchFolders->isChecked())
|
||||
fm_search_add_mime_type(search, "inode/directory");
|
||||
if(ui->searchDocuments->isChecked()) {
|
||||
const char* doc_types[] = {
|
||||
"application/pdf",
|
||||
/* "text/html;" */
|
||||
"application/vnd.oasis.opendocument.*",
|
||||
"application/vnd.openxmlformats-officedocument.*",
|
||||
"application/msword;application/vnd.ms-word",
|
||||
"application/msexcel;application/vnd.ms-excel"
|
||||
};
|
||||
for(i = 0; i < sizeof(doc_types)/sizeof(char*); ++i)
|
||||
fm_search_add_mime_type(search, doc_types[i]);
|
||||
}
|
||||
|
||||
// search based on file size
|
||||
const unsigned int unit_bytes[] = {1, (1024), (1024*1024), (1024*1024*1024)};
|
||||
if(ui->largerThan->isChecked()) {
|
||||
guint64 size = ui->minSize->value() * unit_bytes[ui->minSizeUnit->currentIndex()];
|
||||
fm_search_set_min_size(search, size);
|
||||
}
|
||||
|
||||
if(ui->smallerThan->isChecked()) {
|
||||
guint64 size = ui->maxSize->value() * unit_bytes[ui->maxSizeUnit->currentIndex()];
|
||||
fm_search_set_min_size(search, size);
|
||||
}
|
||||
|
||||
// search based on file mtime (we only support date in YYYY-MM-DD format)
|
||||
if(ui->earlierThan->isChecked()) {
|
||||
fm_search_set_max_mtime(search, ui->maxTime->date().toString(QStringLiteral("yyyy-MM-dd")).toUtf8().constData());
|
||||
}
|
||||
if(ui->laterThan->isChecked()) {
|
||||
fm_search_set_min_mtime(search, ui->minTime->date().toString(QStringLiteral("yyyy-MM-dd")).toUtf8().constData());
|
||||
}
|
||||
|
||||
searchUri_.take(fm_search_dup_path(search));
|
||||
|
||||
fm_search_free(search);
|
||||
}
|
||||
else {
|
||||
QMessageBox::critical(this, tr("Error"), tr("You should add at least add one directory to search."));
|
||||
return;
|
||||
}
|
||||
QDialog::accept();
|
||||
}
|
||||
|
||||
void FileSearchDialog::onAddPath() {
|
||||
QString dir = QFileDialog::getExistingDirectory(this, tr("Select a folder"));
|
||||
if(dir.isEmpty())
|
||||
return;
|
||||
// avoid adding duplicated items
|
||||
if(ui->listView->findItems(dir, Qt::MatchFixedString|Qt::MatchCaseSensitive).isEmpty()) {
|
||||
ui->listView->addItem(dir);
|
||||
}
|
||||
}
|
||||
|
||||
void FileSearchDialog::onRemovePath() {
|
||||
// remove selected items
|
||||
Q_FOREACH(QListWidgetItem* item, ui->listView->selectedItems()) {
|
||||
delete item;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
56
libfm-qt/filesearchdialog.h
Normal file
56
libfm-qt/filesearchdialog.h
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Hong Jen Yee (PCMan) <pcman.tw@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef FM_FILESEARCHDIALOG_H
|
||||
#define FM_FILESEARCHDIALOG_H
|
||||
|
||||
#include "libfmqtglobals.h"
|
||||
#include <QDialog>
|
||||
#include "path.h"
|
||||
|
||||
namespace Ui {
|
||||
class SearchDialog;
|
||||
}
|
||||
|
||||
namespace Fm {
|
||||
|
||||
class LIBFM_QT_API FileSearchDialog : public QDialog
|
||||
{
|
||||
public:
|
||||
FileSearchDialog(QStringList paths = QStringList(), QWidget * parent = 0, Qt::WindowFlags f = 0);
|
||||
~FileSearchDialog();
|
||||
|
||||
Path searchUri() const {
|
||||
return searchUri_;
|
||||
}
|
||||
|
||||
virtual void accept();
|
||||
|
||||
private Q_SLOTS:
|
||||
void onAddPath();
|
||||
void onRemovePath();
|
||||
|
||||
private:
|
||||
Ui::SearchDialog* ui;
|
||||
Path searchUri_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // FM_FILESEARCHDIALOG_H
|
317
libfm-qt/fm-search.c
Normal file
317
libfm-qt/fm-search.c
Normal file
@ -0,0 +1,317 @@
|
||||
/*
|
||||
* fm-search-uri.c
|
||||
*
|
||||
* Copyright 2015 Hong Jen Yee (PCMan) <pcman.tw@gmail.com>
|
||||
* Copyright 2012-2014 Andriy Grytsenko (LStranger) <andrej@rep.kiev.ua>
|
||||
*
|
||||
* 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 "fm-search.h"
|
||||
#include <string.h>
|
||||
|
||||
struct _FmSearch
|
||||
{
|
||||
gboolean recursive;
|
||||
gboolean show_hidden;
|
||||
char* name_patterns;
|
||||
gboolean name_ci;
|
||||
gboolean name_regex;
|
||||
char* content_pattern;
|
||||
gboolean content_ci;
|
||||
gboolean content_regex;
|
||||
GList* mime_types;
|
||||
GList* search_path_list;
|
||||
guint64 max_size;
|
||||
guint64 min_size;
|
||||
char* max_mtime;
|
||||
char* min_mtime;
|
||||
};
|
||||
|
||||
FmSearch* fm_search_new (void)
|
||||
{
|
||||
FmSearch* search = (FmSearch*)g_slice_new0(FmSearch);
|
||||
return search;
|
||||
}
|
||||
|
||||
void fm_search_free(FmSearch* search)
|
||||
{
|
||||
g_list_free_full(search->mime_types, (GDestroyNotify)g_free);
|
||||
g_list_free_full(search->search_path_list, (GDestroyNotify)g_free);
|
||||
g_free(search->name_patterns);
|
||||
g_free(search->content_pattern);
|
||||
g_free(search->max_mtime);
|
||||
g_free(search->min_mtime);
|
||||
g_slice_free(FmSearch, search);
|
||||
}
|
||||
|
||||
gboolean fm_search_get_recursive(FmSearch* search)
|
||||
{
|
||||
return search->recursive;
|
||||
}
|
||||
|
||||
void fm_search_set_recursive(FmSearch* search, gboolean recursive)
|
||||
{
|
||||
search->recursive = recursive;
|
||||
}
|
||||
|
||||
gboolean fm_search_get_show_hidden(FmSearch* search)
|
||||
{
|
||||
return search->show_hidden;
|
||||
}
|
||||
|
||||
void fm_search_set_show_hidden(FmSearch* search, gboolean show_hidden)
|
||||
{
|
||||
search->show_hidden = show_hidden;
|
||||
}
|
||||
|
||||
const char* fm_search_get_name_patterns(FmSearch* search)
|
||||
{
|
||||
return search->name_patterns;
|
||||
}
|
||||
|
||||
void fm_search_set_name_patterns(FmSearch* search, const char* name_patterns)
|
||||
{
|
||||
g_free(search->name_patterns);
|
||||
search->name_patterns = g_strdup(name_patterns);
|
||||
}
|
||||
|
||||
gboolean fm_search_get_name_ci(FmSearch* search)
|
||||
{
|
||||
return search->name_ci;
|
||||
}
|
||||
|
||||
void fm_search_set_name_ci(FmSearch* search, gboolean name_ci)
|
||||
{
|
||||
search->name_ci = name_ci;
|
||||
}
|
||||
|
||||
gboolean fm_search_get_name_regex(FmSearch* search)
|
||||
{
|
||||
return search->name_regex;
|
||||
}
|
||||
|
||||
void fm_search_set_name_regex(FmSearch* search, gboolean name_regex)
|
||||
{
|
||||
search->name_regex = name_regex;
|
||||
}
|
||||
|
||||
const char* fm_search_get_content_pattern(FmSearch* search)
|
||||
{
|
||||
return search->content_pattern;
|
||||
}
|
||||
|
||||
void fm_search_set_content_pattern(FmSearch* search, const char* content_pattern)
|
||||
{
|
||||
g_free(search->content_pattern);
|
||||
search->content_pattern = g_strdup(content_pattern);
|
||||
}
|
||||
|
||||
gboolean fm_search_get_content_ci(FmSearch* search)
|
||||
{
|
||||
return search->content_ci;
|
||||
}
|
||||
|
||||
void fm_search_set_content_ci(FmSearch* search, gboolean content_ci)
|
||||
{
|
||||
search->content_ci = content_ci;
|
||||
}
|
||||
|
||||
gboolean fm_search_get_content_regex(FmSearch* search)
|
||||
{
|
||||
return search->content_regex;
|
||||
}
|
||||
|
||||
void fm_search_set_content_regex(FmSearch* search, gboolean content_regex)
|
||||
{
|
||||
search->content_regex = content_regex;
|
||||
}
|
||||
|
||||
void fm_search_add_dir(FmSearch* search, const char* dir)
|
||||
{
|
||||
GList* l = g_list_find_custom(search->search_path_list, dir, (GCompareFunc)strcmp);
|
||||
if(!l)
|
||||
search->search_path_list = g_list_prepend(search->search_path_list, g_strdup(dir));
|
||||
}
|
||||
|
||||
void fm_search_remove_dir(FmSearch* search, const char* dir)
|
||||
{
|
||||
GList* l = g_list_find_custom(search->search_path_list, dir, (GCompareFunc)strcmp);
|
||||
if(G_LIKELY(l))
|
||||
{
|
||||
g_free(l->data);
|
||||
search->search_path_list = g_list_delete_link(search->search_path_list, l);
|
||||
}
|
||||
}
|
||||
|
||||
GList* fm_search_get_dirs(FmSearch* search)
|
||||
{
|
||||
return search->search_path_list;
|
||||
}
|
||||
|
||||
void fm_search_add_mime_type(FmSearch* search, const char* mime_type)
|
||||
{
|
||||
GList* l = g_list_find_custom(search->mime_types, mime_type, (GCompareFunc)strcmp);
|
||||
if(!l)
|
||||
search->mime_types = g_list_prepend(search->mime_types, g_strdup(mime_type));
|
||||
}
|
||||
|
||||
void fm_search_remove_mime_type(FmSearch* search, const char* mime_type)
|
||||
{
|
||||
GList* l = g_list_find_custom(search->mime_types, mime_type, (GCompareFunc)strcmp);
|
||||
if(G_LIKELY(l))
|
||||
{
|
||||
g_free(l->data);
|
||||
search->mime_types = g_list_delete_link(search->mime_types, l);
|
||||
}
|
||||
}
|
||||
|
||||
GList* fm_search_get_mime_types(FmSearch* search)
|
||||
{
|
||||
return search->mime_types;
|
||||
}
|
||||
|
||||
guint64 fm_search_get_max_size(FmSearch* search)
|
||||
{
|
||||
return search->max_size;
|
||||
}
|
||||
|
||||
void fm_search_set_max_size(FmSearch* search, guint64 size)
|
||||
{
|
||||
search->max_size = size;
|
||||
}
|
||||
|
||||
guint64 fm_search_get_min_size(FmSearch* search)
|
||||
{
|
||||
return search->min_size;
|
||||
}
|
||||
|
||||
void fm_search_set_min_size(FmSearch* search, guint64 size)
|
||||
{
|
||||
search->min_size = size;
|
||||
}
|
||||
|
||||
/* format of mtime: YYYY-MM-DD */
|
||||
const char* fm_search_get_max_mtime(FmSearch* search)
|
||||
{
|
||||
return search->max_mtime;
|
||||
}
|
||||
|
||||
void fm_search_set_max_mtime(FmSearch* search, const char* mtime)
|
||||
{
|
||||
g_free(search->max_mtime);
|
||||
search->max_mtime = g_strdup(mtime);
|
||||
}
|
||||
|
||||
/* format of mtime: YYYY-MM-DD */
|
||||
const char* fm_search_get_min_mtime(FmSearch* search)
|
||||
{
|
||||
return search->min_mtime;
|
||||
}
|
||||
|
||||
void fm_search_set_min_mtime(FmSearch* search, const char* mtime)
|
||||
{
|
||||
g_free(search->min_mtime);
|
||||
search->min_mtime = g_strdup(mtime);
|
||||
}
|
||||
|
||||
/* really build the path */
|
||||
FmPath* fm_search_dup_path(FmSearch* search)
|
||||
{
|
||||
FmPath* search_path = NULL;
|
||||
GString* search_str = g_string_sized_new(1024);
|
||||
/* build the search:// URI to perform the search */
|
||||
g_string_append(search_str, "search://");
|
||||
|
||||
if(search->search_path_list) /* we need to have at least one dir path */
|
||||
{
|
||||
char *escaped;
|
||||
/* add paths */
|
||||
GList* l;
|
||||
for(l = search->search_path_list; ; )
|
||||
{
|
||||
char *path_str = (char*)l->data;
|
||||
/* escape possible '?' and ',' */
|
||||
escaped = g_uri_escape_string(path_str, "!$&'()*+:;=/@", TRUE);
|
||||
g_string_append(search_str, escaped);
|
||||
g_free(escaped);
|
||||
|
||||
l = l->next;
|
||||
if(!l) /* no more items */
|
||||
break;
|
||||
g_string_append_c(search_str, ','); /* separator for paths */
|
||||
}
|
||||
|
||||
g_string_append_c(search_str, '?');
|
||||
g_string_append_printf(search_str, "recursive=%c", search->recursive ? '1' : '0');
|
||||
g_string_append_printf(search_str, "&show_hidden=%c", search->show_hidden ? '1' : '0');
|
||||
if(search->name_patterns && *search->name_patterns)
|
||||
{
|
||||
/* escape ampersands in pattern */
|
||||
escaped = g_uri_escape_string(search->name_patterns, ":/?#[]@!$'()*+,;", TRUE);
|
||||
if(search->name_regex)
|
||||
g_string_append_printf(search_str, "&name_regex=%s", escaped);
|
||||
else
|
||||
g_string_append_printf(search_str, "&name=%s", escaped);
|
||||
if(search->name_ci)
|
||||
g_string_append_printf(search_str, "&name_ci=%c", search->name_ci ? '1' : '0');
|
||||
g_free(escaped);
|
||||
}
|
||||
|
||||
if(search->content_pattern && *search->content_pattern)
|
||||
{
|
||||
/* escape ampersands in pattern */
|
||||
escaped = g_uri_escape_string(search->content_pattern, ":/?#[]@!$'()*+,;^<>{}", TRUE);
|
||||
if(search->content_regex)
|
||||
g_string_append_printf(search_str, "&content_regex=%s", escaped);
|
||||
else
|
||||
g_string_append_printf(search_str, "&content=%s", escaped);
|
||||
g_free(escaped);
|
||||
if(search->content_ci)
|
||||
g_string_append_printf(search_str, "&content_ci=%c", search->content_ci ? '1' : '0');
|
||||
}
|
||||
|
||||
/* search for the files of specific mime-types */
|
||||
if(search->mime_types)
|
||||
{
|
||||
GList* l;
|
||||
g_string_append(search_str, "&mime_types=");
|
||||
for(l = search->mime_types; l; l=l->next)
|
||||
{
|
||||
const char* mime_type = (const char*)l->data;
|
||||
g_string_append(search_str, mime_type);
|
||||
if(l->next)
|
||||
g_string_append_c(search_str, ';');
|
||||
}
|
||||
}
|
||||
|
||||
if(search->min_size)
|
||||
g_string_append_printf(search_str, "&min_size=%llu", search->min_size);
|
||||
|
||||
if(search->max_size)
|
||||
g_string_append_printf(search_str, "&max_size=%llu", search->max_size);
|
||||
|
||||
if(search->min_mtime)
|
||||
g_string_append_printf(search_str, "&min_mtime=%s", search->min_mtime);
|
||||
|
||||
if(search->max_mtime)
|
||||
g_string_append_printf(search_str, "&max_mtime=%s", search->max_mtime);
|
||||
|
||||
search_path = fm_path_new_for_uri(search_str->str);
|
||||
g_string_free(search_str, TRUE);
|
||||
}
|
||||
return search_path;
|
||||
}
|
88
libfm-qt/fm-search.h
Normal file
88
libfm-qt/fm-search.h
Normal file
@ -0,0 +1,88 @@
|
||||
/*
|
||||
* fm-search-uri.h
|
||||
*
|
||||
* Copyright 2015 Hong Jen Yee (PCMan) <pcman.tw@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
* MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/* FmSearch implements a tool used to generate a search:// URI used by libfm to search for files.
|
||||
* This API might become part of libfm in the future.
|
||||
*/
|
||||
|
||||
#ifndef _FM_SEARCH_H_
|
||||
#define _FM_SEARCH_H_
|
||||
|
||||
#include <libfm/fm.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct _FmSearch FmSearch;
|
||||
|
||||
FmSearch* fm_search_new(void);
|
||||
void fm_search_free(FmSearch* search);
|
||||
|
||||
FmPath* fm_search_dup_path(FmSearch* search);
|
||||
|
||||
gboolean fm_search_get_recursive(FmSearch* search);
|
||||
void fm_search_set_recursive(FmSearch* search, gboolean recursive);
|
||||
|
||||
gboolean fm_search_get_show_hidden(FmSearch* search);
|
||||
void fm_search_set_show_hidden(FmSearch* search, gboolean show_hidden);
|
||||
|
||||
const char* fm_search_get_name_patterns(FmSearch* search);
|
||||
void fm_search_set_name_patterns(FmSearch* search, const char* name_patterns);
|
||||
|
||||
gboolean fm_search_get_name_ci(FmSearch* search);
|
||||
void fm_search_set_name_ci(FmSearch* search, gboolean name_ci);
|
||||
|
||||
gboolean fm_search_get_name_regex(FmSearch* search);
|
||||
void fm_search_set_name_regex(FmSearch* search, gboolean name_regex);
|
||||
|
||||
const char* fm_search_get_content_pattern(FmSearch* search);
|
||||
void fm_search_set_content_pattern(FmSearch* search, const char* content_pattern);
|
||||
|
||||
gboolean fm_search_get_content_ci(FmSearch* search);
|
||||
void fm_search_set_content_ci(FmSearch* search, gboolean content_ci);
|
||||
|
||||
gboolean fm_search_get_content_regex(FmSearch* search);
|
||||
void fm_search_set_content_regex(FmSearch* search, gboolean content_regex);
|
||||
|
||||
void fm_search_add_dir(FmSearch* search, const char* dir);
|
||||
void fm_search_remove_dir(FmSearch* search, const char* dir);
|
||||
GList* fm_search_get_dirs(FmSearch* search);
|
||||
|
||||
void fm_search_add_mime_type(FmSearch* search, const char* mime_type);
|
||||
void fm_search_remove_mime_type(FmSearch* search, const char* mime_type);
|
||||
GList* fm_search_get_mime_types(FmSearch* search);
|
||||
|
||||
guint64 fm_search_get_max_size(FmSearch* search);
|
||||
void fm_search_set_max_size(FmSearch* search, guint64 size);
|
||||
|
||||
guint64 fm_search_get_min_size(FmSearch* search);
|
||||
void fm_search_set_min_size(FmSearch* search, guint64 size);
|
||||
|
||||
/* format of mtime: YYYY-MM-DD */
|
||||
const char* fm_search_get_max_mtime(FmSearch* search);
|
||||
void fm_search_set_max_mtime(FmSearch* search, const char* mtime);
|
||||
|
||||
/* format of mtime: YYYY-MM-DD */
|
||||
const char* fm_search_get_min_mtime(FmSearch* search);
|
||||
void fm_search_set_min_mtime(FmSearch* search, const char* mtime);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* _FM_SEARCH_H_ */
|
@ -188,6 +188,12 @@ public:
|
||||
return fm_path_hash(data_);
|
||||
}
|
||||
|
||||
void take(FmPath* path) { // take the ownership of the "path"
|
||||
if(data_)
|
||||
fm_path_unref(data_);
|
||||
data_ = path;
|
||||
}
|
||||
|
||||
Path& operator = (const Path& other) {
|
||||
if(data_)
|
||||
fm_path_unref(data_);
|
||||
|
@ -322,6 +322,8 @@ void PlacesView::onEjectVolume() {
|
||||
void PlacesView::contextMenuEvent(QContextMenuEvent* event) {
|
||||
QModelIndex index = indexAt(event->pos());
|
||||
if(index.isValid() && index.parent().isValid()) {
|
||||
if(index.column() != 0) // the real item is at column 0
|
||||
index = index.sibling(index.row(), 0);
|
||||
QMenu* menu = new QMenu(this);
|
||||
QAction* action;
|
||||
PlacesModelItem* item = static_cast<PlacesModelItem*>(model_->itemFromIndex(index));
|
||||
|
@ -118,6 +118,12 @@ bool ProxyFolderModel::lessThan(const QModelIndex& left, const QModelIndex& righ
|
||||
FmFileInfo* leftInfo = srcModel->fileInfoFromIndex(left);
|
||||
FmFileInfo* rightInfo = srcModel->fileInfoFromIndex(right);
|
||||
|
||||
if(Q_UNLIKELY(!leftInfo || !rightInfo)) {
|
||||
// In theory, this should not happen, but it's safer to add the null check.
|
||||
// This is reported in https://github.com/lxde/pcmanfm-qt/issues/205
|
||||
return false;
|
||||
}
|
||||
|
||||
if(folderFirst_) {
|
||||
bool leftIsFolder = (bool)fm_file_info_is_dir(leftInfo);
|
||||
bool rightIsFolder = (bool)fm_file_info_is_dir(rightInfo);
|
||||
|
@ -1,4 +0,0 @@
|
||||
[Project]
|
||||
Manager=KDevCMakeManager
|
||||
Name=pcmanfm-qt
|
||||
VersionControl=
|
@ -42,6 +42,7 @@
|
||||
#include "mountoperation.h"
|
||||
#include "autorundialog.h"
|
||||
#include "launcher.h"
|
||||
#include "filesearchdialog.h"
|
||||
|
||||
#include <QScreen>
|
||||
#include <QWindow>
|
||||
@ -113,8 +114,8 @@ Application::~Application() {
|
||||
g_object_unref(volumeMonitor_);
|
||||
}
|
||||
|
||||
if(enableDesktopManager_)
|
||||
removeNativeEventFilter(this);
|
||||
// if(enableDesktopManager_)
|
||||
// removeNativeEventFilter(this);
|
||||
}
|
||||
|
||||
bool Application::parseCommandLineArgs() {
|
||||
@ -311,7 +312,7 @@ void Application::desktopManager(bool enabled) {
|
||||
QDesktopWidget* desktopWidget = desktop();
|
||||
if(enabled) {
|
||||
if(!enableDesktopManager_) {
|
||||
installNativeEventFilter(this);
|
||||
// installNativeEventFilter(this);
|
||||
Q_FOREACH(QScreen* screen, screens()) {
|
||||
connect(screen, &QScreen::virtualGeometryChanged, this, &Application::onVirtualGeometryChanged);
|
||||
connect(screen, &QObject::destroyed, this, &Application::onScreenDestroyed);
|
||||
@ -352,7 +353,7 @@ void Application::desktopManager(bool enabled) {
|
||||
disconnect(screen, &QObject::destroyed, this, &Application::onScreenDestroyed);
|
||||
}
|
||||
disconnect(this, &QApplication::screenAdded, this, &Application::onScreenAdded);
|
||||
removeNativeEventFilter(this);
|
||||
// removeNativeEventFilter(this);
|
||||
}
|
||||
}
|
||||
enableDesktopManager_ = enabled;
|
||||
@ -369,9 +370,22 @@ void Application::desktopPrefrences(QString page) {
|
||||
desktopPreferencesDialog_.data()->activateWindow();
|
||||
}
|
||||
|
||||
void Application::onFindFileAccepted() {
|
||||
Fm::FileSearchDialog* dlg = static_cast<Fm::FileSearchDialog*>(sender());
|
||||
Fm::Path uri = dlg->searchUri();
|
||||
// FIXME: we should be able to open it in an existing window
|
||||
FmPathList* paths = fm_path_list_new();
|
||||
fm_path_list_push_tail(paths, uri.data());
|
||||
Launcher(NULL).launchPaths(NULL, paths);
|
||||
fm_path_list_unref(paths);
|
||||
}
|
||||
|
||||
void Application::findFiles(QStringList paths) {
|
||||
// TODO: add a file searching utility here.
|
||||
qDebug("findFiles");
|
||||
// launch file searching utility.
|
||||
Fm::FileSearchDialog* dlg = new Fm::FileSearchDialog(paths);
|
||||
connect(dlg, &QDialog::accepted, this, &Application::onFindFileAccepted);
|
||||
dlg->setAttribute(Qt::WA_DeleteOnClose);
|
||||
dlg->show();
|
||||
}
|
||||
|
||||
void Application::launchFiles(QString cwd, QStringList paths, bool inNewWindow) {
|
||||
@ -635,17 +649,18 @@ void Application::onVolumeAdded(GVolumeMonitor* monitor, GVolume* volume, Applic
|
||||
pThis->autoMountVolume(volume, true);
|
||||
}
|
||||
|
||||
#if 0
|
||||
bool Application::nativeEventFilter(const QByteArray & eventType, void * message, long * result) {
|
||||
if(eventType == "xcb_generic_event_t") { // XCB event
|
||||
// filter all native X11 events (xcb)
|
||||
xcb_generic_event_t* generic_event = reinterpret_cast<xcb_generic_event_t*>(message);
|
||||
// qDebug("XCB event: %d", generic_event->response_type & ~0x80);
|
||||
Q_FOREACH(DesktopWindow * window, desktopWindows_) {
|
||||
window->xcbEvent(generic_event);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
void Application::onScreenAdded(QScreen* newScreen) {
|
||||
if(enableDesktopManager_) {
|
||||
|
@ -25,7 +25,6 @@
|
||||
#include "settings.h"
|
||||
#include "libfmqt.h"
|
||||
#include "editbookmarksdialog.h"
|
||||
#include <QAbstractNativeEventFilter>
|
||||
#include <QVector>
|
||||
#include <QPointer>
|
||||
#include <QProxyStyle>
|
||||
@ -49,7 +48,7 @@ public:
|
||||
virtual int styleHint(StyleHint hint, const QStyleOption * option = 0, const QWidget * widget = 0, QStyleHintReturn * returnData = 0) const;
|
||||
};
|
||||
|
||||
class Application : public QApplication, public QAbstractNativeEventFilter {
|
||||
class Application : public QApplication {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(bool desktopManagerEnabled READ desktopManagerEnabled)
|
||||
|
||||
@ -75,7 +74,7 @@ public:
|
||||
void desktopPrefrences(QString page);
|
||||
void editBookmarks();
|
||||
void desktopManager(bool enabled);
|
||||
void findFiles(QStringList paths);
|
||||
void findFiles(QStringList paths = QStringList());
|
||||
|
||||
bool desktopManagerEnabled() {
|
||||
return enableDesktopManager_;
|
||||
@ -91,8 +90,6 @@ public:
|
||||
return profileName_;
|
||||
}
|
||||
|
||||
virtual bool nativeEventFilter(const QByteArray & eventType, void * message, long * result);
|
||||
|
||||
protected Q_SLOTS:
|
||||
void onAboutToQuit();
|
||||
void onSigtermNotified();
|
||||
@ -108,6 +105,8 @@ protected Q_SLOTS:
|
||||
void onScreenAdded(QScreen* newScreen);
|
||||
void reloadDesktopsAsNeeded();
|
||||
|
||||
void onFindFileAccepted();
|
||||
|
||||
protected:
|
||||
virtual bool eventFilter(QObject* watched, QEvent* event);
|
||||
bool parseCommandLineArgs();
|
||||
|
@ -6,8 +6,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>473</width>
|
||||
<height>428</height>
|
||||
<width>501</width>
|
||||
<height>376</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
@ -200,6 +200,19 @@
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>10</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="advancedPage">
|
||||
|
@ -389,49 +389,6 @@ void DesktopWindow::prepareFolderMenu(Fm::FolderMenu* menu) {
|
||||
connect(action, &QAction::triggered, this, &DesktopWindow::onDesktopPreferences);
|
||||
}
|
||||
|
||||
void DesktopWindow::xcbEvent(xcb_generic_event_t* generic_event) {
|
||||
int event_type = generic_event->response_type & ~0x80;
|
||||
if(showWmMenu_) {
|
||||
// If we want to show the desktop menus provided by the window manager instead of ours,
|
||||
// we have to forward the mouse events we received to the root window.
|
||||
switch(event_type) {
|
||||
case XCB_BUTTON_PRESS: {
|
||||
xcb_button_press_event_t* event = reinterpret_cast<xcb_button_press_event_t*>(generic_event);
|
||||
if(event->event == effectiveWinId()) {
|
||||
// check if the user click on blank area
|
||||
QModelIndex index = listView_->indexAt(QPoint(event->event_x, event->event_y));
|
||||
if(!index.isValid()) {
|
||||
xcb_ungrab_pointer(QX11Info::connection(), event->time);
|
||||
// forward the event to the root window
|
||||
xcb_button_press_event_t event2 = *event;
|
||||
WId root = QX11Info::appRootWindow(QX11Info::appScreen());
|
||||
event2.event = root;
|
||||
xcb_send_event(QX11Info::connection(), 0, root, XCB_EVENT_MASK_BUTTON_PRESS, (char*)&event2);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case XCB_BUTTON_RELEASE: {
|
||||
xcb_button_release_event_t* event = reinterpret_cast<xcb_button_release_event_t*>(generic_event);
|
||||
if(event->event == effectiveWinId()) {
|
||||
// check if the user click on blank area
|
||||
QModelIndex index = listView_->indexAt(QPoint(event->event_x, event->event_y));
|
||||
if(!index.isValid()) {
|
||||
// forward the event to the root window
|
||||
xcb_button_release_event_t event2 = *event;
|
||||
WId root = QX11Info::appRootWindow(QX11Info::appScreen());
|
||||
event2.event = root;
|
||||
xcb_send_event(QX11Info::connection(), 0, root, XCB_EVENT_MASK_BUTTON_RELEASE, (char*)&event2);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DesktopWindow::onDesktopPreferences() {
|
||||
static_cast<Application* >(qApp)->desktopPrefrences(QString());
|
||||
}
|
||||
@ -675,6 +632,69 @@ void DesktopWindow::onFilePropertiesActivated() {
|
||||
}
|
||||
}
|
||||
|
||||
static void forwardMouseEventToRoot(QMouseEvent* event) {
|
||||
xcb_ungrab_pointer(QX11Info::connection(), event->timestamp());
|
||||
// forward the event to the root window
|
||||
xcb_button_press_event_t xcb_event;
|
||||
uint32_t mask = 0;
|
||||
xcb_event.state = 0;
|
||||
switch(event->type()) {
|
||||
case QEvent::MouseButtonPress:
|
||||
xcb_event.response_type = XCB_BUTTON_PRESS;
|
||||
mask = XCB_EVENT_MASK_BUTTON_PRESS;
|
||||
break;
|
||||
case QEvent::MouseButtonRelease:
|
||||
xcb_event.response_type = XCB_BUTTON_RELEASE;
|
||||
mask = XCB_EVENT_MASK_BUTTON_RELEASE;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
// convert Qt button to XCB button
|
||||
switch(event->button()) {
|
||||
case Qt::LeftButton:
|
||||
xcb_event.detail = 1;
|
||||
xcb_event.state |= XCB_BUTTON_MASK_1;
|
||||
break;
|
||||
case Qt::MiddleButton:
|
||||
xcb_event.detail = 2;
|
||||
xcb_event.state |= XCB_BUTTON_MASK_2;
|
||||
break;
|
||||
case Qt::RightButton:
|
||||
xcb_event.detail = 3;
|
||||
xcb_event.state |= XCB_BUTTON_MASK_3;
|
||||
break;
|
||||
default:
|
||||
xcb_event.detail = 0;
|
||||
}
|
||||
|
||||
// convert Qt modifiers to XCB states
|
||||
if(event->modifiers() & Qt::ShiftModifier)
|
||||
xcb_event.state |= XCB_MOD_MASK_SHIFT;
|
||||
if(event->modifiers() & Qt::ControlModifier)
|
||||
xcb_event.state |= XCB_MOD_MASK_SHIFT;
|
||||
if(event->modifiers() & Qt::AltModifier)
|
||||
xcb_event.state |= XCB_MOD_MASK_1;
|
||||
|
||||
xcb_event.sequence = 0;
|
||||
xcb_event.time = event->timestamp();
|
||||
|
||||
WId root = QX11Info::appRootWindow(QX11Info::appScreen());
|
||||
xcb_event.event = root;
|
||||
xcb_event.root = root;
|
||||
xcb_event.child = 0;
|
||||
|
||||
xcb_event.root_x = event->globalX();
|
||||
xcb_event.root_y = event->globalY();
|
||||
xcb_event.event_x = event->x();
|
||||
xcb_event.event_y = event->y();
|
||||
xcb_event.same_screen = 1;
|
||||
|
||||
xcb_send_event(QX11Info::connection(), 0, root, mask, (char*)&xcb_event);
|
||||
xcb_flush(QX11Info::connection());
|
||||
}
|
||||
|
||||
bool DesktopWindow::event(QEvent* event)
|
||||
{
|
||||
switch(event->type()) {
|
||||
@ -721,6 +741,25 @@ bool DesktopWindow::eventFilter(QObject * watched, QEvent * event) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if(watched == listView_->viewport()) {
|
||||
switch(event->type()) {
|
||||
case QEvent::MouseButtonPress:
|
||||
case QEvent::MouseButtonRelease:
|
||||
if(showWmMenu_) {
|
||||
QMouseEvent* e = static_cast<QMouseEvent*>(event);
|
||||
// If we want to show the desktop menus provided by the window manager instead of ours,
|
||||
// we have to forward the mouse events we received to the root window.
|
||||
// check if the user click on blank area
|
||||
QModelIndex index = listView_->indexAt(e->pos());
|
||||
if(!index.isValid() && e->button() != Qt::LeftButton) {
|
||||
forwardMouseEventToRoot(e);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -66,8 +66,6 @@ public:
|
||||
void updateWallpaper();
|
||||
void updateFromSettings(Settings& settings);
|
||||
|
||||
void xcbEvent(xcb_generic_event_t* generic_event);
|
||||
|
||||
void queueRelayout(int delay = 0);
|
||||
|
||||
int screenNum() const {
|
||||
|
@ -7,7 +7,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>431</width>
|
||||
<height>359</height>
|
||||
<height>416</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
@ -76,7 +76,9 @@
|
||||
<string>Add</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="list-add"/>
|
||||
<iconset theme="list-add">
|
||||
<normaloff/>
|
||||
</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -86,7 +88,9 @@
|
||||
<string>Remove</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="list-remove"/>
|
||||
<iconset theme="list-remove">
|
||||
<normaloff/>
|
||||
</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -125,9 +129,6 @@
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
<zorder>buttonBox</zorder>
|
||||
<zorder>groupBox</zorder>
|
||||
<zorder>groupBox_2</zorder>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab_2">
|
||||
<attribute name="title">
|
||||
@ -256,7 +257,7 @@
|
||||
<property name="title">
|
||||
<string>File Size</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<layout class="QFormLayout" name="formLayout_3">
|
||||
<item row="0" column="0">
|
||||
<widget class="QCheckBox" name="checkBox_12">
|
||||
<property name="text">
|
||||
@ -265,18 +266,22 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QSpinBox" name="spinBox">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QComboBox" name="comboBox">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QSpinBox" name="spinBox">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="comboBox">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QCheckBox" name="checkBox_13">
|
||||
@ -286,18 +291,22 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QSpinBox" name="spinBox_2">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QComboBox" name="comboBox_2">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
<widget class="QSpinBox" name="spinBox_2">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="comboBox_2">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
@ -307,7 +316,7 @@
|
||||
<property name="title">
|
||||
<string>Last Modified Time</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<layout class="QFormLayout" name="formLayout_2">
|
||||
<item row="0" column="0">
|
||||
<widget class="QCheckBox" name="checkBox_14">
|
||||
<property name="text">
|
||||
@ -315,6 +324,16 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QDateTimeEdit" name="dateTimeEdit">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="calendarPopup">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QCheckBox" name="checkBox_15">
|
||||
<property name="text">
|
||||
@ -332,16 +351,6 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QDateTimeEdit" name="dateTimeEdit">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="calendarPopup">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
|
@ -20,7 +20,16 @@
|
||||
</property>
|
||||
<widget class="QWidget" name="centralwidget">
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="margin">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
@ -67,7 +76,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>460</width>
|
||||
<height>27</height>
|
||||
<height>23</height>
|
||||
</rect>
|
||||
</property>
|
||||
<widget class="QMenu" name="menu_File">
|
||||
@ -171,6 +180,7 @@
|
||||
</property>
|
||||
<addaction name="actionOpenTerminal"/>
|
||||
<addaction name="actionOpenAsRoot"/>
|
||||
<addaction name="actionFindFiles"/>
|
||||
</widget>
|
||||
<addaction name="menu_File"/>
|
||||
<addaction name="menu_Editw"/>
|
||||
@ -227,7 +237,7 @@
|
||||
</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Home</string>
|
||||
<string>&Home</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Alt+Home</string>
|
||||
@ -447,7 +457,7 @@
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Ascending</string>
|
||||
<string>&Ascending</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionDescending">
|
||||
@ -455,7 +465,7 @@
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Descending</string>
|
||||
<string>&Descending</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionByFileName">
|
||||
@ -463,7 +473,7 @@
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>By File Name</string>
|
||||
<string>&By File Name</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionByMTime">
|
||||
@ -471,7 +481,7 @@
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>By Modification Time</string>
|
||||
<string>By &Modification Time</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionByFileType">
|
||||
@ -479,7 +489,7 @@
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>By File Type</string>
|
||||
<string>By File &Type</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionByOwner">
|
||||
@ -487,7 +497,7 @@
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>By Owner</string>
|
||||
<string>By &Owner</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionFolderFirst">
|
||||
@ -495,7 +505,7 @@
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Folder First</string>
|
||||
<string>&Folder First</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionNewTab">
|
||||
@ -598,7 +608,7 @@
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Case Sensitive</string>
|
||||
<string>&Case Sensitive</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionByFileSize">
|
||||
@ -606,12 +616,12 @@
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>By File Size</string>
|
||||
<string>By File &Size</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionCloseWindow">
|
||||
<property name="text">
|
||||
<string>Close Window</string>
|
||||
<string>&Close Window</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionEdit_Bookmarks">
|
||||
@ -639,10 +649,12 @@
|
||||
</action>
|
||||
<action name="actionNewFolder">
|
||||
<property name="icon">
|
||||
<iconset theme="folder-new"/>
|
||||
<iconset theme="folder-new">
|
||||
<normaloff/>
|
||||
</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Folder</string>
|
||||
<string>&Folder</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+Shift+N</string>
|
||||
@ -650,15 +662,25 @@
|
||||
</action>
|
||||
<action name="actionNewBlankFile">
|
||||
<property name="icon">
|
||||
<iconset theme="document-new"/>
|
||||
<iconset theme="document-new">
|
||||
<normaloff/>
|
||||
</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Blank File</string>
|
||||
<string>&Blank File</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+Alt+N</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionFindFiles">
|
||||
<property name="text">
|
||||
<string>&Find Files</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>F3</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
|
@ -949,6 +949,25 @@ void MainWindow::on_actionOpenAsRoot_triggered() {
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_actionFindFiles_triggered() {
|
||||
Application* app = static_cast<Application*>(qApp);
|
||||
FmPathList* selectedPaths = currentPage()->selectedFilePaths();
|
||||
QStringList paths;
|
||||
if(selectedPaths) {
|
||||
for(GList* l = fm_path_list_peek_head_link(selectedPaths); l; l = l->next) {
|
||||
// FIXME: is it ok to use display name here?
|
||||
// This might be broken on filesystems with non-UTF-8 filenames.
|
||||
Fm::Path path(FM_PATH(l->data));
|
||||
paths.append(path.displayName(false));
|
||||
}
|
||||
fm_path_list_unref(selectedPaths);
|
||||
}
|
||||
else {
|
||||
paths.append(currentPage()->pathName());
|
||||
}
|
||||
app->findFiles(paths);
|
||||
}
|
||||
|
||||
void MainWindow::on_actionOpenTerminal_triggered() {
|
||||
TabPage* page = currentPage();
|
||||
if(page) {
|
||||
|
@ -109,6 +109,7 @@ protected Q_SLOTS:
|
||||
|
||||
void on_actionOpenTerminal_triggered();
|
||||
void on_actionOpenAsRoot_triggered();
|
||||
void on_actionFindFiles_triggered();
|
||||
|
||||
void on_actionAbout_triggered();
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user