Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 30 Apr 2012 18:05:53 -0700 (PDT)
From:      Zhihao Yuan <lichray@gmail.com>
To:        FreeBSD-gnats-submit@FreeBSD.org
Subject:   ports/167466: New port: x11-fm/qtfm A small, lightweight file manager based on pure Qt
Message-ID:  <4f9f36f1.447ab60a.784b.ffffed55@mx.google.com>
Resent-Message-ID: <201205010110.q411ABEt047038@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help

>Number:         167466
>Category:       ports
>Synopsis:       New port: x11-fm/qtfm A small, lightweight file manager based on pure Qt
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    freebsd-ports-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Tue May 01 01:10:11 UTC 2012
>Closed-Date:
>Last-Modified:
>Originator:     Zhihao Yuan
>Release:        FreeBSD 8.3-PRERELEASE amd64
>Organization:
Northern Illinois University
>Environment:
System: FreeBSD elitebook.hp 8.3-PRERELEASE FreeBSD 8.3-PRERELEASE #0 r234564: Sun Apr 22 04:30:51 CDT 2012 lichray@elitebook.hp:/usr/obj/usr/src/sys/HOUKAGO amd64


	
>Description:
	
	A small file manager which only depends on QtGui and QtNetwork (no modern hal, polkit, etc.).
	http://www.qtfm.org/
>How-To-Repeat:
	
>Fix:

	
	1. <sys/vfs.h> -> <sys/mount.h>;
	2. inotify -> QFileSystemWatcher (reported to upstream);
	3. /proc/self/mtab watching -> kevent EVFILT_FS in a thread;
	4. /proc/self/mtab parsing -> getmntinfo(3) (reported).

--- qtfm.shar begins here ---
# This is a shell archive.  Save it in a file, remove anything before
# this line, and then unpack it by entering "sh file".  Note, it may
# create directories; files and directories will be owned by you and
# have default permissions.
#
# This archive contains:
#
#	qtfm
#	qtfm/files
#	qtfm/files/patch-src_propertiesdlg.cpp
#	qtfm/files/patch-src_mainwindow.cpp
#	qtfm/files/patch-src_mymodel.cpp
#	qtfm/files/patch-src_mymodel.h
#	qtfm/files/patch-src_mainwindow.h
#	qtfm/files/patch-src_bookmarks.cpp
#	qtfm/files/patch-qtfm.pro
#	qtfm/distinfo
#	qtfm/pkg-plist
#	qtfm/Makefile
#	qtfm/pkg-descr
#
echo c - qtfm
mkdir -p qtfm > /dev/null 2>&1
echo c - qtfm/files
mkdir -p qtfm/files > /dev/null 2>&1
echo x - qtfm/files/patch-src_propertiesdlg.cpp
sed 's/^X//' >qtfm/files/patch-src_propertiesdlg.cpp << '0d9d84c92531dcafeec4d9768cc602f0'
X--- src/propertiesdlg.cpp~	2012-03-08 20:34:27.000000000 -0600
X+++ src/propertiesdlg.cpp	2012-04-29 06:49:57.546488947 -0500
X@@ -23,7 +23,11 @@
X #include "propertiesdlg.h"
X #include "icondlg.h"
X #include "mainwindow.h"
X+#ifdef __FreeBSD__
X+#include <sys/mount.h>
X+#else
X #include <sys/vfs.h>
X+#endif
X #include <sys/stat.h>
X #include <magic.h>
X 
0d9d84c92531dcafeec4d9768cc602f0
echo x - qtfm/files/patch-src_mainwindow.cpp
sed 's/^X//' >qtfm/files/patch-src_mainwindow.cpp << '44433c87ac59d95ad45b8753666563a1'
X--- src/mainwindow.cpp.orig	2012-03-11 10:11:28.000000000 -0500
X+++ src/mainwindow.cpp	2012-04-29 23:06:06.481938775 -0500
X@@ -21,7 +21,11 @@
X 
X 
X #include <QtGui>
X+#ifdef __FreeBSD__
X+#include <sys/mount.h>
X+#else
X #include <sys/vfs.h>
X+#endif
X #include <fcntl.h>
X 
X #include "mainwindow.h"
X@@ -280,10 +284,15 @@ void MainWindow::lateStart()
X     customMapper = new QSignalMapper();
X     connect(customMapper, SIGNAL(mapped(QString)),this, SLOT(actionMapper(QString)));
X 
X+#ifdef __FreeBSD__
X+    worker = new MountWorker();
X+    worker->setParent(this);
X+    worker->start(QThread::IdlePriority);
X+#else
X     int fd = open("/proc/self/mounts",O_RDONLY,0);
X     notify = new QSocketNotifier(fd,QSocketNotifier::Write);
X     connect(notify, SIGNAL(activated(int)), this, SLOT(mountWatcherTriggered()),Qt::QueuedConnection);
X-
X+#endif
X 
X     term = settings->value("term").toString();
X     progress = 0;
X@@ -336,6 +345,9 @@ void MainWindow::closeEvent(QCloseEvent 
X {
X     writeSettings();
X 
X+#ifdef __FreeBSD__
X+    worker->close();
X+#endif
X     if(isDaemon)
X     {
X         this->setVisible(0);
X@@ -1839,7 +1851,7 @@ void MainWindow::actionMapper(QString cm
X     QString exec = temp.at(0);
X     temp.removeAt(0);
X 
X-    temp.replaceInStrings("\\","\ ");
X+    temp.replaceInStrings("\\"," ");
X 
X     QProcess *customProcess = new QProcess();
X     customProcess->setWorkingDirectory(pathEdit->itemText(0));
44433c87ac59d95ad45b8753666563a1
echo x - qtfm/files/patch-src_mymodel.cpp
sed 's/^X//' >qtfm/files/patch-src_mymodel.cpp << '9d571fc377e081220ac31ba2da3641ae'
X--- src/mymodel.cpp.orig	2012-03-09 05:00:54.000000000 -0600
X+++ src/mymodel.cpp	2012-04-29 16:13:57.725169164 -0500
X@@ -21,7 +21,6 @@
X 
X #include <mainwindow.h>
X #include "mymodel.h"
X-#include <sys/inotify.h>
X #include <unistd.h>
X #include <sys/ioctl.h>
X 
X@@ -63,9 +62,8 @@ myModel::myModel(bool realMime)
X 
X     iconFactory = new QFileIconProvider();
X 
X-    inotifyFD = inotify_init();
X-    notifier = new QSocketNotifier(inotifyFD, QSocketNotifier::Read, this);
X-    connect(notifier, SIGNAL(activated(int)), this, SLOT(notifyChange()));
X+    watcher = new QFileSystemWatcher(this);
X+    connect(watcher, SIGNAL(directoryChanged(QString)), this, SLOT(notifyChange(QString)));
X 
X     realMimeTypes = realMime;
X }
X@@ -188,28 +186,9 @@ QString myModel::getMimeType(const QMode
X }
X 
X //---------------------------------------------------------------------------------------
X-void myModel::notifyChange()
X+void myModel::notifyChange(QString const& path)
X {
X-    notifier->setEnabled(0);
X-
X-    int buffSize = 0;
X-    ioctl(inotifyFD, FIONREAD, (char *) &buffSize);
X-
X-    QByteArray buffer;
X-    buffer.resize(buffSize);
X-    read(inotifyFD,buffer.data(),buffSize);
X-    const char *at = buffer.data();
X-    const char * const end = at + buffSize;
X-
X-    while (at < end)
X-    {
X-        const inotify_event *event = reinterpret_cast<const inotify_event *>(at);
X-
X-        int w = event->wd;
X-
X-        if(watchers.contains(w))
X-        {
X-            myModelItem *parent = rootItem->matchPath(watchers.value(w).split(SEPARATOR));
X+            myModelItem *parent = rootItem->matchPath(path.split(SEPARATOR));
X 
X             if(parent)
X             {
X@@ -230,9 +209,7 @@ void myModel::notifyChange()
X                         //must of been deleted, remove from model
X                         if(child->fileInfo().isDir())
X                         {
X-                            int wd = watchers.key(child->absoluteFilePath());
X-                            inotify_rm_watch(inotifyFD,wd);
X-                            watchers.remove(wd);
X+                            watcher->removePath(child->absoluteFilePath());
X                         }
X                         beginRemoveRows(index(parent->absoluteFilePath()),child->childNumber(),child->childNumber());
X                         parent->removeChild(child);
X@@ -249,23 +226,17 @@ void myModel::notifyChange()
X             }
X             else
X             {
X-                inotify_rm_watch(inotifyFD,w);
X-                watchers.remove(w);
X+                watcher->removePath(path);
X             }
X-        }
X-
X-        at += sizeof(inotify_event) + event->len;
X-    }
X-
X-    notifier->setEnabled(1);
X }
X 
X //---------------------------------------------------------------------------------
X-void myModel::addWatcher(myModelItem *item)
X+void myModel::addToWatcher(myModelItem *item)
X {
X     while(item != rootItem)
X     {
X-        watchers.insert(inotify_add_watch(inotifyFD, item->absoluteFilePath().toLocal8Bit(), IN_MOVE | IN_CREATE | IN_DELETE),item->absoluteFilePath()); //IN_ONESHOT | IN_ALL_EVENTS)
X+        if (!watcher->directories().contains(item->absoluteFilePath()))
X+            watcher->addPath(item->absoluteFilePath());
X         item->watched = 1;
X         item = item->parent();
X     }
X@@ -278,7 +249,7 @@ bool myModel::setRootPath(const QString&
X 
X     myModelItem *item = rootItem->matchPath(path.split(SEPARATOR));
X 
X-    if(item->watched == 0) addWatcher(item);
X+    if(item->watched == 0) addToWatcher(item);
X 
X     if(item->walked == 0)
X     {
X@@ -352,10 +323,7 @@ void myModel::refresh()
X {
X     myModelItem *item = rootItem->matchPath(QStringList("/"));
X 
X-    //free all inotify watches
X-    foreach(int w, watchers.keys())
X-        inotify_rm_watch(inotifyFD,w);
X-    watchers.clear();
X+    watcher->removePaths(watcher->directories());
X 
X     beginResetModel();
X     item->clearAll();
X@@ -811,9 +779,7 @@ bool myModel::remove(const QModelIndex &
X         QFileInfo info(children.at(i));
X         if(info.isDir())
X         {
X-            int wd = watchers.key(info.filePath());
X-            inotify_rm_watch(inotifyFD,wd);
X-            watchers.remove(wd);
X+            watcher->removePath(info.filePath());
X             error |= QDir().rmdir(info.filePath());
X         }
X         else error |= QFile::remove(info.filePath());
9d571fc377e081220ac31ba2da3641ae
echo x - qtfm/files/patch-src_mymodel.h
sed 's/^X//' >qtfm/files/patch-src_mymodel.h << '348051303f98ef66c477a24b73c44bb7'
X--- src/mymodel.h.orig	2012-03-09 00:47:45.000000000 -0600
X+++ src/mymodel.h	2012-04-29 13:59:45.508571462 -0500
X@@ -83,8 +83,8 @@ public:
X         bool realMimeTypes;
X 
X public slots:
X-        void notifyChange();
X-        void addWatcher(myModelItem* path);
X+        void notifyChange(QString const& path);
X+        void addToWatcher(myModelItem* path);
X 
X signals:
X         void dragDropPaste(const QMimeData * data, QString newPath, QStringList cutList);
X@@ -113,9 +113,7 @@ private:
X         QString currentRootPath;
X         QFileIconProvider* iconFactory;
X 
X-        int inotifyFD;
X-        QSocketNotifier *notifier;
X-        QHash<int, QString> watchers;
X+        QFileSystemWatcher *watcher;
X };
X 
X #endif // MYMODEL_H
348051303f98ef66c477a24b73c44bb7
echo x - qtfm/files/patch-src_mainwindow.h
sed 's/^X//' >qtfm/files/patch-src_mainwindow.h << 'e39b4aa67f496c46c3ceac79fb4fcf6e'
X--- src/mainwindow.h.orig	2012-03-08 04:46:39.000000000 -0600
X+++ src/mainwindow.h	2012-04-29 22:53:06.754026702 -0500
X@@ -146,6 +146,15 @@ private:
X     void writeSettings();
X     void recurseFolder(QString path, QString parent, QStringList *);
X 
X+    class MountWorker : public QThread
X+    {
X+        bool ahead;
X+    protected:
X+        void run();
X+    public:
X+        void close();
X+    };
X+
X     int zoom;
X     int zoomTree;
X     int zoomList;
X@@ -182,7 +191,11 @@ private:
X     bookmarkmodel *modelBookmarks;
X     QItemSelectionModel *treeSelectionModel;
X     QItemSelectionModel *listSelectionModel;
X+#ifdef __FreeBSD__
X+    MountWorker *worker;
X+#else
X     QSocketNotifier *notify;
X+#endif
X 
X     QStringList mounts;
X 
e39b4aa67f496c46c3ceac79fb4fcf6e
echo x - qtfm/files/patch-src_bookmarks.cpp
sed 's/^X//' >qtfm/files/patch-src_bookmarks.cpp << '554b56483885fcf897b06e19cd7606b9'
X--- src/bookmarks.cpp.orig	2012-03-08 04:46:39.000000000 -0600
X+++ src/bookmarks.cpp	2012-04-30 14:20:26.157046128 -0500
X@@ -22,6 +22,11 @@
X #ifndef BOOKMARKS_CPP
X #define BOOKMARKS_CPP
X 
X+#ifdef __FreeBSD__
X+#include <sys/event.h>
X+#include <sys/mount.h>
X+#endif
X+
X #include <QtGui>
X #include "bookmarkmodel.h"
X #include "icondlg.h"
X@@ -80,42 +85,74 @@ void MainWindow::mountWatcherTriggered()
X }
X 
X //---------------------------------------------------------------------------
X+#ifdef __FreeBSD__
X+void MainWindow::MountWorker::run()
X+{
X+
X+    ahead = 1;
X+    int kq = kqueue();
X+    struct kevent ki[1];
X+    struct timespec to[1] = {{ 0, 100000 }};
X+
X+    EV_SET(ki, 0, EVFILT_FS, EV_ADD, VQ_MOUNT | VQ_UNMOUNT, 0, 0);
X+    kevent(kq, ki, 1, NULL, 0, NULL);
X+
X+    while (ahead) {
X+        switch (kevent(kq, NULL, 0, ki, 1, to)) {
X+        case -1:
X+            ::perror("kevent");
X+            break;
X+        case 0:
X+            continue;
X+        default:
X+            ((MainWindow *)parent())->MainWindow::autoBookmarkMounts();
X+        }
X+    }
X+    ::close(kq);
X+}
X+
X+void MainWindow::MountWorker::close()
X+{
X+    ahead = 0;
X+    wait();
X+}
X+#endif
X+
X+//---------------------------------------------------------------------------
X void MainWindow::autoBookmarkMounts()
X {
X     QList<QStandardItem *> theBookmarks = modelBookmarks->findItems("*",Qt::MatchWildcard);
X 
X     QStringList autoBookmarks;
X 
X+    size_t mntsize;
X+    struct statfs *mnt, *mntbuf;
X+
X     foreach(QStandardItem *item, theBookmarks)
X     {
X         if(item->data(34).toString() == "1")		    //is an automount
X             autoBookmarks.append(item->data(32).toString());
X     }
X 
X-    QStringList mtabMounts;
X-    QFile mtab("/etc/mtab");
X-    mtab.open(QFile::ReadOnly);
X-    QTextStream stream(&mtab);
X-    do mtabMounts.append(stream.readLine());
X-    while (!stream.atEnd());
X-    mtab.close();
X+    mntsize = getmntinfo(&mntbuf, MNT_NOWAIT);
X 
X     QStringList dontShowList = settings->value("hideBookmarks",0).toStringList();
X     mounts.clear();
X 
X-    foreach(QString item, mtabMounts)
X-        if(item[0] == '/')
X+    for (mnt = mntbuf; mntsize > 0; mntsize--, mnt++)
X+        // XXX zpool name does not start with /
X+        if (mnt->f_mntfromname[0] == '/' or !strcmp(mnt->f_fstypename, "zfs"))
X         {
X-            QString path = item.split(" ").at(1);
X-            path.replace("\\040"," ");
X-
X-            mounts.append(path);
X-            if(!dontShowList.contains(path))
X-                if(!autoBookmarks.contains(path))	    //add a new auto bookmark if it doesn't exist
X+            mounts.append(mnt->f_mntonname);
X+            if(!dontShowList.contains(mnt->f_mntonname))
X+                //add a new auto bookmark if it doesn't exist
X+                if(!autoBookmarks.contains(mnt->f_mntonname))
X                 {
X-                    if(item.split(" ").at(2) == "iso9660") modelBookmarks->addBookmark(path,path,"1","drive-optical");
X-                    else if(item.split(" ").at(2).contains("fat")) modelBookmarks->addBookmark(path,path,"1","drive-removable-media");
X-                    else modelBookmarks->addBookmark(path,path,"1","drive-harddisk");
X+                    if(strstr(mnt->f_fstypename, "9660"))
X+                        modelBookmarks->addBookmark(mnt->f_mntonname,mnt->f_mntonname,"1","drive-optical");
X+                    else if(strstr(mnt->f_fstypename, "fat"))
X+                        modelBookmarks->addBookmark(mnt->f_mntonname,mnt->f_mntonname,"1","drive-removable-media");
X+                    else modelBookmarks->addBookmark(mnt->f_mntonname,mnt->f_mntonname,"1","drive-harddisk");
X                 }
X         }
X 
554b56483885fcf897b06e19cd7606b9
echo x - qtfm/files/patch-qtfm.pro
sed 's/^X//' >qtfm/files/patch-qtfm.pro << '539ce90923915e57a4d8da9176a33b82'
X--- qtfm.pro.orig	2012-04-30 17:08:07.093692960 -0500
X+++ qtfm.pro	2012-04-30 17:48:49.433021364 -0500
X@@ -55,7 +55,7 @@ trans.files += translations/qtfm_da.qm \
X                translations/qtfm_zh.qm \
X                translations/qtfm_zh_TW.qm
X 
X-INSTALLS += target desktop icon docs trans
X+INSTALLS += target desktop icon trans
X 
X 
X 
539ce90923915e57a4d8da9176a33b82
echo x - qtfm/distinfo
sed 's/^X//' >qtfm/distinfo << '2e77555e3ee02543739b10879fbce1af'
XSHA256 (qtfm-5.4.tar.gz) = 8ef4c2464502959944e1b2476aa635b2a889d2859ba62dd61d8f591779c6fd0d
XSIZE (qtfm-5.4.tar.gz) = 147293
2e77555e3ee02543739b10879fbce1af
echo x - qtfm/pkg-plist
sed 's/^X//' >qtfm/pkg-plist << '2aa18a46886aa40174f24aeaf10ceb63'
Xbin/qtfm
Xshare/applications/qtfm.desktop
Xshare/pixmaps/qtfm.png
X%%DATADIR%%/qtfm_da.qm
X%%DATADIR%%/qtfm_de.qm
X%%DATADIR%%/qtfm_es.qm
X%%DATADIR%%/qtfm_fr.qm
X%%DATADIR%%/qtfm_it.qm
X%%DATADIR%%/qtfm_pl.qm
X%%DATADIR%%/qtfm_ru.qm
X%%DATADIR%%/qtfm_sr.qm
X%%DATADIR%%/qtfm_zh.qm
X%%DATADIR%%/qtfm_zh_TW.qm
X@dirrm %%DATADIR%%
2aa18a46886aa40174f24aeaf10ceb63
echo x - qtfm/Makefile
sed 's/^X//' >qtfm/Makefile << 'def7cb58bb8db47afc7f6c9ef8ce34cd'
X# New ports collection makefile for:	qtfm
X# Date created:				29 Apr 2012
X# Whom:					Zhihao Yuan <lichray@gmail.com>
X#
X# $FreeBSD$
X#
X
XPORTNAME=	qtfm
XDISTVERSION=	5.4
XCATEGORIES=	x11-fm
XMASTER_SITES=	http://www.qtfm.org/
X
XMAINTAINER=	lichray@gmail.com
XCOMMENT=	A small, lightweight file manager based on pure Qt
X
XLICENSE=	GPLv2
XLICENSE_FILE=	${WRKSRC}/COPYING
X
XUSE_DOS2UNIX=	yes
XUSE_QT_VER=	4
XQT_COMPONENTS=	gui network qmake_build moc_build rcc_build
X
XMAKE_JOBS_SAFE=	yes
XSTRIP_FILES=	bin/qtfm
X
Xpost-patch:
X	@cd ${WRKSRC} && \
X		${REINPLACE_CMD} -e s@/usr/@${PREFIX}/@g \
X		qtfm.pro src/main.cpp
X	@cd ${WRKSRC}/src && \
X		${REINPLACE_CMD} -e s@/usr/@${LOCALBASE}/@g \
X		icondlg.cpp mainwindow.cpp mymodel.cpp
X
Xdo-configure:
X	@cd ${WRKSRC} && ${SETENV} ${MAKE_ENV} ${QMAKE} \
X		${QMAKEFLAGS} qtfm.pro
X
Xpost-install:
X	${STRIP_CMD} ${STRIP_FILES:S,^,${PREFIX}/,}
X
X.include <bsd.port.mk>
def7cb58bb8db47afc7f6c9ef8ce34cd
echo x - qtfm/pkg-descr
sed 's/^X//' >qtfm/pkg-descr << 'c8a167a29c6b1c2f721eaf16c674b5d9'
XqtFM is a small, lightweight file manager for Linux desktops based on pure Qt
Xand works great with minimal desktop environments like Openbox.
X
XWWW: http://www.qtfm.org/
c8a167a29c6b1c2f721eaf16c674b5d9
exit
--- qtfm.shar ends here ---


>Release-Note:
>Audit-Trail:
>Unformatted:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?4f9f36f1.447ab60a.784b.ffffed55>