diff --git a/CMakeLists.txt b/CMakeLists.txt
index 57e71ebb..645e4691 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,5 +1,9 @@
cmake_minimum_required(VERSION 3.0.2)
-project(filer-qt)
+if(AIRYX)
+ project(Filer)
+else()
+ project(filer-qt)
+endif()
set(PCMANFM_QT_VERSION_MAJOR 0)
set(PCMANFM_QT_VERSION_MINOR 10)
@@ -11,6 +15,11 @@ set(LIBFM_QT_VERSION_MINOR 10)
set(LIBFM_QT_VERSION_PATCH 0)
set(LIBFM_QT_VERSION ${LIBFM_QT_VERSION_MAJOR}.${LIBFM_QT_VERSION_MINOR}.${LIBFM_QT_VERSION_PATCH})
+if(AIRYX)
+ set(CMAKE_INSTALL_BINDIR "/Contents/Airyx")
+ set(CMAKE_INSTALL_DATAROOTDIR "/Contents/Resources")
+endif()
+
list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake")
# We use the libtool versioning scheme for the internal so name, "current:revision:age"
@@ -28,6 +37,9 @@ find_package(Qt5Widgets 5.2 REQUIRED)
find_package(Qt5DBus 5.2 REQUIRED)
find_package(Qt5LinguistTools 5.2 REQUIRED)
find_package(Qt5X11Extras 5.2 REQUIRED)
+if(AIRYX)
+ find_package(Qt5Xdg 3.7 REQUIRED)
+endif()
find_package(PkgConfig)
pkg_check_modules(SYSTEM_LIBS REQUIRED
@@ -64,9 +76,15 @@ configure_file(
"${CMAKE_CURRENT_BINARY_DIR}/filer-qt.1"
@ONLY
)
+if(AIRYX)
+ set(MAN1PATH "${CMAKE_INSTALL_DATAROOTDIR}")
+else()
+ set(MAN1PATH "${CMAKE_INSTALL_MANDIR}/man1")
+endif()
+
install(FILES
"${CMAKE_CURRENT_BINARY_DIR}/filer-qt.1"
- DESTINATION "${CMAKE_INSTALL_MANDIR}/man1"
+ DESTINATION "${MAN1PATH}"
)
# add Doxygen support to generate API docs
diff --git a/Info.plist b/Info.plist
new file mode 100644
index 00000000..7097dde3
--- /dev/null
+++ b/Info.plist
@@ -0,0 +1,51 @@
+
+
+
+
+ CFBundleName
+ Filer
+ CFBundleDisplayName
+ Filer
+ CFBundleIdentifier
+ org.airyx.Filer
+ CFBundleVersion
+ 1.0
+ CFBundlePackageType
+ APPL
+ CFBundleSignature
+ OBJC
+ CFBundleExecutable
+ Filer
+ CFBundleShortVersionString
+ 1.0.0
+ NSHumanReadableCopyright
+ Copyright (C) 2021 Airyx Project
+ CFBundleIconFile
+ Icon.png
+ NSPrincipalClass
+
+ CFBundleDocumentTypes
+
+
+ LSItemContentTypes
+
+ public.folder
+
+ CFBundleTypeName
+ Folder
+ CFBundleTypeRole
+ Editor
+
+
+ LSItemContentTypes
+
+ public.volume
+
+ CFBundleTypeName
+ Volume
+ CFBundleTypeRole
+ Editor
+
+
+
+
diff --git a/Makefile b/Makefile
new file mode 100644
index 00000000..a159fee0
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,16 @@
+# Filer is built by cmake. This dummy makefile just creates the .app bundle.
+
+APP=Filer
+SRCS=
+MK_DEBUG_FILES=no
+RESOURCES=
+FRAMEWORKS=
+
+build: Filer.app
+ cp -fv ${.CURDIR}/airyxOSFiler.png ${APP_DIR}/Contents/Resources/Icon.png
+ cp -fv ${.CURDIR}/Info.plist ${APP_DIR}/Contents
+
+clean:
+ rm -f ${.CURDIR}/build/src/*.o
+
+.include
diff --git a/airyxOSFiler.png b/airyxOSFiler.png
new file mode 100755
index 00000000..ccf4790d
Binary files /dev/null and b/airyxOSFiler.png differ
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 31edb177..28ff7d10 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -1,6 +1,14 @@
set(LIBFM_LIBRARY "fm-qt5")
set(QTX_INCLUDE_DIRS "")
-set(QTX_LIBRARIES Qt5::Widgets Qt5::DBus Qt5::X11Extras)
+if(AIRYX)
+ set(QTX_LIBRARIES Qt5::Widgets Qt5::DBus Qt5::X11Extras Qt5Xdg)
+ set(EXEC_NAME "Filer")
+ set(PCMANFM_DIR "/Contents/Resources")
+else()
+ set(QTX_LIBRARIES Qt5::Widgets Qt5::DBus Qt5::X11Extras)
+ set(EXEC_NAME "filer-qt")
+ set(PCMANFM_DIR "${CMAKE_INSTALL_PREFIX}/share/filer-qt")
+endif()
include_directories(
${QTX_INCLUDE_DIRS}
@@ -17,6 +25,7 @@ link_directories(
)
set(filer_SRCS
+ airyx.cpp
bundle.cpp # probono
libfmqt.cpp
bookmarkaction.cpp
@@ -129,43 +138,51 @@ lxqt_translate_desktop(DESKTOP_FILES
if(APPLE)
set(CMAKE_INSTALL_RPATH "@executable_path") # Darwin, macOS
else()
- set(CMAKE_INSTALL_RPATH "$ORIGIN/../lib") # FreeBSD
+ if(AIRYX)
+ set(CMAKE_INSTALL_RPATH "$ORIGIN/../Resources/lib") # Airyx
+ else()
+ set(CMAKE_INSTALL_RPATH "$ORIGIN/../lib") # FreeBSD
+ endif()
endif()
if(NOT LINUX)
set(CMAKE_BUILD_WITH_INSTALL_RPATH ON) # On Linux we let appimagetool handle it
endif()
-add_executable(filer-qt
+
+add_executable(${EXEC_NAME}
${filer_SRCS}
${filer_UIS_H}
${QM_FILES}
${DESKTOP_FILES}
)
set_property(
- TARGET filer-qt APPEND
+ TARGET ${EXEC_NAME} APPEND
PROPERTY COMPILE_DEFINITIONS
LIBFM_QT_API=Q_DECL_IMPORT
- PCMANFM_DATA_DIR="${CMAKE_INSTALL_PREFIX}/share/filer-qt"
+ PCMANFM_DATA_DIR="${PCMANFM_DIR}"
LIBFM_DATA_DIR="${LIBFM_PREFIX}/share/libfm" # This is a little bit dirty
PCMANFM_QT_VERSION="${PCMANFM_QT_VERSION}"
)
-target_link_libraries(filer-qt
+target_link_libraries(${EXEC_NAME}
${QTX_LIBRARIES}
${LIBFM_LIBRARIES}
${LIBMENUCACHE_LIBRARIES}
${SYSTEM_LIBS_LIBRARIES}
+ ${SYSTEM_FRAMEWORKS}
)
-install(TARGETS filer-qt RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
+install(TARGETS ${EXEC_NAME} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
-# install a desktop entry file for filer-qt and desktop preferences
-install(FILES ${DESKTOP_FILES} DESTINATION "${CMAKE_INSTALL_DATADIR}/applications"
-)
+if(NOT AIRYX)
+ # install a desktop entry file for filer-qt and desktop preferences
+ install(FILES ${DESKTOP_FILES} DESTINATION "${CMAKE_INSTALL_DATADIR}/applications"
+ )
+endif()
-install(FILES ${QM_FILES} DESTINATION "${CMAKE_INSTALL_DATADIR}/filer-qt/translations")
+install(FILES ${QM_FILES} DESTINATION "${CMAKE_INSTALL_DATADIR}/translations")
# prevent the generated files from being deleted during make clean
set_directory_properties(PROPERTIES CLEAN_NO_CUSTOM true)
-qt5_use_modules(filer-qt Widgets DBus)
+qt5_use_modules(${EXEC_NAME} Widgets DBus)
diff --git a/src/about.ui b/src/about.ui
index 259796ed..a94ff931 100644
--- a/src/about.ui
+++ b/src/about.ui
@@ -7,7 +7,7 @@
0
0
543
- 418
+ 541
@@ -24,7 +24,7 @@
- icons/filer-256.png
+ ./Resources/Icon.png
Qt::AlignCenter
@@ -67,7 +67,7 @@
-
- <html><head/><body><p><a href="https://github.com/probonopd/filer/"><span style=" text-decoration: underline; color:#0000ff;">https://github.com/probonopd/filer/</span></a></p></body></html>
+ <html><head/><body><p><a href="https://github.com/mszoek/Filer/"><span style=" text-decoration: underline; color:#0000ff;">https://github.com/mszoek/Filer/</span></a></p></body></html>
Qt::RichText
@@ -80,7 +80,7 @@
-
- 1
+ 0
false
@@ -97,6 +97,7 @@
Programming:
+* Zoe Knox (mszoek)
* Simon Peter (probono)
* Chris Moore (moochris)
* Hong Jen Yee (PCMan) <pcman.tw@gmail.com>
@@ -124,6 +125,7 @@ Application icon:
Filer
+Copyright (C) 2021 Zoe Knox
Copyright (C) 2020-21 Simon Peter
Copyright (C) 2021 Chris Moore
diff --git a/src/airyx.cpp b/src/airyx.cpp
new file mode 100644
index 00000000..edbf9ba5
--- /dev/null
+++ b/src/airyx.cpp
@@ -0,0 +1,207 @@
+/*
+ * Glue code to integrate Filer with Airyx Cocoa frameworks
+ *
+ * Copyright (C) 2021 Zoe Knox
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#if defined(__AIRYX__)
+#import "airyx.h"
+#import
+#include
+
+QList programArguments()
+{
+ CFArrayRef args = (CFArrayRef)CFBundleGetValueForInfoDictionaryKey(
+ CFBundleGetMainBundle(), CFSTR("ProgramArguments" ));
+ QList list;
+ if(!args)
+ return list;
+
+ for(int x = 0; x < CFArrayGetCount(args); ++x) {
+ CFStringRef value = (CFStringRef)CFArrayGetValueAtIndex(args, x);
+ list.append(QString::fromUtf8( CFStringGetCStringPtr(value, kCFStringEncodingUTF8) ));
+ }
+ return list;
+}
+
+bool checkWhetherAppDirOrBundle(QString path)
+{
+ CFStringRef cfpath = CFStringCreateWithCString(NULL, path.toUtf8(), kCFStringEncodingUTF8);
+ CFURLRef url = CFURLCreateWithFileSystemPath(NULL, cfpath, kCFURLPOSIXPathStyle, true);
+ bool check = (LSIsNSBundle(url) | LSIsAppDir(url));
+ CFRelease(url);
+ CFRelease(cfpath);
+ return check;
+}
+
+QString displayNameForBundle(QString path)
+{
+ // This function is only called for App Bundles or
+ // AppDirs, so just a quick check to tell them apart...
+ if(path.toLower().endsWith(".app")) {
+ CFStringRef cfpath = CFStringCreateWithCString(NULL, path.toUtf8(), kCFStringEncodingUTF8);
+ CFURLRef url = CFURLCreateWithFileSystemPath(NULL, cfpath, kCFURLPOSIXPathStyle, true);
+ CFRelease(cfpath);
+ CFBundleRef bundle = CFBundleCreate(NULL, url);
+ CFDictionaryRef infoDict = CFBundleGetInfoDictionary(bundle);
+ CFStringRef name = (CFStringRef)CFDictionaryGetValue(infoDict, CFSTR("CFBundleDisplayName"));
+ if(name == NULL)
+ name = (CFStringRef)CFDictionaryGetValue(infoDict, CFSTR("CFBundleName"));
+ if(name == NULL) {
+ CFURLRef noExt = CFURLCreateCopyDeletingPathExtension(NULL, url);
+ name = CFURLCopyLastPathComponent(noExt);
+ CFRelease(noExt);
+ }
+ QString qname = QString::fromUtf8(CFStringGetCStringPtr(name, kCFStringEncodingUTF8));
+ CFRelease(bundle);
+ CFRelease(url);
+ return qname;
+ }
+
+ // Handle AppDirs by looking for .desktop files. This is ugly.
+ QStringList fileList;
+ QDir folder(path);
+ QStringList entryList(folder.entryList(QStringList(), QDir::Files));
+ for(QStringList::iterator entry = entryList.begin(); entry != entryList.end(); entry++)
+ fileList.append(folder.absoluteFilePath(*entry));
+
+ QDir share(path.append("/usr/share/applications"));
+ entryList = folder.entryList(QStringList(), QDir::Files);
+ for(QStringList::iterator entry = entryList.begin(); entry != entryList.end(); entry++)
+ fileList.append(share.absoluteFilePath(*entry));
+
+ for(QStringList::iterator filepath = fileList.begin(); filepath != fileList.end(); filepath++) {
+ if(filepath->toLower().endsWith(".desktop")) {
+ XdgDesktopFile df;
+ df.load(*filepath);
+ if(df.type() == XdgDesktopFile::ApplicationType) {
+ if(df.name() != QString()) {
+ return df.name();
+ }
+ }
+ }
+ }
+
+ return QFileInfo(path).baseName();
+}
+
+QString getPathForMainBundle()
+{
+ CFBundleRef mainBundle = CFBundleGetMainBundle();
+ CFURLRef url = CFBundleCopyBundleURL(mainBundle);
+ CFStringRef path = CFURLCopyFileSystemPath(url, kCFURLPOSIXPathStyle);
+ QString result(QString::fromUtf8(CFStringGetCStringPtr(path, kCFStringEncodingUTF8)));
+ CFRelease(path);
+ CFRelease(url);
+ return result;
+}
+
+QIcon getIconForBundle(QString path = NULL)
+{
+ QIcon icon = QIcon::fromTheme("do"); // default "executable folder" icon
+
+ // This function is only called for App Bundles or
+ // AppDirs, so just a quick check to tell them apart...
+ if(path.toLower().endsWith(".app")) {
+ CFStringRef cfpath = CFStringCreateWithCString(NULL, path.toUtf8(), kCFStringEncodingUTF8);
+ CFURLRef url = CFURLCreateWithFileSystemPath(NULL, cfpath, kCFURLPOSIXPathStyle, true);
+ CFBundleRef bundle = CFBundleCreate(NULL, url);
+ CFDictionaryRef infoDict = CFBundleGetInfoDictionary(bundle);
+ CFStringRef iconfile = (CFStringRef)CFDictionaryGetValue(infoDict, CFSTR("CFBundleIconFile"));
+
+ if(iconfile == NULL)
+ iconfile = (CFStringRef)CFDictionaryGetValue(infoDict, CFSTR("NSIcon"));
+
+ if(iconfile != NULL) {
+ CFURLRef resourceURL = CFBundleCopyResourcesDirectoryURL(bundle);
+ CFStringRef resourcePath = CFURLCopyFileSystemPath(resourceURL, kCFURLPOSIXPathStyle);
+ QDir resourceDir(QString::fromUtf8(CFStringGetCStringPtr(resourcePath, kCFStringEncodingUTF8)));
+ CFRelease(resourcePath);
+ CFRelease(resourceURL);
+
+ QString iconPath(resourceDir.filePath(QString::fromUtf8(
+ CFStringGetCStringPtr(iconfile, kCFStringEncodingUTF8))));
+ if(resourceDir.exists(iconPath))
+ icon = QIcon(iconPath);
+ }
+
+ CFRelease(bundle);
+ CFRelease(url);
+ CFRelease(cfpath);
+ return icon;
+ }
+
+ // Look for a .DirIcon in AppDir
+ QDir appdir(path);
+ QString iconPath = appdir.filePath(".DirIcon");
+ if(appdir.exists(iconPath))
+ icon = QIcon(iconPath);
+ return icon;
+}
+
+// Scan well-known locations for apps and add to LaunchServices
+AppHunter::AppHunter(QObject *p): QThread(p)
+{
+}
+
+void AppHunter::run(void)
+{
+ QStringList dirs;
+ dirs.append("/Applications");
+ dirs.append("/System/Library/CoreServices");
+ dirs.append("/System/Library/Applications");
+ dirs.append(QDir::homePath().append("/Applications"));
+ dirs.append("/usr/share/applications");
+ dirs.append("/usr/local/share/applications");
+
+ size_t nDirs = dirs.size();
+ for(size_t pos = 0; pos < nDirs; ++pos) {
+ QDir dir(dirs.at(pos));
+ for(QString entry : dir.entryList()) {
+ if(entry == "." || entry == "..")
+ continue;
+
+ QString filepath(dir.filePath(entry));
+ QFileInfo fi(dir, entry);
+
+ if(checkWhetherAppDirOrBundle(filepath) || entry.endsWith(".desktop", Qt::CaseInsensitive)) {
+ CFStringRef cfpath = CFStringCreateWithCString(NULL, filepath.toUtf8(), kCFStringEncodingUTF8);
+ CFURLRef url = CFURLCreateWithFileSystemPath(NULL, cfpath, kCFURLPOSIXPathStyle, true);
+
+// qDebug() << "Registering " << filepath;
+ LSRegisterURL(url, true);
+ CFRelease(url);
+ CFRelease(cfpath);
+ } else if(fi.isDir()) { // is a regular dir?
+ dirs.append(filepath);
+ ++nDirs;
+ }
+ }
+ }
+ // FIXME: Bus Error on thread exit without these lines.
+ // There is an incompatibility with QThread and objc's ARC pools
+ // which results in a Bus Error when the thread exits, crashing
+ // Filer. This little hack gets around the problem for now.
+ yieldCurrentThread();
+ while(1) sleep(1);
+}
+
+#endif
diff --git a/src/airyx.h b/src/airyx.h
new file mode 100644
index 00000000..8005f87e
--- /dev/null
+++ b/src/airyx.h
@@ -0,0 +1,58 @@
+/*
+ * Glue code to integrate Filer with Airyx Cocoa frameworks
+ *
+ * Copyright (C) 2021 Zoe Knox
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#import
+#import
+
+extern "C" void __NSInitializeProcess(int argc, const char **argv);
+
+// Returns the list of strings from key "ProgramArguments" in
+// the bundle's Info.plist
+QList programArguments();
+
+// Returns true if path is an App Bundle or AppDir
+bool checkWhetherAppDirOrBundle(QString path);
+
+// Returns the value of CFBundleDisplayName or CFBundleName
+// and falls back to folder name on error
+QString displayNameForBundle(QString path);
+
+// Returns an icon for a bundle or a generic default
+QIcon getIconForBundle(QString path);
+
+QString getPathForMainBundle();
+
+class AppHunter: public QThread {
+ public:
+ AppHunter(QObject *);
+ void run();
+};
diff --git a/src/application.cpp b/src/application.cpp
index 0ceeb420..bc36d570 100644
--- a/src/application.cpp
+++ b/src/application.cpp
@@ -53,6 +53,9 @@
#include
#include "dbusinterface.h"
+#if defined(__AIRYX__)
+#include "airyx.h"
+#endif
using namespace Filer;
static const char* serviceName = "org.freedesktop.FileManager1";
@@ -84,6 +87,9 @@ Application::Application(int& argc, char** argv):
argc_ = argc;
argv_ = argv;
+#if defined(__AIRYX__)
+ __NSInitializeProcess(argc, (const char **)argv);
+#endif
QDBusConnection dbus = QDBusConnection::sessionBus();
if(dbus.registerService(serviceName)) {
@@ -128,6 +134,40 @@ Application::Application(int& argc, char** argv):
delay(100);
}
}
+#if defined(__AIRYX__)
+ // On Airyx, plasmashell provides the global menu bar and some widgets
+ qDebug("Waiting for services to appear on DBus...");
+ bool plasmaHere(false), menuHere(false);
+ while(plasmaHere == false || menuHere == false) {
+ if(!menuHere) {
+ QDBusInterface* menuIface = new QDBusInterface(
+ QStringLiteral("com.canonical.AppMenu.Registrar"),
+ QStringLiteral("/com/canonical/AppMenu/Registrar"));
+ if (menuIface) {
+ if (menuIface->isValid()) {
+ qDebug("Global menu is available");
+ menuHere = true;
+ }
+ delete menuIface;
+ menuIface = 0;
+ }
+ }
+ if(!plasmaHere) {
+ QDBusInterface* plasmaIface = new QDBusInterface(
+ QStringLiteral("org.kde.plasmashell"),
+ QStringLiteral("/org/kde/plasmashell"));
+ if (plasmaIface) {
+ if (plasmaIface->isValid()) {
+ qDebug("Plasma shell is available");
+ plasmaHere = true;
+ }
+ delete plasmaIface;
+ plasmaIface = 0;
+ }
+ }
+ delay(500);
+ }
+#endif
// Check if LXQt Session is running. LXQt has it's own Desktop Folder
// editor. We just hide our editor when LXQt is running.
@@ -222,11 +262,19 @@ bool Application::parseCommandLineArgs() {
parser.addPositionalArgument("files", tr("Files or directories to open"), tr("[FILE1, FILE2,...]"));
- parser.process(arguments());
+ QList args = arguments();
+#if defined(__AIRYX__)
+ if(args.length() <= 1)
+ args.append(programArguments());
+#endif
+ parser.process(args);
if(isPrimaryInstance) {
qDebug("isPrimaryInstance");
+ AppHunter *apphunter = new AppHunter(this);
+ apphunter->start();
+
if(parser.isSet(daemonOption))
daemonMode_ = true;
if(parser.isSet(profileOption))
@@ -326,7 +374,22 @@ void Application::init() {
translator.load("filer-qt_" + QLocale::system().name(), PCMANFM_DATA_DIR "/translations");
// qDebug("probono: Use relative path from main executable so that this works when it is not installed system-wide, too:");
// qDebug((QCoreApplication::applicationDirPath() + QString("/../share/filer-qt/translations/")).toUtf8()); // probono
- translator.load("filer-qt_" + QLocale::system().name(), QCoreApplication::applicationDirPath() + QString("/../share/filer-qt/translations/")); // probono
+#if defined(__AIRYX__)
+ CFBundleRef watashi = CFBundleGetMainBundle();
+ CFURLRef bundleURL = CFBundleCopyBundleURL(watashi);
+ LSRegisterURL(bundleURL, true); // make sure this app is known to LaunchServices
+ CFRelease(bundleURL);
+
+ CFURLRef resourceURL = CFBundleCopyResourcesDirectoryURL(watashi);
+ CFStringRef cfResourcePath = CFURLCopyFileSystemPath(resourceURL, kCFURLPOSIXPathStyle);
+ QString resourcePath = QString(CFStringGetCStringPtr(cfResourcePath, kCFStringEncodingUTF8));
+ CFRelease(cfResourcePath);
+ CFRelease(resourceURL);
+ CFRelease(watashi);
+ translator.load("filer-qt_" + QLocale::system().name(), resourcePath + "/translations");
+#else
+ translator.load("filer-qt_" + QLocale::system().name(), QCoreApplication::applicationDirPath() + QString("../share/filer-qt/translations")); // probono
+#endif
installTranslator(&translator);
}
@@ -559,8 +622,10 @@ void Application::setWallpaper(QString path, QString modeString) {
for(int i = 0; i < G_N_ELEMENTS(valid_wallpaper_modes); ++i) {
if(modeString == valid_wallpaper_modes[i]) {
mode = (DesktopWindow::WallpaperMode)i;
- if(mode != settings_.wallpaperMode())
+ if(mode != settings_.wallpaperMode()) {
+ settings_.setWallpaperMode(mode);
changed = true;
+ }
break;
}
}
diff --git a/src/bundle.cpp b/src/bundle.cpp
index 612dc881..21c38552 100644
--- a/src/bundle.cpp
+++ b/src/bundle.cpp
@@ -1,5 +1,5 @@
// File added by probono
-
+#if !defined(__AIRYX__)
#include "bundle.h"
#include
@@ -149,3 +149,4 @@ QIcon getIconForBundle(FmFileInfo* _info)
}
}
+#endif // not __AIRYX__
diff --git a/src/desktopwindow.cpp b/src/desktopwindow.cpp
index 19c5b486..b6919716 100644
--- a/src/desktopwindow.cpp
+++ b/src/desktopwindow.cpp
@@ -58,6 +58,9 @@
#include "ui_about.h"
#include "tabpage.h"
#include "trash.h"
+#if defined(__AIRYX__)
+#include "airyx.h"
+#endif
#include
#include
@@ -525,6 +528,10 @@ void DesktopWindow::onAbout()
explicit AboutDialog(QWidget* parent = 0, Qt::WindowFlags f = 0) {
ui.setupUi(this);
ui.version->setText(tr("Version: %1").arg(PCMANFM_QT_VERSION));
+#if defined(__AIRYX__)
+ QIcon icon = getIconForBundle(getPathForMainBundle());
+ ui.label_4->setPixmap(icon.pixmap(icon.availableSizes().first()));
+#endif
}
private:
Ui::AboutDialog ui;
diff --git a/src/filelauncher.cpp b/src/filelauncher.cpp
index 16420923..f0086fe1 100644
--- a/src/filelauncher.cpp
+++ b/src/filelauncher.cpp
@@ -27,7 +27,11 @@
#include "execfiledialog_p.h"
#include "appchooserdialog.h"
#include "utilities.h"
+#if defined(__AIRYX__)
+#include "airyx.h"
+#else
#include "bundle.h"
+#endif
using namespace Fm;
@@ -72,15 +76,33 @@ bool FileLauncher::launchFiles(QWidget* parent, GList* file_infos) {
// Since fm_launch_files needs all items to be opened in multiple tabs at once, we need
// to construct a list that contains those that are not bundles
GList* itemsToBeLaunched = NULL;
+#if defined(__AIRYX__)
+ QStringList LSFiles;
+#endif
for(GList* l = file_infos; l; l = l->next) {
FmFileInfo* info = FM_FILE_INFO(l->data);
+#if defined(__AIRYX__)
+ QString path = QString(fm_path_to_str(fm_file_info_get_path(info)));
+ bool isAppDirOrBundle = checkWhetherAppDirOrBundle(path);
+#else
bool isAppDirOrBundle = checkWhetherAppDirOrBundle(info);
+#endif
if(isAppDirOrBundle == false) {
+#if !defined(__AIRYX__)
qDebug() << "probono: Not an .AppDir or .app bundle. TODO: Make it possible to use the 'launch' command for those, too";
+#endif
// probono: URLs like network://, sftp:// and so on will continue to be handled like this in any case since they need GIO,
// but documents, non-bundle executables etc. could all be handled by 'launch' if we make 'launch' understand them
- itemsToBeLaunched = g_list_append(itemsToBeLaunched, l->data);
+#if defined(__AIRYX__)
+ if(fm_file_info_is_native(info) && !fm_file_info_is_dir(info))
+ LSFiles.append(path);
+ else
+#endif
+ itemsToBeLaunched = g_list_append(itemsToBeLaunched, l->data);
} else {
+#if defined(__AIRYX__)
+ LSFiles.append(path);
+#else
QString launchableExecutable = getLaunchableExecutable(info);
if(QStandardPaths::findExecutable("launch") != "") {
qDebug() << "probono: Launching using the 'launch' command";
@@ -91,8 +113,28 @@ bool FileLauncher::launchFiles(QWidget* parent, GList* file_infos) {
FmFileInfo* launchableExecutableFileInfo = fm_file_info_new_from_native_file(nullptr, launchableExecutable.toUtf8(),nullptr);
itemsToBeLaunched = g_list_append(itemsToBeLaunched, launchableExecutableFileInfo);
}
+#endif
}
+#if defined(__AIRYX__)
}
+
+ CFMutableArrayRef CFLSFiles = CFArrayCreateMutable(NULL, LSFiles.count(), NULL);
+ for(QStringList::iterator f = LSFiles.begin(); f != LSFiles.end(); f++) {
+ CFStringRef item = CFStringCreateWithCString(NULL, f->toUtf8(), kCFStringEncodingUTF8);
+ CFURLRef itemURL = CFURLCreateWithFileSystemPath(NULL, item, kCFURLPOSIXPathStyle, false);
+ CFArrayAppendValue(CFLSFiles, itemURL);
+ CFRelease(item);
+ }
+
+ LSLaunchURLSpec spec;
+ memset(&spec, 0, sizeof(spec));
+ spec.appURL = NULL;
+ spec.itemURLs = CFLSFiles;
+ LSOpenFromURLSpec(&spec, NULL);
+ CFRelease(CFLSFiles);
+#else
+ }
+#endif
bool ret = fm_launch_files(G_APP_LAUNCH_CONTEXT(context), itemsToBeLaunched, &funcs, this);
g_list_free(itemsToBeLaunched);
g_object_unref(context);
diff --git a/src/filepropsdialog.cpp b/src/filepropsdialog.cpp
index ec0f4932..a3d3f7d8 100644
--- a/src/filepropsdialog.cpp
+++ b/src/filepropsdialog.cpp
@@ -31,7 +31,11 @@
#include
#include
#include
+#if defined(__AIRYX__)
+#include "airyx.h"
+#else
#include "bundle.h"
+#endif
#define DIFFERENT_UIDS ((uid)-1)
#define DIFFERENT_GIDS ((gid)-1)
@@ -230,7 +234,12 @@ void FilePropsDialog::initPermissionsPage() {
void FilePropsDialog::initGeneralPage() {
+#if defined(__AIRYX__)
+ QString path = QString(fm_path_to_str(fm_file_info_get_path(fileInfo)));
+ bool isAppDirOrBundle = checkWhetherAppDirOrBundle(path);
+#else
bool isAppDirOrBundle = checkWhetherAppDirOrBundle(fileInfo);
+#endif
// probono: Set some things differently for AppDir/app bundle than for normal folder
if(isAppDirOrBundle) {
@@ -248,7 +257,11 @@ void FilePropsDialog::initGeneralPage() {
qDebug() << "probono: fm_file_info_get_icon(fileInfo) called";
if(isAppDirOrBundle){
+#if defined(__AIRYX__)
+ icon = getIconForBundle(path);
+#else
icon = getIconForBundle(fileInfo);
+#endif
}
}
if(mimeType) {
diff --git a/src/foldermodelitem.cpp b/src/foldermodelitem.cpp
index 8b826609..16446c4e 100644
--- a/src/foldermodelitem.cpp
+++ b/src/foldermodelitem.cpp
@@ -22,7 +22,11 @@
#include
#include
#include
+#if defined(__AIRYX__)
+#include "airyx.h"
+#else
#include "bundle.h"
+#endif
using namespace Fm;
@@ -31,13 +35,18 @@ FolderModelItem::FolderModelItem(FmFileInfo* _info):
displayName = QString::fromUtf8(fm_file_info_get_disp_name(info));
// qDebug() << "probono: (1) FolderModelItem created for" << displayName;
+#if defined(__AIRYX__)
+ QString path = QString(fm_path_to_str(fm_file_info_get_path(_info)));
+ bool isAppDirOrBundle = checkWhetherAppDirOrBundle(path);
+#else
bool isAppDirOrBundle = checkWhetherAppDirOrBundle(_info);
+#endif
icon = IconTheme::icon(fm_file_info_get_icon(_info));
// probono: Set some things differently for AppDir/app bundle than for normal folder
if(isAppDirOrBundle) {
-
+#if !defined(__AIRYX__)
QString path = QString(fm_path_to_str(fm_file_info_get_path(info)));
QFileInfo fileInfo = QFileInfo(path);
QString nameWithoutSuffix = QFileInfo(fileInfo.completeBaseName()).fileName();
@@ -45,14 +54,27 @@ FolderModelItem::FolderModelItem(FmFileInfo* _info):
qDebug("probono: AppDir/app bundle detected xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx " + path.toUtf8());
qDebug("probono: Set different icon for AppDir/app bundle");
- icon = getIconForBundle(info);
+ icon = getIconForBundle(_info);
+#else
+ icon = getIconForBundle(path);
+#endif
// probono: Set display name
+#if defined(__AIRYX__)
+ fm_file_info_set_disp_name(_info, displayNameForBundle(path).toUtf8());
+
+ CFStringRef cfpath = CFStringCreateWithCString(NULL, path.toUtf8(), kCFStringEncodingUTF8);
+ CFURLRef appURL = CFURLCreateWithFileSystemPath(NULL, cfpath, kCFURLPOSIXPathStyle, true);
+
+ LSRegisterURL(appURL, false);
+ CFRelease(appURL);
+ CFRelease(cfpath);
+#else
fm_file_info_set_disp_name(_info, nameWithoutSuffix.toUtf8()); // probono: Remove the suffix from display name
qDebug("probono: TODO: Set the proper display name for AppDir based on Name= entries in desktop file. Similar to what happens when desktop files are displayed");
qDebug("probono: TODO: Submit it to some Launch Services like database?");
-
+#endif
}
thumbnails.reserve(2);
diff --git a/src/icons/.DS_Store b/src/icons/.DS_Store
new file mode 100644
index 00000000..a5cbfd39
Binary files /dev/null and b/src/icons/.DS_Store differ
diff --git a/src/icons/Filer.icns b/src/icons/Filer.icns
index 8e53b9f6..91a4ffbd 100644
Binary files a/src/icons/Filer.icns and b/src/icons/Filer.icns differ
diff --git a/src/icons/filer-1024.png b/src/icons/filer-1024.png
index e18cd6ea..26e46fe4 100644
Binary files a/src/icons/filer-1024.png and b/src/icons/filer-1024.png differ
diff --git a/src/icons/filer-128.png b/src/icons/filer-128.png
index ce47053b..9a8def22 100644
Binary files a/src/icons/filer-128.png and b/src/icons/filer-128.png differ
diff --git a/src/icons/filer-16.png b/src/icons/filer-16.png
index ce2d768c..418df666 100644
Binary files a/src/icons/filer-16.png and b/src/icons/filer-16.png differ
diff --git a/src/icons/filer-256.png b/src/icons/filer-256.png
index daae3947..ec01d2c8 100644
Binary files a/src/icons/filer-256.png and b/src/icons/filer-256.png differ
diff --git a/src/icons/filer-32.png b/src/icons/filer-32.png
index cd44d654..9f43a7b5 100644
Binary files a/src/icons/filer-32.png and b/src/icons/filer-32.png differ
diff --git a/src/icons/filer-512.png b/src/icons/filer-512.png
index f0ac632e..f32fac88 100644
Binary files a/src/icons/filer-512.png and b/src/icons/filer-512.png differ
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp
index d0340df1..c4f47beb 100644
--- a/src/mainwindow.cpp
+++ b/src/mainwindow.cpp
@@ -49,6 +49,9 @@
#include "windowregistry.h"
#include "gotofolderwindow.h"
#include "trash.h"
+#if defined(__AIRYX__)
+#include "airyx.h"
+#endif
// #include "qmodeltest/modeltest.h"
@@ -701,6 +704,10 @@ void MainWindow::on_actionAbout_triggered() {
explicit AboutDialog(QWidget* parent = 0, Qt::WindowFlags f = 0) {
ui.setupUi(this);
ui.version->setText(tr("Version: %1").arg(PCMANFM_QT_VERSION));
+#if defined(__AIRYX__)
+ QIcon icon = getIconForBundle(getPathForMainBundle());
+ ui.label_4->setPixmap(icon.pixmap(icon.availableSizes().first()));
+#endif
}
private:
Ui::AboutDialog ui;