musrview: give the embedded window a proper application name and icon
musrview is a plain executable, hence on macOS it showed up with the generic 'exec' icon. The QApplication behind the embedded display is created by ROOT, musrview now sets its name and icon after the first window is shown (needs Qt6::Widgets, the same Qt ROOT's qt6web links against). - new application icon src/musrview_web/musrview.svg/.png, installed next to musrview.html and found the same way (PMusrWebCanvas::WebDir()) - macOS: an Info.plist embedded into the binary gives name and bundle id - Linux: musrview.desktop plus hicolor icons, and setDesktopFileName() so that Wayland compositors can match the window to its icon Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
875074432c
commit
a18a579d7a
11 files changed
+176
-2
No files matched your search
@@ -588,6 +588,11 @@ message("")
|
||||
message(" musrview (ROOT7 web graphics):")
|
||||
if (MUSRVIEW_HAS_QT6WEB)
|
||||
message(" embedded window (ROOT qt6web) : yes")
|
||||
if (MUSRVIEW_HAS_QT_APP_ICON)
|
||||
message(" application icon (Qt6Widgets) : yes")
|
||||
else ()
|
||||
message(" application icon (Qt6Widgets) : no, Qt6Widgets not found")
|
||||
endif ()
|
||||
else ()
|
||||
message(" embedded window (ROOT qt6web) : no, will use the standard browser")
|
||||
endif ()
|
||||
|
||||
@@ -17,7 +17,7 @@ set (CPACK_RESOURCE_FILE_LICENSE "@PROJECT_SOURCE_DIR@/COPYING")
|
||||
set (CPACK_RESOURCE_FILE_README "@PROJECT_SOURCE_DIR@/README.md")
|
||||
set (CPACK_RESOURCE_FILE_WELCOME "@PROJECT_SOURCE_DIR@/cmake/welcome.txt")
|
||||
|
||||
set (CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION "@CMAKE_INSTALL_PREFIX@;@CMAKE_INSTALL_PREFIX@/bin;@CMAKE_INSTALL_PREFIX@/include;@CMAKE_INSTALL_PREFIX@/share;@CMAKE_INSTALL_PREFIX@/lib64;@CMAKE_INSTALL_PREFIX@/lib;@CMAKE_INSTALL_PREFIX@/pkgconfig;@CMAKE_INSTALL_PREFIX@/share/applications;@CMAKE_INSTALL_PREFIX@/share/icons;@CMAKE_INSTALL_PREFIX@/share/icons/hicolor;@CMAKE_INSTALL_PREFIX@/share/icons/hicolor/48x48;@CMAKE_INSTALL_PREFIX@/share/icons/hicolor/48x48/apps")
|
||||
set (CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION "@CMAKE_INSTALL_PREFIX@;@CMAKE_INSTALL_PREFIX@/bin;@CMAKE_INSTALL_PREFIX@/include;@CMAKE_INSTALL_PREFIX@/share;@CMAKE_INSTALL_PREFIX@/lib64;@CMAKE_INSTALL_PREFIX@/lib;@CMAKE_INSTALL_PREFIX@/pkgconfig;@CMAKE_INSTALL_PREFIX@/share/applications;@CMAKE_INSTALL_PREFIX@/share/icons;@CMAKE_INSTALL_PREFIX@/share/icons/hicolor;@CMAKE_INSTALL_PREFIX@/share/icons/hicolor/48x48;@CMAKE_INSTALL_PREFIX@/share/icons/hicolor/48x48/apps;@CMAKE_INSTALL_PREFIX@/share/icons/hicolor/512x512;@CMAKE_INSTALL_PREFIX@/share/icons/hicolor/512x512/apps;@CMAKE_INSTALL_PREFIX@/share/icons/hicolor/scalable;@CMAKE_INSTALL_PREFIX@/share/icons/hicolor/scalable/apps")
|
||||
|
||||
# we do not have any absolute paths, so do not need DESTDIR
|
||||
set (CPACK_SET_DESTDIR "OFF")
|
||||
|
||||
@@ -93,6 +93,10 @@ rm -rf $RPM_BUILD_ROOT
|
||||
%doc %_prefix/share/doc/musrfit
|
||||
%{_datadir}/applications/musredit.desktop
|
||||
%{_datadir}/icons/hicolor/48x48/apps/musredit.png
|
||||
%{_datadir}/applications/musrview.desktop
|
||||
%{_datadir}/icons/hicolor/512x512/apps/musrview.png
|
||||
%{_datadir}/icons/hicolor/scalable/apps/musrview.svg
|
||||
%_prefix/share/musrfit
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
[Desktop Entry]
|
||||
Name=musrview
|
||||
Comment=viewer for musrfit data and fit results
|
||||
GenericName=musrfit viewer
|
||||
Exec=musrview %f
|
||||
Icon=musrview
|
||||
Terminal=false
|
||||
Type=Application
|
||||
NoDisplay=true
|
||||
StartupWMClass=musrview
|
||||
Categories=Science;DataVisualization;
|
||||
Keywords=muSR;fitting;musrfit;physics;muon;
|
||||
+52
-1
@@ -141,10 +141,61 @@ target_link_libraries(musrview FFTW3::FFTW3 ${ROOT_LIBRARIES} ROOT::ROOTWebDispl
|
||||
#--- MUSRVIEW_WEB_DIR (see src/classes/CMakeLists.txt) points here. During
|
||||
#--- development the environment variable MUSRFIT_WEB_DIR overrides it. -------
|
||||
install(
|
||||
FILES ${CMAKE_SOURCE_DIR}/src/musrview_web/musrview.html
|
||||
FILES
|
||||
${CMAKE_SOURCE_DIR}/src/musrview_web/musrview.html
|
||||
${CMAKE_SOURCE_DIR}/src/musrview_web/musrview.png
|
||||
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/musrfit/musrview
|
||||
)
|
||||
|
||||
#--- application icon of the embedded window: ROOT creates the QApplication,
|
||||
#--- musrview only sets its icon, hence it has to use the very same Qt6 ROOT's
|
||||
#--- qt6web display links against. Without it macOS shows the generic 'exec'.
|
||||
if (MUSRVIEW_HAS_QT6WEB)
|
||||
find_package(Qt6 COMPONENTS Widgets QUIET)
|
||||
if (TARGET Qt6::Widgets)
|
||||
# QT_NO_KEYWORDS: Qt's emit/signals/slots macros break ROOT's TGButton.h (PMsgBox)
|
||||
target_compile_definitions(musrview PRIVATE MUSRVIEW_QT_APP_ICON QT_NO_KEYWORDS)
|
||||
target_link_libraries(musrview Qt6::Widgets)
|
||||
set(MUSRVIEW_HAS_QT_APP_ICON TRUE CACHE INTERNAL "musrview sets the icon of its embedded window")
|
||||
else ()
|
||||
set(MUSRVIEW_HAS_QT_APP_ICON FALSE CACHE INTERNAL "musrview sets the icon of its embedded window")
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
#--- macOS: musrview is a plain executable, not an application bundle. An
|
||||
#--- Info.plist embedded into the binary nevertheless gives it a proper name
|
||||
#--- (Dock, app menu) and bundle identifier. ----------------------------------
|
||||
if (APPLE)
|
||||
configure_file(
|
||||
${CMAKE_SOURCE_DIR}/src/musrview_web/musrview-Info.plist.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/musrview-Info.plist
|
||||
@ONLY
|
||||
)
|
||||
target_link_options(musrview PRIVATE
|
||||
"LINKER:-sectcreate,__TEXT,__info_plist,${CMAKE_CURRENT_BINARY_DIR}/musrview-Info.plist")
|
||||
set_property(TARGET musrview APPEND PROPERTY
|
||||
LINK_DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/musrview-Info.plist)
|
||||
endif ()
|
||||
|
||||
#--- Linux: on Wayland the compositor ignores the icon a window sets and takes
|
||||
#--- it from the .desktop file matching the app-id instead (musrview.cpp sets
|
||||
#--- it via setDesktopFileName). NoDisplay keeps it out of the launchers, since
|
||||
#--- musrview needs an msr-file to start with. --------------------------------
|
||||
if (UNIX AND NOT APPLE)
|
||||
install(
|
||||
FILES ${CMAKE_SOURCE_DIR}/cmake/musrview.desktop
|
||||
DESTINATION ${CMAKE_INSTALL_DATADIR}/applications
|
||||
)
|
||||
install(
|
||||
FILES ${CMAKE_SOURCE_DIR}/src/musrview_web/musrview.png
|
||||
DESTINATION ${CMAKE_INSTALL_DATADIR}/icons/hicolor/512x512/apps
|
||||
)
|
||||
install(
|
||||
FILES ${CMAKE_SOURCE_DIR}/src/musrview_web/musrview.svg
|
||||
DESTINATION ${CMAKE_INSTALL_DATADIR}/icons/hicolor/scalable/apps
|
||||
)
|
||||
endif ()
|
||||
|
||||
add_executable(write_musrRoot_runHeader write_musrRoot_runHeader.cpp)
|
||||
target_compile_options(write_musrRoot_runHeader BEFORE PRIVATE "-DHAVE_CONFIG_H" "${HAVE_GIT_REV_H}")
|
||||
target_include_directories(write_musrRoot_runHeader
|
||||
|
||||
@@ -1097,6 +1097,20 @@ void PMusrWebCanvas::ProcessMessage(unsigned connid, const std::string &msg)
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// WebDir (public, static)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Locates the directory holding the musrview web assets, i.e. the page
|
||||
* and the application icon, see WebDirCandidates() for the search order.
|
||||
*
|
||||
* \return the directory, or an empty string if none was found
|
||||
*/
|
||||
std::string PMusrWebCanvas::WebDir()
|
||||
{
|
||||
return FindWebDir();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Show (public)
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
@@ -113,6 +113,9 @@ class PMusrWebCanvas
|
||||
|
||||
/// Opens the window. \p where is "" (standard browser), "qt6", "chrome", ...
|
||||
Bool_t Show(const std::string &where);
|
||||
/// Directory holding the musrview web assets (page, application icon),
|
||||
/// empty if none was found.
|
||||
static std::string WebDir();
|
||||
/// True once the user has closed the window.
|
||||
Bool_t IsDone() const { return fDone; }
|
||||
/// Closes the window and drops the connection. Needed so that musrview can
|
||||
|
||||
@@ -49,6 +49,11 @@
|
||||
|
||||
#include <ROOT/RWebWindowsManager.hxx>
|
||||
|
||||
#ifdef MUSRVIEW_QT_APP_ICON
|
||||
#include <QApplication>
|
||||
#include <QIcon>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_GIT_REV_H
|
||||
#include "git-revision.h"
|
||||
#endif
|
||||
@@ -151,6 +156,41 @@ std::string musrview_select_display(const std::string &requested)
|
||||
return std::string();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Gives the embedded window a proper application name and icon.
|
||||
*
|
||||
* <p>The QApplication behind the embedded display is created by ROOT the
|
||||
* moment the first window is shown, and nobody sets an icon on it. Since
|
||||
* musrview is a plain executable rather than an application bundle, macOS
|
||||
* then shows the generic 'exec' icon in the Dock and the window switcher.
|
||||
* QApplication::setWindowIcon() replaces the Dock icon as well. Hence this
|
||||
* has to be called after the first PMusrWebCanvas::Show("qt6").
|
||||
*
|
||||
* <p>On X11 the window icon is all it takes. Wayland compositors ignore it and
|
||||
* take the icon from the .desktop file matching the app-id instead, which is
|
||||
* what setDesktopFileName() provides (cmake/musrview.desktop).
|
||||
*/
|
||||
void musrview_set_app_icon()
|
||||
{
|
||||
#ifdef MUSRVIEW_QT_APP_ICON
|
||||
if (QApplication::instance() == nullptr)
|
||||
return;
|
||||
|
||||
QApplication::setApplicationName("musrview");
|
||||
QApplication::setApplicationDisplayName("musrview");
|
||||
QApplication::setDesktopFileName("musrview");
|
||||
|
||||
const std::string webDir = musrview::PMusrWebCanvas::WebDir();
|
||||
if (webDir.empty())
|
||||
return;
|
||||
|
||||
const QIcon icon(QString::fromStdString(webDir + "/musrview.png"));
|
||||
if (!icon.isNull())
|
||||
QApplication::setWindowIcon(icon);
|
||||
#endif
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>The musrview program is used to show muSR fit results in graphical form.
|
||||
@@ -486,6 +526,9 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
|
||||
if (ok && (where == "qt6"))
|
||||
musrview_set_app_icon();
|
||||
|
||||
if (ok) {
|
||||
// run until every window has been closed, or until the timeout expired
|
||||
const auto start = std::chrono::steady_clock::now();
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<!-- embedded into the musrview executable (__TEXT,__info_plist), see src/CMakeLists.txt -->
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleName</key>
|
||||
<string>musrview</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string>musrview</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>musrview</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>ch.psi.lmu.musrview</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>@PROJECT_VERSION@</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>@PROJECT_VERSION@</string>
|
||||
<key>NSHumanReadableCopyright</key>
|
||||
<string>Andreas Suter</string>
|
||||
<key>NSHighResolutionCapable</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 79 KiB |
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- musrview application icon (Dock/task bar), sibling of musredit-bigsur.icns -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1024" height="1024" viewBox="0 0 1024 1024">
|
||||
<defs>
|
||||
<linearGradient id="bg" x1="0" y1="0" x2="0" y2="1">
|
||||
<stop offset="0" stop-color="#a9cde6"/>
|
||||
<stop offset="1" stop-color="#7fb0d4"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<rect x="100" y="100" width="824" height="824" rx="185" ry="185" fill="url(#bg)"/>
|
||||
<path d="M150,640 L874,640" stroke="#2b3a47" stroke-width="8" opacity="0.35"/>
|
||||
<path d="M190.0,210.0 L194.0,212.5 L198.0,216.2 L202.0,221.2 L206.0,227.3 L210.0,234.5 L214.0,242.7 L218.0,252.0 L222.0,262.0 L226.0,272.9 L230.0,284.4 L234.0,296.6 L238.0,309.2 L242.0,322.2 L246.0,335.6 L250.0,349.1 L254.0,362.7 L258.0,376.4 L262.0,389.9 L266.0,403.3 L270.0,416.4 L274.0,429.1 L278.0,441.4 L282.0,453.2 L286.0,464.4 L290.0,474.9 L294.0,484.7 L298.0,493.6 L302.0,501.8 L306.0,509.1 L310.0,515.5 L314.0,521.0 L318.0,525.5 L322.0,529.0 L326.0,531.6 L330.0,533.2 L334.0,533.8 L338.0,533.5 L342.0,532.2 L346.0,530.0 L350.0,527.0 L354.0,523.1 L358.0,518.4 L362.0,513.0 L366.0,506.9 L370.0,500.1 L374.0,492.8 L378.0,485.0 L382.0,476.7 L386.0,468.0 L390.0,459.0 L394.0,449.8 L398.0,440.4 L402.0,430.8 L406.0,421.3 L410.0,411.8 L414.0,402.3 L418.0,393.1 L422.0,384.0 L426.0,375.3 L430.0,366.8 L434.0,358.8 L438.0,351.2 L442.0,344.1 L446.0,337.6 L450.0,331.5 L454.0,326.1 L458.0,321.3 L462.0,317.2 L466.0,313.7 L470.0,310.9 L474.0,308.7 L478.0,307.3 L482.0,306.5 L486.0,306.4 L490.0,307.0 L494.0,308.2 L498.0,310.0 L502.0,312.4 L506.0,315.4 L510.0,319.0 L514.0,323.0 L518.0,327.5 L522.0,332.5 L526.0,337.8 L530.0,343.4 L534.0,349.4 L538.0,355.5 L542.0,361.9 L546.0,368.5 L550.0,375.1 L554.0,381.8 L558.0,388.4 L562.0,395.1 L566.0,401.6 L570.0,408.0 L574.0,414.3 L578.0,420.3 L582.0,426.0 L586.0,431.5 L590.0,436.7 L594.0,441.4 L598.0,445.8 L602.0,449.8 L606.0,453.4 L610.0,456.5 L614.0,459.2 L618.0,461.4 L622.0,463.2 L626.0,464.4 L630.0,465.2 L634.0,465.5 L638.0,465.3 L642.0,464.7 L646.0,463.6 L650.0,462.2 L654.0,460.3 L658.0,458.0 L662.0,455.3 L666.0,452.3 L670.0,449.0 L674.0,445.4 L678.0,441.6 L682.0,437.5 L686.0,433.3 L690.0,428.9 L694.0,424.4 L698.0,419.8 L702.0,415.1 L706.0,410.4 L710.0,405.8 L714.0,401.1 L718.0,396.6 L722.0,392.2 L726.0,387.9 L730.0,383.8 L734.0,379.8 L738.0,376.1 L742.0,372.6 L746.0,369.4 L750.0,366.5 L754.0,363.8 L758.0,361.5 L762.0,359.5 L766.0,357.8 L770.0,356.4 L774.0,355.3 L778.0,354.6 L782.0,354.2 L786.0,354.2 L790.0,354.5 L794.0,355.1 L798.0,356.0 L802.0,357.1 L806.0,358.6 L810.0,360.3 L814.0,362.3 L818.0,364.5 L822.0,366.9 L826.0,369.5 L830.0,372.3 L834.0,375.2 L838.0,378.2" fill="none" stroke="#000000" stroke-width="14" stroke-linejoin="round" stroke-linecap="round"/>
|
||||
<line x1="200" y1="206.5" x2="200" y2="266.5" stroke="#e8141c" stroke-width="10" stroke-linecap="round"/><circle cx="200" cy="236.5" r="24" fill="#e8141c"/><line x1="258" y1="318.4" x2="258" y2="390.4" stroke="#e8141c" stroke-width="10" stroke-linecap="round"/><circle cx="258" cy="354.4" r="24" fill="#e8141c"/><line x1="316" y1="493.3" x2="316" y2="577.3" stroke="#e8141c" stroke-width="10" stroke-linecap="round"/><circle cx="316" cy="535.3" r="24" fill="#e8141c"/><line x1="374" y1="447.8" x2="374" y2="507.8" stroke="#e8141c" stroke-width="10" stroke-linecap="round"/><circle cx="374" cy="477.8" r="24" fill="#e8141c"/><line x1="432" y1="351.8" x2="432" y2="423.8" stroke="#e8141c" stroke-width="10" stroke-linecap="round"/><circle cx="432" cy="387.8" r="24" fill="#e8141c"/><line x1="490" y1="255.0" x2="490" y2="339.0" stroke="#e8141c" stroke-width="10" stroke-linecap="round"/><circle cx="490" cy="297.0" r="24" fill="#e8141c"/><line x1="548" y1="355.8" x2="548" y2="415.8" stroke="#e8141c" stroke-width="10" stroke-linecap="round"/><circle cx="548" cy="385.8" r="24" fill="#e8141c"/><line x1="606" y1="397.4" x2="606" y2="469.4" stroke="#e8141c" stroke-width="10" stroke-linecap="round"/><circle cx="606" cy="433.4" r="24" fill="#e8141c"/><line x1="664" y1="419.9" x2="664" y2="503.9" stroke="#e8141c" stroke-width="10" stroke-linecap="round"/><circle cx="664" cy="461.9" r="24" fill="#e8141c"/><line x1="722" y1="350.2" x2="722" y2="410.2" stroke="#e8141c" stroke-width="10" stroke-linecap="round"/><circle cx="722" cy="380.2" r="24" fill="#e8141c"/><line x1="780" y1="334.4" x2="780" y2="406.4" stroke="#e8141c" stroke-width="10" stroke-linecap="round"/><circle cx="780" cy="370.4" r="24" fill="#e8141c"/><line x1="838" y1="327.2" x2="838" y2="411.2" stroke="#e8141c" stroke-width="10" stroke-linecap="round"/><circle cx="838" cy="369.2" r="24" fill="#e8141c"/>
|
||||
<text x="512" y="850" text-anchor="middle" font-family="Helvetica, Arial, sans-serif" font-weight="bold" font-size="230" fill="#000000">VIEW</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.7 KiB |
Reference in new issue
Block a user